//--------------------------------------------------------------------------- void File__Analyze::Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, const Ztring &Value, bool Replace) { //Integrity if (StreamKind>Stream_Max) return; //Handling values with \r\n inside if (Value.find(_T('\r'))!=string::npos || Value.find(_T('\n'))!=string::npos) { Ztring NewValue=Value; NewValue.FindAndReplace(_T("\r\n"), _T(" / "), 0, Ztring_Recursive); NewValue.FindAndReplace(_T("\r"), _T(" / "), 0, Ztring_Recursive); NewValue.FindAndReplace(_T("\n"), _T(" / "), 0, Ztring_Recursive); if (NewValue.size()>=3 && NewValue.rfind(_T(" / "))==NewValue.size()-3) NewValue.resize(NewValue.size()-3); Fill(StreamKind, StreamPos, Parameter, NewValue, Replace); return; } //Handle Value before StreamKind if (StreamKind==Stream_Max || StreamPos>=(*Stream)[StreamKind].size()) { ZtringList NewList; NewList.push_back(Ztring().From_Number(Parameter)); NewList.push_back(Value); Fill_Temp.push_back(NewList); return; //No streams } Ztring &Target=(*Stream)[StreamKind][StreamPos](Parameter); if (Target.empty() || Replace) Target=Value; //First value else if (Value.empty()) Target.clear(); //Empty value --> clear other values else { Target+=MediaInfoLib::Config.TagSeparator_Get(); Target+=Value; } }
//--------------------------------------------------------------------------- void File_Dsdiff::DSD__PROP_CHNL() { Element_Name("Channels"); //Parsing int16u numChannels; vector<int32u> chIDs; Get_B2 (numChannels, "numChannels"); while (Element_Offset<Element_Size) { int32u chID; Get_C4 (chID, "chID"); chIDs.push_back(chID); } FILLING_BEGIN(); Fill(Stream_Audio, 0, Audio_Channel_s_, numChannels); int32u ChannelPositions=0; int32u ChannelPositions2=0; ZtringList ChannelLayout; ChannelLayout.Separator_Set(0, __T(" ")); for (size_t i=0; i<chIDs.size(); i++) { DSDIFF_CHNL_chID_ChannelPositions(chIDs[i], ChannelPositions); DSDIFF_CHNL_chID_ChannelPositions2(chIDs[i], ChannelPositions2); ChannelLayout.push_back(DSDIFF_CHNL_chID(chIDs[i])); } Ztring ChannelPositions_New=DSDIFF_CHNL_chID_ChannelPositions(ChannelPositions); const Ztring& ChannelPositions_Old=Retrieve_Const(Stream_Audio, 0, Audio_ChannelPositions); if (ChannelPositions_New!=ChannelPositions_Old) Fill(Stream_Audio, 0, Audio_ChannelPositions, ChannelPositions_New); Ztring ChannelPositions2_New=DSDIFF_CHNL_chID_ChannelPositions2(ChannelPositions2); const Ztring& ChannelPositions2_Old=Retrieve_Const(Stream_Audio, 0, Audio_ChannelPositions_String2); if (ChannelPositions2_New!=ChannelPositions2_Old) Fill(Stream_Audio, 0, Audio_ChannelPositions_String2, ChannelPositions2_New); const Ztring& ChannelLayout_New=ChannelLayout.Read(); const Ztring& ChannelLayout_Old=Retrieve_Const(Stream_Audio, 0, Audio_ChannelLayout); if (ChannelLayout_New!=ChannelLayout_Old) Fill(Stream_Audio, 0, Audio_ChannelLayout, ChannelLayout_New); FILLING_END(); }
ZtringList Dir::GetAllFileNames(const Ztring &Dir_Name_, dirlist_t Options) { ZtringList ToReturn; Ztring Dir_Name=Dir_Name_; #ifdef ZENLIB_USEWX int Flags=wxDIR_FILES | wxDIR_DIRS; //Search for files wxArrayString Liste; wxFileName FullPath; FullPath=Dir_Name.c_str(); //-File if (FullPath.FileExists()) { FullPath.Normalize(); Liste.Add(FullPath.GetFullPath()); } //-Directory else if (FullPath.DirExists()) { FullPath.Normalize(); wxDir::GetAllFiles(FullPath.GetFullPath(), &Liste, Ztring(), Flags); } //-WildCards else { wxString FileName=FullPath.GetFullName(); FullPath.SetFullName(Ztring()); //Supress filename FullPath.Normalize(); if (FullPath.DirExists()) wxDir::GetAllFiles(FullPath.GetPath(), &Liste, FileName, Flags); } //Compatible array ToReturn.reserve(Liste.GetCount()); for (size_t Pos=0; Pos<Liste.GetCount(); Pos++) ToReturn.push_back(Liste[Pos].c_str()); #else //ZENLIB_USEWX #ifdef WINDOWS //Is a dir? if (Exists(Dir_Name)) Dir_Name+=_T("\\*"); //Path Ztring Path=FileName::Path_Get(Dir_Name); if (Path.empty()) { #ifdef UNICODE #ifndef ZENLIB_NO_WIN9X_SUPPORT if (IsWin9X_Fast()) { DWORD Path_Size=GetFullPathNameA(Dir_Name.To_Local().c_str(), 0, NULL, NULL); char* PathTemp=new char[Path_Size+1]; if (GetFullPathNameA(Dir_Name.To_Local().c_str(), Path_Size+1, PathTemp, NULL)) Path=FileName::Path_Get(PathTemp); delete [] PathTemp; //PathTemp=NULL; } else #endif //ZENLIB_NO_WIN9X_SUPPORT { DWORD Path_Size=GetFullPathName(Dir_Name.c_str(), 0, NULL, NULL); Char* PathTemp=new Char[Path_Size+1]; if (GetFullPathNameW(Dir_Name.c_str(), Path_Size+1, PathTemp, NULL)) Path=FileName::Path_Get(PathTemp); delete [] PathTemp; //PathTemp=NULL; } #else DWORD Path_Size=GetFullPathName(Dir_Name.c_str(), 0, NULL, NULL); Char* PathTemp=new Char[Path_Size+1]; if (GetFullPathName(Dir_Name.c_str(), Path_Size+1, PathTemp, NULL)) Path=FileName::Path_Get(PathTemp); delete [] PathTemp; //PathTemp=NULL; #endif //UNICODE } #ifdef UNICODE WIN32_FIND_DATAW FindFileDataW; HANDLE hFind; #ifndef ZENLIB_NO_WIN9X_SUPPORT WIN32_FIND_DATAA FindFileDataA; if (IsWin9X_Fast()) hFind=FindFirstFileA(Dir_Name.To_Local().c_str(), &FindFileDataA); else #endif //ZENLIB_NO_WIN9X_SUPPORT hFind=FindFirstFileW(Dir_Name.c_str(), &FindFileDataW); #else WIN32_FIND_DATA FindFileData; HANDLE hFind=FindFirstFile(Dir_Name.c_str(), &FindFileData); #endif //UNICODE if (hFind==INVALID_HANDLE_VALUE) return ZtringList(); BOOL ReturnValue; do { #ifdef UNICODE Ztring File_Name; #ifndef ZENLIB_NO_WIN9X_SUPPORT if (IsWin9X_Fast()) File_Name=FindFileDataA.cFileName; else #endif //ZENLIB_NO_WIN9X_SUPPORT File_Name=FindFileDataW.cFileName; #else Ztring File_Name(FindFileData.cFileName); #endif //UNICODE if (File_Name!=_T(".") && File_Name!=_T("..")) //Avoid . an .. { Ztring File_Name_Complete=Path+_T("\\")+File_Name; if (Exists(File_Name_Complete)) { if (Options&Parse_SubDirs) ToReturn+=GetAllFileNames(File_Name_Complete, Options); //A SubDir } else if ((Options&Include_Hidden) || (!File_Name.empty() && File_Name[0]!=_T('.'))) ToReturn.push_back(File_Name_Complete); //A file } #ifdef UNICODE #ifndef ZENLIB_NO_WIN9X_SUPPORT if (IsWin9X_Fast()) ReturnValue=FindNextFileA(hFind, &FindFileDataA); else #endif //ZENLIB_NO_WIN9X_SUPPORT ReturnValue=FindNextFileW(hFind, &FindFileDataW); #else ReturnValue=FindNextFile(hFind, &FindFileData); #endif //UNICODE } while (ReturnValue); FindClose(hFind); #else //WINDOWS //A file? if (File::Exists(Dir_Name)) { ToReturn.push_back(Dir_Name); //TODO return ToReturn; } //A dir? if (!Dir::Exists(Dir_Name)) return ToReturn; //Does not exist //open #ifdef UNICODE DIR* Dir=opendir(Dir_Name.To_Local().c_str()); #else DIR* Dir=opendir(Dir_Name.c_str()); #endif //UNICODE if (Dir) { //This is a dir //Normalizing dir (the / at the end) size_t Dir_Pos=Dir_Name.rfind(FileName_PathSeparator); if (Dir_Pos==std::string::npos) Dir_Name+=FileName_PathSeparator; else if (Dir_Pos+Ztring(FileName_PathSeparator).size()!=Dir_Name.size()) Dir_Name+=FileName_PathSeparator; struct dirent *DirEnt; while((DirEnt=readdir(Dir))!=NULL) { //A file Ztring File_Name(DirEnt->d_name); if (File_Name!=_T(".") && File_Name!=_T("..")) //Avoid . an .. { Ztring File_Name_Complete=Dir_Name+File_Name; if (Exists(File_Name_Complete)) { if (Options&Parse_SubDirs) ToReturn+=GetAllFileNames(File_Name_Complete, Options); //A SubDir } else if ((Options&Include_Hidden) || (!File_Name.empty() && File_Name[0]!=_T('.'))) ToReturn.push_back(File_Name_Complete); //A file } } //Close it closedir(Dir); } else { glob_t globbuf; if (glob(Dir_Name.To_Local().c_str(), GLOB_NOSORT, NULL, &globbuf)==0) { for (int Pos=0; Pos<globbuf.gl_pathc; Pos++) ToReturn.push_back(Ztring().From_Local(globbuf.gl_pathv[Pos])); } } #endif #endif //ZENLIB_USEWX return ToReturn; }
//--------------------------------------------------------------------------- size_t MediaInfoList_Internal::Open(const String &File_Name, const fileoptions_t Options) { //Option FileOption_Close if (Options & FileOption_CloseAll) Close(All); //Option Recursive //TODO //Get all filenames ZtringList List; if ((File_Name.size()>=7 && File_Name[0]==_T('h') && File_Name[1]==_T('t') && File_Name[2]==_T('t') && File_Name[3]==_T('p') && File_Name[4]==_T(':') && File_Name[5]==_T('/') && File_Name[6]==_T('/')) || (File_Name.size()>=6 && File_Name[0]==_T('f') && File_Name[1]==_T('t') && File_Name[2]==_T('p') && File_Name[3]==_T(':') && File_Name[4]==_T('/') && File_Name[5]==_T('/')) || (File_Name.size()>=6 && File_Name[0]==_T('m') && File_Name[1]==_T('m') && File_Name[2]==_T('s') && File_Name[3]==_T(':') && File_Name[4]==_T('/') && File_Name[5]==_T('/')) || (File_Name.size()>=7 && File_Name[0]==_T('m') && File_Name[1]==_T('m') && File_Name[2]==_T('s') && File_Name[3]==_T('h') && File_Name[4]==_T(':') && File_Name[5]==_T('/') && File_Name[6]==_T('/'))) List.push_back(File_Name); else if (File::Exists(File_Name)) List.push_back(File_Name); else List=Dir::GetAllFileNames(File_Name, (Options&FileOption_NoRecursive)?Dir::Nothing:Dir::Parse_SubDirs); Reader_Directory::Directory_Cleanup(List); //Registering files CS.Enter(); if (ToParse.empty()) CountValid=0; for (ZtringList::iterator L=List.begin(); L!=List.end(); L++) ToParse.push(*L); ToParse_Total+=List.size(); if (ToParse_Total) State=ToParse_AlreadyDone*10000/ToParse_Total; else State=10000; CS.Leave(); //Parsing if (BlockMethod==1) { CS.Enter(); if (!IsRunning()) //If already created, the routine will read the new files { RunAgain(); IsInThread=true; } CS.Leave(); return 0; } else { Entry(); //Normal parsing return Count_Get(); } }
//--------------------------------------------------------------------------- void File_Ptx::Read_Buffer_Continue() { if (File_Offset || Buffer_Offset) { if (Buffer_Size) Reject(); //Problem return; } //Parsing ZtringList Names; Ztring LibraryName, LibraryVersion, Format, Directory; int32u LibraryName_Length, LibraryVersion_Length, LibraryRelease_Length, Format_Length, Platform_Length, Info_Count, Names_Count, Info_Length, Name_Length, FileName_Count, Directory_Length; int32u Unknown_Length; int16u Audio_Count; Element_Begin1("Header"); Skip_B1( "Magic"); Skip_Local(16, "Magic"); Skip_L2( "0x0500"); Skip_L1( "Unknown"); Skip_L1( "0x5A"); Skip_L2( "0x0001"); Skip_L2( "0x0004"); Skip_L2( "0x0000"); Skip_L4( "Unknown"); Skip_L2( "0x035A"); Skip_L2( "0x6400"); Skip_L2( "0x0000"); Skip_L2( "0x0300"); Skip_L2( "0x0000"); Get_L4 (LibraryName_Length, "WritingLibrary name length"); Get_UTF8(LibraryName_Length, LibraryName, "Library name"); Skip_L4( "0x00000003"); Skip_L4( "Library version, major"); Skip_L4( "Library version, minor"); Skip_L4( "Library version, revision"); Get_L4 (LibraryVersion_Length, "Library version length"); Get_UTF8(LibraryVersion_Length, LibraryVersion, "Library version"); Skip_L1( "0x01"); Get_L4 (LibraryRelease_Length, "Library release length"); Skip_UTF8(LibraryRelease_Length, "Library release"); Skip_L1( "0x00"); Get_L4 (Format_Length, "Format length"); Get_UTF8(Format_Length, Format, "Format"); if (Format!=__T("Pro Tools Session File")) { Element_End(); Reject("Ptx"); return; } Skip_L2( "0x0006"); Get_L4 (Platform_Length, "Platform length"); Skip_UTF8(Platform_Length, "Platform"); Skip_L4( "0x00000000"); Skip_L4( "0x00085A05"); Skip_L4( "Unknown"); Skip_L4( "0x00002067"); Skip_L4( "0x002A0000"); Skip_L4( "Unknown"); Skip_L4( "Unknown"); Skip_L4( "Unknown"); Element_End(); Element_Begin1("Info list"); Get_L4 (Info_Count, "Info count"); if (4*Info_Count>Element_Size) { Element_End(); Reject(); return; } for (int32u Pos=0; Pos<Info_Count; Pos++) { Element_Begin1("Info"); Get_L4 (Info_Length, "Info length"); if (Info_Length) { Info_UTF8(Info_Length, Info, "Name"); Element_Info1(Info); } Element_End(); } Element_End(); Element_Begin1("Unknown"); Skip_L4( "0x00000000"); Element_Begin1("Names list 1"); Get_L4 (Names_Count, "Names count minus 1"); if (4*Names_Count>Element_Size) { Element_End(); Reject(); return; } for (int16u Pos=0; Pos<1+Names_Count; Pos++) { Element_Begin1("Name"); Get_L4 (Name_Length, "Name length"); if (Name_Length) { Info_UTF8(Name_Length, Name, "Name"); Element_Name(Name); } Element_End(); } Element_End(); Skip_L4( "0x00000000"); Skip_L4( "0x0000002A"); Skip_L4( "Unknown"); Skip_L4( "Unknown"); Element_Begin1("Names list 2"); Get_L4 (Names_Count, "Names count"); if (4*Names_Count>Element_Size) { Element_End(); Reject(); return; } for (int16u Pos=0; Pos<Names_Count; Pos++) { Element_Begin1("Name"); Get_L4 (Name_Length, "Name length"); if (Name_Length) { Info_UTF8(Name_Length, Name, "Name"); Element_Name(Name); } Element_End(); } Element_End(); Skip_L4( "0x00000000"); Skip_L4( "0x0000002A"); Skip_L4( "Unknown"); Skip_L4( "Unknown"); Skip_L4( "0x00000000"); Skip_L4( "Unknown"); Skip_L4( "0x00000101"); Skip_L4( "0x00055A00"); Skip_L4( "Unknown"); Skip_L4( "0x00012519"); Skip_L4( "0x00000000"); Skip_L4( "0x00000000"); Skip_L4( "0x00000001"); Skip_L2( "0x0003"); Element_End(); Get_L2 (Audio_Count, "Audio count"); if (111*Audio_Count>Element_Size) { Reject(); return; } Element_Begin1("Audio tracks list 1"); for (int16u Pos=0; Pos<Audio_Count; Pos++) { Element_Begin1("Name"); Skip_L4( "0x00000000"); Get_L4 (Unknown_Length, "Name length"); Info_UTF8(Unknown_Length, Name, "Name"); Skip_L2( "0x0000"); Skip_L4( "0x00000000"); Skip_L4( "0x0000002A"); Skip_L4( "Unknown (same 1/2/3)"); Skip_L4( "Unknown (same 1/2/3)"); Info_L1(Number, "Ordered number"); Element_Info1(Number); Element_Info1(Name); Element_End(); Names.push_back(Name); } Element_End(); Skip_L2( "0x0000"); Element_Begin1("Audio tracks list 2"); for (int16u Pos=0; Pos<Audio_Count; Pos++) { Element_Begin1("Name"); int32u Size; Skip_L3( "0x00025A"); Get_L4 (Size, "Size"); Skip_L4( "0x0000251A"); Get_L4 (Unknown_Length, "Name length"); Info_UTF8(Unknown_Length, Name, "Name"); Skip_L2( "0x0000"); Skip_L4( "0x00000000"); Skip_L4( "0x0000002A"); Skip_L4( "Unknown (same 1/2/3)"); Skip_L4( "Unknown (same 1/2/3)"); Info_L1(Number, "Ordered number"); Element_Info1(Number); Skip_L4( "0x00000000"); Element_Info1(Name); if (Unknown_Length+31!=Size) { Reject(); return; } Element_End(); } Element_End(); Get_L2 (Audio_Count, "Audio count"); if (4*Audio_Count>Element_Size) { Reject(); return; } Skip_L2( "0x00"); Element_Begin1("Audio tracks list 3"); for (int16u Pos=0; Pos<Audio_Count; Pos++) { Element_Begin1("Name"); int32u Size; Skip_L3( "0x00025A"); Get_L4 (Size, "Size"); Skip_L4( "0x0000251A"); Get_L4 (Unknown_Length, "Name length"); Info_UTF8(Unknown_Length, Name, "Name"); Skip_L2( "0x0000"); Skip_L4( "0x00000000"); Skip_L4( "0x0000002A"); Skip_L4( "Unknown (same 1/2/3)"); Skip_L4( "Unknown (same 1/2/3)"); Info_L1(Number, "Ordered number"); Element_Info1(Number); Skip_L4( "0x00000000"); Element_Info1(Name); if (Unknown_Length+31!=Size) { Reject(); return; } Element_End(); } Element_End(); Skip_L2( "0x0000"); Skip_L2( "0x0018"); Skip_L4( "0x00000001"); Skip_L2( "0x0018"); Skip_L4( "0x00000001"); Skip_L2( "0x0001"); Skip_L3( "0x00095A"); Get_L4 (Unknown_Length, "Opaque length"); Skip_XX(Unknown_Length, "Opaque"); Skip_L3( "0x00045A"); Skip_L4( "0x00000016"); Skip_L4( "0x06002026"); Skip_L4( "0x00000000"); Skip_L2( "0x0000"); Skip_L4( "Unknown"); Skip_L4( "Unknown"); Skip_L4( "0x00000000"); Skip_L3( "0x00025A"); Skip_L4( "0x00000015"); Skip_L4( "0x075A2032"); Skip_L4( "0x00000C00"); Skip_L4( "0x01204200"); Skip_L4( "0x01000000"); Skip_L4( "Unknown"); Skip_L4( "0x00025A00"); Skip_L4( "Unknown"); Skip_L4( "Unknown"); Skip_L4( "0x015A0000"); Skip_L4( "Unknown"); Skip_L4( "Unknown"); Skip_L4( "0x01000000"); Get_L4 (FileName_Count, "File name count"); if (13*FileName_Count>Element_Size) { Reject(); return; } Get_L4 (Directory_Length, "Directory length"); Get_UTF8(Directory_Length, Directory, "Directory"); Skip_L4( "0x00000000"); Element_Begin1("File names"); size_t Pos_Offset=0; for (int32u Pos=0; Pos<FileName_Count; Pos++) { Ztring Name; int32u Name_Length, Purpose; Element_Begin1("File names"); Skip_L1( "0x0002"); Skip_L4( "Ordered number except WAV files and -1"); Get_L4 (Name_Length, "Name length"); Get_UTF8(Name_Length, Name, "Name"); Element_Name(Name); Get_C4 (Purpose, "Purpose (e.g. EVAW for .wav files)"); Element_End(); switch (Purpose) { case 0x45564157: if (Pos-Pos_Offset<Names.size() && (Name.find(Names[Pos-Pos_Offset])==0 || Name.find(Names[Pos-Pos_Offset]+__T(".wav"))+5==Name.size())) { File__ReferenceFilesHelper::reference ReferenceFile; ReferenceFile.StreamKind=Stream_Audio; ReferenceFile.FileNames.push_back(Directory+PathSeparator+Name); ReferenceFiles->References.push_back(ReferenceFile); } else if (ReferenceFiles->References.empty()) Pos_Offset++; default: ; } } Element_End(); Skip_XX(Element_Size-Element_Offset, "Unknown"); FILLING_BEGIN(); Accept("Ptx"); //Could be Ptf (former formatn but not supported, so we don't care currently Fill("Ptx"); Fill(Stream_General, 0, General_Format, "Pro Tools Session"); Fill(Stream_General, 0, General_Format_Version, "Version 10"); Fill(Stream_General, 0, General_Encoded_Library_Name, LibraryName); Fill(Stream_General, 0, General_Encoded_Library_Version, LibraryVersion); FILLING_END(); }
//--------------------------------------------------------------------------- void File_Ptx::Read_Buffer_Continue() { if (File_Offset || Buffer_Offset) { if (Buffer_Size) Reject(); //Problem return; } //Parsing ZtringList Names; Ztring LibraryName, LibraryVersion, Format, Directory; int32u LibraryName_Length, LibraryVersion_Length, LibraryRelease_Length, Format_Length, Platform_Length, Info_Count, Names_Count, Info_Length, Name_Length, FileName_Count, Directory_Length; int32u Opaque2_Length, Audio_Count; int16u Opaque1_Length; Element_Begin1("Header"); Skip_B1( "Magic"); Skip_Local(16, "Magic"); Skip_L2( "0x0500"); Skip_L1( "Unknown [1]"); Skip_L1( "0x5A [1]"); Skip_L2( "0x0001"); Skip_L2( "0x0004"); Skip_L2( "0x0000 [1]"); Skip_L4( "Unknown [2]"); Skip_L2( "0x035A"); Skip_L2( "0x6400"); Skip_L2( "0x0000 [1]"); Skip_L2( "0x0300"); Skip_L2( "0x0000 [1]"); Get_L4 (LibraryName_Length, "WritingLibrary name length"); Get_UTF8(LibraryName_Length, LibraryName, "Library name"); Skip_L4( "0x00000003"); Skip_L4( "Library version, major"); Skip_L4( "Library version, minor"); Skip_L4( "Library version, revision"); Get_L4 (LibraryVersion_Length, "Library version length"); Get_UTF8(LibraryVersion_Length, LibraryVersion, "Library version"); Skip_L1( "0x01"); Get_L4 (LibraryRelease_Length, "Library release length"); Skip_UTF8(LibraryRelease_Length, "Library release"); Skip_L1( "0x00 [1]"); Get_L4 (Format_Length, "Format length"); Get_UTF8(Format_Length, Format, "Format"); if (Format!=__T("Pro Tools Session File")) { Element_End(); Reject(); return; } Skip_L2( "0x0006"); Get_L4 (Platform_Length, "Platform length"); Skip_UTF8(Platform_Length, "Platform"); Skip_L4( "0x00000000"); Skip_L2( "0x5A05"); Get_L2 (Opaque1_Length, "Info list, Opaque length"); //0x0006 (10.2-) or 0x0008 (10.3+) Skip_L4( "Unknown [3]"); Skip_L4( "0x00002067"); Skip_L2( "0x0000 [1]"); Skip_L2( "0x0000 (once) or 0x002A"); Skip_L2( "0x0000 [1]"); Skip_L2( "Unknown [4]"); Skip_L4( "Unknown [5]"); Skip_L4( "Unknown [6]"); Element_End(); Element_Begin1("Info list"); Get_L4 (Info_Count, "Info count"); if (4*Info_Count>Element_Size) { Element_End(); Reject(); return; } for (int32u Pos=0; Pos<Info_Count; Pos++) { Element_Begin1("Info"); Get_L4 (Info_Length, "Info length"); if (Info_Length) { Info_UTF8(Info_Length, Info, "Name"); Element_Info1(Info); } Element_End(); } Element_End(); Element_Begin1("Unknown"); Skip_L4( "0x00000000"); Element_Begin1("Names list 1"); Get_L4 (Names_Count, "Names count minus 1"); if (4*Names_Count>Element_Size) { Element_End(); Reject(); return; } for (int16u Pos=0; Pos<1+Names_Count; Pos++) { Element_Begin1("Name"); Get_L4 (Name_Length, "Name length"); if (Name_Length) { Info_UTF8(Name_Length, Name, "Name"); Element_Name(Name); } Element_End(); } Element_End(); Skip_L4( "0x00000000"); Skip_L4( "0x00000000 or 0x0000002A"); Skip_L4( "Unknown [7]"); Skip_L4( "Unknown [8]"); Element_Begin1("Names list 2"); Get_L4 (Names_Count, "Names count"); if (4*Names_Count>Element_Size) { Element_End(); Reject(); return; } for (int16u Pos=0; Pos<Names_Count; Pos++) { Element_Begin1("Name"); Get_L4 (Name_Length, "Name length"); if (Name_Length) { Info_UTF8(Name_Length, Name, "Name"); Element_Name(Name); } Element_End(); } Element_End(); Skip_L4( "0x00000000"); Skip_L4( "0x0000002A [1]"); Skip_L4( "Unknown [9]"); Skip_L4( "Unknown [10]"); Skip_L4( "0x00000000"); Skip_L1( "0x00 or 0x01 [2]"); Skip_L1( "0x01"); Skip_L1( "0x00 or 0x01 or 0x02"); Skip_L1( "0x00 [2]"); Skip_L1( "0x01"); Skip_L1( "0x00 (once) or 0x01"); Skip_L1( "0x00 or 0x01 (once)"); Skip_L1( "0x00 or 0x01 (once) or 0x5A"); if (Opaque1_Length<6) { if (Opaque1_Length) Skip_XX(Opaque1_Length, "Opaque1"); } else { Skip_L4( "Opaque1 - Unknown [1]"); Skip_L2( "Opaque1 - Unknown [2]"); if (Opaque1_Length<8) { if (Opaque1_Length-6) Skip_XX(Opaque1_Length-6, "Opaque1 - Unknown [3]"); } else { Skip_L2( "Opaque1 - 0x0000"); if (Opaque1_Length>8) Skip_XX(Opaque1_Length-8, "Opaque1 - Unknown [3]"); } } Skip_L2( "0x2519"); Skip_L2( "0x0001"); Skip_L4( "0x00000000 or B5112287"); Skip_L4( "0x00000000 or 4037F9DC"); Skip_L4( "0x00000001 [1]"); Skip_L2( "0x0003"); Element_End(); Get_L4 (Audio_Count, "Audio count"); if (111*Audio_Count>Element_Size) { Reject(); return; } Element_Begin1("Audio tracks list 1"); for (int16u Pos=0; Pos<Audio_Count; Pos++) { Element_Begin1("Name"); Skip_L2( "0x0000 [New]"); Get_L4 (Name_Length, "(Same 1/2/3) Name length"); Info_UTF8(Name_Length, Name, "(Same 1/2/3) Name"); Skip_L2( "(Same 1/2/3) 0x0000 "); Skip_L4( "(Same 1/2/3) 0x00000000"); Skip_L4( "(Same 1/2/3) 0x0000002A"); Skip_L4( "(Same 1/2/3) Unknown"); Skip_L4( "(Same 1/2/3) Unknown"); Info_L3(Number, "(Same 1/2/3) Ordered number"); Element_Info1(Number); Element_Info1(Name); Element_End(); if (Name==__T("Lf")) //Exception? Typo? Name=__T("Lfe"); Name.MakeLowerCase(); Names.push_back(Name); } Element_End(); Element_Begin1("Audio tracks list 2"); for (int16u Pos=0; Pos<Audio_Count; Pos++) { Element_Begin1("Name"); int32u Size; Skip_L3( "(Same 2/3) 0x00025A [1]"); Get_L4 (Size, "(Same 2/3) Size"); Skip_L4( "(Same 2/3) 0x0000251A"); Get_L4 (Name_Length, "(Same 1/2/3) Name length"); Info_UTF8(Name_Length, Name, "(Same 1/2/3) Name"); Skip_L2( "(Same 1/2/3) 0x0000 "); Skip_L4( "(Same 1/2/3) 0x00000000"); Skip_L4( "(Same 1/2/3) 0x0000002A"); Skip_L4( "(Same 1/2/3) Unknown"); Skip_L4( "(Same 1/2/3) Unknown"); Info_L3(Number, "(Same 1/2/3) Ordered number"); Element_Info1(Number); Skip_L2( "(Same 2/3) 0x0000"); Element_Info1(Name); if (Name_Length+31!=Size) { Element_End(); Element_End(); Reject(); return; } Element_End(); } Element_End(); Get_L4 (Audio_Count, "Audio count"); if (4*Audio_Count>Element_Size) { Reject(); return; } Element_Begin1("Audio tracks list 3"); for (int16u Pos=0; Pos<Audio_Count; Pos++) { Element_Begin1("Name"); int32u Size; Skip_L3( "(Same 2/3) 0x00025A [2]"); Get_L4 (Size, "(Same 2/3) Size"); if (Size>0x10000) { Element_End(); Element_End(); Reject(); return; } Skip_L4( "(Same 2/3) 0x0000251A"); Get_L4 (Name_Length, "(Same 1/2/3) Name length"); Info_UTF8(Name_Length, Name, "(Same 1/2/3) Name"); Skip_L2( "(Same 1/2/3) 0x0000 "); Skip_L4( "(Same 1/2/3) 0x00000000"); Skip_L4( "(Same 1/2/3) 0x0000002A"); Skip_L4( "(Same 1/2/3) Unknown"); Skip_L4( "(Same 1/2/3) Unknown"); Info_L3(Number, "(Same 1/2/3) Ordered number"); Element_Info1(Number); Skip_L2( "(Same 2/3) 0x0000"); Element_Info1(Name); if (Name_Length+31!=Size) { Element_End(); Element_End(); Reject(); return; } Element_End(); } Element_End(); Skip_L2( "0x0000 [4]"); Skip_L2( "0x0018"); Skip_L4( "0x00000001 [2]"); Skip_L2( "0x0018"); Skip_L4( "0x00000001 [2]"); Skip_L2( "0x0001 [3]"); Skip_L3( "0x00095A"); Get_L4 (Opaque2_Length, "Opaque2 length"); Skip_XX(Opaque2_Length, "Opaque2"); Skip_L1( "0x5A [2]"); Skip_L2( "0x0003 (10.0) or 0x0004 (10.2+)"); Get_L4 (Opaque2_Length, "Opaque3 length"); //0x0012 (10.0) or 0x0016 (10.2+) if (Opaque2_Length<0x12) Skip_XX(Opaque2_Length, "Opaque3"); else { Skip_L4( "Opaque3 - 0x06002026"); Skip_L4( "Opaque3 - 0x00000000 [1]"); Skip_L2( "Opaque3 - 0x0000"); Skip_L4( "Opaque3 - Unknown [1]"); Skip_L4( "Opaque3 - Unknown [2]"); if (Opaque2_Length<0x16) { if (Opaque2_Length-0x12) Skip_XX(Opaque2_Length-0x12, "Opaque3 - Unknown [3]"); } else { Skip_L4( "Opaque3 - 0x00000000 [2]"); if (Opaque2_Length>0x16) Skip_XX(Opaque2_Length-0x16, "Opaque3 - Unknown [4]"); } } Skip_L3( "0x00025A [3]"); Get_L4 (Opaque2_Length, "0x00000015 (Opaque4 length?) or something else"); if (Opaque2_Length==0x00000015) { Skip_L4( "0x075A2032"); Skip_L4( "0x00000C00"); Skip_L4( "0x01204200"); Skip_L4( "0x00000000 or 0x01000000"); Skip_L4( "Unknown [13]"); Skip_L1( "0x00 [3]"); Skip_L3( "0x00025A [4]"); Skip_L4( "Unknown [14]"); } Skip_L4( "Unknown [15]"); Skip_L4( "0x015A0000"); Skip_L4( "Unknown [16]"); Skip_L4( "Unknown [17]"); Skip_L4( "0x01000000"); Get_L4 (FileName_Count, "File name count"); if (13*FileName_Count>Element_Size) { Reject(); return; } Get_L4 (Directory_Length, "Directory length"); Get_UTF8(Directory_Length, Directory, "Directory"); Skip_L4( "0x00000000 [11]"); Element_Begin1("File names"); vector<int8u> Roles; vector<Ztring> FileNames; vector<Ztring> FileNamesLowerCase; vector<int32u> Purposes; for (int32u Pos=0; Pos<FileName_Count; Pos++) { Ztring FileName; int32u FileName_Length, Purpose; int8u Role; // Element_Begin1("File names"); Get_L1 (Role, "role? (0x02 for WAV files)"); Skip_L4( "Ordered number except WAV files and -1"); Get_L4 (FileName_Length, "File Name length"); Get_UTF8(FileName_Length, FileName, "File Name"); Element_Name(FileName); Get_C4 (Purpose, "Purpose (e.g. EVAW for .wav files)"); //Found 1 .wav file without "EWAV". Element_End(); Roles.push_back(Role); FileNames.push_back(FileName); FileName.MakeLowerCase(); FileNamesLowerCase.push_back(FileName); Purposes.push_back(Purpose); } Element_End(); Skip_XX(Element_Size-Element_Offset, "Unknown"); FILLING_BEGIN(); Accept("Ptx"); //Could be Ptf (former format but not supported, so we don't care currently) Fill("Ptx"); Fill(Stream_General, 0, General_Format, "Pro Tools Session"); Fill(Stream_General, 0, General_Format_Version, "Version 10"); Fill(Stream_General, 0, General_Encoded_Library_Name, LibraryName); Fill(Stream_General, 0, General_Encoded_Library_Version, LibraryVersion); // Role==2 + Purpose==EWAV + listed if (Names.size()>1 || FileNames.size()==1) { size_t Pos_Offset=0; for (int32u Pos=0; Pos<FileName_Count; Pos++) { if (Roles[Pos]==0x02 && Purposes[Pos]==0x45564157 //"EWAV" && Pos-Pos_Offset<Names.size() && FileNames[Pos]!=__T("1 kHz @ -20dB.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("1k@0vu -20.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos].find(__T(".1Khz.wav"))==string::npos //Exception? && FileNames[Pos].find(__T("_1KTONE_"))==string::npos //Exception? && FileNamesLowerCase[Pos].find(Names[Pos-Pos_Offset]+__T(".wav"))!=string::npos && FileNamesLowerCase[Pos].find(Names[Pos-Pos_Offset]+__T(".wav"))+Names[Pos-Pos_Offset].size()+4==FileNames[Pos].size()) { sequence* Sequence=new sequence; Sequence->StreamKind=Stream_Audio; Sequence->AddFileName(Directory+PathSeparator+FileNames[Pos]); ReferenceFiles->AddSequence(Sequence); } else if (!ReferenceFiles->Sequences_Size()) Pos_Offset++; } if (Names.size()!=ReferenceFiles->Sequences_Size()) ReferenceFiles->Clear(); //Failed to detect correctly } // Role==2 + listed if (!ReferenceFiles->Sequences_Size() && (Names.size()>1 || FileNames.size()==1)) { size_t Pos_Offset=0; for (int32u Pos=0; Pos<FileName_Count; Pos++) { if (Roles[Pos]==0x02 && Pos-Pos_Offset<Names.size() && FileNames[Pos]!=__T("1 kHz @ -20dB.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("1k@0vu -20.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos].find(__T(".1Khz.wav"))==string::npos //Exception? && FileNames[Pos].find(__T("_1KTONE_"))==string::npos) //Exception? { Ztring FileName=FileNames[Pos]; Ztring Name=Names[Pos-Pos_Offset]; FileName.MakeLowerCase(); Name.MakeLowerCase(); if (FileName.find(Name)==0 || FileName.find(Name+__T(".wav"))+5==Name.size()) { sequence* Sequence=new sequence; Sequence->StreamKind=Stream_Audio; Sequence->AddFileName(Directory+PathSeparator+FileNames[Pos]); ReferenceFiles->AddSequence(Sequence); } else if (!ReferenceFiles->Sequences_Size()) Pos_Offset++; } else if (!ReferenceFiles->Sequences_Size()) Pos_Offset++; } if (Names.size()!=ReferenceFiles->Sequences_Size()) ReferenceFiles->Clear(); //Failed to detect correctly } // Role==2 + Purpose==EWAV + listed, special case with specific file names if (!ReferenceFiles->Sequences_Size() && (Names.size()>1 || FileNames.size()==1)) { for (int32u Pos=0; Pos<FileName_Count; Pos++) { if (Roles[Pos]==0x02 && Purposes[Pos]==0x45564157 //"EWAV" && FileNames[Pos]!=__T("1 kHz @ -20dB.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("1k@0vu -20.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos].find(__T(".1Khz.wav"))==string::npos //Exception? && FileNames[Pos].find(__T("_1KTONE_"))==string::npos) //Exception? { for (int32u Pos2=0; Pos2<Names.size(); Pos2++) if (FileNamesLowerCase[Pos].find(Names[Pos2])==0) { sequence* Sequence=new sequence; Sequence->StreamKind=Stream_Audio; Sequence->AddFileName(Directory+PathSeparator+FileNames[Pos]); ReferenceFiles->AddSequence(Sequence); break; } } } } // Role==2 + Purpose==EWAV if (!ReferenceFiles->Sequences_Size()) { for (int32u Pos=0; Pos<FileName_Count; Pos++) { if (Roles[Pos]==0x02 && Purposes[Pos]==0x45564157 //"EWAV" && FileNames[Pos]!=__T("1 kHz @ -20dB.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("1k@0vu -20.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos].find(__T(".1Khz.wav"))==string::npos //Exception? && FileNames[Pos].find(__T("_1KTONE_"))==string::npos) //Exception? { sequence* Sequence=new sequence; Sequence->StreamKind=Stream_Audio; Sequence->AddFileName(Directory+PathSeparator+FileNames[Pos]); ReferenceFiles->AddSequence(Sequence); } } } // Role==2 if (!ReferenceFiles->Sequences_Size()) { for (int32u Pos=0; Pos<FileName_Count; Pos++) { if (Roles[Pos]==0x02 && FileNames[Pos]!=__T("1 kHz @ -20dB.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos]!=__T("1k@0vu -20.wav") //Exception? && FileNames[Pos]!=__T("*****@*****.**") //Exception? && FileNames[Pos].find(__T(".1Khz.wav"))==string::npos //Exception? && FileNames[Pos].find(__T("_1KTONE_"))==string::npos) //Exception? { sequence* Sequence=new sequence; Sequence->StreamKind=Stream_Audio; Sequence->AddFileName(Directory+PathSeparator+FileNames[Pos]); ReferenceFiles->AddSequence(Sequence); } } } FILLING_END(); }
//--------------------------------------------------------------------------- void File__Analyze::Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, const Ztring &Value, bool Replace) { //Integrity if (StreamKind>Stream_Max || Parameter==NULL || Parameter[0]=='\0') return; //Handling values with \r\n inside if (Value.find(_T('\r'))!=string::npos || Value.find(_T('\n'))!=string::npos) { Ztring NewValue=Value; NewValue.FindAndReplace(_T("\r\n"), _T(" / "), 0, Ztring_Recursive); NewValue.FindAndReplace(_T("\r"), _T(" / "), 0, Ztring_Recursive); NewValue.FindAndReplace(_T("\n"), _T(" / "), 0, Ztring_Recursive); if (NewValue.size()>=3 && NewValue.rfind(_T(" / "))==NewValue.size()-3) NewValue.resize(NewValue.size()-3); Fill(StreamKind, StreamPos, Parameter, NewValue, Replace); return; } //Handle Value before StreamKind if (StreamKind==Stream_Max || StreamPos>=(*Stream)[StreamKind].size()) { ZtringList NewList; NewList.push_back(Ztring().From_UTF8(Parameter)); NewList.push_back(Value); Fill_Temp.push_back(NewList); return; //No streams } //Handling of well known parameters size_t Pos=MediaInfoLib::Config.Info_Get(StreamKind).Find(Ztring().From_Local(Parameter)); if (Pos!=Error) { Fill(StreamKind, StreamPos, Pos, Value, Replace); return; } //Handling of unknown parameters if (Value.empty()) { if (!Replace) { size_t Pos=(*Stream_More)[StreamKind][StreamPos].Find(Ztring().From_UTF8(Parameter), Info_Name); if (Pos!=(size_t)-1) (*Stream_More)[StreamKind][StreamPos][Pos].clear(); //Empty value --> clear other values } } else { Ztring &Target=(*Stream_More)[StreamKind][StreamPos](Ztring().From_UTF8(Parameter), Info_Text); if (Target.empty() || Replace) { Target=Value; //First value (*Stream_More)[StreamKind][StreamPos](Ztring().From_UTF8(Parameter), Info_Options)=_T("Y NT"); } else { Target+=MediaInfoLib::Config.TagSeparator_Get(); Target+=Value; } } }