diff --git a/events.py b/events.py index 6c1d1aa..bcc5d84 100644 --- a/events.py +++ b/events.py @@ -2,19 +2,62 @@ """ WebSocket events. """ +import os import types +from urllib import parse + +import config + +async def select_artist(request, ws, data): + """Select an artist.""" + artist = data.get('artist', '') + async with request.app['pool'].acquire() as conn: + albums = await conn.fetch( + "SELECT DISTINCT album, date FROM track " + "WHERE albumartist = $1 ORDER BY date ASC", + data.get('artist', '')) + albums = [dict(record) for record in albums] + ret = {'event': 'artist_albums', 'ok': True, 'data': albums} + await ws.send_json(ret) + + +async def select_album(request, ws, data): + """Select an album.""" + artist = data.get('artist', '') + album = data.get('album', '') + async with request.app['pool'].acquire() as conn: + tracks = await conn.fetch( + "SELECT DISTINCT discnumber, tracknumber, title FROM track " + "WHERE albumartist = $1 AND album = $2 " + "ORDER BY discnumber ASC, tracknumber ASC", + artist, album) + tracks = [dict(record) for record in tracks] + ret = {'event': 'album_tracks', 'ok': True, 'data': tracks} + await ws.send_json(ret) + + +async def select_track(request, ws, data): + """Select a track.""" + artist = data.get('artist', '') + album = data.get('album', '') + discnumber = data.get('discnumber', '') + tracknumber = data.get('tracknumber', '') + async with request.app['pool'].acquire() as conn: + track = await conn.fetchrow( + "SELECT * FROM track " + "WHERE albumartist = $1 AND album = $2 " + "AND discnumber = $3 AND tracknumber = $4", + artist, album, discnumber, tracknumber) + track = dict(track) + fpath = track.pop('filepath') + track.pop('last_modified') + fpath = config.static_prefix + os.path.relpath(fpath, config.music_dir) + fpath = fpath.replace('flac', 'opus') + fpath = parse.quote(fpath) + track['url'] = fpath + ret = {'event': 'track', 'ok': True, 'data': track} + await ws.send_json(ret) -async def select(request, ws, data): - """Retrieve information about an artist, album or track.""" - if data.get('type') == 'artist': - async with request.app['pool'].acquire() as conn: - albums = await conn.fetch( - "SELECT DISTINCT album, date FROM track " - "WHERE albumartist = $1 ORDER BY date ASC", - data.get('artist', '')) - albums = [record['album'] for record in albums] - ret = {'event': 'albums', 'ok': True, 'data': albums} - await ws.send_json(ret) events = {} for obj in dir(): diff --git a/static/scorch.css b/static/scorch.css index cc54455..67fae94 100644 --- a/static/scorch.css +++ b/static/scorch.css @@ -1,4 +1,5 @@ body { + font-family: Helvetica, sans-serif; height: 100vh; margin: 0; padding: 8px; diff --git a/static/scorch.js b/static/scorch.js index f9e0698..323c5ed 100644 --- a/static/scorch.js +++ b/static/scorch.js @@ -12,7 +12,9 @@ function init_websocket() { socket.onclose = onclose; socket.onerror = onerror; socket.events = {}; - socket.events['albums'] = albums_recv; + socket.events['artist_albums'] = artist_albums_recv; + socket.events['album_tracks'] = album_tracks_recv; + socket.events['track'] = track_recv; return socket; } @@ -78,24 +80,69 @@ function onerror(event) { } /* Websocket receive */ -function albums_recv(data) { +function artist_albums_recv(data) { let albums_list = document.querySelector('#albumList'); while (albums_list.firstChild) { albums_list.removeChild(albums_list.lastChild); } for (let album of data) { let option = document.createElement('option'); - option.value = album; - option.innerText = album; + option.value = album['album']; + option.innerText = album['album']; albums_list.appendChild(option); } } +function album_tracks_recv(data) { + let track_list = document.querySelector('#trackList'); + while (track_list.firstChild) { + track_list.removeChild(track_list.lastChild); + } + for (let track of data) { + let option = document.createElement('option'); + option.value = track['title']; + option.innerText = track['discnumber'] + '.' + track['tracknumber'] + ' - ' + track['title']; + option.dataset['discnumber'] = track['discnumber'] + option.dataset['tracknumber'] = track['tracknumber'] + track_list.appendChild(option); + } +} + +function track_recv(data) { + document.querySelector('#nowPlayingArtist').innerText = data['albumartist']; + document.querySelector('#nowPlayingAlbum').innerText = data['album']; + document.querySelector('#nowPlayingTitle').innerText = data['title']; + document.title = 'Musik | ' + data['artist'] + ' - ' + data['title']; + let player = document.querySelector('#player'); + player.firstElementChild.src = data['url']; + player.load(); + player.play(); +} + /* Websocket send */ -function select_artist(option) { - let artist = option.value; - let data = {'type': 'artist', 'artist': artist}; - socket.send_event('select', data); +function select_artist(select) { + let data = { + 'artist': select.value, + }; + socket.send_event('select_artist', data); +} + +function select_album(select) { + let data = { + 'artist': document.querySelector('#artistList').value, + 'album': select.value, + }; + socket.send_event('select_album', data); +} + +function select_track(select) { + let data = { + 'artist': document.querySelector('#artistList').value, + 'album': document.querySelector('#albumList').value, + 'discnumber': select.selectedOptions[0].dataset['discnumber'], + 'tracknumber': select.selectedOptions[0].dataset['tracknumber'], + }; + socket.send_event('select_track', data); } /* DOM */