// Probe for supported codecs AUDIO_CODECS = [ 'audio/ogg', 'audio/mpeg', 'audio/flac', ]; timeout = null; es = null; prev = null; function humanize_duration(d) { var seconds = Math.floor(d % 60); var minutes = Math.floor(d / 60) % 60; var hours = Math.floor(d / 3600); if (seconds < 10) seconds = '0' + seconds; if (minutes < 10) minutes = '0' + minutes; if (hours < 10) hours = '0' + hours; return hours + ":" + minutes + ":" + seconds; } function onDelayedSearch() { var expr = $("#search").val(); if (expr == window.expr) return; console.info("Searching", expr); results.rows().clear().draw(false); if (es) { es.close(); $("#results tbody").empty(); } es = new EventSource("/api/search/?expr=" + expr); // Close socket event listener es.addEventListener("close", function(e) { console.info("Closing search socket"); }); // Open socket event listener es.addEventListener("open", function(e) { console.info("Opened event stream for search expression", expr); }) // Search end result marker es.addEventListener("done", function(e) { var totals = JSON.parse(e.data) console.info("Finished searching, total", totals.relevant_files, "relevant files and", totals.hits, "hits"); es.close(); }) // Keep track of relative path of the XSPF blobs es.addEventListener("chdir", function(e) { console.info("Moving to directory:", e.data); window.relpath = e.data; }) // If XSPF blob is received append it to search results es.addEventListener("xspf", function(e) { var $trackMetadatas = $("playlist trackList track", $.parseXML(e.data)); $trackMetadatas.each(function(index, element) { var location = element.getElementsByTagName("location")[0]; var filename = location.innerHTML; // Decode escaped XML var filename = decodeURIComponent(location.innerHTML); if (filename.indexOf("/") >= 0) { filename = filename.substring(filename.lastIndexOf("/") + 1); } // Escape quotes for jQuery filename = filename.replace("\"", "\\\""); results.row.add([ window.relpath + "/" + filename, $("creator", element).html() || "-", $("album", element).html() || "-", $("trackNum", element).html() || "-", $("title", element).html() || "-", humanize_duration(parseInt($("duration", element).html())/1000), $("meta[rel='mimetype']", element).html(), Math.floor(parseInt($("meta[rel='bitrate']", element).html())/1000)+"kbps", // $("meta[rel='bit_depth']", element).html() + "bit @ " + $("meta[rel='sample_rate']", element).html(), "bla" ]).on('click', 'tr', function () { $(this).toggleClass('selected'); }); clearTimeout(window.timeoutDraw); window.timeoutDraw = setTimeout(results.draw, 100); }); }); } function playNextAudioTrack() { queue.row(queue.row({selected:true}).index()+1).select(); } function playPrevAudioTrack() { queue.row(queue.row({selected:true}).index()-1).select(); } function playTrack(url, mimetype) { var url = "/api/stream/" + url; console.info("Playing:", url, mimetype); $("#seek").val(0); $("#offset").html("00:00:00"); $("#player").unbind("ended").bind("ended", function () { playNextAudioTrack(); }); $("#player").empty(); if (window.AUDIO_CODECS_SUPPORTED.indexOf(mimetype) >= 0) { $("#player").append(""); } else { console.info("Codec", mimetype, "not supported by browser"); } for (var j = 0; j < window.AUDIO_CODECS_SUPPORTED.length; j++) { var alternative = window.AUDIO_CODECS_SUPPORTED[j]; if (mimetype != alternative) { $("#player").append(""); } } $("#player").trigger("load"); $("#player").trigger("play"); } $(document).ready(function() { $('#results tbody').on('dblclick', 'tr', function () { console.info("Got double click"); queue.rows.add(results.rows({ selected: true }).data()); queue.rows.add([results.row(this).data()]); results.rows().deselect(); results.draw(false); queue.draw(false); }); $("#playback-next").on("click", function() { playNextAudioTrack(); }); $("#playback-prev").on("click", function() { playPrevAudioTrack(); }); $("#queue-selection").on("click", function() { queue.rows.add(results.rows({ selected: true }).data()).draw(false); }); $("#queue-all").on("click", function() { queue.rows.add(results.data()).draw(false); }); $("#queue thead").html($("#results thead").html()); $("#queue-clear").on("click", function() { queue.rows().clear().draw(false); }); window.results = $('#results').DataTable({ autoWidth: false, columns: [ null, {width:"20%"}, {width:"20%"}, {width:"1em"}, {width:"20%"}, ], paging: true, ordering: false, searching: false, select: { style: 'multi' }, columnDefs: [ { "targets": [ 0, 6, 7, 8 ], "visible": false, "searchable": false }, ] }); window.queue = $('#queue').DataTable({ autoWidth: false, columns: [ null, {width:"20%"}, {width:"20%"}, {width:"1em"}, {width:"20%"}, ], paging: true, ordering: false, searching: false, select: { style: 'single' }, columnDefs: [ { "targets": [ 0, 6, 7, 8 ], "visible": false, "searchable": false }, ], }).on("select", function(e, dt, type, indexes) { var item = queue.row(indexes).data(); playTrack(item[0], item[6]); }); window.AUDIO_CODECS_SUPPORTED = []; var audioPlayer = document.getElementById("player"); for (var j = 0; j < window.AUDIO_CODECS.length; j++) { if (audioPlayer.canPlayType(window.AUDIO_CODECS[j])) { window.AUDIO_CODECS_SUPPORTED.push(AUDIO_CODECS[j]); } } console.info("This browser supports following audio codecs:", window.AUDIO_CODECS_SUPPORTED); $("#search").keyup(function() { if (prev == $("#search").val()) return; prev = $("#search").val(); clearTimeout(window.timeout); window.timeout = setTimeout(function() { onDelayedSearch(); }, 200); }); });