Косметические доработки интерфейса.
[mpd-lua.git] / mpd.js
1 urlbase="mpd.lua?"
2 minScrollHeight=200
3
4 currentState=""
5
6 function GetFilename(url)
7 {
8    if (url)
9    return url.split('/').pop().split('#')[0].split('?')[0];
10 }
11
12 function EscapeStr(str) {
13   res = str.replace(/'/g,"\\'");
14   return res;
15 }
16
17 function SetSize() {
18   var w = window,
19       d = document,
20       e = d.documentElement,
21       g = d.getElementsByTagName('body')[0],
22       body_h = g.clientHeight,
23       window_h = w.innerHeight|| e.clientHeight|| g.clientHeight,
24       items = d.getElementById('items'),
25       current_h = items.clientHeight,
26       new_h=(window_h-body_h)+current_h;
27       if (new_h>minScrollHeight) {
28         items.style.height=new_h+"px";
29       }
30 }
31
32 function toHHMMSS(seconds) {
33     var hours = Math.floor(seconds / 3600);
34     seconds -= hours*3600;
35     var minutes = Math.floor(seconds / 60);
36     seconds -= minutes*60;
37
38     if (hours   < 10) {hours   = "0"+hours;}
39     if (minutes < 10) {minutes = "0"+minutes;}
40     if (seconds < 10) {seconds = "0"+seconds;}
41     if (hours == 0) {
42      return minutes+':'+seconds;
43     } else {
44      return hours+':'+minutes+':'+seconds;
45     }
46 }
47
48 function RefreshTime() {
49   if (currentSeconds) {
50     currentTime = toHHMMSS(currentSeconds)
51     trackTime = toHHMMSS(trackSeconds)
52     nowPlayingTime = currentTime+"/"+trackTime
53   } else {
54     nowPlayingTime = "-:--/-:--"
55   }
56   document.getElementById('nowplaying_tracklen').innerHTML=nowPlayingTime;
57 }
58
59 function PeriodicRefreshTime() {
60   if (currentState == "play") {
61     nowTime = Date.now()
62     delta = (nowTime - updateTime)/1000
63     currentSeconds = updateSeconds + Math.round(delta)
64     if (currentSeconds > trackSeconds) {
65       currentSeconds = trackSeconds
66     }
67     RefreshTime()
68   }
69 }
70
71 function RefreshPageStatus() {
72
73   var req = new XMLHttpRequest();
74
75   req.onreadystatechange = function () {
76     if (this.readyState != 4 || this.status != 200) return;
77     var returnedData = JSON.parse(this.responseText);
78     trackName = GetFilename(returnedData['current_playing']);
79     trackNo = returnedData['song'];
80     currentState = returnedData['state'];
81     document.title='MPD Player: '+trackName;
82     if (trackNo) {
83       var nowPlayingTrackNo=String(1+Number(trackNo))
84     } else {
85       var nowPlayingTrackNo="--"
86     }
87     nowPlayingTrack = nowPlayingTrackNo + '/' + returnedData['playlistlength'];
88     nowPlayingName = trackName;
89     playingTime = returnedData['time']
90     if (playingTime) {
91       var splits = playingTime.split(":")
92       updateTime = Date.now()
93       currentSeconds = Number(splits[0])
94       updateSeconds = currentSeconds
95       trackSeconds = Number(splits[1])
96     } else {
97       currentSeconds = null
98     }
99     if (currentState=='stop') {
100       nowPlayingName = '<font color="gray">' + nowPlayingName+ '</font>'
101     }
102     document.getElementById('nowplaying_trackno').innerHTML=nowPlayingTrack;
103     document.getElementById('nowplaying_trackname').innerHTML=nowPlayingName;
104     RefreshTime()
105     if (currentState=="play") {
106       document.getElementById('playpausebutton').innerHTML="<span onclick=\"Command('pause')\"><img class=\"button\" title=\"Pause\" src=\"images/pause.svg\"></span>";
107     } else {
108       document.getElementById('playpausebutton').innerHTML="<span onclick=\"Command('play')\"><img class=\"button\" title=\"Play\" src=\"images/play-button.svg\"></span>";
109     }
110     if (currentState=="stop") {
111       document.getElementById('stopbutton').innerHTML="<span><img class=\"button\" src=\"images/stopoff.svg\"></span>";
112     } else {
113       document.getElementById('stopbutton').innerHTML="<span onclick=\"Command('stop')\"><img class=\"button\" title=\"Stop\" src=\"images/stop.svg\"></span>";
114     }
115     if (returnedData["repeat"]=="1") {
116       document.getElementById('repeatstate').innerHTML="<img class=\"button\" title=\"Replay is on\" src=\"images/replay.svg\"></a>";
117     } else {
118       document.getElementById('repeatstate').innerHTML="<img class=\"button\" title=\"Replay is off\" src=\"images/replayoff.svg\"></a>";
119     }
120     document.getElementById('volume_total').innerHTML="<div id=\"volume_actual\" style=\"width:"+returnedData["volume"]+"%\">";
121
122     var items = document.getElementById('items');
123     var table = items.getElementsByClassName('track');
124     var current_track="track_"+trackNo;
125     for (var i = 0; i < table.length; i++) {
126       if (table[i].id==current_track) {
127         table[i].classList.add("itemActive");
128       } else {
129         table[i].classList.remove("itemActive")
130       }
131     }
132         
133   };
134
135   req.open("GET", urlbase+"status", true);
136   req.send();
137
138 }
139
140 function RefreshPlaylist() {
141
142 var req = new XMLHttpRequest();
143
144 req.onreadystatechange = function () {
145   if (this.readyState != 4 || this.status != 200) return;
146   var returnedData = JSON.parse(this.responseText);
147
148   var playlistMenuText = "<table>\
149   <tr>\
150   <td><span onclick=\"EditPlayList()\"><img class=\"medium-button\" title=\"Files\" src=\"images/folder.svg\"></span><td>\
151   <td><span onclick=\"LoadPlayList()\"><img class=\"medium-button\" title=\"Lists\" src=\"images/list.svg\"></span><td>\
152   <td><span onclick=\"SavePlayList()\"><img class=\"medium-button\" title=\"Save current list\" src=\"images/download.svg\"></span><td>\
153   <td><span onclick=\"return confirm('Clear current playlist, are you sure?') ? PlaylistCommand('clear') : false;\" ><img class=\"medium-button\" title=\"Clear current list\"  src=\"images/cancel.svg\"></span><td>\
154   </tr>\
155   </table>";
156
157   var itemsText="<table>\
158   <tr id=\"items_heading\">\
159   <td></td class=\"track_number\"><td class=\"file\">Title</td><td class=\"medium-button\" colspan=\"3\">Controls</td>\
160   </tr>";
161
162   var even = 0;
163   for (var key in returnedData) {
164        var rec=returnedData[key];
165        var name=GetFilename(rec["name"]);
166        var id=rec["id"];
167
168        if (even) { 
169          evText="itemEven"; 
170        } else { 
171          evText="itemOdd";
172        };
173
174        even = ! even;
175
176        itemsText = itemsText + "<tr id=\"track_"+id+"\" class=\"track "+evText+"\">\
177   <td class=\"track_number\">\
178   <a name=\""+id+"\">"+(Number(id)+1)+"</a></td>\
179   </td>\
180   <td class=\"file\">\
181   <span class=\"link\" onclick=\"PlaylistCommand('playitem',"+id+")\">"+name+"</span>\
182   </td>\
183   <td class=\"move\">\
184   <span onclick=\"PlaylistCommand('moveup',"+id+")\"><img class=\"small-button\" title=\"Move up\" src=\"images/up-arrow.svg\"></span>\
185   </td>\
186   <td class=\"move\">\
187   <span onclick=\"PlaylistCommand('movedown',"+id+")\"><img class=\"small-button\" title=\"Move down\" src=\"images/down-arrow.svg\"></span>\
188   </td>\
189   <td class=\"remove\">\
190   <span onclick=\"PlaylistCommand('remove',"+id+")\"><img class=\"small-button\" title=\"Remove\" src=\"images/cancel.svg\"></span>\
191   </td>\
192   </tr>"; 
193   }
194
195   itemsText = itemsText + "</table>";
196
197   document.getElementById('items').innerHTML=itemsText;
198   document.getElementById('playlist_menu_top').innerHTML=playlistMenuText;
199   document.getElementById('playlist_menu_bottom').innerHTML=playlistMenuText;
200 };
201
202 req.open("GET", urlbase+"playlist", true);
203 req.send();
204
205 }
206
207 function EditPlayList(dir) {
208
209 var req = new XMLHttpRequest();
210
211 req.onreadystatechange = function () {
212   if (this.readyState != 4 || this.status != 200) return;
213   var returnedData = JSON.parse(this.responseText);
214
215   var playlistMenuText = "<table>\
216   <tr>\
217   <td><span onclick=\"RefreshPlaylist()\"><img class=\"medium-button\" title=\"Home\" src=\"images/list.svg\"></span><td>\
218   <td><span onclick=\"return confirm('Add all to the list, are you sure?') ? PlaylistEditCommand('add','"+EscapeStr(dir)+"') : false;\" ><img class=\"medium-button\" title=\"Add all\" src=\"images/plus.svg\"></span><td>\
219   </tr>\
220   </table>";
221
222   var itemsText= "<table>\
223   <tr id=\"items_heading\">\
224   <td></td class=\"track_number\"><td class=\"file\">Title</td><td colspan=\"2\">Controls</td>\
225   </tr>";
226
227   var even = 0;
228   if (dir) {
229     var lastSlash=dir.lastIndexOf("/");
230     if (lastSlash>0) {
231       var upperLevel=dir.slice(0,lastSlash);
232     } else {
233       var upperLevel="";
234     }
235     even = ! even;
236     var itemsText = itemsText + "<tr class=\"itemOdd\">\
237   <td class=\"track_number\"></td>\
238   <td class=\"file\"><span class=\"link\" onclick=\"EditPlayList('"+upperLevel+"')\">..</span></td>\
239   <td></td><td></td>";
240   } 
241
242   var i = 0;
243   for (var key in returnedData) {
244        var rec=returnedData[key];
245        var type=rec["type"];
246        var name=rec["name"];
247        var lastSlash=name.lastIndexOf("/");
248        if (lastSlash>0) {
249          var tailName=name.slice(lastSlash+1);
250        } else {
251          var tailName=name
252        };
253
254        if (type == "directory" || type == "file") {
255          if (even) { 
256            evText="itemEven"; 
257          } else { 
258            evText="itemOdd";
259          };
260
261          i = i + 1;
262          even = ! even;
263
264          itemsText = itemsText + "<tr class=\""+evText+"\">\
265            <td class=\"track_number\">\
266            <a name=\""+i+"\"></a></td>\
267            </td>";
268       
269          if (type == "directory") {
270            itemsText = itemsText + "<td class=\"file\">\
271              <span class=\"link\" onclick=\"EditPlayList('"+EscapeStr(name)+"')\">"+tailName+"</span></td><td>\
272              <span onclick=\"PlaylistEditCommand('add','"+EscapeStr(name)+"')\"><img class=\"small-button\" title=\"Add\" src=\"images/plus.svg\"></span></td>";
273          }; 
274
275          if (type == "file") {
276            itemsText = itemsText + "<td class=\"file\">\
277              <span class=\"link\" onclick=\"PlaylistEditCommand('add','"+EscapeStr(name)+"')\">"+tailName+"</span></td><td>\
278              <span onclick=\"PlaylistEditCommand('add','"+EscapeStr(name)+"')\"><img class=\"small-button\" title=\"Add\" src=\"images/plus.svg\"></span></td>";
279          };
280
281          itemsText = itemsText + "</tr>";
282
283        }       
284        
285   }
286
287   var itemsText = itemsText+"</table>";
288   document.getElementById('items').innerHTML=itemsText;
289   document.getElementById('playlist_menu_top').innerHTML=playlistMenuText;
290   document.getElementById('playlist_menu_bottom').innerHTML=playlistMenuText;
291 };
292
293 if (!dir) { dir = ''; };
294
295 req.open("GET", urlbase+"lists|edit|"+dir, true);
296 req.send();
297
298 }
299
300 function LoadPlayList() {
301
302 var req = new XMLHttpRequest();
303
304 req.onreadystatechange = function () {
305   if (this.readyState != 4 || this.status != 200) return;
306   var returnedData = JSON.parse(this.responseText);
307   playlistMenuText="<table>\
308     <tr>\
309       <td><span onclick=\"RefreshPlaylist()\"><img class=\"medium-button\" title=\"Home\" src=\"images/list.svg\"></span><td>\
310       <td><span onclick=\"confirm('Clear current playlist, are you sure?') ? PlaylistCommandRefStatus('clear') : false;\" ><img class=\"medium-button\" title=\"Clear all\" src=\"images/cancel.svg\"></span><td>\
311     </tr>\
312     </table>";
313   itemsText="<table>\
314     <tr id=\"items_heading\">\
315       <td class=\"track_number\"></td><td class=\"file\">Name</td><td>Controls</td>\
316     </tr>";
317
318   var even = 0;
319   for (var key in returnedData) {
320        var name=returnedData[key];
321
322        if (even) { 
323          evText="itemEven"; 
324        } else { 
325          evText="itemOdd";
326        };
327
328        even = ! even;
329
330        itemsText = itemsText + "<tr class=\""+evText+"\">\
331       <td class=\"track_number\"><a name=\"0\"></a></td>\
332       <td class=\"file\"><span class=\"link\" onclick=\"PlaylistEditCommandRefFull('load','"+EscapeStr(name)+"')\">"+name+"</td>\
333       <td class=\"controls\"><span onclick=\"confirm('Delete playlist "+name+", are you sure?') ? DelPlayList('"+EscapeStr(name)+"') : false;\"><img class=\"small-button\" title=\"Delete\" src=\"images/minus.svg\"></span></td>\
334     </tr>";
335   }
336
337   itemsText=itemsText+"</table>";
338   document.getElementById('items').innerHTML=itemsText;
339   document.getElementById('playlist_menu_top').innerHTML=playlistMenuText;
340   document.getElementById('playlist_menu_bottom').innerHTML=playlistMenuText;
341 };
342
343 req.open("GET", urlbase+"lists|load", true);
344 req.send();
345
346 }
347
348 function SavePlayList() {
349
350 var name=window.prompt('List name','');
351
352 var req = new XMLHttpRequest();
353
354 req.onreadystatechange = function () {
355   if (this.readyState != 4 || this.status != 200) return;
356   if (this.responseText != 'OK') {
357     window.alert(this.responseText);
358   }
359 };
360
361 req.open("GET", urlbase+"lists|save|"+name, true);
362 req.send();
363
364 }
365
366 function DelPlayList(item) {
367
368 var req = new XMLHttpRequest();
369
370 req.onreadystatechange = function () {
371   if (this.readyState != 4 || this.status != 200) return;
372   LoadPlayList();
373   RefreshPageStatus();
374 };
375
376 req.open("GET", urlbase+"lists|delete|"+item, true);
377 req.send();
378
379 }
380
381 function RefreshPageContent() {
382   RefreshPlaylist();
383   RefreshPageStatus();
384 }
385
386 function Command(cmd) {
387
388 var req = new XMLHttpRequest();
389
390 req.onreadystatechange = function () {
391   if (this.readyState != 4 || this.status != 200) return;
392   RefreshPageStatus();
393 };
394
395 req.open("GET", urlbase+cmd, true);
396 req.send();
397
398 }
399
400 function PlaylistCommand(cmd,item) {
401
402 var req = new XMLHttpRequest();
403
404 req.onreadystatechange = function () {
405   if (this.readyState != 4 || this.status != 200) return;
406   RefreshPageContent();
407 };
408
409 req.open("GET", urlbase+"cpl|"+cmd+"|"+item, true);
410 req.send();
411
412 }
413
414 function PlaylistCommandRefStatus(cmd,item) {
415
416 var req = new XMLHttpRequest();
417
418 req.onreadystatechange = function () {
419   if (this.readyState != 4 || this.status != 200) return;
420   RefreshPageStatus();
421 };
422
423 req.open("GET", urlbase+"cpl|"+cmd+"|"+item, true);
424 req.send();
425
426 }
427
428 function PlaylistEditCommand(cmd,item) {
429
430 var req = new XMLHttpRequest();
431
432 req.onreadystatechange = function () {
433   if (this.readyState != 4 || this.status != 200) return;
434   RefreshPageStatus();
435 };
436
437 req.open("GET", urlbase+"lists|"+cmd+"|"+item, true);
438 req.send();
439
440 }
441
442 function PlaylistEditCommandRefFull(cmd,item) {
443
444 var req = new XMLHttpRequest();
445
446 req.onreadystatechange = function () {
447   if (this.readyState != 4 || this.status != 200) return;
448   RefreshPageContent();
449 };
450
451 req.open("GET", urlbase+"lists|"+cmd+"|"+item, true);
452 req.send();
453
454 }
455
456 function subscribe_status() {
457   var xhr = new XMLHttpRequest();
458
459   xhr.onreadystatechange = function() {
460     if (this.readyState != 4) return;
461     if (this.status == 200) {
462       RefreshPageStatus()
463       setTimeout(subscribe_status,1000)
464     } else {
465       setTimeout(subscribe_status,15000)
466     }
467   }
468   xhr.open("GET", urlbase+"idle", true);
469   xhr.send();
470 }
471
472 setTimeout(subscribe_status,5000)
473 setInterval(PeriodicRefreshTime, 1000);