@infinito/id3
Version:
ID3 Tag Reader/Writer
186 lines (183 loc) • 5.6 kB
JavaScript
import {TextEncoder,TextDecoder} from 'text-encoding';
import {StringDecoder} from 'string_decoder';
import id3Tag from './id3tag.js';
export default class id3v2_3Frame {
constructor(buf,pos) {
Object.defineProperties(this,{
FRAME_HEADER_SIZE_BYTES:{
value:10
},
FRAME_ID_SIZE_BYTES:{
value:4
},
FRAME_SIZE_BYTES:{
value:4
},
FRAME_FLAGS_BYTES:{
value:2
},
VALID_FRAMES:{
value:{
AENC:"Audio encryption",
APIC:"Attached picture",
COMM:"Comments",
COMR:"Commercial frame",
ENCR:"Encryption method registration",
EQUA:"Equalization",
ETCO:"Event timing codes",
GEOB:"General encapsulated object",
GRID:"Group identification registration",
IPLS:"Involved people list",
LINK:"Linked information",
MCDI:"Music CD identifier",
MLLT:"MPEG location lookup table",
OWNE:"Ownership frame",
PRIV:"Private frame",
PCNT:"Play counter",
POPM:"Popularimeter",
POSS:"Position synchronisation frame",
RBUF:"Recommended buffer size",
RVAD:"Relative volume adjustment",
RVRB:"Reverb",
SYLT:"Synchronized lyric/text",
SYTC:"Synchronized tempo codes",
TALB:"Album/Movie/Show title",
TBPM:"BPM (beats per minute)",
TCOM:"Composer",
TCON:"Content type",
TCOP:"Copyright message",
TDAT:"Date",
TDLY:"Playlist delay",
TENC:"Encoded by",
TEXT:"Lyricist/Text writer",
TFLT:"File type",
TIME:"Time",
TIT1:"Content group description",
TIT2:"Title/songname/content description",
TIT3:"Subtitle/Description refinement",
TKEY:"Initial key",
TLAN:"Language(s)",
TLEN:"Length",
TMED:"Media type",
TOAL:"Original album/movie/show title",
TOFN:"Original filename",
TOLY:"Original lyricist(s)/text writer(s)",
TOPE:"Original artist(s)/performer(s)",
TORY:"Original release year",
TOWN:"File owner/licensee",
TPE1:"Lead performer(s)/Soloist(s)",
TPE2:"Band/orchestra/accompaniment",
TPE3:"Conductor/performer refinement",
TPE4:"Interpreted, remixed, or otherwise modified by",
TPOS:"Part of a set",
TPUB:"Publisher",
TRCK:"Track number/Position in set",
TRDA:"Recording dates",
TRSN:"Internet radio station name",
TRSO:"Internet radio station owner",
TSIZ:"Size",
TSRC:"ISRC (international standard recording code)",
TSSE:"Software/Hardware and settings used for encoding",
TYER:"Year",
TXXX:"User defined text information frame",
UFID:"Unique file identifier",
USER:"Terms of use",
USLT:"Unsychronized lyric/text transcription",
WCOM:"Commercial information",
WCOP:"Copyright/Legal information",
WOAF:"Official audio file webpage",
WOAR:"Official artist/performer webpage",
WOAS:"Official audio source webpage",
WORS:"Official internet radio station homepage",
WPAY:"Payment",
WPUB:"Publishers official webpage",
WXXX:"User defined URL link frame"
}
},
USED_FRAMES:{
value:{
"Album/Movie/Show title":"album",
"Band/orchestra/accompaniment":"album_artist",
"Composer":"composer",
"Content type":"genre",
"Lead performer(s)/Soloist(s)":"artist",
"Length":"length",
"Part of a set":"set",
"Publisher":"publisher",
"Title/songname/content description":"title",
"Track number/Position in set":"track",
"Year":"year"
}
}
});
if(!(buf instanceof ArrayBuffer)) {
if(buf=='default') {
return;
}
throw new TypeError(`Invalid buffer passed to ${this.constructor.name}`);
}
this.id = new Uint8Array(buf,pos,this.FRAME_ID_SIZE_BYTES);
if(typeof this.VALID_FRAMES[this.frame()]=="undefined") {
throw new Error("Invalid frame detected");
}
pos += this.FRAME_ID_SIZE_BYTES;
/* Calculate size */
this.size = 0;
var tempbuf = new Uint8Array(buf,pos,this.FRAME_SIZE_BYTES);
for(var i=0;i<this.FRAME_SIZE_BYTES;i++) {
this.size<<=8;
this.size += tempbuf[i];
}
pos += this.FRAME_SIZE_BYTES;
/* Get flags */
this.flags = new Uint8Array(buf,pos,this.FRAME_FLAGS_BYTES);
pos += this.FRAME_FLAGS_BYTES;
/* Get encoding */
this.encoding = new Uint8Array(buf,pos,1)[0];
pos++;
/* Get data */
this.data = new Uint8Array(buf,pos,this.size-1);
/* Remove Unicode BOM (if necessary) */
if((this.data[0]==0xff)&&(this.data[1]==0xfe)) {
this.data = new Uint8Array(buf,pos+2,this.size-3);
}
}
frame() {
return String.fromCharCode(this.id[0])+String.fromCharCode(this.id[1])+String.fromCharCode(this.id[2])+String.fromCharCode(this.id[3]);
}
tag_name() {
return this.VALID_FRAMES[this.frame()];
}
add_to_ID3(tags_obj) {
var tag_toset = this.USED_FRAMES[this.tag_name()];
if(typeof tag_toset=="undefined") {
return false;
}
if(!(tags_obj instanceof id3Tag)) {
throw new Error("Passed object invalid");
return false;
}
tags_obj[tag_toset] = this.content();
return true;
}
content() {
if(!(this.data instanceof Uint8Array)) {
return "";
}
if(this.data.size==0) {
return "";
}
switch(this.encoding) {
case 0:
var dec = new TextDecoder("windows-1252");
break;
case 1:
var dec = new TextDecoder("utf-8");
break;
default:
throw new Error("Invalid encoding provided");
return "";
}
return dec.decode(this.data).replace(/\0/g,'');
}
}