Skip to content

Commit

Permalink
rewrite in plain JS
Browse files Browse the repository at this point in the history
Removes Elm, and uses plain JSON as protocol.
  • Loading branch information
alicebob committed Jan 4, 2021
1 parent b9ee49b commit 9da8326
Show file tree
Hide file tree
Showing 29 changed files with 991 additions and 2,196 deletions.
6 changes: 1 addition & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
siren/siren
siren/static.go
siren/dist
elm/elm-stuff/
docroot/s/main.js
siren
File renamed without changes.
26 changes: 15 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
.PHONY: build build-pi preparerelease release fakerelease
.PHONY: all test build build-pi run preparerelease release fakerelease

all: test build

test:
go test

build:
$(MAKE) -C elm
$(MAKE) -C siren
go build

build-pi: static
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build

build-pi:
$(MAKE) -C elm
$(MAKE) -C siren build-pi
run: build
./siren -docroot ./docroot

preparerelease:
$(MAKE) -C elm
$(MAKE) -C siren static
preparerelease: test build
go get -v github.com/goreleaser/goreleaser

release: preparerelease
cd siren && goreleaser --rm-dist
goreleaser --rm-dist

fakerelease: preparerelease
cd siren && goreleaser --rm-dist --snapshot
goreleaser --rm-dist --snapshot
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
Browser based MPD client.

Made with Elm and `display:grid`.
Made with plain Javascript and `display:grid`.

<img src="./img_playlist.png" width="400" /><img src="./img_files.png" width="400" />


## Releases

Binary releases are on the [releases](https://github.com/alicebob/siren/releases) page.


## History

Version 1.0 was with Elm 0.18.
Version 2.0 was with Purescript.
Version 3.0 is plain Javascript.


## Build

- you need a Go (>=1.11) and an Elm (==0.18) compiler
- you need a Go (>=1.16)
- `make`
- run the binary from ./siren/siren
- run the binary from ./siren
- open http://localhost:6601/

All resources are bundled in the binary, so you can copy it over to other
Expand All @@ -34,7 +42,7 @@ Thanks to Go's cross-platform support you can build Siren on your laptop, and co

Siren connects to the mpd at localhost:6600 by default. Change it with for example: `./siren -mpd=192.168.1.2:6600`

If you don't want to make Siren available to everyone in you subnet, use: `./siren -listen=localhost:6601`
If you don't want to make Siren available to everyone in your subnet, use: `./siren -listen=localhost:6601`

### Artist vs Albumartist

Expand All @@ -59,7 +67,7 @@ Suggested nginx config:

## Development

Usually the CSS and compiled Elm files are embedded in the executable, but you
Usually the CSS and Javascript files are embedded in the executable, but you
can use the filesystem while developing. Run siren with:

`./siren/siren --docroot ./docroot`
Expand All @@ -68,5 +76,4 @@ can use the filesystem while developing. Run siren with:
## Links

- [Music Player Daemon](https://www.musicpd.org)
- [Elm](https://elm-lang.org)
- [Go](https://golang.org)
89 changes: 83 additions & 6 deletions docroot/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,93 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>🎶</title>
<script src="./s/main.js"></script>
<link rel="icon" class="js-site-favicon" href="./s/play.png">
<script src="./s/siren.js"></script>
<script src="./s/conn.js"></script>
<link rel="stylesheet" href="./s/siren.css" />
</head>
<body id="body">
<script>
var wsURL = (window.location.protocol === "https:" ? "wss://" : "ws://") + window.location.host + window.location.pathname + "mpd/ws";
var node = document.getElementById('body');
var app = Elm.Main.embed(node, {
wsURL: wsURL
});
var wsURL = (window.location.protocol === "https:" ? "wss://" : "ws://") +
window.location.host +
window.location.pathname + "mpd/ws";
const ui = new UI(document.getElementById('body'));
runWS(wsURL, ui);
</script>
<div class="mpd">
<nav>
<a class="logo">Siren!</a>
<span></span>
<a id="playlisttab" class="tab current" title="Show playlist">Playlist</a>
<a id="filestab" class="tab inactive" title="Browse the filesystem">Files</a>
<a id="albumtab" class="tab inactive" title="Browse by albumartist">Artists</a>
<span></span>
<a id="connected" class="status offline" title="initializing">Initializing</a>
</nav>
<div id="pageplaylist" class="playlistwrap">
<div class="playlist">
<div class="commands">
<button onclick="ui.sendCmd('clear')">CLEAR PLAYLIST</button>
</div>
<div class="header">
<div class="track">Track</div>
<div class="title">Title</div>
<div class="artist">Artist</div>
<div class="album">Album</div>
<div class="dur"></div>
</div>
</div>
<div id="playlist" class="entries">
</div>
<div class="player">
<div class="buttons">
<a id="playprevious" class="enabled" onclick="ui.sendCmd('previous')">
<div style="color: white; width: 42px; display: inline-block">
<!-- chevron-circle-left.svg + 'fill="currentColor"' -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="currentColor" d="M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zM142.1 273l135.5 135.5c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L226.9 256l101.6-101.6c9.4-9.4 9.4-24.6 0-33.9l-17-17c-9.4-9.4-24.6-9.4-33.9 0L142.1 239c-9.4 9.4-9.4 24.6 0 34z"/></svg>
</div>
</a>
<a id="playpause" style="display:none" class="enabled" onclick="ui.sendCmd('pause')">
<div style="color: white; width: 42px; display: inline-block">
<!-- play-circle.svg + 'fill="currentColor"' -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm-16 328c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h48c8.8 0 16 7.2 16 16v160zm112 0c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h48c8.8 0 16 7.2 16 16v160z"/></svg>
</div>
</a>
<a id="playplay" class="enabled" onclick="ui.sendCmd('play')">
<div style="color: white; width: 42px; display: inline-block">
<!-- play-circle.svg + 'fill="currentColor"' -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm115.7 272l-176 101c-15.8 8.8-35.7-2.5-35.7-21V152c0-18.4 19.8-29.8 35.7-21l176 107c16.4 9.2 16.4 32.9 0 42z"/></svg>
</div>
</a>
<a id="playstop" class="enabled" onclick="ui.sendCmd('stop')">
<div style="color: white; width: 42px; display: inline-block">
<!-- stop-circle.svg + 'fill="currentColor"' -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm96 328c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h160c8.8 0 16 7.2 16 16v160z"/></svg>
</div>
</a>
<a id="playnext" class="enabled" onclick="ui.sendCmd('next')">
<div style="color: white; width: 42px; display: inline-block">
<!-- chevron-circle-right.svg + 'fill="currentColor"' -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path fill="currentColor" d="M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zm113.9 231L234.4 103.5c-9.4-9.4-24.6-9.4-33.9 0l-17 17c-9.4 9.4-9.4 24.6 0 33.9L285.1 256 183.5 357.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L369.9 273c9.4-9.4 9.4-24.6 0-34z"/></svg>
</div>
</a>
</div>
<div class="title"></div>
<div class="artist"></div>
<div class="time">
<input id="progress" type="range" min="0" max="0" onchange="ui.eventProgress(this.value)" />
<div id="progresstxt"></div>
</div>
</div>
</div>
<div id="pagefiles" style="display:none" class="mc">
<div class="pane">
</div>
</div>
<div id="pagealbum" style="display:none" class="mc">
<div class="pane">
</div>
</div>
</div>
</body>
</html>
51 changes: 51 additions & 0 deletions docroot/s/conn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
function runWS(wsURL, ui) {
console.log("connecting to ", wsURL);
const ws = new WebSocket(wsURL);
ws.addEventListener('open', function (event) {
console.log("got ws connection");
ui.setConnected(true, undefined);
ui.sendCmd = function(name, payload) {
if (payload === undefined) {
payload = {};
}
ws.send(JSON.stringify({"name": name, "value": payload}));
}
});
ws.addEventListener('close', function (event) {
console.log("lost ws connection");
ui.setConnected(false, function() { runWS(wsURL, ui) });
});
ws.addEventListener('message', function (event) {
const msg = JSON.parse(event.data);
handleMsg(msg.name, msg.value, ui);
});
};

function handleMsg(msgName, payload, ui) {
switch(msgName) {
case "siren/config":
ui.mpdhost = payload.mpdhost;
ui.artistmode = payload.artistmode;
break;
case "siren/connection":
ui.setMPDConnected(payload);
break;
case "siren/playlist":
ui.setPlaylist(payload);
break;
case "siren/status":
ui.setPlaybackStatus(payload.songid, payload.state, payload.duration, payload.elapsed);
break;
case "siren/list":
ui.setList(payload.id, payload.list);
break;
case "siren/inodes":
ui.setInodes(payload.id, payload.inodes);
break;
case "siren/track":
ui.setTrack(payload.id, payload.track);
break;
default:
console.log("unhandled message type", msgName, payload);
}
}
Loading

0 comments on commit 9da8326

Please sign in to comment.