mediamonkeyserver
Version:
MediaMonkey Server
531 lines (446 loc) • 11.8 kB
JavaScript
/*jslint node: true, sub: true, esversion: 6 */
;
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, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
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)
});
});
}
}