1 /* Copyright (c) MediaArea.net SARL. All Rights Reserved.
2 *
3 * Use of this source code is governed by a BSD-style license that can
4 * be found in the License.html file in the root of the source tree.
5 */
6
7 //---------------------------------------------------------------------------
8 // Pre-compilation
9 #include "MediaInfo/PreComp.h"
10 #ifdef __BORLANDC__
11 #pragma hdrstop
12 #endif
13 //---------------------------------------------------------------------------
14
15 //---------------------------------------------------------------------------
16 #include "MediaInfo/Setup.h"
17 //---------------------------------------------------------------------------
18
19 //***************************************************************************
20 // Infos (Common)
21 //***************************************************************************
22
23 //---------------------------------------------------------------------------
24 #if defined(MEDIAINFO_ID3V2_YES) || defined(MEDIAINFO_FLAC_YES) || defined(MEDIAINFO_VORBISCOM_YES) || defined(MEDIAINFO_OGG_YES)
25 //---------------------------------------------------------------------------
26
27 #include "ZenLib/Conf.h"
28 using namespace ZenLib;
29
30 namespace MediaInfoLib
31 {
32
33 //---------------------------------------------------------------------------
Id3v2_PictureType(int8u Type)34 extern const char* Id3v2_PictureType(int8u Type)
35 {
36 switch (Type)
37 {
38 case 0x01 :
39 case 0x02 : return "File icon";
40 case 0x03 : return "Cover (front)";
41 case 0x04 : return "Cover (back)";
42 case 0x05 : return "Leaflet page";
43 case 0x06 : return "Media";
44 case 0x07 :
45 case 0x08 : return "Performer";
46 case 0x09 : return "Conductor";
47 case 0x0A : return "Performer";
48 case 0x0B : return "Composer";
49 case 0x0C : return "Lyricist";
50 case 0x0D : return "Recording Location";
51 case 0x0E : return "During recording";
52 case 0x0F : return "During performance";
53 case 0x10 : return "Screen capture";
54 case 0x12 : return "Illustration";
55 case 0x13 : return "Performer logo";
56 case 0x14 : return "Publisher logo";
57 default : return "";
58 }
59 }
60
61 } //NameSpace
62
63 //---------------------------------------------------------------------------
64 #endif //...
65 //---------------------------------------------------------------------------
66
67 //***************************************************************************
68 //
69 //***************************************************************************
70
71 //---------------------------------------------------------------------------
72 #if defined(MEDIAINFO_ID3V2_YES)
73 //---------------------------------------------------------------------------
74
75 //---------------------------------------------------------------------------
76 #include "MediaInfo/Tag/File_Id3v2.h"
77 #include "ZenLib/ZtringListList.h"
78 #include "ZenLib/Utils.h"
79 #include "ThirdParty/base64/base64.h"
80 #include <cstring>
81 using namespace ZenLib;
82 //---------------------------------------------------------------------------
83
84 namespace MediaInfoLib
85 {
86
87 //***************************************************************************
88 // Infos
89 //***************************************************************************
90
91 //---------------------------------------------------------------------------
92 const char* Id3v2_TextEnc[]=
93 {
94 "ISO 8859-1",
95 "UTF-16",
96 "UTF-16BE",
97 "UTF-8",
98 };
99
100 //---------------------------------------------------------------------------
101 const char* Id3v2_RGAD_Name_code[]=
102 {
103 "",
104 "Radio Gain Adjustment",
105 "Audiophile Gain Adjustment",
106 "",
107 "",
108 "",
109 "",
110 "",
111 };
112
113 //---------------------------------------------------------------------------
114 const char* Id3v2_RGAD_Originator_code[]=
115 {
116 "",
117 "Pre-set by artist/producer/mastering engineer",
118 "Set by user",
119 "Determined automatically",
120 "",
121 "",
122 "",
123 "",
124 };
125
126 //***************************************************************************
127 // Constants
128 //***************************************************************************
129
130 namespace Elements
131 {
132 const int32u AENC=0x41454E47;
133 const int32u APIC=0x41504943;
134 const int32u ASPI=0x41535049;
135 const int32u COMM=0x434F4D4D;
136 const int32u COMR=0x434F4D52;
137 const int32u ENCR=0x454E4352;
138 const int32u EQU2=0x45515532;
139 const int32u EQUA=0x45515541;
140 const int32u ETCO=0x4554434F;
141 const int32u GEOB=0x47454F42;
142 const int32u GRID=0x47524944;
143 const int32u IPLS=0x49504C53;
144 const int32u LINK=0x4C494E4B;
145 const int32u MCDI=0x4D434449;
146 const int32u MLLT=0x4D4C4C54;
147 const int32u OWNE=0x4F574E45;
148 const int32u PCNT=0x50434E58;
149 const int32u POPM=0x504F504D;
150 const int32u POSS=0x504F5353;
151 const int32u PRIV=0x50524956;
152 const int32u RBUF=0x52425546;
153 const int32u RGAD=0x52474144;
154 const int32u RVA2=0x52564132;
155 const int32u RVRB=0x52565242;
156 const int32u SEEK=0x5345454B;
157 const int32u SIGN=0x5349474E;
158 const int32u SYLT=0x53594C54;
159 const int32u SYTC=0x53595443;
160 const int32u TALB=0x54414C42;
161 const int32u TBPM=0x5442504D;
162 const int32u TCAT=0x54434154;
163 const int32u TCMP=0x54434D50;
164 const int32u TCOM=0x54434F4D;
165 const int32u TCON=0x54434F4E;
166 const int32u TCOP=0x54434F50;
167 const int32u TDAT=0x54444154;
168 const int32u TDEN=0x5444454E;
169 const int32u TDLY=0x54444C59;
170 const int32u TDOR=0x54444F52;
171 const int32u TDRC=0x54445243;
172 const int32u TDRL=0x5444524C;
173 const int32u TDTG=0x54445447;
174 const int32u TENC=0x54454E43;
175 const int32u TEXT=0x54455854;
176 const int32u TFLT=0x54464C54;
177 const int32u TIME=0x54494D45;
178 const int32u TIPL=0x5449504C;
179 const int32u TIT1=0x54495431;
180 const int32u TIT2=0x54495432;
181 const int32u TIT3=0x54495433;
182 const int32u TKEY=0x544B4559;
183 const int32u TLAN=0x544C414E;
184 const int32u TLEN=0x544C454E;
185 const int32u TMCL=0x544D434C;
186 const int32u TMED=0x544D4544;
187 const int32u TMOO=0x544D4F4F;
188 const int32u TOAL=0x544F414C;
189 const int32u TOFN=0x544F464E;
190 const int32u TOLY=0x544F4C59;
191 const int32u TOPE=0x544F5045;
192 const int32u TORY=0x544F5259;
193 const int32u TOWN=0x544F574E;
194 const int32u TPE1=0x54504531;
195 const int32u TPE2=0x54504532;
196 const int32u TPE3=0x54504533;
197 const int32u TPE4=0x54504534;
198 const int32u TPOS=0x54504F53;
199 const int32u TPRO=0x5450524F;
200 const int32u TPUB=0x54505542;
201 const int32u TRCK=0x5452434B;
202 const int32u TRDA=0x54524441;
203 const int32u TRSN=0x5452534E;
204 const int32u TRSO=0x5452534F;
205 const int32u TSIZ=0x5453495A;
206 const int32u TSO2=0x54534F32;
207 const int32u TSOA=0x54534F41;
208 const int32u TSOC=0x54534F43;
209 const int32u TSOP=0x54534F50;
210 const int32u TSOT=0x54534F54;
211 const int32u TSRC=0x54535243;
212 const int32u TSSE=0x54535345;
213 const int32u TSST=0x54535354;
214 const int32u TXXX=0x54585858;
215 const int32u TYER=0x54594552;
216 const int32u UFID=0x55464944;
217 const int32u USER=0x55534552;
218 const int32u USLT=0x55534C54;
219 const int32u WCOM=0x57434F4D;
220 const int32u WCOP=0x57434F50;
221 const int32u WOAF=0x574F4146;
222 const int32u WOAR=0x574F4152;
223 const int32u WOAS=0x574F4153;
224 const int32u WORS=0x574F5253;
225 const int32u WPAY=0x57504159;
226 const int32u WPUB=0x57505542;
227 const int32u WXXX=0x57585858;
228 const int32u XRVA=0x58525641;
229 const int32u BUF=0x425546;
230 const int32u CNT=0x434E56;
231 const int32u COM=0x434F4D;
232 const int32u CRA=0x435241;
233 const int32u CRM=0x43524D;
234 const int32u EQU=0x455155;
235 const int32u ETC=0x455443;
236 const int32u GEO=0x47454F;
237 const int32u IPL=0x49504C;
238 const int32u LNK=0x4C4E4B;
239 const int32u MCI=0x4D4349;
240 const int32u MLL=0x4D4C4C;
241 const int32u PIC_=0x504943; //PIC is used by shared libs in GCC
242 const int32u POP=0x504F50;
243 const int32u REV=0x524556;
244 const int32u RVA=0x525641;
245 const int32u SLT=0x534C54;
246 const int32u STC=0x535443;
247 const int32u TAL=0x54414C;
248 const int32u TBP=0x544250;
249 const int32u TCM=0x54434D;
250 const int32u TCO=0x54434F;
251 const int32u TCP=0x544350;
252 const int32u TCR=0x544352;
253 const int32u TDA=0x544441;
254 const int32u TDY=0x544459;
255 const int32u TEN=0x54454E;
256 const int32u TFT=0x544654;
257 const int32u TIM=0x54494D;
258 const int32u TKE=0x544B45;
259 const int32u TLA=0x544C41;
260 const int32u TLE=0x544C45;
261 const int32u TMT=0x544D54;
262 const int32u TOA=0x544F41;
263 const int32u TOF=0x544F46;
264 const int32u TOL=0x544F4C;
265 const int32u TOR=0x544F52;
266 const int32u TOT=0x544F54;
267 const int32u TP1=0x545031;
268 const int32u TP2=0x545032;
269 const int32u TP3=0x545033;
270 const int32u TP4=0x545034;
271 const int32u TPA=0x545041;
272 const int32u TPB=0x545042;
273 const int32u TRC=0x545243;
274 const int32u TRD=0x545244;
275 const int32u TRK=0x54524B;
276 const int32u TSI=0x545349;
277 const int32u TSS=0x545353;
278 const int32u TT1=0x545431;
279 const int32u TT2=0x545432;
280 const int32u TT3=0x545433;
281 const int32u TXT=0x545854;
282 const int32u TXX=0x545858;
283 const int32u TYE=0x545945;
284 const int32u UFI=0x554649;
285 const int32u ULT=0x554C54;
286 const int32u WAF=0x574146;
287 const int32u WAR=0x574152;
288 const int32u WAS=0x574153;
289 const int32u WCM=0x57434D;
290 const int32u WCP=0x574350;
291 const int32u WPB=0x575042;
292 const int32u WXX=0x575858;
293 }
294
295 //***************************************************************************
296 // Constructor/Destructor
297 //***************************************************************************
298
299 //---------------------------------------------------------------------------
File_Id3v2()300 File_Id3v2::File_Id3v2()
301 :File__Analyze()
302 {
303 //Temp
304 Id3v2_Size=0;
305 }
306
307 //***************************************************************************
308 // Static stuff
309 //***************************************************************************
310
311 //---------------------------------------------------------------------------
Static_Synchronize_Tags(const int8u * Buffer,size_t Buffer_Offset,size_t Buffer_Size,bool & Tag_Found)312 bool File_Id3v2::Static_Synchronize_Tags(const int8u* Buffer, size_t Buffer_Offset, size_t Buffer_Size, bool &Tag_Found)
313 {
314 //Buffer size
315 if (Buffer_Offset+3>Buffer_Size)
316 return false;
317
318 //ID
319 if ((Buffer[Buffer_Offset ]==0x49 // "ID3"
320 && Buffer[Buffer_Offset+1]==0x44
321 && Buffer[Buffer_Offset+2]==0x33)
322 || (Buffer[Buffer_Offset ]==0x65 // "ea3", found in OpenMG
323 && Buffer[Buffer_Offset+1]==0x61
324 && Buffer[Buffer_Offset+2]==0x33))
325 Tag_Found=true;
326 else
327 Tag_Found=false;
328
329 //Continue
330 return true;
331 }
332
333 //***************************************************************************
334 // Streams management
335 //***************************************************************************
336
337 //---------------------------------------------------------------------------
Streams_Fill()338 void File_Id3v2::Streams_Fill()
339 {
340 if (Count_Get(Stream_General)==0)
341 return;
342
343 //Specific formats (multiple Id3v2 tags for one MI tag)
344 if (Retrieve(Stream_General, 0, General_Recorded_Date).empty() && !Year.empty())
345 {
346 Ztring Recorded_Date=Year;
347 if (!Month.empty())
348 {
349 Recorded_Date+=__T('-');
350 Recorded_Date+=Month;
351 if (!Day.empty())
352 {
353 Recorded_Date+=__T('-');
354 Recorded_Date+=Day;
355 if (!Hour.empty())
356 {
357 Recorded_Date+=__T(' ');
358 Recorded_Date+=Hour;
359 if (!Minute.empty())
360 {
361 Recorded_Date+=__T(':');
362 Recorded_Date+=Minute;
363 }
364 }
365 }
366 }
367 Fill(Stream_General, 0, General_Recorded_Date, Recorded_Date);
368 }
369 }
370
371 //***************************************************************************
372 // Buffer - File header
373 //***************************************************************************
374
375 //---------------------------------------------------------------------------
FileHeader_Parse()376 void File_Id3v2::FileHeader_Parse()
377 {
378 //Parsing
379 int32u Size;
380 int8u Flags;
381 bool ExtendedHeader;
382 Skip_C3( "identifier");
383 Get_B1 (Id3v2_Version, "version_major");
384 Skip_B1( "version_revision");
385 Get_B1 (Flags, "flags");
386 Get_Flags (Flags, 7, Unsynchronisation_Global, "Unsynchronisation");
387 Get_Flags (Flags, 6, ExtendedHeader, "Extended header");
388 Skip_Flags(Flags, 5, "Experimental indicator");
389 Get_B4 (Size, "Size");
390 Id3v2_Size=((Size>>0)&0x7F)
391 | ((Size>>1)&0x3F80)
392 | ((Size>>2)&0x1FC000)
393 | ((Size>>3)&0x0FE00000);
394 Param_Info1(Id3v2_Size);
395 if (ExtendedHeader)
396 {
397 Element_Begin1("Extended header");
398 int32u Size_Extended;
399 Get_B4 (Size_Extended, "Size");
400 Skip_XX(Size_Extended, "Extended header");
401 Element_End0();
402 }
403
404 FILLING_BEGIN();
405 //Versions
406 switch (Id3v2_Version)
407 {
408 case 2 : break;
409 case 3 : break;
410 case 4 : break;
411 default :
412 Skip_XX(Id3v2_Size, "Data");
413 return;
414 }
415
416 Accept("Id3v2");
417 Stream_Prepare(Stream_General);
418
419 Stream_Prepare(Stream_Audio);
420 FILLING_END();
421 }
422
423 //***************************************************************************
424 // Buffer - Per element
425 //***************************************************************************
426
427 //---------------------------------------------------------------------------
Header_Parse()428 void File_Id3v2::Header_Parse()
429 {
430 Unsynchronisation_Frame=false;
431 DataLengthIndicator=false;
432
433 if (Id3v2_Size<10) //first 10 is minimum size of a tag, Second 10 is ID3v2 header size
434 {
435 //Not enough place for a tag, must be padding
436 Header_Fill_Code((int64u)-1, "Padding");
437 Header_Fill_Size(Id3v2_Size);
438 return;
439 }
440
441 if (Buffer_Offset+10>Buffer_Size)
442 {
443 Element_WaitForMoreData();
444 return; //Not enough buffer
445 }
446
447 //Testing padding
448 int32u Frame_ID, Size;
449 Frame_ID=CC1(Buffer+Buffer_Offset);
450 if (Frame_ID==0x00)
451 {
452 //This is the padding
453 Header_Fill_Code(0xFFFFFFFF, "Padding");
454 Header_Fill_Size(Id3v2_Size);
455 return;
456 }
457
458 //Parsing
459 if (Id3v2_Version==2)
460 {
461 Get_C3 (Frame_ID, "Frame ID");
462 Get_B3 (Size, "Size");
463 }
464 else
465 {
466 int16u Flags;
467 Get_C4 (Frame_ID, "Frame ID");
468 if (!(Frame_ID&0xFF))
469 Frame_ID>>=8;
470 Get_B4 (Size, "Size");
471 if (Id3v2_Version!=3)
472 {
473 Size=((Size>>0)&0x7F)
474 | ((Size>>1)&0x3F80)
475 | ((Size>>2)&0x1FC000)
476 | ((Size>>3)&0x0FE00000);
477 Param_Info2(Size, " bytes");
478 }
479 Get_B2 (Flags, "Flags");
480 if (Id3v2_Version==3)
481 {
482 Skip_Flags(Flags, 15, "Tag alter preservation");
483 Skip_Flags(Flags, 14, "File alter preservation");
484 Skip_Flags(Flags, 13, "Read only");
485 Skip_Flags(Flags, 7, "Compression");
486 Skip_Flags(Flags, 6, "Encryption");
487 Skip_Flags(Flags, 5, "Grouping identity");
488 }
489 if (Id3v2_Version==4)
490 {
491 Skip_Flags(Flags, 14, "Tag alter preservation");
492 Skip_Flags(Flags, 13, "File alter preservation");
493 Skip_Flags(Flags, 12, "Read only");
494 Skip_Flags(Flags, 6, "Grouping identity");
495 Skip_Flags(Flags, 3, "Compression");
496 Skip_Flags(Flags, 2, "Encryption");
497 Get_Flags (Flags, 1, Unsynchronisation_Frame, "Unsynchronisation");
498 Get_Flags (Flags, 0, DataLengthIndicator, "Data length indicator");
499 }
500 }
501
502 //Hanlding Unsynchronisation
503 if (Unsynchronisation_Global || Unsynchronisation_Frame)
504 {
505 if (Buffer_Offset+(size_t)Element_Offset+Size>Buffer_Size)
506 {
507 Element_WaitForMoreData();
508 return;
509 }
510 for (size_t Element_Offset_Unsynch=0; Element_Offset_Unsynch+2<Element_Offset+Size; Element_Offset_Unsynch++)
511 if (CC2(Buffer+Buffer_Offset+Element_Offset_Unsynch)==0xFF00)
512 {
513 Size++;
514 if (Buffer_Offset+(size_t)Element_Offset+Size>Buffer_Size)
515 {
516 Element_WaitForMoreData();
517 return;
518 }
519 }
520 }
521
522 //Filling
523 Ztring ToShow;
524 if (Id3v2_Version==2)
525 ToShow.From_CC3(Frame_ID);
526 else
527 ToShow.From_CC4(Frame_ID);
528 Header_Fill_Code(Frame_ID, ToShow);
529 Header_Fill_Size(Element_Offset+Size);
530 }
531
532 //---------------------------------------------------------------------------
Data_Parse()533 void File_Id3v2::Data_Parse()
534 {
535 Id3v2_Size-=Header_Size+Element_Size;
536
537 int32u DataLength=(int32u)-1;
538 if (DataLengthIndicator)
539 {
540 Get_B4 (DataLength, "Data length");
541 DataLength=((DataLength>>0)&0x7F)
542 | ((DataLength>>1)&0x3F80)
543 | ((DataLength>>2)&0x1FC000)
544 | ((DataLength>>3)&0x0FE00000);
545 Param_Info2(DataLength, " bytes");
546 }
547
548 //Unsynchronisation
549 int8u* Buffer_Unsynch=NULL;
550 const int8u* Save_Buffer=Buffer;
551 int64u Save_File_Offset=File_Offset;
552 size_t Save_Buffer_Offset=Buffer_Offset;
553 int64u Save_Element_Size=Element_Size;
554 int64u Element_Offset_Unsynch=Element_Offset;
555 std::vector<size_t> Unsynch_List;
556 if (Unsynchronisation_Global || Unsynchronisation_Frame)
557 {
558 while (Element_Offset_Unsynch+2<Element_Size)
559 {
560 if (CC2(Buffer+Buffer_Offset+(size_t)Element_Offset_Unsynch)==0xFF00)
561 Unsynch_List.push_back((size_t)(Element_Offset_Unsynch+1));
562 Element_Offset_Unsynch++;
563 }
564 if (DataLength!=(int32u)-1 && 4+DataLength!=Element_Size-Unsynch_List.size())
565 {
566 Skip_XX(Element_Size-Element_Offset, "Size coherency issue");
567 return;
568 }
569 if (!Unsynch_List.empty())
570 {
571 //We must change the buffer for keeping out
572 File_Offset=Save_File_Offset+Buffer_Offset;
573 Element_Size=Save_Element_Size-Unsynch_List.size();
574 Buffer_Offset=0;
575 Buffer_Unsynch=new int8u[(size_t)Element_Size];
576 for (size_t Pos=0; Pos<=Unsynch_List.size(); Pos++)
577 {
578 size_t Pos0=(Pos==Unsynch_List.size())?(size_t)Save_Element_Size:(Unsynch_List[Pos]);
579 size_t Pos1=(Pos==0)?0:(Unsynch_List[Pos-1]+1);
580 size_t Buffer_Unsynch_Begin=Pos1-Pos;
581 size_t Save_Buffer_Begin =Pos1;
582 size_t Size= Pos0-Pos1;
583 std::memcpy(Buffer_Unsynch+Buffer_Unsynch_Begin, Save_Buffer+Save_Buffer_Offset+Save_Buffer_Begin, Size);
584 }
585 Buffer=Buffer_Unsynch;
586 }
587 }
588
589 #define CASE_INFO(_NAME, _DETAIL) \
590 case Elements::_NAME : Element_Info1(_DETAIL); _NAME(); break;
591
592 //Parsing
593 Element_Value.clear();
594 Element_Values.clear();
595 switch (Element_Code)
596 {
597 CASE_INFO(AENC, "Audio encryption");
598 CASE_INFO(APIC, "Attached picture");
599 CASE_INFO(ASPI, "Audio seek point index");
600 CASE_INFO(COMM, "Comments");
601 CASE_INFO(COMR, "Commercial frame");
602 CASE_INFO(ENCR, "Encryption method registration");
603 CASE_INFO(EQU2, "Equalisation (2)");
604 CASE_INFO(EQUA, "Equalization");
605 CASE_INFO(ETCO, "Event timing codes");
606 CASE_INFO(GEOB, "General encapsulated object");
607 CASE_INFO(GRID, "Group identification registration");
608 CASE_INFO(IPLS, "Involved people list");
609 CASE_INFO(LINK, "Linked information");
610 CASE_INFO(MCDI, "Music CD identifier");
611 CASE_INFO(MLLT, "MPEG location lookup table");
612 CASE_INFO(OWNE, "Ownership frame");
613 CASE_INFO(PCNT, "Play counter");
614 CASE_INFO(POPM, "Popularimeter");
615 CASE_INFO(POSS, "Position synchronisation frame");
616 CASE_INFO(PRIV, "Private frame");
617 CASE_INFO(RBUF, "Recommended buffer size");
618 CASE_INFO(RGAD, "Replay Gain Adjustment");
619 CASE_INFO(RVA2, "Relative volume adjustment (2)");
620 CASE_INFO(RVRB, "Reverb");
621 CASE_INFO(SEEK, "Seek frame");
622 CASE_INFO(SIGN, "Signature frame");
623 CASE_INFO(SYLT, "Synchronised lyric/text");
624 CASE_INFO(SYTC, "Synchronised tempo codes");
625 CASE_INFO(TALB, "Album/Movie/Show title");
626 CASE_INFO(TBPM, "BPM (beats per minute)");
627 CASE_INFO(TCAT, "iTunes Podcast category");
628 CASE_INFO(TCMP, "iTunes Compilation Flag");
629 CASE_INFO(TCOM, "Composer");
630 CASE_INFO(TCON, "Content type");
631 CASE_INFO(TCOP, "Copyright message");
632 CASE_INFO(TDAT, "Date");
633 CASE_INFO(TDEN, "Encoding time");
634 CASE_INFO(TDLY, "Playlist delay");
635 CASE_INFO(TDOR, "Original release time");
636 CASE_INFO(TDRC, "Recording time");
637 CASE_INFO(TDRL, "Release time");
638 CASE_INFO(TDTG, "Tagging time");
639 CASE_INFO(TENC, "Encoded by");
640 CASE_INFO(TEXT, "Lyricist/Text writer");
641 CASE_INFO(TFLT, "File type");
642 CASE_INFO(TIME, "Time");
643 CASE_INFO(TIPL, "Involved people list");
644 CASE_INFO(TIT1, "Content group description");
645 CASE_INFO(TIT2, "Title/songname/content description");
646 CASE_INFO(TIT3, "Subtitle/Description refinement");
647 CASE_INFO(TKEY, "Initial key");
648 CASE_INFO(TLAN, "Language(s)");
649 CASE_INFO(TLEN, "Length");
650 CASE_INFO(TMCL, "Musician credits list");
651 CASE_INFO(TMED, "Media type");
652 CASE_INFO(TMOO, "Mood");
653 CASE_INFO(TOAL, "Original album/movie/show title");
654 CASE_INFO(TOFN, "Original filename");
655 CASE_INFO(TOLY, "Original lyricist(s)/text writer(s)");
656 CASE_INFO(TOPE, "Original artist(s)/performer(s)");
657 CASE_INFO(TORY, "Original release year");
658 CASE_INFO(TOWN, "File owner/licensee");
659 CASE_INFO(TPE1, "Lead performer(s)/Soloist(s)");
660 CASE_INFO(TPE2, "Band/orchestra/accompaniment");
661 CASE_INFO(TPE3, "Conductor/performer refinement");
662 CASE_INFO(TPE4, "Interpreted, remixed, or otherwise modified by");
663 CASE_INFO(TPOS, "Part of a set");
664 CASE_INFO(TPRO, "Produced notice");
665 CASE_INFO(TPUB, "Publisher");
666 CASE_INFO(TRCK, "Track number/Position in set");
667 CASE_INFO(TRDA, "Recording dates");
668 CASE_INFO(TRSN, "Internet radio station name");
669 CASE_INFO(TRSO, "Internet radio station owner");
670 CASE_INFO(TSIZ, "Size");
671 CASE_INFO(TSO2, "Performer order");
672 CASE_INFO(TSOA, "Album sort order");
673 CASE_INFO(TSOC, "Composer sort order");
674 CASE_INFO(TSOP, "Performer sort order");
675 CASE_INFO(TSOT, "Title sort order");
676 CASE_INFO(TSRC, "ISRC (international standard recording code)");
677 CASE_INFO(TSSE, "Software/Hardware and settings used for encoding");
678 CASE_INFO(TSST, "Set subtitle");
679 CASE_INFO(TXXX, "User defined text information frame");
680 CASE_INFO(TYER, "Year");
681 CASE_INFO(UFID, "Unique file identifier");
682 CASE_INFO(USER, "Terms of use");
683 CASE_INFO(USLT, "Unsynchronised lyric/text transcription");
684 CASE_INFO(WCOM, "Commercial information");
685 CASE_INFO(WCOP, "Copyright/Legal information");
686 CASE_INFO(WOAF, "Official audio file webpage");
687 CASE_INFO(WOAR, "Official artist/performer webpage");
688 CASE_INFO(WOAS, "Official audio source webpage");
689 CASE_INFO(WORS, "Official Internet radio station homepage");
690 CASE_INFO(WPAY, "Payment");
691 CASE_INFO(WPUB, "Publishers official webpage");
692 CASE_INFO(WXXX, "User defined URL link frame");
693 CASE_INFO(XRVA, "Relative volume adjustment (2)");
694 CASE_INFO(BUF, "Recommended buffer size");
695 CASE_INFO(CNT, "Play counter");
696 CASE_INFO(COM, "Comments");
697 CASE_INFO(CRA, "Audio encryption");
698 CASE_INFO(CRM, "Encrypted meta frame");
699 CASE_INFO(EQU, "Equalization");
700 CASE_INFO(ETC, "Event timing codes");
701 CASE_INFO(GEO, "General encapsulated object");
702 CASE_INFO(IPL, "Involved people list");
703 CASE_INFO(LNK, "Linked information");
704 CASE_INFO(MCI, "Music CD Identifier");
705 CASE_INFO(MLL, "MPEG location lookup table");
706 CASE_INFO(PIC_, "Attached picture");
707 CASE_INFO(POP, "Popularimeter");
708 CASE_INFO(REV, "Reverb");
709 CASE_INFO(RVA, "Relative volume adjustment");
710 CASE_INFO(SLT, "Synchronized lyric/text");
711 CASE_INFO(STC, "Synced tempo codes");
712 CASE_INFO(TAL, "Album/Movie/Show title");
713 CASE_INFO(TBP, "BPM (Beats Per Minute)");
714 CASE_INFO(TCM, "Composer");
715 CASE_INFO(TCO, "Content type");
716 CASE_INFO(TCP, "iTunes Compilation Flag");
717 CASE_INFO(TCR, "Copyright message");
718 CASE_INFO(TDA, "Date");
719 CASE_INFO(TDY, "Playlist delay");
720 CASE_INFO(TEN, "Encoded by");
721 CASE_INFO(TFT, "File type");
722 CASE_INFO(TIM, "Time");
723 CASE_INFO(TKE, "Initial key");
724 CASE_INFO(TLA, "Language(s)");
725 CASE_INFO(TLE, "Length");
726 CASE_INFO(TMT, "Media type");
727 CASE_INFO(TOA, "Original artist(s)/performer(s)");
728 CASE_INFO(TOF, "Original filename");
729 CASE_INFO(TOL, "Original Lyricist(s)/text writer(s)");
730 CASE_INFO(TOR, "Original release year");
731 CASE_INFO(TOT, "Original album/Movie/Show title");
732 CASE_INFO(TP1, "Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group");
733 CASE_INFO(TP2, "Band/Orchestra/Accompaniment");
734 CASE_INFO(TP3, "Conductor/Performer refinement");
735 CASE_INFO(TP4, "Interpreted, remixed, or otherwise modified by");
736 CASE_INFO(TPA, "Part of a set");
737 CASE_INFO(TPB, "Publisher");
738 CASE_INFO(TRC, "ISRC (International Standard Recording Code)");
739 CASE_INFO(TRD, "Recording dates");
740 CASE_INFO(TRK, "Track number/Position in set");
741 CASE_INFO(TSI, "Size");
742 CASE_INFO(TSS, "Software/hardware and settings used for encoding");
743 CASE_INFO(TT1, "Content group description");
744 CASE_INFO(TT2, "Title/Songname/Content description");
745 CASE_INFO(TT3, "Subtitle/Description refinement");
746 CASE_INFO(TXT, "Lyricist/text writer");
747 CASE_INFO(TXX, "User defined text information frame");
748 CASE_INFO(TYE, "Year");
749 CASE_INFO(UFI, "Unique file identifier");
750 CASE_INFO(ULT, "Unsychronized lyric/text transcription");
751 CASE_INFO(WAF, "Official audio file webpage");
752 CASE_INFO(WAR, "Official artist/performer webpage");
753 CASE_INFO(WAS, "Official audio source webpage");
754 CASE_INFO(WCM, "Commercial information");
755 CASE_INFO(WCP, "Copyright/Legal information");
756 CASE_INFO(WPB, "Publishers official webpage");
757 CASE_INFO(WXX, "User defined URL link frame");
758 default : Skip_XX(Element_Size, "Data");
759 }
760
761 if (!Unsynch_List.empty())
762 {
763 //We must change the buffer for keeping out
764 File_Offset=Save_File_Offset;
765 Element_Size=Save_Element_Size;
766 Buffer_Offset=Save_Buffer_Offset;
767 delete[] Buffer; Buffer=Save_Buffer;
768 Buffer_Unsynch=NULL; //Same as Buffer...
769 Element_Offset+=Unsynch_List.size();
770 }
771
772 if (!Id3v2_Size)
773 Finish("Id3v2");
774 }
775
776 //***************************************************************************
777 // Elements
778 //***************************************************************************
779
780 //---------------------------------------------------------------------------
781 //
T___()782 void File_Id3v2::T___()
783 {
784 int8u Encoding;
785 Get_B1 (Encoding, "Text_encoding");
786 switch (Encoding)
787 {
788 case 0 : Get_ISO_8859_1 (Element_Size-Element_Offset, Element_Value, "Information"); break;
789 case 1 : Get_UTF16 (Element_Size-Element_Offset, Element_Value, "Information"); break;
790 case 2 : Get_UTF16B (Element_Size-Element_Offset, Element_Value, "Information"); break;
791 case 3 : Get_UTF8 (Element_Size-Element_Offset, Element_Value, "Information"); break;
792 default : ;
793 }
794
795 //Exceptions
796 if (Element_Code==Elements::TCMP || Element_Code==Elements::TCP)
797 {
798 if (Element_Value==__T("0")) Element_Value.clear(); //This is usually set to 0 even if the user did not explicitely indicated something (default)
799 if (Element_Value==__T("1")) Element_Value=__T("Yes");
800 }
801
802 //Filling
803 if (Element_Value.empty())
804 return;
805 Fill_Name();
806 }
807
808 //---------------------------------------------------------------------------
809 //
T__X()810 void File_Id3v2::T__X()
811 {
812 //Integrity
813 if (Element_Size<(Elements::TXXX?4:1))
814 {
815 Element_Values(1).clear();
816 Element_Values(0).clear();
817 return;
818 }
819
820 int8u Encoding;
821 Get_B1 (Encoding, "Text_encoding");
822 if (Element_Code!=Elements::TXXX)
823 Skip_C3( "Language");
824 size_t Value0_Size=0;
825 switch (Encoding)
826 {
827 case 0 :
828 case 3 : //1-byte char
829 while (Element_Offset+Value0_Size<Element_Size && Buffer[Buffer_Offset+(size_t)Element_Offset+Value0_Size]!='\0')
830 Value0_Size++;
831 if (Element_Offset+Value0_Size>=Element_Size)
832 return; //Problem
833 switch (Encoding)
834 {
835 case 0 : Get_ISO_8859_1 (Value0_Size, Element_Values(0), "Short_content_descrip"); break;
836 case 3 : Get_UTF8 (Value0_Size, Element_Values(0), "Short_content_descrip"); break;
837 default : ;
838 }
839 Skip_B1( "Null");
840 switch (Encoding)
841 {
842 case 0 : Get_ISO_8859_1 (Element_Size-Element_Offset, Element_Values(1), "The_actual_text"); break;
843 case 3 : Get_UTF8 (Element_Size-Element_Offset, Element_Values(1), "The_actual_text"); break;
844 default : ;
845 }
846 break;
847 case 1 :
848 case 2 : //2-byte char
849 while (Element_Offset+Value0_Size+1<Element_Size
850 && !(Buffer[Buffer_Offset+(size_t)Element_Offset+Value0_Size ]=='\0'
851 && Buffer[Buffer_Offset+(size_t)Element_Offset+Value0_Size+1]=='\0')) //2-byte zero
852 Value0_Size+=2;
853 if (Element_Offset+Value0_Size>=Element_Size)
854 return; //Problem
855 switch (Encoding)
856 {
857 case 1 : Get_UTF16 (Value0_Size, Element_Values(0), "Short_content_descrip"); break;
858 case 2 : Get_UTF16B(Value0_Size, Element_Values(0), "Short_content_descrip"); break;
859 default : ;
860 }
861 Skip_B2( "Null");
862 switch (Encoding)
863 {
864 case 1 : Get_UTF16 (Element_Size-Element_Offset, Element_Values(1), "The_actual_text"); break;
865 case 2 : Get_UTF16B(Element_Size-Element_Offset, Element_Values(1), "The_actual_text"); break;
866 default : ;
867 }
868 break;
869 default: //Unknown
870 Skip_XX(Element_Size-Element_Offset, "Unknown");
871 ;
872 }
873 }
874
875 //---------------------------------------------------------------------------
W___()876 void File_Id3v2::W___()
877 {
878 Get_ISO_8859_1(Element_Size, Element_Value, "URL");
879
880 //Filling
881 Fill_Name();
882 }
883
884 //---------------------------------------------------------------------------
W__X()885 void File_Id3v2::W__X()
886 {
887 if (Element_Size<1)
888 return; //Problem
889
890 int8u Encoding;
891 Get_B1 (Encoding, "Text_encoding");
892 switch (Encoding)
893 {
894 case 0 : Get_ISO_8859_1 (Element_Size-1, Element_Values(0), "Description"); break;
895 case 1 : Get_UTF16 (Element_Size-1, Element_Values(0), "Description"); break;
896 case 2 : Get_UTF16B (Element_Size-1, Element_Values(0), "Description"); break;
897 case 3 : Get_UTF8 (Element_Size-1, Element_Values(0), "Description"); break;
898 default : ;
899 }
900 Element_Offset=1;
901 switch (Encoding)
902 {
903 case 0 : Element_Offset+=Element_Values(0).size()+1; break; //NULL
904 case 1 : Element_Offset+=Element_Values(0).size()*2+4; break; //UTF-16 BOM + UTF-16 NULL
905 case 2 : Element_Offset+=Element_Values(0).size()*2+2; break; //UTF-16 NULL
906 case 3 : Element_Offset+=Element_Values(0).To_UTF8().size()+1; break; //UTF-8 NULL
907 default : ;
908 }
909 if (Element_Offset<Element_Size)
910 Get_ISO_8859_1(Element_Size-Element_Offset, Element_Values(1), "URL");
911 }
912
913 //---------------------------------------------------------------------------
APIC()914 void File_Id3v2::APIC()
915 {
916 int8u Encoding, PictureType;
917 Ztring Mime, Description;
918 Get_B1 (Encoding, "Text_encoding");
919 if (Id3v2_Version==2)
920 {
921 int32u Image_format;
922 Get_C3(Image_format, "Image_format");
923 switch (Image_format)
924 {
925 case 0x504E47 : Mime="image/png"; break;
926 case 0x4A5047 : Mime="image/jpeg"; break;
927 default : ;
928 }
929 }
930 else
931 {
932 int64u Element_Offset_Real=Element_Offset;
933 Get_ISO_8859_1(Element_Size-Element_Offset, Mime, "MIME_type");
934 Element_Offset=Element_Offset_Real+Mime.size()+1;
935 }
936 Get_B1 (PictureType, "Picture_type"); Element_Info1(Id3v2_PictureType(PictureType));
937 int64u Element_Offset_Real=Element_Offset;
938 switch (Encoding)
939 {
940 case 0 : Get_ISO_8859_1 (Element_Size-Element_Offset, Description, "Description"); break;
941 case 1 : Get_UTF16 (Element_Size-Element_Offset, Description, "Description"); break;
942 case 2 : Get_UTF16B (Element_Size-Element_Offset, Description, "Description"); break;
943 case 3 : Get_UTF8 (Element_Size-Element_Offset, Description, "Description"); break;
944 default : ;
945 }
946 Element_Offset=Element_Offset_Real;
947 switch (Encoding)
948 {
949 case 0 : Element_Offset+=Description.size()+1; break; //NULL
950 case 1 : Element_Offset+=Description.size()*2+4; break; //UTF-16 BOM + UTF-16 NULL
951 case 2 : Element_Offset+=Description.size()*2+2; break; //UTF-16 NULL
952 case 3 : Element_Offset+=Description.To_UTF8().size()+1; break; //UTF-8 NULL
953 default : ;
954 }
955 if (Element_Offset>Element_Size)
956 return; //There is a problem
957
958 //Filling
959 Fill_Name();
960 Fill(Stream_General, 0, General_Cover_Description, Description);
961 Fill(Stream_General, 0, General_Cover_Type, Id3v2_PictureType(PictureType));
962 Fill(Stream_General, 0, General_Cover_Mime, Mime);
963 #if MEDIAINFO_ADVANCED
964 if (MediaInfoLib::Config.Flags1_Get(Flags_Cover_Data_base64))
965 {
966 std::string Data_Raw((const char*)(Buffer+(size_t)(Buffer_Offset+Element_Offset)), (size_t)(Element_Size-Element_Offset));
967 std::string Data_Base64(Base64::encode(Data_Raw));
968 Fill(Stream_General, 0, General_Cover_Data, Data_Base64);
969 }
970 #endif //MEDIAINFO_ADVANCED
971
972 Skip_XX(Element_Size-Element_Offset, "Data");
973 }
974
975 //---------------------------------------------------------------------------
COMM()976 void File_Id3v2::COMM()
977 {
978 T__X();
979
980 //Testing
981 if (Element_Values(0)==__T("iTunes_CDDB_IDs")) return;
982 else if (Element_Values(0)==__T("iTunNORM")) return;
983 else if (Element_Values(0)==__T("iTunSMPB")) return;
984 else if (Element_Values(0)==__T("Songs-DB_Tempo")) return;
985 else if (Element_Values(0)==__T("Songs-DB_Preference")) return;
986 else if (Element_Values(0)==__T("MusicMatch_Tempo")) return;
987 else if (Element_Values(0)==__T("MusicMatch_Mood"))
988 {
989 if (Retrieve(Stream_General, 0, General_Mood).empty())
990 Element_Values(0)=__T("Mood");
991 else
992 return;
993 }
994 else if (Element_Values(0)==__T("MusicMatch_Preference")) return;
995
996 //Filling
997 if (Element_Values(0).empty())
998 {
999 if (Element_Values(1).find(__T("ExactAudioCopy"))==0)
1000 {
1001 Fill(Stream_General, 0, General_Encoded_Application, Element_Values(1));
1002 return;
1003 }
1004
1005 Element_Values(0)=__T("Comment");
1006 }
1007 Fill_Name();
1008 }
1009
1010 //---------------------------------------------------------------------------
RGAD()1011 void File_Id3v2::RGAD()
1012 {
1013 //Parsing
1014 float32 Peak_Amplitude;
1015 Get_BF4 (Peak_Amplitude, "Peak Amplitude");
1016 while (Element_Offset+2<=Element_Size)
1017 {
1018 Element_Begin1("Gain Adjustement");
1019 int16u Replay_Gain_Adjustment;
1020 int8u Name_code;
1021 bool Sign_bit;
1022 BS_Begin();
1023 Get_S1 (3, Name_code, "Name code"); Param_Info1(Id3v2_RGAD_Name_code[Name_code]);
1024 Info_S1(3, Originator_code, "Originator code"); Param_Info1(Id3v2_RGAD_Originator_code[Originator_code]);
1025 Get_SB (Sign_bit, "Sign bit");
1026 Get_S2 (9, Replay_Gain_Adjustment, "Replay Gain Adjustment"); Param_Info3 ((Sign_bit?-1:1)*(float)Replay_Gain_Adjustment/10, " dB", 1);
1027 BS_End();
1028 Element_End0();
1029
1030 FILLING_BEGIN();
1031 switch (Name_code)
1032 {
1033 case 1 : if (Retrieve(Stream_Audio, 0, Audio_ReplayGain_Gain).empty()) //this tag is not precise, we prefer other RG tags
1034 Fill(Stream_Audio, 0, Audio_ReplayGain_Gain, (Sign_bit?-1:1)*(float)Replay_Gain_Adjustment/10, 1);
1035 break;
1036 case 2 : if (Retrieve(Stream_General, 0, General_Album_ReplayGain_Gain).empty()) //this tag is not precise, we prefer other RG tags
1037 Fill(Stream_General, 0, General_Album_ReplayGain_Gain, (Sign_bit?-1:1)*(float)Replay_Gain_Adjustment/10, 1);
1038 break;
1039 default: ;
1040 }
1041 FILLING_END();
1042 }
1043
1044 FILLING_BEGIN();
1045 if (Peak_Amplitude && Retrieve(Stream_Audio, 0, Audio_ReplayGain_Peak).empty()) //this tag is not precise, we prefer other RG tags
1046 Fill(Stream_Audio, 0, Audio_ReplayGain_Peak, Peak_Amplitude, 6);
1047 FILLING_END();
1048 }
1049
1050 //---------------------------------------------------------------------------
PRIV()1051 void File_Id3v2::PRIV()
1052 {
1053 //Parsing
1054 //Ztring Owner;
1055 //Get_ISO_8859_1(Element_Size, Owner, "Owner identifier");
1056 string Owner;
1057 size_t Owner_Size=0;
1058 while (Element_Offset+Owner_Size<Element_Size && Buffer[Buffer_Offset+(size_t)Element_Offset+Owner_Size]!='\0')
1059 Owner_Size++;
1060 if (Owner_Size==0 || Element_Offset+Owner_Size>=Element_Size)
1061 {
1062 Skip_XX(Element_Size-Element_Offset, "Unknown");
1063 return;
1064 }
1065 Get_String(Owner_Size, Owner, "Owner identifier");
1066 Skip_B1( "Null");
1067 if (Owner=="com.apple.streaming.transportStreamTimestamp")
1068 {
1069 //http://tools.ietf.org/html/draft-pantos-http-live-streaming-13
1070 int64u DTS;
1071 Get_B8 (DTS, "DTS");
1072
1073 FILLING_BEGIN();
1074 if (DTS>=0x200000000LL) //33 bits
1075 {
1076 Fill(Stream_Audio, 0, Audio_Delay, DTS/90);
1077 FrameInfo.DTS=DTS*1000000/90;
1078 }
1079 FILLING_END();
1080 }
1081 else
1082 {
1083 Skip_XX(Element_Size-Element_Offset, "Data");
1084 }
1085 }
1086
1087 //---------------------------------------------------------------------------
USLT()1088 void File_Id3v2::USLT()
1089 {
1090 T__X();
1091
1092 //Filling
1093 if (!Element_Values(0).empty())
1094 Element_Values(1)=Element_Values(0)+MediaInfoLib::Config.Language_Get(__T(": "))+Element_Values(1);
1095 Element_Values(0)=__T("Lyrics");
1096
1097 Fill_Name();
1098 }
1099
1100 //---------------------------------------------------------------------------
TXXX()1101 void File_Id3v2::TXXX()
1102 {
1103 T__X();
1104
1105 //Filling
1106 if (Element_Values(0).empty())
1107 Element_Values(0)=__T("Comment");
1108 Fill_Name();
1109 }
1110
1111 //---------------------------------------------------------------------------
SYLT()1112 void File_Id3v2::SYLT()
1113 {
1114 if (Element_Size<6)
1115 {
1116 Skip_XX(Element_Size, "(Problem)");
1117 return;
1118 }
1119
1120 int8u Encoding;
1121 Get_B1 (Encoding, "Text encoding");
1122 Skip_C3( "Language");
1123 Skip_B1( "Time_stamp_format");
1124 Skip_B1( "Content_type");
1125 switch (Encoding)
1126 {
1127 case 0 : Get_ISO_8859_1 (Element_Size-6, Element_Value, "Short_content_descrip"); break;
1128 case 1 : Get_UTF16 (Element_Size-6, Element_Value, "Short_content_descrip"); break;
1129 case 2 : Get_UTF16B (Element_Size-6, Element_Value, "Short_content_descrip"); break;
1130 case 3 : Get_UTF8 (Element_Size-6, Element_Value, "Short_content_descrip"); break;
1131 default : ;
1132 }
1133
1134 //Filling
1135 Fill_Name();
1136 }
1137
1138 //---------------------------------------------------------------------------
WXXX()1139 void File_Id3v2::WXXX()
1140 {
1141 W__X();
1142
1143 //Filling
1144 if (Element_Values(1).empty())
1145 return;
1146 if (Element_Values(0).empty())
1147 Element_Values(0)=__T("URL");
1148 Fill_Name();
1149 }
1150
1151 //***************************************************************************
1152 // Helpers
1153 //***************************************************************************
1154
1155 //---------------------------------------------------------------------------
Fill_Name()1156 void File_Id3v2::Fill_Name()
1157 {
1158 Ztring Value=Ztring().From_CC4((int32u)Element_Code);
1159 if (MediaInfoLib::Config.CustomMapping_IsPresent(__T("Id3v2"), Value))
1160 {
1161 Fill(Stream_General, 0, MediaInfoLib::Config.CustomMapping_Get(__T("Id3v2"), Value).To_Local().c_str(), Element_Value);
1162 return;
1163 }
1164
1165 switch (Element_Code)
1166 {
1167 case Elements::AENC : break;
1168 case Elements::APIC : Fill(Stream_General, 0, General_Cover, "Yes"); break;
1169 case Elements::ASPI : break;
1170 case Elements::COMM : Fill(Stream_General, 0, Element_Values(0).To_UTF8().c_str(), Element_Values(1)); break;
1171 case Elements::COMR : Fill(Stream_General, 0, "Commercial frame", Element_Value); break;
1172 case Elements::ENCR : break;
1173 case Elements::EQU2 : break;
1174 case Elements::EQUA : break;
1175 case Elements::ETCO : break;
1176 case Elements::GEOB : break;
1177 case Elements::GRID : Fill(Stream_General, 0, "Group identification registration", Element_Value); break;
1178 case Elements::IPLS : Fill(Stream_General, 0, "Involved people list", Element_Value); break;
1179 case Elements::LINK : Fill(Stream_General, 0, "Linked information", Element_Value); break;
1180 case Elements::MCDI : Fill(Stream_General, 0, "MCDI", "Yes"); break;
1181 case Elements::MLLT : break;
1182 case Elements::OWNE : Fill(Stream_General, 0, General_Owner, Element_Value); break;
1183 case Elements::PCNT : break;
1184 case Elements::POPM : break;
1185 case Elements::POSS : break;
1186 case Elements::PRIV : break;
1187 case Elements::RBUF : break;
1188 case Elements::RVA2 : break;
1189 case Elements::RVRB : break;
1190 case Elements::SEEK : break;
1191 case Elements::SIGN : break;
1192 case Elements::SYLT : Fill(Stream_General, 0, General_Lyrics, Element_Value); break;
1193 case Elements::SYTC : break;
1194 case Elements::TALB : Fill(Stream_General, 0, General_Album, Element_Value); break;
1195 case Elements::TBPM : Fill(Stream_General, 0, General_BPM, Element_Value); break;
1196 case Elements::TCAT : Fill(Stream_General, 0, General_PodcastCategory, Element_Value); break;
1197 case Elements::TCMP : Fill(Stream_General, 0, General_Compilation, Element_Value); break;
1198 case Elements::TCOM : Fill(Stream_General, 0, General_Composer, Element_Value); break;
1199 case Elements::TCON :
1200 {
1201 if (Element_Value.find(__T('('))==0)
1202 Element_Value=Element_Value.SubString(__T("("), __T(")")); //Replace (nn) by nn
1203 if (Element_Value==__T("0") || Element_Value==__T("255"))
1204 Element_Value.clear();
1205 Fill(Stream_General, 0, General_Genre, Element_Value);
1206 }
1207 break;
1208 case Elements::TCOP : Fill(Stream_General, 0, General_Copyright, Element_Value); break;
1209 case Elements::TDA :
1210 case Elements::TDAT : if (Element_Value.size()==4)
1211 {
1212 Day.assign (Element_Value.c_str(), 0, 2);
1213 Month.assign(Element_Value.c_str(), 2, 2);
1214 }
1215 break;
1216 case Elements::TDEN : Normalize_Date(Element_Value); Fill(Stream_General, 0, "Encoded_Date", Element_Value); break;
1217 case Elements::TDLY : break;
1218 case Elements::TDOR : Normalize_Date(Element_Value); Fill(Stream_General, 0, "Original/Released_Date", Element_Value); break;
1219 case Elements::TDRC : Normalize_Date(Element_Value); Fill(Stream_General, 0, General_Recorded_Date, Element_Value); break;
1220 case Elements::TDRL : Normalize_Date(Element_Value); Fill(Stream_General, 0, General_Released_Date, Element_Value); break;
1221 case Elements::TDTG : Normalize_Date(Element_Value); Fill(Stream_General, 0, General_Tagged_Date, Element_Value); break;
1222 case Elements::TENC : Fill(Stream_General, 0, General_EncodedBy, Element_Value); break;
1223 case Elements::TEXT : Fill(Stream_General, 0, General_Lyricist, Element_Value); break;
1224 case Elements::TFLT : Fill(Stream_General, 0, "File type", Element_Value); break;
1225 case Elements::TIM :
1226 case Elements::TIME : if (Element_Value.size()==4)
1227 {
1228 Hour.assign (Element_Value.c_str(), 0, 2);
1229 Minute.assign(Element_Value.c_str(), 2, 2);
1230 }
1231 break;
1232 case Elements::TIPL : Fill(Stream_General, 0, General_ThanksTo, Element_Value); break;
1233 case Elements::TIT1 : Fill(Stream_General, 0, General_Grouping, Element_Value); break;
1234 case Elements::TIT2 : Fill(Stream_General, 0, General_Track, Element_Value); break;
1235 case Elements::TIT3 : Fill(Stream_General, 0, General_Track_More, Element_Value); break;
1236 case Elements::TKEY : Fill(Stream_General, 0, "Initial key", Element_Value); break;
1237 case Elements::TLAN : Fill(Stream_Audio, 0, Audio_Language, Element_Value); break;
1238 case Elements::TLEN : break; //Fill(Stream_General, 0, "Length", Element_Value); break;
1239 case Elements::TMCL : Fill(Stream_General, 0, "Musician Credit List", Element_Value); break;
1240 case Elements::TMED : Fill(Stream_General, 0, "Media Type", Element_Value); break;
1241 case Elements::TMOO : Fill(Stream_General, 0, "Mood", Element_Value); break;
1242 case Elements::TOAL : Fill(Stream_General, 0, "Original/Album", Element_Value); break;
1243 case Elements::TOFN : Fill(Stream_General, 0, "Original/FileName", Element_Value); break;
1244 case Elements::TOLY : Fill(Stream_General, 0, "Original/Lyricist", Element_Value); break;
1245 case Elements::TOPE : Fill(Stream_General, 0, "Original/Performer", Element_Value); break;
1246 case Elements::TORY : Normalize_Date(Element_Value); Fill(Stream_General, 0, "Original/Released_Date", Element_Value); break;
1247 case Elements::TOWN : Fill(Stream_General, 0, General_Owner, Element_Value); break;
1248 case Elements::TPE1 : Fill(Stream_General, 0, General_Performer, Element_Value); break;
1249 case Elements::TPE2 : Fill(Stream_General, 0, General_Album_Performer, Element_Value); break;
1250 case Elements::TPE3 : Fill(Stream_General, 0, General_Conductor, Element_Value); break;
1251 case Elements::TPE4 : Fill(Stream_General, 0, General_RemixedBy, Element_Value); break;
1252 case Elements::TPOS :
1253 {
1254 ZtringList List; List.Separator_Set(0, __T("/")); List.Write(Element_Value);
1255 if (!List(0).empty())
1256 Fill(Stream_General, 0, General_Part_Position, List(0));
1257 if (!List(1).empty())
1258 Fill(Stream_General, 0, General_Part_Position_Total, List(1));
1259 }
1260 break;
1261 case Elements::TPRO : Fill(Stream_General, 0, General_Producer_Copyright, Element_Value); break;
1262 case Elements::TPUB : Fill(Stream_General, 0, General_Publisher, Element_Value); break;
1263 case Elements::TRCK :
1264 {
1265 ZtringList List; List.Separator_Set(0, __T("/")); List.Write(Element_Value);
1266 if (!List(0).empty())
1267 Fill(Stream_General, 0, General_Track_Position, List(0));
1268 if (!List(1).empty())
1269 Fill(Stream_General, 0, General_Track_Position_Total, List(1));
1270 }
1271 break;
1272 case Elements::TRDA : Normalize_Date(Element_Value); Fill(Stream_General, 0, "Recorded_Date", Element_Value); break;
1273 case Elements::TRSN : Fill(Stream_General, 0, General_ServiceName, Element_Value); break;
1274 case Elements::TRSO : Fill(Stream_General, 0, General_ServiceProvider, Element_Value); break;
1275 case Elements::TSIZ : Fill(Stream_General, 0, "Size", Element_Value); break;
1276 case Elements::TSO2 : Fill(Stream_General, 0, General_Album_Performer_Sort, Element_Value); break;
1277 case Elements::TSOA : Fill(Stream_General, 0, General_Album_Sort, Element_Value); break;
1278 case Elements::TSOC : Fill(Stream_General, 0, General_Composer_Sort, Element_Value); break;
1279 case Elements::TSOP : Fill(Stream_General, 0, General_Performer_Sort, Element_Value); break;
1280 case Elements::TSOT : Fill(Stream_General, 0, General_Track_Sort, Element_Value); break;
1281 case Elements::TSRC : Fill(Stream_General, 0, General_ISRC, Element_Value); break;
1282 case Elements::TSSE : Fill(Stream_General, 0, General_Encoded_Library, Element_Value); break;
1283 case Elements::TSST : Fill(Stream_General, 0, "Set subtitle", Element_Value); break;
1284 case Elements::TXXX : if (Element_Values(0)==__T("AccurateRipResult")) ;
1285 else if (Element_Values(0)==__T("AccurateRipDiscID")) ;
1286 else if (Element_Values(0)==__T("CT_GAPLESS_DATA")) ;
1287 else if (Element_Values(0)==__T("DISCNUMBER")) Fill(Stream_General, 0, General_Part_Position, Element_Values(1), true);
1288 else if (Element_Values(0)==__T("DISCTOTAL")) Fill(Stream_General, 0, General_Part_Position_Total, Element_Values(1), true);
1289 else if (Element_Values(0)==__T("first_played_timestamp")) Fill(Stream_General, 0, General_Played_First_Date, Ztring().Date_From_Milliseconds_1601(Element_Values(1).To_int64u()/10000));
1290 else if (Element_Values(0)==__T("last_played_timestamp")) Fill(Stream_General, 0, General_Played_Last_Date, Ztring().Date_From_Milliseconds_1601(Element_Values(1).To_int64u()/10000));
1291 else if (Element_Values(0)==__T("play_count")) Fill(Stream_General, 0, General_Played_Count, Element_Values(1).To_int64u());
1292 else if (Element_Values(0)==__T("added_timestamp")) Fill(Stream_General, 0, General_Added_Date, Ztring().Date_From_Milliseconds_1601(Element_Values(1).To_int64u()/10000));
1293 else if (Element_Values(0)==__T("replaygain_album_gain")) Fill(Stream_General, 0, General_Album_ReplayGain_Gain, Element_Values(1).To_float64(), 2, true);
1294 else if (Element_Values(0)==__T("replaygain_album_peak")) Fill(Stream_General, 0, General_Album_ReplayGain_Peak, Element_Values(1).To_float64(), 6, true);
1295 else if (Element_Values(0)==__T("replaygain_track_gain")) Fill(Stream_Audio, 0, Audio_ReplayGain_Gain, Element_Values(1).To_float64(), 2, true);
1296 else if (Element_Values(0)==__T("replaygain_track_peak")) Fill(Stream_Audio, 0, Audio_ReplayGain_Peak, Element_Values(1).To_float64(), 6, true);
1297 else if (Element_Values(0)==__T("TRACKTOTAL")) Fill(Stream_General, 0, General_Track_Position_Total, Element_Values(1), true);
1298 else if (Element_Values(0)==__T("OMG_AGENR")) ; //Duplicate of Genre
1299 else if (Element_Values(0)==__T("OMG_ALBMS")) ; //Duplicate of Album
1300 else if (Element_Values(0)==__T("OMG_ASGTM")) ; //?
1301 else if (Element_Values(0)==__T("OMG_ATPE1")) ; //Duplicate of Title
1302 else if (Element_Values(0)==__T("OMG_TIT2S")) ; //Duplicate of Title
1303 else if (Element_Values(0)==__T("OMG_TPE1S")) ; //Duplicate of Artist
1304 else if (Element_Values(0)==__T("OMG_TRACK")) Fill(Stream_General, 0, General_Track_Position, Element_Values(1), true);
1305 else if (Element_Values(0)==__T("OMG_TRLDA")) ; //Duplicate of Date
1306 else
1307 Fill(Stream_General, 0, Element_Values(0).To_UTF8().c_str(), Element_Values(1));
1308 break;
1309 case Elements::TYER : Year=Element_Value; break;
1310 case Elements::UFID : Fill(Stream_Audio, 0, "UID", Element_Value); break;
1311 case Elements::USER : Fill(Stream_General, 0, General_TermsOfUse, Element_Value); break;
1312 case Elements::USLT : Fill(Stream_General, 0, Element_Values(0).To_UTF8().c_str(), Element_Values(1)); break;
1313 case Elements::WCOM : Fill(Stream_General, 0, "Commercial information", Element_Value); break;
1314 case Elements::WCOP : Fill(Stream_General, 0, "Copyright/Legal information", Element_Value); break;
1315 case Elements::WOAF : Fill(Stream_General, 0, "Official audio file webpage", Element_Value); break;
1316 case Elements::WOAR : Fill(Stream_General, 0, "Performer/Url", Element_Value); break;
1317 case Elements::WOAS : Fill(Stream_General, 0, "Official audio source webpage", Element_Value); break;
1318 case Elements::WORS : Fill(Stream_General, 0, General_Service_Url, Element_Value); break;
1319 case Elements::WPAY : Fill(Stream_General, 0, "Payment", Element_Value); break;
1320 case Elements::WPUB : Fill(Stream_General, 0, "Publisher/Url", Element_Value); break;
1321 case Elements::WXXX : Fill(Stream_General, 0, Element_Values(0).To_UTF8().c_str(), Element_Values(1)); break;
1322 case Elements::BUF : break;
1323 case Elements::CNT : break;
1324 case Elements::COM : Fill(Stream_General, 0, Element_Values(0).To_UTF8().c_str(), Element_Values(1)); break;
1325 case Elements::CRA : break;
1326 case Elements::CRM : break;
1327 case Elements::EQU : break;
1328 case Elements::ETC : break;
1329 case Elements::GEO : break;
1330 case Elements::IPL : Fill(Stream_General, 0, "Involved people list", Element_Value); break;
1331 case Elements::LNK : Fill(Stream_General, 0, "Linked information,", Element_Value); break;
1332 case Elements::MCI : Fill(Stream_General, 0, "MCDI", Element_Value); break;
1333 case Elements::MLL : break;
1334 case Elements::PIC_ : Fill(Stream_General, 0, "Cover", "Yes"); break;
1335 case Elements::POP : break;
1336 case Elements::REV : break;
1337 case Elements::RVA : break;
1338 case Elements::SLT : break;
1339 case Elements::STC : break;
1340 case Elements::TAL : Fill(Stream_General, 0, "Album", Element_Value); break;
1341 case Elements::TBP : Fill(Stream_General, 0, "BPM", Element_Value); break;
1342 case Elements::TCM : Fill(Stream_General, 0, "Composer", Element_Value); break;
1343 case Elements::TCO :
1344 {
1345 if (Element_Value.find(__T('('))==0)
1346 Element_Value=Element_Value.SubString(__T("("), __T(")")); //Replace (nn) by nn
1347 if (Element_Value==__T("0") || Element_Value==__T("255"))
1348 Element_Value.clear();
1349 if (!Element_Value.empty())
1350 Fill(Stream_General, 0, General_Genre, Element_Value);
1351 }
1352 break;
1353 case Elements::TCR : Fill(Stream_General, 0, "Copyright", Element_Value); break;
1354 case Elements::TDY : break;
1355 case Elements::TEN : Fill(Stream_General, 0, "Encoded_Library", Element_Value); break;
1356 case Elements::TFT : Fill(Stream_General, 0, "File type", Element_Value); break;
1357 case Elements::TKE : Fill(Stream_General, 0, "Initial key", Element_Value); break;
1358 case Elements::TLA : Fill(Stream_Audio, 0, Audio_Language, Element_Value); break;
1359 case Elements::TLE : break;
1360 case Elements::TMT : Fill(Stream_General, 0, "Media type", Element_Value); break;
1361 case Elements::TOA : Fill(Stream_General, 0, "Original/Performer", Element_Value); break;
1362 case Elements::TOF : Fill(Stream_General, 0, "Original/FileName", Element_Value); break;
1363 case Elements::TOL : Fill(Stream_General, 0, "Original/Lyricist", Element_Value); break;
1364 case Elements::TOR : Normalize_Date(Element_Value); Fill(Stream_General, 0, "Original/Released_Date", Element_Value); break;
1365 case Elements::TOT : Fill(Stream_General, 0, "Original/Album", Element_Value); break;
1366 case Elements::TP1 : Fill(Stream_General, 0, "Performer", Element_Value); break;
1367 case Elements::TP2 : Fill(Stream_General, 0, General_Album_Performer, Element_Value); break;
1368 case Elements::TP3 : Fill(Stream_General, 0, "Conductor", Element_Value); break;
1369 case Elements::TP4 : Fill(Stream_General, 0, "RemixedBy", Element_Value); break;
1370 case Elements::TPA :
1371 {
1372 ZtringList List; List.Separator_Set(0, __T("/")); List.Write(Element_Value);
1373 if (!List(0).empty())
1374 Fill(Stream_General, 0, General_Part_Position, List(0));
1375 if (!List(1).empty())
1376 Fill(Stream_General, 0, General_Part_Position_Total, List(1));
1377 }
1378 break;
1379 case Elements::TPB : Fill(Stream_General, 0, "Publisher", Element_Value); break;
1380 case Elements::TRC : Fill(Stream_General, 0, "ISRC", Element_Value); break;
1381 case Elements::TRD : Normalize_Date(Element_Value); Fill(Stream_General, 0, "Recorded_Date", Element_Value); break;
1382 case Elements::TRK :
1383 {
1384 ZtringList List; List.Separator_Set(0, __T("/")); List.Write(Element_Value);
1385 if (!List(0).empty())
1386 Fill(Stream_General, 0, General_Track_Position, List(0));
1387 if (!List(1).empty())
1388 Fill(Stream_General, 0, General_Track_Position_Total, List(1));
1389 }
1390 break;
1391 case Elements::TSI : break;
1392 case Elements::TSS : break;
1393 case Elements::TT1 : Fill(Stream_General, 0, "Grouping", Element_Value); break;
1394 case Elements::TT2 : Fill(Stream_General, 0, "Track", Element_Value); break;
1395 case Elements::TT3 : Fill(Stream_General, 0, "Track_More", Element_Value); break;
1396 case Elements::TXT : Fill(Stream_General, 0, "Lyricist", Element_Value); break;
1397 case Elements::TXX : Fill(Stream_General, 0, Element_Values(0).To_UTF8().c_str(), Element_Values(1)); break;
1398 case Elements::TYE : Year=Element_Value; break;
1399 case Elements::UFI : Fill(Stream_Audio, 0, "UID", Element_Value); break;
1400 case Elements::ULT : Fill(Stream_General, 0, Element_Values(0).To_UTF8().c_str(), Element_Values(1)); break;
1401 case Elements::WAF : break;
1402 case Elements::WAR : Fill(Stream_General, 0, General_Service_Url, Element_Value); break;
1403 case Elements::WAS : Fill(Stream_General, 0, "Official audio source webpage", Element_Value); break;
1404 case Elements::WCM : Fill(Stream_General, 0, "Commercial information", Element_Value); break;
1405 case Elements::WCP : Fill(Stream_General, 0, "Copyright/Legal information", Element_Value); break;
1406 case Elements::WPB : Fill(Stream_General, 0, "Publisher/Url", Element_Value); break;
1407 case Elements::WXX : Fill(Stream_General, 0, Element_Values(0).To_UTF8().c_str(), Element_Values(1)); break;
1408 default : ;
1409 }
1410 }
1411
1412 //---------------------------------------------------------------------------
Normalize_Date(Ztring & Date)1413 void File_Id3v2::Normalize_Date(Ztring& Date)
1414 {
1415 if (Date.size()<=11 || Date[4]!=__T('-') || Date[7]!=__T('-'))
1416 return; //Format unknown or without time
1417 Date[10]=__T(' '); //could be "T"
1418 Date=Ztring(__T("UTC "))+Date; //Id3v2 specify a UTC date
1419 }
1420
1421 //***************************************************************************
1422 // C++
1423 //***************************************************************************
1424
1425 } //NameSpace
1426
1427 #endif //MEDIAINFO_MPEGA_YES
1428
1429