UNPKG

mediamonkeyserver

Version:
531 lines (446 loc) 11.8 kB
/*jslint node: true, sub: true, esversion: 6 */ 'use strict'; const assert = require('assert'); //const debug = require('debug')('upnpserver:class:object.item'); const Xmlns = require('../xmlns'); const ObjectClass = require('./object'); const _UPNP_CLASS = ObjectClass.UPNP_CLASS + '.item'; class Item extends ObjectClass { get name() { return Item.UPNP_CLASS; } static get UPNP_CLASS() { return _UPNP_CLASS; } /** * */ toJXML(node, attributes, request, filterCallback, callback) { var content = (node.attrs) ? node.attrs.slice(0) : []; assert(node.id !== undefined, 'Invalid node.id'); assert(node.parentId !== undefined, 'Invalid node.parentId'); var xml = { _name: 'item', _attrs: { id: node.id, parentID: node.parentId, restricted: (attributes.restricted === false) ? '0' : '1' }, _content: content }; if (attributes.searchable !== undefined) { xml._attrs.searchable = (attributes.searchable) ? '1' : '0'; } var scs = attributes.searchClasses; if (attributes.searchable && scs) { scs.forEach(function (sc) { content.push({ _name: 'upnp:searchClass', _attrs: { includeDerived: (sc.includeDerived ? '1' : '0') }, _content: sc.name }); }); } // MANDATORY // if (filterCallback(Xmlns.PURL_ELEMENT, "title")) { var title = attributes.title; content.push({ _name: 'dc:title', _content: title || node.name }); // } // MANDATORY // if (filterCallback(Xmlns.UPNP_METADATA, "class")) { if (node.upnpClass) { content.push({ _name: 'upnp:class', _content: node.upnpClass.name }); } // } if (filterCallback(Xmlns.PURL_ELEMENT, 'date')) { if (attributes.date) { content.push({ _name: 'dc:date', _content: Item.toISODate(attributes.date) }); } else if (attributes.year) { var y = attributes.year; var _date; if (y < 10000) { _date = y + '-01-01'; // appendix because of Mantis issues #13198, #11882 } else { var ys = y.toString(); _date = ys.substr(0, 4) + '-' + ys.substr(4, 2) + '-' + ys.substr(6, 2); } content.push({ _name: 'dc:date', _content: _date }); } } if (attributes.year && request.jasminFileMetadatasSupport) { if (filterCallback(Xmlns.JASMIN_FILEMETADATA, 'year')) { content.push({ _name: 'fm:year', _content: attributes.year }); } } _addFileTimes(node, request, xml, attributes, filterCallback); if (filterCallback(Xmlns.UPNP_METADATA, 'artist')) { Item.addList(content, attributes.artists, 'upnp:artist', true); if (attributes.albumArtists) Item.addList(content, Item.addRole(attributes.albumArtists, 'AlbumArtist'), 'upnp:artist', true); } if (filterCallback(Xmlns.UPNP_METADATA, 'actor')) { Item.addList(content, attributes.actors, 'upnp:actor', true); } if (filterCallback(Xmlns.UPNP_METADATA, 'author')) { Item.addList(content, attributes.authors, 'upnp:author', true); } if (filterCallback(Xmlns.UPNP_METADATA, 'producer')) { Item.addList(content, attributes.producers, 'upnp:producer', false); } if (filterCallback(Xmlns.UPNP_METADATA, 'director')) { Item.addList(content, attributes.directors, 'upnp:director', false); } if (filterCallback(Xmlns.PURL_ELEMENT, 'publisher')) { Item.addList(content, attributes.publishers, 'dc:publisher', false); } if (filterCallback(Xmlns.UPNP_METADATA, 'publisher')) { Item.addList(content, attributes.publishers, 'upnp:publisher', false); } if (filterCallback(Xmlns.PURL_ELEMENT, 'contributor')) { Item.addList(content, attributes.contributors, 'dc:contributor', false); } if (filterCallback(Xmlns.UPNP_METADATA, 'rating')) { _addRatings(content, attributes.ratings); } if (filterCallback(Xmlns.UPNP_METADATA, 'genre')) { _addGenres(content, attributes.genres); } if (filterCallback(Xmlns.UPNP_METADATA, 'longDescription')) { if (attributes.comment) content.push({ _name: 'upnp:longDescription', _content: attributes.comment }); } // unofficial attributes: if (filterCallback(Xmlns.UPNP_METADATA, 'PlayCounter')) { if (typeof (attributes.playcount) === 'number') { content.push({ _name: 'upnp:PlayCounter', _content: attributes.playcount }); } } if (filterCallback(Xmlns.UPNP_METADATA, 'MM_Bookmark')) { if (typeof (attributes.bookmark) === 'number') { content.push({ _name: 'upnp:MM_Bookmark', _content: attributes.bookmark }); } } if (filterCallback(Xmlns.VENTIS_METADATA, 'metajson')) { Item.addNamespaceURI(xml, 'ventis', Xmlns.VENTIS_METADATA); var toJSON = {}; var fields = ['rating', 'playcount', 'skipcount', 'bpm', 'bookmark', 'volumeLeveling', 'volumeLevelTrack', 'volumeLevelAlbum', 'last_time_played', 'parental_rating', 'grouping', 'tempo', 'mood', 'occasion', 'quality', 'isrc', 'initialKey', 'conductor', 'contributor', 'lyricist', 'originalTitle', 'originalArtist', 'originalLyricist', 'originalDate', 'copyright', 'encoder', 'subtitle', 'custom1', 'custom2', 'custom3', 'custom4', 'custom5', 'custom6', 'custom7', 'custom8', 'custom9', 'custom10']; fields.forEach((n) => { if (attributes[n]) { toJSON[n] = attributes[n]; } else if (attributes[n + 's']) { toJSON[n] = attributes[n + 's'].join(';'); // like lyricists, conductors } }); var _json = JSON.stringify(toJSON); content.push({ _name: 'ventis:metajson', _content: Item.encodeHTML(_json) }); } return callback(null, xml); } /** * */ static encodeHTML(str) { return str.replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;') .replace(/'/g, '&apos;'); } static addRole(list, role) { var res = []; for (var i = 0; i < list.length; i++) { var name = list[i]; res.push({ name: name, role: role }); } return res; } /** * */ acceptFile( /*fileInfos*/ ) { return true; } /** * */ static getXmlNode(node, name, create) { var content = node._content; for (var i = 0; i < content.length; i++) { if (content[i]._name === name) { return content[i]; } } if (create === false) { return null; } var n = { _name: name }; content.push(n); return n; } /** * */ static toISODate(date) { if (typeof (date) === 'number') { date = new Date(date); } return date.toISOString().replace(/\..+/, ''); // Remove ms } /** * */ static toISODay(date) { if (typeof (date) === 'number') { date = new Date(date); } return date.toISOString().replace(/T.*$/, ''); } /** * */ static toMsDate(date) { if (typeof (date) === 'number') { return date; } return date.getTime(); } /** * */ static addList(content, list, name, hasRole) { if (!list || !list.length) { return; } list.forEach(function (item) { if (!item) { return; } if (typeof (item) === 'object') { var a = { _name: name, _content: item.name }; if (hasRole && item.role) { a._attrs = { role: item.role }; } content.push(a); return; } content.push({ _name: name, _content: item }); }); } /** * */ static addNamespaceURI(xml, prefix, uri) { var attrs = xml._attrs; if (attrs) { for (var name in attrs) { var ret = /xmlns(:[a-z0-9])?/i.exec(name); if (!ret) { continue; } var p = (ret[1] && ret[1].slice(1)) || ''; if ((p || prefix) && (p !== prefix)) { continue; } var value = attrs[name]; if (value !== uri) { throw new Error('XMLNS conflict ' + value + ' <> ' + uri + ' for same prefix \'' + p + '\''); } return; } } if (!attrs) { attrs = {}; xml._attrs = attrs; } attrs['xmlns' + (prefix ? (':' + prefix) : '')] = uri; } } module.exports = Item; function _addGenres(content, list) { if (!list || !list.length) { return; } list.forEach(function (genre) { if (!genre) { return; } if (typeof (genre) === 'object') { var a = { _name: 'upnp:genre', _content: genre.name }; if (genre.id) { a._attrs = { id: genre.id }; if (genre.extended) { a._attrs.extended = genre.extended; } } content.push(a); return; } content.push({ _name: 'upnp:genre', _content: genre }); }); } function _addRatings(content, list) { if (!list || !list.length) { return; } list.forEach(function (rating) { if (!rating) { return; } var a = { _name: 'upnp:rating', _content: rating.rating }; if (rating.type) { a._attrs = a._attrs || {}; a._attrs.type = rating.type; } if (rating.advice) { a._attrs = a._attrs || {}; a._attrs.advice = rating.advice; } if (rating.equivalentAge) { a._attrs = a._attrs || {}; a._attrs.equivalentAge = rating.equivalentAge; } // console.log("Add rating ", a); content.push(a); }); } const FILEMEDATA_TIMES_LIST = ['modifiedTime', 'changeTime', 'accessTime', 'birthTime' ]; function _addFileTimes(node, request, xml, attributes, filterCallback) { var content = xml._content; var secModificationDate = false; var dcmCreationDate = false; if (request.secDlnaSupport) { // http://www.upnp-database.info/device.jsp?deviceId=453 // <sec:modifiationDate>2009-04-23T18:19:56</sec:modifiationDate> if (filterCallback(Xmlns.SEC_DLNA, 'modificationDate')) { var modificationDate = node.contentTime; if (modificationDate) { secModificationDate = true; content.push({ _name: 'sec:modificationDate', _content: Item.toISODate(modificationDate) }); } } // http://www.upnp-database.info/device.jsp?deviceId=453 // <sec:dcmInfo>CREATIONDATE=1240496396,FOLDER=2009-04,BM=0</sec:dcmInfo> if (filterCallback(Xmlns.SEC_DLNA, 'dcmInfo')) { var dcmInfo = Item.getXmlNode(xml, 'sec:dcmInfo', false); var infos = {}; if (dcmInfo && dcmInfo._content) { dcmInfo._content.split(',').forEach(function (token) { var reg = /^([A-Z0-9_-])=(.*)$/i.exec(token); if (reg) { infos[reg[1]] = reg[2]; return; } infos[token] = ''; }); } var birthTime = attributes['birthTime']; if (birthTime) { dcmCreationDate = true; infos.CREATIONDATE = Item.toMsDate(birthTime); } if (attributes.bookmark) { infos.BM = 1; } var ci = []; for (var k in infos) { if (infos[k]) { ci.push(k + '=' + infos[k]); continue; } ci.push(k); } if (ci.length) { if (!dcmInfo) { dcmInfo = Item.getXmlNode(xml, 'sec:dcmInfo', true); } dcmInfo._content = ci.join(','); } } } if (request.jasminFileMetadatasSupport) { FILEMEDATA_TIMES_LIST.forEach(function (time) { var d = attributes[time]; if (time === 'modifiedTime') { if (secModificationDate) { return; } d = node.contentTime; } if (time === 'birthTime' && dcmCreationDate) { return; } // if (!d) { return; } if (!filterCallback(Xmlns.JASMIN_FILEMETADATA, time)) { return; } content.push({ _name: 'fm:' + time, _content: Item.toISODate(d) }); }); } }