379 Commits

Author SHA1 Message Date
Tim Malseed
65a6a4e225 Minor fix for mp4 media header v0 minimum size check (#894)
Mp4 media header (mdhd) v0 atoms are a minimum of 8 bytes for size & type information, plus 24 bytes for remaining entries (`24 +8`) bytes in total, rather than (`24 + 4`).

See https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25615
2019-03-17 08:20:08 -05:00
Tim Malseed
02090f335d Fixed an MP4 AudioProperties parsing error (#892)
The 'unit' (timescale) of 'mdhd' v1 atoms is a 32-bit unsigned integer (4 bytes long), but is parsed as a 64-bit integer (8 bytes long). This also affects the byte offset of the 'length' (duration).  This results in MP4 AudioProperties reporting a track length of zero.

This change addresses both problems.

See:
https://wiki.multimedia.cx/index.php/QuickTime_container
2019-03-16 07:59:13 -05:00
Stephen F. Booth
96a4d896ba Merge branch 'sandsmark-taglib2' into taglib2 2018-10-29 18:16:12 -05:00
Stephen F. Booth
15163b7af2 Resolved merge conflicts 2018-10-29 18:15:50 -05:00
Stephen F. Booth
19ee7c86c4 Merge branch 'master' into taglib2 2018-10-28 10:53:23 -05:00
evpobr
fc31a09c03 Fix undefined PLATFORM_WINRT CMake option (#870) 2018-10-09 18:52:09 -05:00
Alberto Fustinoni
2052cda5fb Added setProperties implementation to TagUnion (#813)
Added setProperties support in TagUnion
2018-08-24 08:40:15 -05:00
Tsuda Kageyu
6048cdef3e Apply smart pointers to MPC::File. 2017-06-14 10:11:37 +09:00
Tsuda Kageyu
ff34e42aef Apply smart pointers to FLAC::File. 2017-06-14 10:09:11 +09:00
Tsuda Kageyu
bac14180e9 Apply smart pointers to DSF::File. 2017-06-14 09:51:38 +09:00
Tsuda Kageyu
c30bae9b00 Apply smart pointers to RIFF related classes. 2017-06-14 09:47:38 +09:00
Tsuda Kageyu
4dcdaaf92a Apply smart pointers to ASF::File. 2017-06-14 09:37:31 +09:00
Tsuda Kageyu
507f1a96a7 Merge branch 'master' into taglib2
# Conflicts:
#	taglib/audioproperties.cpp
2017-06-14 09:15:06 +09:00
Tsuda Kageyu
81945efdff Move deprecated functions setID3v2FrameFactory(). 2017-06-13 09:40:01 +09:00
Tsuda Kageyu
2075d865cd Move deprecated function ByteVector::checksum() to oggpage.cpp.
ByteVector::checksum() was specially designed for Ogg pages.
So it should belong to Ogg rather than ByteVector.
2017-06-13 09:31:30 +09:00
Tsuda Kageyu
89f06af3f7 Remove a deprecated function FileRef::create(). 2017-06-12 17:27:08 +09:00
Tsuda Kageyu
3ae0d4aa90 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/fileref.cpp
#	taglib/fileref.h
#	taglib/mpeg/mpegheader.cpp
#	taglib/tagutils.h
2017-06-12 17:23:44 +09:00
Tsuda Kageyu
7e9f019a49 Remove optional dependencies on Boost.
Standard smart pointers are now common among the latest compilers.
2017-06-09 11:31:22 +09:00
Tsuda Kageyu
10e8866fec Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	ConfigureChecks.cmake
#	taglib/CMakeLists.txt
#	taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp
#	taglib/toolkit/tfilestream.cpp
2017-06-09 11:11:44 +09:00
Tsuda Kageyu
bd4a45b07e Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	ConfigureChecks.cmake
#	taglib/CMakeLists.txt
#	taglib/asf/asfattribute.cpp
#	taglib/it/itproperties.cpp
#	taglib/mod/modproperties.cpp
#	taglib/mpeg/mpegfile.cpp
#	taglib/mpeg/mpegproperties.cpp
#	taglib/ogg/flac/oggflacfile.cpp
#	taglib/s3m/s3mproperties.cpp
#	taglib/tagunion.cpp
#	taglib/toolkit/tfile.cpp
#	taglib/toolkit/trefcounter.h
#	taglib/toolkit/tstring.cpp
#	taglib/xm/xmproperties.cpp
#	tests/test_mpeg.cpp
2017-02-21 10:22:20 +09:00
Tsuda Kageyu
4328f934c8 Merge pull request #781 from claudiuslollarius/taglib2
Fixed incorrect handling of MP4 tags when using wstrings
2017-01-28 22:04:25 +09:00
Tsuda Kageyu
1c20f92a8f Use smart pointers in APE related classes. 2016-12-16 14:42:16 +09:00
Tsuda Kageyu
d8114059ee Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	config.h.cmake
#	taglib/ogg/xiphcomment.cpp
#	taglib/taglib_config.h.cmake
#	taglib/toolkit/tbytevector.cpp
#	taglib/toolkit/trefcounter.cpp
#	taglib/toolkit/tstring.cpp
#	taglib/toolkit/tutils.h
#	taglib/toolkit/tzlib.cpp
#	taglib/xm/xmfile.cpp
#	tests/test_string.cpp
#	tests/test_xiphcomment.cpp
2016-12-13 13:52:35 +09:00
Tsuda Kageyu
eea1a1b200 Allow implicit conversions from const char * or const wchar_t * to FileName in Win32. 2016-12-13 13:32:38 +09:00
Tsuda Kageyu
ef1ae1a8fe Merge pull request #785 from mathbunnyru/add_explicit_keyboard
Add explicit keyword wherever easily possible
2016-12-12 13:56:09 +09:00
mathbunnyru
7eab1bf6df Add explicit keyword wherever easily possible 2016-12-10 15:44:38 +03:00
Alberto Fustinoni
6a2e276767 Formatting 2016-11-28 16:34:01 +09:00
Alberto Fustinoni
e188a39b5c Spacing 2016-11-28 16:33:21 +09:00
Alberto Fustinoni
e77e20597d Nothing in this file requires config.h directives, and it causes compilation to fail when not using one (HAVE_CONFIG_H not set) 2016-11-28 16:30:24 +09:00
Alberto Fustinoni
0b9a2df3ec Fixed incorrect handling of wstring mime types when setting pictures 2016-11-28 16:24:22 +09:00
Tsuda Kageyu
bd5688ae5f Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/mp4/mp4atom.cpp
#	taglib/toolkit/tutils.h
#	tests/test_apetag.cpp
2016-11-09 11:05:53 +09:00
Tsuda Kageyu
13223ad497 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/mp4/mp4atom.cpp
#	taglib/toolkit/tlist.tcc
#	taglib/toolkit/tmap.tcc
#	tests/test_asf.cpp
#	tests/test_ogg.cpp
#	tests/test_oggflac.cpp
#	tests/test_opus.cpp
#	tests/test_speex.cpp
2016-11-04 17:18:59 +09:00
Tsuda Kageyu
5c8cb9b86b Small fix in a comment. 2016-11-03 09:52:20 +09:00
Tsuda Kageyu
3a6f0d46aa Use a smart pointer in TagLib::Picture. 2016-11-01 11:47:37 +09:00
Tsuda Kageyu
ef6d76889b Add a missing copyright header. 2016-11-01 11:13:44 +09:00
Tsuda Kageyu
28470221c0 Suppress MSVC warnings about narrowing conversions. 2016-10-31 01:03:33 +09:00
Tsuda Kageyu
f355110d18 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/toolkit/tbytevector.cpp
#	taglib/toolkit/tfilestream.cpp
#	taglib/toolkit/tiostream.cpp
#	taglib/toolkit/tstring.cpp
2016-10-31 00:37:20 +09:00
Tsuda Kageyu
921a68ae55 Fix mismatched types in tests. 2016-10-30 21:29:06 +09:00
Tsuda Kageyu
d9df59306f Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	AUTHORS
#	ConfigureChecks.cmake
#	taglib/asf/asfutils.h
#	taglib/mp4/mp4atom.cpp
#	taglib/mp4/mp4tag.h
#	taglib/mpeg/id3v2/frames/ownershipframe.cpp
#	taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp
#	taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp
#	taglib/mpeg/id3v2/id3v2frame.cpp
#	taglib/riff/rifffile.cpp
#	taglib/riff/rifffile.h
#	taglib/toolkit/taglib.h
#	taglib/toolkit/tbytevector.cpp
#	taglib/toolkit/tfilestream.cpp
#	taglib/toolkit/tstring.cpp
#	taglib/toolkit/tutils.h
#	taglib/xm/xmfile.cpp
#	tests/test_bytevector.cpp
#	tests/test_fileref.cpp
#	tests/test_id3v2.cpp
#	tests/test_riff.cpp
#	tests/test_string.cpp
2016-10-30 21:20:23 +09:00
Tsuda Kageyu
fea7e3d4a2 Suppress an MSVC warning about 32bit and 64bit shift. 2016-10-28 14:46:48 +09:00
Tsuda Kageyu
b6d21ce890 Remove redundant if blocks from RIFF::File. 2016-10-28 14:42:32 +09:00
Scott Wheeler
51b85abc0b foo 2016-09-14 19:55:55 +03:00
Scott Wheeler
9452970528 No reason to include std::string here 2016-09-14 19:54:16 +03:00
Scott Wheeler
53ac43b5f6 This should be using operator| not operator||
This is bitwise, not logical.
2016-09-14 19:53:46 +03:00
Stephen F. Booth
a64772a832 Merge pull request #748 from supermihi/taglib2
Adds a function for dynamic version information retrieval
2016-08-14 17:10:04 -04:00
Michael Helmling
c352425ee7 Adjust version macros to TagLib naming conventions; use dedicated namespace 2016-07-30 13:47:46 +02:00
Michael Helmling
0f096af504 Extend dynamic version retrieval; remove C++11 dependency 2016-07-28 22:32:44 +02:00
Michael Helmling
a16c95b33f Adds a function for dynamic version information retrieval
The current way of exposing TagLib's version only through #define's
makes it impossible for clients (e.g. language bindings) to reliably
determine the TagLib version that is currently in use: using the
define's in client code will statically copy the compile-time values
into the client's library, but if TagLib is dynamically bound the
version (at least minor and patch version) can change after building
client code.
2016-07-23 13:08:23 +02:00
Scott Wheeler
821ff14a43 Put a to-do note in here to look at before actually releasing this API 2016-04-24 21:54:28 +02:00
Tsuda Kageyu
33c0ece830 Fix type mismatch errors in test_apetag.cpp. 2016-02-04 20:54:43 +09:00
Tsuda Kageyu
57e849b0d5 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/ape/apeitem.cpp
#	taglib/mpeg/mpegheader.cpp
#	taglib/toolkit/tutils.h
2016-02-04 20:48:31 +09:00
Tsuda Kageyu
b972f24193 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/ogg/oggfile.cpp
2016-01-07 09:01:32 +09:00
Tsuda Kageyu
1a73c82a76 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/flac/flacfile.h
#	taglib/mpeg/mpegheader.cpp
#	taglib/mpeg/mpegproperties.cpp
#	taglib/ogg/oggfile.cpp
#	taglib/ogg/oggpage.cpp
#	taglib/ogg/oggpageheader.cpp
#	tests/test_mpeg.cpp
2016-01-06 10:28:09 +09:00
Tsuda Kageyu
c3c862e911 Merge branch 'taglib2' of https://github.com/taglib/taglib into taglib2 2015-12-21 16:17:34 +09:00
Tsuda Kageyu
75159614fc Silence MSVC warnings concerning narrowing conversions. 2015-12-21 15:17:59 +09:00
Tsuda Kageyu
ed0305bd3f Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/ape/apefile.cpp
#	taglib/flac/flacfile.cpp
#	taglib/mpc/mpcfile.cpp
#	taglib/mpeg/mpegfile.cpp
#	taglib/mpeg/mpegfile.h
#	taglib/trueaudio/trueaudiofile.cpp
#	taglib/wavpack/wavpackfile.cpp
2015-12-21 14:56:13 +09:00
Tsuda Kageyu
f72b0ecebf Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	CMakeLists.txt
#	ConfigureChecks.cmake
#	taglib/flac/flacfile.cpp
#	taglib/mp4/mp4file.cpp
#	taglib/mpeg/mpegheader.cpp
#	taglib/mpeg/mpegproperties.cpp
#	taglib/riff/rifffile.cpp
#	taglib/toolkit/trefcounter.h
2015-12-16 13:33:04 +09:00
Tsuda Kageyu
f25a54a177 Merge pull request #696 from FestusHagen/fh1.t2_IntegerConstantTooLargeForLong
Silence error: Integer constant is too large for long type.
2015-12-06 07:12:53 +09:00
Festus Hagen
ff94a6e4a0 Silence error: Integer constant is too large for long type. 2015-12-05 11:41:00 -05:00
Tsuda Kageyu
1f5ed5fb28 Remove custom integer types. 2015-12-03 15:11:09 +09:00
Tsuda Kageyu
0e4f9f4e94 Fix a compilation error caused on the merge. 2015-12-03 14:48:21 +09:00
Tsuda Kageyu
6857926da2 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/ape/apefile.cpp
#	taglib/ape/apeitem.cpp
#	taglib/ape/apeproperties.cpp
#	taglib/ape/apetag.cpp
#	taglib/ape/apetag.h
#	taglib/asf/asffile.cpp
#	taglib/asf/asfpicture.cpp
#	taglib/flac/flacfile.cpp
#	taglib/flac/flacpicture.cpp
#	taglib/flac/flacproperties.cpp
#	taglib/it/itfile.cpp
#	taglib/it/itproperties.cpp
#	taglib/mod/modfile.cpp
#	taglib/mod/modfilebase.cpp
#	taglib/mod/modfilebase.h
#	taglib/mod/modfileprivate.h
#	taglib/mod/modproperties.cpp
#	taglib/mp4/mp4item.cpp
#	taglib/mp4/mp4tag.cpp
#	taglib/mp4/mp4tag.h
#	taglib/mpc/mpcfile.cpp
#	taglib/mpc/mpcproperties.cpp
#	taglib/mpc/mpcproperties.h
#	taglib/mpeg/id3v1/id3v1tag.cpp
#	taglib/mpeg/id3v1/id3v1tag.h
#	taglib/mpeg/id3v2/frames/attachedpictureframe.cpp
#	taglib/mpeg/id3v2/frames/chapterframe.cpp
#	taglib/mpeg/id3v2/frames/eventtimingcodesframe.cpp
#	taglib/mpeg/id3v2/frames/popularimeterframe.cpp
#	taglib/mpeg/id3v2/frames/relativevolumeframe.cpp
#	taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp
#	taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp
#	taglib/mpeg/id3v2/frames/textidentificationframe.cpp
#	taglib/mpeg/id3v2/id3v2frame.cpp
#	taglib/mpeg/id3v2/id3v2framefactory.cpp
#	taglib/mpeg/id3v2/id3v2framefactory.h
#	taglib/mpeg/id3v2/id3v2tag.cpp
#	taglib/mpeg/id3v2/id3v2tag.h
#	taglib/mpeg/mpegfile.cpp
#	taglib/mpeg/mpegheader.cpp
#	taglib/ogg/flac/oggflacfile.cpp
#	taglib/ogg/opus/opusproperties.cpp
#	taglib/ogg/speex/speexproperties.cpp
#	taglib/ogg/vorbis/vorbisproperties.cpp
#	taglib/ogg/xiphcomment.cpp
#	taglib/ogg/xiphcomment.h
#	taglib/riff/aiff/aiffproperties.cpp
#	taglib/riff/rifffile.cpp
#	taglib/riff/rifffile.h
#	taglib/riff/wav/infotag.cpp
#	taglib/riff/wav/infotag.h
#	taglib/riff/wav/wavproperties.cpp
#	taglib/riff/wav/wavproperties.h
#	taglib/s3m/s3mproperties.cpp
#	taglib/tagunion.cpp
#	taglib/tagunion.h
#	taglib/toolkit/taglib.h
#	taglib/toolkit/tbytevector.cpp
#	taglib/toolkit/tbytevector.h
#	taglib/toolkit/tbytevectorlist.cpp
#	taglib/toolkit/tbytevectorstream.cpp
#	taglib/toolkit/tbytevectorstream.h
#	taglib/toolkit/tfile.cpp
#	taglib/toolkit/tfile.h
#	taglib/toolkit/tfilestream.cpp
#	taglib/toolkit/tfilestream.h
#	taglib/toolkit/tiostream.h
#	taglib/toolkit/tlist.h
#	taglib/toolkit/tlist.tcc
#	taglib/toolkit/tmap.h
#	taglib/toolkit/tmap.tcc
#	taglib/toolkit/tstring.cpp
#	taglib/toolkit/tstring.h
#	taglib/trueaudio/trueaudiofile.cpp
#	taglib/trueaudio/trueaudioproperties.cpp
#	taglib/trueaudio/trueaudioproperties.h
#	taglib/wavpack/wavpackfile.cpp
#	taglib/wavpack/wavpackproperties.cpp
#	taglib/wavpack/wavpackproperties.h
#	taglib/xm/xmfile.cpp
#	taglib/xm/xmproperties.cpp
#	tests/test_apetag.cpp
#	tests/test_asf.cpp
#	tests/test_bytevector.cpp
#	tests/test_bytevectorlist.cpp
#	tests/test_file.cpp
#	tests/test_flac.cpp
#	tests/test_flacpicture.cpp
#	tests/test_id3v2.cpp
#	tests/test_info.cpp
#	tests/test_mp4.cpp
#	tests/test_ogg.cpp
#	tests/test_riff.cpp
#	tests/test_string.cpp
#	tests/test_xiphcomment.cpp
2015-12-03 14:44:17 +09:00
Tsuda Kageyu
afa137e1c1 Fix some mistakes on merging. 2015-12-02 09:37:18 +09:00
Tsuda Kageyu
d36550f96d Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/ape/apetag.cpp
#	taglib/ape/apetag.h
#	taglib/flac/flacproperties.cpp
#	taglib/mpeg/id3v1/id3v1tag.cpp
#	taglib/mpeg/id3v2/id3v2tag.cpp
#	taglib/riff/rifffile.cpp
#	taglib/riff/wav/infotag.cpp
#	taglib/toolkit/tbytevector.cpp
2015-12-02 09:31:10 +09:00
Tsuda Kageyu
6f5874a035 Remove the definition of offset_t.
The definition of offset_t has changed over time, and it's just equivalent to long long now.
We no longer have a good reason to keep it.
2015-12-01 22:10:24 +09:00
Tsuda Kageyu
2f29f0e1d0 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	CMakeLists.txt
#	examples/CMakeLists.txt
#	tests/test_asf.cpp
#	tests/test_fileref.cpp
#	tests/test_flac.cpp
#	tests/test_mp4.cpp
#	tests/test_ogg.cpp
#	tests/test_oggflac.cpp
#	tests/test_riff.cpp
2015-11-30 11:25:32 +09:00
Tsuda Kageyu
7baa7e70fe Silence GCC warnings about uninitialized variables. 2015-11-23 23:24:17 +09:00
Tsuda Kageyu
faca7ac8f4 Merge branch 'master' into merge-master-to-talib2
# Conflicts:
#	taglib/asf/asfattribute.cpp
#	taglib/asf/asfpicture.cpp
#	taglib/mp4/mp4coverart.cpp
#	taglib/mp4/mp4item.cpp
#	taglib/mp4/mp4item.h
#	taglib/mpeg/id3v2/id3v2framefactory.cpp
#	taglib/toolkit/tstring.cpp
#	tests/test_string.cpp
2015-11-23 19:04:06 +09:00
Tsuda Kageyu
1063110701 Silence some MSVC warnings about signed/unsigned mismatches. 2015-11-22 17:57:37 +09:00
Tsuda Kageyu
973fb49cde Remove obsolete String::null and related functions. 2015-11-22 17:56:18 +09:00
Tsuda Kageyu
15775d4135 Merge branch 'master' into taglib2 2015-11-22 16:25:34 +09:00
Tsuda Kageyu
52774d66ab Merge pull request #660 from MaxLeb/ASF
ASF: Adds support for pictures
2015-11-22 16:11:05 +09:00
Tsuda Kageyu
b7e3ff8cb5 Merge pull request #659 from MaxLeb/MP4
MP4: Full support of pictures
2015-11-22 16:10:53 +09:00
Tsuda Kageyu
b4a33b0306 Merge pull request #658 from MaxLeb/APE
APE: Adds support for pictures
2015-11-22 16:10:15 +09:00
Tsuda Kageyu
aa9e5c3c2f Merge pull request #657 from MaxLeb/ID3V2
ID3V2: Adds support for pictures
2015-11-22 16:10:05 +09:00
Tsuda Kageyu
0556b6ca33 Merge branch 'Examples' of https://github.com/MaxLeb/taglib into MaxLeb-Examples
# Conflicts:
#	examples/tagwriter.cpp
2015-11-22 16:05:56 +09:00
Tsuda Kageyu
b3014f0878 Merge branch 'pictures' of https://github.com/MaxLeb/taglib into MaxLeb-pictures
# Conflicts:
#	taglib/mpeg/id3v2/id3v2tag.cpp
#	taglib/tagunion.cpp
2015-11-22 15:46:22 +09:00
Tsuda Kageyu
6566352728 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/ape/apefile.cpp
#	taglib/ape/apefile.h
#	taglib/fileref.cpp
#	taglib/flac/flacfile.cpp
#	taglib/flac/flacfile.h
#	taglib/mpc/mpcfile.cpp
#	taglib/mpc/mpcfile.h
#	taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp
#	taglib/mpeg/id3v2/id3v2frame.cpp
#	taglib/tagunion.cpp
#	taglib/toolkit/tiostream.cpp
#	taglib/trueaudio/trueaudiofile.cpp
#	taglib/trueaudio/trueaudiofile.h
#	taglib/wavpack/wavpackfile.cpp
#	taglib/wavpack/wavpackfile.h
#	tests/test_fileref.cpp
#	tests/test_id3v2.cpp
2015-11-21 20:22:07 +09:00
Tsuda Kageyu
1d0552cab1 Change String::npos from a variable to a function.
We can't export a static member function. It may lead to a linkage error.
2015-11-20 16:46:02 +09:00
Tsuda Kageyu
bb49005267 Fix a mismatch between the CMake check and the actual code. 2015-11-20 15:28:38 +09:00
Tsuda Kageyu
47cb23d738 Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	taglib/ape/apefile.cpp
#	taglib/asf/asffile.cpp
#	taglib/asf/asftag.cpp
#	taglib/flac/flacfile.cpp
#	taglib/mp4/mp4tag.cpp
#	taglib/mpc/mpcfile.cpp
#	taglib/mpeg/mpegfile.cpp
#	taglib/mpeg/mpegfile.h
#	taglib/riff/wav/wavfile.cpp
#	taglib/tagunion.cpp
#	taglib/tagunion.h
#	taglib/trueaudio/trueaudiofile.cpp
#	taglib/wavpack/wavpackfile.cpp
2015-11-20 15:17:39 +09:00
Tsuda Kageyu
d37c081cda Fix compilation errors on Clang. 2015-11-19 14:20:51 +09:00
Tsuda Kageyu
dbe3a03b62 Hide string handler implementations from public headers. 2015-11-19 14:08:40 +09:00
Tsuda Kageyu
5da35f5a51 Rename RIFF::Info::FieldListMap to FieldMap.
It doesn't contain string lists.
2015-11-19 13:47:41 +09:00
Tsuda Kageyu
176e133f32 Change ByteVector::npos from a variable to a function.
We can't export a static member function. It may lead to a likage error.
2015-11-19 13:13:15 +09:00
Tsuda Kageyu
722f317f97 Remove ByteVector::null and isNull(). 2015-11-19 11:57:30 +09:00
Tsuda Kageyu
c2753f8d3c Merge branch 'master' into merge-master-to-taglib2
# Conflicts:
#	ConfigureChecks.cmake
#	bindings/c/tag_c.cpp
#	taglib-config.cmd.cmake
#	taglib/asf/asfattribute.cpp
#	taglib/asf/asffile.cpp
#	taglib/audioproperties.cpp
#	taglib/mp4/mp4atom.h
#	taglib/mp4/mp4coverart.cpp
#	taglib/mp4/mp4file.cpp
#	taglib/mp4/mp4item.cpp
#	taglib/mp4/mp4tag.cpp
#	taglib/mpeg/id3v2/id3v2frame.cpp
#	taglib/mpeg/id3v2/id3v2tag.cpp
#	taglib/toolkit/tbytevector.cpp
#	taglib/toolkit/tbytevector.h
#	taglib/toolkit/tfile.cpp
#	taglib/toolkit/tfile.h
#	taglib/toolkit/tlist.h
#	taglib/toolkit/tstring.cpp
#	taglib/toolkit/tstring.h
#	tests/test_apetag.cpp
2015-11-19 11:37:18 +09:00
Tsuda Kageyu
da7424636b Fix a mismatch between List and iterator types. 2015-11-18 17:50:48 +09:00
Tsuda Kageyu
0b2a3ce400 Remove const from the key type of APE::ItemListMap.
A key type must be copy-assignable, and some compilers check it strictly.
2015-11-18 17:27:25 +09:00
Tsuda Kageyu
1ff30e55da Revert "Stop exporting std::string and std::wstring in a public header."
This reverts commit 0e981adcc6.
2015-09-11 19:59:20 +09:00
Tsuda Kageyu
0e981adcc6 Stop exporting std::string and std::wstring in a public header. 2015-09-11 09:14:22 +09:00
Maxime Leblanc
a18d402bd9 asftag.cpp: run astyle on added parts 2015-09-09 10:32:31 +02:00
Maxime Leblanc
dc994a65f0 ASF: full picture handling 2015-09-09 10:31:24 +02:00
Maxime Leblanc
4998dedcf4 mp4tag.cpp: run astyle on added parts 2015-09-09 10:31:08 +02:00
Maxime Leblanc
794d9fd27b MP4: full picture handling 2015-09-09 10:27:03 +02:00
Maxime Leblanc
35cf4afdba apetag.cpp: run astyle 2015-09-09 10:26:26 +02:00
Maxime Leblanc
8ecfba0c30 APE: full picture handling 2015-09-09 10:24:37 +02:00
Maxime Leblanc
ace203a6e9 id3v2tag: run astyle on added parts 2015-09-09 10:23:53 +02:00
Maxime Leblanc
ccb1d036f2 ID3v2: full picture handling 2015-09-09 10:21:15 +02:00
Maxime Leblanc
6dbc340899 Examples: adds picture handling 2015-09-09 10:20:03 +02:00
Maxime Leblanc
34931b1d3f tpicture.h,tpicturemap.h: updates comments 2015-09-09 10:18:17 +02:00
Maxime Leblanc
612c84731c tpicture: use accessors by values instead of const ref 2015-09-09 10:15:31 +02:00
Maxime Leblanc
9e95156319 tpicture: use d as for private ptr 2015-09-09 09:58:42 +02:00
Maxime Leblanc
7ed8763a33 tpicture.h,tpicturemap.h: change copyright 2015-09-09 09:58:40 +02:00
Maxime Leblanc
3ea69ed165 tpicture*: run astyle 2015-09-09 09:43:22 +02:00
Maxime Leblanc
71e8915568 Fix #94: add a unified interface for pictures 2015-09-07 14:56:49 +02:00
Tsuda Kageyu
9b8f774fb3 Merge branch 'master' into merge-master-to-taglib2
Conflicts:
	taglib/ape/apetag.cpp
	taglib/ape/apetag.h
	taglib/mpeg/id3v2/frames/chapterframe.cpp
	taglib/riff/wav/infotag.h
2015-08-25 02:41:49 +09:00
Tsuda Kageyu
30551864fa Fix debug messages in AudioProperties classes. 2015-08-10 12:00:23 +09:00
Tsuda Kageyu
ba2167ef92 RefCounter should not be copyable. 2015-08-10 11:31:35 +09:00
Tsuda Kageyu
dc0cc4e7fa Implement 'Length in milliseconds' feature of DSF/EBML. 2015-08-10 01:35:57 +09:00
Tsuda Kageyu
ef09a707b8 Make AudioProperties::lengthInSeconds() and lengthInMilliseconds() virtual. 2015-08-10 01:10:35 +09:00
Tsuda Kageyu
400fa04b1c Remove deprecated constructors from AudioProperties classes. 2015-08-10 01:01:09 +09:00
Tsuda Kageyu
e6e11c957d Merge branch 'master' into taglib2
Conflicts:
	CMakeLists.txt
	ConfigureChecks.cmake
	config.h.cmake
	taglib/CMakeLists.txt
	taglib/ape/apefile.cpp
	taglib/ape/apefile.h
	taglib/ape/apeproperties.cpp
	taglib/ape/apeproperties.h
	taglib/ape/apetag.cpp
	taglib/asf/asfattribute.cpp
	taglib/asf/asffile.cpp
	taglib/asf/asffile.h
	taglib/asf/asfpicture.cpp
	taglib/asf/asfpicture.h
	taglib/asf/asfproperties.cpp
	taglib/asf/asfproperties.h
	taglib/audioproperties.cpp
	taglib/flac/flacfile.cpp
	taglib/flac/flacfile.h
	taglib/flac/flacproperties.cpp
	taglib/flac/flacproperties.h
	taglib/it/itproperties.cpp
	taglib/mod/modproperties.cpp
	taglib/mp4/mp4atom.cpp
	taglib/mp4/mp4file.cpp
	taglib/mp4/mp4file.h
	taglib/mp4/mp4properties.cpp
	taglib/mp4/mp4tag.cpp
	taglib/mp4/mp4tag.h
	taglib/mpc/mpcfile.cpp
	taglib/mpc/mpcfile.h
	taglib/mpc/mpcproperties.cpp
	taglib/mpc/mpcproperties.h
	taglib/mpeg/id3v2/frames/chapterframe.cpp
	taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp
	taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp
	taglib/mpeg/mpegfile.cpp
	taglib/mpeg/mpegfile.h
	taglib/mpeg/mpegheader.cpp
	taglib/mpeg/mpegproperties.cpp
	taglib/mpeg/mpegproperties.h
	taglib/mpeg/xingheader.cpp
	taglib/mpeg/xingheader.h
	taglib/ogg/opus/opusfile.cpp
	taglib/ogg/opus/opusfile.h
	taglib/ogg/opus/opusproperties.cpp
	taglib/ogg/opus/opusproperties.h
	taglib/ogg/speex/speexfile.cpp
	taglib/ogg/speex/speexfile.h
	taglib/ogg/speex/speexproperties.cpp
	taglib/ogg/speex/speexproperties.h
	taglib/ogg/vorbis/vorbisfile.cpp
	taglib/ogg/vorbis/vorbisfile.h
	taglib/ogg/vorbis/vorbisproperties.cpp
	taglib/ogg/vorbis/vorbisproperties.h
	taglib/riff/aiff/aifffile.cpp
	taglib/riff/aiff/aifffile.h
	taglib/riff/aiff/aiffproperties.cpp
	taglib/riff/aiff/aiffproperties.h
	taglib/riff/wav/infotag.h
	taglib/riff/wav/wavfile.cpp
	taglib/riff/wav/wavfile.h
	taglib/riff/wav/wavproperties.cpp
	taglib/riff/wav/wavproperties.h
	taglib/s3m/s3mproperties.cpp
	taglib/taglib_config.h.cmake
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tfile.cpp
	taglib/toolkit/tfile.h
	taglib/toolkit/tfilestream.cpp
	taglib/toolkit/trefcounter.cpp
	taglib/toolkit/tstring.cpp
	taglib/toolkit/tstring.h
	taglib/toolkit/tutils.h
	taglib/trueaudio/trueaudiofile.cpp
	taglib/trueaudio/trueaudiofile.h
	taglib/trueaudio/trueaudioproperties.cpp
	taglib/trueaudio/trueaudioproperties.h
	taglib/wavpack/wavpackfile.cpp
	taglib/wavpack/wavpackfile.h
	taglib/wavpack/wavpackproperties.cpp
	taglib/wavpack/wavpackproperties.h
	taglib/xm/xmproperties.cpp
	taglib/xm/xmproperties.h
	tests/CMakeLists.txt
	tests/data/alaw.wav
	tests/test_asf.cpp
	tests/test_mp4.cpp
	tests/test_ogg.cpp
	tests/test_opus.cpp
	tests/test_string.cpp
	tests/test_wav.cpp
	tests/test_wavpack.cpp
2015-08-10 00:40:22 +09:00
Lukáš Lalinský
ab2389819e Merge pull request #507 from TsudaKageyu/merge-master-to-taglib2
Merge master to taglib2
2015-05-15 19:46:52 -07:00
Tsuda Kageyu
8e35b43e32 Merge branch 'master' into merge-master-to-taglib2
Conflicts:
	ConfigureChecks.cmake
	config.h.cmake
	taglib/CMakeLists.txt
	taglib/ape/apeproperties.cpp
	taglib/fileref.cpp
	taglib/mp4/mp4atom.cpp
	taglib/mpc/mpcproperties.cpp
	taglib/mpeg/id3v2/frames/chapterframe.cpp
	taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp
	taglib/mpeg/id3v2/id3v2frame.cpp
	taglib/mpeg/id3v2/id3v2framefactory.cpp
	taglib/mpeg/id3v2/id3v2tag.cpp
	taglib/mpeg/mpegfile.cpp
	taglib/mpeg/mpegfile.h
	taglib/riff/aiff/aifffile.cpp
	taglib/riff/aiff/aiffproperties.cpp
	taglib/riff/aiff/aiffproperties.h
	taglib/riff/wav/infotag.cpp
	taglib/riff/wav/wavfile.cpp
	taglib/riff/wav/wavproperties.cpp
	taglib/toolkit/tdebug.cpp
	taglib/toolkit/tstring.cpp
	taglib/toolkit/tutils.h
	tests/test_aiff.cpp
	tests/test_id3v2.cpp
	tests/test_wav.cpp
2015-02-18 10:07:08 +09:00
Scott Wheeler
b85a0d0710 Rebuild TRDC from v2.3 fields
This fixes an issue that was reported to me via email with the recording
date being thrown away from v2.3 tags.
2014-09-25 23:14:46 +02:00
Scott Wheeler
87040570c0 Remove deprecated (and now internally unused) createFrame declarations
This also finally marks this method as virtual, which has been a long standing
bug in TagLib 1
2014-09-25 20:48:30 +02:00
Scott Wheeler
e1b5e2c9c3 Don't leak 2014-09-25 20:45:45 +02:00
Scott Wheeler
51449f131f Missing assignment 2014-09-25 20:41:19 +02:00
Scott Wheeler
c4c4a28daa TableOfContents and ChapterFrame can be added to v2.3 or v2.4 tags 2014-09-25 19:54:57 +02:00
Scott Wheeler
d52baafa24 ByteVector::size is a size_t in taglib2 2014-09-25 19:54:57 +02:00
Scott Wheeler
bdfd7dc003 Seems to have been wrong in the merge 2014-09-25 16:44:08 +02:00
Scott Wheeler
0884945567 Merge branch 'master' into taglib2
Conflicts:
	tests/test_aiff.cpp
	tests/test_flac.cpp
2014-09-25 16:39:26 +02:00
Lukáš Lalinský
93c2758ca6 Merge pull request #432 from TsudaKageyu/lfs-check
Define only least required macros for LFS in config.h.
2014-08-22 19:26:35 +02:00
Tsuda Kageyu
2ec7a884c3 Define only least required macros for LFS in config.h. 2014-08-23 01:28:27 +09:00
Lukáš Lalinský
a5c56d31ac Merge pull request #431 from TsudaKageyu/merge-master-to-taglib2
Merge master to taglib2
2014-08-22 09:49:06 +02:00
Tsuda Kageyu
f0e8f39de1 Merge branch 'master' into merge-master-to-taglib2
Conflicts:
	ConfigureChecks.cmake
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tstring.cpp
	taglib/xm/xmfile.cpp
	tests/test_wav.cpp
2014-08-22 13:54:02 +09:00
Lukáš Lalinský
efcd751a1c Merge pull request #412 from TsudaKageyu/largefile-ifdefs
Removed some useless #ifdefs. _LARGEFILE_SOURCE is always defined.
2014-08-04 10:16:54 +02:00
Tsuda Kageyu
34f5a7da0d Removed some useless #ifdefs. _LARGEFILE_SOURCE is always defined. 2014-08-04 14:09:08 +09:00
Lukáš Lalinský
7345b7569f Merge pull request #407 from TsudaKageyu/merge-master-to-taglib2
Merge master to taglib2
2014-07-24 10:27:18 +02:00
Tsuda Kageyu
f93397fa7b Merge branch 'master' into merge-master-to-taglib2
Conflicts:
	ConfigureChecks.cmake
	taglib/CMakeLists.txt
	taglib/riff/aiff/aiffproperties.cpp
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tbytevector.h
	taglib/toolkit/tfilestream.cpp
	taglib/toolkit/tstring.cpp
	taglib/toolkit/tutils.h
	tests/test_apetag.cpp
	tests/test_bytevector.cpp
	tests/test_flac.cpp
	tests/test_id3v2.cpp
	tests/test_propertymap.cpp
2014-07-24 09:39:08 +09:00
Tsuda Kageyu
81f806317f Merge branch 'master' of https://github.com/taglib/taglib 2014-07-23 17:24:43 +09:00
Tsuda Kageyu
8e6e580c60 Fixed handling UTF-16 byte order. 2014-07-23 15:35:49 +09:00
Lukáš Lalinský
909d28d4fe Merge pull request #379 from TsudaKageyu/sizecheck
Robuster size checking for floating point types.
2014-07-16 17:18:43 +02:00
Lukáš Lalinský
6be3b7a1c7 Merge pull request #383 from TsudaKageyu/redundant-smartptr2
Removed some redundant code from tsmartptr.h.
2014-07-16 16:04:11 +02:00
Stephen F. Booth
29d5f75d0d Merge pull request #388 from TsudaKageyu/stringlist-export
operator<< of StringList lacks TAGLIB_EXPORT.
2014-06-16 21:25:37 -04:00
Tsuda Kageyu
8936fb2fc3 operator<< of StringList lacks TAGLIB_EXPORT. 2014-06-16 15:21:01 +09:00
Tsuda Kageyu
1dc2471d01 Removed some redundant code from tsmartptr.h. 2014-04-13 15:02:17 +09:00
Stephen F. Booth
5687c70d80 Merge pull request #382 from TsudaKageyu/no-tdebug
tdebug.h should not be included in a public header.
2014-04-11 17:38:48 -04:00
Tsuda Kageyu
3f19a522fc tdebug.h should not be included in a public header. 2014-04-12 01:28:20 +09:00
Lukáš Lalinský
3cea7f267a Merge pull request #381 from TsudaKageyu/merge-master-to-taglib2
Merged master into taglib2.
2014-04-11 13:01:57 +02:00
Tsuda Kageyu
1a9c49e42b Merge branch 'master' into merge-master-to-taglib2
Conflicts:
	taglib/asf/asftag.cpp
	taglib/mp4/mp4tag.cpp
	taglib/toolkit/tstring.h
2014-04-11 18:31:49 +09:00
Tsuda Kageyu
76c688bffd Robuster size checking for floating point types. 2014-04-11 11:27:43 +09:00
Lukáš Lalinský
fbbebfcec6 Merge pull request #376 from TsudaKageyu/test-float80
Added a missing test for ByteVector::toFloat80().
2014-04-10 20:10:39 +02:00
Lukáš Lalinský
7f20c95cfc Merge pull request #374 from TsudaKageyu/redundant-smartptr
Removed some redundant code from tsmartptr.h.
2014-04-10 20:10:19 +02:00
Lukáš Lalinský
98c6088f91 Merge pull request #363 from TsudaKageyu/string-std-func
Simplified some functions in tstring.cpp by replacing with standard func...
2014-04-10 20:09:45 +02:00
Lukáš Lalinský
22f8b527f7 Merge pull request #373 from TsudaKageyu/snprintf-spelling
Fixed some misspellings.
2014-04-10 20:04:37 +02:00
Tsuda Kageyu
65beb8cc06 Fixed a wrong conversion in ByteVector::toFloat64BE(). 2014-04-09 14:46:42 +09:00
Tsuda Kageyu
c94d482215 Added a missing test for ByteVector::toFloat80(). 2014-04-09 14:46:42 +09:00
Tsuda Kageyu
d05101153f Fixed some misspellings. 2014-04-07 16:09:12 +09:00
Tsuda Kageyu
bceb568ea8 Removed some redundant code from tsmartptr.h. 2014-04-07 16:05:35 +09:00
Lukáš Lalinský
8390a91e48 Merge pull request #366 from TsudaKageyu/missing-ifdef
Added missing #ifdef HAVE_CONFIG_H
2014-04-04 09:37:55 +02:00
Lukáš Lalinský
4dca1ab68c Merge pull request #369 from TsudaKageyu/remove-switches
Removed some CMake switches which are no longer used.
2014-04-04 09:37:33 +02:00
Lukáš Lalinský
3ced5e92b7 Merge pull request #368 from TsudaKageyu/remove-shlwapi
Removed an unnecessary dependency on shlwapi.lib.
2014-04-04 09:37:20 +02:00
Tsuda Kageyu
dce1664f30 Removed some CMake switches which are no longer used. 2014-04-04 01:12:47 +09:00
Tsuda Kageyu
a303d88782 Removed an unnecessary dependency on shlwapi.lib. 2014-04-04 00:56:27 +09:00
Tsuda Kageyu
8b77051ecf Added missing #ifdef HAVE_CONFIG_H 2014-04-02 22:25:56 +09:00
Lukáš Lalinský
329abdbce7 Merge pull request #365 from TsudaKageyu/remove-cmake-float
Removed some unnecessary CMake checks for the size of numeric types.
2014-04-02 09:36:12 +02:00
Tsuda Kageyu
d3eefdde34 Removed some unnecessary CMake checks for the size of numeric types. 2014-04-02 14:03:35 +09:00
Tsuda Kageyu
c5353ed5ef Added UTF-8 check when constructing a String from a char. 2014-04-02 01:45:23 +09:00
Tsuda Kageyu
5199a3cbb6 Simplified some functions in tstring.cpp by replacing with standard functions. 2014-04-01 18:03:19 +09:00
Lukáš Lalinský
d93b4af8ca Merge pull request #326 from TsudaKageyu/msvc-dsf
Fixed some MSVC warnings in DSF related classes
2014-03-10 07:25:17 +01:00
Lukáš Lalinský
dd1a885f27 Merge pull request #355 from TsudaKageyu/merge-master-to-taglib2
Merge master to taglib2
2014-03-10 07:23:48 +01:00
Tsuda Kageyu
50b55a8a94 Merge branch 'master' into merge-master-to-taglib2
Conflicts:
	taglib/ogg/opus/opusproperties.cpp
2014-03-10 11:42:05 +09:00
Lukáš Lalinský
5d519c5207 Merge pull request #350 from TsudaKageyu/merge-master-to-taglib2
Merge master to taglib2
2014-02-18 10:27:45 +01:00
Tsuda Kageyu
bd84c8928a Merge branch 'master' into merge-master-to-taglib2
Conflicts:
	taglib/riff/wav/infotag.cpp
	taglib/toolkit/trefcounter.h
	taglib/toolkit/tstring.cpp
	taglib/toolkit/tstring.h
	taglib/xm/xmfile.cpp
	tests/test_string.cpp
2014-02-18 17:32:05 +09:00
Tsuda Kageyu
279d71c1e8 Fixed some MSVC warnings in DSF related classes 2013-12-02 23:57:24 +09:00
Stephen F. Booth
d8f5937091 Merge pull request #288 from sbooth/dsf
Added DSF support
2013-12-02 05:09:26 -08:00
Stephen F. Booth
be041ef2aa Another fix for tag stripping 2013-11-29 14:54:15 -05:00
Stephen F. Booth
d643878e9f Update internal state after saving 2013-11-29 13:38:54 -05:00
Stephen F. Booth
0c2e21024f Correctly write the metadata offset in absence of ID3v2 tag 2013-11-29 13:36:57 -05:00
Stephen F. Booth
dad73ebfc5 Strip tag if empty 2013-11-29 10:50:58 -05:00
Stephen F. Booth
37b0ba6989 Merge pull request #323 from TsudaKageyu/ifdefs
Removed some unused #ifdefs
2013-11-29 05:33:13 -08:00
Stephen F. Booth
733b537c63 Read properties more efficiently 2013-11-29 08:27:48 -05:00
Stephen F. Booth
caf705958e Validate the tag's version of file length against the actual length 2013-11-29 08:24:22 -05:00
Stephen F. Booth
ebaecc47f4 Correctly read all 8 bytes for the metadata offset 2013-11-29 08:21:23 -05:00
Stephen F. Booth
69bcc52ef3 Invalidate the file when necessary 2013-11-29 08:18:59 -05:00
Tsuda Kageyu
644b47910f Removed some unused #ifdefs 2013-11-28 14:09:16 +09:00
Stephen F. Booth
97b0f9e5a5 Merge branch 'taglib2' of github.com:taglib/taglib into dsf 2013-11-19 11:47:51 -05:00
Stephen F. Booth
3cdbdfe0b9 Merge pull request #315 from TsudaKageyu/string-redundant
Removed some redundant code from String::operator==()
2013-11-16 04:50:07 -08:00
Stephen F. Booth
7ff61ff5ac Merge pull request #317 from TsudaKageyu/comment
Amended some trivial mistakes in some comments
2013-11-16 04:46:16 -08:00
Tsuda Kageyu
f7d2935d7b Amended some trivial mistakes in some comments 2013-11-16 19:16:13 +09:00
Tsuda Kageyu
8a22c7ce75 Removed some redundant code from String::operator==() 2013-11-16 11:07:20 +09:00
Stephen F. Booth
6dc1ce7fe7 Merge pull request #314 from TsudaKageyu/backslash2
Replaced a wrongly used slash with a backslash
2013-11-15 18:03:25 -08:00
Stephen F. Booth
28cede5965 Merge pull request #313 from TsudaKageyu/merge-master-to-taglib2
Merge master to taglib2
2013-11-15 17:56:23 -08:00
Tsuda Kageyu
634d2ede3b Replaced a wrongly used slash with a backslash 2013-11-16 10:27:23 +09:00
Tsuda Kageyu
753c63e0e6 Merge branch 'master' into merge-master-to-taglib2
Conflicts:
	taglib/mp4/mp4properties.cpp
	taglib/mp4/mp4properties.h
	taglib/mpeg/id3v2/id3v2frame.cpp
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tlist.tcc
	taglib/toolkit/tmap.tcc
	taglib/toolkit/tstring.h
	taglib/wavpack/wavpackproperties.cpp
	tests/test_mp4.cpp
2013-11-16 09:38:38 +09:00
Stephen F. Booth
637a08b8b0 Merge pull request #279 from TsudaKageyu/aifc-msg
Suppressed a useless debug message in aiffproperties.cpp
2013-11-15 15:07:13 -08:00
Stephen F. Booth
0d45ddaf25 Merge pull request #312 from TsudaKageyu/string-format
Unified the string formatting functions
2013-11-15 13:19:31 -08:00
Stephen F. Booth
499d503aa2 Merge pull request #311 from TsudaKageyu/string-default-param
Fixed a wrong default parameter of String::ctor()
2013-11-15 03:55:51 -08:00
Tsuda Kageyu
116b1fcff9 Unified the string formatting functions 2013-11-15 16:34:40 +09:00
Tsuda Kageyu
85e1ef1fba Amended some comments about the Type parameters of String::ctor() 2013-11-15 15:25:18 +09:00
Tsuda Kageyu
88d55057fc Fixed a wrong default parameter of String::ctor() 2013-11-15 15:19:20 +09:00
Stephen F. Booth
cd540cbee2 Merge pull request #305 from TsudaKageyu/fix-string-upper
String::upper() no longer modifies the String itself
2013-10-30 19:45:54 -07:00
Tsuda Kageyu
0acdd2379e Added a test for String::upper() 2013-10-30 22:40:21 +09:00
Tsuda Kageyu
ced5f262ba String::upper() no longer modifies the String itself 2013-10-30 19:37:44 +09:00
Stephen F. Booth
e5c2232b10 Added tag setting test 2013-10-05 14:03:19 -04:00
Stephen F. Booth
8fc110dfd0 Added some basic tests for DSF 2013-10-05 13:59:59 -04:00
Stephen F. Booth
b949e23be3 Rename DSF::Properties to DSF::AudioProperties 2013-10-05 13:58:14 -04:00
Stephen F. Booth
43240b8ecc Fixed a comment 2013-10-05 13:51:39 -04:00
Stephen F. Booth
c09ea21ae3 Correctly handle files with no ID3v2 tag 2013-10-05 09:58:14 -04:00
Stephen F. Booth
57d12de7dd Merge pull request #281 from TsudaKageyu/tdebugh
Removed #include "tdebug.h" from a public header
2013-09-28 18:04:20 -07:00
Stephen F. Booth
0d1ed55c7e Merge pull request #278 from TsudaKageyu/riff-redundant
Removed some redundant code about checking chunk names of RIFF files
2013-09-28 17:47:53 -07:00
Stephen F. Booth
e7cfbfed76 Added DSF support 2013-09-23 21:02:30 -04:00
Tsuda Kageyu
c63dcdc459 Removed #include "tdebug.h" from a public header 2013-09-17 23:03:57 +09:00
Tsuda Kageyu
b7ffa04f20 Simplified the check for AIFF-C format 2013-09-16 21:54:12 +09:00
Tsuda Kageyu
fde99fa2fb Suppressed a useless debug message in aiffproperties.cpp 2013-09-16 04:56:33 +09:00
Tsuda Kageyu
5c9360afa2 Removed some redundant code about checking chunk names of RIFF files 2013-09-13 23:07:30 +09:00
Tsuda Kageyu
60590c0a1a Fixed a bug in appending strings and added some relevant tests 2013-09-08 14:41:35 +09:00
Lukáš Lalinský
70e58dcb21 Merge remote-tracking branch 'TsudaKageyu/taglib-config' into taglib2 2013-09-07 15:42:54 +02:00
Tsuda Kageyu
47561d8350 Unified two equivalent enums 'Endianness' and 'ByteOrder'. 2013-09-07 13:37:35 +09:00
Tsuda Kageyu
829f460c3c Merge branch 'master' into merge-master
Conflicts:
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tstring.cpp
2013-09-07 13:06:24 +09:00
Lukáš Lalinský
bb622bc163 Merge remote-tracking branch 'TsudaKageyu/forward-decl' into taglib2 2013-09-06 20:37:05 +02:00
Lukáš Lalinský
e17b8e14de Merge remote-tracking branch 'Rachus/taglib2' into taglib2 2013-09-06 20:36:29 +02:00
Sebastian Rachuj
f6c23ac92c Probable fix for http://mail.kde.org/pipermail/taglib-devel/2013-July/002516.html 2013-07-28 10:33:25 +02:00
Tsuda Kageyu
dbb4b47be3 Added a missing delete to MPEG::Header 2013-07-25 05:54:29 +09:00
Tsuda Kageyu
9f9af997ee Removed an unnecessary forward declaration 2013-07-24 15:31:27 +09:00
Tsuda Kageyu
314cc33585 Removed taglib_config.h which is no longer used 2013-07-17 18:04:02 +09:00
Tsuda Kageyu
6d40cbc04f Refactored AudioProperties classes in some ways 2013-07-13 10:38:52 +09:00
Lukáš Lalinský
6d89689c0e Fix broken merge 2013-07-11 10:23:01 +02:00
Lukáš Lalinský
48191904f1 Merge branch 'master' into taglib2
Conflicts:
	taglib/ogg/opus/opusfile.cpp
	taglib/riff/wav/wavfile.cpp
	taglib/toolkit/tstring.h
2013-07-11 10:14:09 +02:00
Tsuda Kageyu
45e8e83041 Fixed a wrong integer type 2013-06-24 21:07:33 +09:00
Lukáš Lalinský
c066ccd32d Merge branch 'master' into taglib2
Conflicts:
	taglib/toolkit/tiostream.cpp
2013-06-21 08:04:00 +02:00
Tsuda Kageyu
90d43956ec Fixed a wrong integer type 2013-06-21 11:31:51 +09:00
Tsuda Kageyu
09b574a19a Added a missing #include to fix a MSVC warning 2013-06-21 03:08:21 +09:00
Tsuda Kageyu
8be47ec8dc Fixed compilation errors in Win32 2013-06-21 01:45:53 +09:00
Lukáš Lalinský
2316a9661a Merge branch 'master' into taglib2
Conflicts:
	bindings/c/tag_c.cpp
	taglib/fileref.cpp
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tstring.cpp
2013-06-20 15:38:08 +02:00
Lukáš Lalinský
2c770600c4 Merge branch 'master' into taglib2
Conflicts:
	taglib/asf/asffile.h
	taglib/fileref.cpp
	taglib/flac/flacfile.h
	taglib/mp4/mp4file.h
	taglib/taglib_config.h.cmake
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tfile.cpp
	taglib/toolkit/tfilestream.cpp
	taglib/toolkit/tiostream.h
	tests/test_flac.cpp
2013-06-20 14:44:52 +02:00
Lukáš Lalinský
d3920f4ab6 Merge remote-tracking branch 'TsudaKageyu/vc-warnings2' into taglib2 2013-06-20 14:00:24 +02:00
Tsuda Kageyu
c9904354f9 Prevent string conversion buffer to stay in memory 2013-06-11 12:51:26 +09:00
Tsuda Kageyu
804f882e38 Uses ISO _strdup() instead of POSIX strdup() if possible 2013-06-11 12:06:29 +09:00
Tsuda Kageyu
c6f323357f Fixed some MSVC specific warnings 2013-06-10 12:49:02 +09:00
Tsuda Kageyu
25590fe70c Merge pull request #214 from TsudaKageyu/removeptr
Removed smart pointers from public headers
2013-06-01 08:05:48 -07:00
Tsuda Kageyu
5f5c670f31 Merge pull request #216 from TsudaKageyu/merge-master
Merge branch 'master' into taglib2
2013-05-23 03:13:52 -07:00
Tsuda Kageyu
8fcc992815 Merge branch 'master' into merge-master
Conflicts:
	taglib/toolkit/tfile.cpp
	taglib/toolkit/tfilestream.cpp
2013-05-23 18:36:29 +09:00
Tsuda Kageyu
7c64b1966a Removed smart pointers from public headers 2013-05-23 10:23:33 +09:00
Tsuda Kageyu
6e335694c9 Merge pull request #208 from Rachus/taglib2
A few Matroska testcases and an issue
2013-05-21 03:35:17 -07:00
Sebastian Rachuj
4be506fae2 Corrected indentation 2013-05-21 12:03:43 +02:00
Sebastian Rachuj
6bf8177796 Completed testcases and fixed some bugs, that were found because of the them 2013-05-21 11:58:03 +02:00
Tsuda Kageyu
409bba5936 Merge pull request #212 from TsudaKageyu/list
Interface change of List::find() and contains()
2013-05-20 21:01:31 -07:00
Tsuda Kageyu
ea6ab84c42 Interface change of List::find() and contains() 2013-05-21 12:45:35 +09:00
Tsuda Kageyu
d982b846c4 Merge pull request #211 from TsudaKageyu/tagunion
RIFF::WAV::Tag() returns TagUnion
2013-05-20 20:29:43 -07:00
Tsuda Kageyu
1f08a8d7c6 RIFF::WAV::Tag() returns TagUnion 2013-05-21 12:17:19 +09:00
Sebastian Rachuj
c972b0c080 Merge remote-tracking branch 'correct/taglib2' into taglib2 2013-05-21 00:27:06 +02:00
Tsuda Kageyu
a30f992106 Merge pull request #210 from TsudaKageyu/merge-master
Merge branch 'master' into taglib2
2013-05-20 14:18:57 -07:00
Tsuda Kageyu
e2a168af7a Merge branch 'master' into merge-master
Conflicts:
	taglib/toolkit/tbytevector.cpp
2013-05-21 06:08:13 +09:00
Sebastian Rachuj
8f31d882b0 Added a few testcases 2013-05-20 20:44:12 +02:00
Tsuda Kageyu
a23d41c509 Merge pull request #207 from TsudaKageyu/anonymous
Moved somethings from global to anonymous namespace.
2013-05-19 07:10:45 -07:00
Tsuda Kageyu
ca48435ab6 Moved somethings from global to anonymous namespace. 2013-05-19 23:03:15 +09:00
Tsuda Kageyu
0a4756b527 Merge pull request #206 from TsudaKageyu/smartptrfile
Rewrote File, FileRef and FileStream to use smart pointers
2013-05-19 06:17:19 -07:00
Tsuda Kageyu
437b61a311 Rewrote File, FileRef and FileStream to use smart pointers 2013-05-19 21:56:05 +09:00
Tsuda Kageyu
6c2f99c89a Merge pull request #205 from TsudaKageyu/merge-master
Merge master into TagLib2
2013-05-19 00:04:49 -07:00
Tsuda Kageyu
2b5fee2df1 Merge branch 'master' into merge-master
Conflicts:
	AUTHORS
	ConfigureChecks.cmake
	config.h.cmake
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tfilestream.cpp
	taglib/toolkit/tstring.cpp
	tests/test_id3v2.cpp
2013-05-19 15:45:15 +09:00
Tsuda Kageyu
dd7758c76e Merge pull request #200 from TsudaKageyu/smartptr
Redefined smart pointer classes in safer way
2013-05-17 22:10:00 -07:00
Tsuda Kageyu
5ed8d12478 Redefined smart pointer classes in safer way 2013-05-18 14:03:45 +09:00
Sebastian Rachuj
09e7df8509 Added return for find 2013-05-15 16:54:31 +02:00
Sebastian Rachuj
befa5724f1 Removed unnecessary casts in EBML::Element 2013-05-15 16:51:54 +02:00
Tsuda Kageyu
23418c25a4 Merge pull request #195 from TsudaKageyu/fix-float
Fixed GCC warnings about incompatible type conversions
2013-05-07 08:34:35 -07:00
Tsuda Kageyu
f07bf28f5f Fixed GCC warnings about incompatible type conversions 2013-05-08 00:27:36 +09:00
Tsuda Kageyu
2bdded5597 Merge pull request #193 from TsudaKageyu/tagunion
Changed TagUnion to take the count of tags
2013-05-06 20:17:49 -07:00
Tsuda Kageyu
8826ae2484 Changed TagUnion to take the count of tags 2013-05-07 12:01:51 +09:00
Tsuda Kageyu
2d0644dca7 Merge pull request #192 from TsudaKageyu/classname
Changed names of derived classes of AudioProperties
2013-05-06 18:40:34 -07:00
Tsuda Kageyu
4ce7ebe520 Changed names of derived classes of AudioProperties 2013-05-06 19:23:57 +09:00
Tsuda Kageyu
72bb1a887e Merge pull request #191 from TsudaKageyu/move-macros
Moved some macros from taglib_config.h to config.h.
2013-05-05 05:16:45 -07:00
Tsuda Kageyu
04e07ad4b0 Moved some macros from taglib_config.h to config.h. 2013-05-05 20:52:47 +09:00
Tsuda Kageyu
c6315d8371 Merge pull request #189 from TsudaKageyu/merge-master
Merge master
2013-05-03 09:50:22 -07:00
Tsuda Kageyu
de04f4eb19 Merge branch 'master' into merge-master
Conflicts:
	ConfigureChecks.cmake
	config.h.cmake
	taglib/CMakeLists.txt
	taglib/toolkit/taglib.h
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tmap.tcc
	taglib/toolkit/tstring.h
2013-05-04 01:38:49 +09:00
Tsuda Kageyu
73e5acdae9 Merge pull request #185 from TsudaKageyu/ieee754
IEEE754 numbers support
2013-05-01 21:49:22 -07:00
Tsuda Kageyu
7e1f3545cd IEEE754 numbers support 2013-05-02 13:41:26 +09:00
Tsuda Kageyu
8457be8ab4 Merge pull request #184 from TsudaKageyu/vc-warnings
Fixed some MSVC specific warnings
2013-05-01 06:19:01 -07:00
Tsuda Kageyu
70044534aa Fixed some MSVC specific warnings 2013-05-01 22:14:05 +09:00
Tsuda Kageyu
3e7dc496be Merge pull request #183 from TsudaKageyu/fix-win9x
Fix incompatibility with Win9x
2013-05-01 04:59:33 -07:00
Tsuda Kageyu
43cfbd568b Fix incompatibility with Win9x 2013-05-01 20:50:08 +09:00
Tsuda Kageyu
b3a3aa8a95 Merge pull request #182 from TsudaKageyu/merge-master
Merged master into taglib2
2013-05-01 04:29:40 -07:00
Tsuda Kageyu
36512745cf Merge branch 'master' into merge-master
Conflicts:
	ConfigureChecks.cmake
	config-taglib.h.cmake
	taglib/CMakeLists.txt
	taglib/ape/apefooter.cpp
	taglib/ape/apeitem.cpp
	taglib/ape/apeproperties.cpp
	taglib/asf/asfattribute.cpp
	taglib/asf/asffile.cpp
	taglib/asf/asfpicture.cpp
	taglib/fileref.cpp
	taglib/flac/flacfile.cpp
	taglib/flac/flacpicture.cpp
	taglib/flac/flacproperties.cpp
	taglib/mp4/mp4atom.cpp
	taglib/mp4/mp4coverart.cpp
	taglib/mp4/mp4item.cpp
	taglib/mp4/mp4properties.cpp
	taglib/mp4/mp4tag.cpp
	taglib/mpc/mpcproperties.cpp
	taglib/mpeg/id3v2/frames/popularimeterframe.cpp
	taglib/mpeg/id3v2/frames/relativevolumeframe.cpp
	taglib/mpeg/id3v2/id3v2frame.cpp
	taglib/mpeg/id3v2/id3v2synchdata.cpp
	taglib/mpeg/xingheader.cpp
	taglib/ogg/flac/oggflacfile.cpp
	taglib/ogg/oggpageheader.cpp
	taglib/ogg/opus/opusproperties.cpp
	taglib/ogg/speex/speexproperties.cpp
	taglib/ogg/vorbis/vorbisproperties.cpp
	taglib/ogg/xiphcomment.cpp
	taglib/riff/aiff/aiffproperties.cpp
	taglib/riff/wav/infotag.cpp
	taglib/riff/wav/wavproperties.cpp
	taglib/toolkit/taglib.h
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tbytevector.h
	taglib/toolkit/tfilestream.cpp
	taglib/toolkit/tiostream.h
	taglib/toolkit/tstring.cpp
	taglib/toolkit/tstringhandler.cpp
	taglib/trueaudio/trueaudioproperties.cpp
	taglib/wavpack/wavpackproperties.cpp
2013-05-01 20:14:31 +09:00
Tsuda Kageyu
269f34ff2a Merge pull request #172 from TsudaKageyu/tonumber4
Redesigned toNumber/fromNumber API of ByteVector
2013-05-01 02:18:24 -07:00
Tsuda Kageyu
c50a0ae1dc Merge branch 'taglib2' into tonumber4-merge
Conflicts:
	ConfigureChecks.cmake
	config-taglib.h.cmake
2013-05-01 17:44:02 +09:00
Tsuda Kageyu
6b56510f99 Merge pull request #156 from Rachus/taglib2
A Matroska implementation
2013-05-01 01:17:23 -07:00
Tsuda Kageyu
91d3b8513d Merge pull request #181 from TsudaKageyu/snprintf
Use snprintf instead of sprintf if possible.
2013-05-01 00:34:40 -07:00
Tsuda Kageyu
fbe329bb70 Use snprintf instead of sprintf if possible. 2013-05-01 14:56:59 +09:00
Tsuda Kageyu
ffc7bcfef0 Merge pull request #179 from TsudaKageyu/bytevector
Simplified copy-on-write implementation of ByteVector
2013-04-30 01:09:29 -07:00
Tsuda Kageyu
93db8aa135 Simplified copy-on-write implementation of ByteVector 2013-04-30 16:40:41 +09:00
Tsuda Kageyu
6182378c87 Merge pull request #177 from TsudaKageyu/smart-ptr
Improved reference-counted pointer
2013-04-29 05:59:59 -07:00
Tsuda Kageyu
36ceaadfaa Improved reference-counted pointer 2013-04-29 20:15:05 +09:00
Tsuda Kageyu
362900c721 Redesigned toNumber/fromNumber API of ByteVector 2013-04-27 12:46:21 +09:00
Sebastian Rachuj
fb71d7341a Correct length calculation 2013-04-19 15:24:52 +02:00
Sebastian Rachuj
3dc37a482e Changed to/from LongLong to to/from (U)Int64 2013-04-19 15:22:33 +02:00
Sebastian Rachuj
3d3c97b5ef CMakeLists adjusted for Matroska 2013-04-18 13:34:35 +02:00
Sebastian Rachuj
ea968ae3be Added a rough matroska implementation. 2013-04-18 13:34:30 +02:00
Tsuda Kageyu
82e616101a Merge pull request #152 from TsudaKageyu/missing-include
Add missing inclusions of config.h
2013-04-17 22:25:47 -07:00
Tsuda kageyu
3d8bb4d4b9 Add missing inclusions of config.h 2013-04-18 11:33:26 +09:00
Tsuda Kageyu
454abde101 Update comments in trefcountptr.h 2013-04-18 04:22:04 +09:00
Tsuda Kageyu
f97a422bc2 Merge pull request #151 from TsudaKageyu/shared_ptr
Detect C++11 features automatically
2013-04-17 11:48:06 -07:00
Tsuda kageyu
4fc2a3bdd8 Detect C++11 features automatically 2013-04-18 03:23:12 +09:00
Tsuda Kageyu
10b4bd61e2 Merge pull request #146 from TsudaKageyu/classname
Changed some class names
2013-04-16 21:23:56 -07:00
Tsuda kageyu
c3efe19d8a Changed some class names 2013-04-17 13:07:08 +09:00
Tsuda Kageyu
1390860929 Merge pull request #140 from TsudaKageyu/smart-ptr
Replace RefCounter with a smart pointer
2013-04-16 15:29:10 -07:00
Tsuda kageyu
c44351aab5 RefCounter mimics std::shared_ptr 2013-04-17 06:39:14 +09:00
Tsuda Kageyu
5c96ff42c3 Merge pull request #135 from TsudaKageyu/merge-master
Merge branch 'master' into taglib2
2013-04-15 22:39:21 -07:00
Tsuda kageyu
bb61b43ba0 Merge branch 'master' into merge-master
Conflicts:
	taglib/mp4/mp4tag.cpp
	taglib/toolkit/taglib.h
	taglib/toolkit/tbytevector.cpp
	taglib/toolkit/tbytevector.h
	taglib/toolkit/tfile.cpp
	taglib/toolkit/tstring.cpp
	taglib/toolkit/tstring.h
	taglib/trueaudio/trueaudiofile.cpp
	taglib/wavpack/wavpackfile.cpp
	taglib/wavpack/wavpackfile.h
2013-04-16 14:16:54 +09:00
Tsuda Kageyu
2f711e26ca Merge pull request #124 from TsudaKageyu/merge-bytevector
Merge ByteVector improvement made in pull request #122
2013-04-10 12:10:17 -07:00
Tsuda Kageyu
781aa05f0e Merge ByteVector improvement made in pull request #122 2013-04-11 03:52:17 +09:00
Tsuda Kageyu
c265c2a874 Merge pull request #120 from poiru/taglib2-patch-1
Change tabs in 2711555 to spaces
2013-04-03 03:42:28 -07:00
Birunthan Mohanathas
5171de33e4 Change tabs in 2711555 to spaces 2013-04-03 12:53:38 +03:00
Tsuda Kageyu
2aaf41e0bb Merge pull request #119 from TsudaKageyu/iterator
Avoid possible overruns of iterators
2013-04-02 17:40:33 -07:00
Tsuda Kageyu
27115557a0 Avoid possible iterators' out-of-range 2013-04-03 09:21:48 +09:00
Tsuda Kageyu
86cee56f74 Merge pull request #118 from TsudaKageyu/fix-compile
Fix a compilation error
2013-03-24 14:18:49 -07:00
Tsuda Kageyu
843a12a0c6 Fix a compilation error 2013-03-25 06:13:07 +09:00
Tsuda Kageyu
a0e8963fa0 Merge pull request #117 from TsudaKageyu/win32-lib
Add a required target_link_libraries in Win32
2013-03-24 13:51:21 -07:00
Tsuda Kageyu
265013ef5b Add a required target_link_libraries in Win32 2013-03-25 05:44:57 +09:00
Tsuda Kageyu
39e02ad21b Added myself to AUTHORS 2013-03-24 01:15:25 +09:00
Tsuda Kageyu
fc2b69a81e Merge pull request #114 from TsudaKageyu/size_t
Change the size type of containers from uint to size_t
2013-03-23 02:49:07 -07:00
Tsuda Kageyu
1618833a6b Fix a compilation error 2013-03-23 13:58:44 +09:00
Tsuda Kageyu
56c85a2d68 Change the size type of containers from uint to size_t 2013-03-23 13:42:46 +09:00
Tsuda Kageyu
83b6fdef72 Merge pull request #113 from TsudaKageyu/fix-ulong
Fix uses of ulong where 32-bit integers are expected
2013-03-21 19:27:31 -07:00
Tsuda Kageyu
cd082cd8e3 Fix uses of ulong where 32-bit integers are expected 2013-03-22 11:17:10 +09:00
Tsuda Kageyu
b744f66819 Merge pull request #112 from TsudaKageyu/string-data
Avoid resizing a buffer frequently in String::data()
2013-03-21 17:06:17 -07:00
Tsuda Kageyu
2ed7a59d95 Avoid resizing buffer frequently in String::data() 2013-03-22 08:58:38 +09:00
Tsuda Kageyu
7d5ce5624a Merge pull request #111 from TsudaKageyu/null
Make String:null and ByteVector::null const.
2013-03-21 10:15:23 -07:00
Tsuda Kageyu
e93696f573 Make String:null and ByteVector::null const. 2013-03-22 01:43:46 +09:00
Tsuda Kageyu
914e5f9fd8 Merge pull request #110 from TsudaKageyu/byteswap
Refector ByteVector
2013-03-21 04:09:06 -07:00
Tsuda Kageyu
b1dcdc5bd8 Refector ByteVector 2013-03-21 19:50:35 +09:00
Tsuda Kageyu
b4df82a0b0 Merge pull request #109 from TsudaKageyu/taglib2
Fix GCC warnings in FileStream
2013-03-21 02:39:17 -07:00
Tsuda Kageyu
be081d23d3 Fix GCC warnings in FileStream 2013-03-21 18:29:24 +09:00
Tsuda Kageyu
0acc22e84b Merge pull request #108 from TsudaKageyu/sizeof_wchar_t
Detect sizeof(wchar_t) at compile time
2013-03-20 22:54:28 -07:00
Tsuda Kageyu
62efb9ff17 Detect sizeof(wchar_t) at compile time 2013-03-21 14:43:03 +09:00
Tsuda Kageyu
ca5ce53b1e Merge pull request #107 from TsudaKageyu/endian-detect
Detect UTF-16 byte order at compile time
2013-03-20 18:28:27 -07:00
Tsuda Kageyu
8cae2b9f28 Detect UTF-16 byte order at compile time 2013-03-21 10:21:52 +09:00
Tsuda Kageyu
d719eb0ac6 Merge pull request #105 from TsudaKageyu/shared_ptr
Replace RefCounter with std::shared_ptr if possible
2013-03-20 18:03:57 -07:00
Tsuda Kageyu
cab68e2152 Stop determining whether to enable C++11 features at compile time 2013-03-20 08:39:13 +09:00
Tsuda Kageyu
96cf908232 Replace RefCounter with std::shared_ptr if possible 2013-03-19 21:36:08 +09:00
Tsuda Kageyu
42a74babb5 Merge pull request #103 from TsudaKageyu/string-improvement
Some improvements of String
2013-03-19 01:12:25 -07:00
Tsuda Kageyu
4e05923479 Removed null termination from return value of String::data() 2013-03-18 13:55:49 +09:00
Tsuda Kageyu
c86ea7bdff Use the standard library to convert between UTF-8 and UTF-16 where possible 2013-03-18 13:34:20 +09:00
Tsuda Kageyu
a842220fe6 Revert "Use the standard library to convert between UTF-8 and UTF-16 where possible"
This reverts commit 19ce4d0dfa.
2013-03-18 06:08:05 +09:00
Tsuda Kageyu
19ce4d0dfa Use the standard library to convert between UTF-8 and UTF-16 where possible 2013-03-18 05:56:48 +09:00
Tsuda Kageyu
6e3639de9e Avoid creating new String object when comparing 2013-03-18 02:51:11 +09:00
Tsuda Kageyu
0792eedd12 Fix UTF-16 BOM detection 2013-03-17 20:47:58 +09:00
Tsuda Kageyu
86b7cabf44 Fix UTF-16 decoding where wchar_t is not 16-bit 2013-03-17 20:27:32 +09:00
Tsuda Kageyu
de19ad72ab Fixed CPU endian detection 2013-03-17 19:40:01 +09:00
Tsuda Kageyu
9b19453059 Some improvements of String 2013-03-17 12:51:00 +09:00
Tsuda Kageyu
dbd7c151d6 Fix buffer overrun 2013-03-17 12:41:47 +09:00
Tsuda Kageyu
d3af7c0b02 Fix VC++ x64 warnings 2013-03-16 00:07:01 +09:00
Tsuda Kageyu
64447598e5 Made the destructor of StringHandler virtual. 2013-02-23 00:36:41 +09:00
Tsuda Kageyu
fba8f42588 Fix some VC spesific warnings 2013-02-22 19:29:02 +09:00
Michael Helmling
5578843220 Fixed a typo. 2013-01-03 22:54:12 +01:00
Michael Helmling
90fd336a22 Add TagUnion::removeUnsupportedProperties, further reducing SLOCs. :-) 2012-12-27 13:32:01 +01:00
Michael Helmling
fa38c805f5 Implemented TagUnion::properties() and made Tag::*properties* virtual.
This allows to remove several default implementations in types using
TagUnions.
2012-12-27 13:19:11 +01:00
Michael Helmling
b60b444d7b Merge branch 'master' into taglib2
Conflicts:
	taglib/toolkit/tfile.h
2012-12-27 11:55:12 +01:00
Lukáš Lalinský
db892c43e7 Merge branch 'master' into taglib2
Conflicts:
	taglib/mp4/mp4tag.cpp
	taglib/mp4/mp4tag.h
	taglib/toolkit/tfile.cpp
2012-11-23 10:17:16 +01:00
Lukáš Lalinský
f2b56a5511 Remove no longer needed save methods in MPEG::File 2012-11-12 16:37:06 +01:00
Lukáš Lalinský
2a86da4df5 Move Vorbis to the Ogg namespace 2012-11-12 16:32:15 +01:00
Lukáš Lalinský
f6741b65e4 Add toString() for Vorbis Comments 2012-11-12 16:27:22 +01:00
Lukáš Lalinský
60ba972244 Make the toString() method virtual 2012-11-12 16:22:23 +01:00
Lukáš Lalinský
e8ae4ecd93 Revert "Revert "Add a tool to inspect audio files, only MP4 is implemented for now""
This reverts commit c6f7ad3e83.
2012-11-12 16:16:31 +01:00
Lukáš Lalinský
f407d1456c Merge branch 'master' into taglib2 2012-11-12 16:16:18 +01:00
Lukáš Lalinský
50e616df8d Move stream operators to the TagLib namespace 2012-11-11 14:44:34 +01:00
Lukáš Lalinský
9440055eb1 Fix compilation on clang 2012-11-11 14:35:47 +01:00
Lukáš Lalinský
cb8b8d50f6 Merge branch 'master' into taglib2 2012-11-11 14:26:46 +01:00
Lukáš Lalinský
c3f9c63542 Unify ByteVectorList::split methods 2012-11-04 10:08:18 +01:00
Lukáš Lalinský
aa801e58ec Unify String::toInt methods 2012-11-04 10:04:06 +01:00
Lukáš Lalinský
9e41939eb1 Rename MPEG::XingHeader::xingHeaderOffset 2012-11-04 10:03:02 +01:00
Lukáš Lalinský
0d49e6bff0 No longer needed methods in FLAC::File 2012-11-04 10:01:39 +01:00
Lukáš Lalinský
6e2d5bc1dc Unify FLAC::File constructors 2012-11-04 09:58:56 +01:00
Lukáš Lalinský
9cede44af6 Remove deprecated constructor from FLAC::Properties 2012-11-04 09:54:17 +01:00
Lukáš Lalinský
ae11b3db38 Default parameter values in RelativeVolumeFrame 2012-11-04 09:52:03 +01:00
Lukáš Lalinský
b3c112ed99 Remove obsolete constructor from WavPack::Properties 2012-11-04 09:49:28 +01:00
Lukáš Lalinský
5b604f41be Add default value for addFramingBit to XiphComment::render() 2012-11-04 09:46:50 +01:00
Lukáš Lalinský
8599c1bd38 These functions are now virtual, so the default implementation from TagLib::File can be used 2012-11-04 09:44:51 +01:00
Lukáš Lalinský
27a078fe9b Do not need this anymore 2012-11-04 09:33:11 +01:00
Lukáš Lalinský
2b31fc2037 Merge branch 'master' into taglib2 2012-11-04 09:30:33 +01:00
Lukáš Lalinský
b01f45e141 Merge pull request #77 from TsudaKageyu/largefilesupport
Support large files over 2GB
2012-11-04 01:29:45 -07:00
Lukáš Lalinský
c46ecd186d Make the PropertyMap accessor methods virtual 2012-10-20 09:30:26 +02:00
Lukáš Lalinský
c2eecc0804 Merge branch 'master' into taglib2
Conflicts:
	taglib/mpeg/id3v1/id3v1tag.cpp
2012-10-13 13:44:38 +02:00
Tsuda Kageyu
4dcf0b41c6 Support files over 2GB 2012-10-10 22:22:29 +09:00
Tsuda Kageyu
9577784bae Add the string handler base class 2012-10-04 18:02:25 +09:00
Lukáš Lalinský
f52bab8a01 Merge branch 'master' into taglib2 2012-09-30 10:50:51 +02:00
Lukáš Lalinský
738e2ae7a7 Remove some deprecated methods from APE::Item 2012-09-30 10:42:38 +02:00
Lukáš Lalinský
231eb08396 Add a virtual destructor to FileTypeResolver 2012-09-30 10:34:14 +02:00
255 changed files with 8933 additions and 5639 deletions

View File

@@ -17,6 +17,7 @@ addons:
packages:
- libcppunit-dev
- zlib1g-dev
- libboost-dev
matrix:
exclude:

View File

@@ -127,20 +127,11 @@ endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
configure_file(config.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/config.h")
if(WITH_ASF)
set(TAGLIB_WITH_ASF TRUE)
endif()
if(WITH_MP4)
set(TAGLIB_WITH_MP4 TRUE)
endif()
option(TRACE_IN_RELEASE "Output debug messages even in release mode" OFF)
option(TRACE_IN_RELEASE "Output debug messages even in release mode" OFF)
if(TRACE_IN_RELEASE)
set(TRACE_IN_RELEASE TRUE)
endif()
configure_file(taglib/taglib_config.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/taglib_config.h")
add_subdirectory(taglib)
if(BUILD_BINDINGS)

View File

@@ -1,6 +1,8 @@
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckCXXCompilerFlag)
include(CheckCXXSourceCompiles)
include(TestLargeFiles)
# Check if the size of numeric types are suitable.
@@ -34,6 +36,22 @@ if(NOT ${SIZEOF_DOUBLE} EQUAL 8)
message(FATAL_ERROR "TagLib requires that double is 64-bit wide.")
endif()
# Determine whether your compiler supports large files.
if(NOT WIN32)
test_large_files(SUPPORT_LARGE_FILES)
if(NOT SUPPORT_LARGE_FILES)
MESSAGE(FATAL_ERROR "TagLib requires large files support.")
endif()
endif()
# Enable check_cxx_source_compiles() to work with Boost "header-only" libraries.
find_package(Boost)
if(Boost_FOUND)
set(CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES};${Boost_INCLUDE_DIRS}")
endif()
# Determine which kind of atomic operations your compiler supports.
check_cxx_source_compiles("
@@ -93,6 +111,17 @@ if(NOT HAVE_STD_ATOMIC)
endif()
endif()
# Determine which kind of smart pointers your compiler supports.
check_cxx_source_compiles("
#include <memory>
int main() {
std::shared_ptr<int> x;
std::unique_ptr<int> y;
return 0;
}
" HAVE_STD_SMART_PTR)
# Determine which kind of byte swap functions your compiler supports.
check_cxx_source_compiles("
@@ -211,5 +240,5 @@ endif()
# Detect WinRT mode
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
set(PLATFORM WINRT 1)
set(PLATFORM_WINRT 1)
endif()

View File

@@ -92,32 +92,32 @@ void taglib_free(void* pointer)
TagLib_File *taglib_file_new(const char *filename)
{
return reinterpret_cast<TagLib_File *>(FileRef::create(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(filename));
}
TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
{
switch(type) {
case TagLib_File_MPEG:
return reinterpret_cast<TagLib_File *>(new MPEG::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new MPEG::File(filename)));
case TagLib_File_OggVorbis:
return reinterpret_cast<TagLib_File *>(new Ogg::Vorbis::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new Ogg::Vorbis::File(filename)));
case TagLib_File_FLAC:
return reinterpret_cast<TagLib_File *>(new FLAC::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new FLAC::File(filename)));
case TagLib_File_MPC:
return reinterpret_cast<TagLib_File *>(new MPC::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new MPC::File(filename)));
case TagLib_File_OggFlac:
return reinterpret_cast<TagLib_File *>(new Ogg::FLAC::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new Ogg::FLAC::File(filename)));
case TagLib_File_WavPack:
return reinterpret_cast<TagLib_File *>(new WavPack::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new WavPack::File(filename)));
case TagLib_File_Speex:
return reinterpret_cast<TagLib_File *>(new Ogg::Speex::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new Ogg::Speex::File(filename)));
case TagLib_File_TrueAudio:
return reinterpret_cast<TagLib_File *>(new TrueAudio::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new TrueAudio::File(filename)));
case TagLib_File_MP4:
return reinterpret_cast<TagLib_File *>(new MP4::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new MP4::File(filename)));
case TagLib_File_ASF:
return reinterpret_cast<TagLib_File *>(new ASF::File(filename));
return reinterpret_cast<TagLib_File *>(new FileRef(new ASF::File(filename)));
default:
return 0;
}
@@ -125,29 +125,29 @@ TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
void taglib_file_free(TagLib_File *file)
{
delete reinterpret_cast<File *>(file);
delete reinterpret_cast<FileRef *>(file);
}
BOOL taglib_file_is_valid(const TagLib_File *file)
{
return reinterpret_cast<const File *>(file)->isValid();
return reinterpret_cast<const FileRef *>(file)->isValid();
}
TagLib_Tag *taglib_file_tag(const TagLib_File *file)
{
const File *f = reinterpret_cast<const File *>(file);
const FileRef *f = reinterpret_cast<const FileRef *>(file);
return reinterpret_cast<TagLib_Tag *>(f->tag());
}
const TagLib_AudioProperties *taglib_file_audioproperties(const TagLib_File *file)
{
const File *f = reinterpret_cast<const File *>(file);
const FileRef *f = reinterpret_cast<const FileRef *>(file);
return reinterpret_cast<const TagLib_AudioProperties *>(f->audioProperties());
}
BOOL taglib_file_save(TagLib_File *file)
{
return reinterpret_cast<File *>(file)->save();
return reinterpret_cast<FileRef *>(file)->save();
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,9 @@
#include <sys/types.h>
int main(int argc, char **argv)
{
/* Cause a compile-time error if off_t is smaller than 64 bits */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ];
return 0;
}

View File

@@ -0,0 +1,23 @@
#cmakedefine _LARGEFILE_SOURCE
#cmakedefine _LARGEFILE64_SOURCE
#cmakedefine _LARGE_FILES
#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
/* Cause a compile-time error if off_t is smaller than 64 bits,
* and make sure we have ftello / fseeko.
*/
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ];
FILE *fp = fopen(argv[0],"r");
off_t offset = ftello( fp );
fseeko( fp, offset, SEEK_CUR );
fclose(fp);
return 0;
}

View File

@@ -0,0 +1,104 @@
# - Define macro to check large file support
#
# TEST_LARGE_FILES(VARIABLE)
#
# VARIABLE will be set to true if off_t is 64 bits, and fseeko/ftello present.
# This macro will also set defines necessary enable large file support, for instance
# _LARGE_FILES
# _LARGEFILE_SOURCE
# _FILE_OFFSET_BITS 64
# HAVE_FSEEKO
#
# However, it is YOUR job to make sure these defines are set in a cmakedefine so they
# end up in a config.h file that is included in your source if necessary!
# This macro skips the Windows specific checks. Because TagLib uses Win32 API.
MACRO(TEST_LARGE_FILES VARIABLE)
IF(NOT DEFINED ${VARIABLE})
# On most platforms it is probably overkill to first test the flags for 64-bit off_t,
# and then separately fseeko. However, in the future we might have 128-bit filesystems
# (ZFS), so it might be dangerous to indiscriminately set e.g. _FILE_OFFSET_BITS=64.
MESSAGE(STATUS "Checking for 64-bit off_t")
# First check without any special flags
TRY_COMPILE(FILE64_OK "${PROJECT_BINARY_DIR}"
"${CMAKE_SOURCE_DIR}/cmake/TestFileOffsetBits.c")
if(FILE64_OK)
MESSAGE(STATUS "Checking for 64-bit off_t - present")
endif(FILE64_OK)
if(NOT FILE64_OK)
# Test with _FILE_OFFSET_BITS=64
TRY_COMPILE(FILE64_OK "${PROJECT_BINARY_DIR}"
"${CMAKE_SOURCE_DIR}/cmake/TestFileOffsetBits.c"
COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" )
if(FILE64_OK)
MESSAGE(STATUS "Checking for 64-bit off_t - present with _FILE_OFFSET_BITS=64")
set(_FILE_OFFSET_BITS 64)
endif(FILE64_OK)
endif(NOT FILE64_OK)
if(NOT FILE64_OK)
# Test with _LARGE_FILES
TRY_COMPILE(FILE64_OK "${PROJECT_BINARY_DIR}"
"${CMAKE_SOURCE_DIR}/cmake/TestFileOffsetBits.c"
COMPILE_DEFINITIONS "-D_LARGE_FILES" )
if(FILE64_OK)
MESSAGE(STATUS "Checking for 64-bit off_t - present with _LARGE_FILES")
set(_LARGE_FILES 1)
endif(FILE64_OK)
endif(NOT FILE64_OK)
if(NOT FILE64_OK)
# Test with _LARGEFILE_SOURCE
TRY_COMPILE(FILE64_OK "${PROJECT_BINARY_DIR}"
"${CMAKE_SOURCE_DIR}/cmake/TestFileOffsetBits.c"
COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" )
if(FILE64_OK)
MESSAGE(STATUS "Checking for 64-bit off_t - present with _LARGEFILE_SOURCE")
set(_LARGEFILE_SOURCE 1)
endif(FILE64_OK)
endif(NOT FILE64_OK)
if(NOT FILE64_OK)
MESSAGE(STATUS "Checking for 64-bit off_t - not present")
else(NOT FILE64_OK)
# Set the flags we might have determined to be required above
configure_file("${CMAKE_SOURCE_DIR}/cmake/TestLargeFiles.c.cmakein"
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c")
MESSAGE(STATUS "Checking for fseeko/ftello")
# Test if ftello/fseeko are available
TRY_COMPILE(FSEEKO_COMPILE_OK "${PROJECT_BINARY_DIR}"
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c")
if(FSEEKO_COMPILE_OK)
MESSAGE(STATUS "Checking for fseeko/ftello - present")
endif(FSEEKO_COMPILE_OK)
if(NOT FSEEKO_COMPILE_OK)
# glibc 2.2 neds _LARGEFILE_SOURCE for fseeko (but not 64-bit off_t...)
TRY_COMPILE(FSEEKO_COMPILE_OK "${PROJECT_BINARY_DIR}"
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c"
COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" )
if(FSEEKO_COMPILE_OK)
MESSAGE(STATUS "Checking for fseeko/ftello - present with _LARGEFILE_SOURCE")
set(_LARGEFILE_SOURCE 1)
endif(FSEEKO_COMPILE_OK)
endif(NOT FSEEKO_COMPILE_OK)
endif(NOT FILE64_OK)
if(FSEEKO_COMPILE_OK)
SET(${VARIABLE} 1 CACHE INTERNAL "Result of test for large file support" FORCE)
set(HAVE_FSEEKO 1)
else(FSEEKO_COMPILE_OK)
MESSAGE(STATUS "Checking for fseeko/ftello - not found")
SET(${VARIABLE} 0 CACHE INTERNAL "Result of test for large file support" FORCE)
endif(FSEEKO_COMPILE_OK)
ENDIF(NOT DEFINED ${VARIABLE})
ENDMACRO(TEST_LARGE_FILES VARIABLE)

View File

@@ -3,6 +3,11 @@
#ifndef TAGLIB_CONFIG_H
#define TAGLIB_CONFIG_H
/* Defined if required for large files support */
#cmakedefine _LARGE_FILES ${_LARGE_FILES}
#cmakedefine _LARGEFILE_SOURCE ${_LARGEFILE_SOURCE}
#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
/* Defined if your compiler supports some byte swap functions */
#cmakedefine HAVE_GCC_BYTESWAP 1
#cmakedefine HAVE_GLIBC_BYTESWAP 1
@@ -17,6 +22,9 @@
#cmakedefine HAVE_WIN_ATOMIC 1
#cmakedefine HAVE_IA64_ATOMIC 1
/* Defined if your compiler supports shared_ptr */
#cmakedefine HAVE_STD_SMART_PTR 1
/* Defined if your compiler supports some safer version of vsprintf */
#cmakedefine HAVE_VSNPRINTF 1
#cmakedefine HAVE_VSPRINTF_S 1

View File

@@ -37,3 +37,7 @@ target_link_libraries(framelist tag)
add_executable(strip-id3v1 strip-id3v1.cpp)
target_link_libraries(strip-id3v1 tag)
########### next target ###############
add_executable(inspect inspect.cpp)
target_link_libraries(inspect tag)

48
examples/inspect.cpp Normal file
View File

@@ -0,0 +1,48 @@
/* Copyright (C) 2012 Lukas Lalinsky <lalinsky@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <stdlib.h>
#include <fileref.h>
#include <tfile.h>
using namespace std;
using namespace TagLib;
int main(int argc, char *argv[])
{
// process the command line args
for(int i = 1; i < argc; i++) {
cout << "******************** \"" << argv[i] << "\"********************" << endl;
FileRef f(argv[i]);
if(!f.isNull() && f.file()) {
cout << f.file()->toString().to8Bit(true) << endl;
}
}
}

View File

@@ -28,6 +28,7 @@
#include <fileref.h>
#include <tag.h>
#include <tpicturemap.h>
#include <tpropertymap.h>
using namespace std;
@@ -45,13 +46,15 @@ int main(int argc, char *argv[])
TagLib::Tag *tag = f.tag();
cout << "-- TAG (basic) --" << endl;
cout << "title - \"" << tag->title() << "\"" << endl;
cout << "artist - \"" << tag->artist() << "\"" << endl;
cout << "album - \"" << tag->album() << "\"" << endl;
cout << "year - \"" << tag->year() << "\"" << endl;
cout << "comment - \"" << tag->comment() << "\"" << endl;
cout << "track - \"" << tag->track() << "\"" << endl;
cout << "genre - \"" << tag->genre() << "\"" << endl;
cout << "title - \"" << tag->title() << "\"" << endl;
cout << "artist - \"" << tag->artist() << "\"" << endl;
cout << "album - \"" << tag->album() << "\"" << endl;
cout << "year - \"" << tag->year() << "\"" << endl;
cout << "comment - \"" << tag->comment() << "\"" << endl;
cout << "track - \"" << tag->track() << "\"" << endl;
cout << "genre - \"" << tag->genre() << "\"" << endl;
if(!tag->pictures().isEmpty())
cout << "pictures -" << tag->pictures() << endl;
TagLib::PropertyMap tags = f.file()->properties();

View File

@@ -22,8 +22,10 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <fstream>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string.h>
#include <stdio.h>
@@ -34,6 +36,8 @@
#include <tlist.h>
#include <fileref.h>
#include <tfile.h>
#include <tpicturemap.h>
#include <tag.h>
#include <tpropertymap.h>
@@ -70,6 +74,7 @@ void usage()
cout << " -R <tagname> <tagvalue>" << endl;
cout << " -I <tagname> <tagvalue>" << endl;
cout << " -D <tagname>" << endl;
cout << " -p <picture(jpg only, file between double quotes)>" << endl;
cout << endl;
exit(1);
@@ -110,14 +115,16 @@ int main(int argc, char *argv[])
if(fileList.isEmpty())
usage();
if(argv[argc-1][1] == 'p')
argc++;
for(int i = 1; i < argc - 1; i += 2) {
if(isArgument(argv[i]) && i + 1 < argc && !isArgument(argv[i + 1])) {
char field = argv[i][1];
TagLib::String value = argv[i + 1];
TagLib::List<TagLib::FileRef>::ConstIterator it;
TagLib::List<TagLib::FileRef>::Iterator it;
for(it = fileList.begin(); it != fileList.end(); ++it) {
TagLib::Tag *t = (*it).tag();
@@ -167,6 +174,31 @@ int main(int argc, char *argv[])
checkForRejectedProperties((*it).file()->setProperties(map));
break;
}
case 'p':
{
if(!isFile(value.toCString())) {
cout << value.toCString() << " not found." << endl;
return 1;
}
ifstream picture;
picture.open(value.toCString());
stringstream buffer;
buffer << picture.rdbuf();
picture.close();
TagLib::String buf(buffer.str());
TagLib::ByteVector data(buf.data(TagLib::String::Latin1));
if(!data.find("JFIF")) {
cout << value.toCString() << " is not a JPEG." << endl;
return 1;
}
TagLib::Picture pic(data,
TagLib::Picture::FrontCover,
"image/jpeg",
"Added with taglib");
TagLib::PictureMap picMap(pic);
t->setPictures(picMap);
}
break;
default:
usage();
break;

View File

@@ -1,36 +1,35 @@
@echo off
goto beginning
*
* It is what it is, you can do with it as you please.
*
* Just don't blame me if it teaches your computer to smoke!
*
* -Enjoy
* fh :)_~
*
:beginning
if /i "%1#" == "--libs#" goto doit
if /i "%1#" == "--cflags#" goto doit
if /i "%1#" == "--version#" goto doit
if /i "%1#" == "--prefix#" goto doit
echo "usage: %0 [OPTIONS]"
echo [--libs]
echo [--cflags]
echo [--version]
echo [--prefix]
goto theend
*
* NOTE: Windows does not assume libraries are prefixed with 'lib'.
* NOTE: If '-llibtag' is the last element, it is easily appended in the users installation/makefile process
* to allow for static, shared or debug builds.
* It would be preferable if the top level CMakeLists.txt provided the library name during config. ??
:doit
if /i "%1#" == "--libs#" echo -L${LIB_INSTALL_DIR} -llibtag
if /i "%1#" == "--cflags#" echo -I${INCLUDE_INSTALL_DIR}/taglib
if /i "%1#" == "--version#" echo ${TAGLIB_LIB_VERSION_STRING}
if /i "%1#" == "--prefix#" echo ${CMAKE_INSTALL_PREFIX}
:theend
@echo off
goto beginning
*
* It is what it is, you can do with it as you please.
*
* Just don't blame me if it teaches your computer to smoke!
*
* -Enjoy
* fh :)_~
*
:beginning
if /i "%1#" == "--libs#" goto doit
if /i "%1#" == "--cflags#" goto doit
if /i "%1#" == "--version#" goto doit
if /i "%1#" == "--prefix#" goto doit
echo "usage: %0 [OPTIONS]"
echo [--libs]
echo [--cflags]
echo [--version]
echo [--prefix]
goto theend
*
* NOTE: Windows does not assume libraries are prefixed with 'lib'.
* NOTE: If '-llibtag' is the last element, it is easily appended in the users installation/makefile process
* to allow for static, shared or debug builds.
* It would be preferable if the top level CMakeLists.txt provided the library name during config. ??
:doit
if /i "%1#" == "--libs#" echo -L${LIB_INSTALL_DIR} -llibtag
if /i "%1#" == "--cflags#" echo -I${INCLUDE_INSTALL_DIR}/taglib
if /i "%1#" == "--version#" echo ${TAGLIB_LIB_VERSION_STRING}
if /i "%1#" == "--prefix#" echo ${CMAKE_INSTALL_PREFIX}
:theend

View File

@@ -24,6 +24,8 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/s3m
${CMAKE_CURRENT_SOURCE_DIR}/it
${CMAKE_CURRENT_SOURCE_DIR}/xm
${CMAKE_CURRENT_SOURCE_DIR}/ebml
${CMAKE_CURRENT_SOURCE_DIR}/ebml/matroska
${CMAKE_CURRENT_SOURCE_DIR}/dsf
${CMAKE_CURRENT_SOURCE_DIR}/dsdiff
${CMAKE_SOURCE_DIR}/3rdparty
@@ -40,12 +42,12 @@ set(tag_HDRS
fileref.h
audioproperties.h
taglib_export.h
${CMAKE_CURRENT_BINARY_DIR}/../taglib_config.h
toolkit/taglib.h
toolkit/tstring.h
toolkit/tlist.h
toolkit/tlist.tcc
toolkit/tstringlist.h
toolkit/tstringhandler.h
toolkit/tbytevector.h
toolkit/tbytevectorlist.h
toolkit/tbytevectorstream.h
@@ -54,6 +56,8 @@ set(tag_HDRS
toolkit/tfilestream.h
toolkit/tmap.h
toolkit/tmap.tcc
toolkit/tpicture.h
toolkit/tpicturemap.h
toolkit/tpropertymap.h
toolkit/trefcounter.h
toolkit/tdebuglistener.h
@@ -140,6 +144,12 @@ set(tag_HDRS
s3m/s3mproperties.h
xm/xmfile.h
xm/xmproperties.h
ebml/ebmlfile.h
ebml/ebmlelement.h
ebml/ebmlconstants.h
ebml/matroska/ebmlmatroskafile.h
ebml/matroska/ebmlmatroskaconstants.h
ebml/matroska/ebmlmatroskaaudio.h
dsf/dsffile.h
dsf/dsfproperties.h
dsdiff/dsdifffile.h
@@ -305,6 +315,16 @@ set(dsf_SRCS
dsf/dsfproperties.cpp
)
set(ebml_SRCS
ebml/ebmlfile.cpp
ebml/ebmlelement.cpp
)
set(matroska_SRCS
ebml/matroska/ebmlmatroskafile.cpp
ebml/matroska/ebmlmatroskaaudio.cpp
)
set(dsdiff_SRCS
dsdiff/dsdifffile.cpp
dsdiff/dsdiffproperties.cpp
@@ -312,8 +332,10 @@ set(dsdiff_SRCS
)
set(toolkit_SRCS
toolkit/taglib.cpp
toolkit/tstring.cpp
toolkit/tstringlist.cpp
toolkit/tstringhandler.cpp
toolkit/tbytevector.cpp
toolkit/tbytevectorlist.cpp
toolkit/tbytevectorstream.cpp
@@ -321,6 +343,8 @@ set(toolkit_SRCS
toolkit/tfile.cpp
toolkit/tfilestream.cpp
toolkit/tdebug.cpp
toolkit/tpicture.cpp
toolkit/tpicturemap.cpp
toolkit/tpropertymap.cpp
toolkit/trefcounter.cpp
toolkit/tdebuglistener.cpp
@@ -342,7 +366,8 @@ set(tag_LIB_SRCS
${mpeg_SRCS} ${id3v1_SRCS} ${id3v2_SRCS} ${frames_SRCS} ${ogg_SRCS}
${vorbis_SRCS} ${oggflacs_SRCS} ${mpc_SRCS} ${ape_SRCS} ${toolkit_SRCS} ${flacs_SRCS}
${wavpack_SRCS} ${speex_SRCS} ${trueaudio_SRCS} ${riff_SRCS} ${aiff_SRCS} ${wav_SRCS}
${asf_SRCS} ${mp4_SRCS} ${mod_SRCS} ${s3m_SRCS} ${it_SRCS} ${xm_SRCS} ${opus_SRCS} ${dsf_SRCS} ${dsdiff_SRCS}
${asf_SRCS} ${mp4_SRCS} ${mod_SRCS} ${s3m_SRCS} ${it_SRCS} ${xm_SRCS} ${opus_SRCS}
${ebml_SRCS} ${matroska_SRCS} ${dsf_SRCS} ${dsdiff_SRCS}
${zlib_SRCS}
tag.cpp
tagunion.cpp

View File

@@ -39,6 +39,7 @@
#include <id3v2header.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include <tsmartptr.h>
#include "apefile.h"
#include "apetag.h"
@@ -58,29 +59,21 @@ public:
APELocation(-1),
APESize(0),
ID3v1Location(-1),
ID3v2Header(0),
ID3v2Location(-1),
ID3v2Size(0),
properties(0) {}
ID3v2Size(0) {}
~FilePrivate()
{
delete ID3v2Header;
delete properties;
}
long long APELocation;
long long APESize;
long APELocation;
long APESize;
long long ID3v1Location;
long ID3v1Location;
SCOPED_PTR<ID3v2::Header> ID3v2Header;
long long ID3v2Location;
long long ID3v2Size;
ID3v2::Header *ID3v2Header;
long ID3v2Location;
long ID3v2Size;
DoubleTagUnion tag;
TagUnion tag;
Properties *properties;
SCOPED_PTR<AudioProperties> properties;
};
////////////////////////////////////////////////////////////////////////////////
@@ -92,14 +85,14 @@ bool APE::File::isSupported(IOStream *stream)
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
return (buffer.find("MAC ") >= 0);
return (buffer.find("MAC ") != ByteVector::npos());
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
APE::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
TagLib::File(file),
d(new FilePrivate())
{
@@ -107,7 +100,7 @@ APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
read(readProperties);
}
APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
APE::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) :
TagLib::File(stream),
d(new FilePrivate())
{
@@ -125,16 +118,6 @@ TagLib::Tag *APE::File::tag() const
return &d->tag;
}
PropertyMap APE::File::properties() const
{
return d->tag.properties();
}
void APE::File::removeUnsupportedProperties(const StringList &properties)
{
d->tag.removeUnsupportedProperties(properties);
}
PropertyMap APE::File::setProperties(const PropertyMap &properties)
{
if(ID3v1Tag())
@@ -143,9 +126,9 @@ PropertyMap APE::File::setProperties(const PropertyMap &properties)
return APETag(true)->setProperties(properties);
}
APE::Properties *APE::File::audioProperties() const
APE::AudioProperties *APE::File::audioProperties() const
{
return d->properties;
return d->properties.get();
}
bool APE::File::save()
@@ -195,7 +178,7 @@ bool APE::File::save()
}
const ByteVector data = APETag()->render();
insert(data, d->APELocation, d->APESize);
insert(data, d->APELocation, static_cast<size_t>(d->APESize));
if(d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
@@ -207,7 +190,7 @@ bool APE::File::save()
// APE tag is empty. Remove the old one.
if(d->APELocation >= 0) {
removeBlock(d->APELocation, d->APESize);
removeBlock(d->APELocation, static_cast<size_t>(d->APESize));
if(d->ID3v1Location >= 0)
d->ID3v1Location -= d->APESize;
@@ -264,7 +247,7 @@ void APE::File::read(bool readProperties)
if(d->ID3v2Location >= 0) {
seek(d->ID3v2Location);
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
d->ID3v2Header.reset(new ID3v2::Header(readBlock(ID3v2::Header::size())));
d->ID3v2Size = d->ID3v2Header->completeTagSize();
}
@@ -292,7 +275,7 @@ void APE::File::read(bool readProperties)
if(readProperties) {
long streamLength;
long long streamLength;
if(d->APELocation >= 0)
streamLength = d->APELocation;
@@ -309,6 +292,6 @@ void APE::File::read(bool readProperties)
seek(0);
}
d->properties = new Properties(this, streamLength);
d->properties.reset(new AudioProperties(this, streamLength));
}
}

View File

@@ -90,7 +90,7 @@ namespace TagLib {
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Constructs an APE file from \a stream. If \a readProperties is true the
@@ -102,7 +102,7 @@ namespace TagLib {
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Destroys this instance of the File.
@@ -115,31 +115,18 @@ namespace TagLib {
*/
virtual TagLib::Tag *tag() const;
/*!
* Implements the unified property interface -- export function.
* If the file contains both an APE and an ID3v1 tag, only APE
* will be converted to the PropertyMap.
*/
PropertyMap properties() const;
/*!
* Removes unsupported properties. Forwards to the actual Tag's
* removeUnsupportedProperties() function.
*/
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the unified property interface -- import function.
* Creates an APEv2 tag if necessary. A potentially existing ID3v1
* tag will be updated as well.
*/
PropertyMap setProperties(const PropertyMap &);
virtual PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the APE::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
virtual AudioProperties *audioProperties() const;
/*!
* Saves the file.

View File

@@ -175,19 +175,19 @@ void APE::Footer::parse(const ByteVector &data)
// Read the version number
d->version = data.toUInt(8, false);
d->version = data.toUInt32LE(8);
// Read the tag size
d->tagSize = data.toUInt(12, false);
d->tagSize = data.toUInt32LE(12);
// Read the item count
d->itemCount = data.toUInt(16, false);
d->itemCount = data.toUInt32LE(16);
// Read the flags
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt(20, false)));
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt32LE(20)));
d->headerPresent = flags[31];
d->footerPresent = !flags[30];
@@ -206,15 +206,15 @@ ByteVector APE::Footer::render(bool isHeader) const
// add the version number -- we always render a 2.000 tag regardless of what
// the tag originally was.
v.append(ByteVector::fromUInt(2000, false));
v.append(ByteVector::fromUInt32LE(2000));
// add the tag size
v.append(ByteVector::fromUInt(d->tagSize, false));
v.append(ByteVector::fromUInt32LE(d->tagSize));
// add the item count
v.append(ByteVector::fromUInt(d->itemCount, false));
v.append(ByteVector::fromUInt32LE(d->itemCount));
// render and add the flags
@@ -224,11 +224,11 @@ ByteVector APE::Footer::render(bool isHeader) const
flags[30] = false; // footer is always present
flags[29] = isHeader;
v.append(ByteVector::fromUInt(flags.to_ulong(), false));
v.append(ByteVector::fromUInt32LE(flags.to_ulong()));
// add the reserved 64bit
v.append(ByteVector::fromLongLong(0));
v.append(ByteVector::fromUInt64BE(0));
return v;
}

View File

@@ -54,7 +54,7 @@ namespace TagLib {
* Constructs an APE footer based on \a data. parse() is called
* immediately.
*/
Footer(const ByteVector &data);
explicit Footer(const ByteVector &data);
/*!
* Destroys the footer.

View File

@@ -25,17 +25,17 @@
#include <tbytevectorlist.h>
#include <tdebug.h>
#include <tsmartptr.h>
#include "apeitem.h"
using namespace TagLib;
using namespace APE;
class APE::Item::ItemPrivate
struct ItemData
{
public:
ItemPrivate() :
type(Text),
ItemData() :
type(Item::Text),
readOnly(false) {}
Item::ItemTypes type;
@@ -45,6 +45,15 @@ public:
bool readOnly;
};
class APE::Item::ItemPrivate
{
public:
ItemPrivate() :
data(new ItemData()) {}
SHARED_PTR<ItemData> data;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
@@ -57,27 +66,27 @@ APE::Item::Item() :
APE::Item::Item(const String &key, const String &value) :
d(new ItemPrivate())
{
d->key = key;
d->text.append(value);
d->data->key = key;
d->data->text.append(value);
}
APE::Item::Item(const String &key, const StringList &values) :
d(new ItemPrivate())
{
d->key = key;
d->text = values;
d->data->key = key;
d->data->text = values;
}
APE::Item::Item(const String &key, const ByteVector &value, bool binary) :
d(new ItemPrivate())
{
d->key = key;
d->data->key = key;
if(binary) {
d->type = Binary;
d->value = value;
d->data->type = Binary;
d->data->value = value;
}
else {
d->text.append(value);
d->data->text.append(value);
}
}
@@ -106,135 +115,122 @@ void APE::Item::swap(Item &item)
void APE::Item::setReadOnly(bool readOnly)
{
d->readOnly = readOnly;
d->data->readOnly = readOnly;
}
bool APE::Item::isReadOnly() const
{
return d->readOnly;
return d->data->readOnly;
}
void APE::Item::setType(APE::Item::ItemTypes val)
{
d->type = val;
d->data->type = val;
}
APE::Item::ItemTypes APE::Item::type() const
{
return d->type;
return d->data->type;
}
String APE::Item::key() const
{
return d->key;
return d->data->key;
}
ByteVector APE::Item::binaryData() const
{
return d->value;
return d->data->value;
}
void APE::Item::setBinaryData(const ByteVector &value)
{
d->type = Binary;
d->value = value;
d->text.clear();
}
ByteVector APE::Item::value() const
{
// This seems incorrect as it won't be actually rendering the value to keep it
// up to date.
return d->value;
d->data->type = Binary;
d->data->value = value;
d->data->text.clear();
}
void APE::Item::setKey(const String &key)
{
d->key = key;
d->data->key = key;
}
void APE::Item::setValue(const String &value)
{
d->type = Text;
d->text = value;
d->value.clear();
d->data->type = Text;
d->data->text = value;
d->data->value.clear();
}
void APE::Item::setValues(const StringList &value)
{
d->type = Text;
d->text = value;
d->value.clear();
d->data->type = Text;
d->data->text = value;
d->data->value.clear();
}
void APE::Item::appendValue(const String &value)
{
d->type = Text;
d->text.append(value);
d->value.clear();
d->data->type = Text;
d->data->text.append(value);
d->data->value.clear();
}
void APE::Item::appendValues(const StringList &values)
{
d->type = Text;
d->text.append(values);
d->value.clear();
d->data->type = Text;
d->data->text.append(values);
d->data->value.clear();
}
int APE::Item::size() const
{
int result = 8 + d->key.size() + 1;
switch(d->type) {
size_t result = 8 + d->data->key.size() + 1;
switch(d->data->type) {
case Text:
if(!d->text.isEmpty()) {
StringList::ConstIterator it = d->text.begin();
if(!d->data->text.isEmpty()) {
StringList::ConstIterator it = d->data->text.begin();
result += it->data(String::UTF8).size();
it++;
for(; it != d->text.end(); ++it)
for(; it != d->data->text.end(); ++it)
result += 1 + it->data(String::UTF8).size();
}
break;
case Binary:
case Locator:
result += d->value.size();
result += d->data->value.size();
break;
}
return result;
}
StringList APE::Item::toStringList() const
{
return d->text;
return static_cast<int>(result);
}
StringList APE::Item::values() const
{
return d->text;
return d->data->text;
}
String APE::Item::toString() const
{
if(d->type == Text && !isEmpty())
return d->text.front();
if(d->data->type == Text && !isEmpty())
return d->data->text.front();
else
return String();
}
bool APE::Item::isEmpty() const
{
switch(d->type) {
switch(d->data->type) {
case Text:
if(d->text.isEmpty())
if(d->data->text.isEmpty())
return true;
if(d->text.size() == 1 && d->text.front().isEmpty())
if(d->data->text.size() == 1 && d->data->text.front().isEmpty())
return true;
return false;
case Binary:
case Locator:
return d->value.isEmpty();
return d->data->value.isEmpty();
default:
return false;
}
@@ -249,51 +245,51 @@ void APE::Item::parse(const ByteVector &data)
return;
}
const unsigned int valueLength = data.toUInt(0, false);
const unsigned int flags = data.toUInt(4, false);
const unsigned int valueLength = data.toUInt32LE(0);
const unsigned int flags = data.toUInt32LE(4);
// An item key can contain ASCII characters from 0x20 up to 0x7E, not UTF-8.
// We assume that the validity of the given key has been checked.
d->key = String(&data[8], String::Latin1);
d->data->key = String(&data[8], String::Latin1);
const ByteVector value = data.mid(8 + d->key.size() + 1, valueLength);
const ByteVector value = data.mid(8 + d->data->key.size() + 1, valueLength);
setReadOnly(flags & 1);
setType(ItemTypes((flags >> 1) & 3));
if(Text == d->type)
d->text = StringList(ByteVectorList::split(value, '\0'), String::UTF8);
if(Text == d->data->type)
d->data->text = StringList(ByteVectorList::split(value, '\0'), String::UTF8);
else
d->value = value;
d->data->value = value;
}
ByteVector APE::Item::render() const
{
ByteVector data;
unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
unsigned int flags = ((d->data->readOnly) ? 1 : 0) | (d->data->type << 1);
ByteVector value;
if(isEmpty())
return data;
if(d->type == Text) {
StringList::ConstIterator it = d->text.begin();
if(d->data->type == Text) {
StringList::ConstIterator it = d->data->text.begin();
value.append(it->data(String::UTF8));
it++;
for(; it != d->text.end(); ++it) {
for(; it != d->data->text.end(); ++it) {
value.append('\0');
value.append(it->data(String::UTF8));
}
d->value = value;
d->data->value = value;
}
else
value.append(d->value);
value.append(d->data->value);
data.append(ByteVector::fromUInt(value.size(), false));
data.append(ByteVector::fromUInt(flags, false));
data.append(d->key.data(String::Latin1));
data.append(ByteVector::fromUInt32LE(value.size()));
data.append(ByteVector::fromUInt32LE(flags));
data.append(d->data->key.data(String::Latin1));
data.append(ByteVector('\0'));
data.append(value);

View File

@@ -61,7 +61,6 @@ namespace TagLib {
/*!
* Constructs a text item with \a key and \a value.
*/
// BIC: Remove this, StringList has a constructor from a single string
Item(const String &key, const String &value);
/*!
@@ -112,11 +111,6 @@ namespace TagLib {
*/
void setBinaryData(const ByteVector &value);
#ifndef DO_NOT_DOCUMENT
/* Remove in next binary incompatible release */
ByteVector value() const;
#endif
/*!
* Sets the key for the item to \a key.
*/
@@ -163,11 +157,6 @@ namespace TagLib {
*/
String toString() const;
#ifndef DO_NOT_DOCUMENT
/* Remove in next binary incompatible release */
StringList toStringList() const;
#endif
/*!
* Returns the list of text values. If the data type is not \a Text, always
* returns an empty StringList.

View File

@@ -29,7 +29,7 @@
#include <tstring.h>
#include <tdebug.h>
#include <bitset>
#include "id3v2tag.h"
#include "apeproperties.h"
#include "apefile.h"
@@ -38,7 +38,7 @@
using namespace TagLib;
class APE::Properties::PropertiesPrivate
class APE::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() :
@@ -63,66 +63,59 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
APE::Properties::Properties(File *, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
debug("APE::Properties::Properties() -- This constructor is no longer used.");
}
APE::Properties::Properties(File *file, long streamLength, ReadStyle style) :
AudioProperties(style),
APE::AudioProperties::AudioProperties(File *file, long long streamLength, ReadStyle) :
TagLib::AudioProperties(),
d(new PropertiesPrivate())
{
read(file, streamLength);
}
APE::Properties::~Properties()
APE::AudioProperties::~AudioProperties()
{
delete d;
}
int APE::Properties::length() const
int APE::AudioProperties::length() const
{
return lengthInSeconds();
}
int APE::Properties::lengthInSeconds() const
int APE::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int APE::Properties::lengthInMilliseconds() const
int APE::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int APE::Properties::bitrate() const
int APE::AudioProperties::bitrate() const
{
return d->bitrate;
}
int APE::Properties::sampleRate() const
int APE::AudioProperties::sampleRate() const
{
return d->sampleRate;
}
int APE::Properties::channels() const
int APE::AudioProperties::channels() const
{
return d->channels;
}
int APE::Properties::version() const
int APE::AudioProperties::version() const
{
return d->version;
}
int APE::Properties::bitsPerSample() const
int APE::AudioProperties::bitsPerSample() const
{
return d->bitsPerSample;
}
unsigned int APE::Properties::sampleFrames() const
unsigned int APE::AudioProperties::sampleFrames() const
{
return d->sampleFrames;
}
@@ -138,14 +131,14 @@ namespace
if(header.size() < 6 || !header.startsWith("MAC "))
return -1;
return header.toUShort(4, false);
return header.toUInt16LE(4);
}
}
void APE::Properties::read(File *file, long streamLength)
void APE::AudioProperties::read(File *file, long long streamLength)
{
// First, we assume that the file pointer is set at the first descriptor.
long offset = file->tell();
long long offset = file->tell();
int version = headerVersion(file->readBlock(6));
// Next, we look for the descriptor.
@@ -156,7 +149,7 @@ void APE::Properties::read(File *file, long streamLength)
}
if(version < 0) {
debug("APE::Properties::read() -- APE descriptor not found");
debug("APE::AudioProperties::read() -- APE descriptor not found");
return;
}
@@ -174,17 +167,17 @@ void APE::Properties::read(File *file, long streamLength)
}
}
void APE::Properties::analyzeCurrent(File *file)
void APE::AudioProperties::analyzeCurrent(File *file)
{
// Read the descriptor
file->seek(2, File::Current);
const ByteVector descriptor = file->readBlock(44);
if(descriptor.size() < 44) {
debug("APE::Properties::analyzeCurrent() -- descriptor is too short.");
debug("APE::AudioProperties::analyzeCurrent() -- descriptor is too short.");
return;
}
const unsigned int descriptorBytes = descriptor.toUInt(0, false);
const unsigned int descriptorBytes = descriptor.toUInt32LE(0);
if((descriptorBytes - 52) > 0)
file->seek(descriptorBytes - 52, File::Current);
@@ -192,39 +185,39 @@ void APE::Properties::analyzeCurrent(File *file)
// Read the header
const ByteVector header = file->readBlock(24);
if(header.size() < 24) {
debug("APE::Properties::analyzeCurrent() -- MAC header is too short.");
debug("APE::AudioProperties::analyzeCurrent() -- MAC header is too short.");
return;
}
// Get the APE info
d->channels = header.toShort(18, false);
d->sampleRate = header.toUInt(20, false);
d->bitsPerSample = header.toShort(16, false);
d->channels = header.toUInt16LE(18);
d->sampleRate = header.toUInt32LE(20);
d->bitsPerSample = header.toUInt16LE(16);
const unsigned int totalFrames = header.toUInt(12, false);
const unsigned int totalFrames = header.toUInt32LE(12);
if(totalFrames == 0)
return;
const unsigned int blocksPerFrame = header.toUInt(4, false);
const unsigned int finalFrameBlocks = header.toUInt(8, false);
const unsigned int blocksPerFrame = header.toUInt32LE(4);
const unsigned int finalFrameBlocks = header.toUInt32LE(8);
d->sampleFrames = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks;
}
void APE::Properties::analyzeOld(File *file)
void APE::AudioProperties::analyzeOld(File *file)
{
const ByteVector header = file->readBlock(26);
if(header.size() < 26) {
debug("APE::Properties::analyzeOld() -- MAC header is too short.");
debug("APE::AudioProperties::analyzeOld() -- MAC header is too short.");
return;
}
const unsigned int totalFrames = header.toUInt(18, false);
const unsigned int totalFrames = header.toUInt32LE(18);
// Fail on 0 length APE files (catches non-finalized APE files)
if(totalFrames == 0)
return;
const short compressionLevel = header.toShort(0, false);
const short compressionLevel = header.toUInt32LE(0);
unsigned int blocksPerFrame;
if(d->version >= 3950)
blocksPerFrame = 73728 * 4;
@@ -234,19 +227,19 @@ void APE::Properties::analyzeOld(File *file)
blocksPerFrame = 9216;
// Get the APE info
d->channels = header.toShort(4, false);
d->sampleRate = header.toUInt(6, false);
d->channels = header.toUInt16LE(4);
d->sampleRate = header.toUInt32LE(6);
const unsigned int finalFrameBlocks = header.toUInt(22, false);
const unsigned int finalFrameBlocks = header.toUInt32LE(22);
d->sampleFrames = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks;
// Get the bit depth from the RIFF-fmt chunk.
file->seek(16, File::Current);
const ByteVector fmt = file->readBlock(28);
if(fmt.size() < 28 || !fmt.startsWith("WAVEfmt ")) {
debug("APE::Properties::analyzeOld() -- fmt header is too short.");
debug("APE::AudioProperties::analyzeOld() -- fmt header is too short.");
return;
}
d->bitsPerSample = fmt.toShort(26, false);
d->bitsPerSample = fmt.toUInt16LE(26);
}

View File

@@ -46,27 +46,19 @@ namespace TagLib {
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
/*!
* Create an instance of APE::Properties with the data read from the
* APE::File \a file.
*
* \deprecated
*/
Properties(File *file, ReadStyle style = Average);
AudioProperties(File *file, long long streamLength, ReadStyle style = Average);
/*!
* Create an instance of APE::Properties with the data read from the
* APE::File \a file.
* Destroys this APE::AudioProperties instance.
*/
Properties(File *file, long streamLength, ReadStyle style = Average);
/*!
* Destroys this APE::Properties instance.
*/
virtual ~Properties();
virtual ~AudioProperties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
@@ -84,16 +76,14 @@ namespace TagLib {
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
virtual int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
virtual int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
@@ -126,11 +116,7 @@ namespace TagLib {
int version() const;
private:
Properties(const Properties &);
Properties &operator=(const Properties &);
void read(File *file, long streamLength);
void read(File *file, long long streamLength);
void analyzeCurrent(File *file);
void analyzeOld(File *file);

View File

@@ -34,6 +34,7 @@
#include <tfile.h>
#include <tstring.h>
#include <tmap.h>
#include <tpicturemap.h>
#include <tpropertymap.h>
#include <tdebug.h>
#include <tutils.h>
@@ -80,7 +81,7 @@ public:
footerLocation(0) {}
File *file;
long footerLocation;
long long footerLocation;
Footer footer;
ItemListMap itemListMap;
@@ -96,7 +97,7 @@ APE::Tag::Tag() :
{
}
APE::Tag::Tag(TagLib::File *file, long footerLocation) :
APE::Tag::Tag(TagLib::File *file, long long footerLocation) :
TagLib::Tag(),
d(new TagPrivate())
{
@@ -165,6 +166,42 @@ unsigned int APE::Tag::track() const
return d->itemListMap["TRACK"].toString().toInt();
}
TagLib::PictureMap APE::Tag::pictures() const
{
PictureMap map;
if(d->itemListMap.contains(FRONT_COVER)) {
Item front = d->itemListMap[FRONT_COVER];
if(Item::Binary == front.type()) {
ByteVector picture = front.binaryData();
const size_t index = picture.find('\0');
if(index < picture.size()) {
ByteVector desc = picture.mid(0, index + 1);
String mime = "image/jpeg";
ByteVector data = picture.mid(index + 1);
Picture p(data, Picture::FrontCover, mime, desc);
map.insert(p);
}
}
}
if(d->itemListMap.contains(BACK_COVER)) {
Item back = d->itemListMap[BACK_COVER];
if(Item::Binary == back.type()) {
ByteVector picture = back.binaryData();
const size_t index = picture.find('\0');
if(index < picture.size()) {
ByteVector desc = picture.mid(0, index + 1);
String mime = "image/jpeg";
ByteVector data = picture.mid(index + 1);
Picture p(data, Picture::BackCover, mime, desc);
map.insert(p);
}
}
}
return PictureMap(map);
}
void APE::Tag::setTitle(const String &s)
{
addValue("TITLE", s, true);
@@ -206,6 +243,63 @@ void APE::Tag::setTrack(unsigned int i)
addValue("TRACK", String::number(i), true);
}
void APE::Tag::setPictures(const PictureMap &l)
{
removeItem(FRONT_COVER);
removeItem(BACK_COVER);
for(PictureMap::ConstIterator pictureMapIt = l.begin();
pictureMapIt != l.end();
++pictureMapIt) {
Picture::Type type = pictureMapIt->first;
if(Picture::FrontCover != type && Picture::BackCover != type) {
std::cout << "APE: Trying to add a picture with wrong type"
<< std::endl;
continue;
}
const char *id;
switch(type) {
case Picture::FrontCover:
id = FRONT_COVER;
break;
case Picture::BackCover:
id = BACK_COVER;
break;
default:
id = FRONT_COVER;
break;
}
PictureList list = pictureMapIt->second;
for(PictureList::ConstIterator pictureListIt = list.begin();
pictureListIt != list.end();
++pictureListIt) {
Picture picture = *pictureListIt;
if(d->itemListMap.contains(id)) {
std::cout << "APE: Already added a picture of type "
<< id
<< " '"
<< picture.description()
<< "' "
<< "and next are being ignored"
<< std::endl;
break;
}
ByteVector data = picture.description().data(String::Latin1)
.append('\0')
.append(picture.data());
Item item;
item.setKey(id);
item.setType(Item::Binary);
item.setBinaryData(data);
setItem(item.key(), item);
}
}
}
namespace
{
// conversions of tag keys between what we use in PropertyMap and what's usual
@@ -236,7 +330,7 @@ PropertyMap APE::Tag::properties() const
if(tagName == keyConversions[i][1])
tagName = keyConversions[i][0];
}
properties[tagName].append(it->second.toStringList());
properties[tagName].append(it->second.values());
}
}
return properties;
@@ -393,7 +487,7 @@ ByteVector APE::Tag::render() const
}
d->footer.setItemCount(itemCount);
d->footer.setTagSize(data.size() + Footer::size());
d->footer.setTagSize(static_cast<unsigned int>(data.size() + Footer::size()));
d->footer.setHeaderPresent(true);
return d->footer.renderHeader() + data + d->footer.renderFooter();
@@ -406,18 +500,18 @@ void APE::Tag::parse(const ByteVector &data)
if(data.size() < 11)
return;
unsigned int pos = 0;
size_t pos = 0;
for(unsigned int i = 0; i < d->footer.itemCount() && pos <= data.size() - 11; i++) {
const int nullPos = data.find('\0', pos + 8);
if(nullPos < 0) {
const size_t nullPos = data.find('\0', pos + 8);
if(nullPos == ByteVector::npos()) {
debug("APE::Tag::parse() - Couldn't find a key/value separator. Stopped parsing.");
return;
}
const unsigned int keyLength = nullPos - pos - 8;
const unsigned int valLegnth = data.toUInt(pos, false);
const size_t keyLength = nullPos - pos - 8;
const size_t valLegnth = data.toUInt32LE(pos);
if(keyLength >= MinKeyLength
&& keyLength <= MaxKeyLength

View File

@@ -34,6 +34,9 @@
#include "apeitem.h"
#define FRONT_COVER "COVER ART (FRONT)"
#define BACK_COVER "COVER ART (BACK)"
namespace TagLib {
class File;
@@ -49,7 +52,7 @@ namespace TagLib {
*
* \see APE::Tag::itemListMap()
*/
typedef Map<const String, Item> ItemListMap;
typedef Map<String, Item> ItemListMap;
//! An APE tag implementation
@@ -66,7 +69,7 @@ namespace TagLib {
* Create an APE tag and parse the data in \a file with APE footer at
* \a tagOffset.
*/
Tag(TagLib::File *file, long footerLocation);
Tag(TagLib::File *file, long long footerLocation);
/*!
* Destroys this Tag instance.
@@ -95,6 +98,15 @@ namespace TagLib {
virtual unsigned int year() const;
virtual unsigned int track() const;
/**
* @brief pictures
* According to :
* http://www.hydrogenaud.io/forums/index.php?showtopic=40603&st=50&p=504669&#entry504669
* http://git.videolan.org/?p=vlc.git;a=blob;f=modules/meta_engine/taglib.cpp
* @return
*/
virtual PictureMap pictures() const;
virtual void setTitle(const String &s);
virtual void setArtist(const String &s);
virtual void setAlbum(const String &s);
@@ -102,6 +114,7 @@ namespace TagLib {
virtual void setGenre(const String &s);
virtual void setYear(unsigned int i);
virtual void setTrack(unsigned int i);
virtual void setPictures(const PictureMap &l);
/*!
* Implements the unified tag dictionary interface -- export function.

View File

@@ -1,4 +1,4 @@
/**************************************************************************
/**************************************************************************
copyright : (C) 2005-2007 by Lukáš Lalinský
email : lalinsky@gmail.com
**************************************************************************/
@@ -25,7 +25,7 @@
#include <taglib.h>
#include <tdebug.h>
#include <trefcounter.h>
#include <tsmartptr.h>
#include "asfattribute.h"
#include "asffile.h"
@@ -33,21 +33,35 @@
using namespace TagLib;
class ASF::Attribute::AttributePrivate : public RefCounter
namespace
{
struct AttributeData
{
AttributeData() :
numericValue(0),
stream(0),
language(0) {}
ASF::Attribute::AttributeTypes type;
String stringValue;
ByteVector byteVectorValue;
ASF::Picture pictureValue;
unsigned long long numericValue;
int stream;
int language;
};
}
class ASF::Attribute::AttributePrivate
{
public:
AttributePrivate() :
pictureValue(ASF::Picture::fromInvalid()),
numericValue(0),
stream(0),
language(0) {}
AttributeTypes type;
String stringValue;
ByteVector byteVectorValue;
ASF::Picture pictureValue;
unsigned long long numericValue;
int stream;
int language;
data(new AttributeData())
{
data->pictureValue = ASF::Picture::fromInvalid();
}
SHARED_PTR<AttributeData> data;
};
////////////////////////////////////////////////////////////////////////////////
@@ -57,62 +71,61 @@ public:
ASF::Attribute::Attribute() :
d(new AttributePrivate())
{
d->type = UnicodeType;
d->data->type = UnicodeType;
}
ASF::Attribute::Attribute(const ASF::Attribute &other) :
d(other.d)
d(new AttributePrivate(*other.d))
{
d->ref();
}
ASF::Attribute::Attribute(const String &value) :
d(new AttributePrivate())
{
d->type = UnicodeType;
d->stringValue = value;
d->data->type = UnicodeType;
d->data->stringValue = value;
}
ASF::Attribute::Attribute(const ByteVector &value) :
d(new AttributePrivate())
{
d->type = BytesType;
d->byteVectorValue = value;
d->data->type = BytesType;
d->data->byteVectorValue = value;
}
ASF::Attribute::Attribute(const ASF::Picture &value) :
d(new AttributePrivate())
{
d->type = BytesType;
d->pictureValue = value;
d->data->type = BytesType;
d->data->pictureValue = value;
}
ASF::Attribute::Attribute(unsigned int value) :
d(new AttributePrivate())
{
d->type = DWordType;
d->numericValue = value;
d->data->type = DWordType;
d->data->numericValue = value;
}
ASF::Attribute::Attribute(unsigned long long value) :
d(new AttributePrivate())
{
d->type = QWordType;
d->numericValue = value;
d->data->type = QWordType;
d->data->numericValue = value;
}
ASF::Attribute::Attribute(unsigned short value) :
d(new AttributePrivate())
{
d->type = WordType;
d->numericValue = value;
d->data->type = WordType;
d->data->numericValue = value;
}
ASF::Attribute::Attribute(bool value) :
d(new AttributePrivate())
{
d->type = BoolType;
d->numericValue = value;
d->data->type = BoolType;
d->data->numericValue = value;
}
ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other)
@@ -130,62 +143,62 @@ void ASF::Attribute::swap(Attribute &other)
ASF::Attribute::~Attribute()
{
if(d->deref())
delete d;
delete d;
}
ASF::Attribute::AttributeTypes ASF::Attribute::type() const
{
return d->type;
return d->data->type;
}
String ASF::Attribute::toString() const
{
return d->stringValue;
return d->data->stringValue;
}
ByteVector ASF::Attribute::toByteVector() const
{
if(d->pictureValue.isValid())
return d->pictureValue.render();
return d->byteVectorValue;
if(d->data->pictureValue.isValid())
return d->data->pictureValue.render();
return d->data->byteVectorValue;
}
unsigned short ASF::Attribute::toBool() const
{
return d->numericValue ? 1 : 0;
return d->data->numericValue ? 1 : 0;
}
unsigned short ASF::Attribute::toUShort() const
{
return static_cast<unsigned short>(d->numericValue);
return static_cast<unsigned short>(d->data->numericValue);
}
unsigned int ASF::Attribute::toUInt() const
{
return static_cast<unsigned int>(d->numericValue);
return static_cast<unsigned int>(d->data->numericValue);
}
unsigned long long ASF::Attribute::toULongLong() const
{
return static_cast<unsigned long long>(d->numericValue);
return static_cast<unsigned long long>(d->data->numericValue);
}
ASF::Picture ASF::Attribute::toPicture() const
{
return d->pictureValue;
return d->data->pictureValue;
}
String ASF::Attribute::parse(ASF::File &f, int kind)
{
unsigned int size, nameLength;
String name;
d->pictureValue = Picture::fromInvalid();
d->data->pictureValue = Picture::fromInvalid();
// extended content descriptor
if(kind == 0) {
nameLength = readWORD(&f);
name = readString(&f, nameLength);
d->type = ASF::Attribute::AttributeTypes(readWORD(&f));
d->data->type = ASF::Attribute::AttributeTypes(readWORD(&f));
size = readWORD(&f);
}
// metadata & metadata library
@@ -193,11 +206,11 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
int temp = readWORD(&f);
// metadata library
if(kind == 2) {
d->language = temp;
d->data->language = temp;
}
d->stream = readWORD(&f);
d->data->stream = readWORD(&f);
nameLength = readWORD(&f);
d->type = ASF::Attribute::AttributeTypes(readWORD(&f));
d->data->type = ASF::Attribute::AttributeTypes(readWORD(&f));
size = readDWORD(&f);
name = readString(&f, nameLength);
}
@@ -206,42 +219,42 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
debug("ASF::Attribute::parse() -- Value larger than 64kB");
}
switch(d->type) {
switch(d->data->type) {
case WordType:
d->numericValue = readWORD(&f);
d->data->numericValue = readWORD(&f);
break;
case BoolType:
if(kind == 0) {
d->numericValue = (readDWORD(&f) != 0);
d->data->numericValue = (readDWORD(&f) != 0);
}
else {
d->numericValue = (readWORD(&f) != 0);
d->data->numericValue = (readWORD(&f) != 0);
}
break;
case DWordType:
d->numericValue = readDWORD(&f);
d->data->numericValue = readDWORD(&f);
break;
case QWordType:
d->numericValue = readQWORD(&f);
d->data->numericValue = readQWORD(&f);
break;
case UnicodeType:
d->stringValue = readString(&f, size);
d->data->stringValue = readString(&f, size);
break;
case BytesType:
case GuidType:
d->byteVectorValue = f.readBlock(size);
d->data->byteVectorValue = f.readBlock(size);
break;
}
if(d->type == BytesType && name == "WM/Picture") {
d->pictureValue.parse(d->byteVectorValue);
if(d->pictureValue.isValid()) {
d->byteVectorValue.clear();
if(d->data->type == BytesType && name == "WM/Picture") {
d->data->pictureValue.parse(d->data->byteVectorValue);
if(d->data->pictureValue.isValid()) {
d->data->byteVectorValue.clear();
}
}
@@ -250,7 +263,7 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
int ASF::Attribute::dataSize() const
{
switch (d->type) {
switch (d->data->type) {
case WordType:
return 2;
case BoolType:
@@ -260,12 +273,12 @@ int ASF::Attribute::dataSize() const
case QWordType:
return 5;
case UnicodeType:
return d->stringValue.size() * 2 + 2;
return static_cast<int>(d->data->stringValue.size() * 2 + 2);
case BytesType:
if(d->pictureValue.isValid())
return d->pictureValue.dataSize();
if(d->data->pictureValue.isValid())
return d->data->pictureValue.dataSize();
case GuidType:
return d->byteVectorValue.size();
return static_cast<int>(d->data->byteVectorValue.size());
}
return 0;
}
@@ -274,55 +287,55 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
{
ByteVector data;
switch (d->type) {
switch (d->data->type) {
case WordType:
data.append(ByteVector::fromShort(toUShort(), false));
data.append(ByteVector::fromUInt16LE(toUShort()));
break;
case BoolType:
if(kind == 0) {
data.append(ByteVector::fromUInt(toBool(), false));
data.append(ByteVector::fromUInt32LE(toBool()));
}
else {
data.append(ByteVector::fromShort(toBool(), false));
data.append(ByteVector::fromUInt16LE(toBool()));
}
break;
case DWordType:
data.append(ByteVector::fromUInt(toUInt(), false));
data.append(ByteVector::fromUInt32LE(toUInt()));
break;
case QWordType:
data.append(ByteVector::fromLongLong(toULongLong(), false));
data.append(ByteVector::fromUInt64LE(toULongLong()));
break;
case UnicodeType:
data.append(renderString(d->stringValue));
data.append(renderString(d->data->stringValue));
break;
case BytesType:
if(d->pictureValue.isValid()) {
data.append(d->pictureValue.render());
if(d->data->pictureValue.isValid()) {
data.append(d->data->pictureValue.render());
break;
}
case GuidType:
data.append(d->byteVectorValue);
data.append(d->data->byteVectorValue);
break;
}
if(kind == 0) {
data = renderString(name, true) +
ByteVector::fromShort((int)d->type, false) +
ByteVector::fromShort(data.size(), false) +
ByteVector::fromUInt16LE((int)d->data->type) +
ByteVector::fromUInt16LE(data.size()) +
data;
}
else {
ByteVector nameData = 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) +
data = ByteVector::fromUInt16LE(kind == 2 ? d->data->language : 0) +
ByteVector::fromUInt16LE(d->data->stream) +
ByteVector::fromUInt16LE(nameData.size()) +
ByteVector::fromUInt16LE((int)d->data->type) +
ByteVector::fromUInt32LE(data.size()) +
nameData +
data;
}
@@ -332,20 +345,20 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
int ASF::Attribute::language() const
{
return d->language;
return d->data->language;
}
void ASF::Attribute::setLanguage(int value)
{
d->language = value;
d->data->language = value;
}
int ASF::Attribute::stream() const
{
return d->stream;
return d->data->stream;
}
void ASF::Attribute::setStream(int value)
{
d->stream = value;
d->data->stream = value;
}

View File

@@ -36,7 +36,6 @@ namespace TagLib
namespace ASF
{
class File;
class Picture;
@@ -185,17 +184,13 @@ namespace TagLib
*/
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;
String parse(ASF::File &file, int kind = 0);
ByteVector render(const String &name, int kind = 0) const;
class AttributePrivate;

View File

@@ -28,6 +28,7 @@
#include <tpropertymap.h>
#include <tstring.h>
#include <tagutils.h>
#include <tsmartptr.h>
#include "asffile.h"
#include "asftag.h"
@@ -50,37 +51,24 @@ public:
class MetadataObject;
class MetadataLibraryObject;
FilePrivate():
headerSize(0),
tag(0),
properties(0),
contentDescriptionObject(0),
extendedContentDescriptionObject(0),
headerExtensionObject(0),
metadataObject(0),
metadataLibraryObject(0)
{
objects.setAutoDelete(true);
}
typedef List<SHARED_PTR<BaseObject> > ObjectList;
typedef ObjectList::ConstIterator ObjectConstIterator;
~FilePrivate()
{
delete tag;
delete properties;
}
FilePrivate():
headerSize(0) {}
unsigned long long headerSize;
ASF::Tag *tag;
ASF::Properties *properties;
SCOPED_PTR<ASF::Tag> tag;
SCOPED_PTR<ASF::AudioProperties> properties;
List<BaseObject *> objects;
ObjectList objects;
ContentDescriptionObject *contentDescriptionObject;
ExtendedContentDescriptionObject *extendedContentDescriptionObject;
HeaderExtensionObject *headerExtensionObject;
MetadataObject *metadataObject;
MetadataLibraryObject *metadataLibraryObject;
SHARED_PTR<ContentDescriptionObject> contentDescriptionObject;
SHARED_PTR<ExtendedContentDescriptionObject> extendedContentDescriptionObject;
SHARED_PTR<HeaderExtensionObject> headerExtensionObject;
SHARED_PTR<MetadataObject> metadataObject;
SHARED_PTR<MetadataLibraryObject> metadataLibraryObject;
};
namespace
@@ -113,7 +101,7 @@ class ASF::File::FilePrivate::UnknownObject : public ASF::File::FilePrivate::Bas
{
ByteVector myGuid;
public:
UnknownObject(const ByteVector &guid);
explicit UnknownObject(const ByteVector &guid);
ByteVector guid() const;
};
@@ -169,7 +157,7 @@ public:
class ASF::File::FilePrivate::HeaderExtensionObject : public ASF::File::FilePrivate::BaseObject
{
public:
List<ASF::File::FilePrivate::BaseObject *> objects;
ObjectList objects;
HeaderExtensionObject();
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
@@ -194,7 +182,7 @@ private:
void ASF::File::FilePrivate::BaseObject::parse(ASF::File *file, unsigned int size)
{
data.clear();
if(size > 24 && size <= (unsigned int)(file->length()))
if(size > 24 && static_cast<long long>(size) <= file->length())
data = file->readBlock(size - 24);
else
data = ByteVector();
@@ -202,7 +190,7 @@ void ASF::File::FilePrivate::BaseObject::parse(ASF::File *file, unsigned int siz
ByteVector ASF::File::FilePrivate::BaseObject::render(ASF::File * /*file*/)
{
return guid() + ByteVector::fromLongLong(data.size() + 24, false) + data;
return guid() + ByteVector::fromUInt64LE(data.size() + 24) + data;
}
ASF::File::FilePrivate::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid)
@@ -227,8 +215,8 @@ void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, unsign
return;
}
const long long duration = data.toLongLong(40, false);
const long long preroll = data.toLongLong(56, false);
const long long duration = data.toInt64LE(40);
const long long preroll = data.toInt64LE(56);
file->d->properties->setLengthInMilliseconds(static_cast<int>(duration / 10000.0 - preroll + 0.5));
}
@@ -245,11 +233,11 @@ void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsi
return;
}
file->d->properties->setCodec(data.toUShort(54, false));
file->d->properties->setChannels(data.toUShort(56, false));
file->d->properties->setSampleRate(data.toUInt(58, false));
file->d->properties->setBitrate(static_cast<int>(data.toUInt(62, false) * 8.0 / 1000.0 + 0.5));
file->d->properties->setBitsPerSample(data.toUShort(68, false));
file->d->properties->setCodec(data.toUInt16LE(54));
file->d->properties->setChannels(data.toUInt16LE(56));
file->d->properties->setSampleRate(data.toUInt32LE(58));
file->d->properties->setBitrate(static_cast<int>(data.toUInt32LE(62) * 8.0 / 1000.0 + 0.5));
file->d->properties->setBitsPerSample(data.toUInt16LE(68));
}
ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const
@@ -279,11 +267,11 @@ ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *f
const ByteVector v4 = renderString(file->d->tag->comment());
const ByteVector v5 = 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(ByteVector::fromUInt16LE(v1.size()));
data.append(ByteVector::fromUInt16LE(v2.size()));
data.append(ByteVector::fromUInt16LE(v3.size()));
data.append(ByteVector::fromUInt16LE(v4.size()));
data.append(ByteVector::fromUInt16LE(v5.size()));
data.append(v1);
data.append(v2);
data.append(v3);
@@ -310,7 +298,7 @@ void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
@@ -333,7 +321,7 @@ void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, unsigned int
ByteVector ASF::File::FilePrivate::MetadataObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
@@ -356,14 +344,13 @@ void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, unsig
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
ASF::File::FilePrivate::HeaderExtensionObject::HeaderExtensionObject()
{
objects.setAutoDelete(true);
}
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::guid() const
@@ -388,17 +375,17 @@ void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsig
file->setValid(false);
break;
}
BaseObject *obj;
SHARED_PTR<BaseObject> obj;
if(guid == metadataGuid) {
file->d->metadataObject = new MetadataObject();
file->d->metadataObject.reset(new MetadataObject());
obj = file->d->metadataObject;
}
else if(guid == metadataLibraryGuid) {
file->d->metadataLibraryObject = new MetadataLibraryObject();
file->d->metadataLibraryObject.reset(new MetadataLibraryObject());
obj = file->d->metadataLibraryObject;
}
else {
obj = new UnknownObject(guid);
obj.reset(new UnknownObject(guid));
}
obj->parse(file, (unsigned int)size);
objects.append(obj);
@@ -409,10 +396,10 @@ void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsig
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::render(ASF::File *file)
{
data.clear();
for(List<BaseObject *>::ConstIterator it = objects.begin(); it != objects.end(); ++it) {
for(ObjectConstIterator it = objects.begin(); it != objects.end(); ++it) {
data.append((*it)->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;
data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt32LE(data.size()) + data;
return BaseObject::render(file);
}
@@ -431,7 +418,7 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in
unsigned int pos = 16;
const int count = data.toUInt(pos, false);
const int count = data.toUInt32LE(pos);
pos += 4;
for(int i = 0; i < count; ++i) {
@@ -439,22 +426,22 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in
if(pos >= data.size())
break;
const CodecType type = static_cast<CodecType>(data.toUShort(pos, false));
const CodecType type = static_cast<CodecType>(data.toUInt16LE(pos));
pos += 2;
int nameLength = data.toUShort(pos, false);
int nameLength = data.toUInt16LE(pos);
pos += 2;
const unsigned int namePos = pos;
pos += nameLength * 2;
const int descLength = data.toUShort(pos, false);
const int descLength = data.toUInt16LE(pos);
pos += 2;
const unsigned int descPos = pos;
pos += descLength * 2;
const int infoLength = data.toUShort(pos, false);
const int infoLength = data.toUInt16LE(pos);
pos += 2 + infoLength * 2;
if(type == CodecListObject::Audio) {
@@ -487,7 +474,7 @@ bool ASF::File::isSupported(IOStream *stream)
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::File::File(FileName file, bool, Properties::ReadStyle) :
ASF::File::File(FileName file, bool, AudioProperties::ReadStyle) :
TagLib::File(file),
d(new FilePrivate())
{
@@ -495,7 +482,7 @@ ASF::File::File(FileName file, bool, Properties::ReadStyle) :
read();
}
ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) :
ASF::File::File(IOStream *stream, bool, AudioProperties::ReadStyle) :
TagLib::File(stream),
d(new FilePrivate())
{
@@ -510,27 +497,12 @@ ASF::File::~File()
ASF::Tag *ASF::File::tag() const
{
return d->tag;
return d->tag.get();
}
PropertyMap ASF::File::properties() const
ASF::AudioProperties *ASF::File::audioProperties() const
{
return d->tag->properties();
}
void ASF::File::removeUnsupportedProperties(const StringList &properties)
{
d->tag->removeUnsupportedProperties(properties);
}
PropertyMap ASF::File::setProperties(const PropertyMap &properties)
{
return d->tag->setProperties(properties);
}
ASF::Properties *ASF::File::audioProperties() const
{
return d->properties;
return d->properties.get();
}
bool ASF::File::save()
@@ -546,23 +518,23 @@ bool ASF::File::save()
}
if(!d->contentDescriptionObject) {
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
d->contentDescriptionObject.reset(new FilePrivate::ContentDescriptionObject());
d->objects.append(d->contentDescriptionObject);
}
if(!d->extendedContentDescriptionObject) {
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
d->extendedContentDescriptionObject.reset(new FilePrivate::ExtendedContentDescriptionObject());
d->objects.append(d->extendedContentDescriptionObject);
}
if(!d->headerExtensionObject) {
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
d->headerExtensionObject.reset(new FilePrivate::HeaderExtensionObject());
d->objects.append(d->headerExtensionObject);
}
if(!d->metadataObject) {
d->metadataObject = new FilePrivate::MetadataObject();
d->metadataObject.reset(new FilePrivate::MetadataObject());
d->headerExtensionObject->objects.append(d->metadataObject);
}
if(!d->metadataLibraryObject) {
d->metadataLibraryObject = new FilePrivate::MetadataLibraryObject();
d->metadataLibraryObject.reset(new FilePrivate::MetadataLibraryObject());
d->headerExtensionObject->objects.append(d->metadataLibraryObject);
}
@@ -601,16 +573,16 @@ bool ASF::File::save()
}
ByteVector data;
for(List<FilePrivate::BaseObject *>::ConstIterator it = d->objects.begin(); it != d->objects.end(); ++it) {
for(FilePrivate::ObjectConstIterator it = d->objects.begin(); it != d->objects.end(); ++it) {
data.append((*it)->render(this));
}
seek(16);
writeBlock(ByteVector::fromLongLong(data.size() + 30, false));
writeBlock(ByteVector::fromUInt(d->objects.size(), false));
writeBlock(ByteVector::fromUInt64LE(data.size() + 30));
writeBlock(ByteVector::fromUInt32LE(d->objects.size()));
writeBlock(ByteVector("\x01\x02", 2));
insert(data, 30, static_cast<unsigned long>(d->headerSize - 30));
insert(data, 30, static_cast<size_t>(d->headerSize - 30));
d->headerSize = data.size() + 30;
@@ -632,8 +604,8 @@ void ASF::File::read()
return;
}
d->tag = new ASF::Tag();
d->properties = new ASF::Properties();
d->tag.reset(new ASF::Tag());
d->properties.reset(new ASF::AudioProperties());
bool ok;
d->headerSize = readQWORD(this, &ok);
@@ -648,8 +620,8 @@ void ASF::File::read()
}
seek(2, Current);
FilePrivate::FilePropertiesObject *filePropertiesObject = 0;
FilePrivate::StreamPropertiesObject *streamPropertiesObject = 0;
SHARED_PTR<FilePrivate::FilePropertiesObject> filePropertiesObject;
SHARED_PTR<FilePrivate::StreamPropertiesObject> streamPropertiesObject;
for(int i = 0; i < numObjects; i++) {
const ByteVector guid = readBlock(16);
if(guid.size() != 16) {
@@ -661,29 +633,29 @@ void ASF::File::read()
setValid(false);
break;
}
FilePrivate::BaseObject *obj;
SHARED_PTR<FilePrivate::BaseObject> obj;
if(guid == filePropertiesGuid) {
filePropertiesObject = new FilePrivate::FilePropertiesObject();
filePropertiesObject.reset(new FilePrivate::FilePropertiesObject());
obj = filePropertiesObject;
}
else if(guid == streamPropertiesGuid) {
streamPropertiesObject = new FilePrivate::StreamPropertiesObject();
streamPropertiesObject.reset(new FilePrivate::StreamPropertiesObject());
obj = streamPropertiesObject;
}
else if(guid == contentDescriptionGuid) {
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
d->contentDescriptionObject.reset(new FilePrivate::ContentDescriptionObject());
obj = d->contentDescriptionObject;
}
else if(guid == extendedContentDescriptionGuid) {
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
d->extendedContentDescriptionObject.reset(new FilePrivate::ExtendedContentDescriptionObject());
obj = d->extendedContentDescriptionObject;
}
else if(guid == headerExtensionGuid) {
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
d->headerExtensionObject.reset(new FilePrivate::HeaderExtensionObject());
obj = d->headerExtensionObject;
}
else if(guid == codecListGuid) {
obj = new FilePrivate::CodecListObject();
obj.reset(new FilePrivate::CodecListObject());
}
else {
if(guid == contentEncryptionGuid ||
@@ -691,7 +663,7 @@ void ASF::File::read()
guid == advancedContentEncryptionGuid) {
d->properties->setEncrypted(true);
}
obj = new FilePrivate::UnknownObject(guid);
obj.reset(new FilePrivate::UnknownObject(guid));
}
obj->parse(this, size);
d->objects.append(obj);

View File

@@ -48,17 +48,21 @@ namespace TagLib {
public:
/*!
* Constructs an ASF file from \a file.
* 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. The audio properties are always
* read.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Constructs an ASF file from \a stream.
* 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. The audio properties are always
@@ -68,7 +72,7 @@ namespace TagLib {
* responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Destroys this instance of the File.
@@ -87,26 +91,10 @@ namespace TagLib {
*/
virtual Tag *tag() const;
/*!
* Implements the unified property interface -- export function.
*/
PropertyMap properties() const;
/*!
* Removes unsupported properties. Forwards to the actual Tag's
* removeUnsupportedProperties() function.
*/
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the unified property interface -- import function.
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the ASF audio properties for this file.
*/
virtual Properties *audioProperties() const;
virtual AudioProperties *audioProperties() const;
/*!
* Save the file.

View File

@@ -25,7 +25,7 @@
#include <taglib.h>
#include <tdebug.h>
#include <trefcounter.h>
#include <tsmartptr.h>
#include "asfattribute.h"
#include "asffile.h"
@@ -34,14 +34,25 @@
using namespace TagLib;
class ASF::Picture::PicturePrivate : public RefCounter
namespace
{
struct PictureData
{
bool valid;
ASF::Picture::Type type;
String mimeType;
String description;
ByteVector picture;
};
}
class ASF::Picture::PicturePrivate
{
public:
bool valid;
Type type;
String mimeType;
String description;
ByteVector picture;
PicturePrivate() :
data(new PictureData()) {}
SHARED_PTR<PictureData> data;
};
////////////////////////////////////////////////////////////////////////////////
@@ -51,71 +62,69 @@ public:
ASF::Picture::Picture() :
d(new PicturePrivate())
{
d->valid = true;
d->data->valid = true;
}
ASF::Picture::Picture(const Picture& other) :
d(other.d)
d(new PicturePrivate(*other.d))
{
d->ref();
}
ASF::Picture::~Picture()
{
if(d->deref())
delete d;
delete d;
}
bool ASF::Picture::isValid() const
{
return d->valid;
return d->data->valid;
}
String ASF::Picture::mimeType() const
{
return d->mimeType;
return d->data->mimeType;
}
void ASF::Picture::setMimeType(const String &value)
{
d->mimeType = value;
d->data->mimeType = value;
}
ASF::Picture::Type ASF::Picture::type() const
{
return d->type;
return d->data->type;
}
void ASF::Picture::setType(const ASF::Picture::Type& t)
{
d->type = t;
d->data->type = t;
}
String ASF::Picture::description() const
{
return d->description;
return d->data->description;
}
void ASF::Picture::setDescription(const String &desc)
{
d->description = desc;
d->data->description = desc;
}
ByteVector ASF::Picture::picture() const
{
return d->picture;
return d->data->picture;
}
void ASF::Picture::setPicture(const ByteVector &p)
{
d->picture = p;
d->data->picture = p;
}
int ASF::Picture::dataSize() const
{
return
9 + (d->mimeType.length() + d->description.length()) * 2 +
d->picture.size();
return static_cast<int>(
9 + (d->data->mimeType.length() + d->data->description.length()) * 2 +
d->data->picture.size());
}
ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other)
@@ -137,47 +146,47 @@ ByteVector ASF::Picture::render() const
return ByteVector();
return
ByteVector((char)d->type) +
ByteVector::fromUInt(d->picture.size(), false) +
renderString(d->mimeType) +
renderString(d->description) +
d->picture;
ByteVector((char)d->data->type) +
ByteVector::fromUInt32LE(d->data->picture.size()) +
renderString(d->data->mimeType) +
renderString(d->data->description) +
d->data->picture;
}
void ASF::Picture::parse(const ByteVector& bytes)
{
d->valid = false;
d->data->valid = false;
if(bytes.size() < 9)
return;
int pos = 0;
d->type = (Type)bytes[0]; ++pos;
const unsigned int dataLen = bytes.toUInt(pos, false); pos+=4;
size_t pos = 0;
d->data->type = (Type)bytes[0]; ++pos;
const unsigned int dataLen = bytes.toUInt32LE(pos); pos+=4;
const ByteVector nullStringTerminator(2, 0);
int endPos = bytes.find(nullStringTerminator, pos, 2);
if(endPos < 0)
size_t endPos = bytes.find(nullStringTerminator, pos, 2);
if(endPos == ByteVector::npos())
return;
d->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
d->data->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
pos = endPos+2;
endPos = bytes.find(nullStringTerminator, pos, 2);
if(endPos < 0)
if(endPos == ByteVector::npos())
return;
d->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
d->data->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
pos = endPos+2;
if(dataLen + pos != bytes.size())
return;
d->picture = bytes.mid(pos, dataLen);
d->valid = true;
d->data->picture = bytes.mid(pos, dataLen);
d->data->valid = true;
return;
}
ASF::Picture ASF::Picture::fromInvalid()
{
Picture ret;
ret.d->valid = false;
ret.d->data->valid = false;
return ret;
}

View File

@@ -35,6 +35,7 @@ namespace TagLib
{
namespace ASF
{
class Attribute;
//! An ASF attached picture interface implementation
@@ -46,7 +47,8 @@ namespace TagLib
* \see Attribute::toPicture()
* \see Attribute::Attribute(const Picture& picture)
*/
class TAGLIB_EXPORT Picture {
class TAGLIB_EXPORT Picture
{
public:
/*!
@@ -103,7 +105,7 @@ namespace TagLib
Picture();
/*!
* Construct an picture as a copy of \a other.
* Constructs an picture as a copy of \a other.
*/
Picture(const Picture& other);
@@ -206,16 +208,15 @@ namespace TagLib
*/
int dataSize() const;
#ifndef DO_NOT_DOCUMENT
/* THIS IS PRIVATE, DON'T TOUCH IT! */
void parse(const ByteVector& );
static Picture fromInvalid();
#endif
private:
friend class Attribute;
private:
class PicturePrivate;
PicturePrivate *d;
};
void parse(const ByteVector &);
static Picture fromInvalid();
class PicturePrivate;
PicturePrivate *d;
};
}
}

View File

@@ -29,7 +29,7 @@
using namespace TagLib;
class ASF::Properties::PropertiesPrivate
class ASF::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() :
@@ -38,7 +38,7 @@ public:
sampleRate(0),
channels(0),
bitsPerSample(0),
codec(ASF::Properties::Unknown),
codec(ASF::AudioProperties::Unknown),
encrypted(false) {}
int length;
@@ -46,7 +46,7 @@ public:
int sampleRate;
int channels;
int bitsPerSample;
ASF::Properties::Codec codec;
ASF::AudioProperties::Codec codec;
String codecName;
String codecDescription;
bool encrypted;
@@ -56,68 +56,68 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::Properties::Properties() :
AudioProperties(AudioProperties::Average),
ASF::AudioProperties::AudioProperties() :
TagLib::AudioProperties(),
d(new PropertiesPrivate())
{
}
ASF::Properties::~Properties()
ASF::AudioProperties::~AudioProperties()
{
delete d;
}
int ASF::Properties::length() const
int ASF::AudioProperties::length() const
{
return lengthInSeconds();
}
int ASF::Properties::lengthInSeconds() const
int ASF::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int ASF::Properties::lengthInMilliseconds() const
int ASF::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int ASF::Properties::bitrate() const
int ASF::AudioProperties::bitrate() const
{
return d->bitrate;
}
int ASF::Properties::sampleRate() const
int ASF::AudioProperties::sampleRate() const
{
return d->sampleRate;
}
int ASF::Properties::channels() const
int ASF::AudioProperties::channels() const
{
return d->channels;
}
int ASF::Properties::bitsPerSample() const
int ASF::AudioProperties::bitsPerSample() const
{
return d->bitsPerSample;
}
ASF::Properties::Codec ASF::Properties::codec() const
ASF::AudioProperties::Codec ASF::AudioProperties::codec() const
{
return d->codec;
}
String ASF::Properties::codecName() const
String ASF::AudioProperties::codecName() const
{
return d->codecName;
}
String ASF::Properties::codecDescription() const
String ASF::AudioProperties::codecDescription() const
{
return d->codecDescription;
}
bool ASF::Properties::isEncrypted() const
bool ASF::AudioProperties::isEncrypted() const
{
return d->encrypted;
}
@@ -126,37 +126,32 @@ bool ASF::Properties::isEncrypted() const
// private members
////////////////////////////////////////////////////////////////////////////////
void ASF::Properties::setLength(int /*length*/)
{
debug("ASF::Properties::setLength() -- This method is deprecated. Do not use.");
}
void ASF::Properties::setLengthInMilliseconds(int value)
void ASF::AudioProperties::setLengthInMilliseconds(int value)
{
d->length = value;
}
void ASF::Properties::setBitrate(int value)
void ASF::AudioProperties::setBitrate(int value)
{
d->bitrate = value;
}
void ASF::Properties::setSampleRate(int value)
void ASF::AudioProperties::setSampleRate(int value)
{
d->sampleRate = value;
}
void ASF::Properties::setChannels(int value)
void ASF::AudioProperties::setChannels(int value)
{
d->channels = value;
}
void ASF::Properties::setBitsPerSample(int value)
void ASF::AudioProperties::setBitsPerSample(int value)
{
d->bitsPerSample = value;
}
void ASF::Properties::setCodec(int value)
void ASF::AudioProperties::setCodec(int value)
{
switch(value)
{
@@ -178,17 +173,17 @@ void ASF::Properties::setCodec(int value)
}
}
void ASF::Properties::setCodecName(const String &value)
void ASF::AudioProperties::setCodecName(const String &value)
{
d->codecName = value;
}
void ASF::Properties::setCodecDescription(const String &value)
void ASF::AudioProperties::setCodecDescription(const String &value)
{
d->codecDescription = value;
}
void ASF::Properties::setEncrypted(bool value)
void ASF::AudioProperties::setEncrypted(bool value)
{
d->encrypted = value;
}

View File

@@ -34,11 +34,14 @@ namespace TagLib {
namespace ASF {
//! An implementation of ASF audio properties
class TAGLIB_EXPORT Properties : public AudioProperties
{
public:
class File;
//! An implementation of ASF audio properties
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
friend class File;
public:
/*!
* Audio codec types can be used in ASF file.
*/
@@ -71,14 +74,14 @@ namespace TagLib {
};
/*!
* Creates an instance of ASF::Properties.
* Creates an instance of ASF::AudioProperties.
*/
Properties();
AudioProperties();
/*!
* Destroys this ASF::Properties instance.
* Destroys this ASF::AudioProperties instance.
*/
virtual ~Properties();
virtual ~AudioProperties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
@@ -96,16 +99,14 @@ namespace TagLib {
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
virtual int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
virtual int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
@@ -159,10 +160,7 @@ namespace TagLib {
*/
bool isEncrypted() const;
#ifndef DO_NOT_DOCUMENT
// deprecated
void setLength(int value);
private:
void setLengthInMilliseconds(int value);
void setBitrate(int value);
void setSampleRate(int value);
@@ -172,9 +170,7 @@ namespace TagLib {
void setCodecName(const String &value);
void setCodecDescription(const String &value);
void setEncrypted(bool value);
#endif
private:
class PropertiesPrivate;
PropertiesPrivate *d;
};

View File

@@ -23,6 +23,7 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tpicturemap.h>
#include <tpropertymap.h>
#include "asftag.h"
@@ -110,6 +111,91 @@ String ASF::Tag::genre() const
return String();
}
PictureMap ASF::Tag::pictures() const
{
PictureMap map;
if(d->attributeListMap.contains("WM/Picture")) {
AttributeList list = d->attributeListMap["WM/Picture"];
for(AttributeList::ConstIterator it = list.begin();
it != list.end();
++it) {
ASF::Picture asfPicture = (*it).toPicture();
TagLib::Picture::Type type;
switch(asfPicture.type()) {
case ASF::Picture::FileIcon:
type = TagLib::Picture::FileIcon;
break;
case ASF::Picture::OtherFileIcon:
type = TagLib::Picture::OtherFileIcon;
break;
case ASF::Picture::FrontCover:
type = TagLib::Picture::FrontCover;
break;
case ASF::Picture::BackCover:
type = TagLib::Picture::BackCover;
break;
case ASF::Picture::LeafletPage:
type = TagLib::Picture::LeafletPage;
break;
case ASF::Picture::Media:
type = TagLib::Picture::Media;
break;
case ASF::Picture::LeadArtist:
type = TagLib::Picture::LeadArtist;
break;
case ASF::Picture::Artist:
type = TagLib::Picture::Artist;
break;
case ASF::Picture::Conductor:
type = TagLib::Picture::Conductor;
break;
case ASF::Picture::Band:
type = TagLib::Picture::Band;
break;
case ASF::Picture::Composer:
type = TagLib::Picture::Composer;
break;
case ASF::Picture::Lyricist:
type = TagLib::Picture::Lyricist;
break;
case ASF::Picture::RecordingLocation:
type = TagLib::Picture::RecordingLocation;
break;
case ASF::Picture::DuringRecording:
type = TagLib::Picture::DuringRecording;
break;
case ASF::Picture::DuringPerformance:
type = TagLib::Picture::DuringPerformance;
break;
case ASF::Picture::MovieScreenCapture:
type = TagLib::Picture::MovieScreenCapture;
break;
case ASF::Picture::ColouredFish:
type = TagLib::Picture::ColouredFish;
break;
case ASF::Picture::Illustration:
type = TagLib::Picture::Illustration;
break;
case ASF::Picture::BandLogo:
type = TagLib::Picture::BandLogo;
break;
case ASF::Picture::PublisherLogo:
type = TagLib::Picture::PublisherLogo;
break;
default:
type = TagLib::Picture::Other;
break;
}
TagLib::Picture picture(asfPicture.picture(),
type,
asfPicture.mimeType(),
asfPicture.description());
map.insert(picture);
}
}
return PictureMap(map);
}
void ASF::Tag::setTitle(const String &value)
{
d->title = value;
@@ -155,6 +241,94 @@ void ASF::Tag::setTrack(unsigned int value)
setAttribute("WM/TrackNumber", String::number(value));
}
void ASF::Tag::setPictures(const PictureMap &l)
{
removeItem("WM/Picture");
for(PictureMap::ConstIterator pictureMapIt = l.begin();
pictureMapIt != l.end();
++pictureMapIt)
{
PictureList list = pictureMapIt->second;
for( PictureList::ConstIterator pictureListIt = list.begin();
pictureListIt != list.end();
++pictureListIt)
{
const TagLib::Picture picture = (*pictureListIt);
ASF::Picture asfPicture;
asfPicture.setPicture(picture.data());
asfPicture.setMimeType(picture.mime());
asfPicture.setDescription(picture.description());
switch (picture.type()) {
case TagLib::Picture::Other:
asfPicture.setType(ASF::Picture::Other);
break;
case TagLib::Picture::FileIcon:
asfPicture.setType(ASF::Picture::FileIcon);
break;
case TagLib::Picture::OtherFileIcon:
asfPicture.setType(ASF::Picture::OtherFileIcon);
break;
case TagLib::Picture::FrontCover:
asfPicture.setType(ASF::Picture::FrontCover);
break;
case TagLib::Picture::BackCover:
asfPicture.setType(ASF::Picture::BackCover);
break;
case TagLib::Picture::LeafletPage:
asfPicture.setType(ASF::Picture::LeafletPage);
break;
case TagLib::Picture::Media:
asfPicture.setType(ASF::Picture::Media);
break;
case TagLib::Picture::LeadArtist:
asfPicture.setType(ASF::Picture::LeadArtist);
break;
case TagLib::Picture::Artist:
asfPicture.setType(ASF::Picture::Artist);
break;
case TagLib::Picture::Conductor:
asfPicture.setType(ASF::Picture::Conductor);
break;
case TagLib::Picture::Band:
asfPicture.setType(ASF::Picture::Band);
break;
case TagLib::Picture::Composer:
asfPicture.setType(ASF::Picture::Composer);
break;
case TagLib::Picture::Lyricist:
asfPicture.setType(ASF::Picture::Lyricist);
break;
case TagLib::Picture::RecordingLocation:
asfPicture.setType(ASF::Picture::RecordingLocation);
break;
case TagLib::Picture::DuringRecording:
asfPicture.setType(ASF::Picture::DuringRecording);
break;
case TagLib::Picture::DuringPerformance:
asfPicture.setType(ASF::Picture::DuringPerformance);
break;
case TagLib::Picture::MovieScreenCapture:
asfPicture.setType(ASF::Picture::MovieScreenCapture);
break;
case TagLib::Picture::ColouredFish:
asfPicture.setType(ASF::Picture::ColouredFish);
break;
case TagLib::Picture::Illustration:
asfPicture.setType(ASF::Picture::Illustration);
break;
case TagLib::Picture::BandLogo:
asfPicture.setType(ASF::Picture::BandLogo);
break;
case TagLib::Picture::PublisherLogo:
asfPicture.setType(ASF::Picture::PublisherLogo);
break;
}
addAttribute("WM/Picture", Attribute(asfPicture));
}
}
}
ASF::AttributeListMap& ASF::Tag::attributeListMap()
{
return d->attributeListMap;

View File

@@ -98,6 +98,8 @@ namespace TagLib {
*/
virtual unsigned int track() const;
virtual PictureMap pictures() const;
/*!
* Sets the title to \a s.
*/
@@ -144,6 +146,8 @@ namespace TagLib {
*/
virtual void setTrack(unsigned int i);
virtual void setPictures(const PictureMap &l);
/*!
* Returns true if the tag does not contain any data. This should be
* reimplemented in subclasses that provide more than the basic tagging

View File

@@ -45,7 +45,7 @@ namespace TagLib
return 0;
}
if(ok) *ok = true;
return v.toUShort(false);
return v.toUInt16LE(0);
}
inline unsigned int readDWORD(File *file, bool *ok = 0)
@@ -56,7 +56,7 @@ namespace TagLib
return 0;
}
if(ok) *ok = true;
return v.toUInt(false);
return v.toUInt32LE(0);
}
inline long long readQWORD(File *file, bool *ok = 0)
@@ -67,13 +67,13 @@ namespace TagLib
return 0;
}
if(ok) *ok = true;
return v.toLongLong(false);
return v.toInt64LE(0);
}
inline String readString(File *file, int length)
{
ByteVector data = file->readBlock(length);
unsigned int size = data.size();
size_t size = data.size();
while (size >= 2) {
if(data[size - 1] != '\0' || data[size - 2] != '\0') {
break;
@@ -88,9 +88,9 @@ namespace TagLib
inline ByteVector renderString(const String &str, bool includeLength = false)
{
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false);
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromUInt16LE(0);
if(includeLength) {
data = ByteVector::fromShort(data.size(), false) + data;
data = ByteVector::fromUInt16LE(data.size()) + data;
}
return data;
}

View File

@@ -23,95 +23,34 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tbytevector.h>
#include "aiffproperties.h"
#include "apeproperties.h"
#include "asfproperties.h"
#include "flacproperties.h"
#include "mp4properties.h"
#include "mpcproperties.h"
#include "mpegproperties.h"
#include "opusproperties.h"
#include "speexproperties.h"
#include "trueaudioproperties.h"
#include "vorbisproperties.h"
#include "wavproperties.h"
#include "wavpackproperties.h"
#include "dsfproperties.h"
#include "dsdiffproperties.h"
#include <tstringlist.h>
#include "audioproperties.h"
using namespace TagLib;
// This macro is a workaround for the fact that we can't add virtual functions.
// Should be true virtual functions in taglib2.
#define VIRTUAL_FUNCTION_WORKAROUND(function_name, default_value) \
if(dynamic_cast<const APE::Properties*>(this)) \
return dynamic_cast<const APE::Properties*>(this)->function_name(); \
else if(dynamic_cast<const ASF::Properties*>(this)) \
return dynamic_cast<const ASF::Properties*>(this)->function_name(); \
else if(dynamic_cast<const FLAC::Properties*>(this)) \
return dynamic_cast<const FLAC::Properties*>(this)->function_name(); \
else if(dynamic_cast<const MP4::Properties*>(this)) \
return dynamic_cast<const MP4::Properties*>(this)->function_name(); \
else if(dynamic_cast<const MPC::Properties*>(this)) \
return dynamic_cast<const MPC::Properties*>(this)->function_name(); \
else if(dynamic_cast<const MPEG::Properties*>(this)) \
return dynamic_cast<const MPEG::Properties*>(this)->function_name(); \
else if(dynamic_cast<const Ogg::Opus::Properties*>(this)) \
return dynamic_cast<const Ogg::Opus::Properties*>(this)->function_name(); \
else if(dynamic_cast<const Ogg::Speex::Properties*>(this)) \
return dynamic_cast<const Ogg::Speex::Properties*>(this)->function_name(); \
else if(dynamic_cast<const TrueAudio::Properties*>(this)) \
return dynamic_cast<const TrueAudio::Properties*>(this)->function_name(); \
else if(dynamic_cast<const RIFF::AIFF::Properties*>(this)) \
return dynamic_cast<const RIFF::AIFF::Properties*>(this)->function_name(); \
else if(dynamic_cast<const RIFF::WAV::Properties*>(this)) \
return dynamic_cast<const RIFF::WAV::Properties*>(this)->function_name(); \
else if(dynamic_cast<const Vorbis::Properties*>(this)) \
return dynamic_cast<const Vorbis::Properties*>(this)->function_name(); \
else if(dynamic_cast<const WavPack::Properties*>(this)) \
return dynamic_cast<const WavPack::Properties*>(this)->function_name(); \
else if(dynamic_cast<const DSF::Properties*>(this)) \
return dynamic_cast<const DSF::Properties*>(this)->function_name(); \
else if(dynamic_cast<const DSDIFF::Properties*>(this)) \
return dynamic_cast<const DSDIFF::Properties*>(this)->function_name(); \
else \
return (default_value);
class AudioProperties::AudioPropertiesPrivate
{
};
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
AudioProperties::~AudioProperties()
{
}
int AudioProperties::lengthInSeconds() const
String AudioProperties::toString() const
{
VIRTUAL_FUNCTION_WORKAROUND(lengthInSeconds, 0)
}
int AudioProperties::lengthInMilliseconds() const
{
VIRTUAL_FUNCTION_WORKAROUND(lengthInMilliseconds, 0)
StringList desc;
desc.append("Audio");
desc.append(String::number(length()) + " seconds");
desc.append(String::number(bitrate()) + " kbps");
return desc.toString(", ");
}
////////////////////////////////////////////////////////////////////////////////
// protected methods
////////////////////////////////////////////////////////////////////////////////
AudioProperties::AudioProperties(ReadStyle) :
AudioProperties::AudioProperties() :
d(0)
{
}

View File

@@ -27,6 +27,7 @@
#define TAGLIB_AUDIOPROPERTIES_H
#include "taglib_export.h"
#include "tstring.h"
namespace TagLib {
@@ -75,16 +76,14 @@ namespace TagLib {
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
virtual int lengthInSeconds() const = 0;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
virtual int lengthInMilliseconds() const = 0;
/*!
* Returns the most appropriate bit rate for the file in kb/s. For constant
@@ -103,23 +102,27 @@ namespace TagLib {
*/
virtual int channels() const = 0;
/*!
* Returns description of the audio file.
*/
virtual String toString() const;
protected:
/*!
* Construct an audio properties instance. This is protected as this class
* Constructs an audio properties instance. This is protected as this class
* should not be instantiated directly, but should be instantiated via its
* subclasses and can be fetched from the FileRef or File APIs.
*
* \see ReadStyle
*/
AudioProperties(ReadStyle style);
AudioProperties();
private:
// Noncopyable. Derived classes as well.
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
class AudioPropertiesPrivate;
AudioPropertiesPrivate *d;
class PropertiesPrivate;
PropertiesPrivate *d;
};
}

View File

@@ -26,6 +26,7 @@
#include "dsdiffdiintag.h"
#include "tstringlist.h"
#include "tpropertymap.h"
#include "tpicturemap.h"
using namespace TagLib;
using namespace DSDIFF::DIIN;
@@ -86,20 +87,19 @@ unsigned int DSDIFF::DIIN::Tag::track() const
return 0;
}
PictureMap DSDIFF::DIIN::Tag::pictures() const
{
return PictureMap();
}
void DSDIFF::DIIN::Tag::setTitle(const String &title)
{
if(title.isNull() || title.isEmpty())
d->title = String();
else
d->title = title;
d->title = title;
}
void DSDIFF::DIIN::Tag::setArtist(const String &artist)
{
if(artist.isNull() || artist.isEmpty())
d->artist = String();
else
d->artist = artist;
d->artist = artist;
}
void DSDIFF::DIIN::Tag::setAlbum(const String &)
@@ -122,6 +122,10 @@ void DSDIFF::DIIN::Tag::setTrack(unsigned int)
{
}
void DSDIFF::DIIN::Tag::setPictures( const PictureMap& l )
{
}
PropertyMap DSDIFF::DIIN::Tag::properties() const
{
PropertyMap properties;

View File

@@ -49,75 +49,85 @@ namespace TagLib {
* Returns the track name; if no track name is present in the tag
* String() will be returned.
*/
String title() const;
virtual String title() const;
/*!
* Returns the artist name; if no artist name is present in the tag
* String() will be returned.
*/
String artist() const;
virtual String artist() const;
/*!
* Not supported. Therefore always returns String().
*/
String album() const;
virtual String album() const;
/*!
* Not supported. Therefore always returns String().
*/
String comment() const;
virtual String comment() const;
/*!
* Not supported. Therefore always returns String().
*/
String genre() const;
virtual String genre() const;
/*!
* Not supported. Therefore always returns 0.
*/
unsigned int year() const;
virtual unsigned int year() const;
/*!
* Not supported. Therefore always returns 0.
*/
unsigned int track() const;
virtual unsigned int track() const;
/*!
* Not supported. Therefore always returns an empty list.
*/
virtual PictureMap pictures() const;
/*!
* Sets the title to \a title. If \a title is String() then this
* value will be cleared.
*/
void setTitle(const String &title);
virtual void setTitle(const String &title);
/*!
* Sets the artist to \a artist. If \a artist is String() then this
* value will be cleared.
*/
void setArtist(const String &artist);
virtual void setArtist(const String &artist);
/*!
* Not supported and therefore ignored.
*/
void setAlbum(const String &album);
virtual void setAlbum(const String &album);
/*!
* Not supported and therefore ignored.
*/
void setComment(const String &comment);
virtual void setComment(const String &comment);
/*!
* Not supported and therefore ignored.
*/
void setGenre(const String &genre);
virtual void setGenre(const String &genre);
/*!
* Not supported and therefore ignored.
*/
void setYear(unsigned int year);
virtual void setYear(unsigned int year);
/*!
* Not supported and therefore ignored.
*/
void setTrack(unsigned int track);
virtual void setTrack(unsigned int track);
/*!
* Not supported and therefore ignored.
*/
virtual void setPictures( const PictureMap& l );
/*!
* Implements the unified property interface -- export function.

View File

@@ -29,6 +29,7 @@
#include <tstringlist.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include <tsmartptr.h>
#include "tagunion.h"
#include "dsdifffile.h"
@@ -63,7 +64,6 @@ public:
size(0),
isID3InPropChunk(false),
duplicateID3V2chunkIndex(-1),
properties(0),
id3v2TagChunkID("ID3 "),
hasID3v2(false),
hasDiin(false)
@@ -72,11 +72,6 @@ public:
childChunkIndex[DIINIndex] = -1;
}
~FilePrivate()
{
delete properties;
}
Endianness endianness;
ByteVector type;
unsigned long long size;
@@ -88,9 +83,9 @@ public:
int duplicateID3V2chunkIndex; // 2 ID3 chunks are present. This is then the index of the one in
// PROP chunk that will be removed upon next save to remove duplicates.
Properties *properties;
SCOPED_PTR<AudioProperties> properties;
TagUnion tag;
DoubleTagUnion tag;
ByteVector id3v2TagChunkID;
@@ -115,7 +110,7 @@ bool DSDIFF::File::isSupported(IOStream *stream)
////////////////////////////////////////////////////////////////////////////////
DSDIFF::File::File(FileName file, bool readProperties,
Properties::ReadStyle propertiesStyle) : TagLib::File(file)
AudioProperties::ReadStyle propertiesStyle) : TagLib::File(file)
{
d = new FilePrivate;
d->endianness = BigEndian;
@@ -124,7 +119,7 @@ DSDIFF::File::File(FileName file, bool readProperties,
}
DSDIFF::File::File(IOStream *stream, bool readProperties,
Properties::ReadStyle propertiesStyle) : TagLib::File(stream)
AudioProperties::ReadStyle propertiesStyle) : TagLib::File(stream)
{
d = new FilePrivate;
d->endianness = BigEndian;
@@ -184,9 +179,9 @@ PropertyMap DSDIFF::File::setProperties(const PropertyMap &properties)
return d->tag.access<ID3v2::Tag>(ID3v2Index, true)->setProperties(properties);
}
DSDIFF::Properties *DSDIFF::File::audioProperties() const
DSDIFF::AudioProperties *DSDIFF::File::audioProperties() const
{
return d->properties;
return d->properties.get();
}
bool DSDIFF::File::save()
@@ -230,18 +225,24 @@ bool DSDIFF::File::save()
if(d->hasDiin) {
DSDIFF::DIIN::Tag *diinTag = d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
if(!diinTag->title().isNull() && !diinTag->title().isEmpty()) {
if(!diinTag->title().isEmpty()) {
ByteVector diinTitle;
diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian));
if(d->endianness == BigEndian)
diinTitle.append(ByteVector::fromUInt32BE(diinTag->title().size()));
else
diinTitle.append(ByteVector::fromUInt32LE(diinTag->title().size()));
diinTitle.append(ByteVector::fromCString(diinTag->title().toCString()));
setChildChunkData("DITI", diinTitle, DIINChunk);
}
else
setChildChunkData("DITI", ByteVector(), DIINChunk);
if(!diinTag->artist().isNull() && !diinTag->artist().isEmpty()) {
if(!diinTag->artist().isEmpty()) {
ByteVector diinArtist;
diinArtist.append(ByteVector::fromUInt(diinTag->artist().size(), d->endianness == BigEndian));
if(d->endianness == BigEndian)
diinArtist.append(ByteVector::fromUInt32BE(diinTag->artist().size()));
else
diinArtist.append(ByteVector::fromUInt32LE(diinTag->artist().size()));
diinArtist.append(ByteVector::fromCString(diinTag->artist().toCString()));
setChildChunkData("DIAR", diinArtist, DIINChunk);
}
@@ -264,12 +265,15 @@ bool DSDIFF::File::save()
void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
{
if(data.isNull() || data.isEmpty()) {
if(data.isEmpty()) {
// Null data: remove chunk
// Update global size
unsigned long long removedChunkTotalSize = d->chunks[i].size + d->chunks[i].padding + 12;
d->size -= removedChunkTotalSize;
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt64BE(d->size), 4, 8);
else
insert(ByteVector::fromUInt64LE(d->size), 4, 8);
removeBlock(d->chunks[i].offset - 12, removedChunkTotalSize);
@@ -284,7 +288,10 @@ void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
// Non null data: update chunk
// First we update the global size
d->size += ((data.size() + 1) & ~1) - (d->chunks[i].size + d->chunks[i].padding);
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt64BE(d->size), 4, 8);
else
insert(ByteVector::fromUInt64LE(d->size), 4, 8);
// Now update the specific chunk
writeChunk(d->chunks[i].name,
@@ -320,7 +327,10 @@ void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &da
// First we update the global size
d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt64BE(d->size), 4, 8);
else
insert(ByteVector::fromUInt64LE(d->size), 4, 8);
// Now add the chunk to the file
writeChunk(name,
@@ -344,17 +354,24 @@ void DSDIFF::File::setChildChunkData(unsigned int i,
{
std::vector<Chunk64> &childChunks = d->childChunks[childChunkNum];
if(data.isNull() || data.isEmpty()) {
if(data.isEmpty()) {
// Null data: remove chunk
// Update global size
unsigned long long removedChunkTotalSize = childChunks[i].size + childChunks[i].padding + 12;
d->size -= removedChunkTotalSize;
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt64BE(d->size), 4, 8);
else
insert(ByteVector::fromUInt64LE(d->size), 4, 8);
// Update child chunk size
d->chunks[d->childChunkIndex[childChunkNum]].size -= removedChunkTotalSize;
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
d->endianness == BigEndian),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt64BE(d->chunks[d->childChunkIndex[childChunkNum]].size),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
else
insert(ByteVector::fromUInt64LE(d->chunks[d->childChunkIndex[childChunkNum]].size),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
// Remove the chunk
removeBlock(childChunks[i].offset - 12, removedChunkTotalSize);
@@ -379,13 +396,19 @@ void DSDIFF::File::setChildChunkData(unsigned int i,
// Non null data: update chunk
// First we update the global size
d->size += ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt64BE(d->size), 4, 8);
else
insert(ByteVector::fromUInt64LE(d->size), 4, 8);
// And the PROP chunk size
d->chunks[d->childChunkIndex[childChunkNum]].size += ((data.size() + 1) & ~1)
- (childChunks[i].size + childChunks[i].padding);
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
d->endianness == BigEndian),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt64BE(d->chunks[d->childChunkIndex[childChunkNum]].size),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
else
insert(ByteVector::fromUInt64LE(d->chunks[d->childChunkIndex[childChunkNum]].size),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
// Now update the specific chunk
writeChunk(childChunks[i].name,
@@ -426,7 +449,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
}
// Do not attempt to remove a non existing chunk
if(data.isNull() || data.isEmpty())
if(data.isEmpty())
return;
// Couldn't find an existing chunk, so let's create a new one.
@@ -435,13 +458,19 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
// First we update the global size
d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt64BE(d->size), 4, 8);
else
insert(ByteVector::fromUInt64LE(d->size), 4, 8);
// And the child chunk size
d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1)
+ ((data.size() + 1) & ~1) + 12;
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
d->endianness == BigEndian),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt64BE(d->chunks[d->childChunkIndex[childChunkNum]].size),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
else
insert(ByteVector::fromUInt64LE(d->chunks[d->childChunkIndex[childChunkNum]].size),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
// Now add the chunk to the file
unsigned long long nextRootChunkIdx = length();
@@ -504,18 +533,18 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
}
}
void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
void DSDIFF::File::read(bool readProperties, AudioProperties::ReadStyle propertiesStyle)
{
bool bigEndian = (d->endianness == BigEndian);
d->type = readBlock(4);
d->size = readBlock(8).toLongLong(bigEndian);
d->size = bigEndian ? readBlock(8).toInt64BE(0) : readBlock(8).toInt64LE(0);
d->format = readBlock(4);
// + 12: chunk header at least, fix for additional junk bytes
while(tell() + 12 <= length()) {
ByteVector chunkName = readBlock(4);
unsigned long long chunkSize = readBlock(8).toLongLong(bigEndian);
unsigned long long chunkSize = bigEndian ? readBlock(8).toInt64BE(0) : readBlock(8).toInt64LE(0);
if(!isValidChunkID(chunkName)) {
debug("DSDIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID");
@@ -570,7 +599,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
while(tell() + 12 <= dstChunkEnd) {
ByteVector dstChunkName = readBlock(4);
long long dstChunkSize = readBlock(8).toLongLong(bigEndian);
long long dstChunkSize = bigEndian ? readBlock(8).toInt64BE(0) : readBlock(8).toInt64LE(0);
if(!isValidChunkID(dstChunkName)) {
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName + "' has invalid ID");
@@ -587,8 +616,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
if(dstChunkName == "FRTE") {
// Found the DST frame information chunk
dstNumFrames = readBlock(4).toUInt(bigEndian);
dstFrameRate = readBlock(2).toUShort(bigEndian);
dstNumFrames = bigEndian ? readBlock(4).toUInt32BE(0) : readBlock(4).toUInt32LE(0);
dstFrameRate = bigEndian ? readBlock(2).toUInt16BE(0) : readBlock(2).toUInt16LE(0);
break; // Found the wanted one, no need to look at the others
}
@@ -611,7 +640,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
seek(d->chunks[i].offset + 4); // +4 to remove the 'SND ' marker at beginning of 'PROP' chunk
while(tell() + 12 <= propChunkEnd) {
ByteVector propChunkName = readBlock(4);
long long propChunkSize = readBlock(8).toLongLong(bigEndian);
long long propChunkSize = bigEndian ? readBlock(8).toInt64BE(0) : readBlock(8).toInt64LE(0);
if(!isValidChunkID(propChunkName)) {
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid ID");
@@ -656,7 +685,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
while(tell() + 12 <= diinChunkEnd) {
ByteVector diinChunkName = readBlock(4);
long long diinChunkSize = readBlock(8).toLongLong(bigEndian);
long long diinChunkSize = bigEndian ? readBlock(8).toInt64BE(0) : readBlock(8).toInt64LE(0);
if(!isValidChunkID(diinChunkName)) {
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName + "' has invalid ID");
@@ -728,12 +757,12 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
else if(d->childChunks[PROPChunk][i].name == "FS ") {
// Sample rate
seek(d->childChunks[PROPChunk][i].offset);
sampleRate = readBlock(4).toUInt(0, 4, bigEndian);
sampleRate = bigEndian ? readBlock(4).toUInt32BE(0) : readBlock(4).toUInt32LE(0);
}
else if(d->childChunks[PROPChunk][i].name == "CHNL") {
// Channels
seek(d->childChunks[PROPChunk][i].offset);
channels = readBlock(2).toShort(0, bigEndian);
channels = bigEndian ? readBlock(2).toInt16BE(0) : readBlock(2).toInt16LE(0);
}
}
@@ -744,7 +773,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
for(unsigned int i = 0; i < d->childChunks[DIINChunk].size(); i++) {
if(d->childChunks[DIINChunk][i].name == "DITI") {
seek(d->childChunks[DIINChunk][i].offset);
unsigned int titleStrLength = readBlock(4).toUInt(0, 4, bigEndian);
unsigned int titleStrLength = bigEndian ? readBlock(4).toUInt32BE(0) : readBlock(4).toUInt32LE(0);
if(titleStrLength <= d->childChunks[DIINChunk][i].size) {
ByteVector titleStr = readBlock(titleStrLength);
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setTitle(titleStr);
@@ -752,7 +781,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
}
else if(d->childChunks[DIINChunk][i].name == "DIAR") {
seek(d->childChunks[DIINChunk][i].offset);
unsigned int artistStrLength = readBlock(4).toUInt(0, 4, bigEndian);
unsigned int artistStrLength = bigEndian ? readBlock(4).toUInt32BE(0) : readBlock(4).toUInt32LE(0);
if(artistStrLength <= d->childChunks[DIINChunk][i].size) {
ByteVector artistStr = readBlock(artistStrLength);
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setArtist(artistStr);
@@ -779,11 +808,11 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
if(lengthDSDSamplesTimeChannels > 0)
bitrate = (audioDataSizeinBytes*8*sampleRate) / lengthDSDSamplesTimeChannels / 1000;
d->properties = new Properties(sampleRate,
channels,
lengthDSDSamplesTimeChannels,
bitrate,
propertiesStyle);
d->properties.reset(new AudioProperties(sampleRate,
channels,
lengthDSDSamplesTimeChannels,
bitrate,
propertiesStyle));
}
if(!ID3v2Tag()) {
@@ -802,7 +831,10 @@ void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
combined.append(ByteVector(leadingPadding, '\x00'));
combined.append(name);
combined.append(ByteVector::fromLongLong(data.size(), d->endianness == BigEndian));
if(d->endianness == BigEndian)
combined.append(ByteVector::fromUInt64BE(data.size()));
else
combined.append(ByteVector::fromUInt64LE(data.size()));
combined.append(data);
if((data.size() & 0x01) != 0)
combined.append('\x00');

View File

@@ -40,7 +40,7 @@ namespace TagLib {
*
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
* chunk as well as properties from the file.
* Description of the DSDIFF format is available
* Description of the DSDIFF format is available
* at http://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf
* DSDIFF standard does not explictly specify the ID3V2 chunk
* It can be found at the root level, but also sometimes inside the PROP chunk
@@ -68,7 +68,7 @@ namespace TagLib {
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Constructs an DSDIFF file from \a stream. If \a readProperties is true
@@ -80,7 +80,7 @@ namespace TagLib {
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Destroys this instance of the File.
@@ -137,10 +137,10 @@ namespace TagLib {
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the AIFF::Properties for this file. If no audio properties
* Returns the DSDIFF::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
virtual AudioProperties *audioProperties() const;
/*!
* Save the file. If at least one tag -- ID3v1 or DIIN -- exists this
@@ -178,7 +178,7 @@ namespace TagLib {
bool hasID3v2Tag() const;
/*!
* Returns whether or not the file on disk actually has the DSDIFF
* Returns whether or not the file on disk actually has the DSDIFF
* Title & Artist tag.
*
* \see DIINTag()
@@ -245,7 +245,7 @@ namespace TagLib {
void updateRootChunksStructure(unsigned int startingChunk);
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
void read(bool readProperties, AudioProperties::ReadStyle propertiesStyle);
void writeChunk(const ByteVector &name, const ByteVector &data,
unsigned long long offset, unsigned long replace = 0,
unsigned int leadingPadding = 0);

View File

@@ -30,10 +30,10 @@
using namespace TagLib;
class DSDIFF::Properties::PropertiesPrivate
class DSDIFF::AudioProperties::AudioPropertiesPrivate
{
public:
PropertiesPrivate() :
AudioPropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
@@ -55,14 +55,12 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
DSDIFF::Properties::Properties(const unsigned int sampleRate,
const unsigned short channels,
const unsigned long long samplesCount,
const int bitrate,
ReadStyle style) : AudioProperties(style)
DSDIFF::AudioProperties::AudioProperties(const unsigned int sampleRate,
const unsigned short channels,
const unsigned long long samplesCount,
const int bitrate,
ReadStyle style) : TagLib::AudioProperties(), d(new AudioPropertiesPrivate)
{
d = new PropertiesPrivate;
d->channels = channels;
d->sampleCount = samplesCount;
d->sampleWidth = 1;
@@ -73,48 +71,47 @@ DSDIFF::Properties::Properties(const unsigned int sampleRate,
: 0;
}
DSDIFF::Properties::~Properties()
DSDIFF::AudioProperties::~AudioProperties()
{
delete d;
}
int DSDIFF::Properties::length() const
int DSDIFF::AudioProperties::length() const
{
return lengthInSeconds();
}
int DSDIFF::Properties::lengthInSeconds() const
int DSDIFF::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int DSDIFF::Properties::lengthInMilliseconds() const
int DSDIFF::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int DSDIFF::Properties::bitrate() const
int DSDIFF::AudioProperties::bitrate() const
{
return d->bitrate;
}
int DSDIFF::Properties::sampleRate() const
int DSDIFF::AudioProperties::sampleRate() const
{
return d->sampleRate;
}
int DSDIFF::Properties::channels() const
int DSDIFF::AudioProperties::channels() const
{
return d->channels;
}
int DSDIFF::Properties::bitsPerSample() const
int DSDIFF::AudioProperties::bitsPerSample() const
{
return d->sampleWidth;
}
long long DSDIFF::Properties::sampleCount() const
long long DSDIFF::AudioProperties::sampleCount() const
{
return d->sampleCount;
}

View File

@@ -41,21 +41,21 @@ namespace TagLib {
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
/*!
* Create an instance of DSDIFF::Properties with the data read from the
* Create an instance of DSDIFF::AudioProperties with the data read from the
* ByteVector \a data.
*/
Properties(const unsigned int sampleRate, const unsigned short channels,
const unsigned long long samplesCount, const int bitrate,
ReadStyle style);
AudioProperties(const unsigned int sampleRate, const unsigned short channels,
const unsigned long long samplesCount, const int bitrate,
ReadStyle style);
/*!
* Destroys this DSDIFF::Properties instance.
* Destroys this DSDIFF::AudioProperties instance.
*/
virtual ~Properties();
virtual ~AudioProperties();
// Reimplementations.
@@ -70,11 +70,11 @@ namespace TagLib {
long long sampleCount() const;
private:
Properties(const Properties &);
Properties &operator=(const Properties &);
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
class PropertiesPrivate;
PropertiesPrivate *d;
class AudioPropertiesPrivate;
AudioPropertiesPrivate *d;
};
}
}

View File

@@ -1,6 +1,6 @@
/***************************************************************************
copyright : (C) 2013 - 2018 by Stephen F. Booth
email : me@sbooth.org
copyright : (C) 2013 - 2018 by Stephen F. Booth
email : me@sbooth.org
***************************************************************************/
/***************************************************************************
@@ -28,6 +28,7 @@
#include <id3v2tag.h>
#include <tstringlist.h>
#include <tpropertymap.h>
#include <tsmartptr.h>
#include <tagutils.h>
#include "dsffile.h"
@@ -40,21 +41,14 @@ class DSF::File::FilePrivate
{
public:
FilePrivate() :
properties(0),
tag(0)
{
}
~FilePrivate()
{
delete properties;
delete tag;
}
fileSize(0),
metadataOffset(0) {}
long long fileSize;
long long metadataOffset;
Properties *properties;
ID3v2::Tag *tag;
SCOPED_PTR<AudioProperties> properties;
SCOPED_PTR<ID3v2::Tag> tag;
};
////////////////////////////////////////////////////////////////////////////////
@@ -73,7 +67,7 @@ bool DSF::File::isSupported(IOStream *stream)
////////////////////////////////////////////////////////////////////////////////
DSF::File::File(FileName file, bool readProperties,
Properties::ReadStyle propertiesStyle) :
AudioProperties::ReadStyle propertiesStyle) :
TagLib::File(file),
d(new FilePrivate())
{
@@ -82,7 +76,7 @@ DSF::File::File(FileName file, bool readProperties,
}
DSF::File::File(IOStream *stream, bool readProperties,
Properties::ReadStyle propertiesStyle) :
AudioProperties::ReadStyle propertiesStyle) :
TagLib::File(stream),
d(new FilePrivate())
{
@@ -97,7 +91,12 @@ DSF::File::~File()
ID3v2::Tag *DSF::File::tag() const
{
return d->tag;
return d->tag.get();
}
DSF::AudioProperties *DSF::File::audioProperties() const
{
return d->properties.get();
}
PropertyMap DSF::File::properties() const
@@ -110,11 +109,6 @@ PropertyMap DSF::File::setProperties(const PropertyMap &properties)
return d->tag->setProperties(properties);
}
DSF::Properties *DSF::File::audioProperties() const
{
return d->properties;
}
bool DSF::File::save()
{
if(readOnly()) {
@@ -134,13 +128,13 @@ bool DSF::File::save()
// Update the file size
if(d->fileSize != newFileSize) {
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
insert(ByteVector::fromUInt64LE(newFileSize), 12, 8);
d->fileSize = newFileSize;
}
// Update the metadata offset to 0 since there is no longer a tag
if(d->metadataOffset) {
insert(ByteVector::fromLongLong(0ULL, false), 20, 8);
insert(ByteVector::fromUInt64LE(0ULL), 20, 8);
d->metadataOffset = 0;
}
@@ -156,13 +150,13 @@ bool DSF::File::save()
// Update the file size
if(d->fileSize != newFileSize) {
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
insert(ByteVector::fromUInt64LE(newFileSize), 12, 8);
d->fileSize = newFileSize;
}
// Update the metadata offset
if(d->metadataOffset != newMetadataOffset) {
insert(ByteVector::fromLongLong(newMetadataOffset, false), 20, 8);
insert(ByteVector::fromUInt64LE(newMetadataOffset), 20, 8);
d->metadataOffset = newMetadataOffset;
}
@@ -177,8 +171,7 @@ bool DSF::File::save()
// private members
////////////////////////////////////////////////////////////////////////////////
void DSF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
void DSF::File::read(bool readProperties, AudioProperties::ReadStyle propertiesStyle)
{
// A DSF file consists of four chunks: DSD chunk, format chunk, data chunk, and metadata chunk
// The file format is not chunked in the sense of a RIFF File, though
@@ -191,25 +184,25 @@ void DSF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
return;
}
long long chunkSize = readBlock(8).toLongLong(false);
long long chunkSize = readBlock(8).toInt64LE(0);
// Integrity check
if(28 != chunkSize) {
debug("DSF::File::read() -- File is corrupted, wrong chunk size");
debug("DSF::File::read() -- File is corrupted.");
setValid(false);
return;
}
d->fileSize = readBlock(8).toLongLong(false);
d->fileSize = readBlock(8).toInt64LE(0);
// File is malformed or corrupted
if(d->fileSize != length()) {
debug("DSF::File::read() -- File is corrupted wrong length");
debug("DSF::File::read() -- File is corrupted.");
setValid(false);
return;
}
d->metadataOffset = readBlock(8).toLongLong(false);
d->metadataOffset = readBlock(8).toInt64LE(0);
// File is malformed or corrupted
if(d->metadataOffset > d->fileSize) {
@@ -226,16 +219,16 @@ void DSF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
return;
}
chunkSize = readBlock(8).toLongLong(false);
chunkSize = readBlock(8).toInt64LE(0);
d->properties = new Properties(readBlock(chunkSize), propertiesStyle);
d->properties.reset(
new AudioProperties(readBlock(static_cast<size_t>(chunkSize)), propertiesStyle));
// Skip the data chunk
// A metadata offset of 0 indicates the absence of an ID3v2 tag
if(0 == d->metadataOffset)
d->tag = new ID3v2::Tag();
d->tag.reset(new ID3v2::Tag());
else
d->tag = new ID3v2::Tag(this, d->metadataOffset);
d->tag.reset(new ID3v2::Tag(this, d->metadataOffset));
}

View File

@@ -60,7 +60,7 @@ namespace TagLib {
* false, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Contructs an DSF file from \a file. If \a readProperties is true the
@@ -68,7 +68,7 @@ namespace TagLib {
* false, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Destroys this instance of the File.
@@ -78,25 +78,25 @@ namespace TagLib {
/*!
* Returns the Tag for this file.
*/
ID3v2::Tag *tag() const;
/*!
* Implements the unified property interface -- export function.
* This method forwards to ID3v2::Tag::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified property interface -- import function.
* This method forwards to ID3v2::Tag::setProperties().
*/
PropertyMap setProperties(const PropertyMap &);
virtual ID3v2::Tag *tag() const;
/*!
* Returns the DSF::AudioProperties for this file. If no audio properties
* were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
virtual AudioProperties *audioProperties() const;
/*!
* Implements the unified property interface -- export function.
* This method forwards to ID3v2::Tag::properties().
*/
virtual PropertyMap properties() const;
/*!
* Implements the unified property interface -- import function.
* This method forwards to ID3v2::Tag::setProperties().
*/
virtual PropertyMap setProperties(const PropertyMap &);
/*!
* Saves the file.
@@ -116,7 +116,7 @@ namespace TagLib {
File(const File &);
File &operator=(const File &);
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
void read(bool readProperties, AudioProperties::ReadStyle propertiesStyle);
class FilePrivate;
FilePrivate *d;
@@ -125,4 +125,3 @@ namespace TagLib {
}
#endif

View File

@@ -30,22 +30,20 @@
using namespace TagLib;
class DSF::Properties::PropertiesPrivate
class DSF::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() :
formatVersion(0),
formatID(0),
channelType(0),
channelNum(0),
samplingFrequency(0),
bitsPerSample(0),
sampleCount(0),
blockSizePerChannel(0),
bitrate(0),
length(0)
{
}
formatVersion(0),
formatID(0),
channelType(0),
channelNum(0),
samplingFrequency(0),
bitsPerSample(0),
sampleCount(0),
blockSizePerChannel(0),
bitrate(0),
length(0) {}
// Nomenclature is from DSF file format specification
unsigned int formatVersion;
@@ -58,82 +56,82 @@ public:
unsigned int blockSizePerChannel;
// Computed
unsigned int bitrate;
unsigned int length;
int bitrate;
int length;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
DSF::Properties::Properties(const ByteVector &data, ReadStyle style) : TagLib::AudioProperties(style)
DSF::AudioProperties::AudioProperties(const ByteVector &data, ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate;
read(data);
}
DSF::Properties::~Properties()
DSF::AudioProperties::~AudioProperties()
{
delete d;
}
int DSF::Properties::length() const
int DSF::AudioProperties::length() const
{
return lengthInSeconds();
}
int DSF::Properties::lengthInSeconds() const
int DSF::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int DSF::Properties::lengthInMilliseconds() const
int DSF::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int DSF::Properties::bitrate() const
int DSF::AudioProperties::bitrate() const
{
return d->bitrate;
}
int DSF::Properties::sampleRate() const
int DSF::AudioProperties::sampleRate() const
{
return d->samplingFrequency;
}
int DSF::Properties::channels() const
int DSF::AudioProperties::channels() const
{
return d->channelNum;
}
// DSF specific
int DSF::Properties::formatVersion() const
int DSF::AudioProperties::formatVersion() const
{
return d->formatVersion;
}
int DSF::Properties::formatID() const
int DSF::AudioProperties::formatID() const
{
return d->formatID;
}
int DSF::Properties::channelType() const
int DSF::AudioProperties::channelType() const
{
return d->channelType;
}
int DSF::Properties::bitsPerSample() const
int DSF::AudioProperties::bitsPerSample() const
{
return d->bitsPerSample;
}
long long DSF::Properties::sampleCount() const
long long DSF::AudioProperties::sampleCount() const
{
return d->sampleCount;
}
int DSF::Properties::blockSizePerChannel() const
int DSF::AudioProperties::blockSizePerChannel() const
{
return d->blockSizePerChannel;
}
@@ -142,20 +140,19 @@ int DSF::Properties::blockSizePerChannel() const
// private members
////////////////////////////////////////////////////////////////////////////////
void DSF::Properties::read(const ByteVector &data)
void DSF::AudioProperties::read(const ByteVector &data)
{
d->formatVersion = data.toUInt(0U,false);
d->formatID = data.toUInt(4U,false);
d->channelType = data.toUInt(8U,false);
d->channelNum = data.toUInt(12U,false);
d->samplingFrequency = data.toUInt(16U,false);
d->bitsPerSample = data.toUInt(20U,false);
d->sampleCount = data.toLongLong(24U,false);
d->blockSizePerChannel = data.toUInt(32U,false);
d->formatVersion = data.toUInt32LE(0);
d->formatID = data.toUInt32LE(4);
d->channelType = data.toUInt32LE(8);
d->channelNum = data.toUInt32LE(12);
d->samplingFrequency = data.toUInt32LE(16);
d->bitsPerSample = data.toUInt32LE(20);
d->sampleCount = data.toInt64LE(24);
d->blockSizePerChannel = data.toUInt32LE(32);
d->bitrate
= static_cast<unsigned int>((d->samplingFrequency * d->bitsPerSample * d->channelNum) / 1000.0 + 0.5);
d->length
= d->samplingFrequency > 0 ? static_cast<unsigned int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5) : 0;
d->bitrate = static_cast<int>(d->samplingFrequency * d->bitsPerSample * d->channelNum / 1000.0 + 0.5);
if(d->samplingFrequency > 0)
d->length = static_cast<int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5);
}

View File

@@ -41,19 +41,19 @@ namespace TagLib {
* API.
*/
class TAGLIB_EXPORT Properties : public TagLib::AudioProperties
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
/*!
* Create an instance of DSF::AudioProperties with the data read from the
* ByteVector \a data.
*/
Properties(const ByteVector &data, ReadStyle style);
AudioProperties(const ByteVector &data, ReadStyle style);
/*!
* Destroys this DSF::AudioProperties instance.
*/
virtual ~Properties();
virtual ~AudioProperties();
// Reimplementations.
@@ -68,7 +68,7 @@ namespace TagLib {
int formatID() const;
/*!
* Channel type values: 1 = mono, 2 = stereo, 3 = 3 channels,
* Channel type values: 1 = mono, 2 = stereo, 3 = 3 channels,
* 4 = quad, 5 = 4 channels, 6 = 5 channels, 7 = 5.1 channels
*/
int channelType() const;
@@ -77,8 +77,8 @@ namespace TagLib {
int blockSizePerChannel() const;
private:
Properties(const Properties &);
Properties &operator=(const Properties &);
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read(const ByteVector &data);
@@ -89,4 +89,3 @@ namespace TagLib {
}
#endif

View File

@@ -0,0 +1,58 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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_EBML_CONSTANTS
#define TAGLIB_EBML_CONSTANTS
namespace TagLib {
namespace EBML {
//! Shorter representation of the type.
typedef unsigned long long int ulli;
//! The id of an EBML Void element that is just a placeholder.
const ulli Void = 0xecL;
//! The id of an EBML CRC32 element that contains a crc32 value.
const ulli CRC32 = 0xc3L;
//! A namespace containing the ids of the EBML header's elements.
namespace Header {
const ulli EBML = 0x1a45dfa3L;
const ulli EBMLVersion = 0x4286L;
const ulli EBMLReadVersion = 0x42f7L;
const ulli EBMLMaxIDWidth = 0x42f2L;
const ulli EBMLMaxSizeWidth = 0x42f3L;
const ulli DocType = 0x4282L;
const ulli DocTypeVersion = 0x4287L;
const ulli DocTypeReadVersion = 0x4285L;
}
}
}
#endif

489
taglib/ebml/ebmlelement.cpp Normal file
View File

@@ -0,0 +1,489 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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 "tdebug.h"
#include "ebmlelement.h"
using namespace TagLib;
class EBML::Element::ElementPrivate
{
public:
// The id of this element.
ulli id;
// The position of the element, where the header begins.
long long position;
// The size of the element as read from the header. Note: Actually an ulli but
// due to the variable integer size limited, thus long long is ok.
long long size;
// The position of the element's data.
long long data;
// The element's children.
List<Element *> children;
// True: Treated this element as container and read children.
bool populated;
// The parent element. If NULL (0) this is the document root.
Element *parent;
// The file used to read and write.
File *document;
// Destructor: Clean up all children.
~ElementPrivate()
{
for(List<Element *>::Iterator i = children.begin(); i != children.end(); ++i) {
delete *i;
}
}
// Reads a variable length integer from the file at the given position
// and saves its value to result. If cutOne is true the first one of the
// binary representation of the result is removed (required for size). If
// cutOne is false the one will remain in the result (required for id).
// This method returns the position directly after the read integer.
long long readVInt(long long position, ulli *result, bool cutOne = true)
{
document->seek(position);
// Determine the length of the integer
char firstByte = document->readBlock(1)[0];
size_t byteSize = 1;
for(size_t i = 0; i < 8 && ((firstByte << i) & (1 << 7)) == 0; ++i)
++byteSize;
// Load the integer
document->seek(position);
ByteVector vint = document->readBlock(byteSize);
// Cut the one if requested
if(cutOne)
vint[0] = (vint[0] & (~(1 << (8 - byteSize))));
// Store the result and return the current position
if(result)
*result = static_cast<ulli>(vint.toInt64BE(0));
return position + byteSize;
}
// Returns a BytVector containing the given number in the variable integer
// format. Truncates numbers > 2^56 (^ means potency in this case).
// If addOne is true, the ByteVector will remain the One to determine the
// integer's length.
// If shortest is true, the ByteVector will be as short as possible (required
// for the id)
ByteVector createVInt(ulli number, bool addOne = true, bool shortest = true)
{
ByteVector vint = ByteVector::fromUInt64BE(number);
// Do we actually need to calculate the length of the variable length
// integer? If not, then prepend the 0b0000 0001 if necessary and return the
// vint.
if(!shortest) {
if(addOne)
vint[0] = 1;
return vint;
}
// Calculate the minimal length of the variable length integer
size_t byteSize = vint.size();
for(size_t i = 0; byteSize > 0 && vint[i] == 0; ++i)
--byteSize;
if(!addOne)
return ByteVector(vint.data() + vint.size() - byteSize, byteSize);
ulli firstByte = (1ULL << (vint.size() - byteSize));
// The most significant byte loses #bytSize bits for storing information.
// Therefore, we might need to increase byteSize.
if(number >= (firstByte << (8 * (byteSize - 1))) && byteSize < vint.size())
++byteSize;
// Add the one at the correct position
size_t firstBytePosition = vint.size() - byteSize;
vint[firstBytePosition] |= (1 << firstBytePosition);
return ByteVector(vint.data() + firstBytePosition, byteSize);
}
// Returns a void element within this element which is at least "least" in
// size. Uses best fit method. Returns a null pointer if no suitable element
// was found.
Element *searchVoid(long long least = 0L)
{
Element *currentBest = 0;
for(List<Element *>::Iterator i = children.begin(); i != children.end(); ++i) {
if((*i)->d->id == Void &&
// We need room for the header if we don't remove the element.
((((*i)->d->size + (*i)->d->data - (*i)->d->position) == least || ((*i)->d->size >= least)) &&
// best fit
(!currentBest || (*i)->d->size < currentBest->d->size))
) {
currentBest = *i;
}
}
return currentBest;
}
// Replaces this element by a Void element. Returns true on success and false
// on error.
bool makeVoid()
{
ulli realSize = size + data - position;
ByteVector header(createVInt(Void, false));
ulli leftSize = realSize - (header.size() + sizeof(ulli));
// Does not make sense to create a Void element
if (leftSize > realSize)
return false;
header.append(createVInt(leftSize, true, false));
// Write to file
document->seek(position);
document->writeBlock(header);
// Update data
data = position + header.size();
size = leftSize;
return true;
// XXX: We actually should merge Voids, if possible.
}
// Reading constructor: Reads all unknown information from the file.
ElementPrivate(File *p_document, Element *p_parent = 0, long long p_position = 0) :
id(0),
position(p_position),
data(0),
populated(false),
parent(p_parent),
document(p_document)
{
if(parent) {
ulli ssize;
data = readVInt(readVInt(position, &id, false), &ssize);
size = static_cast<long long>(ssize);
}
else {
document->seek(0, File::End);
size = document->tell();
}
}
// Writing constructor: Takes given information, calculates missing information
// and writes everything to the file.
// Tries to use void elements if available in the parent.
ElementPrivate(ulli p_id, File *p_document, Element *p_parent,
long long p_position, long long p_size) :
id(p_id),
position(p_position),
size(p_size),
populated(true), // It is a new element so we know, there are no children.
parent(p_parent),
document(p_document)
{
// header
ByteVector content(createVInt(id, false).append(createVInt(size, true, false)));
data = position + content.size();
// space for children
content.resize(static_cast<size_t>(data - position + size));
Element *freeSpace;
if (!(freeSpace = searchVoid(content.size()))) {
// We have to make room
document->insert(content, position);
// Update parents
for(Element *current = parent; current->d->parent; current = current->d->parent) {
current->d->size += content.size();
// Create new header and write it.
ByteVector parentHeader(createVInt(current->d->id, false).append(createVInt(current->d->size, true, false)));
size_t oldHeaderSize = static_cast<size_t>(current->d->data - current->d->position);
if(oldHeaderSize < parentHeader.size()) {
ByteVector secondHeader(createVInt(current->d->id, false).append(createVInt(current->d->size)));
if(oldHeaderSize == secondHeader.size()) {
// Write the header where the old one was.
document->seek(current->d->position);
document->writeBlock(secondHeader);
continue; // Very important here!
}
}
// Insert the new header
document->insert(parentHeader, current->d->position, oldHeaderSize);
current->d->data = current->d->position + parentHeader.size();
}
}
else {
document->seek(freeSpace->d->position);
if((freeSpace->d->size + freeSpace->d->data - freeSpace->d->position)
== static_cast<long long>(content.size())) {
// Write to file
document->writeBlock(content);
// Update parent
for(List<Element *>::Iterator i = parent->d->children.begin();
i != parent->d->children.end(); ++i) {
if(freeSpace == *i)
parent->d->children.erase(i);
}
delete freeSpace;
}
else {
ulli newSize = freeSpace->d->size - content.size();
ByteVector newVoid(createVInt(Void, false).append(createVInt(newSize, true, false)));
// Check if the original size of the size field was really 8 byte
if (static_cast<long long>(newVoid.size()) != (freeSpace->d->data - freeSpace->d->position))
newVoid = createVInt(Void, false).append(createVInt(newSize));
// Update freeSpace
freeSpace->d->size = newSize;
freeSpace->d->data = freeSpace->d->position + newVoid.size();
// Write to file
document->writeBlock(
newVoid.resize(static_cast<size_t>(newVoid.size() + newSize)).append(content));
}
}
}
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
EBML::Element::~Element()
{
delete d;
}
EBML::Element::Element(EBML::File *document)
: d(new EBML::Element::ElementPrivate(document))
{
}
EBML::Element *EBML::Element::getChild(EBML::ulli id)
{
populate();
for(List<Element *>::Iterator i = d->children.begin(); i != d->children.end();
++i) {
if ((*i)->d->id == id)
return *i;
}
return 0;
}
List<EBML::Element *> EBML::Element::getChildren(EBML::ulli id)
{
populate();
List<Element *> result;
for(List<Element *>::Iterator i = d->children.begin(); i != d->children.end();
++i) {
if ((*i)->d->id == id)
result.append(*i);
}
return result;
}
List<EBML::Element *> EBML::Element::getChildren()
{
populate();
return d->children;
}
EBML::Element *EBML::Element::getParent()
{
return d->parent;
}
ByteVector EBML::Element::getAsBinary()
{
d->document->seek(d->data);
return d->document->readBlock(static_cast<size_t>(d->size));
}
String EBML::Element::getAsString()
{
return String(getAsBinary(), String::UTF8);
}
long long EBML::Element::getAsInt()
{
// The debug note about returning 0 because of empty data is irrelevant. The
// behavior is as expected.
return getAsBinary().toInt64BE(0);
}
EBML::ulli EBML::Element::getAsUnsigned()
{
// The debug note about returning 0 because of empty data is irrelevant. The
// behavior is as expected.
return static_cast<ulli>(getAsBinary().toInt64BE(0));
}
long double EBML::Element::getAsFloat()
{
const ByteVector bin = getAsBinary();
switch (bin.size())
{
case 4:
return bin.toFloat32BE(0);
case 8:
return bin.toFloat64BE(0);
case 10:
return bin.toFloat80BE(0);
default:
debug("EBML::Element::getAsFloat() - Invalid data size. Returning 0.");
return 0.0;
}
}
EBML::Element *EBML::Element::addElement(EBML::ulli id)
{
Element *elem = new Element(
new ElementPrivate(id, d->document, this, d->data + d->size, 0)
);
d->children.append(elem);
return elem;
}
EBML::Element *EBML::Element::addElement(EBML::ulli id, const ByteVector &binary)
{
Element *elem = new Element(
new ElementPrivate(id, d->document, this, d->data + d->size, binary.size())
);
d->document->seek(elem->d->data);
d->document->writeBlock(binary);
d->children.append(elem);
return elem;
}
EBML::Element *EBML::Element::addElement(EBML::ulli id, const String &string)
{
return addElement(id, string.data(String::UTF8));
}
EBML::Element *EBML::Element::addElement(EBML::ulli id, signed long long number)
{
return addElement(id, ByteVector::fromUInt64BE(number));
}
EBML::Element *EBML::Element::addElement(EBML::ulli id, EBML::ulli number)
{
return addElement(id, ByteVector::fromUInt64BE(number));
}
EBML::Element *EBML::Element::addElement(EBML::ulli id, long double number)
{
// Probably, we will never need this method.
return 0;
}
bool EBML::Element::removeChildren(EBML::ulli id, bool useVoid)
{
bool result = false;
for(List<Element *>::Iterator i = d->children.begin(); i != d->children.end(); ++i)
if((*i)->d->id == id) {
removeChild(*i, useVoid);
result = true;
}
return result;
}
bool EBML::Element::removeChildren(bool useVoid)
{
// Maybe a better implementation, because we probably create a lot of voids
// in a row where a huge Void would be more appropriate.
if (d->children.isEmpty())
return false;
for(List<Element *>::Iterator i = d->children.begin(); i != d->children.end(); ++i)
removeChild(*i, useVoid);
return true;
}
bool EBML::Element::removeChild(Element *element, bool useVoid)
{
if (!d->children.contains(element))
return false;
if(!useVoid || !element->d->makeVoid()) {
d->document->removeBlock(element->d->position, static_cast<size_t>(element->d->size));
// Update parents
for(Element* current = this; current; current = current->d->parent)
current->d->size -= element->d->size;
// Update this element
for(List<Element *>::Iterator i = d->children.begin(); i != d->children.end(); ++i)
if(element == *i)
d->children.erase(i);
delete element;
}
return true;
}
void EBML::Element::setAsBinary(const ByteVector &binary)
{
// Maybe: Search for void element after this one
d->document->insert(binary, d->data, static_cast<size_t>(d->size));
}
void EBML::Element::setAsString(const String &string)
{
setAsBinary(string.data(String::UTF8));
}
void EBML::Element::setAsInt(signed long long number)
{
setAsBinary(ByteVector::fromUInt64BE(number));
}
void EBML::Element::setAsUnsigned(EBML::ulli number)
{
setAsBinary(ByteVector::fromUInt64BE(number));
}
void EBML::Element::setAsFloat(long double)
{
// Probably, we will never need this method.
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void EBML::Element::populate()
{
if(!d->populated) {
d->populated = true;
long long end = d->data + d->size;
for(long long i = d->data; i < end;) {
Element *elem = new Element(
new ElementPrivate(d->document, this, i)
);
d->children.append(elem);
i = elem->d->data + elem->d->size;
}
}
}
EBML::Element::Element(EBML::Element::ElementPrivate *pe) : d(pe)
{}

276
taglib/ebml/ebmlelement.h Normal file
View File

@@ -0,0 +1,276 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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_EBMLELEMENT_H
#define TAGLIB_EBMLELEMENT_H
#include "tlist.h"
#include "tbytevector.h"
#include "tstring.h"
#include "ebmlfile.h"
namespace TagLib {
namespace EBML {
/*!
* Represents an element of the EBML. The only instance of this child, that
* is directly used is the root element. Every other element is accessed
* via pointers to the elements within the root element.
*
* Just create one root instance per file to prevent race conditions.
*
* Changes of the document tree will be directly written back to the file.
* Invalid values (exceeding the maximal value defined in the RFC) will be
* truncated.
*
* This class should not be used by library users since the proper file
* class should handle the internals.
*
* NOTE: Currently does not adjust CRC32 values.
*/
class TAGLIB_EXPORT Element
{
public:
//! Destroys the instance of the element.
~Element();
/*!
* Creates an root element using document.
*/
explicit Element(File *document);
/*!
* Returns the first found child element with the given id. Returns a null
* pointer if the child does not exist.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*/
Element *getChild(const ulli id);
/*!
* Returns a list of all child elements with the given id. Returns an
* empty list if no such element exists.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*/
List<Element *> getChildren(const ulli id);
/*!
* Returns a list of every child elements available. Returns an empty list
* if there are no children.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*/
List<Element *> getChildren();
/*!
* Returns the parent element or null if no such element exists.
*/
Element *getParent();
/*!
* Returns the raw content of the element.
*/
ByteVector getAsBinary();
/*!
* Returns the content of this element interpreted as a string.
*/
String getAsString();
/*!
* Returns the content of this element interpreted as an signed integer.
*
* Do not call this method if *this element is not an INT element (see
* corresponding DTD)
*/
long long getAsInt();
/*!
* Returns the content of this element interpreted as an unsigned integer.
*
* Do not call this method if *this element is not an UINT element (see
* corresponding DTD)
*/
ulli getAsUnsigned();
/*!
* Returns the content of this element interpreted as a floating point
* type.
*
* Do not call this method if *this element is not an FLOAT element (see
* corresponding DTD)
*
* NOTE: There are 10 byte floats defined, therefore we might need a long
* double to store the value.
*/
long double getAsFloat();
/*!
* Adds an empty element with given id to this element. Returns a pointer
* to the new element.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*/
Element *addElement(ulli id);
/*!
* Adds a new element, containing the given binary, to this element.
* Returns a pointer to the new element.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*/
Element *addElement(ulli id, const ByteVector &binary);
/*!
* Adds a new element, containing the given string, to this element.
* Returns a pointer to the new element.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*/
Element *addElement(ulli id, const String &string);
/*!
* Adds a new element, containing the given integer, to this element.
* Returns a pointer to the new element.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*/
Element *addElement(ulli id, signed long long number);
/*!
* Adds a new element, containing the given unsigned integer, to this element.
* Returns a pointer to the new element.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*/
Element *addElement(ulli id, ulli number);
/*!
* Adds a new element, containing the given floating point value, to this element.
* Returns a pointer to the new element.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*
* This method is not implemented!
*/
Element *addElement(ulli id, long double number);
/*!
* Removes all children with the given id. Returns false if there was no
* such element.
* If useVoid is true, the element will be changed to a void element.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*
* Every pointer to a removed element is invalidated.
*/
bool removeChildren(ulli id, bool useVoid = true);
/*!
* Removes all children. Returns false if this element had no children.
* If useVoid ist rue, the element will be changed to a void element.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*
* Every pointer to a removed element is invalidated.
*/
bool removeChildren(bool useVoid = true);
/*!
* Removes the given element.
* If useVoid is true, the element will be changed to a void element.
*
* Do not call this method if *this element is not a container element (see
* corresponding DTD)
*
* The pointer to the given element is invalidated.
*/
bool removeChild(Element *element, bool useVoid = true);
/*!
* Writes the given binary to this element.
*/
void setAsBinary(const ByteVector &binary);
/*!
* Writes the given string to this element.
*/
void setAsString(const String &string);
/*!
* Writes the given integer to this element.
*/
void setAsInt(signed long long number);
/*!
* Writes the given unsigned integer to this element.
*/
void setAsUnsigned(ulli number);
/*!
* Writes the given floating point variable to this element.
*
* This method is not implemented!
*/
void setAsFloat(long double number);
private:
//! Non-copyable
Element(const Element &);
//! Non-copyable
Element &operator=(const File &);
//! Lazy parsing. This method will be triggered when trying to access
//! children.
void populate();
class ElementPrivate;
ElementPrivate *d;
//! Creates a new Element from an ElementPrivate. (The constructor takes
//! ownership of the pointer and will delete it when the element is
//! destroyed.
Element(ElementPrivate *pe);
};
}
}
#endif

102
taglib/ebml/ebmlfile.cpp Normal file
View File

@@ -0,0 +1,102 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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 "ebmlelement.h"
using namespace TagLib;
class EBML::File::FilePrivate
{
public:
explicit FilePrivate(File *document) : root(document)
{
}
// Performs a few basic checks and creates the FilePrivate if they were
// successful.
static FilePrivate *checkAndCreate(File* document)
{
document->seek(0);
ByteVector magical = document->readBlock(4);
if(static_cast<ulli>(magical.toUInt32BE(0)) != Header::EBML)
return 0;
FilePrivate *d = new FilePrivate(document);
Element *head = d->root.getChild(Header::EBML);
Element *p;
if(!head ||
!((p = head->getChild(Header::EBMLVersion)) && p->getAsUnsigned() == 1L) ||
!((p = head->getChild(Header::EBMLReadVersion)) && p->getAsUnsigned() == 1L) ||
// Actually 4 is the current maximum of the EBML spec, but we support up to 8
!((p = head->getChild(Header::EBMLMaxIDWidth)) && p->getAsUnsigned() <= 8) ||
!((p = head->getChild(Header::EBMLMaxSizeWidth)) && p->getAsUnsigned() <= 8)
) {
delete d;
return 0;
}
return d;
}
Element root;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
EBML::File::~File()
{
delete d;
}
EBML::Element *EBML::File::getDocumentRoot()
{
if(!d && isValid())
d = new FilePrivate(this);
return &d->root;
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
EBML::File::File(FileName file) :
TagLib::File(file)
{
if(isOpen()) {
d = FilePrivate::checkAndCreate(this);
if(!d)
setValid(false);
}
}
EBML::File::File(IOStream *stream) :
TagLib::File(stream)
{
if(isOpen()) {
d = FilePrivate::checkAndCreate(this);
if(!d)
setValid(false);
}
}

86
taglib/ebml/ebmlfile.h Normal file
View File

@@ -0,0 +1,86 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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_EBMLFILE_H
#define TAGLIB_EBMLFILE_H
#include "taglib_export.h"
#include "tfile.h"
#include "ebmlconstants.h"
namespace TagLib {
//! A namespace for the classes used by EBML-based metadata files
namespace EBML {
class Element;
/*!
* Represents an EBML file. It offers access to the root element which can
* be used to obtain the necessary information and to change the file
* according to changes.
*/
class TAGLIB_EXPORT File : public TagLib::File
{
public:
//! Destroys the instance of the file.
virtual ~File();
/*!
* Returns a pointer to the document root element of the EBML file.
*/
Element *getDocumentRoot();
protected:
/*!
* Constructs an instance of an EBML file from \a file.
*
* This constructor is protected since an object should be created
* through a specific subclass.
*/
explicit File(FileName file);
/*!
* Constructs an instance of an EBML file from an IOStream.
*
* This constructor is protected since an object should be created
* through a specific subclass.
*/
explicit File(IOStream *stream);
private:
//! Non-copyable
File(const File&);
File &operator=(const File &);
class FilePrivate;
FilePrivate *d;
};
}
}
#endif

View File

@@ -0,0 +1,135 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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 "ebmlmatroskaconstants.h"
#include "ebmlmatroskaaudio.h"
using namespace TagLib;
class EBML::Matroska::AudioProperties::AudioPropertiesPrivate
{
public:
// Constructor
AudioPropertiesPrivate() :
length(0),
bitrate(0),
channels(1),
samplerate(8000) {}
// The length of the file
int length;
// The bitrate
int bitrate;
// The amount of channels
int channels;
// The sample rate
int samplerate;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
EBML::Matroska::AudioProperties::AudioProperties(File *document) :
d(new AudioPropertiesPrivate())
{
read(document);
}
EBML::Matroska::AudioProperties::~AudioProperties()
{
delete d;
}
int EBML::Matroska::AudioProperties::length() const
{
return lengthInSeconds();
}
int EBML::Matroska::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int EBML::Matroska::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int EBML::Matroska::AudioProperties::bitrate() const
{
return d->bitrate;
}
int EBML::Matroska::AudioProperties::channels() const
{
return d->channels;
}
int EBML::Matroska::AudioProperties::sampleRate() const
{
return d->samplerate;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void EBML::Matroska::AudioProperties::read(File *document)
{
Element *elem = document->getDocumentRoot()->getChild(Constants::Segment);
Element *info = elem->getChild(Constants::SegmentInfo);
Element *value;
if(info && (value = info->getChild(Constants::Duration))) {
const double length = value->getAsFloat() / 1000000.0;
if((value = info->getChild(Constants::TimecodeScale)))
d->length = static_cast<int>(length * value->getAsUnsigned() + 0.5);
else
d->length = static_cast<int>(length * 1000000 + 0.5);
}
info = elem->getChild(Constants::Tracks);
if(!info || !(info = info->getChild(Constants::TrackEntry)) ||
!(info = info->getChild(Constants::Audio))) {
return;
}
// Dirty bitrate:
if(d->length > 0)
d->bitrate = static_cast<int>(document->length() * 8.0 / d->length + 0.5);
if((value = info->getChild(Constants::Channels)))
d->channels = static_cast<int>(value->getAsUnsigned());
if((value = info->getChild(Constants::SamplingFrequency)))
d->samplerate = static_cast<int>(value->getAsFloat());
}

View File

@@ -0,0 +1,92 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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_EBMLMATROSKAAUDIO_H
#define TAGLIB_EBMLMATROSKAAUDIO_H
#include "ebmlmatroskafile.h"
#include "audioproperties.h"
namespace TagLib {
namespace EBML {
namespace Matroska {
/*!
* This class represents the audio properties of a matroska file.
* Currently all information are read from the container format and
* could be inexact.
*/
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
//! Destructor
virtual ~AudioProperties();
/*!
* Constructs an instance from a file.
*/
explicit AudioProperties(File *document);
/*!
* Returns the length of the file.
*/
virtual int length() const;
virtual int lengthInSeconds() const;
virtual int lengthInMilliseconds() const;
/*!
* Returns the bit rate of the file. Since the container format does not
* offer a proper value, it ist currently calculated by dividing the
* file size by the length.
*/
virtual int bitrate() const;
/*!
* Returns the amount of channels of the file.
*/
virtual int channels() const;
/*!
* Returns the sample rate of the file.
*/
virtual int sampleRate() const;
private:
void read(File *document);
class AudioPropertiesPrivate;
AudioPropertiesPrivate *d;
};
}
}
}
#endif

View File

@@ -0,0 +1,140 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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_EBMLMATROSKACONSTANTS_H
#define TAGLIB_EBMLMATROSKACONSTANTS_H
#include "ebmlconstants.h"
#include "tstring.h"
namespace TagLib {
namespace EBML {
namespace Matroska {
namespace Constants {
//! ID of an Matroska segment.
const ulli Segment = 0x18538067L;
//! ID of the tags element.
const ulli Tags = 0x1254c367L;
//! ID of the tag element.
const ulli Tag = 0x7373L;
//! ID of the targets element.
const ulli Targets = 0x63c0L;
//! ID of the target type value element.
const ulli TargetTypeValue = 0x68caL;
//! ID of the target type element.
const ulli TargetType = 0x63caL;
//! ID of a simple tag element.
const ulli SimpleTag = 0x67c8L;
//! ID of the tag name.
const ulli TagName = 0x45a3L;
//! ID of the tag content.
const ulli TagString = 0x4487L;
//! The DocType of a matroska file.
const String DocTypeMatroska = "matroska";
//! The DocType of a WebM file.
const String DocTypeWebM = "webm";
//! The TITLE entry
const String TITLE = "TITLE";
//! The ARTIST entry
const String ARTIST = "ARTIST";
//! The COMMENT entry
const String COMMENT = "COMMENT";
//! The GENRE entry
const String GENRE = "GENRE";
//! The DATE_RELEASE entry
const String DATE_RELEASE = "DATE_RELEASE";
//! The PART_NUMBER entry
const String PART_NUMBER = "PART_NUMBER";
//! The TargetTypeValue of the most common grouping level (e.g. album)
const ulli MostCommonGroupingValue = 50;
//! The TargetTypeValue of the most common parts of a group (e.g. track)
const ulli MostCommonPartValue = 30;
//! Name of the TargetType of an album.
const String ALBUM = "ALBUM";
//! Name of the TargetType of a track.
const String TRACK = "TRACK";
// For AudioProperties
//! ID of the Info block within the Segment.
const ulli SegmentInfo = 0x1549a966L;
//! ID of the duration element.
const ulli Duration = 0x4489L;
//! ID of TimecodeScale element.
const ulli TimecodeScale = 0x2ad7b1L;
//! ID of the Tracks container
const ulli Tracks = 0x1654ae6bL;
//! ID of a TrackEntry element.
const ulli TrackEntry = 0xaeL;
//! ID of the Audio container.
const ulli Audio = 0xe1L;
//! ID of the SamplingFrequency element.
const ulli SamplingFrequency = 0xb5L;
//! ID of the Channels element.
const ulli Channels = 0x9fL;
//! ID of the BitDepth element.
const ulli BitDepth = 0x6264L;
}
}
}
}
#endif

View File

@@ -0,0 +1,563 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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 "ebmlmatroskaconstants.h"
#include "ebmlmatroskaaudio.h"
#include "tpicturemap.h"
#include "tpropertymap.h"
using namespace TagLib;
class EBML::Matroska::File::FilePrivate
{
public:
// Returns true if simpleTag has a TagName and TagString child and writes
// their contents into name and value.
bool extractContent(Element *simpleTag, String &name, String &value)
{
Element *n = simpleTag->getChild(Constants::TagName);
Element *v = simpleTag->getChild(Constants::TagString);
if(!n || !v)
return false;
name = n->getAsString();
value = v->getAsString();
return true;
}
explicit FilePrivate(File *p_document) : tag(0), document(p_document)
{
// Just get the first segment, because "Typically a Matroska file is
// composed of 1 segment."
Element* elem = document->getDocumentRoot()->getChild(Constants::Segment);
// We take the first tags element (there shouldn't be more), if there is
// non such element, consider the file as not compatible.
if(!elem || !(elem = elem->getChild(Constants::Tags))) {
document->setValid(false);
return;
}
// Load all Tag entries
List<Element *> entries = elem->getChildren(Constants::Tag);
for(List<Element *>::Iterator i = entries.begin(); i != entries.end(); ++i) {
Element *target = (*i)->getChild(Constants::Targets);
ulli ttvalue = 50; // 50 is default (see spec.)
if(target && (target = target->getChild(Constants::TargetTypeValue)))
ttvalue = target->getAsUnsigned();
// Load all SimpleTags
PropertyMap tagEntries;
List<Element *> simpleTags = (*i)->getChildren(Constants::SimpleTag);
for(List<Element *>::Iterator j = simpleTags.begin(); j != simpleTags.end();
++j) {
String name, value;
if(!extractContent(*j, name, value))
continue;
tagEntries.insert(name, StringList(value));
}
tags.append(std::pair<PropertyMap, std::pair<Element *, ulli> >(tagEntries, std::pair<Element *, ulli>(*i, ttvalue)));
}
}
// Creates Tag and AudioProperties. Late creation because both require a fully
// functional FilePrivate (well AudioProperties doesn't...)
void lateCreate()
{
tag = new Tag(document);
audio = new AudioProperties(document);
}
// Checks the EBML header and creates the FilePrivate.
static FilePrivate *checkAndCreate(File *document)
{
Element *elem = document->getDocumentRoot()->getChild(Header::EBML);
Element *child = elem->getChild(Header::DocType);
if(child) {
String dt = child->getAsString();
if (dt == Constants::DocTypeMatroska || dt == Constants::DocTypeWebM) {
FilePrivate *fp = new FilePrivate(document);
return fp;
}
}
return 0;
}
// The tags with their Element and TargetTypeValue
List<std::pair<PropertyMap, std::pair<Element *, ulli> > > tags;
// The tag
Tag *tag;
// The audio properties
AudioProperties *audio;
// The corresponding file.
File *document;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
EBML::Matroska::File::~File()
{
if (d) {
delete d->tag;
delete d->audio;
delete d;
}
}
EBML::Matroska::File::File(FileName file, bool, AudioProperties::ReadStyle) : EBML::File(file), d(0)
{
if(isValid() && isOpen()) {
d = FilePrivate::checkAndCreate(this);
if(!d)
setValid(false);
else
d->lateCreate();
}
}
EBML::Matroska::File::File(IOStream *stream, bool, AudioProperties::ReadStyle) : EBML::File(stream), d(0)
{
if(isValid() && isOpen()) {
d = FilePrivate::checkAndCreate(this);
if(!d)
setValid(false);
else
d->lateCreate();
}
}
Tag *EBML::Matroska::File::tag() const
{
return d->tag;
}
PropertyMap EBML::Matroska::File::properties() const
{
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator best = d->tags.end();
for(List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator i = d->tags.begin();
i != d->tags.end(); ++i) {
if(best == d->tags.end() || best->second.second > i->second.second)
best = i;
}
return best->first;
}
PropertyMap EBML::Matroska::File::setProperties(const PropertyMap &properties)
{
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator best = d->tags.end();
for(List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator i = d->tags.begin();
i != d->tags.end(); ++i) {
if(best == d->tags.end() || best->second.second > i->second.second)
best = i;
}
std::pair<PropertyMap, std::pair<Element *, ulli> > replace(properties, best->second);
d->tags.erase(best);
d->tags.prepend(replace);
return PropertyMap();
}
AudioProperties *EBML::Matroska::File::audioProperties() const
{
return d->audio;
}
bool EBML::Matroska::File::save()
{
if(readOnly())
return false;
// C++11 features would be nice: for(auto &i : d->tags) { /* ... */ }
// Well, here we just iterate each extracted element.
for(List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator i = d->tags.begin();
i != d->tags.end(); ++i) {
for(PropertyMap::Iterator j = i->first.begin(); j != i->first.end(); ++j) {
// No element? Create it!
if(!i->second.first) {
// Should be save, since we already checked, when creating the object.
Element *container = d->document->getDocumentRoot()
->getChild(Constants::Segment)->getChild(Constants::Tags);
// Create Targets container
i->second.first = container->addElement(Constants::Tag);
Element *target = i->second.first->addElement(Constants::Targets);
if(i->second.second == Constants::MostCommonPartValue)
target->addElement(Constants::TargetType, Constants::TRACK);
else if(i->second.second == Constants::MostCommonGroupingValue)
target->addElement(Constants::TargetType, Constants::ALBUM);
target->addElement(Constants::TargetTypeValue, i->second.second);
}
// Find entries
List<Element *> simpleTags = i->second.first->getChildren(Constants::SimpleTag);
StringList::Iterator str = j->second.begin();
List<Element *>::Iterator k = simpleTags.begin();
for(; k != simpleTags.end(); ++k) {
String name, value;
if(!d->extractContent(*k, name, value))
continue;
// Write entry from StringList
if(name == j->first) {
if(str == j->second.end()) {
// We have all StringList elements but still found another element
// with the same name? Let's delete it!
i->second.first->removeChild(*k);
}
else {
if(value != *str) {
// extractContent already checked for availability
(*k)->getChild(Constants::TagString)->setAsString(*str);
}
++str;
}
}
}
// If we didn't write the complete StringList, we have to write the rest.
for(; str != j->second.end(); ++str) {
Element *stag = i->second.first->addElement(Constants::SimpleTag);
stag->addElement(Constants::TagName, j->first);
stag->addElement(Constants::TagString, *str);
}
}
// Finally, we have to find elements that are not in the PropertyMap and
// remove them.
List<Element *> simpleTags = i->second.first->getChildren(Constants::SimpleTag);
for(List<Element *>::Iterator j = simpleTags.begin(); j != simpleTags.end(); ++j) {
String name, value;
if(!d->extractContent(*j, name, value))
continue;
if(i->first.find(name) == i->first.end()){
i->second.first->removeChild(*j);}
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
// Tag
//
////////////////////////////////////////////////////////////////////////////////
class EBML::Matroska::File::Tag::TagPrivate
{
public:
// Creates a TagPrivate instance
explicit TagPrivate(File *p_document) :
document(p_document),
title(document->d->tags.end()),
artist(document->d->tags.end()),
album(document->d->tags.end()),
comment(document->d->tags.end()),
genre(document->d->tags.end()),
year(document->d->tags.end()),
track(document->d->tags.end())
{
for(List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator i =
document->d->tags.begin(); i != document->d->tags.end(); ++i) {
// Just save it, if the title is more specific, or there is no title yet.
if(i->first.find(Constants::TITLE) != i->first.end() &&
(title == document->d->tags.end() ||
title->second.second > i->second.second ||
i->second.second == Constants::MostCommonPartValue)) {
title = i;
}
// Same goes for artist.
if(i->first.find(Constants::ARTIST) != i->first.end() &&
(artist == document->d->tags.end() ||
artist->second.second > i->second.second ||
i->second.second == Constants::MostCommonPartValue)) {
artist = i;
}
// Here, we also look for a title (the album title), but since we
// specified the granularity, we have to search for it exactly.
// Therefore it is possible, that title and album are the same (if only
// the title of the album is given).
if(i->first.find(Constants::TITLE) != i->first.end() &&
i->second.second == Constants::MostCommonGroupingValue) {
album = i;
}
// Again the same as title and artist.
if(i->first.find(Constants::COMMENT) != i->first.end() &&
(comment == document->d->tags.end() ||
comment->second.second > i->second.second ||
i->second.second == Constants::MostCommonPartValue)) {
comment = i;
}
// Same goes for genre.
if(i->first.find(Constants::GENRE) != i->first.end() &&
(genre == document->d->tags.end() ||
genre->second.second > i->second.second ||
i->second.second == Constants::MostCommonPartValue)) {
genre = i;
}
// And year (in our case: DATE_REALEASE)
if(i->first.find(Constants::DATE_RELEASE) != i->first.end() &&
(year == document->d->tags.end() ||
year->second.second > i->second.second ||
i->second.second == Constants::MostCommonPartValue)) {
year = i;
}
// And track (in our case: PART_NUMBER)
if(i->first.find(Constants::PART_NUMBER) != i->first.end() &&
(track == document->d->tags.end() ||
track->second.second > i->second.second ||
i->second.second == Constants::MostCommonPartValue)) {
track = i;
}
}
}
// Searches for the Tag with given TargetTypeValue (returns the first one)
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator
find(ulli ttv)
{
for(List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator i =
document->d->tags.begin(); i != document->d->tags.end(); ++i) {
if(i->second.second == ttv)
return i;
}
return document->d->tags.end();
}
// Updates the given information
void update(
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator t,
const String &tagname,
const String &s
)
{
t->first.find(tagname)->second.front() = s;
}
// Inserts a tag with given information
void insert(const String &tagname, const ulli ttv, const String &s)
{
for(List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator i =
document->d->tags.begin(); i != document->d->tags.end(); ++i) {
if(i->second.second == ttv) {
i->first.insert(tagname, StringList(s));
return;
}
}
// Not found? Create new!
PropertyMap pm;
pm.insert(tagname, StringList(s));
document->d->tags.append(
std::pair<PropertyMap, std::pair<Element *, ulli> >(pm,
std::pair<Element *, ulli>(static_cast<Element *>(0), ttv)
)
);
}
// The PropertyMap from the Matroska::File
File *document;
// Iterators to the tags.
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator title;
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator artist;
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator album;
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator comment;
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator genre;
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator year;
List<std::pair<PropertyMap, std::pair<Element *, ulli> > >::Iterator track;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
EBML::Matroska::File::Tag::~Tag()
{
delete e;
}
EBML::Matroska::File::Tag::Tag(EBML::Matroska::File *document) :
e(new EBML::Matroska::File::Tag::TagPrivate(document))
{
}
String EBML::Matroska::File::Tag::title() const
{
if(e->title != e->document->d->tags.end())
return e->title->first.find(Constants::TITLE)->second.front();
else
return String();
}
String EBML::Matroska::File::Tag::artist() const
{
if(e->artist != e->document->d->tags.end())
return e->artist->first.find(Constants::ARTIST)->second.front();
else
return String();
}
String EBML::Matroska::File::Tag::album() const
{
if(e->album != e->document->d->tags.end())
return e->album->first.find(Constants::TITLE)->second.front();
else
return String();
}
PictureMap EBML::Matroska::File::Tag::pictures() const
{
return PictureMap();
}
String EBML::Matroska::File::Tag::comment() const
{
if(e->comment != e->document->d->tags.end())
return e->comment->first.find(Constants::COMMENT)->second.front();
else
return String();
}
String EBML::Matroska::File::Tag::genre() const
{
if(e->genre != e->document->d->tags.end())
return e->genre->first.find(Constants::GENRE)->second.front();
else
return String();
}
unsigned int EBML::Matroska::File::Tag::year() const
{
if(e->year != e->document->d->tags.end())
return e->year->first.find(Constants::DATE_RELEASE)->second.front().toInt();
else
return 0;
}
unsigned int EBML::Matroska::File::Tag::track() const
{
if(e->track != e->document->d->tags.end())
return e->track->first.find(Constants::PART_NUMBER)->second.front().toInt();
else
return 0;
}
void EBML::Matroska::File::Tag::setTitle(const String &s)
{
if(e->title != e->document->d->tags.end())
e->update(e->title, Constants::TITLE, s);
else
e->insert(Constants::TITLE, Constants::MostCommonPartValue, s);
}
void EBML::Matroska::File::Tag::setArtist(const String &s)
{
if(e->artist != e->document->d->tags.end())
e->update(e->artist, Constants::ARTIST, s);
else
e->insert(Constants::ARTIST, Constants::MostCommonPartValue, s);
}
void EBML::Matroska::File::Tag::setAlbum(const String &s)
{
if(e->album != e->document->d->tags.end())
e->update(e->album, Constants::TITLE, s);
else
e->insert(Constants::TITLE, Constants::MostCommonGroupingValue, s);
}
void EBML::Matroska::File::Tag::setPictures(const PictureMap& p )
{
(void)p; // avoid warning for unused variable
}
void EBML::Matroska::File::Tag::setComment(const String &s)
{
if(e->comment != e->document->d->tags.end())
e->update(e->comment, Constants::COMMENT, s);
else
e->insert(Constants::COMMENT, Constants::MostCommonPartValue, s);
}
void EBML::Matroska::File::Tag::setGenre(const String &s)
{
if(e->genre != e->document->d->tags.end())
e->update(e->genre, Constants::GENRE, s);
else
e->insert(Constants::GENRE, Constants::MostCommonPartValue, s);
}
void EBML::Matroska::File::Tag::setYear(unsigned int i)
{
String s = String::number(i);
if(e->year != e->document->d->tags.end())
e->update(e->year, Constants::DATE_RELEASE, s);
else
e->insert(Constants::DATE_RELEASE, Constants::MostCommonPartValue, s);
}
void EBML::Matroska::File::Tag::setTrack(unsigned int i)
{
String s = String::number(i);
if(e->track != e->document->d->tags.end())
e->update(e->track, Constants::PART_NUMBER, s);
else
e->insert(Constants::PART_NUMBER, Constants::MostCommonPartValue, s);
}

View File

@@ -0,0 +1,228 @@
/***************************************************************************
copyright : (C) 2013 by Sebastian Rachuj
email : rachus@web.de
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 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_EBMLMATROSKAFILE_H
#define TAGLIB_EBMLMATROSKAFILE_H
#include "ebmlelement.h"
#include "audioproperties.h"
namespace TagLib {
namespace EBML {
//! Implementation for reading Matroska tags.
namespace Matroska {
/*!
* Implements the TagLib::File API and offers access to the tags of the
* matroska file.
*/
class TAGLIB_EXPORT File : public EBML::File
{
public:
//! Destroys the instance of the file.
virtual ~File();
/*!
* Constructs a Matroska 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. The audio properties are always
* read.
*/
explicit File(FileName file, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Constructs a Matroska file from \a stream. 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. The audio properties are always
* read.
*/
explicit File(IOStream *stream, bool readproperties = true,
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Returns the pointer to a tag that allow access on common tags.
*/
virtual TagLib::Tag *tag() const;
/*!
* Exports the tags to a PropertyMap. Due to the diversity of the
* Matroska format (e.g. multiple media streams in one file, each with
* its own tags), only the best fitting tags are taken into account.
* There are no unsupported tags.
*/
virtual PropertyMap properties() const;
/*!
* Sets the tags of the file to those specified in properties. The
* returned PropertyMap is always empty.
* Note: Only the best fitting tags are taken into account.
*/
virtual PropertyMap setProperties(const PropertyMap &properties);
/*!
* Returns a pointer to this file's audio properties.
*
* I'm glad about not having a setAudioProperties method ;)
*/
virtual AudioProperties *audioProperties() const;
/*!
* Saves the file. Returns true on success.
*/
bool save();
/*!
* Offers access to a few common tag entries.
*/
class Tag : public TagLib::Tag
{
public:
//! Destroys the tag.
~Tag();
/*!
* Creates a new Tag for Matroska files. The given properties are gained
* by the Matroska::File.
*/
explicit Tag(File *document);
/*!
* Returns the track name; if no track name is present in the tag
* String::null will be returned.
*/
virtual String title() const;
/*!
* Returns the artist name; if no artist name is present in the tag
* String::null will be returned.
*/
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 a list of pictures; if no picture is present in the tag
* an empty PictureMap is returned
*/
virtual PictureMap pictures() const;
/*!
* Returns the track comment; if no comment is present in the tag
* String::null will be returned.
*/
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 year; if there is no year set, this will return 0.
*/
virtual unsigned int year() const;
/*!
* Returns the track number; if there is no track number set, this will
* return 0.
*/
virtual unsigned int track() const;
/*!
* Sets the title to s. If s is String::null then this value will be
* cleared.
*/
virtual void setTitle(const String &s);
/*!
* Sets the artist to s. If s is String::null then this value will be
* cleared.
*/
virtual void setArtist(const String &s);
/*!
* Sets the album to s. If s is String::null then this value will be
* cleared.
*/
virtual void setAlbum(const String &s);
/*!
* Sets the picture map to p. If p is empty then this value will be
* cleared
*/
virtual void setPictures(const PictureMap& p );
/*!
* Sets the comment to s. If s is String::null then this value will be
* cleared.
*/
virtual void setComment(const String &s);
/*!
* Sets the genre to s. If s is String::null then this value will be
* cleared.
*/
virtual void setGenre(const String &s);
/*!
* Sets the year to i. If s is 0 then this value will be cleared.
*/
virtual void setYear(unsigned int i);
/*!
* Sets the track to i. If s is 0 then this value will be cleared.
*/
virtual void setTrack(unsigned int i);
private:
class TagPrivate;
TagPrivate *e;
};
private:
class FilePrivate;
FilePrivate *d;
};
}
}
}
#endif

View File

@@ -31,7 +31,7 @@
#include <tfilestream.h>
#include <tstring.h>
#include <tdebug.h>
#include <trefcounter.h>
#include <tsmartptr.h>
#include "fileref.h"
#include "asffile.h"
@@ -54,6 +54,7 @@
#include "xmfile.h"
#include "dsffile.h"
#include "dsdifffile.h"
#include "ebmlmatroskafile.h"
using namespace TagLib;
@@ -83,14 +84,14 @@ namespace
AudioProperties::ReadStyle audioPropertiesStyle)
{
#ifdef _WIN32
const String s = stream->name().toString();
const String s(stream->name().wstr());
#else
const String s(stream->name());
#endif
String ext;
const int pos = s.rfind(".");
if(pos != -1)
const size_t pos = s.rfind(".");
if(pos != String::npos())
ext = s.substr(pos + 1).upper();
// If this list is updated, the method defaultFileExtensions() should also be
@@ -107,7 +108,7 @@ namespace
if(ext == "OGG")
return new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "FLAC")
return new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
return new FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "MPC")
return new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WV")
@@ -141,6 +142,9 @@ namespace
return new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "DSF")
return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
if (ext == "MKA" || ext == "MKV") {
return new EBML::Matroska::File(stream, readAudioProperties, audioPropertiesStyle);
}
return 0;
}
@@ -159,7 +163,7 @@ namespace
else if(Ogg::FLAC::File::isSupported(stream))
file = new Ogg::FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
else if(FLAC::File::isSupported(stream))
file = new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
file = new FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
else if(MPC::File::isSupported(stream))
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
else if(WavPack::File::isSupported(stream))
@@ -197,98 +201,29 @@ namespace
return 0;
}
// Internal function that supports FileRef::create().
// This looks redundant, but necessary in order not to change the previous
// behavior of FileRef::create().
File* createInternal(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
struct FileRefData
{
File *file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
if(file)
return file;
FileRefData() :
file(0),
stream(0) {}
#ifdef _WIN32
const String s = fileName.toString();
#else
const String s(fileName);
#endif
String ext;
const int pos = s.rfind(".");
if(pos != -1)
ext = s.substr(pos + 1).upper();
if(ext.isEmpty())
return 0;
if(ext == "MP3")
return new MPEG::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
if(ext == "OGG")
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "OGA") {
/* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
if(file->isValid())
return file;
~FileRefData() {
delete file;
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
delete stream;
}
if(ext == "FLAC")
return new FLAC::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
if(ext == "MPC")
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "WV")
return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "SPX")
return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "OPUS")
return new Ogg::Opus::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "TTA")
return new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "WMA" || ext == "ASF")
return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "WAV")
return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "APE")
return new APE::File(fileName, readAudioProperties, audioPropertiesStyle);
// module, nst and wow are possible but uncommon extensions
if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
return new Mod::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "S3M")
return new S3M::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "IT")
return new IT::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "XM")
return new XM::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "DFF" || ext == "DSDIFF")
return new DSDIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "DSF")
return new DSF::File(fileName, readAudioProperties, audioPropertiesStyle);
return 0;
}
File *file;
IOStream *stream;
};
}
class FileRef::FileRefPrivate : public RefCounter
class FileRef::FileRefPrivate
{
public:
FileRefPrivate() :
RefCounter(),
file(0),
stream(0) {}
data(new FileRefData()) {}
~FileRefPrivate() {
delete file;
delete stream;
}
File *file;
IOStream *stream;
SHARED_PTR<FileRefData> data;
};
////////////////////////////////////////////////////////////////////////////////
@@ -316,19 +251,17 @@ FileRef::FileRef(IOStream* stream, bool readAudioProperties, AudioProperties::Re
FileRef::FileRef(File *file) :
d(new FileRefPrivate())
{
d->file = file;
d->data->file = file;
}
FileRef::FileRef(const FileRef &ref) :
d(ref.d)
d(new FileRefPrivate(*ref.d))
{
d->ref();
}
FileRef::~FileRef()
{
if(d->deref())
delete d;
delete d;
}
Tag *FileRef::tag() const
@@ -337,7 +270,37 @@ Tag *FileRef::tag() const
debug("FileRef::tag() - Called without a valid file.");
return 0;
}
return d->file->tag();
return d->data->file->tag();
}
PropertyMap FileRef::properties() const
{
if(isNull()) {
debug("FileRef::properties() - Called without a valid file.");
return PropertyMap();
}
return d->data->file->properties();
}
void FileRef::removeUnsupportedProperties(const StringList& properties)
{
if(isNull()) {
debug("FileRef::removeUnsupportedProperties() - Called without a valid file.");
return;
}
d->data->file->removeUnsupportedProperties(properties);
}
PropertyMap FileRef::setProperties(const PropertyMap &properties)
{
if(isNull()) {
debug("FileRef::setProperties() - Called without a valid file.");
return PropertyMap();
}
return d->data->file->setProperties(properties);
}
AudioProperties *FileRef::audioProperties() const
@@ -346,12 +309,12 @@ AudioProperties *FileRef::audioProperties() const
debug("FileRef::audioProperties() - Called without a valid file.");
return 0;
}
return d->file->audioProperties();
return d->data->file->audioProperties();
}
File *FileRef::file() const
{
return d->file;
return d->data->file;
}
bool FileRef::save()
@@ -360,7 +323,7 @@ bool FileRef::save()
debug("FileRef::save() - Called without a valid file.");
return false;
}
return d->file->save();
return d->data->file->save();
}
const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::FileTypeResolver *resolver) // static
@@ -404,13 +367,20 @@ StringList FileRef::defaultFileExtensions()
l.append("dsf");
l.append("dff");
l.append("dsdiff"); // alias for "dff"
l.append("mka");
l.append("mkv");
return l;
}
bool FileRef::isValid() const
{
return (d->data->file && d->data->file->isValid());
}
bool FileRef::isNull() const
{
return (!d->file || !d->file->isValid());
return !isValid();
}
FileRef &FileRef::operator=(const FileRef &ref)
@@ -428,18 +398,12 @@ void FileRef::swap(FileRef &ref)
bool FileRef::operator==(const FileRef &ref) const
{
return (ref.d->file == d->file);
return (ref.d->data == d->data);
}
bool FileRef::operator!=(const FileRef &ref) const
{
return (ref.d->file != d->file);
}
File *FileRef::create(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle) // static
{
return createInternal(fileName, readAudioProperties, audioPropertiesStyle);
return (ref.d->data != d->data);
}
////////////////////////////////////////////////////////////////////////////////
@@ -451,27 +415,27 @@ void FileRef::parse(FileName fileName, bool readAudioProperties,
{
// Try user-defined resolvers.
d->file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
if(d->file)
d->data->file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
if(d->data->file)
return;
// Try to resolve file types based on the file extension.
d->stream = new FileStream(fileName);
d->file = detectByExtension(d->stream, readAudioProperties, audioPropertiesStyle);
if(d->file)
d->data->stream = new FileStream(fileName);
d->data->file = detectByExtension(d->data->stream, readAudioProperties, audioPropertiesStyle);
if(d->data->file)
return;
// At last, try to resolve file types based on the actual content.
d->file = detectByContent(d->stream, readAudioProperties, audioPropertiesStyle);
if(d->file)
d->data->file = detectByContent(d->data->stream, readAudioProperties, audioPropertiesStyle);
if(d->data->file)
return;
// Stream have to be closed here if failed to resolve file types.
delete d->stream;
d->stream = 0;
delete d->data->stream;
d->data->stream = 0;
}
void FileRef::parse(IOStream *stream, bool readAudioProperties,
@@ -481,11 +445,11 @@ void FileRef::parse(IOStream *stream, bool readAudioProperties,
// Try to resolve file types based on the file extension.
d->file = detectByExtension(stream, readAudioProperties, audioPropertiesStyle);
if(d->file)
d->data->file = detectByExtension(stream, readAudioProperties, audioPropertiesStyle);
if(d->data->file)
return;
// At last, try to resolve file types based on the actual content of the file.
d->file = detectByContent(stream, readAudioProperties, audioPropertiesStyle);
d->data->file = detectByContent(stream, readAudioProperties, audioPropertiesStyle);
}

View File

@@ -26,10 +26,10 @@
#ifndef TAGLIB_FILEREF_H
#define TAGLIB_FILEREF_H
#include "taglib_export.h"
#include "tfile.h"
#include "tstringlist.h"
#include "taglib_export.h"
#include "tpropertymap.h"
#include "audioproperties.h"
namespace TagLib {
@@ -91,8 +91,9 @@ namespace TagLib {
class TAGLIB_EXPORT FileTypeResolver
{
TAGLIB_IGNORE_MISSING_DESTRUCTOR
public:
virtual ~FileTypeResolver() {}
/*!
* This method must be overridden to provide an additional file type
* resolver. If the resolver is able to determine the file type it should
@@ -173,6 +174,41 @@ namespace TagLib {
*/
Tag *tag() const;
/*!
* Exports the tags of the file as dictionary mapping (human readable) tag
* names (uppercase Strings) to StringLists of tag values. Calls the according
* specialization in the File subclasses.
* For each metadata object of the file that could not be parsed into the PropertyMap
* format, the returend map's unsupportedData() list will contain one entry identifying
* that object (e.g. the frame type for ID3v2 tags). Use removeUnsupportedProperties()
* to remove (a subset of) them.
* For files that contain more than one tag (e.g. an MP3 with both an ID3v1 and an ID3v2
* tag) only the most "modern" one will be exported (ID3v2 in this case).
*/
PropertyMap properties() const;
/*!
* Removes unsupported properties, or a subset of them, from the file's metadata.
* The parameter \a properties must contain only entries from
* properties().unsupportedData().
*/
void removeUnsupportedProperties(const StringList& properties);
/*!
* Sets the tags of this File to those specified in \a properties. Calls the
* according specialization method in the subclasses of File to do the translation
* into the format-specific details.
* If some value(s) could not be written imported to the specific metadata format,
* the returned PropertyMap will contain those value(s). Otherwise it will be empty,
* indicating that no problems occured.
* With file types that support several tag formats (for instance, MP3 files can have
* ID3v1, ID3v2, and APEv2 tags), this function will create the most appropriate one
* (ID3v2 for MP3 files). Older formats will be updated as well, if they exist, but won't
* be taken into account for the return value of this function.
* See the documentation of the subclass implementations for detailed descriptions.
*/
PropertyMap setProperties(const PropertyMap &properties);
/*!
* Returns the audio properties for this FileRef. If no audio properties
* were read then this will returns a null pointer.
@@ -233,8 +269,17 @@ namespace TagLib {
*/
static StringList defaultFileExtensions();
/*!
* Returns true if the file is open and readable.
*
* \note Just a negative of isNull().
*/
bool isValid() const;
/*!
* Returns true if the file (and as such other pointers) are null.
*
* \note Just a negative of isValid().
*/
bool isNull() const;
@@ -259,21 +304,6 @@ namespace TagLib {
*/
bool operator!=(const FileRef &ref) const;
/*!
* A simple implementation of file type guessing. If \a readAudioProperties
* is true then the audio properties will be read using
* \a audioPropertiesStyle. If \a readAudioProperties is false then
* \a audioPropertiesStyle will be ignored.
*
* \note You generally shouldn't use this method, but instead the constructor
* directly.
*
* \deprecated
*/
static File *create(FileName fileName,
bool readAudioProperties = true,
AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average);
private:
void parse(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle);
void parse(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle);

View File

@@ -30,6 +30,7 @@
#include <tagunion.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include <tsmartptr.h>
#include <id3v2header.h>
#include <id3v2tag.h>
@@ -45,53 +46,61 @@ using namespace TagLib;
namespace
{
typedef List<FLAC::MetadataBlock *> BlockList;
typedef List<SHARED_PTR<FLAC::MetadataBlock> > BlockList;
typedef BlockList::Iterator BlockIterator;
typedef BlockList::Iterator BlockConstIterator;
enum { FlacXiphIndex = 0, FlacID3v2Index = 1, FlacID3v1Index = 2 };
const long MinPaddingLength = 4096;
const long MaxPaddingLegnth = 1024 * 1024;
const long long MinPaddingLength = 4096;
const long long MaxPaddingLegnth = 1024 * 1024;
const char LastBlockFlag = '\x80';
}
namespace TagLib
{
namespace FLAC
{
// Enables BlockList::find() to take raw pointers.
bool operator==(SHARED_PTR<MetadataBlock> lhs, MetadataBlock *rhs)
{
return lhs.get() == rhs;
}
}
}
class FLAC::File::FilePrivate
{
public:
FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) :
ID3v2FrameFactory(frameFactory),
explicit FilePrivate(const ID3v2::FrameFactory *frameFactory) :
ID3v2FrameFactory(ID3v2::FrameFactory::instance()),
ID3v2Location(-1),
ID3v2OriginalSize(0),
ID3v1Location(-1),
properties(0),
flacStart(0),
streamStart(0),
scanned(false)
{
blocks.setAutoDelete(true);
}
~FilePrivate()
{
delete properties;
if(frameFactory)
ID3v2FrameFactory = frameFactory;
}
const ID3v2::FrameFactory *ID3v2FrameFactory;
long ID3v2Location;
long ID3v2OriginalSize;
long long ID3v2Location;
long long ID3v2OriginalSize;
long ID3v1Location;
long long ID3v1Location;
TagUnion tag;
TripleTagUnion tag;
Properties *properties;
SCOPED_PTR<AudioProperties> properties;
ByteVector xiphCommentData;
BlockList blocks;
long flacStart;
long streamStart;
long long flacStart;
long long streamStart;
bool scanned;
};
@@ -104,23 +113,15 @@ bool FLAC::File::isSupported(IOStream *stream)
// A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede.
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
return (buffer.find("fLaC") >= 0);
return (buffer.find("fLaC") != ByteVector::npos());
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
TagLib::File(file),
d(new FilePrivate())
{
if(isOpen())
read(readProperties);
}
FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle) :
FLAC::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle,
ID3v2::FrameFactory *frameFactory) :
TagLib::File(file),
d(new FilePrivate(frameFactory))
{
@@ -128,8 +129,8 @@ FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
read(readProperties);
}
FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle) :
FLAC::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle,
ID3v2::FrameFactory *frameFactory) :
TagLib::File(stream),
d(new FilePrivate(frameFactory))
{
@@ -147,24 +148,14 @@ TagLib::Tag *FLAC::File::tag() const
return &d->tag;
}
PropertyMap FLAC::File::properties() const
{
return d->tag.properties();
}
void FLAC::File::removeUnsupportedProperties(const StringList &unsupported)
{
d->tag.removeUnsupportedProperties(unsupported);
}
PropertyMap FLAC::File::setProperties(const PropertyMap &properties)
{
return xiphComment(true)->setProperties(properties);
}
FLAC::Properties *FLAC::File::audioProperties() const
FLAC::AudioProperties *FLAC::File::audioProperties() const
{
return d->properties;
return d->properties.get();
}
bool FLAC::File::save()
@@ -190,20 +181,20 @@ bool FLAC::File::save()
for(BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
if((*it)->code() == MetadataBlock::VorbisComment) {
// Set the new Vorbis Comment block
delete *it;
d->blocks.erase(it);
break;
}
}
d->blocks.append(new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData));
d->blocks.append(SHARED_PTR<MetadataBlock>(
new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData)));
// Render data for the metadata blocks
ByteVector data;
for(BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
ByteVector blockData = (*it)->render();
ByteVector blockHeader = ByteVector::fromUInt(blockData.size());
ByteVector blockHeader = ByteVector::fromUInt32BE(blockData.size());
blockHeader[0] = (*it)->code();
data.append(blockHeader);
data.append(blockData);
@@ -211,8 +202,8 @@ bool FLAC::File::save()
// Compute the amount of padding, and append that to data.
long originalLength = d->streamStart - d->flacStart;
long paddingLength = originalLength - data.size() - 4;
long long originalLength = d->streamStart - d->flacStart;
long long paddingLength = originalLength - data.size() - 4;
if(paddingLength <= 0) {
paddingLength = MinPaddingLength;
@@ -220,7 +211,7 @@ bool FLAC::File::save()
else {
// Padding won't increase beyond 1% of the file size or 1MB.
long threshold = length() / 100;
long long threshold = length() / 100;
threshold = std::max(threshold, MinPaddingLength);
threshold = std::min(threshold, MaxPaddingLegnth);
@@ -228,14 +219,14 @@ bool FLAC::File::save()
paddingLength = MinPaddingLength;
}
ByteVector paddingHeader = ByteVector::fromUInt(paddingLength);
ByteVector paddingHeader = ByteVector::fromUInt32BE(static_cast<unsigned int>(paddingLength));
paddingHeader[0] = static_cast<char>(MetadataBlock::Padding | LastBlockFlag);
data.append(paddingHeader);
data.resize(static_cast<unsigned int>(data.size() + paddingLength));
data.resize(static_cast<size_t>(data.size() + paddingLength));
// Write the data to the file
insert(data, d->flacStart, originalLength);
insert(data, d->flacStart, static_cast<size_t>(originalLength));
d->streamStart += (static_cast<long>(data.size()) - originalLength);
@@ -252,7 +243,7 @@ bool FLAC::File::save()
d->ID3v2Location = 0;
data = ID3v2Tag()->render();
insert(data, d->ID3v2Location, d->ID3v2OriginalSize);
insert(data, d->ID3v2Location, static_cast<size_t>(d->ID3v2OriginalSize));
d->flacStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
d->streamStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
@@ -267,7 +258,7 @@ bool FLAC::File::save()
// ID3v2 tag is empty. Remove the old one.
if(d->ID3v2Location >= 0) {
removeBlock(d->ID3v2Location, d->ID3v2OriginalSize);
removeBlock(d->ID3v2Location, static_cast<size_t>(d->ID3v2OriginalSize));
d->flacStart -= d->ID3v2OriginalSize;
d->streamStart -= d->ID3v2OriginalSize;
@@ -322,28 +313,11 @@ Ogg::XiphComment *FLAC::File::xiphComment(bool create)
return d->tag.access<Ogg::XiphComment>(FlacXiphIndex, create);
}
void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
{
d->ID3v2FrameFactory = factory;
}
ByteVector FLAC::File::streamInfoData()
{
debug("FLAC::File::streamInfoData() -- This function is obsolete. Returning an empty ByteVector.");
return ByteVector();
}
long FLAC::File::streamLength()
{
debug("FLAC::File::streamLength() -- This function is obsolete. Returning zero.");
return 0;
}
List<FLAC::Picture *> FLAC::File::pictureList()
{
List<Picture *> pictures;
for(BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
Picture *picture = dynamic_cast<Picture *>(*it);
Picture *picture = dynamic_cast<Picture *>(it->get());
if(picture) {
pictures.append(picture);
}
@@ -353,24 +327,20 @@ List<FLAC::Picture *> FLAC::File::pictureList()
void FLAC::File::addPicture(Picture *picture)
{
d->blocks.append(picture);
d->blocks.append(SHARED_PTR<Picture>(picture));
}
void FLAC::File::removePicture(Picture *picture, bool del)
void FLAC::File::removePicture(Picture *picture)
{
BlockIterator it = d->blocks.find(picture);
if(it != d->blocks.end())
d->blocks.erase(it);
if(del)
delete picture;
}
void FLAC::File::removePictures()
{
for(BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ) {
if(dynamic_cast<Picture *>(*it)) {
delete *it;
if(dynamic_cast<Picture *>(it->get())) {
it = d->blocks.erase(it);
}
else {
@@ -448,14 +418,14 @@ void FLAC::File::read(bool readProperties)
const ByteVector infoData = d->blocks.front()->render();
long streamLength;
long long streamLength;
if(d->ID3v1Location >= 0)
streamLength = d->ID3v1Location - d->streamStart;
else
streamLength = length() - d->streamStart;
d->properties = new Properties(infoData, streamLength);
d->properties.reset(new AudioProperties(infoData, streamLength));
}
}
@@ -469,7 +439,7 @@ void FLAC::File::scan()
if(!isValid())
return;
long nextBlockOffset;
long long nextBlockOffset;
if(d->ID3v2Location >= 0)
nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize);
@@ -504,7 +474,7 @@ void FLAC::File::scan()
const char blockType = header[0] & ~LastBlockFlag;
const bool isLastBlock = (header[0] & LastBlockFlag) != 0;
const unsigned int blockLength = header.toUInt(1U, 3U);
const size_t blockLength = header.toUInt24BE(1);
// First block should be the stream_info metadata
@@ -529,33 +499,32 @@ void FLAC::File::scan()
return;
}
MetadataBlock *block = 0;
SHARED_PTR<MetadataBlock> block;
// Found the vorbis-comment
if(blockType == MetadataBlock::VorbisComment) {
if(d->xiphCommentData.isEmpty()) {
d->xiphCommentData = data;
block = new UnknownMetadataBlock(MetadataBlock::VorbisComment, data);
block.reset(new UnknownMetadataBlock(MetadataBlock::VorbisComment, data));
}
else {
debug("FLAC::File::scan() -- multiple Vorbis Comment blocks found, discarding");
}
}
else if(blockType == MetadataBlock::Picture) {
FLAC::Picture *picture = new FLAC::Picture();
SHARED_PTR<FLAC::Picture> picture(new FLAC::Picture());
if(picture->parse(data)) {
block = picture;
}
else {
debug("FLAC::File::scan() -- invalid picture found, discarding");
delete picture;
}
}
else if(blockType == MetadataBlock::Padding) {
// Skip all padding blocks.
}
else {
block = new UnknownMetadataBlock(blockType, data);
block.reset(new UnknownMetadataBlock(blockType, data));
}
if(block)

View File

@@ -83,18 +83,6 @@ namespace TagLib {
AllTags = 0xffff
};
/*!
* Constructs a FLAC file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*
* \deprecated This constructor will be dropped in favor of the one below
* in a future version.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Constructs an FLAC file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
@@ -104,27 +92,27 @@ namespace TagLib {
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
// BIC: merge with the above constructor
File(FileName file, ID3v2::FrameFactory *frameFactory,
File(FileName file,
bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average,
ID3v2::FrameFactory *frameFactory = 0);
/*!
* Constructs a FLAC file from \a stream. If \a readProperties is true the
* Constructs a FLAC file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* If this file contains and ID3v2 tag the frames will be created using
* \a frameFactory.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*/
// BIC: merge with the above constructor
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
File(IOStream *stream,
bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average,
ID3v2::FrameFactory *frameFactory = 0);
/*!
* Destroys this instance of the File.
@@ -141,16 +129,6 @@ namespace TagLib {
*/
virtual TagLib::Tag *tag() const;
/*!
* Implements the unified property interface -- export function.
* If the file contains more than one tag (e.g. XiphComment and ID3v1),
* only the first one (in the order XiphComment, ID3v2, ID3v1) will be
* converted to the PropertyMap.
*/
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList &);
/*!
* Implements the unified property interface -- import function.
* This always creates a Xiph comment, if none exists. The return value
@@ -158,13 +136,13 @@ namespace TagLib {
* Ignores any changes to ID3v1 or ID3v2 comments since they are not allowed
* in the FLAC specification.
*/
PropertyMap setProperties(const PropertyMap &);
virtual PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the FLAC::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
virtual AudioProperties *audioProperties() const;
/*!
* Save the file. This will primarily save the XiphComment, but
@@ -232,42 +210,15 @@ namespace TagLib {
*/
Ogg::XiphComment *xiphComment(bool create = false);
/*!
* Set the ID3v2::FrameFactory to something other than the default. This
* can be used to specify the way that ID3v2 frames will be interpreted
* when
*
* \see ID3v2FrameFactory
* \deprecated This value should be passed in via the constructor
*/
void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
/*!
* Returns the block of data used by FLAC::Properties for parsing the
* stream properties.
*
* \deprecated Always returns an empty vector.
*/
ByteVector streamInfoData(); // BIC: remove
/*!
* Returns the length of the audio-stream, used by FLAC::Properties for
* calculating the bitrate.
*
* \deprecated Always returns zero.
*/
long streamLength(); // BIC: remove
/*!
* Returns a list of pictures attached to the FLAC file.
*/
List<Picture *> pictureList();
/*!
* Removes an attached picture. If \a del is true the picture's memory
* will be freed; if it is false, it must be deleted by the user.
* Removes an attached picture. The picture's memory will be freed.
*/
void removePicture(Picture *picture, bool del = true);
void removePicture(Picture *picture);
/*!
* Remove all attached images.

View File

@@ -78,10 +78,10 @@ bool FLAC::Picture::parse(const ByteVector &data)
return false;
}
unsigned int pos = 0;
d->type = FLAC::Picture::Type(data.toUInt(pos));
size_t pos = 0;
d->type = FLAC::Picture::Type(data.toUInt32BE(pos));
pos += 4;
unsigned int mimeTypeLength = data.toUInt(pos);
const unsigned int mimeTypeLength = data.toUInt32BE(pos);
pos += 4;
if(pos + mimeTypeLength + 24 > data.size()) {
debug("Invalid picture block.");
@@ -89,7 +89,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
}
d->mimeType = String(data.mid(pos, mimeTypeLength), String::UTF8);
pos += mimeTypeLength;
unsigned int descriptionLength = data.toUInt(pos);
const unsigned int descriptionLength = data.toUInt32BE(pos);
pos += 4;
if(pos + descriptionLength + 20 > data.size()) {
debug("Invalid picture block.");
@@ -97,15 +97,15 @@ bool FLAC::Picture::parse(const ByteVector &data)
}
d->description = String(data.mid(pos, descriptionLength), String::UTF8);
pos += descriptionLength;
d->width = data.toUInt(pos);
d->width = data.toUInt32BE(pos);
pos += 4;
d->height = data.toUInt(pos);
d->height = data.toUInt32BE(pos);
pos += 4;
d->colorDepth = data.toUInt(pos);
d->colorDepth = data.toUInt32BE(pos);
pos += 4;
d->numColors = data.toUInt(pos);
d->numColors = data.toUInt32BE(pos);
pos += 4;
unsigned int dataLength = data.toUInt(pos);
const unsigned int dataLength = data.toUInt32BE(pos);
pos += 4;
if(pos + dataLength > data.size()) {
debug("Invalid picture block.");
@@ -119,18 +119,18 @@ bool FLAC::Picture::parse(const ByteVector &data)
ByteVector FLAC::Picture::render() const
{
ByteVector result;
result.append(ByteVector::fromUInt(d->type));
result.append(ByteVector::fromUInt32BE(d->type));
ByteVector mimeTypeData = d->mimeType.data(String::UTF8);
result.append(ByteVector::fromUInt(mimeTypeData.size()));
result.append(ByteVector::fromUInt32BE(mimeTypeData.size()));
result.append(mimeTypeData);
ByteVector descriptionData = d->description.data(String::UTF8);
result.append(ByteVector::fromUInt(descriptionData.size()));
result.append(ByteVector::fromUInt32BE(descriptionData.size()));
result.append(descriptionData);
result.append(ByteVector::fromUInt(d->width));
result.append(ByteVector::fromUInt(d->height));
result.append(ByteVector::fromUInt(d->colorDepth));
result.append(ByteVector::fromUInt(d->numColors));
result.append(ByteVector::fromUInt(d->data.size()));
result.append(ByteVector::fromUInt32BE(d->width));
result.append(ByteVector::fromUInt32BE(d->height));
result.append(ByteVector::fromUInt32BE(d->colorDepth));
result.append(ByteVector::fromUInt32BE(d->numColors));
result.append(ByteVector::fromUInt32BE(d->data.size()));
result.append(d->data);
return result;
}

View File

@@ -89,7 +89,7 @@ namespace TagLib {
};
Picture();
Picture(const ByteVector &data);
explicit Picture(const ByteVector &data);
~Picture();
/*!
@@ -199,8 +199,6 @@ namespace TagLib {
PicturePrivate *d;
};
typedef List<Picture> PictureList;
}
}

View File

@@ -31,7 +31,7 @@
using namespace TagLib;
class FLAC::Properties::PropertiesPrivate
class FLAC::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() :
@@ -55,71 +55,64 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) :
AudioProperties(style),
FLAC::AudioProperties::AudioProperties(const ByteVector &data, long long streamLength, ReadStyle) :
TagLib::AudioProperties(),
d(new PropertiesPrivate())
{
read(data, streamLength);
}
FLAC::Properties::Properties(File *, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
debug("FLAC::Properties::Properties() - This constructor is no longer used.");
}
FLAC::Properties::~Properties()
FLAC::AudioProperties::~AudioProperties()
{
delete d;
}
int FLAC::Properties::length() const
int FLAC::AudioProperties::length() const
{
return lengthInSeconds();
}
int FLAC::Properties::lengthInSeconds() const
int FLAC::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int FLAC::Properties::lengthInMilliseconds() const
int FLAC::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int FLAC::Properties::bitrate() const
int FLAC::AudioProperties::bitrate() const
{
return d->bitrate;
}
int FLAC::Properties::sampleRate() const
int FLAC::AudioProperties::sampleRate() const
{
return d->sampleRate;
}
int FLAC::Properties::bitsPerSample() const
int FLAC::AudioProperties::bitsPerSample() const
{
return d->bitsPerSample;
}
int FLAC::Properties::sampleWidth() const
int FLAC::AudioProperties::sampleWidth() const
{
return bitsPerSample();
}
int FLAC::Properties::channels() const
int FLAC::AudioProperties::channels() const
{
return d->channels;
}
unsigned long long FLAC::Properties::sampleFrames() const
unsigned long long FLAC::AudioProperties::sampleFrames() const
{
return d->sampleFrames;
}
ByteVector FLAC::Properties::signature() const
ByteVector FLAC::AudioProperties::signature() const
{
return d->signature;
}
@@ -128,14 +121,14 @@ ByteVector FLAC::Properties::signature() const
// private members
////////////////////////////////////////////////////////////////////////////////
void FLAC::Properties::read(const ByteVector &data, long streamLength)
void FLAC::AudioProperties::read(const ByteVector &data, long long streamLength)
{
if(data.size() < 18) {
debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
debug("FLAC::AudioProperties::read() - FLAC properties must contain at least 18 bytes.");
return;
}
unsigned int pos = 0;
size_t pos = 0;
// Minimum block size (in samples)
pos += 2;
@@ -149,7 +142,7 @@ void FLAC::Properties::read(const ByteVector &data, long streamLength)
// Maximum frame size (in bytes)
pos += 3;
const unsigned int flags = data.toUInt(pos, true);
const unsigned int flags = data.toUInt32BE(pos);
pos += 4;
d->sampleRate = flags >> 12;
@@ -160,7 +153,7 @@ void FLAC::Properties::read(const ByteVector &data, long streamLength)
// stream length in samples. (Audio files measured in days)
const unsigned long long hi = flags & 0xf;
const unsigned long long lo = data.toUInt(pos, true);
const unsigned long long lo = data.toUInt32BE(pos);
pos += 4;
d->sampleFrames = (hi << 32) | lo;

View File

@@ -42,27 +42,19 @@ namespace TagLib {
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
/*!
* Create an instance of FLAC::Properties with the data read from the
* ByteVector \a data.
* Creates an instance of FLAC::AudioProperties with the data read from
* the ByteVector \a data.
*/
// BIC: switch to const reference
Properties(ByteVector data, long streamLength, ReadStyle style = Average);
AudioProperties(const ByteVector &data, long long streamLength, ReadStyle style = Average);
/*!
* Create an instance of FLAC::Properties with the data read from the
* FLAC::File \a file.
* Destroys this FLAC::AudioProperties instance.
*/
// BIC: remove
Properties(File *file, ReadStyle style = Average);
/*!
* Destroys this FLAC::Properties instance.
*/
virtual ~Properties();
virtual ~AudioProperties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
@@ -80,16 +72,14 @@ namespace TagLib {
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
virtual int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
virtual int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
@@ -134,10 +124,7 @@ namespace TagLib {
ByteVector signature() const;
private:
Properties(const Properties &);
Properties &operator=(const Properties &);
void read(const ByteVector &data, long streamLength);
void read(const ByteVector &data, long long streamLength);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@@ -36,13 +36,13 @@ using namespace IT;
class IT::File::FilePrivate
{
public:
FilePrivate(AudioProperties::ReadStyle propertiesStyle)
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
: tag(), properties(propertiesStyle)
{
}
Mod::Tag tag;
IT::Properties properties;
IT::AudioProperties properties;
};
IT::File::File(FileName file, bool readProperties,
@@ -73,17 +73,7 @@ Mod::Tag *IT::File::tag() const
return &d->tag;
}
PropertyMap IT::File::properties() const
{
return d->tag.properties();
}
PropertyMap IT::File::setProperties(const PropertyMap &properties)
{
return d->tag.setProperties(properties);
}
IT::Properties *IT::File::audioProperties() const
IT::AudioProperties *IT::File::audioProperties() const
{
return &d->properties;
}
@@ -114,7 +104,7 @@ bool IT::File::save()
StringList lines = d->tag.comment().split("\n");
for(unsigned short i = 0; i < instrumentCount; ++ i) {
seek(192L + length + ((long)i << 2));
unsigned long instrumentOffset = 0;
unsigned int instrumentOffset = 0;
if(!readU32L(instrumentOffset))
return false;
@@ -129,7 +119,7 @@ bool IT::File::save()
for(unsigned short i = 0; i < sampleCount; ++ i) {
seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
unsigned long sampleOffset = 0;
unsigned int sampleOffset = 0;
if(!readU32L(sampleOffset))
return false;
@@ -156,14 +146,14 @@ bool IT::File::save()
unsigned short special = 0;
unsigned short messageLength = 0;
unsigned long messageOffset = 0;
unsigned int messageOffset = 0;
seek(46);
if(!readU16L(special))
return false;
unsigned long fileSize = File::length();
if(special & Properties::MessageAttached) {
unsigned int fileSize = static_cast<unsigned int>(File::length());
if(special & AudioProperties::MessageAttached) {
seek(54);
if(!readU16L(messageLength) || !readU32L(messageOffset))
return false;
@@ -181,7 +171,7 @@ bool IT::File::save()
if(messageOffset + messageLength >= fileSize) {
// append new message
seek(54);
writeU16L(message.size());
writeU16L(static_cast<unsigned short>(message.size()));
writeU32L(messageOffset);
seek(messageOffset);
writeBlock(message);
@@ -233,14 +223,14 @@ void IT::File::read(bool)
// sample/instrument names are abused as comments so
// I just add all together.
String message;
if(special & Properties::MessageAttached) {
if(special & AudioProperties::MessageAttached) {
READ_U16L_AS(messageLength);
READ_U32L_AS(messageOffset);
seek(messageOffset);
ByteVector messageBytes = readBlock(messageLength);
READ_ASSERT(messageBytes.size() == messageLength);
int index = messageBytes.find((char) 0);
if(index > -1)
const size_t index = messageBytes.find((char) 0);
if(index != ByteVector::npos())
messageBytes.resize(index, 0);
messageBytes.replace('\r', '\n');
message = messageBytes;

View File

@@ -67,23 +67,11 @@ namespace TagLib {
Mod::Tag *tag() const;
/*!
* Forwards to Mod::Tag::properties().
* BIC: will be removed once File::toDict() is made virtual
*/
PropertyMap properties() const;
/*!
* Forwards to Mod::Tag::setProperties().
* BIC: will be removed once File::setProperties() is made virtual
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the IT::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
IT::Properties *audioProperties() const;
IT::AudioProperties *audioProperties() const;
/*!
* Save the file.

View File

@@ -1,4 +1,4 @@
/***************************************************************************
/***************************************************************************
copyright :(C) 2011 by Mathias Panzenböck
email : grosser.meister.morti@gmx.net
***************************************************************************/
@@ -29,7 +29,7 @@
using namespace TagLib;
using namespace IT;
class IT::Properties::PropertiesPrivate
class IT::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() :
@@ -47,9 +47,7 @@ public:
tempo(0),
bpmSpeed(0),
panningSeparation(0),
pitchWheelDepth(0)
{
}
pitchWheelDepth(0) {}
int channels;
unsigned short lengthInPatterns;
@@ -68,193 +66,201 @@ public:
unsigned char pitchWheelDepth;
};
IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
AudioProperties(propertiesStyle),
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
IT::AudioProperties::AudioProperties(AudioProperties::ReadStyle) :
TagLib::AudioProperties(),
d(new PropertiesPrivate())
{
}
IT::Properties::~Properties()
IT::AudioProperties::~AudioProperties()
{
delete d;
}
int IT::Properties::length() const
int IT::AudioProperties::length() const
{
return 0;
}
int IT::Properties::lengthInSeconds() const
int IT::AudioProperties::lengthInSeconds() const
{
return 0;
}
int IT::Properties::lengthInMilliseconds() const
int IT::AudioProperties::lengthInMilliseconds() const
{
return 0;
}
int IT::Properties::bitrate() const
int IT::AudioProperties::bitrate() const
{
return 0;
}
int IT::Properties::sampleRate() const
int IT::AudioProperties::sampleRate() const
{
return 0;
}
int IT::Properties::channels() const
int IT::AudioProperties::channels() const
{
return d->channels;
}
unsigned short IT::Properties::lengthInPatterns() const
unsigned short IT::AudioProperties::lengthInPatterns() const
{
return d->lengthInPatterns;
}
bool IT::Properties::stereo() const
bool IT::AudioProperties::stereo() const
{
return d->flags & Stereo;
}
unsigned short IT::Properties::instrumentCount() const
unsigned short IT::AudioProperties::instrumentCount() const
{
return d->instrumentCount;
}
unsigned short IT::Properties::sampleCount() const
unsigned short IT::AudioProperties::sampleCount() const
{
return d->sampleCount;
}
unsigned short IT::Properties::patternCount() const
unsigned short IT::AudioProperties::patternCount() const
{
return d->patternCount;
}
unsigned short IT::Properties::version() const
unsigned short IT::AudioProperties::version() const
{
return d->version;
}
unsigned short IT::Properties::compatibleVersion() const
unsigned short IT::AudioProperties::compatibleVersion() const
{
return d->compatibleVersion;
}
unsigned short IT::Properties::flags() const
unsigned short IT::AudioProperties::flags() const
{
return d->flags;
}
unsigned short IT::Properties::special() const
unsigned short IT::AudioProperties::special() const
{
return d->special;
}
unsigned char IT::Properties::globalVolume() const
unsigned char IT::AudioProperties::globalVolume() const
{
return d->globalVolume;
}
unsigned char IT::Properties::mixVolume() const
unsigned char IT::AudioProperties::mixVolume() const
{
return d->mixVolume;
}
unsigned char IT::Properties::tempo() const
unsigned char IT::AudioProperties::tempo() const
{
return d->tempo;
}
unsigned char IT::Properties::bpmSpeed() const
unsigned char IT::AudioProperties::bpmSpeed() const
{
return d->bpmSpeed;
}
unsigned char IT::Properties::panningSeparation() const
unsigned char IT::AudioProperties::panningSeparation() const
{
return d->panningSeparation;
}
unsigned char IT::Properties::pitchWheelDepth() const
unsigned char IT::AudioProperties::pitchWheelDepth() const
{
return d->pitchWheelDepth;
}
void IT::Properties::setChannels(int channels)
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void IT::AudioProperties::setChannels(int channels)
{
d->channels = channels;
}
void IT::Properties::setLengthInPatterns(unsigned short lengthInPatterns)
void IT::AudioProperties::setLengthInPatterns(unsigned short lengthInPatterns)
{
d->lengthInPatterns = lengthInPatterns;
}
void IT::Properties::setInstrumentCount(unsigned short instrumentCount)
void IT::AudioProperties::setInstrumentCount(unsigned short instrumentCount)
{
d->instrumentCount = instrumentCount;
}
void IT::Properties::setSampleCount(unsigned short sampleCount)
void IT::AudioProperties::setSampleCount(unsigned short sampleCount)
{
d->sampleCount = sampleCount;
}
void IT::Properties::setPatternCount(unsigned short patternCount)
void IT::AudioProperties::setPatternCount(unsigned short patternCount)
{
d->patternCount = patternCount;
}
void IT::Properties::setFlags(unsigned short flags)
void IT::AudioProperties::setFlags(unsigned short flags)
{
d->flags = flags;
}
void IT::Properties::setSpecial(unsigned short special)
void IT::AudioProperties::setSpecial(unsigned short special)
{
d->special = special;
}
void IT::Properties::setCompatibleVersion(unsigned short compatibleVersion)
void IT::AudioProperties::setCompatibleVersion(unsigned short compatibleVersion)
{
d->compatibleVersion = compatibleVersion;
}
void IT::Properties::setVersion(unsigned short version)
void IT::AudioProperties::setVersion(unsigned short version)
{
d->version = version;
}
void IT::Properties::setGlobalVolume(unsigned char globalVolume)
void IT::AudioProperties::setGlobalVolume(unsigned char globalVolume)
{
d->globalVolume = globalVolume;
}
void IT::Properties::setMixVolume(unsigned char mixVolume)
void IT::AudioProperties::setMixVolume(unsigned char mixVolume)
{
d->mixVolume = mixVolume;
}
void IT::Properties::setTempo(unsigned char tempo)
void IT::AudioProperties::setTempo(unsigned char tempo)
{
d->tempo = tempo;
}
void IT::Properties::setBpmSpeed(unsigned char bpmSpeed)
void IT::AudioProperties::setBpmSpeed(unsigned char bpmSpeed)
{
d->bpmSpeed = bpmSpeed;
}
void IT::Properties::setPanningSeparation(unsigned char panningSeparation)
void IT::AudioProperties::setPanningSeparation(unsigned char panningSeparation)
{
d->panningSeparation = panningSeparation;
}
void IT::Properties::setPitchWheelDepth(unsigned char pitchWheelDepth)
void IT::AudioProperties::setPitchWheelDepth(unsigned char pitchWheelDepth)
{
d->pitchWheelDepth = pitchWheelDepth;
}

View File

@@ -30,9 +30,15 @@
#include "audioproperties.h"
namespace TagLib {
namespace IT {
class TAGLIB_EXPORT Properties : public AudioProperties {
class File;
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
friend class File;
public:
/*! Flag bits. */
enum {
@@ -52,8 +58,8 @@ namespace TagLib {
MidiConfEmbedded = 8
};
Properties(AudioProperties::ReadStyle propertiesStyle);
virtual ~Properties();
explicit AudioProperties(AudioProperties::ReadStyle propertiesStyle);
virtual ~AudioProperties();
int length() const;
int lengthInSeconds() const;
@@ -78,6 +84,7 @@ namespace TagLib {
unsigned char panningSeparation() const;
unsigned char pitchWheelDepth() const;
private:
void setChannels(int channels);
void setLengthInPatterns(unsigned short lengthInPatterns);
void setInstrumentCount(unsigned short instrumentCount);
@@ -94,10 +101,6 @@ namespace TagLib {
void setPanningSeparation(unsigned char panningSeparation);
void setPitchWheelDepth (unsigned char pitchWheelDepth);
private:
Properties(const Properties&);
Properties &operator=(const Properties&);
class PropertiesPrivate;
PropertiesPrivate *d;
};

View File

@@ -36,13 +36,13 @@ using namespace Mod;
class Mod::File::FilePrivate
{
public:
FilePrivate(AudioProperties::ReadStyle propertiesStyle)
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
: properties(propertiesStyle)
{
}
Mod::Tag tag;
Mod::Properties properties;
Mod::AudioProperties properties;
};
Mod::File::File(FileName file, bool readProperties,
@@ -73,21 +73,11 @@ Mod::Tag *Mod::File::tag() const
return &d->tag;
}
Mod::Properties *Mod::File::audioProperties() const
Mod::AudioProperties *Mod::File::audioProperties() const
{
return &d->properties;
}
PropertyMap Mod::File::properties() const
{
return d->tag.properties();
}
PropertyMap Mod::File::setProperties(const PropertyMap &properties)
{
return d->tag.setProperties(properties);
}
bool Mod::File::save()
{
if(readOnly()) {
@@ -97,13 +87,13 @@ bool Mod::File::save()
seek(0);
writeString(d->tag.title(), 20);
StringList lines = d->tag.comment().split("\n");
unsigned int n = std::min(lines.size(), d->properties.instrumentCount());
for(unsigned int i = 0; i < n; ++ i) {
size_t n = std::min<size_t>(lines.size(), d->properties.instrumentCount());
for(size_t i = 0; i < n; ++ i) {
writeString(lines[i], 22);
seek(8, Current);
}
for(unsigned int i = n; i < d->properties.instrumentCount(); ++ i) {
for(size_t i = n; i < d->properties.instrumentCount(); ++ i) {
writeString(String(), 22);
seek(8, Current);
}

View File

@@ -72,22 +72,11 @@ namespace TagLib {
Mod::Tag *tag() const;
/*!
* Implements the unified property interface -- export function.
* Forwards to Mod::Tag::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified property interface -- import function.
* Forwards to Mod::Tag::setProperties().
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the Mod::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
Mod::Properties *audioProperties() const;
Mod::AudioProperties *audioProperties() const;
/*!
* Save the file.

View File

@@ -38,20 +38,19 @@ Mod::FileBase::FileBase(IOStream *stream) : TagLib::File(stream)
{
}
void Mod::FileBase::writeString(const String &s, unsigned long size, char padding)
void Mod::FileBase::writeString(const String &s, unsigned int size, char padding)
{
ByteVector data(s.data(String::Latin1));
data.resize(size, padding);
writeBlock(data);
}
bool Mod::FileBase::readString(String &s, unsigned long size)
bool Mod::FileBase::readString(String &s, unsigned int size)
{
ByteVector data(readBlock(size));
if(data.size() < size) return false;
int index = data.find((char) 0);
if(index > -1)
{
const size_t index = data.find((char) 0);
if(index != ByteVector::npos()) {
data.resize(index);
}
data.replace('\xff', ' ');
@@ -68,22 +67,22 @@ void Mod::FileBase::writeByte(unsigned char byte)
void Mod::FileBase::writeU16L(unsigned short number)
{
writeBlock(ByteVector::fromShort(number, false));
writeBlock(ByteVector::fromUInt16LE(number));
}
void Mod::FileBase::writeU32L(unsigned long number)
void Mod::FileBase::writeU32L(unsigned int number)
{
writeBlock(ByteVector::fromUInt(number, false));
writeBlock(ByteVector::fromUInt32LE(number));
}
void Mod::FileBase::writeU16B(unsigned short number)
{
writeBlock(ByteVector::fromShort(number, true));
writeBlock(ByteVector::fromUInt16BE(number));
}
void Mod::FileBase::writeU32B(unsigned long number)
void Mod::FileBase::writeU32B(unsigned int number)
{
writeBlock(ByteVector::fromUInt(number, true));
writeBlock(ByteVector::fromUInt32BE(number));
}
bool Mod::FileBase::readByte(unsigned char &byte)
@@ -98,14 +97,14 @@ bool Mod::FileBase::readU16L(unsigned short &number)
{
ByteVector data(readBlock(2));
if(data.size() < 2) return false;
number = data.toUShort(false);
number = data.toUInt16LE(0);
return true;
}
bool Mod::FileBase::readU32L(unsigned long &number) {
bool Mod::FileBase::readU32L(unsigned int &number) {
ByteVector data(readBlock(4));
if(data.size() < 4) return false;
number = data.toUInt(false);
number = data.toUInt32LE(0);
return true;
}
@@ -113,13 +112,13 @@ bool Mod::FileBase::readU16B(unsigned short &number)
{
ByteVector data(readBlock(2));
if(data.size() < 2) return false;
number = data.toUShort(true);
number = data.toUInt16BE(0);
return true;
}
bool Mod::FileBase::readU32B(unsigned long &number) {
bool Mod::FileBase::readU32B(unsigned int &number) {
ByteVector data(readBlock(4));
if(data.size() < 4) return false;
number = data.toUInt(true);
number = data.toUInt32BE(0);
return true;
}

View File

@@ -41,22 +41,22 @@ namespace TagLib {
class TAGLIB_EXPORT FileBase : public TagLib::File
{
protected:
FileBase(FileName file);
FileBase(IOStream *stream);
explicit FileBase(FileName file);
explicit FileBase(IOStream *stream);
void writeString(const String &s, unsigned long size, char padding = 0);
void writeString(const String &s, unsigned int size, char padding = 0);
void writeByte(unsigned char byte);
void writeU16L(unsigned short number);
void writeU32L(unsigned long number);
void writeU32L(unsigned int number);
void writeU16B(unsigned short number);
void writeU32B(unsigned long number);
void writeU32B(unsigned int number);
bool readString(String &s, unsigned long size);
bool readString(String &s, unsigned int size);
bool readByte(unsigned char &byte);
bool readU16L(unsigned short &number);
bool readU32L(unsigned long &number);
bool readU32L(unsigned int &number);
bool readU16B(unsigned short &number);
bool readU32B(unsigned long &number);
bool readU32B(unsigned int &number);
};
}

View File

@@ -39,9 +39,9 @@
#define READ_BYTE(setter) READ(setter,unsigned char,readByte)
#define READ_U16L(setter) READ(setter,unsigned short,readU16L)
#define READ_U32L(setter) READ(setter,unsigned long,readU32L)
#define READ_U32L(setter) READ(setter,unsigned int,readU32L)
#define READ_U16B(setter) READ(setter,unsigned short,readU16B)
#define READ_U32B(setter) READ(setter,unsigned long,readU32B)
#define READ_U32B(setter) READ(setter,unsigned int,readU32B)
#define READ_STRING(setter,size) \
{ \
@@ -56,9 +56,9 @@
#define READ_BYTE_AS(name) READ_AS(unsigned char,name,readByte)
#define READ_U16L_AS(name) READ_AS(unsigned short,name,readU16L)
#define READ_U32L_AS(name) READ_AS(unsigned long,name,readU32L)
#define READ_U32L_AS(name) READ_AS(unsigned int,name,readU32L)
#define READ_U16B_AS(name) READ_AS(unsigned short,name,readU16B)
#define READ_U32B_AS(name) READ_AS(unsigned long,name,readU32B)
#define READ_U32B_AS(name) READ_AS(unsigned int,name,readU32B)
#define READ_STRING_AS(name,size) \
String name; \

View File

@@ -1,4 +1,4 @@
/***************************************************************************
/***************************************************************************
copyright : (C) 2011 by Mathias Panzenböck
email : grosser.meister.morti@gmx.net
***************************************************************************/
@@ -29,83 +29,89 @@
using namespace TagLib;
using namespace Mod;
class Mod::Properties::PropertiesPrivate
class Mod::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() :
channels(0),
instrumentCount(0),
lengthInPatterns(0)
{
}
lengthInPatterns(0) {}
int channels;
unsigned int instrumentCount;
unsigned char lengthInPatterns;
};
Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
AudioProperties(propertiesStyle),
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
Mod::AudioProperties::AudioProperties(AudioProperties::ReadStyle) :
TagLib::AudioProperties(),
d(new PropertiesPrivate())
{
}
Mod::Properties::~Properties()
Mod::AudioProperties::~AudioProperties()
{
delete d;
}
int Mod::Properties::length() const
int Mod::AudioProperties::length() const
{
return 0;
}
int Mod::Properties::lengthInSeconds() const
int Mod::AudioProperties::lengthInSeconds() const
{
return 0;
}
int Mod::Properties::lengthInMilliseconds() const
int Mod::AudioProperties::lengthInMilliseconds() const
{
return 0;
}
int Mod::Properties::bitrate() const
int Mod::AudioProperties::bitrate() const
{
return 0;
}
int Mod::Properties::sampleRate() const
int Mod::AudioProperties::sampleRate() const
{
return 0;
}
int Mod::Properties::channels() const
int Mod::AudioProperties::channels() const
{
return d->channels;
}
unsigned int Mod::Properties::instrumentCount() const
unsigned int Mod::AudioProperties::instrumentCount() const
{
return d->instrumentCount;
}
unsigned char Mod::Properties::lengthInPatterns() const
unsigned char Mod::AudioProperties::lengthInPatterns() const
{
return d->lengthInPatterns;
}
void Mod::Properties::setChannels(int channels)
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void Mod::AudioProperties::setChannels(int channels)
{
d->channels = channels;
}
void Mod::Properties::setInstrumentCount(unsigned int instrumentCount)
void Mod::AudioProperties::setInstrumentCount(unsigned int instrumentCount)
{
d->instrumentCount = instrumentCount;
}
void Mod::Properties::setLengthInPatterns(unsigned char lengthInPatterns)
void Mod::AudioProperties::setLengthInPatterns(unsigned char lengthInPatterns)
{
d->lengthInPatterns = lengthInPatterns;
}

View File

@@ -33,11 +33,15 @@ namespace TagLib {
namespace Mod {
class TAGLIB_EXPORT Properties : public AudioProperties
class File;
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
friend class File;
public:
Properties(AudioProperties::ReadStyle propertiesStyle);
virtual ~Properties();
explicit AudioProperties(AudioProperties::ReadStyle propertiesStyle);
virtual ~AudioProperties();
int length() const;
int lengthInSeconds() const;
@@ -49,17 +53,12 @@ namespace TagLib {
unsigned int instrumentCount() const;
unsigned char lengthInPatterns() const;
private:
void setChannels(int channels);
void setInstrumentCount(unsigned int sampleCount);
void setLengthInPatterns(unsigned char lengthInPatterns);
private:
friend class File;
Properties(const Properties&);
Properties &operator=(const Properties&);
class PropertiesPrivate;
PropertiesPrivate *d;
};

View File

@@ -27,6 +27,7 @@
#include "modtag.h"
#include "tstringlist.h"
#include "tpropertymap.h"
#include "tpicturemap.h"
using namespace TagLib;
using namespace Mod;
@@ -89,6 +90,11 @@ unsigned int Mod::Tag::track() const
return 0;
}
TagLib::PictureMap Mod::Tag::pictures() const
{
return PictureMap();
}
String Mod::Tag::trackerName() const
{
return d->trackerName;
@@ -124,6 +130,10 @@ void Mod::Tag::setTrack(unsigned int)
{
}
void Mod::Tag::setPictures(const PictureMap &l)
{
}
void Mod::Tag::setTrackerName(const String &trackerName)
{
d->trackerName = trackerName;

View File

@@ -88,6 +88,8 @@ namespace TagLib {
*/
virtual unsigned int track() const;
PictureMap pictures() const;
/*!
* Returns the name of the tracker used to create/edit the module file.
* Only XM files store this tag to the file as such, for other formats
@@ -151,6 +153,8 @@ namespace TagLib {
*/
virtual void setTrack(unsigned int track);
void setPictures(const PictureMap &l);
/*!
* Sets the tracker name to \a trackerName. If \a trackerName is
* String::null then this value will be cleared.

View File

@@ -23,18 +23,17 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <climits>
#include <tdebug.h>
#include <tstring.h>
#include "mp4atom.h"
using namespace TagLib;
const char *MP4::Atom::containers[11] = {
"moov", "udta", "mdia", "meta", "ilst",
"stbl", "minf", "moof", "traf", "trak",
"stsd"
"moov", "udta", "mdia", "meta", "ilst",
"stbl", "minf", "moof", "traf", "trak",
"stsd"
};
MP4::Atom::Atom(File *file)
@@ -52,7 +51,7 @@ MP4::Atom::Atom(File *file)
return;
}
length = header.toUInt();
length = header.toUInt32BE(0);
if(length == 0) {
// The last atom which extends to the end of the file.
@@ -60,17 +59,7 @@ MP4::Atom::Atom(File *file)
}
else if(length == 1) {
// The atom has a 64-bit length.
const long long longLength = file->readBlock(8).toLongLong();
if(longLength <= LONG_MAX) {
// The actual length fits in long. That's always the case if long is 64-bit.
length = static_cast<long>(longLength);
}
else {
debug("MP4: 64-bit atoms are not supported");
length = 0;
file->seek(0, File::End);
return;
}
length = file->readBlock(8).toInt64BE(0);
}
if(length < 8) {
@@ -156,7 +145,7 @@ MP4::Atoms::Atoms(File *file)
atoms.setAutoDelete(true);
file->seek(0, File::End);
long end = file->tell();
long long end = file->tell();
file->seek(0);
while(file->tell() + 8 <= end) {
MP4::Atom *atom = new MP4::Atom(file);

View File

@@ -77,13 +77,13 @@ namespace TagLib {
class Atom
{
public:
Atom(File *file);
explicit Atom(File *file);
~Atom();
Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0);
AtomList findall(const char *name, bool recursive = false);
long offset;
long length;
long long offset;
long long length;
TagLib::ByteVector name;
AtomList children;
private:
@@ -95,7 +95,7 @@ namespace TagLib {
class Atoms
{
public:
Atoms(File *file);
explicit Atoms(File *file);
~Atoms();
Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
AtomList path(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);

View File

@@ -23,22 +23,33 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <taglib.h>
#include <tdebug.h>
#include "trefcounter.h"
#include "taglib.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "mp4coverart.h"
using namespace TagLib;
class MP4::CoverArt::CoverArtPrivate : public RefCounter
namespace
{
struct CoverArtData
{
MP4::CoverArt::Format format;
ByteVector data;
};
}
class MP4::CoverArt::CoverArtPrivate
{
public:
CoverArtPrivate() :
RefCounter(),
format(MP4::CoverArt::JPEG) {}
CoverArtPrivate(Format f, const ByteVector &v) :
data(new CoverArtData())
{
data->format = f;
data->data = v;
}
Format format;
ByteVector data;
SHARED_PTR<CoverArtData> data;
};
////////////////////////////////////////////////////////////////////////////////
@@ -46,16 +57,13 @@ public:
////////////////////////////////////////////////////////////////////////////////
MP4::CoverArt::CoverArt(Format format, const ByteVector &data) :
d(new CoverArtPrivate())
d(new CoverArtPrivate(format, data))
{
d->format = format;
d->data = data;
}
MP4::CoverArt::CoverArt(const CoverArt &item) :
d(item.d)
d(new CoverArtPrivate(*item.d))
{
d->ref();
}
MP4::CoverArt &
@@ -75,19 +83,17 @@ MP4::CoverArt::swap(CoverArt &item)
MP4::CoverArt::~CoverArt()
{
if(d->deref()) {
delete d;
}
delete d;
}
MP4::CoverArt::Format
MP4::CoverArt::format() const
{
return d->format;
return d->data->format;
}
ByteVector
MP4::CoverArt::data() const
{
return d->data;
return d->data->data;
}

View File

@@ -76,9 +76,7 @@ namespace TagLib {
};
typedef List<CoverArt> CoverArtList;
}
}
#endif

View File

@@ -66,9 +66,9 @@ public:
delete properties;
}
MP4::Tag *tag;
MP4::Atoms *atoms;
MP4::Properties *properties;
MP4::Tag *tag;
MP4::Atoms *atoms;
MP4::AudioProperties *properties;
};
////////////////////////////////////////////////////////////////////////////////
@@ -114,22 +114,7 @@ MP4::File::tag() const
return d->tag;
}
PropertyMap MP4::File::properties() const
{
return d->tag->properties();
}
void MP4::File::removeUnsupportedProperties(const StringList &properties)
{
d->tag->removeUnsupportedProperties(properties);
}
PropertyMap MP4::File::setProperties(const PropertyMap &properties)
{
return d->tag->setProperties(properties);
}
MP4::Properties *
MP4::AudioProperties *
MP4::File::audioProperties() const
{
return d->properties;
@@ -155,7 +140,7 @@ MP4::File::read(bool readProperties)
d->tag = new Tag(this, d->atoms);
if(readProperties) {
d->properties = new Properties(this, d->atoms);
d->properties = new AudioProperties(this, d->atoms);
}
}

View File

@@ -55,19 +55,19 @@ namespace TagLib {
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average);
/*!
* Constructs an MP4 file from \a stream. If \a readProperties is true the
* Constructs an MP4 file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average);
/*!
* Destroys this instance of the File.
@@ -86,26 +86,10 @@ namespace TagLib {
*/
Tag *tag() const;
/*!
* Implements the unified property interface -- export function.
*/
PropertyMap properties() const;
/*!
* Removes unsupported properties. Forwards to the actual Tag's
* removeUnsupportedProperties() function.
*/
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the unified property interface -- import function.
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the MP4 audio properties for this file.
*/
Properties *audioProperties() const;
AudioProperties *audioProperties() const;
/*!
* Save the file.

View File

@@ -23,46 +23,58 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <taglib.h>
#include <tdebug.h>
#include "trefcounter.h"
#include "taglib.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "mp4item.h"
#include "tutils.h"
using namespace TagLib;
class MP4::Item::ItemPrivate : public RefCounter
namespace
{
struct ItemData
{
bool valid;
MP4::AtomDataType atomDataType;
MP4::Item::ItemType type;
union {
bool m_bool;
int m_int;
MP4::Item::IntPair m_intPair;
unsigned char m_byte;
unsigned int m_uint;
long long m_longlong;
};
StringList m_stringList;
ByteVectorList m_byteVectorList;
MP4::CoverArtList m_coverArtList;
};
}
class MP4::Item::ItemPrivate
{
public:
ItemPrivate() :
RefCounter(),
valid(true),
atomDataType(TypeUndefined) {}
data(new ItemData())
{
data->valid = true;
data->atomDataType = MP4::TypeUndefined;
data->type = MP4::Item::TypeUndefined;
}
bool valid;
AtomDataType atomDataType;
union {
bool m_bool;
int m_int;
IntPair m_intPair;
unsigned char m_byte;
unsigned int m_uint;
long long m_longlong;
};
StringList m_stringList;
ByteVectorList m_byteVectorList;
MP4::CoverArtList m_coverArtList;
SHARED_PTR<ItemData> data;
};
MP4::Item::Item() :
d(new ItemPrivate())
{
d->valid = false;
d->data->valid = false;
}
MP4::Item::Item(const Item &item) :
d(item.d)
d(new ItemPrivate(*item.d))
{
d->ref();
}
MP4::Item &
@@ -82,131 +94,176 @@ MP4::Item::swap(Item &item)
MP4::Item::~Item()
{
if(d->deref())
delete d;
delete d;
}
MP4::Item::Item(bool value) :
d(new ItemPrivate())
{
d->m_bool = value;
d->data->m_bool = value;
d->data->type = TypeBool;
}
MP4::Item::Item(int value) :
d(new ItemPrivate())
{
d->m_int = value;
d->data->m_int = value;
d->data->type = TypeInt;
}
MP4::Item::Item(unsigned char value) :
d(new ItemPrivate())
{
d->m_byte = value;
d->data->m_byte = value;
d->data->type = TypeByte;
}
MP4::Item::Item(unsigned int value) :
d(new ItemPrivate())
{
d->m_uint = value;
d->data->m_uint = value;
d->data->type = TypeUInt;
}
MP4::Item::Item(long long value) :
d(new ItemPrivate())
{
d->m_longlong = value;
d->data->m_longlong = value;
d->data->type = TypeLongLong;
}
MP4::Item::Item(int value1, int value2) :
d(new ItemPrivate())
{
d->m_intPair.first = value1;
d->m_intPair.second = value2;
d->data->m_intPair.first = value1;
d->data->m_intPair.second = value2;
d->data->type = TypeIntPair;
}
MP4::Item::Item(const ByteVectorList &value) :
d(new ItemPrivate())
{
d->m_byteVectorList = value;
d->data->m_byteVectorList = value;
d->data->type = TypeByteVectorList;
}
MP4::Item::Item(const StringList &value) :
d(new ItemPrivate())
{
d->m_stringList = value;
d->data->m_stringList = value;
d->data->type = TypeStringList;
}
MP4::Item::Item(const MP4::CoverArtList &value) :
d(new ItemPrivate())
{
d->m_coverArtList = value;
d->data->m_coverArtList = value;
d->data->type = TypeCoverArtList;
}
void MP4::Item::setAtomDataType(MP4::AtomDataType type)
{
d->atomDataType = type;
d->data->atomDataType = type;
}
MP4::AtomDataType MP4::Item::atomDataType() const
{
return d->atomDataType;
return d->data->atomDataType;
}
bool
MP4::Item::toBool() const
{
return d->m_bool;
return d->data->m_bool;
}
int
MP4::Item::toInt() const
{
return d->m_int;
return d->data->m_int;
}
unsigned char
MP4::Item::toByte() const
{
return d->m_byte;
return d->data->m_byte;
}
unsigned int
MP4::Item::toUInt() const
{
return d->m_uint;
return d->data->m_uint;
}
long long
MP4::Item::toLongLong() const
{
return d->m_longlong;
return d->data->m_longlong;
}
MP4::Item::IntPair
MP4::Item::toIntPair() const
{
return d->m_intPair;
return d->data->m_intPair;
}
StringList
MP4::Item::toStringList() const
{
return d->m_stringList;
return d->data->m_stringList;
}
ByteVectorList
MP4::Item::toByteVectorList() const
{
return d->m_byteVectorList;
return d->data->m_byteVectorList;
}
MP4::CoverArtList
MP4::Item::toCoverArtList() const
{
return d->m_coverArtList;
return d->data->m_coverArtList;
}
bool
MP4::Item::isValid() const
{
return d->valid;
return d->data->valid;
}
String
MP4::Item::toString() const
{
StringList desc;
switch (d->data->type) {
case TypeBool:
return d->data->m_bool ? "true" : "false";
case TypeInt:
return Utils::formatString("%d", d->data->m_int);
case TypeIntPair:
return Utils::formatString("%d/%d", d->data->m_intPair.first, d->data->m_intPair.second);
case TypeByte:
return Utils::formatString("%d", d->data->m_byte);
case TypeUInt:
return Utils::formatString("%u", d->data->m_uint);
case TypeLongLong:
return Utils::formatString("%lld", d->data->m_longlong);
case TypeStringList:
return d->data->m_stringList.toString(" / ");
case TypeByteVectorList:
for(size_t i = 0; i < d->data->m_byteVectorList.size(); i++) {
desc.append(Utils::formatString(
"[%d bytes of data]", static_cast<int>(d->data->m_byteVectorList[i].size())));
}
return desc.toString(", ");
case TypeCoverArtList:
for(size_t i = 0; i < d->data->m_coverArtList.size(); i++) {
desc.append(Utils::formatString(
"[%d bytes of data]", static_cast<int>(d->data->m_coverArtList[i].data().size())));
}
return desc.toString(", ");
case TypeUndefined:
return "[unknown]";
}
return String();
}

View File

@@ -41,6 +41,19 @@ namespace TagLib {
int first, second;
};
enum ItemType {
TypeUndefined = 0,
TypeBool,
TypeInt,
TypeIntPair,
TypeByte,
TypeUInt,
TypeLongLong,
TypeStringList,
TypeByteVectorList,
TypeCoverArtList,
};
Item();
Item(const Item &item);
@@ -79,8 +92,12 @@ namespace TagLib {
ByteVectorList toByteVectorList() const;
CoverArtList toCoverArtList() const;
ItemType type() const;
bool isValid() const;
String toString() const;
private:
class ItemPrivate;
ItemPrivate *d;

View File

@@ -31,7 +31,7 @@
using namespace TagLib;
class MP4::Properties::PropertiesPrivate
class MP4::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() :
@@ -41,7 +41,7 @@ public:
channels(0),
bitsPerSample(0),
encrypted(false),
codec(MP4::Properties::Unknown) {}
codec(MP4::AudioProperties::Unknown) {}
int length;
int bitrate;
@@ -56,78 +56,98 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) :
AudioProperties(style),
MP4::AudioProperties::AudioProperties(File *file, MP4::Atoms *atoms, ReadStyle) :
TagLib::AudioProperties(),
d(new PropertiesPrivate())
{
read(file, atoms);
}
MP4::Properties::~Properties()
MP4::AudioProperties::~AudioProperties()
{
delete d;
}
int
MP4::Properties::channels() const
MP4::AudioProperties::channels() const
{
return d->channels;
}
int
MP4::Properties::sampleRate() const
MP4::AudioProperties::sampleRate() const
{
return d->sampleRate;
}
int
MP4::Properties::length() const
MP4::AudioProperties::length() const
{
return lengthInSeconds();
}
int
MP4::Properties::lengthInSeconds() const
MP4::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int
MP4::Properties::lengthInMilliseconds() const
MP4::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int
MP4::Properties::bitrate() const
MP4::AudioProperties::bitrate() const
{
return d->bitrate;
}
int
MP4::Properties::bitsPerSample() const
MP4::AudioProperties::bitsPerSample() const
{
return d->bitsPerSample;
}
bool
MP4::Properties::isEncrypted() const
MP4::AudioProperties::isEncrypted() const
{
return d->encrypted;
}
MP4::Properties::Codec
MP4::Properties::codec() const
MP4::AudioProperties::Codec
MP4::AudioProperties::codec() const
{
return d->codec;
}
String
MP4::AudioProperties::toString() const
{
String format;
if(d->codec == AAC) {
format = "AAC";
}
else if(d->codec == ALAC) {
format = "ALAC";
}
else {
format = "Unknown";
}
StringList desc;
desc.append("MPEG-4 audio (" + format + ")");
desc.append(String::number(length()) + " seconds");
desc.append(String::number(bitrate()) + " kbps");
return desc.toString(", ");
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void
MP4::Properties::read(File *file, Atoms *atoms)
MP4::AudioProperties::read(File *file, Atoms *atoms)
{
MP4::Atom *moov = atoms->find("moov");
if(!moov) {
@@ -147,7 +167,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
return;
}
file->seek(hdlr->offset);
data = file->readBlock(hdlr->length);
data = file->readBlock(static_cast<size_t>(hdlr->length));
if(data.containsAt("soun", 16)) {
break;
}
@@ -165,7 +185,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
}
file->seek(mdhd->offset);
data = file->readBlock(mdhd->length);
data = file->readBlock(static_cast<size_t>(mdhd->length));
const unsigned int version = data[8];
long long unit;
@@ -175,16 +195,16 @@ MP4::Properties::read(File *file, Atoms *atoms)
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
return;
}
unit = data.toLongLong(28U);
length = data.toLongLong(36U);
unit = data.toUInt32BE(28);
length = data.toInt64BE(32);
}
else {
if(data.size() < 24 + 4) {
if(data.size() < 24 + 8) {
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
return;
}
unit = data.toUInt(20U);
length = data.toUInt(24U);
unit = data.toUInt32BE(20);
length = data.toUInt32BE(24);
}
if(unit > 0 && length > 0)
d->length = static_cast<int>(length * 1000.0 / unit + 0.5);
@@ -195,12 +215,12 @@ MP4::Properties::read(File *file, Atoms *atoms)
}
file->seek(atom->offset);
data = file->readBlock(atom->length);
data = file->readBlock(static_cast<size_t>(atom->length));
if(data.containsAt("mp4a", 20)) {
d->codec = AAC;
d->channels = data.toShort(40U);
d->bitsPerSample = data.toShort(42U);
d->sampleRate = data.toUInt(46U);
d->channels = data.toUInt16BE(40);
d->bitsPerSample = data.toUInt16BE(42);
d->sampleRate = data.toUInt32BE(46);
if(data.containsAt("esds", 56) && data[64] == 0x03) {
unsigned int pos = 65;
if(data.containsAt("\x80\x80\x80", pos)) {
@@ -213,7 +233,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
pos += 3;
}
pos += 10;
d->bitrate = static_cast<int>((data.toUInt(pos) + 500) / 1000.0 + 0.5);
d->bitrate = static_cast<int>((data.toUInt32BE(pos) + 500) / 1000.0 + 0.5);
}
}
}
@@ -222,8 +242,8 @@ MP4::Properties::read(File *file, Atoms *atoms)
d->codec = ALAC;
d->bitsPerSample = data.at(69);
d->channels = data.at(73);
d->bitrate = static_cast<int>(data.toUInt(80U) / 1000.0 + 0.5);
d->sampleRate = data.toUInt(84U);
d->bitrate = static_cast<int>(data.toUInt32BE(80) / 1000.0 + 0.5);
d->sampleRate = data.toUInt32BE(84);
}
}

View File

@@ -37,7 +37,7 @@ namespace TagLib {
class File;
//! An implementation of MP4 audio properties
class TAGLIB_EXPORT Properties : public AudioProperties
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
enum Codec {
@@ -46,8 +46,8 @@ namespace TagLib {
ALAC
};
Properties(File *file, Atoms *atoms, ReadStyle style = Average);
virtual ~Properties();
AudioProperties(File *file, Atoms *atoms, ReadStyle style = Average);
virtual ~AudioProperties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
@@ -65,16 +65,14 @@ namespace TagLib {
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
virtual int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
virtual int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
@@ -106,6 +104,8 @@ namespace TagLib {
*/
Codec codec() const;
String toString() const;
private:
void read(File *file, Atoms *atoms);

View File

@@ -22,9 +22,10 @@
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <cstring>
#include <tdebug.h>
#include <tstring.h>
#include <tpicturemap.h>
#include <tpropertymap.h>
#include "mp4atom.h"
#include "mp4tag.h"
@@ -112,18 +113,18 @@ MP4::AtomDataList
MP4::Tag::parseData2(const MP4::Atom *atom, int expectedFlags, bool freeForm)
{
AtomDataList result;
ByteVector data = d->file->readBlock(atom->length - 8);
ByteVector data = d->file->readBlock(static_cast<size_t>(atom->length - 8));
int i = 0;
unsigned int pos = 0;
size_t pos = 0;
while(pos < data.size()) {
const int length = static_cast<int>(data.toUInt(pos));
const int length = static_cast<int>(data.toUInt32BE(pos));
if(length < 12) {
debug("MP4: Too short atom");
return result;
}
const ByteVector name = data.mid(pos + 4, 4);
const int flags = static_cast<int>(data.toUInt(pos + 8));
const int flags = static_cast<int>(data.toUInt32BE(pos + 8));
if(freeForm && i < 2) {
if(i == 0 && name != "mean") {
debug("MP4: Unexpected atom \"" + name + "\", expecting \"mean\"");
@@ -166,7 +167,7 @@ MP4::Tag::parseInt(const MP4::Atom *atom)
{
ByteVectorList data = parseData(atom);
if(!data.isEmpty()) {
addItem(atom->name, (int)data[0].toShort());
addItem(atom->name, (int)data[0].toInt16BE(0));
}
}
@@ -175,7 +176,7 @@ MP4::Tag::parseUInt(const MP4::Atom *atom)
{
ByteVectorList data = parseData(atom);
if(!data.isEmpty()) {
addItem(atom->name, data[0].toUInt());
addItem(atom->name, data[0].toUInt32BE(0));
}
}
@@ -184,7 +185,7 @@ MP4::Tag::parseLongLong(const MP4::Atom *atom)
{
ByteVectorList data = parseData(atom);
if(!data.isEmpty()) {
addItem(atom->name, data[0].toLongLong());
addItem(atom->name, data[0].toInt64BE(0));
}
}
@@ -202,7 +203,7 @@ MP4::Tag::parseGnre(const MP4::Atom *atom)
{
ByteVectorList data = parseData(atom);
if(!data.isEmpty()) {
int idx = (int)data[0].toShort();
int idx = (int)data[0].toInt16BE(0);
if(idx > 0) {
addItem("\251gen", StringList(ID3v1::genre(idx - 1)));
}
@@ -214,8 +215,8 @@ MP4::Tag::parseIntPair(const MP4::Atom *atom)
{
ByteVectorList data = parseData(atom);
if(!data.isEmpty()) {
const int a = data[0].toShort(2U);
const int b = data[0].toShort(4U);
const int a = data[0].toInt16BE(2);
const int b = data[0].toInt16BE(4);
addItem(atom->name, MP4::Item(a, b));
}
}
@@ -288,17 +289,17 @@ void
MP4::Tag::parseCovr(const MP4::Atom *atom)
{
MP4::CoverArtList value;
ByteVector data = d->file->readBlock(atom->length - 8);
ByteVector data = d->file->readBlock(static_cast<size_t>(atom->length - 8));
unsigned int pos = 0;
while(pos < data.size()) {
const int length = static_cast<int>(data.toUInt(pos));
const int length = static_cast<int>(data.toUInt32BE(pos));
if(length < 12) {
debug("MP4: Too short atom");
break;;
}
const ByteVector name = data.mid(pos + 4, 4);
const int flags = static_cast<int>(data.toUInt(pos + 8));
const int flags = static_cast<int>(data.toUInt32BE(pos + 8));
if(name != "data") {
debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\"");
break;
@@ -321,7 +322,7 @@ ByteVector
MP4::Tag::padIlst(const ByteVector &data, int length) const
{
if(length == -1) {
length = ((data.size() + 1023) & ~1023) - data.size();
length = static_cast<int>(((data.size() + 1023) & ~1023) - data.size());
}
return renderAtom("free", ByteVector(length, '\1'));
}
@@ -329,7 +330,7 @@ MP4::Tag::padIlst(const ByteVector &data, int length) const
ByteVector
MP4::Tag::renderAtom(const ByteVector &name, const ByteVector &data) const
{
return ByteVector::fromUInt(data.size() + 8) + name + data;
return ByteVector::fromUInt32BE(data.size() + 8) + name + data;
}
ByteVector
@@ -337,7 +338,7 @@ MP4::Tag::renderData(const ByteVector &name, int flags, const ByteVectorList &da
{
ByteVector result;
for(ByteVectorList::ConstIterator it = data.begin(); it != data.end(); ++it) {
result.append(renderAtom("data", ByteVector::fromUInt(flags) + ByteVector(4, '\0') + *it));
result.append(renderAtom("data", ByteVector::fromUInt32BE(flags) + ByteVector(4, '\0') + *it));
}
return renderAtom(name, result);
}
@@ -354,7 +355,7 @@ ByteVector
MP4::Tag::renderInt(const ByteVector &name, const MP4::Item &item) const
{
ByteVectorList data;
data.append(ByteVector::fromShort(item.toInt()));
data.append(ByteVector::fromUInt16BE(item.toInt()));
return renderData(name, TypeInteger, data);
}
@@ -362,7 +363,7 @@ ByteVector
MP4::Tag::renderUInt(const ByteVector &name, const MP4::Item &item) const
{
ByteVectorList data;
data.append(ByteVector::fromUInt(item.toUInt()));
data.append(ByteVector::fromUInt32BE(item.toUInt()));
return renderData(name, TypeInteger, data);
}
@@ -370,7 +371,7 @@ ByteVector
MP4::Tag::renderLongLong(const ByteVector &name, const MP4::Item &item) const
{
ByteVectorList data;
data.append(ByteVector::fromLongLong(item.toLongLong()));
data.append(ByteVector::fromUInt64BE(item.toLongLong()));
return renderData(name, TypeInteger, data);
}
@@ -387,8 +388,8 @@ MP4::Tag::renderIntPair(const ByteVector &name, const MP4::Item &item) const
{
ByteVectorList data;
data.append(ByteVector(2, '\0') +
ByteVector::fromShort(item.toIntPair().first) +
ByteVector::fromShort(item.toIntPair().second) +
ByteVector::fromUInt16BE(item.toIntPair().first) +
ByteVector::fromUInt16BE(item.toIntPair().second) +
ByteVector(2, '\0'));
return renderData(name, TypeImplicit, data);
}
@@ -398,8 +399,8 @@ MP4::Tag::renderIntPairNoTrailing(const ByteVector &name, const MP4::Item &item)
{
ByteVectorList data;
data.append(ByteVector(2, '\0') +
ByteVector::fromShort(item.toIntPair().first) +
ByteVector::fromShort(item.toIntPair().second));
ByteVector::fromUInt16BE(item.toIntPair().first) +
ByteVector::fromUInt16BE(item.toIntPair().second));
return renderData(name, TypeImplicit, data);
}
@@ -420,7 +421,7 @@ MP4::Tag::renderCovr(const ByteVector &name, const MP4::Item &item) const
ByteVector data;
MP4::CoverArtList value = item.toCoverArtList();
for(MP4::CoverArtList::ConstIterator it = value.begin(); it != value.end(); ++it) {
data.append(renderAtom("data", ByteVector::fromUInt(it->format()) +
data.append(renderAtom("data", ByteVector::fromUInt32BE(it->format()) +
ByteVector(4, '\0') + it->data()));
}
return renderAtom(name, data);
@@ -435,8 +436,8 @@ MP4::Tag::renderFreeForm(const String &name, const MP4::Item &item) const
return ByteVector();
}
ByteVector data;
data.append(renderAtom("mean", ByteVector::fromUInt(0) + header[1].data(String::UTF8)));
data.append(renderAtom("name", ByteVector::fromUInt(0) + header[2].data(String::UTF8)));
data.append(renderAtom("mean", ByteVector::fromUInt32BE(0) + header[1].data(String::UTF8)));
data.append(renderAtom("name", ByteVector::fromUInt32BE(0) + header[2].data(String::UTF8)));
AtomDataType type = item.atomDataType();
if(type == TypeUndefined) {
if(!item.toStringList().isEmpty()) {
@@ -449,13 +450,13 @@ MP4::Tag::renderFreeForm(const String &name, const MP4::Item &item) const
if(type == TypeUTF8) {
StringList value = item.toStringList();
for(StringList::ConstIterator it = value.begin(); it != value.end(); ++it) {
data.append(renderAtom("data", ByteVector::fromUInt(type) + ByteVector(4, '\0') + it->data(String::UTF8)));
data.append(renderAtom("data", ByteVector::fromUInt32BE(type) + ByteVector(4, '\0') + it->data(String::UTF8)));
}
}
else {
ByteVectorList value = item.toByteVectorList();
for(ByteVectorList::ConstIterator it = value.begin(); it != value.end(); ++it) {
data.append(renderAtom("data", ByteVector::fromUInt(type) + ByteVector(4, '\0') + *it));
data.append(renderAtom("data", ByteVector::fromUInt32BE(type) + ByteVector(4, '\0') + *it));
}
}
return renderAtom("----", data);
@@ -531,25 +532,25 @@ MP4::Tag::updateParents(const AtomList &path, long delta, int ignore)
for(AtomList::ConstIterator it = path.begin(); it != itEnd; ++it) {
d->file->seek((*it)->offset);
long size = d->file->readBlock(4).toUInt();
long size = d->file->readBlock(4).toUInt32BE(0);
// 64-bit
if (size == 1) {
d->file->seek(4, File::Current); // Skip name
long long longSize = d->file->readBlock(8).toLongLong();
long long longSize = d->file->readBlock(8).toInt64BE(0);
// Seek the offset of the 64-bit size
d->file->seek((*it)->offset + 8);
d->file->writeBlock(ByteVector::fromLongLong(longSize + delta));
d->file->writeBlock(ByteVector::fromUInt64BE(longSize + delta));
}
// 32-bit
else {
d->file->seek((*it)->offset);
d->file->writeBlock(ByteVector::fromUInt(size + delta));
d->file->writeBlock(ByteVector::fromUInt32BE(size + delta));
}
}
}
void
MP4::Tag::updateOffsets(long delta, long offset)
MP4::Tag::updateOffsets(long delta, long long offset)
{
MP4::Atom *moov = d->atoms->find("moov");
if(moov) {
@@ -560,16 +561,16 @@ MP4::Tag::updateOffsets(long delta, long offset)
atom->offset += delta;
}
d->file->seek(atom->offset + 12);
ByteVector data = d->file->readBlock(atom->length - 12);
unsigned int count = data.toUInt();
ByteVector data = d->file->readBlock(static_cast<size_t>(atom->length - 12));
unsigned int count = data.toUInt32BE(0);
d->file->seek(atom->offset + 16);
unsigned int pos = 4;
size_t pos = 4;
while(count--) {
long o = static_cast<long>(data.toUInt(pos));
long o = data.toUInt32BE(pos);
if(o > offset) {
o += delta;
}
d->file->writeBlock(ByteVector::fromUInt(o));
d->file->writeBlock(ByteVector::fromUInt32BE(o));
pos += 4;
}
}
@@ -581,16 +582,16 @@ MP4::Tag::updateOffsets(long delta, long offset)
atom->offset += delta;
}
d->file->seek(atom->offset + 12);
ByteVector data = d->file->readBlock(atom->length - 12);
unsigned int count = data.toUInt();
ByteVector data = d->file->readBlock(static_cast<size_t>(atom->length - 12));
unsigned int count = data.toUInt32BE(0);
d->file->seek(atom->offset + 16);
unsigned int pos = 4;
size_t pos = 4;
while(count--) {
long long o = data.toLongLong(pos);
long long o = data.toInt64BE(pos);
if(o > offset) {
o += delta;
}
d->file->writeBlock(ByteVector::fromLongLong(o));
d->file->writeBlock(ByteVector::fromUInt64BE(o));
pos += 8;
}
}
@@ -605,15 +606,15 @@ MP4::Tag::updateOffsets(long delta, long offset)
atom->offset += delta;
}
d->file->seek(atom->offset + 9);
ByteVector data = d->file->readBlock(atom->length - 9);
const unsigned int flags = data.toUInt(0, 3, true);
ByteVector data = d->file->readBlock(static_cast<size_t>(atom->length - 9));
const unsigned int flags = data.toUInt24BE(0);
if(flags & 1) {
long long o = data.toLongLong(7U);
long long o = data.toInt64BE(7);
if(o > offset) {
o += delta;
}
d->file->seek(atom->offset + 16);
d->file->writeBlock(ByteVector::fromLongLong(o));
d->file->writeBlock(ByteVector::fromUInt64BE(o));
}
}
}
@@ -633,11 +634,11 @@ MP4::Tag::saveNew(ByteVector data)
data = renderAtom("udta", data);
}
long offset = path.back()->offset + 8;
long long offset = path.back()->offset + 8;
d->file->insert(data, offset, 0);
updateParents(path, data.size());
updateOffsets(data.size(), offset);
updateParents(path, static_cast<long>(data.size()));
updateOffsets(static_cast<long>(data.size()), offset);
// Insert the newly created atoms into the tree to keep it up-to-date.
@@ -651,8 +652,8 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
AtomList::ConstIterator it = path.end();
MP4::Atom *ilst = *(--it);
long offset = ilst->offset;
long length = ilst->length;
long long offset = ilst->offset;
long long length = ilst->length;
MP4::Atom *meta = *(--it);
AtomList::ConstIterator index = meta->children.find(ilst);
@@ -677,17 +678,17 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
}
}
long delta = data.size() - length;
long delta = static_cast<long>(data.size() - length);
if(delta > 0 || (delta < 0 && delta > -8)) {
data.append(padIlst(data));
delta = data.size() - length;
delta = static_cast<long>(data.size() - length);
}
else if(delta < 0) {
data.append(padIlst(data, -delta - 8));
data.append(padIlst(data, 0 - delta - 8));
delta = 0;
}
d->file->insert(data, offset, length);
d->file->insert(data, offset, static_cast<size_t>(length));
if(delta) {
updateParents(path, delta, 1);
@@ -751,6 +752,42 @@ MP4::Tag::track() const
return 0;
}
PictureMap
MP4::Tag::pictures() const
{
if(!d->items.contains("covr"))
return PictureMap();
CoverArtList list = d->items["covr"].toCoverArtList();
if(list.isEmpty())
return PictureMap();
PictureMap map;
for(CoverArtList::ConstIterator it = list.begin(); it != list.end(); ++it) {
CoverArt art = *it;
String mime = "image/";
switch(art.format()) {
case CoverArt::BMP:
mime.append("bmp");
break;
case CoverArt::JPEG:
mime.append("jpeg");
break;
case CoverArt::GIF:
mime.append("gif");
break;
case CoverArt::PNG:
mime.append("png");
break;
case CoverArt::Unknown:
break;
}
Picture picture(art.data(), Picture::Other, mime);
map.insert(picture);
}
return PictureMap(map);
}
void
MP4::Tag::setTitle(const String &value)
{
@@ -793,6 +830,39 @@ MP4::Tag::setTrack(unsigned int value)
d->items["trkn"] = MP4::Item(value, 0);
}
void
MP4::Tag::setPictures(const PictureMap &l)
{
CoverArtList list;
for(PictureMap::ConstIterator pictureMapIt = l.begin();
pictureMapIt != l.end();
++pictureMapIt) {
PictureList pictures = pictureMapIt->second;
for(PictureList::ConstIterator pictureListIt = pictures.begin();
pictureListIt != pictures.end();
++pictureListIt) {
Picture picture = *pictureListIt;
CoverArt::Format format;
String mime = picture.mime();
if(String("image/") == mime)
format = CoverArt::Unknown;
else if(String("image/bmp") == mime)
format = CoverArt::BMP;
else if(String("image/png") == mime)
format = CoverArt::PNG;
else if(String("image/gif") == mime)
format = CoverArt::GIF;
else if(String("image/jpeg") == mime)
format = CoverArt::JPEG;
else
format = CoverArt::Unknown;
CoverArt art(format, picture.data());
list.append(art);
}
}
d->items["covr"] = list;
}
bool MP4::Tag::isEmpty() const
{
return d->items.isEmpty();
@@ -828,6 +898,16 @@ bool MP4::Tag::contains(const String &key) const
return d->items.contains(key);
}
String
MP4::Tag::toString() const
{
StringList desc;
for(MP4::ItemListMap::Iterator i = d->items.begin(); i != d->items.end(); i++) {
desc.append(i->first + "=" + i->second.toString());
}
return desc.toString("\n");
}
namespace
{
const char *keyTranslation[][2] = {

View File

@@ -60,6 +60,7 @@ namespace TagLib {
virtual String genre() const;
virtual unsigned int year() const;
virtual unsigned int track() const;
virtual PictureMap pictures() const;
virtual void setTitle(const String &value);
virtual void setArtist(const String &value);
@@ -68,6 +69,7 @@ namespace TagLib {
virtual void setGenre(const String &value);
virtual void setYear(unsigned int value);
virtual void setTrack(unsigned int value);
virtual void setPictures(const PictureMap &l);
virtual bool isEmpty() const;
@@ -102,6 +104,8 @@ namespace TagLib {
*/
bool contains(const String &key) const;
String toString() const;
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList& properties);
PropertyMap setProperties(const PropertyMap &properties);
@@ -139,7 +143,7 @@ namespace TagLib {
ByteVector renderCovr(const ByteVector &name, const Item &item) const;
void updateParents(const AtomList &path, long delta, int ignore = 0);
void updateOffsets(long delta, long offset);
void updateOffsets(long delta, long long offset);
void saveNew(ByteVector data);
void saveExisting(ByteVector data, const AtomList &path);

View File

@@ -29,6 +29,7 @@
#include <tdebug.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include <tsmartptr.h>
#include "mpcfile.h"
#include "id3v1tag.h"
@@ -50,29 +51,21 @@ public:
APELocation(-1),
APESize(0),
ID3v1Location(-1),
ID3v2Header(0),
ID3v2Location(-1),
ID3v2Size(0),
properties(0) {}
ID3v2Size(0) {}
~FilePrivate()
{
delete ID3v2Header;
delete properties;
}
long long APELocation;
long long APESize;
long APELocation;
long APESize;
long long ID3v1Location;
long ID3v1Location;
SCOPED_PTR<ID3v2::Header> ID3v2Header;
long long ID3v2Location;
long long ID3v2Size;
ID3v2::Header *ID3v2Header;
long ID3v2Location;
long ID3v2Size;
DoubleTagUnion tag;
TagUnion tag;
Properties *properties;
SCOPED_PTR<AudioProperties> properties;
};
////////////////////////////////////////////////////////////////////////////////
@@ -92,7 +85,7 @@ bool MPC::File::isSupported(IOStream *stream)
// public members
////////////////////////////////////////////////////////////////////////////////
MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
MPC::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
TagLib::File(file),
d(new FilePrivate())
{
@@ -100,7 +93,7 @@ MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
read(readProperties);
}
MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
MPC::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) :
TagLib::File(stream),
d(new FilePrivate())
{
@@ -118,16 +111,6 @@ TagLib::Tag *MPC::File::tag() const
return &d->tag;
}
PropertyMap MPC::File::properties() const
{
return d->tag.properties();
}
void MPC::File::removeUnsupportedProperties(const StringList &properties)
{
d->tag.removeUnsupportedProperties(properties);
}
PropertyMap MPC::File::setProperties(const PropertyMap &properties)
{
if(ID3v1Tag())
@@ -136,9 +119,9 @@ PropertyMap MPC::File::setProperties(const PropertyMap &properties)
return APETag(true)->setProperties(properties);
}
MPC::Properties *MPC::File::audioProperties() const
MPC::AudioProperties *MPC::File::audioProperties() const
{
return d->properties;
return d->properties.get();
}
bool MPC::File::save()
@@ -151,7 +134,7 @@ bool MPC::File::save()
// Possibly strip ID3v2 tag
if(!d->ID3v2Header && d->ID3v2Location >= 0) {
removeBlock(d->ID3v2Location, d->ID3v2Size);
removeBlock(d->ID3v2Location, static_cast<size_t>(d->ID3v2Size));
if(d->APELocation >= 0)
d->APELocation -= d->ID3v2Size;
@@ -203,7 +186,7 @@ bool MPC::File::save()
}
const ByteVector data = APETag()->render();
insert(data, d->APELocation, d->APESize);
insert(data, d->APELocation, static_cast<size_t>(d->APESize));
if(d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
@@ -215,7 +198,7 @@ bool MPC::File::save()
// APE tag is empty. Remove the old one.
if(d->APELocation >= 0) {
removeBlock(d->APELocation, d->APESize);
removeBlock(d->APELocation, static_cast<size_t>(d->APESize));
if(d->ID3v1Location >= 0)
d->ID3v1Location -= d->APESize;
@@ -249,10 +232,8 @@ void MPC::File::strip(int tags)
if(!ID3v1Tag())
APETag(true);
if(tags & ID3v2) {
delete d->ID3v2Header;
d->ID3v2Header = 0;
}
if(tags & ID3v2)
d->ID3v2Header.reset();
}
void MPC::File::remove(int tags)
@@ -282,7 +263,7 @@ void MPC::File::read(bool readProperties)
if(d->ID3v2Location >= 0) {
seek(d->ID3v2Location);
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
d->ID3v2Header.reset(new ID3v2::Header(readBlock(ID3v2::Header::size())));
d->ID3v2Size = d->ID3v2Header->completeTagSize();
}
@@ -310,7 +291,7 @@ void MPC::File::read(bool readProperties)
if(readProperties) {
long streamLength;
long long streamLength;
if(d->APELocation >= 0)
streamLength = d->APELocation;
@@ -327,6 +308,6 @@ void MPC::File::read(bool readProperties)
seek(0);
}
d->properties = new Properties(this, streamLength);
d->properties.reset(new AudioProperties(this, streamLength));
}
}

View File

@@ -90,7 +90,7 @@ namespace TagLib {
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Constructs an MPC file from \a stream. If \a readProperties is true the
@@ -102,7 +102,7 @@ namespace TagLib {
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Destroys this instance of the File.
@@ -115,27 +115,18 @@ namespace TagLib {
*/
virtual TagLib::Tag *tag() const;
/*!
* Implements the unified property interface -- export function.
* If the file contains both an APE and an ID3v1 tag, only the APE
* tag will be converted to the PropertyMap.
*/
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the unified property interface -- import function.
* Affects only the APEv2 tag which will be created if necessary.
* If an ID3v1 tag exists, it will be updated as well.
*/
PropertyMap setProperties(const PropertyMap &);
virtual PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the MPC::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
virtual AudioProperties *audioProperties() const;
/*!
* Saves the file.

View File

@@ -33,7 +33,12 @@
using namespace TagLib;
class MPC::Properties::PropertiesPrivate
namespace
{
const unsigned int HeaderSize = 56;
}
class MPC::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() :
@@ -67,15 +72,8 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
readSV7(data, streamLength);
}
MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
AudioProperties(style),
MPC::AudioProperties::AudioProperties(File *file, long long streamLength, ReadStyle) :
TagLib::AudioProperties(),
d(new PropertiesPrivate())
{
ByteVector magic = file->readBlock(4);
@@ -85,76 +83,76 @@ MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
}
else {
// Musepack version 7 or older, fixed size header
readSV7(magic + file->readBlock(MPC::HeaderSize - 4), streamLength);
readSV7(magic + file->readBlock(HeaderSize - 4), streamLength);
}
}
MPC::Properties::~Properties()
MPC::AudioProperties::~AudioProperties()
{
delete d;
}
int MPC::Properties::length() const
int MPC::AudioProperties::length() const
{
return lengthInSeconds();
}
int MPC::Properties::lengthInSeconds() const
int MPC::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int MPC::Properties::lengthInMilliseconds() const
int MPC::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int MPC::Properties::bitrate() const
int MPC::AudioProperties::bitrate() const
{
return d->bitrate;
}
int MPC::Properties::sampleRate() const
int MPC::AudioProperties::sampleRate() const
{
return d->sampleRate;
}
int MPC::Properties::channels() const
int MPC::AudioProperties::channels() const
{
return d->channels;
}
int MPC::Properties::mpcVersion() const
int MPC::AudioProperties::mpcVersion() const
{
return d->version;
}
unsigned int MPC::Properties::totalFrames() const
unsigned int MPC::AudioProperties::totalFrames() const
{
return d->totalFrames;
}
unsigned int MPC::Properties::sampleFrames() const
unsigned int MPC::AudioProperties::sampleFrames() const
{
return d->sampleFrames;
}
int MPC::Properties::trackGain() const
int MPC::AudioProperties::trackGain() const
{
return d->trackGain;
}
int MPC::Properties::trackPeak() const
int MPC::AudioProperties::trackPeak() const
{
return d->trackPeak;
}
int MPC::Properties::albumGain() const
int MPC::AudioProperties::albumGain() const
{
return d->albumGain;
}
int MPC::Properties::albumPeak() const
int MPC::AudioProperties::albumPeak() const
{
return d->albumPeak;
}
@@ -165,7 +163,7 @@ int MPC::Properties::albumPeak() const
namespace
{
unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof)
unsigned long readSize(File *file, size_t &sizeLength, bool &eof)
{
sizeLength = 0;
eof = false;
@@ -187,7 +185,7 @@ namespace
return size;
}
unsigned long readSize(const ByteVector &data, unsigned int &pos)
unsigned long readSize(const ByteVector &data, size_t &pos)
{
unsigned char tmp;
unsigned long size = 0;
@@ -204,26 +202,26 @@ namespace
const unsigned short sftable [8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
}
void MPC::Properties::readSV8(File *file, long streamLength)
void MPC::AudioProperties::readSV8(File *file, long long streamLength)
{
bool readSH = false, readRG = false;
while(!readSH && !readRG) {
const ByteVector packetType = file->readBlock(2);
unsigned int packetSizeLength;
size_t packetSizeLength;
bool eof;
const unsigned long packetSize = readSize(file, packetSizeLength, eof);
const size_t packetSize = readSize(file, packetSizeLength, eof);
if(eof) {
debug("MPC::Properties::readSV8() - Reached to EOF.");
debug("MPC::AudioProperties::readSV8() - Reached to EOF.");
break;
}
const unsigned long dataSize = packetSize - 2 - packetSizeLength;
const size_t dataSize = packetSize - 2 - packetSizeLength;
const ByteVector data = file->readBlock(dataSize);
if(data.size() != dataSize) {
debug("MPC::Properties::readSV8() - dataSize doesn't match the actual data size.");
debug("MPC::AudioProperties::readSV8() - dataSize doesn't match the actual data size.");
break;
}
@@ -232,28 +230,29 @@ void MPC::Properties::readSV8(File *file, long streamLength)
// http://trac.musepack.net/wiki/SV8Specification#StreamHeaderPacket
if(dataSize <= 5) {
debug("MPC::Properties::readSV8() - \"SH\" packet is too short to parse.");
debug("MPC::AudioProperties::readSV8() - \"SH\" packet is too short to parse.");
break;
}
readSH = true;
unsigned int pos = 4;
size_t pos = 4;
d->version = data[pos];
pos += 1;
d->sampleFrames = readSize(data, pos);
if(pos > dataSize - 3) {
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
debug("MPC::AudioProperties::readSV8() - \"SH\" packet is corrupt.");
break;
}
const unsigned long begSilence = readSize(data, pos);
if(pos > dataSize - 2) {
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
debug("MPC::AudioProperties::readSV8() - \"SH\" packet is corrupt.");
break;
}
const unsigned short flags = data.toUShort(pos, true);
const unsigned short flags = data.toUInt16BE(pos);
pos += 2;
d->sampleRate = sftable[(flags >> 13) & 0x07];
@@ -271,7 +270,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
// http://trac.musepack.net/wiki/SV8Specification#ReplaygainPacket
if(dataSize <= 9) {
debug("MPC::Properties::readSV8() - \"RG\" packet is too short to parse.");
debug("MPC::AudioProperties::readSV8() - \"RG\" packet is too short to parse.");
break;
}
@@ -279,10 +278,10 @@ void MPC::Properties::readSV8(File *file, long streamLength)
const int replayGainVersion = data[0];
if(replayGainVersion == 1) {
d->trackGain = data.toShort(1, true);
d->trackPeak = data.toShort(3, true);
d->albumGain = data.toShort(5, true);
d->albumPeak = data.toShort(7, true);
d->trackGain = data.toUInt16BE(1);
d->trackPeak = data.toUInt16BE(3);
d->albumGain = data.toUInt16BE(5);
d->albumPeak = data.toUInt16BE(7);
}
}
@@ -296,25 +295,25 @@ void MPC::Properties::readSV8(File *file, long streamLength)
}
}
void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
void MPC::AudioProperties::readSV7(const ByteVector &data, long long streamLength)
{
if(data.startsWith("MP+")) {
d->version = data[3] & 15;
if(d->version < 7)
return;
d->totalFrames = data.toUInt(4, false);
d->totalFrames = data.toUInt32LE(4);
const unsigned int flags = data.toUInt(8, false);
const unsigned int flags = data.toUInt32LE(8);
d->sampleRate = sftable[(flags >> 16) & 0x03];
d->channels = 2;
const unsigned int gapless = data.toUInt(5, false);
const unsigned int gapless = data.toUInt32LE(5);
d->trackGain = data.toShort(14, false);
d->trackPeak = data.toShort(12, false);
d->albumGain = data.toShort(18, false);
d->albumPeak = data.toShort(16, false);
d->trackGain = data.toUInt16LE(14);
d->trackPeak = data.toUInt16LE(12);
d->albumGain = data.toUInt16LE(18);
d->albumPeak = data.toUInt16LE(16);
// convert gain info
if(d->trackGain != 0) {
@@ -344,7 +343,7 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
d->sampleFrames = d->totalFrames * 1152 - 576;
}
else {
const unsigned int headerData = data.toUInt(0, false);
const unsigned int headerData = data.toUInt32LE(0);
d->bitrate = (headerData >> 23) & 0x01ff;
d->version = (headerData >> 11) & 0x03ff;
@@ -352,9 +351,9 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
d->channels = 2;
if(d->version >= 5)
d->totalFrames = data.toUInt(4, false);
d->totalFrames = data.toUInt32LE(4);
else
d->totalFrames = data.toUShort(6, false);
d->totalFrames = data.toUInt16LE(6);
d->sampleFrames = d->totalFrames * 1152 - 576;
}

View File

@@ -35,8 +35,6 @@ namespace TagLib {
class File;
static const unsigned int HeaderSize = 8 * 7;
//! An implementation of audio property reading for MPC
/*!
@@ -44,27 +42,19 @@ namespace TagLib {
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
/*!
* Create an instance of MPC::Properties with the data read from the
* ByteVector \a data.
*
* This constructor is deprecated. It only works for MPC version up to 7.
*/
Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
/*!
* Create an instance of MPC::Properties with the data read directly
* Creates an instance of MPC::AudioProperties with the data read directly
* from a MPC::File.
*/
Properties(File *file, long streamLength, ReadStyle style = Average);
AudioProperties(File *file, long long streamLength, ReadStyle style = Average);
/*!
* Destroys this MPC::Properties instance.
*/
virtual ~Properties();
virtual ~AudioProperties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
@@ -82,16 +72,14 @@ namespace TagLib {
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
virtual int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
virtual int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
@@ -143,11 +131,8 @@ namespace TagLib {
int albumPeak() const;
private:
Properties(const Properties &);
Properties &operator=(const Properties &);
void readSV7(const ByteVector &data, long streamLength);
void readSV8(File *file, long streamLength);
void readSV7(const ByteVector &data, long long streamLength);
void readSV8(File *file, long long streamLength);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@@ -25,6 +25,7 @@
#include <tdebug.h>
#include <tfile.h>
#include <tpicturemap.h>
#include "id3v1tag.h"
#include "id3v1genres.h"
@@ -34,8 +35,28 @@ using namespace ID3v1;
namespace
{
const ID3v1::StringHandler defaultStringHandler;
const ID3v1::StringHandler *stringHandler = &defaultStringHandler;
class DefaultStringHandler : public TagLib::StringHandler
{
public:
DefaultStringHandler() :
TagLib::StringHandler() {}
virtual String parse(const ByteVector &data) const
{
return String(data, String::Latin1).stripWhiteSpace();
}
virtual ByteVector render(const String &s) const
{
if(s.isLatin1())
return s.data(String::Latin1);
else
return ByteVector();
}
};
const DefaultStringHandler defaultStringHandler;
const TagLib::StringHandler *stringHandler = &defaultStringHandler;
}
class ID3v1::Tag::TagPrivate
@@ -48,7 +69,7 @@ public:
genre(255) {}
File *file;
long tagOffset;
long long tagOffset;
String title;
String artist;
@@ -59,27 +80,6 @@ public:
unsigned char genre;
};
////////////////////////////////////////////////////////////////////////////////
// StringHandler implementation
////////////////////////////////////////////////////////////////////////////////
StringHandler::StringHandler()
{
}
String ID3v1::StringHandler::parse(const ByteVector &data) const
{
return String(data, String::Latin1).stripWhiteSpace();
}
ByteVector ID3v1::StringHandler::render(const String &s) const
{
if(s.isLatin1())
return s.data(String::Latin1);
else
return ByteVector();
}
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
@@ -90,7 +90,7 @@ ID3v1::Tag::Tag() :
{
}
ID3v1::Tag::Tag(File *file, long tagOffset) :
ID3v1::Tag::Tag(File *file, long long tagOffset) :
TagLib::Tag(),
d(new TagPrivate())
{
@@ -162,6 +162,11 @@ unsigned int ID3v1::Tag::track() const
return d->track;
}
TagLib::PictureMap ID3v1::Tag::pictures() const
{
return PictureMap();
}
void ID3v1::Tag::setTitle(const String &s)
{
d->title = s;
@@ -197,6 +202,10 @@ void ID3v1::Tag::setTrack(unsigned int i)
d->track = i < 256 ? i : 0;
}
void ID3v1::Tag::setPictures(const PictureMap &l)
{
}
unsigned int ID3v1::Tag::genreNumber() const
{
return d->genre;
@@ -207,7 +216,7 @@ void ID3v1::Tag::setGenreNumber(unsigned int i)
d->genre = i < 256 ? i : 255;
}
void ID3v1::Tag::setStringHandler(const StringHandler *handler)
void ID3v1::Tag::setStringHandler(const TagLib::StringHandler *handler)
{
if(handler)
stringHandler = handler;

View File

@@ -28,6 +28,7 @@
#include "tag.h"
#include "tbytevector.h"
#include "tstringhandler.h"
#include "taglib_export.h"
namespace TagLib {
@@ -38,50 +39,6 @@ namespace TagLib {
namespace ID3v1 {
//! A abstraction for the string to data encoding in ID3v1 tags.
/*!
* ID3v1 should in theory always contain ISO-8859-1 (Latin1) data. In
* practice it does not. TagLib by default only supports ISO-8859-1 data
* in ID3v1 tags.
*
* However by subclassing this class and reimplementing parse() and render()
* and setting your reimplementation as the default with
* ID3v1::Tag::setStringHandler() you can define how you would like these
* transformations to be done.
*
* \warning It is advisable <b>not</b> to write non-ISO-8859-1 data to ID3v1
* tags. Please consider disabling the writing of ID3v1 tags in the case
* that the data is not ISO-8859-1.
*
* \see ID3v1::Tag::setStringHandler()
*/
class TAGLIB_EXPORT StringHandler
{
TAGLIB_IGNORE_MISSING_DESTRUCTOR
public:
// BIC: Add virtual destructor.
StringHandler();
/*!
* Decode a string from \a data. The default implementation assumes that
* \a data is an ISO-8859-1 (Latin1) character array.
*/
virtual String parse(const ByteVector &data) const;
/*!
* Encode a ByteVector with the data from \a s. The default implementation
* assumes that \a s is an ISO-8859-1 (Latin1) string. If the string is
* does not conform to ISO-8859-1, no value is written.
*
* \warning It is recommended that you <b>not</b> override this method, but
* instead do not write an ID3v1 tag in the case that the data is not
* ISO-8859-1.
*/
virtual ByteVector render(const String &s) const;
};
//! The main class in the ID3v1 implementation
/*!
@@ -114,7 +71,7 @@ namespace TagLib {
* Create an ID3v1 tag and parse the data in \a file starting at
* \a tagOffset.
*/
Tag(File *file, long tagOffset);
Tag(File *file, long long tagOffset);
/*!
* Destroys this Tag instance.
@@ -142,6 +99,7 @@ namespace TagLib {
virtual String genre() const;
virtual unsigned int year() const;
virtual unsigned int track() const;
virtual PictureMap pictures() const;
virtual void setTitle(const String &s);
virtual void setArtist(const String &s);
@@ -150,6 +108,7 @@ namespace TagLib {
virtual void setGenre(const String &s);
virtual void setYear(unsigned int i);
virtual void setTrack(unsigned int i);
virtual void setPictures(const PictureMap &l);
/*!
* Returns the genre in number.
@@ -174,16 +133,15 @@ namespace TagLib {
*
* \note The caller is responsible for deleting the previous handler
* as needed after it is released.
*
* \see StringHandler
*/
static void setStringHandler(const StringHandler *handler);
static void setStringHandler(const TagLib::StringHandler *handler);
protected:
/*!
* Reads from the file specified in the constructor.
*/
void read();
/*!
* Pareses the body of the tag in \a data.
*/

View File

@@ -135,17 +135,17 @@ void AttachedPictureFrame::parseFields(const ByteVector &data)
d->textEncoding = String::Type(data[0]);
int pos = 1;
size_t pos = 1;
d->mimeType = readStringField(data, String::Latin1, &pos);
d->mimeType = readStringField(data, String::Latin1, pos);
/* Now we need at least two more bytes available */
if(static_cast<unsigned int>(pos) + 1 >= data.size()) {
if(pos + 1 >= data.size()) {
debug("Truncated picture frame.");
return;
}
d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
d->description = readStringField(data, d->textEncoding, &pos);
d->description = readStringField(data, d->textEncoding, pos);
d->data = data.mid(pos);
}
@@ -191,7 +191,7 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
d->textEncoding = String::Type(data[0]);
int pos = 1;
size_t pos = 1;
String fixedString = String(data.mid(pos, 3), String::Latin1);
pos += 3;
@@ -206,7 +206,7 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
}
d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
d->description = readStringField(data, d->textEncoding, &pos);
d->description = readStringField(data, d->textEncoding, pos);
d->data = data.mid(pos);
}

View File

@@ -241,24 +241,25 @@ ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVec
void ChapterFrame::parseFields(const ByteVector &data)
{
unsigned int size = data.size();
size_t size = data.size();
if(size < 18) {
debug("A CHAP frame must contain at least 18 bytes (1 byte element ID "
"terminated by null and 4x4 bytes for start and end time and offset).");
return;
}
int pos = 0;
unsigned int embPos = 0;
d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
d->startTime = data.toUInt(pos, true);
size_t pos = 0;
size_t embPos = 0;
d->elementID = readStringField(data, String::Latin1, pos).data(String::Latin1);
d->startTime = data.toUInt32BE(pos);
pos += 4;
d->endTime = data.toUInt(pos, true);
d->endTime = data.toUInt32BE(pos);
pos += 4;
d->startOffset = data.toUInt(pos, true);
d->startOffset = data.toUInt32BE(pos);
pos += 4;
d->endOffset = data.toUInt(pos, true);
d->endOffset = data.toUInt32BE(pos);
pos += 4;
size -= pos;
// Embedded frames are optional
@@ -267,7 +268,7 @@ void ChapterFrame::parseFields(const ByteVector &data)
return;
while(embPos < size - header()->size()) {
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), (d->tagHeader != 0));
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
if(!frame)
return;
@@ -289,10 +290,10 @@ ByteVector ChapterFrame::renderFields() const
data.append(d->elementID);
data.append('\0');
data.append(ByteVector::fromUInt(d->startTime, true));
data.append(ByteVector::fromUInt(d->endTime, true));
data.append(ByteVector::fromUInt(d->startOffset, true));
data.append(ByteVector::fromUInt(d->endOffset, true));
data.append(ByteVector::fromUInt32BE(d->startTime));
data.append(ByteVector::fromUInt32BE(d->endTime));
data.append(ByteVector::fromUInt32BE(d->startOffset));
data.append(ByteVector::fromUInt32BE(d->endOffset));
FrameList l = d->embeddedFrameList;
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
data.append((*it)->render());

View File

@@ -98,7 +98,7 @@ void EventTimingCodesFrame::setSynchedEvents(
void EventTimingCodesFrame::parseFields(const ByteVector &data)
{
const int end = data.size();
const size_t end = data.size();
if(end < 1) {
debug("An event timing codes frame must contain at least 1 byte.");
return;
@@ -106,11 +106,11 @@ void EventTimingCodesFrame::parseFields(const ByteVector &data)
d->timestampFormat = TimestampFormat(data[0]);
int pos = 1;
size_t pos = 1;
d->synchedEvents.clear();
while(pos + 4 < end) {
EventType type = static_cast<EventType>(static_cast<unsigned char>(data[pos++]));
unsigned int time = data.toUInt(pos, true);
unsigned int time = data.toUInt32BE(pos);
pos += 4;
d->synchedEvents.append(SynchedEvent(time, type));
}
@@ -126,7 +126,7 @@ ByteVector EventTimingCodesFrame::renderFields() const
++it) {
const SynchedEvent &entry = *it;
v.append(char(entry.type));
v.append(ByteVector::fromUInt(entry.time));
v.append(ByteVector::fromUInt32BE(entry.time));
}
return v;

View File

@@ -144,11 +144,11 @@ void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data)
d->textEncoding = String::Type(data[0]);
int pos = 1;
size_t pos = 1;
d->mimeType = readStringField(data, String::Latin1, &pos);
d->fileName = readStringField(data, d->textEncoding, &pos);
d->description = readStringField(data, d->textEncoding, &pos);
d->mimeType = readStringField(data, String::Latin1, pos);
d->fileName = readStringField(data, d->textEncoding, pos);
d->description = readStringField(data, d->textEncoding, pos);
d->data = data.mid(pos);
}

Some files were not shown because too many files have changed in this diff Show More