1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
4.6 KiB

/*jslint laxbreak:true */
/*jslint laxcomma:true */
/*jslint loopfunc:true */
/*jslint strict:true */
/*jslint browser:true */
/*jslint devel:true */
define([
"underscore"
, "backbone"
, "models/dmap-type"
, "collections/dmap"
]
, function (_, Backbone, DMAPType, DMAPCollection) {
"use strict";
var that
, Model = Backbone.Model.extend({
idAttribute: "_id"
, initialize: function (attributes, options) {
that = this;
this.contentCodes = options && options.contentCodes || null;
console.log("Initial", options, this.contentCodes);
if (options.buffer instanceof ArrayBuffer) {
attributes = parseWrapper(options.buffer);
delete options.buffer;
this.set(attributes);
}
return this;
}
/*
, set: function (attributes, options) {
console.log(attributes, options);
this._id = attributes["dmap.persistentid"] || attributes["dmap.itemid"] || attributes["dmap.containeritemid"];
Model.__super__.set(this, arguments);
return this;
}
*/
, update: function (attributes, options) {
that.trigger("dmap.model.update", this, arguments);
return that.apply(that, arguments);
}
, parse: function (reponse) {
return that.attributes;
}
, fetch: function (options) {
that.trigger("dmap.model.fetch", this, arguments);
return that;
}
, save: function (attributes, options) {
that.trigger("dmap.model.save", this, arguments);
return that;
}
, destroy: function (options) {
that.trigger("dmap.model.destroy", this, arguments);
return that;
}
, unset: function (options) {
that.trigger("dmap.model.unset", this, arguments);
return that;
}
, clear: function (options) {
that.trigger("dmap.model.unset", this, arguments);
return that;
}
})
, parseCodeDictionnary = function(dictChunk) {
var codeElement = {};
while (dictChunk.byteLength > 8) {
var contentCode = DMAPType.getType(dictChunk);
var contentLength = DMAPType.getInt32(dictChunk.slice(4,8));
//console.log(contentLength);
switch (contentCode) {
case 'mcnm':
codeElement.code = DMAPType.getString(dictChunk.slice(8, 8+contentLength));
break;
case 'mcna':
var codeName = DMAPType.getString(dictChunk.slice(8, 8+contentLength));
codeElement.name = codeName.replace(/\./g, '_');
//console.log(codeElement.name);
break;
case 'mcty':
var typeData = DMAPType.getInt16(dictChunk.slice(8, 8+contentLength));
codeElement.type = new DMAPType(typeData);
break;
}
dictChunk = dictChunk.slice(8+contentLength);
}
return codeElement;
}
, parseBinaryChunk = function (binaryChunk) {
var entry = {};
while (binaryChunk.byteLength > 8) {
var tagName = DMAPType.getType(binaryChunk);
var tagLength = DMAPType.getInt32(binaryChunk.slice(4,8));
//console.debug(codeInfo, tagName, tagLength);
if (that.contentCodes === null) {
switch (tagName) {
case 'mdcl':
var contentCode = parseCodeDictionnary(binaryChunk.slice(8, 8+tagLength));
var codeId = contentCode.code.toLowerCase();
entry[codeId] = _.extend({}, contentCode, contentCode.type);
break;
case 'mstt':
// Nothing to do with the status, skip it
break;
}
} else {
var codeInfo = that.contentCodes.get(tagName);
if (codeInfo) {
if (codeInfo.type === 12) {
if (typeof entry[codeInfo.name] === "undefined") {
// Here we might want to select different collection types depending on the tag
entry[codeInfo.name] = new DMAPCollection();
}
entry[codeInfo.name].add(binaryChunk.slice(8, tagLength), {silent: true});
} else {
//console.log(codeInfo);
entry[codeInfo.name] = codeInfo.unpack(binaryChunk.slice(8), tagLength);
}
} else {
// TODO: we should try to guess.
console.info("Unknown type: " + tagName + "(" + tagLength + ")");
}
}
binaryChunk = binaryChunk.slice(8 + tagLength);
}
return entry;
}
, parseWrapper = function(binaryData) {
var containerType = DMAPType.getType(binaryData);
//var binaryLength = DMAPType.getUint32(binaryData.slice(4,8));
var contentData = binaryData.slice(8);
switch (containerType) {
// Update
case "mupd":
// Unsupported
return;
break;
default:
console.info("Unknown type: " + containerType/*, binaryLength*/, contentData);
// Content codes
case "mccr":
// Server Info
case "msrv":
// Login
case "mlog":
// Database
case "adbs":
// Database info
case "avdb":
// Playlist info
case "aply":
// List of songs
case "apso":
return parseBinaryChunk(contentData);
break;
}
}
;
return Model;
});