This commit is contained in:
Ondrej Zara 2019-04-16 09:03:42 +02:00
parent 87a7c5680a
commit 1f5dd9d618
6 changed files with 33 additions and 22 deletions

View file

@ -2,6 +2,7 @@
CYP is a web-based frontend for [MPD](https://www.musicpd.org/), the Music Player Daemon. You can use it to control the playback without having to install native application(s). It works in modern web browsers, both desktop and mobile.
## Features
- Control the playback, queue, volume
- Save and load playlists
@ -9,6 +10,7 @@ CYP is a web-based frontend for [MPD](https://www.musicpd.org/), the Music Playe
- Display album art via native MPD calls (no need to access the library; requires MPD >= 0.21)
- [Youtube-dl](https://ytdl-org.github.io/youtube-dl/index.html) intergration
## Installation
Make sure you have a working MPD setup first.
@ -21,16 +23,21 @@ node .
Point your browser to http://localhost:8080 to open the interface.
## Technology
- Connected to MPD via WebSockets (using the [ws2mpd](https://github.com/ondras/ws2mpd/) bridge)
- Token-based access to the WebSocket endpoint (better than an `Origin` check)
- Modern ES6+ (modules, async/await)
- Responsive layout via Flexbox
- CSS Custom Properties
- SVG icons (Material Design)
- Dark/Light theme available
- Album art downloaded directly from MPD (and cached via localStorage)
- Can spawn Youtube-dl to download audio files
- Album art retrieved directly from MPD (and cached via localStorage)
## TODO
- [ ] Bundling
- [ ] Range styling
- [ ] Browser testing

View file

@ -14,15 +14,16 @@ body {
line-height: 1.25;
background-color: var(--bg);
color: var(--fg);
text-shadow: var(--shadow);
text-shadow: var(--text-shadow);
max-width: 800px;
margin: 0 auto;
overflow: hidden;
height: 100vh;
}
body > header,
body > footer {
box-shadow: 0 0 3px #000;
header,
footer {
z-index: 1;
box-shadow: var(--box-shadow);
}
input,
select,
@ -280,7 +281,7 @@ nav ul li.active {
.component li .info .icon {
color: var(--primary);
margin-right: var(--icon-spacing);
filter: drop-shadow(var(--shadow));
filter: drop-shadow(var(--text-shadow));
}
.component li .info h2 {
font-size: var(--font-size-large);
@ -339,7 +340,7 @@ nav ul li.active {
#queue li .info .icon {
color: var(--primary);
margin-right: var(--icon-spacing);
filter: drop-shadow(var(--shadow));
filter: drop-shadow(var(--text-shadow));
}
#queue li .info h2 {
font-size: var(--font-size-large);
@ -401,7 +402,7 @@ nav ul li.active {
#library li .info .icon {
color: var(--primary);
margin-right: var(--icon-spacing);
filter: drop-shadow(var(--shadow));
filter: drop-shadow(var(--text-shadow));
}
#library li .info h2 {
font-size: var(--font-size-large);
@ -436,7 +437,7 @@ nav ul li.active {
width: 64px;
}
#library .art .icon {
filter: drop-shadow(var(--shadow));
filter: drop-shadow(var(--text-shadow));
}
#library .group {
cursor: pointer;
@ -497,7 +498,7 @@ nav ul li.active {
#fs li .info .icon {
color: var(--primary);
margin-right: var(--icon-spacing);
filter: drop-shadow(var(--shadow));
filter: drop-shadow(var(--text-shadow));
}
#fs li .info h2 {
font-size: var(--font-size-large);
@ -576,7 +577,7 @@ nav ul li.active {
#playlists li .info .icon {
color: var(--primary);
margin-right: var(--icon-spacing);
filter: drop-shadow(var(--shadow));
filter: drop-shadow(var(--text-shadow));
}
#playlists li .info h2 {
font-size: var(--font-size-large);
@ -643,7 +644,7 @@ nav ul li.active {
#yt li .info .icon {
color: var(--primary);
margin-right: var(--icon-spacing);
filter: drop-shadow(var(--shadow));
filter: drop-shadow(var(--text-shadow));
}
#yt li .info h2 {
font-size: var(--font-size-large);
@ -759,18 +760,19 @@ nav ul li.active {
--icon-spacing: 4px;
--primary: rgb(var(--primary-raw));
--spacing: 8px;
--box-shadow: 0 0 3px #000;
}
:root[data-theme=light] {
--fg: #333;
--bg: #f0f0f0;
--bg-alt: #e0e0e0;
--shadow: none;
--text-shadow: none;
}
:root[data-theme=dark] {
--fg: #f0f0f0;
--bg: #333;
--bg-alt: #555;
--shadow: 0 1px 1px rgba(0, 0, 0, 0.8);
--text-shadow: 0 1px 1px rgba(0, 0, 0, 0.8);
}
:root[data-color=dodgerblue] {
--primary-raw: 30, 144, 255;

View file

@ -12,15 +12,16 @@ body {
line-height: 1.25;
background-color: var(--bg);
color: var(--fg);
text-shadow: var(--shadow);
text-shadow: var(--text-shadow);
max-width: 800px;
margin: 0 auto;
overflow: hidden;
height: 100vh;
}
> header, > footer {
box-shadow: 0 0 3px #000;
}
header, footer {
z-index: 1;
box-shadow: var(--box-shadow);
}
input, select, button {

View file

@ -33,7 +33,7 @@
.icon {
color: var(--primary);
margin-right: var(--icon-spacing);
filter: drop-shadow(var(--shadow));
filter: drop-shadow(var(--text-shadow));
}
h2 {

View file

@ -15,7 +15,7 @@
}
.art .icon {
filter: drop-shadow(var(--shadow));
filter: drop-shadow(var(--text-shadow));
}
.group {

View file

@ -3,20 +3,21 @@
--icon-spacing: 4px;
--primary: rgb(var(--primary-raw));
--spacing: 8px;
--box-shadow: 0 0 3px #000;
}
:root[data-theme=light] {
--fg: #333;
--bg: #f0f0f0;
--bg-alt: #e0e0e0;
--shadow: none;
--text-shadow: none;
}
:root[data-theme=dark] {
--fg: #f0f0f0;
--bg: #333;
--bg-alt: #555;
--shadow: 0 1px 1px rgba(0, 0, 0, 0.8);
--text-shadow: 0 1px 1px rgba(0, 0, 0, 0.8);
}
:root[data-color=dodgerblue] {