Files
website/dist/projects/musicplayer/index.html
2025-09-29 11:24:54 +02:00

372 lines
16 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<!-- CSS -->
<link rel="stylesheet" href="https://static.janishutz.com/css/slider.css">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/side-by-side.css">
<!-- SEO -->
<title>MusicPlayer - Fully browser based with built-in remote playlist display with animations | janishutz.com
</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=7" />
<meta name="keywords" content="browser-based, music player, remote display" />
<meta name="description"
content="Want to show off what the currently playing song is for your next party? MusicPlayer has a lot of party-oriented features built in!" />
<meta name="og:title"
content="MusicPlayer - Fully browser based with built-in remote playlist display with animations" />
<meta name="og:description"
content="Want to show off what the currently playing song is for your next party? MusicPlayer has a lot of party-oriented features built in!" />
<meta name="og:image" content="https://static.janishutz.com/projects/musicplayer-title.jpg" />
<meta name="og:type" content="website" />
<meta name="og:url" content="https://janishutz.com/projects/musicplayer" />
<meta name="og:locale" content="en_GB" />
<meta property="twitter:card" content="summary_large_image">
<meta name="theme-color" content="#152b5c">
</head>
<body>
<nav><script>
// Themeing
let loadedTheme = localStorage.getItem( 'theme' ) ?? 'auto';
var theme = loadedTheme;
let loadTheme = () => {
loadedTheme = localStorage.getItem( 'theme' ) ?? 'auto';
if ( loadedTheme === 'auto' ) {
if ( window.matchMedia( '(prefers-color-scheme: dark)' ).matches ) {
theme = 'dark_mode';
} else {
theme = 'light_mode';
}
}
if ( theme === 'dark_mode' ) {
document.documentElement.classList.remove( 'light' );
document.documentElement.classList.add( 'dark' );
} else {
document.documentElement.classList.add( 'light' );
document.documentElement.classList.remove( 'dark' );
theme === 'light_mode';
}
}
loadTheme();
setTimeout( () => {
document.querySelector( 'body' ).classList.add( 'loaded' );
}, 500 );
function changeTheme () {
theme = document.getElementById( 'theme-select' ).value;
localStorage.setItem( 'theme', theme );
loadTheme();
}
</script>
<div class="nav-placeholder"></div>
<div class="nav-top-bar">
<a href="/" class="logo-wrapper">
<img src="https://static.janishutz.com/logo.jpg" alt="janishutz.com logo" class="logo">
</a>
<!-- <img src="https://static.janishutz.com/logo.jpg" alt="janishutz.com logo" class="logo"> -->
<div class="nav-toggle" onclick="openMenu( 'toggle' )">
<span class="line" id="line1"></span>
<span class="line" id="line2"></span>
<span class="line" id="line3"></span>
</div>
</div>
<div class="nav-menu">
<div class="nav-link-wrapper">
<a class="nav-link-header" href="/projects">
<span class="material-symbols-outlined nav-icon">lightbulb</span>
<div>Projects</div>
</a>
<div class="nav-link-dropdown">
<a href="/projects">View all</a>
<a href="/projects/storagemanager">StorageManager</a>
<a href="/projects/qrscanner">QR & Barcode Insight</a>
<a href="/projects/libreevent">libreǝvent</a>
<a href="/projects/musicplayer">MusicPlayer</a>
<a href="https://conductorcalc.com" target="_blank">ConductorCalc</a>
</div>
</div>
<div class="nav-link-wrapper">
<a class="nav-link-header" href="/services">
<span class="material-symbols-outlined nav-icon">build</span>
<div>Services</div>
</a>
<div class="nav-link-dropdown">
<a href="https://store.janishutz.com">Store</a>
<a href="https://account.janishutz.com">Account</a>
<a href="https://development.janishutz.com">Custom Websites</a>
</div>
</div>
<a href="/" class="logo-wrapper">
<img src="https://static.janishutz.com/logo.jpg" alt="janishutz.com logo" class="logo">
</a>
<div class="nav-link-wrapper">
<a class="nav-link-header" href="/about">
<span class="material-symbols-outlined nav-icon">info</span>
<div>About</div>
</a>
<div class="nav-link-dropdown">
<a href="/about">About janishutz.com</a>
<a href="/about/aboutme">About Janis Hutz</a>
<a href="https://blog.janishutz.com" target="_blank">Blog</a>
<a href="/legal">Legal</a>
</div>
</div>
<div class="nav-link-wrapper">
<a class="nav-link-header" href="/support">
<span class="material-symbols-outlined nav-icon">support_agent</span>
<div>Support</div>
</a>
<div class="nav-link-dropdown">
<a href="https://support.janishutz.com" target="_blank">Support Hub</a>
<a href="https://support.janishutz.com/knowledgebase.php" target="_blank">Knowledgebase</a>
<a href="/support/old">Old websites</a>
</div>
</div>
</div>
<script>
const toggle = document.getElementsByClassName( 'nav-toggle' )[ 0 ];
const menu = document.getElementsByClassName( 'nav-menu' )[ 0 ];
const bar = document.getElementsByClassName( 'nav-top-bar' )[ 0 ];
function openMenu( action ) {
if ( action === 'toggle' ) {
if ( menu.classList.contains( 'active' ) ) {
openMenu( 'close' );
} else {
openMenu( 'open' );
}
} else if ( action === 'close' ) {
menu.classList.remove( 'active' );
toggle.classList.remove( 'active' );
document.body.classList.remove( 'no-scroll' );
} else if ( action === 'open' ) {
document.body.classList.add( 'no-scroll' );
toggle.classList.add( 'active' );
menu.classList.add( 'active' );
bar.classList.remove( 'slide-up' );
menu.classList.remove( 'slide-up' );
}
}
let oldScroll = 0;
document.addEventListener( 'scroll', () => {
if ( oldScroll < window.scrollY && window.innerHeight * 0.2 < window.scrollY ) {
bar.classList.add( 'slide-up' );
menu.classList.add( 'slide-up' );
} else if ( oldScroll > window.scrollY ) {
bar.classList.remove( 'slide-up' );
menu.classList.remove( 'slide-up' );
}
oldScroll = window.scrollY;
} );
// TODO: Hide menu on when scrolling down
</script>
</nav>
<div class="slider">
<div class="slider-container">
<div class="slider-element current"
style="background-image: url( 'https://store-cdn.janishutz.com/assets/musicplayer/library-local.jpg' );">
<div class="slider-info">
<h2>Sources</h2>
<p>Play your local music or use Apple Music (Apple Music Subscription required)</p>
<a href="https://music.janishutz.com/" class="button">Website</a>
</div>
</div>
<div class="slider-element"
style="background-image: url( 'https://store-cdn.janishutz.com/assets/musicplayer/fancy.jpg' );">
<div class="slider-info">
<h2>Shared Playlists</h2>
<p>Seamlessly sync and display what you are currently playing on other devices. Perfect for your
next party!</p>
<a href="https://music.janishutz.com/get" class="button">Get it today</a>
</div>
</div>
<div class="slider-element"
style="background-image: url( 'https://store-cdn.janishutz.com/assets/musicplayer/player.jpg' );">
<div class="slider-info">
<h2>Browser based</h2>
<p>No need to install anything. Runs on any platform</p>
<a href="https://music.janishutz.com/get" class="button">Get it today</a>
</div>
</div>
<div class="slider-element"
style="background-image: url( 'https://static.janishutz.com/assets/musicplayer/main.jpg' );">
<div class="slider-info">
<h2>Hosted for you</h2>
<p>Need the convenience of an already set up version?</p>
<a href="https://music.janishutz.com/" class="button">Website</a>
</div>
</div>
<div class="slider-element"
style="background-image: url( 'https://static.janishutz.com/assets/projects/musicplayer-title.jpg' );">
<div class="slider-info">
<h2>Open Source</h2>
<p>Developed by Janis Hutz &amp; the community</p>
<a href="https://github.com/janishutz/MusicPlayerV2" class="button">GitHub</a>
</div>
</div>
<div class="slider-element"
style="background-image: url( 'https://store-cdn.janishutz.com/assets/musicplayer/library-dark.jpg' );">
<div class="slider-info">
<h2>Self-Hostable</h2>
<p>Host it yourself. You need to be member of the Apple Developer Program for access to the Apple
Music API</p>
<a href="https://github.com/janishutz/MusicPlayerV2/wiki/Installation" class="button">Docs</a>
</div>
</div>
</div>
<span class="slider-controls slider-control-left material-symbols-outlined"
onclick="sliderControl( 'previous' )">arrow_back</span>
<span class="slider-controls slider-control-right material-symbols-outlined"
onclick="sliderControl( 'next' )">arrow_forward
</div>
<div class="content">
<img src="https://github.com/janishutz/MusicPlayerV2/raw/master/assets/logo.png" alt="MusicPlayer logo"
class="project-logo">
<h1>Music&shy;Player</h1>
<a href="/projects" class="back-button">&leftarrow; All projects</a>
<p>Play music fully in the browser and remotely share what you are currently playing. Perfect for your next
party!</p>
<a href="https://music.janishutz.com" target="_blank" class="button">Get it today</a>
<hr class="divider">
<h2>Features</h2>
<div class="side-by-side">
<div class="side-by-side-item left">
<h3>Remote Playback Status</h3>
<p>Remotely display what is currently playing via a link you can share. There is an additional link that
can be used to display the same information, but with animations that sync to the music (Microphone
access required on the target device and animations will sync up to the sound audible on that
device)</p>
</div>
<div class="side-by-side-item right">
<h3>Two Sources</h3>
<p>You can choose between two sources for audio: Your local disk or Apple Music and you can mix the two
in a single playlist. Cover Art and song information is fetched from the Apple Music API
automatically if you are using the hosted version or have configured the Apple Music API
authentication tokens</p>
</div>
</div>
<div class="side-by-side">
<div class="side-by-side-item left">
<h3>Fully Featured Player</h3>
<p>All the features you'd expect from a Music Player are present in MusicPlayer. Shuffle, Repeat,
Playlist support, adding more songs to queue, just to name a few, are all present.</p>
</div>
<div class="side-by-side-item right">
<h3>Browser based</h3>
<p>There is no need to install anything. MusicPlayer runs fully in your browser and is thus cross
platform. You could even run it off of your phone, if you wish!</p>
</div>
</div>
<hr class="divider">
<a href="https://music.janishutz.com" target="_blank" class="button" style="margin-top: 50px;">Get it today</a>
</div>
<footer><div class="footer-container">
<img src="https://static.janishutz.com/logo.jpg" alt="janishutz.com logo" class="logo">
<div class="footer-text-container">
<div class="footer-category">
<h3>Projects</h3>
<a href="/projects">View all</a>
<a href="/projects/storagemanager">StorageManager</a>
<a href="/projects/qrscanner">QR & Barcode Insight</a>
<a href="/projects/libreevent">libreǝvent</a>
<a href="/projects/musicplayer">MusicPlayer</a>
<a href="/projects/biogascontrollerapp">BiogasControllerApp</a>
</div>
<div class="footer-category">
<h3>Info</h3>
<a href="/about">About janishutz.com</a>
<a href="/about/aboutme">About Janis Hutz</a>
<div class="theme-selector">
<span class="material-symbols-outlined" id="theme-switcher-icon">light_mode</span>
<select id="theme-select" onchange="changeTheme()">
<option value="auto">Auto</option>
<option value="light_mode">Light</option>
<option value="dark_mode">Dark</option>
</select>
</div>
</div>
<div class="footer-category">
<h3>Support</h3>
<a href="https://support.janishutz.com">Get support</a>
<a href="https://support.janishutz.com/knowledgebase.php">Knowledgebase</a>
<a href="/support/support-status">Support status</a>
</div>
<div class="footer-category">
<h3>Legal</h3>
<a href="/legal/privacy">Privacy Policy</a>
<a href="/legal/tos">Terms of Service</a>
<a href="/legal/returns">Return policy</a>
<a href="/support/support-status">Support Status</a>
<div onclick="showAnalytics()" style="cursor: pointer;">Analytics</div>
</div>
<div class="analytics-notice" id="analytics">
<h2>Analytics</h2>
<p>This website uses privacy preserving product analytics allowing me to analyze aggregated statistics for this website. All data collected will not allow me to uniquely identify you. <br><a href="/legal/privacy">Privacy Policy</a></p>
<!-- Matomo stuff -->
<div id="matomo-opt-out">
Loading...
</div>
<script src="https://analytics.janishutz.com/index.php?module=CoreAdminHome&action=optOutJS&divId=matomo-opt-out&language=auto&fontColor=000000&fontSize=12px&fontFamily=monospace&showIntro=1"></script>
<!-- Matomo Image Tracker-->
<img referrerpolicy="no-referrer-when-downgrade" src="https://analytics.janishutz.com/matomo.php?idsite=2&amp;rec=1" style="border:0" alt="" />
<!-- End Matomo -->
<button class="analytics-button" onclick="closeAnalytics()"><span class="material-symbols-outlined">close</span></button>
<div class="small-symbol" onclick="showAnalytics()" title="Change your analytics preferences"><span class="material-symbols-outlined">Analytics</span></div>
</div>
</div>
<script>
function closeAnalytics () {
document.getElementById( 'analytics' ).classList.remove( 'show' );
localStorage.setItem( 'analytics-dismissed', 'true' );
}
function showAnalytics () {
document.getElementById( 'analytics' ).classList.add( 'show' );
}
if ( !localStorage.getItem( 'analytics-dismissed' ) ) {
document.getElementById( 'analytics' ).classList.add( 'show' );
}
// Show which theme is loaded
document.getElementById( 'theme-select' ).value = loadedTheme;
</script>
</div>
</footer>
<script src="https://static.janishutz.com/js/slider.js"></script>
<script>
activateSlider(7500);
</script>
</body>
</html>