1559 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
Stephen F. Booth
5cb589a5b8 Updated NEWS for the latest changes 2018-10-28 08:43:45 -05:00
Stephen F. Booth
a4d04e0c40 Added APE, DSF, and DFF formats to the list 2018-10-28 08:42:19 -05:00
Stephen F. Booth
4ab0891646 Added DSF and DSDIFF authors 2018-10-28 08:35:15 -05:00
Jonas Kvinge
d71398c953 Add DSF and DSDIFF file types management (#878)
* Add DSF and DSDIFF file types management

* Fixes for some build chains

* unit64_t replaced by unsigned long long, warning fixes

* Remove C++11 extension incompatible with some build chains (enumeration in a nested name specifier)

* Change typedef types (uint, ulong, ...) to standard types
remove BUILD_FRAMEWORK changes from this pull request

* Replace deprecated String::null and ByteVector::null by String() and ByteVector()
Styling update, thanks to FestusHagen

* Restyling

* Restyling to reduce length of excessively long lines

* Add to detectByExtension

* Added `isSupported(IOStream *stream)` to `DSF::File` and `DSDIFF::File`
2018-10-26 19:45:49 -05:00
evpobr
bfed3797a0 Improve CMake VISIBILITY_HIDDEN option handling (#810)
Use standard CMake's CXX_VISIBILITY_PRESET property.
2018-10-26 19:26:53 -05:00
Ola Nordstrom
e435372146 added OS X built files to .gitignore (#828) 2018-10-26 19:23:44 -05:00
Bert Wesarg
c2f544c9d1 Fill TableOfContentsFrame::toString(). (#852) 2018-10-26 19:21:18 -05:00
Scott Wheeler
8ca75f03b5 Follow TagLib's brace style 2018-10-10 19:24:44 +02:00
safu9
036a0317b9 Add support for file descriptor to FileStream (#832)
Add support for file descriptor
2018-10-10 12:25:02 -04:00
Bert Wesarg
8f6fe0b16c Don't list the description twice in UserTextIdentificationFrame::toString() (#853) 2018-10-09 18:55:02 -05:00
evpobr
fc31a09c03 Fix undefined PLATFORM_WINRT CMake option (#870) 2018-10-09 18:52:09 -05:00
Scott Gayou
2c4ae870ec Fixed OOB read when loading invalid ogg flac file. (#868) (#869)
CVE-2018-11439 is caused by a failure to check the minimum length
of a ogg flac header. This header is detailed in full at:
https://xiph.org/flac/ogg_mapping.html. Added more strict checking
for entire header.
2018-10-09 18:46:55 -05:00
Alberto Fustinoni
2052cda5fb Added setProperties implementation to TagUnion (#813)
Added setProperties support in TagUnion
2018-08-24 08:40:15 -05:00
Urs Fleisch
d8d56d3937 Add support for cmID, purl, egid MP4 atoms (#862). (#863) 2018-04-09 08:32:05 -05:00
Scott Wheeler
a80093167f Update links 2017-11-20 00:03:52 +01:00
Xijian Yan
249f892455 Fix crash when loading an empty mpeg file (#830)
When loading an empty file (empty.txt -> empty.mp3 ), TagLib will crash.
buffer.size() is 0, then buffer.size() - 1 is undefined (unsigned int)
2017-11-06 09:48:17 -06:00
Stephen F. Booth
cb9f07d9dc Don't assume TDRC is an instance of TextIdentificationFrame (#831)
If TDRC is encrypted, FrameFactory::createFrame() returns UnknownFrame
which causes problems in rebuildAggregateFrames() when it is assumed
that TDRC is a TextIdentificationFrame
2017-09-30 10:15:41 -05:00
Sergei Trofimovich
0b583bafd0 taglib: fix test build failure on powerpc/c++11 (#834)
powerpc is a platform with 'char' == 'unsigned char'.
As a result '-1' is not expressible in char and build fails as:

```
    # '-funsigned-char' to force test build failure on other platforms
    $ cmake .. -DBUILD_TESTS=YES -DCMAKE_CXX_FLAGS="-O2 -funsigned-char" -DCMAKE_C_FLAGS="-O2 -funsigned-char"
    ...
    $ make check
    tests/test_synchdata.cpp: In member function 'void TestID3v2SynchData::testToUIntBroken()':
    tests/test_synchdata.cpp:78:33: error: narrowing conversion of '-1' from 'int' to 'char' inside { } [-Wnarrowing]
     char data[] = { 0, 0, 0, -1 };
                                 ^
```

The fix is to expliticly cast -1 to 'char'.

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
2017-09-18 20:06:55 -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
4648394841 Check if mandatory header objects are present when opening ASF files.
Also removes some assignments of "this".
It feels too tricky when it is not absolutely necessary.
2017-06-13 17:22:00 +09:00
Tsuda Kageyu
e026d797e0 Use a macro to pretend virtual functions. 2017-06-13 17:01:53 +09:00
Tsuda Kageyu
eeb2f5de09 Fix some typos in debug messages. 2017-06-13 15:05:25 +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
1792ee9db8 Update NEWS. 2017-06-12 13:07:21 +09:00
Tsuda Kageyu
1fb310ec1f Merge pull request #799 from TsudaKageyu/filetype-detection
Enable FileRef to detect file types by the actual content of a stream.
2017-06-12 13:04:15 +09:00
Tsuda Kageyu
c8bcd153fe TableOfContentsFrame depends on ByteVectorList. 2017-06-09 17:52:56 +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
662f340f93 Merge pull request #824 from evpobr/fix-createfile2
Fix WinRT configuring
2017-06-09 08:53:25 +09:00
Tsuda Kageyu
48d8c0a808 Merge pull request #823 from TsudaKageyu/isolate-3rdparty-lib
Isolate 3rdparty library for easier maintenance.
2017-06-09 08:53:10 +09:00
evpobr
5ebd3d5276 Fix WinRT configuring
Don't rely on _WIN32_WINNT value to enable WinRT support.

if _WIN32_WINNT is not set manually, it is defaulted to SDK version. So
if you use SDK > 8 you cannot use TagLib under Win7 and lower because of
CreateFile2 function dependency.

PLATFORM_WINRT option (OFF by default) was introduced to enable WinRT
build.

Related issues: https://github.com/Microsoft/vcpkg/issues/1240
2017-06-08 19:00:37 +05:00
Tsuda Kageyu
14af861d24 Isolate 3rdparty library for easier maintenance. 2017-06-07 12:51:44 +09:00
Tsuda Kageyu
3795f277fb Update UTF8-CPP to v2.3.5. 2017-06-07 12:12:31 +09:00
Tsuda Kageyu
6045995e65 Remove an unused include directory from taglib/CMakeLists.txt. 2017-06-07 11:38:46 +09:00
Tsuda Kageyu
c2fe93c12b Restore FileRef::create() in order not to change the previous behavior. 2017-06-06 09:17:34 +09:00
Michael Helmling
ea9202d9ee Update INSTALL.md
Added a note that with MS Visual Studio 2017 one can directly open the CMake project.
2017-06-05 14:49:09 +02:00
Stephen F. Booth
3c657d1a44 Merge pull request #821 from supermihi/master
Fix Markdown syntax of INSTALL file and rename it to *.md
2017-06-05 07:37:12 -04:00
Michael Helmling
adf0f76360 Fix Markdown syntax of INSTALL file and rename it to *.md
This enables proper formatted display of the file on e.g. GitHub, increasing readability.
2017-06-05 11:09:16 +02:00
Tsuda Kageyu
682ea77c2b Mention that FileRef::create no longer works. 2017-05-31 09:41:41 +09:00
Tsuda Kageyu
15c3c756ca Update NEWS. 2017-05-31 09:28:30 +09:00
Tsuda Kageyu
4801fbb927 Merge pull request #818 from LindyBalboa/add_rate_atom_support
Add direct support for "rate" atom
2017-05-31 09:20:27 +09:00
Tsuda Kageyu
22de22b701 Fix memory leaks in a test. 2017-05-26 16:49:36 +09:00
Tsuda Kageyu
48a1a05a88 Fix MSVC warnings about unreferenced variables. 2017-05-23 17:46:16 +09:00
Tsuda Kageyu
6000a19f70 Fix the Travis-CI testing on OS X.
AppleClang 7.3 doesn't get along with CppUnit by default.
2017-05-23 17:33:22 +09:00
Conner R. Phillips
ff28cf276c Add direct support for "rate" atom
Resolves #817
2017-04-22 07:45:29 +02:00
Tsuda Kageyu
4891ee729d Remove an useless UTF-8 BOM. 2017-02-24 15:47:30 +09:00
Tsuda Kageyu
9419dab51b Allow SYLT frames to have a timestamp with no text.
Thanks to lemonboy999.
2017-02-24 15:40:30 +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
45ee18e206 FilePrivate is responsible to delete a stream pointer instead of File.
Generally, TagLib leaves the Private classes to delete their members.
2017-02-08 17:49:48 +09:00
Tsuda Kageyu
bf7ee62dc6 Merge branch 'filetype-detection' of https://github.com/TsudaKageyu/taglib into filetype-detection 2017-02-07 22:37:13 +09:00
Tsuda Kageyu
f76b1e5429 Rename the functions 'isValidStream' to 'isSupported'.
The name 'isValidStream' is a little misleading because it doesn't check if the stream is really valid. Additionally, 'isSupported' can be naturally overloaded.
2017-02-07 22:36:56 +09:00
Tsuda Kageyu
f7b15fad20 Remove some redundant code. 2017-02-06 10:35:49 +09:00
Tsuda Kageyu
dd4adf94ce Fix wrong endian of boolean values when saving ASF files. 2017-02-06 10:06:10 +09:00
Tsuda Kageyu
d4d8410c08 Restore the layout of the copyright header of test_fileref.cpp. 2017-02-04 23:45:15 +09:00
Tsuda Kageyu
931bb042c3 Enable FileRef to detect file types by the actual content of a stream.
FileRef doesn't work with ByteVectorStream as reported at #796, since ByteVectorStream is not associated with a file name and FileRef detects file types based on file extensions.
This commit makes FileRef to work with ByteVectorStream by enabling it to detect file types based on the actual content of a stream.
2017-02-04 23:31:08 +09:00
Tsuda Kageyu
a5d9e49c49 Remove obsolete comments.
The bug mentioned in the comments are already fixed.
2017-02-04 01:31:20 +09:00
Scott Wheeler
179c175a6c Ignore warnings about OSAtomicIncrement32Barrier
The warnings suggest moving to std::atomic functions, but those are only
available in C++11.  It would be possible to switch to the C versions of
those functions, which are now provided in stdatoic.h (in C11), but
let's wait until we actually hit problems with this function and are a
few more OS versions into C11 headers being included by default.
2017-02-03 13:56:02 +00:00
Tsuda Kageyu
ba98628919 Avoid searching the same area twice in MPEG::File::previousFrameOffset(). 2017-02-01 14:23:03 +09:00
Tsuda Kageyu
87fc4012f4 Add some test cases for invalid UTF-8 sequences. 2017-01-31 14:27:23 +09:00
Tsuda Kageyu
dd5ab2a08f Fix and add some test cases for invalid surrogate pairs. 2017-01-31 14:19:30 +09:00
Tsuda Kageyu
b74ffba4b5 Update NEWS. 2017-01-31 00:21:41 +09:00
Tsuda Kageyu
4552f2c2eb Remove redundant functions in tstring.cpp.
Two versions of copyFromUTF16() are almost the same.
2017-01-30 22:38:08 +09:00
Tsuda Kageyu
6398796f95 Remove function bodies of some non-specialized template functions.
The code won't link when a wrong version is used. It's better than showing a debug message.
2017-01-30 16:11:59 +09:00
Tsuda Kageyu
2c7ac6d6a9 Add a few more test cases for invalid UTF-8 sequences. 2017-01-30 12:56:53 +09:00
Tsuda Kageyu
6a61f02f85 Merge pull request #794 from TsudaKageyu/utf8-library
Replace unicode.h/unicode.cpp by the UTF8-CPP library.
2017-01-30 12:54:43 +09:00
Tsuda Kageyu
038b52ae01 Check an invalid UTF-8 sequence consists of single char.
Single char can be an invalid UTF sequence. For example, { 0x80 } is invalid.
2017-01-30 11:35:39 +09:00
Tsuda Kageyu
598ab752bc Stop assuming that std::wstring has a contiguous and null-terminated buffer. 2017-01-30 00:36:38 +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
922fd611ae Reduce useless memory reallocation in String::upper(). 2017-01-28 01:17:21 +09:00
Tsuda Kageyu
3d14ff74b1 Remove a duplicate test file. 2017-01-27 22:10:02 +09:00
Tsuda Kageyu
978b822774 Remove some redundant code in tstring.cpp. 2017-01-27 15:11:08 +09:00
Tsuda Kageyu
0c45c63943 Replace unicode.h/unicode.cpp by the UTF8-CPP library.
unicode.h/unicode.cpp are no longer maintained and incompatible with Debian's guideline.
UTF8-CPP is maintained on GitHub and published under the Boost Software License which is compatible with either LGPL or MPL and should go along with Debian's guideline.
2017-01-27 14:47:55 +09:00
Tsuda Kageyu
586c9bd962 Add a test for unpaired surrogate characters in a UTF-16 string. 2017-01-26 17:33:54 +09:00
Tsuda Kageyu
fc38a0e401 Remove some redundant code.
TagUnion::access() does the same thing as FLAC::File::ID3v2Tag().
2017-01-22 00:43:32 +09:00
Tsuda Kageyu
5fc5a2e81a Prefer isEmpty()/empty() to size() == 0. 2017-01-21 19:10:32 +09:00
Tsuda Kageyu
a358e87cc4 Revert useless changes accidentally committed. 2017-01-21 11:13:49 +09:00
Tsuda Kageyu
5ba8b740f9 Add missing consts. 2017-01-21 11:09:05 +09:00
Tsuda Kageyu
c4a3c3ab97 Combine two internal functions which are always used together. 2017-01-21 01:34:50 +09:00
Tsuda Kageyu
6bb92c34fa Ignore fake MPEG frame headers when seeking them. 2017-01-20 22:38:25 +09:00
Tsuda Kageyu
d2e0e55223 Efficient lookup for an ID3v2 tag in MPEG files with garbage.
This looks for an ID3v2 tag until reaching the first valid MPEG frame in O(n) time.
2017-01-20 21:14:38 +09:00
Tsuda Kageyu
d64c833359 Update NEWS. 2017-01-16 01:14:35 +09:00
Tsuda Kageyu
c9c757e0ff Merge pull request #791 from TsudaKageyu/flac-empty-seektable
Be tolerant of empty FLAC seektable blocks.
2017-01-16 01:12:07 +09:00
Tsuda Kageyu
9b548260f5 Initialize d-pointers in class member initializer list. 2017-01-16 01:05:30 +09:00
Tsuda Kageyu
406e872ac3 Always use parentheses with new. It's a bit safer. 2017-01-16 01:00:28 +09:00
Tsuda Kageyu
193cbe3b6b Initialize all the data members of ASF::Attribute. 2017-01-14 23:29:46 +09:00
Tsuda Kageyu
13be28a52c Be tolerant of empty FLAC seektable blocks. 2017-01-10 00:11:13 +09:00
Tsuda Kageyu
56a7656c2e Remove some TODO comments which are no longer necessary. 2017-01-08 01:43:04 +09:00
Michael Helmling
c97be6630e Fix #789 (typo in member doc) 2017-01-06 09:08:02 +01:00
Stephen F. Booth
6fcc690233 Merge pull request #787 from rshanmu/master
Renamed unsupported-extension.xxx and modified test
2016-12-22 12:17:12 -05:00
Ramesh Shanmugasundaram
83c72518ab Renamed unsupported-extension.xxx and modified test
The file name unsupported-extension.xxx causes issue when unpacked
taglib-xxx.gz over an NFS partition. The file extension ".xxx" is the
one NFS uses for its own purpose and hence it will not allow creation
of this file.

Hence renamed the file and modified the test cases that checks for this
file.

Signed-off-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
2016-12-22 15:19:45 +00:00
Tsuda Kageyu
de87cd7736 Remove the CMake check for Boost I missed out on. 2016-12-20 12:06:21 +09:00
Tsuda Kageyu
14c3ce5737 Remove all the optional dependencies on Boost. 2016-12-20 11:54:06 +09:00
Tsuda Kageyu
ffa32b19a7 Fix the CMake check for std::atomic_int.
std::atomic_int of Visual C++ 2012 cannot be constructed with integer.
2016-12-20 11:48:14 +09:00
Tsuda Kageyu
8905e7095a Safer conversion of boolean values in ASF attributes.
Technically, boolean values in Extended Content Description Object is not necessarily be 0 or 1.
2016-12-19 10:37:10 +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
Tsuda Kageyu
a19a623d4b Make use of increment/decrement operators of std::atomic. 2016-12-09 10:09:31 +09:00
Tsuda Kageyu
250c59f783 Remove optional dependencies on Boost's dynamic libraries.
Using precompiled Boost libraries can lead to depending on external dynamic libraries.
2016-12-09 09:42:29 +09:00
Tsuda Kageyu
8eda5d5053 Merge pull request #784 from haoxi911/master
Fix #667: Compiled TagLib framework for OS X fails at codesign.
2016-12-09 09:00:04 +09:00
Hao Xi
b5115e3497 Fix #667: Compiled TagLib framework for OS X fails at codesign. 2016-12-08 12:53:40 +08:00
Tsuda Kageyu
36ccad2bd4 Rewrite ByteVector::replace() to run in O(n) time. 2016-12-05 11:02:59 +09:00
Tsuda Kageyu
b00a5c1aab Add a test to check if ByteVector is detached correctly when being replaced. 2016-12-05 10:15:26 +09:00
Tsuda Kageyu
f6a604f54b #include guards in CMake generated headers. 2016-12-02 17:26:43 +09:00
Tsuda Kageyu
489e2e6cbb Update NEWS. 2016-12-01 15:25:30 +09:00
Tsuda Kageyu
9336c82da3 Fix possible Ogg packet losses. 2016-12-01 11:32:01 +09:00
Tsuda Kageyu
cfbaf34597 Prevent the segment table of Ogg pages from exceeding the size limit. 2016-12-01 10:51:59 +09:00
Tsuda Kageyu
046c98230f Remove Utils::floatByteOrder() and use systemByteOrder() instead.
We can safely assume that the integer and float byte orders are the same on IEEE754 compliant systems.
2016-11-29 14:58:39 +09:00
Tsuda Kageyu
4381bd75f3 Add a test for #743/#779. 2016-11-29 10:53:33 +09:00
Tsuda Kageyu
6df61cf2af Small fix in style. 2016-11-29 10:38:11 +09:00
Tsuda Kageyu
e9ef40fe7f Merge pull request #779 from supermihi/master
Fixes #743 by not overwriting existing Xiph comment in FLAC::File::save
2016-11-28 21:03:39 +09: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
Michael Helmling
2786aa7463 Fixes #743 by not overwriting existing Xiph comment in FLAC::File::save 2016-11-27 19:17:13 +01:00
Tsuda Kageyu
d3062f3af4 A bit more tolerant check to return itself in String::substr(). 2016-11-26 13:05:14 +09:00
Stephen F. Booth
7871afec37 Merge pull request #778 from martin-flaska/optimization
String::substr optimization
2016-11-25 16:38:32 -05:00
Martin Flaska
c9a0754e3b tstring: String::substr optimization when returning itself as a substring
Use copy ctor to return in a case whole string is being returned.

The intention was to optimize String::stripWhiteSpace for no-strip case
(without any leading or trailing white space removal).

copyFromUTF16 was used in any case previously and allocated duplicate
buffer for the same string - no implicit sharing.

Signed-off-by: Martin Flaska <martin.flaska@legrand.us>
2016-11-25 15:32:26 +01:00
Martin Flaska
6cfb11bb12 test_string: Make 'stripWhiteSpace' test more complex
No string without leading/trailing spaces was used in the test.

Signed-off-by: Martin Flaska <martin.flaska@legrand.us>
2016-11-25 13:56:39 +01:00
Tsuda Kageyu
ad075a56f9 Suppress MSVC warnings in test. 2016-11-24 14:45:22 +09:00
Stephen F. Booth
f80a7c0d83 Merge pull request #776 from mathbunnyru/small_improvements
Small improvements
2016-11-23 23:31:49 -05:00
mathbunnyru
5e1d9fad31 Small fixes 2016-11-24 02:05:19 +03:00
mathbunnyru
eff28c55bf Increment fixes 2016-11-22 01:10:28 +03:00
Tsuda Kageyu
d5b9d7b8a7 Update NEWS. 2016-11-18 13:55:43 +09:00
Tsuda Kageyu
ce77fbb0e7 Merge pull request #772 from TsudaKageyu/vorbis-fields
Fix handling of lowercase 'metadata_block_picture' field
2016-11-18 13:52:38 +09:00
Tsuda Kageyu
b98a984b66 Fix handling of lowercase 'metadata_block_picture' fields in Vorbis comments.
Also refactored some redundant code for parsing pictures.
2016-11-11 00:07:32 +09:00
Tsuda Kageyu
f9a747dceb Avoid adding fields with invalid keys to Vorbis Comments.
According to the spec, '\x7F' is not allowed.
2016-11-10 23:35:14 +09:00
Tsuda Kageyu
7b8d576bde Don't decode redundant UTF-8 sequences in Win32.
Linux and OS X are working well and won't be affected.
2016-11-10 17:12:58 +09:00
Tsuda Kageyu
2651372291 Separate some tests to make them more specific. 2016-11-09 15:51:33 +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
499f6db977 Check invalid Unicode APE keys properly. 2016-11-09 00:29:03 +09:00
Tsuda Kageyu
9d58e9f8e8 Removed a utility function which is used only at one place. 2016-11-08 23:27:55 +09:00
Tsuda Kageyu
56cd3695f7 Add README.md. 2016-11-08 22:56:42 +09:00
Tsuda Kageyu
d81d894d41 tolower() depends on the current locale.
It's much easier to write our own function than to use locales properly.
2016-11-08 21:39:53 +09:00
Tsuda Kageyu
e390cbac52 Update NEWS. 2016-11-08 21:17:00 +09:00
Tsuda Kageyu
253c61e37d Merge pull request #765 from TsudaKageyu/zero-length-atom
Proper handling of MP4 atoms with zero length.
2016-11-08 21:12:47 +09:00
Tsuda Kageyu
1848b3bc6f Merge pull request #759 from ufleisch/mp4_classical
Support new classical music frames introduced with iTunes 12.5, #758.
2016-11-08 21:12:31 +09:00
Tsuda Kageyu
aae23f3c07 Initialize all the data members of ID3v2::ChapterFrame. 2016-11-07 14:12:38 +09:00
Tsuda Kageyu
da9df1b2a8 Values of FILE_* macros are guaranteed in Win32. 2016-11-07 00:42:12 +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
70334edd19 Add List::swap() and Map::swap(). 2016-11-04 16:43:14 +09:00
Tsuda Kageyu
5c8cb9b86b Small fix in a comment. 2016-11-03 09:52:20 +09:00
Tsuda Kageyu
f5ca097379 Proper handling of MP4 atoms with zero length.
If the size of an atom is 0, it designates the last atom which extends to the end of the file.
2016-11-02 15:44:50 +09:00
Tsuda Kageyu
eb6d058ab9 Remove a useless branch.
longLength <= LONG_MAX is always true if sizeof(long) == sizeof(long long).
2016-11-01 16:03:15 +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
e6a69e24bc Add a common function to generate a long string to test. 2016-10-31 20:01:52 +09:00
Tsuda Kageyu
dcab8ed90e Allow ScopedFileCopy to be const. 2016-10-31 10:29:13 +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
f5ce498182 Suppress MSVC warnings about narrowing conversions. 2016-10-30 23:51:35 +09:00
Tsuda Kageyu
ee7fa78011 Update NEWS. 2016-10-30 22:51:15 +09:00
Tsuda Kageyu
873c917081 Assume that SetFilePointerEx() and GetFileSizeEx() are always available.
This drops support for Windows 9x and NT 4.0 or older.
2016-10-30 22:36:18 +09:00
Tsuda Kageyu
d3bd8fb7ff Assume that CreateFileW() is always available.
This drops support for Windows 9x.
2016-10-30 22:25:34 +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
005441faaa Prevent overflows, just in case. 2016-10-28 15:25:50 +09:00
Tsuda Kageyu
935534aa53 Backport a test from taglib2 branch. 2016-10-28 15:19:35 +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
Tsuda Kageyu
65a24bbc51 Remove some useless seek()/tell() from RIFF::File. 2016-10-28 14:22:50 +09:00
Tsuda Kageyu
711b35cc6e Encourage compilers to optimize out debug() and debugData().
It's sort of like a throwback, but I found that debug(const String &s) {} doesn't prevent a String from being constructed and the error messages from being embedded.
2016-10-28 11:19:51 +09:00
Tsuda Kageyu
d53ca6f736 Update NEWS. 2016-10-27 15:40:14 +09:00
Tsuda Kageyu
aa5f9bb221 Suppress some warnings in test. 2016-10-27 15:23:24 +09:00
Tsuda Kageyu
d2b3547254 Add a test for File::truncate(). 2016-10-27 15:15:22 +09:00
Tsuda Kageyu
06ca9a099d Check if file size <= LONG_MAX. 2016-10-27 15:10:34 +09:00
Tsuda Kageyu
8d873e4e3e Merge pull request #761 from albertofustinoni/master
WinRT compatibility
2016-10-24 22:06:35 +09:00
Alberto Fustinoni
b2fa124451 formatting 2016-10-24 21:24:53 +09:00
Alberto Fustinoni
ff5b2dc96f Whitespace 2016-10-24 21:22:57 +09:00
Alberto Fustinoni
757f5ebc96 Refactoring 2016-10-24 21:19:31 +09:00
Tsuda Kageyu
e36a9cabb9 Update NEWS. 2016-10-24 12:03:23 +09:00
Alberto Fustinoni
606f6c0e74 Better define guards 2016-10-23 23:25:16 +09:00
Alberto Fustinoni
1cc047c953 Styling 2016-10-23 20:17:49 +09:00
Alberto Fustinoni
cae4f1b804 Merge branch 'master' of https://github.com/albertofustinoni/taglib.git 2016-10-23 20:13:26 +09:00
Alberto Fustinoni
deffe83fd0 Use newer file system calls when in Windows 8+ to allow compilation as WinRT asembly 2016-10-23 12:32:16 +09:00
Tsuda Kageyu
597dcde72a Update the version to v1.11.1. 2016-10-22 02:45:52 +09:00
Tsuda Kageyu
6a96a6426a Replace a possibly non-free file in the test suite. 2016-10-22 02:11:16 +09:00
Tsuda Kageyu
69c65284a5 Update NEWS. 2016-10-22 01:06:57 +09:00
Tsuda Kageyu
97aaa0f979 Restore the ABI breakage by bringing back a removed private static variable. 2016-10-19 15:57:28 +09:00
Urs Fleisch
1b64bb0cb7 Support new classical music frames introduced with iTunes 12.5, #758.
M4A:
    ©wrk: Work (string)
    ©mvn: Movement Name (string)
    ©mvi: Movement Number (number)
    ©mvc: Movement Count (number)
    shwm: Show Work & Movement (0/1)

ID3 (2.3, 2.4; MVN, MVI for 2.2):
    MVNM: Movement Name
    MVIN: Movement Number/Count
2016-10-18 20:45:54 +02:00
Tsuda Kageyu
0dac721ce2 Update NEWS. 2016-09-26 17:48:44 +09:00
Stephen F. Booth
bbeeca6fdb Merge pull request #754 from hyperquantum/master
Fix defect in ByteVectorStream::seek when Position==End.
2016-09-15 21:11:08 -04:00
Kevin André
7e90313690 Fix defect in ByteVectorStream::seek when Position==End. 2016-09-15 16:30:16 +02: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
Tsuda Kageyu
1d3c95f692 Merge pull request #752 from evpobr/cmake-ver
Move cmake_minimum_required at the top
2016-09-12 15:56:45 +09:00
Tsuda Kageyu
8c3801f18d Merge pull request #753 from FestusHagen/fh1.m_AddBuildSharedLibsOption
Add BUILD_SHARED_LIBS option for CMake GUI.
2016-09-12 15:56:33 +09:00
Festus Hagen
c9bdd416ef Add BUILD_SHARED_LIBS option for CMake GUI. 2016-08-25 15:03:44 -04:00
evpobr
9f28e037fe Move cmake_minimum_required at the top 2016-08-20 22:37:53 +05:00
Stephen F. Booth
92c070ba9e Merge pull request #749 from jwelton/fix-typo
Fix Typo
2016-08-14 17:10:18 -04: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
Jake Welton
75e3ec73aa Change string to end offset 2016-08-14 22:02:33 +01: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
Tsuda Kageyu
3e47a036fb Update NEWS. 2016-05-14 10:46:42 +09:00
Tsuda Kageyu
9b995544e4 Fix reading table of contents frames with a lot of children. 2016-05-14 09:58:19 +09:00
Tsuda Kageyu
d8e5077961 Update NEWS. 2016-04-29 17:26:33 +09: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
6422054540 Merge pull request #739 from frgm/master
c: fix a typo
2016-04-23 06:54:59 +09:00
Svyatoslav Mishyn
1b878102f0 c: fix a typo
readble => readable
2016-04-22 16:46:15 +03:00
Tsuda Kageyu
0a85f9b227 Revert "Hide a private static variable."
This reverts commit 25ffbcb4b9.

# Conflicts:
#	taglib/mpeg/id3v2/id3v2framefactory.cpp
#	taglib/mpeg/id3v2/id3v2framefactory.h
2016-04-22 09:27:04 +09:00
Stephen F. Booth
31f3109b47 Merge pull request #732 from dirkvdb/master
Also ignore the virtual destructor warning when compiling with clang
2016-04-02 13:21:39 -04:00
Dirk Vanden Boer
76f8ff388f Also ignore the virtual destructor warning when compiling with clang 2016-03-20 20:33:04 +01:00
Tsuda Kageyu
7627ae48ed Change some static_casts to dynamic_casts in test_id3v2.cpp.
static_casts are unsafe and some of following tests doesn't work well with them.
2016-03-17 22:50:34 +09:00
Tsuda Kageyu
b2a6768704 Don't stop parsing an ID3v2 SYLT frame when its description is empty. 2016-03-14 20:35:09 +09:00
Tsuda Kageyu
7d270a7e20 Update NEWS. 2016-03-10 21:38:08 +09:00
Tsuda Kageyu
bf53dc6131 Merge pull request #726 from amethystAnt/ape-keys-bug
Fixed bug #725 - changed the maximum length of an APE key to 255
2016-03-07 06:41:21 +09:00
Karel Patlejch
ff8b6a91e7 Fixed bug #725 - changed the maximum length of an APE key to 255 2016-03-06 21:15:18 +01:00
Tsuda Kageyu
1a82419872 Add myself to maintainers. 2016-03-03 10:06:51 +09:00
Tsuda Kageyu
5a3265d031 Update NEWS for v1.11 BETA 2. 2016-03-03 05:02:14 +09:00
Tsuda Kageyu
a27199b772 Support Boost iostreams library to decode compressed ID3v2 frames in additiion to zlib.
This will help Windows users build TagLib without zlib source.
2016-03-02 11:14:11 +09:00
Tsuda Kageyu
6c27a32de8 Skip a useless debug message. 2016-02-24 21:32:25 +09:00
Tsuda Kageyu
11abffc0f6 Update NEWS. 2016-02-22 23:27:46 +09:00
Tsuda Kageyu
2aea23aed2 Add some debug messages to RIFF::File, just in case. 2016-02-22 23:17:17 +09:00
Tsuda Kageyu
e8ef0e0a4b Improve the padding handling of RIFF files a bit. 2016-02-22 23:12:34 +09:00
Tsuda Kageyu
520da50bc5 Always update the global RIFF size when updating RIFF files. 2016-02-22 22:27:18 +09:00
Tsuda Kageyu
c0a909b709 Fix a broken indent. 2016-02-22 01:39:40 +09:00
Tsuda Kageyu
8d09f12847 Remove some #ifdefs and #includes no longer used. 2016-02-22 00:35:11 +09:00
Tsuda Kageyu
710166e32d Separate zlib related code rather than having several #ifdef blocks. 2016-02-21 23:16:48 +09:00
Tsuda Kageyu
01054009ac Make the code in ByteVector::append() a bit more clearer. 2016-02-21 00:43:33 +09:00
Tsuda Kageyu
7d8aa7b8bd ByteVector::append() can't take the vector itself. 2016-02-20 19:42:46 +09:00
Tsuda Kageyu
98a57744c3 Add some tests for ByteVector::replace(). 2016-02-20 11:50:47 +09:00
Tsuda Kageyu
8c4b484e67 Fix a possible out-of-bounds access in SynchData::decode().
This also avoids an extra memory copy.
2016-02-19 20:58:09 +09:00
Tsuda Kageyu
2166d703e0 Small fix in style. 2016-02-18 14:34:16 +09:00
Tsuda Kageyu
887f3b28e5 Add a TODO comment in ByteVector::replace(). 2016-02-18 14:29:17 +09:00
Tsuda Kageyu
6a9db50c03 Revert "Remove more useless inline specifiers."
This reverts commit dadfe79799.
2016-02-18 03:51:42 +09:00
Tsuda Kageyu
07d95e0dc0 Add an overload of ByteVector::replace() which takes chars.
Currently, this is only way of using ByteVector::replace().
2016-02-18 03:47:02 +09:00
Tsuda Kageyu
a9acca5d81 Decode unsynchronized ID3v2 frames efficiently.
It makes a great difference when decoding huge unsynchronized ID3v2 frames.
2016-02-18 03:07:38 +09:00
Tsuda Kageyu
dadfe79799 Remove more useless inline specifiers.
They are no longer needed since the unnamed namespaces have solved the ODR violation.
2016-02-17 22:06:36 +09:00
Tsuda Kageyu
552185a8b8 Cast the parameters of boost::endian::endian_reverse(), just in case. 2016-02-16 20:35:27 +09:00
Tsuda Kageyu
46eacaeba4 Inline functions had better have internal linkages.
This also removes useless inline specifiers.
2016-02-15 20:53:27 +09:00
Tsuda Kageyu
455e827e1e Explicitly set a false flag in ConfigureChecks.cmake. 2016-02-15 02:18:42 +09:00
Tsuda Kageyu
c08e0b1357 Reorganize some redundant or missing tests. 2016-02-15 01:49:23 +09:00
Tsuda Kageyu
f3016c0892 Enable Boost Endian library again.
It should be detected properly now.
2016-02-15 01:36:17 +09:00
Tsuda Kageyu
f8f7cb0904 Update NEWS. 2016-02-15 00:26:41 +09:00
Tsuda Kageyu
d037b8c908 Make sure we don't write UTF8 or UTF16BE to ID3v2.3 tags. 2016-02-15 00:22:18 +09:00
Tsuda Kageyu
c349ba3a31 Add OS X settings to travis.yml. 2016-02-14 03:29:03 +09:00
Tsuda Kageyu
bb006e41d7 Disable Boost Endian library for now.
It's not detected properly depending on the environment.
2016-02-14 03:17:37 +09:00
Tsuda Kageyu
ab2267f9aa Find Boost properly.
check_cxx_source_compiles() depends on the Visual Studio settings.
2016-02-14 01:53:02 +09:00
Tsuda Kageyu
73662037eb Merge branch 'master' of https://github.com/taglib/taglib 2016-02-11 20:53:22 +09:00
Tsuda Kageyu
aa339eba87 Fix a wrong test for base64 decoding. 2016-02-11 20:47:55 +09:00
Scott Wheeler
45a3bdb695 Properly mark functions as virtual 2016-02-10 11:08:46 +00:00
Tsuda Kageyu
5a155ef4ce Fix memory leaks when saving Ogg files. 2016-02-07 04:46:40 +09:00
Tsuda Kageyu
184a151d41 Add some missing FileRef tests. 2016-02-06 21:56:51 +09:00
Tsuda Kageyu
cc2ccbc20c Test if FileRef chooses a correct File type. 2016-02-06 21:32:03 +09:00
Tsuda Kageyu
fa46185ca4 Add a supplementary note to a comment. 2016-02-06 21:14:12 +09:00
Tsuda Kageyu
fffff35ca5 Correct the license information. 2016-02-06 01:27:36 +09:00
Tsuda Kageyu
31894f47f6 Fix another typo in NEWS. 2016-02-05 19:57:09 +09:00
Tsuda Kageyu
c1e3d65b68 Fix a typo in NEWS 2016-02-05 10:53:56 +09: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
a8ecbbaef4 Update NEWS. 2016-02-03 20:33:13 +09:00
Tsuda Kageyu
24575aab23 Remove strnlen() since some compilers lack it. 2016-02-03 20:21:04 +09:00
Tsuda Kageyu
c04b24a2f5 More efficient handling of broken APE item keys.
This also improves the performance when handling intact APE items.
2016-02-03 01:08:16 +09:00
Tsuda Kageyu
013fbbf22c APE::Tag::addValue() may append a string to non-text items. 2016-02-02 00:42:08 +09:00
Tsuda Kageyu
5350bc8501 Oops! We already have a function to check APE item keys. 2016-02-01 22:46:08 +09:00
Tsuda Kageyu
92a1a00624 APE item keys should be ASCII between 0x20 and 0x7E, not UTF-8. 2016-02-01 22:19:43 +09:00
Tsuda Kageyu
8afbf6c92a Update NEWS. 2016-01-30 11:13:32 +09:00
Tsuda Kageyu
9976155aa9 Ignore 'fact' chunk of WAV files if their format is PCM.
TagLib reports wrong length of some PCM files with a 'fact' chunk.
2016-01-30 00:51:28 +09:00
Tsuda Kageyu
c2cb9ab8b0 Update NEWS with the specific release date. 2016-01-28 13:31:22 +09:00
Tsuda Kageyu
758b7e39ce Update the version to v1.11. 2016-01-28 13:17:56 +09:00
Tsuda Kageyu
4ba7bb5a8a Reorganize NEWS to put new features first. 2016-01-28 12:13:18 +09:00
Tsuda Kageyu
0b62ba1530 Remove the body of deprecated function Ogg::Page::getCopyWithNewPageSequenceNumber(). 2016-01-28 12:00:27 +09:00
Tsuda Kageyu
fe92f3dffe Add a test for broken MPEG audio frames. 2016-01-09 13:30:00 +09:00
Tsuda Kageyu
b8e82a7775 Amend an outdated comment. 2016-01-09 10:15:42 +09:00
Tsuda Kageyu
3dc873b7d0 Check if two consecutive MPEG audio frames are consistent.
This fixes reading the audio properties of some MP3 files reported by a Kodi user.
This is basically the same check as FFmpeg does.
2016-01-08 20:08:04 +09:00
Tsuda Kageyu
1254534ed4 Another workaround for broken MPEG headers. 2016-01-08 02:30:17 +09:00
Tsuda Kageyu
7a5fb7d672 Revert some unnecessary changes. 2016-01-08 02:22:44 +09:00
Tsuda Kageyu
5b7ee5bc1a Initialize all the private data members. 2016-01-08 01:57:18 +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
815d1583e9 Avoid repeating insert() operations in Ogg::File. 2016-01-06 17:57:37 +09:00
Tsuda Kageyu
6c183a7df8 Update NEWS. 2016-01-06 17:43: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
8d5f821b16 Merge pull request #689 from TsudaKageyu/save-ogg
Fix a segfault when saving an Ogg file repeatedly.
2016-01-06 09:46:35 +09:00
Tsuda Kageyu
0611744171 Merge pull request #706 from TwoFX/master
Remove "FORCE" in CMake path specifications to allow installation to a non-standard directory structure
2016-01-05 13:20:28 +09:00
Markus Himmel
c25e0c6ead Remove "FORCE" in CMake path specifications to allow installation to a
non-standard directory structure.
2015-12-29 10:29:58 +01:00
Tsuda Kageyu
45762d20f1 Fix a silly mistake. 2015-12-25 16:52:26 +09:00
Tsuda Kageyu
67434aa7b4 Merge pull request #705 from TsudaKageyu/mpeg-invalid-frame
More robust checks for invalid MPEG frame headers. (again)
2015-12-25 08:58:06 +09:00
Tsuda Kageyu
cb23f91c98 Merge branch 'master' of https://github.com/dukeyin/taglib into dukeyin-master
# Conflicts:
#	tests/test_id3v2.cpp
2015-12-24 13:47:55 +09:00
Tsuda Kageyu
37c4d0b11d Update NEWS. 2015-12-24 09:43:21 +09:00
Tsuda Kageyu
626d13467e Merge pull request #701 from TsudaKageyu/flac-strip
Enable FLAC::File to remove non-standard tags.
2015-12-24 09:41:48 +09:00
Tsuda Kageyu
02eac18d00 Fix a segfault when saving an Ogg file repeatedly.
This also reduces memory usage when reading/writing Ogg files.
Especially, it stops holding an entire file when renumbering Ogg pages.
2015-12-24 08:58:56 +09:00
Tsuda Kageyu
4064b34eff A bit more tolerant check for the MPEG frame length. 2015-12-22 20:39:58 +09:00
Tsuda Kageyu
22708a0af6 Add some supplementary comments. 2015-12-22 17:06:40 +09:00
Tsuda Kageyu
12da0ebd6d Amend a vague comment and debug message. 2015-12-22 15:18:53 +09:00
Tsuda Kageyu
d13a3e3e16 Update NEWS. 2015-12-22 15:11:21 +09:00
Tsuda Kageyu
e8b28a0466 Merge pull request #703 from inizan-yannick/master
Fix .pc file configuration.
2015-12-22 15:07:27 +09:00
Tsuda Kageyu
081d6eaf76 More robust checks for invalid MPEG frame headers. (again) 2015-12-22 14:57:23 +09:00
Tsuda Kageyu
ac361c7692 Unify some duplicate internal functions. 2015-12-22 11:49:55 +09:00
Yannick Inizan
d7de3983d9 Fix .pc file configuration. 2015-12-21 22:25:49 +01: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
1aca1f64fe Enable FLAC::File to remove non-standard tags. 2015-12-21 15:42:41 +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
5a1f44d166 Avoid the risk of subtracting between signed and unsigned types. 2015-12-21 14:29:59 +09:00
Tsuda Kageyu
130654316b Backport some comments from tablib2 branch. 2015-12-21 13:54:02 +09:00
Tsuda Kageyu
5cd139a578 Small fix in style. 2015-12-21 13:34:48 +09:00
Tsuda Kageyu
dd2ed47703 Avoid an implicit const cast. 2015-12-21 13:06:43 +09:00
Tsuda Kageyu
d0238ba82f Avoid the risk of subtracting between signed and unsigned types. 2015-12-21 11:44:25 +09:00
Tsuda Kageyu
cf5d431d77 Remove an unused private data member. 2015-12-21 10:49:46 +09:00
Tsuda Kageyu
4ec264b6a1 Update NEWS. 2015-12-21 10:05:05 +09:00
Tsuda Kageyu
ef92ee223f Merge pull request #699 from TsudaKageyu/flac-duplicate-comments
Remove duplicate Vorbis comment blocks when saving a FLAC file.
2015-12-21 10:03:14 +09:00
Tsuda Kageyu
8b6bcf411a Update NEWS. 2015-12-18 13:54:47 +09:00
Tsuda Kageyu
aa66b0651d Merge pull request #688 from TsudaKageyu/save-wv
Fix saving WavPack files.
2015-12-18 13:52:54 +09:00
Tsuda Kageyu
7c5d1e02de Update NEWS. 2015-12-18 09:03:31 +09:00
Tsuda Kageyu
6d27a1013d Merge pull request #687 from TsudaKageyu/save-mpc
Fix saving MPC files.
2015-12-18 09:00:45 +09:00
Tsuda Kageyu
50711f4758 Update NEWS. 2015-12-17 16:59:28 +09:00
Tsuda Kageyu
6998be94f6 Merge pull request #686 from TsudaKageyu/save-ape
Fix saving APE files.
2015-12-17 16:57:24 +09:00
Tsuda Kageyu
862952bdcc Remove unnecessary private data members from TrueAudio::File. 2015-12-17 11:43:11 +09:00
Tsuda Kageyu
f0b0b736e3 Update NEWS. 2015-12-17 11:26:45 +09:00
Tsuda Kageyu
546870d83a Merge pull request #684 from TsudaKageyu/save-mpeg
Fix saving MPEG files.
2015-12-17 11:24:25 +09:00
Tsuda Kageyu
581e58585a Amend a comment that refers to a deprecated function. 2015-12-16 13:39:22 +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
36b905670c Replace TagLib::uint with unsinged int. 2015-12-16 12:59:43 +09:00
Tsuda Kageyu
42459fe457 Update NEWS. 2015-12-16 11:49:55 +09:00
Tsuda Kageyu
fc571e5150 Merge pull request #683 from TsudaKageyu/save-mp4
Fix saving MP4 files.
2015-12-16 11:48:52 +09:00
Tsuda Kageyu
5480458dfc Change a method name of XiphComment to make it consistent with other method. 2015-12-16 11:00:13 +09:00
Tsuda Kageyu
9950fca3c2 Remove duplicate Vorbis comment blocks when saving a FLAC file. 2015-12-16 10:00:08 +09:00
Tsuda Kageyu
63e838f831 Make use of List iterators and setAutoDelete() in FLAC::File. 2015-12-15 15:31:33 +09:00
Tsuda Kageyu
94f28b4fa1 Update NEWS. 2015-12-15 15:18:07 +09:00
Tsuda Kageyu
680784c7b7 Merge pull request #682 from TsudaKageyu/save-flac
Fix saving FLAC files.
2015-12-15 15:08:14 +09:00
Tsuda Kageyu
5d517127ae Merge pull request #698 from TsudaKageyu/mpeg-header-check
More robust checks for invalid MPEG frame headers.
2015-12-15 10:11:13 +09:00
Tsuda Kageyu
be9b5cc93a More robust checks for invalid MPEG frame headers. 2015-12-08 11:20:51 +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
847eec23cf Fix careless copy-and-paste code. 2015-12-04 14:29:26 +09:00
Tsuda Kageyu
9dfb3fe452 Update NEWS. 2015-12-04 14:15:51 +09:00
Tsuda Kageyu
a013c7c4c2 Merge pull request #694 from FestusHagen/fh1.m_NoSharedLibTests
Disable tests with a shared library.
2015-12-04 11:41:44 +09:00
Festus Hagen
62ec63b039 Disable tests with a shared library. 2015-12-03 15:04:37 -05:00
Tsuda Kageyu
52d3122e9e Remove some unused private data members. 2015-12-03 16:55:05 +09: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
24f220224d Move a test to the proper place.
The test is actually for XiphComment, not Vorbis::File.
2015-12-03 13:05:18 +09:00
Tsuda Kageyu
a1ac23530e Simpler conversion from bits to bytes. 2015-12-03 12:34:54 +09:00
Tsuda Kageyu
e99910dd74 Revert some ABI breaking changes. 2015-12-03 10:06:04 +09:00
Tsuda Kageyu
88ad2843f4 Small cosmetic fixes. 2015-12-03 02:25:16 +09:00
Tsuda Kageyu
a0b8683656 Use a standard type rather than TagLib::uint.
This won't break the ABI compatibility.
2015-12-03 02:15:41 +09:00
Tsuda Kageyu
085a0ef298 Use a standard type rather than TagLib::ulong.
This won't break the ABI compatibility.
2015-12-03 00:03:06 +09:00
Tsuda Kageyu
363c471a2d Small cosmetic fixes. 2015-12-02 23:21:23 +09:00
Tsuda Kageyu
7f8efec4d4 Merge pull request #545 from FestusHagen/fh1.m_TDRC
Append TIME to TDRC, adjusted test_id3v2.cpp as appropriate.
2015-12-02 21:11:53 +09:00
Tsuda Kageyu
dcc0fe553c Use a standard type rather than TagLib::ushort.
This won't break the ABI compatibility.
2015-12-02 18:59:45 +09:00
Tsuda Kageyu
8bdddaabce Use a standard type rather than TagLib::uchar.
This won't break the ABI compatibility.
2015-12-02 18:11:52 +09:00
Tsuda Kageyu
2cb89b85c9 Make use of List iterators and setAutoDelete() in XiphComment. 2015-12-02 17:33:11 +09:00
Tsuda Kageyu
e6e9ba6094 Fix saving FLAC files.
This fixes all the issues reported at #622.
2015-12-02 17:21:12 +09:00
Tsuda Kageyu
7b854c5434 Update NEWS. 2015-12-02 15:01:10 +09:00
Tsuda Kageyu
1529af7a12 Merge branch 'xiph-picture' of https://github.com/gogglesmm/taglib into gogglesmm-xiph-picture
# Conflicts:
#	tests/test_bytevector.cpp
#	tests/test_ogg.cpp
2015-12-02 14:59:50 +09:00
Tsuda Kageyu
e475e31e0d Update NEWS. 2015-12-02 14:28:41 +09:00
Tsuda Kageyu
ea55c8b5c1 Merge branch 'cmake-allow-BUILD_SHARED_LIBS-to-drive-ENABLE_STATIC' of https://github.com/tSed/taglib into tSed-cmake-allow-BUILD_SHARED_LIBS-to-drive-ENABLE_STATIC
# Conflicts:
#	CMakeLists.txt
#	examples/CMakeLists.txt
2015-12-02 14:21:58 +09:00
Tsuda Kageyu
bc8b60ea46 Remove an unreachable statement. 2015-12-02 14:08:20 +09:00
Tsuda Kageyu
83ffc87598 Surround some internal stuff by anonymous namespaces. 2015-12-02 12:00:43 +09:00
Tsuda Kageyu
d97292c593 Amend some comments refer to the 'offset_t' type. It no longer exists. 2015-12-02 11:36:54 +09:00
Tsuda Kageyu
060a50ab11 Use a standard type rather than TagLib::wchar.
This won't break the ABI compatibility.
2015-12-02 11:30:29 +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
6966be4292 Use a standard type rather than TagLib::ulonglong.
TagLib::ulonglong is not used in the public headers, so the changes are trivial.
2015-12-02 09:13:10 +09:00
Lukáš Lalinský
f38749aacf Merge pull request #690 from stefansaraev/pkgconfig
fix pkgconfig file for cross compiling
2015-12-01 16:47:47 +01: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
b4b16fd7e0 Merge pull request #691 from FestusHagen/fh1.m_ushortAmbiguities
Silence ushort ambiguity errors
2015-12-01 00:02:25 +09:00
Festus Hagen
b1c67fc5dc Silence ushort ambiguity errors 2015-11-30 08:09:08 -05:00
Stefan Saraev
90f1f03163 fix pkgconfig file for cross compiling 2015-11-30 14:14:10 +02:00
Tsuda Kageyu
101a330d55 The new test wasn't called. 2015-11-30 18:32:49 +09:00
Tsuda Kageyu
59088096e6 Add some tests for M4V files. 2015-11-30 17:18:50 +09:00
Tsuda Kageyu
d1ceffd1f0 Merge branch 'm4v' of https://github.com/videolabs/taglib into videolabs-m4v
# Conflicts:
#	taglib/fileref.cpp
2015-11-30 17:12:03 +09:00
Tsuda Kageyu
eb6542bc8b Unify some duplicate internal functions. 2015-11-30 16:35:37 +09:00
Tsuda Kageyu
bccd57a470 Add const to an unchanged data member. 2015-11-30 16:21:58 +09:00
Tsuda Kageyu
a6701ddcda Remove some private data members not needed to belong to private classes. 2015-11-30 15:43:18 +09:00
Tsuda Kageyu
31d1f11969 Use a const pointer to initialize a const pointer. 2015-11-30 15:00:32 +09:00
Tsuda Kageyu
f9e558eef5 Avoid trying to remove tag chunks when an AIFF file doesn't have an ID3v2 tag. 2015-11-30 14:17:26 +09:00
Tsuda Kageyu
fcdf7c2ae2 Add some tests to check if the internal flags are updated when writing WAV files. 2015-11-30 13:46:43 +09:00
Tsuda Kageyu
8c424badad Avoid writing an empty ID3v2 tag in an AIFF file. 2015-11-30 13:42:25 +09:00
Tsuda Kageyu
f1b683b582 Remove some private data members not needed to be carried. 2015-11-30 13:09:11 +09:00
Tsuda Kageyu
5e37f0101d Remove some private data members not needed to be carried. 2015-11-30 12:53:52 +09:00
Tsuda Kageyu
b541ec8b68 Remove some private data members not needed to be carried. 2015-11-30 12:35:29 +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
1fa677e2ef Add some tests about splitting/merging Ogg pages. 2015-11-29 01:57:15 +09:00
Festus Hagen
463e8f313a Append TIME to TDRC, adjusted test_id3v2.cpp as appropriate. 2015-11-27 17:54:20 -05:00
Tsuda Kageyu
8130b30397 Close temporary files regardless if the tests are successful or not.
delete statements are skipped when assertions fail.
2015-11-27 15:20:16 +09:00
Tsuda Kageyu
6b836c6ba7 Add ENABLE_CCACHE build option to allow users opt in to use ccache. 2015-11-27 12:15:03 +09:00
Tsuda Kageyu
f5a3f2b6c1 Update NEWS. 2015-11-27 09:37:29 +09:00
Tsuda Kageyu
4b8e39e8f0 Merge branch 'fh1.m_AddBuildBindingsOption' of https://github.com/FestusHagen/taglib into FestusHagen-fh1.m_AddBuildBindingsOption
# Conflicts:
#	CMakeLists.txt
2015-11-27 09:35:13 +09:00
Tsuda Kageyu
905bf89e66 Fix saving WavPack files.
This fixes the issue reported at #624.
2015-11-27 09:30:03 +09:00
Tsuda Kageyu
67cbf2c0a8 Silence a GCC warning in tests about ignoring a return value. 2015-11-27 02:45:33 +09:00
Tsuda Kageyu
3f84621d58 Small cleanups in CMakeLists.txt. 2015-11-27 02:27:24 +09:00
Tsuda Kageyu
083eadec60 Fix saving MPC files.
This fixes the issue reported at #624.
2015-11-27 00:53:03 +09:00
Tsuda Kageyu
f180445be5 Fix saving APE files.
This fixes the issue reported at #624.
2015-11-27 00:22:07 +09:00
Tsuda Kageyu
cbc279b899 Merge pull request #685 from g-coder/patch-2
Added ccache support for faster compilation
2015-11-26 20:03:17 +09:00
g-coder
e1bcb101f0 Update CMakeLists.txt 2015-11-26 15:51:42 +05:30
g-coder
14f3b6c928 Added ccache support for faster compilation
ccache is a compiler cache. It speeds up recompilation by caching previous compilations and detecting when the same compilation is being done again. It provides support for C/C++ languages.
It makes compilation fast if it is available on the machine.
https://ccache.samba.org/
2015-11-26 15:12:23 +05:30
Tsuda Kageyu
b6361ddde5 Fix saving MPEG files.
This fixes all the issues reported at #618.
2015-11-25 01:56:07 +09:00
Tsuda Kageyu
66dd0b8a6f Small cosmetic fixes. 2015-11-25 00:12:18 +09:00
Tsuda Kageyu
94b7828990 Fix saving MP4 files.
This fixes the issue reported at #619.
2015-11-24 23:41:10 +09:00
Tsuda Kageyu
fa4289e044 Fix instance references to a static member function. 2015-11-24 16:36:50 +09:00
Tsuda Kageyu
3612c2cc24 Small cosmetic fix. 2015-11-24 15:45:38 +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
477aba9465 Merge pull request #676 from TsudaKageyu/string-hide-private
Hide private things from a public header.
2015-11-23 17:48:06 +09:00
Tsuda Kageyu
a640074a21 Hide some private functions from a public header. 2015-11-23 03:26:38 +09:00
Tsuda Kageyu
25ffbcb4b9 Hide a private static variable.
This is so-called Scott Mayers' singleton pattern.
2015-11-23 01:32:12 +09:00
Tsuda Kageyu
e44de9f37f Remove duplicate tags when saving AIFF files.
Just the same way as WAV already does.
2015-11-22 21:03:33 +09:00
Tsuda Kageyu
2b7d6fef47 Reduce redundant ref()/deref() operations. 2015-11-22 20:11:08 +09:00
Tsuda Kageyu
ae633105d6 Fix an instance reference to a static data member. 2015-11-22 19:43:17 +09:00
Tsuda Kageyu
6978131d22 Silence some GCC warnings about no return statement. 2015-11-22 18:42:49 +09:00
Tsuda Kageyu
83a0bc3710 Avoid using obsolete XiphComment::removeField(). 2015-11-22 18:30:56 +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
6477132301 Update NEWS. 2015-11-22 16:23:53 +09:00
Tsuda Kageyu
559c6b28c9 Merge pull request #681 from TsudaKageyu/xiph-remove-fields
Add alternative methods to XiphComment::removeField() that may cause …
2015-11-22 16:19:15 +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
e9f70a59b2 Merge branch 'genversion' of https://github.com/ufleisch/taglib into ufleisch-genversion
# Conflicts:
#	CMakeLists.txt
2015-11-22 10:38:35 +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
f34d73d319 Make FileRef::FileTypeResolver work properly. 2015-11-21 18:29:41 +09:00
Tsuda Kageyu
ef3ce1e38a Style fixes in fileref.cpp. 2015-11-21 17:06:26 +09:00
Tsuda Kageyu
8724184d56 Fix a typo in a comment. 2015-11-21 10:32:32 +09:00
Tsuda Kageyu
61dabe61a7 Update NEWS. 2015-11-21 10:30:48 +09:00
Tsuda Kageyu
de0fc83066 Style fixes in fileref.cpp. 2015-11-21 10:29:37 +09:00
Tsuda Kageyu
c3807e59cd Merge pull request #528 from chouquette/master
FileRef: Allow an IOStream to be used
2015-11-21 09:51:03 +09:00
Tsuda Kageyu
b592f78238 Unify common functions for finding tags.
Several classes have exactly identical functions for finding tags.
This also hides the functions from public headers.
2015-11-21 09:30:04 +09:00
Tsuda Kageyu
84e3582332 Add alternative methods to XiphComment::removeField().
Using XiphComment::removeField() may lead to a linkage error, however we can't fix the method itself without breaking the ABI or changing its behavior.
So we added some alternative method and marked the old one deprecated.
2015-11-20 23:28:32 +09:00
Tsuda Kageyu
ce1c03faa3 Update NEWS. 2015-11-20 23:08:43 +09:00
Tsuda Kageyu
94c941928a Merge pull request #654 from TsudaKageyu/xiph-setcomment
Fix XiphComment::setComment() for the case that a Vorbis comment has …
2015-11-20 23:02:51 +09:00
Tsuda Kageyu
8c6fe45453 Avoid using String::null where an empty string is required.
String::null is not necessarily be empty or remains the same instance.
Using it in a public header may lead to a linkage error.
2015-11-20 22:21:47 +09:00
Tsuda Kageyu
c4fe65787c Avoid using String::isNull() where it is considered to be confused with isEmpty(). 2015-11-20 20:59:13 +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
29b0568dec Revert "Add a test about handing "COMMENT" and "DESCIPRION" fields in XiphComment."
This reverts commit 8f147034d6.
2015-11-20 14:18:40 +09:00
Tsuda Kageyu
7d0a651f3e Revert "Use always "COMMENT" field when updating XiphComment."
This reverts commit ba5137bf2d.
2015-11-20 14:18:23 +09:00
Tsuda Kageyu
224f133d65 Merge pull request #643 from TsudaKageyu/save-asf
Avoid writing duplicate tags when saving ASF files.
2015-11-20 13:52:33 +09:00
Tsuda Kageyu
f956c89141 Remove a warning from a comment and update NEWS. 2015-11-20 13:48:51 +09:00
Tsuda Kageyu
6dc8d701a8 Avoid writing duplicate tags when saving ASF files.
Reduce memory reallocations and copies when saving ASF files.
2015-11-20 13:48:25 +09:00
Tsuda Kageyu
779f904940 Update NEWS. 2015-11-20 13:35:07 +09:00
Tsuda Kageyu
4161746d89 Update NEWS. 2015-11-20 13:25:28 +09:00
Tsuda Kageyu
6d5654028a Merge pull request #642 from TsudaKageyu/strip-and-properties
Fix segfaults when calling File::properties() after strip().
2015-11-20 13:24:01 +09:00
Tsuda Kageyu
93d55dafd6 Update NEWS. 2015-11-20 10:50:21 +09:00
Tsuda Kageyu
e1e1b6c60c Merge pull request #623 from TsudaKageyu/erase-duplicate-id3v2
Skip duplicate ID3v2 tags and treat them as an extra blank of the first one.
2015-11-20 10:49:11 +09:00
Tsuda Kageyu
1cc3e4cc57 Consistent rounding when calculating the MP4 audio length. 2015-11-19 18:24:20 +09:00
Tsuda Kageyu
f310b1810d Update NEWS. 2015-11-19 17:55:18 +09:00
Tsuda Kageyu
e10684312e Efficient lookup for an ID3v2 tag in a MPEG file.
An ID3v2 tag or MPEG frame is most likely be at the beginning of the file.
2015-11-19 17:31:51 +09:00
Tsuda Kageyu
a3564d8c68 Efficient lookup for the MP4/ASF field name and ID3v1 genre tables.
Linear lookup is much faster and memory efficient when an array is very small.
2015-11-19 16:35:55 +09:00
Tsuda Kageyu
95ef0e7882 Add some tests for String::toInt() with too large values. 2015-11-19 14:52:02 +09:00
Tsuda Kageyu
13a258d9ed Backport shorter versions of some functions from taglib2. 2015-11-19 14:45:36 +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
72a807def1 Fix a string conversion bug in tag_c.cpp. 2015-11-19 11:50:39 +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
539d951277 Avoid using ByteVector::null where an empty vector is required.
ByteVector::null is not necessarily be empty or remains the same instance.
Using it in a public header may lead to a linkage error.
2015-11-19 10:52:46 +09:00
Tsuda Kageyu
21788f4a26 Efficient lookup for the ID3v2 frame ID table.
Linear lookup is much faster and memory efficient when an array is very small.
2015-11-19 10:07:10 +09:00
Tsuda Kageyu
74cb6f3fc7 Merge pull request #493 from TsudaKageyu/nested-refcounter
Simplify overly complicated ByteVector::mid() implementation.
2015-11-19 09:37:40 +09:00
Tsuda Kageyu
e0f1151c5c Resolve some conflicts before merging. 2015-11-19 09:27:15 +09:00
Tsuda Kageyu
10e1fcd686 Consistent notations between ByteVector::data() and at(). 2015-11-19 09:23:20 +09:00
Tsuda Kageyu
3bce77a359 Use linear search instead of the Knuth-Morris-Pratt algorithm in ByteVector::find().
In almost all cases, it handles too small data for KMP to work effectively.
2015-11-19 09:23:19 +09:00
Tsuda Kageyu
0ffd2e8ab9 Replace DATA macro with more straightforward notations. 2015-11-19 09:23:19 +09:00
Tsuda Kageyu
7e85d9b202 Simplify overly complicated ByteVector::mid() implementation.
Especially remove the useless nested RefCounters.
2015-11-19 09:23:19 +09:00
Tsuda Kageyu
c6443dabc6 Use the same type name between a List and its iterator. 2015-11-18 17:58:13 +09:00
Tsuda Kageyu
da7424636b Fix a mismatch between List and iterator types. 2015-11-18 17:50:48 +09:00
Tsuda Kageyu
c5db39fbf4 Merge pull request #661 from ufleisch/podcast-frames
Support for Apple podcast frames
2015-11-18 17:48:14 +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
b6469bda1a Merge pull request #628 from RyanLucchese/rl-ConstReverseIterator-solaris-bug
return const correct reverse iterator for newer Sun compiler
2015-11-18 17:23:16 +09:00
Tsuda Kageyu
978a5f0a27 Merge pull request #629 from RyanLucchese/rl-fix-class-instantiation-solstudio
check SUNPRO_CC version before using Map workaround
2015-11-18 17:22:25 +09:00
Tsuda Kageyu
8203ccf04c Merge pull request #608 from TsudaKageyu/mp4-has-tags
Add a method to check if an MP4 file on disk actually has a tag.
2015-11-18 17:14:26 +09:00
Tsuda Kageyu
47860c20f4 Make use of List iterators. 2015-11-18 17:06:49 +09:00
Tsuda Kageyu
6e6e11f21a Use List::isEmpty() rather than size() to check if the list is empty.
std::list::empty() is guaranteed to be an O(1) operation.
2015-11-18 16:57:41 +09:00
Tsuda Kageyu
288e97ad44 Make use of List iterators. 2015-11-18 16:38:30 +09:00
Tsuda Kageyu
07b26ab3e4 Make use of List iterators and setAutoDelete(). 2015-11-18 15:29:04 +09:00
Tsuda Kageyu
0f00dfc778 Add a comment to List::isEmpty(). 2015-11-18 15:14:50 +09:00
Tsuda Kageyu
b01fecd280 Separate some tests for MP4::File::hasMP4Tag(). 2015-11-18 14:25:22 +09:00
Tsuda Kageyu
69921b8090 Amend the comment on MP4::File::hasMP4Tag(). 2015-11-18 14:17:29 +09:00
Tsuda Kageyu
1caaa8a020 Reduce duplicate code between String::ctor() and operator=().
It's safer to have only one pair of ref()/deref() than to have a several pairs.
2015-11-18 14:03:45 +09:00
Tsuda Kageyu
4f3844114a Mark some variables and functions deprecated.
ByteVector::null, ByteVector::isNull(), String::null, String::isNull() have got marked deprecated.
It's dangerous to use them, and they will be removed in taglib2.
2015-11-18 10:29:25 +09:00
Tsuda Kageyu
76de4234a1 Add a test for the CRC checksum of Ogg pages. 2015-11-17 15:05:43 +09:00
Tsuda Kageyu
4bac99e3da Add some notes about ByteVector::isNull() and ByteVector::null. 2015-11-17 13:06:03 +09:00
Tsuda Kageyu
6b7a2c4cf7 Add some notes about String::isNull() and String::null. 2015-11-17 11:41:13 +09:00
Tsuda Kageyu
1a942627bf Add String::clear() method to clear the string. 2015-11-17 11:29:52 +09:00
Tsuda Kageyu
3128f425b8 vsnprintf()/vsprintf() does not necessarily return -1 when failed. 2015-11-17 11:06:19 +09:00
Tsuda Kageyu
3f968933f4 Use std::wstring::empty() rather than size() == 0.
Depending on the implementation, empty() can be more efficient than size().
2015-11-17 10:49:30 +09:00
Tsuda Kageyu
67f44071cd Fix the usage of boost::endian::endian_reverse(). 2015-11-14 14:49:59 +09:00
Tsuda Kageyu
11fbf394a3 Skip duplicate ID3v2 tags and treat them as an extra blank of the first one.
This enables all the file formats to handle duplicate ID3v2 tags properly and erase them automatically.
2015-11-13 11:55:56 +09:00
Tsuda Kageyu
a25e1e9f90 Correct the ID3v2 padding size calculation. 2015-11-13 11:44:12 +09:00
Tsuda Kageyu
091ab9dee0 Reduce memory reallocation when rendering an ID3v2 tag.
Prevent an ID3v2 padding from being ridiculously large.
2015-11-13 11:35:37 +09:00
Tsuda Kageyu
c353a71ce5 Remove an unused private data member. 2015-11-13 11:23:27 +09:00
Tsuda Kageyu
762581fe3f Add a method to check if an MP4 file on disk actually has a tag. 2015-11-13 11:14:12 +09:00
Tsuda Kageyu
8f147034d6 Add a test about handing "COMMENT" and "DESCIPRION" fields in XiphComment. 2015-11-13 11:07:50 +09:00
Tsuda Kageyu
6775cef651 Make use of the Boost Endian library for byte swapping.
It's likely to be better at choosing the most efficient method than our CMake tests.
2015-11-13 10:58:23 +09:00
Tsuda Kageyu
86c7e905ba Silence some MSVC security warnings by replacing strdup() with _strdup().
Backported from taglib2.
2015-11-13 10:06:01 +09:00
Sander Jansen
2184aa476f xiph: preserve any picture data we can't decode in the text comments 2015-11-12 08:50:34 -06:00
Sander Jansen
3e8eff16b8 another style fix 2015-11-12 08:50:34 -06:00
Sander Jansen
41a44f4ab2 Support reading deprecated COVERART xiphcomment 2015-11-12 08:50:34 -06:00
Sander Jansen
70e471f1d1 Check if saved picture can be read back correctly 2015-11-12 08:50:34 -06:00
Sander Jansen
f836cb4dea Two more spaces 2015-11-12 08:50:34 -06:00
Sander Jansen
47bd01ecda Minor style fixes 2015-11-12 08:50:34 -06:00
Sander Jansen
90ad17b4c5 Additional unit tests for base64 encoder/decoder 2015-11-12 08:50:34 -06:00
Sander Jansen
f4c1beb161 Make fromBase64 more strict and update code to follow taglib coding style 2015-11-12 08:50:34 -06:00
Sander Jansen
c963d3ba04 correctly filter out invalid base64 characters 2015-11-12 08:50:34 -06:00
Sander Jansen
c4a02a1799 remove redundant size specificier in mid usage 2015-11-12 08:50:34 -06:00
Sander Jansen
59a1b7a491 add forgotten const cast 2015-11-12 08:50:34 -06:00
Sander Jansen
62bb3c95c8 Make ByteVector::fromBase64 as static member function 2015-11-12 08:50:34 -06:00
Sander Jansen
d3351a0012 Delete pictures in XiphComment destructor 2015-11-12 08:50:34 -06:00
Sander Jansen
0c14bd0ed0 Add FLAC::Picture support to Xiph Comment 2015-11-12 08:50:34 -06:00
Sander Jansen
7bbf5a2e79 add base64 encoder/decoder to bytevector 2015-11-12 08:48:00 -06:00
Tsuda Kageyu
ba5137bf2d Use always "COMMENT" field when updating XiphComment.
The recommended field name for additional comments is "COMMENT".
It's the same behavior as "DATE" or "TRACKNUMBER" field.
2015-11-12 17:37:22 +09:00
Tsuda Kageyu
b3cea6cca7 Fix XiphComment::setComment() for the case that a Vorbis comment has the "COMMENT" field. 2015-11-12 17:16:47 +09:00
Tsuda Kageyu
a533b9c665 Hide private things from a public header.
Some functions and a variable in tstring.h are not needed to be exposed in a public header.
2015-11-12 15:36:02 +09:00
Tsuda Kageyu
ec8e611909 Fix an instance reference to a static data member. 2015-11-12 14:48:24 +09:00
Tsuda Kageyu
c66e6b27d9 Small cleanups in CMakeLists.txt. 2015-11-12 14:41:15 +09:00
Tsuda Kageyu
1d379fdb2f Small cleanups in audioproperties.cpp. 2015-11-12 14:24:04 +09:00
Tsuda Kageyu
47813c5a7f A bit more accurate calculation of the AIFF audio length.
Actually, it's unlikely to improve the accuracy, but prevents a useless round-trip conversion between double and int.
2015-11-12 14:10:09 +09:00
Tsuda Kageyu
94ff9124c7 Skip both ID3v1 and APE tags when seeking the last MPEG frame. 2015-11-12 13:52:46 +09:00
Lukáš Lalinský
9f697fce8e 1.10 2015-11-11 22:41:59 +01:00
Tsuda Kageyu
320d0f5ad7 Use List::isEmpty() than size() > 0.
Small revision of pokowaka's fix. isEmpty() is a little better than size() > 0, since std::list::empty() is guaranteed to be an O(1) operation.
2015-11-06 16:13:43 +09:00
Tsuda Kageyu
77087cf865 Merge pull request #675 from garima-g/patch-1
Add self-assignment check in operator=
2015-11-05 15:43:03 +09:00
garima-g
8b4a27beb4 Add self-assignment check in operator=
Method 'operator=' should check its argument with 'this' pointer.
2015-11-05 11:19:44 +05:30
garima-g
998ebf4ce6 Add self-assignment check in operator=
Method 'operator=' should check its argument with 'this' pointer.
2015-11-05 11:16:34 +05:30
garima-g
ccaf650214 Add self-assignment check in operator=
Method 'operator=' should check its argument with 'this' pointer.
2015-11-05 11:12:24 +05:30
garima-g
9fad0b28a5 Add self-assignment check in operator=
Method 'operator=' should check its argument with 'this' pointer.
2015-11-05 11:09:20 +05:30
Lukáš Lalinský
153820bf12 Merge pull request #669 from pokowaka/bad_access
Fixes access violation
2015-10-12 14:30:00 +02:00
Erwin Jansen
29be00dc59 Fixes access violation
- Fixes access violation when setting empty stringlist on integer
  properties in mp4 tag
- Add a unit test that validates the fix.
2015-10-09 22:11:27 -07:00
Stephen F. Booth
ab30ec3a6f Merge pull request #664 from pbhd/master
add options R, I, D for replace/insert/delete of arbitrary tags
2015-09-23 23:09:55 -04:00
Peter Bauer
0a90687805 add options R, I, D for replace/insert/delete of arbitrary tags 2015-09-23 14:11:40 +02:00
Hugo Beauzée-Luyssen
e750cb491d FileRef: Allow an IOStream to be used 2015-09-15 15:01:40 +02:00
Steve Lhomme
1f7715a5da Add support for M4V tag parsing 2015-09-15 13:15:51 +02: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
Urs Fleisch
8e7504a66f Add support for ID2v2 PCST frames (podcast). 2015-09-08 20:42:30 +02:00
Hasso Tepper
9ad5bb1d62 Support for proprietary frames Apple iTunes uses to tag podcast files. 2015-09-07 20:25:34 +02:00
Maxime Leblanc
71e8915568 Fix #94: add a unified interface for pictures 2015-09-07 14:56:49 +02:00
Tsuda Kageyu
5ca4cd2f52 Revert "Small cleanups in audioproperties.cpp."
This reverts commit b49e3e5620.
2015-08-31 16:29:13 +09:00
Tsuda Kageyu
70f8fb1bae Revert "Add and fix some comments in ConfigureChecks.cmake."
This reverts commit fa6f33e552.
2015-08-31 16:28:24 +09:00
Tsuda Kageyu
030e177640 Revert "Small cleanups in CMakeLists.txt."
This reverts commit 021c539002.
2015-08-31 16:28:12 +09:00
Tsuda Kageyu
3bb0b11bff Revert "Fix an instance reference to a static data member."
This reverts commit 9666b64f28.
2015-08-31 16:21:26 +09:00
Tsuda Kageyu
60558d6a4a Revert "A bit more accurate calculation of the AIFF audio length."
This reverts commit 15a1505880.
2015-08-31 16:20:58 +09:00
Tsuda Kageyu
12f59d774e Revert "Hide an internal variable from a public header."
This reverts commit fbd3b71690.
2015-08-31 16:20:41 +09:00
Tsuda Kageyu
e2466a72f8 Revert "Skip both ID3v1 and APE tags when seeking the last MPEG frame."
This reverts commit 6d925da75e.
2015-08-31 16:20:15 +09:00
Tsuda Kageyu
9666b64f28 Fix an instance reference to a static data member. 2015-08-31 10:34:12 +09:00
Tsuda Kageyu
15a1505880 A bit more accurate calculation of the AIFF audio length. 2015-08-31 01:48:29 +09:00
Tsuda Kageyu
fbd3b71690 Hide an internal variable from a public header. 2015-08-30 01:01:34 +09:00
Tsuda Kageyu
6a76f491f8 Merge pull request #579 from TsudaKageyu/frameoffset2
Skip both ID3v1 and APE tags when seeking the last MPEG frame.
2015-08-29 00:09:14 +09:00
Tsuda Kageyu
6d925da75e Skip both ID3v1 and APE tags when seeking the last MPEG frame. 2015-08-28 17:04:15 +09:00
Tsuda Kageyu
e178875b40 Mention that String::toWString()/toCWString() doesn't return UTF-32 string. 2015-08-28 13:38:22 +09:00
Tsuda Kageyu
bf45cfd84a Check if QT_VERSION macro is defined. 2015-08-28 01:38:09 +09:00
Tsuda Kageyu
b49e3e5620 Small cleanups in audioproperties.cpp. 2015-08-27 11:29:40 +09:00
Tsuda Kageyu
fa6f33e552 Add and fix some comments in ConfigureChecks.cmake. 2015-08-26 15:05:34 +09:00
Tsuda Kageyu
021c539002 Small cleanups in CMakeLists.txt. 2015-08-26 08:14:31 +09:00
Lukáš Lalinský
aedfeba66b Missed the full version string in taglib-config.cmd.cmake 2015-08-25 20:46:11 +02:00
Lukáš Lalinský
29ed265281 Skip the patch version if it's 0 2015-08-25 17:04:34 +02:00
Tsuda Kageyu
b6adb1f108 Remove a private data member not needed to carry. 2015-08-25 11:03:00 +09:00
Tsuda Kageyu
c7231c58a3 Improve a test about handling duplicate tags in WAV files. 2015-08-25 11:03:00 +09:00
Tsuda Kageyu
c5cf9b93bc Fix segfaults when calling File::properties() after strip().
Backport TagUnion::properties() and TagUnion::removeUnsupportedProperties() from taglib2.
2015-08-25 11:03:00 +09:00
Tsuda Kageyu
1bb06b1f7a Add RIFF::WAV::File::strip() function.
Avoid saving an empty tag.
2015-08-25 11:03:00 +09: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
Lukáš Lalinský
35aa6c4e84 Update date in NEWS 2015-08-23 20:09:22 +02:00
Lukáš Lalinský
54cea3edc3 Reorganize NEWS to put new features first 2015-08-23 12:20:25 +02:00
Lukáš Lalinský
0178d47c85 Don't use const ref to an integer in ChapterFrame 2015-08-23 12:20:25 +02:00
Lukáš Lalinský
71bc17b5e6 Lalala 2015-08-23 12:20:25 +02:00
Tsuda Kageyu
ac38f4ade1 Remove an unused private data member. 2015-08-23 18:25:17 +09:00
Tsuda Kageyu
b9f898698d Revert "Remove some private data members not needed to carry."
This reverts commit 7c17d32b3a.
2015-08-23 18:21:51 +09:00
Tsuda Kageyu
bd564546f4 Fix some typos in comments. 2015-08-14 00:10:19 +09:00
Tsuda Kageyu
d90617959b Fix some typos in comments. 2015-08-11 09:45:32 +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
bc106ad81e Separate two variable initializations. 2015-08-10 00:50:13 +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
Tsuda Kageyu
a23f808627 Remove an useless #include. 2015-08-09 13:26:51 +09:00
Tsuda Kageyu
e4cd963b12 Improve a test about splitting OGG pages.
Check for #529.
2015-08-08 15:18:16 +09:00
Tsuda Kageyu
eff92fed98 Improve a test about splitting OGG pages.
Check for #529.
2015-08-07 16:47:13 +09:00
Tsuda Kageyu
80441ff754 Remove a workaround for an older version of GCC.
GLIBC's byte swap functions are a good fallback option.
2015-08-07 08:59:16 +09:00
Festus Hagen
35d5ba4eff Add BUILD_BINDINGS option, moved if(BUILD_EXAMPLES) to taglib/CMakeLists, plus some cleanup. 2015-08-06 17:26:37 -04:00
Tsuda Kageyu
edbafdbd88 Remove some redundant code from trefcounter.cpp. 2015-08-07 02:10:56 +09:00
Tsuda Kageyu
98ac8ba569 Add a comment about unused constants. 2015-08-07 02:03:03 +09:00
Tsuda Kageyu
173c58cf49 Merge pull request #580 from TsudaKageyu/negative-seek
Fix inconsistent negative seek behavior between Linux and Windows.
2015-08-07 01:32:26 +09:00
Tsuda Kageyu
ec3d050adc Merge pull request #644 from petrows/master
Install target should be checked to avoid conflicts
2015-08-07 01:20:03 +09:00
Tsuda Kageyu
19a7e45997 Merge pull request #639 from TsudaKageyu/remove-cmake-check-float
Run-time check for byte order rather than CMake check.
2015-08-07 01:17:27 +09:00
Tsuda Kageyu
49563a9cd0 Merge pull request #640 from TsudaKageyu/cmake-vsprintf
CMake check for vsprintf_s/vsnprintf rather than sprintf_s/snprintf.
2015-08-07 01:14:12 +09:00
Tsuda Kageyu
1abe61640a Merge pull request #645 from FestusHagen/fh1.m_UintAmbiguities_WavePackProperties
Silence uint ambiguity error in wavepackproperties.
2015-08-06 16:35:45 +09:00
Festus Hagen
65a6572299 Silence uint ambiguity errors in wavepackproperties. 2015-08-06 03:22:03 -04:00
Peter Petrovich
46e74c9391 Install target check fix 2015-08-05 08:45:27 +03:00
Tsuda Kageyu
7c17d32b3a Remove some private data members not needed to carry. 2015-08-05 11:54:30 +09:00
Tsuda Kageyu
bfe4ec5df5 Update NEWS.
Added support for reading the encoder information of WMA files.
Added support for reading the codec of WAV files.
Added support for multi channel WavPack files.
Added support for reading the nominal bitrate of Ogg Speex files.
Added support for VBR headers in MPEG files.
2015-08-05 02:58:45 +09:00
Tsuda Kageyu
81b7d0046e Merge branch 'master' of https://github.com/TsudaKageyu/taglib 2015-08-04 23:34:01 +09:00
Tsuda Kageyu
5990c72a01 Fix a typo in NEWS. 2015-08-04 23:27:28 +09:00
Tsuda Kageyu
018e969026 Add warnings about calling File::save() repeatedly. 2015-08-04 15:47:18 +09:00
Tsuda Kageyu
04ec7eae25 Add some supplementary comments. 2015-08-03 22:31:16 +09:00
Tsuda Kageyu
b6e7bb2c84 Update version to 1.10.0. 2015-08-03 16:14:48 +09:00
Tsuda Kageyu
f112d538ea Merge pull request #612 from TsudaKageyu/flac-id3v1
Avoid overwriting the audio stream when adding an ID3v1 tag to a FLAC…
2015-08-03 15:54:16 +09:00
Tsuda Kageyu
ac5ef0291c Update NEWS.
Fixed possible file corruptions when adding an ID3v1 tag to FLAC files.
2015-08-03 15:51:50 +09:00
Tsuda Kageyu
8fa86162c7 Add a test to check if the FLAC audio stream remains intact after adding an ID3v1 tag. 2015-08-03 15:40:30 +09:00
Tsuda Kageyu
fa17b4da6b Avoid overwriting the audio stream when adding an ID3v1 tag to a FLAC file. 2015-08-03 15:39:27 +09:00
Tsuda Kageyu
076e845912 Run-time check for integer byte order rather than CMake check.
It will easily be optimized out.
2015-08-03 13:08:58 +09:00
Tsuda Kageyu
f830177b3b Correct the order of #includes in tests. 2015-08-03 11:41:55 +09:00
Tsuda Kageyu
0650dc77a1 Fix some comments. 2015-08-02 03:24:25 +09:00
Tsuda Kageyu
c0f537a155 Merge pull request #581 from FestusHagen/fh2.m_FixUintAmbiguitiesInTests
Silence uint ambiguity errors in tests.
2015-08-02 02:40:20 +09:00
Tsuda Kageyu
44d9f2bf25 Run-time check for floating point byte order rather than CMake check.
It's safer not to use an unofficial CMake script.
2015-08-01 23:40:23 +09:00
Tsuda Kageyu
89e6ad96a4 Check for vsnprintf first. 2015-08-01 23:38:50 +09:00
Tsuda Kageyu
aa1dd0278d CMake check for vsprintf_s/vsnprintf rather than sprintf_s/snprintf. 2015-08-01 23:38:50 +09:00
Tsuda Kageyu
13dab99af0 Remove unused includes from ConfigureChecks.cmake. 2015-08-01 23:34:36 +09:00
Tsuda Kageyu
03ec83ecca Add AudioProperties::lengthInSeconds() and lengthInMilliseconds() functions to emulate virtual abstract functions. 2015-08-01 02:23:18 +09:00
Tsuda Kageyu
ce02910c6b Update NEWS.
Marked FLAC::File::streamInfoData() deprecated. It returns an empty ByteVector.
Marked FLAC::File::streamLength() deprecated. It returns zero.
2015-08-01 02:06:35 +09:00
Tsuda Kageyu
f25e30d33f Revert "Reorder CMake checks for sprintf() variants."
This reverts commit c69364d831.
2015-08-01 01:59:36 +09:00
Tsuda Kageyu
4dcccfbd6a Update NEWS.
New API for the audio length in milliseconds.
2015-08-01 01:46:35 +09:00
Tsuda Kageyu
7ca1b0c4d3 Merge pull request #575 from TsudaKageyu/chunk-offset
Stop calculating the offset in RIFF::File::chunkData().
2015-08-01 01:31:17 +09:00
Tsuda Kageyu
11f4e4e1ca Merge pull request #567 from TsudaKageyu/audioprop-wv
(wishlist) WavPack: AudioProperties improvements
2015-08-01 01:30:19 +09:00
Tsuda Kageyu
9759bd2dd7 Merge pull request #566 from TsudaKageyu/audioprop-tta
(wishlist) TrueAudio: AudioProperties improvements
2015-08-01 01:30:12 +09:00
Tsuda Kageyu
b28784538a Merge pull request #565 from TsudaKageyu/audioprop-wav
(wishlist) WAV: AudioProperties improvements
2015-08-01 01:30:03 +09:00
Tsuda Kageyu
fdea096c8d Merge pull request #564 from TsudaKageyu/audioprop-aiff
(wishlist) AIFF: AudioProperties improvements
2015-08-01 01:29:46 +09:00
Tsuda Kageyu
a9d030544a Merge pull request #563 from TsudaKageyu/audioprop-vorbis
(wishlist) Ogg Vorbis: AudioProperties improvements
2015-08-01 01:29:35 +09:00
Tsuda Kageyu
8344c4d7f8 Merge pull request #562 from TsudaKageyu/audioprop-speex
(wishlist) Ogg Speex: AudioProperties improvements
2015-08-01 01:29:22 +09:00
Tsuda Kageyu
8b1e872f81 Merge pull request #561 from TsudaKageyu/audioprop-opus
(wishlist) Ogg Opus: AudioProperties improvements
2015-08-01 01:29:13 +09:00
Tsuda Kageyu
6a778751ee Merge pull request #560 from TsudaKageyu/audioprop-mpeg
(wishlist) MPEG: AudioProperties improvements
2015-08-01 01:29:06 +09:00
Tsuda Kageyu
4328a830f9 Merge pull request #559 from TsudaKageyu/audioprop-mpc
(wishlist) MusePak: AudioProperties improvements
2015-08-01 01:27:20 +09:00
Tsuda Kageyu
ae99cbe64e Merge pull request #558 from TsudaKageyu/audioprop-mp4
(wishlist) MP4: AudioProperties improvements
2015-08-01 01:27:15 +09:00
Tsuda Kageyu
692ce897cb Merge pull request #557 from TsudaKageyu/audioprop-flac
(wishlist) FLAC: AudioProperties improvements
2015-08-01 01:27:06 +09:00
Tsuda Kageyu
0ed1c29acc Merge pull request #556 from TsudaKageyu/audioprop-asf
(wishlist) ASF: AudioProperties improvements
2015-08-01 01:26:52 +09:00
Tsuda Kageyu
3c59b7858a Merge pull request #555 from TsudaKageyu/audioprop-ape
(wishlist) APE: AudioProperties improvements
2015-08-01 01:21:59 +09:00
Tsuda Kageyu
2c9f63d9b0 Merge pull request #568 from TsudaKageyu/audioprop-mod
(wishlist) MOD: AudioProperties improvements
2015-08-01 01:04:34 +09:00
Tsuda Kageyu
0b43b7136d FLAC: Remove unused formal parameters. 2015-08-01 00:49:25 +09:00
Tsuda Kageyu
1e752a1e8f FLAC: Add debug messages to tell some functions are obsolete. 2015-08-01 00:49:23 +09:00
Tsuda Kageyu
29a31859ff FLAC: Move some public functions to above private ones. 2015-08-01 00:49:22 +09:00
Tsuda Kageyu
0b01461d50 FLAC: Avoid using deprecated functions. 2015-08-01 00:49:22 +09:00
Tsuda Kageyu
a77abedf63 Remove some more data members not needed to carry. 2015-08-01 00:49:22 +09:00
Tsuda Kageyu
21412e2ba2 FLAC: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Add bitsPerSample() property besides sampleWidth(). (#360)
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.
2015-08-01 00:49:21 +09:00
Tsuda Kageyu
dbf9644c8d WavPack: Remove unused formal parameters. 2015-08-01 00:44:41 +09:00
Tsuda Kageyu
592e14f950 TrueAudio: Remove unused formal parameters. 2015-08-01 00:41:42 +09:00
Tsuda Kageyu
1fb3727c4c WAV: Remove unused formal parameters. 2015-08-01 00:37:31 +09:00
Tsuda Kageyu
0501fbdd72 AIFF: Remove unused formal parameters. 2015-08-01 00:33:56 +09:00
Tsuda Kageyu
5235abc498 Vorbis: Remove unused formal parameters. 2015-08-01 00:30:13 +09:00
Tsuda Kageyu
d944009904 Speex: Remove unused formal parameters. 2015-08-01 00:22:09 +09:00
Tsuda Kageyu
f729f863cd Opus: Remove unused formal parameters. 2015-08-01 00:19:20 +09:00
Tsuda Kageyu
c715ec09e4 MPEG: Hide an internal function from the public header. 2015-08-01 00:15:51 +09:00
Tsuda Kageyu
4f621140ce MPEG: Remove unused formal parameters. 2015-08-01 00:09:59 +09:00
Tsuda Kageyu
bd251aed37 MusePak: Remove unused formal parameters. 2015-08-01 00:04:27 +09:00
Tsuda Kageyu
34ab65aa57 MP4: Hide an internal function from the public header. 2015-07-31 23:59:22 +09:00
Tsuda Kageyu
7f0c547ba6 MP4: Remove unused formal parameters. 2015-07-31 23:55:30 +09:00
Tsuda Kageyu
0ff38ed52b ASF: Remove unused formal parameters. 2015-07-31 23:39:58 +09:00
Tsuda Kageyu
2b1116cec1 APE: Remove unused formal parameters. 2015-07-31 23:18:50 +09:00
Tsuda Kageyu
88947e7a48 Silence some MSVC specific warnings in tests. 2015-07-31 20:55:23 +09:00
Tsuda Kageyu
5ad69a81dc Silence some MSVC2015 specific warnings. 2015-07-31 12:23:01 +09:00
Tsuda Kageyu
c9963af848 MP4 atom length is limited up to 31 bits.
32-bit value will be negative.
2015-07-31 11:24:36 +09:00
Tsuda Kageyu
f38e32163e Add some comments to tutils.h. 2015-07-31 10:27:16 +09:00
Tsuda Kageyu
c69364d831 Reorder CMake checks for sprintf() variants.
VS2015 has snprintf(), however sprintf_s() is still recommended.
2015-07-31 10:11:01 +09:00
Tsuda Kageyu
3142330bee Remove sudo from .travis.yml.
This allows our tests to run faster on the container-based infrastructure.
2015-07-31 09:06:24 +09:00
Tsuda Kageyu
9b849c5da8 Merge pull request #554 from FestusHagen/fh1.m_FriendlyCppUnitSearch
Don't look for CppUnit unless BUILD_TESTS, general cleanup.
2015-07-30 23:55:16 +09:00
Tsuda Kageyu
a197f45ca8 Merge pull request #595 from TsudaKageyu/gcc-warning-test
Silence a GCC warning about ignoring a return value in test.
2015-07-30 23:39:04 +09:00
Tsuda Kageyu
6dcecf0e71 Fix a typo in a debug message. 2015-07-30 23:36:44 +09:00
Tsuda Kageyu
47800d1000 Merge pull request #625 from TsudaKageyu/checksum-comment
(minor, comment only) Add a supplementary comment to ByteVector::checksum().
2015-07-30 23:30:43 +09:00
Tsuda Kageyu
cc8c3cd1fd Merge pull request #617 from TsudaKageyu/useless-call
Remove an useless function call.
2015-07-30 23:30:18 +09:00
Tsuda Kageyu
58994e330e Update NEWS.
Fixed reading FLAC files with zero-sized padding blocks.
2015-07-30 22:03:02 +09:00
Tsuda Kageyu
572afd437d Merge pull request #638 from TsudaKageyu/update-news
Update NEWS.
2015-07-30 22:00:00 +09:00
Tsuda Kageyu
1eef4177e7 Merge pull request #637 from TsudaKageyu/flac-zero-sized-padding
Make FLAC::File tolerant to zero-sized padding blocks.
2015-07-30 21:58:42 +09:00
Tsuda Kageyu
64fac517ed Update NEWS. 2015-07-30 10:03:47 +09:00
Tsuda Kageyu
f79c766ba4 Avoid creating zero-sized padding blocks. 2015-07-29 23:05:17 +09:00
Tsuda Kageyu
6f944b0291 Make FLAC::File tolerant to zero-sized padding blocks. 2015-07-29 20:52:56 +09:00
Ryan Lucchese
04bee3faec added comments explaining ByteVector::rbegin() const and ByteVector::rend() const 2015-07-06 16:25:57 -06:00
Ryan Lucchese
e8c1a11730 better const correctness for ByteVector::rbegin() const and ByteVector::rend() const 2015-07-01 15:47:21 -06:00
Ryan Lucchese
d8e8ec69fe changed SUNPRO_CC version check to first check if SUNPRO_CC is defined 2015-06-30 13:41:09 -06:00
Ryan Lucchese
6d0712c8df changed SUNPRO_CC version check to first check if SUNPRO_CC is defined 2015-06-30 13:23:25 -06:00
Ryan Lucchese
00b2f6a386 check SUNPRO_CC version before defining WANT_CLASS_INSTANTIATION_OF_MAP in apetag.cpp - causes problems on newer Solaris Studio compiler 2015-06-30 12:50:03 -06:00
Ryan Lucchese
a3dccdc7a3 added sun compiler version check before changing constness of ConstReverseIterator in ByteVector 2015-06-30 12:46:25 -06:00
Ryan Lucchese
b698c73690 return const correct reverse iterator to prevent Solaris compiler from choking on const conversion 2015-06-30 12:18:12 -06:00
Tsuda Kageyu
801c9db810 WAV: Avoid using a magic number. 2015-06-30 15:59:01 +09:00
Tsuda Kageyu
409b135dd5 MPEG: Fix warnings about signed/unsigned mismatch on some compilers. 2015-06-30 11:58:07 +09:00
Tsuda Kageyu
4dd14d4d73 Add a supplementary comment to ByteVector::checksum(). 2015-06-27 01:29:16 +09:00
Tsuda Kageyu
44e6419644 ASF: Hide some internal functions from the public header. 2015-06-23 18:22:31 +09:00
Tsuda Kageyu
467658e463 ASF: Make use of List iterators and setAutoDelete(). 2015-06-23 17:43:50 +09:00
Tsuda Kageyu
3fcb21642c ASF: Hide internal class declarations from the public header. 2015-06-23 17:34:33 +09:00
Tsuda Kageyu
472ce9f42c ASF: Use CodecType enum instead of a magic number. 2015-06-23 11:48:25 +09:00
Tsuda Kageyu
be33340383 Remove an useless function call. 2015-06-22 09:54:17 +09:00
Tsuda Kageyu
91ed3548f1 ASF: Enable ASF::Properties to get the audio codec information. 2015-06-21 02:42:47 +09:00
Tsuda Kageyu
b56f4c4372 APE: Reduce useless File::Find() operations. 2015-06-20 20:41:02 +09:00
Tsuda Kageyu
2155b4fd50 TrueAudio: A bit more accurate calculation of the stream length. 2015-06-20 17:36:00 +09:00
Tsuda Kageyu
e605e96835 MusePak: Avoid seeking a file when not needed. 2015-06-20 17:30:25 +09:00
Tsuda Kageyu
dfee7020da APE: Find an ID3v2 tag and calculate the stream length in APE::File. 2015-06-20 04:34:34 +09:00
Scott Wheeler
e90b5e5f2f Merge pull request #614 from TsudaKageyu/win32-pkg-config
Enable pkg-config on Windows.
2015-06-19 09:12:32 +02:00
Tsuda Kageyu
642baca4ed Fix inconsistent negative seek behavior between Linux and Windows. 2015-06-19 02:42:18 +09:00
Tsuda Kageyu
da01fa5745 Enable pkg-config on Windows. 2015-06-19 01:26:12 +09:00
Tsuda Kageyu
78c70cf5bb MOD: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (always return 0)
2015-06-18 18:03:53 +09:00
Tsuda Kageyu
8f6af3f020 WavPack: A bit more accurate calculation of the stream length. 2015-06-18 18:00:03 +09:00
Tsuda Kageyu
22f250eaa4 WavPack: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Add isLossless() property.
Support multi channel. (#92)
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 17:59:06 +09:00
Tsuda Kageyu
eb73612a2b TrueAudio: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Avoid possible arithmetic overflows. (#520)
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 17:52:36 +09:00
Tsuda Kageyu
9c8e36d3be WAV: Move property parsing code to Properties.
Make use of 'fact' chunk to get the number of total samples.
2015-06-18 17:47:39 +09:00
Tsuda Kageyu
ed25204d75 WAV: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Add bitsPerSample() property besides sampleWidth(). (#360)
Add format() property. (#360)
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 17:43:09 +09:00
Tsuda Kageyu
03fd0a3ead AIFF: Calculate the actual average bitrate even if a file is compressed.
Move property parsing code to Properties.
2015-06-18 17:38:41 +09:00
Tsuda Kageyu
aede4ac851 AIFF: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Add bitsPerSample() property besides sampleWidth(). (#360)
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 17:30:58 +09:00
Tsuda Kageyu
3823afcc87 Ogg Vorbis: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 17:24:31 +09:00
Tsuda Kageyu
4dba88fa31 Ogg Speex: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Add bitrateNominal() property.
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 17:23:03 +09:00
Tsuda Kageyu
f3d8100c7b Ogg Opus: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 17:19:23 +09:00
Tsuda Kageyu
b2c79bc084 MPEG: No need to get the length of an ID3v2 tag twice. 2015-06-18 17:14:12 +09:00
Tsuda Kageyu
f82be353b4 MPEG: Properties::xingHeader() should return null if a VBR header is not found. 2015-06-18 17:14:12 +09:00
Tsuda Kageyu
9ec6d28239 MPEG: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Support VBRI header in addition to Xing. (#136)
Fix MPEG frame seeker functions. (maybe #190)
Calculate MPEG frame length accurately.
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 17:14:04 +09:00
Tsuda Kageyu
3a1c784eec MusePak: A bit more accurate calculation of the stream length. 2015-06-18 17:05:58 +09:00
Tsuda Kageyu
4a014c8113 MusePak: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 17:05:58 +09:00
Tsuda Kageyu
5d77553759 MP4: Remove useless ByteVector::mid() operations. 2015-06-18 17:00:10 +09:00
Tsuda Kageyu
da14f67e2c MP4: Do rounding when calculating the bit rate. 2015-06-18 17:00:10 +09:00
Tsuda Kageyu
9226fa76b3 MP4: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Add some tests for audio properties.
Add some supplementary comments.
Move parsing code to read() for consistency with other classes.
2015-06-18 17:00:10 +09:00
Tsuda Kageyu
ff36648e92 ASF: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Add bitsPerSample() property. (#360)
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 16:33:56 +09:00
Scott Wheeler
447a4739c5 Merge pull request #611 from TsudaKageyu/fix-bufsize
Fix mismatched file I/O buffer sizes.
2015-06-18 08:22:59 +02:00
Tsuda Kageyu
f15fe869a5 Add a test for APE files with an ID3v2 tag. 2015-06-18 14:41:37 +09:00
Tsuda Kageyu
125d887b85 APE: Use the audio stream length in calculating the bit rate. 2015-06-18 14:41:37 +09:00
Tsuda Kageyu
9a8e41b9d6 APE: AudioProperties improvements
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Enable to read bit depth from older version files. (#360)
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.
2015-06-18 14:41:37 +09:00
Tsuda Kageyu
68ef160dbc Fix mismatched file I/O buffer sizes. 2015-06-18 11:23:31 +09:00
Scott Wheeler
6d71bdf8b7 Merge pull request #607 from TsudaKageyu/unused-function
Remove some unused private function prototypes.
2015-06-15 21:15:08 +02:00
Tsuda Kageyu
b37eaace15 Removed an unused data member from MPE::File.
It seems to be related to scan().
2015-06-12 14:07:52 +09:00
Tsuda Kageyu
c1c70edb76 Remove some unused private function prototypes. 2015-06-12 11:50:38 +09:00
Tsuda Kageyu
75159d5d8a Silence a GCC warning about ignoring a return value in test. 2015-06-10 03:44:30 +09:00
Stephen F. Booth
46862bf537 Merge pull request #594 from TsudaKageyu/typos-in-comment
Fix some typos in comments.
2015-06-08 22:19:27 -04:00
Tsuda Kageyu
2b260fd2e8 Fix some typos in comments. 2015-06-09 10:33:32 +09:00
Scott Wheeler
b1a35a8b31 Add const to docs 2015-06-03 01:21:12 +02:00
Stephen F. Booth
88ef556d4e Merge pull request #591 from TsudaKageyu/wmemcpy
Use wmemcpy() rather than memcpy() and sizeof(wchar_t).
2015-06-02 08:19:33 -04:00
Samuel Martin
00c6e7ea79 cmake: use BUILD_SHARED_LIBS instead of ENABLE_STATIC to drive the shared object build
In case ENABLE_STATIC is still set on the CMake command line, this
change will makes CMake bail out becaus e this option is no longer
supported.

This patch makes taglib more compliant with the distro package framework
that uses the standards CMake options.

Signed-off-by: Samuel Martin <s.martin49@gmail.com>
2015-06-01 19:27:05 +02:00
Tsuda Kageyu
0c0f123a08 Use wmemcpy() rather than memcpy() and sizeof(wchar_t). 2015-06-01 13:52:55 +09:00
Festus Hagen
48311cca14 Undo comment stacking. 2015-05-31 22:12:18 -04:00
Michael Helmling
db90f4b358 Prefix #ifndef with TAGLIB_ in tpropertymap.h 2015-05-29 19:53:42 +02:00
Festus Hagen
b5d65edab7 Silence uint ambiguity errors in tests. 2015-05-27 14:07:53 -04:00
Scott Wheeler
a06d55ae6f Merge pull request #577 from TsudaKageyu/frameoffset
Fix MPEG::File::firstFrameOffset() and lastFrameOffset(). (#190)
2015-05-26 17:53:24 +02:00
Stephen F. Booth
c5f2e9342d Merge pull request #578 from TsudaKageyu/test-temp
A lot of zero-sized temporary files are left after a test session on …
2015-05-25 08:41:37 -04:00
Tsuda Kageyu
2d778d5a0a A lot of zero-sized temporary files are left after a test session on Windows. 2015-05-25 15:51:19 +09:00
Stephen F. Booth
0aa75b2e8d Merge pull request #574 from TsudaKageyu/skip-dup-chunks
Skip duplicate chunks when reading AIFF/WAV files.
2015-05-24 14:38:50 -04:00
Tsuda Kageyu
618a939c56 Fix MPEG::File::firstFrameOffset() and lastFrameOffset(). (#190) 2015-05-25 02:41:27 +09:00
Tsuda Kageyu
2337fbcfc6 Stop calculating the offset in RIFF::File::chunkData(). 2015-05-25 00:43:36 +09:00
Tsuda Kageyu
9da20a8a52 Skip duplicate chunks when reading AIFF/WAV files.
Similar to #492.
There is no good reason to use the last chunk rather than the first one.
2015-05-25 00:40:13 +09:00
Stephen F. Booth
4129b919c1 Merge pull request #572 from TsudaKageyu/map-erase2
Map::erase() can take a key directly so no need to call find() before…
2015-05-23 08:21:58 -04:00
Tsuda Kageyu
6d6f544010 Map::erase() can take a key directly so no need to call find() beforehand. 2015-05-23 18:12:01 +09:00
Stephen F. Booth
93da3ba6d9 Merge pull request #571 from TsudaKageyu/fuzzed-wv
Avoid an infinite loop when reading fuzzed WavPack files. (#482)
2015-05-22 07:44:41 -04:00
Stephen F. Booth
e064b88049 Merge pull request #570 from TsudaKageyu/audioprop-typo
Fix a typo in comment.
2015-05-22 07:41:46 -04:00
Tsuda Kageyu
3094540a4b Avoid an infinite loop when reading fuzzed WavPack files. (#482) 2015-05-22 14:15:10 +09:00
Tsuda Kageyu
8e21dcc3d4 Fix a typo in comment. 2015-05-22 12:06:01 +09:00
Stephen F. Booth
0ea22348cb Merge pull request #569 from TsudaKageyu/map-erase
std::map::erase() can take a key directly and has no-throw guarantee.
2015-05-21 22:46:15 -04:00
Stephen F. Booth
48ca54de1f Merge pull request #484 from TsudaKageyu/fix-rfind
Fix File::rfind() for small files.
2015-05-21 22:44:10 -04:00
Tsuda Kageyu
54de66f275 std::map::erase() can take a key directly and has no-throw guarantee. 2015-05-22 01:26:56 +09:00
Lukáš Lalinský
d4b0ba2a7a TagLib::XM::Properties is a public class that should be exported 2015-05-20 15:18:01 -07:00
Festus Hagen
abc5743222 Removed missed unnecessary BUILD_TESTS check. 2015-05-20 15:34:05 -04:00
Scott Wheeler
525396d9c2 Merge pull request #550 from TsudaKageyu/fix-test
Fix test code to work on some environments.
2015-05-20 19:24:52 +02:00
Tsuda Kageyu
bb9679b51a Fix test code to work on some environments.
const char * is more preferable than string for ifstream constructor.
2015-05-21 02:03:06 +09:00
Festus Hagen
e44cba56b5 Don't look for CppUnit unless BUILD_TESTS, general cleanup. 2015-05-20 11:11:55 -04:00
Scott Wheeler
e4cf012522 Bring the API more in line with the rest of TagLib
Like in #255, this also makes it possible to read values from the
tag in a const function.
2015-05-20 14:26:53 +02:00
Scott Wheeler
a37d423ea8 Merge pull request #549 from TsudaKageyu/win32-test
Modify the test code to work on MSVC/Windows.
2015-05-20 13:50:49 +02:00
Tsuda Kageyu
88a4cf34b8 Modify the test code to work on MSVC/Windows. 2015-05-20 20:19:20 +09:00
Scott Wheeler
81261dd128 This should also work Windows and has less duplicated code 2015-05-20 11:53:32 +02:00
Scott Wheeler
3bea9f6bee Don't use tempnam on UNIX
This silences the huge stream of warnings when building the tests.

I think I didn't break the Windows version in the process (though
it may make sense to use the built in Windows functions there
instead), but I don't have a Windows build environment here, so
I can't test.
2015-05-20 11:45:32 +02:00
Scott Wheeler
9cc2d7cfee Merge pull request #546 from TsudaKageyu/test-surrogate-pair
Add a test for strings that contains surrogate pairs.
2015-05-19 19:57:47 +02:00
Scott Wheeler
fe1bf015bb Merge pull request #548 from TsudaKageyu/render-twice
No need to call ID3v2::Frame::render() twice when saving an ID3v2 tag.
2015-05-19 11:28:50 +02:00
Tsuda Kageyu
287078566f No need to call ID3v2::Frame::render() twice when saving an ID3v2 tag. 2015-05-19 17:39:37 +09:00
Scott Wheeler
60966518e2 Quote path names including user-provided variables
This should make these work even if the value contains spaces

Closes #344
2015-05-19 10:15:15 +02:00
Tsuda Kageyu
2268efb49e Add a test for strings that contains surrogate pairs. 2015-05-19 09:01:47 +09:00
Scott Wheeler
29f535dc8d Remove *file argument to private members
This is already covered by d->file, so there's no reason to pass a pointer
to the member dozens of times.
2015-05-18 23:11:51 +02:00
Scott Wheeler
592522d34c Moar const fixes 2015-05-18 23:00:16 +02:00
Scott Wheeler
6b9e4e4403 1001 Const fixes (plus iterator rename) 2015-05-18 22:48:55 +02:00
Scott Wheeler
089e44f3db Remove unnecessary checks for null before delete
Closes #343
2015-05-18 21:40:21 +02:00
Scott Wheeler
bd3c4dc1b2 Merge pull request #515 from TsudaKageyu/empty-id3v2-frame
Skip empty ID3v2 frames when saving an ID3v2 tag.
2015-05-18 21:36:37 +02:00
Scott Wheeler
bba562b557 Add accessors to manipulate MP4 tags without modifying the internal structure
This brings the MP4 API in line closer to other tag formats and makes it
possible to access the tag data from const functions.

"ItemListMap" has been renamed to "ItemMap" (with the old version
deprecated).  It seems that the "ListMap" notion was copied probably
from Allan's ApeTag implementation, which incorrectly copied the term
from the XiphTag.  Notably, in XiphTag, because a field can have multiple
values, the "ListMap" is a map of lists.  Calling things a "ListMap" where
there can be only one value doesn't fit.

Closes #255
2015-05-18 21:18:33 +02:00
Scott Wheeler
451d23ca37 Add isEmpty() to MP4
Closes #457
2015-05-18 20:30:19 +02:00
Scott Wheeler
d248f77ab9 Show something useful for ChapterFrame::toString()
Closes #517
2015-05-18 19:51:18 +02:00
Tsuda Kageyu
727a11573a Fix File::rfind() for small files to work just like ByteVector::rfind(). 2015-05-19 01:24:37 +09:00
Scott Wheeler
34da0c0dab Update signature and docs
Specifically this allows the frame to be constructed and then to have
the children and embedded frames set later.
2015-05-18 18:19:43 +02:00
Scott Wheeler
7316cd331d Remove the null termination stuff from the ToC frames too 2015-05-18 18:17:10 +02:00
Scott Wheeler
3a977c55c4 We've moved away from including the null byte in the returned value
This does change previous behavior, but the previous behavior was
particularly stupid and inconsistent with everything else in TagLib.

It should be possible to mitigate this by putting the same safety
guards in the TableOfContents
2015-05-18 17:29:52 +02:00
Scott Wheeler
a094ce7dd2 Don't underflow if there are no embedded frames
Closes #513
2015-05-18 17:11:18 +02:00
Scott Wheeler
941efcba18 This isn't tracked as part of the elementID anymore 2015-05-18 16:53:12 +02:00
Scott Wheeler
ffb543acbb Split chapter data and embedded frame data
This will allow us to test parsing them separately
2015-05-18 16:45:57 +02:00
Scott Wheeler
fc24b3d22b Don't require users to include a padding byte explicitly
This makes it where the natural construction can be used of something
like:

new ChapterFrame("ID", ... )

Closes #514
2015-05-18 16:41:30 +02:00
Scott Wheeler
a9e064c58e Also test second constructor 2015-05-18 16:30:37 +02:00
Scott Wheeler
1a5d89d29e Update signature and docs to be more in-line with TagLib's style 2015-05-18 16:00:47 +02:00
Scott Wheeler
650b581f9e Merge pull request #544 from TsudaKageyu/advance
Use std::advance rather than a loop and increment.
2015-05-18 15:09:28 +02:00
Scott Wheeler
0739dd232a It doesn't make sense to set the factory after construction
Closes #259
2015-05-18 14:21:55 +02:00
Scott Wheeler
41a250a15d Make this macro work with current Qt versions
Closes #499
2015-05-18 12:42:24 +02:00
Tsuda Kageyu
8da0013482 Add a test to check if an empty ID3v2 frame is really skipped. 2015-05-18 19:03:20 +09:00
Scott Wheeler
0288059495 Add astylerc 2015-05-18 11:31:55 +02:00
Tsuda Kageyu
6e40361c0e Use std::advance rather than a loop and increment. 2015-05-18 09:31:43 +09:00
Lukáš Lalinský
c2570fe115 Merge pull request #521 from TsudaKageyu/gcc-warning
Fix a GCC/Clang warning about singed/unsigned comparison.
2015-05-17 10:06:10 -07:00
Lukáš Lalinský
bd91da55ba Merge pull request #542 from TsudaKageyu/comment-typos
Fix some typos in comment.
2015-05-17 10:05:43 -07:00
Tsuda Kageyu
3a3a6a6fda Fix some typos in comment. 2015-05-18 00:31:46 +09:00
Lukáš Lalinský
64c43b0d3f Merge pull request #535 from FestusHagen/fh1.m_UintAmbiguity
Silenced uint ambiguity error.
2015-05-16 17:03:53 -07:00
Lukáš Lalinský
db2dfa9515 Merge pull request #538 from gogglesmm/optimize-mid-to-uint
bytevector.mid(pos,4).toUInt() => bytevector.toUInt(pos)
2015-05-15 20:06:24 -07:00
Lukáš Lalinský
0069debf0c Merge pull request #536 from FestusHagen/fh1.m_CMakeSubProjectFix
Fix for using Taglib as a CMake sub directory project.
2015-05-15 19:48:43 -07: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
Lukáš Lalinský
69563d83a0 Merge pull request #533 from TsudaKageyu/bytevector-resize
Fix the wrong padding of ByteVector::resize().
2015-05-15 19:43:38 -07:00
Sander Jansen
60775306ea Fix code styling 2015-05-15 21:39:34 -05:00
Sander Jansen
4f77420248 replace use of bytevector.mid(pos,4).toUInt() with more optimized bytevector.toUInt(pos) 2015-05-15 21:25:44 -05:00
Tsuda Kageyu
b021ed44e9 Revert the last two commits.
But leave the tests unchanged, and add some comments.
2015-05-16 11:16:00 +09:00
Tsuda Kageyu
1f99c93a61 Reduce redundant memset when resizing ByteVector. 2015-05-16 03:46:34 +09:00
Tsuda Kageyu
a924ca0db7 Expand the internal buffer of ByteVector only if really needed.
Add tests for all execution paths of ByteVector::resize().
2015-05-14 11:20:35 +09:00
Urs Fleisch
b5c0ab58ba Get version information from taglib.h.
This avoids duplication of the version information in both
CMakeLists.txt and taglib.h while keeping the possibility to
use something different from CMake.
2015-05-10 10:30:51 +02:00
Festus Hagen
e43c1a3c09 Fix for using Taglib as a CMake sub directory project. 2015-05-09 20:29:52 -04:00
Festus Hagen
1e9529380d Silenced uint ambiguity error. 2015-05-09 14:19:33 -04:00
Tsuda Kageyu
ff8443f33a Fix the wrong padding of ByteVector::resize().
The expanded area will be filled with garbage instead of correct padding in some corner cases.
2015-05-02 02:43:08 +09:00
Lukáš Lalinský
62ab41fa07 Merge pull request #532 from TsudaKageyu/bytevector-detach-test
A little robuster tests for ByteVector iterators after detaching.
2015-04-29 10:14:16 -07:00
Tsuda Kageyu
00e3504264 A little robuster tests for ByteVector iterators after detaching. 2015-04-29 17:15:13 +09:00
Lukáš Lalinský
852da79899 Merge pull request #531 from TsudaKageyu/bytevector-detach
Fix ByteVector to return correct iterators after detached.
2015-04-28 20:34:53 -07:00
Tsuda Kageyu
ab047f6054 Fix ByteVector to return correct iterators after detached. 2015-04-29 10:28:08 +09:00
Lukáš Lalinský
5bad35c4cb Merge pull request #527 from TsudaKageyu/wma-guid
Fix saving WMA files with some GUID fields.
2015-04-28 10:42:06 -07:00
Tsuda Kageyu
8d708c03e1 Store any GUID fields in Metadata Library Object. 2015-04-28 16:40:24 +09:00
Tsuda Kageyu
f9a0b50830 Fix saving WMA files with some GUID fields. 2015-04-28 12:06:24 +09:00
Tsuda Kageyu
8491266b12 Fix a GCC/Clang warning about singed/unsigned comparison. 2015-04-17 09:38:21 +09:00
Stephen F. Booth
066b5aa57e Merge pull request #492 from TsudaKageyu/duplicate-id3v2-aiff-wav
Check AIFF/WAV files for duplicate tags.
2015-03-25 08:16:41 -04:00
Tsuda Kageyu
5f0a7da481 Take into account the frame header version when skipping an empty frame. 2015-03-24 10:41:39 +09:00
Tsuda Kageyu
d33d684fab Discard empty ID3v2 frames instead of adding a dummy null byte. 2015-03-24 10:31:52 +09:00
Tsuda Kageyu
4c4be0a263 Add a dummy byte to an empty ID3v2 frame to stick to the ID3v2 spec. 2015-03-22 22:14:21 +09:00
Michael Helmling
f476cf2b45 Merge pull request #511 from TsudaKageyu/tag-prop
Fix a bug that Tag::setProperties() clears the date instead of the track number
2015-03-20 10:28:20 +01:00
Tsuda Kageyu
68c0b0591b Fix a bug that Tag::setProperties() clears the date instead of the track number. 2015-03-20 13:33:13 +09:00
Stephen F. Booth
8fccaf30d2 Merge pull request #479 from TsudaKageyu/fuzzed-mp4
Fix an infinite loop when parsing MP4 files.
2015-02-18 08:15:50 -05:00
Tsuda Kageyu
b69973bcf2 Fix infinite loops when parsing MP4 files. 2015-02-18 11:33:10 +09:00
Tsuda Kageyu
30eac7569f Check AIFF/WAV files for duplicate tags.
AIFF/WAV files can have duplicate tags and it leads to memory leak.
2015-02-18 11:31:55 +09: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
Lukáš Lalinský
f6081ed32e Merge pull request #505 from TsudaKageyu/fuzzed-ape-tests
Separate the tests for fuzzed APE files.
2015-02-17 09:22:35 +01:00
Tsuda Kageyu
0839a23902 Separate the tests for fuzzed APE files. 2015-02-17 12:36:57 +09:00
Lukáš Lalinský
f35a279dd1 Merge pull request #496 from TsudaKageyu/fuzzed-mpc
Some fixes for fuzzed MPC files.
2015-02-16 19:26:57 +01:00
Tsuda Kageyu
e463d14f2e Check for EOF to fix a segfault while parsing fuzzed MPC files. 2015-02-17 01:22:39 +09:00
Tsuda Kageyu
829ae2112a Check the packet size to fix a segfault error while parsing fuzzed MPC files. 2015-02-17 01:22:39 +09:00
Tsuda Kageyu
65664e6855 Check for EOF to fix an infinite loop while parsing fuzzed MPC files. 2015-02-17 01:22:39 +09:00
Tsuda Kageyu
2193d6dd84 Fix an out-of-bounds access and consequent errors while parsing fuzzed MPC files.
Consequent errors may vary: segfault, zerodiv and so forth.
2015-02-17 01:22:38 +09:00
Stephen F. Booth
ef786188ad Merge pull request #502 from TsudaKageyu/fix-save-wav
Fix saving ID3v2/INFO tags of WAV files.
2015-01-31 14:12:18 -05:00
Tsuda Kageyu
2b5ee8deb9 Fix saving ID3v2/INFO tags of WAV files.
The old tag won't be removed when the new tag is empty.
2015-01-30 14:51:28 +09:00
Scott Wheeler
ed09c9cf87 Merge pull request #494 from TsudaKageyu/fix-zlib
Fix a wrong parameter for zlib.
2015-01-06 17:06:10 +01:00
Tsuda Kageyu
9d91610fc0 Fix a wrong parameter for zlib.
z_stream.avail_in has to be the length of the input buffer.
It will fail when frameDataLength is smaller than the actual compressed data size.
2015-01-06 18:45:42 +09:00
Stephen F. Booth
aed689c145 Merge pull request #491 from TsudaKageyu/aiff-hasid3v2
Implement missing AIFF::File::hasID3v2Tag().
2015-01-05 08:17:21 -05:00
Tsuda Kageyu
c6a63a3a2f Implement missing AIFF::File::hasID3v2Tag(). 2015-01-05 18:20:31 +09:00
Stephen F. Booth
2b0a540228 Merge pull request #490 from TsudaKageyu/remove-uncompr
Remove an unused file from taglib/CMakeLists.txt.
2015-01-04 22:31:42 -05:00
Tsuda Kageyu
2685ec1842 Remove an unused file from taglib/CMakeLists.txt.
uncompr.c is no longer used since caa53e8
2015-01-05 11:00:47 +09:00
Scott Wheeler
fdea6dcd40 Merge pull request #489 from TsudaKageyu/frame-flag-tests
Add some tests for huge memory allocation due to bad ID3v2 frame header ...
2015-01-05 02:03:06 +01:00
Tsuda Kageyu
ed253d3691 Add some tests for huge memory allocation due to bad ID3v2 frame header flags.
The tests covers #466 and #486.
Also fixes a compilation error on some compilers.
2015-01-05 09:34:30 +09:00
Scott Wheeler
57729b834a Show a debugging message when we have an error reading 2015-01-04 20:13:24 +01:00
Scott Wheeler
caa53e8de5 Read the compressed data as a stream
This avoids allocating the complete buffer at first based solely
on the value read from the frame header.  This then does a sanity
check at the end of reading to make sure that the two values match.
At present, it just prints a debugging message if the values do not
match.

Fixes #466
2015-01-04 19:58:18 +01:00
Lukáš Lalinský
31982660c8 Merge pull request #485 from TsudaKageyu/oga-segfault
Fix a segfault when reading faulty Ogg/FLAC files.
2015-01-01 19:48:23 +01:00
Lukáš Lalinský
bd7b8cc36a Merge pull request #473 from TsudaKageyu/fix-infotag
Fix an infinite loop when parsing an INFO tag.
2015-01-01 19:46:53 +01:00
Tsuda Kageyu
bc9bbfe3fa Add a check for faulty Ogg/FLAC files. 2015-01-02 00:10:51 +09:00
Tsuda Kageyu
7adea3df22 Separate tests for fuzzed WAV files. 2015-01-01 23:18:43 +09:00
Tsuda Kageyu
5ebb2ece80 Fix a segfault when reading faulty Ogg/FLAC files. 2015-01-01 19:59:30 +09:00
Tsuda Kageyu
0d2e01df61 Fix a segfault when parsing WAV properties. 2014-12-31 01:46:30 +09:00
Tsuda Kageyu
695fb5ec16 Add a test for fuzzed WAV files. 2014-12-31 01:44:25 +09:00
Tsuda Kageyu
3170d47ec3 Fix an infinite loop when parsing an INFO tag. 2014-12-31 01:44:25 +09:00
Stephen F. Booth
79b7c14129 Merge pull request #481 from TsudaKageyu/aiff-c
Add support for AIFF-C files.
2014-12-30 10:51:17 -05:00
Tsuda Kageyu
977fb2aeb0 Fix compilation errors on Clang. 2014-12-31 00:41:22 +09:00
Tsuda Kageyu
3b8c7d4e3a Add support for AIFF-C files. 2014-12-30 23:53:40 +09:00
Lukáš Lalinský
be33389884 Merge pull request #476 from TsudaKageyu/fuzzed-ape
Some fixes for fuzzed APE files.
2014-12-29 09:47:10 +01:00
Lukáš Lalinský
59ae61de6e Merge pull request #456 from TsudaKageyu/id3v2-padding
ID3v2 padding won't increase beyond 1% of the file size.
2014-12-29 09:26:55 +01:00
Tsuda Kageyu
16ac2cd240 Added some tests for fuzzed APE files. 2014-12-23 21:02:00 +09:00
Tsuda Kageyu
61543432c0 Fix an excessive loop when parsing an APE file. 2014-12-23 20:58:36 +09:00
Tsuda Kageyu
4a9614bfc3 Fix a division by zero error when parsing an APE file. 2014-12-23 20:54:20 +09:00
Tsuda Kageyu
1a917a38cd Fix ID3v2 padding size calculation. 2014-12-09 10:54:21 +09:00
Lukáš Lalinský
735e17f504 Merge remote-tracking branch 'TsudaKageyu/64bit-atom'
Conflicts:
	ConfigureChecks.cmake
2014-12-08 16:52:33 -08:00
Tsuda Kageyu
0731bc7b2e Remove CMake check for sizeof(long). 2014-12-09 08:55:46 +09:00
Bart van der Velden
fb1c744daf Compile without warnings with MSVC 2014-12-08 09:42:04 -08:00
Lukáš Lalinský
1bc5acd7a7 Merge pull request #424 from TsudaKageyu/format
Unified redundant string format functions. (backport from taglib2)
2014-12-08 09:38:03 -08:00
Lukáš Lalinský
f30f5ccce5 Merge pull request #441 from xhochy/tests-fix-vectorsize
Fix ByteVector sizes in some test cases
2014-12-08 09:36:28 -08:00
Lukáš Lalinský
421eb5e97e Merge pull request #420 from TsudaKageyu/remove-codecvt
Replaced codecvt with Win32 API.
2014-12-08 09:14:00 -08:00
Lukáš Lalinský
5e60ec48e9 Merge pull request #454 from TsudaKageyu/duplicate-id3v2
Skip duplicate ID3v2 tags in MPEG files.
2014-12-08 09:09:28 -08:00
Lukáš Lalinský
68eca440c9 Merge pull request #458 from achalddave/fix-gcc-errors
Fix more uint/TagLib::uint ambiguities
2014-12-08 08:54:27 -08:00
Achal Dave
7b03403791 Fix more uint/TagLib::uint ambiguities 2014-11-18 15:06:10 -08:00
Tsuda Kageyu
d80c4c96c3 ID3v2 padding won't increase beyond 1% of the file size. 2014-10-23 12:38:38 +09:00
Tsuda Kageyu
73b9b9b58d Avoid reading an entire ID3v2 tag when skipping it. 2014-10-23 08:14:10 +09:00
Lukáš Lalinský
072851869a Merge pull request #453 from TsudaKageyu/editorconfig
Suggestion: Use EditorConfig to help us stick to our coding style.
2014-10-22 19:31:14 +02:00
Tsuda Kageyu
269e78f1a0 Add a test for duplicate ID3v2 tags. 2014-10-21 00:16:43 +09:00
Tsuda Kageyu
71acf3b6f7 Comment on a weird workaround for duplicate ID3v2 tags. 2014-10-20 23:13:15 +09:00
Tsuda Kageyu
e41dc68a6b Skip duplicate ID3v2 tags in MPEG files. 2014-10-20 21:21:32 +09:00
Tsuda Kageyu
cfad951442 Use EditorConfig to help us stick to our coding style.
http://editorconfig.org/
2014-10-20 11:27:30 +09:00
Lukáš Lalinský
23ffb24472 Merge pull request #448 from TsudaKageyu/msvc-error
Fix a compilation error on MSVC.
2014-10-16 10:15:51 +02:00
Tsuda Kageyu
a8bfcd81be Fix a compilation error on MSVC. 2014-10-16 07:19:31 +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
bd7419f0bd 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:07:09 +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
71c1ce375f Don't leak 2014-09-25 20:46:47 +02:00
Scott Wheeler
cff8d22818 Missing assignment 2014-09-25 20:46:47 +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
0051351ebb TableOfContents and ChapterFrame can be added to v2.3 or v2.4 tags 2014-09-25 20:01:00 +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
Scott Wheeler
82315276db Take ownership of embedded frames, as documented
Previously embedded frames that were created automatically were
never deleted.

Fixes #440
2014-09-18 16:23:28 +02:00
Scott Wheeler
8ea07be47e Merge branch 'master' of https://github.com/taglib/taglib 2014-09-18 16:12:34 +02:00
Scott Wheeler
eae4605e6e Merge pull request #439 from xhochy/test-memleaks
Fix various memleaks in the tests
2014-09-18 16:11:12 +02:00
Scott Wheeler
b6289c64dd Break up the mega-lines 2014-09-18 11:21:18 +02:00
Scott Wheeler
e6d7dd08f2 No reason to store this in the d-pointer 2014-09-18 10:24:48 +02:00
Uwe L. Korn
ee283789b7 Fix ByteVector sizes in some test cases 2014-09-14 20:08:31 +01:00
Uwe L. Korn
205569c8d2 Fix various memleaks in the tests 2014-09-14 18:03:27 +01:00
Lukáš Lalinský
4b67beffc8 Merge pull request #434 from DidierMalenfant/master
Ignoring files generated when creating an Xcode project via cmake.
2014-08-25 14:09:44 +02:00
Didier Malenfant
b7a514886d Ignoring files generated when creating an Xcode project via cmake. 2014-08-23 20:37:32 -07: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
Tsuda Kageyu
0e6d8617ae Revert "Removed an ambiguous cast from FileNameHandle to FileName."
This reverts commit 9af7601bae.
2014-08-23 00:04:33 +09:00
Tsuda Kageyu
dfbaee4103 Removed an ambiguous cast from FileNameHandle to FileName. 2014-08-23 00:04:33 +09:00
Tsuda Kageyu
f29c5f45f8 Workaround for 64-bit MP4 atoms. 2014-08-23 00:04:33 +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ý
b1a8205561 Merge pull request #430 from TsudaKageyu/const-iterator
Reduce useless detach operations by making some non-const iterators cons...
2014-08-21 09:47:36 +02:00
Tsuda Kageyu
2971891c69 Reduce useless detach operations by making some non-const iterators const. 2014-08-21 16:35:35 +09:00
Lukáš Lalinský
d5e3d6ea7c Merge pull request #421 from TsudaKageyu/fix-wav-strip
Fixed a bug on stripping tags when saving .WAV files.
2014-08-20 10:12:43 +02:00
Lukáš Lalinský
20ce66f98b Merge pull request #422 from TsudaKageyu/detach
Added some missing detach()s to List<T>, ByteVector and String.
2014-08-20 10:09:08 +02:00
Stephen F. Booth
aff3351a25 Merge pull request #427 from TsudaKageyu/linebreak
Small fixes in line breaking.
2014-08-17 09:01:47 -04:00
Tsuda Kageyu
387890d956 Small fixes in line breaking. 2014-08-16 15:33:39 +09:00
Lukáš Lalinský
8765d40c2c Merge pull request #426 from TsudaKageyu/string-cmp
Added some operators to compare String to string literals.
2014-08-12 18:15:37 +02:00
Tsuda Kageyu
9bb0eb7ee9 Added some operators to compare String to string literals. 2014-08-12 23:58:45 +09:00
Lukáš Lalinský
d34c922c75 Merge pull request #425 from TsudaKageyu/fix-cmake
Removed a useless line from ConfigureChecks.cmake.
2014-08-12 09:42:19 +02:00
Tsuda Kageyu
3c727e091e Removed a useless line from ConfigureChecks.cmake. 2014-08-12 13:42:44 +09:00
Tsuda Kageyu
a055933e10 Unified the same debug messages. 2014-08-12 13:33:25 +09:00
Tsuda Kageyu
20c0aac309 Unified redundant string format functions. (backport from taglib2) 2014-08-11 01:09:07 +09:00
Tsuda Kageyu
929829b2b5 Removed useless strlen() and wcslen(). 2014-08-10 01:13:25 +09:00
Tsuda Kageyu
1944588595 Added some missing detach()s to List<T>, ByteVector and String. 2014-08-08 13:12:14 +09:00
Tsuda Kageyu
31a74927e4 Fixed a bug on stripping tags when saving .WAV files. 2014-08-07 18:49:53 +09:00
Tsuda Kageyu
972aa1feef Replaced codecvt with Win32 API. 2014-08-07 17:35:42 +09:00
Lukáš Lalinský
c23ee5331f Merge pull request #418 from TsudaKageyu/debug-msg
Fixed some debug messages.
2014-08-07 00:37:17 +02:00
Lukáš Lalinský
0f605be198 Merge pull request #414 from TsudaKageyu/fix-floattest
Fixed some mistakes in the CMake module for float types.
2014-08-07 00:36:59 +02:00
Tsuda Kageyu
590cb29f99 Improved the CMake check for float/double format. (Intel compiler support) 2014-08-06 20:57:04 +09:00
Tsuda Kageyu
286fd2abec Fixed some debug messages. 2014-08-06 16:13:15 +09:00
Tsuda Kageyu
f76d76728d Fixed some mistakes in the CMake module for float types. 2014-08-04 17:51:05 +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
Lukáš Lalinský
80f5436370 Merge pull request #413 from TsudaKageyu/msvc-tests3
Fixed a test to work with MSVC.
2014-08-04 09:09:20 +02:00
Tsuda Kageyu
043d2bbef5 Fixed a test to work with MSVC. 2014-08-04 15:11:50 +09: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
Lukáš Lalinský
cf59d51d93 Merge pull request #406 from TsudaKageyu/utf16-byteorder
Fixed handling UTF-16 byte order.
2014-07-23 10:21:37 +02:00
Lukáš Lalinský
9569b99e4c Merge pull request #405 from TsudaKageyu/missing-include
Added a missing #include.
2014-07-23 10:20:38 +02:00
Tsuda Kageyu
590405d878 Fixed handling UTF-16 byte order. 2014-07-23 15:36:16 +09:00
Tsuda Kageyu
8e6e580c60 Fixed handling UTF-16 byte order. 2014-07-23 15:35:49 +09:00
Tsuda Kageyu
c03b91aed3 Added a missing #include. 2014-07-23 14:56:18 +09:00
Lukáš Lalinský
ee2908a6cf Merge pull request #399 from TsudaKageyu/float-conv
Added float conversion functions to ByteVector.
2014-07-22 12:10:54 +02:00
Tsuda Kageyu
e29f1d39e7 Added float conversion functions to ByteVector.
Added CMake checks about IEEE754 compliance.
2014-07-17 12:09:14 +09:00
Lukáš Lalinský
b509106031 Merge pull request #398 from TsudaKageyu/fix-chap
Fixed some compilation error on MSVC in CHAP and CTOC frames support.
2014-07-16 22:30:10 +02:00
Tsuda Kageyu
47cd6fad4f Fixed some compilation error on MSVC in CHAP and CTOC frames support. 2014-07-17 01:43:56 +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
Lukáš Lalinský
fb24dfe7cf Merge pull request #393 from TsudaKageyu/msvc-tests
Modified some tests to work with MSVC.
2014-07-16 16:02:10 +02:00
Lukáš Lalinský
f42263e04a Merge pull request #392 from TsudaKageyu/zlib-source
Added a Windows-friendly build option ZLIB_SOURCE.
2014-07-16 15:58:52 +02:00
Lukáš Lalinský
43872f362d Merge pull request #390 from TsudaKageyu/vector-bounds
Fixed out-of-bounds access in findVector().
2014-07-16 15:57:55 +02:00
Lukáš Lalinský
73d3436570 Merge pull request #391 from TsudaKageyu/setlasterror
Added some SetLastError()s to get correct error codes in Win32.
2014-07-16 15:56:59 +02:00
Lukáš Lalinský
1e50b8dc25 Merge pull request #394 from ufleisch/master
Add genres 148 to 191 to list of ID3v1 genres.
2014-07-16 15:54:03 +02:00
Lukáš Lalinský
4a585c5258 Merge remote-tracking branch 'krejclu6/krejclu6_chapters' 2014-07-16 15:52:41 +02:00
Tsuda Kageyu
5f738a9819 Changed to skip the ZLib check when ZLIB_SOURCE is set. 2014-07-09 09:52:08 +09:00
Tsuda Kageyu
d7995b807f Fixed the tests to work with MSVC when UNICODE is set. 2014-06-24 01:29:15 +09:00
Urs Fleisch
3e60e339a4 Add genres 148 to 191 to list of ID3v1 genres.
This genres were added for Winamp version 5.6, see
<http://en.wikipedia.org/wiki/ID3#List_of_genres>.
2014-06-21 12:34:42 +02:00
Tsuda Kageyu
5feabe0988 Updated INSTALL. 2014-06-20 10:36:09 +09:00
Tsuda Kageyu
29a5129096 Modified some tests to work with MSVC. 2014-06-20 09:06:26 +09:00
Tsuda Kageyu
fadb57e4cd Added a Windows-friendly build option ZLIB_SOURCE. 2014-06-19 19:54:12 +09:00
Tsuda Kageyu
653b631aea Added a check for patternSize and removed a useless check. 2014-06-19 16:57:36 +09:00
Tsuda Kageyu
cb3abf15ad Added a test for out-of-bounds access in findVector(). 2014-06-19 13:22:50 +09:00
Tsuda Kageyu
29377fc8f1 Added some SetLastError()s to get correct error codes in Win32. 2014-06-19 12:58:07 +09:00
Tsuda Kageyu
663f10d51d Fixed out-of-bounds access in findVector(). 2014-06-19 12:19:18 +09: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
Lukas Krejci
a192db07c0 Code clean-up. 2014-06-11 17:52:05 +02:00
Lukas Krejci
459adc69ad Merge branch 'krejclu6_chapters' of https://github.com/krejclu6/taglib into krejclu6_chapters
Conflicts:
	taglib/mpeg/id3v2/id3v2framefactory.cpp
	tests/test_id3v2.cpp
2014-05-18 16:29:54 +02:00
Lukas Krejci
500b3e630b Uncommenting unit test. 2014-05-18 16:15:35 +02:00
Lukas Krejci
5c5c89e8d9 Added functions for work with embedded frames.
Added embedded frames parsing.

Added embedded frames rendering.
Modified constructor of CHAP and CTOC frame, so it can accept list of embedded frames.

Added unit tests for CHAP and CTOC frames parsing and rendering (with support of embedded frames).
Fixed bugs in rendering of CTOC frames.
Added functions for adding and removing child elements in CTOC frames.
2014-05-18 16:15:35 +02:00
Lukáš Krejčí
140fb2b3f6 Removed duplicated CHAP frame testing funtion. 2014-05-18 16:15:35 +02:00
Lukáš Krejčí
98ed58f910 Changed copyright and e-mail in modified files. 2014-05-18 16:15:35 +02:00
Lukáš Krejčí
7d99b8276a Fixed errors in ChapterFrame constructor.
Fixed errors in ChapterFrame method renderFields.
Fixed errors in TableOfContentsFrame method parseFields.
Added ChapterFrame and TableOfContentsFrame headers and sources to CMakeLists.txt.
Added some basic testing of CHAP and CTOC frames parsing.
2014-05-18 16:15:35 +02:00
Lukáš Krejčí
17841e89ae Fixed error in childElements function. 2014-05-18 16:14:00 +02:00
Lukáš Krejčí
c5f9258462 Finished parseFields, renderFields and asProperty methods of ChapterFrame and TableOfContentsFrame classes.
Methods setElementID of ChapterFrame and TableOfContentsFrame classes now automatically terminates new element ID with null.
2014-05-18 16:14:00 +02:00
Lukáš Krejčí
3a1040d55b Added basic members of ChapterFrame and TableOfContentsFrame classes.
Fixed minor bugs in ChapterFrame and TableOfContentsFrame headers.
2014-05-18 16:11:55 +02:00
Lukáš Krejčí
0864634ea6 Created CPP and H files for CTOC and CHAP frames. 2014-05-18 16:11:55 +02:00
Stephen F. Booth
f27e0aaecf Merge pull request #370 from supermihi/fix162v2
Fix #162: Xiph and APE generic getters return space-concatenated values
2014-04-24 21:35:50 -04: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
Lukáš Lalinský
ecc768d459 Merge pull request #380 from TsudaKageyu/fix-comment
Removed a wrong note from a comment in tstring.h.
2014-04-11 10:33:56 +02:00
Tsuda Kageyu
fabc411cb9 Removed a wrong note from a comment in tstring.h. 2014-04-11 17:16:55 +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ý
2d528d844a Merge pull request #356 from TsudaKageyu/string-comment
Added some comment about UTF-16 encoding to String::data().
2014-04-10 20:05:55 +02:00
Lukáš Lalinský
c65753c766 Add ALBUMARTIST property mapping for WMA 2014-04-10 20:05:14 +02:00
Lukáš Lalinský
22f8b527f7 Merge pull request #373 from TsudaKageyu/snprintf-spelling
Fixed some misspellings.
2014-04-10 20:04:37 +02:00
Lukáš Lalinský
7e10b13962 Merge pull request #372 from TsudaKageyu/cmake-warning
Suppressed the warning "Policy CMP0022 is not set" on CMake 2.8.12.
2014-04-10 20:04:17 +02:00
Lukáš Lalinský
05e26119f7 Merge pull request #377 from amigadave/master
Add ALBUMARTIST property mapping for MP4
2014-04-10 20:01:36 +02:00
David King
95a59c416b Add ALBUMARTIST property mapping for MP4
https://code.google.com/p/mp4v2/wiki/iTunesMetadata
2014-04-10 17:33:29 +01: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
Tsuda Kageyu
3f557be608 Suppressed the warning "Policy CMP0022 is not set" on CMake 2.8.12. 2014-04-05 21:08:21 +09:00
Lukáš Lalinský
9ca7877587 Merge pull request #371 from TsudaKageyu/cmake-ver
Changed cmake_minimum_required from 2.6.0 to 2.8.0.
2014-04-05 13:07:58 +02:00
Tsuda Kageyu
a93ee10134 Changed cmake_minimum_required from 2.6.0 to 2.8.0. 2014-04-05 19:44:47 +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
Michael Helmling
1723e9b18a Fix #162: Xiph and APE generic getters return space-concatenated values 2014-04-03 21:07:29 +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ý
16b8688c1a Merge pull request #362 from ufleisch/master
Add support for synchronized lyrics (SYLT) and event timing codes (ETCO) for ID3v2
2014-03-30 19:21:47 +02:00
Urs Fleisch
3b60af2c0b Add support for ID3v2 ETCO frames (event timing codes). 2014-03-30 09:28:14 +02:00
Urs Fleisch
eba99c3a70 Add support for ID3v2 SYLT frames (synchronized lyrics). 2014-03-30 09:26:03 +02:00
Tsuda Kageyu
6bcd422afa Small fix of a comment 2014-03-14 15:12:03 +09:00
Tsuda Kageyu
c357d293a1 Added some comment about UTF-16 encoding to String::data(). 2014-03-13 14:38:03 +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
Stephen F. Booth
cfb43223dc Merge pull request #354 from TsudaKageyu/opus-bitrate
opus: Estimate the bitrate if possible
2014-03-09 21:37:50 -04:00
Tsuda Kageyu
72cd379f30 opus: Estimate the bitrate if possible 2014-03-10 09:37:10 +09:00
Lukáš Lalinský
a3d724af27 Merge pull request #352 from TsudaKageyu/tagreader-sprintf
Avoid using sprintf() in tagreader.cpp to fix an MSVC warning.
2014-02-19 16:34:42 +01:00
Tsuda Kageyu
05e0081414 Avoid using sprintf() in tagreader.cpp to fix an MSVC warning. 2014-02-19 23:35:23 +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
Lukáš Lalinský
b658f95e06 Merge pull request #338 from funman/master
Also build/install taglib_c.pc when targetting windows
2014-02-17 08:46:13 +01:00
Lukáš Lalinský
2758aed34d Merge pull request #348 from TsudaKageyu/string-memcpy
Reduced a useless memory copy in tstring.cpp.
2014-02-17 08:45:49 +01:00
Lukáš Lalinský
12b25868b7 Merge pull request #349 from TsudaKageyu/install-typo
Fixed a typo in INSTALL.
2014-02-17 08:44:54 +01:00
Tsuda Kageyu
1deff52d95 Fixed a typo in INSTALL. 2014-02-17 11:22:40 +09:00
Tsuda Kageyu
69eaa75f64 Reduced a useless memory copy in tstring.cpp. 2014-02-15 20:25:00 +09:00
Lukáš Lalinský
3e0c73bdbc Merge pull request #347 from TsudaKageyu/xm-seek
Changed XM::File::save() to use seek() properly.
2014-02-14 17:21:49 +01:00
Tsuda Kageyu
9e94f8bb6c Changed XM::File::save() to use seek() properly. 2014-02-14 19:22:53 +09:00
Lukáš Lalinský
aa49723b48 Merge pull request #330 from TsudaKageyu/fix-emptystring
Fixed a bug reported at #328
2014-02-05 00:02:47 -08:00
Tsuda Kageyu
167513ae57 Avoid using &d->data[0] when d->data is empty. 2014-02-05 10:35:07 +09:00
Tsuda Kageyu
d0f3e9b186 Use std::string::c_str() rather than &s[0] where a const pointer is required. 2014-01-24 09:48:39 +09:00
Stephen F. Booth
4fc020e0d3 Merge pull request #340 from mineo/patch-1
Remove a superfluos 'x'
2014-01-18 13:12:21 -08:00
Wieland Hoffmann
db147e672e Remove a superfluos 'x' 2014-01-18 18:11:31 +01:00
Rafaël Carré
c45a0694f9 Also build/install taglib.pc when targetting windows
.pc file is notably used when cross-compiling windows software
2014-01-13 22:49:17 +01:00
Tsuda Kageyu
584bbc7c78 Fixed conversion from empty String to ByteVector 2013-12-04 09:37:59 +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
Lukáš Lalinský
10b804e0ae Merge pull request #322 from TsudaKageyu/mailaddress
Fixed a mail address
2013-11-24 23:25:19 -08:00
Tsuda Kageyu
4f8ab4b63f Fixed a mail address 2013-11-25 14:12:34 +09:00
Stephen F. Booth
5593c251c8 Merge pull request #321 from TsudaKageyu/nominmax
Fixed warnings in MinGW
2013-11-23 19:24:55 -08:00
Tsuda Kageyu
7d7a7be115 Fixed warnings in MinGW 2013-11-23 23:42:20 +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
f733077917 Merge pull request #307 from TsudaKageyu/string-abi
Fixed the ABI breakage in TagLib::String
2013-11-15 15:04:30 -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
Stephen F. Booth
670493f97f Merge pull request #310 from TsudaKageyu/backslash
Replaced wrongly used slashes with backslashes in some comments
2013-11-15 03:55:04 -08:00
Tsuda Kageyu
116b1fcff9 Unified the string formatting functions 2013-11-15 16:34:40 +09:00
Tsuda Kageyu
d4adc22922 Replaced wrongly used slashes with backslashes in some comments 2013-11-15 15:31:23 +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
34f8cd8a90 Merge pull request #309 from TsudaKageyu/fix-replace
Rewrote ByteVector::replace() simpler (fix for the issue #308)
2013-11-14 07:01:29 -08:00
Tsuda Kageyu
4a7d31c87b Rewrote ByteVector::replace() simpler 2013-11-14 14:58:14 +09:00
Tsuda Kageyu
3bf30af66c Fixed ABI breakage in TagLib::String 2013-11-06 17:01:21 +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
Lukáš Lalinský
ee9720a997 Merge pull request #304 from funman/master
Win32: avoid symbol lookup if UNICODE is defined
2013-10-28 01:12:48 -07:00
Rafaël Carré
69e58b5f3f Win32: avoid symbol lookup if UNICODE is defined 2013-10-28 04:39:04 +01:00
Duke Yin
de17843d8c Update tests 2013-10-17 15:14:29 -04:00
Duke Yin
944143a91b Handle iTunes ID3v2.3 hacks
iTunes writes the 2.4 frames TSOA, TSOT, TSOP to 2.3 files.  (It
additionally defines TSO2 and TSOC for both 2.3 and 2.4.)  TagLib should
not delete these frames.
2013-10-16 18:48:49 -04:00
Lukas Krejci
1ce5385e30 Uncommenting unit test. 2013-10-13 18:38:54 +02:00
Lukas Krejci
5ed2d88f78 Added functions for work with embedded frames.
Added embedded frames parsing.

Added embedded frames rendering.
Modified constructor of CHAP and CTOC frame, so it can accept list of embedded frames.

Added unit tests for CHAP and CTOC frames parsing and rendering (with support of embedded frames).
Fixed bugs in rendering of CTOC frames.
Added functions for adding and removing child elements in CTOC frames.
2013-10-13 18:27:43 +02:00
Lukáš Lalinský
aa61823432 Fix the length of the TXXX translation mapping (closes #283) 2013-10-08 17:50:01 +02:00
Lukáš Lalinský
2f7af42092 Update version to 1.9.1 2013-10-08 17:46:34 +02:00
Lukáš Lalinský
2d5abd46d2 Added TagLib::MP4::PropertyMap::codec() 2013-10-08 17:41:09 +02:00
Lukáš Lalinský
9b5869ea37 Merge remote-tracking branch 'TsudaKageyu/chunksize' 2013-10-08 16:18:43 +02:00
Lukáš Lalinský
02ebd0bcbe Change log for 1.9.1 2013-10-08 16:18:30 +02:00
Lukáš Lalinský
5693ab0403 Merge remote-tracking branch 'TsudaKageyu/fix-string' 2013-10-08 16:12:49 +02:00
Lukáš Lalinský
27000438f5 Merge remote-tracking branch 'TsudaKageyu/msvc_wchar_t' 2013-10-08 16:09:01 +02:00
Lukáš Lalinský
a6f759cc9a These shouldn't be executable either 2013-10-08 16:06:58 +02:00
Lukáš Lalinský
a175b8356b Reintroduce the old RefCounter from 1.8, which is needed by TagLib::Map<> and TagLib::List<> (closes #296) 2013-10-08 16:06:03 +02:00
Tsuda Kageyu
873df184fe Workaround for when MSVC doesn't have wchar_t as a built-in type 2013-10-08 19:55:44 +09:00
Tsuda Kageyu
079e3e0b87 Fixed detecting RIFF files with invalid chunk sizes 2013-10-07 17:04:55 +09:00
Lukáš Lalinský
95776b5905 These files should not be marked as executable 2013-10-06 17:11:01 +02: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
Lukáš Lalinský
dcfb71bcb4 Update version number to 1.9 2013-10-05 10:53:15 +02:00
Lukáš Lalinský
f2c9ed4f36 Update NEWS 2013-10-05 10:09:09 +02:00
Lukáš Lalinský
2407933087 Merge remote-tracking branch 'TsudaKageyu/wavpack-samplerate' 2013-10-05 09:53:49 +02:00
Stephen F. Booth
2af43ec8bf Merge pull request #290 from FestusHagen/m_WinInstallNotes
Update Windows INSTALL notes.
2013-10-01 19:51:11 -07:00
Festus Hagen
85d76a2428 Update Windows INSTALL notes. 2013-09-30 18:06:55 -04:00
Stephen F. Booth
5a4a05d9bc Merge pull request #280 from TsudaKageyu/info-fieldlist
Added a missing fieldListmap() method to RIFF::Info::Tag
2013-09-28 18:07:26 -07: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
Stephen F. Booth
a2188e6cf9 Merge pull request #285 from TsudaKageyu/algorithm
Added missing #include <algorithm> for std::min() and std::max()
2013-09-20 04:59:27 -07:00
Tsuda Kageyu
e6f9a06894 Added missing #include <algorithm> for std::min() and std::max() 2013-09-20 08:26:37 +09:00
Tsuda Kageyu
e125bcb78b Fixed a possible out-of-bound access when reading WavPack files 2013-09-19 04:09:28 +09:00
Tsuda Kageyu
c63dcdc459 Removed #include "tdebug.h" from a public header 2013-09-17 23:03:57 +09:00
Tsuda Kageyu
23b418b4e9 Added a missing fieldListmap() method to RIFF::Info::Tag 2013-09-17 14:59:19 +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
cf892f2cb8 Fixed a bug in creating String from ByteVector 2013-09-13 03:47:03 +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
Lukáš Lalinský
c12b6697f9 Merge remote-tracking branch 'TsudaKageyu/byteorder-detection' 2013-07-21 14:42:50 +02:00
Tsuda Kageyu
89fcab5669 Fixed an MSVC specific runtime error only in debug mode 2013-07-17 23:35:41 +09:00
Tsuda Kageyu
314cc33585 Removed taglib_config.h which is no longer used 2013-07-17 18:04:02 +09:00
Tsuda Kageyu
35ca010df6 Introduced the runtime byte order detection when config.h is missing 2013-07-17 15:02:02 +09:00
Tsuda Kageyu
0f58646bfb Added a test for APE::Item 2013-07-14 11:35:10 +09:00
Tsuda Kageyu
4d126c49e9 Fixed a crash of APE::Item::toString() when the data type is binary 2013-07-14 02:47:48 +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
Lukáš Lalinský
3a636c752b Merge remote-tracking branch 'TsudaKageyu/string-api-master' 2013-07-11 10:08:05 +02:00
Lukáš Lalinský
ff5ab030c5 Merge remote-tracking branch 'TsudaKageyu/fix-opus' 2013-07-11 10:06:35 +02:00
Lukáš Lalinský
ff3b1466e1 Merge remote-tracking branch 'TsudaKageyu/comment-update' 2013-07-11 10:05:29 +02:00
Lukáš Lalinský
89cb785f22 Merge remote-tracking branch 'TsudaKageyu/has-tags' 2013-07-11 10:03:28 +02:00
Tsuda Kageyu
30f62ba887 Updated the relevant comments 2013-07-04 22:14:42 +09:00
Tsuda Kageyu
1503909824 Added the methods to check which kind of tags the file actually has. 2013-07-04 18:11:33 +09:00
Tsuda Kageyu
45e8e83041 Fixed a wrong integer type 2013-06-24 21:07:33 +09:00
Tsuda Kageyu
75b685fa53 Updated the related comments 2013-06-24 01:29:33 +09:00
Tsuda Kageyu
62d55223b2 Added conversion from String to const wchar_t* 2013-06-24 01:13:25 +09:00
Tsuda Kageyu
418a6c79cb Comment update: Added some supplementary explanations and fixed some spellings. 2013-06-23 02:08:10 +09:00
Tsuda Kageyu
ab417fd9e3 Changed the style to follow TagLib's one 2013-06-22 18:06:40 +09:00
Tsuda Kageyu
35cdcd3b95 Added a missing check if an Opus file is open 2013-06-22 16:12:57 +09:00
Tsuda Kageyu
a845f70c49 Added some test cases for FileRef about unsupported files 2013-06-21 15:29:00 +09:00
Lukáš Lalinský
c066ccd32d Merge branch 'master' into taglib2
Conflicts:
	taglib/toolkit/tiostream.cpp
2013-06-21 08:04:00 +02:00
Lukáš Lalinský
7e866e11ad Merge remote-tracking branch 'FestusHagen/sw_initorder' 2013-06-21 08:01:50 +02:00
Tsuda Kageyu
90d43956ec Fixed a wrong integer type 2013-06-21 11:31:51 +09:00
Festus Hagen
6acbcfc68a Fix file modes 2. 2013-06-20 18:50:14 -04:00
Festus Hagen
02c81aaac2 Fix file modes. 2013-06-20 18:37:06 -04:00
Festus Hagen
550510ff3f Silence Initialization Order Warnings 2. 2013-06-20 16:40:05 -04: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ý
5051010835 Move byteSwap to a (private) shared include file, rather than having the same code in tstring.cpp and tbytevector.cpp 2013-06-20 15:22:06 +02:00
Lukáš Lalinský
fdb8a6b065 Reintroduce HAVE_CONFIG_H so that TagLib can be built without CMake 2013-06-20 15:07:25 +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
Lukáš Lalinský
6d4299ea94 Merge remote-tracking branch 'TsudaKageyu/debug-msg3' 2013-06-20 13:40:26 +02:00
Tsuda Kageyu
b84b3afc9c Making use of std::bitset::to_string() 2013-06-15 13:21:07 +09:00
Festus Hagen
451616f99a Silence Initialization Order Warnings. 2013-06-11 17:20:46 -04:00
Tsuda Kageyu
496b58e0c9 Updated the comment for DebugListener class 2013-06-11 19:23:46 +09: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
886236b978 Removed getDebugListener() 2013-06-10 16:29:33 +09:00
Tsuda Kageyu
c6f323357f Fixed some MSVC specific warnings 2013-06-10 12:49:02 +09:00
Tsuda Kageyu
6d2e0e8050 Moved a macro from taglib_config.h to config.h 2013-06-10 01:19:47 +09:00
Tsuda Kageyu
2f29ed003c Added a CMake option that allows to show debug messages in release mode 2013-06-09 23:52:05 +09:00
Tsuda Kageyu
12953b3fdc Removed TAGLIB_EXPORT from getDebugListener 2013-06-08 22:26:13 +09:00
Tsuda Kageyu
448648d61b Simplified DebugListener class 2013-06-08 21:40:30 +09:00
Lukáš Lalinský
241465eaac Merge branch 'revert-changes' of https://github.com/TsudaKageyu/taglib 2013-06-08 12:58:53 +02:00
Tsuda Kageyu
dce00b96b8 Revert "Fixed some MSVC specific warnings"
This reverts commit 93f304a91d.
2013-06-08 13:14:06 +09:00
Tsuda Kageyu
3b2d620671 Enabled users to define custom debug message listeners 2013-06-08 09:59:36 +09:00
Tsuda Kageyu
e18546560e Enabled users to define custom debug message listeners 2013-06-08 03:05:50 +09:00
naiar
fc9abc7a33 fixed build failure 2013-06-07 20:00:13 +09:00
Tsuda Kageyu
98d010f460 Merge pull request #232 from TsudaKageyu/remove-shlwapi
Removed the dependency on shlwapi.dll in Win32
2013-06-05 21:59:11 -07:00
Tsuda Kageyu
36d7f9ba32 Removed the dependency on shlwapi.dll in Win32 2013-06-06 13:45:23 +09:00
Tsuda Kageyu
c4c5b06643 Merge pull request #231 from TsudaKageyu/containsat
Fixed behavior change of ByteVector::containsAt()
2013-06-01 12:03:34 -07:00
Tsuda Kageyu
767a6ec4a2 Added some tests for containsAt() 2013-06-02 04:00:34 +09:00
Tsuda Kageyu
860a605c8d Fixed behavior change of ByteVector::containsAt() 2013-06-02 03:45:13 +09:00
Tsuda Kageyu
df5bf232eb Merge pull request #230 from TsudaKageyu/gcc42-3
Fixed compilation error with GCC4.2
2013-06-01 10:49:07 -07:00
Tsuda Kageyu
90a4bae6cc Fixed compilation error with GCC4.2 2013-06-02 02:37:15 +09:00
Tsuda Kageyu
3ae452ee2a Merge pull request #229 from TsudaKageyu/gcc42-2
Fixed compilation error with GCC4.2
2013-06-01 10:11:52 -07:00
Tsuda Kageyu
bc2d3ea72e Fixed compilation error with GCC4.2 2013-06-02 02:05:11 +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
9ccc4878d0 Merge pull request #228 from TsudaKageyu/gcc42
Fixed compilation error with GCC4.2
2013-06-01 08:05:29 -07:00
Tsuda Kageyu
6365f36c75 Fixed compilation error with GCC4.2 2013-06-01 23:55:52 +09:00
Tsuda Kageyu
da3d9b1c55 Merge pull request #226 from TsudaKageyu/file-comments
Fixed comments for File constructors
2013-05-30 22:34:21 -07:00
Tsuda Kageyu
f77a84486e Fixed comments for File constructors 2013-05-30 02:04:10 +09:00
Tsuda Kageyu
cf9f2a436b Merge pull request #224 from TsudaKageyu/memoryleak
Fixed memory leak of ByteVector
2013-05-27 08:20:38 -07:00
Tsuda Kageyu
e73afa3325 Fixed memory leak of ByteVector 2013-05-28 00:02:09 +09:00
Tsuda Kageyu
dfee045d46 Merge pull request #222 from TsudaKageyu/vc-filename
Fixed some MSVC specific warnings
2013-05-26 06:03:49 -07:00
Tsuda Kageyu
93f304a91d Fixed some MSVC specific warnings 2013-05-26 14:38:36 +09:00
Tsuda Kageyu
ddabffc7ef Merge pull request #221 from TsudaKageyu/fix-shlwapi
Fixed shlwapi.h and shlwapi.lib detection for MSVC
2013-05-25 12:20:57 -07:00
Tsuda Kageyu
42d268c2c9 Fixed shlwapi.h and shlwapi.lib detection for MSVC 2013-05-26 04:17:18 +09:00
Tsuda Kageyu
e7c0f3322d Merge pull request #220 from FestusHagen/cmake_shlwapi
Added FindShlwapi.cmake in lieu of pragma comment() in fileref.h.
2013-05-25 12:04:08 -07:00
Festus Hagen
b3f3eeeec7 Added FindShlwapi.cmake in lieu of pragma comment() in fileref.h. 2013-05-25 01:58:49 -04:00
Tsuda Kageyu
54fbe15611 Merge pull request #219 from joelverhagen/master
Windows build fails on master (due to RefCounter not being exported)
2013-05-23 18:44:15 -07:00
Joel Verhagen
d7523d7843 Added TAGLIB_EXPORT to RefCounter for Windows build 2013-05-23 13:42:51 -04: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
ca801c5411 Merge pull request #215 from TsudaKageyu/smallfile
Fixed bugs on manipulating small files
2013-05-23 02:22:48 -07:00
Tsuda Kageyu
4667ba02e5 Fixed bugs on manipulating small files 2013-05-23 17:45:16 +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
Tsuda Kageyu
3151336050 Merge pull request #209 from TsudaKageyu/bytevector
Changed behavior of ByteVector::toNumber() when overrun
2013-05-20 13:50:59 -07:00
Tsuda Kageyu
848f8c316e Changed behavior of ByteVector::toNumber() when overrun 2013-05-21 05:36:01 +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
2303da48a2 Merge pull request #204 from TsudaKageyu/number
Changed String::number() to use a standard function
2013-05-18 22:59:02 -07:00
Tsuda Kageyu
bbec1c7f81 Changed String::number() to use a standard function 2013-05-19 14:39:45 +09:00
Tsuda Kageyu
79f3edebc0 Added myself to AUTHORS 2013-05-19 11:59:37 +09:00
Tsuda Kageyu
d49d0a6888 Merge pull request #203 from TsudaKageyu/fix-filestream
Fixed initialization of FileStream
2013-05-18 19:21:36 -07:00
Tsuda Kageyu
5c3f096fe4 Fixed initialization of FileStream 2013-05-19 11:09:43 +09:00
Tsuda Kageyu
7060d53cf3 Merge pull request #202 from TsudaKageyu/fix-filestream
Small refactoring of FileStream
2013-05-18 10:49:31 -07:00
Tsuda Kageyu
dcf11b9586 Small refactoring of FileStream 2013-05-19 02:33:17 +09:00
Tsuda Kageyu
229d69864d Merge pull request #201 from TsudaKageyu/unicodefile
Small change in Win9x support
2013-05-18 07:41:07 -07:00
Tsuda Kageyu
36d9fc1973 Small change in Win9x support 2013-05-18 23:30: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
Tsuda Kageyu
d06f480f82 Merge pull request #199 from TsudaKageyu/fix-zlib
Fixed the test for ID3V2's compressed frame
2013-05-16 04:38:24 -07:00
Tsuda Kageyu
f9efcfb8d6 Fixed the test for ID3V2's compressed frame 2013-05-16 20:29:58 +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
Lukáš Krejčí
cbd6f73431 Removed duplicated CHAP frame testing funtion. 2013-05-04 21:25:55 +02: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
db06166330 Merge pull request #187 from TsudaKageyu/config
Removed config.h and moved macros into taglib_config.h
2013-05-03 08:03:51 -07:00
Tsuda Kageyu
5d8f781467 Fixed mismatched macro names 2013-05-03 21:05:55 +09:00
Tsuda Kageyu
03adafbfd9 Removed TAGLIB_HAVE_STD_WSTRING macro that affects the public ABI 2013-05-03 18:28:28 +09:00
Tsuda Kageyu
198530547d Removed RefCounter implementation from a public header 2013-05-03 13:53:32 +09:00
Tsuda Kageyu
4b6745b59b Merge pull request #188 from TsudaKageyu/string-comment
Fixed comments in tstring.h
2013-05-02 21:10:26 -07:00
Tsuda Kageyu
6f0bf734d5 Fixed comments in tstring.h 2013-05-03 13:03:38 +09:00
Tsuda Kageyu
23bd3784a1 Separated public and private config.h 2013-05-03 11:44:36 +09:00
Tsuda Kageyu
8f8ef3788f Prefixed public variables 2013-05-02 23:26:06 +09:00
Tsuda Kageyu
b0938a3cf1 Removed config.h and moved macros into taglib_config.h 2013-05-02 20:41:59 +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
a2688a1ff0 Merge pull request #180 from TsudaKageyu/master
Fixed possible memory leak
2013-04-30 09:39:23 -07:00
Tsuda Kageyu
d6fc2ef4aa Fixed possible memory leak 2013-05-01 01:32:48 +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
9f29804f60 Merge pull request #178 from rakuco/clear-mbstate_t-correctly
Correctly initialize std::mbstate_t.
2013-04-29 15:06:57 -07:00
Raphael Kubo da Costa
289b6abb43 Correctly initialize std::mbstate_t.
mbstate_t is an opaque type that is often a union or a struct, so setting it
directly to 0 is incorrect and causes build failures with some compilers
such as clang.
2013-04-29 23:56:07 +03: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
55f1224d6e Merge pull request #176 from TsudaKageyu/master
Add some error handling to tfilestream.cpp
2013-04-27 17:37:17 -07:00
Tsuda Kageyu
395743eb49 Add some error handling to tfilestream.cpp 2013-04-28 09:14:37 +09:00
Tsuda Kageyu
62827269b6 Merge pull request #175 from TsudaKageyu/master
Comment update
2013-04-27 11:10:37 -07:00
Tsuda Kageyu
d2273a7218 Comment update 2013-04-28 03:06:59 +09:00
Tsuda Kageyu
bd85cf8928 Merge pull request #174 from TsudaKageyu/alignment
Fixed detection of alignment-tolerant CPUs
2013-04-27 11:02:31 -07:00
Tsuda Kageyu
f3cbb883f2 Fixed detection of alignment-tolerant CPUs 2013-04-28 02:57:51 +09:00
Lukáš Krejčí
65006952f3 Changed copyright and e-mail in modified files. 2013-04-27 16:09:15 +02:00
Lukáš Krejčí
4815dbba68 Fixed errors in ChapterFrame constructor.
Fixed errors in ChapterFrame method renderFields.
Fixed errors in TableOfContentsFrame method parseFields.
Added ChapterFrame and TableOfContentsFrame headers and sources to CMakeLists.txt.
Added some basic testing of CHAP and CTOC frames parsing.
2013-04-27 15:42:23 +02:00
Tsuda Kageyu
362900c721 Redesigned toNumber/fromNumber API of ByteVector 2013-04-27 12:46:21 +09:00
Lukáš Krejčí
bcad792e75 Fixed error in childElements function. 2013-04-26 23:16:06 +02:00
Tsuda Kageyu
a80222efa5 Merge pull request #171 from TsudaKageyu/string-test
Add some tests for String
2013-04-26 04:35:57 -07:00
Tsuda Kageyu
5e13e0c838 Add some tests for String 2013-04-26 19:43:10 +09:00
Tsuda Kageyu
58765ac40a Merge pull request #170 from TsudaKageyu/master
Small bug fix in tstring.cpp
2013-04-26 01:52:15 -07:00
Tsuda Kageyu
6e35e56d7f Small bug fix in tstring.cpp 2013-04-26 17:32:39 +09:00
Tsuda Kageyu
a9cdbb7e75 Merge pull request #166 from TsudaKageyu/cmake_test
Refactor out some stuff to CMake tests
2013-04-25 18:54:37 -07:00
Tsuda Kageyu
8c71428d4f Add missing HAVE_WIN_ATOMIC block 2013-04-23 16:25:18 +09:00
Tsuda Kageyu
2c85b4d178 Fix mistaken preprocessor conditionals 2013-04-23 10:42:45 +09:00
Tsuda Kageyu
3293cee11e Skip unnecessary CMake tests 2013-04-23 08:47:48 +09:00
Tsuda Kageyu
27990d0623 Merge pull request #169 from TsudaKageyu/win9x-unicode
Improve Unicode file name handling in Win9x
2013-04-22 10:10:14 -07:00
Tsuda Kageyu
986ee3c44a Improve Unicode file name handling in Win9x 2013-04-23 01:59:02 +09:00
Tsuda Kageyu
dfb3962511 Merge pull request #168 from TsudaKageyu/fix-win9x
Fix a change breaks compatibility with Win9x
2013-04-22 08:28:34 -07:00
Tsuda Kageyu
3e89f7cb40 Fix a change breaks compatibility with Win9x 2013-04-23 00:15:54 +09:00
Tsuda Kageyu
8c233f4552 Merge pull request #167 from TsudaKageyu/filesize
Improve getting file size in Win32
2013-04-21 16:29:26 -07:00
Tsuda Kageyu
c2896fd629 Improve getting file size in Win32 2013-04-22 08:01:25 +09:00
Lukáš Krejčí
fcfd9f59fe Finished parseFields, renderFields and asProperty methods of ChapterFrame and TableOfContentsFrame classes.
Methods setElementID of ChapterFrame and TableOfContentsFrame classes now automatically terminates new element ID with null.
2013-04-21 16:16:57 +02:00
Tsuda kageyu
49b07a2662 Refactor out some stuff to CMake tests 2013-04-21 22:24:12 +09:00
Tsuda Kageyu
529d78f54b Merge pull request #165 from TsudaKageyu/sign-ext
Fix unexpected sign extension
2013-04-21 00:15:02 -07:00
Tsuda kageyu
dc89bdd3f0 Fix unexpected sign extension 2013-04-21 16:06:12 +09:00
Lukáš Krejčí
4be1279430 Added basic members of ChapterFrame and TableOfContentsFrame classes.
Fixed minor bugs in ChapterFrame and TableOfContentsFrame headers.
2013-04-20 16:49:57 +02:00
Lukáš Krejčí
08ae0e8c63 Created CPP and H files for CTOC and CHAP frames. 2013-04-20 15:52:52 +02:00
Tsuda Kageyu
81a9f0474d Merge pull request #161 from TsudaKageyu/fix-syncdata
Fix reading corrupted ID3v2 syncdata
2013-04-19 17:43:16 -07:00
Tsuda kageyu
8a7d1dd796 Fix reading corrupted ID3v2 syncdata 2013-04-20 09:40:01 +09:00
Tsuda Kageyu
457b1abac8 Merge pull request #160 from TsudaKageyu/fix-cast-align
Fix -Wcast-align violation
2013-04-19 14:43:42 -07:00
Tsuda kageyu
e8498b9264 Fix -Wcast-align violation 2013-04-20 05:54:06 +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
Tsuda Kageyu
3eeff8b933 Merge pull request #158 from TsudaKageyu/fix-errmsg
Fix an error message in Win32
2013-04-18 14:30:37 -07:00
Tsuda kageyu
d959ab89f1 Fix an error message in Win32 2013-04-19 06:13:27 +09:00
Tsuda Kageyu
b081fb2833 Merge pull request #157 from TsudaKageyu/file-win32
Fix improper file handling in Win32
2013-04-18 06:38:48 -07:00
Tsuda kageyu
e0805b039c Fix improper file handling in Win32 2013-04-18 22:16:59 +09: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
c352b5e0c7 Merge pull request #155 from TsudaKageyu/gcc-warnings
Fix some GCC specific warnings
2013-04-18 04:09:30 -07:00
Tsuda kageyu
a71749a6b5 Fix some GCC specific warnings 2013-04-18 19:52:52 +09:00
Tsuda Kageyu
a188778eb8 Merge pull request #154 from TsudaKageyu/tonumber
ByteVector::toUInt() takes offset and length
2013-04-18 03:26:21 -07:00
Tsuda kageyu
439f27640a ByteVector::toUInt() takes offset and length 2013-04-18 18:36:19 +09: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
c9209cc99e Merge pull request #150 from TsudaKageyu/detect-codecvt
Detect <codecvt> header automatically
2013-04-17 08:42:14 -07:00
Tsuda kageyu
1370a1cc83 Detect <codecvt> header automatically 2013-04-18 00:32:14 +09:00
Tsuda Kageyu
266e8f5ae4 Merge pull request #149 from TsudaKageyu/fileref-string
Fix improper string handling
2013-04-17 07:55:33 -07:00
Tsuda kageyu
ccaac6c336 Fix improper string handling 2013-04-17 23:47:09 +09:00
Tsuda Kageyu
88005640d5 Merge pull request #148 from TsudaKageyu/reset-smart-pointer
Revert changes concerning the smart pointer
2013-04-17 07:08:36 -07:00
Tsuda kageyu
1f4e06ea7c Revert changes concerning the smart pointer 2013-04-17 22:54:56 +09:00
Tsuda Kageyu
b6c9fb2da1 Merge pull request #147 from TsudaKageyu/shared_ptr
Use shared_ptr if possible regardless of C++11 support
2013-04-17 06:03:28 -07:00
Tsuda kageyu
66f5f396ff Use shared_ptr if possible regardless of C++11 support 2013-04-17 21:41:23 +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
c9628aae49 Merge pull request #145 from TsudaKageyu/classname
Changed some class names
2013-04-16 20:51:33 -07:00
Tsuda kageyu
bb5d3f0600 Changed some class names 2013-04-17 12:45:14 +09:00
Tsuda Kageyu
1f819ce2c5 Merge pull request #144 from TsudaKageyu/restore-abi2
Restore ABI changed in pull request #60
2013-04-16 20:38:29 -07:00
Tsuda kageyu
593eda7d9d Restore ABI changed in pull request #60 2013-04-17 12:28:00 +09:00
Tsuda Kageyu
14dab7c649 Merge pull request #143 from TsudaKageyu/restore-abi
Restore ABI breaking change
2013-04-16 19:41:55 -07:00
Tsuda kageyu
94a07fa39a Restore ABI breaking change 2013-04-17 11:33:01 +09:00
Tsuda Kageyu
492a0f8199 Merge pull request #142 from TsudaKageyu/shared_ptr
Use std::shared_ptr<T> if C++11 is available
2013-04-16 19:27:42 -07:00
Tsuda kageyu
24736b919a Use std::shared_ptr<T> if C++11 is available 2013-04-17 11:12:42 +09:00
Tsuda Kageyu
38220a57ce Merge pull request #141 from TsudaKageyu/smart-ptr
Replace RefCounter with a smart pointer
2013-04-16 18:38:41 -07:00
Tsuda kageyu
b14dc1572d Replace RefCounter with a smart pointer 2013-04-17 10:10:25 +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
21964f3cbc Merge pull request #139 from TsudaKageyu/refactor-string
Small refactoring of tstring.cpp
2013-04-16 06:47:28 -07:00
Tsuda kageyu
c13921b7c7 Small refactoring of tstring.cpp 2013-04-16 21:47:12 +09:00
Tsuda Kageyu
39fef2705c Merge pull request #138 from TsudaKageyu/refector-bytevector
Small refactoring of tbytevector.cpp
2013-04-16 05:34:59 -07:00
Tsuda kageyu
8c427c7de9 Small refactoring of tbytevector.cpp 2013-04-16 19:57:04 +09:00
Tsuda Kageyu
0bb995abd0 Merge pull request #137 from TsudaKageyu/refactor-bytevector
Small refactoring of tbytevector.cpp
2013-04-15 22:55:22 -07: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
0195eef865 Small refactoring of tbytevector.cpp 2013-04-16 14:35:47 +09: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
cc3dbd84ce Merge pull request #134 from TsudaKageyu/fix-byteswap
Bug fix for #132
2013-04-15 14:02:17 -07:00
Tsuda kageyu
5e6285afab Bug fix for #132 2013-04-16 05:53:36 +09:00
Tsuda Kageyu
df28a1335a Merge pull request #133 from TsudaKageyu/fix-byteswap
Bug fix for #132
2013-04-15 12:22:37 -07:00
Tsuda kageyu
88a0871784 Bug fix for #132 2013-04-16 04:06:29 +09:00
Tsuda Kageyu
f0edca2f8c Merge pull request #132 from TsudaKageyu/byteswap
Add cross-platform byte order conversions
2013-04-15 08:26:32 -07:00
Tsuda Kageyu
f5462e3e19 Add cross-platform byte order conversions 2013-04-16 00:12:37 +09:00
Lukáš Lalinský
53c5a97b4c Add tests for newline handling in String (#125) 2013-04-15 10:47:43 +02:00
Lukáš Lalinský
a3352fd899 Use the first instance of a MP4 atom (#126)
When a file contains multiple MP4 atoms with the same name, use the first
one. This is consistent with iTunes and other popular software.
2013-04-15 10:13:47 +02:00
Jingmin Wei
4a85e1e1ca Allow the second byte of MPEG header to contain 0xFF
0xFF in the second byte means MPEG Version 1, Layer I, no CRC protection.

http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html
2013-04-15 09:46:08 +02:00
Lukáš Lalinský
94efe5c187 Merge pull request #116 from ufleisch/tagduplication
Parameter to disable duplication between ID3v1 and ID3v2 tags, #115.
2013-04-14 23:47:59 -07:00
Tsuda Kageyu
bef59a0b9a Merge pull request #131 from TsudaKageyu/vc-warning
Fix VC++ specific warnings
2013-04-14 13:29:29 -07:00
Tsuda Kageyu
86142343ee Fix VC++ specific warnings 2013-04-15 05:23:39 +09:00
Tsuda Kageyu
5b2458ed66 Merge pull request #130 from TsudaKageyu/improve-string
Some improvements of String
2013-04-14 13:17:31 -07:00
Tsuda Kageyu
b52cd44c25 Some improvements of String 2013-04-15 05:03: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
40997e7fc9 Merge pull request #122 from TsudaKageyu/reduce-copy
Reduce unnecessary memory copies by ByteVector
2013-04-06 06:32:26 -07:00
Tsuda Kageyu
a4e68a0304 Reduce unnecessary memory copies by ByteVector 2013-04-05 22:07:58 +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
Urs Fleisch
703736fbcb Parameter to disable duplication between ID3v1 and ID3v2 tags, #115. 2013-03-23 13:56:31 +01: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
fd45808555 Merge pull request #104 from TsudaKageyu/test-warnings
Fix warnings in test_flacpicture.cpp
2013-03-19 06:03:23 -07:00
Tsuda Kageyu
e9fec47411 Fix warnings in test_flacpicture.cpp 2013-03-19 21:54:56 +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
Stephen F. Booth
6029352c09 Merge pull request #96 from nightingale-media-player/master
Make textual lyric frames use UTF8
2013-01-20 07:56:30 -08:00
rsjtdrjgfuzkfg
077208d17a Create UTF8-Lyrics per default. 2013-01-18 17:21:35 +01:00
Michael Helmling
08863dec0b Found and fixed more missing property interface forwarders.
Probably due to a copy-and-paste error the implementation of
File::removeUnsupportedProperties() contained cases for several type
which do not reimplement this method; for others the implementation was
missing and is now included.

In addition, the formats Speex and Opus suffered from the same bug as
OggFLAC in the commit before, which is now fixed.
2013-01-03 23:20:15 +01:00
Michael Helmling
80af92a715 Add forwarders for the property interface to Ogg::FLAC::File.
Fixes an infinite method resolution recursion in File::properties() and
File::setProperties(). Thanks to Sebastian Rachuj for pointing out this bug.
2013-01-03 23:00:17 +01:00
Michael Helmling
5578843220 Fixed a typo. 2013-01-03 22:54:12 +01:00
Lukáš Lalinský
237e0ec23c Merge pull request #93 from magcius/master
c: Add support for TAGLIB_STATIC to the C bindings
2013-01-01 03:00:27 -08:00
Jasper St. Pierre
d52e97dfcd c: Add support for TAGLIB_STATIC to the C bindings
Otherwise, we'll fail with dllimport/dllexport linking errors on
Windows.
2013-01-01 04:28:00 -05: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
Michael Helmling
8329d6ac1a Update documentation of the property map interface in TagLib::File. 2012-12-27 11:38:01 +01:00
Michael Helmling
f1d723077f Consistently handle invalid and deprecated tags in setProperties()
This commit reverts the use of strip() in setProperties() because the
latter function should not change the file before save() is called.
Instead, the following policy is now consistently applied for file formats
with multiple tag types:
- the recommended tag type is created, if it does not exist
- deprecated tags are updated, if they exist, but not created
- illegal tag types are ignored by setProperties(), but used in properties()
  if no others exist.

The only tag types considered "illegal" so far are APEv2 in MPEG and ID3 in FLAC.
2012-12-26 22:46:37 +01:00
Michael Helmling
a095c468b2 Revert "Add a test to show a problem with properties() and duplication."
This reverts commit 6e3391a846. The "problem" demonstrated in there won't be fixed due to lack of significance.
2012-12-20 17:30:19 +01:00
Michael Helmling
b14e6a3570 Update for pull request #89: Change how setProperties() updates tags.
For file types supporting more than one tag format, setProperties() now always creates the most modern one. Deprecated tags are stripped.
2012-12-20 17:28:50 +01:00
Michael Helmling
6e3391a846 Add a test to show a problem with properties() and duplication. 2012-12-10 21:22:11 +01:00
Michael Helmling
c0ca5c97d5 Fix issue #88 by changing the behavior of setProperties().
For file types that support multiple tag standards (for example, FLAC
files can have ID3v1, ID3v2, and Vorbis comments) setProperties is now
called for all existing tags instead of only for the most recommended
one.
This fixes the problem that under some circumstances it was not possible
to delete a value using setProperties() because upon save() the call to
Tag::duplicate recovered that value from the ID3v1 tag.
2012-12-10 20:56:16 +01:00
Michael Helmling
d5cf6d72e2 Merge remote-tracking branch 'official/master' 2012-12-10 19:55:29 +01:00
Michael Helmling
9eb0f2941f Add a test case for the return value of setProperties() 2012-12-10 19:55:23 +01:00
naota
3fa295d99d Include sys/stat.h to define S_* properly
Without including sys/stat.h, this file failed to build on FreeBSD with the following error.

In file included from /var/tmp/portage/media-libs/taglib-1.8/work/taglib-1.8/tests/test_trueaudio.cpp:5:0:
/var/tmp/portage/media-libs/taglib-1.8/work/taglib-1.8/tests/utils.h: In function 'std::string copyFile(const string&, const string&)':
/var/tmp/portage/media-libs/taglib-1.8/work/taglib-1.8/tests/utils.h:36:62: error: 'S_IRUSR' was not declared in this scope
/var/tmp/portage/media-libs/taglib-1.8/work/taglib-1.8/tests/utils.h:36:72: error: 'S_IWUSR' was not declared in this scope
In file included from /var/tmp/portage/media-libs/taglib-1.8/work/taglib-1.8/tests/test_mpeg.cpp:6:0:
/var/tmp/portage/media-libs/taglib-1.8/work/taglib-1.8/tests/utils.h: In function 'std::string copyFile(const string&, const string&)':
/var/tmp/portage/media-libs/taglib-1.8/work/taglib-1.8/tests/utils.h:36:62: error: 'S_IRUSR' was not declared in this scope
/var/tmp/portage/media-libs/taglib-1.8/work/taglib-1.8/tests/utils.h:36:72: error: 'S_IWUSR' was not declared in this scope
gmake[2]: *** [tests/CMakeFiles/test_runner.dir/test_mpeg.cpp.o] Error 1
2012-11-28 07:54:08 +09: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ý
812f63502b Implement the PropertyMap interface for WMA 2012-11-23 09:32:00 +01:00
Lukáš Lalinský
353eb9f00f Implement the PropertyMap interface for MP4 2012-11-22 10:40:22 +01:00
Lukáš Lalinský
1b813d9d6c Document sort names 2012-11-21 17:26:17 +01:00
Lukáš Lalinský
c5dade5ee7 Use names that are consistent with Vorbis Comments 2012-11-21 17:24:32 +01:00
Lukáš Lalinský
e75d6f616c Add support for reading MusicBrainz IDs from ID3v2 tags to PropertyMap 2012-11-21 17:21:30 +01:00
Lukáš Lalinský
15b601f053 Use PropertyMap in tagreader 2012-11-21 14:40:26 +01:00
Lukáš Lalinský
45317ef7f2 Revert "Fix opening of read-only files on Windows"
This reverts commit ade8dc1a21.
2012-11-20 18:34:51 +01:00
Lukáš Lalinský
3da792152a Merge pull request #85 from TsudaKageyu/fix-readonly
Fix reading read-only files in Win32
2012-11-20 09:23:16 -08:00
Tsuda Kageyu
3f6da779d2 Fix compilation in non-Win32 2012-11-20 22:46:03 +09:00
Tsuda Kageyu
57b8ae6e1c Fix reading read-only files in Win32 2012-11-20 22:20:34 +09:00
Lukáš Lalinský
ade8dc1a21 Fix opening of read-only files on Windows
The CreateFile* functions return INVALID_HANDLE_VALUE on error, not NULL.

http://article.gmane.org/gmane.comp.kde.devel.taglib/2346
2012-11-20 14:15: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ý
c6f7ad3e83 Revert "Add a tool to inspect audio files, only MP4 is implemented for now"
This reverts commit 45b0279b41.
2012-11-12 16:14:32 +01:00
Lukáš Lalinský
dbe6be778b Build also examples 2012-11-11 16:44:01 +01:00
Lukáš Lalinský
45b0279b41 Add a tool to inspect audio files, only MP4 is implemented for now 2012-11-11 16:43:36 +01:00
Lukáš Lalinský
3a5aeb4573 Parse covr atoms with type 0 (fixes issue #84) 2012-11-11 16:04:08 +01:00
Lukáš Lalinský
72745846f4 Update NEWS 2012-11-11 14:49:31 +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ý
9e788bb8c2 Fix tests when compiled with clang on Linux 2012-11-11 14:26:10 +01:00
Lukáš Lalinský
56fbe7e14d Make travis run tests also with clang 2012-11-10 20:51:17 +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ý
44155f6771 Merge pull request #79 from gonemad/master
Check if file is open before reading tags
2012-11-04 01:27:43 -07:00
Lukáš Lalinský
341711c04b Merge pull request #83 from jmarshallnz/more_itunes_hacks
A small fix, and some additional iTunes hacks (v2.2 frames in v2.3 tag)
2012-11-04 01:26:26 -07:00
Jonathan Marshall
be6187e893 adds new iTunes hack for v2.2 frames stored in a v2.3 tag (iTunes v8.1.1.10 for example) 2012-11-04 19:54:28 +13:00
Jonathan Marshall
c42bdeab43 fixes noop frame id size check in ID3v2::FrameFactory::createFrame 2012-11-04 19:52:10 +13:00
Lukáš Lalinský
c46ecd186d Make the PropertyMap accessor methods virtual 2012-10-20 09:30:26 +02:00
gonemad
7d7c58cb8e Merge branch 'master' of https://github.com/taglib/taglib 2012-10-18 20:17:35 -04:00
Lukáš Lalinský
c2eecc0804 Merge branch 'master' into taglib2
Conflicts:
	taglib/mpeg/id3v1/id3v1tag.cpp
2012-10-13 13:44:38 +02:00
Lukáš Lalinský
044da877e6 Make sure we build the tests 2012-10-13 13:38:35 +02:00
Lukáš Lalinský
2d7686b5fa Actually run the tests 2012-10-13 13:36:33 +02:00
Lukáš Lalinský
074f6db6d8 Needs sudo 2012-10-13 13:34:44 +02:00
Lukáš Lalinský
7a884af0ef Experimenting with Travis CI 2012-10-13 13:33:36 +02:00
Lukáš Lalinský
e568e1019d Remove useless debug print 2012-10-13 09:11:20 +02:00
Lukáš Lalinský
ca543039a5 Include Opus in docs 2012-10-13 09:06:09 +02:00
Lukáš Lalinský
5e7b1da632 Add support for Ogg Opus 2012-10-13 08:55:23 +02:00
gonemad
6b9ef6421f Fixed indents 2012-10-11 22:10:19 -04:00
gonemad
d15c8453ac Added check if file is open before attempting to read tags 2012-10-11 21:20:03 -04:00
Lukáš Lalinský
1e660dda71 Partial changelog for 1.9 2012-10-10 17:09:03 +02:00
Lukáš Lalinský
2a77afc593 Merge remote-tracking branch 'nightingale/master' 2012-10-10 16:45:36 +02:00
Tsuda Kageyu
4dcf0b41c6 Support files over 2GB 2012-10-10 22:22:29 +09:00
Tsuda Kageyu
a9df3e48f7 Fix a bug in updating MP4 tags 2012-10-10 21:17:05 +09:00
rsjtdrjgfuzkfg
c8994ede3f Restrict url frame generation to W??? Frames to prevent known non-text non-url frameIDs to be handled as url when containing only one String. No longer describe the default comment as "COMMENT". 2012-10-08 20:19:12 +02:00
Lukáš Lalinský
7e255733e0 Merge remote-tracking branch 'TsudaKageyu/id3v1-genrenumber' 2012-10-08 13:23:17 +02:00
Julien Ramseier
72f9a96cce Fix missing CppUnit include directive 2012-10-07 15:41:40 +02:00
Stephen F. Booth
1308ff6479 Merge pull request #73 from ArnaudBienner/master
Corrupted FLAC files scan can result in heavy CPU consumption: fix
2012-10-07 05:29:02 -07:00
Arnaud Bienner
b7a15092d8 Faster FLAC::FilePrivate destructor 2012-10-07 03:07:53 +02:00
Arnaud Bienner
ad9ffc62e6 Consider FLAC file as being invalid if a 0 length block is found 2012-10-07 03:04:02 +02:00
Tsuda Kageyu
46e613dcca Add reading/writing ID3v1 genre in number 2012-10-04 19:23:10 +09:00
Tsuda Kageyu
9577784bae Add the string handler base class 2012-10-04 18:02:25 +09:00
Urs Fleisch
2d7414733e Crash when saving xm files (fixes #68) 2012-09-30 15:42:16 +02:00
Lukáš Lalinský
f52bab8a01 Merge branch 'master' into taglib2 2012-09-30 10:50:51 +02:00
Lukáš Lalinský
9f597bab1b Change some variables to follow the TagLib naming convention 2012-09-30 10:50:19 +02:00
Lukáš Lalinský
321b9b5a8b Merge remote-tracking branch 'TsudaKageyu/filestream' 2012-09-30 10:43:58 +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
Lukáš Lalinský
60a3a4e455 Various uint fixes
We really need to get rid of TagLib::uint...
2012-09-30 10:22:10 +02:00
Lukáš Lalinský
57e5cc8c17 Merge remote-tracking branch 'TsudaKageyu/infotag-patch' 2012-09-30 10:15:56 +02:00
Lukáš Lalinský
5250673fa0 Merge pull request #70 from FestusHagen/taglib-config_cmd
Win32 taglib-config.cmd support.
2012-09-30 01:06:49 -07:00
Lukáš Lalinský
ab5e19a016 Merge pull request #69 from FestusHagen/SW_MinGW
Silence warnings with MinGW 4.6.3.
2012-09-29 06:54:36 -07:00
Festus Hagen
8790e9de01 Silence warnings with MinGW 4.6.3. 2012-09-29 09:01:44 -04:00
Festus Hagen
1086d4476d Win32 taglib-config.cmd support. 2012-09-28 21:41:45 -04:00
Lukáš Lalinský
7b80418122 Fix the version number 2012-09-26 20:30:53 +02:00
Stephen F. Booth
02d034f53f Merge pull request #65 from TsudaKageyu/tagsondisk
Add MPEG::FILE::Has*Tag functions
2012-09-08 05:14:30 -07:00
Tsuda Kageyu
e7126db97c Add MPEG::FILE::Has*Tag functions 2012-09-08 14:13:20 +09:00
Tsuda Kageyu
4582ea3b27 Fixed CMakeLists.txt 2012-09-08 01:17:15 +09:00
Tsuda Kageyu
43e100fd37 FileStream improvement in Win32 2012-09-07 23:48:06 +09:00
Tsuda Kageyu
071a1477b5 Fixed an API change 2012-09-07 08:16:30 +09:00
Tsuda Kageyu
61c8013f2c Added missing comments 2012-09-07 08:16:28 +09:00
Tsuda Kageyu
9c8c215c30 Support INFO tags of RIFF wave files. 2012-09-07 08:16:26 +09:00
372 changed files with 31350 additions and 11373 deletions

18
.astylerc Normal file
View File

@@ -0,0 +1,18 @@
--suffix=none
--style=kr
--indent=spaces=2
--indent-col1-comments
--min-conditional-indent=0
--attach-extern-c
--attach-namespaces
--indent-namespaces
--pad-oper
--unpad-paren
--align-pointer=name
--align-reference=name
--max-instatement-indent=40
--break-closing-brackets
--remove-brackets
--convert-tabs
--max-code-length=100
--break-after-logical

21
.editorconfig Normal file
View File

@@ -0,0 +1,21 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Non-specified newlines with a newline ending every file
[*]
insert_final_newline = true
# 2 space indentation
[*.{h,cpp,tcc,cmake,yml}]
indent_style = space
indent_size = 2
# Trim traling whitespaces
[*.{h,cpp,tcc,cmake,yml}]
trim_trailing_whitespace = true
# UTF-8 without BOM
[*]
charset = utf-8

5
.gitignore vendored
View File

@@ -19,8 +19,10 @@ CMakeFiles/
/taglib.pc
/tests/test_runner
/tests/Testing
/taglib/libtag.a
/taglib_config.h
/taglib-config
/bindings/c/libtag_c.a
/bindings/c/taglib_c.pc
/bindings/c/Debug
/bindings/c/MinSizeRel
@@ -42,3 +44,6 @@ CMakeFiles/
/taglib/tag.dir/Release
/ALL_BUILD.dir
/ZERO_CHECK.dir
taglib.h.stamp
taglib.xcodeproj
CMakeScripts

30
.travis.yml Normal file
View File

@@ -0,0 +1,30 @@
language: cpp
sudo: false
os:
- linux
- osx
dist: trusty
compiler:
- gcc
- clang
addons:
apt:
packages:
- libcppunit-dev
- zlib1g-dev
- libboost-dev
matrix:
exclude:
- os: osx
compiler: gcc
install:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install cppunit; fi
script: cmake -DBUILD_TESTS=ON -DBUILD_EXAMPLES=ON -DBUILD_BINDINGS=ON -DCMAKE_CXX_FLAGS="-std=c++11" . && make && make check

327
3rdparty/utf8-cpp/checked.h vendored Normal file
View File

@@ -0,0 +1,327 @@
// Copyright 2006-2016 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "core.h"
#include <stdexcept>
namespace utf8
{
// Base for the exceptions that may be thrown from the library
class exception : public ::std::exception {
};
// Exceptions that may be thrown from the library functions.
class invalid_code_point : public exception {
uint32_t cp;
public:
invalid_code_point(uint32_t codepoint) : cp(codepoint) {}
virtual const char* what() const throw() { return "Invalid code point"; }
uint32_t code_point() const {return cp;}
};
class invalid_utf8 : public exception {
uint8_t u8;
public:
invalid_utf8 (uint8_t u) : u8(u) {}
virtual const char* what() const throw() { return "Invalid UTF-8"; }
uint8_t utf8_octet() const {return u8;}
};
class invalid_utf16 : public exception {
uint16_t u16;
public:
invalid_utf16 (uint16_t u) : u16(u) {}
virtual const char* what() const throw() { return "Invalid UTF-16"; }
uint16_t utf16_word() const {return u16;}
};
class not_enough_room : public exception {
public:
virtual const char* what() const throw() { return "Not enough space"; }
};
/// The library API - functions intended to be called by the users
template <typename octet_iterator>
octet_iterator append(uint32_t cp, octet_iterator result)
{
if (!utf8::internal::is_code_point_valid(cp))
throw invalid_code_point(cp);
if (cp < 0x80) // one octet
*(result++) = static_cast<uint8_t>(cp);
else if (cp < 0x800) { // two octets
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else if (cp < 0x10000) { // three octets
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else { // four octets
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
return result;
}
template <typename octet_iterator, typename output_iterator>
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
{
while (start != end) {
octet_iterator sequence_start = start;
internal::utf_error err_code = utf8::internal::validate_next(start, end);
switch (err_code) {
case internal::UTF8_OK :
for (octet_iterator it = sequence_start; it != start; ++it)
*out++ = *it;
break;
case internal::NOT_ENOUGH_ROOM:
throw not_enough_room();
case internal::INVALID_LEAD:
out = utf8::append (replacement, out);
++start;
break;
case internal::INCOMPLETE_SEQUENCE:
case internal::OVERLONG_SEQUENCE:
case internal::INVALID_CODE_POINT:
out = utf8::append (replacement, out);
++start;
// just one replacement mark for the sequence
while (start != end && utf8::internal::is_trail(*start))
++start;
break;
}
}
return out;
}
template <typename octet_iterator, typename output_iterator>
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
{
static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
return utf8::replace_invalid(start, end, out, replacement_marker);
}
template <typename octet_iterator>
uint32_t next(octet_iterator& it, octet_iterator end)
{
uint32_t cp = 0;
internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
switch (err_code) {
case internal::UTF8_OK :
break;
case internal::NOT_ENOUGH_ROOM :
throw not_enough_room();
case internal::INVALID_LEAD :
case internal::INCOMPLETE_SEQUENCE :
case internal::OVERLONG_SEQUENCE :
throw invalid_utf8(*it);
case internal::INVALID_CODE_POINT :
throw invalid_code_point(cp);
}
return cp;
}
template <typename octet_iterator>
uint32_t peek_next(octet_iterator it, octet_iterator end)
{
return utf8::next(it, end);
}
template <typename octet_iterator>
uint32_t prior(octet_iterator& it, octet_iterator start)
{
// can't do much if it == start
if (it == start)
throw not_enough_room();
octet_iterator end = it;
// Go back until we hit either a lead octet or start
while (utf8::internal::is_trail(*(--it)))
if (it == start)
throw invalid_utf8(*it); // error - no lead byte in the sequence
return utf8::peek_next(it, end);
}
/// Deprecated in versions that include "prior"
template <typename octet_iterator>
uint32_t previous(octet_iterator& it, octet_iterator pass_start)
{
octet_iterator end = it;
while (utf8::internal::is_trail(*(--it)))
if (it == pass_start)
throw invalid_utf8(*it); // error - no lead byte in the sequence
octet_iterator temp = it;
return utf8::next(temp, end);
}
template <typename octet_iterator, typename distance_type>
void advance (octet_iterator& it, distance_type n, octet_iterator end)
{
for (distance_type i = 0; i < n; ++i)
utf8::next(it, end);
}
template <typename octet_iterator>
typename std::iterator_traits<octet_iterator>::difference_type
distance (octet_iterator first, octet_iterator last)
{
typename std::iterator_traits<octet_iterator>::difference_type dist;
for (dist = 0; first < last; ++dist)
utf8::next(first, last);
return dist;
}
template <typename u16bit_iterator, typename octet_iterator>
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
{
while (start != end) {
uint32_t cp = utf8::internal::mask16(*start++);
// Take care of surrogate pairs first
if (utf8::internal::is_lead_surrogate(cp)) {
if (start != end) {
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
if (utf8::internal::is_trail_surrogate(trail_surrogate))
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
else
throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
}
else
throw invalid_utf16(static_cast<uint16_t>(cp));
}
// Lone trail surrogate
else if (utf8::internal::is_trail_surrogate(cp))
throw invalid_utf16(static_cast<uint16_t>(cp));
result = utf8::append(cp, result);
}
return result;
}
template <typename u16bit_iterator, typename octet_iterator>
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
{
while (start < end) {
uint32_t cp = utf8::next(start, end);
if (cp > 0xffff) { //make a surrogate pair
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
}
else
*result++ = static_cast<uint16_t>(cp);
}
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
{
while (start != end)
result = utf8::append(*(start++), result);
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
{
while (start < end)
(*result++) = utf8::next(start, end);
return result;
}
// The iterator class
template <typename octet_iterator>
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
octet_iterator it;
octet_iterator range_start;
octet_iterator range_end;
public:
iterator () {}
explicit iterator (const octet_iterator& octet_it,
const octet_iterator& rangestart,
const octet_iterator& rangeend) :
it(octet_it), range_start(rangestart), range_end(rangeend)
{
if (it < range_start || it > range_end)
throw std::out_of_range("Invalid utf-8 iterator position");
}
// the default "big three" are OK
octet_iterator base () const { return it; }
uint32_t operator * () const
{
octet_iterator temp = it;
return utf8::next(temp, range_end);
}
bool operator == (const iterator& rhs) const
{
if (range_start != rhs.range_start || range_end != rhs.range_end)
throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
return (it == rhs.it);
}
bool operator != (const iterator& rhs) const
{
return !(operator == (rhs));
}
iterator& operator ++ ()
{
utf8::next(it, range_end);
return *this;
}
iterator operator ++ (int)
{
iterator temp = *this;
utf8::next(it, range_end);
return temp;
}
iterator& operator -- ()
{
utf8::prior(it, range_start);
return *this;
}
iterator operator -- (int)
{
iterator temp = *this;
utf8::prior(it, range_start);
return temp;
}
}; // class iterator
} // namespace utf8
#endif //header guard

332
3rdparty/utf8-cpp/core.h vendored Normal file
View File

@@ -0,0 +1,332 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include <iterator>
namespace utf8
{
// The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
// You may need to change them to match your system.
// These typedefs have the same names as ones from cstdint, or boost/cstdint
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
// Helper code - not intended to be directly called by the library users. May be changed at any time
namespace internal
{
// Unicode constants
// Leading (high) surrogates: 0xd800 - 0xdbff
// Trailing (low) surrogates: 0xdc00 - 0xdfff
const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
// Maximum valid value for a Unicode code point
const uint32_t CODE_POINT_MAX = 0x0010ffffu;
template<typename octet_type>
inline uint8_t mask8(octet_type oc)
{
return static_cast<uint8_t>(0xff & oc);
}
template<typename u16_type>
inline uint16_t mask16(u16_type oc)
{
return static_cast<uint16_t>(0xffff & oc);
}
template<typename octet_type>
inline bool is_trail(octet_type oc)
{
return ((utf8::internal::mask8(oc) >> 6) == 0x2);
}
template <typename u16>
inline bool is_lead_surrogate(u16 cp)
{
return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
}
template <typename u16>
inline bool is_trail_surrogate(u16 cp)
{
return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
}
template <typename u16>
inline bool is_surrogate(u16 cp)
{
return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
}
template <typename u32>
inline bool is_code_point_valid(u32 cp)
{
return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
}
template <typename octet_iterator>
inline typename std::iterator_traits<octet_iterator>::difference_type
sequence_length(octet_iterator lead_it)
{
uint8_t lead = utf8::internal::mask8(*lead_it);
if (lead < 0x80)
return 1;
else if ((lead >> 5) == 0x6)
return 2;
else if ((lead >> 4) == 0xe)
return 3;
else if ((lead >> 3) == 0x1e)
return 4;
else
return 0;
}
template <typename octet_difference_type>
inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
{
if (cp < 0x80) {
if (length != 1)
return true;
}
else if (cp < 0x800) {
if (length != 2)
return true;
}
else if (cp < 0x10000) {
if (length != 3)
return true;
}
return false;
}
enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
/// Helper for get_sequence_x
template <typename octet_iterator>
utf_error increase_safely(octet_iterator& it, octet_iterator end)
{
if (++it == end)
return NOT_ENOUGH_ROOM;
if (!utf8::internal::is_trail(*it))
return INCOMPLETE_SEQUENCE;
return UTF8_OK;
}
#define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
/// get_sequence_x functions decode utf-8 sequences of the length x
template <typename octet_iterator>
utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
return UTF8_OK;
}
template <typename octet_iterator>
utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
return UTF8_OK;
}
template <typename octet_iterator>
utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point += (*it) & 0x3f;
return UTF8_OK;
}
template <typename octet_iterator>
utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point += (*it) & 0x3f;
return UTF8_OK;
}
#undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
template <typename octet_iterator>
utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
// Save the original value of it so we can go back in case of failure
// Of course, it does not make much sense with i.e. stream iterators
octet_iterator original_it = it;
uint32_t cp = 0;
// Determine the sequence length based on the lead octet
typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
const octet_difference_type length = utf8::internal::sequence_length(it);
// Get trail octets and calculate the code point
utf_error err = UTF8_OK;
switch (length) {
case 0:
return INVALID_LEAD;
case 1:
err = utf8::internal::get_sequence_1(it, end, cp);
break;
case 2:
err = utf8::internal::get_sequence_2(it, end, cp);
break;
case 3:
err = utf8::internal::get_sequence_3(it, end, cp);
break;
case 4:
err = utf8::internal::get_sequence_4(it, end, cp);
break;
}
if (err == UTF8_OK) {
// Decoding succeeded. Now, security checks...
if (utf8::internal::is_code_point_valid(cp)) {
if (!utf8::internal::is_overlong_sequence(cp, length)){
// Passed! Return here.
code_point = cp;
++it;
return UTF8_OK;
}
else
err = OVERLONG_SEQUENCE;
}
else
err = INVALID_CODE_POINT;
}
// Failure branch - restore the original value of the iterator
it = original_it;
return err;
}
template <typename octet_iterator>
inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
uint32_t ignored;
return utf8::internal::validate_next(it, end, ignored);
}
} // namespace internal
/// The library API - functions intended to be called by the users
// Byte order mark
const uint8_t bom[] = {0xef, 0xbb, 0xbf};
template <typename octet_iterator>
octet_iterator find_invalid(octet_iterator start, octet_iterator end)
{
octet_iterator result = start;
while (result != end) {
utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
if (err_code != internal::UTF8_OK)
return result;
}
return result;
}
template <typename octet_iterator>
inline bool is_valid(octet_iterator start, octet_iterator end)
{
return (utf8::find_invalid(start, end) == end);
}
template <typename octet_iterator>
inline bool starts_with_bom (octet_iterator it, octet_iterator end)
{
return (
((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
((it != end) && (utf8::internal::mask8(*it)) == bom[2])
);
}
//Deprecated in release 2.3
template <typename octet_iterator>
inline bool is_bom (octet_iterator it)
{
return (
(utf8::internal::mask8(*it++)) == bom[0] &&
(utf8::internal::mask8(*it++)) == bom[1] &&
(utf8::internal::mask8(*it)) == bom[2]
);
}
} // namespace utf8
#endif // header guard

View File

@@ -2,6 +2,10 @@ Scott Wheeler <wheeler@kde.org>
Author, maintainer
Lukas Lalinsky <lalinsky@gmail.com>
Implementation of multiple new file formats, many bug fixes, maintainer
Tsuda Kageyu <tsuda.kageyu@gmail.com>
A lot of bug fixes and performance improvements, maintainer.
Stephen F. Booth <me@sbooth.org>
DSF metadata implementation, bug fixes, maintainer.
Ismael Orenstein <orenstein@kde.org>
Xing header implementation
Allan Sandfeld Jensen <kde@carewolf.org>
@@ -10,6 +14,8 @@ Teemu Tervo <teemu.tervo@gmx.net>
Numerous bug reports and fixes
Mathias Panzenböck <grosser.meister.morti@gmx.net>
Mod, S3M, IT and XM metadata implementations
Damien Plisson <damien78@audirvana.com>
DSDIFF metadata implementation
Please send all patches and questions to taglib-devel@kde.org rather than to
individual developers!

View File

@@ -1,64 +1,102 @@
cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
project(taglib)
cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR)
if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.12)
cmake_policy(SET CMP0022 OLD)
endif()
option(ENABLE_STATIC "Make static version of libtag" OFF)
if(ENABLE_STATIC)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
if(DEFINED ENABLE_STATIC)
message(FATAL_ERROR "This option is no longer available, use BUILD_SHARED_LIBS instead")
endif()
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
if(APPLE)
option(BUILD_FRAMEWORK "Build an OS X framework" OFF)
if(BUILD_FRAMEWORK)
set(BUILD_SHARED_LIBS ON)
#set(CMAKE_MACOSX_RPATH 1)
set(FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.")
endif()
endif()
if(NOT BUILD_SHARED_LIBS)
add_definitions(-DTAGLIB_STATIC)
set(BUILD_SHARED_LIBS OFF)
else()
set(BUILD_SHARED_LIBS ON)
endif()
OPTION(ENABLE_STATIC_RUNTIME "Visual Studio, link with runtime statically" OFF)
option(ENABLE_STATIC_RUNTIME "Visual Studio, link with runtime statically" OFF)
option(VISIBILITY_HIDDEN "Build with -fvisibility=hidden" OFF)
if(VISIBILITY_HIDDEN)
add_definitions (-fvisibility=hidden)
option(ENABLE_CCACHE "Use ccache when building libtag" OFF)
if(ENABLE_CCACHE)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif()
endif()
option(BUILD_TESTS "Build the test suite" OFF)
option(BUILD_EXAMPLES "Build the examples" OFF)
option(VISIBILITY_HIDDEN "Build with -fvisibility=hidden" OFF)
option(BUILD_TESTS "Build the test suite" OFF)
option(BUILD_EXAMPLES "Build the examples" OFF)
option(BUILD_BINDINGS "Build the bindings" ON)
option(NO_ITUNES_HACKS "Disable workarounds for iTunes bugs" OFF)
option(NO_ITUNES_HACKS "Disable workarounds for iTunes bugs" OFF)
option(PLATFORM_WINRT "Enable WinRT support" OFF)
if(PLATFORM_WINRT)
add_definitions(-DPLATFORM_WINRT)
endif()
add_definitions(-DHAVE_CONFIG_H)
set(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
## the following are directories where stuff will be installed to
set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)")
set(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH "Base directory for executables and libraries" FORCE)
set(BIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" CACHE PATH "The subdirectory to the binaries prefix (default prefix/bin)" FORCE)
set(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE)
set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The subdirectory to the header prefix" FORCE)
if(APPLE)
option(BUILD_FRAMEWORK "Build an OS X framework" OFF)
set(FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.")
endif()
set(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH "Base directory for executables and libraries")
set(BIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" CACHE PATH "The subdirectory to the binaries prefix (default prefix/bin)")
set(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})")
set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The subdirectory to the header prefix")
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif()
if (MSVC AND ENABLE_STATIC_RUNTIME)
if(MSVC AND ENABLE_STATIC_RUNTIME)
foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endforeach(flag_var)
endif()
set(TAGLIB_LIB_MAJOR_VERSION "1")
set(TAGLIB_LIB_MINOR_VERSION "8")
set(TAGLIB_LIB_PATCH_VERSION "0")
# Read version information from file taglib/toolkit/taglib.h into variables
# TAGLIB_LIB_MAJOR_VERSION, TAGLIB_LIB_MINOR_VERSION, TAGLIB_LIB_PATCH_VERSION.
foreach(version_part MAJOR MINOR PATCH)
set(version_var_name "TAGLIB_${version_part}_VERSION")
file(STRINGS taglib/toolkit/taglib.h version_line
REGEX "^#define +${version_var_name}")
if(NOT version_line)
message(FATAL_ERROR "${version_var_name} not found in taglib.h")
endif()
string(REGEX MATCH "${version_var_name} +([^ ]+)" result ${version_line})
set(TAGLIB_LIB_${version_part}_VERSION ${CMAKE_MATCH_1})
endforeach(version_part)
set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}")
# Only used to force cmake rerun when taglib.h changes.
configure_file(taglib/toolkit/taglib.h ${CMAKE_CURRENT_BINARY_DIR}/taglib.h.stamp)
if("${TAGLIB_LIB_PATCH_VERSION}" EQUAL "0")
set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}")
else()
set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}")
endif()
# 1. If the library source code has changed at all since the last update, then increment revision.
# 2. If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0.
# 3. If any interfaces have been added since the last public release, then increment age.
# 4. If any interfaces have been removed since the last public release, then set age to 0.
set(TAGLIB_SOVERSION_CURRENT 13)
# 4. If any interfaces have been removed since the last public release, then set age to 0.
set(TAGLIB_SOVERSION_CURRENT 18)
set(TAGLIB_SOVERSION_REVISION 0)
set(TAGLIB_SOVERSION_AGE 12)
set(TAGLIB_SOVERSION_AGE 17)
math(EXPR TAGLIB_SOVERSION_MAJOR "${TAGLIB_SOVERSION_CURRENT} - ${TAGLIB_SOVERSION_AGE}")
math(EXPR TAGLIB_SOVERSION_MINOR "${TAGLIB_SOVERSION_AGE}")
@@ -66,43 +104,56 @@ math(EXPR TAGLIB_SOVERSION_PATCH "${TAGLIB_SOVERSION_REVISION}")
include(ConfigureChecks.cmake)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/taglib-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib-config )
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/taglib-config DESTINATION ${BIN_INSTALL_DIR})
if(NOT WIN32)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/taglib-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/taglib-config")
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/taglib-config" DESTINATION "${BIN_INSTALL_DIR}")
endif()
if(NOT WIN32 AND NOT BUILD_FRAMEWORK)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/taglib.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib.pc )
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/taglib.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
if(WIN32)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/taglib-config.cmd.cmake" "${CMAKE_CURRENT_BINARY_DIR}/taglib-config.cmd")
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/taglib-config.cmd" DESTINATION "${BIN_INSTALL_DIR}")
endif()
if(NOT BUILD_FRAMEWORK)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/taglib.pc.cmake" "${CMAKE_CURRENT_BINARY_DIR}/taglib.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/taglib.pc" DESTINATION "${LIB_INSTALL_DIR}/pkgconfig")
endif()
if(NOT HAVE_ZLIB AND ZLIB_SOURCE)
set(HAVE_ZLIB 1)
set(HAVE_ZLIB_SOURCE 1)
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
configure_file(config-taglib.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
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)
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)
add_subdirectory(taglib)
add_subdirectory(bindings)
if(BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif(BUILD_TESTS)
add_subdirectory(examples)
if(BUILD_BINDINGS)
add_subdirectory(bindings)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.cmake ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
if(BUILD_TESTS AND NOT BUILD_SHARED_LIBS)
enable_testing()
add_subdirectory(tests)
endif()
if(BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.cmake" "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
file(COPY doc/taglib.png DESTINATION doc)
add_custom_target(docs doxygen)
# uninstall target
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
if(NOT TARGET uninstall)
add_custom_target(uninstall COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
endif()

View File

@@ -1,23 +1,244 @@
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckCXXCompilerFlag)
include(CheckCXXSourceCompiles)
include(TestLargeFiles)
# check for libz using the cmake supplied FindZLIB.cmake
find_package(ZLIB)
if(ZLIB_FOUND)
set(HAVE_ZLIB 1)
else()
set(HAVE_ZLIB 0)
# Check if the size of numeric types are suitable.
check_type_size("short" SIZEOF_SHORT)
if(NOT ${SIZEOF_SHORT} EQUAL 2)
message(FATAL_ERROR "TagLib requires that short is 16-bit wide.")
endif()
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
find_package(CppUnit)
if(NOT CppUnit_FOUND AND BUILD_TESTS)
message(STATUS "CppUnit not found, disabling tests.")
set(BUILD_TESTS OFF)
check_type_size("int" SIZEOF_INT)
if(NOT ${SIZEOF_INT} EQUAL 4)
message(FATAL_ERROR "TagLib requires that int is 32-bit wide.")
endif()
check_type_size("long long" SIZEOF_LONGLONG)
if(NOT ${SIZEOF_LONGLONG} EQUAL 8)
message(FATAL_ERROR "TagLib requires that long long is 64-bit wide.")
endif()
check_type_size("wchar_t" SIZEOF_WCHAR_T)
if(${SIZEOF_WCHAR_T} LESS 2)
message(FATAL_ERROR "TagLib requires that wchar_t is sufficient to store a UTF-16 char.")
endif()
check_type_size("float" SIZEOF_FLOAT)
if(NOT ${SIZEOF_FLOAT} EQUAL 4)
message(FATAL_ERROR "TagLib requires that float is 32-bit wide.")
endif()
check_type_size("double" SIZEOF_DOUBLE)
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("
#include <atomic>
int main() {
std::atomic_int x(1);
++x;
--x;
return 0;
}
" HAVE_STD_ATOMIC)
if(NOT HAVE_STD_ATOMIC)
check_cxx_source_compiles("
int main() {
volatile int x;
__sync_add_and_fetch(&x, 1);
int y = __sync_sub_and_fetch(&x, 1);
return 0;
}
" HAVE_GCC_ATOMIC)
if(NOT HAVE_GCC_ATOMIC)
check_cxx_source_compiles("
#include <libkern/OSAtomic.h>
int main() {
volatile int32_t x;
OSAtomicIncrement32Barrier(&x);
int32_t y = OSAtomicDecrement32Barrier(&x);
return 0;
}
" HAVE_MAC_ATOMIC)
if(NOT HAVE_MAC_ATOMIC)
check_cxx_source_compiles("
#include <windows.h>
int main() {
volatile LONG x;
InterlockedIncrement(&x);
LONG y = InterlockedDecrement(&x);
return 0;
}
" HAVE_WIN_ATOMIC)
if(NOT HAVE_WIN_ATOMIC)
check_cxx_source_compiles("
#include <ia64intrin.h>
int main() {
volatile int x;
__sync_add_and_fetch(&x, 1);
int y = __sync_sub_and_fetch(&x, 1);
return 0;
}
" HAVE_IA64_ATOMIC)
endif()
endif()
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("
int main() {
__builtin_bswap16(0);
__builtin_bswap32(0);
__builtin_bswap64(0);
return 0;
}
" HAVE_GCC_BYTESWAP)
if(NOT HAVE_GCC_BYTESWAP)
check_cxx_source_compiles("
#include <byteswap.h>
int main() {
__bswap_16(0);
__bswap_32(0);
__bswap_64(0);
return 0;
}
" HAVE_GLIBC_BYTESWAP)
if(NOT HAVE_GLIBC_BYTESWAP)
check_cxx_source_compiles("
#include <stdlib.h>
int main() {
_byteswap_ushort(0);
_byteswap_ulong(0);
_byteswap_uint64(0);
return 0;
}
" HAVE_MSC_BYTESWAP)
if(NOT HAVE_MSC_BYTESWAP)
check_cxx_source_compiles("
#include <libkern/OSByteOrder.h>
int main() {
OSSwapInt16(0);
OSSwapInt32(0);
OSSwapInt64(0);
return 0;
}
" HAVE_MAC_BYTESWAP)
if(NOT HAVE_MAC_BYTESWAP)
check_cxx_source_compiles("
#include <sys/endian.h>
int main() {
swap16(0);
swap32(0);
swap64(0);
return 0;
}
" HAVE_OPENBSD_BYTESWAP)
endif()
endif()
endif()
endif()
# Determine whether your compiler supports some safer version of vsprintf.
check_cxx_source_compiles("
#include <cstdio>
#include <cstdarg>
int main() {
char buf[20];
va_list args;
vsnprintf(buf, 20, \"%d\", args);
return 0;
}
" HAVE_VSNPRINTF)
if(NOT HAVE_VSNPRINTF)
check_cxx_source_compiles("
#include <cstdio>
#include <cstdarg>
int main() {
char buf[20];
va_list args;
vsprintf_s(buf, \"%d\", args);
return 0;
}
" HAVE_VSPRINTF_S)
endif()
# Determine whether your compiler supports ISO _strdup.
check_cxx_source_compiles("
#include <cstring>
int main() {
_strdup(0);
return 0;
}
" HAVE_ISO_STRDUP)
# Determine whether zlib is installed.
if(NOT ZLIB_SOURCE)
find_package(ZLIB)
if(ZLIB_FOUND)
set(HAVE_ZLIB 1)
else()
set(HAVE_ZLIB 0)
endif()
endif()
# Determine whether CppUnit is installed.
if(BUILD_TESTS AND NOT BUILD_SHARED_LIBS)
find_package(CppUnit)
if(NOT CppUnit_FOUND)
message(STATUS "CppUnit not found, disabling tests.")
set(BUILD_TESTS OFF)
endif()
endif()
# Detect WinRT mode
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
set(PLATFORM_WINRT 1)
endif()

70
INSTALL
View File

@@ -1,70 +0,0 @@
TagLib Installation
===================
TagLib uses the CMake build system. As a user, you will most likely want to
build TagLib in release mode and install it into a system-wide location.
This can be done using the following commands:
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_RELEASE_TYPE=Release .
make
sudo make install
In order to build the included examples, use the BUILD_EXAMPLES option:
cmake -DBUILD_EXAMPLES=ON [...]
See http://www.cmake.org/cmake/help/runningcmake.html for generic help on
running CMake.
Mac OS X
--------
On Mac OS X, you might want to build a framework that can be easily integrated
into your application. If you set the BUILD_FRAMEWORK option on, it will compile
TagLib as a framework. For example, the following command can be used to build
an Universal Binary framework with Mac OS X 10.4 as the deployment target:
cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_FRAMEWORK=ON \
-DCMAKE_C_COMPILER=/usr/bin/gcc-4.0 \
-DCMAKE_CXX_COMPILER=/usr/bin/c++-4.0 \
-DCMAKE_OSX_SYSROOT=/Developer/SDKs/MacOSX10.4u.sdk/ \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.4 \
-DCMAKE_OSX_ARCHITECTURES="ppc;i386;x86_64"
For a 10.6 Snow Leopard static library with both 32-bit and 64-bit code, use:
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.6 \
-DCMAKE_OSX_ARCHITECTURES="i386;x86_64" \
-DENABLE_STATIC=ON \
-DCMAKE_INSTALL_PREFIX="<folder you want to build to>"
After 'make', and 'make install', add libtag.a to your XCode project, and add
the include folder to the project's User Header Search Paths.
Windows
-------
For building a static library on Windows with Visual Studio 2010, cd to
the TagLib folder then:
cmake -DENABLE_STATIC=ON -DENABLE_STATIC_RUNTIME=ON -G "Visual Studio 10" ...
Including ENABLE_STATIC_RUNTIME=ON indicates you want TagLib built using the
static runtime library, rather than the DLL form of the runtime.
CMake will create a Visual Studio solution, taglib.sln that you can open and
build as normal.
Unit Tests
----------
If you want to run the test suite to make sure TagLib works properly on your
system, you need to have cppunit installed. To build the tests, include
the option -DBUILD_TESTS=on when running cmake.
The test suite has a custom target in the build system, so you can run
the tests using make:
make check

175
INSTALL.md Normal file
View File

@@ -0,0 +1,175 @@
TagLib Installation
===================
TagLib uses the CMake build system. As a user, you will most likely want to
build TagLib in release mode and install it into a system-wide location.
This can be done using the following commands:
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release .
make
sudo make install
In order to build the included examples, use the `BUILD_EXAMPLES` option:
cmake -DBUILD_EXAMPLES=ON [...]
See http://www.cmake.org/cmake/help/runningcmake.html for generic help on
running CMake.
Mac OS X
--------
On Mac OS X, you might want to build a framework that can be easily integrated
into your application. If you set the BUILD_FRAMEWORK option on, it will compile
TagLib as a framework. For example, the following command can be used to build
an Universal Binary framework with Mac OS X 10.4 as the deployment target:
cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_FRAMEWORK=ON \
-DCMAKE_C_COMPILER=/usr/bin/gcc-4.0 \
-DCMAKE_CXX_COMPILER=/usr/bin/c++-4.0 \
-DCMAKE_OSX_SYSROOT=/Developer/SDKs/MacOSX10.4u.sdk/ \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.4 \
-DCMAKE_OSX_ARCHITECTURES="ppc;i386;x86_64"
For a 10.6 Snow Leopard static library with both 32-bit and 64-bit code, use:
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.6 \
-DCMAKE_OSX_ARCHITECTURES="i386;x86_64" \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_INSTALL_PREFIX="<folder you want to build to>"
After `make`, and `make install`, add `libtag.` to your XCode project, and add
the include folder to the project's User Header Search Paths.
Windows
-------
It's Windows ... Systems vary!
This means you need to adjust things to suit your system, especially paths.
Tested with:
* Microsoft Visual Studio 2010, 2015, 2017
* Microsoft C++ Build Tools 2015, 2017 (standalone packages not requiring Visual Studio)
* Gcc by mingw-w64.sf.net v4.6.3 (Strawberry Perl 32b)
* MinGW32-4.8.0
Requirements:
* Tool chain, build environment, whatever ya want to call it ...
Installed and working.
* CMake program. (Available at: www.cmake.org)
Installed and working.
Optional:
* Zlib library.
Available in some tool chains, not all.
Search the web, take your choice.
Useful configuration options used with CMake (GUI and/or command line):
Any of the `ZLIB_` variables may be used at the command line, `ZLIB_ROOT` is only
available on the command line.
| option | description |
---------------------| ------------|
`ZLIB_ROOT=` | Where to find ZLib's root directory. Assumes parent of: `\include` and `\lib.`|
`ZLIB_INCLUDE_DIR=` | Where to find ZLib's Include directory.|
`ZLIB_LIBRARY=` | Where to find ZLib's Library.
`ZLIB_SOURCE=` | Where to find ZLib's Source Code. Alternative to `ZLIB_INCLUDE_DIR` and `ZLIB_LIBRARY`.
`CMAKE_INSTALL_PREFIX=` | Where to install Taglib. |
`CMAKE_BUILD_TYPE=` | Release, Debug, etc ... (Not available in MSVC) |
The easiest way is at the command prompt (Visual C++ command prompt for MSVS users batch file and/or shortcuts are your friends).
1. **Build the Makefiles:**
Replace "GENERATOR" with your needs.
* For MSVS: `Visual Studio XX YYYY`, e.g. `Visual Studio 14 2015`.
**Note**: As Visual Studio 2017 supports CMake, you can skip this step and open the taglib
folder in VS instead.
* For MinGW: `MinGW Makefiles`
C:\GitRoot\taglib> cmake -G "GENERATOR" -DCMAKE_INSTALL_PREFIX=C:\Libraries\taglib
Or use the CMake GUI:
1. Open CMake GUI.
2. Set paths: *Where is the source code* and *Where to build the binaries*.
In the example, both would be: `C:\GitRoot\taglib`
3. Tick: Advanced
4. Select: Configure
5. Select: Generator
6. Tick: Use default native compilers
7. Select: Finish
Wait until done.
8. If using ZLib, Scroll down.
(to the bottom of the list of options ... should go over them all)
1. Edit: `ZLIB_INCLUDE_DIR`
2. Edit: `ZLIB_LIBRARY`
9. Select: Generate
2. **Build the project**
* MSVS:
C:\GitRoot\taglib> msbuild all_build.vcxproj /p:Configuration=Release
OR (Depending on MSVS version or personal choice)
C:\GitRoot\taglib> devenv all_build.vcxproj /build Release
OR in the MSVS GUI:
1. Open MSVS.
2. Open taglib solution.
3. Set build type to: Release (look in the tool bars)
2. Hit F7 to build the solution. (project)
* MinGW:
C:\GitRoot\taglib> gmake
OR (Depending on MinGW install)
C:\GitRoot\taglib> mingw32-make
3. **Install the project**
(Change `install` to `uninstall` to uninstall the project)
* MSVS:
C:\GitRoot\taglib> msbuild install.vcxproj
OR (Depending on MSVC version or personal choice)
C:\GitRoot\taglib> devenv install.vcxproj
Or in the MSVS GUI:
1. Open project.
2. Open Solution Explorer.
3. Right Click: INSTALL
4. Select: Project Only
5. Select: Build Only INSTALL
* MinGW:
C:\GitRoot\taglib> gmake install
OR (Depending on MinGW install)
C:\GitRoot\taglib> mingw32-make install
To build a static library, set the following two options with CMake:
-DBUILD_SHARED_LIBS=OFF -DENABLE_STATIC_RUNTIME=ON
Including `ENABLE_STATIC_RUNTIME=ON` indicates you want TagLib built using the
static runtime library, rather than the DLL form of the runtime.
Unit Tests
----------
If you want to run the test suite to make sure TagLib works properly on your
system, you need to have cppunit installed. To build the tests, include
the option `-DBUILD_TESTS=on` when running cmake.
The test suite has a custom target in the build system, so you can run
the tests using make:
make check

167
NEWS
View File

@@ -1,5 +1,170 @@
============================
* Added support for DSF and DSDIFF files.
* Added support for WinRT.
* Added support for classical music tags of iTunes 12.5.
* Added support for file descriptor to FileStream.
* Added support for 'cmID', 'purl', 'egid' MP4 atoms.
* Enabled FileRef to detect file types based on the stream content.
* Dropped support for Windows 9x and NT 4.0 or older.
* Check for mandatory header objects in ASF files.
* Fixed OOB read on invalid Ogg FLAC files (CVE-2018-11439).
* Fixed handling of empty MPEG files.
* Fixed reading MP4 atoms with zero length.
* Fixed reading FLAC files with zero-sized seektables.
* Fixed handling of lowercase field names in Vorbis Comments.
* Fixed handling of 'rate' atoms in MP4 files.
* Fixed handling of invalid UTF-8 sequences.
* Fixed possible file corruptions when saving Ogg files.
* TableOfContentsFrame::toString() improved.
* UserTextIdentificationFrame::toString() improved.
* Marked FileRef::create() deprecated.
* Several smaller bug fixes and performance improvements.
TagLib 1.11.1 (Oct 24, 2016)
============================
* Fixed binary incompatible change in TagLib::String.
* Fixed reading ID3v2 CTOC frames with a lot of entries.
* Fixed seeking ByteVectorStream from the end.
TagLib 1.11 (Apr 29, 2016)
==========================
1.11:
* Fixed reading APE items with long keys.
* Fixed reading ID3v2 SYLT frames when description is empty.
1.11 BETA 2:
* Better handling of PCM WAV files with a 'fact' chunk.
* Better handling of corrupted APE tags.
* Efficient decoding of unsynchronized ID3v2 frames.
* Fixed text encoding when saving certain frames in ID3v2.3 tags.
* Fixed updating the size of RIFF files when removing chunks.
* Several smaller bug fixes and performance improvements.
1.11 BETA:
* New API for creating FileRef from IOStream.
* Added support for ID3v2 PCST and WFED frames.
* Added support for pictures in XiphComment.
* Added String::clear().
* Added FLAC::File::strip() for removing non-standard tags.
* Added alternative functions to XiphComment::removeField().
* Added BUILD_BINDINGS build option.
* Added ENABLE_CCACHE build option.
* Replaced ENABLE_STATIC build option with BUILD_SHARED_LIBS.
* Better handling of duplicate ID3v2 tags in all kinds of files.
* Better handling of duplicate tag chunks in WAV files.
* Better handling of duplicate tag chunks in AIFF files.
* Better handling of duplicate Vorbis comment blocks in FLAC files.
* Better handling of broken MPEG audio frames.
* Fixed crash when calling File::properties() after strip().
* Fixed crash when parsing certain MPEG files.
* Fixed crash when saving Ogg files.
* Fixed possible file corruptions when saving ASF files.
* Fixed possible file corruptions when saving FLAC files.
* Fixed possible file corruptions when saving MP4 files.
* Fixed possible file corruptions when saving MPEG files.
* Fixed possible file corruptions when saving APE files.
* Fixed possible file corruptions when saving Musepack files.
* Fixed possible file corruptions when saving WavPack files.
* Fixed updating the comment field of Vorbis comments.
* Fixed reading date and time in ID3v2.3 tags.
* Marked ByteVector::null and ByteVector::isNull() deprecated.
* Marked String::null and String::isNull() deprecated.
* Marked XiphComment::removeField() deprecated.
* Marked Ogg::Page::getCopyWithNewPageSequenceNumber() deprecated. It returns null.
* Marked custom integer types deprecated.
* Many smaller bug fixes and performance improvements.
TagLib 1.10 (Nov 11, 2015)
==========================
1.10:
* Added new options to the tagwriter example.
* Fixed self-assignment operator in some types.
* Fixed extraction of MP4 tag keys with an empty list.
1.10 BETA:
* New API for the audio length in milliseconds.
* Added support for ID3v2 ETCO and SYLT frames.
* Added support for album artist in PropertyMap API of MP4 files.
* Added support for embedded frames in ID3v2 CHAP and CTOC frames.
* Added support for AIFF-C files.
* Better handling of duplicate ID3v2 tags in MPEG files.
* Allowed generating taglib.pc on Windows.
* Added ZLIB_SOURCE build option.
* Fixed backwards-incompatible change in TagLib::String when constructing UTF16 strings.
* Fixed crash when parsing certain FLAC files.
* Fixed crash when encoding empty strings.
* Fixed saving of certain XM files on OS X.
* Changed Xiph and APE generic getters to return space-concatenated values.
* Fixed possible file corruptions when removing tags from WAV files.
* Added support for MP4 files with 64-bit atoms in certain 64-bit environments.
* Prevented ID3v2 padding from being too large.
* Fixed crash when parsing corrupted APE files.
* Fixed crash when parsing corrupted WAV files.
* Fixed crash when parsing corrupted Ogg FLAC files.
* Fixed crash when parsing corrupted MPEG files.
* Fixed saving empty tags in WAV files.
* Fixed crash when parsing corrupted Musepack files.
* Fixed possible memory leaks when parsing AIFF and WAV files.
* Fixed crash when parsing corrupted MP4 files.
* Stopped writing empty ID3v2 frames.
* Fixed possible file corruptions when saving WMA files.
* Added TagLib::MP4::Tag::isEmpty().
* Added accessors to manipulate MP4 tags.
* Fixed crash when parsing corrupted WavPack files.
* Fixed seeking MPEG frames.
* Fixed reading FLAC files with zero-sized padding blocks.
* Added support for reading the encoder information of WMA files.
* Added support for reading the codec of WAV files.
* Added support for multi channel WavPack files.
* Added support for reading the nominal bitrate of Ogg Speex files.
* Added support for VBR headers in MPEG files.
* Marked FLAC::File::streamInfoData() deprecated. It returns an empty ByteVector.
* Marked FLAC::File::streamLength() deprecated. It returns zero.
* Fixed possible file corruptions when adding an ID3v1 tag to FLAC files.
* Many smaller bug fixes and performance improvements.
TagLib 1.9.1 (Oct 8, 2013)
==========================
* Fixed binary incompatible change in TagLib::Map and TagLib::List.
* Fixed constructing String from ByteVector.
* Fixed compilation on MSVC with the /Zc:wchar_t- option.
* Fixed detecting of RIFF files with invalid chunk sizes.
* Added TagLib::MP4::Properties::codec().
TagLib 1.9 (Oct 6, 2013)
========================
* Added support for the Ogg Opus file format.
* Added support for INFO tags in WAV files.
* Changed FileStream to use Windows file API.
* Included taglib-config.cmd script for Windows.
* New ID3v1::Tag methods for working directly with genre numbers.
* New MPEG::File methods for checking which tags are saved in the file.
* Added support for the PropertyMap API to ASF and MP4 files.
* Added MusicBrainz identifiers to the PropertyMap API.
* Allowed reading of MP4 cover art without an explicitly specified format.
* Better parsing of corrupted FLAC files.
* Fixed saving of PropertyMap comments without description into ID3v2 tags.
* Fixed crash when parsing certain XM files.
* Fixed compilation of unit test with clang.
* Better handling of files that can't be open or have read-only permissions.
* Improved atomic reference counting.
* New hookable API for debug messages.
* More complete Windows install instructions.
* Many smaller bug fixes and performance improvements.
TagLib 1.8 (Sep 6, 2012)
==============================
========================
1.8:

26
README.md Normal file
View File

@@ -0,0 +1,26 @@
# TagLib
[![Build Status](https://travis-ci.org/taglib/taglib.svg?branch=master)](https://travis-ci.org/taglib/taglib)
### TagLib Audio Metadata Library
http://taglib.org/
TagLib is a library for reading and editing the metadata of several
popular audio formats. Currently it supports both ID3v1 and [ID3v2][]
for MP3 files, [Ogg Vorbis][] comments and ID3 tags
in [FLAC][], MPC, Speex, WavPack, TrueAudio, WAV, AIFF, MP4, APE,
DSF, DFF, and ASF files.
TagLib is distributed under the [GNU Lesser General Public License][]
(LGPL) and [Mozilla Public License][] (MPL). Essentially that means that
it may be used in proprietary applications, but if changes are made to
TagLib they must be contributed back to the project. Please review the
licenses if you are considering using TagLib in your project.
[ID3v2]: http://www.id3.org
[Ogg Vorbis]: http://vorbis.com/
[FLAC]: https://xiph.org/flac/
[GNU Lesser General Public License]: http://www.gnu.org/licenses/lgpl.html
[Mozilla Public License]: http://www.mozilla.org/MPL/MPL-1.1.html

View File

@@ -21,7 +21,14 @@ set(tag_c_HDRS tag_c.h)
add_library(tag_c tag_c.cpp ${tag_c_HDRS})
target_link_libraries(tag_c tag)
set_target_properties(tag_c PROPERTIES PUBLIC_HEADER "${tag_c_HDRS}")
set_target_properties(tag_c PROPERTIES
PUBLIC_HEADER "${tag_c_HDRS}"
DEFINE_SYMBOL MAKE_TAGLIB_LIB
)
if(VISIBILITY_HIDDEN)
set_target_properties(tag_c PROPERTIES C_VISIBILITY_PRESET hidden
)
endif()
if(BUILD_FRAMEWORK)
set_target_properties(tag_c PROPERTIES FRAMEWORK TRUE)
endif()
@@ -61,7 +68,7 @@ install(TARGETS tag_c
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/taglib
)
if(NOT WIN32 AND NOT BUILD_FRAMEWORK)
if(NOT BUILD_FRAMEWORK)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/taglib_c.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib_c.pc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/taglib_c.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
endif()

View File

@@ -20,7 +20,7 @@
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
# include <config.h>
#endif
#include <stdlib.h>
@@ -44,18 +44,41 @@
using namespace TagLib;
static List<char *> strings;
static bool unicodeStrings = true;
static bool stringManagementEnabled = true;
namespace
{
List<char *> strings;
bool unicodeStrings = true;
bool stringManagementEnabled = true;
char *stringToCharArray(const String &s)
{
const std::string str = s.to8Bit(unicodeStrings);
#ifdef HAVE_ISO_STRDUP
return ::_strdup(str.c_str());
#else
return ::strdup(str.c_str());
#endif
}
String charArrayToString(const char *s)
{
return String(s, unicodeStrings ? String::UTF8 : String::Latin1);
}
}
void taglib_set_strings_unicode(BOOL unicode)
{
unicodeStrings = bool(unicode);
unicodeStrings = (unicode != 0);
}
void taglib_set_string_management_enabled(BOOL management)
{
stringManagementEnabled = bool(management);
stringManagementEnabled = (management != 0);
}
void taglib_free(void* pointer)
@@ -69,64 +92,62 @@ 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;
}
return 0;
}
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();
}
////////////////////////////////////////////////////////////////////////////////
@@ -136,7 +157,7 @@ BOOL taglib_file_save(TagLib_File *file)
char *taglib_tag_title(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
char *s = ::strdup(t->title().toCString(unicodeStrings));
char *s = stringToCharArray(t->title());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -145,7 +166,7 @@ char *taglib_tag_title(const TagLib_Tag *tag)
char *taglib_tag_artist(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
char *s = ::strdup(t->artist().toCString(unicodeStrings));
char *s = stringToCharArray(t->artist());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -154,7 +175,7 @@ char *taglib_tag_artist(const TagLib_Tag *tag)
char *taglib_tag_album(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
char *s = ::strdup(t->album().toCString(unicodeStrings));
char *s = stringToCharArray(t->album());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -163,7 +184,7 @@ char *taglib_tag_album(const TagLib_Tag *tag)
char *taglib_tag_comment(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
char *s = ::strdup(t->comment().toCString(unicodeStrings));
char *s = stringToCharArray(t->comment());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -172,7 +193,7 @@ char *taglib_tag_comment(const TagLib_Tag *tag)
char *taglib_tag_genre(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
char *s = ::strdup(t->genre().toCString(unicodeStrings));
char *s = stringToCharArray(t->genre());
if(stringManagementEnabled)
strings.append(s);
return s;
@@ -193,31 +214,31 @@ unsigned int taglib_tag_track(const TagLib_Tag *tag)
void taglib_tag_set_title(TagLib_Tag *tag, const char *title)
{
Tag *t = reinterpret_cast<Tag *>(tag);
t->setTitle(String(title, unicodeStrings ? String::UTF8 : String::Latin1));
t->setTitle(charArrayToString(title));
}
void taglib_tag_set_artist(TagLib_Tag *tag, const char *artist)
{
Tag *t = reinterpret_cast<Tag *>(tag);
t->setArtist(String(artist, unicodeStrings ? String::UTF8 : String::Latin1));
t->setArtist(charArrayToString(artist));
}
void taglib_tag_set_album(TagLib_Tag *tag, const char *album)
{
Tag *t = reinterpret_cast<Tag *>(tag);
t->setAlbum(String(album, unicodeStrings ? String::UTF8 : String::Latin1));
t->setAlbum(charArrayToString(album));
}
void taglib_tag_set_comment(TagLib_Tag *tag, const char *comment)
{
Tag *t = reinterpret_cast<Tag *>(tag);
t->setComment(String(comment, unicodeStrings ? String::UTF8 : String::Latin1));
t->setComment(charArrayToString(comment));
}
void taglib_tag_set_genre(TagLib_Tag *tag, const char *genre)
{
Tag *t = reinterpret_cast<Tag *>(tag);
t->setGenre(String(genre, unicodeStrings ? String::UTF8 : String::Latin1));
t->setGenre(charArrayToString(genre));
}
void taglib_tag_set_year(TagLib_Tag *tag, unsigned int year)
@@ -237,7 +258,7 @@ void taglib_tag_free_strings()
if(!stringManagementEnabled)
return;
for(List<char *>::Iterator it = strings.begin(); it != strings.end(); ++it)
for(List<char *>::ConstIterator it = strings.begin(); it != strings.end(); ++it)
free(*it);
strings.clear();
}

View File

@@ -29,7 +29,9 @@
extern "C" {
#endif
#if defined(_WIN32) || defined(_WIN64)
#if defined(TAGLIB_STATIC)
#define TAGLIB_C_EXPORT
#elif defined(_WIN32) || defined(_WIN64)
#ifdef MAKE_TAGLIB_C_LIB
#define TAGLIB_C_EXPORT __declspec(dllexport)
#else
@@ -122,7 +124,7 @@ TAGLIB_C_EXPORT TagLib_File *taglib_file_new_type(const char *filename, TagLib_F
TAGLIB_C_EXPORT void taglib_file_free(TagLib_File *file);
/*!
* Returns true if the file is open and readble and valid information for
* Returns true if the file is open and readable and valid information for
* the Tag and / or AudioProperties was found.
*/
@@ -135,7 +137,7 @@ TAGLIB_C_EXPORT BOOL taglib_file_is_valid(const TagLib_File *file);
TAGLIB_C_EXPORT TagLib_Tag *taglib_file_tag(const TagLib_File *file);
/*!
* Returns a pointer to the the audio properties associated with this file. This
* Returns a pointer to the audio properties associated with this file. This
* will be freed automatically when the file is freed.
*/
TAGLIB_C_EXPORT const TagLib_AudioProperties *taglib_file_audioproperties(const TagLib_File *file);

View File

@@ -7,6 +7,6 @@ includedir=${INCLUDE_INSTALL_DIR}
Name: TagLib C Bindings
Description: Audio meta-data library (C bindings)
Requires: taglib
Version: ${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}
Version: ${TAGLIB_LIB_VERSION_STRING}
Libs: -L${LIB_INSTALL_DIR} -ltag_c
Cflags: -I${INCLUDE_INSTALL_DIR}/taglib

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

@@ -1,11 +0,0 @@
/* config-taglib.h. Generated by cmake from config-taglib.h.cmake */
/* Define if you have libz */
#cmakedefine HAVE_ZLIB 1
#cmakedefine NO_ITUNES_HACKS 1
#cmakedefine WITH_ASF 1
#cmakedefine WITH_MP4 1
#cmakedefine TESTS_DIR "@TESTS_DIR@"

43
config.h.cmake Normal file
View File

@@ -0,0 +1,43 @@
/* config.h. Generated by cmake from config.h.cmake */
#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
#cmakedefine HAVE_MSC_BYTESWAP 1
#cmakedefine HAVE_MAC_BYTESWAP 1
#cmakedefine HAVE_OPENBSD_BYTESWAP 1
/* Defined if your compiler supports some atomic operations */
#cmakedefine HAVE_STD_ATOMIC 1
#cmakedefine HAVE_GCC_ATOMIC 1
#cmakedefine HAVE_MAC_ATOMIC 1
#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
/* Defined if your compiler supports ISO _strdup */
#cmakedefine HAVE_ISO_STRDUP 1
/* Defined if zlib is installed */
#cmakedefine HAVE_ZLIB 1
/* Indicates whether debug messages are shown even in release mode */
#cmakedefine TRACE_IN_RELEASE 1
#cmakedefine TESTS_DIR "@TESTS_DIR@"
#endif

View File

@@ -1,50 +1,43 @@
if(BUILD_EXAMPLES)
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../taglib
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/toolkit
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ape
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v1
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2
${CMAKE_CURRENT_SOURCE_DIR}/../bindings/c/ )
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../taglib
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/toolkit
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ape
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v1
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2
${CMAKE_CURRENT_SOURCE_DIR}/../bindings/c/
)
if(ENABLE_STATIC)
add_definitions(-DTAGLIB_STATIC)
endif(ENABLE_STATIC)
if(NOT BUILD_SHARED_LIBS)
add_definitions(-DTAGLIB_STATIC)
endif()
########### next target ###############
ADD_EXECUTABLE(tagreader tagreader.cpp)
TARGET_LINK_LIBRARIES(tagreader tag )
add_executable(tagreader tagreader.cpp)
target_link_libraries(tagreader tag)
########### next target ###############
ADD_EXECUTABLE(tagreader_c tagreader_c.c)
TARGET_LINK_LIBRARIES(tagreader_c tag_c )
add_executable(tagreader_c tagreader_c.c)
target_link_libraries(tagreader_c tag_c)
########### next target ###############
ADD_EXECUTABLE(tagwriter tagwriter.cpp)
TARGET_LINK_LIBRARIES(tagwriter tag )
add_executable(tagwriter tagwriter.cpp)
target_link_libraries(tagwriter tag)
########### next target ###############
ADD_EXECUTABLE(framelist framelist.cpp)
TARGET_LINK_LIBRARIES(framelist tag )
add_executable(framelist framelist.cpp)
target_link_libraries(framelist tag)
########### next target ###############
ADD_EXECUTABLE(strip-id3v1 strip-id3v1.cpp)
add_executable(strip-id3v1 strip-id3v1.cpp)
target_link_libraries(strip-id3v1 tag)
TARGET_LINK_LIBRARIES(strip-id3v1 tag )
endif(BUILD_EXAMPLES)
########### next target ###############
add_executable(inspect inspect.cpp)
target_link_libraries(inspect tag)

View File

@@ -95,7 +95,10 @@ int main(int argc, char *argv[])
for(APE::ItemListMap::ConstIterator it = ape->itemListMap().begin();
it != ape->itemListMap().end(); ++it)
{
cout << (*it).first << " - \"" << (*it).second.toString() << "\"" << endl;
if((*it).second.type() != APE::Item::Binary)
cout << (*it).first << " - \"" << (*it).second.toString() << "\"" << endl;
else
cout << (*it).first << " - Binary data (" << (*it).second.binaryData().size() << " bytes)" << endl;
}
}
else

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

@@ -23,20 +23,16 @@
*/
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <fileref.h>
#include <tag.h>
#include <tpicturemap.h>
#include <tpropertymap.h>
using namespace std;
TagLib::String formatSeconds(int seconds)
{
char secondsString[3];
sprintf(secondsString, "%02i", seconds);
return secondsString;
}
int main(int argc, char *argv[])
{
for(int i = 1; i < argc; i++) {
@@ -49,14 +45,33 @@ int main(int argc, char *argv[])
TagLib::Tag *tag = f.tag();
cout << "-- TAG --" << 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 << "-- 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;
if(!tag->pictures().isEmpty())
cout << "pictures -" << tag->pictures() << endl;
TagLib::PropertyMap tags = f.file()->properties();
unsigned int longest = 0;
for(TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) {
if (i->first.size() > longest) {
longest = i->first.size();
}
}
cout << "-- TAG (properties) --" << endl;
for(TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) {
for(TagLib::StringList::ConstIterator j = i->second.begin(); j != i->second.end(); ++j) {
cout << left << std::setw(longest) << i->first << " - " << '"' << *j << '"' << endl;
}
}
}
if(!f.isNull() && f.audioProperties()) {
@@ -70,7 +85,7 @@ int main(int argc, char *argv[])
cout << "bitrate - " << properties->bitrate() << endl;
cout << "sample rate - " << properties->sampleRate() << endl;
cout << "channels - " << properties->channels() << endl;
cout << "length - " << minutes << ":" << formatSeconds(seconds) << endl;
cout << "length - " << minutes << ":" << setfill('0') << setw(2) << seconds << endl;
}
}
return 0;

View File

@@ -22,7 +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>
@@ -33,7 +36,10 @@
#include <tlist.h>
#include <fileref.h>
#include <tfile.h>
#include <tpicturemap.h>
#include <tag.h>
#include <tpropertymap.h>
using namespace std;
@@ -65,11 +71,33 @@ void usage()
cout << " -g <genre>" << endl;
cout << " -y <year>" << endl;
cout << " -T <track>" << endl;
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);
}
void checkForRejectedProperties(const TagLib::PropertyMap &tags)
{ // stolen from tagreader.cpp
if(tags.size() > 0) {
unsigned int longest = 0;
for(TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) {
if(i->first.size() > longest) {
longest = i->first.size();
}
}
cout << "-- rejected TAGs (properties) --" << endl;
for(TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) {
for(TagLib::StringList::ConstIterator j = i->second.begin(); j != i->second.end(); ++j) {
cout << left << std::setw(longest) << i->first << " - " << '"' << *j << '"' << endl;
}
}
}
}
int main(int argc, char *argv[])
{
TagLib::List<TagLib::FileRef> fileList;
@@ -87,13 +115,15 @@ 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>::Iterator it;
for(it = fileList.begin(); it != fileList.end(); ++it) {
@@ -121,6 +151,54 @@ int main(int argc, char *argv[])
case 'T':
t->setTrack(value.toInt());
break;
case 'R':
case 'I':
if(i + 2 < argc) {
TagLib::PropertyMap map = (*it).file()->properties ();
if(field == 'R') {
map.replace(value, TagLib::String(argv[i + 2]));
}
else {
map.insert(value, TagLib::String(argv[i + 2]));
}
++i;
checkForRejectedProperties((*it).file()->setProperties(map));
}
else {
usage();
}
break;
case 'D': {
TagLib::PropertyMap map = (*it).file()->properties();
map.erase(value);
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;
@@ -131,7 +209,7 @@ int main(int argc, char *argv[])
usage();
}
TagLib::List<TagLib::FileRef>::Iterator it;
TagLib::List<TagLib::FileRef>::ConstIterator it;
for(it = fileList.begin(); it != fileList.end(); ++it)
(*it).file()->save();

View File

@@ -35,7 +35,7 @@ do
flags="$flags -I$includedir/taglib"
;;
--version)
echo ${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}
echo ${TAGLIB_LIB_VERSION_STRING}
;;
--prefix)
echo $prefix

35
taglib-config.cmd.cmake Normal file
View File

@@ -0,0 +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

View File

@@ -1,11 +1,11 @@
prefix=${CMAKE_INSTALL_PREFIX}
exec_prefix=${CMAKE_INSTALL_PREFIX}
libdir=${LIB_INSTALL_DIR}
includedir=${INCLUDE_INSTALL_DIR}
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@LIB_INSTALL_DIR@
includedir=@INCLUDE_INSTALL_DIR@
Name: TagLib
Description: Audio meta-data library
Requires:
Version: ${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}
Libs: -L${LIB_INSTALL_DIR} -ltag
Cflags: -I${INCLUDE_INSTALL_DIR}/taglib
Version: @TAGLIB_LIB_VERSION_STRING@
Libs: -L${libdir} -ltag
Cflags: -I${includedir}/taglib

View File

@@ -10,6 +10,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/mp4
${CMAKE_CURRENT_SOURCE_DIR}/ogg/vorbis
${CMAKE_CURRENT_SOURCE_DIR}/ogg/speex
${CMAKE_CURRENT_SOURCE_DIR}/ogg/opus
${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v2
${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v2/frames
${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v1
@@ -23,10 +24,17 @@ 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
)
if(ZLIB_FOUND)
include_directories(${ZLIB_INCLUDE_DIR})
elseif(HAVE_ZLIB_SOURCE)
include_directories(${ZLIB_SOURCE})
endif()
set(tag_HDRS
@@ -34,12 +42,12 @@ set(tag_HDRS
fileref.h
audioproperties.h
taglib_export.h
${CMAKE_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
@@ -48,7 +56,11 @@ 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
mpeg/mpegfile.h
mpeg/mpegproperties.h
mpeg/mpegheader.h
@@ -64,16 +76,21 @@ set(tag_HDRS
mpeg/id3v2/id3v2tag.h
mpeg/id3v2/frames/attachedpictureframe.h
mpeg/id3v2/frames/commentsframe.h
mpeg/id3v2/frames/eventtimingcodesframe.h
mpeg/id3v2/frames/generalencapsulatedobjectframe.h
mpeg/id3v2/frames/ownershipframe.h
mpeg/id3v2/frames/popularimeterframe.h
mpeg/id3v2/frames/privateframe.h
mpeg/id3v2/frames/relativevolumeframe.h
mpeg/id3v2/frames/synchronizedlyricsframe.h
mpeg/id3v2/frames/textidentificationframe.h
mpeg/id3v2/frames/uniquefileidentifierframe.h
mpeg/id3v2/frames/unknownframe.h
mpeg/id3v2/frames/unsynchronizedlyricsframe.h
mpeg/id3v2/frames/urllinkframe.h
mpeg/id3v2/frames/chapterframe.h
mpeg/id3v2/frames/tableofcontentsframe.h
mpeg/id3v2/frames/podcastframe.h
ogg/oggfile.h
ogg/oggpage.h
ogg/oggpageheader.h
@@ -83,6 +100,8 @@ set(tag_HDRS
ogg/flac/oggflacfile.h
ogg/speex/speexfile.h
ogg/speex/speexproperties.h
ogg/opus/opusfile.h
ogg/opus/opusproperties.h
flac/flacfile.h
flac/flacpicture.h
flac/flacproperties.h
@@ -103,6 +122,7 @@ set(tag_HDRS
riff/aiff/aiffproperties.h
riff/wav/wavfile.h
riff/wav/wavproperties.h
riff/wav/infotag.h
asf/asffile.h
asf/asfproperties.h
asf/asftag.h
@@ -124,6 +144,17 @@ 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
dsdiff/dsdiffproperties.h
dsdiff/dsdiffdiintag.h
)
set(mpeg_SRCS
@@ -151,16 +182,21 @@ set(id3v2_SRCS
set(frames_SRCS
mpeg/id3v2/frames/attachedpictureframe.cpp
mpeg/id3v2/frames/commentsframe.cpp
mpeg/id3v2/frames/eventtimingcodesframe.cpp
mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp
mpeg/id3v2/frames/ownershipframe.cpp
mpeg/id3v2/frames/popularimeterframe.cpp
mpeg/id3v2/frames/privateframe.cpp
mpeg/id3v2/frames/relativevolumeframe.cpp
mpeg/id3v2/frames/synchronizedlyricsframe.cpp
mpeg/id3v2/frames/textidentificationframe.cpp
mpeg/id3v2/frames/uniquefileidentifierframe.cpp
mpeg/id3v2/frames/unknownframe.cpp
mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp
mpeg/id3v2/frames/urllinkframe.cpp
mpeg/id3v2/frames/chapterframe.cpp
mpeg/id3v2/frames/tableofcontentsframe.cpp
mpeg/id3v2/frames/podcastframe.cpp
)
set(ogg_SRCS
@@ -219,6 +255,11 @@ set(speex_SRCS
ogg/speex/speexproperties.cpp
)
set(opus_SRCS
ogg/opus/opusfile.cpp
ogg/opus/opusproperties.cpp
)
set(trueaudio_SRCS
trueaudio/trueaudiofile.cpp
trueaudio/trueaudioproperties.cpp
@@ -244,6 +285,7 @@ set(aiff_SRCS
set(wav_SRCS
riff/wav/wavfile.cpp
riff/wav/wavproperties.cpp
riff/wav/infotag.cpp
)
set(mod_SRCS
@@ -268,9 +310,32 @@ set(xm_SRCS
xm/xmproperties.cpp
)
set(dsf_SRCS
dsf/dsffile.cpp
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
dsdiff/dsdiffdiintag.cpp
)
set(toolkit_SRCS
toolkit/taglib.cpp
toolkit/tstring.cpp
toolkit/tstringlist.cpp
toolkit/tstringhandler.cpp
toolkit/tbytevector.cpp
toolkit/tbytevectorlist.cpp
toolkit/tbytevectorstream.cpp
@@ -278,25 +343,43 @@ set(toolkit_SRCS
toolkit/tfile.cpp
toolkit/tfilestream.cpp
toolkit/tdebug.cpp
toolkit/tpicture.cpp
toolkit/tpicturemap.cpp
toolkit/tpropertymap.cpp
toolkit/unicode.cpp
toolkit/trefcounter.cpp
toolkit/tdebuglistener.cpp
toolkit/tzlib.cpp
)
if(HAVE_ZLIB_SOURCE)
set(zlib_SRCS
${ZLIB_SOURCE}/adler32.c
${ZLIB_SOURCE}/crc32.c
${ZLIB_SOURCE}/inffast.c
${ZLIB_SOURCE}/inflate.c
${ZLIB_SOURCE}/inftrees.c
${ZLIB_SOURCE}/zutil.c
)
endif()
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}
${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
fileref.cpp
audioproperties.cpp
tagutils.cpp
)
add_library(tag ${tag_LIB_SRCS} ${tag_HDRS})
if(ZLIB_FOUND)
target_link_libraries(tag ${ZLIB_LIBRARIES})
if(HAVE_ZLIB AND NOT HAVE_ZLIB_SOURCE)
target_link_libraries(tag ${ZLIB_LIBRARIES})
endif()
set_target_properties(tag PROPERTIES
@@ -307,15 +390,25 @@ set_target_properties(tag PROPERTIES
LINK_INTERFACE_LIBRARIES ""
PUBLIC_HEADER "${tag_HDRS}"
)
if(VISIBILITY_HIDDEN)
set_target_properties(tag PROPERTIES C_VISIBILITY_PRESET hidden
)
endif()
if(BUILD_FRAMEWORK)
set_target_properties(tag PROPERTIES FRAMEWORK TRUE)
unset(INSTALL_NAME_DIR)
set_target_properties(tag PROPERTIES
FRAMEWORK TRUE
MACOSX_RPATH 1
VERSION "A"
SOVERSION "A"
)
endif()
install(TARGETS tag
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/taglib
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/taglib
)

View File

@@ -36,10 +36,12 @@
#include <tdebug.h>
#include <tagunion.h>
#include <id3v1tag.h>
#include <id3v2header.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include <tsmartptr.h>
#include "apefile.h"
#include "apetag.h"
#include "apefooter.h"
@@ -47,7 +49,7 @@ using namespace TagLib;
namespace
{
enum { ApeAPEIndex, ApeID3v1Index };
enum { ApeAPEIndex = 0, ApeID3v1Index = 1 };
}
class APE::File::FilePrivate
@@ -57,47 +59,53 @@ public:
APELocation(-1),
APESize(0),
ID3v1Location(-1),
properties(0),
hasAPE(false),
hasID3v1(false) {}
ID3v2Location(-1),
ID3v2Size(0) {}
~FilePrivate()
{
delete properties;
}
long long APELocation;
long long APESize;
long APELocation;
uint APESize;
long long ID3v1Location;
long ID3v1Location;
SCOPED_PTR<ID3v2::Header> ID3v2Header;
long long ID3v2Location;
long long ID3v2Size;
TagUnion tag;
DoubleTagUnion tag;
Properties *properties;
// These indicate whether the file *on disk* has these tags, not if
// this data structure does. This is used in computing offsets.
bool hasAPE;
bool hasID3v1;
SCOPED_PTR<AudioProperties> properties;
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
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 ") != ByteVector::npos());
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
APE::File::File(FileName file, bool readProperties,
Properties::ReadStyle propertiesStyle) : TagLib::File(file)
APE::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
TagLib::File(file),
d(new FilePrivate())
{
d = new FilePrivate;
read(readProperties, propertiesStyle);
if(isOpen())
read(readProperties);
}
APE::File::File(IOStream *stream, bool readProperties,
Properties::ReadStyle propertiesStyle) : TagLib::File(stream)
APE::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) :
TagLib::File(stream),
d(new FilePrivate())
{
d = new FilePrivate;
read(readProperties, propertiesStyle);
if(isOpen())
read(readProperties);
}
APE::File::~File()
@@ -110,36 +118,17 @@ TagLib::Tag *APE::File::tag() const
return &d->tag;
}
PropertyMap APE::File::properties() const
{
if(d->hasAPE)
return d->tag.access<APE::Tag>(ApeAPEIndex, false)->properties();
if(d->hasID3v1)
return d->tag.access<ID3v1::Tag>(ApeID3v1Index, false)->properties();
return PropertyMap();
}
void APE::File::removeUnsupportedProperties(const StringList &properties)
{
if(d->hasAPE)
d->tag.access<APE::Tag>(ApeAPEIndex, false)->removeUnsupportedProperties(properties);
if(d->hasID3v1)
d->tag.access<ID3v1::Tag>(ApeID3v1Index, false)->removeUnsupportedProperties(properties);
}
PropertyMap APE::File::setProperties(const PropertyMap &properties)
{
if(d->hasAPE)
return d->tag.access<APE::Tag>(ApeAPEIndex, false)->setProperties(properties);
else if(d->hasID3v1)
return d->tag.access<ID3v1::Tag>(ApeID3v1Index, false)->setProperties(properties);
else
return d->tag.access<APE::Tag>(ApeAPEIndex, true)->setProperties(properties);
if(ID3v1Tag())
ID3v1Tag()->setProperties(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()
@@ -151,64 +140,67 @@ bool APE::File::save()
// Update ID3v1 tag
if(ID3v1Tag()) {
if(d->hasID3v1) {
if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
// ID3v1 tag is not empty. Update the old one or create a new one.
if(d->ID3v1Location >= 0) {
seek(d->ID3v1Location);
writeBlock(ID3v1Tag()->render());
}
else {
seek(0, End);
d->ID3v1Location = tell();
writeBlock(ID3v1Tag()->render());
d->hasID3v1 = true;
}
writeBlock(ID3v1Tag()->render());
}
else {
if(d->hasID3v1) {
removeBlock(d->ID3v1Location, 128);
d->hasID3v1 = false;
if(d->hasAPE) {
if(d->APELocation > d->ID3v1Location)
d->APELocation -= 128;
}
// ID3v1 tag is empty. Remove the old one.
if(d->ID3v1Location >= 0) {
truncate(d->ID3v1Location);
d->ID3v1Location = -1;
}
}
// Update APE tag
if(APETag()) {
if(d->hasAPE)
insert(APETag()->render(), d->APELocation, d->APESize);
else {
if(d->hasID3v1) {
insert(APETag()->render(), d->ID3v1Location, 0);
d->APESize = APETag()->footer()->completeTagSize();
d->hasAPE = true;
if(APETag() && !APETag()->isEmpty()) {
// APE tag is not empty. Update the old one or create a new one.
if(d->APELocation < 0) {
if(d->ID3v1Location >= 0)
d->APELocation = d->ID3v1Location;
d->ID3v1Location += d->APESize;
}
else {
seek(0, End);
d->APELocation = tell();
writeBlock(APETag()->render());
d->APESize = APETag()->footer()->completeTagSize();
d->hasAPE = true;
}
else
d->APELocation = length();
}
const ByteVector data = APETag()->render();
insert(data, d->APELocation, static_cast<size_t>(d->APESize));
if(d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
d->APESize = data.size();
}
else {
if(d->hasAPE) {
removeBlock(d->APELocation, d->APESize);
d->hasAPE = false;
if(d->hasID3v1) {
if(d->ID3v1Location > d->APELocation) {
d->ID3v1Location -= d->APESize;
}
}
// APE tag is empty. Remove the old one.
if(d->APELocation >= 0) {
removeBlock(d->APELocation, static_cast<size_t>(d->APESize));
if(d->ID3v1Location >= 0)
d->ID3v1Location -= d->APESize;
d->APELocation = -1;
d->APESize = 0;
}
}
return true;
return true;
}
ID3v1::Tag *APE::File::ID3v1Tag(bool create)
@@ -223,83 +215,83 @@ APE::Tag *APE::File::APETag(bool create)
void APE::File::strip(int tags)
{
if(tags & ID3v1) {
if(tags & ID3v1)
d->tag.set(ApeID3v1Index, 0);
APETag(true);
}
if(tags & APE) {
if(tags & APE)
d->tag.set(ApeAPEIndex, 0);
if(!ID3v1Tag())
APETag(true);
}
if(!ID3v1Tag())
APETag(true);
}
bool APE::File::hasAPETag() const
{
return (d->APELocation >= 0);
}
bool APE::File::hasID3v1Tag() const
{
return (d->ID3v1Location >= 0);
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void APE::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */)
void APE::File::read(bool readProperties)
{
// Look for an ID3v2 tag
d->ID3v2Location = Utils::findID3v2(this);
if(d->ID3v2Location >= 0) {
seek(d->ID3v2Location);
d->ID3v2Header.reset(new ID3v2::Header(readBlock(ID3v2::Header::size())));
d->ID3v2Size = d->ID3v2Header->completeTagSize();
}
// Look for an ID3v1 tag
d->ID3v1Location = findID3v1();
d->ID3v1Location = Utils::findID3v1(this);
if(d->ID3v1Location >= 0) {
if(d->ID3v1Location >= 0)
d->tag.set(ApeID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
d->hasID3v1 = true;
}
// Look for an APE tag
d->APELocation = findAPE();
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
if(d->APELocation >= 0) {
d->tag.set(ApeAPEIndex, new APE::Tag(this, d->APELocation));
d->APESize = APETag()->footer()->completeTagSize();
d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize;
d->hasAPE = true;
d->APELocation = d->APELocation + APE::Footer::size() - d->APESize;
}
if(!d->hasID3v1)
if(d->ID3v1Location < 0)
APETag(true);
// Look for APE audio properties
if(readProperties) {
d->properties = new Properties(this);
long long streamLength;
if(d->APELocation >= 0)
streamLength = d->APELocation;
else if(d->ID3v1Location >= 0)
streamLength = d->ID3v1Location;
else
streamLength = length();
if(d->ID3v2Location >= 0) {
seek(d->ID3v2Location + d->ID3v2Size);
streamLength -= (d->ID3v2Location + d->ID3v2Size);
}
else {
seek(0);
}
d->properties.reset(new AudioProperties(this, streamLength));
}
}
long APE::File::findAPE()
{
if(!isValid())
return -1;
if(d->hasID3v1)
seek(-160, End);
else
seek(-32, End);
long p = tell();
if(readBlock(8) == APE::Tag::fileIdentifier())
return p;
return -1;
}
long APE::File::findID3v1()
{
if(!isValid())
return -1;
seek(-128, End);
long p = tell();
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
return p;
return -1;
}

View File

@@ -59,7 +59,7 @@ namespace TagLib {
//! An implementation of TagLib::File with APE specific methods
/*!
* This implements and provides an interface APE WavPack files to the
* This implements and provides an interface for APE files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to APE files.
@@ -84,23 +84,25 @@ namespace TagLib {
};
/*!
* Contructs an WavPack file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
* Constructs an APE 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.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Contructs an WavPack file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
* Constructs an APE file from \a stream. 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.
*
* \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.
@@ -113,30 +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.
* As for the export, only one tag is taken into account. If the file
* has no tag at all, APE will be created.
* 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.
@@ -149,27 +139,38 @@ namespace TagLib {
/*!
* Returns a pointer to the ID3v1 tag of the file.
*
* If \a create is false (the default) this will return a null pointer
* If \a create is false (the default) this may return a null pointer
* if there is no valid ID3v1 tag. If \a create is true it will create
* an ID3v1 tag if one does not exist. If there is already an APE tag, the
* new ID3v1 tag will be placed after it.
* an ID3v1 tag if one does not exist and returns a valid pointer.
*
* \note The Tag <b>is still</b> owned by the APE::File and should not be
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
* on disk actually has an ID3v1 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
* \see hasID3v1Tag()
*/
ID3v1::Tag *ID3v1Tag(bool create = false);
/*!
* Returns a pointer to the APE tag of the file.
*
* If \a create is false (the default) this will return a null pointer
* If \a create is false (the default) this may return a null pointer
* if there is no valid APE tag. If \a create is true it will create
* a APE tag if one does not exist.
* an APE tag if one does not exist and returns a valid pointer.
*
* \note The Tag <b>is still</b> owned by the APE::File and should not be
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an APE tag. Use hasAPETag() to check if the file
* on disk actually has an APE tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
* \see hasAPETag()
*/
APE::Tag *APETag(bool create = false);
@@ -183,14 +184,34 @@ namespace TagLib {
*/
void strip(int tags = AllTags);
/*!
* Returns whether or not the file on disk actually has an APE tag.
*
* \see APETag()
*/
bool hasAPETag() const;
/*!
* Returns whether or not the file on disk actually has an ID3v1 tag.
*
* \see ID3v1Tag()
*/
bool hasID3v1Tag() const;
/*!
* Returns whether or not the given \a stream can be opened as an APE
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
File(const File &);
File &operator=(const File &);
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
void scan();
long findID3v1();
long findAPE();
void read(bool readProperties);
class FilePrivate;
FilePrivate *d;

View File

@@ -38,54 +38,51 @@ using namespace APE;
class APE::Footer::FooterPrivate
{
public:
FooterPrivate() : version(0),
footerPresent(true),
headerPresent(false),
isHeader(false),
itemCount(0),
tagSize(0) {}
FooterPrivate() :
version(0),
footerPresent(true),
headerPresent(false),
isHeader(false),
itemCount(0),
tagSize(0) {}
~FooterPrivate() {}
uint version;
unsigned int version;
bool footerPresent;
bool headerPresent;
bool isHeader;
uint itemCount;
uint tagSize;
static const uint size = 32;
unsigned int itemCount;
unsigned int tagSize;
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
TagLib::uint APE::Footer::size()
unsigned int APE::Footer::size()
{
return FooterPrivate::size;
return 32;
}
ByteVector APE::Footer::fileIdentifier()
{
return ByteVector::fromCString("APETAGEX");
return ByteVector("APETAGEX");
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
APE::Footer::Footer()
APE::Footer::Footer() :
d(new FooterPrivate())
{
d = new FooterPrivate;
}
APE::Footer::Footer(const ByteVector &data)
APE::Footer::Footer(const ByteVector &data) :
d(new FooterPrivate())
{
d = new FooterPrivate;
parse(data);
}
@@ -94,7 +91,7 @@ APE::Footer::~Footer()
delete d;
}
TagLib::uint APE::Footer::version() const
unsigned int APE::Footer::version() const
{
return d->version;
}
@@ -119,30 +116,30 @@ void APE::Footer::setHeaderPresent(bool b) const
d->headerPresent = b;
}
TagLib::uint APE::Footer::itemCount() const
unsigned int APE::Footer::itemCount() const
{
return d->itemCount;
}
void APE::Footer::setItemCount(uint s)
void APE::Footer::setItemCount(unsigned int s)
{
d->itemCount = s;
}
TagLib::uint APE::Footer::tagSize() const
unsigned int APE::Footer::tagSize() const
{
return d->tagSize;
}
TagLib::uint APE::Footer::completeTagSize() const
unsigned int APE::Footer::completeTagSize() const
{
if(d->headerPresent)
return d->tagSize + d->size;
return d->tagSize + size();
else
return d->tagSize;
}
void APE::Footer::setTagSize(uint s)
void APE::Footer::setTagSize(unsigned int s)
{
d->tagSize = s;
}
@@ -154,13 +151,14 @@ void APE::Footer::setData(const ByteVector &data)
ByteVector APE::Footer::renderFooter() const
{
return render(false);
return render(false);
}
ByteVector APE::Footer::renderHeader() const
{
if (!d->headerPresent) return ByteVector();
if(!d->headerPresent)
return ByteVector();
else
return render(true);
}
@@ -177,19 +175,19 @@ void APE::Footer::parse(const ByteVector &data)
// Read the version number
d->version = data.mid(8, 4).toUInt(false);
d->version = data.toUInt32LE(8);
// Read the tag size
d->tagSize = data.mid(12, 4).toUInt(false);
d->tagSize = data.toUInt32LE(12);
// Read the item count
d->itemCount = data.mid(16, 4).toUInt(false);
d->itemCount = data.toUInt32LE(16);
// Read the flags
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.mid(20, 4).toUInt(false)));
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt32LE(20)));
d->headerPresent = flags[31];
d->footerPresent = !flags[30];
@@ -208,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
@@ -226,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

@@ -37,7 +37,7 @@ namespace TagLib {
/*!
* This class implements APE footers (and headers). It attempts to follow, both
* semantically and programatically, the structure specified in
* semantically and programmatically, the structure specified in
* the APE v2.0 standard. The API is based on the properties of APE footer and
* headers specified there.
*/
@@ -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.
@@ -64,7 +64,7 @@ namespace TagLib {
/*!
* Returns the version number. (Note: This is the 1000 or 2000.)
*/
uint version() const;
unsigned int version() const;
/*!
* Returns true if a header is present in the tag.
@@ -89,13 +89,13 @@ namespace TagLib {
/*!
* Returns the number of items in the tag.
*/
uint itemCount() const;
unsigned int itemCount() const;
/*!
* Set the item count to \a s.
* \see itemCount()
*/
void setItemCount(uint s);
void setItemCount(unsigned int s);
/*!
* Returns the tag size in bytes. This is the size of the frame content and footer.
@@ -103,7 +103,7 @@ namespace TagLib {
*
* \see completeTagSize()
*/
uint tagSize() const;
unsigned int tagSize() const;
/*!
* Returns the tag size, including if present, the header
@@ -111,18 +111,18 @@ namespace TagLib {
*
* \see tagSize()
*/
uint completeTagSize() const;
unsigned int completeTagSize() const;
/*!
* Set the tag size to \a s.
* \see tagSize()
*/
void setTagSize(uint s);
void setTagSize(unsigned int s);
/*!
* Returns the size of the footer. Presently this is always 32 bytes.
*/
static uint size();
static unsigned int size();
/*!
* Returns the string used to identify an APE tag inside of a file.

View File

@@ -25,16 +25,18 @@
#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), readOnly(false) {}
ItemData() :
type(Item::Text),
readOnly(false) {}
Item::ItemTypes type;
String key;
@@ -43,40 +45,54 @@ public:
bool readOnly;
};
APE::Item::Item()
class APE::Item::ItemPrivate
{
public:
ItemPrivate() :
data(new ItemData()) {}
SHARED_PTR<ItemData> data;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
APE::Item::Item() :
d(new ItemPrivate())
{
d = new ItemPrivate;
}
APE::Item::Item(const String &key, const String &value)
APE::Item::Item(const String &key, const String &value) :
d(new ItemPrivate())
{
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)
APE::Item::Item(const String &key, const StringList &values) :
d(new ItemPrivate())
{
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)
APE::Item::Item(const String &key, const ByteVector &value, bool binary) :
d(new ItemPrivate())
{
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->data->text.append(value);
}
else
d->text.append(value);
}
APE::Item::Item(const Item &item)
APE::Item::Item(const Item &item) :
d(new ItemPrivate(*item.d))
{
d = new ItemPrivate(*item.d);
}
APE::Item::~Item()
@@ -86,135 +102,135 @@ APE::Item::~Item()
Item &APE::Item::operator=(const Item &item)
{
delete d;
d = new ItemPrivate(*item.d);
Item(item).swap(*this);
return *this;
}
void APE::Item::swap(Item &item)
{
using std::swap;
swap(d, item.d);
}
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;
}
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->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->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->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->data->type = Text;
d->data->text.append(values);
d->data->value.clear();
}
int APE::Item::size() const
{
// SFB: Why is d->key.size() used when size() returns the length in UniChars and not UTF-8?
int result = 8 + d->key.size() /* d->key.data(String::UTF8).size() */ + 1;
switch (d->type) {
size_t result = 8 + d->data->key.size() + 1;
switch(d->data->type) {
case Text:
if(d->text.size()) {
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
{
return isEmpty() ? String::null : 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;
}
@@ -229,46 +245,51 @@ void APE::Item::parse(const ByteVector &data)
return;
}
uint valueLength = data.mid(0, 4).toUInt(false);
uint flags = data.mid(4, 4).toUInt(false);
const unsigned int valueLength = data.toUInt32LE(0);
const unsigned int flags = data.toUInt32LE(4);
d->key = String(data.mid(8), String::UTF8);
// 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->value = data.mid(8 + d->key.size() + 1, valueLength);
d->data->key = String(&data[8], String::Latin1);
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(d->value, '\0'), String::UTF8);
if(Text == d->data->type)
d->data->text = StringList(ByteVectorList::split(value, '\0'), String::UTF8);
else
d->data->value = value;
}
ByteVector APE::Item::render() const
{
ByteVector data;
TagLib::uint 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::UTF8));
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);
/*!
@@ -90,6 +89,11 @@ namespace TagLib {
*/
Item &operator=(const Item &item);
/*!
* Exchanges the content of this item by the content of \a item.
*/
void swap(Item &item);
/*!
* Returns the key.
*/
@@ -97,7 +101,7 @@ namespace TagLib {
/*!
* Returns the binary value.
* If the item type is not \a Binary, the returned contents are undefined
* If the item type is not \a Binary, always returns an empty ByteVector.
*/
ByteVector binaryData() const;
@@ -107,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.
*/
@@ -152,18 +151,15 @@ namespace TagLib {
int size() const;
/*!
* Returns the value as a single string. In case of multiple strings,
* the first is returned.
* Returns the value as a single string. In case of multiple strings,
* the first is returned. If the data type is not \a Text, always returns
* an empty String.
*/
String toString() const;
#ifndef DO_NOT_DOCUMENT
/* Remove in next binary incompatible release */
StringList toStringList() const;
#endif
/*!
* Returns the list of text values.
* Returns the list of text values. If the data type is not \a Text, always
* returns an empty StringList.
*/
StringList values() const;

View File

@@ -29,26 +29,26 @@
#include <tstring.h>
#include <tdebug.h>
#include <bitset>
#include "id3v2tag.h"
#include "apeproperties.h"
#include "apefile.h"
#include "apetag.h"
#include "apefooter.h"
using namespace TagLib;
class APE::Properties::PropertiesPrivate
class APE::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(File *file, long streamLength) :
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
channels(0),
version(0),
bitsPerSample(0),
sampleFrames(0),
file(file),
streamLength(streamLength) {}
sampleFrames(0) {}
int length;
int bitrate;
@@ -56,57 +56,66 @@ public:
int channels;
int version;
int bitsPerSample;
uint sampleFrames;
File *file;
long streamLength;
unsigned int sampleFrames;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
APE::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style)
APE::AudioProperties::AudioProperties(File *file, long long streamLength, ReadStyle) :
TagLib::AudioProperties(),
d(new PropertiesPrivate())
{
d = new PropertiesPrivate(file, file->length());
read();
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::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
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;
}
TagLib::uint APE::Properties::sampleFrames() const
unsigned int APE::AudioProperties::sampleFrames() const
{
return d->sampleFrames;
}
@@ -115,117 +124,122 @@ TagLib::uint APE::Properties::sampleFrames() const
// private members
////////////////////////////////////////////////////////////////////////////////
void APE::Properties::read()
namespace
{
// First we are searching the descriptor
long offset = findDescriptor();
if(offset < 0)
return;
int headerVersion(const ByteVector &header)
{
if(header.size() < 6 || !header.startsWith("MAC "))
return -1;
// Then we read the header common for all versions of APE
d->file->seek(offset);
ByteVector commonHeader=d->file->readBlock(6);
if(!commonHeader.startsWith("MAC "))
return;
d->version = commonHeader.mid(4).toUInt(false);
if(d->version >= 3980) {
analyzeCurrent();
}
else {
analyzeOld();
return header.toUInt16LE(4);
}
}
long APE::Properties::findDescriptor()
void APE::AudioProperties::read(File *file, long long streamLength)
{
long ID3v2Location = findID3v2();
long ID3v2OriginalSize = 0;
bool hasID3v2 = false;
if(ID3v2Location >= 0) {
ID3v2::Tag tag(d->file, ID3v2Location);
ID3v2OriginalSize = tag.header()->completeTagSize();
if(tag.header()->tagSize() > 0)
hasID3v2 = true;
// First, we assume that the file pointer is set at the first descriptor.
long long offset = file->tell();
int version = headerVersion(file->readBlock(6));
// Next, we look for the descriptor.
if(version < 0) {
offset = file->find("MAC ", offset);
file->seek(offset);
version = headerVersion(file->readBlock(6));
}
long offset = 0;
if(hasID3v2)
offset = d->file->find("MAC ", ID3v2Location + ID3v2OriginalSize);
if(version < 0) {
debug("APE::AudioProperties::read() -- APE descriptor not found");
return;
}
d->version = version;
if(d->version >= 3980)
analyzeCurrent(file);
else
offset = d->file->find("MAC ");
analyzeOld(file);
if(offset < 0) {
debug("APE::Properties::findDescriptor() -- APE descriptor not found");
return -1;
if(d->sampleFrames > 0 && d->sampleRate > 0) {
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
}
return offset;
}
long APE::Properties::findID3v2()
{
if(!d->file->isValid())
return -1;
d->file->seek(0);
if(d->file->readBlock(3) == ID3v2::Header::fileIdentifier())
return 0;
return -1;
}
void APE::Properties::analyzeCurrent()
void APE::AudioProperties::analyzeCurrent(File *file)
{
// Read the descriptor
d->file->seek(2, File::Current);
ByteVector descriptor = d->file->readBlock(44);
uint descriptorBytes = descriptor.mid(0,4).toUInt(false);
file->seek(2, File::Current);
const ByteVector descriptor = file->readBlock(44);
if(descriptor.size() < 44) {
debug("APE::AudioProperties::analyzeCurrent() -- descriptor is too short.");
return;
}
if ((descriptorBytes - 52) > 0)
d->file->seek(descriptorBytes - 52, File::Current);
const unsigned int descriptorBytes = descriptor.toUInt32LE(0);
if((descriptorBytes - 52) > 0)
file->seek(descriptorBytes - 52, File::Current);
// Read the header
ByteVector header = d->file->readBlock(24);
const ByteVector header = file->readBlock(24);
if(header.size() < 24) {
debug("APE::AudioProperties::analyzeCurrent() -- MAC header is too short.");
return;
}
// Get the APE info
d->channels = header.mid(18, 2).toShort(false);
d->sampleRate = header.mid(20, 4).toUInt(false);
d->bitsPerSample = header.mid(16, 2).toShort(false);
//d->compressionLevel =
d->channels = header.toUInt16LE(18);
d->sampleRate = header.toUInt32LE(20);
d->bitsPerSample = header.toUInt16LE(16);
uint totalFrames = header.mid(12, 4).toUInt(false);
uint blocksPerFrame = header.mid(4, 4).toUInt(false);
uint finalFrameBlocks = header.mid(8, 4).toUInt(false);
d->sampleFrames = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
const unsigned int totalFrames = header.toUInt32LE(12);
if(totalFrames == 0)
return;
const unsigned int blocksPerFrame = header.toUInt32LE(4);
const unsigned int finalFrameBlocks = header.toUInt32LE(8);
d->sampleFrames = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks;
}
void APE::Properties::analyzeOld()
void APE::AudioProperties::analyzeOld(File *file)
{
ByteVector header = d->file->readBlock(26);
uint totalFrames = header.mid(18, 4).toUInt(false);
const ByteVector header = file->readBlock(26);
if(header.size() < 26) {
debug("APE::AudioProperties::analyzeOld() -- MAC header is too short.");
return;
}
const unsigned int totalFrames = header.toUInt32LE(18);
// Fail on 0 length APE files (catches non-finalized APE files)
if(totalFrames == 0)
return;
short compressionLevel = header.mid(0, 2).toShort(false);
uint blocksPerFrame;
const short compressionLevel = header.toUInt32LE(0);
unsigned int blocksPerFrame;
if(d->version >= 3950)
blocksPerFrame = 73728 * 4;
else if(d->version >= 3900 || (d->version >= 3800 && compressionLevel == 4000))
blocksPerFrame = 73728;
else
blocksPerFrame = 9216;
d->channels = header.mid(4, 2).toShort(false);
d->sampleRate = header.mid(6, 4).toUInt(false);
uint finalFrameBlocks = header.mid(22, 4).toUInt(false);
uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
d->length = totalBlocks / d->sampleRate;
d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
}
// Get the APE info
d->channels = header.toUInt16LE(4);
d->sampleRate = header.toUInt32LE(6);
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::AudioProperties::analyzeOld() -- fmt header is too short.");
return;
}
d->bitsPerSample = fmt.toUInt16LE(26);
}

View File

@@ -46,32 +46,69 @@ 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
* ByteVector \a data.
* APE::File \a file.
*/
Properties(File *f, ReadStyle style = Average);
AudioProperties(File *file, long long streamLength, ReadStyle style = Average);
/*!
* Destroys this APE::Properties instance.
* Destroys this APE::AudioProperties instance.
*/
virtual ~Properties();
// Reimplementations.
virtual ~AudioProperties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
*/
virtual int length() const;
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
virtual int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
virtual int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
/*!
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
/*!
* Returns the number of audio channels.
*/
virtual int channels() const;
/*!
* Returns number of bits per sample.
* Returns the number of bits per audio sample.
*/
int bitsPerSample() const;
uint sampleFrames() const;
/*!
* Returns the total number of audio samples in file.
*/
unsigned int sampleFrames() const;
/*!
* Returns APE version.
@@ -79,16 +116,9 @@ namespace TagLib {
int version() const;
private:
Properties(const Properties &);
Properties &operator=(const Properties &);
void read();
long findDescriptor();
long findID3v2();
void analyzeCurrent();
void analyzeOld();
void read(File *file, long long streamLength);
void analyzeCurrent(File *file);
void analyzeOld(File *file);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@@ -23,7 +23,7 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef __SUNPRO_CC
#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5130)
// Sun Studio finds multiple specializations of Map because
// it considers specializations with and without class types
// to be different; this define forces Map to use only the
@@ -34,7 +34,10 @@
#include <tfile.h>
#include <tstring.h>
#include <tmap.h>
#include <tpicturemap.h>
#include <tpropertymap.h>
#include <tdebug.h>
#include <tutils.h>
#include "apetag.h"
#include "apefooter.h"
@@ -43,17 +46,44 @@
using namespace TagLib;
using namespace APE;
namespace
{
const unsigned int MinKeyLength = 2;
const unsigned int MaxKeyLength = 255;
bool isKeyValid(const ByteVector &key)
{
const char *invalidKeys[] = { "ID3", "TAG", "OGGS", "MP+", 0 };
// only allow printable ASCII including space (32..126)
for(ByteVector::ConstIterator it = key.begin(); it != key.end(); ++it) {
const int c = static_cast<unsigned char>(*it);
if(c < 32 || c > 126)
return false;
}
const String upperKey = String(key).upper();
for(size_t i = 0; invalidKeys[i] != 0; ++i) {
if(upperKey == invalidKeys[i])
return false;
}
return true;
}
}
class APE::Tag::TagPrivate
{
public:
TagPrivate() : file(0), footerLocation(-1), tagLength(0) {}
TagPrivate() :
file(0),
footerLocation(0) {}
TagLib::File *file;
long footerLocation;
long tagLength;
File *file;
long long footerLocation;
Footer footer;
ItemListMap itemListMap;
};
@@ -61,14 +91,16 @@ public:
// public methods
////////////////////////////////////////////////////////////////////////////////
APE::Tag::Tag() : TagLib::Tag()
APE::Tag::Tag() :
TagLib::Tag(),
d(new TagPrivate())
{
d = new TagPrivate;
}
APE::Tag::Tag(TagLib::File *file, long footerLocation) : TagLib::Tag()
APE::Tag::Tag(TagLib::File *file, long long footerLocation) :
TagLib::Tag(),
d(new TagPrivate())
{
d = new TagPrivate;
d->file = file;
d->footerLocation = footerLocation;
@@ -88,52 +120,88 @@ ByteVector APE::Tag::fileIdentifier()
String APE::Tag::title() const
{
if(d->itemListMap["TITLE"].isEmpty())
return String::null;
return d->itemListMap["TITLE"].toString();
return String();
return d->itemListMap["TITLE"].values().toString();
}
String APE::Tag::artist() const
{
if(d->itemListMap["ARTIST"].isEmpty())
return String::null;
return d->itemListMap["ARTIST"].toString();
return String();
return d->itemListMap["ARTIST"].values().toString();
}
String APE::Tag::album() const
{
if(d->itemListMap["ALBUM"].isEmpty())
return String::null;
return d->itemListMap["ALBUM"].toString();
return String();
return d->itemListMap["ALBUM"].values().toString();
}
String APE::Tag::comment() const
{
if(d->itemListMap["COMMENT"].isEmpty())
return String::null;
return d->itemListMap["COMMENT"].toString();
return String();
return d->itemListMap["COMMENT"].values().toString();
}
String APE::Tag::genre() const
{
if(d->itemListMap["GENRE"].isEmpty())
return String::null;
return d->itemListMap["GENRE"].toString();
return String();
return d->itemListMap["GENRE"].values().toString();
}
TagLib::uint APE::Tag::year() const
unsigned int APE::Tag::year() const
{
if(d->itemListMap["YEAR"].isEmpty())
return 0;
return d->itemListMap["YEAR"].toString().toInt();
}
TagLib::uint APE::Tag::track() const
unsigned int APE::Tag::track() const
{
if(d->itemListMap["TRACK"].isEmpty())
return 0;
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);
@@ -159,30 +227,91 @@ void APE::Tag::setGenre(const String &s)
addValue("GENRE", s, true);
}
void APE::Tag::setYear(uint i)
void APE::Tag::setYear(unsigned int i)
{
if(i <= 0)
if(i == 0)
removeItem("YEAR");
else
addValue("YEAR", String::number(i), true);
}
void APE::Tag::setTrack(uint i)
void APE::Tag::setTrack(unsigned int i)
{
if(i <= 0)
if(i == 0)
removeItem("TRACK");
else
addValue("TRACK", String::number(i), true);
}
// conversions of tag keys between what we use in PropertyMap and what's usual
// for APE tags
static const TagLib::uint keyConversionsSize = 5; //usual, APE
static const char *keyConversions[][2] = {{"TRACKNUMBER", "TRACK" },
{"DATE", "YEAR" },
{"ALBUMARTIST", "ALBUM ARTIST"},
{"DISCNUMBER", "DISC" },
{"REMIXER", "MIXARTIST" }};
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
// for APE tags
// usual, APE
const char *keyConversions[][2] = {{"TRACKNUMBER", "TRACK" },
{"DATE", "YEAR" },
{"ALBUMARTIST", "ALBUM ARTIST"},
{"DISCNUMBER", "DISC" },
{"REMIXER", "MIXARTIST" }};
const size_t keyConversionsSize = sizeof(keyConversions) / sizeof(keyConversions[0]);
}
PropertyMap APE::Tag::properties() const
{
@@ -192,14 +321,16 @@ PropertyMap APE::Tag::properties() const
String tagName = it->first.upper();
// if the item is Binary or Locator, or if the key is an invalid string,
// add to unsupportedData
if(it->second.type() != Item::Text || tagName.isNull())
if(it->second.type() != Item::Text || tagName.isEmpty()) {
properties.unsupportedData().append(it->first);
}
else {
// Some tags need to be handled specially
for(uint i = 0; i < keyConversionsSize; ++i)
for(size_t i = 0; i < keyConversionsSize; ++i) {
if(tagName == keyConversions[i][1])
tagName = keyConversions[i][0];
properties[tagName].append(it->second.toStringList());
}
properties[tagName].append(it->second.values());
}
}
return properties;
@@ -217,7 +348,7 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
PropertyMap properties(origProps); // make a local copy that can be modified
// see comment in properties()
for(uint i = 0; i < keyConversionsSize; ++i)
for(size_t i = 0; i < keyConversionsSize; ++i)
if(properties.contains(keyConversions[i][0])) {
properties.insert(keyConversions[i][1], properties[keyConversions[i][0]]);
properties.erase(keyConversions[i][0]);
@@ -229,11 +360,11 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
for(; remIt != itemListMap().end(); ++remIt) {
String key = remIt->first.upper();
// only remove if a) key is valid, b) type is text, c) key not contained in new properties
if(!key.isNull() && remIt->second.type() == APE::Item::Text && !properties.contains(key))
if(!key.isEmpty() && remIt->second.type() == APE::Item::Text && !properties.contains(key))
toRemove.append(remIt->first);
}
for (StringList::Iterator removeIt = toRemove.begin(); removeIt != toRemove.end(); removeIt++)
for(StringList::ConstIterator removeIt = toRemove.begin(); removeIt != toRemove.end(); removeIt++)
removeItem(*removeIt);
// now sync in the "forward direction"
@@ -244,7 +375,7 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
if(!checkKey(tagName))
invalid.insert(it->first, it->second);
else if(!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == it->second)) {
if(it->second.size() == 0)
if(it->second.isEmpty())
removeItem(tagName);
else {
StringList::ConstIterator valueIt = it->second.begin();
@@ -260,16 +391,10 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
bool APE::Tag::checkKey(const String &key)
{
if(key.size() < 2 || key.size() > 16)
return false;
for(String::ConstIterator it = key.begin(); it != key.end(); it++)
// only allow printable ASCII including space (32..127)
if (*it < 32 || *it >= 128)
return false;
String upperKey = key.upper();
if (upperKey=="ID3" || upperKey=="TAG" || upperKey=="OGGS" || upperKey=="MP+")
return false;
return true;
if(key.size() < MinKeyLength || key.size() > MaxKeyLength)
return false;
return isKeyValid(key.data(String::UTF8));
}
APE::Footer *APE::Tag::footer() const
@@ -284,40 +409,46 @@ const APE::ItemListMap& APE::Tag::itemListMap() const
void APE::Tag::removeItem(const String &key)
{
Map<const String, Item>::Iterator it = d->itemListMap.find(key.upper());
if(it != d->itemListMap.end())
d->itemListMap.erase(it);
d->itemListMap.erase(key.upper());
}
void APE::Tag::addValue(const String &key, const String &value, bool replace)
{
if(replace)
removeItem(key);
if(!key.isEmpty() && !value.isEmpty()) {
if(!replace && d->itemListMap.contains(key)) {
// Text items may contain more than one value
if(APE::Item::Text == d->itemListMap.begin()->second.type())
d->itemListMap[key.upper()].appendValue(value);
// Binary or locator items may have only one value
else
setItem(key, Item(key, value));
}
else
setItem(key, Item(key, value));
}
if(value.isEmpty())
return;
// Text items may contain more than one value.
// Binary or locator items may have only one value, hence always replaced.
ItemListMap::Iterator it = d->itemListMap.find(key.upper());
if(it != d->itemListMap.end() && it->second.type() == Item::Text)
it->second.appendValue(value);
else
setItem(key, Item(key, value));
}
void APE::Tag::setData(const String &key, const ByteVector &value)
{
removeItem(key);
if(!key.isEmpty() && !value.isEmpty())
setItem(key, Item(key, value, true));
if(value.isEmpty())
return;
setItem(key, Item(key, value, true));
}
void APE::Tag::setItem(const String &key, const Item &item)
{
if(!key.isEmpty())
d->itemListMap.insert(key.upper(), item);
if(!checkKey(key)) {
debug("APE::Tag::setItem() - Couldn't set an item due to an invalid key.");
return;
}
d->itemListMap[key.upper()] = item;
}
bool APE::Tag::isEmpty() const
@@ -337,7 +468,7 @@ void APE::Tag::read()
d->footer.setData(d->file->readBlock(Footer::size()));
if(d->footer.tagSize() <= Footer::size() ||
d->footer.tagSize() > uint(d->file->length()))
d->footer.tagSize() > static_cast<unsigned long>(d->file->length()))
return;
d->file->seek(d->footerLocation + Footer::size() - d->footer.tagSize());
@@ -348,19 +479,15 @@ void APE::Tag::read()
ByteVector APE::Tag::render() const
{
ByteVector data;
uint itemCount = 0;
unsigned int itemCount = 0;
{
for(Map<const String, Item>::ConstIterator it = d->itemListMap.begin();
it != d->itemListMap.end(); ++it)
{
data.append(it->second.render());
itemCount++;
}
for(ItemListMap::ConstIterator it = d->itemListMap.begin(); it != d->itemListMap.end(); ++it) {
data.append(it->second.render());
itemCount++;
}
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();
@@ -368,16 +495,37 @@ ByteVector APE::Tag::render() const
void APE::Tag::parse(const ByteVector &data)
{
uint pos = 0;
// 11 bytes is the minimum size for an APE item
for(uint i = 0; i < d->footer.itemCount() && pos <= data.size() - 11; i++) {
APE::Item item;
item.parse(data.mid(pos));
if(data.size() < 11)
return;
d->itemListMap.insert(item.key().upper(), item);
size_t pos = 0;
pos += item.size();
for(unsigned int i = 0; i < d->footer.itemCount() && pos <= data.size() - 11; i++) {
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 size_t keyLength = nullPos - pos - 8;
const size_t valLegnth = data.toUInt32LE(pos);
if(keyLength >= MinKeyLength
&& keyLength <= MaxKeyLength
&& isKeyValid(data.mid(pos + 8, keyLength)))
{
APE::Item item;
item.parse(data.mid(pos));
d->itemListMap.insert(item.key().upper(), item);
}
else {
debug("APE::Tag::parse() - Skipped an item due to an invalid key.");
}
pos += keyLength + valLegnth + 9;
}
}

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.
@@ -92,16 +95,26 @@ namespace TagLib {
virtual String album() const;
virtual String comment() const;
virtual String genre() const;
virtual uint year() const;
virtual uint track() const;
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);
virtual void setComment(const String &s);
virtual void setGenre(const String &s);
virtual void setYear(uint i);
virtual void setTrack(uint i);
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.
@@ -143,7 +156,7 @@ namespace TagLib {
* Returns a reference to the item list map. This is an ItemListMap of
* all of the items in the tag.
*
* This is the most powerfull structure for accessing the items of the tag.
* This is the most powerful structure for accessing the items of the tag.
*
* APE tags are case-insensitive, all keys in this map have been converted
* to upper case.

View File

@@ -1,4 +1,4 @@
/**************************************************************************
/**************************************************************************
copyright : (C) 2005-2007 by Lukáš Lalinský
email : lalinsky@gmail.com
**************************************************************************/
@@ -23,226 +23,238 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <taglib.h>
#include <tdebug.h>
#include <tsmartptr.h>
#include "asfattribute.h"
#include "asffile.h"
#include "asfutils.h"
using namespace TagLib;
class ASF::Attribute::AttributePrivate : public RefCounter
namespace
{
public:
AttributePrivate()
: pictureValue(ASF::Picture::fromInvalid()),
struct AttributeData
{
AttributeData() :
numericValue(0),
stream(0),
language(0) {}
AttributeTypes type;
String stringValue;
ByteVector byteVectorValue;
ASF::Picture pictureValue;
union {
unsigned int intValue;
unsigned short shortValue;
unsigned long long longLongValue;
bool boolValue;
ASF::Attribute::AttributeTypes type;
String stringValue;
ByteVector byteVectorValue;
ASF::Picture pictureValue;
unsigned long long numericValue;
int stream;
int language;
};
int stream;
int language;
}
class ASF::Attribute::AttributePrivate
{
public:
AttributePrivate() :
data(new AttributeData())
{
data->pictureValue = ASF::Picture::fromInvalid();
}
SHARED_PTR<AttributeData> data;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::Attribute::Attribute()
ASF::Attribute::Attribute() :
d(new AttributePrivate())
{
d = new AttributePrivate;
d->type = UnicodeType;
d->data->type = UnicodeType;
}
ASF::Attribute::Attribute(const ASF::Attribute &other)
: d(other.d)
ASF::Attribute::Attribute(const ASF::Attribute &other) :
d(new AttributePrivate(*other.d))
{
d->ref();
}
ASF::Attribute::Attribute(const String &value) :
d(new AttributePrivate())
{
d->data->type = UnicodeType;
d->data->stringValue = value;
}
ASF::Attribute::Attribute(const ByteVector &value) :
d(new AttributePrivate())
{
d->data->type = BytesType;
d->data->byteVectorValue = value;
}
ASF::Attribute::Attribute(const ASF::Picture &value) :
d(new AttributePrivate())
{
d->data->type = BytesType;
d->data->pictureValue = value;
}
ASF::Attribute::Attribute(unsigned int value) :
d(new AttributePrivate())
{
d->data->type = DWordType;
d->data->numericValue = value;
}
ASF::Attribute::Attribute(unsigned long long value) :
d(new AttributePrivate())
{
d->data->type = QWordType;
d->data->numericValue = value;
}
ASF::Attribute::Attribute(unsigned short value) :
d(new AttributePrivate())
{
d->data->type = WordType;
d->data->numericValue = value;
}
ASF::Attribute::Attribute(bool value) :
d(new AttributePrivate())
{
d->data->type = BoolType;
d->data->numericValue = value;
}
ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other)
{
if(d->deref())
delete d;
d = other.d;
d->ref();
Attribute(other).swap(*this);
return *this;
}
void ASF::Attribute::swap(Attribute &other)
{
using std::swap;
swap(d, other.d);
}
ASF::Attribute::~Attribute()
{
if(d->deref())
delete d;
}
ASF::Attribute::Attribute(const String &value)
{
d = new AttributePrivate;
d->type = UnicodeType;
d->stringValue = value;
}
ASF::Attribute::Attribute(const ByteVector &value)
{
d = new AttributePrivate;
d->type = BytesType;
d->byteVectorValue = value;
}
ASF::Attribute::Attribute(const ASF::Picture &value)
{
d = new AttributePrivate;
d->type = BytesType;
d->pictureValue = value;
}
ASF::Attribute::Attribute(unsigned int value)
{
d = new AttributePrivate;
d->type = DWordType;
d->intValue = value;
}
ASF::Attribute::Attribute(unsigned long long value)
{
d = new AttributePrivate;
d->type = QWordType;
d->longLongValue = value;
}
ASF::Attribute::Attribute(unsigned short value)
{
d = new AttributePrivate;
d->type = WordType;
d->shortValue = value;
}
ASF::Attribute::Attribute(bool value)
{
d = new AttributePrivate;
d->type = BoolType;
d->boolValue = value;
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->shortValue;
return d->data->numericValue ? 1 : 0;
}
unsigned short ASF::Attribute::toUShort() const
{
return d->shortValue;
return static_cast<unsigned short>(d->data->numericValue);
}
unsigned int ASF::Attribute::toUInt() const
{
return d->intValue;
return static_cast<unsigned int>(d->data->numericValue);
}
unsigned long long ASF::Attribute::toULongLong() const
{
return d->longLongValue;
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)
{
uint size, nameLength;
unsigned int size, nameLength;
String name;
d->pictureValue = Picture::fromInvalid();
d->data->pictureValue = Picture::fromInvalid();
// extended content descriptor
if(kind == 0) {
nameLength = f.readWORD();
name = f.readString(nameLength);
d->type = ASF::Attribute::AttributeTypes(f.readWORD());
size = f.readWORD();
nameLength = readWORD(&f);
name = readString(&f, nameLength);
d->data->type = ASF::Attribute::AttributeTypes(readWORD(&f));
size = readWORD(&f);
}
// metadata & metadata library
else {
int temp = f.readWORD();
int temp = readWORD(&f);
// metadata library
if(kind == 2) {
d->language = temp;
d->data->language = temp;
}
d->stream = f.readWORD();
nameLength = f.readWORD();
d->type = ASF::Attribute::AttributeTypes(f.readWORD());
size = f.readDWORD();
name = f.readString(nameLength);
d->data->stream = readWORD(&f);
nameLength = readWORD(&f);
d->data->type = ASF::Attribute::AttributeTypes(readWORD(&f));
size = readDWORD(&f);
name = readString(&f, nameLength);
}
if(kind != 2 && size > 65535) {
debug("ASF::Attribute::parse() -- Value larger than 64kB");
}
switch(d->type) {
switch(d->data->type) {
case WordType:
d->shortValue = f.readWORD();
d->data->numericValue = readWORD(&f);
break;
case BoolType:
if(kind == 0) {
d->boolValue = f.readDWORD() == 1;
d->data->numericValue = (readDWORD(&f) != 0);
}
else {
d->boolValue = f.readWORD() == 1;
d->data->numericValue = (readWORD(&f) != 0);
}
break;
case DWordType:
d->intValue = f.readDWORD();
d->data->numericValue = readDWORD(&f);
break;
case QWordType:
d->longLongValue = f.readQWORD();
d->data->numericValue = readQWORD(&f);
break;
case UnicodeType:
d->stringValue = f.readString(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();
}
}
@@ -251,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:
@@ -261,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;
}
@@ -275,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(d->shortValue, false));
data.append(ByteVector::fromUInt16LE(toUShort()));
break;
case BoolType:
if(kind == 0) {
data.append(ByteVector::fromUInt(d->boolValue ? 1 : 0, false));
data.append(ByteVector::fromUInt32LE(toBool()));
}
else {
data.append(ByteVector::fromShort(d->boolValue ? 1 : 0, false));
data.append(ByteVector::fromUInt16LE(toBool()));
}
break;
case DWordType:
data.append(ByteVector::fromUInt(d->intValue, false));
data.append(ByteVector::fromUInt32LE(toUInt()));
break;
case QWordType:
data.append(ByteVector::fromLongLong(d->longLongValue, false));
data.append(ByteVector::fromUInt64LE(toULongLong()));
break;
case UnicodeType:
data.append(File::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 = File::renderString(name, true) +
ByteVector::fromShort((int)d->type, false) +
ByteVector::fromShort(data.size(), false) +
data = renderString(name, true) +
ByteVector::fromUInt16LE((int)d->data->type) +
ByteVector::fromUInt16LE(data.size()) +
data;
}
else {
ByteVector nameData = File::renderString(name);
data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
ByteVector::fromShort(d->stream, false) +
ByteVector::fromShort(nameData.size(), false) +
ByteVector::fromShort((int)d->type, false) +
ByteVector::fromUInt(data.size(), false) +
ByteVector nameData = renderString(name);
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;
}
@@ -333,21 +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;
@@ -113,7 +112,12 @@ namespace TagLib
/*!
* Copies the contents of \a other into this item.
*/
ASF::Attribute &operator=(const Attribute &other);
Attribute &operator=(const Attribute &other);
/*!
* Exchanges the content of the Attribute by the content of \a other.
*/
void swap(Attribute &other);
/*!
* Destroys the attribute.
@@ -180,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

@@ -23,218 +23,255 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <tdebug.h>
#include <tbytevectorlist.h>
#include <tpropertymap.h>
#include <tstring.h>
#include <tagutils.h>
#include <tsmartptr.h>
#include "asffile.h"
#include "asftag.h"
#include "asfproperties.h"
#include "asfutils.h"
using namespace TagLib;
class ASF::File::FilePrivate
{
public:
class BaseObject;
class UnknownObject;
class FilePropertiesObject;
class StreamPropertiesObject;
class ContentDescriptionObject;
class ExtendedContentDescriptionObject;
class HeaderExtensionObject;
class CodecListObject;
class MetadataObject;
class MetadataLibraryObject;
typedef List<SHARED_PTR<BaseObject> > ObjectList;
typedef ObjectList::ConstIterator ObjectConstIterator;
FilePrivate():
size(0),
tag(0),
properties(0),
contentDescriptionObject(0),
extendedContentDescriptionObject(0),
headerExtensionObject(0),
metadataObject(0),
metadataLibraryObject(0) {}
unsigned long long size;
ASF::Tag *tag;
ASF::Properties *properties;
List<ASF::File::BaseObject *> objects;
ASF::File::ContentDescriptionObject *contentDescriptionObject;
ASF::File::ExtendedContentDescriptionObject *extendedContentDescriptionObject;
ASF::File::HeaderExtensionObject *headerExtensionObject;
ASF::File::MetadataObject *metadataObject;
ASF::File::MetadataLibraryObject *metadataLibraryObject;
headerSize(0) {}
unsigned long long headerSize;
SCOPED_PTR<ASF::Tag> tag;
SCOPED_PTR<ASF::AudioProperties> properties;
ObjectList objects;
SHARED_PTR<ContentDescriptionObject> contentDescriptionObject;
SHARED_PTR<ExtendedContentDescriptionObject> extendedContentDescriptionObject;
SHARED_PTR<HeaderExtensionObject> headerExtensionObject;
SHARED_PTR<MetadataObject> metadataObject;
SHARED_PTR<MetadataLibraryObject> metadataLibraryObject;
};
static ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
static ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16);
static ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16);
static ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
static ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16);
static ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16);
static ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16);
static ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16);
static ByteVector contentEncryptionGuid("\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E", 16);
static ByteVector extendedContentEncryptionGuid("\x14\xE6\x8A\x29\x22\x26 \x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C", 16);
static ByteVector advancedContentEncryptionGuid("\xB6\x9B\x07\x7A\xA4\xDA\x12\x4E\xA5\xCA\x91\xD3\x8D\xC1\x1A\x8D", 16);
namespace
{
const ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
const ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16);
const ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16);
const ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
const ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16);
const ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16);
const ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16);
const ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16);
const ByteVector codecListGuid("\x40\x52\xd1\x86\x1d\x31\xd0\x11\xa3\xa4\x00\xa0\xc9\x03\x48\xf6", 16);
const ByteVector contentEncryptionGuid("\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E", 16);
const ByteVector extendedContentEncryptionGuid("\x14\xE6\x8A\x29\x22\x26 \x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C", 16);
const ByteVector advancedContentEncryptionGuid("\xB6\x9B\x07\x7A\xA4\xDA\x12\x4E\xA5\xCA\x91\xD3\x8D\xC1\x1A\x8D", 16);
}
class ASF::File::BaseObject
class ASF::File::FilePrivate::BaseObject
{
public:
ByteVector data;
virtual ~BaseObject() {}
virtual ByteVector guid() = 0;
virtual ByteVector guid() const = 0;
virtual void parse(ASF::File *file, unsigned int size);
virtual ByteVector render(ASF::File *file);
};
class ASF::File::UnknownObject : public ASF::File::BaseObject
class ASF::File::FilePrivate::UnknownObject : public ASF::File::FilePrivate::BaseObject
{
ByteVector myGuid;
public:
UnknownObject(const ByteVector &guid);
ByteVector guid();
explicit UnknownObject(const ByteVector &guid);
ByteVector guid() const;
};
class ASF::File::FilePropertiesObject : public ASF::File::BaseObject
class ASF::File::FilePrivate::FilePropertiesObject : public ASF::File::FilePrivate::BaseObject
{
public:
ByteVector guid();
void parse(ASF::File *file, uint size);
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
};
class ASF::File::StreamPropertiesObject : public ASF::File::BaseObject
class ASF::File::FilePrivate::StreamPropertiesObject : public ASF::File::FilePrivate::BaseObject
{
public:
ByteVector guid();
void parse(ASF::File *file, uint size);
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
};
class ASF::File::ContentDescriptionObject : public ASF::File::BaseObject
class ASF::File::FilePrivate::ContentDescriptionObject : public ASF::File::FilePrivate::BaseObject
{
public:
ByteVector guid();
void parse(ASF::File *file, uint size);
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
ByteVector render(ASF::File *file);
};
class ASF::File::ExtendedContentDescriptionObject : public ASF::File::BaseObject
class ASF::File::FilePrivate::ExtendedContentDescriptionObject : public ASF::File::FilePrivate::BaseObject
{
public:
ByteVectorList attributeData;
ByteVector guid();
void parse(ASF::File *file, uint size);
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
ByteVector render(ASF::File *file);
};
class ASF::File::MetadataObject : public ASF::File::BaseObject
class ASF::File::FilePrivate::MetadataObject : public ASF::File::FilePrivate::BaseObject
{
public:
ByteVectorList attributeData;
ByteVector guid();
void parse(ASF::File *file, uint size);
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
ByteVector render(ASF::File *file);
};
class ASF::File::MetadataLibraryObject : public ASF::File::BaseObject
class ASF::File::FilePrivate::MetadataLibraryObject : public ASF::File::FilePrivate::BaseObject
{
public:
ByteVectorList attributeData;
ByteVector guid();
void parse(ASF::File *file, uint size);
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
ByteVector render(ASF::File *file);
};
class ASF::File::HeaderExtensionObject : public ASF::File::BaseObject
class ASF::File::FilePrivate::HeaderExtensionObject : public ASF::File::FilePrivate::BaseObject
{
public:
List<ASF::File::BaseObject *> objects;
~HeaderExtensionObject();
ByteVector guid();
void parse(ASF::File *file, uint size);
ObjectList objects;
HeaderExtensionObject();
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
ByteVector render(ASF::File *file);
};
ASF::File::HeaderExtensionObject::~HeaderExtensionObject()
class ASF::File::FilePrivate::CodecListObject : public ASF::File::FilePrivate::BaseObject
{
for(unsigned int i = 0; i < objects.size(); i++) {
delete objects[i];
}
}
public:
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
void ASF::File::BaseObject::parse(ASF::File *file, unsigned int size)
private:
enum CodecType
{
Video = 0x0001,
Audio = 0x0002,
Unknown = 0xFFFF
};
};
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::null;
data = ByteVector();
}
ByteVector ASF::File::BaseObject::render(ASF::File * /*file*/)
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::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid)
ASF::File::FilePrivate::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid)
{
}
ByteVector ASF::File::UnknownObject::guid()
ByteVector ASF::File::FilePrivate::UnknownObject::guid() const
{
return myGuid;
}
ByteVector ASF::File::FilePropertiesObject::guid()
ByteVector ASF::File::FilePrivate::FilePropertiesObject::guid() const
{
return filePropertiesGuid;
}
void ASF::File::FilePropertiesObject::parse(ASF::File *file, uint size)
void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, unsigned int size)
{
BaseObject::parse(file, size);
file->d->properties->setLength((int)(data.mid(40, 8).toLongLong(false) / 10000000L - data.mid(56, 8).toLongLong(false) / 1000L));
if(data.size() < 64) {
debug("ASF::File::FilePrivate::FilePropertiesObject::parse() -- data is too short.");
return;
}
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));
}
ByteVector ASF::File::StreamPropertiesObject::guid()
ByteVector ASF::File::FilePrivate::StreamPropertiesObject::guid() const
{
return streamPropertiesGuid;
}
void ASF::File::StreamPropertiesObject::parse(ASF::File *file, uint size)
void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsigned int size)
{
BaseObject::parse(file, size);
file->d->properties->setChannels(data.mid(56, 2).toShort(false));
file->d->properties->setSampleRate(data.mid(58, 4).toUInt(false));
file->d->properties->setBitrate(data.mid(62, 4).toUInt(false) * 8 / 1000);
if(data.size() < 70) {
debug("ASF::File::FilePrivate::StreamPropertiesObject::parse() -- data is too short.");
return;
}
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::ContentDescriptionObject::guid()
ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const
{
return contentDescriptionGuid;
}
void ASF::File::ContentDescriptionObject::parse(ASF::File *file, uint /*size*/)
void ASF::File::FilePrivate::ContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/)
{
file->d->contentDescriptionObject = this;
int titleLength = file->readWORD();
int artistLength = file->readWORD();
int copyrightLength = file->readWORD();
int commentLength = file->readWORD();
int ratingLength = file->readWORD();
file->d->tag->setTitle(file->readString(titleLength));
file->d->tag->setArtist(file->readString(artistLength));
file->d->tag->setCopyright(file->readString(copyrightLength));
file->d->tag->setComment(file->readString(commentLength));
file->d->tag->setRating(file->readString(ratingLength));
const int titleLength = readWORD(file);
const int artistLength = readWORD(file);
const int copyrightLength = readWORD(file);
const int commentLength = readWORD(file);
const int ratingLength = readWORD(file);
file->d->tag->setTitle(readString(file,titleLength));
file->d->tag->setArtist(readString(file,artistLength));
file->d->tag->setCopyright(readString(file,copyrightLength));
file->d->tag->setComment(readString(file,commentLength));
file->d->tag->setRating(readString(file,ratingLength));
}
ByteVector ASF::File::ContentDescriptionObject::render(ASF::File *file)
ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *file)
{
ByteVector v1 = file->renderString(file->d->tag->title());
ByteVector v2 = file->renderString(file->d->tag->artist());
ByteVector v3 = file->renderString(file->d->tag->copyright());
ByteVector v4 = file->renderString(file->d->tag->comment());
ByteVector v5 = file->renderString(file->d->tag->rating());
const ByteVector v1 = renderString(file->d->tag->title());
const ByteVector v2 = renderString(file->d->tag->artist());
const ByteVector v3 = renderString(file->d->tag->copyright());
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);
@@ -243,15 +280,14 @@ ByteVector ASF::File::ContentDescriptionObject::render(ASF::File *file)
return BaseObject::render(file);
}
ByteVector ASF::File::ExtendedContentDescriptionObject::guid()
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::guid() const
{
return extendedContentDescriptionGuid;
}
void ASF::File::ExtendedContentDescriptionObject::parse(ASF::File *file, uint /*size*/)
void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/)
{
file->d->extendedContentDescriptionObject = this;
int count = file->readWORD();
int count = readWORD(file);
while(count--) {
ASF::Attribute attribute;
String name = attribute.parse(*file);
@@ -259,23 +295,22 @@ void ASF::File::ExtendedContentDescriptionObject::parse(ASF::File *file, uint /*
}
}
ByteVector ASF::File::ExtendedContentDescriptionObject::render(ASF::File *file)
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(attributeData.toByteVector(ByteVector::null));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
ByteVector ASF::File::MetadataObject::guid()
ByteVector ASF::File::FilePrivate::MetadataObject::guid() const
{
return metadataGuid;
}
void ASF::File::MetadataObject::parse(ASF::File *file, uint /*size*/)
void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, unsigned int /*size*/)
{
file->d->metadataObject = this;
int count = file->readWORD();
int count = readWORD(file);
while(count--) {
ASF::Attribute attribute;
String name = attribute.parse(*file, 1);
@@ -283,23 +318,22 @@ void ASF::File::MetadataObject::parse(ASF::File *file, uint /*size*/)
}
}
ByteVector ASF::File::MetadataObject::render(ASF::File *file)
ByteVector ASF::File::FilePrivate::MetadataObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(attributeData.toByteVector(ByteVector::null));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
ByteVector ASF::File::MetadataLibraryObject::guid()
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::guid() const
{
return metadataLibraryGuid;
}
void ASF::File::MetadataLibraryObject::parse(ASF::File *file, uint /*size*/)
void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, unsigned int /*size*/)
{
file->d->metadataLibraryObject = this;
int count = file->readWORD();
int count = readWORD(file);
while(count--) {
ASF::Attribute attribute;
String name = attribute.parse(*file, 2);
@@ -307,24 +341,27 @@ void ASF::File::MetadataLibraryObject::parse(ASF::File *file, uint /*size*/)
}
}
ByteVector ASF::File::MetadataLibraryObject::render(ASF::File *file)
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(attributeData.toByteVector(ByteVector::null));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
ByteVector ASF::File::HeaderExtensionObject::guid()
ASF::File::FilePrivate::HeaderExtensionObject::HeaderExtensionObject()
{
}
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::guid() const
{
return headerExtensionGuid;
}
void ASF::File::HeaderExtensionObject::parse(ASF::File *file, uint /*size*/)
void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsigned int /*size*/)
{
file->d->headerExtensionObject = this;
file->seek(18, File::Current);
long long dataSize = file->readDWORD();
long long dataSize = readDWORD(file);
long long dataPos = 0;
while(dataPos < dataSize) {
ByteVector guid = file->readBlock(16);
@@ -333,20 +370,22 @@ void ASF::File::HeaderExtensionObject::parse(ASF::File *file, uint /*size*/)
break;
}
bool ok;
long long size = file->readQWORD(&ok);
long long size = readQWORD(file, &ok);
if(!ok) {
file->setValid(false);
break;
}
BaseObject *obj;
SHARED_PTR<BaseObject> obj;
if(guid == metadataGuid) {
obj = new MetadataObject();
file->d->metadataObject.reset(new MetadataObject());
obj = file->d->metadataObject;
}
else if(guid == metadataLibraryGuid) {
obj = 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);
@@ -354,124 +393,116 @@ void ASF::File::HeaderExtensionObject::parse(ASF::File *file, uint /*size*/)
}
}
ByteVector ASF::File::HeaderExtensionObject::render(ASF::File *file)
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::render(ASF::File *file)
{
data.clear();
for(unsigned int i = 0; i < objects.size(); i++) {
data.append(objects[i]->render(file));
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);
}
ByteVector ASF::File::FilePrivate::CodecListObject::guid() const
{
return codecListGuid;
}
void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned int size)
{
BaseObject::parse(file, size);
if(data.size() <= 20) {
debug("ASF::File::FilePrivate::CodecListObject::parse() -- data is too short.");
return;
}
unsigned int pos = 16;
const int count = data.toUInt32LE(pos);
pos += 4;
for(int i = 0; i < count; ++i) {
if(pos >= data.size())
break;
const CodecType type = static_cast<CodecType>(data.toUInt16LE(pos));
pos += 2;
int nameLength = data.toUInt16LE(pos);
pos += 2;
const unsigned int namePos = pos;
pos += nameLength * 2;
const int descLength = data.toUInt16LE(pos);
pos += 2;
const unsigned int descPos = pos;
pos += descLength * 2;
const int infoLength = data.toUInt16LE(pos);
pos += 2 + infoLength * 2;
if(type == CodecListObject::Audio) {
// First audio codec found.
const String name(data.mid(namePos, nameLength * 2), String::UTF16LE);
file->d->properties->setCodecName(name.stripWhiteSpace());
const String desc(data.mid(descPos, descLength * 2), String::UTF16LE);
file->d->properties->setCodecDescription(desc.stripWhiteSpace());
break;
}
}
}
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
bool ASF::File::isSupported(IOStream *stream)
{
// An ASF file has to start with the designated GUID.
const ByteVector id = Utils::readHeader(stream, 16, false);
return (id == headerGuid);
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::File::File(FileName file, bool readProperties, Properties::ReadStyle propertiesStyle)
: TagLib::File(file)
ASF::File::File(FileName file, bool, AudioProperties::ReadStyle) :
TagLib::File(file),
d(new FilePrivate())
{
d = new FilePrivate;
read(readProperties, propertiesStyle);
if(isOpen())
read();
}
ASF::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle propertiesStyle)
: TagLib::File(stream)
ASF::File::File(IOStream *stream, bool, AudioProperties::ReadStyle) :
TagLib::File(stream),
d(new FilePrivate())
{
d = new FilePrivate;
read(readProperties, propertiesStyle);
if(isOpen())
read();
}
ASF::File::~File()
{
for(unsigned int i = 0; i < d->objects.size(); i++) {
delete d->objects[i];
}
if(d->tag) {
delete d->tag;
}
if(d->properties) {
delete d->properties;
}
delete d;
}
ASF::Tag *ASF::File::tag() const
{
return d->tag;
return d->tag.get();
}
ASF::Properties *ASF::File::audioProperties() const
ASF::AudioProperties *ASF::File::audioProperties() const
{
return d->properties;
}
void ASF::File::read(bool /*readProperties*/, Properties::ReadStyle /*propertiesStyle*/)
{
if(!isValid())
return;
ByteVector guid = readBlock(16);
if(guid != headerGuid) {
debug("ASF: Not an ASF file.");
setValid(false);
return;
}
d->tag = new ASF::Tag();
d->properties = new ASF::Properties();
bool ok;
d->size = readQWORD(&ok);
if(!ok) {
setValid(false);
return;
}
int numObjects = readDWORD(&ok);
if(!ok) {
setValid(false);
return;
}
seek(2, Current);
for(int i = 0; i < numObjects; i++) {
ByteVector guid = readBlock(16);
if(guid.size() != 16) {
setValid(false);
break;
}
long size = (long)readQWORD(&ok);
if(!ok) {
setValid(false);
break;
}
BaseObject *obj;
if(guid == filePropertiesGuid) {
obj = new FilePropertiesObject();
}
else if(guid == streamPropertiesGuid) {
obj = new StreamPropertiesObject();
}
else if(guid == contentDescriptionGuid) {
obj = new ContentDescriptionObject();
}
else if(guid == extendedContentDescriptionGuid) {
obj = new ExtendedContentDescriptionObject();
}
else if(guid == headerExtensionGuid) {
obj = new HeaderExtensionObject();
}
else {
if(guid == contentEncryptionGuid ||
guid == extendedContentEncryptionGuid ||
guid == advancedContentEncryptionGuid) {
d->properties->setEncrypted(true);
}
obj = new UnknownObject(guid);
}
obj->parse(this, size);
d->objects.append(obj);
}
return d->properties.get();
}
bool ASF::File::save()
@@ -487,40 +518,51 @@ bool ASF::File::save()
}
if(!d->contentDescriptionObject) {
d->contentDescriptionObject = new ContentDescriptionObject();
d->contentDescriptionObject.reset(new FilePrivate::ContentDescriptionObject());
d->objects.append(d->contentDescriptionObject);
}
if(!d->extendedContentDescriptionObject) {
d->extendedContentDescriptionObject = new ExtendedContentDescriptionObject();
d->extendedContentDescriptionObject.reset(new FilePrivate::ExtendedContentDescriptionObject());
d->objects.append(d->extendedContentDescriptionObject);
}
if(!d->headerExtensionObject) {
d->headerExtensionObject = new HeaderExtensionObject();
d->headerExtensionObject.reset(new FilePrivate::HeaderExtensionObject());
d->objects.append(d->headerExtensionObject);
}
if(!d->metadataObject) {
d->metadataObject = new MetadataObject();
d->metadataObject.reset(new FilePrivate::MetadataObject());
d->headerExtensionObject->objects.append(d->metadataObject);
}
if(!d->metadataLibraryObject) {
d->metadataLibraryObject = new MetadataLibraryObject();
d->metadataLibraryObject.reset(new FilePrivate::MetadataLibraryObject());
d->headerExtensionObject->objects.append(d->metadataLibraryObject);
}
ASF::AttributeListMap::ConstIterator it = d->tag->attributeListMap().begin();
for(; it != d->tag->attributeListMap().end(); it++) {
d->extendedContentDescriptionObject->attributeData.clear();
d->metadataObject->attributeData.clear();
d->metadataLibraryObject->attributeData.clear();
const AttributeListMap allAttributes = d->tag->attributeListMap();
for(AttributeListMap::ConstIterator it = allAttributes.begin(); it != allAttributes.end(); ++it) {
const String &name = it->first;
const AttributeList &attributes = it->second;
bool inExtendedContentDescriptionObject = false;
bool inMetadataObject = false;
for(unsigned int j = 0; j < attributes.size(); j++) {
const Attribute &attribute = attributes[j];
bool largeValue = attribute.dataSize() > 65535;
if(!inExtendedContentDescriptionObject && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
for(AttributeList::ConstIterator jt = attributes.begin(); jt != attributes.end(); ++jt) {
const Attribute &attribute = *jt;
const bool largeValue = (attribute.dataSize() > 65535);
const bool guid = (attribute.type() == Attribute::GuidType);
if(!inExtendedContentDescriptionObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
d->extendedContentDescriptionObject->attributeData.append(attribute.render(name));
inExtendedContentDescriptionObject = true;
}
else if(!inMetadataObject && !largeValue && attribute.language() == 0 && attribute.stream() != 0) {
else if(!inMetadataObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() != 0) {
d->metadataObject->attributeData.append(attribute.render(name, 1));
inMetadataObject = true;
}
@@ -531,85 +573,105 @@ bool ASF::File::save()
}
ByteVector data;
for(unsigned int i = 0; i < d->objects.size(); i++) {
data.append(d->objects[i]->render(this));
for(FilePrivate::ObjectConstIterator it = d->objects.begin(); it != d->objects.end(); ++it) {
data.append((*it)->render(this));
}
data = headerGuid + ByteVector::fromLongLong(data.size() + 30, false) + ByteVector::fromUInt(d->objects.size(), false) + ByteVector("\x01\x02", 2) + data;
insert(data, 0, (TagLib::ulong)d->size);
seek(16);
writeBlock(ByteVector::fromUInt64LE(data.size() + 30));
writeBlock(ByteVector::fromUInt32LE(d->objects.size()));
writeBlock(ByteVector("\x01\x02", 2));
insert(data, 30, static_cast<size_t>(d->headerSize - 30));
d->headerSize = data.size() + 30;
return true;
}
////////////////////////////////////////////////////////////////////////////////
// protected members
// private members
////////////////////////////////////////////////////////////////////////////////
int ASF::File::readBYTE(bool *ok)
void ASF::File::read()
{
ByteVector v = readBlock(1);
if(v.size() != 1) {
if(ok) *ok = false;
return 0;
}
if(ok) *ok = true;
return v[0];
}
if(!isValid())
return;
int ASF::File::readWORD(bool *ok)
{
ByteVector v = readBlock(2);
if(v.size() != 2) {
if(ok) *ok = false;
return 0;
if(readBlock(16) != headerGuid) {
debug("ASF::File::read(): Not an ASF file.");
setValid(false);
return;
}
if(ok) *ok = true;
return v.toUShort(false);
}
unsigned int ASF::File::readDWORD(bool *ok)
{
ByteVector v = readBlock(4);
if(v.size() != 4) {
if(ok) *ok = false;
return 0;
d->tag.reset(new ASF::Tag());
d->properties.reset(new ASF::AudioProperties());
bool ok;
d->headerSize = readQWORD(this, &ok);
if(!ok) {
setValid(false);
return;
}
if(ok) *ok = true;
return v.toUInt(false);
}
long long ASF::File::readQWORD(bool *ok)
{
ByteVector v = readBlock(8);
if(v.size() != 8) {
if(ok) *ok = false;
return 0;
int numObjects = readDWORD(this, &ok);
if(!ok) {
setValid(false);
return;
}
if(ok) *ok = true;
return v.toLongLong(false);
}
seek(2, Current);
String ASF::File::readString(int length)
{
ByteVector data = readBlock(length);
unsigned int size = data.size();
while (size >= 2) {
if(data[size - 1] != '\0' || data[size - 2] != '\0') {
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) {
setValid(false);
break;
}
size -= 2;
long size = (long)readQWORD(this, &ok);
if(!ok) {
setValid(false);
break;
}
SHARED_PTR<FilePrivate::BaseObject> obj;
if(guid == filePropertiesGuid) {
filePropertiesObject.reset(new FilePrivate::FilePropertiesObject());
obj = filePropertiesObject;
}
else if(guid == streamPropertiesGuid) {
streamPropertiesObject.reset(new FilePrivate::StreamPropertiesObject());
obj = streamPropertiesObject;
}
else if(guid == contentDescriptionGuid) {
d->contentDescriptionObject.reset(new FilePrivate::ContentDescriptionObject());
obj = d->contentDescriptionObject;
}
else if(guid == extendedContentDescriptionGuid) {
d->extendedContentDescriptionObject.reset(new FilePrivate::ExtendedContentDescriptionObject());
obj = d->extendedContentDescriptionObject;
}
else if(guid == headerExtensionGuid) {
d->headerExtensionObject.reset(new FilePrivate::HeaderExtensionObject());
obj = d->headerExtensionObject;
}
else if(guid == codecListGuid) {
obj.reset(new FilePrivate::CodecListObject());
}
else {
if(guid == contentEncryptionGuid ||
guid == extendedContentEncryptionGuid ||
guid == advancedContentEncryptionGuid) {
d->properties->setEncrypted(true);
}
obj.reset(new FilePrivate::UnknownObject(guid));
}
obj->parse(this, size);
d->objects.append(obj);
}
if(size != data.size()) {
data.resize(size);
}
return String(data, String::UTF16LE);
}
ByteVector ASF::File::renderString(const String &str, bool includeLength)
{
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false);
if(includeLength) {
data = ByteVector::fromShort(data.size(), false) + data;
if(!filePropertiesObject || !streamPropertiesObject) {
debug("ASF::File::read(): Missing mandatory header objects.");
setValid(false);
return;
}
return data;
}

View File

@@ -53,12 +53,11 @@ namespace TagLib {
* false, \a propertiesStyle is ignored.
*
* \note In the current implementation, both \a readProperties and
* \a propertiesStyle are ignored.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
* \a propertiesStyle are ignored. The audio properties are always
* read.
*/
File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
File(FileName file, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Contructs an ASF file from \a file. If \a readProperties is true the
@@ -66,12 +65,14 @@ namespace TagLib {
* false, \a propertiesStyle is ignored.
*
* \note In the current implementation, both \a readProperties and
* \a propertiesStyle are ignored.
* \a propertiesStyle are ignored. The audio properties are always
* read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*/
File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
File(IOStream *stream, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Destroys this instance of the File.
@@ -93,7 +94,7 @@ namespace TagLib {
/*!
* Returns the ASF audio properties for this file.
*/
virtual Properties *audioProperties() const;
virtual AudioProperties *audioProperties() const;
/*!
* Save the file.
@@ -102,28 +103,17 @@ namespace TagLib {
*/
virtual bool save();
/*!
* Returns whether or not the given \a stream can be opened as an ASF
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
int readBYTE(bool *ok = 0);
int readWORD(bool *ok = 0);
unsigned int readDWORD(bool *ok = 0);
long long readQWORD(bool *ok = 0);
static ByteVector renderString(const String &str, bool includeLength = false);
String readString(int len);
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
friend class Attribute;
friend class Picture;
class BaseObject;
class UnknownObject;
class FilePropertiesObject;
class StreamPropertiesObject;
class ContentDescriptionObject;
class ExtendedContentDescriptionObject;
class HeaderExtensionObject;
class MetadataObject;
class MetadataLibraryObject;
void read();
class FilePrivate;
FilePrivate *d;

View File

@@ -23,160 +23,170 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <taglib.h>
#include <tdebug.h>
#include <tsmartptr.h>
#include "asfattribute.h"
#include "asffile.h"
#include "asfpicture.h"
#include "asfutils.h"
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;
};
////////////////////////////////////////////////////////////////////////////////
// Picture class members
////////////////////////////////////////////////////////////////////////////////
ASF::Picture::Picture()
ASF::Picture::Picture() :
d(new PicturePrivate())
{
d = new PicturePrivate();
d->valid = true;
d->data->valid = true;
}
ASF::Picture::Picture(const Picture& other)
: d(other.d)
ASF::Picture::Picture(const Picture& other) :
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)
{
if(other.d != d) {
if(d->deref())
delete d;
d = other.d;
d->ref();
}
Picture(other).swap(*this);
return *this;
}
void ASF::Picture::swap(Picture &other)
{
using std::swap;
swap(d, other.d);
}
ByteVector ASF::Picture::render() const
{
if(!isValid())
return ByteVector::null;
return ByteVector();
return
ByteVector((char)d->type) +
ByteVector::fromUInt(d->picture.size(), false) +
ASF::File::renderString(d->mimeType) +
ASF::File::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;
uint dataLen = bytes.mid(pos, 4).toUInt(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);
@@ -117,6 +119,11 @@ namespace TagLib
*/
Picture& operator=(const Picture& other);
/*!
* Exchanges the content of the Picture by the content of \a other.
*/
void swap(Picture &other);
/*!
* Returns true if Picture stores valid picture
*/
@@ -201,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();
private:
friend class Attribute;
#endif
private:
class PicturePrivate;
PicturePrivate *d;
};
void parse(const ByteVector &);
static Picture fromInvalid();
class PicturePrivate;
PicturePrivate *d;
};
}
}

View File

@@ -23,24 +23,32 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <tdebug.h>
#include <tstring.h>
#include "asfproperties.h"
using namespace TagLib;
class ASF::Properties::PropertiesPrivate
class ASF::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(): length(0), bitrate(0), sampleRate(0), channels(0), encrypted(false) {}
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
channels(0),
bitsPerSample(0),
codec(ASF::AudioProperties::Unknown),
encrypted(false) {}
int length;
int bitrate;
int sampleRate;
int channels;
int bitsPerSample;
ASF::AudioProperties::Codec codec;
String codecName;
String codecDescription;
bool encrypted;
};
@@ -48,38 +56,68 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::Properties::Properties() : AudioProperties(AudioProperties::Average)
ASF::AudioProperties::AudioProperties() :
TagLib::AudioProperties(),
d(new PropertiesPrivate())
{
d = new PropertiesPrivate;
}
ASF::Properties::~Properties()
ASF::AudioProperties::~AudioProperties()
{
if(d)
delete d;
delete d;
}
int ASF::Properties::length() const
int ASF::AudioProperties::length() const
{
return lengthInSeconds();
}
int ASF::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
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;
}
bool ASF::Properties::isEncrypted() const
int ASF::AudioProperties::bitsPerSample() const
{
return d->bitsPerSample;
}
ASF::AudioProperties::Codec ASF::AudioProperties::codec() const
{
return d->codec;
}
String ASF::AudioProperties::codecName() const
{
return d->codecName;
}
String ASF::AudioProperties::codecDescription() const
{
return d->codecDescription;
}
bool ASF::AudioProperties::isEncrypted() const
{
return d->encrypted;
}
@@ -88,28 +126,64 @@ bool ASF::Properties::isEncrypted() const
// private members
////////////////////////////////////////////////////////////////////////////////
void ASF::Properties::setLength(int length)
void ASF::AudioProperties::setLengthInMilliseconds(int value)
{
d->length = length;
d->length = value;
}
void ASF::Properties::setBitrate(int length)
void ASF::AudioProperties::setBitrate(int value)
{
d->bitrate = length;
d->bitrate = value;
}
void ASF::Properties::setSampleRate(int length)
void ASF::AudioProperties::setSampleRate(int value)
{
d->sampleRate = length;
d->sampleRate = value;
}
void ASF::Properties::setChannels(int length)
void ASF::AudioProperties::setChannels(int value)
{
d->channels = length;
d->channels = value;
}
void ASF::Properties::setEncrypted(bool encrypted)
void ASF::AudioProperties::setBitsPerSample(int value)
{
d->encrypted = encrypted;
d->bitsPerSample = value;
}
void ASF::AudioProperties::setCodec(int value)
{
switch(value)
{
case 0x0160:
d->codec = WMA1;
break;
case 0x0161:
d->codec = WMA2;
break;
case 0x0162:
d->codec = WMA9Pro;
break;
case 0x0163:
d->codec = WMA9Lossless;
break;
default:
d->codec = Unknown;
break;
}
}
void ASF::AudioProperties::setCodecName(const String &value)
{
d->codecName = value;
}
void ASF::AudioProperties::setCodecDescription(const String &value)
{
d->codecDescription = value;
}
void ASF::AudioProperties::setEncrypted(bool value)
{
d->encrypted = value;
}

View File

@@ -34,37 +34,143 @@ namespace TagLib {
namespace ASF {
class File;
//! An implementation of ASF audio properties
class TAGLIB_EXPORT Properties : public AudioProperties
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
friend class File;
public:
/*!
* Audio codec types can be used in ASF file.
*/
enum Codec
{
/*!
* Couldn't detect the codec.
*/
Unknown = 0,
/*!
* Windows Media Audio 1
*/
WMA1,
/*!
* Windows Media Audio 2 or above
*/
WMA2,
/*!
* Windows Media Audio 9 Professional
*/
WMA9Pro,
/*!
* Windows Media Audio 9 Lossless
*/
WMA9Lossless,
};
/*!
* Create 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();
// Reimplementations.
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
*/
virtual int length() const;
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
virtual int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
virtual int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
/*!
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
/*!
* Returns the number of audio channels.
*/
virtual int channels() const;
/*!
* Returns the number of bits per audio sample.
*/
int bitsPerSample() const;
/*!
* Returns the codec used in the file.
*
* \see codecName()
* \see codecDescription()
*/
Codec codec() const;
/*!
* Returns the concrete codec name, for example "Windows Media Audio 9.1"
* used in the file if available, otherwise an empty string.
*
* \see codec()
* \see codecDescription()
*/
String codecName() const;
/*!
* Returns the codec description, typically contains the encoder settings,
* for example "VBR Quality 50, 44kHz, stereo 1-pass VBR" if available,
* otherwise an empty string.
*
* \see codec()
* \see codecName()
*/
String codecDescription() const;
/*!
* Returns whether or not the file is encrypted.
*/
bool isEncrypted() const;
#ifndef DO_NOT_DOCUMENT
void setLength(int value);
private:
void setLengthInMilliseconds(int value);
void setBitrate(int value);
void setSampleRate(int value);
void setChannels(int value);
void setBitsPerSample(int value);
void setCodec(int value);
void setCodecName(const String &value);
void setCodecDescription(const String &value);
void setEncrypted(bool value);
#endif
private:
class PropertiesPrivate;
PropertiesPrivate *d;
};

View File

@@ -23,10 +23,8 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <tpicturemap.h>
#include <tpropertymap.h>
#include "asftag.h"
using namespace TagLib;
@@ -42,16 +40,15 @@ public:
AttributeListMap attributeListMap;
};
ASF::Tag::Tag()
: TagLib::Tag()
ASF::Tag::Tag() :
TagLib::Tag(),
d(new TagPrivate())
{
d = new TagPrivate;
}
ASF::Tag::~Tag()
{
if(d)
delete d;
delete d;
}
String ASF::Tag::title() const
@@ -68,7 +65,7 @@ String ASF::Tag::album() const
{
if(d->attributeListMap.contains("WM/AlbumTitle"))
return d->attributeListMap["WM/AlbumTitle"][0].toString();
return String::null;
return String();
}
String ASF::Tag::copyright() const
@@ -111,7 +108,92 @@ String ASF::Tag::genre() const
{
if(d->attributeListMap.contains("WM/Genre"))
return d->attributeListMap["WM/Genre"][0].toString();
return String::null;
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)
@@ -149,26 +231,127 @@ void ASF::Tag::setGenre(const String &value)
setAttribute("WM/Genre", value);
}
void ASF::Tag::setYear(uint value)
void ASF::Tag::setYear(unsigned int value)
{
setAttribute("WM/Year", String::number(value));
}
void ASF::Tag::setTrack(uint value)
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;
}
const ASF::AttributeListMap &ASF::Tag::attributeListMap() const
{
return d->attributeListMap;
}
bool ASF::Tag::contains(const String &key) const
{
return d->attributeListMap.contains(key);
}
void ASF::Tag::removeItem(const String &key)
{
AttributeListMap::Iterator it = d->attributeListMap.find(key);
if(it != d->attributeListMap.end())
d->attributeListMap.erase(it);
d->attributeListMap.erase(key);
}
ASF::AttributeList ASF::Tag::attribute(const String &name) const
{
return d->attributeListMap[name];
}
void ASF::Tag::setAttribute(const String &name, const Attribute &attribute)
@@ -178,6 +361,11 @@ void ASF::Tag::setAttribute(const String &name, const Attribute &attribute)
d->attributeListMap.insert(name, value);
}
void ASF::Tag::setAttribute(const String &name, const AttributeList &values)
{
d->attributeListMap.insert(name, values);
}
void ASF::Tag::addAttribute(const String &name, const Attribute &attribute)
{
if(d->attributeListMap.contains(name)) {
@@ -196,3 +384,169 @@ bool ASF::Tag::isEmpty() const
d->attributeListMap.isEmpty();
}
namespace
{
const char *keyTranslation[][2] = {
{ "WM/AlbumTitle", "ALBUM" },
{ "WM/AlbumArtist", "ALBUMARTIST" },
{ "WM/Composer", "COMPOSER" },
{ "WM/Writer", "WRITER" },
{ "WM/Conductor", "CONDUCTOR" },
{ "WM/ModifiedBy", "REMIXER" },
{ "WM/Year", "DATE" },
{ "WM/OriginalReleaseYear", "ORIGINALDATE" },
{ "WM/Producer", "PRODUCER" },
{ "WM/ContentGroupDescription", "GROUPING" },
{ "WM/SubTitle", "SUBTITLE" },
{ "WM/SetSubTitle", "DISCSUBTITLE" },
{ "WM/TrackNumber", "TRACKNUMBER" },
{ "WM/PartOfSet", "DISCNUMBER" },
{ "WM/Genre", "GENRE" },
{ "WM/BeatsPerMinute", "BPM" },
{ "WM/Mood", "MOOD" },
{ "WM/ISRC", "ISRC" },
{ "WM/Lyrics", "LYRICS" },
{ "WM/Media", "MEDIA" },
{ "WM/Publisher", "LABEL" },
{ "WM/CatalogNo", "CATALOGNUMBER" },
{ "WM/Barcode", "BARCODE" },
{ "WM/EncodedBy", "ENCODEDBY" },
{ "WM/AlbumSortOrder", "ALBUMSORT" },
{ "WM/AlbumArtistSortOrder", "ALBUMARTISTSORT" },
{ "WM/ArtistSortOrder", "ARTISTSORT" },
{ "WM/TitleSortOrder", "TITLESORT" },
{ "WM/Script", "SCRIPT" },
{ "WM/Language", "LANGUAGE" },
{ "MusicBrainz/Track Id", "MUSICBRAINZ_TRACKID" },
{ "MusicBrainz/Artist Id", "MUSICBRAINZ_ARTISTID" },
{ "MusicBrainz/Album Id", "MUSICBRAINZ_ALBUMID" },
{ "MusicBrainz/Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
{ "MusicBrainz/Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
{ "MusicBrainz/Work Id", "MUSICBRAINZ_WORKID" },
{ "MusicIP/PUID", "MUSICIP_PUID" },
{ "Acoustid/Id", "ACOUSTID_ID" },
{ "Acoustid/Fingerprint", "ACOUSTID_FINGERPRINT" },
};
const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
String translateKey(const String &key)
{
for(size_t i = 0; i < keyTranslationSize; ++i) {
if(key == keyTranslation[i][0])
return keyTranslation[i][1];
}
return String();
}
}
PropertyMap ASF::Tag::properties() const
{
PropertyMap props;
if(!d->title.isEmpty()) {
props["TITLE"] = d->title;
}
if(!d->artist.isEmpty()) {
props["ARTIST"] = d->artist;
}
if(!d->copyright.isEmpty()) {
props["COPYRIGHT"] = d->copyright;
}
if(!d->comment.isEmpty()) {
props["COMMENT"] = d->comment;
}
ASF::AttributeListMap::ConstIterator it = d->attributeListMap.begin();
for(; it != d->attributeListMap.end(); ++it) {
const String key = translateKey(it->first);
if(!key.isEmpty()) {
AttributeList::ConstIterator it2 = it->second.begin();
for(; it2 != it->second.end(); ++it2) {
if(key == "TRACKNUMBER") {
if(it2->type() == ASF::Attribute::DWordType)
props.insert(key, String::number(it2->toUInt()));
else
props.insert(key, it2->toString());
}
else {
props.insert(key, it2->toString());
}
}
}
else {
props.unsupportedData().append(it->first);
}
}
return props;
}
void ASF::Tag::removeUnsupportedProperties(const StringList &props)
{
StringList::ConstIterator it = props.begin();
for(; it != props.end(); ++it)
d->attributeListMap.erase(*it);
}
PropertyMap ASF::Tag::setProperties(const PropertyMap &props)
{
static Map<String, String> reverseKeyMap;
if(reverseKeyMap.isEmpty()) {
int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
for(int i = 0; i < numKeys; i++) {
reverseKeyMap[keyTranslation[i][1]] = keyTranslation[i][0];
}
}
PropertyMap origProps = properties();
PropertyMap::ConstIterator it = origProps.begin();
for(; it != origProps.end(); ++it) {
if(!props.contains(it->first) || props[it->first].isEmpty()) {
if(it->first == "TITLE") {
d->title.clear();
}
else if(it->first == "ARTIST") {
d->artist.clear();
}
else if(it->first == "COMMENT") {
d->comment.clear();
}
else if(it->first == "COPYRIGHT") {
d->copyright.clear();
}
else {
d->attributeListMap.erase(reverseKeyMap[it->first]);
}
}
}
PropertyMap ignoredProps;
it = props.begin();
for(; it != props.end(); ++it) {
if(reverseKeyMap.contains(it->first)) {
String name = reverseKeyMap[it->first];
removeItem(name);
StringList::ConstIterator it2 = it->second.begin();
for(; it2 != it->second.end(); ++it2) {
addAttribute(name, *it2);
}
}
else if(it->first == "TITLE") {
d->title = it->second.toString();
}
else if(it->first == "ARTIST") {
d->artist = it->second.toString();
}
else if(it->first == "COMMENT") {
d->comment = it->second.toString();
}
else if(it->first == "COPYRIGHT") {
d->copyright = it->second.toString();
}
else {
ignoredProps.insert(it->first, it->second);
}
}
return ignoredProps;
}

View File

@@ -90,13 +90,15 @@ namespace TagLib {
/*!
* Returns the year; if there is no year set, this will return 0.
*/
virtual uint year() const;
virtual unsigned int year() const;
/*!
* Returns the track number; if there is no track number set, this will
* return 0.
*/
virtual uint track() const;
virtual unsigned int track() const;
virtual PictureMap pictures() const;
/*!
* Sets the title to \a s.
@@ -137,12 +139,14 @@ namespace TagLib {
/*!
* Sets the year to \a i. If \a s is 0 then this value will be cleared.
*/
virtual void setYear(uint i);
virtual void setYear(unsigned int i);
/*!
* Sets the track to \a i. If \a s is 0 then this value will be cleared.
*/
virtual void setTrack(uint i);
virtual void setTrack(unsigned int i);
virtual void setPictures(const PictureMap &l);
/*!
* Returns true if the tag does not contain any data. This should be
@@ -152,30 +156,53 @@ namespace TagLib {
virtual bool isEmpty() const;
/*!
* Returns a reference to the item list map. This is an AttributeListMap of
* all of the items in the tag.
*
* This is the most powerfull structure for accessing the items of the tag.
* \deprecated
*/
AttributeListMap &attributeListMap();
/*!
* Returns a reference to the item list map. This is an AttributeListMap of
* all of the items in the tag.
*/
const AttributeListMap &attributeListMap() const;
/*!
* \return True if a value for \a attribute is currently set.
*/
bool contains(const String &name) const;
/*!
* Removes the \a key attribute from the tag
*/
void removeItem(const String &name);
/*!
* \return The list of values for the key \a name, or an empty list if no
* values have been set.
*/
AttributeList attribute(const String &name) const;
/*!
* Sets the \a key attribute to the value of \a attribute. If an attribute
* with the \a key is already present, it will be replaced.
*/
void setAttribute(const String &name, const Attribute &attribute);
/*!
* Sets multiple \a values to the key \a name.
*/
void setAttribute(const String &name, const AttributeList &values);
/*!
* Sets the \a key attribute to the value of \a attribute. If an attribute
* with the \a key is already present, it will be added to the list.
*/
void addAttribute(const String &name, const Attribute &attribute);
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList& properties);
PropertyMap setProperties(const PropertyMap &properties);
private:
class TagPrivate;

104
taglib/asf/asfutils.h Normal file
View File

@@ -0,0 +1,104 @@
/***************************************************************************
copyright : (C) 2015 by Tsuda Kageyu
email : tsuda.kageyu@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 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_ASFUTILS_H
#define TAGLIB_ASFUTILS_H
// THIS FILE IS NOT A PART OF THE TAGLIB API
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
namespace TagLib
{
namespace ASF
{
namespace
{
inline unsigned short readWORD(File *file, bool *ok = 0)
{
const ByteVector v = file->readBlock(2);
if(v.size() != 2) {
if(ok) *ok = false;
return 0;
}
if(ok) *ok = true;
return v.toUInt16LE(0);
}
inline unsigned int readDWORD(File *file, bool *ok = 0)
{
const ByteVector v = file->readBlock(4);
if(v.size() != 4) {
if(ok) *ok = false;
return 0;
}
if(ok) *ok = true;
return v.toUInt32LE(0);
}
inline long long readQWORD(File *file, bool *ok = 0)
{
const ByteVector v = file->readBlock(8);
if(v.size() != 8) {
if(ok) *ok = false;
return 0;
}
if(ok) *ok = true;
return v.toInt64LE(0);
}
inline String readString(File *file, int length)
{
ByteVector data = file->readBlock(length);
size_t size = data.size();
while (size >= 2) {
if(data[size - 1] != '\0' || data[size - 2] != '\0') {
break;
}
size -= 2;
}
if(size != data.size()) {
data.resize(size);
}
return String(data, String::UTF16LE);
}
inline ByteVector renderString(const String &str, bool includeLength = false)
{
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromUInt16LE(0);
if(includeLength) {
data = ByteVector::fromUInt16LE(data.size()) + data;
}
return data;
}
}
}
}
#endif
#endif

View File

@@ -23,29 +23,34 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tstringlist.h>
#include "audioproperties.h"
using namespace TagLib;
class AudioProperties::AudioPropertiesPrivate
{
};
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
AudioProperties::~AudioProperties()
{
}
String AudioProperties::toString() const
{
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 {
@@ -34,7 +35,7 @@ namespace TagLib {
/*!
* The values here are common to most audio formats. For more specific, codec
* dependant values, please see see the subclasses APIs. This is meant to
* dependent values, please see see the subclasses APIs. This is meant to
* compliment the TagLib::File and TagLib::Tag APIs in providing a simple
* interface that is sufficient for most applications.
*/
@@ -69,6 +70,21 @@ namespace TagLib {
*/
virtual int length() const = 0;
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
virtual int lengthInSeconds() const = 0;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
virtual int lengthInMilliseconds() const = 0;
/*!
* Returns the most appropriate bit rate for the file in kb/s. For constant
* bitrate formats this is simply the bitrate of the file. For variable
@@ -86,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

@@ -0,0 +1,166 @@
/***************************************************************************
copyright : (C) 2016 by Damien Plisson, Audirvana
email : damien78@audirvana.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 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 "dsdiffdiintag.h"
#include "tstringlist.h"
#include "tpropertymap.h"
#include "tpicturemap.h"
using namespace TagLib;
using namespace DSDIFF::DIIN;
class DSDIFF::DIIN::Tag::TagPrivate
{
public:
TagPrivate()
{
}
String title;
String artist;
};
DSDIFF::DIIN::Tag::Tag() : TagLib::Tag()
{
d = new TagPrivate;
}
DSDIFF::DIIN::Tag::~Tag()
{
delete d;
}
String DSDIFF::DIIN::Tag::title() const
{
return d->title;
}
String DSDIFF::DIIN::Tag::artist() const
{
return d->artist;
}
String DSDIFF::DIIN::Tag::album() const
{
return String();
}
String DSDIFF::DIIN::Tag::comment() const
{
return String();
}
String DSDIFF::DIIN::Tag::genre() const
{
return String();
}
unsigned int DSDIFF::DIIN::Tag::year() const
{
return 0;
}
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)
{
d->title = title;
}
void DSDIFF::DIIN::Tag::setArtist(const String &artist)
{
d->artist = artist;
}
void DSDIFF::DIIN::Tag::setAlbum(const String &)
{
}
void DSDIFF::DIIN::Tag::setComment(const String &)
{
}
void DSDIFF::DIIN::Tag::setGenre(const String &)
{
}
void DSDIFF::DIIN::Tag::setYear(unsigned int)
{
}
void DSDIFF::DIIN::Tag::setTrack(unsigned int)
{
}
void DSDIFF::DIIN::Tag::setPictures( const PictureMap& l )
{
}
PropertyMap DSDIFF::DIIN::Tag::properties() const
{
PropertyMap properties;
properties["TITLE"] = d->title;
properties["ARTIST"] = d->artist;
return properties;
}
PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps)
{
PropertyMap properties(origProps);
properties.removeEmpty();
StringList oneValueSet;
if(properties.contains("TITLE")) {
d->title = properties["TITLE"].front();
oneValueSet.append("TITLE");
} else
d->title = String();
if(properties.contains("ARTIST")) {
d->artist = properties["ARTIST"].front();
oneValueSet.append("ARTIST");
} else
d->artist = String();
// for each tag that has been set above, remove the first entry in the corresponding
// value list. The others will be returned as unsupported by this format.
for(StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
if(properties[*it].size() == 1)
properties.erase(*it);
else
properties[*it].erase(properties[*it].begin());
}
return properties;
}

View File

@@ -0,0 +1,160 @@
/***************************************************************************
copyright : (C) 2016 by Damien Plisson, Audirvana
email : damien78@audirvana.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 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_DSDIFFDIINTAG_H
#define TAGLIB_DSDIFFDIINTAG_H
#include "tag.h"
namespace TagLib {
namespace DSDIFF {
namespace DIIN {
/*!
* Tags from the Edited Master Chunk Info
*
* Only Title and Artist tags are supported
*/
class TAGLIB_EXPORT Tag : public TagLib::Tag
{
public:
Tag();
virtual ~Tag();
/*!
* Returns the track name; if no track name is present in the tag
* String() will be returned.
*/
virtual String title() const;
/*!
* Returns the artist name; if no artist name is present in the tag
* String() will be returned.
*/
virtual String artist() const;
/*!
* Not supported. Therefore always returns String().
*/
virtual String album() const;
/*!
* Not supported. Therefore always returns String().
*/
virtual String comment() const;
/*!
* Not supported. Therefore always returns String().
*/
virtual String genre() const;
/*!
* Not supported. Therefore always returns 0.
*/
virtual unsigned int year() const;
/*!
* Not supported. Therefore always returns 0.
*/
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.
*/
virtual void setTitle(const String &title);
/*!
* Sets the artist to \a artist. If \a artist is String() then this
* value will be cleared.
*/
virtual void setArtist(const String &artist);
/*!
* Not supported and therefore ignored.
*/
virtual void setAlbum(const String &album);
/*!
* Not supported and therefore ignored.
*/
virtual void setComment(const String &comment);
/*!
* Not supported and therefore ignored.
*/
virtual void setGenre(const String &genre);
/*!
* Not supported and therefore ignored.
*/
virtual void setYear(unsigned int year);
/*!
* Not supported and therefore ignored.
*/
virtual void setTrack(unsigned int track);
/*!
* Not supported and therefore ignored.
*/
virtual void setPictures( const PictureMap& l );
/*!
* Implements the unified property interface -- export function.
* Since the DIIN tag is very limited, the exported map is as well.
*/
PropertyMap properties() const;
/*!
* Implements the unified property interface -- import function.
* Because of the limitations of the DIIN file tag, any tags besides
* TITLE and ARTIST, will be
* returned. Additionally, if the map contains tags with multiple values,
* all but the first will be contained in the returned map of unsupported
* properties.
*/
PropertyMap setProperties(const PropertyMap &);
private:
Tag(const Tag &);
Tag &operator=(const Tag &);
class TagPrivate;
TagPrivate *d;
};
}
}
}
#endif

View File

@@ -0,0 +1,844 @@
/***************************************************************************
copyright : (C) 2016 by Damien Plisson, Audirvana
email : damien78@audirvana.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 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 <tbytevector.h>
#include <tdebug.h>
#include <id3v2tag.h>
#include <tstringlist.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include <tsmartptr.h>
#include "tagunion.h"
#include "dsdifffile.h"
using namespace TagLib;
struct Chunk64
{
ByteVector name;
unsigned long long offset;
unsigned long long size;
char padding;
};
namespace
{
enum {
ID3v2Index = 0,
DIINIndex = 1
};
enum {
PROPChunk = 0,
DIINChunk = 1
};
}
class DSDIFF::File::FilePrivate
{
public:
FilePrivate() :
endianness(BigEndian),
size(0),
isID3InPropChunk(false),
duplicateID3V2chunkIndex(-1),
id3v2TagChunkID("ID3 "),
hasID3v2(false),
hasDiin(false)
{
childChunkIndex[ID3v2Index] = -1;
childChunkIndex[DIINIndex] = -1;
}
Endianness endianness;
ByteVector type;
unsigned long long size;
ByteVector format;
std::vector<Chunk64> chunks;
std::vector<Chunk64> childChunks[2];
int childChunkIndex[2];
bool isID3InPropChunk; // Two possibilities can be found: ID3V2 chunk inside PROP chunk or at root level
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.
SCOPED_PTR<AudioProperties> properties;
DoubleTagUnion tag;
ByteVector id3v2TagChunkID;
bool hasID3v2;
bool hasDiin;
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
bool DSDIFF::File::isSupported(IOStream *stream)
{
// A DSDIFF file has to start with "FRM8????????DSD ".
const ByteVector id = Utils::readHeader(stream, 16, false);
return (id.startsWith("FRM8") && id.containsAt("DSD ", 12));
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
DSDIFF::File::File(FileName file, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) : TagLib::File(file)
{
d = new FilePrivate;
d->endianness = BigEndian;
if(isOpen())
read(readProperties, propertiesStyle);
}
DSDIFF::File::File(IOStream *stream, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) : TagLib::File(stream)
{
d = new FilePrivate;
d->endianness = BigEndian;
if(isOpen())
read(readProperties, propertiesStyle);
}
DSDIFF::File::~File()
{
delete d;
}
TagLib::Tag *DSDIFF::File::tag() const
{
return &d->tag;
}
ID3v2::Tag *DSDIFF::File::ID3v2Tag() const
{
return d->tag.access<ID3v2::Tag>(ID3v2Index, false);
}
bool DSDIFF::File::hasID3v2Tag() const
{
return d->hasID3v2;
}
DSDIFF::DIIN::Tag *DSDIFF::File::DIINTag() const
{
return d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
}
bool DSDIFF::File::hasDIINTag() const
{
return d->hasDiin;
}
PropertyMap DSDIFF::File::properties() const
{
if(d->hasID3v2)
return d->tag.access<ID3v2::Tag>(ID3v2Index, false)->properties();
return PropertyMap();
}
void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported)
{
if(d->hasID3v2)
d->tag.access<ID3v2::Tag>(ID3v2Index, false)->removeUnsupportedProperties(unsupported);
if(d->hasDiin)
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->removeUnsupportedProperties(unsupported);
}
PropertyMap DSDIFF::File::setProperties(const PropertyMap &properties)
{
return d->tag.access<ID3v2::Tag>(ID3v2Index, true)->setProperties(properties);
}
DSDIFF::AudioProperties *DSDIFF::File::audioProperties() const
{
return d->properties.get();
}
bool DSDIFF::File::save()
{
if(readOnly()) {
debug("DSDIFF::File::save() -- File is read only.");
return false;
}
if(!isValid()) {
debug("DSDIFF::File::save() -- Trying to save invalid file.");
return false;
}
// First: save ID3V2 chunk
ID3v2::Tag *id3v2Tag = d->tag.access<ID3v2::Tag>(ID3v2Index, false);
if(d->isID3InPropChunk) {
if(id3v2Tag != NULL && !id3v2Tag->isEmpty()) {
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(), PROPChunk);
d->hasID3v2 = true;
}
else {
// Empty tag: remove it
setChildChunkData(d->id3v2TagChunkID, ByteVector(), PROPChunk);
d->hasID3v2 = false;
}
}
else {
if(id3v2Tag != NULL && !id3v2Tag->isEmpty()) {
setRootChunkData(d->id3v2TagChunkID, id3v2Tag->render());
d->hasID3v2 = true;
}
else {
// Empty tag: remove it
setRootChunkData(d->id3v2TagChunkID, ByteVector());
d->hasID3v2 = false;
}
}
// Second: save the DIIN chunk
if(d->hasDiin) {
DSDIFF::DIIN::Tag *diinTag = d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
if(!diinTag->title().isEmpty()) {
ByteVector diinTitle;
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().isEmpty()) {
ByteVector diinArtist;
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);
}
else
setChildChunkData("DIAR", ByteVector(), DIINChunk);
}
// Third: remove the duplicate ID3V2 chunk (inside PROP chunk) if any
if(d->duplicateID3V2chunkIndex>=0) {
setChildChunkData(d->duplicateID3V2chunkIndex, ByteVector(), PROPChunk);
d->duplicateID3V2chunkIndex = -1;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
{
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;
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);
// Update the internal offsets
for(unsigned long r = i + 1; r < d->chunks.size(); r++)
d->chunks[r].offset = d->chunks[r - 1].offset + 12
+ d->chunks[r - 1].size + d->chunks[r - 1].padding;
d->chunks.erase(d->chunks.begin() + i);
}
else {
// 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);
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,
data,
d->chunks[i].offset - 12,
d->chunks[i].size + d->chunks[i].padding + 12);
d->chunks[i].size = data.size();
d->chunks[i].padding = (data.size() & 0x01) ? 1 : 0;
// Finally update the internal offsets
updateRootChunksStructure(i + 1);
}
}
void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &data)
{
if(d->chunks.size() == 0) {
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
return;
}
for(unsigned int i = 0; i < d->chunks.size(); i++) {
if(d->chunks[i].name == name) {
setRootChunkData(i, data);
return;
}
}
// Couldn't find an existing chunk, so let's create a new one.
unsigned int i = d->chunks.size() - 1;
unsigned long offset = d->chunks[i].offset + d->chunks[i].size + d->chunks[i].padding;
// First we update the global size
d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
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,
data,
offset,
std::max<unsigned long long>(0, length() - offset),
(offset & 1) ? 1 : 0);
Chunk64 chunk;
chunk.name = name;
chunk.size = data.size();
chunk.offset = offset + 12;
chunk.padding = (data.size() & 0x01) ? 1 : 0;
d->chunks.push_back(chunk);
}
void DSDIFF::File::setChildChunkData(unsigned int i,
const ByteVector &data,
unsigned int childChunkNum)
{
std::vector<Chunk64> &childChunks = d->childChunks[childChunkNum];
if(data.isEmpty()) {
// Null data: remove chunk
// Update global size
unsigned long long removedChunkTotalSize = childChunks[i].size + childChunks[i].padding + 12;
d->size -= removedChunkTotalSize;
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;
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);
// Update the internal offsets
// For child chunks
if((i + 1) < childChunks.size()) {
childChunks[i + 1].offset = childChunks[i].offset;
i++;
for(i++; i < childChunks.size(); i++)
childChunks[i].offset = childChunks[i - 1].offset + 12
+ childChunks[i - 1].size + childChunks[i - 1].padding;
}
// And for root chunks
for(i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++)
d->chunks[i].offset = d->chunks[i - 1].offset + 12
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
childChunks.erase(childChunks.begin() + i);
}
else {
// Non null data: update chunk
// First we update the global size
d->size += ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
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);
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,
data,
childChunks[i].offset - 12,
childChunks[i].size + childChunks[i].padding + 12);
childChunks[i].size = data.size();
childChunks[i].padding = (data.size() & 0x01) ? 1 : 0;
// Now update the internal offsets
// For child Chunks
for(i++; i < childChunks.size(); i++)
childChunks[i].offset = childChunks[i - 1].offset + 12
+ childChunks[i - 1].size + childChunks[i - 1].padding;
// And for root chunks
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
}
}
void DSDIFF::File::setChildChunkData(const ByteVector &name,
const ByteVector &data,
unsigned int childChunkNum)
{
std::vector<Chunk64> &childChunks = d->childChunks[childChunkNum];
if(childChunks.size() == 0) {
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
return;
}
for(unsigned int i = 0; i < childChunks.size(); i++) {
if(childChunks[i].name == name) {
setChildChunkData(i, data, childChunkNum);
return;
}
}
// Do not attempt to remove a non existing chunk
if(data.isEmpty())
return;
// Couldn't find an existing chunk, so let's create a new one.
unsigned int i = childChunks.size() - 1;
unsigned long offset = childChunks[i].offset + childChunks[i].size + childChunks[i].padding;
// First we update the global size
d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
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;
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();
if((d->childChunkIndex[childChunkNum] + 1) < static_cast<int>(d->chunks.size()))
nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12;
writeChunk(name, data, offset,
std::max<unsigned long long>(0, nextRootChunkIdx - offset),
(offset & 1) ? 1 : 0);
// For root chunks
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
Chunk64 chunk;
chunk.name = name;
chunk.size = data.size();
chunk.offset = offset + 12;
chunk.padding = (data.size() & 0x01) ? 1 : 0;
childChunks.push_back(chunk);
}
static bool isValidChunkID(const ByteVector &name)
{
if(name.size() != 4)
return false;
for(int i = 0; i < 4; i++) {
if(name[i] < 32 || name[i] > 127)
return false;
}
return true;
}
void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
{
for(unsigned int i = startingChunk; i < d->chunks.size(); i++)
d->chunks[i].offset = d->chunks[i - 1].offset + 12
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
// Update childchunks structure as well
if(d->childChunkIndex[PROPChunk] >= static_cast<int>(startingChunk)) {
std::vector<Chunk64> &childChunksToUpdate = d->childChunks[PROPChunk];
if(childChunksToUpdate.size() > 0) {
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[PROPChunk]].offset + 12;
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
+ childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
}
}
if(d->childChunkIndex[DIINChunk] >= static_cast<int>(startingChunk)) {
std::vector<Chunk64> &childChunksToUpdate = d->childChunks[DIINChunk];
if(childChunksToUpdate.size() > 0) {
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[DIINChunk]].offset + 12;
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
+ childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
}
}
}
void DSDIFF::File::read(bool readProperties, AudioProperties::ReadStyle propertiesStyle)
{
bool bigEndian = (d->endianness == BigEndian);
d->type = readBlock(4);
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 = bigEndian ? readBlock(8).toInt64BE(0) : readBlock(8).toInt64LE(0);
if(!isValidChunkID(chunkName)) {
debug("DSDIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID");
setValid(false);
break;
}
if(static_cast<unsigned long long>(tell()) + chunkSize > static_cast<unsigned long long>(length())) {
debug("DSDIFF::File::read() -- Chunk '" + chunkName
+ "' has invalid size (larger than the file size)");
setValid(false);
break;
}
Chunk64 chunk;
chunk.name = chunkName;
chunk.size = chunkSize;
chunk.offset = tell();
seek(chunk.size, Current);
// Check padding
chunk.padding = 0;
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
else
chunk.padding = 1;
}
d->chunks.push_back(chunk);
}
unsigned long long lengthDSDSamplesTimeChannels = 0; // For DSD uncompressed
unsigned long long audioDataSizeinBytes = 0; // For computing bitrate
unsigned long dstNumFrames = 0; // For DST compressed frames
unsigned short dstFrameRate = 0; // For DST compressed frames
for(unsigned int i = 0; i < d->chunks.size(); i++) {
if(d->chunks[i].name == "DSD ") {
lengthDSDSamplesTimeChannels = d->chunks[i].size * 8;
audioDataSizeinBytes = d->chunks[i].size;
}
else if(d->chunks[i].name == "DST ") {
// Now decode the chunks inside the DST chunk to read the DST Frame Information one
long long dstChunkEnd = d->chunks[i].offset + d->chunks[i].size;
seek(d->chunks[i].offset);
audioDataSizeinBytes = d->chunks[i].size;
while(tell() + 12 <= dstChunkEnd) {
ByteVector dstChunkName = readBlock(4);
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");
setValid(false);
break;
}
if(static_cast<long long>(tell()) + dstChunkSize > dstChunkEnd) {
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName
+ "' has invalid size (larger than the DST chunk)");
setValid(false);
break;
}
if(dstChunkName == "FRTE") {
// Found the DST frame information chunk
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
}
seek(dstChunkSize, Current);
// Check padding
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
}
}
}
else if(d->chunks[i].name == "PROP") {
d->childChunkIndex[PROPChunk] = i;
// Now decodes the chunks inside the PROP chunk
long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size;
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 = bigEndian ? readBlock(8).toInt64BE(0) : readBlock(8).toInt64LE(0);
if(!isValidChunkID(propChunkName)) {
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid ID");
setValid(false);
break;
}
if(static_cast<long long>(tell()) + propChunkSize > propChunkEnd) {
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName
+ "' has invalid size (larger than the PROP chunk)");
setValid(false);
break;
}
Chunk64 chunk;
chunk.name = propChunkName;
chunk.size = propChunkSize;
chunk.offset = tell();
seek(chunk.size, Current);
// Check padding
chunk.padding = 0;
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
else
chunk.padding = 1;
}
d->childChunks[PROPChunk].push_back(chunk);
}
}
else if(d->chunks[i].name == "DIIN") {
d->childChunkIndex[DIINChunk] = i;
d->hasDiin = true;
// Now decode the chunks inside the DIIN chunk
long long diinChunkEnd = d->chunks[i].offset + d->chunks[i].size;
seek(d->chunks[i].offset);
while(tell() + 12 <= diinChunkEnd) {
ByteVector diinChunkName = readBlock(4);
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");
setValid(false);
break;
}
if(static_cast<long long>(tell()) + diinChunkSize > diinChunkEnd) {
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName
+ "' has invalid size (larger than the DIIN chunk)");
setValid(false);
break;
}
Chunk64 chunk;
chunk.name = diinChunkName;
chunk.size = diinChunkSize;
chunk.offset = tell();
seek(chunk.size, Current);
// Check padding
chunk.padding = 0;
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
else
chunk.padding = 1;
}
d->childChunks[DIINChunk].push_back(chunk);
}
}
else if(d->chunks[i].name == "ID3 " || d->chunks[i].name == "id3 ") {
d->id3v2TagChunkID = d->chunks[i].name;
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->chunks[i].offset));
d->isID3InPropChunk = false;
d->hasID3v2 = true;
}
}
if(!isValid())
return;
if(d->childChunkIndex[PROPChunk] < 0) {
debug("DSDIFF::File::read() -- no PROP chunk found");
setValid(false);
return;
}
// Read properties
unsigned int sampleRate=0;
unsigned short channels=0;
for(unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) {
if(d->childChunks[PROPChunk][i].name == "ID3 " || d->childChunks[PROPChunk][i].name == "id3 ") {
if(d->hasID3v2) {
d->duplicateID3V2chunkIndex = i;
continue; // ID3V2 tag has already been found at root level
}
d->id3v2TagChunkID = d->childChunks[PROPChunk][i].name;
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->childChunks[PROPChunk][i].offset));
d->isID3InPropChunk = true;
d->hasID3v2 = true;
}
else if(d->childChunks[PROPChunk][i].name == "FS ") {
// Sample rate
seek(d->childChunks[PROPChunk][i].offset);
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 = bigEndian ? readBlock(2).toInt16BE(0) : readBlock(2).toInt16LE(0);
}
}
// Read title & artist from DIIN chunk
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, true);
if(d->hasDiin) {
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 = 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);
}
}
else if(d->childChunks[DIINChunk][i].name == "DIAR") {
seek(d->childChunks[DIINChunk][i].offset);
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);
}
}
}
}
if(readProperties) {
if(lengthDSDSamplesTimeChannels == 0) {
// DST compressed signal : need to compute length of DSD uncompressed frames
if(dstFrameRate > 0)
lengthDSDSamplesTimeChannels = (unsigned long long)dstNumFrames
* (unsigned long long)sampleRate / (unsigned long long)dstFrameRate;
else
lengthDSDSamplesTimeChannels = 0;
}
else {
// In DSD uncompressed files, the read number of samples is the total for each channel
if(channels > 0)
lengthDSDSamplesTimeChannels /= channels;
}
int bitrate = 0;
if(lengthDSDSamplesTimeChannels > 0)
bitrate = (audioDataSizeinBytes*8*sampleRate) / lengthDSDSamplesTimeChannels / 1000;
d->properties.reset(new AudioProperties(sampleRate,
channels,
lengthDSDSamplesTimeChannels,
bitrate,
propertiesStyle));
}
if(!ID3v2Tag()) {
d->tag.access<ID3v2::Tag>(ID3v2Index, true);
d->isID3InPropChunk = false; // By default, ID3 chunk is at root level
d->hasID3v2 = false;
}
}
void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
unsigned long long offset, unsigned long replace,
unsigned int leadingPadding)
{
ByteVector combined;
if(leadingPadding)
combined.append(ByteVector(leadingPadding, '\x00'));
combined.append(name);
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');
insert(combined, offset, replace);
}

260
taglib/dsdiff/dsdifffile.h Normal file
View File

@@ -0,0 +1,260 @@
/***************************************************************************
copyright : (C) 2016 by Damien Plisson, Audirvana
email : damien78@audirvana.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 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_DSDIFFFILE_H
#define TAGLIB_DSDIFFFILE_H
#include "rifffile.h"
#include "id3v2tag.h"
#include "dsdiffproperties.h"
#include "dsdiffdiintag.h"
namespace TagLib {
//! An implementation of DSDIFF metadata
/*!
* This is implementation of DSDIFF metadata.
*
* 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
* 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
* In addition, title and artist info are stored as part of the standard
*/
namespace DSDIFF {
//! An implementation of TagLib::File with DSDIFF specific methods
/*!
* This implements and provides an interface for DSDIFF files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to DSDIFF files.
*/
class TAGLIB_EXPORT File : public TagLib::File
{
public:
/*!
* Constructs an DSDIFF 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.
*/
File(FileName file, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Constructs an DSDIFF file from \a stream. 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.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Destroys this instance of the File.
*/
virtual ~File();
/*!
* Returns a pointer to a tag that is the union of the ID3v2 and DIIN
* tags. The ID3v2 tag is given priority in reading the information -- if
* requested information exists in both the ID3v2 tag and the ID3v1 tag,
* the information from the ID3v2 tag will be returned.
*
* If you would like more granular control over the content of the tags,
* with the concession of generality, use the tag-type specific calls.
*
* \note As this tag is not implemented as an ID3v2 tag or a DIIN tag,
* but a union of the two this pointer may not be cast to the specific
* tag types.
*
* \see ID3v2Tag()
* \see DIINTag()
*/
virtual Tag *tag() const;
/*!
* Returns the ID3V2 Tag for this file.
*
* \note This always returns a valid pointer regardless of whether or not
* the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the
* file on disk actually has an ID3v2 tag.
*
* \see hasID3v2Tag()
*/
virtual ID3v2::Tag *ID3v2Tag() const;
/*!
* Returns the DSDIFF DIIN Tag for this file
*
*/
DSDIFF::DIIN::Tag *DIINTag() const;
/*!
* Implements the unified property interface -- export function.
* This method forwards to ID3v2::Tag::properties().
*/
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the unified property interface -- import function.
* This method forwards to ID3v2::Tag::setProperties().
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the DSDIFF::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
virtual AudioProperties *audioProperties() const;
/*!
* Save the file. If at least one tag -- ID3v1 or DIIN -- exists this
* will duplicate its content into the other tag. This returns true
* if saving was successful.
*
* If neither exists or if both tags are empty, this will strip the tags
* from the file.
*
* This is the same as calling save(AllTags);
*
* If you would like more granular control over the content of the tags,
* with the concession of generality, use paramaterized save call below.
*
* \see save(int tags)
*/
virtual bool save();
/*!
* Save the file. This will attempt to save all of the tag types that are
* specified by OR-ing together TagTypes values. The save() method above
* uses AllTags. This returns true if saving was successful.
*
* This strips all tags not included in the mask, but does not modify them
* in memory, so later calls to save() which make use of these tags will
* remain valid. This also strips empty tags.
*/
bool save(int tags);
/*!
* Returns whether or not the file on disk actually has an ID3v2 tag.
*
* \see ID3v2Tag()
*/
bool hasID3v2Tag() const;
/*!
* Returns whether or not the file on disk actually has the DSDIFF
* Title & Artist tag.
*
* \see DIINTag()
*/
bool hasDIINTag() const;
/*!
* Returns whether or not the given \a stream can be opened as a DSDIFF
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
protected:
enum Endianness { BigEndian, LittleEndian };
File(FileName file, Endianness endianness);
File(IOStream *stream, Endianness endianness);
private:
File(const File &);
File &operator=(const File &);
/*!
* Sets the data for the the specified chunk at root level to \a data.
*
* \warning This will update the file immediately.
*/
void setRootChunkData(unsigned int i, const ByteVector &data);
/*!
* Sets the data for the root-level chunk \a name to \a data.
* If a root-level chunk with the given name already exists
* it will be overwritten, otherwise it will be
* created after the existing chunks.
*
* \warning This will update the file immediately.
*/
void setRootChunkData(const ByteVector &name, const ByteVector &data);
/*!
* Sets the data for the the specified child chunk to \a data.
*
* If data is null, then remove the chunk
*
* \warning This will update the file immediately.
*/
void setChildChunkData(unsigned int i, const ByteVector &data,
unsigned int childChunkNum);
/*!
* Sets the data for the child chunk \a name to \a data. If a chunk with
* the given name already exists it will be overwritten, otherwise it will
* be created after the existing chunks inside child chunk.
*
* If data is null, then remove the chunks with \a name name
*
* \warning This will update the file immediately.
*/
void setChildChunkData(const ByteVector &name, const ByteVector &data,
unsigned int childChunkNum);
void updateRootChunksStructure(unsigned int startingChunk);
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);
class FilePrivate;
FilePrivate *d;
};
}
}
#endif

View File

@@ -0,0 +1,117 @@
/***************************************************************************
copyright : (C) 2016 by Damien Plisson, Audirvana
email : damien78@audirvana.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 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 <tstring.h>
#include <tdebug.h>
#include "dsdiffproperties.h"
using namespace TagLib;
class DSDIFF::AudioProperties::AudioPropertiesPrivate
{
public:
AudioPropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
channels(0),
sampleWidth(0),
sampleCount(0)
{
}
int length;
int bitrate;
int sampleRate;
int channels;
int sampleWidth;
unsigned long long sampleCount;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
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->channels = channels;
d->sampleCount = samplesCount;
d->sampleWidth = 1;
d->sampleRate = sampleRate;
d->bitrate = bitrate;
d->length = d->sampleRate > 0
? static_cast<int>((d->sampleCount * 1000.0) / d->sampleRate + 0.5)
: 0;
}
DSDIFF::AudioProperties::~AudioProperties()
{
delete d;
}
int DSDIFF::AudioProperties::length() const
{
return lengthInSeconds();
}
int DSDIFF::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int DSDIFF::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int DSDIFF::AudioProperties::bitrate() const
{
return d->bitrate;
}
int DSDIFF::AudioProperties::sampleRate() const
{
return d->sampleRate;
}
int DSDIFF::AudioProperties::channels() const
{
return d->channels;
}
int DSDIFF::AudioProperties::bitsPerSample() const
{
return d->sampleWidth;
}
long long DSDIFF::AudioProperties::sampleCount() const
{
return d->sampleCount;
}

View File

@@ -0,0 +1,83 @@
/***************************************************************************
copyright : (C) 2016 by Damien Plisson, Audirvana
email : damien78@audirvana.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 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_DSDIFFPROPERTIES_H
#define TAGLIB_DSDIFFPROPERTIES_H
#include "audioproperties.h"
namespace TagLib {
namespace DSDIFF {
class File;
//! An implementation of audio property reading for DSDIFF
/*!
* This reads the data from an DSDIFF stream found in the AudioProperties
* API.
*/
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
/*!
* Create an instance of DSDIFF::AudioProperties with the data read from the
* ByteVector \a data.
*/
AudioProperties(const unsigned int sampleRate, const unsigned short channels,
const unsigned long long samplesCount, const int bitrate,
ReadStyle style);
/*!
* Destroys this DSDIFF::AudioProperties instance.
*/
virtual ~AudioProperties();
// Reimplementations.
virtual int length() const;
virtual int lengthInSeconds() const;
virtual int lengthInMilliseconds() const;
virtual int bitrate() const;
virtual int sampleRate() const;
virtual int channels() const;
int bitsPerSample() const;
long long sampleCount() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
class AudioPropertiesPrivate;
AudioPropertiesPrivate *d;
};
}
}
#endif

234
taglib/dsf/dsffile.cpp Normal file
View File

@@ -0,0 +1,234 @@
/***************************************************************************
copyright : (C) 2013 - 2018 by Stephen F. Booth
email : me@sbooth.org
***************************************************************************/
/***************************************************************************
* 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 <tbytevector.h>
#include <tdebug.h>
#include <id3v2tag.h>
#include <tstringlist.h>
#include <tpropertymap.h>
#include <tsmartptr.h>
#include <tagutils.h>
#include "dsffile.h"
using namespace TagLib;
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
class DSF::File::FilePrivate
{
public:
FilePrivate() :
fileSize(0),
metadataOffset(0) {}
long long fileSize;
long long metadataOffset;
SCOPED_PTR<AudioProperties> properties;
SCOPED_PTR<ID3v2::Tag> tag;
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
bool DSF::File::isSupported(IOStream *stream)
{
// A DSF file has to start with "DSD "
const ByteVector id = Utils::readHeader(stream, 4, false);
return id.startsWith("DSD ");
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
DSF::File::File(FileName file, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) :
TagLib::File(file),
d(new FilePrivate())
{
if(isOpen())
read(readProperties, propertiesStyle);
}
DSF::File::File(IOStream *stream, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) :
TagLib::File(stream),
d(new FilePrivate())
{
if(isOpen())
read(readProperties, propertiesStyle);
}
DSF::File::~File()
{
delete d;
}
ID3v2::Tag *DSF::File::tag() const
{
return d->tag.get();
}
DSF::AudioProperties *DSF::File::audioProperties() const
{
return d->properties.get();
}
PropertyMap DSF::File::properties() const
{
return d->tag->properties();
}
PropertyMap DSF::File::setProperties(const PropertyMap &properties)
{
return d->tag->setProperties(properties);
}
bool DSF::File::save()
{
if(readOnly()) {
debug("DSF::File::save() -- File is read only.");
return false;
}
if(!isValid()) {
debug("DSF::File::save() -- Trying to save invalid file.");
return false;
}
// Three things must be updated: the file size, the tag data, and the metadata offset
if(d->tag->isEmpty()) {
long long newFileSize = d->metadataOffset ? d->metadataOffset : d->fileSize;
// Update the file size
if(d->fileSize != newFileSize) {
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::fromUInt64LE(0ULL), 20, 8);
d->metadataOffset = 0;
}
// Delete the old tag
truncate(newFileSize);
}
else {
ByteVector tagData = d->tag->render();
long long newMetadataOffset = d->metadataOffset ? d->metadataOffset : d->fileSize;
long long newFileSize = newMetadataOffset + tagData.size();
long long oldTagSize = d->fileSize - newMetadataOffset;
// Update the file size
if(d->fileSize != newFileSize) {
insert(ByteVector::fromUInt64LE(newFileSize), 12, 8);
d->fileSize = newFileSize;
}
// Update the metadata offset
if(d->metadataOffset != newMetadataOffset) {
insert(ByteVector::fromUInt64LE(newMetadataOffset), 20, 8);
d->metadataOffset = newMetadataOffset;
}
// Delete the old tag and write the new one
insert(tagData, newMetadataOffset, static_cast<size_t>(oldTagSize));
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
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
// DSD chunk
ByteVector chunkName = readBlock(4);
if(chunkName != "DSD ") {
debug("DSF::File::read() -- Not a DSF file.");
setValid(false);
return;
}
long long chunkSize = readBlock(8).toInt64LE(0);
// Integrity check
if(28 != chunkSize) {
debug("DSF::File::read() -- File is corrupted.");
setValid(false);
return;
}
d->fileSize = readBlock(8).toInt64LE(0);
// File is malformed or corrupted
if(d->fileSize != length()) {
debug("DSF::File::read() -- File is corrupted.");
setValid(false);
return;
}
d->metadataOffset = readBlock(8).toInt64LE(0);
// File is malformed or corrupted
if(d->metadataOffset > d->fileSize) {
debug("DSF::File::read() -- Invalid metadata offset.");
setValid(false);
return;
}
// Format chunk
chunkName = readBlock(4);
if(chunkName != "fmt ") {
debug("DSF::File::read() -- Missing 'fmt ' chunk.");
setValid(false);
return;
}
chunkSize = readBlock(8).toInt64LE(0);
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.reset(new ID3v2::Tag());
else
d->tag.reset(new ID3v2::Tag(this, d->metadataOffset));
}

127
taglib/dsf/dsffile.h Normal file
View File

@@ -0,0 +1,127 @@
/***************************************************************************
copyright : (C) 2013 - 2018 by Stephen F. Booth
email : me@sbooth.org
***************************************************************************/
/***************************************************************************
* 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_DSFFILE_H
#define TAGLIB_DSFFILE_H
#include "tfile.h"
#include "id3v2tag.h"
#include "dsfproperties.h"
namespace TagLib {
//! An implementation of DSF metadata
/*!
* This is implementation of DSF metadata.
*
* This supports an ID3v2 tag as well as properties from the file.
*/
namespace DSF {
//! An implementation of TagLib::File with DSF specific methods
/*!
* This implements and provides an interface for DSF files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to DSF files.
*/
class TAGLIB_EXPORT File : public TagLib::File
{
public:
/*!
* Contructs an DSF file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Contructs an DSF file from \a file. If \a readProperties is true the
* file's audio properties will also be read using \a propertiesStyle. If
* false, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
/*!
* Destroys this instance of the File.
*/
virtual ~File();
/*!
* Returns the Tag for this file.
*/
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 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.
*/
virtual bool save();
/*!
* Returns whether or not the given \a stream can be opened as a DSF
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
File(const File &);
File &operator=(const File &);
void read(bool readProperties, AudioProperties::ReadStyle propertiesStyle);
class FilePrivate;
FilePrivate *d;
};
}
}
#endif

View File

@@ -0,0 +1,158 @@
/***************************************************************************
copyright : (C) 2013 by Stephen F. Booth
email : me@sbooth.org
***************************************************************************/
/***************************************************************************
* 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 <tstring.h>
#include <tdebug.h>
#include "dsfproperties.h"
using namespace TagLib;
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) {}
// Nomenclature is from DSF file format specification
unsigned int formatVersion;
unsigned int formatID;
unsigned int channelType;
unsigned int channelNum;
unsigned int samplingFrequency;
unsigned int bitsPerSample;
long long sampleCount;
unsigned int blockSizePerChannel;
// Computed
int bitrate;
int length;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
DSF::AudioProperties::AudioProperties(const ByteVector &data, ReadStyle style) :
d(new PropertiesPrivate())
{
read(data);
}
DSF::AudioProperties::~AudioProperties()
{
delete d;
}
int DSF::AudioProperties::length() const
{
return lengthInSeconds();
}
int DSF::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
int DSF::AudioProperties::lengthInMilliseconds() const
{
return d->length;
}
int DSF::AudioProperties::bitrate() const
{
return d->bitrate;
}
int DSF::AudioProperties::sampleRate() const
{
return d->samplingFrequency;
}
int DSF::AudioProperties::channels() const
{
return d->channelNum;
}
// DSF specific
int DSF::AudioProperties::formatVersion() const
{
return d->formatVersion;
}
int DSF::AudioProperties::formatID() const
{
return d->formatID;
}
int DSF::AudioProperties::channelType() const
{
return d->channelType;
}
int DSF::AudioProperties::bitsPerSample() const
{
return d->bitsPerSample;
}
long long DSF::AudioProperties::sampleCount() const
{
return d->sampleCount;
}
int DSF::AudioProperties::blockSizePerChannel() const
{
return d->blockSizePerChannel;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void DSF::AudioProperties::read(const ByteVector &data)
{
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<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

@@ -0,0 +1,91 @@
/***************************************************************************
copyright : (C) 2013 by Stephen F. Booth
email : me@sbooth.org
***************************************************************************/
/***************************************************************************
* 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_DSFPROPERTIES_H
#define TAGLIB_DSFPROPERTIES_H
#include "audioproperties.h"
namespace TagLib {
namespace DSF {
class File;
//! An implementation of audio property reading for DSF
/*!
* This reads the data from a DSF stream found in the AudioProperties
* API.
*/
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
/*!
* Create an instance of DSF::AudioProperties with the data read from the
* ByteVector \a data.
*/
AudioProperties(const ByteVector &data, ReadStyle style);
/*!
* Destroys this DSF::AudioProperties instance.
*/
virtual ~AudioProperties();
// Reimplementations.
virtual int length() const;
virtual int lengthInSeconds() const;
virtual int lengthInMilliseconds() const;
virtual int bitrate() const;
virtual int sampleRate() const;
virtual int channels() const;
int formatVersion() const;
int formatID() const;
/*!
* 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;
int bitsPerSample() const;
long long sampleCount() const;
int blockSizePerChannel() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read(const ByteVector &data);
class PropertiesPrivate;
PropertiesPrivate *d;
};
}
}
#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

@@ -27,13 +27,11 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <tfile.h>
#include <tfilestream.h>
#include <tstring.h>
#include <tdebug.h>
#include <tsmartptr.h>
#include "fileref.h"
#include "asffile.h"
@@ -45,6 +43,7 @@
#include "mp4file.h"
#include "wavpackfile.h"
#include "speexfile.h"
#include "opusfile.h"
#include "trueaudiofile.h"
#include "aifffile.h"
#include "wavfile.h"
@@ -53,52 +52,216 @@
#include "s3mfile.h"
#include "itfile.h"
#include "xmfile.h"
#include "dsffile.h"
#include "dsdifffile.h"
#include "ebmlmatroskafile.h"
using namespace TagLib;
class FileRef::FileRefPrivate : public RefCounter
namespace
{
public:
FileRefPrivate(File *f) : RefCounter(), file(f) {}
~FileRefPrivate() {
delete file;
typedef List<const FileRef::FileTypeResolver *> ResolverList;
ResolverList fileTypeResolvers;
// Detect the file type by user-defined resolvers.
File *detectByResolvers(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
ResolverList::ConstIterator it = fileTypeResolvers.begin();
for(; it != fileTypeResolvers.end(); ++it) {
File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle);
if(file)
return file;
}
return 0;
}
File *file;
static List<const FileTypeResolver *> fileTypeResolvers;
};
// Detect the file type based on the file extension.
List<const FileRef::FileTypeResolver *> FileRef::FileRefPrivate::fileTypeResolvers;
File* detectByExtension(IOStream *stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
#ifdef _WIN32
const String s(stream->name().wstr());
#else
const String s(stream->name());
#endif
String ext;
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
// updated. However at some point that list should be created at the same time
// that a default file type resolver is created.
if(ext.isEmpty())
return 0;
// .oga can be any audio in the Ogg container. So leave it to content-based detection.
if(ext == "MP3")
return new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
if(ext == "OGG")
return new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "FLAC")
return new FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "MPC")
return new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WV")
return new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "SPX")
return new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "OPUS")
return new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "TTA")
return new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
return new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WMA" || ext == "ASF")
return new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
return new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WAV")
return new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "APE")
return new APE::File(stream, readAudioProperties, audioPropertiesStyle);
// module, nst and wow are possible but uncommon extensions
if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
return new Mod::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "S3M")
return new S3M::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "IT")
return new IT::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "XM")
return new XM::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "DFF" || ext == "DSDIFF")
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;
}
// Detect the file type based on the actual content of the stream.
File *detectByContent(IOStream *stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
File *file = 0;
if(MPEG::File::isSupported(stream))
file = new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
else if(Ogg::Vorbis::File::isSupported(stream))
file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
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, readAudioProperties, audioPropertiesStyle);
else if(MPC::File::isSupported(stream))
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
else if(WavPack::File::isSupported(stream))
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
else if(Ogg::Speex::File::isSupported(stream))
file = new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
else if(Ogg::Opus::File::isSupported(stream))
file = new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
else if(TrueAudio::File::isSupported(stream))
file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
else if(MP4::File::isSupported(stream))
file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ASF::File::isSupported(stream))
file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
else if(RIFF::AIFF::File::isSupported(stream))
file = new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
else if(RIFF::WAV::File::isSupported(stream))
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
else if(APE::File::isSupported(stream))
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
else if(DSDIFF::File::isSupported(stream))
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
else if(DSF::File::isSupported(stream))
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
// isSupported() only does a quick check, so double check the file here.
if(file) {
if(file->isValid())
return file;
else
delete file;
}
return 0;
}
struct FileRefData
{
FileRefData() :
file(0),
stream(0) {}
~FileRefData() {
delete file;
delete stream;
}
File *file;
IOStream *stream;
};
}
class FileRef::FileRefPrivate
{
public:
FileRefPrivate() :
data(new FileRefData()) {}
SHARED_PTR<FileRefData> data;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
FileRef::FileRef()
FileRef::FileRef() :
d(new FileRefPrivate())
{
d = new FileRefPrivate(0);
}
FileRef::FileRef(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
AudioProperties::ReadStyle audioPropertiesStyle) :
d(new FileRefPrivate())
{
d = new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle));
parse(fileName, readAudioProperties, audioPropertiesStyle);
}
FileRef::FileRef(File *file)
FileRef::FileRef(IOStream* stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) :
d(new FileRefPrivate())
{
d = new FileRefPrivate(file);
parse(stream, readAudioProperties, audioPropertiesStyle);
}
FileRef::FileRef(const FileRef &ref) : d(ref.d)
FileRef::FileRef(File *file) :
d(new FileRefPrivate())
{
d->data->file = file;
}
FileRef::FileRef(const FileRef &ref) :
d(new FileRefPrivate(*ref.d))
{
d->ref();
}
FileRef::~FileRef()
{
if(d->deref())
delete d;
delete d;
}
Tag *FileRef::tag() const
@@ -107,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
@@ -116,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()
@@ -130,12 +323,12 @@ 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
{
FileRefPrivate::fileTypeResolvers.prepend(resolver);
fileTypeResolvers.prepend(resolver);
return resolver;
}
@@ -157,6 +350,7 @@ StringList FileRef::defaultFileExtensions()
l.append("m4p");
l.append("3g2");
l.append("mp4");
l.append("m4v");
l.append("wma");
l.append("asf");
l.append("aif");
@@ -170,110 +364,92 @@ StringList FileRef::defaultFileExtensions()
l.append("s3m");
l.append("it");
l.append("xm");
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)
{
if(&ref == this)
return *this;
if(d->deref())
delete d;
d = ref.d;
d->ref();
FileRef(ref).swap(*this);
return *this;
}
void FileRef::swap(FileRef &ref)
{
using std::swap;
swap(d, ref.d);
}
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;
return (ref.d->data != d->data);
}
File *FileRef::create(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle) // static
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void FileRef::parse(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
// Try user-defined resolvers.
List<const FileTypeResolver *>::ConstIterator it = FileRefPrivate::fileTypeResolvers.begin();
d->data->file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
if(d->data->file)
return;
for(; it != FileRefPrivate::fileTypeResolvers.end(); ++it) {
File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle);
if(file)
return file;
}
// Try to resolve file types based on the file extension.
// Ok, this is really dumb for now, but it works for testing.
d->data->stream = new FileStream(fileName);
d->data->file = detectByExtension(d->data->stream, readAudioProperties, audioPropertiesStyle);
if(d->data->file)
return;
String s;
// At last, try to resolve file types based on the actual content.
#ifdef _WIN32
s = (wcslen((const wchar_t *) fileName) > 0) ? String((const wchar_t *) fileName) : String((const char *) fileName);
#else
s = fileName;
#endif
d->data->file = detectByContent(d->data->stream, readAudioProperties, audioPropertiesStyle);
if(d->data->file)
return;
// If this list is updated, the method defaultFileExtensions() should also be
// updated. However at some point that list should be created at the same time
// that a default file type resolver is created.
// Stream have to be closed here if failed to resolve file types.
int pos = s.rfind(".");
if(pos != -1) {
String ext = s.substr(pos + 1).upper();
if(ext == "MP3")
return new MPEG::File(fileName, 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;
delete file;
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
}
if(ext == "FLAC")
return new FLAC::File(fileName, 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 == "TTA")
return new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2")
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "WMA" || ext == "ASF")
return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "AIF" || ext == "AIFF")
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);
}
return 0;
delete d->data->stream;
d->data->stream = 0;
}
void FileRef::parse(IOStream *stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
// User-defined resolvers won't work with a stream.
// Try to resolve file types based on the file extension.
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->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 {
@@ -72,7 +72,7 @@ namespace TagLib {
*
* class MyFileTypeResolver : FileTypeResolver
* {
* TagLib::File *createFile(TagLib::FileName *fileName, bool, AudioProperties::ReadStyle)
* TagLib::File *createFile(TagLib::FileName *fileName, bool, AudioProperties::ReadStyle) const
* {
* if(someCheckForAnMP3File(fileName))
* return new TagLib::MPEG::File(fileName);
@@ -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
@@ -128,7 +129,24 @@ namespace TagLib {
audioPropertiesStyle = AudioProperties::Average);
/*!
* Contruct a FileRef using \a file. The FileRef now takes ownership of the
* Construct a FileRef from an opened \a IOStream. 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.
*
* Also see the note in the class documentation about why you may not want to
* use this method in your application.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*/
explicit FileRef(IOStream* stream,
bool readAudioProperties = true,
AudioProperties::ReadStyle
audioPropertiesStyle = AudioProperties::Average);
/*!
* Construct a FileRef using \a file. The FileRef now takes ownership of the
* pointer and will delete the File when it passes out of scope.
*/
explicit FileRef(File *file);
@@ -156,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.
@@ -191,7 +244,7 @@ namespace TagLib {
* is tried.
*
* Returns a pointer to the added resolver (the same one that's passed in --
* this is mostly so that static inialializers have something to use for
* this is mostly so that static initializers have something to use for
* assignment).
*
* \see FileTypeResolver
@@ -209,15 +262,24 @@ namespace TagLib {
* by TagLib for resolution is case-insensitive.
*
* \note This does not account for any additional file type resolvers that
* are plugged in. Also note that this is not intended to replace a propper
* are plugged in. Also note that this is not intended to replace a proper
* mime-type resolution system, but is just here for reference.
*
* \see FileTypeResolver
*/
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;
@@ -226,6 +288,11 @@ namespace TagLib {
*/
FileRef &operator=(const FileRef &ref);
/*!
* Exchanges the content of the FileRef by the content of \a ref.
*/
void swap(FileRef &ref);
/*!
* Returns true if this FileRef and \a ref point to the same File object.
*/
@@ -237,23 +304,10 @@ 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);
class FileRefPrivate;
FileRefPrivate *d;
};

View File

@@ -29,6 +29,8 @@
#include <tdebug.h>
#include <tagunion.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include <tsmartptr.h>
#include <id3v2header.h>
#include <id3v2tag.h>
@@ -44,89 +46,96 @@ using namespace TagLib;
namespace
{
typedef List<SHARED_PTR<FLAC::MetadataBlock> > BlockList;
typedef BlockList::Iterator BlockIterator;
typedef BlockList::Iterator BlockConstIterator;
enum { FlacXiphIndex = 0, FlacID3v2Index = 1, FlacID3v1Index = 2 };
enum { MinPaddingLength = 4096 };
enum { LastBlockFlag = 0x80 };
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() :
explicit FilePrivate(const ID3v2::FrameFactory *frameFactory) :
ID3v2FrameFactory(ID3v2::FrameFactory::instance()),
ID3v2Location(-1),
ID3v2OriginalSize(0),
ID3v1Location(-1),
properties(0),
flacStart(0),
streamStart(0),
streamLength(0),
scanned(false),
hasXiphComment(false),
hasID3v2(false),
hasID3v1(false)
scanned(false)
{
}
~FilePrivate()
{
for(uint i = 0; i < blocks.size(); i++) {
delete blocks[i];
}
delete properties;
if(frameFactory)
ID3v2FrameFactory = frameFactory;
}
const ID3v2::FrameFactory *ID3v2FrameFactory;
long ID3v2Location;
uint ID3v2OriginalSize;
long long ID3v2Location;
long long ID3v2OriginalSize;
long ID3v1Location;
long long ID3v1Location;
TagUnion tag;
TripleTagUnion tag;
Properties *properties;
ByteVector streamInfoData;
SCOPED_PTR<AudioProperties> properties;
ByteVector xiphCommentData;
List<MetadataBlock *> blocks;
BlockList blocks;
long flacStart;
long streamStart;
long streamLength;
long long flacStart;
long long streamStart;
bool scanned;
bool hasXiphComment;
bool hasID3v2;
bool hasID3v1;
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
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") != ByteVector::npos());
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
FLAC::File::File(FileName file, bool readProperties,
Properties::ReadStyle propertiesStyle) :
TagLib::File(file)
FLAC::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle,
ID3v2::FrameFactory *frameFactory) :
TagLib::File(file),
d(new FilePrivate(frameFactory))
{
d = new FilePrivate;
read(readProperties, propertiesStyle);
if(isOpen())
read(readProperties);
}
FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle propertiesStyle) :
TagLib::File(file)
FLAC::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle,
ID3v2::FrameFactory *frameFactory) :
TagLib::File(stream),
d(new FilePrivate(frameFactory))
{
d = new FilePrivate;
d->ID3v2FrameFactory = frameFactory;
read(readProperties, propertiesStyle);
}
FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle propertiesStyle) :
TagLib::File(stream)
{
d = new FilePrivate;
d->ID3v2FrameFactory = frameFactory;
read(readProperties, propertiesStyle);
if(isOpen())
read(readProperties);
}
FLAC::File::~File()
@@ -139,47 +148,16 @@ TagLib::Tag *FLAC::File::tag() const
return &d->tag;
}
PropertyMap FLAC::File::properties() const
{
// once Tag::properties() is virtual, this case distinction could actually be done
// within TagUnion.
if(d->hasXiphComment)
return d->tag.access<Ogg::XiphComment>(FlacXiphIndex, false)->properties();
if(d->hasID3v2)
return d->tag.access<ID3v2::Tag>(FlacID3v2Index, false)->properties();
if(d->hasID3v1)
return d->tag.access<ID3v1::Tag>(FlacID3v1Index, false)->properties();
return PropertyMap();
}
void FLAC::File::removeUnsupportedProperties(const StringList &unsupported)
{
if(d->hasXiphComment)
d->tag.access<Ogg::XiphComment>(FlacXiphIndex, false)->removeUnsupportedProperties(unsupported);
if(d->hasID3v2)
d->tag.access<ID3v2::Tag>(FlacID3v2Index, false)->removeUnsupportedProperties(unsupported);
if(d->hasID3v1)
d->tag.access<ID3v1::Tag>(FlacID3v1Index, false)->removeUnsupportedProperties(unsupported);
}
PropertyMap FLAC::File::setProperties(const PropertyMap &properties)
{
if(d->hasXiphComment)
return d->tag.access<Ogg::XiphComment>(FlacXiphIndex, false)->setProperties(properties);
else if(d->hasID3v2)
return d->tag.access<ID3v2::Tag>(FlacID3v2Index, false)->setProperties(properties);
else if(d->hasID3v1)
return d->tag.access<ID3v1::Tag>(FlacID3v1Index, false)->setProperties(properties);
else
return d->tag.access<Ogg::XiphComment>(FlacXiphIndex, true)->setProperties(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()
{
if(readOnly()) {
@@ -193,93 +171,136 @@ bool FLAC::File::save()
}
// Create new vorbis comments
Tag::duplicate(&d->tag, xiphComment(true), false);
if(!hasXiphComment())
Tag::duplicate(&d->tag, xiphComment(true), false);
d->xiphCommentData = xiphComment()->render(false);
// Replace metadata blocks
bool foundVorbisCommentBlock = false;
List<MetadataBlock *> newBlocks;
for(uint i = 0; i < d->blocks.size(); i++) {
MetadataBlock *block = d->blocks[i];
if(block->code() == MetadataBlock::VorbisComment) {
for(BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
if((*it)->code() == MetadataBlock::VorbisComment) {
// Set the new Vorbis Comment block
delete block;
block = new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData);
foundVorbisCommentBlock = true;
d->blocks.erase(it);
break;
}
if(block->code() == MetadataBlock::Padding) {
delete block;
continue;
}
newBlocks.append(block);
}
if(!foundVorbisCommentBlock) {
newBlocks.append(new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData));
foundVorbisCommentBlock = true;
}
d->blocks = newBlocks;
d->blocks.append(SHARED_PTR<MetadataBlock>(
new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData)));
// Render data for the metadata blocks
ByteVector data;
for(uint i = 0; i < newBlocks.size(); i++) {
FLAC::MetadataBlock *block = newBlocks[i];
ByteVector blockData = block->render();
ByteVector blockHeader = ByteVector::fromUInt(blockData.size());
blockHeader[0] = block->code();
for(BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
ByteVector blockData = (*it)->render();
ByteVector blockHeader = ByteVector::fromUInt32BE(blockData.size());
blockHeader[0] = (*it)->code();
data.append(blockHeader);
data.append(blockData);
}
// Adjust the padding block(s)
// Compute the amount of padding, and append that to data.
long originalLength = d->streamStart - d->flacStart;
int paddingLength = originalLength - data.size() - 4;
if (paddingLength < 0) {
long long originalLength = d->streamStart - d->flacStart;
long long paddingLength = originalLength - data.size() - 4;
if(paddingLength <= 0) {
paddingLength = MinPaddingLength;
}
ByteVector padding = ByteVector::fromUInt(paddingLength);
padding.resize(paddingLength + 4);
padding[0] = (char)(FLAC::MetadataBlock::Padding | LastBlockFlag);
data.append(padding);
else {
// Padding won't increase beyond 1% of the file size or 1MB.
long long threshold = length() / 100;
threshold = std::max(threshold, MinPaddingLength);
threshold = std::min(threshold, MaxPaddingLegnth);
if(paddingLength > threshold)
paddingLength = MinPaddingLength;
}
ByteVector paddingHeader = ByteVector::fromUInt32BE(static_cast<unsigned int>(paddingLength));
paddingHeader[0] = static_cast<char>(MetadataBlock::Padding | LastBlockFlag);
data.append(paddingHeader);
data.resize(static_cast<size_t>(data.size() + paddingLength));
// Write the data to the file
insert(data, d->flacStart, originalLength);
d->hasXiphComment = true;
insert(data, d->flacStart, static_cast<size_t>(originalLength));
d->streamStart += (static_cast<long>(data.size()) - originalLength);
if(d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - originalLength);
// Update ID3 tags
if(ID3v2Tag()) {
if(d->hasID3v2) {
if(d->ID3v2Location < d->flacStart)
debug("FLAC::File::save() -- This can't be right -- an ID3v2 tag after the "
"start of the FLAC bytestream? Not writing the ID3v2 tag.");
else
insert(ID3v2Tag()->render(), d->ID3v2Location, d->ID3v2OriginalSize);
if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) {
// ID3v2 tag is not empty. Update the old one or create a new one.
if(d->ID3v2Location < 0)
d->ID3v2Location = 0;
data = ID3v2Tag()->render();
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);
if(d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
d->ID3v2OriginalSize = data.size();
}
else {
// ID3v2 tag is empty. Remove the old one.
if(d->ID3v2Location >= 0) {
removeBlock(d->ID3v2Location, static_cast<size_t>(d->ID3v2OriginalSize));
d->flacStart -= d->ID3v2OriginalSize;
d->streamStart -= d->ID3v2OriginalSize;
if(d->ID3v1Location >= 0)
d->ID3v1Location -= d->ID3v2OriginalSize;
d->ID3v2Location = -1;
d->ID3v2OriginalSize = 0;
}
else
insert(ID3v2Tag()->render(), 0, 0);
}
if(ID3v1Tag()) {
seek(-128, End);
if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
// ID3v1 tag is not empty. Update the old one or create a new one.
if(d->ID3v1Location >= 0) {
seek(d->ID3v1Location);
}
else {
seek(0, End);
d->ID3v1Location = tell();
}
writeBlock(ID3v1Tag()->render());
}
else {
// ID3v1 tag is empty. Remove the old one.
if(d->ID3v1Location >= 0) {
truncate(d->ID3v1Location);
d->ID3v1Location = -1;
}
}
return true;
}
ID3v2::Tag *FLAC::File::ID3v2Tag(bool create)
{
if(!create || d->tag[FlacID3v2Index])
return static_cast<ID3v2::Tag *>(d->tag[FlacID3v2Index]);
d->tag.set(FlacID3v2Index, new ID3v2::Tag);
return static_cast<ID3v2::Tag *>(d->tag[FlacID3v2Index]);
return d->tag.access<ID3v2::Tag>(FlacID3v2Index, create);
}
ID3v1::Tag *FLAC::File::ID3v1Tag(bool create)
@@ -292,42 +313,92 @@ Ogg::XiphComment *FLAC::File::xiphComment(bool create)
return d->tag.access<Ogg::XiphComment>(FlacXiphIndex, create);
}
void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
List<FLAC::Picture *> FLAC::File::pictureList()
{
d->ID3v2FrameFactory = factory;
List<Picture *> pictures;
for(BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
Picture *picture = dynamic_cast<Picture *>(it->get());
if(picture) {
pictures.append(picture);
}
}
return pictures;
}
void FLAC::File::addPicture(Picture *picture)
{
d->blocks.append(SHARED_PTR<Picture>(picture));
}
void FLAC::File::removePicture(Picture *picture)
{
BlockIterator it = d->blocks.find(picture);
if(it != d->blocks.end())
d->blocks.erase(it);
}
void FLAC::File::removePictures()
{
for(BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ) {
if(dynamic_cast<Picture *>(it->get())) {
it = d->blocks.erase(it);
}
else {
++it;
}
}
}
void FLAC::File::strip(int tags)
{
if(tags & ID3v1)
d->tag.set(FlacID3v1Index, 0);
if(tags & ID3v2)
d->tag.set(FlacID3v2Index, 0);
if(tags & XiphComment) {
xiphComment()->removeAllFields();
xiphComment()->removeAllPictures();
}
}
bool FLAC::File::hasXiphComment() const
{
return !d->xiphCommentData.isEmpty();
}
bool FLAC::File::hasID3v1Tag() const
{
return (d->ID3v1Location >= 0);
}
bool FLAC::File::hasID3v2Tag() const
{
return (d->ID3v2Location >= 0);
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
void FLAC::File::read(bool readProperties)
{
// Look for an ID3v2 tag
d->ID3v2Location = findID3v2();
d->ID3v2Location = Utils::findID3v2(this);
if(d->ID3v2Location >= 0) {
d->tag.set(FlacID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize();
if(ID3v2Tag()->header()->tagSize() <= 0)
d->tag.set(FlacID3v2Index, 0);
else
d->hasID3v2 = true;
}
// Look for an ID3v1 tag
d->ID3v1Location = findID3v1();
d->ID3v1Location = Utils::findID3v1(this);
if(d->ID3v1Location >= 0) {
if(d->ID3v1Location >= 0)
d->tag.set(FlacID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
d->hasID3v1 = true;
}
// Look for FLAC metadata, including vorbis comments
@@ -336,28 +407,26 @@ void FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
if(!isValid())
return;
if(d->hasXiphComment)
d->tag.set(FlacXiphIndex, new Ogg::XiphComment(xiphCommentData()));
if(!d->xiphCommentData.isEmpty())
d->tag.set(FlacXiphIndex, new Ogg::XiphComment(d->xiphCommentData));
else
d->tag.set(FlacXiphIndex, new Ogg::XiphComment);
d->tag.set(FlacXiphIndex, new Ogg::XiphComment());
if(readProperties)
d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle);
}
if(readProperties) {
ByteVector FLAC::File::streamInfoData()
{
return isValid() ? d->streamInfoData : ByteVector();
}
// First block should be the stream_info metadata
ByteVector FLAC::File::xiphCommentData() const
{
return (isValid() && d->hasXiphComment) ? d->xiphCommentData : ByteVector();
}
const ByteVector infoData = d->blocks.front()->render();
long FLAC::File::streamLength()
{
return d->streamLength;
long long streamLength;
if(d->ID3v1Location >= 0)
streamLength = d->ID3v1Location - d->streamStart;
else
streamLength = length() - d->streamStart;
d->properties.reset(new AudioProperties(infoData, streamLength));
}
}
void FLAC::File::scan()
@@ -370,9 +439,9 @@ void FLAC::File::scan()
if(!isValid())
return;
long nextBlockOffset;
long long nextBlockOffset;
if(d->hasID3v2)
if(d->ID3v2Location >= 0)
nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize);
else
nextBlockOffset = find("fLaC");
@@ -386,172 +455,90 @@ void FLAC::File::scan()
nextBlockOffset += 4;
d->flacStart = nextBlockOffset;
seek(nextBlockOffset);
while(true) {
ByteVector header = readBlock(4);
seek(nextBlockOffset);
const ByteVector header = readBlock(4);
// Header format (from spec):
// <1> Last-metadata-block flag
// <7> BLOCK_TYPE
// 0 : STREAMINFO
// 1 : PADDING
// ..
// 4 : VORBIS_COMMENT
// ..
// <24> Length of metadata to follow
// Header format (from spec):
// <1> Last-metadata-block flag
// <7> BLOCK_TYPE
// 0 : STREAMINFO
// 1 : PADDING
// ..
// 4 : VORBIS_COMMENT
// ..
// 6 : PICTURE
// ..
// <24> Length of metadata to follow
char blockType = header[0] & 0x7f;
bool isLastBlock = (header[0] & 0x80) != 0;
uint length = header.mid(1, 3).toUInt();
const char blockType = header[0] & ~LastBlockFlag;
const bool isLastBlock = (header[0] & LastBlockFlag) != 0;
const size_t blockLength = header.toUInt24BE(1);
// First block should be the stream_info metadata
// First block should be the stream_info metadata
if(blockType != MetadataBlock::StreamInfo) {
debug("FLAC::File::scan() -- invalid FLAC stream");
setValid(false);
return;
}
d->streamInfoData = readBlock(length);
d->blocks.append(new UnknownMetadataBlock(blockType, d->streamInfoData));
nextBlockOffset += length + 4;
// Search through the remaining metadata
while(!isLastBlock) {
header = readBlock(4);
blockType = header[0] & 0x7f;
isLastBlock = (header[0] & 0x80) != 0;
length = header.mid(1, 3).toUInt();
ByteVector data = readBlock(length);
if(data.size() != length) {
debug("FLAC::File::scan() -- FLAC stream corrupted");
if(d->blocks.isEmpty() && blockType != MetadataBlock::StreamInfo) {
debug("FLAC::File::scan() -- First block should be the stream_info metadata");
setValid(false);
return;
}
MetadataBlock *block = 0;
if(blockLength == 0
&& blockType != MetadataBlock::Padding && blockType != MetadataBlock::SeekTable)
{
debug("FLAC::File::scan() -- Zero-sized metadata block found");
setValid(false);
return;
}
const ByteVector data = readBlock(blockLength);
if(data.size() != blockLength) {
debug("FLAC::File::scan() -- Failed to read a metadata block");
setValid(false);
return;
}
SHARED_PTR<MetadataBlock> block;
// Found the vorbis-comment
if(blockType == MetadataBlock::VorbisComment) {
if(!d->hasXiphComment) {
if(d->xiphCommentData.isEmpty()) {
d->xiphCommentData = data;
d->hasXiphComment = true;
block.reset(new UnknownMetadataBlock(MetadataBlock::VorbisComment, data));
}
else {
debug("FLAC::File::scan() -- multiple Vorbis Comment blocks found, using the first one");
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, discarting");
delete picture;
debug("FLAC::File::scan() -- invalid picture found, discarding");
}
}
if(!block) {
block = new UnknownMetadataBlock(blockType, data);
}
if(block->code() != MetadataBlock::Padding) {
d->blocks.append(block);
else if(blockType == MetadataBlock::Padding) {
// Skip all padding blocks.
}
else {
delete block;
block.reset(new UnknownMetadataBlock(blockType, data));
}
nextBlockOffset += length + 4;
if(block)
d->blocks.append(block);
if(nextBlockOffset >= File::length()) {
debug("FLAC::File::scan() -- FLAC stream corrupted");
setValid(false);
return;
}
seek(nextBlockOffset);
nextBlockOffset += blockLength + 4;
if(isLastBlock)
break;
}
// End of metadata, now comes the datastream
d->streamStart = nextBlockOffset;
d->streamLength = File::length() - d->streamStart;
if(d->hasID3v1)
d->streamLength -= 128;
d->scanned = true;
}
long FLAC::File::findID3v1()
{
if(!isValid())
return -1;
seek(-128, End);
long p = tell();
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
return p;
return -1;
}
long FLAC::File::findID3v2()
{
if(!isValid())
return -1;
seek(0);
if(readBlock(3) == ID3v2::Header::fileIdentifier())
return 0;
return -1;
}
List<FLAC::Picture *> FLAC::File::pictureList()
{
List<Picture *> pictures;
for(uint i = 0; i < d->blocks.size(); i++) {
Picture *picture = dynamic_cast<Picture *>(d->blocks[i]);
if(picture) {
pictures.append(picture);
}
}
return pictures;
}
void FLAC::File::addPicture(Picture *picture)
{
d->blocks.append(picture);
}
void FLAC::File::removePicture(Picture *picture, bool del)
{
MetadataBlock *block = picture;
List<MetadataBlock *>::Iterator it = d->blocks.find(block);
if(it != d->blocks.end())
d->blocks.erase(it);
if(del)
delete picture;
}
void FLAC::File::removePictures()
{
List<MetadataBlock *> newBlocks;
for(uint i = 0; i < d->blocks.size(); i++) {
Picture *picture = dynamic_cast<Picture *>(d->blocks[i]);
if(picture) {
delete picture;
}
else {
newBlocks.append(d->blocks[i]);
}
}
d->blocks = newBlocks;
}

View File

@@ -46,7 +46,7 @@ namespace TagLib {
/*!
* This is implementation of FLAC metadata for non-Ogg FLAC files. At some
* point when Ogg / FLAC is more common there will be a similar implementation
* under the Ogg hiearchy.
* under the Ogg hierarchy.
*
* This supports ID3v1, ID3v2 and Xiph style comments as well as reading stream
* properties from the file.
@@ -67,44 +67,52 @@ namespace TagLib {
{
public:
/*!
* Contructs a FLAC 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.
*
* \deprecated This constructor will be dropped in favor of the one below
* in a future version.
* This set of flags is used for various operations and is suitable for
* being OR-ed together.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
enum TagTypes {
//! Empty set. Matches no tag types.
NoTags = 0x0000,
//! Matches Vorbis comments.
XiphComment = 0x0001,
//! Matches ID3v1 tags.
ID3v1 = 0x0002,
//! Matches ID3v2 tags.
ID3v2 = 0x0004,
//! Matches all tag types.
AllTags = 0xffff
};
/*!
* Contructs a FLAC 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.
* Constructs an FLAC file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* If this file contains and ID3v2 tag the frames will be created using
* \a frameFactory.
*
* \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);
/*!
* Contructs a FLAC 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.
* Constructs a FLAC file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* 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.
@@ -121,28 +129,20 @@ 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.
* As with the export, only one tag is taken into account. If the file
* has no tag at all, a XiphComment will be created.
* This always creates a Xiph comment, if none exists. The return value
* relates to the Xiph comment only.
* 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
@@ -156,77 +156,69 @@ namespace TagLib {
/*!
* Returns a pointer to the ID3v2 tag of the file.
*
* If \a create is false (the default) this will return a null pointer
* If \a create is false (the default) this returns a null pointer
* if there is no valid ID3v2 tag. If \a create is true it will create
* an ID3v2 tag if one does not exist.
* an ID3v2 tag if one does not exist and returns a valid pointer.
*
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file
* on disk actually has an ID3v2 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
* \see hasID3v2Tag()
*/
ID3v2::Tag *ID3v2Tag(bool create = false);
/*!
* Returns a pointer to the ID3v1 tag of the file.
*
* If \a create is false (the default) this will return a null pointer
* if there is no valid ID3v1 tag. If \a create is true it will create
* an ID3v1 tag if one does not exist.
* If \a create is false (the default) this returns a null pointer
* if there is no valid APE tag. If \a create is true it will create
* an APE tag if one does not exist and returns a valid pointer.
*
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
* on disk actually has an ID3v1 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
* \see hasID3v1Tag()
*/
ID3v1::Tag *ID3v1Tag(bool create = false);
/*!
* Returns a pointer to the XiphComment for the file.
*
* If \a create is false (the default) this will return a null pointer
* If \a create is false (the default) this returns a null pointer
* if there is no valid XiphComment. If \a create is true it will create
* a XiphComment if one does not exist.
* a XiphComment if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has a XiphComment. Use hasXiphComment() to check if the
* file on disk actually has a XiphComment.
*
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
* \see hasXiphComment()
*/
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
*/
void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
/*!
* Returns the block of data used by FLAC::Properties for parsing the
* stream properties.
*
* \deprecated This method will not be public in a future release.
*/
ByteVector streamInfoData(); // BIC: remove
/*!
* Returns the length of the audio-stream, used by FLAC::Properties for
* calculating the bitrate.
*
* \deprecated This method will not be public in a future release.
*/
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.
@@ -241,16 +233,57 @@ namespace TagLib {
*/
void addPicture(Picture *picture);
/*!
* This will remove the tags that match the OR-ed together TagTypes from
* the file. By default it removes all tags.
*
* \warning This will also invalidate pointers to the tags as their memory
* will be freed.
*
* \note In order to make the removal permanent save() still needs to be
* called.
*
* \note This won't remove the Vorbis comment block completely. The
* vendor ID will be preserved.
*/
void strip(int tags = AllTags);
/*!
* Returns whether or not the file on disk actually has a XiphComment.
*
* \see xiphComment()
*/
bool hasXiphComment() const;
/*!
* Returns whether or not the file on disk actually has an ID3v1 tag.
*
* \see ID3v1Tag()
*/
bool hasID3v1Tag() const;
/*!
* Returns whether or not the file on disk actually has an ID3v2 tag.
*
* \see ID3v2Tag()
*/
bool hasID3v2Tag() const;
/*!
* Returns whether or not the given \a stream can be opened as a FLAC
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
File(const File &);
File &operator=(const File &);
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
void read(bool readProperties);
void scan();
long findID3v2();
long findID3v1();
ByteVector xiphCommentData() const;
long findPaddingBreak(long nextPageOffset, long targetOffset, bool *isLast);
class FilePrivate;
FilePrivate *d;

View File

@@ -23,10 +23,6 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <taglib.h>
#include <tdebug.h>
#include "flacmetadatablock.h"

View File

@@ -23,10 +23,6 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <taglib.h>
#include <tdebug.h>
#include "flacpicture.h"
@@ -54,14 +50,14 @@ public:
ByteVector data;
};
FLAC::Picture::Picture()
FLAC::Picture::Picture() :
d(new PicturePrivate())
{
d = new PicturePrivate;
}
FLAC::Picture::Picture(const ByteVector &data)
FLAC::Picture::Picture(const ByteVector &data) :
d(new PicturePrivate())
{
d = new PicturePrivate;
parse(data);
}
@@ -82,10 +78,10 @@ bool FLAC::Picture::parse(const ByteVector &data)
return false;
}
int pos = 0;
d->type = FLAC::Picture::Type(data.mid(pos, 4).toUInt());
size_t pos = 0;
d->type = FLAC::Picture::Type(data.toUInt32BE(pos));
pos += 4;
uint mimeTypeLength = data.mid(pos, 4).toUInt();
const unsigned int mimeTypeLength = data.toUInt32BE(pos);
pos += 4;
if(pos + mimeTypeLength + 24 > data.size()) {
debug("Invalid picture block.");
@@ -93,7 +89,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
}
d->mimeType = String(data.mid(pos, mimeTypeLength), String::UTF8);
pos += mimeTypeLength;
uint descriptionLength = data.mid(pos, 4).toUInt();
const unsigned int descriptionLength = data.toUInt32BE(pos);
pos += 4;
if(pos + descriptionLength + 20 > data.size()) {
debug("Invalid picture block.");
@@ -101,15 +97,15 @@ bool FLAC::Picture::parse(const ByteVector &data)
}
d->description = String(data.mid(pos, descriptionLength), String::UTF8);
pos += descriptionLength;
d->width = data.mid(pos, 4).toUInt();
d->width = data.toUInt32BE(pos);
pos += 4;
d->height = data.mid(pos, 4).toUInt();
d->height = data.toUInt32BE(pos);
pos += 4;
d->colorDepth = data.mid(pos, 4).toUInt();
d->colorDepth = data.toUInt32BE(pos);
pos += 4;
d->numColors = data.mid(pos, 4).toUInt();
d->numColors = data.toUInt32BE(pos);
pos += 4;
uint dataLength = data.mid(pos, 4).toUInt();
const unsigned int dataLength = data.toUInt32BE(pos);
pos += 4;
if(pos + dataLength > data.size()) {
debug("Invalid picture block.");
@@ -123,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,27 +31,21 @@
using namespace TagLib;
class FLAC::Properties::PropertiesPrivate
class FLAC::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(ByteVector d, long st, ReadStyle s) :
data(d),
streamLength(st),
style(s),
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
sampleWidth(0),
bitsPerSample(0),
channels(0),
sampleFrames(0) {}
ByteVector data;
long streamLength;
ReadStyle style;
int length;
int bitrate;
int sampleRate;
int sampleWidth;
int bitsPerSample;
int channels;
unsigned long long sampleFrames;
ByteVector signature;
@@ -61,54 +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())
{
d = new PropertiesPrivate(data, streamLength, style);
read();
read(data, streamLength);
}
FLAC::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style)
{
d = new PropertiesPrivate(file->streamInfoData(), file->streamLength(), style);
read();
}
FLAC::Properties::~Properties()
FLAC::AudioProperties::~AudioProperties()
{
delete d;
}
int FLAC::Properties::length() const
int FLAC::AudioProperties::length() const
{
return lengthInSeconds();
}
int FLAC::AudioProperties::lengthInSeconds() const
{
return d->length / 1000;
}
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::sampleWidth() const
int FLAC::AudioProperties::bitsPerSample() const
{
return d->sampleWidth;
return d->bitsPerSample;
}
int FLAC::Properties::channels() const
int FLAC::AudioProperties::sampleWidth() const
{
return bitsPerSample();
}
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;
}
@@ -117,14 +121,14 @@ ByteVector FLAC::Properties::signature() const
// private members
////////////////////////////////////////////////////////////////////////////////
void FLAC::Properties::read()
void FLAC::AudioProperties::read(const ByteVector &data, long long streamLength)
{
if(d->data.size() < 18) {
debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
if(data.size() < 18) {
debug("FLAC::AudioProperties::read() - FLAC properties must contain at least 18 bytes.");
return;
}
int pos = 0;
size_t pos = 0;
// Minimum block size (in samples)
pos += 2;
@@ -138,32 +142,28 @@ void FLAC::Properties::read()
// Maximum frame size (in bytes)
pos += 3;
uint flags = d->data.mid(pos, 4).toUInt(true);
const unsigned int flags = data.toUInt32BE(pos);
pos += 4;
d->sampleRate = flags >> 12;
d->channels = ((flags >> 9) & 7) + 1;
d->sampleWidth = ((flags >> 4) & 31) + 1;
d->sampleRate = flags >> 12;
d->channels = ((flags >> 9) & 7) + 1;
d->bitsPerSample = ((flags >> 4) & 31) + 1;
// The last 4 bits are the most significant 4 bits for the 36 bit
// stream length in samples. (Audio files measured in days)
unsigned long long hi = flags & 0xf;
unsigned long long lo = d->data.mid(pos, 4).toUInt(true);
const unsigned long long hi = flags & 0xf;
const unsigned long long lo = data.toUInt32BE(pos);
pos += 4;
d->sampleFrames = (hi << 32) | lo;
if(d->sampleRate > 0)
d->length = int(d->sampleFrames / d->sampleRate);
if(d->sampleFrames > 0 && d->sampleRate > 0) {
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
}
// Uncompressed bitrate:
//d->bitrate = ((d->sampleRate * d->channels) / 1000) * d->sampleWidth;
// Real bitrate:
d->bitrate = d->length > 0 ? ((d->streamLength * 8UL) / d->length) / 1000 : 0;
d->signature = d->data.mid(pos, 32);
if(data.size() >= pos + 16)
d->signature = data.mid(pos, 16);
}

View File

@@ -42,57 +42,89 @@ 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);
virtual ~AudioProperties();
/*!
* Destroys this FLAC::Properties instance.
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
*/
virtual ~Properties();
// Reimplementations.
virtual int length() const;
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
virtual int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
virtual int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
/*!
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
/*!
* Returns the number of audio channels.
*/
virtual int channels() const;
/*!
* Returns the number of bits per audio sample as read from the FLAC
* identification header.
*/
int bitsPerSample() const;
/*!
* Returns the sample width as read from the FLAC identification
* header.
*
* \note This method is just an alias of bitsPerSample().
*
* \deprecated
*/
int sampleWidth() const;
/*!
* Return the number of sample frames
* Return the number of sample frames.
*/
unsigned long long sampleFrames() const;
/*!
* Returns the MD5 signature of the uncompressed audio stream as read
* from the stream info header header.
* from the stream info header.
*/
ByteVector signature() const;
private:
Properties(const Properties &);
Properties &operator=(const Properties &);
void read();
void read(const ByteVector &data, long long streamLength);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@@ -23,10 +23,6 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <taglib.h>
#include <tdebug.h>
#include <tstring.h>
@@ -43,11 +39,10 @@ public:
ByteVector data;
};
FLAC::UnknownMetadataBlock::UnknownMetadataBlock(int code, const ByteVector &data)
FLAC::UnknownMetadataBlock::UnknownMetadataBlock(int code, const ByteVector &data) :
d(new UnknownMetadataBlockPrivate())
{
d = new UnknownMetadataBlockPrivate;
d->code = code;
//debug(String(data.toHex()));
d->data = data;
}

View File

@@ -5,7 +5,7 @@
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,10 +15,15 @@
* *
* 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 *
* 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 "tstringlist.h"
#include "itfile.h"
#include "tdebug.h"
@@ -31,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,
@@ -45,7 +50,8 @@ IT::File::File(FileName file, bool readProperties,
Mod::FileBase(file),
d(new FilePrivate(propertiesStyle))
{
read(readProperties);
if(isOpen())
read(readProperties);
}
IT::File::File(IOStream *stream, bool readProperties,
@@ -53,7 +59,8 @@ IT::File::File(IOStream *stream, bool readProperties,
Mod::FileBase(stream),
d(new FilePrivate(propertiesStyle))
{
read(readProperties);
if(isOpen())
read(readProperties);
}
IT::File::~File()
@@ -66,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;
}
@@ -94,9 +91,9 @@ bool IT::File::save()
seek(2, Current);
ushort length = 0;
ushort instrumentCount = 0;
ushort sampleCount = 0;
unsigned short length = 0;
unsigned short instrumentCount = 0;
unsigned short sampleCount = 0;
if(!readU16L(length) || !readU16L(instrumentCount) || !readU16L(sampleCount))
return false;
@@ -105,9 +102,9 @@ bool IT::File::save()
// write comment as instrument and sample names:
StringList lines = d->tag.comment().split("\n");
for(ushort i = 0; i < instrumentCount; ++ i) {
for(unsigned short i = 0; i < instrumentCount; ++ i) {
seek(192L + length + ((long)i << 2));
ulong instrumentOffset = 0;
unsigned int instrumentOffset = 0;
if(!readU32L(instrumentOffset))
return false;
@@ -116,28 +113,28 @@ bool IT::File::save()
if(i < lines.size())
writeString(lines[i], 25);
else
writeString(String::null, 25);
writeString(String(), 25);
writeByte(0);
}
for(ushort i = 0; i < sampleCount; ++ i) {
for(unsigned short i = 0; i < sampleCount; ++ i) {
seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
ulong sampleOffset = 0;
unsigned int sampleOffset = 0;
if(!readU32L(sampleOffset))
return false;
seek(sampleOffset + 20);
if((TagLib::uint)(i + instrumentCount) < lines.size())
if((unsigned int)(i + instrumentCount) < lines.size())
writeString(lines[i + instrumentCount], 25);
else
writeString(String::null, 25);
writeString(String(), 25);
writeByte(0);
}
// write rest as message:
StringList messageLines;
for(uint i = instrumentCount + sampleCount; i < lines.size(); ++ i)
for(unsigned int i = instrumentCount + sampleCount; i < lines.size(); ++ i)
messageLines.append(lines[i]);
ByteVector message = messageLines.toString("\r").data(String::Latin1);
@@ -147,16 +144,16 @@ bool IT::File::save()
message.resize(7999);
message.append((char)0);
ushort special = 0;
ushort messageLength = 0;
ulong messageOffset = 0;
unsigned short special = 0;
unsigned short messageLength = 0;
unsigned int messageOffset = 0;
seek(46);
if(!readU16L(special))
return false;
ulong 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;
@@ -174,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);
@@ -226,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;
@@ -257,8 +254,8 @@ void IT::File::read(bool)
d->properties.setChannels(channels);
// real length might be shorter because of skips and terminator
ushort realLength = 0;
for(ushort i = 0; i < length; ++ i) {
unsigned short realLength = 0;
for(unsigned short i = 0; i < length; ++ i) {
READ_BYTE_AS(order);
if(order == 255) break;
if(order != 254) ++ realLength;
@@ -272,7 +269,7 @@ void IT::File::read(bool)
// Currently I just discard anything after a nil, but
// e.g. VLC seems to interprete a nil as a space. I
// don't know what is the proper behaviour.
for(ushort i = 0; i < instrumentCount; ++ i) {
for(unsigned short i = 0; i < instrumentCount; ++ i) {
seek(192L + length + ((long)i << 2));
READ_U32L_AS(instrumentOffset);
seek(instrumentOffset);
@@ -288,7 +285,7 @@ void IT::File::read(bool)
comment.append(instrumentName);
}
for(ushort i = 0; i < sampleCount; ++ i) {
for(unsigned short i = 0; i < sampleCount; ++ i) {
seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
READ_U32L_AS(sampleOffset);

View File

@@ -36,23 +36,27 @@ namespace TagLib {
class TAGLIB_EXPORT File : public Mod::FileBase {
public:
/*!
* Contructs a Impulse Tracker 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.
* Constructs a Impulse Tracker file from \a file.
*
* \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,
AudioProperties::ReadStyle propertiesStyle =
AudioProperties::Average);
/*!
* Contructs a Impulse Tracker 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.
* Constructs a Impulse Tracker file from \a stream.
*
* \note In the current implementation, both \a readProperties and
* \a propertiesStyle are ignored. The audio properties are always
* read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*/
File(IOStream *stram, bool readProperties = true,
File(IOStream *stream, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle =
AudioProperties::Average);
@@ -63,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,11 +1,11 @@
/***************************************************************************
/***************************************************************************
copyright :(C) 2011 by Mathias Panzenböck
email : grosser.meister.morti@gmx.net
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,16 +15,21 @@
* *
* 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 *
* 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 "itproperties.h"
using namespace TagLib;
using namespace IT;
class IT::Properties::PropertiesPrivate
class IT::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() :
@@ -42,204 +47,220 @@ public:
tempo(0),
bpmSpeed(0),
panningSeparation(0),
pitchWheelDepth(0)
{
}
pitchWheelDepth(0) {}
int channels;
ushort lengthInPatterns;
ushort instrumentCount;
ushort sampleCount;
ushort patternCount;
ushort version;
ushort compatibleVersion;
ushort flags;
ushort special;
uchar globalVolume;
uchar mixVolume;
uchar tempo;
uchar bpmSpeed;
uchar panningSeparation;
uchar pitchWheelDepth;
int channels;
unsigned short lengthInPatterns;
unsigned short instrumentCount;
unsigned short sampleCount;
unsigned short patternCount;
unsigned short version;
unsigned short compatibleVersion;
unsigned short flags;
unsigned short special;
unsigned char globalVolume;
unsigned char mixVolume;
unsigned char tempo;
unsigned char bpmSpeed;
unsigned char panningSeparation;
unsigned char pitchWheelDepth;
};
IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
AudioProperties(propertiesStyle),
d(new PropertiesPrivate)
////////////////////////////////////////////////////////////////////////////////
// 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::bitrate() const
int IT::AudioProperties::lengthInSeconds() const
{
return 0;
}
int IT::Properties::sampleRate() const
int IT::AudioProperties::lengthInMilliseconds() const
{
return 0;
}
int IT::Properties::channels() const
int IT::AudioProperties::bitrate() const
{
return 0;
}
int IT::AudioProperties::sampleRate() const
{
return 0;
}
int IT::AudioProperties::channels() const
{
return d->channels;
}
TagLib::ushort 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;
}
TagLib::ushort IT::Properties::instrumentCount() const
unsigned short IT::AudioProperties::instrumentCount() const
{
return d->instrumentCount;
}
TagLib::ushort IT::Properties::sampleCount() const
unsigned short IT::AudioProperties::sampleCount() const
{
return d->sampleCount;
}
TagLib::ushort IT::Properties::patternCount() const
unsigned short IT::AudioProperties::patternCount() const
{
return d->patternCount;
}
TagLib::ushort IT::Properties::version() const
unsigned short IT::AudioProperties::version() const
{
return d->version;
}
TagLib::ushort IT::Properties::compatibleVersion() const
unsigned short IT::AudioProperties::compatibleVersion() const
{
return d->compatibleVersion;
}
TagLib::ushort IT::Properties::flags() const
unsigned short IT::AudioProperties::flags() const
{
return d->flags;
}
TagLib::ushort IT::Properties::special() const
unsigned short IT::AudioProperties::special() const
{
return d->special;
}
uchar IT::Properties::globalVolume() const
unsigned char IT::AudioProperties::globalVolume() const
{
return d->globalVolume;
}
uchar IT::Properties::mixVolume() const
unsigned char IT::AudioProperties::mixVolume() const
{
return d->mixVolume;
}
uchar IT::Properties::tempo() const
unsigned char IT::AudioProperties::tempo() const
{
return d->tempo;
}
uchar IT::Properties::bpmSpeed() const
unsigned char IT::AudioProperties::bpmSpeed() const
{
return d->bpmSpeed;
}
uchar IT::Properties::panningSeparation() const
unsigned char IT::AudioProperties::panningSeparation() const
{
return d->panningSeparation;
}
uchar 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(ushort lengthInPatterns)
void IT::AudioProperties::setLengthInPatterns(unsigned short lengthInPatterns)
{
d->lengthInPatterns = lengthInPatterns;
}
void IT::Properties::setInstrumentCount(ushort instrumentCount)
void IT::AudioProperties::setInstrumentCount(unsigned short instrumentCount)
{
d->instrumentCount = instrumentCount;
}
void IT::Properties::setSampleCount(ushort sampleCount)
void IT::AudioProperties::setSampleCount(unsigned short sampleCount)
{
d->sampleCount = sampleCount;
}
void IT::Properties::setPatternCount(ushort patternCount)
void IT::AudioProperties::setPatternCount(unsigned short patternCount)
{
d->patternCount = patternCount;
}
void IT::Properties::setFlags(ushort flags)
void IT::AudioProperties::setFlags(unsigned short flags)
{
d->flags = flags;
}
void IT::Properties::setSpecial(ushort special)
void IT::AudioProperties::setSpecial(unsigned short special)
{
d->special = special;
}
void IT::Properties::setCompatibleVersion(ushort compatibleVersion)
void IT::AudioProperties::setCompatibleVersion(unsigned short compatibleVersion)
{
d->compatibleVersion = compatibleVersion;
}
void IT::Properties::setVersion(ushort version)
void IT::AudioProperties::setVersion(unsigned short version)
{
d->version = version;
}
void IT::Properties::setGlobalVolume(uchar globalVolume)
void IT::AudioProperties::setGlobalVolume(unsigned char globalVolume)
{
d->globalVolume = globalVolume;
}
void IT::Properties::setMixVolume(uchar mixVolume)
void IT::AudioProperties::setMixVolume(unsigned char mixVolume)
{
d->mixVolume = mixVolume;
}
void IT::Properties::setTempo(uchar tempo)
void IT::AudioProperties::setTempo(unsigned char tempo)
{
d->tempo = tempo;
}
void IT::Properties::setBpmSpeed(uchar bpmSpeed)
void IT::AudioProperties::setBpmSpeed(unsigned char bpmSpeed)
{
d->bpmSpeed = bpmSpeed;
}
void IT::Properties::setPanningSeparation(uchar panningSeparation)
void IT::AudioProperties::setPanningSeparation(unsigned char panningSeparation)
{
d->panningSeparation = panningSeparation;
}
void IT::Properties::setPitchWheelDepth(uchar pitchWheelDepth)
void IT::AudioProperties::setPitchWheelDepth(unsigned char pitchWheelDepth)
{
d->pitchWheelDepth = pitchWheelDepth;
}

View File

@@ -5,7 +5,7 @@
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,8 +15,12 @@
* *
* 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 *
* 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_ITPROPERTIES_H
@@ -26,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 {
@@ -48,49 +58,48 @@ namespace TagLib {
MidiConfEmbedded = 8
};
Properties(AudioProperties::ReadStyle propertiesStyle);
virtual ~Properties();
explicit AudioProperties(AudioProperties::ReadStyle propertiesStyle);
virtual ~AudioProperties();
int length() const;
int bitrate() const;
int sampleRate() const;
int channels() const;
int length() const;
int lengthInSeconds() const;
int lengthInMilliseconds() const;
int bitrate() const;
int sampleRate() const;
int channels() const;
ushort lengthInPatterns() const;
bool stereo() const;
ushort instrumentCount() const;
ushort sampleCount() const;
ushort patternCount() const;
ushort version() const;
ushort compatibleVersion() const;
ushort flags() const;
ushort special() const;
uchar globalVolume() const;
uchar mixVolume() const;
uchar tempo() const;
uchar bpmSpeed() const;
uchar panningSeparation() const;
uchar pitchWheelDepth() const;
void setChannels(int channels);
void setLengthInPatterns(ushort lengthInPatterns);
void setInstrumentCount(ushort instrumentCount);
void setSampleCount (ushort sampleCount);
void setPatternCount(ushort patternCount);
void setVersion (ushort version);
void setCompatibleVersion(ushort compatibleVersion);
void setFlags (ushort flags);
void setSpecial (ushort special);
void setGlobalVolume(uchar globalVolume);
void setMixVolume (uchar mixVolume);
void setTempo (uchar tempo);
void setBpmSpeed (uchar bpmSpeed);
void setPanningSeparation(uchar panningSeparation);
void setPitchWheelDepth (uchar pitchWheelDepth);
unsigned short lengthInPatterns() const;
bool stereo() const;
unsigned short instrumentCount() const;
unsigned short sampleCount() const;
unsigned short patternCount() const;
unsigned short version() const;
unsigned short compatibleVersion() const;
unsigned short flags() const;
unsigned short special() const;
unsigned char globalVolume() const;
unsigned char mixVolume() const;
unsigned char tempo() const;
unsigned char bpmSpeed() const;
unsigned char panningSeparation() const;
unsigned char pitchWheelDepth() const;
private:
Properties(const Properties&);
Properties &operator=(const Properties&);
void setChannels(int channels);
void setLengthInPatterns(unsigned short lengthInPatterns);
void setInstrumentCount(unsigned short instrumentCount);
void setSampleCount (unsigned short sampleCount);
void setPatternCount(unsigned short patternCount);
void setVersion (unsigned short version);
void setCompatibleVersion(unsigned short compatibleVersion);
void setFlags (unsigned short flags);
void setSpecial (unsigned short special);
void setGlobalVolume(unsigned char globalVolume);
void setMixVolume (unsigned char mixVolume);
void setTempo (unsigned char tempo);
void setBpmSpeed (unsigned char bpmSpeed);
void setPanningSeparation(unsigned char panningSeparation);
void setPitchWheelDepth (unsigned char pitchWheelDepth);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@@ -5,7 +5,7 @@
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,10 +15,15 @@
* *
* 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 *
* 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 "modfile.h"
#include "tstringlist.h"
#include "tdebug.h"
@@ -31,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,
@@ -45,7 +50,8 @@ Mod::File::File(FileName file, bool readProperties,
Mod::FileBase(file),
d(new FilePrivate(propertiesStyle))
{
read(readProperties);
if(isOpen())
read(readProperties);
}
Mod::File::File(IOStream *stream, bool readProperties,
@@ -53,7 +59,8 @@ Mod::File::File(IOStream *stream, bool readProperties,
Mod::FileBase(stream),
d(new FilePrivate(propertiesStyle))
{
read(readProperties);
if(isOpen())
read(readProperties);
}
Mod::File::~File()
@@ -66,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()) {
@@ -90,14 +87,14 @@ bool Mod::File::save()
seek(0);
writeString(d->tag.title(), 20);
StringList lines = d->tag.comment().split("\n");
uint n = std::min(lines.size(), d->properties.instrumentCount());
for(uint 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(uint i = n; i < d->properties.instrumentCount(); ++ i) {
writeString(String::null, 22);
for(size_t i = n; i < d->properties.instrumentCount(); ++ i) {
writeString(String(), 22);
seek(8, Current);
}
return true;
@@ -112,8 +109,8 @@ void Mod::File::read(bool)
ByteVector modId = readBlock(4);
READ_ASSERT(modId.size() == 4);
int channels = 4;
uint instruments = 31;
int channels = 4;
unsigned int instruments = 31;
if(modId == "M.K." || modId == "M!K!" || modId == "M&K!" || modId == "N.T.") {
d->tag.setTrackerName("ProTracker");
channels = 4;
@@ -157,7 +154,7 @@ void Mod::File::read(bool)
READ_STRING(d->tag.setTitle, 20);
StringList comment;
for(uint i = 0; i < instruments; ++ i) {
for(unsigned int i = 0; i < instruments; ++ i) {
READ_STRING_AS(instrumentName, 22);
// value in words, * 2 (<< 1) for bytes:
READ_U16B_AS(sampleLength);

View File

@@ -5,7 +5,7 @@
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,8 +15,12 @@
* *
* 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 *
* 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_MODFILE_H
@@ -37,18 +41,22 @@ namespace TagLib {
{
public:
/*!
* Contructs a Protracker 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.
* Constructs a Protracker file from \a file.
*
* \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,
AudioProperties::ReadStyle propertiesStyle =
AudioProperties::Average);
/*!
* Contructs a Protracker 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.
* Constructs a Protracker file from \a stream.
*
* \note In the current implementation, both \a readProperties and
* \a propertiesStyle are ignored. The audio properties are always
* read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
@@ -64,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

@@ -5,7 +5,7 @@
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,10 +15,15 @@
* *
* 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 *
* 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 "modfilebase.h"
@@ -33,55 +38,54 @@ Mod::FileBase::FileBase(IOStream *stream) : TagLib::File(stream)
{
}
void Mod::FileBase::writeString(const String &s, ulong 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, ulong 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((char) 0xff, ' ');
data.replace('\xff', ' ');
s = data;
return true;
}
void Mod::FileBase::writeByte(uchar byte)
void Mod::FileBase::writeByte(unsigned char byte)
{
ByteVector data(1, byte);
writeBlock(data);
}
void Mod::FileBase::writeU16L(ushort number)
void Mod::FileBase::writeU16L(unsigned short number)
{
writeBlock(ByteVector::fromShort(number, false));
writeBlock(ByteVector::fromUInt16LE(number));
}
void Mod::FileBase::writeU32L(ulong number)
void Mod::FileBase::writeU32L(unsigned int number)
{
writeBlock(ByteVector::fromUInt(number, false));
writeBlock(ByteVector::fromUInt32LE(number));
}
void Mod::FileBase::writeU16B(ushort number)
void Mod::FileBase::writeU16B(unsigned short number)
{
writeBlock(ByteVector::fromShort(number, true));
writeBlock(ByteVector::fromUInt16BE(number));
}
void Mod::FileBase::writeU32B(ulong number)
void Mod::FileBase::writeU32B(unsigned int number)
{
writeBlock(ByteVector::fromUInt(number, true));
writeBlock(ByteVector::fromUInt32BE(number));
}
bool Mod::FileBase::readByte(uchar &byte)
bool Mod::FileBase::readByte(unsigned char &byte)
{
ByteVector data(readBlock(1));
if(data.size() < 1) return false;
@@ -89,32 +93,32 @@ bool Mod::FileBase::readByte(uchar &byte)
return true;
}
bool Mod::FileBase::readU16L(ushort &number)
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(ulong &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;
}
bool Mod::FileBase::readU16B(ushort &number)
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(ulong &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

@@ -5,7 +5,7 @@
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,8 +15,12 @@
* *
* 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 *
* 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_MODFILEBASE_H
@@ -37,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, ulong size, char padding = 0);
void writeByte(uchar byte);
void writeU16L(ushort number);
void writeU32L(ulong number);
void writeU16B(ushort number);
void writeU32B(ulong number);
void writeString(const String &s, unsigned int size, char padding = 0);
void writeByte(unsigned char byte);
void writeU16L(unsigned short number);
void writeU32L(unsigned int number);
void writeU16B(unsigned short number);
void writeU32B(unsigned int number);
bool readString(String &s, ulong size);
bool readByte(uchar &byte);
bool readU16L(ushort &number);
bool readU32L(ulong &number);
bool readU16B(ushort &number);
bool readU32B(ulong &number);
bool readString(String &s, unsigned int size);
bool readByte(unsigned char &byte);
bool readU16L(unsigned short &number);
bool readU32L(unsigned int &number);
bool readU16B(unsigned short &number);
bool readU32B(unsigned int &number);
};
}

View File

@@ -37,11 +37,11 @@
setter(number); \
}
#define READ_BYTE(setter) READ(setter,uchar,readByte)
#define READ_U16L(setter) READ(setter,ushort,readU16L)
#define READ_U32L(setter) READ(setter,ulong,readU32L)
#define READ_U16B(setter) READ(setter,ushort,readU16B)
#define READ_U32B(setter) READ(setter,ulong,readU32B)
#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 int,readU32L)
#define READ_U16B(setter) READ(setter,unsigned short,readU16B)
#define READ_U32B(setter) READ(setter,unsigned int,readU32B)
#define READ_STRING(setter,size) \
{ \
@@ -54,11 +54,11 @@
type name = 0; \
READ_ASSERT(read(name));
#define READ_BYTE_AS(name) READ_AS(uchar,name,readByte)
#define READ_U16L_AS(name) READ_AS(ushort,name,readU16L)
#define READ_U32L_AS(name) READ_AS(ulong,name,readU32L)
#define READ_U16B_AS(name) READ_AS(ushort,name,readU16B)
#define READ_U32B_AS(name) READ_AS(ulong,name,readU32B)
#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 int,name,readU32L)
#define READ_U16B_AS(name) READ_AS(unsigned short,name,readU16B)
#define READ_U32B_AS(name) READ_AS(unsigned int,name,readU32B)
#define READ_STRING_AS(name,size) \
String name; \

View File

@@ -1,11 +1,11 @@
/***************************************************************************
/***************************************************************************
copyright : (C) 2011 by Mathias Panzenböck
email : grosser.meister.morti@gmx.net
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,82 +15,103 @@
* *
* 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 *
* 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 "modproperties.h"
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;
uint instrumentCount;
uchar lengthInPatterns;
int channels;
unsigned int instrumentCount;
unsigned char lengthInPatterns;
};
Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
AudioProperties(propertiesStyle),
d(new PropertiesPrivate)
////////////////////////////////////////////////////////////////////////////////
// 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::bitrate() const
int Mod::AudioProperties::lengthInSeconds() const
{
return 0;
}
int Mod::Properties::sampleRate() const
int Mod::AudioProperties::lengthInMilliseconds() const
{
return 0;
}
int Mod::Properties::channels() const
int Mod::AudioProperties::bitrate() const
{
return 0;
}
int Mod::AudioProperties::sampleRate() const
{
return 0;
}
int Mod::AudioProperties::channels() const
{
return d->channels;
}
TagLib::uint Mod::Properties::instrumentCount() const
unsigned int Mod::AudioProperties::instrumentCount() const
{
return d->instrumentCount;
}
uchar 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(uint instrumentCount)
void Mod::AudioProperties::setInstrumentCount(unsigned int instrumentCount)
{
d->instrumentCount = instrumentCount;
}
void Mod::Properties::setLengthInPatterns(uchar lengthInPatterns)
void Mod::AudioProperties::setLengthInPatterns(unsigned char lengthInPatterns)
{
d->lengthInPatterns = lengthInPatterns;
}

View File

@@ -5,7 +5,7 @@
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,8 +15,12 @@
* *
* 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 *
* 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_MODPROPERTIES_H
@@ -29,30 +33,31 @@ namespace TagLib {
namespace Mod {
class TAGLIB_EXPORT Properties : public AudioProperties
class File;
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
Properties(AudioProperties::ReadStyle propertiesStyle);
virtual ~Properties();
int length() const;
int bitrate() const;
int sampleRate() const;
int channels() const;
uint instrumentCount() const;
uchar lengthInPatterns() const;
void setChannels(int channels);
void setInstrumentCount(uint sampleCount);
void setLengthInPatterns(uchar lengthInPatterns);
private:
friend class File;
Properties(const Properties&);
Properties &operator=(const Properties&);
public:
explicit AudioProperties(AudioProperties::ReadStyle propertiesStyle);
virtual ~AudioProperties();
int length() const;
int lengthInSeconds() const;
int lengthInMilliseconds() const;
int bitrate() const;
int sampleRate() const;
int channels() const;
unsigned int instrumentCount() const;
unsigned char lengthInPatterns() const;
private:
void setChannels(int channels);
void setInstrumentCount(unsigned int sampleCount);
void setLengthInPatterns(unsigned char lengthInPatterns);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@@ -5,7 +5,7 @@
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,13 +15,19 @@
* *
* 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 *
* 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 "modtag.h"
#include "tstringlist.h"
#include "tpropertymap.h"
#include "tpicturemap.h"
using namespace TagLib;
using namespace Mod;
@@ -38,9 +44,10 @@ public:
String trackerName;
};
Mod::Tag::Tag() : TagLib::Tag()
Mod::Tag::Tag() :
TagLib::Tag(),
d(new TagPrivate())
{
d = new TagPrivate;
}
Mod::Tag::~Tag()
@@ -55,12 +62,12 @@ String Mod::Tag::title() const
String Mod::Tag::artist() const
{
return String::null;
return String();
}
String Mod::Tag::album() const
{
return String::null;
return String();
}
String Mod::Tag::comment() const
@@ -70,19 +77,24 @@ String Mod::Tag::comment() const
String Mod::Tag::genre() const
{
return String::null;
return String();
}
TagLib::uint Mod::Tag::year() const
unsigned int Mod::Tag::year() const
{
return 0;
}
TagLib::uint Mod::Tag::track() const
unsigned int Mod::Tag::track() const
{
return 0;
}
TagLib::PictureMap Mod::Tag::pictures() const
{
return PictureMap();
}
String Mod::Tag::trackerName() const
{
return d->trackerName;
@@ -110,11 +122,15 @@ void Mod::Tag::setGenre(const String &)
{
}
void Mod::Tag::setYear(uint)
void Mod::Tag::setYear(unsigned int)
{
}
void Mod::Tag::setTrack(uint)
void Mod::Tag::setTrack(unsigned int)
{
}
void Mod::Tag::setPictures(const PictureMap &l)
{
}
@@ -128,7 +144,7 @@ PropertyMap Mod::Tag::properties() const
PropertyMap properties;
properties["TITLE"] = d->title;
properties["COMMENT"] = d->comment;
if(!(d->trackerName.isNull()))
if(!(d->trackerName.isEmpty()))
properties["TRACKERNAME"] = d->trackerName;
return properties;
}
@@ -142,23 +158,23 @@ PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps)
d->title = properties["TITLE"].front();
oneValueSet.append("TITLE");
} else
d->title = String::null;
d->title.clear();
if(properties.contains("COMMENT")) {
d->comment = properties["COMMENT"].front();
oneValueSet.append("COMMENT");
} else
d->comment = String::null;
d->comment.clear();
if(properties.contains("TRACKERNAME")) {
d->trackerName = properties["TRACKERNAME"].front();
oneValueSet.append("TRACKERNAME");
} else
d->trackerName = String::null;
d->trackerName.clear();
// for each tag that has been set above, remove the first entry in the corresponding
// value list. The others will be returned as unsupported by this format.
for(StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
for(StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
if(properties[*it].size() == 1)
properties.erase(*it);
else

View File

@@ -5,7 +5,7 @@
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 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 *
@@ -15,8 +15,12 @@
* *
* 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 *
* 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_MODTAG_H
@@ -50,39 +54,41 @@ namespace TagLib {
* Returns the track name; if no track name is present in the tag
* String::null will be returned.
*/
String title() const;
virtual String title() const;
/*!
* Not supported by module files. Therefore always returns String::null.
*/
String artist() const;
virtual String artist() const;
/*!
* Not supported by module files. Therefore always returns String::null.
*/
String album() const;
virtual String album() const;
/*!
* Returns the track comment derived from the instrument/sample/pattern
* names; if no comment is present in the tag String::null will be
* returned.
*/
String comment() const;
virtual String comment() const;
/*!
* Not supported by module files. Therefore always returns String::null.
*/
String genre() const;
virtual String genre() const;
/*!
* Not supported by module files. Therefore always returns 0.
*/
uint year() const;
virtual unsigned int year() const;
/*!
* Not supported by module files. Therefore always returns 0.
*/
uint track() const;
virtual unsigned int track() const;
PictureMap pictures() const;
/*!
* Returns the name of the tracker used to create/edit the module file.
@@ -97,21 +103,21 @@ namespace TagLib {
* Sets the title to \a title. If \a title is String::null then this
* value will be cleared.
*
* The length limits per file type are (1 characetr = 1 byte):
* The length limits per file type are (1 character = 1 byte):
* Mod 20 characters, S3M 27 characters, IT 25 characters and XM 20
* characters.
*/
void setTitle(const String &title);
virtual void setTitle(const String &title);
/*!
* Not supported by module files and therefore ignored.
*/
void setArtist(const String &artist);
virtual void setArtist(const String &artist);
/*!
* Not supported by module files and therefore ignored.
*/
void setAlbum(const String &album);
virtual void setAlbum(const String &album);
/*!
* Sets the comment to \a comment. If \a comment is String::null then
@@ -126,26 +132,28 @@ namespace TagLib {
* an thus the line length in comments are limited. Too big comments
* will be truncated.
*
* The line length limits per file type are (1 characetr = 1 byte):
* The line length limits per file type are (1 character = 1 byte):
* Mod 22 characters, S3M 27 characters, IT 25 characters and XM 22
* characters.
*/
void setComment(const String &comment);
virtual void setComment(const String &comment);
/*!
* Not supported by module files and therefore ignored.
*/
void setGenre(const String &genre);
virtual void setGenre(const String &genre);
/*!
* Not supported by module files and therefore ignored.
*/
void setYear(uint year);
virtual void setYear(unsigned int year);
/*!
* Not supported by module files and therefore ignored.
*/
void setTrack(uint track);
virtual void setTrack(unsigned int track);
void setPictures(const PictureMap &l);
/*!
* Sets the tracker name to \a trackerName. If \a trackerName is
@@ -169,7 +177,7 @@ namespace TagLib {
* Implements the unified property interface -- import function.
* Because of the limitations of the module file tag, any tags besides
* COMMENT, TITLE and, if it is an XM file, TRACKERNAME, will be
* returened. Additionally, if the map contains tags with multiple values,
* returned. Additionally, if the map contains tags with multiple values,
* all but the first will be contained in the returned map of unsupported
* properties.
*/

View File

@@ -23,27 +23,26 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#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)
{
children.setAutoDelete(true);
offset = file->tell();
ByteVector header = file->readBlock(8);
if (header.size() != 8) {
if(header.size() != 8) {
// The atom header must be 8 bytes long, otherwise there is either
// trailing garbage or the file is truncated
debug("MP4: Couldn't read 8 bytes of data for atom header");
@@ -52,22 +51,18 @@ MP4::Atom::Atom(File *file)
return;
}
length = header.mid(0, 4).toUInt();
length = header.toUInt32BE(0);
if (length == 1) {
long long longLength = file->readBlock(8).toLongLong();
if (longLength >= 8 && longLength <= 0xFFFFFFFF) {
// The atom has a 64-bit length, but it's actually a 32-bit value
length = (long)longLength;
}
else {
debug("MP4: 64-bit atoms are not supported");
length = 0;
file->seek(0, File::End);
return;
}
if(length == 0) {
// The last atom which extends to the end of the file.
length = file->length() - offset;
}
if (length < 8) {
else if(length == 1) {
// The atom has a 64-bit length.
length = file->readBlock(8).toInt64BE(0);
}
if(length < 8) {
debug("MP4: Invalid atom size");
length = 0;
file->seek(0, File::End);
@@ -87,7 +82,7 @@ MP4::Atom::Atom(File *file)
while(file->tell() < offset + length) {
MP4::Atom *child = new MP4::Atom(file);
children.append(child);
if (child->length == 0)
if(child->length == 0)
return;
}
return;
@@ -99,10 +94,6 @@ MP4::Atom::Atom(File *file)
MP4::Atom::~Atom()
{
for(unsigned int i = 0; i < children.size(); i++) {
delete children[i];
}
children.clear();
}
MP4::Atom *
@@ -111,9 +102,9 @@ MP4::Atom::find(const char *name1, const char *name2, const char *name3, const c
if(name1 == 0) {
return this;
}
for(unsigned int i = 0; i < children.size(); i++) {
if(children[i]->name == name1) {
return children[i]->find(name2, name3, name4);
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if((*it)->name == name1) {
return (*it)->find(name2, name3, name4);
}
}
return 0;
@@ -123,12 +114,12 @@ MP4::AtomList
MP4::Atom::findall(const char *name, bool recursive)
{
MP4::AtomList result;
for(unsigned int i = 0; i < children.size(); i++) {
if(children[i]->name == name) {
result.append(children[i]);
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if((*it)->name == name) {
result.append(*it);
}
if(recursive) {
result.append(children[i]->findall(name, recursive));
result.append((*it)->findall(name, recursive));
}
}
return result;
@@ -141,9 +132,9 @@ MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const
if(name1 == 0) {
return true;
}
for(unsigned int i = 0; i < children.size(); i++) {
if(children[i]->name == name1) {
return children[i]->path(path, name2, name3);
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if((*it)->name == name1) {
return (*it)->path(path, name2, name3);
}
}
return false;
@@ -151,8 +142,10 @@ MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const
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);
@@ -164,18 +157,14 @@ MP4::Atoms::Atoms(File *file)
MP4::Atoms::~Atoms()
{
for(unsigned int i = 0; i < atoms.size(); i++) {
delete atoms[i];
}
atoms.clear();
}
MP4::Atom *
MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4)
{
for(unsigned int i = 0; i < atoms.size(); i++) {
if(atoms[i]->name == name1) {
return atoms[i]->find(name2, name3, name4);
for(AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) {
if((*it)->name == name1) {
return (*it)->find(name2, name3, name4);
}
}
return 0;
@@ -185,9 +174,9 @@ MP4::AtomList
MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4)
{
MP4::AtomList path;
for(unsigned int i = 0; i < atoms.size(); i++) {
if(atoms[i]->name == name1) {
if(!atoms[i]->path(path, name2, name3, name4)) {
for(AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) {
if((*it)->name == name1) {
if(!(*it)->path(path, name2, name3, name4)) {
path.clear();
}
return path;
@@ -195,4 +184,3 @@ MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const
}
return path;
}

View File

@@ -59,7 +59,7 @@ namespace TagLib {
TypeDateTime = 17, // in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits
TypeGenred = 18, // a list of enumerated values
TypeInteger = 21, // a signed big-endian integer with length one of { 1,2,3,4,8 } bytes
TypeRIAAPA = 24, // RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit ingteger
TypeRIAAPA = 24, // RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit integer
TypeUPC = 25, // Universal Product Code, in text UTF-8 format (valid as an ID)
TypeBMP = 27, // Windows bitmap image
TypeUndefined = 255 // undefined
@@ -77,29 +77,29 @@ namespace TagLib {
class Atom
{
public:
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;
TagLib::ByteVector name;
AtomList children;
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 long offset;
long long length;
TagLib::ByteVector name;
AtomList children;
private:
static const int numContainers = 11;
static const char *containers[11];
static const int numContainers = 11;
static const char *containers[11];
};
//! Root-level atoms
class Atoms
{
public:
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);
AtomList atoms;
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);
AtomList atoms;
};
}

View File

@@ -23,64 +23,77 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <taglib.h>
#include <tdebug.h>
#include "taglib.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "mp4coverart.h"
using namespace TagLib;
class MP4::CoverArt::CoverArtPrivate : public RefCounter
namespace
{
public:
CoverArtPrivate() : RefCounter(), format(MP4::CoverArt::JPEG) {}
Format format;
ByteVector data;
};
MP4::CoverArt::CoverArt(Format format, const ByteVector &data)
{
d = new CoverArtPrivate;
d->format = format;
d->data = data;
struct CoverArtData
{
MP4::CoverArt::Format format;
ByteVector data;
};
}
MP4::CoverArt::CoverArt(const CoverArt &item) : d(item.d)
class MP4::CoverArt::CoverArtPrivate
{
public:
CoverArtPrivate(Format f, const ByteVector &v) :
data(new CoverArtData())
{
data->format = f;
data->data = v;
}
SHARED_PTR<CoverArtData> data;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
MP4::CoverArt::CoverArt(Format format, const ByteVector &data) :
d(new CoverArtPrivate(format, data))
{
}
MP4::CoverArt::CoverArt(const CoverArt &item) :
d(new CoverArtPrivate(*item.d))
{
d->ref();
}
MP4::CoverArt &
MP4::CoverArt::operator=(const CoverArt &item)
{
if(d->deref()) {
delete d;
}
d = item.d;
d->ref();
CoverArt(item).swap(*this);
return *this;
}
void
MP4::CoverArt::swap(CoverArt &item)
{
using std::swap;
swap(d, item.d);
}
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;
}

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