Compare commits

...

9 Commits

Author SHA1 Message Date
Jamie
3ccc390155
Add file_new and file_new_type wchar variants for C binding (#1271) 2025-05-16 17:01:23 +02:00
Urs Fleisch
fbbead3efd
Support custom temp and tests directories (#1268) (#1270)
The following user-settable values for CMake are supported:

- TESTS_DIR: Tests directory, is path to unit test data when 'data' is
  appended. Can be used to run the unit tests on a target.
- TESTS_TMPDIR: Directory for temporary files created during unit tests,
  system tmpdir is used if undefined. Has to be defined on systems
  without global temporary directory.
2025-05-01 19:55:46 +02:00
Urs Fleisch
ee1931b811
Compile time configuration of supported formats (#1262)
CMake options WITH_APE, WITH_ASF, WITH_DSF, WITH_MOD, WITH_MP4,
WITH_RIFF, WITH_SHORTEN, WITH_TRUEAUDIO, WITH_VORBIS, by default,
they are all ON.
2025-02-02 12:24:26 +01:00
Stephen Booth
648f5e5882
Add Shorten (SHN) support (#1257)
* Add Shorten (SHN) support

* Add `<cmath>` include and use `std::log2`

* Use `uintptr_t` for buffer size calculations

* Work around `byteSwap` not using fixed width types

* Remove four-character codes

* Attempt to fix `static_assert`

* Revert previous commit

* Update `read_uint`* functions

* Use ByteVector for byte swaps

* Use different ByteVector ctor

* Rework variable-length input to use ByteVector

* Rename some variables

* Naming and formatting cleanup

* Add basic Shorten tests

* Rename a constant

* Rename `internalFileType` to `fileType`

* Add documentation on `fileType` meaning

* Add DO_NOT_DOCUMENT guard

* Fix shadowVariable issues reported by cppcheck

cppcheck --enable=all --inline-suppr \
  --suppress=noExplicitConstructor --suppress=unusedFunction \
  --suppress=missingIncludeSystem --project=compile_commands.json

* Formatting cleanup

* More explicit types

Reason for these changes: getRiceGolombCode(k, uInt32CodeSize) was
called with int k for uint32_t& argument.
There was also a warning from MSVC for line 299:
warning C4267: 'argument': conversion from 'size_t' to 'int'

* Additional explicit types

* Rename `SHN` namespace to `Shorten`

Also rename files to match

---------

Co-authored-by: Urs Fleisch <ufleisch@users.sourceforge.net>
2024-12-30 07:23:11 -06:00
Stephen Booth
c1c60ebeea
Use fixed width types (#1258)
Use fixed width types in `byteSwap` functions
2024-12-22 07:02:05 -06:00
Urs Fleisch
3bc0ea0ecb
Preserve unicode encoding when downgrading to ID3v2.3 (#1259) (#1260) 2024-12-22 12:07:25 +01:00
Christian Schmitz
225c73e181
Fixed warning about shadowing variable (#1254)
You can't name parameter and structure field the same as complier frequently complain about this.
2024-11-22 06:55:34 +01:00
Urs Fleisch
90f62a3c94
Do not store too large FLAC metadata blocks (#1249) (#1250)
The size of FLAC metadata blocks is stored in only 24 bits. Remove
blocks exceeding this limit when saving FLAC and Ogg FLAC files.
2024-11-14 17:43:18 +01:00
Urs Fleisch
5b6f9ef848
Fix segfaults with String and ByteVector nullptr arguments (#1247) (#1248) 2024-11-02 06:39:21 +01:00
41 changed files with 2796 additions and 548 deletions

View File

@ -48,7 +48,10 @@ set(TAGLIB_INSTALL_SUFFIX "" CACHE STRING
"Suffix added to installed files (include directory, libraries, .pc)")
add_definitions(-DHAVE_CONFIG_H)
set(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
set(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/" CACHE STRING
"Tests directory, is path to unit test data when 'data' is appended")
set(TESTS_TMPDIR "" CACHE STRING
"Directory for temporary files created during unit tests, system tmpdir is used if undefined")
if(CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
@ -97,6 +100,16 @@ set(TAGLIB_SOVERSION_PATCH 2)
include(ConfigureChecks.cmake)
option(WITH_APE "Build with APE, MPC, WavPack" ON)
option(WITH_ASF "Build with ASF" ON)
option(WITH_DSF "Build with DSF" ON)
option(WITH_MOD "Build with Tracker modules" ON)
option(WITH_MP4 "Build with MP4" ON)
option(WITH_RIFF "Build with AIFF, RIFF, WAV" ON)
option(WITH_SHORTEN "Build with Shorten" ON)
option(WITH_TRUEAUDIO "Build with TrueAudio" ON)
option(WITH_VORBIS "Build with Vorbis, FLAC, Ogg, Opus" ON)
# Determine whether zlib is installed.
option(WITH_ZLIB "Build with ZLIB" ON)
@ -178,6 +191,36 @@ else()
endif()
endif()
if(WITH_APE)
set(TAGLIB_WITH_APE TRUE)
endif()
if(WITH_ASF)
set(TAGLIB_WITH_ASF TRUE)
endif()
if(WITH_DSF)
set(TAGLIB_WITH_DSF TRUE)
endif()
if(WITH_MOD)
set(TAGLIB_WITH_MOD TRUE)
endif()
if(WITH_MP4)
set(TAGLIB_WITH_MP4 TRUE)
endif()
if(WITH_RIFF)
set(TAGLIB_WITH_RIFF TRUE)
endif()
if(WITH_SHORTEN)
set(TAGLIB_WITH_SHORTEN TRUE)
endif()
if(WITH_TRUEAUDIO)
set(TAGLIB_WITH_TRUEAUDIO TRUE)
endif()
if(WITH_VORBIS)
set(TAGLIB_WITH_VORBIS TRUE)
endif()
configure_file(taglib/taglib_config.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/taglib_config.h")
add_subdirectory(taglib)
if(BUILD_BINDINGS)

View File

@ -42,6 +42,9 @@ CMakeLists.txt file.
| `TAGLIB_INSTALL_SUFFIX` | Suffix added to installed libraries, includes, ... |
| `ENABLE_STATIC_RUNTIME` | Link with MSVC runtime statically |
| `BUILD_FRAMEWORK` | Build a macOS framework |
| `TESTS_DIR` | Where to find unit test data (with data appended) |
| `TESTS_TMPDIR` | Where to create temporary files in unit tests |
If you want to install TagLib 2 alongside TagLib 1, you can use
`-DTAGLIB_INSTALL_SUFFIX=-2` and make sure that `BUILD_EXAMPLES` is not `ON`
@ -49,6 +52,30 @@ for both versions. The installed files will then include bin/taglib-2-config,
include/taglib-2, cmake/taglib-2, pkgconfig/taglib-2.pc,
pkgconfig/taglib_c-2.pc and the libraries have a suffix "-2".
### Compile Time Configuration of Supported Formats
To reduce the size of the library, it is possible to switch off supported file
formats. By default, all formats are enabled. Support for MPEG files (MP3, AAC)
and ID3 tags cannot be disabled. The following CMake options are available:
| Option | Description |
|-------------------------|----------------------------------------------------|
| `WITH_APE` | Build with APE, MPC, WavPack (default ON) |
| `WITH_ASF` | Build with ASF (default ON) |
| `WITH_DSF` | Build with DSF (default ON) |
| `WITH_MOD` | Build with Tracker modules (default ON) |
| `WITH_MP4` | Build with MP4 (default ON) |
| `WITH_RIFF` | Build with AIFF, RIFF, WAV (default ON) |
| `WITH_SHORTEN` | Build with Shorten (default ON) |
| `WITH_TRUEAUDIO` | Build with TrueAudio (default ON) |
| `WITH_VORBIS` | Build with Vorbis, FLAC, Ogg, Opus (default ON) |
Note that disabling formats will remove exported symbols from the library and
thus break binary compatibility. These options should therefore only be used
if the library is built specifically for a certain project. The public header
files still contain the full API, if you use TagLib with a reduced set of
formats, you can include taglib_config.h and use its definitions (prefixed with
`TAGLIB_`, e.g. `TAGLIB_WITH_APE`), as it is done in examples/framelist.cpp.
## Dependencies
@ -438,3 +465,54 @@ cmake --build build_mingw --config Release
PATH=$PATH:$TAGLIB_PREFIX/bin
build_mingw/tagreader /path/to/audio-file
```
## Android
### Using vcpkg
The bash script below can be used to build TagLib for Android using vcpkg.
It must be started in the parent folder of the taglib source folder and will
build in a folder _android_build_ and install into _android_pkg_.
The package and the unit tests are then transferred to an Android device
and the unit tests are run on the device.
Note that `TESTS_TMPDIR` is set because there is no system-wide temporary folder
on Android. `TESTS_DIR` is set to run the tests on the target.
```
# You may have to adapt the NDK and vcpkg paths and the ABI/triplet.
export ANDROID_NDK_HOME=$HOME/Development/android-sdk/ndk/23.1.7779620
export VCPKG_ROOT=$HOME/Development/vcpkg
PATH=$PATH:$VCPKG_ROOT
# armeabi-v7a/arm-android or arm64-v8a/arm64-android or x86/x86-android or x86_64/x64-android
android_abi=armeabi-v7a
vcpkg_target_triplet=arm-android
vcpkg_toolchain_file=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
android_toolchain_file=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake
vcpkg install --triplet $vcpkg_target_triplet utfcpp zlib cppunit
cmake -B android_build -S taglib \
-DCMAKE_TOOLCHAIN_FILE=$vcpkg_toolchain_file \
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=$android_toolchain_file \
-DVCPKG_TARGET_TRIPLET=$vcpkg_target_triplet \
-DANDROID_ABI=$android_abi \
-GNinja -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release \
-DVISIBILITY_HIDDEN=ON -DENABLE_CCACHE=ON -DBUILD_EXAMPLES=ON -DBUILD_TESTING=ON \
-DTESTS_DIR=/data/local/tmp/tests/ -DTESTS_TMPDIR=/data/local/tmp
cmake --build android_build --config Release
cmake --install android_build --config Release --prefix android_pkg --strip
cp -a android_build/tests/test_runner android_pkg/bin/
if hash adb 2>/dev/null; then
adb push android_pkg /data/local/tmp/
adb push android_build/tests/test_runner /data/local/tmp/tests/test_runner
adb push taglib/tests/data /data/local/tmp/tests/
adb shell "env LD_LIBRARY_PATH=/data/local/tmp/android_pkg/lib /data/local/tmp/tests/test_runner"
# You could also try an example binary:
# adb shell "env LD_LIBRARY_PATH=/data/local/tmp/android_pkg/lib /data/local/tmp/android_pkg/bin/tagreader '/sdcard/Music/Some Album/A Track.mp3'"
fi
```

View File

@ -1,31 +1,69 @@
include_directories(
set(tag_c_HDR_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/toolkit
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/asf
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpeg
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/vorbis
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/flac
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/flac
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpc
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mp4
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpeg/id3v2
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpeg/id3v2/frames
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/wavpack
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/speex
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/trueaudio
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff/aiff
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff/wav
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ape
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/it
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mod
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/s3m
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/xm
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/opus
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/dsf
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/dsdiff
)
if(WITH_ASF)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/asf
)
endif()
if(WITH_VORBIS)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/vorbis
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/flac
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/flac
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/speex
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/opus
)
endif()
if(WITH_APE)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpc
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/wavpack
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ape
)
endif()
if(WITH_MP4)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mp4
)
endif()
if(WITH_TRUEAUDIO)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/trueaudio
)
endif()
if(WITH_RIFF)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff/aiff
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff/wav
)
endif()
if(WITH_MOD)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/it
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mod
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/s3m
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/xm
)
endif()
if(WITH_DSF)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/dsf
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/dsdiff
)
endif()
if(WITH_SHORTEN)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/shorten
)
endif()
include_directories(${tag_c_HDR_DIRS})
set(tag_c_HDRS tag_c.h)

View File

@ -29,34 +29,57 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "taglib_config.h"
#include "tstringlist.h"
#include "tbytevectorstream.h"
#include "tiostream.h"
#include "tfile.h"
#include "tpropertymap.h"
#include "fileref.h"
#include "asffile.h"
#include "vorbisfile.h"
#include "mpegfile.h"
#include "tag.h"
#include "id3v2framefactory.h"
#ifdef TAGLIB_WITH_ASF
#include "asffile.h"
#endif
#ifdef TAGLIB_WITH_VORBIS
#include "vorbisfile.h"
#include "flacfile.h"
#include "oggflacfile.h"
#include "speexfile.h"
#include "opusfile.h"
#endif
#ifdef TAGLIB_WITH_APE
#include "mpcfile.h"
#include "wavpackfile.h"
#include "speexfile.h"
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
#include "trueaudiofile.h"
#endif
#ifdef TAGLIB_WITH_MP4
#include "mp4file.h"
#endif
#ifdef TAGLIB_WITH_RIFF
#include "aifffile.h"
#include "wavfile.h"
#endif
#ifdef TAGLIB_WITH_APE
#include "apefile.h"
#endif
#ifdef TAGLIB_WITH_MOD
#include "itfile.h"
#include "modfile.h"
#include "s3mfile.h"
#include "xmfile.h"
#include "opusfile.h"
#endif
#ifdef TAGLIB_WITH_DSF
#include "dsffile.h"
#include "dsdifffile.h"
#include "tag.h"
#include "id3v2framefactory.h"
#endif
#ifdef TAGLIB_WITH_SHORTEN
#include "shortenfile.h"
#endif
using namespace TagLib;
@ -126,49 +149,73 @@ TagLib_File *taglib_file_new(const char *filename)
return reinterpret_cast<TagLib_File *>(new FileRef(filename));
}
TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
#ifdef _WIN32
TagLib_File *taglib_file_new_wchar(const wchar_t *filename)
{
return reinterpret_cast<TagLib_File *>(new FileRef(filename));
}
#endif
template<typename T>
TagLib_File *taglib_file_new_type_any_char(const T *filename, TagLib_File_Type type)
{
File *file = NULL;
switch(type) {
case TagLib_File_MPEG:
file = new MPEG::File(filename);
break;
#ifdef TAGLIB_WITH_VORBIS
case TagLib_File_OggVorbis:
file = new Ogg::Vorbis::File(filename);
break;
case TagLib_File_FLAC:
file = new FLAC::File(filename);
break;
case TagLib_File_MPC:
file = new MPC::File(filename);
break;
case TagLib_File_OggFlac:
file = new Ogg::FLAC::File(filename);
break;
case TagLib_File_WavPack:
file = new WavPack::File(filename);
break;
case TagLib_File_Speex:
file = new Ogg::Speex::File(filename);
break;
case TagLib_File_Opus:
file = new Ogg::Opus::File(filename);
break;
#endif
#ifdef TAGLIB_WITH_APE
case TagLib_File_MPC:
file = new MPC::File(filename);
break;
case TagLib_File_WavPack:
file = new WavPack::File(filename);
break;
case TagLib_File_APE:
file = new APE::File(filename);
break;
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
case TagLib_File_TrueAudio:
file = new TrueAudio::File(filename);
break;
#endif
#ifdef TAGLIB_WITH_MP4
case TagLib_File_MP4:
file = new MP4::File(filename);
break;
#endif
#ifdef TAGLIB_WITH_ASF
case TagLib_File_ASF:
file = new ASF::File(filename);
break;
#endif
#ifdef TAGLIB_WITH_RIFF
case TagLib_File_AIFF:
file = new RIFF::AIFF::File(filename);
break;
case TagLib_File_WAV:
file = new RIFF::WAV::File(filename);
break;
case TagLib_File_APE:
file = new APE::File(filename);
break;
#endif
#ifdef TAGLIB_WITH_MOD
case TagLib_File_IT:
file = new IT::File(filename);
break;
@ -181,21 +228,38 @@ TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
case TagLib_File_XM:
file = new XM::File(filename);
break;
case TagLib_File_Opus:
file = new Ogg::Opus::File(filename);
break;
#endif
#ifdef TAGLIB_WITH_DSF
case TagLib_File_DSF:
file = new DSF::File(filename);
break;
case TagLib_File_DSDIFF:
file = new DSDIFF::File(filename);
break;
#endif
#ifdef TAGLIB_WITH_SHORTEN
case TagLib_File_SHORTEN:
file = new Shorten::File(filename);
break;
#endif
default:
break;
}
return file ? reinterpret_cast<TagLib_File *>(new FileRef(file)) : NULL;
}
TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
{
return taglib_file_new_type_any_char(filename, type);
}
#ifdef _WIN32
TagLib_File *taglib_file_new_type_wchar(const wchar_t *filename, TagLib_File_Type type)
{
return taglib_file_new_type_any_char(filename, type);
}
#endif
TagLib_File *taglib_file_new_iostream(TagLib_IOStream *stream)
{
return reinterpret_cast<TagLib_File *>(

View File

@ -130,7 +130,8 @@ typedef enum {
TagLib_File_XM,
TagLib_File_Opus,
TagLib_File_DSF,
TagLib_File_DSDIFF
TagLib_File_DSDIFF,
TagLib_File_SHORTEN
} TagLib_File_Type;
/*!
@ -141,12 +142,18 @@ typedef enum {
* be opened.
*/
TAGLIB_C_EXPORT TagLib_File *taglib_file_new(const char *filename);
#ifdef _WIN32
TAGLIB_C_EXPORT TagLib_File *taglib_file_new_wchar(const wchar_t *filename);
#endif
/*!
* Creates a TagLib file based on \a filename. Rather than attempting to guess
* the type, it will use the one specified by \a type.
*/
TAGLIB_C_EXPORT TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type);
#ifdef _WIN32
TAGLIB_C_EXPORT TagLib_File *taglib_file_new_type_wchar(const wchar_t *filename, TagLib_File_Type type);
#endif
/*!
* Creates a TagLib file from a \a stream.

View File

@ -20,5 +20,6 @@
#cmakedefine TRACE_IN_RELEASE 1
#cmakedefine TESTS_DIR "@TESTS_DIR@"
#cmakedefine TESTS_TMPDIR "@TESTS_TMPDIR@"
#endif

View File

@ -25,6 +25,7 @@
#include <iostream>
#include <cstdlib>
#include "taglib_config.h"
#include "tbytevector.h"
#include "mpegfile.h"
#include "id3v2tag.h"
@ -32,7 +33,9 @@
#include "id3v2header.h"
#include "commentsframe.h"
#include "id3v1tag.h"
#ifdef TAGLIB_WITH_APE
#include "apetag.h"
#endif
using namespace TagLib;
@ -90,6 +93,7 @@ int main(int argc, char *argv[])
else
std::cout << "file does not have a valid id3v1 tag" << std::endl;
#ifdef TAGLIB_WITH_APE
APE::Tag *ape = f.APETag();
std::cout << std::endl << "APE" << std::endl;
@ -106,6 +110,7 @@ int main(int argc, char *argv[])
}
else
std::cout << "file does not have a valid APE tag" << std::endl;
#endif
std::cout << std::endl;
}

View File

@ -1,38 +1,77 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories(
set(tag_HDR_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/toolkit
${CMAKE_CURRENT_SOURCE_DIR}/asf
${CMAKE_CURRENT_SOURCE_DIR}/mpeg
${CMAKE_CURRENT_SOURCE_DIR}/ogg
${CMAKE_CURRENT_SOURCE_DIR}/ogg/flac
${CMAKE_CURRENT_SOURCE_DIR}/flac
${CMAKE_CURRENT_SOURCE_DIR}/mpc
${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
${CMAKE_CURRENT_SOURCE_DIR}/ape
${CMAKE_CURRENT_SOURCE_DIR}/wavpack
${CMAKE_CURRENT_SOURCE_DIR}/trueaudio
${CMAKE_CURRENT_SOURCE_DIR}/riff
${CMAKE_CURRENT_SOURCE_DIR}/riff/aiff
${CMAKE_CURRENT_SOURCE_DIR}/riff/wav
${CMAKE_CURRENT_SOURCE_DIR}/mod
${CMAKE_CURRENT_SOURCE_DIR}/s3m
${CMAKE_CURRENT_SOURCE_DIR}/it
${CMAKE_CURRENT_SOURCE_DIR}/xm
${CMAKE_CURRENT_SOURCE_DIR}/dsf
${CMAKE_CURRENT_SOURCE_DIR}/dsdiff
)
if(WITH_ASF)
set(tag_HDR_DIRS ${tag_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/asf
)
endif()
if(WITH_VORBIS)
set(tag_HDR_DIRS ${tag_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/ogg
${CMAKE_CURRENT_SOURCE_DIR}/ogg/flac
${CMAKE_CURRENT_SOURCE_DIR}/flac
${CMAKE_CURRENT_SOURCE_DIR}/ogg/vorbis
${CMAKE_CURRENT_SOURCE_DIR}/ogg/speex
${CMAKE_CURRENT_SOURCE_DIR}/ogg/opus
)
endif()
if(WITH_APE)
set(tag_HDR_DIRS ${tag_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/mpc
${CMAKE_CURRENT_SOURCE_DIR}/ape
${CMAKE_CURRENT_SOURCE_DIR}/wavpack
)
endif()
if(WITH_MP4)
set(tag_HDR_DIRS ${tag_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/mp4
)
endif()
if(WITH_TRUEAUDIO)
set(tag_HDR_DIRS ${tag_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/trueaudio
)
endif()
if(WITH_RIFF)
set(tag_HDR_DIRS ${tag_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/riff
${CMAKE_CURRENT_SOURCE_DIR}/riff/aiff
${CMAKE_CURRENT_SOURCE_DIR}/riff/wav
)
endif()
if(WITH_MOD)
set(tag_HDR_DIRS ${tag_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/mod
${CMAKE_CURRENT_SOURCE_DIR}/s3m
${CMAKE_CURRENT_SOURCE_DIR}/it
${CMAKE_CURRENT_SOURCE_DIR}/xm
)
endif()
if(WITH_DSF)
set(tag_HDR_DIRS ${tag_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/dsf
${CMAKE_CURRENT_SOURCE_DIR}/dsdiff
)
endif()
if(WITH_SHORTEN)
set(tag_HDR_DIRS ${tag_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/shorten
)
endif()
include_directories(${tag_HDR_DIRS})
set(tag_HDRS
tag.h
fileref.h
audioproperties.h
taglib_export.h
${CMAKE_CURRENT_BINARY_DIR}/../taglib_config.h
toolkit/taglib.h
toolkit/tstring.h
toolkit/tlist.h
@ -82,66 +121,105 @@ set(tag_HDRS
mpeg/id3v2/frames/chapterframe.h
mpeg/id3v2/frames/tableofcontentsframe.h
mpeg/id3v2/frames/podcastframe.h
ogg/oggfile.h
ogg/oggpage.h
ogg/oggpageheader.h
ogg/xiphcomment.h
ogg/vorbis/vorbisfile.h
ogg/vorbis/vorbisproperties.h
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
flac/flacmetadatablock.h
ape/apefile.h
ape/apeproperties.h
ape/apetag.h
ape/apefooter.h
ape/apeitem.h
mpc/mpcfile.h
mpc/mpcproperties.h
wavpack/wavpackfile.h
wavpack/wavpackproperties.h
trueaudio/trueaudiofile.h
trueaudio/trueaudioproperties.h
riff/rifffile.h
riff/aiff/aifffile.h
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
asf/asfattribute.h
asf/asfpicture.h
mp4/mp4file.h
mp4/mp4atom.h
mp4/mp4tag.h
mp4/mp4item.h
mp4/mp4properties.h
mp4/mp4coverart.h
mp4/mp4itemfactory.h
mod/modfilebase.h
mod/modfile.h
mod/modtag.h
mod/modproperties.h
it/itfile.h
it/itproperties.h
s3m/s3mfile.h
s3m/s3mproperties.h
xm/xmfile.h
xm/xmproperties.h
dsf/dsffile.h
dsf/dsfproperties.h
dsdiff/dsdifffile.h
dsdiff/dsdiffproperties.h
dsdiff/dsdiffdiintag.h
)
if(WITH_VORBIS)
set(tag_HDRS ${tag_HDRS}
ogg/oggfile.h
ogg/oggpage.h
ogg/oggpageheader.h
ogg/xiphcomment.h
ogg/vorbis/vorbisfile.h
ogg/vorbis/vorbisproperties.h
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
flac/flacmetadatablock.h
)
endif()
if(WITH_APE)
set(tag_HDRS ${tag_HDRS}
ape/apefile.h
ape/apeproperties.h
ape/apetag.h
ape/apefooter.h
ape/apeitem.h
mpc/mpcfile.h
mpc/mpcproperties.h
wavpack/wavpackfile.h
wavpack/wavpackproperties.h
)
endif()
if(WITH_TRUEAUDIO)
set(tag_HDRS ${tag_HDRS}
trueaudio/trueaudiofile.h
trueaudio/trueaudioproperties.h
)
endif()
if(WITH_RIFF)
set(tag_HDRS ${tag_HDRS}
riff/rifffile.h
riff/aiff/aifffile.h
riff/aiff/aiffproperties.h
riff/wav/wavfile.h
riff/wav/wavproperties.h
riff/wav/infotag.h
)
endif()
if(WITH_ASF)
set(tag_HDRS ${tag_HDRS}
asf/asffile.h
asf/asfproperties.h
asf/asftag.h
asf/asfattribute.h
asf/asfpicture.h
)
endif()
if(WITH_MP4)
set(tag_HDRS ${tag_HDRS}
mp4/mp4file.h
mp4/mp4atom.h
mp4/mp4tag.h
mp4/mp4item.h
mp4/mp4properties.h
mp4/mp4coverart.h
mp4/mp4itemfactory.h
)
endif()
if(WITH_MOD)
set(tag_HDRS ${tag_HDRS}
mod/modfilebase.h
mod/modfile.h
mod/modtag.h
mod/modproperties.h
it/itfile.h
it/itproperties.h
s3m/s3mfile.h
s3m/s3mproperties.h
xm/xmfile.h
xm/xmproperties.h
)
endif()
if(WITH_DSF)
set(tag_HDRS ${tag_HDRS}
dsf/dsffile.h
dsf/dsfproperties.h
dsdiff/dsdifffile.h
dsdiff/dsdiffproperties.h
dsdiff/dsdiffdiintag.h
)
endif()
if(WITH_SHORTEN)
set(tag_HDRS ${tag_HDRS}
shorten/shortenfile.h
shorten/shortenproperties.h
shorten/shortentag.h
)
endif()
set(mpeg_SRCS
mpeg/mpegfile.cpp
@ -185,128 +263,152 @@ set(frames_SRCS
mpeg/id3v2/frames/podcastframe.cpp
)
set(ogg_SRCS
ogg/oggfile.cpp
ogg/oggpage.cpp
ogg/oggpageheader.cpp
ogg/xiphcomment.cpp
)
if(WITH_VORBIS)
set(ogg_SRCS
ogg/oggfile.cpp
ogg/oggpage.cpp
ogg/oggpageheader.cpp
ogg/xiphcomment.cpp
)
set(vorbis_SRCS
ogg/vorbis/vorbisfile.cpp
ogg/vorbis/vorbisproperties.cpp
)
set(vorbis_SRCS
ogg/vorbis/vorbisfile.cpp
ogg/vorbis/vorbisproperties.cpp
)
set(flacs_SRCS
flac/flacfile.cpp
flac/flacpicture.cpp
flac/flacproperties.cpp
flac/flacmetadatablock.cpp
flac/flacunknownmetadatablock.cpp
)
set(flacs_SRCS
flac/flacfile.cpp
flac/flacpicture.cpp
flac/flacproperties.cpp
flac/flacmetadatablock.cpp
flac/flacunknownmetadatablock.cpp
)
set(oggflacs_SRCS
ogg/flac/oggflacfile.cpp
)
set(oggflacs_SRCS
ogg/flac/oggflacfile.cpp
)
set(mpc_SRCS
mpc/mpcfile.cpp
mpc/mpcproperties.cpp
)
set(speex_SRCS
ogg/speex/speexfile.cpp
ogg/speex/speexproperties.cpp
)
set(mp4_SRCS
mp4/mp4file.cpp
mp4/mp4atom.cpp
mp4/mp4tag.cpp
mp4/mp4item.cpp
mp4/mp4properties.cpp
mp4/mp4coverart.cpp
mp4/mp4itemfactory.cpp
)
set(opus_SRCS
ogg/opus/opusfile.cpp
ogg/opus/opusproperties.cpp
)
endif()
set(ape_SRCS
ape/apetag.cpp
ape/apefooter.cpp
ape/apeitem.cpp
ape/apefile.cpp
ape/apeproperties.cpp
)
if(WITH_APE)
set(mpc_SRCS
mpc/mpcfile.cpp
mpc/mpcproperties.cpp
)
set(wavpack_SRCS
wavpack/wavpackfile.cpp
wavpack/wavpackproperties.cpp
)
set(ape_SRCS
ape/apetag.cpp
ape/apefooter.cpp
ape/apeitem.cpp
ape/apefile.cpp
ape/apeproperties.cpp
)
set(speex_SRCS
ogg/speex/speexfile.cpp
ogg/speex/speexproperties.cpp
)
set(wavpack_SRCS
wavpack/wavpackfile.cpp
wavpack/wavpackproperties.cpp
)
endif()
set(opus_SRCS
ogg/opus/opusfile.cpp
ogg/opus/opusproperties.cpp
)
if(WITH_MP4)
set(mp4_SRCS
mp4/mp4file.cpp
mp4/mp4atom.cpp
mp4/mp4tag.cpp
mp4/mp4item.cpp
mp4/mp4properties.cpp
mp4/mp4coverart.cpp
mp4/mp4itemfactory.cpp
)
endif()
set(trueaudio_SRCS
trueaudio/trueaudiofile.cpp
trueaudio/trueaudioproperties.cpp
)
if(WITH_TRUEAUDIO)
set(trueaudio_SRCS
trueaudio/trueaudiofile.cpp
trueaudio/trueaudioproperties.cpp
)
endif()
set(asf_SRCS
asf/asftag.cpp
asf/asffile.cpp
asf/asfproperties.cpp
asf/asfattribute.cpp
asf/asfpicture.cpp
)
if(WITH_ASF)
set(asf_SRCS
asf/asftag.cpp
asf/asffile.cpp
asf/asfproperties.cpp
asf/asfattribute.cpp
asf/asfpicture.cpp
)
endif()
set(riff_SRCS
riff/rifffile.cpp
)
if(WITH_RIFF)
set(riff_SRCS
riff/rifffile.cpp
)
set(aiff_SRCS
riff/aiff/aifffile.cpp
riff/aiff/aiffproperties.cpp
)
set(aiff_SRCS
riff/aiff/aifffile.cpp
riff/aiff/aiffproperties.cpp
)
set(wav_SRCS
riff/wav/wavfile.cpp
riff/wav/wavproperties.cpp
riff/wav/infotag.cpp
)
set(wav_SRCS
riff/wav/wavfile.cpp
riff/wav/wavproperties.cpp
riff/wav/infotag.cpp
)
endif()
set(mod_SRCS
mod/modfilebase.cpp
mod/modfile.cpp
mod/modtag.cpp
mod/modproperties.cpp
)
if(WITH_MOD)
set(mod_SRCS
mod/modfilebase.cpp
mod/modfile.cpp
mod/modtag.cpp
mod/modproperties.cpp
)
set(s3m_SRCS
s3m/s3mfile.cpp
s3m/s3mproperties.cpp
)
set(s3m_SRCS
s3m/s3mfile.cpp
s3m/s3mproperties.cpp
)
set(it_SRCS
it/itfile.cpp
it/itproperties.cpp
)
set(it_SRCS
it/itfile.cpp
it/itproperties.cpp
)
set(xm_SRCS
xm/xmfile.cpp
xm/xmproperties.cpp
)
set(xm_SRCS
xm/xmfile.cpp
xm/xmproperties.cpp
)
endif()
set(dsf_SRCS
dsf/dsffile.cpp
dsf/dsfproperties.cpp
)
if(WITH_DSF)
set(dsf_SRCS
dsf/dsffile.cpp
dsf/dsfproperties.cpp
)
set(dsdiff_SRCS
dsdiff/dsdifffile.cpp
dsdiff/dsdiffproperties.cpp
dsdiff/dsdiffdiintag.cpp
)
set(dsdiff_SRCS
dsdiff/dsdifffile.cpp
dsdiff/dsdiffproperties.cpp
dsdiff/dsdiffdiintag.cpp
)
endif()
if(WITH_SHORTEN)
set(shorten_SRCS
shorten/shortenfile.cpp
shorten/shortenproperties.cpp
shorten/shortentag.cpp
)
endif()
set(toolkit_SRCS
toolkit/tstring.cpp
@ -331,7 +433,7 @@ set(tag_LIB_SRCS
${vorbis_SRCS} ${oggflacs_SRCS} ${mpc_SRCS} ${ape_SRCS} ${toolkit_SRCS} ${flacs_SRCS}
${wavpack_SRCS} ${speex_SRCS} ${trueaudio_SRCS} ${riff_SRCS} ${aiff_SRCS} ${wav_SRCS}
${asf_SRCS} ${mp4_SRCS} ${mod_SRCS} ${s3m_SRCS} ${it_SRCS} ${xm_SRCS} ${opus_SRCS}
${dsf_SRCS} ${dsdiff_SRCS}
${dsf_SRCS} ${dsdiff_SRCS} ${shorten_SRCS}
tag.cpp
tagunion.cpp
fileref.cpp

View File

@ -26,7 +26,7 @@
#ifndef TAGLIB_DSDIFFFILE_H
#define TAGLIB_DSDIFFFILE_H
#include "rifffile.h"
#include "tfile.h"
#include "id3v2tag.h"
#include "dsdiffproperties.h"
#include "dsdiffdiintag.h"

View File

@ -32,31 +32,51 @@
#include <cstring>
#include <utility>
#include "taglib_config.h"
#include "tfilestream.h"
#include "tpropertymap.h"
#include "tstringlist.h"
#include "tvariant.h"
#include "tdebug.h"
#include "aifffile.h"
#include "apefile.h"
#include "asffile.h"
#include "flacfile.h"
#include "itfile.h"
#include "modfile.h"
#include "mp4file.h"
#include "mpcfile.h"
#include "mpegfile.h"
#ifdef TAGLIB_WITH_RIFF
#include "aifffile.h"
#include "wavfile.h"
#endif
#ifdef TAGLIB_WITH_APE
#include "apefile.h"
#include "mpcfile.h"
#include "wavpackfile.h"
#endif
#ifdef TAGLIB_WITH_ASF
#include "asffile.h"
#endif
#ifdef TAGLIB_WITH_VORBIS
#include "flacfile.h"
#include "speexfile.h"
#include "vorbisfile.h"
#include "oggflacfile.h"
#include "opusfile.h"
#include "s3mfile.h"
#include "speexfile.h"
#include "trueaudiofile.h"
#include "vorbisfile.h"
#include "wavfile.h"
#include "wavpackfile.h"
#endif
#ifdef TAGLIB_WITH_MOD
#include "itfile.h"
#include "modfile.h"
#include "xmfile.h"
#include "s3mfile.h"
#endif
#ifdef TAGLIB_WITH_MP4
#include "mp4file.h"
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
#include "trueaudiofile.h"
#endif
#ifdef TAGLIB_WITH_DSF
#include "dsffile.h"
#include "dsdifffile.h"
#endif
#ifdef TAGLIB_WITH_SHORTEN
#include "shortenfile.h"
#endif
using namespace TagLib;
@ -135,6 +155,7 @@ namespace
if(ext == "MP3" || ext == "MP2" || ext == "AAC")
file = new MPEG::File(stream, readAudioProperties, audioPropertiesStyle);
#ifdef TAGLIB_WITH_VORBIS
else if(ext == "OGG")
file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "OGA") {
@ -147,26 +168,38 @@ namespace
}
else if(ext == "FLAC")
file = new FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "MPC")
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "WV")
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "SPX")
file = new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "OPUS")
file = new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_APE
else if(ext == "MPC")
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "WV")
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "APE")
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
else if(ext == "TTA")
file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_MP4
else if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_ASF
else if(ext == "WMA" || ext == "ASF")
file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_RIFF
else if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
file = new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "WAV")
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "APE")
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_MOD
// module, nst and wow are possible but uncommon extensions
else if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
file = new Mod::File(stream, readAudioProperties, audioPropertiesStyle);
@ -176,10 +209,17 @@ namespace
file = new IT::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "XM")
file = new XM::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_DSF
else if(ext == "DSF")
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "DFF" || ext == "DSDIFF")
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_SHORTEN
else if(ext == "SHN")
file = new Shorten::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
// if file is not valid, leave it to content-based detection.
@ -201,36 +241,54 @@ namespace
if(MPEG::File::isSupported(stream))
file = new MPEG::File(stream, readAudioProperties, audioPropertiesStyle);
#ifdef TAGLIB_WITH_VORBIS
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);
#endif
#ifdef TAGLIB_WITH_APE
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(APE::File::isSupported(stream))
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
else if(TrueAudio::File::isSupported(stream))
file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_MP4
else if(MP4::File::isSupported(stream))
file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_ASF
else if(ASF::File::isSupported(stream))
file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_RIFF
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);
#endif
#ifdef TAGLIB_WITH_DSF
else if(DSF::File::isSupported(stream))
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
else if(DSDIFF::File::isSupported(stream))
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_SHORTEN
else if(Shorten::File::isSupported(stream))
file = new Shorten::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
// isSupported() only does a quick check, so double check the file here.
@ -400,17 +458,25 @@ StringList FileRef::defaultFileExtensions()
{
StringList l;
l.append("mp3");
l.append("mp2");
l.append("aac");
#ifdef TAGLIB_WITH_VORBIS
l.append("ogg");
l.append("flac");
l.append("oga");
l.append("opus");
l.append("mp3");
l.append("mp2");
l.append("spx");
#endif
#ifdef TAGLIB_WITH_APE
l.append("mpc");
l.append("wv");
l.append("spx");
l.append("ape");
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
l.append("tta");
l.append("aac");
#endif
#ifdef TAGLIB_WITH_MP4
l.append("m4a");
l.append("m4r");
l.append("m4b");
@ -418,14 +484,19 @@ StringList FileRef::defaultFileExtensions()
l.append("3g2");
l.append("mp4");
l.append("m4v");
#endif
#ifdef TAGLIB_WITH_ASF
l.append("wma");
l.append("asf");
#endif
#ifdef TAGLIB_WITH_RIFF
l.append("aif");
l.append("aiff");
l.append("afc");
l.append("aifc");
l.append("wav");
l.append("ape");
#endif
#ifdef TAGLIB_WITH_MOD
l.append("mod");
l.append("module"); // alias for "mod"
l.append("nst"); // alias for "mod"
@ -433,9 +504,15 @@ StringList FileRef::defaultFileExtensions()
l.append("s3m");
l.append("it");
l.append("xm");
#endif
#ifdef TAGLIB_WITH_DSF
l.append("dsf");
l.append("dff");
l.append("dsdiff"); // alias for "dff"
#endif
#ifdef TAGLIB_WITH_SHORTEN
l.append("shn");
#endif
return l;
}

View File

@ -265,12 +265,19 @@ bool FLAC::File::save()
// Render data for the metadata blocks
ByteVector data;
for(const auto &block : std::as_const(d->blocks)) {
ByteVector blockData = block->render();
for(auto it = d->blocks.begin(); it != d->blocks.end();) {
ByteVector blockData = (*it)->render();
ByteVector blockHeader = ByteVector::fromUInt(blockData.size());
blockHeader[0] = block->code();
if(blockHeader[0] != 0) {
debug("FLAC::File::save() -- Removing too large block.");
delete *it;
it = d->blocks.erase(it);
continue;
}
blockHeader[0] = (*it)->code();
data.append(blockHeader);
data.append(blockData);
++it;
}
// Compute the amount of padding, and append that to data.

View File

@ -60,8 +60,8 @@ namespace TagLib {
#ifndef DO_NOT_DOCUMENT
struct AtomData {
AtomData(AtomDataType type, const ByteVector &data) :
type(type), data(data) { }
AtomData(AtomDataType ptype, const ByteVector &pdata) :
type(ptype), data(pdata) { }
AtomDataType type;
int locale { 0 };
ByteVector data;

View File

@ -56,6 +56,28 @@ namespace
constexpr long MinPaddingSize = 1024;
constexpr long MaxPaddingSize = 1024 * 1024;
/*!
* Downgrade ID3v2.4 text \a encoding to value supported by ID3v2.3.
*/
String::Type downgradeTextEncoding(String::Type encoding)
{
return encoding == String::Latin1 ? String::Latin1 : String::UTF16;
}
/*!
* Downgrade ID3v2.4 text encoding to value supported by ID3v2.3.
* \param frame1 first contributing ID3v2.4 frame, can be null
* \param frame2 second contributing ID3v2.4 frame, can be null
* \return ID3v2.3 encoding suitable for both contributing source frames.
*/
String::Type downgradeTextEncoding(ID3v2::TextIdentificationFrame *frame1,
ID3v2::TextIdentificationFrame *frame2)
{
return (!frame1 || frame1->textEncoding() == String::Latin1) &&
(!frame2 || frame2->textEncoding() == String::Latin1)
? String::Latin1 : String::UTF16;
}
} // namespace
class ID3v2::Tag::TagPrivate
@ -578,7 +600,8 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
String content = frameTDOR->toString();
if(content.size() >= 4) {
auto frameTORY = new ID3v2::TextIdentificationFrame("TORY", String::Latin1);
auto frameTORY = new ID3v2::TextIdentificationFrame(
"TORY", downgradeTextEncoding(frameTDOR->textEncoding()));
frameTORY->setText(content.substr(0, 4));
frames->append(frameTORY);
newFrames->append(frameTORY);
@ -587,17 +610,20 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
if(frameTDRC) {
if(String content = frameTDRC->toString(); content.size() >= 4) {
auto frameTYER = new ID3v2::TextIdentificationFrame("TYER", String::Latin1);
auto frameTYER = new ID3v2::TextIdentificationFrame(
"TYER", downgradeTextEncoding(frameTDRC->textEncoding()));
frameTYER->setText(content.substr(0, 4));
frames->append(frameTYER);
newFrames->append(frameTYER);
if(content.size() >= 10 && content[4] == '-' && content[7] == '-') {
auto frameTDAT = new ID3v2::TextIdentificationFrame("TDAT", String::Latin1);
auto frameTDAT = new ID3v2::TextIdentificationFrame(
"TDAT", downgradeTextEncoding(frameTDRC->textEncoding()));
frameTDAT->setText(content.substr(8, 2) + content.substr(5, 2));
frames->append(frameTDAT);
newFrames->append(frameTDAT);
if(content.size() >= 16 && content[10] == 'T' && content[13] == ':') {
auto frameTIME = new ID3v2::TextIdentificationFrame("TIME", String::Latin1);
auto frameTIME = new ID3v2::TextIdentificationFrame(
"TIME", downgradeTextEncoding(frameTDRC->textEncoding()));
frameTIME->setText(content.substr(11, 2) + content.substr(14, 2));
frames->append(frameTIME);
newFrames->append(frameTIME);
@ -607,7 +633,8 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
}
if(frameTIPL || frameTMCL) {
auto frameIPLS = new ID3v2::TextIdentificationFrame("IPLS", String::Latin1);
auto frameIPLS = new ID3v2::TextIdentificationFrame(
"IPLS", downgradeTextEncoding(frameTIPL, frameTMCL));
StringList people;
@ -653,7 +680,8 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
if(!genreText.isEmpty())
combined += genreText;
frameTCON = new ID3v2::TextIdentificationFrame("TCON", String::Latin1);
frameTCON = new ID3v2::TextIdentificationFrame(
"TCON", downgradeTextEncoding(frameTCON->textEncoding()));
frameTCON->setText(combined);
frames->append(frameTCON);
newFrames->append(frameTCON);

View File

@ -25,11 +25,14 @@
#include "mpegfile.h"
#include "taglib_config.h"
#include "id3v2framefactory.h"
#include "tdebug.h"
#include "tpropertymap.h"
#ifdef TAGLIB_WITH_APE
#include "apefooter.h"
#include "apetag.h"
#endif
#include "id3v1tag.h"
#include "id3v2tag.h"
#include "tagunion.h"
@ -277,6 +280,7 @@ bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, Duplica
}
}
#ifdef TAGLIB_WITH_APE
if(APE & tags) {
if(APETag() && !APETag()->isEmpty()) {
@ -305,6 +309,7 @@ bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, Duplica
File::strip(APE, false);
}
}
#endif
return true;
}
@ -321,7 +326,11 @@ ID3v1::Tag *MPEG::File::ID3v1Tag(bool create)
APE::Tag *MPEG::File::APETag(bool create)
{
#ifdef TAGLIB_WITH_APE
return d->tag.access<APE::Tag>(APEIndex, create);
#else
return nullptr;
#endif
}
bool MPEG::File::strip(int tags, bool freeMemory)
@ -480,6 +489,7 @@ void MPEG::File::read(bool readProperties, Properties::ReadStyle readStyle)
if(d->ID3v1Location >= 0)
d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
#ifdef TAGLIB_WITH_APE
// Look for an APE tag
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
@ -489,6 +499,7 @@ void MPEG::File::read(bool readProperties, Properties::ReadStyle readStyle)
d->APEOriginalSize = APETag()->footer()->completeTagSize();
d->APELocation = d->APELocation + APE::Footer::size() - d->APEOriginalSize;
}
#endif
if(readProperties)
d->properties = std::make_unique<Properties>(this, readStyle);

View File

@ -25,10 +25,13 @@
#include "mpegproperties.h"
#include "taglib_config.h"
#include "tdebug.h"
#include "mpegfile.h"
#include "xingheader.h"
#ifdef TAGLIB_WITH_APE
#include "apetag.h"
#endif
using namespace TagLib;

View File

@ -113,6 +113,17 @@ bool Ogg::FLAC::File::save()
// Put the size in the first 32 bit (I assume no more than 24 bit are used)
ByteVector v = ByteVector::fromUInt(d->xiphCommentData.size());
if(v[0] != 0) {
// Block size uses more than 24 bits, try again with pictures removed.
d->comment->removeAllPictures();
d->xiphCommentData = d->comment->render(false);
v = ByteVector::fromUInt(d->xiphCommentData.size());
if(v[0] != 0) {
debug("Ogg::FLAC::File::save() -- Invalid, metadata block is too large.");
return false;
}
debug("Ogg::FLAC::File::save() -- Metadata block is too large, pictures removed.");
}
// Set the type of the metadata-block to be a Xiph / Vorbis comment

View File

@ -0,0 +1,542 @@
/***************************************************************************
copyright : (C) 2020-2024 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 "shortenfile.h"
#include <cmath>
#include "shortenutils.h"
#include "tdebug.h"
#include "tutils.h"
#include "tagutils.h"
#include "tpropertymap.h"
using namespace TagLib;
namespace {
// MARK: Constants
constexpr int minSupportedVersion = 1;
constexpr int maxSupportedVersion = 3;
// Possible values of k
constexpr int32_t channelCountCodeSize = 0;
constexpr int32_t functionCodeSize = 2;
constexpr int32_t verbatimChunkSizeCodeSize = 5;
constexpr int32_t verbatimByteCodeSize = 8;
constexpr int32_t uInt32CodeSize = 2;
constexpr int32_t skipBytesCodeSize = 1;
constexpr int32_t lpcqCodeSize = 2;
constexpr int32_t extraByteCodeSize = 7;
constexpr int32_t fileTypeCodeSize = 4;
constexpr int32_t functionVerbatim = 9;
constexpr int32_t canonicalHeaderSize = 44;
constexpr int32_t verbatimChunkMaxSize = 256;
constexpr uint32_t maxChannelCount = 8;
constexpr uint32_t defaultBlockSize = 256;
constexpr uint32_t maxBlockSize = 65535;
constexpr int waveFormatPCMTag = 0x0001;
// MARK: Variable-Length Input
//! Variable-length input using Golomb-Rice coding.
class VariableLengthInput {
public:
//! Creates a new \c VariableLengthInput object.
VariableLengthInput(File *file) : file(file) {}
~VariableLengthInput() = default;
VariableLengthInput() = delete;
VariableLengthInput(const VariableLengthInput &) = delete;
VariableLengthInput(VariableLengthInput &&) = delete;
VariableLengthInput &operator=(const VariableLengthInput &) = delete;
VariableLengthInput &operator=(VariableLengthInput &&) = delete;
bool getRiceGolombCode(int32_t &i32, int k);
bool getUInt(uint32_t &ui32, int version, int32_t k);
private:
//! Refills \c bitBuffer with a single \c uint32_t from \c buffer,
//! refilling \c buffer if necessary.
bool refillBitBuffer();
//! Input stream
File *file { nullptr };
//! Byte buffer
ByteVector buffer;
//! Current position in buffer
unsigned int bufferPosition { 0 };
//! Bit buffer
uint32_t bitBuffer { 0 };
//! Bits available in \c bitBuffer, 0..32
int bitsAvailable { 0 };
};
bool VariableLengthInput::getRiceGolombCode(int32_t &i32, int32_t k)
{
static constexpr uint32_t sMaskTable[] = {
0x0,
0x1, 0x3, 0x7, 0xf,
0x1f, 0x3f, 0x7f, 0xff,
0x1ff, 0x3ff, 0x7ff, 0xfff,
0x1fff, 0x3fff, 0x7fff, 0xffff,
0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff
};
if(bitsAvailable == 0 && !refillBitBuffer())
return false;
int32_t result;
for(result = 0; !(bitBuffer & (1L << --bitsAvailable)); ++result) {
if(bitsAvailable == 0 && !refillBitBuffer())
return false;
}
while(k != 0) {
if(bitsAvailable >= k) {
result = (result << k) | static_cast<int32_t>(
(bitBuffer >> (bitsAvailable - k)) & sMaskTable[k]);
bitsAvailable -= k;
k = 0;
}
else {
result = (result << bitsAvailable) | static_cast<int32_t>(
bitBuffer & sMaskTable[bitsAvailable]);
k -= bitsAvailable;
if(!refillBitBuffer())
return false;
}
}
i32 = result;
return true;
}
bool VariableLengthInput::getUInt(uint32_t &ui32, int version, int32_t k)
{
if(version > 0 && !getRiceGolombCode(k, uInt32CodeSize))
return false;
int32_t i32;
if(!getRiceGolombCode(i32, k))
return false;
ui32 = static_cast<uint32_t>(i32);
return true;
}
bool VariableLengthInput::refillBitBuffer()
{
if(buffer.size() - bufferPosition < 4) {
static constexpr size_t bufferSize = 512;
auto block = file->readBlock(bufferSize);
if(block.size() < 4)
return false;
buffer = block;
bufferPosition = 0;
}
bitBuffer = buffer.toUInt(bufferPosition, true);
bufferPosition += 4;
bitsAvailable = 32;
return true;
}
} // namespace
class Shorten::File::FilePrivate
{
public:
FilePrivate() = default;
~FilePrivate() = default;
FilePrivate(const FilePrivate &) = delete;
FilePrivate &operator=(const FilePrivate &) = delete;
std::unique_ptr<Properties> properties;
std::unique_ptr<Tag> tag;
};
bool Shorten::File::isSupported(IOStream *stream)
{
// A Shorten file has to start with "ajkg"
const ByteVector id = Utils::readHeader(stream, 4, false);
return id.startsWith("ajkg");
}
Shorten::File::File(FileName file, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) :
TagLib::File(file),
d(std::make_unique<FilePrivate>())
{
if(isOpen())
read(propertiesStyle);
}
Shorten::File::File(IOStream *stream, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) :
TagLib::File(stream),
d(std::make_unique<FilePrivate>())
{
if(isOpen())
read(propertiesStyle);
}
Shorten::File::~File() = default;
Shorten::Tag *Shorten::File::tag() const
{
return d->tag.get();
}
PropertyMap Shorten::File::properties() const
{
return d->tag->properties();
}
PropertyMap Shorten::File::setProperties(const PropertyMap &properties)
{
return d->tag->setProperties(properties);
}
Shorten::Properties *Shorten::File::audioProperties() const
{
return d->properties.get();
}
bool Shorten::File::save()
{
if(readOnly()) {
debug("Shorten::File::save() - Cannot save to a read only file.");
return false;
}
debug("Shorten::File::save() - Saving not supported.");
return false;
}
void Shorten::File::read(AudioProperties::ReadStyle propertiesStyle)
{
if(!isOpen())
return;
// Read magic number
auto magic = readBlock(4);
if(magic != "ajkg") {
debug("Shorten::File::read() -- Not a Shorten file.");
setValid(false);
return;
}
PropertyValues props{};
// Read file version
int version = readBlock(1).toUInt();
if(version < minSupportedVersion || version > maxSupportedVersion) {
debug("Shorten::File::read() -- Unsupported version.");
setValid(false);
return;
}
props.version = version;
// Set up variable length input
VariableLengthInput input(this);
// Read file type
uint32_t fileType;
if(!input.getUInt(fileType, version, fileTypeCodeSize)) {
debug("Shorten::File::read() -- Unable to read file type.");
setValid(false);
return;
}
props.fileType = static_cast<int>(fileType);
// Read number of channels
uint32_t channelCount = 0;
if(!input.getUInt(channelCount, version, channelCountCodeSize) ||
channelCount == 0 || channelCount > maxChannelCount) {
debug("Shorten::File::read() -- Invalid or unsupported channel count.");
setValid(false);
return;
}
props.channelCount = static_cast<int>(channelCount);
// Read block size if version > 0
if(version > 0) {
uint32_t blockSize = 0;
if(!input.getUInt(blockSize, version,
static_cast<int32_t>(std::log2(defaultBlockSize))) ||
blockSize == 0 || blockSize > maxBlockSize) {
debug("Shorten::File::read() -- Invalid or unsupported block size.");
setValid(false);
return;
}
uint32_t maxnlpc = 0;
if(!input.getUInt(maxnlpc, version, lpcqCodeSize) /*|| maxnlpc > 1024*/) {
debug("Shorten::File::read() -- Invalid maximum nlpc.");
setValid(false);
return;
}
uint32_t nmean = 0;
if(!input.getUInt(nmean, version, 0) /*|| nmean > 32768*/) {
debug("Shorten::File::read() -- Invalid nmean.");
setValid(false);
return;
}
uint32_t skipCount;
if(!input.getUInt(skipCount, version, skipBytesCodeSize)) {
setValid(false);
return;
}
for(uint32_t i = 0; i < skipCount; ++i) {
uint32_t dummy;
if(!input.getUInt(dummy, version, extraByteCodeSize)) {
setValid(false);
return;
}
}
}
// Parse the WAVE or AIFF header in the verbatim section
int32_t function;
if(!input.getRiceGolombCode(function, functionCodeSize) ||
function != functionVerbatim) {
debug("Shorten::File::read() -- Missing initial verbatim section.");
setValid(false);
return;
}
int32_t header_size;
if(!input.getRiceGolombCode(header_size, verbatimChunkSizeCodeSize) ||
header_size < canonicalHeaderSize || header_size > verbatimChunkMaxSize) {
debug("Shorten::File::read() -- Incorrect header size.");
setValid(false);
return;
}
ByteVector header(header_size, 0);
auto it = header.begin();
for(int32_t i = 0; i < header_size; ++i) {
int32_t byte;
if(!input.getRiceGolombCode(byte, verbatimByteCodeSize)) {
debug("Shorten::File::read() -- Unable to read header.");
setValid(false);
return;
}
*it++ = static_cast<uint8_t>(byte);
}
// header is at least canonicalHeaderSize (44) bytes in size
auto chunkID = header.toUInt(0, true);
// auto chunkSize = header.toUInt(4, true);
const auto chunkData = ByteVector(header, 8, header.size() - 8);
// WAVE
if(chunkID == 0x52494646 /*'RIFF'*/) {
unsigned int offset = 0;
chunkID = chunkData.toUInt(offset, true);
offset += 4;
if(chunkID != 0x57415645 /*'WAVE'*/) {
debug("Shorten::File::read() -- Missing 'WAVE' in 'RIFF' chunk.");
setValid(false);
return;
}
auto sawFormatChunk = false;
uint32_t dataChunkSize = 0;
uint16_t blockAlign = 0;
while(offset < chunkData.size()) {
chunkID = chunkData.toUInt(offset, true);
offset += 4;
auto chunkSize = chunkData.toUInt(offset, false);
offset += 4;
switch(chunkID) {
case 0x666d7420 /*'fmt '*/:
{
if(chunkSize < 16) {
debug("Shorten::File::read() -- 'fmt ' chunk is too small.");
setValid(false);
return;
}
int formatTag = chunkData.toUShort(offset, false);
offset += 2;
if(formatTag != waveFormatPCMTag) {
debug("Shorten::File::read() -- Unsupported WAVE format tag.");
setValid(false);
return;
}
int fmtChannelCount = chunkData.toUShort(offset, false);
offset += 2;
if(props.channelCount != fmtChannelCount)
debug("Shorten::File::read() -- Channel count mismatch between Shorten and 'fmt ' chunk.");
props.sampleRate = static_cast<int>(chunkData.toUInt(offset, false));
offset += 4;
// Skip average bytes per second
offset += 4;
blockAlign = chunkData.toUShort(offset, false);
offset += 2;
props.bitsPerSample = static_cast<int>(chunkData.toUShort(offset, false));
offset += 2;
sawFormatChunk = true;
break;
}
case 0x64617461 /*'data'*/:
dataChunkSize = chunkSize;
break;
}
}
if(!sawFormatChunk) {
debug("Shorten::File::read() -- Missing 'fmt ' chunk.");
setValid(false);
return;
}
if(dataChunkSize && blockAlign)
props.sampleFrames = static_cast<unsigned long>(dataChunkSize / blockAlign);
}
// AIFF
else if(chunkID == 0x464f524d /*'FORM'*/) {
unsigned int offset = 0;
chunkID = chunkData.toUInt(offset, true);
offset += 4;
if(chunkID != 0x41494646 /*'AIFF'*/ && chunkID != 0x41494643 /*'AIFC'*/) {
debug("Shorten::File::read() -- Missing 'AIFF' or 'AIFC' in 'FORM' chunk.");
setValid(false);
return;
}
// if(chunkID == 0x41494643 /*'AIFC'*/)
// props.big_endian = true;
auto sawCommonChunk = false;
while(offset < chunkData.size()) {
chunkID = chunkData.toUInt(offset, true);
offset += 4;
auto chunkSize = chunkData.toUInt(offset, true);
offset += 4;
// All chunks must have an even length but the pad byte is not included in chunkSize
chunkSize += (chunkSize & 1);
switch(chunkID) {
case 0x434f4d4d /*'COMM'*/:
{
if(chunkSize < 18) {
debug("Shorten::File::read() -- 'COMM' chunk is too small.");
setValid(false);
return;
}
int commChannelCount = chunkData.toUShort(offset, true);
offset += 2;
if(props.channelCount != commChannelCount)
debug("Shorten::File::read() -- Channel count mismatch between Shorten and 'COMM' chunk.");
props.sampleFrames = static_cast<unsigned long>(chunkData.toUInt(offset, true));
offset += 4;
props.bitsPerSample = static_cast<int>(chunkData.toUShort(offset, true));
offset += 2;
// sample rate is IEEE 754 80-bit extended float
// (16-bit exponent, 1-bit integer part, 63-bit fraction)
auto exp = static_cast<int16_t>(chunkData.toUShort(offset, true)) - 16383 - 63;
offset += 2;
if(exp < -63 || exp > 63) {
debug("Shorten::File::read() -- exp out of range.");
setValid(false);
return;
}
auto frac = chunkData.toULongLong(offset, true);
offset += 8;
if(exp >= 0)
props.sampleRate = static_cast<int>(frac << exp);
else
props.sampleRate = static_cast<int>(
(frac + (static_cast<uint64_t>(1) << (-exp - 1))) >> -exp);
sawCommonChunk = true;
break;
}
// Skip all other chunks
default:
offset += chunkSize;
break;
}
}
if(!sawCommonChunk) {
debug("Shorten::File::read() -- Missing 'COMM' chunk");
setValid(false);
return;
}
}
else {
debug("Shorten::File::read() -- Unsupported data format.");
setValid(false);
return;
}
d->tag = std::make_unique<Tag>();
d->properties = std::make_unique<Properties>(&props, propertiesStyle);
}

View File

@ -0,0 +1,140 @@
/***************************************************************************
copyright : (C) 2020-2024 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_SHORTENFILE_H
#define TAGLIB_SHORTENFILE_H
#include <memory>
#include "taglib_export.h"
#include "tfile.h"
#include "shortenproperties.h"
#include "shortentag.h"
namespace TagLib {
//! An implementation of Shorten metadata
/*!
* This is an implementation of Shorten metadata.
*/
namespace Shorten {
//! An implementation of \c TagLib::File with Shorten specific methods
/*!
* This implements and provides an interface for Shorten files to the
* \c TagLib::Tag and \c TagLib::AudioProperties interfaces by way of implementing
* the abstract \c TagLib::File API as well as providing some additional
* information specific to Shorten files.
*/
class TAGLIB_EXPORT File : public TagLib::File {
public:
/*!
* Constructs a Shorten 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);
/*!
* Constructs a Shorten 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 *stream, bool readProperties = true,
AudioProperties::ReadStyle propertiesStyle =
AudioProperties::Average);
/*!
* Destroys this instance of the File.
*/
~File() override;
File(const File &) = delete;
File &operator=(const File &) = delete;
/*!
* Returns the \c Shorten::Tag for this file.
*
* \note While the returned \c Tag instance is non-null Shorten tags are not supported.
*/
Tag *tag() const override;
/*!
* Implements the unified property interface -- export function.
*/
PropertyMap properties() const override;
/*!
* Implements the unified property interface -- import function.
*/
PropertyMap setProperties(const PropertyMap &) override;
/*!
* Returns the \c Shorten::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
Properties *audioProperties() const override;
/*!
* Save the file.
*
* \note Saving Shorten tags is not supported.
*/
bool save() override;
/*!
* Returns whether or not the given \a stream can be opened as a Shorten
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
void read(AudioProperties::ReadStyle propertiesStyle);
class FilePrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<FilePrivate> d;
};
} // namespace Shorten
} // namespace TagLib
#endif

View File

@ -0,0 +1,112 @@
/***************************************************************************
copyright : (C) 2020-2024 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 "shortenproperties.h"
#include "shortenutils.h"
using namespace TagLib;
class Shorten::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() = default;
~PropertiesPrivate() = default;
PropertiesPrivate(const PropertiesPrivate &) = delete;
PropertiesPrivate &operator=(const PropertiesPrivate &) = delete;
int version { 0 };
int fileType { 0 };
int channelCount { 0 };
int sampleRate { 0 };
int bitsPerSample { 0 };
unsigned long sampleFrames { 0 };
// Computed
int bitrate { 0 };
int length { 0 };
};
Shorten::Properties::Properties(const PropertyValues *values, ReadStyle style) :
AudioProperties(style),
d(std::make_unique<PropertiesPrivate>())
{
if(values) {
d->version = values->version;
d->fileType = values->fileType;
d->channelCount = values->channelCount;
d->sampleRate = values->sampleRate;
d->bitsPerSample = values->bitsPerSample;
d->sampleFrames = values->sampleFrames;
d->bitrate = static_cast<int>(d->sampleRate * d->bitsPerSample * d->channelCount / 1000.0 + 0.5);
if(d->sampleRate > 0)
d->length = static_cast<int>(d->sampleFrames * 1000.0 / d->sampleRate + 0.5);
}
}
Shorten::Properties::~Properties() = default;
int Shorten::Properties::lengthInMilliseconds() const
{
return d->length;
}
int Shorten::Properties::bitrate() const
{
return d->bitrate;
}
int Shorten::Properties::sampleRate() const
{
return d->sampleRate;
}
int Shorten::Properties::channels() const
{
return d->channelCount;
}
int Shorten::Properties::shortenVersion() const
{
return d->version;
}
int Shorten::Properties::fileType() const
{
return d->fileType;
}
int Shorten::Properties::bitsPerSample() const
{
return d->bitsPerSample;
}
unsigned long Shorten::Properties::sampleFrames() const
{
return d->sampleFrames;
}

View File

@ -0,0 +1,74 @@
/***************************************************************************
copyright : (C) 2020-2024 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_SHORTENPROPERTIES_H
#define TAGLIB_SHORTENPROPERTIES_H
#include <memory>
#include "taglib_export.h"
#include "audioproperties.h"
namespace TagLib {
namespace Shorten {
struct PropertyValues;
//! An implementation of audio properties for Shorten
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
Properties(const PropertyValues *values, ReadStyle style = Average);
~Properties() override;
Properties(const Properties &) = delete;
Properties &operator=(const Properties &) = delete;
int lengthInMilliseconds() const override;
int bitrate() const override;
int sampleRate() const override;
int channels() const override;
//! Returns the Shorten file version (1-3).
int shortenVersion() const;
//! Returns the file type (0-9).
//! 0 = 8-bit µ-law,
//! 1 = signed 8-bit PCM, 2 = unsigned 8-bit PCM,
//! 3 = signed big-endian 16-bit PCM, 4 = unsigned big-endian 16-bit PCM,
//! 5 = signed little-endian 16-bit PCM, 6 = unsigned little-endian 16-bit PCM,
//! 7 = 8-bit ITU-T G.711 µ-law, 8 = 8-bit µ-law,
//! 9 = 8-bit A-law, 10 = 8-bit ITU-T G.711 A-law
int fileType() const;
int bitsPerSample() const;
unsigned long sampleFrames() const;
private:
class PropertiesPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<PropertiesPrivate> d;
};
} // namespace Shorten
} // namespace TagLib
#endif

View File

@ -0,0 +1,114 @@
/***************************************************************************
copyright : (C) 2020-2024 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 "shortentag.h"
#include "tpropertymap.h"
using namespace TagLib;
class Shorten::Tag::TagPrivate
{
};
Shorten::Tag::Tag() :
d(std::make_unique<TagPrivate>())
{
}
Shorten::Tag::~Tag() = default;
String Shorten::Tag::title() const
{
return String();
}
String Shorten::Tag::artist() const
{
return String();
}
String Shorten::Tag::album() const
{
return String();
}
String Shorten::Tag::comment() const
{
return String();
}
String Shorten::Tag::genre() const
{
return String();
}
unsigned int Shorten::Tag::year() const
{
return 0;
}
unsigned int Shorten::Tag::track() const
{
return 0;
}
void Shorten::Tag::setTitle(const String &)
{
}
void Shorten::Tag::setArtist(const String &)
{
}
void Shorten::Tag::setAlbum(const String &)
{
}
void Shorten::Tag::setComment(const String &)
{
}
void Shorten::Tag::setGenre(const String &)
{
}
void Shorten::Tag::setYear(unsigned int)
{
}
void Shorten::Tag::setTrack(unsigned int)
{
}
PropertyMap Shorten::Tag::properties() const
{
return PropertyMap{};
}
PropertyMap Shorten::Tag::setProperties(const PropertyMap &origProps)
{
return PropertyMap{origProps};
}

139
taglib/shorten/shortentag.h Normal file
View File

@ -0,0 +1,139 @@
/***************************************************************************
copyright : (C) 2020-2024 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_SHORTENTAG_H
#define TAGLIB_SHORTENTAG_H
#include "tag.h"
namespace TagLib {
namespace Shorten {
//! A Shorten file tag implementation
/*!
* Tags for Shorten files.
*
* This is a stub class; Shorten files do not support tags.
*/
class TAGLIB_EXPORT Tag : public TagLib::Tag
{
public:
Tag();
~Tag() override;
Tag(const Tag &) = delete;
Tag &operator=(const Tag &) = delete;
/*!
* Not supported by Shorten files. Therefore always returns an empty string.
*/
String title() const override;
/*!
* Not supported by Shorten files. Therefore always returns an empty string.
*/
String artist() const override;
/*!
* Not supported by Shorten files. Therefore always returns an empty string.
*/
String album() const override;
/*!
* Not supported by Shorten files. Therefore always returns an empty string.
*/
String comment() const override;
/*!
* Not supported by Shorten files. Therefore always returns an empty string.
*/
String genre() const override;
/*!
* Not supported by Shorten files. Therefore always returns 0.
*/
unsigned int year() const override;
/*!
* Not supported by Shorten files. Therefore always returns 0.
*/
unsigned int track() const override;
/*!
* Not supported by Shorten files and therefore ignored.
*/
void setTitle(const String &title) override;
/*!
* Not supported by Shorten files and therefore ignored.
*/
void setArtist(const String &artist) override;
/*!
* Not supported by Shorten files and therefore ignored.
*/
void setAlbum(const String &album) override;
/*!
* Not supported by Shorten files and therefore ignored.
*/
void setComment(const String &comment) override;
/*!
* Not supported by Shorten files and therefore ignored.
*/
void setGenre(const String &genre) override;
/*!
* Not supported by Shorten files and therefore ignored.
*/
void setYear(unsigned int year) override;
/*!
* Not supported by Shorten files and therefore ignored.
*/
void setTrack(unsigned int track) override;
/*!
* Implements the unified property interface -- export function.
*/
PropertyMap properties() const override;
/*!
* Implements the unified property interface -- import function.
*/
PropertyMap setProperties(const PropertyMap &) override;
private:
class TagPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<TagPrivate> d;
};
} // namespace Shorten
} // namespace TagLib
#endif

View File

@ -0,0 +1,51 @@
/***************************************************************************
copyright : (C) 2020-2024 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_SHORTENUTILS_H
#define TAGLIB_SHORTENUTILS_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 Shorten {
/// Values shared with \c Shorten::Properties by \c Shorten::File
struct PropertyValues
{
int version { 0 };
int fileType { 0 };
int channelCount { 0 };
int sampleRate { 0 };
int bitsPerSample { 0 };
unsigned long sampleFrames { 0 };
};
} // namespace Shorten
} // namespace TagLib
#endif
#endif

View File

@ -0,0 +1,16 @@
/* taglib_config.h. Generated by cmake from taglib_config.h.cmake */
#ifndef TAGLIB_TAGLIB_CONFIG_H
#define TAGLIB_TAGLIB_CONFIG_H
#cmakedefine TAGLIB_WITH_APE 1
#cmakedefine TAGLIB_WITH_ASF 1
#cmakedefine TAGLIB_WITH_DSF 1
#cmakedefine TAGLIB_WITH_MOD 1
#cmakedefine TAGLIB_WITH_MP4 1
#cmakedefine TAGLIB_WITH_RIFF 1
#cmakedefine TAGLIB_WITH_SHORTEN 1
#cmakedefine TAGLIB_WITH_TRUEAUDIO 1
#cmakedefine TAGLIB_WITH_VORBIS 1
#endif

View File

@ -25,11 +25,14 @@
#include "tagutils.h"
#include "taglib_config.h"
#include "tfile.h"
#include "id3v1tag.h"
#include "id3v2header.h"
#ifdef TAGLIB_WITH_APE
#include "apetag.h"
#endif
using namespace TagLib;
@ -45,7 +48,13 @@ offset_t Utils::findID3v1(File *file)
const offset_t p = file->tell() + 3;
if(const TagLib::ByteVector data = file->readBlock(8);
data.containsAt(ID3v1::Tag::fileIdentifier(), 3) && data != APE::Tag::fileIdentifier())
data.containsAt(ID3v1::Tag::fileIdentifier(), 3) &&
#ifdef TAGLIB_WITH_APE
data != APE::Tag::fileIdentifier()
#else
data != ByteVector::fromCString("APETAGEX")
#endif
)
return p;
} else {
file->seek(-128, File::End);
@ -83,7 +92,13 @@ offset_t Utils::findAPE(File *file, offset_t id3v1Location)
const offset_t p = file->tell();
if(file->readBlock(8) == APE::Tag::fileIdentifier())
if(file->readBlock(8) ==
#ifdef TAGLIB_WITH_APE
APE::Tag::fileIdentifier()
#else
ByteVector::fromCString("APETAGEX")
#endif
)
return p;
return -1;

View File

@ -158,7 +158,7 @@ ByteVector fromNumber(T value, bool mostSignificantByteFirst)
template <typename TFloat, typename TInt, Utils::ByteOrder ENDIAN>
TFloat toFloat(const ByteVector &v, size_t offset)
{
if(offset > v.size() - sizeof(TInt)) {
if(offset + sizeof(TInt) > v.size()) {
debug("toFloat() - offset is out of range. Returning 0.");
return 0.0;
}
@ -195,7 +195,7 @@ long double toFloat80(const ByteVector &v, size_t offset)
{
using std::swap;
if(offset > v.size() - 10) {
if(offset + 10 > v.size()) {
debug("toFloat80() - offset is out of range. Returning 0.");
return 0.0;
}
@ -282,47 +282,47 @@ ByteVector ByteVector::fromCString(const char *s, unsigned int length)
ByteVector ByteVector::fromUInt(unsigned int value, bool mostSignificantByteFirst)
{
return fromNumber<unsigned int>(value, mostSignificantByteFirst);
return fromNumber<uint32_t>(value, mostSignificantByteFirst);
}
ByteVector ByteVector::fromShort(short value, bool mostSignificantByteFirst)
{
return fromNumber<unsigned short>(value, mostSignificantByteFirst);
return fromNumber<uint16_t>(value, mostSignificantByteFirst);
}
ByteVector ByteVector::fromUShort(unsigned short value, bool mostSignificantByteFirst)
{
return fromNumber<unsigned short>(value, mostSignificantByteFirst);
return fromNumber<uint16_t>(value, mostSignificantByteFirst);
}
ByteVector ByteVector::fromLongLong(long long value, bool mostSignificantByteFirst)
{
return fromNumber<unsigned long long>(value, mostSignificantByteFirst);
return fromNumber<uint64_t>(value, mostSignificantByteFirst);
}
ByteVector ByteVector::fromULongLong(unsigned long long value, bool mostSignificantByteFirst)
{
return fromNumber<unsigned long long>(value, mostSignificantByteFirst);
return fromNumber<uint64_t>(value, mostSignificantByteFirst);
}
ByteVector ByteVector::fromFloat32LE(float value)
{
return fromFloat<float, unsigned int, Utils::LittleEndian>(value);
return fromFloat<float, uint32_t, Utils::LittleEndian>(value);
}
ByteVector ByteVector::fromFloat32BE(float value)
{
return fromFloat<float, unsigned int, Utils::BigEndian>(value);
return fromFloat<float, uint32_t, Utils::BigEndian>(value);
}
ByteVector ByteVector::fromFloat64LE(double value)
{
return fromFloat<double, unsigned long long, Utils::LittleEndian>(value);
return fromFloat<double, uint64_t, Utils::LittleEndian>(value);
}
ByteVector ByteVector::fromFloat64BE(double value)
{
return fromFloat<double, unsigned long long, Utils::BigEndian>(value);
return fromFloat<double, uint64_t, Utils::BigEndian>(value);
}
////////////////////////////////////////////////////////////////////////////////
@ -360,7 +360,7 @@ ByteVector::ByteVector(const char *data, unsigned int length) :
}
ByteVector::ByteVector(const char *data) :
d(std::make_unique<ByteVectorPrivate>(data, static_cast<unsigned int>(::strlen(data))))
d(std::make_unique<ByteVectorPrivate>(data, data ? static_cast<unsigned int>(::strlen(data)) : 0))
{
}
@ -656,79 +656,86 @@ bool ByteVector::isEmpty() const
return d->length == 0;
}
// Sanity checks
static_assert(sizeof(unsigned short) == sizeof(uint16_t), "unsigned short and uint16_t are different sizes");
static_assert(sizeof(unsigned int) == sizeof(uint32_t), "unsigned int and uint32_t are different sizes");
static_assert(sizeof(unsigned long long) == sizeof(uint64_t), "unsigned long long and uint64_t are different sizes");
static_assert(sizeof(float) == sizeof(uint32_t), "float and uint32_t are different sizes");
static_assert(sizeof(double) == sizeof(uint64_t), "double and uint64_t are different sizes");
unsigned int ByteVector::toUInt(bool mostSignificantByteFirst) const
{
return toNumber<unsigned int>(*this, 0, mostSignificantByteFirst);
return toNumber<uint32_t>(*this, 0, mostSignificantByteFirst);
}
unsigned int ByteVector::toUInt(unsigned int offset, bool mostSignificantByteFirst) const
{
return toNumber<unsigned int>(*this, offset, mostSignificantByteFirst);
return toNumber<uint32_t>(*this, offset, mostSignificantByteFirst);
}
unsigned int ByteVector::toUInt(unsigned int offset, unsigned int length, bool mostSignificantByteFirst) const
{
return toNumber<unsigned int>(*this, offset, length, mostSignificantByteFirst);
return toNumber<uint32_t>(*this, offset, length, mostSignificantByteFirst);
}
short ByteVector::toShort(bool mostSignificantByteFirst) const
{
return toNumber<unsigned short>(*this, 0, mostSignificantByteFirst);
return toNumber<uint16_t>(*this, 0, mostSignificantByteFirst);
}
short ByteVector::toShort(unsigned int offset, bool mostSignificantByteFirst) const
{
return toNumber<unsigned short>(*this, offset, mostSignificantByteFirst);
return toNumber<uint16_t>(*this, offset, mostSignificantByteFirst);
}
unsigned short ByteVector::toUShort(bool mostSignificantByteFirst) const
{
return toNumber<unsigned short>(*this, 0, mostSignificantByteFirst);
return toNumber<uint16_t>(*this, 0, mostSignificantByteFirst);
}
unsigned short ByteVector::toUShort(unsigned int offset, bool mostSignificantByteFirst) const
{
return toNumber<unsigned short>(*this, offset, mostSignificantByteFirst);
return toNumber<uint16_t>(*this, offset, mostSignificantByteFirst);
}
long long ByteVector::toLongLong(bool mostSignificantByteFirst) const
{
return toNumber<unsigned long long>(*this, 0, mostSignificantByteFirst);
return toNumber<uint64_t>(*this, 0, mostSignificantByteFirst);
}
long long ByteVector::toLongLong(unsigned int offset, bool mostSignificantByteFirst) const
{
return toNumber<unsigned long long>(*this, offset, mostSignificantByteFirst);
return toNumber<uint64_t>(*this, offset, mostSignificantByteFirst);
}
unsigned long long ByteVector::toULongLong(bool mostSignificantByteFirst) const
{
return toNumber<unsigned long long>(*this, 0, mostSignificantByteFirst);
return toNumber<uint64_t>(*this, 0, mostSignificantByteFirst);
}
unsigned long long ByteVector::toULongLong(unsigned int offset, bool mostSignificantByteFirst) const
{
return toNumber<unsigned long long>(*this, offset, mostSignificantByteFirst);
return toNumber<uint64_t>(*this, offset, mostSignificantByteFirst);
}
float ByteVector::toFloat32LE(size_t offset) const
{
return toFloat<float, unsigned int, Utils::LittleEndian>(*this, offset);
return toFloat<float, uint32_t, Utils::LittleEndian>(*this, offset);
}
float ByteVector::toFloat32BE(size_t offset) const
{
return toFloat<float, unsigned int, Utils::BigEndian>(*this, offset);
return toFloat<float, uint32_t, Utils::BigEndian>(*this, offset);
}
double ByteVector::toFloat64LE(size_t offset) const
{
return toFloat<double, unsigned long long, Utils::LittleEndian>(*this, offset);
return toFloat<double, uint64_t, Utils::LittleEndian>(*this, offset);
}
double ByteVector::toFloat64BE(size_t offset) const
{
return toFloat<double, unsigned long long, Utils::BigEndian>(*this, offset);
return toFloat<double, uint64_t, Utils::BigEndian>(*this, offset);
}
long double ByteVector::toFloat80LE(size_t offset) const
@ -767,6 +774,9 @@ bool ByteVector::operator!=(const ByteVector &v) const
bool ByteVector::operator==(const char *s) const
{
if(!s)
return isEmpty();
if(size() != ::strlen(s))
return false;

View File

@ -195,23 +195,27 @@ String::String(const wchar_t *s) :
String::String(const wchar_t *s, Type t) :
d(std::make_shared<StringPrivate>())
{
if(t == UTF16 || t == UTF16BE || t == UTF16LE) {
copyFromUTF16(d->data, s, ::wcslen(s), t);
}
else {
debug("String::String() -- const wchar_t * should not contain Latin1 or UTF-8.");
if(s) {
if(t == UTF16 || t == UTF16BE || t == UTF16LE) {
copyFromUTF16(d->data, s, ::wcslen(s), t);
}
else {
debug("String::String() -- const wchar_t * should not contain Latin1 or UTF-8.");
}
}
}
String::String(const char *s, Type t) :
d(std::make_shared<StringPrivate>())
{
if(t == Latin1)
copyFromLatin1(d->data, s, ::strlen(s));
else if(t == String::UTF8)
copyFromUTF8(d->data, s, ::strlen(s));
else {
debug("String::String() -- const char * should not contain UTF16.");
if(s) {
if(t == Latin1)
copyFromLatin1(d->data, s, ::strlen(s));
else if(t == String::UTF8)
copyFromUTF8(d->data, s, ::strlen(s));
else {
debug("String::String() -- const char * should not contain UTF16.");
}
}
}
@ -546,6 +550,10 @@ bool String::operator!=(const String &s) const
bool String::operator==(const char *s) const
{
if(!s) {
return isEmpty();
}
const wchar_t *p = toCWString();
while(*p != L'\0' || *s != '\0') {
@ -562,6 +570,10 @@ bool String::operator!=(const char *s) const
bool String::operator==(const wchar_t *s) const
{
if(!s) {
return isEmpty();
}
return d->data == s;
}
@ -580,18 +592,22 @@ String &String::operator+=(const String &s)
String &String::operator+=(const wchar_t *s)
{
detach();
if(s) {
detach();
d->data += s;
d->data += s;
}
return *this;
}
String &String::operator+=(const char *s)
{
detach();
if(s) {
detach();
for(int i = 0; s[i] != 0; i++)
d->data += static_cast<unsigned char>(s[i]);
for(int i = 0; s[i] != 0; i++)
d->data += static_cast<unsigned char>(s[i]);
}
return *this;
}

View File

@ -30,6 +30,7 @@
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
#include <cstdint>
#include <cstdio>
#include <cstdarg>
#include <cstring>
@ -60,7 +61,7 @@ namespace TagLib
/*!
* Reverses the order of bytes in a 16-bit integer.
*/
inline unsigned short byteSwap(unsigned short x)
inline uint16_t byteSwap(uint16_t x)
{
#if defined(HAVE_GCC_BYTESWAP)
@ -92,7 +93,7 @@ namespace TagLib
/*!
* Reverses the order of bytes in a 32-bit integer.
*/
inline unsigned int byteSwap(unsigned int x)
inline uint32_t byteSwap(uint32_t x)
{
#if defined(HAVE_GCC_BYTESWAP)
@ -127,7 +128,7 @@ namespace TagLib
/*!
* Reverses the order of bytes in a 64-bit integer.
*/
inline unsigned long long byteSwap(unsigned long long x)
inline uint64_t byteSwap(uint64_t x)
{
#if defined(HAVE_GCC_BYTESWAP)

View File

@ -1,33 +1,71 @@
INCLUDE_DIRECTORIES(
SET(test_HDR_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/../taglib
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/toolkit
${CMAKE_CURRENT_SOURCE_DIR}/../bindings/c
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ape
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/asf
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v1
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2/frames
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpc
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mp4
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/riff
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/riff/aiff
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/riff/wav
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/trueaudio
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/vorbis
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/flac
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/speex
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/opus
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/flac
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/wavpack
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mod
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/s3m
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/it
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/xm
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/dsf
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/dsdiff
)
IF(WITH_APE)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ape
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpc
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/wavpack
)
ENDIF()
IF(WITH_ASF)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/asf
)
ENDIF()
IF(WITH_MP4)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mp4
)
ENDIF()
IF(WITH_RIFF)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/riff
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/riff/aiff
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/riff/wav
)
ENDIF()
IF(WITH_TRUEAUDIO)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/trueaudio
)
ENDIF()
IF(WITH_VORBIS)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/vorbis
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/flac
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/speex
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/opus
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/flac
)
ENDIF()
IF(WITH_MOD)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mod
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/s3m
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/it
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/xm
)
ENDIF()
IF(WITH_DSF)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/dsf
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/dsdiff
)
ENDIF()
IF(WITH_SHORTEN)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/shorten
)
ENDIF()
INCLUDE_DIRECTORIES(${test_HDR_DIRS})
SET(test_runner_SRCS
main.cpp
@ -35,7 +73,6 @@ SET(test_runner_SRCS
test_map.cpp
test_mpeg.cpp
test_synchdata.cpp
test_trueaudio.cpp
test_bytevector.cpp
test_bytevectorlist.cpp
test_bytevectorstream.cpp
@ -48,35 +85,73 @@ SET(test_runner_SRCS
test_id3v1.cpp
test_id3v2.cpp
test_id3v2framefactory.cpp
test_xiphcomment.cpp
test_aiff.cpp
test_riff.cpp
test_ogg.cpp
test_oggflac.cpp
test_flac.cpp
test_flacpicture.cpp
test_flacunknownmetadatablock.cpp
test_ape.cpp
test_apetag.cpp
test_wav.cpp
test_info.cpp
test_wavpack.cpp
test_mp4.cpp
test_mp4item.cpp
test_mp4coverart.cpp
test_asf.cpp
test_mod.cpp
test_s3m.cpp
test_it.cpp
test_xm.cpp
test_mpc.cpp
test_opus.cpp
test_speex.cpp
test_dsf.cpp
test_dsdiff.cpp
test_sizes.cpp
test_versionnumber.cpp
)
IF(WITH_TRUEAUDIO)
SET(test_runner_SRCS ${test_runner_SRCS}
test_trueaudio.cpp
)
ENDIF()
IF(WITH_VORBIS)
SET(test_runner_SRCS ${test_runner_SRCS}
test_xiphcomment.cpp
test_ogg.cpp
test_oggflac.cpp
test_flac.cpp
test_flacpicture.cpp
test_flacunknownmetadatablock.cpp
test_opus.cpp
test_speex.cpp
)
ENDIF()
IF(WITH_RIFF)
SET(test_runner_SRCS ${test_runner_SRCS}
test_aiff.cpp
test_riff.cpp
test_wav.cpp
test_info.cpp
)
ENDIF()
if(WITH_APE)
SET(test_runner_SRCS ${test_runner_SRCS}
test_ape.cpp
test_apetag.cpp
test_wavpack.cpp
test_mpc.cpp
)
ENDIF()
IF(WITH_MP4)
SET(test_runner_SRCS ${test_runner_SRCS}
test_mp4.cpp
test_mp4item.cpp
test_mp4coverart.cpp
)
ENDIF()
IF(WITH_ASF)
SET(test_runner_SRCS ${test_runner_SRCS}
test_asf.cpp
)
ENDIF()
IF(WITH_MOD)
SET(test_runner_SRCS ${test_runner_SRCS}
test_mod.cpp
test_s3m.cpp
test_it.cpp
test_xm.cpp
)
ENDIF()
IF(WITH_DSF)
SET(test_runner_SRCS ${test_runner_SRCS}
test_dsf.cpp
test_dsdiff.cpp
)
ENDIF()
IF(WITH_SHORTEN)
SET(test_runner_SRCS ${test_runner_SRCS}
test_shorten.cpp
)
ENDIF()
IF(BUILD_BINDINGS)
SET(test_runner_SRCS ${test_runner_SRCS}
test_tag_c.cpp

File diff suppressed because one or more lines are too long

View File

@ -23,6 +23,7 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <cstring>
#define _USE_MATH_DEFINES
#include <cmath>
@ -53,6 +54,7 @@ class TestByteVector : public CppUnit::TestFixture
CPPUNIT_TEST(testAppend1);
CPPUNIT_TEST(testAppend2);
CPPUNIT_TEST(testBase64);
CPPUNIT_TEST(testEmpty);
CPPUNIT_TEST_SUITE_END();
public:
@ -612,6 +614,94 @@ public:
}
void testEmpty()
{
const ByteVector empty;
const ByteVector notEmpty("A");
ByteVector mutEmpty;
CPPUNIT_ASSERT_EQUAL(empty, ByteVector(""));
CPPUNIT_ASSERT_EQUAL(empty, ByteVector("", 0));
CPPUNIT_ASSERT_EQUAL(empty, ByteVector(0U));
CPPUNIT_ASSERT_EQUAL(empty, ByteVector(empty, 0, 0));
CPPUNIT_ASSERT_EQUAL(empty, ByteVector(notEmpty, 1, 0));
CPPUNIT_ASSERT_EQUAL(empty, ByteVector(static_cast<const char *>(nullptr)));
CPPUNIT_ASSERT_EQUAL(empty, ByteVector(static_cast<const char *>(nullptr), 0));
CPPUNIT_ASSERT_EQUAL(mutEmpty.setData("", 0), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.setData(""), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.setData(nullptr, 0), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.setData(nullptr), empty);
CPPUNIT_ASSERT(!empty.data());
CPPUNIT_ASSERT(!mutEmpty.data());
CPPUNIT_ASSERT_EQUAL(empty.mid(0), empty);
CPPUNIT_ASSERT_EQUAL(empty.at(0), '\0');
// Note that the behavior of ByteVector::find() with an empty pattern is
// not consistent with String::find() and std::string::find().
CPPUNIT_ASSERT_EQUAL(empty.find(mutEmpty), -1);
CPPUNIT_ASSERT_EQUAL(empty.find(notEmpty), -1);
CPPUNIT_ASSERT_EQUAL(notEmpty.find(empty), -1);
CPPUNIT_ASSERT_EQUAL(empty.find('\0'), -1);
CPPUNIT_ASSERT_EQUAL(empty.rfind(mutEmpty), -1);
CPPUNIT_ASSERT_EQUAL(empty.rfind(notEmpty), -1);
CPPUNIT_ASSERT_EQUAL(notEmpty.rfind(empty), -1);
CPPUNIT_ASSERT_EQUAL(empty.containsAt(mutEmpty, 0), false);
CPPUNIT_ASSERT_EQUAL(empty.startsWith(mutEmpty), false);
CPPUNIT_ASSERT_EQUAL(empty.startsWith(notEmpty), false);
CPPUNIT_ASSERT_EQUAL(notEmpty.startsWith(empty), false);
CPPUNIT_ASSERT_EQUAL(empty.endsWith(mutEmpty), false);
CPPUNIT_ASSERT_EQUAL(empty.endsWithPartialMatch(mutEmpty), -1);
CPPUNIT_ASSERT_EQUAL(mutEmpty.replace('a', 'b'), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.replace("abc", ""), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.append(empty), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.append(notEmpty), notEmpty);
mutEmpty.clear();
CPPUNIT_ASSERT_EQUAL(mutEmpty, empty);
CPPUNIT_ASSERT_EQUAL(ByteVector(notEmpty).append(empty), notEmpty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.append('A'), notEmpty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.resize(0), empty);
CPPUNIT_ASSERT_EQUAL(empty.size(), 0U);
CPPUNIT_ASSERT(empty.begin() == empty.end());
CPPUNIT_ASSERT(empty.cbegin() == empty.cend());
CPPUNIT_ASSERT(empty.rbegin() == empty.rend());
CPPUNIT_ASSERT(mutEmpty.begin() == mutEmpty.end());
CPPUNIT_ASSERT(mutEmpty.rbegin() == mutEmpty.rend());
CPPUNIT_ASSERT(empty.isEmpty());
CPPUNIT_ASSERT_EQUAL(empty.toUInt(), 0U);
CPPUNIT_ASSERT_EQUAL(empty.toUInt(0, true), 0U);
CPPUNIT_ASSERT_EQUAL(empty.toUInt(0, 0, true), 0U);
CPPUNIT_ASSERT_EQUAL(empty.toShort(), static_cast<short>(0));
CPPUNIT_ASSERT_EQUAL(empty.toShort(0, true), static_cast<short>(0));
CPPUNIT_ASSERT_EQUAL(empty.toUShort(), static_cast<unsigned short>(0));
CPPUNIT_ASSERT_EQUAL(empty.toUShort(0, true), static_cast<unsigned short>(0));
CPPUNIT_ASSERT_EQUAL(empty.toLongLong(), 0LL);
CPPUNIT_ASSERT_EQUAL(empty.toLongLong(0, true), 0LL);
CPPUNIT_ASSERT_EQUAL(empty.toULongLong(), 0ULL);
CPPUNIT_ASSERT_EQUAL(empty.toULongLong(0, true), 0ULL);
CPPUNIT_ASSERT_EQUAL(empty.toFloat32LE(0), 0.f);
CPPUNIT_ASSERT_EQUAL(empty.toFloat32BE(0), 0.f);
CPPUNIT_ASSERT_EQUAL(empty.toFloat64LE(0), 0.);
CPPUNIT_ASSERT_EQUAL(empty.toFloat64BE(0), 0.);
CPPUNIT_ASSERT_EQUAL(empty.toFloat80LE(0), 0.l);
CPPUNIT_ASSERT_EQUAL(empty.toFloat80BE(0), 0.l);
CPPUNIT_ASSERT(empty == mutEmpty);
CPPUNIT_ASSERT(empty != notEmpty);
CPPUNIT_ASSERT(empty == "");
CPPUNIT_ASSERT(empty != " ");
CPPUNIT_ASSERT(empty == static_cast<const char *>(nullptr));
CPPUNIT_ASSERT(!(empty != static_cast<const char *>(nullptr)));
CPPUNIT_ASSERT(empty < notEmpty);
CPPUNIT_ASSERT(!(empty > notEmpty));
CPPUNIT_ASSERT_EQUAL(empty + mutEmpty, empty);
CPPUNIT_ASSERT_EQUAL(empty + notEmpty, notEmpty);
CPPUNIT_ASSERT_EQUAL(mutEmpty = static_cast<const char *>(nullptr), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty = notEmpty, notEmpty);
ByteVector tmp;
mutEmpty.swap(tmp);
CPPUNIT_ASSERT_EQUAL(mutEmpty, empty);
CPPUNIT_ASSERT_EQUAL(empty.toHex(), empty);
CPPUNIT_ASSERT_EQUAL(empty.toBase64(), empty);
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestByteVector);

View File

@ -23,21 +23,30 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "asfpicture.h"
#include "flacpicture.h"
#include "flacfile.h"
#include "taglib_config.h"
#include "tbytevector.h"
#include "tvariant.h"
#include "tzlib.h"
#include "fileref.h"
#include "apetag.h"
#include "asftag.h"
#include "mp4tag.h"
#include "xiphcomment.h"
#include "id3v1tag.h"
#include "id3v2tag.h"
#include "attachedpictureframe.h"
#include "generalencapsulatedobjectframe.h"
#ifdef TAGLIB_WITH_ASF
#include "asfpicture.h"
#include "asftag.h"
#endif
#ifdef TAGLIB_WITH_VORBIS
#include "flacpicture.h"
#include "flacfile.h"
#include "xiphcomment.h"
#endif
#ifdef TAGLIB_WITH_APE
#include "apetag.h"
#endif
#ifdef TAGLIB_WITH_MP4
#include "mp4tag.h"
#endif
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"
@ -69,17 +78,25 @@ class TestComplexProperties : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestComplexProperties);
CPPUNIT_TEST(testReadMp3Picture);
CPPUNIT_TEST(testSetGetId3Geob);
CPPUNIT_TEST(testSetGetId3Picture);
CPPUNIT_TEST(testNonExistent);
#ifdef TAGLIB_WITH_MP4
CPPUNIT_TEST(testReadM4aPicture);
CPPUNIT_TEST(testSetGetMp4Picture);
#endif
#ifdef TAGLIB_WITH_VORBIS
CPPUNIT_TEST(testReadOggPicture);
CPPUNIT_TEST(testReadWriteFlacPicture);
CPPUNIT_TEST(testReadWriteMultipleProperties);
CPPUNIT_TEST(testSetGetId3Geob);
CPPUNIT_TEST(testSetGetId3Picture);
CPPUNIT_TEST(testSetGetApePicture);
CPPUNIT_TEST(testSetGetAsfPicture);
CPPUNIT_TEST(testSetGetMp4Picture);
CPPUNIT_TEST(testSetGetXiphPicture);
CPPUNIT_TEST(testNonExistent);
#endif
#ifdef TAGLIB_WITH_APE
CPPUNIT_TEST(testSetGetApePicture);
#endif
#ifdef TAGLIB_WITH_ASF
CPPUNIT_TEST(testSetGetAsfPicture);
#endif
CPPUNIT_TEST_SUITE_END();
public:
@ -103,6 +120,7 @@ public:
}
}
#ifdef TAGLIB_WITH_MP4
void testReadM4aPicture()
{
const ByteVector expectedData1(
@ -145,7 +163,9 @@ public:
CPPUNIT_ASSERT_EQUAL(String("image/jpeg"),
picture.value("mimeType").value<String>());
}
#endif
#ifdef TAGLIB_WITH_VORBIS
void testReadOggPicture()
{
FileRef f(TEST_FILE_PATH_C("lowercase-fields.ogg"), false);
@ -217,6 +237,7 @@ public:
CPPUNIT_ASSERT(f.pictureList().isEmpty());
}
}
#endif
void testReadWriteMultipleProperties()
{
@ -311,6 +332,7 @@ public:
CPPUNIT_ASSERT_EQUAL(ID3v2::AttachedPictureFrame::FrontCover, frame->type());
}
#ifdef TAGLIB_WITH_APE
void testSetGetApePicture()
{
const String FRONT_COVER("COVER ART (FRONT)");
@ -326,7 +348,9 @@ public:
.append(picture.value("data").value<ByteVector>()),
item.binaryData());
}
#endif
#ifdef TAGLIB_WITH_ASF
void testSetGetAsfPicture()
{
VariantMap picture(TEST_PICTURE);
@ -344,7 +368,9 @@ public:
asfPicture.description());
CPPUNIT_ASSERT_EQUAL(ASF::Picture::FrontCover, asfPicture.type());
}
#endif
#ifdef TAGLIB_WITH_MP4
void testSetGetMp4Picture()
{
VariantMap picture(TEST_PICTURE);
@ -360,7 +386,9 @@ public:
covr.data());
CPPUNIT_ASSERT_EQUAL(MP4::CoverArt::JPEG, covr.format());
}
#endif
#ifdef TAGLIB_WITH_VORBIS
void testSetGetXiphPicture()
{
VariantMap picture(TEST_PICTURE);
@ -386,6 +414,7 @@ public:
CPPUNIT_ASSERT_EQUAL(1, pic->width());
CPPUNIT_ASSERT_EQUAL(1, pic->height());
}
#endif
void testNonExistent()
{

View File

@ -26,27 +26,44 @@
#include <string>
#include <cstdio>
#include "taglib_config.h"
#include "tfilestream.h"
#include "tbytevectorstream.h"
#include "tag.h"
#include "fileref.h"
#include "mpegfile.h"
#ifdef TAGLIB_WITH_VORBIS
#include "oggflacfile.h"
#include "vorbisfile.h"
#include "mpegfile.h"
#include "mpcfile.h"
#include "asffile.h"
#include "speexfile.h"
#include "flacfile.h"
#include "trueaudiofile.h"
#include "mp4file.h"
#include "wavfile.h"
#include "apefile.h"
#include "aifffile.h"
#include "wavpackfile.h"
#include "opusfile.h"
#endif
#ifdef TAGLIB_WITH_APE
#include "mpcfile.h"
#include "apefile.h"
#include "wavpackfile.h"
#endif
#ifdef TAGLIB_WITH_ASF
#include "asffile.h"
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
#include "trueaudiofile.h"
#endif
#ifdef TAGLIB_WITH_MP4
#include "mp4file.h"
#endif
#ifdef TAGLIB_WITH_RIFF
#include "wavfile.h"
#include "aifffile.h"
#endif
#ifdef TAGLIB_WITH_MOD
#include "xmfile.h"
#endif
#ifdef TAGLIB_WITH_DSF
#include "dsffile.h"
#include "dsdifffile.h"
#endif
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"
@ -55,6 +72,7 @@ using namespace TagLib;
namespace
{
#ifdef TAGLIB_WITH_VORBIS
class DummyResolver : public FileRef::FileTypeResolver
{
public:
@ -63,7 +81,9 @@ namespace
return new Ogg::Vorbis::File(fileName);
}
};
#endif
#ifdef TAGLIB_WITH_MP4
class DummyStreamResolver : public FileRef::StreamTypeResolver
{
public:
@ -77,36 +97,51 @@ namespace
return new MP4::File(s);
}
};
#endif
} // namespace
class TestFileRef : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestFileRef);
CPPUNIT_TEST(testASF);
CPPUNIT_TEST(testMusepack);
CPPUNIT_TEST(testVorbis);
CPPUNIT_TEST(testSpeex);
CPPUNIT_TEST(testFLAC);
CPPUNIT_TEST(testMP3);
CPPUNIT_TEST(testOGA_FLAC);
CPPUNIT_TEST(testOGA_Vorbis);
CPPUNIT_TEST(testMP4_1);
CPPUNIT_TEST(testMP4_2);
CPPUNIT_TEST(testMP4_3);
CPPUNIT_TEST(testMP4_4);
CPPUNIT_TEST(testTrueAudio);
CPPUNIT_TEST(testAPE);
CPPUNIT_TEST(testWav);
CPPUNIT_TEST(testAIFF_1);
CPPUNIT_TEST(testAIFF_2);
CPPUNIT_TEST(testWavPack);
CPPUNIT_TEST(testOpus);
CPPUNIT_TEST(testDSF);
CPPUNIT_TEST(testDSDIFF);
CPPUNIT_TEST(testUnsupported);
CPPUNIT_TEST(testAudioProperties);
CPPUNIT_TEST(testDefaultFileExtensions);
CPPUNIT_TEST(testFileResolver);
#ifdef TAGLIB_WITH_ASF
CPPUNIT_TEST(testASF);
#endif
#ifdef TAGLIB_WITH_APE
CPPUNIT_TEST(testMusepack);
CPPUNIT_TEST(testAPE);
CPPUNIT_TEST(testWavPack);
#endif
#ifdef TAGLIB_WITH_VORBIS
CPPUNIT_TEST(testVorbis);
CPPUNIT_TEST(testSpeex);
CPPUNIT_TEST(testFLAC);
CPPUNIT_TEST(testOGA_FLAC);
CPPUNIT_TEST(testOGA_Vorbis);
CPPUNIT_TEST(testOpus);
#endif
#ifdef TAGLIB_WITH_MP4
CPPUNIT_TEST(testMP4_1);
CPPUNIT_TEST(testMP4_2);
CPPUNIT_TEST(testMP4_3);
CPPUNIT_TEST(testMP4_4);
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
CPPUNIT_TEST(testTrueAudio);
#endif
#ifdef TAGLIB_WITH_RIFF
CPPUNIT_TEST(testWav);
CPPUNIT_TEST(testAIFF_1);
CPPUNIT_TEST(testAIFF_2);
#endif
#ifdef TAGLIB_WITH_DSF
CPPUNIT_TEST(testDSF);
CPPUNIT_TEST(testDSDIFF);
#endif
CPPUNIT_TEST_SUITE_END();
public:
@ -239,16 +274,21 @@ public:
}
}
#ifdef TAGLIB_WITH_APE
void testMusepack()
{
fileRefSave<MPC::File>("click", ".mpc");
}
#endif
#ifdef TAGLIB_WITH_ASF
void testASF()
{
fileRefSave<ASF::File>("silence-1", ".wma");
}
#endif
#ifdef TAGLIB_WITH_VORBIS
void testVorbis()
{
fileRefSave<Ogg::Vorbis::File>("empty", ".ogg");
@ -263,17 +303,21 @@ public:
{
fileRefSave<FLAC::File>("no-tags", ".flac");
}
#endif
void testMP3()
{
fileRefSave<MPEG::File>("xing", ".mp3");
}
#ifdef TAGLIB_WITH_TRUEAUDIO
void testTrueAudio()
{
fileRefSave<TrueAudio::File>("empty", ".tta");
}
#endif
#ifdef TAGLIB_WITH_MP4
void testMP4_1()
{
fileRefSave<MP4::File>("has-tags", ".m4a");
@ -293,12 +337,16 @@ public:
{
fileRefSave<MP4::File>("blank_video", ".m4v");
}
#endif
#ifdef TAGLIB_WITH_RIFF
void testWav()
{
fileRefSave<RIFF::WAV::File>("empty", ".wav");
}
#endif
#ifdef TAGLIB_WITH_VORBIS
void testOGA_FLAC()
{
fileRefSave<Ogg::FLAC::File>("empty_flac", ".oga");
@ -308,12 +356,16 @@ public:
{
fileRefSave<Ogg::Vorbis::File>("empty_vorbis", ".oga");
}
#endif
#ifdef TAGLIB_WITH_APE
void testAPE()
{
fileRefSave<APE::File>("mac-399", ".ape");
}
#endif
#ifdef TAGLIB_WITH_RIFF
void testAIFF_1()
{
fileRefSave<RIFF::AIFF::File>("empty", ".aiff");
@ -323,17 +375,23 @@ public:
{
fileRefSave<RIFF::AIFF::File>("alaw", ".aifc");
}
#endif
#ifdef TAGLIB_WITH_APE
void testWavPack()
{
fileRefSave<WavPack::File>("click", ".wv");
}
#endif
#ifdef TAGLIB_WITH_VORBIS
void testOpus()
{
fileRefSave<Ogg::Opus::File>("correctness_gain_silent_output", ".opus");
}
#endif
#ifdef TAGLIB_WITH_DSF
void testDSF()
{
fileRefSave<DSF::File>("empty10ms",".dsf");
@ -343,6 +401,7 @@ public:
{
fileRefSave<DSDIFF::File>("empty10ms",".dff");
}
#endif
void testUnsupported()
{
@ -364,27 +423,56 @@ public:
void testDefaultFileExtensions()
{
const StringList extensions = FileRef::defaultFileExtensions();
#ifdef TAGLIB_WITH_APE
CPPUNIT_ASSERT(extensions.contains("mpc"));
#endif
#ifdef TAGLIB_WITH_ASF
CPPUNIT_ASSERT(extensions.contains("wma"));
#endif
#ifdef TAGLIB_WITH_VORBIS
CPPUNIT_ASSERT(extensions.contains("ogg"));
CPPUNIT_ASSERT(extensions.contains("spx"));
CPPUNIT_ASSERT(extensions.contains("flac"));
#endif
CPPUNIT_ASSERT(extensions.contains("mp3"));
#ifdef TAGLIB_WITH_TRUEAUDIO
CPPUNIT_ASSERT(extensions.contains("tta"));
#endif
#ifdef TAGLIB_WITH_MP4
CPPUNIT_ASSERT(extensions.contains("m4a"));
CPPUNIT_ASSERT(extensions.contains("3g2"));
CPPUNIT_ASSERT(extensions.contains("m4v"));
#endif
#ifdef TAGLIB_WITH_RIFF
CPPUNIT_ASSERT(extensions.contains("wav"));
#endif
#ifdef TAGLIB_WITH_VORBIS
CPPUNIT_ASSERT(extensions.contains("oga"));
#endif
#ifdef TAGLIB_WITH_APE
CPPUNIT_ASSERT(extensions.contains("ape"));
#endif
#ifdef TAGLIB_WITH_RIFF
CPPUNIT_ASSERT(extensions.contains("aiff"));
CPPUNIT_ASSERT(extensions.contains("aifc"));
#endif
#ifdef TAGLIB_WITH_APE
CPPUNIT_ASSERT(extensions.contains("wv"));
#endif
#ifdef TAGLIB_WITH_VORBIS
CPPUNIT_ASSERT(extensions.contains("opus"));
#endif
#ifdef TAGLIB_WITH_MOD
CPPUNIT_ASSERT(extensions.contains("xm"));
#endif
#ifdef TAGLIB_WITH_DSF
CPPUNIT_ASSERT(extensions.contains("dsf"));
CPPUNIT_ASSERT(extensions.contains("dff"));
CPPUNIT_ASSERT(extensions.contains("dsdiff"));
#endif
#ifdef TAGLIB_WITH_SHORTEN
CPPUNIT_ASSERT(extensions.contains("shn"));
#endif
}
void testFileResolver()
@ -394,6 +482,7 @@ public:
CPPUNIT_ASSERT(dynamic_cast<MPEG::File *>(f.file()) != nullptr);
}
#ifdef TAGLIB_WITH_VORBIS
DummyResolver resolver;
FileRef::addFileTypeResolver(&resolver);
@ -401,7 +490,9 @@ public:
FileRef f(TEST_FILE_PATH_C("xing.mp3"));
CPPUNIT_ASSERT(dynamic_cast<Ogg::Vorbis::File *>(f.file()) != nullptr);
}
#endif
#ifdef TAGLIB_WITH_MP4
DummyStreamResolver streamResolver;
FileRef::addFileTypeResolver(&streamResolver);
@ -410,6 +501,7 @@ public:
FileRef f(&s);
CPPUNIT_ASSERT(dynamic_cast<MP4::File *>(f.file()) != nullptr);
}
#endif
FileRef::clearFileTypeResolvers();
}

View File

@ -26,21 +26,30 @@
#include <functional>
#include <memory>
#include "flacproperties.h"
#include "taglib_config.h"
#include "mpegproperties.h"
#include "tbytevector.h"
#include "tpropertymap.h"
#include "mpegfile.h"
#include "flacfile.h"
#include "trueaudiofile.h"
#include "trueaudioproperties.h"
#include "wavfile.h"
#include "aifffile.h"
#include "dsffile.h"
#include "dsdifffile.h"
#include "id3v2tag.h"
#include "id3v2frame.h"
#include "id3v2framefactory.h"
#ifdef TAGLIB_WITH_VORBIS
#include "flacproperties.h"
#include "flacfile.h"
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
#include "trueaudiofile.h"
#include "trueaudioproperties.h"
#endif
#ifdef TAGLIB_WITH_RIFF
#include "wavfile.h"
#include "aifffile.h"
#endif
#ifdef TAGLIB_WITH_DSF
#include "dsffile.h"
#include "dsdifffile.h"
#endif
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"
@ -118,12 +127,20 @@ class TestId3v2FrameFactory : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestId3v2FrameFactory);
CPPUNIT_TEST(testMPEG);
#ifdef TAGLIB_WITH_VORBIS
CPPUNIT_TEST(testFLAC);
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
CPPUNIT_TEST(testTrueAudio);
#endif
#ifdef TAGLIB_WITH_RIFF
CPPUNIT_TEST(testWAV);
CPPUNIT_TEST(testAIFF);
#endif
#ifdef TAGLIB_WITH_DSF
CPPUNIT_TEST(testDSF);
CPPUNIT_TEST(testDSDIFF);
#endif
CPPUNIT_TEST_SUITE_END();
public:
@ -236,6 +253,7 @@ public:
);
}
#ifdef TAGLIB_WITH_VORBIS
void testFLAC()
{
ScopedFileCopy copy("no-tags", ".flac");
@ -260,7 +278,9 @@ public:
}
);
}
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
void testTrueAudio()
{
ScopedFileCopy copy("empty", ".tta");
@ -285,7 +305,9 @@ public:
}
);
}
#endif
#ifdef TAGLIB_WITH_RIFF
void testWAV()
{
ScopedFileCopy copy("empty", ".wav");
@ -335,7 +357,9 @@ public:
}
);
}
#endif
#ifdef TAGLIB_WITH_DSF
void testDSF()
{
ScopedFileCopy copy("empty10ms", ".dsf");
@ -385,6 +409,7 @@ public:
}
);
}
#endif
};

View File

@ -27,12 +27,15 @@
#include <cstdio>
#include <array>
#include "taglib_config.h"
#include "tstring.h"
#include "tpropertymap.h"
#include "mpegfile.h"
#include "id3v2tag.h"
#include "id3v1tag.h"
#ifdef TAGLIB_WITH_APE
#include "apetag.h"
#endif
#include "mpegproperties.h"
#include "xingheader.h"
#include "mpegheader.h"
@ -67,7 +70,9 @@ class TestMPEG : public CppUnit::TestFixture
CPPUNIT_TEST(testRepeatedSave3);
CPPUNIT_TEST(testEmptyID3v2);
CPPUNIT_TEST(testEmptyID3v1);
#ifdef TAGLIB_WITH_APE
CPPUNIT_TEST(testEmptyAPE);
#endif
CPPUNIT_TEST(testIgnoreGarbage);
CPPUNIT_TEST(testExtendedHeader);
CPPUNIT_TEST(testReadStyleFast);
@ -304,7 +309,9 @@ public:
{
MPEG::File f(copy.fileName().c_str());
f.ID3v2Tag(true)->setTitle("ID3v2");
#ifdef TAGLIB_WITH_APE
f.APETag(true)->setTitle("APE");
#endif
f.ID3v1Tag(true)->setTitle("ID3v1");
f.save();
}
@ -312,8 +319,10 @@ public:
MPEG::File f(copy.fileName().c_str());
CPPUNIT_ASSERT_EQUAL(String("ID3v2"), f.properties()["TITLE"].front());
f.strip(MPEG::File::ID3v2);
#ifdef TAGLIB_WITH_APE
CPPUNIT_ASSERT_EQUAL(String("APE"), f.properties()["TITLE"].front());
f.strip(MPEG::File::APE);
#endif
CPPUNIT_ASSERT_EQUAL(String("ID3v1"), f.properties()["TITLE"].front());
f.strip(MPEG::File::ID3v1);
CPPUNIT_ASSERT(f.properties().isEmpty());
@ -464,17 +473,23 @@ public:
CPPUNIT_ASSERT(!f.hasAPETag());
CPPUNIT_ASSERT(!f.hasID3v1Tag());
#ifdef TAGLIB_WITH_APE
f.APETag(true)->setTitle("01234 56789 ABCDE FGHIJ");
f.save();
f.APETag()->setTitle("0");
f.save();
#endif
f.ID3v1Tag(true)->setTitle("01234 56789 ABCDE FGHIJ");
#ifdef TAGLIB_WITH_APE
f.APETag()->setTitle("01234 56789 ABCDE FGHIJ 01234 56789 ABCDE FGHIJ 01234 56789");
#endif
f.save();
}
{
MPEG::File f(copy.fileName().c_str());
#ifdef TAGLIB_WITH_APE
CPPUNIT_ASSERT(f.hasAPETag());
#endif
CPPUNIT_ASSERT(f.hasID3v1Tag());
}
}
@ -519,6 +534,7 @@ public:
}
}
#ifdef TAGLIB_WITH_APE
void testEmptyAPE()
{
ScopedFileCopy copy("xing", ".mp3");
@ -538,6 +554,7 @@ public:
CPPUNIT_ASSERT(!f.hasAPETag());
}
}
#endif
void testIgnoreGarbage()
{

View File

@ -23,15 +23,26 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "taglib_config.h"
#include "tpropertymap.h"
#include "tag.h"
#include "apetag.h"
#include "asftag.h"
#include "id3v1tag.h"
#include "id3v2tag.h"
#ifdef TAGLIB_WITH_APE
#include "apetag.h"
#endif
#ifdef TAGLIB_WITH_ASF
#include "asftag.h"
#endif
#ifdef TAGLIB_WITH_RIFF
#include "infotag.h"
#endif
#ifdef TAGLIB_WITH_MP4
#include "mp4tag.h"
#endif
#ifdef TAGLIB_WITH_VORBIS
#include "xiphcomment.h"
#endif
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"
@ -41,14 +52,24 @@ class TestPropertyMap : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestPropertyMap);
CPPUNIT_TEST(testInvalidKeys);
CPPUNIT_TEST(testGetSetApe);
CPPUNIT_TEST(testGetSetAsf);
CPPUNIT_TEST(testGetSetId3v1);
CPPUNIT_TEST(testGetSetId3v2);
CPPUNIT_TEST(testGetSetInfo);
CPPUNIT_TEST(testGetSetMp4);
CPPUNIT_TEST(testGetSetXiphComment);
CPPUNIT_TEST(testGetSet);
#ifdef TAGLIB_WITH_APE
CPPUNIT_TEST(testGetSetApe);
#endif
#ifdef TAGLIB_WITH_ASF
CPPUNIT_TEST(testGetSetAsf);
#endif
#ifdef TAGLIB_WITH_RIFF
CPPUNIT_TEST(testGetSetInfo);
#endif
#ifdef TAGLIB_WITH_MP4
CPPUNIT_TEST(testGetSetMp4);
#endif
#ifdef TAGLIB_WITH_VORBIS
CPPUNIT_TEST(testGetSetXiphComment);
#endif
CPPUNIT_TEST_SUITE_END();
public:
@ -141,30 +162,40 @@ public:
tagGetSet<ID3v2::Tag>();
}
#ifdef TAGLIB_WITH_VORBIS
void testGetSetXiphComment()
{
tagGetSet<Ogg::XiphComment>();
}
#endif
#ifdef TAGLIB_WITH_APE
void testGetSetApe()
{
tagGetSet<APE::Tag>();
}
#endif
#ifdef TAGLIB_WITH_ASF
void testGetSetAsf()
{
tagGetSet<ASF::Tag>();
}
#endif
#ifdef TAGLIB_WITH_MP4
void testGetSetMp4()
{
tagGetSet<MP4::Tag>();
}
#endif
#ifdef TAGLIB_WITH_RIFF
void testGetSetInfo()
{
tagGetSet<RIFF::Info::Tag>();
}
#endif
void testGetSet()
{

44
tests/test_shorten.cpp Normal file
View File

@ -0,0 +1,44 @@
#include <string>
#include <cstdio>
#include "tbytevectorlist.h"
#include "tpropertymap.h"
#include "tag.h"
#include "shortenfile.h"
#include "plainfile.h"
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"
using namespace std;
using namespace TagLib;
class TestShorten : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestShorten);
CPPUNIT_TEST(testBasic);
CPPUNIT_TEST(testTags);
CPPUNIT_TEST_SUITE_END();
public:
void testBasic()
{
Shorten::File f(TEST_FILE_PATH_C("2sec-silence.shn"));
CPPUNIT_ASSERT(f.audioProperties());
CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->lengthInSeconds());
CPPUNIT_ASSERT_EQUAL(2000, f.audioProperties()->lengthInMilliseconds());
CPPUNIT_ASSERT_EQUAL(1411, f.audioProperties()->bitrate());
CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->shortenVersion());
CPPUNIT_ASSERT_EQUAL(5, f.audioProperties()->fileType());
CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->bitsPerSample());
CPPUNIT_ASSERT_EQUAL(static_cast<unsigned long>(88200), f.audioProperties()->sampleFrames());
}
void testTags()
{
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestShorten);

View File

@ -25,34 +25,25 @@
#include <cstring>
#include "aifffile.h"
#include "aiffproperties.h"
#include "apefile.h"
#include "apefooter.h"
#include "apeitem.h"
#include "apeproperties.h"
#include "apetag.h"
#include "asfattribute.h"
#include "asffile.h"
#include "asfpicture.h"
#include "asfproperties.h"
#include "asftag.h"
#include "attachedpictureframe.h"
#include "audioproperties.h"
#include "chapterframe.h"
#include "commentsframe.h"
#include "dsffile.h"
#include "dsfproperties.h"
#include "dsdifffile.h"
#include "dsdiffproperties.h"
#include "eventtimingcodesframe.h"
#include "taglib_config.h"
#include "tag.h"
#include "tbytevector.h"
#include "tbytevectorlist.h"
#include "tbytevectorstream.h"
#include "tdebuglistener.h"
#include "tfile.h"
#include "tfilestream.h"
#include "tiostream.h"
#include "tlist.h"
#include "tmap.h"
#include "tpropertymap.h"
#include "tstring.h"
#include "tstringlist.h"
#include "fileref.h"
#include "flacfile.h"
#include "flacmetadatablock.h"
#include "flacunknownmetadatablock.h"
#include "flacpicture.h"
#include "flacproperties.h"
#include "generalencapsulatedobjectframe.h"
#include "mpegfile.h"
#include "mpegheader.h"
#include "mpegproperties.h"
#include "xingheader.h"
#include "id3v1tag.h"
#include "id3v2extendedheader.h"
#include "id3v2footer.h"
@ -60,72 +51,103 @@
#include "id3v2framefactory.h"
#include "id3v2header.h"
#include "id3v2tag.h"
#include "attachedpictureframe.h"
#include "audioproperties.h"
#include "chapterframe.h"
#include "commentsframe.h"
#include "eventtimingcodesframe.h"
#include "generalencapsulatedobjectframe.h"
#include "ownershipframe.h"
#include "podcastframe.h"
#include "popularimeterframe.h"
#include "privateframe.h"
#include "relativevolumeframe.h"
#include "synchronizedlyricsframe.h"
#include "tableofcontentsframe.h"
#include "textidentificationframe.h"
#include "uniquefileidentifierframe.h"
#include "unknownframe.h"
#include "unsynchronizedlyricsframe.h"
#include "urllinkframe.h"
#ifdef TAGLIB_WITH_RIFF
#include "aifffile.h"
#include "aiffproperties.h"
#include "infotag.h"
#include "itfile.h"
#include "itproperties.h"
#include "modfile.h"
#include "modfilebase.h"
#include "modproperties.h"
#include "modtag.h"
#include "mp4coverart.h"
#include "mp4file.h"
#include "mp4item.h"
#include "mp4itemfactory.h"
#include "mp4properties.h"
#include "mp4tag.h"
#include "rifffile.h"
#include "wavfile.h"
#include "wavproperties.h"
#endif
#ifdef TAGLIB_WITH_APE
#include "apefile.h"
#include "apefooter.h"
#include "apeitem.h"
#include "apeproperties.h"
#include "apetag.h"
#include "mpcfile.h"
#include "mpcproperties.h"
#include "mpegfile.h"
#include "mpegheader.h"
#include "mpegproperties.h"
#include "wavpackfile.h"
#include "wavpackproperties.h"
#endif
#ifdef TAGLIB_WITH_ASF
#include "asfattribute.h"
#include "asffile.h"
#include "asfpicture.h"
#include "asfproperties.h"
#include "asftag.h"
#endif
#ifdef TAGLIB_WITH_DSF
#include "dsffile.h"
#include "dsfproperties.h"
#include "dsdifffile.h"
#include "dsdiffproperties.h"
#endif
#ifdef TAGLIB_WITH_VORBIS
#include "flacfile.h"
#include "flacmetadatablock.h"
#include "flacunknownmetadatablock.h"
#include "flacpicture.h"
#include "flacproperties.h"
#include "oggfile.h"
#include "oggflacfile.h"
#include "oggpage.h"
#include "oggpageheader.h"
#include "opusfile.h"
#include "opusproperties.h"
#include "ownershipframe.h"
#include "podcastframe.h"
#include "popularimeterframe.h"
#include "privateframe.h"
#include "relativevolumeframe.h"
#include "rifffile.h"
#include "s3mfile.h"
#include "s3mproperties.h"
#include "speexfile.h"
#include "speexproperties.h"
#include "synchronizedlyricsframe.h"
#include "tableofcontentsframe.h"
#include "tag.h"
#include "tbytevector.h"
#include "tbytevectorlist.h"
#include "tbytevectorstream.h"
#include "tdebuglistener.h"
#include "textidentificationframe.h"
#include "tfile.h"
#include "tfilestream.h"
#include "tiostream.h"
#include "tlist.h"
#include "tmap.h"
#include "tpropertymap.h"
#include "trueaudiofile.h"
#include "trueaudioproperties.h"
#include "tstring.h"
#include "tstringlist.h"
#include "uniquefileidentifierframe.h"
#include "unknownframe.h"
#include "unsynchronizedlyricsframe.h"
#include "urllinkframe.h"
#include "vorbisfile.h"
#include "vorbisproperties.h"
#include "wavfile.h"
#include "wavpackfile.h"
#include "wavpackproperties.h"
#include "wavproperties.h"
#include "xingheader.h"
#include "xiphcomment.h"
#endif
#ifdef TAGLIB_WITH_MOD
#include "itfile.h"
#include "itproperties.h"
#include "modfile.h"
#include "modfilebase.h"
#include "modproperties.h"
#include "modtag.h"
#include "s3mfile.h"
#include "s3mproperties.h"
#include "xmfile.h"
#include "xmproperties.h"
#endif
#ifdef TAGLIB_WITH_MP4
#include "mp4coverart.h"
#include "mp4file.h"
#include "mp4item.h"
#include "mp4itemfactory.h"
#include "mp4properties.h"
#include "mp4tag.h"
#endif
#ifdef TAGLIB_WITH_SHORTEN
#include "shortenfile.h"
#include "shortenproperties.h"
#include "shortentag.h"
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
#include "trueaudiofile.h"
#include "trueaudioproperties.h"
#endif
#include <cppunit/extensions/HelperMacros.h>
@ -144,31 +166,11 @@ public:
// Class list was built by generating XML docs with Doxygen, and then running:
// $ grep kind=\"class\" index.xml | sed -E -e 's/(.*<name>|<\/name>.*)//g'
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::APE::File));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::APE::Footer));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::APE::Item));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::APE::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::APE::Tag));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::ASF::Attribute));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::ASF::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::ASF::Picture));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::ASF::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::ASF::Tag));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::AudioProperties));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::ByteVector));
CPPUNIT_ASSERT_EQUAL(classSize(2, false), sizeof(TagLib::ByteVectorList));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::ByteVectorStream));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::DebugListener));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSDIFF::DIIN::Tag));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSDIFF::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSDIFF::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSF::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSF::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::FLAC::MetadataBlock));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::Picture));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::UnknownMetadataBlock));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::FileRef));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::FileRef::FileTypeResolver));
@ -204,26 +206,47 @@ public:
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::ID3v2::UserTextIdentificationFrame));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::ID3v2::UserUrlLinkFrame));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::IOStream));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::IT::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::IT::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::List<int>));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::MP4::CoverArt));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MP4::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::MP4::Item));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::MP4::ItemFactory));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MP4::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MP4::Tag));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MPC::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MPC::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MPEG::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::MPEG::Header));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MPEG::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::MPEG::XingHeader));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::Map<int, int>));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::Mod::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Mod::FileBase));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Mod::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Mod::Tag));
CPPUNIT_ASSERT_EQUAL(classSize(2, false), sizeof(TagLib::PropertyMap));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::String));
CPPUNIT_ASSERT_EQUAL(classSize(2, false), sizeof(TagLib::StringList));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::Tag));
#ifdef TAGLIB_WITH_APE
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::APE::File));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::APE::Footer));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::APE::Item));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::APE::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::APE::Tag));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MPC::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MPC::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::WavPack::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::WavPack::Properties));
#endif
#ifdef TAGLIB_WITH_ASF
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::ASF::Attribute));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::ASF::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::ASF::Picture));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::ASF::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::ASF::Tag));
#endif
#ifdef TAGLIB_WITH_DSF
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSDIFF::DIIN::Tag));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSDIFF::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSDIFF::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSF::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSF::Properties));
#endif
#ifdef TAGLIB_WITH_VORBIS
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::File));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::FLAC::MetadataBlock));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::Picture));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::UnknownMetadataBlock));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::Ogg::FLAC::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Ogg::File));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::Ogg::Opus::File));
@ -235,7 +258,29 @@ public:
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::Ogg::Vorbis::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Ogg::Vorbis::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Ogg::XiphComment));
CPPUNIT_ASSERT_EQUAL(classSize(2, false), sizeof(TagLib::PropertyMap));
#endif
#ifdef TAGLIB_WITH_MOD
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::IT::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::IT::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::Mod::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Mod::FileBase));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Mod::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Mod::Tag));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::S3M::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::S3M::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::XM::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::XM::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::Variant));
#endif
#ifdef TAGLIB_WITH_MP4
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::MP4::CoverArt));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MP4::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::MP4::Item));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::MP4::ItemFactory));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MP4::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::MP4::Tag));
#endif
#ifdef TAGLIB_WITH_RIFF
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::RIFF::AIFF::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::RIFF::AIFF::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::RIFF::File));
@ -243,18 +288,16 @@ public:
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::RIFF::Info::Tag));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::RIFF::WAV::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::RIFF::WAV::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::S3M::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::S3M::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::String));
CPPUNIT_ASSERT_EQUAL(classSize(2, false), sizeof(TagLib::StringList));
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::Tag));
#endif
#ifdef TAGLIB_WITH_SHORTEN
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Shorten::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Shorten::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Shorten::Tag));
#endif
#ifdef TAGLIB_WITH_TRUEAUDIO
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::TrueAudio::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::TrueAudio::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::WavPack::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::WavPack::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(2, true), sizeof(TagLib::XM::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::XM::Properties));
CPPUNIT_ASSERT_EQUAL(classSize(1, false), sizeof(TagLib::Variant));
#endif
}
private:

View File

@ -23,9 +23,12 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <string>
#include <cstring>
#include "tstring.h"
#include "tstringlist.h"
#include "tbytevector.h"
#include "tutils.h"
#include <cppunit/extensions/HelperMacros.h>
@ -54,6 +57,7 @@ class TestString : public CppUnit::TestFixture
CPPUNIT_TEST(testEncodeNonBMP);
CPPUNIT_TEST(testIterator);
CPPUNIT_TEST(testInvalidUTF8);
CPPUNIT_TEST(testEmpty);
CPPUNIT_TEST_SUITE_END();
public:
@ -370,6 +374,80 @@ public:
CPPUNIT_ASSERT(String(ByteVector("\xED\xB0\x80\xED\xA0\x80"), String::UTF8).isEmpty());
}
void testEmpty()
{
const String empty;
const String notEmpty("A");
String mutEmpty;
CPPUNIT_ASSERT_EQUAL(empty, String(""));
CPPUNIT_ASSERT_EQUAL(empty, String(std::wstring()));
CPPUNIT_ASSERT_EQUAL(empty, String(static_cast<const wchar_t *>(nullptr)));
CPPUNIT_ASSERT(empty != String('\0'));
CPPUNIT_ASSERT_EQUAL(empty, String(L'\0'));
CPPUNIT_ASSERT_EQUAL(empty, String(static_cast<const char *>(nullptr)));
CPPUNIT_ASSERT_EQUAL(empty, String(ByteVector()));
CPPUNIT_ASSERT_EQUAL(empty.to8Bit(), std::string());
CPPUNIT_ASSERT_EQUAL(empty.toWString(), std::wstring());
CPPUNIT_ASSERT_EQUAL(::strlen(empty.toCString()), (size_t)0);
CPPUNIT_ASSERT_EQUAL(::wcslen(empty.toCWString()), (size_t)0);
CPPUNIT_ASSERT(empty.begin() == empty.end());
CPPUNIT_ASSERT(empty.cbegin() == empty.cend());
CPPUNIT_ASSERT(mutEmpty.begin() == mutEmpty.end());
CPPUNIT_ASSERT_EQUAL(empty.find(mutEmpty), 0);
CPPUNIT_ASSERT_EQUAL(empty.find(notEmpty), -1);
CPPUNIT_ASSERT_EQUAL(notEmpty.find(empty), 0);
CPPUNIT_ASSERT_EQUAL(empty.rfind(mutEmpty), 0);
CPPUNIT_ASSERT_EQUAL(empty.rfind(notEmpty), -1);
CPPUNIT_ASSERT_EQUAL(notEmpty.rfind(empty), 1);
CPPUNIT_ASSERT_EQUAL(empty.split(), StringList(empty));
CPPUNIT_ASSERT_EQUAL(empty.startsWith(mutEmpty), true);
CPPUNIT_ASSERT_EQUAL(empty.startsWith(notEmpty), false);
CPPUNIT_ASSERT_EQUAL(notEmpty.startsWith(empty), true);
CPPUNIT_ASSERT_EQUAL(empty.substr(0), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.append(empty), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty.append(notEmpty), notEmpty);
mutEmpty.clear();
CPPUNIT_ASSERT_EQUAL(mutEmpty, empty);
CPPUNIT_ASSERT_EQUAL(String(notEmpty).append(empty), notEmpty);
CPPUNIT_ASSERT_EQUAL(empty.upper(), empty);
CPPUNIT_ASSERT_EQUAL(empty.size(), 0U);
CPPUNIT_ASSERT_EQUAL(empty.length(), 0U);
CPPUNIT_ASSERT_EQUAL(empty.isEmpty(), true);
CPPUNIT_ASSERT_EQUAL(empty.data(String::Latin1), ByteVector());
CPPUNIT_ASSERT_EQUAL(empty.data(String::UTF16LE), ByteVector());
bool ok;
empty.toInt(&ok);
CPPUNIT_ASSERT(!ok);
CPPUNIT_ASSERT_EQUAL(empty.stripWhiteSpace(), empty);
CPPUNIT_ASSERT_EQUAL(empty.isLatin1(), true);
CPPUNIT_ASSERT_EQUAL(empty.isAscii(), true);
CPPUNIT_ASSERT(empty == mutEmpty);
CPPUNIT_ASSERT(empty != notEmpty);
CPPUNIT_ASSERT(empty == "");
CPPUNIT_ASSERT(empty != " ");
CPPUNIT_ASSERT(empty == L"");
CPPUNIT_ASSERT(empty != L" ");
CPPUNIT_ASSERT(empty == static_cast<const char *>(nullptr));
CPPUNIT_ASSERT(!(empty != static_cast<const char *>(nullptr)));
CPPUNIT_ASSERT(empty == static_cast<const wchar_t *>(nullptr));
CPPUNIT_ASSERT(!(empty != static_cast<const wchar_t *>(nullptr)));
CPPUNIT_ASSERT_EQUAL(mutEmpty += empty, empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty += notEmpty, notEmpty);
mutEmpty.clear();
CPPUNIT_ASSERT_EQUAL(mutEmpty += static_cast<const char *>(nullptr), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty += static_cast<const wchar_t *>(nullptr), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty = static_cast<const char *>(nullptr), empty);
CPPUNIT_ASSERT_EQUAL(mutEmpty = static_cast<const wchar_t *>(nullptr), empty);
String tmp;
mutEmpty.swap(tmp);
CPPUNIT_ASSERT_EQUAL(mutEmpty, empty);
CPPUNIT_ASSERT_EQUAL(empty < notEmpty, true);
CPPUNIT_ASSERT_EQUAL(empty + mutEmpty, empty);
CPPUNIT_ASSERT_EQUAL(empty + notEmpty, notEmpty);
CPPUNIT_ASSERT_EQUAL(empty + static_cast<const char *>(nullptr), empty);
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestString);

View File

@ -27,6 +27,7 @@
#include <unordered_map>
#include <list>
#include "taglib_config.h"
#include "tag_c.h"
#include "tbytevector.h"
#include "tstring.h"
@ -77,7 +78,9 @@ class TestTagC : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestTagC);
CPPUNIT_TEST(testMp3);
#ifdef TAGLIB_WITH_VORBIS
CPPUNIT_TEST(testStream);
#endif
CPPUNIT_TEST_SUITE_END();
public:
@ -165,6 +168,7 @@ public:
taglib_tag_free_strings();
}
#ifdef TAGLIB_WITH_VORBIS
void testStream()
{
// Only fetch the beginning of a FLAC file
@ -233,6 +237,7 @@ public:
taglib_tag_free_strings();
}
#endif
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestTagC);

View File

@ -54,12 +54,14 @@ inline string copyFile(const string &filename, const string &ext)
{
char testFileName[1024];
#ifdef _WIN32
#ifdef TESTS_TMPDIR
snprintf(testFileName, sizeof(testFileName), "%s/taglib-test%s", TESTS_TMPDIR, ext.c_str());
#elif defined _WIN32
char tempDir[MAX_PATH + 1];
GetTempPathA(sizeof(tempDir), tempDir);
wsprintfA(testFileName, "%s\\taglib-test%s", tempDir, ext.c_str());
#else
snprintf(testFileName, sizeof(testFileName), "/%s/taglib-test%s", P_tmpdir, ext.c_str());
snprintf(testFileName, sizeof(testFileName), "%s/taglib-test%s", P_tmpdir, ext.c_str());
#endif
string sourceFileName = testFilePath(filename) + ext;