1 <?xml version=
"1.0" encoding=
"utf-8" ?>
2 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.1//EN"
3 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4 <html xmlns=
"http://www.w3.org/1999/xhtml"
5 xmlns:
svg=
"http://www.w3.org/2000/svg">
8 <meta http-equiv=
"Content-Type" content=
"text/html;charset=utf-8" />
9 <script type=
"text/javascript" charset=
"utf-8">
11 function getPlaybackStatusUpdate() {
12 var request =
"/ctrl-int/1/playstatusupdate";
14 if (lastUpdate && lastUpdate.revision) {
15 request +=
"?revision-number="+lastUpdate.revision;
18 ajax.request(request, function (response) {
19 var tree = new Node(response);
21 var up = new PlayStatusUpdate(tree,
0);
25 if (!lastUpdate || up.revision != lastUpdate.revision) {
27 getAlbumArt(up.revision);
28 if ((!lastUpdate && up.status ==
4)
29 || (lastUpdate.status ==
2 && up.status ==
4)) {
30 document.body.className =
"playing";
36 getPlaybackStatusUpdate();
42 function getPlaylistUpdate() {
43 var request =
"/ctrl-int/1/playlist";
44 ajax.request(request, function (text) {
45 var tree = new Node(text);
46 var playlist = new Playlist(tree,
0);
47 updatePlaylist(playlist);
51 function getAlbumArt(revision) {
52 document.getElementById(
"albumart").src =
"/ctrl-int/1/nowplayingartwork?revision="+revision;
55 function getPlaylists() {
56 var request =
"/databases/1/containers";
57 var callback = function (text) {
59 var tree = new Node(text);
61 var list = findNode(tree,
0,
"mlcl");
63 var playlists = getItems(tree, list, function (t, i) {
64 return new Container(t, i);
67 var parent = document.getElementById(
"browse-playlists-container");
68 while (parent.childNodes.length
> 0) {
69 parent.removeChild(parent.firstChild);
72 for (p in playlists) {
73 var item = document.createElement(
"DIV");
74 item.
className=
"item";
76 item.appendChild(createNode(
"title", playlists[p].name));
77 item.appendChild(createNode(
"count", playlists[p].items));
78 item.collection = playlists[p].id;
79 item.persistent = playlists[p].persistent;
81 if (playlists[p].id == lastUpdate.container) {
82 item.className +=
" current";
85 parent.appendChild(item);
88 ajax.request(request, callback);
91 function getArtists() {
92 var request =
"/databases/1/browse/artists";
93 var callback = function (text) {
95 var tree = new Node(text);
97 var list = findNode(tree,
0,
"abar");
99 var artists = getItems(tree, list, function (t, i) {
100 return t.stringVal(i);
103 var parent = document.getElementById(
"browse-artists-container");
104 while (parent.childNodes.length
> 0) {
105 parent.removeChild(parent.firstChild);
109 var item = document.createElement(
"DIV");
110 item.
className=
"item";
111 item.
query=
"'daap.songartist:"+artists[a]+
"'";
113 item.appendChild(createNode(
"title", artists[a]));
115 parent.appendChild(item);
118 ajax.request(request, callback);
121 function getAlbums(query, callback) {
122 var request =
"/databases/1/groups?group-type=albums&sort=albums&query="+query;
123 var fn = function (text) {
125 var tree = new Node(text);
127 var list = findNode(tree,
0,
"mlcl");
129 var albums = getItems(tree, list, function (t, i) {
130 return new Album(t, i);
135 ajax.request(request, fn);
139 function getTracks(query, callback) {
141 var request =
"/databases/1/containers/1/items?query="+query;
142 var fn = function (text) {
144 var tree = new Node(text);
146 var list = findNode(tree,
0,
"mlcl");
148 var tracks = getItems(tree, list, function (t, i) {
149 return new Track(t, i);
154 ajax.request(request, fn);
157 function getCollectionTracks(collection, callback) {
159 var request =
"/databases/1/containers/" + collection +
"/items";
160 var fn = function (text) {
162 var tree = new Node(text);
164 var list = findNode(tree,
0,
"mlcl");
166 var tracks = getItems(tree, list, function (t, i) {
167 return new Track(t, i);
172 ajax.request(request, fn);
175 function getVolume() {
177 var request =
"/ctrl-int/1/getproperty?properties=dmcp.volume"
178 var fn = function (text) {
180 var tree = new Node(text);
182 var volume = tree.intVal(findNode(tree,
0,
"cmvo"));
184 var vol =
15 + (volume *
270 /
100);
186 document.getElementById(
"volume-control").setAttribute(
"cx", vol);
188 ajax.request(request, fn);
191 function setVolume(volume) {
192 var request = new XMLHttpRequest();
193 request.open(
"GET",
"/ctrl-int/1/setproperty?dmcp.volume="+volume);
198 var request = new XMLHttpRequest();
199 request.open(
"GET",
"/ctrl-int/1/nextitem", true);
204 var request = new XMLHttpRequest();
205 request.open(
"GET",
"/ctrl-int/1/previtem", true);
210 var request = new XMLHttpRequest();
211 request.open(
"GET",
"/ctrl-int/1/playpause", true);
216 var request = new XMLHttpRequest();
217 request.open(
"GET",
"/ctrl-int/1/pause", true);
221 function jump(index) {
222 var request = new XMLHttpRequest();
223 request.open(
"GET",
"/ctrl-int/1/cue?command=play&index="+index);
228 var request = new XMLHttpRequest();
229 request.open(
"GET",
"/ctrl-int/1/cue?command=clear");
233 function enqueue(query) {
234 var request = new XMLHttpRequest();
235 request.open(
"GET",
"/ctrl-int/1/cue?command=play&query="+query);
239 function setCollection(persistent) {
240 var request = new XMLHttpRequest();
241 request.open(
"GET",
"/ctrl-int/1/playspec?playlist-spec="+persistent);
246 var previousPane = new Array();
248 function updateStatus(update) {
250 if (update.status ==
2) {
251 document.getElementById(
"state").className =
"stopped";
253 document.getElementById(
"play").className =
"";
254 document.getElementById(
"pause").className =
"hidden";
255 } else if (update.status ==
3) {
256 document.getElementById(
"state").className =
"paused";
257 setText(document.getElementById(
"title"), update.title);
258 setText(document.getElementById(
"artist"), update.artist);
259 setText(document.getElementById(
"album"), update.album);
260 setText(document.getElementById(
"genre"), update.genre);
262 document.getElementById(
"play").className =
"";
263 document.getElementById(
"pause").className =
"hidden";
264 } else if (update.status ==
4) {
265 document.getElementById(
"state").className =
"playing";
266 setText(document.getElementById(
"title"), update.title);
267 setText(document.getElementById(
"artist"), update.artist);
268 setText(document.getElementById(
"album"), update.album);
269 setText(document.getElementById(
"genre"), update.genre);
270 document.title = update.title +
" - " + update.artist;
272 document.getElementById(
"play").className =
"hidden";
273 document.getElementById(
"pause").className =
"";
277 function setText(node, text) {
278 while (node.childNodes.length
> 0) {
279 node.removeChild(node.firstChild);
281 node.appendChild(document.createTextNode(text));
284 function updatePlaylist(playlist) {
286 var list = document.getElementById(
"playlist");
289 var current = lastUpdate.id;
291 for (i in playlist.tracks) {
292 var track = playlist.tracks[i];
294 var node = document.createElement(
"DIV");
295 node.className =
"item";
297 node.appendChild(createNode(
"album", track.album));
298 node.appendChild(createNode(
"title", track.title));
299 node.appendChild(createNode(
"artist", track.artist));
300 node.appendChild(createNode(
"genre", track.genre));
301 node.appendChild(createNode(
"id", track.id));
303 if (current && track.id == current) {
304 node.className +=
" current";
307 while (list.childNodes.length
> 2) {
308 list.removeChild(list.childNodes[
0]);
312 list.appendChild(node);
316 function createNode(type, value) {
317 var node = document.createElement(
"DIV");
318 node.className = type;
319 node.appendChild(document.createTextNode(value));
323 function registerControls() {
325 document.getElementById(
"back").onclick = function() {
326 if (previousPane.length ==
0) {
327 previousPane.push(
"playlists");
329 document.body.className = previousPane.pop();
331 document.getElementById(
"playing").onclick = function() {
332 if (document.body.className) {
333 previousPane.push(document.body.className);
335 document.body.className =
"playing";
338 document.body.className =
"playlists";
340 document.getElementById(
"previous").onclick = function() {
343 document.getElementById(
"play").onclick = function() {
346 document.getElementById(
"pause").onclick = function() {
349 document.getElementById(
"next").onclick = function() {
353 var dragging = false;
354 document.getElementById(
"volume-control").onmousedown = function() {
357 document.getElementById(
"volume").onmouseup = function(e) {
360 var x = e.clientX-document.getElementById(
"volume-wrapper").offsetLeft;
362 if (x
> 285) x =
285;
363 var volume = Math.round((x -
15) *
100 /
270);
367 document.getElementById(
"volume").onmouseout = function(e) {
368 if (dragging && e.target == document.getElementById(
"volume")) {
370 var x = e.clientX-document.getElementById(
"volume-wrapper").offsetLeft;
372 if (x
> 285) x =
285;
373 var volume = Math.round((x -
15) *
100 /
270);
377 document.getElementById(
"volume").onmousemove = function(e) {
379 var x = e.clientX-document.getElementById(
"volume-wrapper").offsetLeft;
381 if (x
> 285) x =
285;
382 var control = document.getElementById(
"volume-control");
383 control.setAttribute(
"cx", x);
387 document.getElementById(
"playlist").onclick = function(e) {
389 while (!node.className.match(
"item")) {
390 node = node.parentNode;
391 if (node == document.body)
394 var playlist = document.getElementById(
"playlist");
396 for (child in playlist.childNodes) {
397 if (playlist.childNodes[child].className
398 && playlist.childNodes[child].className
405 for (child in playlist.childNodes) {
406 if (playlist.childNodes[child] == node) {
407 jump(child - offset);
413 document.getElementById(
"browse-playlists-container").onclick = function(e) {
415 while (!node.className.match(
"item")) {
416 node = node.parentNode;
417 if (node == document.body)
421 var collection = node.collection;
422 var persistent = node.persistent;
424 getCollectionTracks(collection, function (tracks) {
425 var parent = document.getElementById(
"browse-playlists-tracks");
426 while (parent.childNodes.length
> 0) {
427 parent.removeChild(parent.firstChild);
430 var shuffle = document.createElement(
"DIV");
431 shuffle.
className=
"item";
432 shuffle.persistent=persistent;
434 shuffle.appendChild(createNode(
"title",
"Shuffle"));
435 shuffle.appendChild(createNode(
"artist",
""));
436 parent.appendChild(shuffle);
439 var item = document.createElement(
"DIV");
440 item.
className=
"item";
441 item.persistent=persistent;
442 item.
query=
"'dmap.persistentid:"+tracks[t].persistent+
"'";
444 item.appendChild(createNode(
"title", tracks[t].title));
445 item.appendChild(createNode(
"artist", tracks[t].artist));
447 parent.appendChild(item);
449 previousPane.push(
"playlists");
450 document.body.className =
"playlist-tracks";
454 document.getElementById(
"browse-playlists-tracks").onclick = function(e) {
456 while (!node.className.match(
"item")) {
457 node = node.parentNode;
458 if (node == document.body)
462 var query = node.query;
463 var persistent = node.persistent;
465 setCollection(persistent);
472 previousPane.push(
"playlist-tracks");
473 document.body.className =
"playing";
476 document.getElementById(
"browse-artists-container").onclick = function(e) {
478 while (!node.className.match(
"item")) {
479 node = node.parentNode;
480 if (node == document.body)
484 var query = node.query;
486 getAlbums(query, function (albums) {
487 var parent = document.getElementById(
"browse-artists-albums");
488 while (parent.childNodes.length
> 0) {
489 parent.removeChild(parent.firstChild);
492 var item = document.createElement(
"DIV");
493 item.
className=
"item";
494 item.
query=
"'daap.songalbum="+albums[a].name+
"'";
496 item.appendChild(createNode(
"title", albums[a].name));
498 parent.appendChild(item);
500 previousPane.push(
"artists");
501 document.body.className =
"artist-albums";
505 document.getElementById(
"browse-artists-albums").onclick = function(e) {
507 while (!node.className.match(
"item")) {
508 node = node.parentNode;
509 if (node == document.body)
512 var query =
"'daap.songalbum:"+node.textContent+
"'";
513 getTracks(query, function (tracks) {
514 var parent = document.getElementById(
"browse-artists-tracks");
515 while (parent.childNodes.length
> 0) {
516 parent.removeChild(parent.firstChild);
519 var item = document.createElement(
"DIV");
520 item.
className=
"item";
522 item.appendChild(createNode(
"title",
"All Songs"));
523 parent.appendChild(item);
526 item = document.createElement(
"DIV");
527 item.
className=
"item";
528 item.query = query+
"+'dmap.itemname:"+tracks[t].title+
"'";
529 item.appendChild(createNode(
"title", tracks[t].title));
531 parent.appendChild(item);
533 previousPane.push(
"artist-albums");
534 document.body.className =
"artist-tracks";
538 document.getElementById(
"browse-artists-tracks").onclick = function (e) {
540 while (!node.className.match(
"item")) {
541 node = node.parentNode;
542 if (node == document.body)
546 var query = node.query;
551 previousPane.push(
"artist-tracks");
552 document.body.className =
"playing";
555 document.getElementById(
"browse-albums-container").onclick = function(e) {
557 while (!node.className.match(
"item")) {
558 node = node.parentNode;
559 if (node == document.body)
563 var query = node.query;
565 getTracks(query, function (tracks) {
566 var parent = document.getElementById(
"browse-albums-tracks");
567 while (parent.childNodes.length
> 0) {
568 parent.removeChild(parent.firstChild);
571 var item = document.createElement(
"DIV");
572 item.
className=
"item";
574 item.appendChild(createNode(
"title",
"All Songs"));
575 parent.appendChild(item);
578 item = document.createElement(
"DIV");
579 item.
className=
"item";
580 item.query = query+
"+'dmap.itemname:"+tracks[t].title+
"'";
581 item.appendChild(createNode(
"title", tracks[t].title));
582 item.appendChild(createNode(
"artist", tracks[t].artist));
583 parent.appendChild(item);
586 previousPane.push(
"albums");
587 document.body.className =
"album-tracks";
591 document.getElementById(
"browse-albums-tracks").onclick = function (e) {
593 while (!node.className.match(
"item")) {
594 node = node.parentNode;
595 if (node == document.body)
599 var query = node.query;
604 previousPane.push(
"album-tracks");
605 document.body.className =
"playing";
608 document.getElementById(
"browse-menu-playlists").onclick = function() {
610 document.body.className =
"playlists";
612 document.getElementById(
"browse-menu-artists").onclick = function() {
614 document.body.className =
"artists";
616 document.getElementById(
"browse-menu-albums").onclick = function() {
617 getAlbums(
"'daap.songalbum!:'", function (albums) {
618 var parent = document.getElementById(
"browse-albums-container");
619 while (parent.childNodes.length
> 0) {
620 parent.removeChild(parent.firstChild);
623 var item = document.createElement(
"DIV");
624 item.
className=
"item";
625 item.
query=
"'daap.songalbum:"+albums[a].name+
"'";
627 item.appendChild(createNode(
"title", albums[a].name));
629 parent.appendChild(item);
631 document.body.className =
"albums";
634 document.getElementById(
"browse-menu-search").onclick = function() {
636 document.body.className =
"search";
639 document.body.className =
"playlists";
644 <link rel=
"stylesheet" type=
"text/css" href=
"style.css" />
647 <body onload=
"registerControls(); getPlaybackStatusUpdate(); getVolume();">
648 <div id=
"navigation">
649 <div id=
"back">Back
</div>
650 <div id=
"playing">Now Playing
</div>
653 <div id=
"state"><img id=
"albumart" src=
"" alt=
"" />
654 <div id=
"title" class=
"title"></div>
655 <div id=
"album" class=
"album"></div>
656 <div id=
"artist" class=
"artist"></div>
657 <div id=
"genre" class=
"genre"></div>
660 <div id=
"previous">previous
</div>
661 <div id=
"play">play
</div>
662 <div id=
"pause">pause
</div>
663 <div id=
"next">next
</div>
664 <div id=
"volume">volume
</div>
666 <div id=
"playlist" class=
"content"></div>
669 <div id=
"browse-menu">
670 <div id=
"browse-menu-playlists">Playlists
</div>
671 <div id=
"browse-menu-artists">Artists
</div>
672 <div id=
"browse-menu-albums">Albums
</div>
673 <div id=
"browse-menu-search">Search
</div>
675 <div id=
"browse-playlists" class=
"content">
676 <div id=
"browse-playlists-container" class=
"container"></div>
677 <div id=
"browse-playlists-tracks" class=
"container"></div>
679 <div id=
"browse-artists" class=
"content">
680 <div id=
"browse-artists-container" class=
"container"></div>
681 <div id=
"browse-artists-albums" class=
"container"></div>
682 <div id=
"browse-artists-tracks" class=
"container"></div>
684 <div id=
"browse-albums" class=
"content">
685 <div id=
"browse-albums-container" class=
"container"></div>
686 <div id=
"browse-albums-tracks" class=
"container"></div>
688 <div id=
"browse-search" class=
"content">
689 <div id=
"browse-search-interface">
690 <input type=
"text" name=
"songs" id=
"browse-search-input" />
691 <button type=
"submit" />
693 <div id=
"browse-search-container" class=
"container"></div>
697 <script type=
"text/javascript" src=
"svgloader.js"></script>
698 <script type=
"text/javascript" src=
"ajax.js"></script>
699 <script type=
"text/javascript" src=
"dacp.js"></script>
700 <script type=
"text/javascript" src=
"bignum.js"></script>
701 <script type=
"text/javascript">