123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- /* ympd
- (c) 2013-2014 Andrew Karpow <andy@ndyk.de>
- This project's homepage is: http://www.ympd.org
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- var socket;
- var last_state;
- var current_app;
- var lastSongTitle = "";
- var current_song = new Object();
- var app = $.sammy(function() {
- this.before('/', function(e, data) {
- $('#nav_links > li').removeClass('active');
- });
- this.get('#/', function() {
- current_app = 'queue';
- $('#breadcrump').addClass('hide');
- $('#salamisandwich').find("tr:gt(0)").remove();
- socket.send('MPD_API_GET_QUEUE');
- $('#panel-heading').text("Queue");
- $('#queue').addClass('active');
- });
- this.get(/\#\/browse\/(.*)/, function() {
- current_app = 'browse';
- $('#breadcrump').removeClass('hide').empty().append("<li><a href=\"#/browse/\">root</a></li>");
- $('#salamisandwich').find("tr:gt(0)").remove();
- var path = this.params['splat'][0];
- socket.send('MPD_API_GET_BROWSE,' + path);
- $('#panel-heading').text("Browse database: "+path);
- var path_array = path.split('/');
- var full_path = "";
- $.each(path_array, function(index, chunk) {
- if(path_array.length - 1 == index) {
- $('#breadcrump').append("<li class=\"active\">"+ chunk + "</li>");
- return;
- }
- full_path = full_path + chunk;
- $('#breadcrump').append("<li><a href=\"#/browse/" + full_path + "\">"+chunk+"</a></li>");
- full_path += "/";
- });
- $('#browse').addClass('active');
- });
- this.get(/\#\/search\/(.*)/, function() {
- current_app = 'search';
- $('#salamisandwich').find("tr:gt(0)").remove();
- var searchstr = this.params['splat'][0];
- $('#search > div > input').val(searchstr);
- socket.send('MPD_API_SEARCH,' + searchstr);
- $('#panel-heading').text("Search: "+searchstr);
- });
- this.get("/", function(context) {
- context.redirect("#/");
- });
- });
- $(document).ready(function(){
- webSocketConnect();
- $("#volumeslider").slider(0);
- $("#volumeslider").on('slider.newValue', function(evt,data){
- socket.send("MPD_API_SET_VOLUME,"+data.val);
- });
- $('#progressbar').slider(0);
- $("#progressbar").on('slider.newValue', function(evt,data){
- if(current_song && current_song.currentSongId >= 0) {
- var seekVal = Math.ceil(current_song.totalTime*(data.val/100));
- socket.send("MPD_API_SET_SEEK,"+current_song.currentSongId+","+seekVal);
- }
- });
- if(!notificationsSupported())
- $('#btnnotify').addClass("disabled");
- else
- if ($.cookie("notification") === "true")
- $('#btnnotify').addClass("active")
- });
- function webSocketConnect() {
- if (typeof MozWebSocket != "undefined") {
- socket = new MozWebSocket(get_appropriate_ws_url());
- } else {
- socket = new WebSocket(get_appropriate_ws_url());
- }
- try {
- socket.onopen = function() {
- console.log("connected");
- $('.top-right').notify({
- message:{text:"Connected to ympd"},
- fadeOut: { enabled: true, delay: 500 }
- }).show();
- app.run();
- }
- socket.onmessage =function got_packet(msg) {
- if(msg.data === last_state)
- return;
- var obj = JSON.parse(msg.data);
- switch (obj.type) {
- case "queue":
- if(current_app !== 'queue')
- break;
- $('#salamisandwich > tbody').empty();
- for (var song in obj.data) {
- var minutes = Math.floor(obj.data[song].duration / 60);
- var seconds = obj.data[song].duration - minutes * 60;
- $('#salamisandwich > tbody').append(
- "<tr trackid=\"" + obj.data[song].id + "\"><td>" + (obj.data[song].pos + 1) + "</td>" +
- "<td>"+ obj.data[song].title +"</td>" +
- "<td>"+ minutes + ":" + (seconds < 10 ? '0' : '') + seconds +
- "</td><td></td></tr>");
- }
- $('#salamisandwich > tbody > tr').on({
- mouseover: function(){
- if($(this).children().last().has("a").length == 0)
- $(this).children().last().append(
- "<a class=\"pull-right btn-group-hover\" href=\"#/\" " +
- "onclick=\"socket.send('MPD_API_RM_TRACK," + $(this).attr("trackid") +"'); $(this).parents('tr').remove();\">" +
- "<span class=\"glyphicon glyphicon-trash\"></span></a>")
- .find('a').fadeTo('fast',1);
- },
- click: function() {
- $('#salamisandwich > tbody > tr').removeClass('active');
- socket.send('MPD_API_PLAY_TRACK,'+$(this).attr('trackid'));
- $(this).addClass('active');
- },
- mouseleave: function(){
- $(this).children().last().find("a").stop().remove();
- }
- });
- break;
- case "search":
- case "browse":
- if(current_app !== 'browse' && current_app !== 'search')
- break;
- for (var item in obj.data) {
- switch(obj.data[item].type) {
- case "directory":
- $('#salamisandwich > tbody').append(
- "<tr uri=\"" + obj.data[item].dir + "\" class=\"dir\">" +
- "<td><span class=\"glyphicon glyphicon-folder-open\"></span></td>" +
- "<td><a>" + basename(obj.data[item].dir) + "</a></td>" +
- "<td></td><td></td></tr>"
- );
- break;
- case "playlist":
- $('#salamisandwich > tbody').append(
- "<tr uri=\"" + obj.data[item].plist + "\" class=\"plist\">" +
- "<td><span class=\"glyphicon glyphicon-list\"></span></td>" +
- "<td><a>" + basename(obj.data[item].plist) + "</a></td>" +
- "<td></td><td></td></tr>"
- );
- break;
- case "song":
- var minutes = Math.floor(obj.data[item].duration / 60);
- var seconds = obj.data[item].duration - minutes * 60;
- $('#salamisandwich > tbody').append(
- "<tr uri=\"" + obj.data[item].uri + "\" class=\"song\">" +
- "<td><span class=\"glyphicon glyphicon-music\"></span></td>" +
- "<td>" + obj.data[item].title +"</td>" +
- "<td>"+ minutes + ":" + (seconds < 10 ? '0' : '') + seconds +
- "</td><td></td></tr>"
- );
- break;
- }
- }
- function appendClickableIcon(appendTo, onClickAction, glyphicon) {
- $(appendTo).children().last().append(
- "<a role=\"button\" class=\"pull-right btn-group-hover\">" +
- "<span class=\"glyphicon glyphicon-" + glyphicon + "\"></span></a>")
- .find('a').click(function(e) {
- e.stopPropagation();
- socket.send(onClickAction + "," + $(this).parents("tr").attr("uri"));
- $('.top-right').notify({
- message:{
- text: $('td:nth-child(2)', $(this).parents("tr")).text() + " added"
- } }).show();
- }).fadeTo('fast',1);
- }
- $('#salamisandwich > tbody > tr').on({
- mouseenter: function() {
- if($(this).is(".dir"))
- appendClickableIcon($(this), 'MPD_API_ADD_TRACK', 'plus');
- else if($(this).is(".song"))
- appendClickableIcon($(this), 'MPD_API_ADD_PLAY_TRACK', 'play');
- },
- click: function() {
- if($(this).is(".dir"))
- app.setLocation("#/browse/"+$(this).attr("uri"));
- else {
- if($(this).is(".song"))
- socket.send("MPD_API_ADD_TRACK," + $(this).attr("uri"));
- else
- socket.send("MPD_API_ADD_PLAYLIST," + $(this).attr("uri"));
- $('.top-right').notify({
- message:{
- text: $('td:nth-child(2)', this).text() + " added"
- }
- }).show();
- }
- },
- mouseleave: function(){
- $(this).children().last().find("a").stop().remove();
- }
- });
- break;
- case "state":
- updatePlayIcon(obj.data.state);
- updateVolumeIcon(obj.data.volume);
- if(JSON.stringify(obj) === JSON.stringify(last_state))
- break;
- current_song.totalTime = obj.data.totalTime;
- current_song.currentSongId = obj.data.currentsongid;
- var total_minutes = Math.floor(obj.data.totalTime / 60);
- var total_seconds = obj.data.totalTime - total_minutes * 60;
- var elapsed_minutes = Math.floor(obj.data.elapsedTime / 60);
- var elapsed_seconds = obj.data.elapsedTime - elapsed_minutes * 60;
- $('#volumeslider').slider(obj.data.volume);
- var progress = Math.floor(100*obj.data.elapsedTime/obj.data.totalTime);
- $('#progressbar').slider(progress);
- $('#counter')
- .text(elapsed_minutes + ":" +
- (elapsed_seconds < 10 ? '0' : '') + elapsed_seconds + " / " +
- total_minutes + ":" + (total_seconds < 10 ? '0' : '') + total_seconds);
- $('#salamisandwich > tbody > tr').removeClass('active').css("font-weight", "");
- $('#salamisandwich > tbody > tr[trackid='+obj.data.currentsongid+']').addClass('active').css("font-weight", "bold");
- if(obj.data.random)
- $('#btnrandom').addClass("active")
- else
- $('#btnrandom').removeClass("active");
- if(obj.data.consume)
- $('#btnconsume').addClass("active")
- else
- $('#btnconsume').removeClass("active");
- if(obj.data.single)
- $('#btnsingle').addClass("active")
- else
- $('#btnsingle').removeClass("active");
- if(obj.data.repeat)
- $('#btnrepeat').addClass("active")
- else
- $('#btnrepeat').removeClass("active");
- last_state = obj;
- break;
- case "disconnected":
- if($('.top-right').has('div').length == 0)
- $('.top-right').notify({
- message:{text:"ympd lost connection to MPD "},
- type: "danger",
- fadeOut: { enabled: true, delay: 1000 },
- }).show();
- break;
- case "update_queue":
- if(current_app === 'queue')
- socket.send('MPD_API_GET_QUEUE');
- break;
- case "song_change":
- $('#currenttrack').text(" " + obj.data.title);
- var notification = "<strong><h4>" + obj.data.title + "</h4></strong>";
- if(obj.data.album) {
- $('#album').text(obj.data.album);
- notification += obj.data.album + "<br />";
- }
- if(obj.data.artist) {
- $('#artist').text(obj.data.artist);
- notification += obj.data.artist + "<br />";
- }
- if ($.cookie("notification") === "true")
- songNotify(obj.data.title, obj.data.artist + " " + obj.data.album );
- else
- $('.top-right').notify({
- message:{html: notification},
- type: "info",
- }).show();
-
- break;
- case "mpdhost":
- $('#mpdhost').val(obj.data.host);
- $('#mpdport').val(obj.data.port);
- if(obj.data.passwort_set) {
- $('#mpd_pw').attr('placeholder', '*******');
- $('#mpd_pw_con').attr('placeholder', '*******');
- }
- break;
- case "error":
- $('.top-right').notify({
- message:{text: obj.data},
- type: "danger",
- }).show();
- default:
- break;
- }
- }
- socket.onclose = function(){
- console.log("disconnected");
- $('.top-right').notify({
- message:{text:"Connection to ympd lost, retrying in 3 seconds "},
- type: "danger",
- onClose: function () {
- webSocketConnect();
- }
- }).show();
- }
- } catch(exception) {
- alert('<p>Error' + exception);
- }
- }
- function get_appropriate_ws_url()
- {
- var pcol;
- var u = document.URL;
- /*
- /* We open the websocket encrypted if this page came on an
- /* https:// url itself, otherwise unencrypted
- /*/
- if (u.substring(0, 5) == "https") {
- pcol = "wss://";
- u = u.substr(8);
- } else {
- pcol = "ws://";
- if (u.substring(0, 4) == "http")
- u = u.substr(7);
- }
- u = u.split('/');
- return pcol + u[0];
- }
- var updateVolumeIcon = function(volume)
- {
- $("#volume-icon").removeClass("glyphicon-volume-off");
- $("#volume-icon").removeClass("glyphicon-volume-up");
- $("#volume-icon").removeClass("glyphicon-volume-down");
- if(volume == 0) {
- $("#volume-icon").addClass("glyphicon-volume-off");
- } else if (volume < 50) {
- $("#volume-icon").addClass("glyphicon-volume-down");
- } else {
- $("#volume-icon").addClass("glyphicon-volume-up");
- }
- }
- var updatePlayIcon = function(state)
- {
- $("#play-icon").removeClass("glyphicon-play")
- .removeClass("glyphicon-pause");
- $('#track-icon').removeClass("glyphicon-play")
- .removeClass("glyphicon-pause")
- .removeClass("glyphicon-stop");
- if(state == 1) { // stop
- $("#play-icon").addClass("glyphicon-play");
- $('#track-icon').addClass("glyphicon-stop");
- } else if(state == 2) { // pause
- $("#play-icon").addClass("glyphicon-pause");
- $('#track-icon').addClass("glyphicon-play");
- } else { // play
- $("#play-icon").addClass("glyphicon-play");
- $('#track-icon').addClass("glyphicon-pause");
- }
- }
- function updateDB() {
- socket.send('MPD_API_UPDATE_DB');
- $('.top-right').notify({
- message:{text:"Updating MPD Database... "}
- }).show();
- }
- function clickPlay() {
- if($('#track-icon').hasClass('glyphicon-stop'))
- socket.send('MPD_API_SET_PLAY');
- else
- socket.send('MPD_API_SET_PAUSE');
- }
- function basename(path) {
- return path.split('/').reverse()[0];
- }
- $('#btnrandom').on('click', function (e) {
- socket.send("MPD_API_TOGGLE_RANDOM," + ($(this).hasClass('active') ? 0 : 1));
- });
- $('#btnconsume').on('click', function (e) {
- socket.send("MPD_API_TOGGLE_CONSUME," + ($(this).hasClass('active') ? 0 : 1));
- });
- $('#btnsingle').on('click', function (e) {
- socket.send("MPD_API_TOGGLE_SINGLE," + ($(this).hasClass('active') ? 0 : 1));
- });
- $('#btnrepeat').on('click', function (e) {
- socket.send("MPD_API_TOGGLE_REPEAT," + ($(this).hasClass('active') ? 0 : 1));
- });
- $('#btnnotify').on('click', function (e) {
- if($.cookie("notification") === "true")
- $.cookie("notification", false);
- else {
- window.webkitNotifications.requestPermission();
- if (window.webkitNotifications.checkPermission() == 0)
- {
- $.cookie("notification", true);
- $('btnnotify').addClass("active");
- }
- }
- });
- function getHost() {
- socket.send('MPD_API_GET_MPDHOST');
- function onEnter(event) {
- if ( event.which == 13 ) {
- confirmSettings();
- }
- }
- $('#mpdhost').keypress(onEnter);
- $('#mpdport').keypress(onEnter);
- $('#mpd_pw').keypress(onEnter);
- $('#mpd_pw_con').keypress(onEnter);
- }
- $('#search').submit(function () {
- app.setLocation("#/search/"+$('#search > div > input').val());
- return false;
- });
- function confirmSettings() {
- if($('#mpd_pw').val().length + $('#mpd_pw_con').val().length > 0) {
- if ($('#mpd_pw').val() !== $('#mpd_pw_con').val())
- {
- $('#mpd_pw_con').popover('show');
- setTimeout(function() {
- $('#mpd_pw_con').popover('hide');
- }, 2000);
- return;
- } else
- socket.send('MPD_API_SET_MPDPASS,'+$('#mpd_pw').val());
- }
- socket.send('MPD_API_SET_MPDHOST,'+$('#mpdport').val()+','+$('#mpdhost').val());
- $('#settings').modal('hide');
- }
- function notificationsSupported() {
- return "webkitNotifications" in window;
- }
- function songNotify(artist, title) {
- if (!notificationsSupported())
- return;
- if (window.webkitNotifications.checkPermission() == 0) {
- var notification = window.webkitNotifications.createNotification("assets/favicon.ico", artist, title);
- notification.show();
- setTimeout(function(notification) {
- notification.cancel();
- }, 3000, notification);
- } else {
- window.webkitNotifications.requestPermission();
- }
- }
|