From a3e86f3be768c8fa1fc2af12d5e5d66d9d9b82e8 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Tue, 16 Aug 2011 14:49:40 +0200 Subject: Implemented basic cuesheet support, some playlist fixes. --- static/icons/delete.png | Bin 0 -> 715 bytes static/index.html | 4 ++-- static/player.js | 30 ++++++++++++++++++++-------- static/playlist.js | 52 ++++++++++++++++++++++++++++++++++++++++++------ static/style.css | 4 +++- 5 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 static/icons/delete.png (limited to 'static') diff --git a/static/icons/delete.png b/static/icons/delete.png new file mode 100644 index 0000000..08f2493 Binary files /dev/null and b/static/icons/delete.png differ diff --git a/static/index.html b/static/index.html index 6f24aba..c1d75db 100644 --- a/static/index.html +++ b/static/index.html @@ -16,12 +16,12 @@
- + Browse directory Add all - + Song queue
    diff --git a/static/player.js b/static/player.js index 90acf0b..b358eb5 100644 --- a/static/player.js +++ b/static/player.js @@ -12,22 +12,28 @@ for(var i = 0; i < cache_images.length; i++) { img.src = '/static/icons/' + cache_images[i]; } -function MusicListing(type, path, name, cached) { +function MusicListing(type, path, name, track, cached) { this.type = type; this.path = path; this.name = name ? name : path.split('/').pop(); + this.track = track; this.a = document.createElement('a'); this.a.ml = this; this.play = function() { + var path = '/play?path=' + encodeURIComponent(this.path); + if(this.track) + path += '&track=' + this.track; log('playing ' + path); xmlhttp = new XMLHttpRequest(); - xmlhttp.open('GET', '/play?path=' + encodeURIComponent(path)); + xmlhttp.open('GET', path); xmlhttp.send(null); } this.recode = function() { var path = '/recode?path=' + encodeURIComponent(this.path); + if(this.track) + path += '&track=' + this.track; var a = this.a; var ml = this; var xmlhttp = new XMLHttpRequest(); @@ -43,7 +49,10 @@ function MusicListing(type, path, name, cached) { className += ' file-cached' a.setAttribute('class', className); a.setAttribute('href', '#'); - a.appendChild(document.createTextNode(this.name)); + var name = this.name; + if(this.track) + name += ' (track ' + this.track + ')'; + a.appendChild(document.createTextNode(name)); var ml = this; a.onclick = function() { @@ -104,9 +113,10 @@ function list(root) { for(var i = 0; i < json.length; i++) { var type = json[i]["type"]; var path = json[i]["name"]; + var track = json[i]["track"]; var name = path.substring(path.lastIndexOf('/')+1); var cached = type == "file" ? json[i]["cached"] : false; - var l = new MusicListing(type, path, name, cached); + var l = new MusicListing(type, path, name, track, cached); output_link(l); } } @@ -131,11 +141,11 @@ function add_directory() { var source = null; -function get_a(path) { +function get_a(path, track) { var as = document.getElementById('song-links').getElementsByTagName('a'); for(var i = 0; i < as.length; i++) { var a = as[i]; - if(a.ml.path == path) + if(a.ml.path == path && (!track || track == a.ml.track)) return a; } } @@ -146,12 +156,16 @@ function event_handler(event) { case 'cached': case 'recoding': log('[' + data['type'] + '] ' + data['path']); + var track = null; + if('track' in data) + track = data['track']; + log('track: ' + track); // update directory browser - var a = get_a(data['path']); + var a = get_a(data['path'], track); if(a) a.setAttribute('class', 'file file-' + data['type']); // update song queue - var li = playlist.get(data['path']); + var li = playlist.get(data['path'], track); if(li) { a = li.getElementsByTagName('a')[0]; if(data['type'] == 'cached') { diff --git a/static/playlist.js b/static/playlist.js index 38db463..d2ac424 100644 --- a/static/playlist.js +++ b/static/playlist.js @@ -3,12 +3,15 @@ function Playlist(pl, audio) { this.audio = audio; this.current = null; - this.get = function(path) { + this.get = function(path, track) { var li = this.pl.getElementsByTagName('li')[0]; while(li) { - var a = li.getElementsByTagName('a')[0]; - if(a.ml.path == path) - return li; + var as = li.getElementsByTagName('a'); + if(as.length > 0) { + var a = as[0]; + if(a.ml.path == path && (!track || a.ml.track == track)) + return li; + } li = li.nextElementSibling; } return null; @@ -17,7 +20,10 @@ function Playlist(pl, audio) { this.add = function(ml) { var a = document.createElement('a'); a.setAttribute('href', '#'); - a.appendChild(document.createTextNode(ml.path)); + var name = ml.name; + if(ml.track) + name += ' (track ' + ml.track + ')'; + a.appendChild(document.createTextNode(name)); a.ml = ml; var li = document.createElement('li'); var pl = this; @@ -30,9 +36,13 @@ function Playlist(pl, audio) { var nextsong = li.nextElementSibling; log('nextsong: ' + nextsong); + // avoid breaking when a track has been removed + while(nextsong && nextsong.childElementCount == 0) + nextsong = nextsong.nextElementSibling; if(nextsong) { var nexta = nextsong.getElementsByTagName('a')[0]; log('nexta: ' + nexta); + log(nexta.onclick); log('next ml: ' + nexta.ml); nexta.ml.recode(); } @@ -41,7 +51,34 @@ function Playlist(pl, audio) { } log(a.click); - li.appendChild(a); + var span = document.createElement('div'); + + // anchor to remove track from playlist + var a_del = document.createElement('a'); + a_del.setAttribute('class', 'delete'); + a_del.setAttribute('href', '#'); + a_del.setAttribute('title', 'Remove'); + var del_img = new Image(); + del_img.src = '/static/icons/delete.png'; + a_del.appendChild(del_img); + a_del.onclick = function() { + li.removeChild(span); + return false; + } + a_del.hidden = true; + + span.onmouseover = function() { + a_del.hidden = false; + } + span.onmouseout = function() { + a_del.hidden = true; + } + + span.appendChild(a); + span.appendChild(document.createTextNode(' ')); + span.appendChild(a_del); + + li.appendChild(span); this.pl.appendChild(li); if(this.pl.firstChild == li || (this.current && this.current.nextElementSibling == li)) @@ -58,6 +95,9 @@ function Playlist(pl, audio) { this.current = this.current.nextElementSibling; old.parentElement.removeChild(old); } + // avoid breaking when a track has been removed + while(this.current && this.current.childElementCount == 0) + this.current = this.current.nextElementSibling; if(this.current) { var a = this.current.getElementsByTagName('a')[0]; a.onclick(); diff --git a/static/style.css b/static/style.css index 35319c0..8f3b636 100644 --- a/static/style.css +++ b/static/style.css @@ -4,7 +4,8 @@ ul#song-links a:hover, ul#playlist a:hover { text-decoration: underline; } a.dir { background-image: url('/static/icons/folder.png'); } a.file { background-image: url('/static/icons/music.png'); } a.file-cached { background-image: url('/static/icons/music-cached.png'); } -a.dir, a.file, ul#playlist li a { background-repeat: no-repeat; padding-left: 20px; } +a.dir, a.file, ul#playlist li a:first-child { background-repeat: no-repeat; padding-left: 20px; } +ul#playlist img { vertical-align: middle; } a.file-recoding { background-image: url('/static/icons/loading.gif'); } a.file-queued { background-image: url('/static/icons/music-queued.png'); } div#hpanel { margin-top: 1em; } @@ -14,3 +15,4 @@ ul#playlist li a.playing { background-image: url('/static/icons/sound.png'); } span.list-header { font-size: large; } ul#song-links { width: 30em; overflow: auto; white-space: nowrap; resize: both; } a#add-dir { font-size: small; } +span#playlist-span { position: absolute; left: 30em; right: 1em; } -- cgit v1.2.3