Added APE and ASF tag support
parent
9827964b63
commit
132fe98e84
|
@ -199,6 +199,18 @@
|
||||||
176608460F50A49000FD5752 /* mp4udtabox.h in Headers */ = {isa = PBXBuildFile; fileRef = 176607FE0F50A49000FD5752 /* mp4udtabox.h */; };
|
176608460F50A49000FD5752 /* mp4udtabox.h in Headers */ = {isa = PBXBuildFile; fileRef = 176607FE0F50A49000FD5752 /* mp4udtabox.h */; };
|
||||||
17F767190F4FE2B2008498A7 /* tlist.tcc in Headers */ = {isa = PBXBuildFile; fileRef = 174C79A60F4FD40B00E18B0F /* tlist.tcc */; settings = {ATTRIBUTES = (Public, ); }; };
|
17F767190F4FE2B2008498A7 /* tlist.tcc in Headers */ = {isa = PBXBuildFile; fileRef = 174C79A60F4FD40B00E18B0F /* tlist.tcc */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
17F7671A0F4FE2B2008498A7 /* tmap.tcc in Headers */ = {isa = PBXBuildFile; fileRef = 174C79A80F4FD40B00E18B0F /* tmap.tcc */; settings = {ATTRIBUTES = (Public, ); }; };
|
17F7671A0F4FE2B2008498A7 /* tmap.tcc in Headers */ = {isa = PBXBuildFile; fileRef = 174C79A80F4FD40B00E18B0F /* tmap.tcc */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
83BE026717FD6CF300973169 /* apefile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BE026317FD6CF300973169 /* apefile.cpp */; };
|
||||||
|
83BE026817FD6CF300973169 /* apefile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BE026417FD6CF300973169 /* apefile.h */; };
|
||||||
|
83BE026917FD6CF300973169 /* apeproperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BE026517FD6CF300973169 /* apeproperties.cpp */; };
|
||||||
|
83BE026A17FD6CF300973169 /* apeproperties.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BE026617FD6CF300973169 /* apeproperties.h */; };
|
||||||
|
83BE027417FD716F00973169 /* asfattribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BE026C17FD716F00973169 /* asfattribute.cpp */; };
|
||||||
|
83BE027517FD716F00973169 /* asfattribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BE026D17FD716F00973169 /* asfattribute.h */; };
|
||||||
|
83BE027617FD716F00973169 /* asffile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BE026E17FD716F00973169 /* asffile.cpp */; };
|
||||||
|
83BE027717FD716F00973169 /* asffile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BE026F17FD716F00973169 /* asffile.h */; };
|
||||||
|
83BE027817FD716F00973169 /* asfproperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BE027017FD716F00973169 /* asfproperties.cpp */; };
|
||||||
|
83BE027917FD716F00973169 /* asfproperties.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BE027117FD716F00973169 /* asfproperties.h */; };
|
||||||
|
83BE027A17FD716F00973169 /* asftag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BE027217FD716F00973169 /* asftag.cpp */; };
|
||||||
|
83BE027B17FD716F00973169 /* asftag.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BE027317FD716F00973169 /* asftag.h */; };
|
||||||
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
|
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
@ -396,6 +408,18 @@
|
||||||
176607FC0F50A49000FD5752 /* mp4trakbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mp4trakbox.h; sourceTree = "<group>"; };
|
176607FC0F50A49000FD5752 /* mp4trakbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mp4trakbox.h; sourceTree = "<group>"; };
|
||||||
176607FD0F50A49000FD5752 /* mp4udtabox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mp4udtabox.cpp; sourceTree = "<group>"; };
|
176607FD0F50A49000FD5752 /* mp4udtabox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mp4udtabox.cpp; sourceTree = "<group>"; };
|
||||||
176607FE0F50A49000FD5752 /* mp4udtabox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mp4udtabox.h; sourceTree = "<group>"; };
|
176607FE0F50A49000FD5752 /* mp4udtabox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mp4udtabox.h; sourceTree = "<group>"; };
|
||||||
|
83BE026317FD6CF300973169 /* apefile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apefile.cpp; sourceTree = "<group>"; };
|
||||||
|
83BE026417FD6CF300973169 /* apefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apefile.h; sourceTree = "<group>"; };
|
||||||
|
83BE026517FD6CF300973169 /* apeproperties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apeproperties.cpp; sourceTree = "<group>"; };
|
||||||
|
83BE026617FD6CF300973169 /* apeproperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apeproperties.h; sourceTree = "<group>"; };
|
||||||
|
83BE026C17FD716F00973169 /* asfattribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = asfattribute.cpp; sourceTree = "<group>"; };
|
||||||
|
83BE026D17FD716F00973169 /* asfattribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asfattribute.h; sourceTree = "<group>"; };
|
||||||
|
83BE026E17FD716F00973169 /* asffile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = asffile.cpp; sourceTree = "<group>"; };
|
||||||
|
83BE026F17FD716F00973169 /* asffile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asffile.h; sourceTree = "<group>"; };
|
||||||
|
83BE027017FD716F00973169 /* asfproperties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = asfproperties.cpp; sourceTree = "<group>"; };
|
||||||
|
83BE027117FD716F00973169 /* asfproperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asfproperties.h; sourceTree = "<group>"; };
|
||||||
|
83BE027217FD716F00973169 /* asftag.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = asftag.cpp; sourceTree = "<group>"; };
|
||||||
|
83BE027317FD716F00973169 /* asftag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asftag.h; sourceTree = "<group>"; };
|
||||||
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||||
8DC2EF5B0486A6940098B216 /* TagLib.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TagLib.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
8DC2EF5B0486A6940098B216 /* TagLib.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TagLib.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
@ -467,6 +491,7 @@
|
||||||
174C79340F4FD40B00E18B0F /* taglib */ = {
|
174C79340F4FD40B00E18B0F /* taglib */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
83BE026B17FD716F00973169 /* asf */,
|
||||||
174C79350F4FD40B00E18B0F /* ape */,
|
174C79350F4FD40B00E18B0F /* ape */,
|
||||||
174C793D0F4FD40B00E18B0F /* audioproperties.cpp */,
|
174C793D0F4FD40B00E18B0F /* audioproperties.cpp */,
|
||||||
174C793E0F4FD40B00E18B0F /* audioproperties.h */,
|
174C793E0F4FD40B00E18B0F /* audioproperties.h */,
|
||||||
|
@ -494,6 +519,10 @@
|
||||||
174C79350F4FD40B00E18B0F /* ape */ = {
|
174C79350F4FD40B00E18B0F /* ape */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
83BE026317FD6CF300973169 /* apefile.cpp */,
|
||||||
|
83BE026417FD6CF300973169 /* apefile.h */,
|
||||||
|
83BE026517FD6CF300973169 /* apeproperties.cpp */,
|
||||||
|
83BE026617FD6CF300973169 /* apeproperties.h */,
|
||||||
174C79360F4FD40B00E18B0F /* ape-tag-format.txt */,
|
174C79360F4FD40B00E18B0F /* ape-tag-format.txt */,
|
||||||
174C79370F4FD40B00E18B0F /* apefooter.cpp */,
|
174C79370F4FD40B00E18B0F /* apefooter.cpp */,
|
||||||
174C79380F4FD40B00E18B0F /* apefooter.h */,
|
174C79380F4FD40B00E18B0F /* apefooter.h */,
|
||||||
|
@ -782,6 +811,21 @@
|
||||||
path = m4a;
|
path = m4a;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
83BE026B17FD716F00973169 /* asf */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
83BE026C17FD716F00973169 /* asfattribute.cpp */,
|
||||||
|
83BE026D17FD716F00973169 /* asfattribute.h */,
|
||||||
|
83BE026E17FD716F00973169 /* asffile.cpp */,
|
||||||
|
83BE026F17FD716F00973169 /* asffile.h */,
|
||||||
|
83BE027017FD716F00973169 /* asfproperties.cpp */,
|
||||||
|
83BE027117FD716F00973169 /* asfproperties.h */,
|
||||||
|
83BE027217FD716F00973169 /* asftag.cpp */,
|
||||||
|
83BE027317FD716F00973169 /* asftag.h */,
|
||||||
|
);
|
||||||
|
path = asf;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
8E75700C09F318D70080F1EE /* Source */ = {
|
8E75700C09F318D70080F1EE /* Source */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -804,6 +848,7 @@
|
||||||
174C79C00F4FD40B00E18B0F /* apetag.h in Headers */,
|
174C79C00F4FD40B00E18B0F /* apetag.h in Headers */,
|
||||||
174C79C20F4FD40B00E18B0F /* audioproperties.h in Headers */,
|
174C79C20F4FD40B00E18B0F /* audioproperties.h in Headers */,
|
||||||
174C79C40F4FD40B00E18B0F /* fileref.h in Headers */,
|
174C79C40F4FD40B00E18B0F /* fileref.h in Headers */,
|
||||||
|
83BE027B17FD716F00973169 /* asftag.h in Headers */,
|
||||||
174C79C60F4FD40B00E18B0F /* flacfile.h in Headers */,
|
174C79C60F4FD40B00E18B0F /* flacfile.h in Headers */,
|
||||||
174C79C80F4FD40B00E18B0F /* flacproperties.h in Headers */,
|
174C79C80F4FD40B00E18B0F /* flacproperties.h in Headers */,
|
||||||
174C79CA0F4FD40B00E18B0F /* mpcfile.h in Headers */,
|
174C79CA0F4FD40B00E18B0F /* mpcfile.h in Headers */,
|
||||||
|
@ -818,6 +863,7 @@
|
||||||
174C79DC0F4FD40B00E18B0F /* uniquefileidentifierframe.h in Headers */,
|
174C79DC0F4FD40B00E18B0F /* uniquefileidentifierframe.h in Headers */,
|
||||||
174C79DE0F4FD40B00E18B0F /* unknownframe.h in Headers */,
|
174C79DE0F4FD40B00E18B0F /* unknownframe.h in Headers */,
|
||||||
174C79E00F4FD40B00E18B0F /* unsynchronizedlyricsframe.h in Headers */,
|
174C79E00F4FD40B00E18B0F /* unsynchronizedlyricsframe.h in Headers */,
|
||||||
|
83BE027917FD716F00973169 /* asfproperties.h in Headers */,
|
||||||
174C79E20F4FD40B00E18B0F /* urllinkframe.h in Headers */,
|
174C79E20F4FD40B00E18B0F /* urllinkframe.h in Headers */,
|
||||||
174C79E80F4FD40B00E18B0F /* id3v2extendedheader.h in Headers */,
|
174C79E80F4FD40B00E18B0F /* id3v2extendedheader.h in Headers */,
|
||||||
174C79EA0F4FD40B00E18B0F /* id3v2footer.h in Headers */,
|
174C79EA0F4FD40B00E18B0F /* id3v2footer.h in Headers */,
|
||||||
|
@ -832,12 +878,14 @@
|
||||||
174C79FC0F4FD40B00E18B0F /* xingheader.h in Headers */,
|
174C79FC0F4FD40B00E18B0F /* xingheader.h in Headers */,
|
||||||
174C79FE0F4FD40B00E18B0F /* oggflacfile.h in Headers */,
|
174C79FE0F4FD40B00E18B0F /* oggflacfile.h in Headers */,
|
||||||
174C7A000F4FD40B00E18B0F /* oggfile.h in Headers */,
|
174C7A000F4FD40B00E18B0F /* oggfile.h in Headers */,
|
||||||
|
83BE026A17FD6CF300973169 /* apeproperties.h in Headers */,
|
||||||
174C7A020F4FD40B00E18B0F /* oggpage.h in Headers */,
|
174C7A020F4FD40B00E18B0F /* oggpage.h in Headers */,
|
||||||
174C7A040F4FD40B00E18B0F /* oggpageheader.h in Headers */,
|
174C7A040F4FD40B00E18B0F /* oggpageheader.h in Headers */,
|
||||||
174C7A060F4FD40B00E18B0F /* speexfile.h in Headers */,
|
174C7A060F4FD40B00E18B0F /* speexfile.h in Headers */,
|
||||||
174C7A080F4FD40B00E18B0F /* speexproperties.h in Headers */,
|
174C7A080F4FD40B00E18B0F /* speexproperties.h in Headers */,
|
||||||
174C7A0A0F4FD40B00E18B0F /* vorbisfile.h in Headers */,
|
174C7A0A0F4FD40B00E18B0F /* vorbisfile.h in Headers */,
|
||||||
174C7A0C0F4FD40B00E18B0F /* vorbisproperties.h in Headers */,
|
174C7A0C0F4FD40B00E18B0F /* vorbisproperties.h in Headers */,
|
||||||
|
83BE027717FD716F00973169 /* asffile.h in Headers */,
|
||||||
174C7A0E0F4FD40B00E18B0F /* xiphcomment.h in Headers */,
|
174C7A0E0F4FD40B00E18B0F /* xiphcomment.h in Headers */,
|
||||||
174C7A100F4FD40B00E18B0F /* tag.h in Headers */,
|
174C7A100F4FD40B00E18B0F /* tag.h in Headers */,
|
||||||
174C7A120F4FD40B00E18B0F /* taglib_export.h in Headers */,
|
174C7A120F4FD40B00E18B0F /* taglib_export.h in Headers */,
|
||||||
|
@ -847,6 +895,7 @@
|
||||||
174C7A190F4FD40B00E18B0F /* tbytevectorlist.h in Headers */,
|
174C7A190F4FD40B00E18B0F /* tbytevectorlist.h in Headers */,
|
||||||
174C7A1B0F4FD40B00E18B0F /* tdebug.h in Headers */,
|
174C7A1B0F4FD40B00E18B0F /* tdebug.h in Headers */,
|
||||||
174C7A1D0F4FD40B00E18B0F /* tfile.h in Headers */,
|
174C7A1D0F4FD40B00E18B0F /* tfile.h in Headers */,
|
||||||
|
83BE026817FD6CF300973169 /* apefile.h in Headers */,
|
||||||
174C7A1E0F4FD40B00E18B0F /* tlist.h in Headers */,
|
174C7A1E0F4FD40B00E18B0F /* tlist.h in Headers */,
|
||||||
174C7A200F4FD40B00E18B0F /* tmap.h in Headers */,
|
174C7A200F4FD40B00E18B0F /* tmap.h in Headers */,
|
||||||
174C7A230F4FD40B00E18B0F /* tstring.h in Headers */,
|
174C7A230F4FD40B00E18B0F /* tstring.h in Headers */,
|
||||||
|
@ -870,6 +919,7 @@
|
||||||
176608120F50A49000FD5752 /* itunesgrpbox.h in Headers */,
|
176608120F50A49000FD5752 /* itunesgrpbox.h in Headers */,
|
||||||
176608140F50A49000FD5752 /* itunesnambox.h in Headers */,
|
176608140F50A49000FD5752 /* itunesnambox.h in Headers */,
|
||||||
176608160F50A49000FD5752 /* itunestmpobox.h in Headers */,
|
176608160F50A49000FD5752 /* itunestmpobox.h in Headers */,
|
||||||
|
83BE027517FD716F00973169 /* asfattribute.h in Headers */,
|
||||||
176608180F50A49000FD5752 /* itunestrknbox.h in Headers */,
|
176608180F50A49000FD5752 /* itunestrknbox.h in Headers */,
|
||||||
1766081A0F50A49000FD5752 /* ituneswrtbox.h in Headers */,
|
1766081A0F50A49000FD5752 /* ituneswrtbox.h in Headers */,
|
||||||
1766081C0F50A49000FD5752 /* mp4audioproperties.h in Headers */,
|
1766081C0F50A49000FD5752 /* mp4audioproperties.h in Headers */,
|
||||||
|
@ -976,6 +1026,7 @@
|
||||||
174C79C90F4FD40B00E18B0F /* mpcfile.cpp in Sources */,
|
174C79C90F4FD40B00E18B0F /* mpcfile.cpp in Sources */,
|
||||||
174C79CB0F4FD40B00E18B0F /* mpcproperties.cpp in Sources */,
|
174C79CB0F4FD40B00E18B0F /* mpcproperties.cpp in Sources */,
|
||||||
174C79CD0F4FD40B00E18B0F /* id3v1genres.cpp in Sources */,
|
174C79CD0F4FD40B00E18B0F /* id3v1genres.cpp in Sources */,
|
||||||
|
83BE026717FD6CF300973169 /* apefile.cpp in Sources */,
|
||||||
174C79CF0F4FD40B00E18B0F /* id3v1tag.cpp in Sources */,
|
174C79CF0F4FD40B00E18B0F /* id3v1tag.cpp in Sources */,
|
||||||
174C79D10F4FD40B00E18B0F /* attachedpictureframe.cpp in Sources */,
|
174C79D10F4FD40B00E18B0F /* attachedpictureframe.cpp in Sources */,
|
||||||
174C79D30F4FD40B00E18B0F /* commentsframe.cpp in Sources */,
|
174C79D30F4FD40B00E18B0F /* commentsframe.cpp in Sources */,
|
||||||
|
@ -983,6 +1034,7 @@
|
||||||
174C79D70F4FD40B00E18B0F /* relativevolumeframe.cpp in Sources */,
|
174C79D70F4FD40B00E18B0F /* relativevolumeframe.cpp in Sources */,
|
||||||
174C79D90F4FD40B00E18B0F /* textidentificationframe.cpp in Sources */,
|
174C79D90F4FD40B00E18B0F /* textidentificationframe.cpp in Sources */,
|
||||||
174C79DB0F4FD40B00E18B0F /* uniquefileidentifierframe.cpp in Sources */,
|
174C79DB0F4FD40B00E18B0F /* uniquefileidentifierframe.cpp in Sources */,
|
||||||
|
83BE027617FD716F00973169 /* asffile.cpp in Sources */,
|
||||||
174C79DD0F4FD40B00E18B0F /* unknownframe.cpp in Sources */,
|
174C79DD0F4FD40B00E18B0F /* unknownframe.cpp in Sources */,
|
||||||
174C79DF0F4FD40B00E18B0F /* unsynchronizedlyricsframe.cpp in Sources */,
|
174C79DF0F4FD40B00E18B0F /* unsynchronizedlyricsframe.cpp in Sources */,
|
||||||
174C79E10F4FD40B00E18B0F /* urllinkframe.cpp in Sources */,
|
174C79E10F4FD40B00E18B0F /* urllinkframe.cpp in Sources */,
|
||||||
|
@ -999,6 +1051,7 @@
|
||||||
174C79FB0F4FD40B00E18B0F /* xingheader.cpp in Sources */,
|
174C79FB0F4FD40B00E18B0F /* xingheader.cpp in Sources */,
|
||||||
174C79FD0F4FD40B00E18B0F /* oggflacfile.cpp in Sources */,
|
174C79FD0F4FD40B00E18B0F /* oggflacfile.cpp in Sources */,
|
||||||
174C79FF0F4FD40B00E18B0F /* oggfile.cpp in Sources */,
|
174C79FF0F4FD40B00E18B0F /* oggfile.cpp in Sources */,
|
||||||
|
83BE026917FD6CF300973169 /* apeproperties.cpp in Sources */,
|
||||||
174C7A010F4FD40B00E18B0F /* oggpage.cpp in Sources */,
|
174C7A010F4FD40B00E18B0F /* oggpage.cpp in Sources */,
|
||||||
174C7A030F4FD40B00E18B0F /* oggpageheader.cpp in Sources */,
|
174C7A030F4FD40B00E18B0F /* oggpageheader.cpp in Sources */,
|
||||||
174C7A050F4FD40B00E18B0F /* speexfile.cpp in Sources */,
|
174C7A050F4FD40B00E18B0F /* speexfile.cpp in Sources */,
|
||||||
|
@ -1028,6 +1081,7 @@
|
||||||
1766080B0F50A49000FD5752 /* itunesdaybox.cpp in Sources */,
|
1766080B0F50A49000FD5752 /* itunesdaybox.cpp in Sources */,
|
||||||
1766080D0F50A49000FD5752 /* itunesdiskbox.cpp in Sources */,
|
1766080D0F50A49000FD5752 /* itunesdiskbox.cpp in Sources */,
|
||||||
1766080F0F50A49000FD5752 /* itunesgenbox.cpp in Sources */,
|
1766080F0F50A49000FD5752 /* itunesgenbox.cpp in Sources */,
|
||||||
|
83BE027817FD716F00973169 /* asfproperties.cpp in Sources */,
|
||||||
176608110F50A49000FD5752 /* itunesgrpbox.cpp in Sources */,
|
176608110F50A49000FD5752 /* itunesgrpbox.cpp in Sources */,
|
||||||
176608130F50A49000FD5752 /* itunesnambox.cpp in Sources */,
|
176608130F50A49000FD5752 /* itunesnambox.cpp in Sources */,
|
||||||
176608150F50A49000FD5752 /* itunestmpobox.cpp in Sources */,
|
176608150F50A49000FD5752 /* itunestmpobox.cpp in Sources */,
|
||||||
|
@ -1042,11 +1096,13 @@
|
||||||
176608270F50A49000FD5752 /* mp4isobox.cpp in Sources */,
|
176608270F50A49000FD5752 /* mp4isobox.cpp in Sources */,
|
||||||
176608290F50A49000FD5752 /* mp4isofullbox.cpp in Sources */,
|
176608290F50A49000FD5752 /* mp4isofullbox.cpp in Sources */,
|
||||||
1766082B0F50A49000FD5752 /* mp4itunestag.cpp in Sources */,
|
1766082B0F50A49000FD5752 /* mp4itunestag.cpp in Sources */,
|
||||||
|
83BE027A17FD716F00973169 /* asftag.cpp in Sources */,
|
||||||
1766082D0F50A49000FD5752 /* mp4mdiabox.cpp in Sources */,
|
1766082D0F50A49000FD5752 /* mp4mdiabox.cpp in Sources */,
|
||||||
1766082F0F50A49000FD5752 /* mp4metabox.cpp in Sources */,
|
1766082F0F50A49000FD5752 /* mp4metabox.cpp in Sources */,
|
||||||
176608310F50A49000FD5752 /* mp4minfbox.cpp in Sources */,
|
176608310F50A49000FD5752 /* mp4minfbox.cpp in Sources */,
|
||||||
176608330F50A49000FD5752 /* mp4moovbox.cpp in Sources */,
|
176608330F50A49000FD5752 /* mp4moovbox.cpp in Sources */,
|
||||||
176608350F50A49000FD5752 /* mp4mvhdbox.cpp in Sources */,
|
176608350F50A49000FD5752 /* mp4mvhdbox.cpp in Sources */,
|
||||||
|
83BE027417FD716F00973169 /* asfattribute.cpp in Sources */,
|
||||||
176608370F50A49000FD5752 /* mp4propsproxy.cpp in Sources */,
|
176608370F50A49000FD5752 /* mp4propsproxy.cpp in Sources */,
|
||||||
176608390F50A49000FD5752 /* mp4sampleentry.cpp in Sources */,
|
176608390F50A49000FD5752 /* mp4sampleentry.cpp in Sources */,
|
||||||
1766083B0F50A49000FD5752 /* mp4skipbox.cpp in Sources */,
|
1766083B0F50A49000FD5752 /* mp4skipbox.cpp in Sources */,
|
||||||
|
|
|
@ -0,0 +1,270 @@
|
||||||
|
/***************************************************************************
|
||||||
|
copyright : (C) 2010 by Alex Novichkov
|
||||||
|
email : novichko@atnet.ru
|
||||||
|
|
||||||
|
copyright : (C) 2006 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
(original WavPack implementation)
|
||||||
|
|
||||||
|
copyright : (C) 2004 by Allan Sandfeld Jensen
|
||||||
|
email : kde@carewolf.org
|
||||||
|
(original MPC implementation)
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <tbytevector.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tagunion.h>
|
||||||
|
|
||||||
|
#include "apefile.h"
|
||||||
|
#include "id3v1tag.h"
|
||||||
|
|
||||||
|
#include "apetag.h"
|
||||||
|
#include "apefooter.h"
|
||||||
|
|
||||||
|
using namespace TagLib;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
enum { APEIndex, ID3v1Index };
|
||||||
|
}
|
||||||
|
|
||||||
|
class APE::File::FilePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FilePrivate() :
|
||||||
|
APELocation(-1),
|
||||||
|
APESize(0),
|
||||||
|
ID3v1Location(-1),
|
||||||
|
properties(0),
|
||||||
|
hasAPE(false),
|
||||||
|
hasID3v1(false) {}
|
||||||
|
|
||||||
|
~FilePrivate()
|
||||||
|
{
|
||||||
|
delete properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
long APELocation;
|
||||||
|
uint APESize;
|
||||||
|
|
||||||
|
long ID3v1Location;
|
||||||
|
|
||||||
|
TagUnion tag;
|
||||||
|
|
||||||
|
Properties *properties;
|
||||||
|
|
||||||
|
// These indicate whether the file *on disk* has these tags, not if
|
||||||
|
// this data structure does. This is used in computing offsets.
|
||||||
|
|
||||||
|
bool hasAPE;
|
||||||
|
bool hasID3v1;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// public members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
APE::File::File(FileName file, bool readProperties,
|
||||||
|
Properties::ReadStyle propertiesStyle) : TagLib::File(file)
|
||||||
|
{
|
||||||
|
d = new FilePrivate;
|
||||||
|
read(readProperties, propertiesStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
APE::File::~File()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
TagLib::Tag *APE::File::tag() const
|
||||||
|
{
|
||||||
|
return &d->tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
APE::Properties *APE::File::audioProperties() const
|
||||||
|
{
|
||||||
|
return d->properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool APE::File::save()
|
||||||
|
{
|
||||||
|
if(readOnly()) {
|
||||||
|
debug("APE::File::save() -- File is read only.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update ID3v1 tag
|
||||||
|
|
||||||
|
if(ID3v1Tag()) {
|
||||||
|
if(d->hasID3v1) {
|
||||||
|
seek(d->ID3v1Location);
|
||||||
|
writeBlock(ID3v1Tag()->render());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
seek(0, End);
|
||||||
|
d->ID3v1Location = tell();
|
||||||
|
writeBlock(ID3v1Tag()->render());
|
||||||
|
d->hasID3v1 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(d->hasID3v1) {
|
||||||
|
removeBlock(d->ID3v1Location, 128);
|
||||||
|
d->hasID3v1 = false;
|
||||||
|
if(d->hasAPE) {
|
||||||
|
if(d->APELocation > d->ID3v1Location)
|
||||||
|
d->APELocation -= 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update APE tag
|
||||||
|
|
||||||
|
if(APETag()) {
|
||||||
|
if(d->hasAPE)
|
||||||
|
insert(APETag()->render(), d->APELocation, d->APESize);
|
||||||
|
else {
|
||||||
|
if(d->hasID3v1) {
|
||||||
|
insert(APETag()->render(), d->ID3v1Location, 0);
|
||||||
|
d->APESize = APETag()->footer()->completeTagSize();
|
||||||
|
d->hasAPE = true;
|
||||||
|
d->APELocation = d->ID3v1Location;
|
||||||
|
d->ID3v1Location += d->APESize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
seek(0, End);
|
||||||
|
d->APELocation = tell();
|
||||||
|
writeBlock(APETag()->render());
|
||||||
|
d->APESize = APETag()->footer()->completeTagSize();
|
||||||
|
d->hasAPE = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(d->hasAPE) {
|
||||||
|
removeBlock(d->APELocation, d->APESize);
|
||||||
|
d->hasAPE = false;
|
||||||
|
if(d->hasID3v1) {
|
||||||
|
if(d->ID3v1Location > d->APELocation) {
|
||||||
|
d->ID3v1Location -= d->APESize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3v1::Tag *APE::File::ID3v1Tag(bool create)
|
||||||
|
{
|
||||||
|
return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
|
||||||
|
}
|
||||||
|
|
||||||
|
APE::Tag *APE::File::APETag(bool create)
|
||||||
|
{
|
||||||
|
return d->tag.access<APE::Tag>(APEIndex, create);
|
||||||
|
}
|
||||||
|
|
||||||
|
void APE::File::strip(int tags)
|
||||||
|
{
|
||||||
|
if(tags & ID3v1) {
|
||||||
|
d->tag.set(ID3v1Index, 0);
|
||||||
|
APETag(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tags & APE) {
|
||||||
|
d->tag.set(APEIndex, 0);
|
||||||
|
|
||||||
|
if(!ID3v1Tag())
|
||||||
|
APETag(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// private members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void APE::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */)
|
||||||
|
{
|
||||||
|
// Look for an ID3v1 tag
|
||||||
|
|
||||||
|
d->ID3v1Location = findID3v1();
|
||||||
|
|
||||||
|
if(d->ID3v1Location >= 0) {
|
||||||
|
d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||||
|
d->hasID3v1 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for an APE tag
|
||||||
|
|
||||||
|
d->APELocation = findAPE();
|
||||||
|
|
||||||
|
if(d->APELocation >= 0) {
|
||||||
|
d->tag.set(APEIndex, new APE::Tag(this, d->APELocation));
|
||||||
|
d->APESize = APETag()->footer()->completeTagSize();
|
||||||
|
d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize;
|
||||||
|
d->hasAPE = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!d->hasID3v1)
|
||||||
|
APETag(true);
|
||||||
|
|
||||||
|
// Look for APE audio properties
|
||||||
|
|
||||||
|
if(readProperties) {
|
||||||
|
d->properties = new Properties(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long APE::File::findAPE()
|
||||||
|
{
|
||||||
|
if(!isValid())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(d->hasID3v1)
|
||||||
|
seek(-160, End);
|
||||||
|
else
|
||||||
|
seek(-32, End);
|
||||||
|
|
||||||
|
long p = tell();
|
||||||
|
|
||||||
|
if(readBlock(8) == APE::Tag::fileIdentifier())
|
||||||
|
return p;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long APE::File::findID3v1()
|
||||||
|
{
|
||||||
|
if(!isValid())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
seek(-128, End);
|
||||||
|
long p = tell();
|
||||||
|
|
||||||
|
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
|
||||||
|
return p;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
/***************************************************************************
|
||||||
|
copyright : (C) 2010 by Alex Novichkov
|
||||||
|
email : novichko@atnet.ru
|
||||||
|
|
||||||
|
copyright : (C) 2006 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
(original WavPack implementation)
|
||||||
|
|
||||||
|
copyright : (C) 2004 by Allan Sandfeld Jensen
|
||||||
|
email : kde@carewolf.org
|
||||||
|
(original MPC implementation)
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TAGLIB_APEFILE_H
|
||||||
|
#define TAGLIB_APEFILE_H
|
||||||
|
|
||||||
|
#include "tfile.h"
|
||||||
|
#include "taglib_export.h"
|
||||||
|
#include "apeproperties.h"
|
||||||
|
|
||||||
|
namespace TagLib {
|
||||||
|
|
||||||
|
class Tag;
|
||||||
|
|
||||||
|
namespace ID3v1 { class Tag; }
|
||||||
|
namespace APE { class Tag; }
|
||||||
|
|
||||||
|
//! An implementation of APE metadata
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This is implementation of APE metadata.
|
||||||
|
*
|
||||||
|
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
|
||||||
|
* properties from the file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace APE {
|
||||||
|
|
||||||
|
//! An implementation of TagLib::File with APE specific methods
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This implements and provides an interface APE WavPack files to the
|
||||||
|
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||||
|
* the abstract TagLib::File API as well as providing some additional
|
||||||
|
* information specific to APE files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TAGLIB_EXPORT File : public TagLib::File
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* This set of flags is used for various operations and is suitable for
|
||||||
|
* being OR-ed together.
|
||||||
|
*/
|
||||||
|
enum TagTypes {
|
||||||
|
//! Empty set. Matches no tag types.
|
||||||
|
NoTags = 0x0000,
|
||||||
|
//! Matches ID3v1 tags.
|
||||||
|
ID3v1 = 0x0001,
|
||||||
|
//! Matches APE tags.
|
||||||
|
APE = 0x0002,
|
||||||
|
//! Matches all tag types.
|
||||||
|
AllTags = 0xffff
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Contructs an WavPack file from \a file. If \a readProperties is true the
|
||||||
|
* file's audio properties will also be read using \a propertiesStyle. If
|
||||||
|
* false, \a propertiesStyle is ignored.
|
||||||
|
*/
|
||||||
|
File(FileName file, bool readProperties = true,
|
||||||
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Destroys this instance of the File.
|
||||||
|
*/
|
||||||
|
virtual ~File();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
|
||||||
|
* or a combination of the two.
|
||||||
|
*/
|
||||||
|
virtual TagLib::Tag *tag() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the APE::Properties for this file. If no audio properties
|
||||||
|
* were read then this will return a null pointer.
|
||||||
|
*/
|
||||||
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Saves the file.
|
||||||
|
*
|
||||||
|
* \note According to the official Monkey's Audio SDK, an APE file
|
||||||
|
* can only have either ID3V1 or APE tags, so a parameter is used here.
|
||||||
|
*/
|
||||||
|
virtual bool save();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns a pointer to the ID3v1 tag of the file.
|
||||||
|
*
|
||||||
|
* If \a create is false (the default) this will return a null pointer
|
||||||
|
* if there is no valid ID3v1 tag. If \a create is true it will create
|
||||||
|
* an ID3v1 tag if one does not exist. If there is already an APE tag, the
|
||||||
|
* new ID3v1 tag will be placed after it.
|
||||||
|
*
|
||||||
|
* \note The Tag <b>is still</b> owned by the APE::File and should not be
|
||||||
|
* deleted by the user. It will be deleted when the file (object) is
|
||||||
|
* destroyed.
|
||||||
|
*/
|
||||||
|
ID3v1::Tag *ID3v1Tag(bool create = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns a pointer to the APE tag of the file.
|
||||||
|
*
|
||||||
|
* If \a create is false (the default) this will return a null pointer
|
||||||
|
* if there is no valid APE tag. If \a create is true it will create
|
||||||
|
* a APE tag if one does not exist.
|
||||||
|
*
|
||||||
|
* \note The Tag <b>is still</b> owned by the APE::File and should not be
|
||||||
|
* deleted by the user. It will be deleted when the file (object) is
|
||||||
|
* destroyed.
|
||||||
|
*/
|
||||||
|
APE::Tag *APETag(bool create = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This will remove the tags that match the OR-ed together TagTypes from the
|
||||||
|
* file. By default it removes all tags.
|
||||||
|
*
|
||||||
|
* \note This will also invalidate pointers to the tags
|
||||||
|
* as their memory will be freed.
|
||||||
|
* \note In order to make the removal permanent save() still needs to be called
|
||||||
|
*/
|
||||||
|
void strip(int tags = AllTags);
|
||||||
|
|
||||||
|
private:
|
||||||
|
File(const File &);
|
||||||
|
File &operator=(const File &);
|
||||||
|
|
||||||
|
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
||||||
|
void scan();
|
||||||
|
long findID3v1();
|
||||||
|
long findAPE();
|
||||||
|
|
||||||
|
class FilePrivate;
|
||||||
|
FilePrivate *d;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,224 @@
|
||||||
|
/***************************************************************************
|
||||||
|
copyright : (C) 2010 by Alex Novichkov
|
||||||
|
email : novichko@atnet.ru
|
||||||
|
|
||||||
|
copyright : (C) 2006 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
(original WavPack implementation)
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <tstring.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <bitset>
|
||||||
|
#include "id3v2tag.h"
|
||||||
|
#include "apeproperties.h"
|
||||||
|
#include "apefile.h"
|
||||||
|
|
||||||
|
using namespace TagLib;
|
||||||
|
|
||||||
|
class APE::Properties::PropertiesPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PropertiesPrivate(File *file, long streamLength) :
|
||||||
|
length(0),
|
||||||
|
bitrate(0),
|
||||||
|
sampleRate(0),
|
||||||
|
channels(0),
|
||||||
|
version(0),
|
||||||
|
bitsPerSample(0),
|
||||||
|
file(file),
|
||||||
|
streamLength(streamLength) {}
|
||||||
|
|
||||||
|
long streamLength;
|
||||||
|
int length;
|
||||||
|
int bitrate;
|
||||||
|
int sampleRate;
|
||||||
|
int channels;
|
||||||
|
int version;
|
||||||
|
int bitsPerSample;
|
||||||
|
File *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// public members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
APE::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style)
|
||||||
|
{
|
||||||
|
d = new PropertiesPrivate(file, file->length());
|
||||||
|
read();
|
||||||
|
}
|
||||||
|
|
||||||
|
APE::Properties::~Properties()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
int APE::Properties::length() const
|
||||||
|
{
|
||||||
|
return d->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int APE::Properties::bitrate() const
|
||||||
|
{
|
||||||
|
return d->bitrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
int APE::Properties::sampleRate() const
|
||||||
|
{
|
||||||
|
return d->sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
int APE::Properties::channels() const
|
||||||
|
{
|
||||||
|
return d->channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
int APE::Properties::version() const
|
||||||
|
{
|
||||||
|
return d->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
int APE::Properties::bitsPerSample() const
|
||||||
|
{
|
||||||
|
return d->bitsPerSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// private members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
void APE::Properties::read()
|
||||||
|
{
|
||||||
|
// First we are searching the descriptor
|
||||||
|
long offset = findDescriptor();
|
||||||
|
if(offset < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Then we read the header common for all versions of APE
|
||||||
|
d->file->seek(offset);
|
||||||
|
ByteVector commonHeader=d->file->readBlock(6);
|
||||||
|
if(!commonHeader.startsWith("MAC "))
|
||||||
|
return;
|
||||||
|
d->version = commonHeader.mid(4).toUInt(false);
|
||||||
|
|
||||||
|
if(d->version >= 3980) {
|
||||||
|
analyzeCurrent();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
analyzeOld();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long APE::Properties::findDescriptor()
|
||||||
|
{
|
||||||
|
long ID3v2Location = findID3v2();
|
||||||
|
long ID3v2OriginalSize = 0;
|
||||||
|
bool hasID3v2 = false;
|
||||||
|
if(ID3v2Location >= 0) {
|
||||||
|
ID3v2::Tag tag(d->file, ID3v2Location, 0);
|
||||||
|
ID3v2OriginalSize = tag.header()->completeTagSize();
|
||||||
|
if(tag.header()->tagSize() > 0)
|
||||||
|
hasID3v2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
long offset = 0;
|
||||||
|
if(hasID3v2)
|
||||||
|
offset = d->file->find("MAC ", ID3v2Location + ID3v2OriginalSize);
|
||||||
|
else
|
||||||
|
offset = d->file->find("MAC ");
|
||||||
|
|
||||||
|
if(offset < 0) {
|
||||||
|
debug("APE::Properties::findDescriptor() -- APE descriptor not found");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
long APE::Properties::findID3v2()
|
||||||
|
{
|
||||||
|
if(!d->file->isValid())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
d->file->seek(0);
|
||||||
|
|
||||||
|
if(d->file->readBlock(3) == ID3v2::Header::fileIdentifier())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void APE::Properties::analyzeCurrent()
|
||||||
|
{
|
||||||
|
// Read the descriptor
|
||||||
|
d->file->seek(2, File::Current);
|
||||||
|
ByteVector descriptor = d->file->readBlock(44);
|
||||||
|
uint descriptorBytes = descriptor.mid(0,4).toUInt(false);
|
||||||
|
|
||||||
|
if ((descriptorBytes - 52) > 0)
|
||||||
|
d->file->seek(descriptorBytes - 52, File::Current);
|
||||||
|
|
||||||
|
// Read the header
|
||||||
|
ByteVector header = d->file->readBlock(24);
|
||||||
|
|
||||||
|
// Get the APE info
|
||||||
|
d->channels = header.mid(18, 2).toShort(false);
|
||||||
|
d->sampleRate = header.mid(20, 4).toUInt(false);
|
||||||
|
d->bitsPerSample = header.mid(16, 2).toShort(false);
|
||||||
|
//d->compressionLevel =
|
||||||
|
|
||||||
|
uint totalFrames = header.mid(12, 4).toUInt(false);
|
||||||
|
uint blocksPerFrame = header.mid(4, 4).toUInt(false);
|
||||||
|
uint finalFrameBlocks = header.mid(8, 4).toUInt(false);
|
||||||
|
uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
|
||||||
|
d->length = totalBlocks / d->sampleRate;
|
||||||
|
d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void APE::Properties::analyzeOld()
|
||||||
|
{
|
||||||
|
ByteVector header = d->file->readBlock(26);
|
||||||
|
uint totalFrames = header.mid(18, 4).toUInt(false);
|
||||||
|
|
||||||
|
// Fail on 0 length APE files (catches non-finalized APE files)
|
||||||
|
if(totalFrames == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
short compressionLevel = header.mid(0, 2).toShort(false);
|
||||||
|
uint blocksPerFrame;
|
||||||
|
if(d->version >= 3950)
|
||||||
|
blocksPerFrame = 73728 * 4;
|
||||||
|
else if(d->version >= 3900 || (d->version >= 3800 && compressionLevel == 4000))
|
||||||
|
blocksPerFrame = 73728;
|
||||||
|
else
|
||||||
|
blocksPerFrame = 9216;
|
||||||
|
d->channels = header.mid(4, 2).toShort(false);
|
||||||
|
d->sampleRate = header.mid(6, 4).toUInt(false);
|
||||||
|
uint finalFrameBlocks = header.mid(22, 4).toUInt(false);
|
||||||
|
uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
|
||||||
|
d->length = totalBlocks / d->sampleRate;
|
||||||
|
d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/***************************************************************************
|
||||||
|
copyright : (C) 2010 by Alex Novichkov
|
||||||
|
email : novichko@atnet.ru
|
||||||
|
|
||||||
|
copyright : (C) 2006 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
(original WavPack implementation)
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TAGLIB_APEPROPERTIES_H
|
||||||
|
#define TAGLIB_APEPROPERTIES_H
|
||||||
|
|
||||||
|
#include "taglib_export.h"
|
||||||
|
#include "audioproperties.h"
|
||||||
|
|
||||||
|
namespace TagLib {
|
||||||
|
|
||||||
|
namespace APE {
|
||||||
|
|
||||||
|
class File;
|
||||||
|
|
||||||
|
//! An implementation of audio property reading for APE
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This reads the data from an APE stream found in the AudioProperties
|
||||||
|
* API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TAGLIB_EXPORT Properties : public AudioProperties
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* Create an instance of APE::Properties with the data read from the
|
||||||
|
* ByteVector \a data.
|
||||||
|
*/
|
||||||
|
Properties(File *f, ReadStyle style = Average);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Destroys this APE::Properties instance.
|
||||||
|
*/
|
||||||
|
virtual ~Properties();
|
||||||
|
|
||||||
|
// Reimplementations.
|
||||||
|
|
||||||
|
virtual int length() const;
|
||||||
|
virtual int bitrate() const;
|
||||||
|
virtual int sampleRate() const;
|
||||||
|
virtual int channels() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns number of bits per sample.
|
||||||
|
*/
|
||||||
|
int bitsPerSample() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns APE version.
|
||||||
|
*/
|
||||||
|
int version() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Properties(const Properties &);
|
||||||
|
Properties &operator=(const Properties &);
|
||||||
|
|
||||||
|
void read();
|
||||||
|
|
||||||
|
long findDescriptor();
|
||||||
|
long findID3v2();
|
||||||
|
|
||||||
|
void analyzeCurrent();
|
||||||
|
void analyzeOld();
|
||||||
|
|
||||||
|
class PropertiesPrivate;
|
||||||
|
PropertiesPrivate *d;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -66,7 +66,7 @@ namespace TagLib {
|
||||||
* Create an APE tag and parse the data in \a file with APE footer at
|
* Create an APE tag and parse the data in \a file with APE footer at
|
||||||
* \a tagOffset.
|
* \a tagOffset.
|
||||||
*/
|
*/
|
||||||
Tag(File *file, long footerLocation);
|
Tag(TagLib::File *file, long footerLocation);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this Tag instance.
|
* Destroys this Tag instance.
|
||||||
|
|
|
@ -0,0 +1,338 @@
|
||||||
|
/**************************************************************************
|
||||||
|
copyright : (C) 2005-2007 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <taglib.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include "asfattribute.h"
|
||||||
|
#include "asffile.h"
|
||||||
|
|
||||||
|
using namespace TagLib;
|
||||||
|
|
||||||
|
class ASF::Attribute::AttributePrivate : public RefCounter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AttributePrivate()
|
||||||
|
: stream(0),
|
||||||
|
language(0) {}
|
||||||
|
AttributeTypes type;
|
||||||
|
String stringValue;
|
||||||
|
ByteVector byteVectorValue;
|
||||||
|
union {
|
||||||
|
unsigned int intValue;
|
||||||
|
unsigned short shortValue;
|
||||||
|
unsigned long long longLongValue;
|
||||||
|
bool boolValue;
|
||||||
|
};
|
||||||
|
int stream;
|
||||||
|
int language;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// public members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ASF::Attribute::Attribute()
|
||||||
|
{
|
||||||
|
d = new AttributePrivate;
|
||||||
|
d->type = UnicodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute::Attribute(const ASF::Attribute &other)
|
||||||
|
: d(other.d)
|
||||||
|
{
|
||||||
|
d->ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute &
|
||||||
|
ASF::Attribute::operator=(const ASF::Attribute &other)
|
||||||
|
{
|
||||||
|
if(d->deref())
|
||||||
|
delete d;
|
||||||
|
d = other.d;
|
||||||
|
d->ref();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute::~Attribute()
|
||||||
|
{
|
||||||
|
if(d->deref())
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute::Attribute(const String &value)
|
||||||
|
{
|
||||||
|
d = new AttributePrivate;
|
||||||
|
d->type = UnicodeType;
|
||||||
|
d->stringValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute::Attribute(const ByteVector &value)
|
||||||
|
{
|
||||||
|
d = new AttributePrivate;
|
||||||
|
d->type = BytesType;
|
||||||
|
d->byteVectorValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute::Attribute(unsigned int value)
|
||||||
|
{
|
||||||
|
d = new AttributePrivate;
|
||||||
|
d->type = DWordType;
|
||||||
|
d->intValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute::Attribute(unsigned long long value)
|
||||||
|
{
|
||||||
|
d = new AttributePrivate;
|
||||||
|
d->type = QWordType;
|
||||||
|
d->longLongValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute::Attribute(unsigned short value)
|
||||||
|
{
|
||||||
|
d = new AttributePrivate;
|
||||||
|
d->type = WordType;
|
||||||
|
d->shortValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute::Attribute(bool value)
|
||||||
|
{
|
||||||
|
d = new AttributePrivate;
|
||||||
|
d->type = BoolType;
|
||||||
|
d->boolValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Attribute::AttributeTypes
|
||||||
|
ASF::Attribute::type() const
|
||||||
|
{
|
||||||
|
return d->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::Attribute::toString() const
|
||||||
|
{
|
||||||
|
return d->stringValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::Attribute::toByteVector() const
|
||||||
|
{
|
||||||
|
return d->byteVectorValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short
|
||||||
|
ASF::Attribute::toBool() const
|
||||||
|
{
|
||||||
|
return d->shortValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short
|
||||||
|
ASF::Attribute::toUShort() const
|
||||||
|
{
|
||||||
|
return d->shortValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
ASF::Attribute::toUInt() const
|
||||||
|
{
|
||||||
|
return d->intValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long
|
||||||
|
ASF::Attribute::toULongLong() const
|
||||||
|
{
|
||||||
|
return d->longLongValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::Attribute::parse(ASF::File &f, int kind)
|
||||||
|
{
|
||||||
|
int size, nameLength;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
// extended content descriptor
|
||||||
|
if(kind == 0) {
|
||||||
|
nameLength = f.readWORD();
|
||||||
|
name = f.readString(nameLength);
|
||||||
|
d->type = ASF::Attribute::AttributeTypes(f.readWORD());
|
||||||
|
size = f.readWORD();
|
||||||
|
}
|
||||||
|
// metadata & metadata library
|
||||||
|
else {
|
||||||
|
int temp = f.readWORD();
|
||||||
|
// metadata library
|
||||||
|
if(kind == 2) {
|
||||||
|
d->language = temp;
|
||||||
|
}
|
||||||
|
d->stream = f.readWORD();
|
||||||
|
nameLength = f.readWORD();
|
||||||
|
d->type = ASF::Attribute::AttributeTypes(f.readWORD());
|
||||||
|
size = f.readDWORD();
|
||||||
|
name = f.readString(nameLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(kind != 2 && size > 65535) {
|
||||||
|
debug("ASF::Attribute::parse() -- Value larger than 64kB");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(d->type) {
|
||||||
|
case WordType:
|
||||||
|
d->shortValue = f.readWORD();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BoolType:
|
||||||
|
if(kind == 0) {
|
||||||
|
d->boolValue = f.readDWORD() == 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d->boolValue = f.readWORD() == 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DWordType:
|
||||||
|
d->intValue = f.readDWORD();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QWordType:
|
||||||
|
d->longLongValue = f.readQWORD();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UnicodeType:
|
||||||
|
d->stringValue = f.readString(size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BytesType:
|
||||||
|
case GuidType:
|
||||||
|
d->byteVectorValue = f.readBlock(size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ASF::Attribute::dataSize() const
|
||||||
|
{
|
||||||
|
switch (d->type) {
|
||||||
|
case WordType:
|
||||||
|
return 2;
|
||||||
|
case BoolType:
|
||||||
|
return 4;
|
||||||
|
case DWordType:
|
||||||
|
return 4;
|
||||||
|
case QWordType:
|
||||||
|
return 5;
|
||||||
|
case UnicodeType:
|
||||||
|
return d->stringValue.size() * 2 + 2;
|
||||||
|
case BytesType:
|
||||||
|
case GuidType:
|
||||||
|
return d->byteVectorValue.size();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::Attribute::render(const String &name, int kind) const
|
||||||
|
{
|
||||||
|
ByteVector data;
|
||||||
|
|
||||||
|
switch (d->type) {
|
||||||
|
case WordType:
|
||||||
|
data.append(ByteVector::fromShort(d->shortValue, false));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BoolType:
|
||||||
|
if(kind == 0) {
|
||||||
|
data.append(ByteVector::fromUInt(d->boolValue ? 1 : 0, false));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data.append(ByteVector::fromShort(d->boolValue ? 1 : 0, false));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DWordType:
|
||||||
|
data.append(ByteVector::fromUInt(d->intValue, false));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QWordType:
|
||||||
|
data.append(ByteVector::fromLongLong(d->longLongValue, false));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UnicodeType:
|
||||||
|
data.append(File::renderString(d->stringValue));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BytesType:
|
||||||
|
case GuidType:
|
||||||
|
data.append(d->byteVectorValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(kind == 0) {
|
||||||
|
data = File::renderString(name, true) +
|
||||||
|
ByteVector::fromShort((int)d->type, false) +
|
||||||
|
ByteVector::fromShort(data.size(), false) +
|
||||||
|
data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ByteVector nameData = File::renderString(name);
|
||||||
|
data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
|
||||||
|
ByteVector::fromShort(d->stream, false) +
|
||||||
|
ByteVector::fromShort(nameData.size(), false) +
|
||||||
|
ByteVector::fromShort((int)d->type, false) +
|
||||||
|
ByteVector::fromUInt(data.size(), false) +
|
||||||
|
nameData +
|
||||||
|
data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ASF::Attribute::language() const
|
||||||
|
{
|
||||||
|
return d->language;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Attribute::setLanguage(int value)
|
||||||
|
{
|
||||||
|
d->language = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ASF::Attribute::stream() const
|
||||||
|
{
|
||||||
|
return d->stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Attribute::setStream(int value)
|
||||||
|
{
|
||||||
|
d->stream = value;
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
/**************************************************************************
|
||||||
|
copyright : (C) 2005-2007 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TAGLIB_ASFATTRIBUTE_H
|
||||||
|
#define TAGLIB_ASFATTRIBUTE_H
|
||||||
|
|
||||||
|
#include "tstring.h"
|
||||||
|
#include "tbytevector.h"
|
||||||
|
#include "taglib_export.h"
|
||||||
|
|
||||||
|
namespace TagLib
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ASF
|
||||||
|
{
|
||||||
|
|
||||||
|
class File;
|
||||||
|
|
||||||
|
class TAGLIB_EXPORT Attribute
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enum of types an Attribute can have.
|
||||||
|
*/
|
||||||
|
enum AttributeTypes {
|
||||||
|
UnicodeType = 0,
|
||||||
|
BytesType = 1,
|
||||||
|
BoolType = 2,
|
||||||
|
DWordType = 3,
|
||||||
|
QWordType = 4,
|
||||||
|
WordType = 5,
|
||||||
|
GuidType = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constructs an empty attribute.
|
||||||
|
*/
|
||||||
|
Attribute();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constructs an attribute with \a key and a UnicodeType \a value.
|
||||||
|
*/
|
||||||
|
Attribute(const String &value);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constructs an attribute with \a key and a BytesType \a value.
|
||||||
|
*/
|
||||||
|
Attribute(const ByteVector &value);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constructs an attribute with \a key and a DWordType \a value.
|
||||||
|
*/
|
||||||
|
Attribute(unsigned int value);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constructs an attribute with \a key and a QWordType \a value.
|
||||||
|
*/
|
||||||
|
Attribute(unsigned long long value);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constructs an attribute with \a key and a WordType \a value.
|
||||||
|
*/
|
||||||
|
Attribute(unsigned short value);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constructs an attribute with \a key and a BoolType \a value.
|
||||||
|
*/
|
||||||
|
Attribute(bool value);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Construct an attribute as a copy of \a other.
|
||||||
|
*/
|
||||||
|
Attribute(const Attribute &item);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Copies the contents of \a other into this item.
|
||||||
|
*/
|
||||||
|
ASF::Attribute &operator=(const Attribute &other);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Destroys the attribute.
|
||||||
|
*/
|
||||||
|
virtual ~Attribute();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns type of the value.
|
||||||
|
*/
|
||||||
|
AttributeTypes type() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the BoolType \a value.
|
||||||
|
*/
|
||||||
|
unsigned short toBool() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the WordType \a value.
|
||||||
|
*/
|
||||||
|
unsigned short toUShort() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the DWordType \a value.
|
||||||
|
*/
|
||||||
|
unsigned int toUInt() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the QWordType \a value.
|
||||||
|
*/
|
||||||
|
unsigned long long toULongLong() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the UnicodeType \a value.
|
||||||
|
*/
|
||||||
|
String toString() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the BytesType \a value.
|
||||||
|
*/
|
||||||
|
ByteVector toByteVector() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the language number, or 0 is no stream number was set.
|
||||||
|
*/
|
||||||
|
int language() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the language number.
|
||||||
|
*/
|
||||||
|
void setLanguage(int value);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the stream number, or 0 is no stream number was set.
|
||||||
|
*/
|
||||||
|
int stream() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the stream number.
|
||||||
|
*/
|
||||||
|
void setStream(int value);
|
||||||
|
|
||||||
|
#ifndef DO_NOT_DOCUMENT
|
||||||
|
/* THIS IS PRIVATE, DON'T TOUCH IT! */
|
||||||
|
String parse(ASF::File &file, int kind = 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! Returns the size of the stored data
|
||||||
|
int dataSize() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class File;
|
||||||
|
|
||||||
|
ByteVector render(const String &name, int kind = 0) const;
|
||||||
|
|
||||||
|
class AttributePrivate;
|
||||||
|
AttributePrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,559 @@
|
||||||
|
/**************************************************************************
|
||||||
|
copyright : (C) 2005-2007 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tbytevectorlist.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#include "asffile.h"
|
||||||
|
#include "asftag.h"
|
||||||
|
#include "asfproperties.h"
|
||||||
|
|
||||||
|
using namespace TagLib;
|
||||||
|
|
||||||
|
class ASF::File::FilePrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FilePrivate():
|
||||||
|
size(0),
|
||||||
|
tag(0),
|
||||||
|
properties(0),
|
||||||
|
contentDescriptionObject(0),
|
||||||
|
extendedContentDescriptionObject(0),
|
||||||
|
headerExtensionObject(0),
|
||||||
|
metadataObject(0),
|
||||||
|
metadataLibraryObject(0) {}
|
||||||
|
unsigned long long size;
|
||||||
|
ASF::Tag *tag;
|
||||||
|
ASF::Properties *properties;
|
||||||
|
List<ASF::File::BaseObject *> objects;
|
||||||
|
ASF::File::ContentDescriptionObject *contentDescriptionObject;
|
||||||
|
ASF::File::ExtendedContentDescriptionObject *extendedContentDescriptionObject;
|
||||||
|
ASF::File::HeaderExtensionObject *headerExtensionObject;
|
||||||
|
ASF::File::MetadataObject *metadataObject;
|
||||||
|
ASF::File::MetadataLibraryObject *metadataLibraryObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
|
||||||
|
static ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16);
|
||||||
|
static ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16);
|
||||||
|
static ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
|
||||||
|
static ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16);
|
||||||
|
static ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16);
|
||||||
|
static ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16);
|
||||||
|
static ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16);
|
||||||
|
|
||||||
|
class ASF::File::BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ByteVector data;
|
||||||
|
virtual ~BaseObject() {}
|
||||||
|
virtual ByteVector guid() = 0;
|
||||||
|
virtual void parse(ASF::File *file, unsigned int size);
|
||||||
|
virtual ByteVector render(ASF::File *file);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ASF::File::UnknownObject : public ASF::File::BaseObject
|
||||||
|
{
|
||||||
|
ByteVector myGuid;
|
||||||
|
public:
|
||||||
|
UnknownObject(const ByteVector &guid);
|
||||||
|
ByteVector guid();
|
||||||
|
};
|
||||||
|
|
||||||
|
class ASF::File::FilePropertiesObject : public ASF::File::BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ByteVector guid();
|
||||||
|
void parse(ASF::File *file, uint size);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ASF::File::StreamPropertiesObject : public ASF::File::BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ByteVector guid();
|
||||||
|
void parse(ASF::File *file, uint size);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ASF::File::ContentDescriptionObject : public ASF::File::BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ByteVector guid();
|
||||||
|
void parse(ASF::File *file, uint size);
|
||||||
|
ByteVector render(ASF::File *file);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ASF::File::ExtendedContentDescriptionObject : public ASF::File::BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ByteVectorList attributeData;
|
||||||
|
ByteVector guid();
|
||||||
|
void parse(ASF::File *file, uint size);
|
||||||
|
ByteVector render(ASF::File *file);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ASF::File::MetadataObject : public ASF::File::BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ByteVectorList attributeData;
|
||||||
|
ByteVector guid();
|
||||||
|
void parse(ASF::File *file, uint size);
|
||||||
|
ByteVector render(ASF::File *file);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ASF::File::MetadataLibraryObject : public ASF::File::BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ByteVectorList attributeData;
|
||||||
|
ByteVector guid();
|
||||||
|
void parse(ASF::File *file, uint size);
|
||||||
|
ByteVector render(ASF::File *file);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ASF::File::HeaderExtensionObject : public ASF::File::BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
List<ASF::File::BaseObject *> objects;
|
||||||
|
ByteVector guid();
|
||||||
|
void parse(ASF::File *file, uint size);
|
||||||
|
ByteVector render(ASF::File *file);
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::File::BaseObject::parse(ASF::File *file, unsigned int size)
|
||||||
|
{
|
||||||
|
data = file->readBlock(size - 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::BaseObject::render(ASF::File * /*file*/)
|
||||||
|
{
|
||||||
|
return guid() + ByteVector::fromLongLong(data.size() + 24, false) + data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::File::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::UnknownObject::guid()
|
||||||
|
{
|
||||||
|
return myGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::FilePropertiesObject::guid()
|
||||||
|
{
|
||||||
|
return filePropertiesGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::File::FilePropertiesObject::parse(ASF::File *file, uint size)
|
||||||
|
{
|
||||||
|
BaseObject::parse(file, size);
|
||||||
|
file->d->properties->setLength((int)(data.mid(40, 8).toLongLong(false) / 10000000L - data.mid(56, 8).toLongLong(false) / 1000L));
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::StreamPropertiesObject::guid()
|
||||||
|
{
|
||||||
|
return streamPropertiesGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::File::StreamPropertiesObject::parse(ASF::File *file, uint size)
|
||||||
|
{
|
||||||
|
BaseObject::parse(file, size);
|
||||||
|
file->d->properties->setChannels(data.mid(56, 2).toShort(false));
|
||||||
|
file->d->properties->setSampleRate(data.mid(58, 4).toUInt(false));
|
||||||
|
file->d->properties->setBitrate(data.mid(62, 4).toUInt(false) * 8 / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::ContentDescriptionObject::guid()
|
||||||
|
{
|
||||||
|
return contentDescriptionGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::File::ContentDescriptionObject::parse(ASF::File *file, uint /*size*/)
|
||||||
|
{
|
||||||
|
file->d->contentDescriptionObject = this;
|
||||||
|
int titleLength = file->readWORD();
|
||||||
|
int artistLength = file->readWORD();
|
||||||
|
int copyrightLength = file->readWORD();
|
||||||
|
int commentLength = file->readWORD();
|
||||||
|
int ratingLength = file->readWORD();
|
||||||
|
file->d->tag->setTitle(file->readString(titleLength));
|
||||||
|
file->d->tag->setArtist(file->readString(artistLength));
|
||||||
|
file->d->tag->setCopyright(file->readString(copyrightLength));
|
||||||
|
file->d->tag->setComment(file->readString(commentLength));
|
||||||
|
file->d->tag->setRating(file->readString(ratingLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::ContentDescriptionObject::render(ASF::File *file)
|
||||||
|
{
|
||||||
|
ByteVector v1 = file->renderString(file->d->tag->title());
|
||||||
|
ByteVector v2 = file->renderString(file->d->tag->artist());
|
||||||
|
ByteVector v3 = file->renderString(file->d->tag->copyright());
|
||||||
|
ByteVector v4 = file->renderString(file->d->tag->comment());
|
||||||
|
ByteVector v5 = file->renderString(file->d->tag->rating());
|
||||||
|
data.clear();
|
||||||
|
data.append(ByteVector::fromShort(v1.size(), false));
|
||||||
|
data.append(ByteVector::fromShort(v2.size(), false));
|
||||||
|
data.append(ByteVector::fromShort(v3.size(), false));
|
||||||
|
data.append(ByteVector::fromShort(v4.size(), false));
|
||||||
|
data.append(ByteVector::fromShort(v5.size(), false));
|
||||||
|
data.append(v1);
|
||||||
|
data.append(v2);
|
||||||
|
data.append(v3);
|
||||||
|
data.append(v4);
|
||||||
|
data.append(v5);
|
||||||
|
return BaseObject::render(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::ExtendedContentDescriptionObject::guid()
|
||||||
|
{
|
||||||
|
return extendedContentDescriptionGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::File::ExtendedContentDescriptionObject::parse(ASF::File *file, uint /*size*/)
|
||||||
|
{
|
||||||
|
file->d->extendedContentDescriptionObject = this;
|
||||||
|
int count = file->readWORD();
|
||||||
|
while(count--) {
|
||||||
|
ASF::Attribute attribute;
|
||||||
|
String name = attribute.parse(*file);
|
||||||
|
file->d->tag->addAttribute(name, attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::ExtendedContentDescriptionObject::render(ASF::File *file)
|
||||||
|
{
|
||||||
|
data.clear();
|
||||||
|
data.append(ByteVector::fromShort(attributeData.size(), false));
|
||||||
|
data.append(attributeData.toByteVector(ByteVector::null));
|
||||||
|
return BaseObject::render(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::MetadataObject::guid()
|
||||||
|
{
|
||||||
|
return metadataGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::File::MetadataObject::parse(ASF::File *file, uint /*size*/)
|
||||||
|
{
|
||||||
|
file->d->metadataObject = this;
|
||||||
|
int count = file->readWORD();
|
||||||
|
while(count--) {
|
||||||
|
ASF::Attribute attribute;
|
||||||
|
String name = attribute.parse(*file, 1);
|
||||||
|
file->d->tag->addAttribute(name, attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::MetadataObject::render(ASF::File *file)
|
||||||
|
{
|
||||||
|
data.clear();
|
||||||
|
data.append(ByteVector::fromShort(attributeData.size(), false));
|
||||||
|
data.append(attributeData.toByteVector(ByteVector::null));
|
||||||
|
return BaseObject::render(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::MetadataLibraryObject::guid()
|
||||||
|
{
|
||||||
|
return metadataLibraryGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::File::MetadataLibraryObject::parse(ASF::File *file, uint /*size*/)
|
||||||
|
{
|
||||||
|
file->d->metadataLibraryObject = this;
|
||||||
|
int count = file->readWORD();
|
||||||
|
while(count--) {
|
||||||
|
ASF::Attribute attribute;
|
||||||
|
String name = attribute.parse(*file, 2);
|
||||||
|
file->d->tag->addAttribute(name, attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::MetadataLibraryObject::render(ASF::File *file)
|
||||||
|
{
|
||||||
|
data.clear();
|
||||||
|
data.append(ByteVector::fromShort(attributeData.size(), false));
|
||||||
|
data.append(attributeData.toByteVector(ByteVector::null));
|
||||||
|
return BaseObject::render(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::HeaderExtensionObject::guid()
|
||||||
|
{
|
||||||
|
return headerExtensionGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::File::HeaderExtensionObject::parse(ASF::File *file, uint /*size*/)
|
||||||
|
{
|
||||||
|
file->d->headerExtensionObject = this;
|
||||||
|
file->seek(18, File::Current);
|
||||||
|
long long dataSize = file->readDWORD();
|
||||||
|
long long dataPos = 0;
|
||||||
|
while(dataPos < dataSize) {
|
||||||
|
ByteVector guid = file->readBlock(16);
|
||||||
|
long long size = file->readQWORD();
|
||||||
|
BaseObject *obj;
|
||||||
|
if(guid == metadataGuid) {
|
||||||
|
obj = new MetadataObject();
|
||||||
|
}
|
||||||
|
else if(guid == metadataLibraryGuid) {
|
||||||
|
obj = new MetadataLibraryObject();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj = new UnknownObject(guid);
|
||||||
|
}
|
||||||
|
obj->parse(file, size);
|
||||||
|
objects.append(obj);
|
||||||
|
dataPos += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::HeaderExtensionObject::render(ASF::File *file)
|
||||||
|
{
|
||||||
|
data.clear();
|
||||||
|
for(unsigned int i = 0; i < objects.size(); i++) {
|
||||||
|
data.append(objects[i]->render(file));
|
||||||
|
}
|
||||||
|
data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt(data.size(), false) + data;
|
||||||
|
return BaseObject::render(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// public members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ASF::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle)
|
||||||
|
: TagLib::File(file)
|
||||||
|
{
|
||||||
|
d = new FilePrivate;
|
||||||
|
read(readProperties, propertiesStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::File::~File()
|
||||||
|
{
|
||||||
|
for(unsigned int i = 0; i < d->objects.size(); i++) {
|
||||||
|
delete d->objects[i];
|
||||||
|
}
|
||||||
|
if(d->tag) {
|
||||||
|
delete d->tag;
|
||||||
|
}
|
||||||
|
if(d->properties) {
|
||||||
|
delete d->properties;
|
||||||
|
}
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Tag *ASF::File::tag() const
|
||||||
|
{
|
||||||
|
return d->tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Properties *ASF::File::audioProperties() const
|
||||||
|
{
|
||||||
|
return d->properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASF::File::read(bool /*readProperties*/, Properties::ReadStyle /*propertiesStyle*/)
|
||||||
|
{
|
||||||
|
if(!isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ByteVector guid = readBlock(16);
|
||||||
|
if(guid != headerGuid) {
|
||||||
|
debug("ASF: Not an ASF file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->tag = new ASF::Tag();
|
||||||
|
d->properties = new ASF::Properties();
|
||||||
|
|
||||||
|
d->size = readQWORD();
|
||||||
|
int numObjects = readDWORD();
|
||||||
|
seek(2, Current);
|
||||||
|
|
||||||
|
for(int i = 0; i < numObjects; i++) {
|
||||||
|
ByteVector guid = readBlock(16);
|
||||||
|
long size = (long)readQWORD();
|
||||||
|
BaseObject *obj;
|
||||||
|
if(guid == filePropertiesGuid) {
|
||||||
|
obj = new FilePropertiesObject();
|
||||||
|
}
|
||||||
|
else if(guid == streamPropertiesGuid) {
|
||||||
|
obj = new StreamPropertiesObject();
|
||||||
|
}
|
||||||
|
else if(guid == contentDescriptionGuid) {
|
||||||
|
obj = new ContentDescriptionObject();
|
||||||
|
}
|
||||||
|
else if(guid == extendedContentDescriptionGuid) {
|
||||||
|
obj = new ExtendedContentDescriptionObject();
|
||||||
|
}
|
||||||
|
else if(guid == headerExtensionGuid) {
|
||||||
|
obj = new HeaderExtensionObject();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj = new UnknownObject(guid);
|
||||||
|
}
|
||||||
|
obj->parse(this, size);
|
||||||
|
d->objects.append(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ASF::File::save()
|
||||||
|
{
|
||||||
|
if(readOnly()) {
|
||||||
|
debug("ASF: File is read-only.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!d->contentDescriptionObject) {
|
||||||
|
d->contentDescriptionObject = new ContentDescriptionObject();
|
||||||
|
d->objects.append(d->contentDescriptionObject);
|
||||||
|
}
|
||||||
|
if(!d->extendedContentDescriptionObject) {
|
||||||
|
d->extendedContentDescriptionObject = new ExtendedContentDescriptionObject();
|
||||||
|
d->objects.append(d->extendedContentDescriptionObject);
|
||||||
|
}
|
||||||
|
if(!d->headerExtensionObject) {
|
||||||
|
d->headerExtensionObject = new HeaderExtensionObject();
|
||||||
|
d->objects.append(d->headerExtensionObject);
|
||||||
|
}
|
||||||
|
if(!d->metadataObject) {
|
||||||
|
d->metadataObject = new MetadataObject();
|
||||||
|
d->headerExtensionObject->objects.append(d->metadataObject);
|
||||||
|
}
|
||||||
|
if(!d->metadataLibraryObject) {
|
||||||
|
d->metadataLibraryObject = new MetadataLibraryObject();
|
||||||
|
d->headerExtensionObject->objects.append(d->metadataLibraryObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::AttributeListMap::ConstIterator it = d->tag->attributeListMap().begin();
|
||||||
|
for(; it != d->tag->attributeListMap().end(); it++) {
|
||||||
|
const String &name = it->first;
|
||||||
|
const AttributeList &attributes = it->second;
|
||||||
|
bool inExtendedContentDescriptionObject = false;
|
||||||
|
bool inMetadataObject = false;
|
||||||
|
for(unsigned int j = 0; j < attributes.size(); j++) {
|
||||||
|
const Attribute &attribute = attributes[j];
|
||||||
|
bool largeValue = attribute.dataSize() > 65535;
|
||||||
|
if(!inExtendedContentDescriptionObject && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
|
||||||
|
d->extendedContentDescriptionObject->attributeData.append(attribute.render(name));
|
||||||
|
inExtendedContentDescriptionObject = true;
|
||||||
|
}
|
||||||
|
else if(!inMetadataObject && !largeValue && attribute.language() == 0 && attribute.stream() != 0) {
|
||||||
|
d->metadataObject->attributeData.append(attribute.render(name, 1));
|
||||||
|
inMetadataObject = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d->metadataLibraryObject->attributeData.append(attribute.render(name, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector data;
|
||||||
|
for(unsigned int i = 0; i < d->objects.size(); i++) {
|
||||||
|
data.append(d->objects[i]->render(this));
|
||||||
|
}
|
||||||
|
data = headerGuid + ByteVector::fromLongLong(data.size() + 30, false) + ByteVector::fromUInt(d->objects.size(), false) + ByteVector("\x01\x02", 2) + data;
|
||||||
|
insert(data, 0, d->size);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// protected members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int ASF::File::readBYTE()
|
||||||
|
{
|
||||||
|
ByteVector v = readBlock(1);
|
||||||
|
return v[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
int ASF::File::readWORD()
|
||||||
|
{
|
||||||
|
ByteVector v = readBlock(2);
|
||||||
|
return v.toShort(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int ASF::File::readDWORD()
|
||||||
|
{
|
||||||
|
ByteVector v = readBlock(4);
|
||||||
|
return v.toUInt(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
long long ASF::File::readQWORD()
|
||||||
|
{
|
||||||
|
ByteVector v = readBlock(8);
|
||||||
|
return v.toLongLong(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::File::readString(int length)
|
||||||
|
{
|
||||||
|
ByteVector data = readBlock(length);
|
||||||
|
unsigned int size = data.size();
|
||||||
|
while (size >= 2) {
|
||||||
|
if(data[size - 1] != '\0' || data[size - 2] != '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size -= 2;
|
||||||
|
}
|
||||||
|
if(size != data.size()) {
|
||||||
|
data.resize(size);
|
||||||
|
}
|
||||||
|
return String(data, String::UTF16LE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector
|
||||||
|
ASF::File::renderString(const String &str, bool includeLength)
|
||||||
|
{
|
||||||
|
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false);
|
||||||
|
if(includeLength) {
|
||||||
|
data = ByteVector::fromShort(data.size(), false) + data;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
/**************************************************************************
|
||||||
|
copyright : (C) 2005-2007 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TAGLIB_ASFFILE_H
|
||||||
|
#define TAGLIB_ASFFILE_H
|
||||||
|
|
||||||
|
#include "tag.h"
|
||||||
|
#include "tfile.h"
|
||||||
|
#include "taglib_export.h"
|
||||||
|
#include "asfproperties.h"
|
||||||
|
#include "asftag.h"
|
||||||
|
|
||||||
|
namespace TagLib {
|
||||||
|
|
||||||
|
//! An implementation of ASF (WMA) metadata
|
||||||
|
namespace ASF {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This implements and provides an interface for ASF files to the
|
||||||
|
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||||
|
* the abstract TagLib::File API as well as providing some additional
|
||||||
|
* information specific to ASF files.
|
||||||
|
*/
|
||||||
|
class TAGLIB_EXPORT File : public TagLib::File
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Contructs an ASF file from \a file. If \a readProperties is true the
|
||||||
|
* file's audio properties will also be read using \a propertiesStyle. If
|
||||||
|
* false, \a propertiesStyle is ignored.
|
||||||
|
*
|
||||||
|
* \note In the current implementation, both \a readProperties and
|
||||||
|
* \a propertiesStyle are ignored.
|
||||||
|
*/
|
||||||
|
File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Destroys this instance of the File.
|
||||||
|
*/
|
||||||
|
virtual ~File();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns a pointer to the ASF tag of the file.
|
||||||
|
*
|
||||||
|
* ASF::Tag implements the tag interface, so this serves as the
|
||||||
|
* reimplementation of TagLib::File::tag().
|
||||||
|
*
|
||||||
|
* \note The Tag <b>is still</b> owned by the ASF::File and should not be
|
||||||
|
* deleted by the user. It will be deleted when the file (object) is
|
||||||
|
* destroyed.
|
||||||
|
*/
|
||||||
|
virtual Tag *tag() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the ASF audio properties for this file.
|
||||||
|
*/
|
||||||
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Save the file.
|
||||||
|
*
|
||||||
|
* This returns true if the save was successful.
|
||||||
|
*/
|
||||||
|
virtual bool save();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int readBYTE();
|
||||||
|
int readWORD();
|
||||||
|
unsigned int readDWORD();
|
||||||
|
long long readQWORD();
|
||||||
|
static ByteVector renderString(const String &str, bool includeLength = false);
|
||||||
|
String readString(int len);
|
||||||
|
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
||||||
|
|
||||||
|
friend class Attribute;
|
||||||
|
|
||||||
|
class BaseObject;
|
||||||
|
class UnknownObject;
|
||||||
|
class FilePropertiesObject;
|
||||||
|
class StreamPropertiesObject;
|
||||||
|
class ContentDescriptionObject;
|
||||||
|
class ExtendedContentDescriptionObject;
|
||||||
|
class HeaderExtensionObject;
|
||||||
|
class MetadataObject;
|
||||||
|
class MetadataLibraryObject;
|
||||||
|
|
||||||
|
class FilePrivate;
|
||||||
|
FilePrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,103 @@
|
||||||
|
/**************************************************************************
|
||||||
|
copyright : (C) 2005-2007 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#include "asfproperties.h"
|
||||||
|
|
||||||
|
using namespace TagLib;
|
||||||
|
|
||||||
|
class ASF::Properties::PropertiesPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PropertiesPrivate(): length(0), bitrate(0), sampleRate(0), channels(0) {}
|
||||||
|
int length;
|
||||||
|
int bitrate;
|
||||||
|
int sampleRate;
|
||||||
|
int channels;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// public members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ASF::Properties::Properties() : AudioProperties(AudioProperties::Average)
|
||||||
|
{
|
||||||
|
d = new PropertiesPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Properties::~Properties()
|
||||||
|
{
|
||||||
|
if(d)
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ASF::Properties::length() const
|
||||||
|
{
|
||||||
|
return d->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ASF::Properties::bitrate() const
|
||||||
|
{
|
||||||
|
return d->bitrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ASF::Properties::sampleRate() const
|
||||||
|
{
|
||||||
|
return d->sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ASF::Properties::channels() const
|
||||||
|
{
|
||||||
|
return d->channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// private members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void ASF::Properties::setLength(int length)
|
||||||
|
{
|
||||||
|
d->length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASF::Properties::setBitrate(int length)
|
||||||
|
{
|
||||||
|
d->bitrate = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASF::Properties::setSampleRate(int length)
|
||||||
|
{
|
||||||
|
d->sampleRate = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASF::Properties::setChannels(int length)
|
||||||
|
{
|
||||||
|
d->channels = length;
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**************************************************************************
|
||||||
|
copyright : (C) 2005-2007 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TAGLIB_ASFPROPERTIES_H
|
||||||
|
#define TAGLIB_ASFPROPERTIES_H
|
||||||
|
|
||||||
|
#include "audioproperties.h"
|
||||||
|
#include "tstring.h"
|
||||||
|
#include "taglib_export.h"
|
||||||
|
|
||||||
|
namespace TagLib {
|
||||||
|
|
||||||
|
namespace ASF {
|
||||||
|
|
||||||
|
//! An implementation of ASF audio properties
|
||||||
|
class TAGLIB_EXPORT Properties : public AudioProperties
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Create an instance of ASF::Properties.
|
||||||
|
*/
|
||||||
|
Properties();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Destroys this ASF::Properties instance.
|
||||||
|
*/
|
||||||
|
virtual ~Properties();
|
||||||
|
|
||||||
|
// Reimplementations.
|
||||||
|
virtual int length() const;
|
||||||
|
virtual int bitrate() const;
|
||||||
|
virtual int sampleRate() const;
|
||||||
|
virtual int channels() const;
|
||||||
|
|
||||||
|
#ifndef DO_NOT_DOCUMENT
|
||||||
|
void setLength(int value);
|
||||||
|
void setBitrate(int value);
|
||||||
|
void setSampleRate(int value);
|
||||||
|
void setChannels(int value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
class PropertiesPrivate;
|
||||||
|
PropertiesPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,259 @@
|
||||||
|
/**************************************************************************
|
||||||
|
copyright : (C) 2005-2007 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "asftag.h"
|
||||||
|
|
||||||
|
using namespace TagLib;
|
||||||
|
|
||||||
|
class ASF::Tag::TagPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String title;
|
||||||
|
String artist;
|
||||||
|
String copyright;
|
||||||
|
String comment;
|
||||||
|
String rating;
|
||||||
|
AttributeListMap attributeListMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
ASF::Tag::Tag()
|
||||||
|
: TagLib::Tag()
|
||||||
|
{
|
||||||
|
d = new TagPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::Tag::~Tag()
|
||||||
|
{
|
||||||
|
if(d)
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::Tag::title() const
|
||||||
|
{
|
||||||
|
return d->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::Tag::artist() const
|
||||||
|
{
|
||||||
|
return d->artist;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::Tag::album() const
|
||||||
|
{
|
||||||
|
if(d->attributeListMap.contains("WM/AlbumTitle"))
|
||||||
|
return d->attributeListMap["WM/AlbumTitle"][0].toString();
|
||||||
|
return String::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::Tag::copyright() const
|
||||||
|
{
|
||||||
|
return d->copyright;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::Tag::comment() const
|
||||||
|
{
|
||||||
|
return d->comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::Tag::rating() const
|
||||||
|
{
|
||||||
|
return d->rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
ASF::Tag::year() const
|
||||||
|
{
|
||||||
|
if(d->attributeListMap.contains("WM/Year"))
|
||||||
|
return d->attributeListMap["WM/Year"][0].toString().toInt();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
ASF::Tag::track() const
|
||||||
|
{
|
||||||
|
if(d->attributeListMap.contains("WM/TrackNumber")) {
|
||||||
|
const ASF::Attribute attr = d->attributeListMap["WM/TrackNumber"][0];
|
||||||
|
if(attr.type() == ASF::Attribute::DWordType)
|
||||||
|
return attr.toUInt();
|
||||||
|
else
|
||||||
|
return attr.toString().toInt();
|
||||||
|
}
|
||||||
|
if(d->attributeListMap.contains("WM/Track"))
|
||||||
|
return d->attributeListMap["WM/Track"][0].toUInt();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
ASF::Tag::genre() const
|
||||||
|
{
|
||||||
|
if(d->attributeListMap.contains("WM/Genre"))
|
||||||
|
return d->attributeListMap["WM/Genre"][0].toString();
|
||||||
|
return String::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
ASF::Tag::rgAlbumGain() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
ASF::Tag::rgAlbumPeak() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
ASF::Tag::rgTrackGain() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
ASF::Tag::rgTrackPeak() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setTitle(const String &value)
|
||||||
|
{
|
||||||
|
d->title = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setArtist(const String &value)
|
||||||
|
{
|
||||||
|
d->artist = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setCopyright(const String &value)
|
||||||
|
{
|
||||||
|
d->copyright = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setComment(const String &value)
|
||||||
|
{
|
||||||
|
d->comment = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setRating(const String &value)
|
||||||
|
{
|
||||||
|
d->rating = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setAlbum(const String &value)
|
||||||
|
{
|
||||||
|
setAttribute("WM/AlbumTitle", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setGenre(const String &value)
|
||||||
|
{
|
||||||
|
setAttribute("WM/Genre", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setYear(uint value)
|
||||||
|
{
|
||||||
|
setAttribute("WM/Year", String::number(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setTrack(uint value)
|
||||||
|
{
|
||||||
|
setAttribute("WM/TrackNumber", String::number(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setRGAlbumGain(float)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setRGAlbumPeak(float)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setRGTrackGain(float)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ASF::Tag::setRGTrackPeak(float)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF::AttributeListMap&
|
||||||
|
ASF::Tag::attributeListMap()
|
||||||
|
{
|
||||||
|
return d->attributeListMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASF::Tag::removeItem(const String &key)
|
||||||
|
{
|
||||||
|
AttributeListMap::Iterator it = d->attributeListMap.find(key);
|
||||||
|
if(it != d->attributeListMap.end())
|
||||||
|
d->attributeListMap.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASF::Tag::setAttribute(const String &name, const Attribute &attribute)
|
||||||
|
{
|
||||||
|
AttributeList value;
|
||||||
|
value.append(attribute);
|
||||||
|
d->attributeListMap.insert(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASF::Tag::addAttribute(const String &name, const Attribute &attribute)
|
||||||
|
{
|
||||||
|
if(d->attributeListMap.contains(name)) {
|
||||||
|
d->attributeListMap[name].append(attribute);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setAttribute(name, attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ASF::Tag::isEmpty() const {
|
||||||
|
return TagLib::Tag::isEmpty() &&
|
||||||
|
copyright().isEmpty() &&
|
||||||
|
rating().isEmpty() &&
|
||||||
|
d->attributeListMap.isEmpty();
|
||||||
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
/**************************************************************************
|
||||||
|
copyright : (C) 2005-2007 by Lukáš Lalinský
|
||||||
|
email : lalinsky@gmail.com
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
* *
|
||||||
|
* Alternatively, this file is available under the Mozilla Public *
|
||||||
|
* License Version 1.1. You may obtain a copy of the License at *
|
||||||
|
* http://www.mozilla.org/MPL/ *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TAGLIB_ASFTAG_H
|
||||||
|
#define TAGLIB_ASFTAG_H
|
||||||
|
|
||||||
|
#include "tag.h"
|
||||||
|
#include "tlist.h"
|
||||||
|
#include "tmap.h"
|
||||||
|
#include "taglib_export.h"
|
||||||
|
#include "asfattribute.h"
|
||||||
|
|
||||||
|
namespace TagLib {
|
||||||
|
|
||||||
|
namespace ASF {
|
||||||
|
|
||||||
|
typedef List<Attribute> AttributeList;
|
||||||
|
typedef Map<String, AttributeList> AttributeListMap;
|
||||||
|
|
||||||
|
class TAGLIB_EXPORT Tag : public TagLib::Tag {
|
||||||
|
|
||||||
|
friend class File;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Tag();
|
||||||
|
|
||||||
|
virtual ~Tag();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the track name.
|
||||||
|
*/
|
||||||
|
virtual String title() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the artist name.
|
||||||
|
*/
|
||||||
|
virtual String artist() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the album name; if no album name is present in the tag
|
||||||
|
* String::null will be returned.
|
||||||
|
*/
|
||||||
|
virtual String album() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the track comment.
|
||||||
|
*/
|
||||||
|
virtual String comment() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the genre name; if no genre is present in the tag String::null
|
||||||
|
* will be returned.
|
||||||
|
*/
|
||||||
|
virtual String genre() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the rating.
|
||||||
|
*/
|
||||||
|
virtual String rating() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the genre name; if no genre is present in the tag String::null
|
||||||
|
* will be returned.
|
||||||
|
*/
|
||||||
|
virtual String copyright() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the year; if there is no year set, this will return 0.
|
||||||
|
*/
|
||||||
|
virtual uint year() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the track number; if there is no track number set, this will
|
||||||
|
* return 0.
|
||||||
|
*/
|
||||||
|
virtual uint track() const;
|
||||||
|
|
||||||
|
virtual float rgAlbumGain() const;
|
||||||
|
virtual float rgAlbumPeak() const;
|
||||||
|
virtual float rgTrackGain() const;
|
||||||
|
virtual float rgTrackPeak() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the title to \a s.
|
||||||
|
*/
|
||||||
|
virtual void setTitle(const String &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the artist to \a s.
|
||||||
|
*/
|
||||||
|
virtual void setArtist(const String &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the album to \a s. If \a s is String::null then this value will be
|
||||||
|
* cleared.
|
||||||
|
*/
|
||||||
|
virtual void setAlbum(const String &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the comment to \a s.
|
||||||
|
*/
|
||||||
|
virtual void setComment(const String &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the rating to \a s.
|
||||||
|
*/
|
||||||
|
virtual void setRating(const String &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the copyright to \a s.
|
||||||
|
*/
|
||||||
|
virtual void setCopyright(const String &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the genre to \a s.
|
||||||
|
*/
|
||||||
|
virtual void setGenre(const String &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the year to \a i. If \a s is 0 then this value will be cleared.
|
||||||
|
*/
|
||||||
|
virtual void setYear(uint i);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the track to \a i. If \a s is 0 then this value will be cleared.
|
||||||
|
*/
|
||||||
|
virtual void setTrack(uint i);
|
||||||
|
|
||||||
|
virtual void setRGAlbumGain(float f);
|
||||||
|
virtual void setRGAlbumPeak(float f);
|
||||||
|
virtual void setRGTrackGain(float f);
|
||||||
|
virtual void setRGTrackPeak(float f);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns true if the tag does not contain any data. This should be
|
||||||
|
* reimplemented in subclasses that provide more than the basic tagging
|
||||||
|
* abilities in this class.
|
||||||
|
*/
|
||||||
|
virtual bool isEmpty() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns a reference to the item list map. This is an AttributeListMap of
|
||||||
|
* all of the items in the tag.
|
||||||
|
*
|
||||||
|
* This is the most powerfull structure for accessing the items of the tag.
|
||||||
|
*/
|
||||||
|
AttributeListMap &attributeListMap();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Removes the \a key attribute from the tag
|
||||||
|
*/
|
||||||
|
void removeItem(const String &name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the \a key attribute to the value of \a attribute. If an attribute
|
||||||
|
* with the \a key is already present, it will be replaced.
|
||||||
|
*/
|
||||||
|
void setAttribute(const String &name, const Attribute &attribute);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Sets the \a key attribute to the value of \a attribute. If an attribute
|
||||||
|
* with the \a key is already present, it will be added to the list.
|
||||||
|
*/
|
||||||
|
void addAttribute(const String &name, const Attribute &attribute);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
class TagPrivate;
|
||||||
|
TagPrivate *d;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,6 +1,10 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
copyright : (C) 2002 - 2008 by Scott Wheeler
|
copyright : (C) 2002 - 2008 by Scott Wheeler
|
||||||
email : wheeler@kde.org
|
email : wheeler@kde.org
|
||||||
|
|
||||||
|
copyright : (C) 2010 by Alex Novichkov
|
||||||
|
email : novichko@atnet.ru
|
||||||
|
(added APE file support)
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -27,6 +31,7 @@
|
||||||
#include <tstring.h>
|
#include <tstring.h>
|
||||||
|
|
||||||
#include "fileref.h"
|
#include "fileref.h"
|
||||||
|
#include "asffile.h"
|
||||||
#include "mpegfile.h"
|
#include "mpegfile.h"
|
||||||
#include "vorbisfile.h"
|
#include "vorbisfile.h"
|
||||||
#include "flacfile.h"
|
#include "flacfile.h"
|
||||||
|
@ -36,6 +41,7 @@
|
||||||
#include "speexfile.h"
|
#include "speexfile.h"
|
||||||
#include "trueaudiofile.h"
|
#include "trueaudiofile.h"
|
||||||
#include "mp4file.h"
|
#include "mp4file.h"
|
||||||
|
#include "apefile.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace TagLib;
|
||||||
|
|
||||||
|
@ -123,6 +129,13 @@ StringList FileRef::defaultFileExtensions()
|
||||||
l.append("spx");
|
l.append("spx");
|
||||||
l.append("tta");
|
l.append("tta");
|
||||||
l.append("m4a");
|
l.append("m4a");
|
||||||
|
l.append("m4b");
|
||||||
|
l.append("m4p");
|
||||||
|
l.append("3g2");
|
||||||
|
l.append("mp4");
|
||||||
|
l.append("wma");
|
||||||
|
l.append("asf");
|
||||||
|
l.append("ape");
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
@ -182,25 +195,36 @@ File *FileRef::create(FileName fileName, bool readAudioProperties,
|
||||||
// updated. However at some point that list should be created at the same time
|
// updated. However at some point that list should be created at the same time
|
||||||
// that a default file type resolver is created.
|
// that a default file type resolver is created.
|
||||||
|
|
||||||
if(s.size() > 4) {
|
int pos = s.rfind(".");
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".OGG")
|
if(pos != -1) {
|
||||||
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
String ext = s.substr(pos + 1).upper();
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".MP3")
|
if(ext == "MP3")
|
||||||
return new MPEG::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new MPEG::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".OGA")
|
if(ext == "OGG")
|
||||||
return new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(s.substr(s.size() - 5, 5).upper() == ".FLAC")
|
if(ext == "OGA") {
|
||||||
|
File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (file->isValid())
|
||||||
|
return file;
|
||||||
|
delete file;
|
||||||
|
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
}
|
||||||
|
if(ext == "FLAC")
|
||||||
return new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".MPC")
|
if(ext == "MPC")
|
||||||
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(s.substr(s.size() - 3, 3).upper() == ".WV")
|
if(ext == "WV")
|
||||||
return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".SPX")
|
if(ext == "SPX")
|
||||||
return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".TTA")
|
if(ext == "TTA")
|
||||||
return new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".M4A")
|
if(ext == "M4A" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2")
|
||||||
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if(ext == "WMA" || ext == "ASF")
|
||||||
|
return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if(ext == "APE")
|
||||||
|
return new APE::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -295,6 +295,17 @@ int String::find(const String &s, int offset) const
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int String::rfind(const String &s, int offset) const
|
||||||
|
{
|
||||||
|
wstring::size_type position =
|
||||||
|
d->data.rfind(s.d->data, offset == -1 ? wstring::npos : offset);
|
||||||
|
|
||||||
|
if(position != wstring::npos)
|
||||||
|
return position;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
bool String::startsWith(const String &s) const
|
bool String::startsWith(const String &s) const
|
||||||
{
|
{
|
||||||
if(s.length() > length())
|
if(s.length() > length())
|
||||||
|
|
|
@ -225,6 +225,13 @@ namespace TagLib {
|
||||||
*/
|
*/
|
||||||
int find(const String &s, int offset = 0) const;
|
int find(const String &s, int offset = 0) const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Finds the last occurrence of pattern \a s in this string, searched backwards,
|
||||||
|
* either from the end of the string or starting from \a offset. If the pattern
|
||||||
|
* is not found, -1 is returned.
|
||||||
|
*/
|
||||||
|
int rfind(const String &s, int offset = -1) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns true if the strings starts with the substring \a s.
|
* Returns true if the strings starts with the substring \a s.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -174,12 +174,12 @@
|
||||||
+ (NSArray *)fileTypes
|
+ (NSArray *)fileTypes
|
||||||
{
|
{
|
||||||
//May be a way to get a list of supported formats
|
//May be a way to get a list of supported formats
|
||||||
return [NSArray arrayWithObjects:@"ogg", @"mpc", @"flac", @"m4a", @"mp3", nil];
|
return [NSArray arrayWithObjects:@"ape", @"asf", @"wma", @"ogg", @"mpc", @"flac", @"m4a", @"mp3", nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSArray *)mimeTypes
|
+ (NSArray *)mimeTypes
|
||||||
{
|
{
|
||||||
return [NSArray arrayWithObjects:@"application/ogg", @"application/x-ogg", @"audio/x-vorbis+ogg", @"audio/x-musepack", @"audio/x-flac", @"audio/x-m4a", @"audio/mpeg", @"audio/x-mp3", nil];
|
return [NSArray arrayWithObjects:@"audio/x-ape", @"audio/x-ms-wma", @"application/ogg", @"application/x-ogg", @"audio/x-vorbis+ogg", @"audio/x-musepack", @"audio/x-flac", @"audio/x-m4a", @"audio/mpeg", @"audio/x-mp3", nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in New Issue