2 put: function (name, code, type) {
3 var n = name.split('.');
10 c[n[i]] = new Constant(name, code, type);
15 contentcodesresponse: new Constant("dmap.contentcodesresponse", "mccr", 12),
16 dictionary: new Constant("dmap.dictionary", "mdcl", 12),
17 contentcodesnumber: new Constant("dmap.contentcodesnumber", "mcnm", 5),
18 contentcodesname: new Constant("dmap.contentcodesname", "mcna", 9),
19 contentcodestype: new Constant("dmap.contentcodestype", "mcty", 3)
24 com: { apple: { itunes: new Object() } }
27 function Constant(name, code, type) {
33 function DACPNode(text) {
35 var parseNum = function (index, len) {
36 if (len > 4) return parseBigNum(index, len);
38 var num = text.charCodeAt(index) & 255;
39 for (var i = 1; i < len; i++) {
41 num += text.charCodeAt(index + i) & 255;
46 var parseBigNum = function (index, len) {
47 var num = new BigNumber(text.charCodeAt(index) & 255);
48 for (var i = 1; i < len; i++) {
49 num = num.multiply(256);
50 num = num.add(text.charCodeAt(index + i) & 255);
55 this.name = function (index) {
56 return text.substring(index, index+4);
58 this.length = function (index) {
59 return parseNum(index+4, 4);
61 this.byteVal = function (index) {
62 return parseNum(index+8, 1);
64 this.shortVal = function (index) {
65 return parseNum(index+8, 2);
67 this.intVal = function (index) {
68 return parseNum(index+8, 4);
70 this.longVal = function (index) {
71 return parseNum(index+8, 8);
73 this.longlongVal = function (index) {
75 0: parseNum(index+8, 4),
76 1: parseNum(index+12, 4),
77 2: parseNum(index+16, 4),
78 3: parseNum(index+20, 4)
81 this.stringVal = function (index) {
82 var length = this.length(index);
84 for ( var i = 8; i < 8+length;) {
85 var c = text.charCodeAt(index + i) & 255;
88 string += String.fromCharCode(c);
90 } else if (c > 191 && c < 224) {
91 c2 = text.charCodeAt(index + i + 1) & 255;
92 string += String.fromCharCode(((c & 31)) << 6 | (c2 & 63));
95 c2 = text.charCodeAt(index + i + 1) & 255;
96 c3 = text.charCodeAt(index + i + 2) & 255;
97 string += String.fromCharCode(((c & 15)) << 12 | (c2 & 63) << 6
104 this.dateVal = function (index) {
105 return parseNum(index+8, 8);
107 this.versionVal = function (index) {
108 var version = text.charCodeAt(index+8) & 255;
111 version += text.charCodeAt(index+8 + i) & 255;
115 this.children = function (index) {
116 var kids = new Array();
117 var len = index + 8 + this.length(index);
121 i += 8 + this.length(i);
125 this.findNode = function (index, tag) {
126 var kids = this.children(index);
127 for (child in kids) {
128 if (this.name(kids[child]) == tag) {
136 function DACPPlayStatusUpdate(tree, index) {
138 var kids = tree.children(index);
149 for (child in kids) {
150 var node = kids[child];
151 switch (tree.name(node)) {
153 this.status = tree.byteVal(node);
156 this.revision = tree.intVal(node);
159 this.title = tree.stringVal(node);
162 this.artist = tree.stringVal(node);
165 this.album = tree.stringVal(node);
168 this.genre = tree.stringVal(node);
171 this.container = tree.longlongVal(node)[1];
172 this.id = tree.longlongVal(node)[3];
178 function getItems(tree, index, handler) {
180 var items = new Array();
182 var kids = tree.children(index);
183 for (child in kids) {
184 items.push(handler(tree, kids[child]));
190 function DACPContainer(tree, index) {
199 var kids = tree.children(index);
200 for (child in kids) {
201 var node = kids[child];
202 switch (tree.name(node)) {
203 case constants.dmap.itemid.code:
204 this.id = tree.intVal(node);
206 case constants.dmap.persistentid.code:
207 this.persistent = tree.longVal(node);
209 case constants.dmap.itemname.code:
210 this.name = tree.stringVal(node);
212 case constants.daap.baseplaylist.code:
213 this.base = tree.byteVal(node);
215 case constants.dmap.parentcontainerid.code:
216 this.parent = tree.intVal(node);
218 case constants.dmap.itemcount.code:
219 this.items = tree.intVal(node);
225 this.node.className += " -database-playlist";
226 this.appendChild(this.name, "-database-playlist-name");
227 //this.appendChild(this.items, "-database-playlist-items");
228 //this.appendChild(this.id, "-database-playlist-id");
230 DACPContainer.prototype = new Item;
231 DACPContainer.prototype.selected = function () {
232 Item.prototype.selected.call(this);
233 dacp.playlist = this.id;
236 DACPContainer.prototype.deselected = function () {
237 Item.prototype.deselected.call(this);
238 if (dacp.playlist == this.id) {
243 function DACPPlaylist(tree, index) {
245 this.tracks = new Array();
247 var kids = tree.children(index);
249 for (child in kids) {
250 if (tree.name(kids[child]) == "mlcl") {
260 kids = tree.children(list);
261 for (child in kids) {
262 this.tracks.push(new DACPTrack(tree, kids[child]));
266 DACPPlaylist.prototype = new View;
268 function DACPAlbum(tree, index) {
273 this.persistantId = 0;
275 var kids = tree.children(index);
276 for (child in kids) {
277 var node = kids[child];
278 switch (tree.name(node)) {
280 this.id = tree.intVal(node);
283 this.name = tree.stringVal(node);
286 this.artist = tree.stringVal(node);
289 this.persistantId = tree.longVal(node);
295 this.node.className += " -stereo-album";
297 this.appendChild(this.name, "-stereo-album-title");
298 this.appendChild(this.title, "-stereo-album-artist");
300 DACPAlbum.prototype = new Item;
302 function DACPTrack(tree, index) {
311 var kids = tree.children(index);
312 for (child in kids) {
313 var node = kids[child];
314 switch (tree.name(node)) {
316 this.album = tree.stringVal(node);
319 this.title = tree.stringVal(node);
322 this.artist = tree.stringVal(node);
325 this.genre = tree.stringVal(node);
328 this.id = tree.intVal(node);
331 this.persistent = tree.longVal(node);
337 this.node.className += " -stereo-track";
339 var title = document.createElement("DIV");
340 title.appendChild(document.createTextNode(this.title));
342 this.appendChild(this.artist, "-stereo-track-artist");
343 this.appendChild(title, "-stereo-track-title");
344 this.appendChild(this.album, "-stereo-track-album");
345 this.appendChild(this.genre, "-stereo-track-genre");
347 var arrow = document.createElement("SPAN");
348 //arrow.innerHTML = "▶";
349 arrow.innerHTML = "enqueue";
350 arrow.className = "enqueue hover";
351 title.appendChild(arrow);
353 var play = document.createElement("SPAN");
354 play.innerHTML = "play";
355 play.className = "play hover";
356 title.appendChild(play);
358 this.clicked = function (e) {
359 if (e.target.className && e.target.className.indexOf("play") != -1) {
360 dacp.play(constants.dmap.itemid.name + ":" + this.id);
362 else if (e.target.className && e.target.className.indexOf("enqueue") != -1) {
363 dacp.enqueue(constants.dmap.itemid.name + ":" + this.id);
366 DACPTrack.prototype.clicked.call(this);
370 DACPTrack.prototype = new Item;
372 function BrowseItem(tree, index, type) {
375 this.value = tree.stringVal(index);
378 this.node.className += " -browse-item";
380 var arrow = document.createElement("DIV");
381 //arrow.innerHTML = "▶";
382 arrow.innerHTML = "enqueue";
383 this.appendChild(arrow, "enqueue hover");
385 var play = document.createElement("DIV");
386 play.innerHTML = "play";
387 this.appendChild(play, "play hover");
389 this.appendChild(this.value);
391 this.clicked = function (e) {
392 if (e.target.className && e.target.className.indexOf("play") != -1) {
393 dacp.play(this.type.name + ":" + this.value);
395 else if (e.target.className && e.target.className.indexOf("enqueue") != -1) {
396 dacp.enqueue(this.type.name + ":" + this.value);
399 BrowseItem.prototype.clicked.call(this);
404 BrowseItem.prototype = new Item;
405 BrowseItem.prototype.selected = function () {
406 dacp.setSearch(this.type.name + ":" + this.value);
409 function sysout(text) {
410 if (window.console) {
411 window.console.log(text);
414 var p = document.createElement("PRE");
415 p.className = "debug";
416 p.appendChild(document.createTextNode(text));
417 document.body.appendChild(p);