/*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; });