jsmediatags
Version:
Media Tags Reader (ID3, MP4)
194 lines (157 loc) • 7.63 kB
JavaScript
;
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
var MediaTagReader = require('./MediaTagReader');
var MediaFileReader = require('./MediaFileReader');
var ID3v2FrameReader = require('./ID3v2FrameReader');
var ID3_HEADER_SIZE = 10;
var ID3v2TagReader = /*#__PURE__*/function (_MediaTagReader) {
_inherits(ID3v2TagReader, _MediaTagReader);
var _super = _createSuper(ID3v2TagReader);
function ID3v2TagReader() {
_classCallCheck(this, ID3v2TagReader);
return _super.apply(this, arguments);
}
_createClass(ID3v2TagReader, [{
key: "_loadData",
value: function _loadData(mediaFileReader, callbacks) {
mediaFileReader.loadRange([6, 9], {
onSuccess: function onSuccess() {
mediaFileReader.loadRange( // The tag size does not include the header size.
[0, ID3_HEADER_SIZE + mediaFileReader.getSynchsafeInteger32At(6) - 1], callbacks);
},
onError: callbacks.onError
});
}
}, {
key: "_parseData",
value: function _parseData(data, tags) {
var offset = 0;
var major = data.getByteAt(offset + 3);
if (major > 4) {
return {
"type": "ID3",
"version": ">2.4",
"tags": {}
};
}
var revision = data.getByteAt(offset + 4);
var unsynch = data.isBitSetAt(offset + 5, 7);
var xheader = data.isBitSetAt(offset + 5, 6);
var xindicator = data.isBitSetAt(offset + 5, 5);
var size = data.getSynchsafeInteger32At(offset + 6);
offset += 10;
if (xheader) {
// We skip the extended header and don't offer support for it right now.
if (major === 4) {
var xheadersize = data.getSynchsafeInteger32At(offset);
offset += xheadersize;
} else {
var xheadersize = data.getLongAt(offset, true); // The 'Extended header size', currently 6 or 10 bytes, excludes itself.
offset += xheadersize + 4;
}
}
var id3 = {
"type": "ID3",
"version": '2.' + major + '.' + revision,
"major": major,
"revision": revision,
"flags": {
"unsynchronisation": unsynch,
"extended_header": xheader,
"experimental_indicator": xindicator,
// TODO: footer_present
"footer_present": false
},
"size": size,
"tags": {}
};
if (tags) {
var expandedTags = this._expandShortcutTags(tags);
}
var offsetEnd = size + 10
/*header size*/
; // When this flag is set the entire tag needs to be un-unsynchronised
// before parsing each individual frame. Individual frame sizes might not
// take unsynchronisation into consideration when it's set on the tag
// header.
if (id3.flags.unsynchronisation) {
data = ID3v2FrameReader.getUnsyncFileReader(data, offset, size);
offset = 0;
offsetEnd = data.getSize();
}
var frames = ID3v2FrameReader.readFrames(offset, offsetEnd, data, id3, expandedTags); // create shortcuts for most common data.
for (var name in SHORTCUTS) {
if (SHORTCUTS.hasOwnProperty(name)) {
var frameData = this._getFrameData(frames, SHORTCUTS[name]);
if (frameData) {
id3.tags[name] = frameData;
}
}
}
for (var frame in frames) {
if (frames.hasOwnProperty(frame)) {
id3.tags[frame] = frames[frame];
}
}
return id3;
}
}, {
key: "_getFrameData",
value: function _getFrameData(frames, ids) {
var frame;
for (var i = 0, id; id = ids[i]; i++) {
if (id in frames) {
if (frames[id] instanceof Array) {
frame = frames[id][0];
} else {
frame = frames[id];
}
return frame.data;
}
}
}
}, {
key: "getShortcuts",
value: function getShortcuts() {
return SHORTCUTS;
}
}], [{
key: "getTagIdentifierByteRange",
value: function getTagIdentifierByteRange() {
// ID3 header
return {
offset: 0,
length: ID3_HEADER_SIZE
};
}
}, {
key: "canReadTagFormat",
value: function canReadTagFormat(tagIdentifier) {
var id = String.fromCharCode.apply(String, tagIdentifier.slice(0, 3));
return id === 'ID3';
}
}]);
return ID3v2TagReader;
}(MediaTagReader);
var SHORTCUTS = {
"title": ["TIT2", "TT2"],
"artist": ["TPE1", "TP1"],
"album": ["TALB", "TAL"],
"year": ["TYER", "TYE"],
"comment": ["COMM", "COM"],
"track": ["TRCK", "TRK"],
"genre": ["TCON", "TCO"],
"picture": ["APIC", "PIC"],
"lyrics": ["USLT", "ULT"]
};
module.exports = ID3v2TagReader;