82 Commits

Author SHA1 Message Date
Urs Fleisch
7d86716194 Version 2.1.1 2025-06-29 17:35:45 +02:00
Urs Fleisch
eb749ac55b Use ldexpl() instead of ldexp()
This will fix "warning: conversion from ‘long double’ to
‘double’ may change value [-Wfloat-conversion]".
2025-06-25 22:08:09 +02:00
Urs Fleisch
148cc9a921 Fix conversion compiler warnings
Using a release build with GCC 14.2.0 and -Wextra -Wconversion -Wall.
The generated binaries are not changed by this commit.
2025-06-25 22:08:09 +02:00
Urs Fleisch
88d6b18b4f Convert IPLS to TIPL and TMCL (#1274)
The involvement/involvee pairs which are supported for TIPL properties
(ARRANGER, ENGINEER, PRODUCER, DJ-MIX, MIX) are left in the TIPL
frame, other pairs are moved to a TMCL frame. This will result in a
consistent behavior for both ID3v2.3 and ID3v2.4 tags produced by
MusicBrainz Picard.
2025-06-21 10:45:43 +02:00
Urs Fleisch
d61a333f27 Map lowercase MusicBrainz TIPL keys to properties (#1274) 2025-06-21 10:45:43 +02:00
Urs Fleisch
e73517d058 CMake targets with TAGLIB_STATIC compile definition (#1277) 2025-06-20 10:19:01 +02:00
Urs Fleisch
6563ceaafa C bindings: Include missing wchar header in tag_c.h (#1273)
In C++, wchar_t is a built-in fundamental type, but in C, it is not.
Compilation with MinGW will fail without a header included which
defines wchar_t (wchar.h or stddef.h). The other compilers used in our
CI (gcc on Ubuntu, clang on macOS and MSVC on Windows) seem to
know wchar_t without an include.
2025-06-14 08:53:30 +02:00
Urs Fleisch
c57431e903 GitHub Actions: Build with MinGW 2025-06-14 08:53:30 +02:00
Urs Fleisch
42dcfec86b Use tag_c.h as first include in build with C compiler (#1273)
This will fail on MinGW because its gcc does not have wchar_t without
including wchar.h. With g++ as used with test_tag_c.cpp, the problem is
undetected because g++ supports wchar_t without including wchar.h.
2025-06-14 08:53:30 +02:00
Urs Fleisch
d48f02030d Version 2.1 2025-05-21 21:05:30 +02:00
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
Urs Fleisch
e3de03501f Version 2.0.2 2024-08-24 06:40:41 +02:00
Urs Fleisch
1bd0d711ca Support older utfcpp versions with utf8cpp CMake target (#1243) (#1244)
This affects for example openSUSE Leap 15.6, which installs
utfcpp 3.2.1 in its own folder.
Now not only utf8::cpp, but also utf8cpp is supported as a CMake
target.
2024-08-15 12:44:17 +02:00
nekiwo
7c85fcaa81 Remove 'using namespace std' to avoid potential conflicts in example files (#1241)
Co-authored-by: nekiwo <nekiwo@users.noreply.github.com>
2024-08-05 21:54:33 +02:00
Urs Fleisch
cbe54d2f40 Support free form tags with MP4 properties (#1239) (#1240) 2024-07-29 20:24:33 +02:00
Urs Fleisch
c4ed590032 tagwriter option -p not working properly (#1236) (#1237)
The -p option of tagwriter sample does not work.
This is because the picture file is open in text mode instead of binary.
Also, the isFile function does not work on Windows in 32 bit mode with
large files. Using _stat64 instead of stat solves the problem.
2024-07-19 12:25:46 +02:00
Stephen Booth
f3fb4d83a4 Skip unknown MP4 boxes (#1231) 2024-05-18 06:45:10 +02:00
Urs Fleisch
3d4428726e Fix parsing of ID3v2.2 frames (#1228) 2024-05-18 06:43:00 +02:00
Urs Fleisch
ebf4c5bbb1 Version 2.0.1 2024-04-09 19:55:08 +02:00
Urs Fleisch
20cec27ac0 C bindings: Support UTF-8 for property values 2024-04-01 08:45:52 +02:00
Urs Fleisch
99bc87ccff Fix WASM build by inverting wchar_t size check
When building WASM with emscripten

cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/Emscripten.cmake ...

all SIZEOF_ variables which should be defined in ConfigureChecks.cmake
are empty and the wchar_t check fails with "LESS" "2", the other
checks seem to pass since they start with NOT. Instead of explicitly
skipping the check for "if(NOT EMSCRIPTEN)" as is done in vcpkg's
disable-wchar-t-check-emscripten.patch, the check is inverted to
start with NOT, so the build still has a chance to run for compilers
which behave like emscripten.
2024-03-25 20:14:19 +01:00
Urs Fleisch
7951f572b5 Avoid offset_t conflict on Illumos
Taken from NetBSD patch-taglib_toolkit_taglib.h.
2024-03-25 20:14:19 +01:00
Urs Fleisch
59ff35772e Fix building with -DBUILD_TESTING=ON -DBUILD_BINDINGS=OFF 2024-03-25 20:14:19 +01:00
Urs Fleisch
3784628155 Provide equal operator for MP4::Item
This is needed to generate MP4::ItemMap bindings with SWIG.
2024-03-25 20:13:55 +01:00
Urs Fleisch
e60df53152 Add virtual to abstract overridden destructor
This is redundant, but required by SWIG.
2024-03-25 20:13:55 +01:00
Urs Fleisch
1ae8e18db5 Windows: Suppress yet another MSVC C4251 warning 2024-03-25 20:13:55 +01:00
Urs Fleisch
0896fb9092 Detect utf8cpp by header if cmake config is not found (#1217) 2024-02-03 06:28:40 +01:00
Jonas Kvinge
920d97606b FileStream: Fix opening long paths on Windows (#1216)
To make sure paths longer than MAX_PATH (260) can be opened, prefix local
paths with `\\?\`, and UNC paths with `\\?\UNC\`.

I've tested on Windows 10 22H2 (Build 19045.3930), even when setting
LongPathsEnabled to 1 in the registry, it still won't open files with long
paths without prefixing them.

For more information see:
https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry
2024-01-28 16:22:14 +01:00
Urs Fleisch
0d2c31b102 Clarify 2.0 source compatibility, remove obsolete URL (#1214) 2024-01-28 07:17:05 +01:00
Urs Fleisch
c8c4e5faec Fix 'get() != pointer()' assertion copying ByteVectorList/StringList (#1211)
This reverts dfef09f13 but keeps the assignments as a comment so these
functions do not look like they can be defaulted even though they cannot.
2024-01-27 10:56:31 +01:00
Urs Fleisch
0ebb14b855 Version 2.0 2024-01-24 05:10:43 +01:00
Rosen Penev
89af92333c clang-tidy: use dynamic_cast
Found with cppcoreguidelines-pro-type-static-cast-downcast

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-22 18:35:30 +01:00
Rosen Penev
b356fabe12 clang-tidy: avoid else after return
Found with: readability-else-after-return

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-22 18:35:30 +01:00
Rosen Penev
8a65068f3b clang-tidy: fix wrong cast
Found with bugprone-misplaced-widening-cast

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-22 18:35:30 +01:00
Rosen Penev
e1ac724cfe convert const double to const auto
Fixes some Wconversion warnings.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-22 18:35:30 +01:00
Urs Fleisch
a08acdcf23 Remove unused types from taglib.h 2024-01-21 20:46:27 +01:00
Urs Fleisch
1799b98c17 Inspection: Table is not correctly formatted 2024-01-21 20:46:27 +01:00
Urs Fleisch
e49390c7c5 Inspection: Type can be replaced with auto 2024-01-21 20:46:27 +01:00
Urs Fleisch
7bcfb96098 Inspection: Code redundancies 2024-01-21 20:46:27 +01:00
Urs Fleisch
580b0b0c82 Inspection: Possibly unused #include directive 2024-01-21 20:46:27 +01:00
Urs Fleisch
5fc3e5c192 Inspection: Possibly uninitialized class member 2024-01-21 20:46:27 +01:00
Urs Fleisch
570b40bdcd Inspection: Polymorphic class with non-virtual public destructor 2024-01-21 20:46:27 +01:00
Urs Fleisch
c3d73a26ff Inspection: Parameter names do not match 2024-01-21 20:46:27 +01:00
Urs Fleisch
790815bcf4 Inspection: Missing include guard 2024-01-21 20:46:27 +01:00
Urs Fleisch
1a5c417558 Inspection: Function is not implemented 2024-01-21 20:46:27 +01:00
Urs Fleisch
d87b2dad48 Inspection: Expression can be simplified 2024-01-21 20:46:27 +01:00
Urs Fleisch
613355665c Inspection: Variable can be moved to inner scope 2024-01-21 20:46:27 +01:00
Urs Fleisch
dfe2aa5253 Inspection: Variable can be moved to init statement 2024-01-21 20:46:27 +01:00
Urs Fleisch
5d921c6325 Inspection: Variable can be made constexpr 2024-01-21 20:46:27 +01:00
Urs Fleisch
710522e6e1 Inspection: Result of a postfix operator is discarded 2024-01-21 20:46:27 +01:00
Urs Fleisch
6b17aa3694 Inspection: Parameter can be made pointer to const 2024-01-21 20:46:27 +01:00
Urs Fleisch
b4f77a4d52 Inspection: Member function can be made const 2024-01-21 20:46:27 +01:00
Urs Fleisch
c907d8b273 Inspection: Functional-style cast is used instead of a C++ cast 2024-01-21 20:46:27 +01:00
Urs Fleisch
98175168f3 Inspection: Declaration and assignment can be joined 2024-01-21 20:46:27 +01:00
Urs Fleisch
73aff544b3 Inspection: C-style cast is used instead of a C++ cast 2024-01-21 20:46:27 +01:00
Rosen Penev
9cbb6615d5 clang-tidy: use using
Found with modernize-use-using

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
8b7b48cc9b clang-tidy: add ending namespace comments
Found with llvm-namespace
2024-01-19 21:57:55 +01:00
Rosen Penev
be8d71dad8 MSVC: fix signed/unsigned comparison
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
6abbe579a2 clang-tidy: remove virtual from prot destructors
Found with cppcoreguidelines-virtual-class-destructor

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
208fc93aaa cppcheck: match function argument names
Found with funcArgNamesDifferent

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
769feafbe0 cppcheck: include system headers with <>
Found with missingInclude

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
dfef09f134 cppcheck: assign d to a value
Found with operatorEqVarError, missingMemberCopy

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
3a003c1229 cppcheck: add const
Found with constVariablePointer, constParameterPointer

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
8b9a260d18 clang-tidy: fix doubled cases
Found with bugprone-branch-clone

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
c2eb6b59b5 clang-tidy: avoid endl
Found with performance-avoid-endl

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
99ba7635be clang-tidy: remove pointless const
Found with cppcoreguidelines-avoid-const-or-ref-data-members

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Rosen Penev
82b5ded8ee tvariant: fix -Wconversion warning
char -> wchar_t. Just directly use int and remove the cast.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2024-01-19 21:57:55 +01:00
Urs Fleisch
0318201fbd Make classes with destructor as only virtual member non-virtual
These classes are probably not meant to be used polymorphically.
2024-01-17 21:25:44 +01:00
Urs Fleisch
6c1ba88eab Make Frame::Header::size(), Frame::headerSize() const 2024-01-17 21:25:44 +01:00
Urs Fleisch
fb0f7dfa57 More API documentation corrections 2024-01-17 20:54:56 +01:00
Urs Fleisch
c5d798a50d Correct the API documentation 2024-01-04 17:18:23 +01:00
Urs Fleisch
ef013b76db Add checks for the expected sizes of new public classes 2024-01-02 14:16:22 +01:00
Urs Fleisch
a6dbc70644 Fix shadowArgument issue reported by cppcheck 2024-01-02 13:50:11 +01:00
Urs Fleisch
9a026976ae Do not use std::visit() for std::variant
It is not supported for macOS 10.13 and earlier, see
https://stackoverflow.com/questions/53946674/noexcept-visitation-for-stdvariant.
2023-12-29 07:36:03 +01:00
241 changed files with 5126 additions and 2335 deletions

View File

@@ -9,10 +9,14 @@ jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, macos-latest, windows-latest, windows-2025]
include:
- os: windows-latest
cmake_extra_args: '-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"'
- os: windows-2025
cmake_extra_args: '-G "MinGW Makefiles" -DCPPUNIT_INCLUDE_DIR="$env:GITHUB_WORKSPACE/pkg/usr/local/include" -DCPPUNIT_LIBRARIES="$($env:GITHUB_WORKSPACE -replace "\\", "/")/pkg/usr/local/lib/libcppunit.dll.a" -DCPPUNIT_INSTALLED_VERSION="1.15.1"'
# The windows-2025 runner is used for MinGW.
name: ${{ matrix.os == 'windows-2025' && 'mingw' || matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
@@ -32,6 +36,24 @@ jobs:
run: vcpkg install cppunit utfcpp zlib --triplet x64-windows
if: matrix.os == 'windows-latest'
- name: Set up MinGW
shell: bash
run: |
# Fetch utf8cpp, build cppunit
git submodule update --init
# Fails with fatal error: cppunit/config-auto.h: No such file or directory
# vcpkg install cppunit utfcpp zlib --triplet x64-mingw-dynamic
# Probably not working with CMake and MinGW, so we have to build it ourselves.
curl -sL "https://dev-www.libreoffice.org/src/cppunit-1.15.1.tar.gz" | tar xz
mkdir -p build_cppunit
(cd build_cppunit && MAKE=mingw32-make ../cppunit-1.15.1/configure \
--enable-shared=yes --enable-static=no \
--disable-dependency-tracking --disable-doxygen)
find build_cppunit -name Makefile -exec sed -i 's/\($[({]SHELL[)}]\)/"\1"/' {} \;
sed -i 's/^\(SUBDIRS.*\) examples\(.*\)$/\1\2/' build_cppunit/Makefile
(cd build_cppunit && mingw32-make -j$(nproc) install DESTDIR=$(cd .. && pwd)/pkg)
if: matrix.os == 'windows-2025'
- name: Configure
run: >
cmake -B${{github.workspace}}/build
@@ -41,12 +63,12 @@ jobs:
${{ matrix.cmake_extra_args }}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
- name: Test
working-directory: ${{github.workspace}}/build
run: ctest -C ${{env.BUILD_TYPE}} -V --no-tests=error
if: matrix.os != 'windows-latest'
if: matrix.os != 'windows-latest' && matrix.os != 'windows-2025'
- name: Test Windows
working-directory: ${{github.workspace}}/build
@@ -57,3 +79,10 @@ jobs:
$env:Path += ";$env:VCPKG_INSTALLATION_ROOT\packages\zlib_x64-windows\bin"
ctest -C ${{env.BUILD_TYPE}} -V --no-tests=error
if: matrix.os == 'windows-latest'
- name: Test MinGW
working-directory: ${{github.workspace}}/build
run: |
$env:Path += ";$PWD/taglib;$PWD/bindings/c;${{github.workspace}}/pkg/usr/local/bin"
ctest -C ${{env.BUILD_TYPE}} -V --no-tests=error
if: matrix.os == 'windows-2025'

1
.gitignore vendored
View File

@@ -22,7 +22,6 @@ CMakeLists.txt.user*
/tests/test_runner
/tests/Testing
/taglib/libtag.a
/taglib_config.h
/taglib-config
/bindings/c/libtag_c.a
/bindings/c/taglib_c.pc

View File

@@ -1,8 +1,49 @@
TagLib 2.1.1 (June 30, 2025)
============================
* Map ID3v2.3 IPLS frames to both ID3v2.4 TIPL and TMCL to have a consistent
behavior when using MusicBrainz tags with the property map interface.
* Fix missing include for `wchar_t` when using C bindings with MinGW.
TagLib 2.1 (May 31, 2025)
=========================
* Support for Shorten (SHN) files.
* Compile time configuration of supported formats: WITH_APE, WITH_ASF, ...
* Compile time configuration of data and temporary directories for unit tests:
TESTS_DIR and TESTS_TMPDIR.
* C bindings: Added taglib_file_new_wchar() and taglib_file_new_type_wchar().
* Preserve unicode encoding when downgrading to ID3v2.3.
* Do not store FLAC metadata blocks which are too large.
* Fix segfaults with String and ByteVector nullptr arguments.
TagLib 2.0.2 (Aug 24, 2024)
===========================
* Fix parsing of ID3v2.2 frames.
* Tolerate MP4 files with unknown atom types as generated by Android tools.
* Support setting properties with arbitrary names in MP4 tags.
* Windows: Fix "-p" option in tagwriter example.
* Support building with older utfcpp versions.
TagLib 2.0.1 (Apr 9, 2024)
==========================
* Fix aborting when _GLIBCXX_ASSERTIONS are enabled.
* Fall back to utf8cpp header detection in the case that its CMake
configuration is removed.
* Improve compatibility with the SWIG interface compiler.
* Build system fixes for testing without bindings, Emscripten and Illumos.
* C bindings: Fix setting UTF-8 encoded property values.
* Windows: Fix opening long paths.
TagLib 2.0 (Jan 24, 2024)
=========================
* New major version, binary incompatible, but source-compatible with the
latest 1.x release if no deprecated features are used.
* New major version, binary incompatible, but mostly source-compatible
with the latest 1.x release if no deprecated features are used.
Simple applications should build without changes, more complex
applications (e.g. extending classes of TagLib) will have to be adapted.
* Requires a C++17 compiler and uses features of C++17.
* Major code cleanup, fixed warnings issued by compilers and static analyzers.
* Made methods virtual which should have been virtual but could not be
@@ -74,6 +115,15 @@ TagLib 2.0 (Jan 24, 2024)
- String::null
- TrueAudio::File::setID3v2FrameFactory(): Use constructor
- WavPack::Properties::Properties(const ByteVector &, long, ReadStyle)
* Made methods const: Frame::Header::size(), Frame::headerSize(),
MP4::Atom::findall(), MP4::Atoms::find(), MP4::Atoms::path().
* Made classes non-virtual: APE::Footer, APE::Item, ASF::Attribute,
ASF::Picture, MP4::CoverArt, MP4::Item, ID3v2::ExtendedHeader, ID3v2::Footer,
ID3v2::Header, MPEG::Header, MPEG::XingHeader, Ogg::Page, Ogg::PageHeader.
* Removed type definitions in TagLib namespace: wchar, uchar, ushort, uint,
ulong, ulonglong, wstring: Use the standard types.
* Removed include file taglib_config.h and its defines TAGLIB_WITH_ASF,
TAGLIB_WITH_MP4: They were always 1 since version 1.8.
* Behavioral changes:
- The basic tag methods (e.g. genre()) separate multiple values with " / "
instead of " ".

View File

@@ -19,9 +19,6 @@ if(APPLE)
set(FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.")
endif()
endif()
if(NOT BUILD_SHARED_LIBS)
add_definitions(-DTAGLIB_STATIC)
endif()
option(ENABLE_STATIC_RUNTIME "Visual Studio, link with runtime statically" OFF)
option(ENABLE_CCACHE "Use ccache when building libtag" OFF)
@@ -48,7 +45,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")
@@ -92,11 +92,21 @@ endif()
# Minor version: increase it if you add ABI compatible features.
# Patch version: increase it for bug fix releases.
set(TAGLIB_SOVERSION_MAJOR 2)
set(TAGLIB_SOVERSION_MINOR 0)
set(TAGLIB_SOVERSION_PATCH 0)
set(TAGLIB_SOVERSION_MINOR 1)
set(TAGLIB_SOVERSION_PATCH 1)
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)
@@ -148,23 +158,66 @@ if(TRACE_IN_RELEASE)
set(TRACE_IN_RELEASE TRUE)
endif()
configure_file(taglib/taglib_config.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/taglib_config.h")
find_package(utf8cpp QUIET)
if(NOT utf8cpp_FOUND)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/utfcpp/CMakeLists.txt)
add_subdirectory("3rdparty/utfcpp")
message(STATUS "Using utfcpp from ${utf8cpp_SOURCE_DIR}")
else()
message(FATAL_ERROR
"utfcpp not found. Either install package (probably utfcpp, utf8cpp, or libutfcpp-dev) "
"or fetch the git submodule using\n"
"git submodule update --init")
endif()
else()
if(utf8cpp_FOUND)
message(STATUS "Using utfcpp ${utf8cpp_VERSION} from ${utf8cpp_CONFIG}")
else()
find_path(utf8cpp_INCLUDE_DIR NAMES utf8.h PATH_SUFFIXES utf8cpp
DOC "utf8cpp include directory")
mark_as_advanced(utf8cpp_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(utf8cpp REQUIRED_VARS utf8cpp_INCLUDE_DIR)
if(utf8cpp_FOUND)
set(utf8cpp_INCLUDE_DIRS "${utf8cpp_INCLUDE_DIR}")
if(NOT TARGET utf8::cpp)
add_library(utf8::cpp INTERFACE IMPORTED)
set_target_properties(utf8::cpp PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${utf8cpp_INCLUDE_DIR}")
endif()
message(STATUS "Using utfcpp from ${utf8cpp_INCLUDE_DIR}")
else()
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/utfcpp/CMakeLists.txt)
add_subdirectory("3rdparty/utfcpp")
message(STATUS "Using utfcpp from ${utf8cpp_SOURCE_DIR}")
else()
message(FATAL_ERROR
"utfcpp not found. Either install package (probably utfcpp, utf8cpp, or libutfcpp-dev) "
"or fetch the git submodule using\n"
"git submodule update --init")
endif()
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

@@ -20,7 +20,7 @@ if(NOT ${SIZEOF_LONGLONG} EQUAL 8)
endif()
check_type_size("wchar_t" SIZEOF_WCHAR_T)
if(${SIZEOF_WCHAR_T} LESS 2)
if(NOT ${SIZEOF_WCHAR_T} GREATER 1)
message(FATAL_ERROR "TagLib requires that wchar_t is sufficient to store a UTF-16 char.")
endif()

View File

@@ -12,7 +12,6 @@ OUTPUT_DIRECTORY = doc
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
OUTPUT_TEXT_DIRECTION = None
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
@@ -239,7 +238,6 @@ PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
@@ -252,7 +250,6 @@ COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
@@ -273,7 +270,6 @@ XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
@@ -309,7 +305,6 @@ EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES

View File

@@ -27,7 +27,7 @@ These are the most important build options. For details, have a look into the
CMakeLists.txt file.
| Option | Description |
| ----------------------- | -------------------------------------------------- |
|-------------------------|----------------------------------------------------|
| `BUILD_SHARED_LIBS` | Build shared libraries |
| `CMAKE_BUILD_TYPE` | Debug, Release, RelWithDebInfo, MinSizeRel |
| `BUILD_EXAMPLES` | Build examples |
@@ -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

@@ -7,10 +7,10 @@
https://taglib.org/
TagLib is a library for reading and editing the metadata of several
popular audio formats. Currently, it supports both ID3v1 and [ID3v2][]
popular audio formats. Currently, it supports both ID3v1 and ID3v2
for MP3 files, [Ogg Vorbis][] comments and ID3 tags
in [FLAC][], MPC, Speex, WavPack, TrueAudio, WAV, AIFF, MP4, APE,
and ASF files.
in [FLAC][], MPC, Speex, WavPack, TrueAudio, WAV, AIFF, MP4, APE, ASF,
DSF, DFF and AAC files.
TagLib is distributed under the [GNU Lesser General Public License][]
(LGPL) and [Mozilla Public License][] (MPL). Essentially that means that
@@ -18,7 +18,6 @@ it may be used in proprietary applications, but if changes are made to
TagLib they must be contributed back to the project. Please review the
licenses if you are considering using TagLib in your project.
[ID3v2]: https://id3.org/
[Ogg Vorbis]: https://xiph.org/vorbis/
[FLAC]: https://xiph.org/flac/
[GNU Lesser General Public License]: https://www.gnu.org/licenses/lgpl.html

View File

@@ -2,5 +2,4 @@ There are a few other people that have done bindings externally that I have
been made aware of. I have not personally reviewed these bindings, but I'm
listing them here so that those who find them useful are able to find them:
http://developer.kde.org/~wheeler/taglib.html#bindings
https://taglib.org/#language-bindings

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)
@@ -74,6 +112,9 @@ set_target_properties(tag_c PROPERTIES
DEFINE_SYMBOL MAKE_TAGLIB_C_LIB
INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR}
)
if(NOT BUILD_SHARED_LIBS)
target_compile_definitions(tag_c PUBLIC TAGLIB_STATIC)
endif()
if(TAGLIB_INSTALL_SUFFIX)
if(BUILD_SHARED_LIBS)

View File

@@ -29,35 +29,57 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "taglib_config.h"
#include "tstringlist.h"
#include "tbytevectorlist.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;
@@ -127,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;
@@ -182,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 *>(
@@ -236,7 +299,7 @@ BOOL taglib_file_save(TagLib_File *file)
char *taglib_tag_title(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
auto t = reinterpret_cast<const Tag *>(tag);
char *s = stringToCharArray(t->title());
if(stringManagementEnabled)
strings.append(s);
@@ -245,7 +308,7 @@ char *taglib_tag_title(const TagLib_Tag *tag)
char *taglib_tag_artist(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
auto t = reinterpret_cast<const Tag *>(tag);
char *s = stringToCharArray(t->artist());
if(stringManagementEnabled)
strings.append(s);
@@ -254,7 +317,7 @@ char *taglib_tag_artist(const TagLib_Tag *tag)
char *taglib_tag_album(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
auto t = reinterpret_cast<const Tag *>(tag);
char *s = stringToCharArray(t->album());
if(stringManagementEnabled)
strings.append(s);
@@ -263,7 +326,7 @@ char *taglib_tag_album(const TagLib_Tag *tag)
char *taglib_tag_comment(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
auto t = reinterpret_cast<const Tag *>(tag);
char *s = stringToCharArray(t->comment());
if(stringManagementEnabled)
strings.append(s);
@@ -272,7 +335,7 @@ char *taglib_tag_comment(const TagLib_Tag *tag)
char *taglib_tag_genre(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
auto t = reinterpret_cast<const Tag *>(tag);
char *s = stringToCharArray(t->genre());
if(stringManagementEnabled)
strings.append(s);
@@ -281,55 +344,55 @@ char *taglib_tag_genre(const TagLib_Tag *tag)
unsigned int taglib_tag_year(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
auto t = reinterpret_cast<const Tag *>(tag);
return t->year();
}
unsigned int taglib_tag_track(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
auto t = reinterpret_cast<const Tag *>(tag);
return t->track();
}
void taglib_tag_set_title(TagLib_Tag *tag, const char *title)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setTitle(charArrayToString(title));
}
void taglib_tag_set_artist(TagLib_Tag *tag, const char *artist)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setArtist(charArrayToString(artist));
}
void taglib_tag_set_album(TagLib_Tag *tag, const char *album)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setAlbum(charArrayToString(album));
}
void taglib_tag_set_comment(TagLib_Tag *tag, const char *comment)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setComment(charArrayToString(comment));
}
void taglib_tag_set_genre(TagLib_Tag *tag, const char *genre)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setGenre(charArrayToString(genre));
}
void taglib_tag_set_year(TagLib_Tag *tag, unsigned int year)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setYear(year);
}
void taglib_tag_set_track(TagLib_Tag *tag, unsigned int track)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setTrack(track);
}
@@ -411,14 +474,14 @@ void _taglib_property_set(TagLib_File *file, const char* prop, const char* value
if(value) {
auto property = map.find(prop);
if(property == map.end()) {
map.insert(prop, StringList(value));
map.insert(prop, StringList(charArrayToString(value)));
}
else {
if(append) {
property->second.append(value);
property->second.append(charArrayToString(value));
}
else {
property->second = StringList(value);
property->second = StringList(charArrayToString(value));
}
}
}
@@ -431,17 +494,17 @@ void _taglib_property_set(TagLib_File *file, const char* prop, const char* value
} // namespace
void taglib_property_set(TagLib_File *f, const char *prop, const char *value)
void taglib_property_set(TagLib_File *file, const char *prop, const char *value)
{
_taglib_property_set(f, prop, value, false);
_taglib_property_set(file, prop, value, false);
}
void taglib_property_set_append(TagLib_File *f, const char *prop, const char *value)
void taglib_property_set_append(TagLib_File *file, const char *prop, const char *value)
{
_taglib_property_set(f, prop, value, true);
_taglib_property_set(file, prop, value, true);
}
char** taglib_property_keys(TagLib_File *file)
char** taglib_property_keys(const TagLib_File *file)
{
if(file == NULL)
return NULL;
@@ -461,7 +524,7 @@ char** taglib_property_keys(TagLib_File *file)
return props;
}
char **taglib_property_get(TagLib_File *file, const char *prop)
char **taglib_property_get(const TagLib_File *file, const char *prop)
{
if(file == NULL || prop == NULL)
return NULL;
@@ -520,8 +583,7 @@ bool _taglib_complex_property_set(
while(*attrPtr) {
const TagLib_Complex_Property_Attribute *attr = *attrPtr;
String attrKey(attr->key);
TagLib_Variant_Type type = attr->value.type;
switch(type) {
switch(attr->value.type) {
case TagLib_Variant_Void:
map.insert(attrKey, Variant());
break;
@@ -544,14 +606,14 @@ bool _taglib_complex_property_set(
map.insert(attrKey, attr->value.value.doubleValue);
break;
case TagLib_Variant_String:
map.insert(attrKey, attr->value.value.stringValue);
map.insert(attrKey, charArrayToString(attr->value.value.stringValue));
break;
case TagLib_Variant_StringList: {
StringList strs;
if(attr->value.value.stringListValue) {
char **s = attr->value.value.stringListValue;;
while(*s) {
strs.append(*s++);
strs.append(charArrayToString(*s++));
}
}
map.insert(attrKey, strs);
@@ -585,7 +647,7 @@ BOOL taglib_complex_property_set_append(
return _taglib_complex_property_set(file, key, value, true);
}
char** taglib_complex_property_keys(TagLib_File *file)
char** taglib_complex_property_keys(const TagLib_File *file)
{
if(file == NULL) {
return NULL;
@@ -608,7 +670,7 @@ char** taglib_complex_property_keys(TagLib_File *file)
}
TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
TagLib_File *file, const char *key)
const TagLib_File *file, const char *key)
{
if(file == NULL || key == NULL) {
return NULL;
@@ -619,15 +681,15 @@ TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
return NULL;
}
TagLib_Complex_Property_Attribute ***props = static_cast<TagLib_Complex_Property_Attribute ***>(
auto props = static_cast<TagLib_Complex_Property_Attribute ***>(
malloc(sizeof(TagLib_Complex_Property_Attribute **) * (variantMaps.size() + 1)));
TagLib_Complex_Property_Attribute ***propPtr = props;
for(const auto &variantMap : variantMaps) {
if(!variantMap.isEmpty()) {
TagLib_Complex_Property_Attribute **attrs = static_cast<TagLib_Complex_Property_Attribute **>(
auto attrs = static_cast<TagLib_Complex_Property_Attribute **>(
malloc(sizeof(TagLib_Complex_Property_Attribute *) * (variantMap.size() + 1)));
TagLib_Complex_Property_Attribute *attr = static_cast<TagLib_Complex_Property_Attribute *>(
auto attr = static_cast<TagLib_Complex_Property_Attribute *>(
malloc(sizeof(TagLib_Complex_Property_Attribute) * variantMap.size()));
TagLib_Complex_Property_Attribute **attrPtr = attrs;
// The next assignment is redundant to silence the clang analyzer,
@@ -675,7 +737,7 @@ TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
}
case Variant::StringList: {
attr->value.type = TagLib_Variant_StringList;
StringList strs = v.value<StringList>();
auto strs = v.value<StringList>();
auto strPtr = static_cast<char **>(malloc(sizeof(char *) * (strs.size() + 1)));
attr->value.value.stringListValue = strPtr;
attr->value.size = strs.size();
@@ -727,8 +789,7 @@ void taglib_picture_from_complex_property(
TagLib_Complex_Property_Attribute** attrPtr = *propPtr;
while(*attrPtr) {
TagLib_Complex_Property_Attribute *attr = *attrPtr;
TagLib_Variant_Type type = attr->value.type;
switch(type) {
switch(attr->value.type) {
case TagLib_Variant_String:
if(strcmp("mimeType", attr->key) == 0) {
picture->mimeType = attr->value.value.stringValue;
@@ -779,8 +840,7 @@ void taglib_complex_property_free(
TagLib_Complex_Property_Attribute** attrPtr = *propPtr;
while(*attrPtr) {
TagLib_Complex_Property_Attribute *attr = *attrPtr;
TagLib_Variant_Type type = attr->value.type;
switch(type) {
switch(attr->value.type) {
case TagLib_Variant_String:
free(attr->value.value.stringValue);
break;

View File

@@ -43,6 +43,7 @@ extern "C" {
#define TAGLIB_C_EXPORT
#endif
#include <wchar.h>
#ifdef _MSC_VER
/* minwindef.h contains typedef int BOOL */
#include <windows.h>
@@ -130,7 +131,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 +143,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.
@@ -164,7 +172,7 @@ TAGLIB_C_EXPORT TagLib_File *taglib_file_new_iostream(TagLib_IOStream *stream);
TAGLIB_C_EXPORT void taglib_file_free(TagLib_File *file);
/*!
* Returns true if the file is open and readable and valid information for
* Returns \c true if the file is open and readable and valid information for
* the Tag and / or AudioProperties was found.
*/
@@ -232,12 +240,12 @@ TAGLIB_C_EXPORT char *taglib_tag_comment(const TagLib_Tag *tag);
TAGLIB_C_EXPORT char *taglib_tag_genre(const TagLib_Tag *tag);
/*!
* Returns the tag's year or 0 if year is not set.
* Returns the tag's year or 0 if the year is not set.
*/
TAGLIB_C_EXPORT unsigned int taglib_tag_year(const TagLib_Tag *tag);
/*!
* Returns the tag's track number or 0 if track number is not set.
* Returns the tag's track number or 0 if the track number is not set.
*/
TAGLIB_C_EXPORT unsigned int taglib_tag_track(const TagLib_Tag *tag);
@@ -354,7 +362,7 @@ TAGLIB_C_EXPORT void taglib_property_set_append(TagLib_File *file, const char *p
* \return NULL terminated array of C-strings (char *), only NULL if empty.
* It must be freed by the client using taglib_property_free().
*/
TAGLIB_C_EXPORT char** taglib_property_keys(TagLib_File *file);
TAGLIB_C_EXPORT char** taglib_property_keys(const TagLib_File *file);
/*!
* Get value(s) of property \a prop.
@@ -362,7 +370,7 @@ TAGLIB_C_EXPORT char** taglib_property_keys(TagLib_File *file);
* \return NULL terminated array of C-strings (char *), only NULL if empty.
* It must be freed by the client using taglib_property_free().
*/
TAGLIB_C_EXPORT char** taglib_property_get(TagLib_File *file, const char *prop);
TAGLIB_C_EXPORT char** taglib_property_get(const TagLib_File *file, const char *prop);
/*!
* Frees the NULL terminated array \a props and the C-strings it contains.
@@ -541,7 +549,7 @@ TAGLIB_C_EXPORT BOOL taglib_complex_property_set_append(
* \return NULL terminated array of C-strings (char *), only NULL if empty.
* It must be freed by the client using taglib_complex_property_free_keys().
*/
TAGLIB_C_EXPORT char** taglib_complex_property_keys(TagLib_File *file);
TAGLIB_C_EXPORT char** taglib_complex_property_keys(const TagLib_File *file);
/*!
* Get value(s) of complex property \a key.
@@ -551,7 +559,7 @@ TAGLIB_C_EXPORT char** taglib_complex_property_keys(TagLib_File *file);
* It must be freed by the client using taglib_complex_property_free().
*/
TAGLIB_C_EXPORT TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
TagLib_File *file, const char *key);
const TagLib_File *file, const char *key);
/*!
* Extract the complex property values of a picture.

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,9 +33,10 @@
#include "id3v2header.h"
#include "commentsframe.h"
#include "id3v1tag.h"
#ifdef TAGLIB_WITH_APE
#include "apetag.h"
#endif
using namespace std;
using namespace TagLib;
int main(int argc, char *argv[])
@@ -44,7 +46,7 @@ int main(int argc, char *argv[])
for(int i = 1; i < argc; i++) {
cout << "******************** \"" << argv[i] << "\"********************" << endl;
std::cout << "******************** \"" << argv[i] << "\"********************" << std::endl;
MPEG::File f(argv[i]);
@@ -52,62 +54,64 @@ int main(int argc, char *argv[])
if(id3v2tag) {
cout << "ID3v2."
std::cout << "ID3v2."
<< id3v2tag->header()->majorVersion()
<< "."
<< id3v2tag->header()->revisionNumber()
<< ", "
<< id3v2tag->header()->tagSize()
<< " bytes in tag"
<< endl;
<< std::endl;
const auto &frames = id3v2tag->frameList();
for(auto it = frames.begin(); it != frames.end(); it++) {
cout << (*it)->frameID();
std::cout << (*it)->frameID();
if(auto comment = dynamic_cast<ID3v2::CommentsFrame *>(*it))
if(!comment->description().isEmpty())
cout << " [" << comment->description() << "]";
std::cout << " [" << comment->description() << "]";
cout << " - \"" << (*it)->toString() << "\"" << endl;
std::cout << " - \"" << (*it)->toString() << "\"" << std::endl;
}
}
else
cout << "file does not have a valid id3v2 tag" << endl;
std::cout << "file does not have a valid id3v2 tag" << std::endl;
cout << endl << "ID3v1" << endl;
std::cout << std::endl << "ID3v1" << std::endl;
ID3v1::Tag *id3v1tag = f.ID3v1Tag();
if(id3v1tag) {
cout << "title - \"" << id3v1tag->title() << "\"" << endl;
cout << "artist - \"" << id3v1tag->artist() << "\"" << endl;
cout << "album - \"" << id3v1tag->album() << "\"" << endl;
cout << "year - \"" << id3v1tag->year() << "\"" << endl;
cout << "comment - \"" << id3v1tag->comment() << "\"" << endl;
cout << "track - \"" << id3v1tag->track() << "\"" << endl;
cout << "genre - \"" << id3v1tag->genre() << "\"" << endl;
std::cout << "title - \"" << id3v1tag->title() << "\"" << std::endl;
std::cout << "artist - \"" << id3v1tag->artist() << "\"" << std::endl;
std::cout << "album - \"" << id3v1tag->album() << "\"" << std::endl;
std::cout << "year - \"" << id3v1tag->year() << "\"" << std::endl;
std::cout << "comment - \"" << id3v1tag->comment() << "\"" << std::endl;
std::cout << "track - \"" << id3v1tag->track() << "\"" << std::endl;
std::cout << "genre - \"" << id3v1tag->genre() << "\"" << std::endl;
}
else
cout << "file does not have a valid id3v1 tag" << endl;
std::cout << "file does not have a valid id3v1 tag" << std::endl;
#ifdef TAGLIB_WITH_APE
APE::Tag *ape = f.APETag();
cout << endl << "APE" << endl;
std::cout << std::endl << "APE" << std::endl;
if(ape) {
const auto &items = ape->itemListMap();
for(auto it = items.begin(); it != items.end(); ++it)
{
if((*it).second.type() != APE::Item::Binary)
cout << (*it).first << " - \"" << (*it).second.toString() << "\"" << endl;
std::cout << (*it).first << " - \"" << (*it).second.toString() << "\"" << std::endl;
else
cout << (*it).first << " - Binary data (" << (*it).second.binaryData().size() << " bytes)" << endl;
std::cout << (*it).first << " - Binary data (" << (*it).second.binaryData().size() << " bytes)" << std::endl;
}
}
else
cout << "file does not have a valid APE tag" << endl;
std::cout << "file does not have a valid APE tag" << std::endl;
#endif
cout << endl;
std::cout << std::endl;
}
}

View File

@@ -32,13 +32,11 @@
#include "fileref.h"
#include "tag.h"
using namespace std;
int main(int argc, char *argv[])
{
for(int i = 1; i < argc; i++) {
cout << "******************** \"" << argv[i] << "\" ********************" << endl;
std::cout << "******************** \"" << argv[i] << "\" ********************" << std::endl;
TagLib::FileRef f(argv[i]);
@@ -46,14 +44,14 @@ int main(int argc, char *argv[])
TagLib::Tag *tag = f.tag();
cout << "-- TAG (basic) --" << endl;
cout << "title - \"" << tag->title() << "\"" << endl;
cout << "artist - \"" << tag->artist() << "\"" << endl;
cout << "album - \"" << tag->album() << "\"" << endl;
cout << "year - \"" << tag->year() << "\"" << endl;
cout << "comment - \"" << tag->comment() << "\"" << endl;
cout << "track - \"" << tag->track() << "\"" << endl;
cout << "genre - \"" << tag->genre() << "\"" << endl;
std::cout << "-- TAG (basic) --" << std::endl;
std::cout << "title - \"" << tag->title() << "\"" << std::endl;
std::cout << "artist - \"" << tag->artist() << "\"" << std::endl;
std::cout << "album - \"" << tag->album() << "\"" << std::endl;
std::cout << "year - \"" << tag->year() << "\"" << std::endl;
std::cout << "comment - \"" << tag->comment() << "\"" << std::endl;
std::cout << "track - \"" << tag->track() << "\"" << std::endl;
std::cout << "genre - \"" << tag->genre() << "\"" << std::endl;
TagLib::PropertyMap tags = f.properties();
if(!tags.isEmpty()) {
@@ -64,10 +62,10 @@ int main(int argc, char *argv[])
}
}
cout << "-- TAG (properties) --" << endl;
std::cout << "-- TAG (properties) --" << std::endl;
for(auto j = tags.cbegin(); j != tags.cend(); ++j) {
for(auto k = j->second.begin(); k != j->second.end(); ++k) {
cout << left << std::setfill(' ') << std::setw(longest) << j->first << " - " << '"' << *k << '"' << endl;
std::cout << std::left << std::setfill(' ') << std::setw(longest) << j->first << " - " << '"' << *k << '"' << std::endl;
}
}
}
@@ -76,13 +74,13 @@ int main(int argc, char *argv[])
for(const auto &name : names) {
const auto& properties = f.complexProperties(name);
for(const auto &property : properties) {
cout << name << ":" << endl;
std::cout << name << ":" << std::endl;
for(const auto &[key, value] : property) {
cout << " " << left << std::setfill(' ') << std::setw(11) << key << " - ";
std::cout << " " << std::left << std::setfill(' ') << std::setw(11) << key << " - ";
if(value.type() == TagLib::Variant::ByteVector) {
cout << "(" << value.value<TagLib::ByteVector>().size() << " bytes)" << endl;
std::cout << "(" << value.value<TagLib::ByteVector>().size() << " bytes)" << std::endl;
/* The picture could be extracted using:
ofstream picture;
std::ofstream picture;
TagLib::String fn(argv[i]);
int slashPos = fn.rfind('/');
int dotPos = fn.rfind('.');
@@ -90,13 +88,13 @@ int main(int argc, char *argv[])
fn = fn.substr(slashPos + 1, dotPos - slashPos - 1);
}
fn += ".jpg";
picture.open(fn.toCString(), ios_base::out | ios_base::binary);
picture.open(fn.toCString(), std::ios_base::out | std::ios_base::binary);
picture << value.value<TagLib::ByteVector>();
picture.close();
*/
}
else {
cout << value << endl;
std::cout << value << std::endl;
}
}
}
@@ -110,12 +108,13 @@ int main(int argc, char *argv[])
int seconds = properties->lengthInSeconds() % 60;
int minutes = (properties->lengthInSeconds() - seconds) / 60;
cout << "-- AUDIO --" << endl;
cout << "bitrate - " << properties->bitrate() << endl;
cout << "sample rate - " << properties->sampleRate() << endl;
cout << "channels - " << properties->channels() << endl;
cout << "length - " << minutes << ":" << setfill('0') << setw(2) << right << seconds << endl;
std::cout << "-- AUDIO --" << std::endl;
std::cout << "bitrate - " << properties->bitrate() << std::endl;
std::cout << "sample rate - " << properties->sampleRate() << std::endl;
std::cout << "channels - " << properties->channels() << std::endl;
std::cout << "length - " << minutes << ":" << std::setfill('0') << std::setw(2) << std::right << seconds << std::endl;
}
}
return 0;
}

View File

@@ -22,11 +22,11 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "tag_c.h"
#include <stdio.h>
#include <string.h>
#include "tag_c.h"
#ifndef FALSE
#define FALSE 0
#endif

View File

@@ -39,8 +39,6 @@
#include "fileref.h"
#include "tag.h"
using namespace std;
bool isArgument(const char *s)
{
return strlen(s) == 2 && s[0] == '-';
@@ -48,32 +46,33 @@ bool isArgument(const char *s)
bool isFile(const char *s)
{
struct stat st;
#ifdef _WIN32
return ::stat(s, &st) == 0 && (st.st_mode & (S_IFREG));
struct _stat64 st;
return ::_stat64(s, &st) == 0 && (st.st_mode & S_IFREG);
#else
struct stat st;
return ::stat(s, &st) == 0 && (st.st_mode & (S_IFREG | S_IFLNK));
#endif
}
void usage()
{
cout << endl;
cout << "Usage: tagwriter <fields> <files>" << endl;
cout << endl;
cout << "Where the valid fields are:" << endl;
cout << " -t <title>" << endl;
cout << " -a <artist>" << endl;
cout << " -A <album>" << endl;
cout << " -c <comment>" << endl;
cout << " -g <genre>" << endl;
cout << " -y <year>" << endl;
cout << " -T <track>" << endl;
cout << " -R <tagname> <tagvalue>" << endl;
cout << " -I <tagname> <tagvalue>" << endl;
cout << " -D <tagname>" << endl;
cout << " -p <picturefile> <description> (\"\" \"\" to remove)" << endl;
cout << endl;
std::cout << std::endl;
std::cout << "Usage: tagwriter <fields> <files>" << std::endl;
std::cout << std::endl;
std::cout << "Where the valid fields are:" << std::endl;
std::cout << " -t <title>" << std::endl;
std::cout << " -a <artist>" << std::endl;
std::cout << " -A <album>" << std::endl;
std::cout << " -c <comment>" << std::endl;
std::cout << " -g <genre>" << std::endl;
std::cout << " -y <year>" << std::endl;
std::cout << " -T <track>" << std::endl;
std::cout << " -R <tagname> <tagvalue>" << std::endl;
std::cout << " -I <tagname> <tagvalue>" << std::endl;
std::cout << " -D <tagname>" << std::endl;
std::cout << " -p <picturefile> <description> (\"\" \"\" to remove)" << std::endl;
std::cout << std::endl;
exit(1);
}
@@ -87,10 +86,10 @@ void checkForRejectedProperties(const TagLib::PropertyMap &tags)
longest = i->first.size();
}
}
cout << "-- rejected TAGs (properties) --" << endl;
std::cout << "-- rejected TAGs (properties) --" << std::endl;
for(auto i = tags.begin(); i != tags.end(); ++i) {
for(auto j = i->second.begin(); j != i->second.end(); ++j) {
cout << left << std::setw(longest) << i->first << " - " << '"' << *j << '"' << endl;
std::cout << std::left << std::setw(longest) << i->first << " - " << '"' << *j << '"' << std::endl;
}
}
}
@@ -176,12 +175,12 @@ int main(int argc, char *argv[])
numArgsConsumed = 3;
if(!value.isEmpty()) {
if(!isFile(value.toCString())) {
cout << value.toCString() << " not found." << endl;
std::cout << value.toCString() << " not found." << std::endl;
return 1;
}
ifstream picture;
picture.open(value.toCString());
stringstream buffer;
std::ifstream picture;
picture.open(value.toCString(), std::ios::in | std::ios::binary);
std::stringstream buffer;
buffer << picture.rdbuf();
picture.close();
TagLib::String buf(buffer.str());

View File

@@ -1,32 +1,70 @@
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
@@ -83,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
@@ -186,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
@@ -332,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
@@ -348,7 +449,7 @@ target_include_directories(tag INTERFACE
)
target_link_libraries(tag
PRIVATE $<$<TARGET_EXISTS:utf8::cpp>:utf8::cpp>
PRIVATE $<IF:$<TARGET_EXISTS:utf8::cpp>,utf8::cpp,$<$<TARGET_EXISTS:utf8cpp>:utf8cpp>>
$<$<TARGET_EXISTS:ZLIB::ZLIB>:ZLIB::ZLIB>
)
@@ -360,6 +461,9 @@ set_target_properties(tag PROPERTIES
INTERFACE_LINK_LIBRARIES "${ZLIB_INTERFACE_LINK_LIBRARIES}"
PUBLIC_HEADER "${tag_HDRS}"
)
if(NOT BUILD_SHARED_LIBS)
target_compile_definitions(tag PUBLIC TAGLIB_STATIC)
endif()
if(VISIBILITY_HIDDEN)
set_target_properties(tag PROPERTIES C_VISIBILITY_PRESET hidden)
set_target_properties(tag PROPERTIES CXX_VISIBILITY_PRESET hidden)

View File

@@ -75,7 +75,7 @@ bool APE::File::isSupported(IOStream *stream)
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
return (buffer.find("MAC ") >= 0);
return buffer.find("MAC ") >= 0;
}
////////////////////////////////////////////////////////////////////////////////
@@ -178,7 +178,7 @@ bool APE::File::save()
insert(data, d->APELocation, d->APESize);
if(d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
d->ID3v1Location += static_cast<long>(data.size()) - d->APESize;
d->APESize = data.size();
}
@@ -224,12 +224,12 @@ void APE::File::strip(int tags)
bool APE::File::hasAPETag() const
{
return (d->APELocation >= 0);
return d->APELocation >= 0;
}
bool APE::File::hasID3v1Tag() const
{
return (d->ID3v1Location >= 0);
return d->ID3v1Location >= 0;
}
////////////////////////////////////////////////////////////////////////////////
@@ -283,7 +283,7 @@ void APE::File::read(bool readProperties)
if(d->ID3v2Location >= 0) {
seek(d->ID3v2Location + d->ID3v2Size);
streamLength -= (d->ID3v2Location + d->ID3v2Size);
streamLength -= d->ID3v2Location + d->ID3v2Size;
}
else {
seek(0);

View File

@@ -48,7 +48,7 @@ namespace TagLib {
//! An implementation of APE metadata
/*!
* This is implementation of APE metadata.
* This is an implementation of APE metadata.
*
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
* properties from the file.
@@ -84,7 +84,7 @@ namespace TagLib {
};
/*!
* Constructs an APE file from \a file. If \a readProperties is true the
* Constructs an APE file from \a file. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
@@ -93,7 +93,7 @@ namespace TagLib {
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Constructs an APE file from \a stream. If \a readProperties is true the
* Constructs an APE file from \a stream. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
@@ -155,15 +155,15 @@ namespace TagLib {
/*!
* Returns a pointer to the ID3v1 tag of the file.
*
* If \a create is false (the default) this may return a null pointer
* if there is no valid ID3v1 tag. If \a create is true it will create
* If \a create is \c false (the default) this may return a null pointer
* if there is no valid ID3v1 tag. If \a create is \c true it will create
* an ID3v1 tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
* on disk actually has an ID3v1 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* \note The Tag <b>is still</b> owned by the APE::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
@@ -174,15 +174,15 @@ namespace TagLib {
/*!
* Returns a pointer to the APE tag of the file.
*
* If \a create is false (the default) this may return a null pointer
* if there is no valid APE tag. If \a create is true it will create
* If \a create is \c false (the default) this may return a null pointer
* if there is no valid APE tag. If \a create is \c true it will create
* an APE tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an APE tag. Use hasAPETag() to check if the file
* on disk actually has an APE tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* \note The Tag <b>is still</b> owned by the APE::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*

View File

@@ -28,6 +28,8 @@
#include <bitset>
#include "taglib.h"
using namespace TagLib;
using namespace APE;

View File

@@ -59,7 +59,7 @@ namespace TagLib {
/*!
* Destroys the footer.
*/
virtual ~Footer();
~Footer();
Footer(const Footer &) = delete;
Footer &operator=(const Footer &) = delete;
@@ -70,17 +70,17 @@ namespace TagLib {
unsigned int version() const;
/*!
* Returns true if a header is present in the tag.
* Returns \c true if a header is present in the tag.
*/
bool headerPresent() const;
/*!
* Returns true if a footer is present in the tag.
* Returns \c true if a footer is present in the tag.
*/
bool footerPresent() const;
/*!
* Returns true this is actually the header.
* Returns \c true if this is actually the header.
*/
bool isHeader() const;
@@ -145,8 +145,8 @@ namespace TagLib {
ByteVector renderFooter() const;
/*!
* Renders the header corresponding to the footer. If headerPresent is
* set to false, it returns an empty ByteVector.
* Renders the header corresponding to the footer. If headerPresent() is
* \c false, it returns an empty ByteVector.
*/
ByteVector renderHeader() const;

View File

@@ -141,10 +141,10 @@ void APE::Item::setValue(const String &value)
d->value.clear();
}
void APE::Item::setValues(const StringList &value)
void APE::Item::setValues(const StringList &values)
{
d->type = Text;
d->text = value;
d->text = values;
d->value.clear();
}
@@ -241,7 +241,7 @@ void APE::Item::parse(const ByteVector &data)
ByteVector APE::Item::render() const
{
ByteVector data;
unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
unsigned int flags = (d->readOnly ? 1 : 0) | (d->type << 1);
ByteVector val;
if(isEmpty())

View File

@@ -63,7 +63,7 @@ namespace TagLib {
/*!
* Constructs an item with \a key and \a value.
* If \a binary is true a Binary item will be created, otherwise \a value will be interpreted as text
* If \a binary is \c true a Binary item will be created, otherwise \a value will be interpreted as text
*/
Item(const String &key, const ByteVector &value, bool binary);
@@ -75,7 +75,7 @@ namespace TagLib {
/*!
* Destroys the item.
*/
virtual ~Item();
~Item();
/*!
* Copies the contents of \a item into this item.
@@ -83,7 +83,7 @@ namespace TagLib {
Item &operator=(const Item &item);
/*!
* Exchanges the content of this item by the content of \a item.
* Exchanges the content of this item with the content of \a item.
*/
void swap(Item &item) noexcept;
@@ -172,7 +172,7 @@ namespace TagLib {
void setReadOnly(bool readOnly);
/*!
* Return true if the item is read-only.
* Return \c true if the item is read-only.
*/
bool isReadOnly() const;
@@ -189,7 +189,7 @@ namespace TagLib {
ItemTypes type() const;
/*!
* Returns if the item has any real content.
* Returns \c false if the item has any real content.
*/
bool isEmpty() const;

View File

@@ -137,9 +137,9 @@ void APE::Properties::read(File *file, offset_t streamLength)
analyzeOld(file);
if(d->sampleFrames > 0 && d->sampleRate > 0) {
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
const auto length = static_cast<double>(d->sampleFrames) * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
d->bitrate = static_cast<int>(static_cast<double>(streamLength) * 8.0 / length + 0.5);
}
}
@@ -153,9 +153,8 @@ void APE::Properties::analyzeCurrent(File *file)
return;
}
const unsigned int descriptorBytes = descriptor.toUInt(0, false);
if((descriptorBytes - 52) > 0)
if(const unsigned int descriptorBytes = descriptor.toUInt(0, false);
descriptorBytes - 52 > 0)
file->seek(descriptorBytes - 52, File::Current);
// Read the header

View File

@@ -97,7 +97,7 @@ namespace TagLib {
unsigned int sampleFrames() const;
/*!
* Returns APE version.
* Returns the APE version.
*/
int version() const;

View File

@@ -47,8 +47,8 @@ using namespace APE;
namespace
{
const unsigned int MinKeyLength = 2;
const unsigned int MaxKeyLength = 255;
constexpr unsigned int MinKeyLength = 2;
constexpr unsigned int MaxKeyLength = 255;
const String FRONT_COVER("COVER ART (FRONT)");
const String BACK_COVER("COVER ART (BACK)");
@@ -203,10 +203,10 @@ PropertyMap APE::Tag::properties() const
{
PropertyMap properties;
for(const auto &[tag, item] : std::as_const(itemListMap())) {
String tagName = tag.upper();
// if the item is Binary or Locator, or if the key is an invalid string,
// add to unsupportedData
if(item.type() != Item::Text || tagName.isEmpty()) {
if(String tagName = tag.upper();
item.type() != Item::Text || tagName.isEmpty()) {
properties.addUnsupportedData(tag);
}
else {
@@ -241,9 +241,9 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
// first check if tags need to be removed completely
StringList toRemove;
for(const auto &[k, t] : std::as_const(itemListMap())) {
String key = k.upper();
// only remove if a) key is valid, b) type is text, c) key not contained in new properties
if(!key.isEmpty() && t.type() == APE::Item::Text && !props.contains(key))
if(String key = k.upper();
!key.isEmpty() && t.type() == APE::Item::Text && !props.contains(key))
toRemove.append(k);
}
@@ -255,7 +255,7 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
for(const auto &[tagName, val] : std::as_const(props)) {
if(!checkKey(tagName))
invalid.insert(tagName, val);
else if(!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == val)) {
else if(!itemListMap().contains(tagName) || itemListMap()[tagName].values() != val) {
if(val.isEmpty())
removeItem(tagName);
else {
@@ -281,13 +281,12 @@ StringList APE::Tag::complexPropertyKeys() const
List<VariantMap> APE::Tag::complexProperties(const String &key) const
{
List<VariantMap> props;
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
const StringList itemNames = StringList(FRONT_COVER).append(BACK_COVER);
for(const auto &itemName: itemNames) {
if(d->itemListMap.contains(itemName)) {
Item picture = d->itemListMap.value(itemName);
if(picture.type() == Item::Binary) {
if(Item picture = d->itemListMap.value(itemName);
picture.type() == Item::Binary) {
ByteVector data = picture.binaryData();
// Do not search for a description if the first byte could start JPG or PNG
// data.
@@ -316,8 +315,7 @@ List<VariantMap> APE::Tag::complexProperties(const String &key) const
bool APE::Tag::setComplexProperties(const String &key, const List<VariantMap> &value)
{
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
removeItem(FRONT_COVER);
removeItem(BACK_COVER);

View File

@@ -29,6 +29,7 @@
#include "tbytevector.h"
#include "tmap.h"
#include "tstring.h"
#include "taglib.h"
#include "taglib_export.h"
#include "tag.h"
#include "apeitem.h"
@@ -116,6 +117,7 @@ namespace TagLib {
*
* The only conversion done by this export function is to rename the APE tags
* TRACK to TRACKNUMBER, YEAR to DATE, and ALBUM ARTIST to ALBUMARTIST, respectively,
* (and a few other keys, see \ref p_propertymapping)
* in order to be compliant with the names used in other formats.
*/
PropertyMap properties() const override;
@@ -165,7 +167,7 @@ namespace TagLib {
/*!
* Adds to the text item specified by \a key the data \a value. If \a replace
* is true, then all of the other values on the same key will be removed
* is \c true, then all of the other values on the same key will be removed
* first. If a binary item exists for \a key it will be removed first.
*/
void addValue(const String &key, const String &value, bool replace = true);
@@ -184,7 +186,7 @@ namespace TagLib {
void setItem(const String &key, const Item &item);
/*!
* Returns true if the tag does not contain any data.
* Returns \c true if the tag does not contain any data.
*/
bool isEmpty() const override;

View File

@@ -39,7 +39,7 @@ public:
pictureValue(ASF::Picture::fromInvalid())
{
}
AttributeTypes type;
AttributeTypes type { UnicodeType };
String stringValue;
ByteVector byteVectorValue;
ASF::Picture pictureValue;
@@ -154,7 +154,7 @@ unsigned int ASF::Attribute::toUInt() const
unsigned long long ASF::Attribute::toULongLong() const
{
return static_cast<unsigned long long>(d->numericValue);
return d->numericValue;
}
ASF::Picture ASF::Attribute::toPicture() const
@@ -162,30 +162,30 @@ ASF::Picture ASF::Attribute::toPicture() const
return d->pictureValue;
}
String ASF::Attribute::parse(ASF::File &f, int kind)
String ASF::Attribute::parse(ASF::File &file, int kind)
{
unsigned int size, nameLength;
String name;
d->pictureValue = Picture::fromInvalid();
// extended content descriptor
if(kind == 0) {
nameLength = readWORD(&f);
name = readString(&f, nameLength);
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&f));
size = readWORD(&f);
nameLength = readWORD(&file);
name = readString(&file, nameLength);
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&file));
size = readWORD(&file);
}
// metadata & metadata library
else {
int temp = readWORD(&f);
int temp = readWORD(&file);
// metadata library
if(kind == 2) {
d->language = temp;
}
d->stream = readWORD(&f);
nameLength = readWORD(&f);
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&f));
size = readDWORD(&f);
name = readString(&f, nameLength);
d->stream = readWORD(&file);
nameLength = readWORD(&file);
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&file));
size = readDWORD(&file);
name = readString(&file, nameLength);
}
if(kind != 2 && size > 65535) {
@@ -194,33 +194,33 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
switch(d->type) {
case WordType:
d->numericValue = readWORD(&f);
d->numericValue = readWORD(&file);
break;
case BoolType:
if(kind == 0) {
d->numericValue = (readDWORD(&f) != 0);
d->numericValue = readDWORD(&file) != 0;
}
else {
d->numericValue = (readWORD(&f) != 0);
d->numericValue = readWORD(&file) != 0;
}
break;
case DWordType:
d->numericValue = readDWORD(&f);
d->numericValue = readDWORD(&file);
break;
case QWordType:
d->numericValue = readQWORD(&f);
d->numericValue = readQWORD(&file);
break;
case UnicodeType:
d->stringValue = readString(&f, size);
d->stringValue = readString(&file, size);
break;
case BytesType:
case GuidType:
d->byteVectorValue = f.readBlock(size);
d->byteVectorValue = file.readBlock(size);
break;
}
@@ -240,7 +240,6 @@ int ASF::Attribute::dataSize() const
case WordType:
return 2;
case BoolType:
return 4;
case DWordType:
return 4;
case QWordType:
@@ -303,16 +302,16 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
if(kind == 0) {
data = renderString(name, true) +
ByteVector::fromShort(static_cast<int>(d->type), false) +
ByteVector::fromShort(data.size(), false) +
ByteVector::fromShort(static_cast<short>(d->type), false) +
ByteVector::fromShort(static_cast<short>(data.size()), false) +
data;
}
else {
ByteVector nameData = renderString(name);
data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
ByteVector::fromShort(d->stream, false) +
ByteVector::fromShort(nameData.size(), false) +
ByteVector::fromShort(static_cast<int>(d->type), false) +
data = ByteVector::fromShort(static_cast<short>(kind == 2 ? d->language : 0), false) +
ByteVector::fromShort(static_cast<short>(d->stream), false) +
ByteVector::fromShort(static_cast<short>(nameData.size()), false) +
ByteVector::fromShort(static_cast<short>(d->type), false) +
ByteVector::fromUInt(data.size(), false) +
nameData +
data;

View File

@@ -38,6 +38,8 @@ namespace TagLib
class File;
class Picture;
//! Attribute of ASF (WMA) metadata
class TAGLIB_EXPORT Attribute
{
public:
@@ -114,17 +116,17 @@ namespace TagLib
Attribute &operator=(const Attribute &other);
/*!
* Exchanges the content of the Attribute by the content of \a other.
* Exchanges the content of the Attribute with the content of \a other.
*/
void swap(Attribute &other) noexcept;
/*!
* Destroys the attribute.
*/
virtual ~Attribute();
~Attribute();
/*!
* Returns type of the value.
* Returns the type of the value.
*/
AttributeTypes type() const;

View File

@@ -221,7 +221,8 @@ void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, long l
const long long duration = data.toLongLong(40, false);
const long long preroll = data.toLongLong(56, false);
file->d->properties->setLengthInMilliseconds(static_cast<int>(duration / 10000.0 - preroll + 0.5));
file->d->properties->setLengthInMilliseconds(
static_cast<int>(static_cast<double>(duration) / 10000.0 - static_cast<double>(preroll) + 0.5));
}
ByteVector ASF::File::FilePrivate::StreamPropertiesObject::guid() const
@@ -271,11 +272,11 @@ ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *f
const ByteVector v4 = renderString(file->d->tag->comment());
const ByteVector v5 = renderString(file->d->tag->rating());
data.clear();
data.append(ByteVector::fromShort(v1.size(), false));
data.append(ByteVector::fromShort(v2.size(), false));
data.append(ByteVector::fromShort(v3.size(), false));
data.append(ByteVector::fromShort(v4.size(), false));
data.append(ByteVector::fromShort(v5.size(), false));
data.append(ByteVector::fromShort(static_cast<short>(v1.size()), false));
data.append(ByteVector::fromShort(static_cast<short>(v2.size()), false));
data.append(ByteVector::fromShort(static_cast<short>(v3.size()), false));
data.append(ByteVector::fromShort(static_cast<short>(v4.size()), false));
data.append(ByteVector::fromShort(static_cast<short>(v5.size()), false));
data.append(v1);
data.append(v2);
data.append(v3);
@@ -302,7 +303,7 @@ void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(ByteVector::fromShort(static_cast<short>(attributeData.size()), false));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
@@ -325,7 +326,7 @@ void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, long long /*
ByteVector ASF::File::FilePrivate::MetadataObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(ByteVector::fromShort(static_cast<short>(attributeData.size()), false));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
@@ -348,7 +349,7 @@ void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, long
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(ByteVector::fromShort(static_cast<short>(attributeData.size()), false));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
@@ -472,7 +473,7 @@ bool ASF::File::isSupported(IOStream *stream)
// An ASF file has to start with the designated GUID.
const ByteVector id = Utils::readHeader(stream, 16, false);
return (id == headerGuid);
return id == headerGuid;
}
////////////////////////////////////////////////////////////////////////////////
@@ -564,8 +565,8 @@ bool ASF::File::save()
bool inMetadataObject = false;
for(const auto &attribute : attributes) {
const bool largeValue = (attribute.dataSize() > 65535);
const bool guid = (attribute.type() == Attribute::GuidType);
const bool largeValue = attribute.dataSize() > 65535;
const bool guid = attribute.type() == Attribute::GuidType;
if(!inExtendedContentDescriptionObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
d->extendedContentDescriptionObject->attributeData.append(attribute.render(name));
@@ -681,6 +682,5 @@ void ASF::File::read()
if(!filePropertiesObject || !streamPropertiesObject) {
debug("ASF::File::read(): Missing mandatory header objects.");
setValid(false);
return;
}
}

View File

@@ -35,6 +35,8 @@
namespace TagLib {
//! An implementation of ASF (WMA) metadata
namespace ASF {
//! An implementation of TagLib::File with ASF specific methods
/*!
* This implements and provides an interface for ASF files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
@@ -112,7 +114,7 @@ namespace TagLib {
/*!
* Save the file.
*
* This returns true if the save was successful.
* This returns \c true if the save was successful.
*/
bool save() override;

View File

@@ -30,7 +30,6 @@
#include "tbytevector.h"
#include "tpicturetype.h"
#include "taglib_export.h"
#include "attachedpictureframe.h"
namespace TagLib
{
@@ -40,9 +39,9 @@ namespace TagLib
//! An ASF attached picture interface implementation
/*!
* This is an implementation of ASF attached pictures interface. Pictures may be
* This is an implementation of ASF attached pictures. Pictures may be
* included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture
* attribute in a single tag). These pictures are usually in either JPEG or
* attributes in a single tag). These pictures are usually in either JPEG or
* PNG format.
* \see Attribute::toPicture()
* \see Attribute::Attribute(const Picture& picture)
@@ -50,7 +49,7 @@ namespace TagLib
class TAGLIB_EXPORT Picture {
public:
/*!
/*
* This describes the function or content of the picture.
*/
DECLARE_PICTURE_TYPE_ENUM(Type)
@@ -61,14 +60,14 @@ namespace TagLib
Picture();
/*!
* Construct an picture as a copy of \a other.
* Construct a picture as a copy of \a other.
*/
Picture(const Picture& other);
/*!
* Destroys the picture.
*/
virtual ~Picture();
~Picture();
/*!
* Copies the contents of \a other into this picture.
@@ -76,12 +75,12 @@ namespace TagLib
Picture& operator=(const Picture& other);
/*!
* Exchanges the content of the Picture by the content of \a other.
* Exchanges the content of the Picture with the content of \a other.
*/
void swap(Picture &other) noexcept;
/*!
* Returns true if Picture stores valid picture
* Returns \c true if Picture stores valid picture
*/
bool isValid() const;
@@ -136,7 +135,7 @@ namespace TagLib
/*!
* Returns the image data as a ByteVector.
*
* \note ByteVector has a data() method that returns a const char * which
* \note ByteVector has a data() method that returns a <tt>const char *</tt> which
* should make it easy to export this data to external programs.
*
* \see setPicture()

View File

@@ -38,7 +38,7 @@ namespace TagLib {
public:
/*!
* Audio codec types can be used in ASF file.
* Audio codec types which can be used in ASF files.
*/
enum Codec
{

View File

@@ -313,8 +313,7 @@ PropertyMap ASF::Tag::properties() const
}
for(const auto &[k, attributes] : std::as_const(d->attributeListMap)) {
const String key = translateKey(k);
if(!key.isEmpty()) {
if(const String key = translateKey(k); !key.isEmpty()) {
for(const auto &attr : attributes) {
if(key == "TRACKNUMBER") {
if(attr.type() == ASF::Attribute::DWordType)
@@ -411,8 +410,7 @@ StringList ASF::Tag::complexPropertyKeys() const
List<VariantMap> ASF::Tag::complexProperties(const String &key) const
{
List<VariantMap> props;
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
const AttributeList pictures = d->attributeListMap.value("WM/Picture");
for(const Attribute &attr : pictures) {
ASF::Picture picture = attr.toPicture();
@@ -430,8 +428,7 @@ List<VariantMap> ASF::Tag::complexProperties(const String &key) const
bool ASF::Tag::setComplexProperties(const String &key, const List<VariantMap> &value)
{
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
removeItem("WM/Picture");
for(const auto &property : value) {

View File

@@ -39,6 +39,8 @@ namespace TagLib {
using AttributeList = List<Attribute>;
using AttributeListMap = Map<String, AttributeList>;
//! An implementation of ASF (WMA) tags
class TAGLIB_EXPORT Tag : public TagLib::Tag {
friend class File;
@@ -64,7 +66,7 @@ namespace TagLib {
/*!
* Returns the album name; if no album name is present in the tag
* String::null will be returned.
* an empty string will be returned.
*/
String album() const override;
@@ -74,7 +76,7 @@ namespace TagLib {
String comment() const override;
/*!
* Returns the genre name; if no genre is present in the tag String::null
* Returns the genre name; if no genre is present in the tag an empty string
* will be returned.
*/
String genre() const override;
@@ -85,8 +87,8 @@ namespace TagLib {
virtual String rating() const;
/*!
* Returns the genre name; if no genre is present in the tag String::null
* will be returned.
* Returns the copyright information; if no copyright information is
* present in the tag an empty string will be returned.
*/
virtual String copyright() const;
@@ -112,7 +114,7 @@ namespace TagLib {
void setArtist(const String &value) override;
/*!
* Sets the album to \a value. If \a value is String::null then this value will be
* Sets the album to \a value. If \a value is an empty string then this value will be
* cleared.
*/
void setAlbum(const String &value) override;
@@ -148,7 +150,7 @@ namespace TagLib {
void setTrack(unsigned int value) override;
/*!
* Returns true if the tag does not contain any data. This should be
* Returns \c true if the tag does not contain any data. This should be
* reimplemented in subclasses that provide more than the basic tagging
* abilities in this class.
*/
@@ -168,7 +170,7 @@ namespace TagLib {
const AttributeListMap &attributeListMap() const;
/*!
* \return True if a value for \a key is currently set.
* \return \c true if a value for \a key is currently set.
*/
bool contains(const String &key) const;

View File

@@ -90,7 +90,7 @@ namespace TagLib
{
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false);
if(includeLength) {
data = ByteVector::fromShort(data.size(), false) + data;
data = ByteVector::fromShort(static_cast<short>(data.size()), false) + data;
}
return data;
}

View File

@@ -37,7 +37,7 @@ namespace TagLib {
/*!
* The values here are common to most audio formats. For more specific, codec
* dependent values, please see see the subclasses APIs. This is meant to
* dependent values, please see the subclasses APIs. This is meant to
* compliment the TagLib::File and TagLib::Tag APIs in providing a simple
* interface that is sufficient for most applications.
*/

View File

@@ -48,7 +48,7 @@ namespace
char padding;
};
typedef std::vector<Chunk64> ChunkList;
using ChunkList = std::vector<Chunk64>;
int chunkIndex(const ChunkList &chunks, const ByteVector &id)
{
@@ -86,7 +86,7 @@ namespace
class DSDIFF::File::FilePrivate
{
public:
FilePrivate(ID3v2::FrameFactory *frameFactory)
FilePrivate(const ID3v2::FrameFactory *frameFactory)
: ID3v2FrameFactory(frameFactory ? frameFactory
: ID3v2::FrameFactory::instance())
{
@@ -130,7 +130,7 @@ bool DSDIFF::File::isSupported(IOStream *stream)
{
// A DSDIFF file has to start with "FRM8????????DSD ".
const ByteVector id = Utils::readHeader(stream, 16, false);
return (id.startsWith("FRM8") && id.containsAt("DSD ", 12));
return id.startsWith("FRM8") && id.containsAt("DSD ", 12);
}
////////////////////////////////////////////////////////////////////////////////
@@ -189,9 +189,9 @@ PropertyMap DSDIFF::File::properties() const
return d->tag.properties();
}
void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported)
void DSDIFF::File::removeUnsupportedProperties(const StringList &properties)
{
d->tag.removeUnsupportedProperties(unsupported);
d->tag.removeUnsupportedProperties(properties);
}
PropertyMap DSDIFF::File::setProperties(const PropertyMap &properties)
@@ -226,9 +226,7 @@ bool DSDIFF::File::save(int tags, StripTags strip, ID3v2::Version version)
// First: save ID3V2 chunk
ID3v2::Tag *id3v2Tag = ID3v2Tag();
if((tags & ID3v2) && id3v2Tag) {
if(const ID3v2::Tag *id3v2Tag = ID3v2Tag(); (tags & ID3v2) && id3v2Tag) {
if(d->isID3InPropChunk) {
if(!id3v2Tag->isEmpty()) {
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(version), PROPChunk);
@@ -255,9 +253,7 @@ bool DSDIFF::File::save(int tags, StripTags strip, ID3v2::Version version)
// Second: save the DIIN chunk
DSDIFF::DIIN::Tag *diinTag = DIINTag();
if((tags & DIIN) && diinTag) {
if(const DSDIFF::DIIN::Tag *diinTag = DIINTag(); (tags & DIIN) && diinTag) {
if(!diinTag->title().isEmpty()) {
ByteVector diinTitle;
diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian));
@@ -433,7 +429,7 @@ void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum)
// Update the internal offsets
// For child chunks
if((i + 1) < childChunks.size()) {
if(i + 1 < childChunks.size()) {
childChunks[i + 1].offset = childChunks[i].offset;
for(unsigned int c = i + 2; c < childChunks.size(); ++c)
childChunks[c].offset = childChunks[c - 1].offset + 12
@@ -527,8 +523,8 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
int i = d->childChunkIndex[DIINChunk];
if(i < 0) {
setRootChunkData("DIIN", ByteVector());
const int lastChunkIndex = static_cast<int>(d->chunks.size()) - 1;
if(lastChunkIndex >= 0 && d->chunks[lastChunkIndex].name == "DIIN") {
if(const int lastChunkIndex = static_cast<int>(d->chunks.size()) - 1;
lastChunkIndex >= 0 && d->chunks[lastChunkIndex].name == "DIIN") {
i = lastChunkIndex;
d->childChunkIndex[DIINChunk] = lastChunkIndex;
d->hasDiin = true;
@@ -559,13 +555,13 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
// Now add the chunk to the file
unsigned long long nextRootChunkIdx = length();
if((d->childChunkIndex[childChunkNum] + 1) < static_cast<int>(d->chunks.size()))
if(d->childChunkIndex[childChunkNum] + 1 < static_cast<int>(d->chunks.size()))
nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12;
writeChunk(name, data, offset,
static_cast<unsigned long>(
nextRootChunkIdx > offset ? nextRootChunkIdx - offset : 0),
(offset & 1) ? 1 : 0);
offset & 1 ? 1 : 0);
// For root chunks
@@ -575,7 +571,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
chunk.name = name;
chunk.size = data.size();
chunk.offset = offset + 12;
chunk.padding = (data.size() & 0x01) ? 1 : 0;
chunk.padding = data.size() & 0x01 ? 1 : 0;
childChunks.push_back(chunk);
}
@@ -589,8 +585,8 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
// Update child chunks structure as well
if(d->childChunkIndex[PROPChunk] >= static_cast<int>(startingChunk)) {
ChunkList &childChunksToUpdate = d->childChunks[PROPChunk];
if(!childChunksToUpdate.empty()) {
if(ChunkList &childChunksToUpdate = d->childChunks[PROPChunk];
!childChunksToUpdate.empty()) {
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[PROPChunk]].offset + 12;
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
@@ -599,8 +595,8 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
}
if(d->childChunkIndex[DIINChunk] >= static_cast<int>(startingChunk)) {
ChunkList &childChunksToUpdate = d->childChunks[DIINChunk];
if(!childChunksToUpdate.empty()) {
if(ChunkList &childChunksToUpdate = d->childChunks[DIINChunk];
!childChunksToUpdate.empty()) {
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[DIINChunk]].offset + 12;
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
@@ -647,10 +643,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
// Check padding
chunk.padding = 0;
offset_t uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
if(offset_t uPosNotPadded = tell(); (uPosNotPadded & 0x01) != 0) {
if(ByteVector iByte = readBlock(1);
iByte.size() != 1 || iByte[0] != 0)
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
else
@@ -708,10 +703,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
seek(dstChunkSize, Current);
// Check padding
offset_t uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
if(offset_t uPosNotPadded = tell(); (uPosNotPadded & 0x01) != 0) {
if(ByteVector iByte = readBlock(1);
iByte.size() != 1 || iByte[0] != 0)
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
}
@@ -749,10 +743,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
// Check padding
chunk.padding = 0;
offset_t uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
if(offset_t uPosNotPadded = tell(); (uPosNotPadded & 0x01) != 0) {
if(ByteVector iByte = readBlock(1);
iByte.size() != 1 || iByte[0] != 0)
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
else
@@ -797,11 +790,10 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
// Check padding
chunk.padding = 0;
offset_t uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
if(offset_t uPosNotPadded = tell(); (uPosNotPadded & 0x01) != 0) {
if(ByteVector iByte = readBlock(1);
iByte.size() != 1 || iByte[0] != 0)
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
else
@@ -867,16 +859,16 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
for(unsigned int i = 0; i < d->childChunks[DIINChunk].size(); i++) {
if(d->childChunks[DIINChunk][i].name == "DITI") {
seek(d->childChunks[DIINChunk][i].offset);
unsigned int titleStrLength = readBlock(4).toUInt(0, 4, bigEndian);
if(titleStrLength <= d->childChunks[DIINChunk][i].size) {
if(unsigned int titleStrLength = readBlock(4).toUInt(0, 4, bigEndian);
titleStrLength <= d->childChunks[DIINChunk][i].size) {
ByteVector titleStr = readBlock(titleStrLength);
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setTitle(titleStr);
}
}
else if(d->childChunks[DIINChunk][i].name == "DIAR") {
seek(d->childChunks[DIINChunk][i].offset);
unsigned int artistStrLength = readBlock(4).toUInt(0, 4, bigEndian);
if(artistStrLength <= d->childChunks[DIINChunk][i].size) {
if(unsigned int artistStrLength = readBlock(4).toUInt(0, 4, bigEndian);
artistStrLength <= d->childChunks[DIINChunk][i].size) {
ByteVector artistStr = readBlock(artistStrLength);
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setArtist(artistStr);
}
@@ -902,7 +894,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
int bitrate = 0;
if(lengthDSDSamplesTimeChannels > 0)
bitrate = static_cast<int>(
(audioDataSizeinBytes * 8 * sampleRate) / lengthDSDSamplesTimeChannels / 1000);
audioDataSizeinBytes * 8 * sampleRate / lengthDSDSamplesTimeChannels / 1000);
d->properties = std::make_unique<Properties>(sampleRate, channels,
lengthDSDSamplesTimeChannels, bitrate, propertiesStyle);

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"
@@ -36,20 +36,21 @@ namespace TagLib {
//! An implementation of DSDIFF metadata
/*!
* This is implementation of DSDIFF metadata.
* This is an implementation of DSDIFF metadata.
*
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
* chunk as well as properties from the file.
* Description of the DSDIFF format is available
* at http://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf
* DSDIFF standard does not explicitly specify the ID3V2 chunk
* It can be found at the root level, but also sometimes inside the PROP chunk
* In addition, title and artist info are stored as part of the standard
* Description of the DSDIFF format is available at
* <a href="https://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf">
* DSDIFF_1.5_Spec.pdf</a>.
* The DSDIFF standard does not explicitly specify the ID3 chunk.
* It can be found at the root level, but also sometimes inside the PROP chunk.
* In addition, title and artist info are stored as part of the standard.
*/
namespace DSDIFF {
//! An implementation of TagLib::File with DSDIFF specific methods
//! An implementation of TagLib::File with DSDIFF specific methods.
/*!
* This implements and provides an interface for DSDIFF files to the
@@ -78,7 +79,7 @@ namespace TagLib {
};
/*!
* Constructs a DSDIFF file from \a file. If \a readProperties is true
* Constructs a DSDIFF file from \a file. If \a readProperties is \c true
* the file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
@@ -91,7 +92,7 @@ namespace TagLib {
ID3v2::FrameFactory *frameFactory = nullptr);
/*!
* Constructs an DSDIFF file from \a stream. If \a readProperties is true
* Constructs a DSDIFF file from \a stream. If \a readProperties is \c true
* the file's audio properties will also be read.
*
* If this file contains an ID3v2 tag, the frames will be created using
@@ -168,7 +169,7 @@ namespace TagLib {
/*!
* Save the file. If at least one tag -- ID3v1 or DIIN -- exists this
* will duplicate its content into the other tag. This returns true
* will duplicate its content into the other tag. This returns \c true
* if saving was successful.
*
* If neither exists or if both tags are empty, this will strip the tags
@@ -177,7 +178,7 @@ namespace TagLib {
* This is the same as calling save(AllTags);
*
* If you would like more granular control over the content of the tags,
* with the concession of generality, use paramaterized save call below.
* with the concession of generality, use parameterized save call below.
*
* \see save(int tags)
*/
@@ -193,7 +194,7 @@ namespace TagLib {
/*!
* This will strip the tags that match the OR-ed together TagTypes from the
* file. By default it strips all tags. It returns true if the tags are
* file. By default it strips all tags. It returns \c true if the tags are
* successfully stripped.
*
* \note This will update the file immediately.
@@ -227,9 +228,6 @@ namespace TagLib {
protected:
enum Endianness { BigEndian, LittleEndian };
File(FileName file, Endianness endianness);
File(IOStream *stream, Endianness endianness);
private:
void removeRootChunk(const ByteVector &id);
void removeRootChunk(unsigned int i);
@@ -237,7 +235,7 @@ namespace TagLib {
void removeChildChunk(unsigned int i, unsigned int childChunkNum);
/*!
* Sets the data for the the specified chunk at root level to \a data.
* Sets the data for the specified chunk at root level to \a data.
*
* \warning This will update the file immediately.
*/
@@ -254,7 +252,7 @@ namespace TagLib {
void setRootChunkData(const ByteVector &name, const ByteVector &data);
/*!
* Sets the data for the the specified child chunk to \a data.
* Sets the data for the specified child chunk to \a data.
*
* If data is null, then remove the chunk
*
@@ -266,7 +264,7 @@ namespace TagLib {
/*!
* Sets the data for the child chunk \a name to \a data. If a chunk with
* the given name already exists it will be overwritten, otherwise it will
* be created after the existing chunks inside child chunk.
* be created after the existing chunks inside the child chunk.
*
* If data is null, then remove the chunks with \a name name
*

View File

@@ -26,7 +26,6 @@
#include "dsdiffproperties.h"
#include "tstring.h"
#include "tdebug.h"
using namespace TagLib;
@@ -45,10 +44,10 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
DSDIFF::Properties::Properties(const unsigned int sampleRate,
const unsigned short channels,
const unsigned long long samplesCount,
const int bitrate,
DSDIFF::Properties::Properties(unsigned int sampleRate,
unsigned short channels,
unsigned long long samplesCount,
int bitrate,
ReadStyle style) :
AudioProperties(style),
d(std::make_unique<PropertiesPrivate>())
@@ -59,7 +58,7 @@ DSDIFF::Properties::Properties(const unsigned int sampleRate,
d->sampleRate = sampleRate;
d->bitrate = bitrate;
d->length = d->sampleRate > 0
? static_cast<int>((d->sampleCount * 1000.0) / d->sampleRate + 0.5)
? static_cast<int>(static_cast<double>(d->sampleCount) * 1000.0 / d->sampleRate + 0.5)
: 0;
}

View File

@@ -37,7 +37,7 @@ namespace TagLib {
//! An implementation of audio property reading for DSDIFF
/*!
* This reads the data from an DSDIFF stream found in the AudioProperties
* This reads the data from a DSDIFF stream found in the AudioProperties
* API.
*/
@@ -48,8 +48,8 @@ namespace TagLib {
* Create an instance of DSDIFF::Properties with the data read from the
* ByteVector \a data.
*/
Properties(const unsigned int sampleRate, const unsigned short channels,
const unsigned long long samplesCount, const int bitrate,
Properties(unsigned int sampleRate, unsigned short channels,
unsigned long long samplesCount, int bitrate,
ReadStyle style);
/*!

View File

@@ -31,12 +31,10 @@
using namespace TagLib;
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
class DSF::File::FilePrivate
{
public:
FilePrivate(ID3v2::FrameFactory *frameFactory)
FilePrivate(const ID3v2::FrameFactory *frameFactory)
: ID3v2FrameFactory(frameFactory ? frameFactory
: ID3v2::FrameFactory::instance())
{
@@ -61,7 +59,7 @@ bool DSF::File::isSupported(IOStream *stream)
return id.startsWith("DSD ");
}
DSF::File::File(FileName file, bool readProperties,
DSF::File::File(FileName file, bool,
AudioProperties::ReadStyle propertiesStyle,
ID3v2::FrameFactory *frameFactory) :
TagLib::File(file),
@@ -71,7 +69,7 @@ DSF::File::File(FileName file, bool readProperties,
read(propertiesStyle);
}
DSF::File::File(IOStream *stream, bool readProperties,
DSF::File::File(IOStream *stream, bool,
AudioProperties::ReadStyle propertiesStyle,
ID3v2::FrameFactory *frameFactory) :
TagLib::File(stream),

View File

@@ -36,7 +36,27 @@
#include "id3v2tag.h"
namespace TagLib {
//! An implementation of DSF metadata
/*!
* This is an implementation of DSF metadata using an ID3v2 tag inside the
* metadata chunk.
* The DSF specification is located at
* http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
*/
namespace DSF {
//! An implementation of TagLib::File with DSF specific methods
/*!
* This implements and provides an interface for DSF files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to DSF files.
*/
class TAGLIB_EXPORT File : public TagLib::File {
public:
/*!
@@ -103,7 +123,7 @@ namespace TagLib {
/*!
* Save the file.
*
* This returns true if the save was successful.
* This returns \c true if the save was successful.
*/
bool save() override;

View File

@@ -127,8 +127,8 @@ void DSF::Properties::read(const ByteVector &data)
d->blockSizePerChannel = data.toUInt(32U,false);
d->bitrate = static_cast<unsigned int>(
(d->samplingFrequency * d->bitsPerSample * d->channelNum) / 1000.0 + 0.5);
d->samplingFrequency * d->bitsPerSample * d->channelNum / 1000.0 + 0.5);
d->length = d->samplingFrequency > 0
? static_cast<unsigned int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5)
? static_cast<unsigned int>(static_cast<double>(d->sampleCount) * 1000.0 / d->samplingFrequency + 0.5)
: 0;
}

View File

@@ -34,6 +34,7 @@
namespace TagLib {
namespace DSF {
//! An implementation of audio properties for DSF
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
Properties(const ByteVector &data, ReadStyle style);

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;
@@ -119,8 +139,7 @@ namespace
#endif
String ext;
const int pos = s.rfind(".");
if(pos != -1)
if(const int pos = s.rfind("."); pos != -1)
ext = s.substr(pos + 1).upper();
// If this list is updated, the method defaultFileExtensions() should also be
@@ -136,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") {
@@ -148,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);
@@ -177,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.
@@ -202,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.
@@ -264,7 +321,7 @@ public:
return !file || !file->isValid();
}
bool isNullWithDebugMessage(const String &methodName) const
bool isNullWithDebugMessage([[maybe_unused]] const String &methodName) const
{
if(isNull()) {
debug("FileRef::" + methodName + "() - Called without a valid file.");
@@ -401,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");
@@ -419,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"
@@ -434,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;
}
@@ -457,12 +533,12 @@ void FileRef::swap(FileRef &ref) noexcept
bool FileRef::operator==(const FileRef &ref) const
{
return (ref.d->file == d->file);
return ref.d->file == d->file;
}
bool FileRef::operator!=(const FileRef &ref) const
{
return (ref.d->file != d->file);
return ref.d->file != d->file;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -60,34 +60,12 @@ namespace TagLib {
{
public:
//! A class for pluggable file type resolution.
//! A class for pluggable file type resolution.
/*!
* This class is used to extend TagLib's very basic file name based file
* type resolution.
*
* This can be accomplished with:
*
* \code
*
* class MyFileTypeResolver : FileTypeResolver
* {
* TagLib::File *createFile(TagLib::FileName *fileName, bool, AudioProperties::ReadStyle) const
* {
* if(someCheckForAnMP3File(fileName))
* return new TagLib::MPEG::File(fileName);
* return 0;
* }
* }
*
* FileRef::addFileTypeResolver(new MyFileTypeResolver);
*
* \endcode
*
* Naturally a less contrived example would be slightly more complex. This
* can be used to plug in mime-type detection systems or to add new file types
* to TagLib.
*/
/*!
* %File type resolver, better implement StreamTypeResolver in order to
* support both file and stream resolution.
*/
class TAGLIB_EXPORT FileTypeResolver
{
@@ -120,6 +98,44 @@ namespace TagLib {
std::unique_ptr<FileTypeResolverPrivate> d;
};
//! A class for pluggable stream type resolution.
/*!
* This class is used to extend TagLib's very basic file name based file
* type resolution.
*
* This can be accomplished with:
*
* \code
*
* class MyStreamTypeResolver : StreamTypeResolver
* {
* TagLib::File *createFile(TagLib::FileName *fileName, bool readProps,
* AudioProperties::ReadStyle readStyle) const override
* {
* if(someCheckForAnMP3File(fileName))
* return new TagLib::MPEG::File(fileName, readProps, readStyle);
* return nullptr;
* }
*
* TagLib::File *createFileFromStream(TagLib::IOStream *s, bool readProps,
* AudioProperties::ReadStyle readStyle) const override
* {
* if(someCheckForAnMP3Stream(s))
* return new TagLib::MPEG::File(s, readProps, readStyle);
* return nullptr;
* }
* }
*
* FileRef::addFileTypeResolver(new MyStreamTypeResolver);
*
* \endcode
*
* Naturally a less contrived example would be slightly more complex. This
* can be used to plug in mime-type detection systems or to add new file types
* to TagLib.
*/
class TAGLIB_EXPORT StreamTypeResolver : public FileTypeResolver
{
public:
@@ -127,11 +143,22 @@ namespace TagLib {
/*!
* Destroys this StreamTypeResolver instance.
*/
~StreamTypeResolver() override = 0;
virtual ~StreamTypeResolver() override = 0; // virtual is needed by SWIG
StreamTypeResolver(const StreamTypeResolver &) = delete;
StreamTypeResolver &operator=(const StreamTypeResolver &) = delete;
/*!
* This method must be overridden to provide an additional stream type
* resolver. If the resolver is able to determine the file type it should
* return a valid File object; if not it should return nullptr.
*
* \note The created file is then owned by the FileRef and should not be
* deleted. Deletion will happen automatically when the FileRef passes
* out of scope.
*
* \see createFile()
*/
virtual File *createFileFromStream(IOStream *stream,
bool readAudioProperties = true,
AudioProperties::ReadStyle
@@ -148,9 +175,9 @@ namespace TagLib {
FileRef();
/*!
* Create a FileRef from \a fileName. If \a readAudioProperties is true then
* Create a FileRef from \a fileName. If \a readAudioProperties is \c true then
* the audio properties will be read using \a audioPropertiesStyle. If
* \a readAudioProperties is false then \a audioPropertiesStyle will be
* \a readAudioProperties is \c false then \a audioPropertiesStyle will be
* ignored.
*
* Also see the note in the class documentation about why you may not want to
@@ -163,8 +190,8 @@ namespace TagLib {
/*!
* Construct a FileRef from an opened \a IOStream. If \a readAudioProperties
* is true then the audio properties will be read using \a audioPropertiesStyle.
* If \a readAudioProperties is false then \a audioPropertiesStyle will be
* is \c true then the audio properties will be read using \a audioPropertiesStyle.
* If \a readAudioProperties is \c false then \a audioPropertiesStyle will be
* ignored.
*
* Also see the note in the class documentation about why you may not want to
@@ -195,7 +222,7 @@ namespace TagLib {
~FileRef();
/*!
* Returns a pointer to represented file's tag.
* Returns a pointer to the represented file's tag.
*
* \warning This pointer will become invalid when this FileRef and all
* copies pass out of scope.
@@ -287,7 +314,7 @@ namespace TagLib {
/*!
* Returns the audio properties for this FileRef. If no audio properties
* were read then this will returns a null pointer.
* were read then this will return a null pointer.
*/
AudioProperties *audioProperties() const;
@@ -309,7 +336,7 @@ namespace TagLib {
File *file() const;
/*!
* Saves the file. Returns true on success.
* Saves the file. Returns \c true on success.
*/
bool save();
@@ -351,7 +378,7 @@ namespace TagLib {
static StringList defaultFileExtensions();
/*!
* Returns true if the file (and as such other pointers) are null.
* Returns \c true if the file (and as such other pointers) are null.
*/
bool isNull() const;
@@ -361,17 +388,17 @@ namespace TagLib {
FileRef &operator=(const FileRef &ref);
/*!
* Exchanges the content of the FileRef by the content of \a ref.
* Exchanges the content of the FileRef with the content of \a ref.
*/
void swap(FileRef &ref) noexcept;
/*!
* Returns true if this FileRef and \a ref point to the same File object.
* Returns \c true if this FileRef and \a ref point to the same File object.
*/
bool operator==(const FileRef &ref) const;
/*!
* Returns true if this FileRef and \a ref do not point to the same File
* Returns \c true if this FileRef and \a ref do not point to the same File
* object.
*/
bool operator!=(const FileRef &ref) const;

View File

@@ -45,10 +45,10 @@ namespace
{
enum { FlacXiphIndex = 0, FlacID3v2Index = 1, FlacID3v1Index = 2 };
const long MinPaddingLength = 4096;
const long MaxPaddingLegnth = 1024 * 1024;
constexpr long MinPaddingLength = 4096;
constexpr long MaxPaddingLegnth = 1024 * 1024;
const char LastBlockFlag = '\x80';
constexpr char LastBlockFlag = '\x80';
} // namespace
class FLAC::File::FilePrivate
@@ -86,7 +86,7 @@ bool FLAC::File::isSupported(IOStream *stream)
// A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede.
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
return (buffer.find("fLaC") >= 0);
return buffer.find("fLaC") >= 0;
}
////////////////////////////////////////////////////////////////////////////////
@@ -171,8 +171,7 @@ StringList FLAC::File::complexPropertyKeys() const
List<VariantMap> FLAC::File::complexProperties(const String &key) const
{
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
List<VariantMap> props;
for(const auto &block : std::as_const(d->blocks)) {
if(auto picture = dynamic_cast<Picture *>(block)) {
@@ -196,8 +195,7 @@ List<VariantMap> FLAC::File::complexProperties(const String &key) const
bool FLAC::File::setComplexProperties(const String &key, const List<VariantMap> &value)
{
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
removePictures();
for(const auto &property : value) {
@@ -267,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] = static_cast<char>((*it)->code());
data.append(blockHeader);
data.append(blockData);
++it;
}
// Compute the amount of padding, and append that to data.
@@ -303,10 +308,10 @@ bool FLAC::File::save()
insert(data, d->flacStart, originalLength);
d->streamStart += (static_cast<long>(data.size()) - originalLength);
d->streamStart += static_cast<long>(data.size()) - originalLength;
if(d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - originalLength);
d->ID3v1Location += static_cast<long>(data.size()) - originalLength;
// Update ID3 tags
@@ -320,11 +325,11 @@ bool FLAC::File::save()
data = ID3v2Tag()->render();
insert(data, d->ID3v2Location, d->ID3v2OriginalSize);
d->flacStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
d->streamStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
d->flacStart += static_cast<long>(data.size()) - d->ID3v2OriginalSize;
d->streamStart += static_cast<long>(data.size()) - d->ID3v2OriginalSize;
if(d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
d->ID3v1Location += static_cast<long>(data.size()) - d->ID3v2OriginalSize;
d->ID3v2OriginalSize = data.size();
}
@@ -449,12 +454,12 @@ bool FLAC::File::hasXiphComment() const
bool FLAC::File::hasID3v1Tag() const
{
return (d->ID3v1Location >= 0);
return d->ID3v1Location >= 0;
}
bool FLAC::File::hasID3v2Tag() const
{
return (d->ID3v2Location >= 0);
return d->ID3v2Location >= 0;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -43,7 +43,7 @@ namespace TagLib {
//! An implementation of FLAC metadata
/*!
* This is implementation of FLAC metadata for non-Ogg FLAC files. At some
* This is an implementation of FLAC metadata for non-Ogg FLAC files. At some
* point when Ogg / FLAC is more common there will be a similar implementation
* under the Ogg hierarchy.
*
@@ -83,7 +83,7 @@ namespace TagLib {
};
/*!
* Constructs a FLAC file from \a file. If \a readProperties is true the
* Constructs a FLAC file from \a file. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
@@ -96,13 +96,15 @@ namespace TagLib {
ID3v2::FrameFactory *frameFactory = nullptr);
/*!
* Constructs an FLAC file from \a file. If \a readProperties is true the
* Constructs a FLAC file from \a file. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* If this file contains an ID3v2 tag, the frames will be created using
* \a frameFactory.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*
* \deprecated Use the constructor above.
*/
TAGLIB_DEPRECATED
File(FileName file, ID3v2::FrameFactory *frameFactory,
@@ -110,7 +112,7 @@ namespace TagLib {
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Constructs a FLAC file from \a stream. If \a readProperties is true the
* Constructs a FLAC file from \a stream. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
@@ -126,7 +128,7 @@ namespace TagLib {
ID3v2::FrameFactory *frameFactory = nullptr);
/*!
* Constructs a FLAC file from \a stream. If \a readProperties is true the
* Constructs a FLAC file from \a stream. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
@@ -136,6 +138,8 @@ namespace TagLib {
* \a frameFactory.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*
* \deprecated Use the constructor above.
*/
TAGLIB_DEPRECATED
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
@@ -207,22 +211,22 @@ namespace TagLib {
* will also keep any old ID3-tags up to date. If the file
* has no XiphComment, one will be constructed from the ID3-tags.
*
* This returns true if the save was successful.
* This returns \c true if the save was successful.
*/
bool save() override;
/*!
* Returns a pointer to the ID3v2 tag of the file.
*
* If \a create is false (the default) this returns a null pointer
* if there is no valid ID3v2 tag. If \a create is true it will create
* If \a create is \c false (the default) this returns a null pointer
* if there is no valid ID3v2 tag. If \a create is \c true it will create
* an ID3v2 tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file
* on disk actually has an ID3v2 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
@@ -233,15 +237,15 @@ namespace TagLib {
/*!
* Returns a pointer to the ID3v1 tag of the file.
*
* If \a create is false (the default) this returns a null pointer
* if there is no valid APE tag. If \a create is true it will create
* If \a create is \c false (the default) this returns a null pointer
* if there is no valid APE tag. If \a create is \c true it will create
* an APE tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
* on disk actually has an ID3v1 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
@@ -252,8 +256,8 @@ namespace TagLib {
/*!
* Returns a pointer to the XiphComment for the file.
*
* If \a create is false (the default) this returns a null pointer
* if there is no valid XiphComment. If \a create is true it will create
* If \a create is \c false (the default) this returns a null pointer
* if there is no valid XiphComment. If \a create is \c true it will create
* a XiphComment if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
@@ -274,8 +278,8 @@ namespace TagLib {
List<Picture *> pictureList();
/*!
* Removes an attached picture. If \a del is true the picture's memory
* will be freed; if it is false, it must be deleted by the user.
* Removes an attached picture. If \a del is \c true the picture's memory
* will be freed; if it is \c false, it must be deleted by the user.
*/
void removePicture(Picture *picture, bool del = true);

View File

@@ -26,12 +26,12 @@
#ifndef TAGLIB_FLACMETADATABLOCK_H
#define TAGLIB_FLACMETADATABLOCK_H
#include "tlist.h"
#include "tbytevector.h"
#include "taglib_export.h"
namespace TagLib {
namespace FLAC {
//! FLAC metadata block
class TAGLIB_EXPORT MetadataBlock
{
public:

View File

@@ -35,11 +35,12 @@
namespace TagLib {
namespace FLAC {
//! FLAC picture
class TAGLIB_EXPORT Picture : public MetadataBlock
{
public:
/*!
/*
* This describes the function or content of the picture.
*/
DECLARE_PICTURE_TYPE_ENUM(Type)
@@ -71,7 +72,7 @@ namespace TagLib {
* Sets the mime type of the image. This should in most cases be
* "image/png" or "image/jpeg".
*/
void setMimeType(const String &m);
void setMimeType(const String &mimeType);
/*!
* Returns a text description of the image.
@@ -80,10 +81,10 @@ namespace TagLib {
String description() const;
/*!
* Sets a textual description of the image to \a desc.
* Sets a textual description of the image to \a description.
*/
void setDescription(const String &desc);
void setDescription(const String &description);
/*!
* Returns the width of the image.
@@ -93,7 +94,7 @@ namespace TagLib {
/*!
* Sets the width of the image.
*/
void setWidth(int w);
void setWidth(int width);
/*!
* Returns the height of the image.
@@ -103,7 +104,7 @@ namespace TagLib {
/*!
* Sets the height of the image.
*/
void setHeight(int h);
void setHeight(int height);
/*!
* Returns the color depth (in bits-per-pixel) of the image.
@@ -113,7 +114,7 @@ namespace TagLib {
/*!
* Sets the color depth (in bits-per-pixel) of the image.
*/
void setColorDepth(int depth);
void setColorDepth(int colorDepth);
/*!
* Returns the number of colors used on the image..
@@ -148,7 +149,7 @@ namespace TagLib {
/*!
* Parse the picture data in the FLAC picture block format.
*/
bool parse(const ByteVector &rawData);
bool parse(const ByteVector &data);
private:
class PicturePrivate;

View File

@@ -28,8 +28,6 @@
#include "tstring.h"
#include "tdebug.h"
#include "flacfile.h"
using namespace TagLib;
class FLAC::Properties::PropertiesPrivate
@@ -134,9 +132,9 @@ void FLAC::Properties::read(const ByteVector &data, offset_t streamLength)
d->sampleFrames = (hi << 32) | lo;
if(d->sampleFrames > 0 && d->sampleRate > 0) {
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
const auto length = static_cast<double>(d->sampleFrames) * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
d->bitrate = static_cast<int>(static_cast<double>(streamLength) * 8.0 / length + 0.5);
}
if(data.size() >= pos + 16)

View File

@@ -37,7 +37,7 @@ namespace TagLib {
//! An implementation of audio property reading for FLAC
/*!
* This reads the data from an FLAC stream found in the AudioProperties
* This reads the data from a FLAC stream found in the AudioProperties
* API.
*/

View File

@@ -33,6 +33,7 @@
namespace TagLib {
namespace FLAC {
//! Unknown FLAC metadata block
class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock
{
public:

View File

@@ -27,7 +27,6 @@
#include "tstringlist.h"
#include "tdebug.h"
#include "tpropertymap.h"
#include "modfileprivate.h"
using namespace TagLib;
@@ -168,7 +167,7 @@ bool IT::File::save()
if(messageOffset + messageLength >= fileSize) {
// append new message
seek(54);
writeU16L(message.size());
writeU16L(static_cast<unsigned short>(message.size()));
writeU32L(messageOffset);
seek(messageOffset);
writeBlock(message);

View File

@@ -31,12 +31,27 @@
namespace TagLib {
//! An implementation of Impulse Tracker metadata
/*!
* This is an implementation of Impulse Tracker metadata.
*/
namespace IT {
//! An implementation of TagLib::File with IT specific methods
/*!
* This implements and provides an interface for IT files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to IT files.
*/
class TAGLIB_EXPORT File : public Mod::FileBase {
public:
/*!
* Constructs a Impulse Tracker file from \a file.
* Constructs an Impulse Tracker file from \a file.
*
* \note In the current implementation, both \a readProperties and
* \a propertiesStyle are ignored. The audio properties are always
@@ -47,7 +62,7 @@ namespace TagLib {
AudioProperties::Average);
/*!
* Constructs a Impulse Tracker file from \a stream.
* Constructs an Impulse Tracker file from \a stream.
*
* \note In the current implementation, both \a readProperties and
* \a propertiesStyle are ignored. The audio properties are always

View File

@@ -26,11 +26,11 @@
#ifndef TAGLIB_ITPROPERTIES_H
#define TAGLIB_ITPROPERTIES_H
#include "taglib.h"
#include "audioproperties.h"
namespace TagLib {
namespace IT {
//! An implementation of audio property reading for IT
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*! Flag bits. */

View File

@@ -34,7 +34,24 @@
#include "modproperties.h"
namespace TagLib {
//! An implementation of Protracker metadata
/*!
* This is an implementation of Protracker metadata.
*/
namespace Mod {
//! An implementation of TagLib::File with Mod specific methods
/*!
* This implements and provides an interface for Mod files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to Mod files.
*/
class TAGLIB_EXPORT File : public TagLib::Mod::FileBase
{
public:

View File

@@ -28,14 +28,12 @@
#include "taglib.h"
#include "tfile.h"
#include "tstring.h"
#include "tlist.h"
#include "taglib_export.h"
#include <algorithm>
namespace TagLib {
namespace Mod {
//! Base class for module files
class TAGLIB_EXPORT FileBase : public TagLib::File
{
public:

View File

@@ -26,11 +26,11 @@
#ifndef TAGLIB_MODPROPERTIES_H
#define TAGLIB_MODPROPERTIES_H
#include "taglib.h"
#include "audioproperties.h"
namespace TagLib {
namespace Mod {
//! An implementation of audio property reading for Mod
class TAGLIB_EXPORT Properties : public AudioProperties
{
public:

View File

@@ -128,7 +128,7 @@ PropertyMap Mod::Tag::properties() const
PropertyMap properties;
properties["TITLE"] = d->title;
properties["COMMENT"] = d->comment;
if(!(d->trackerName.isEmpty()))
if(!d->trackerName.isEmpty())
properties["TRACKERNAME"] = d->trackerName;
return properties;
}

View File

@@ -30,6 +30,9 @@
namespace TagLib {
namespace Mod {
//! A module file tag implementation
/*!
* Tags for module files (Mod, S3M, IT, XM).
*
@@ -53,29 +56,29 @@ namespace TagLib {
/*!
* Returns the track name; if no track name is present in the tag
* String::null will be returned.
* an empty string will be returned.
*/
String title() const override;
/*!
* Not supported by module files. Therefore always returns String::null.
* Not supported by module files. Therefore always returns an empty string.
*/
String artist() const override;
/*!
* Not supported by module files. Therefore always returns String::null.
* Not supported by module files. Therefore always returns an empty string.
*/
String album() const override;
/*!
* Returns the track comment derived from the instrument/sample/pattern
* names; if no comment is present in the tag String::null will be
* names; if no comment is present in the tag an empty string will be
* returned.
*/
String comment() const override;
/*!
* Not supported by module files. Therefore always returns String::null.
* Not supported by module files. Therefore always returns an empty string.
*/
String genre() const override;
@@ -94,12 +97,12 @@ namespace TagLib {
* Only XM files store this tag to the file as such, for other formats
* (Mod, S3M, IT) this is derived from the file type or the flavour of
* the file type. Therefore only XM files might have an empty
* (String::null) tracker name.
* tracker name.
*/
String trackerName() const;
/*!
* Sets the title to \a title. If \a title is String::null then this
* Sets the title to \a title. If \a title is an empty string then this
* value will be cleared.
*
* The length limits per file type are (1 character = 1 byte):
@@ -119,7 +122,7 @@ namespace TagLib {
void setAlbum(const String &album) override;
/*!
* Sets the comment to \a comment. If \a comment is String::null then
* Sets the comment to \a comment. If \a comment is an empty string then
* this value will be cleared.
*
* Note that module file formats don't actually support a comment tag.
@@ -128,7 +131,7 @@ namespace TagLib {
* module file is fixed to the number of instruments/patterns/samples.
*
* Also note that the instrument/pattern/sample name length is limited
* an thus the line length in comments are limited. Too big comments
* and thus the line length in comments are limited. Too big comments
* will be truncated.
*
* The line length limits per file type are (1 character = 1 byte):
@@ -154,7 +157,7 @@ namespace TagLib {
/*!
* Sets the tracker name to \a trackerName. If \a trackerName is
* String::null then this value will be cleared.
* an empty string then this value will be cleared.
*
* Note that only XM files support this tag. Setting the
* tracker name for other module file formats will be ignored.

View File

@@ -25,6 +25,7 @@
#include "mp4atom.h"
#include <array>
#include <climits>
#include <utility>
@@ -73,8 +74,8 @@ MP4::Atom::Atom(File *file)
}
else if(d->length == 1) {
// The atom has a 64-bit length.
const long long longLength = file->readBlock(8).toLongLong();
if(longLength <= LONG_MAX) {
if(const long long longLength = file->readBlock(8).toLongLong();
longLength <= LONG_MAX) {
// The actual length fits in long. That's always the case if long is 64-bit.
d->length = static_cast<long>(longLength);
}
@@ -94,14 +95,6 @@ MP4::Atom::Atom(File *file)
}
d->name = header.mid(4, 4);
for(int i = 0; i < 4; ++i) {
const char ch = d->name.at(i);
if((ch < ' ' || ch > '~') && ch != '\251') {
debug("MP4: Invalid atom type");
d->length = 0;
file->seek(0, File::End);
}
}
for(auto c : containers) {
if(d->name == c) {
@@ -143,12 +136,12 @@ MP4::Atom::find(const char *name1, const char *name2, const char *name3, const c
return this;
}
auto it = std::find_if(d->children.cbegin(), d->children.cend(),
[&name1](Atom *child) { return child->d->name == name1; });
[&name1](const Atom *child) { return child->d->name == name1; });
return it != d->children.cend() ? (*it)->find(name2, name3, name4) : nullptr;
}
MP4::AtomList
MP4::Atom::findall(const char *name, bool recursive)
MP4::Atom::findall(const char *name, bool recursive) const
{
MP4::AtomList result;
for(const auto &child : std::as_const(d->children)) {
@@ -170,7 +163,7 @@ MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const
return true;
}
auto it = std::find_if(d->children.cbegin(), d->children.cend(),
[&name1](Atom *child) { return child->d->name == name1; });
[&name1](const Atom *child) { return child->d->name == name1; });
return it != d->children.cend() ? (*it)->path(path, name2, name3) : false;
}
@@ -240,19 +233,19 @@ MP4::Atoms::Atoms(File *file) :
MP4::Atoms::~Atoms() = default;
MP4::Atom *
MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4)
MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4) const
{
auto it = std::find_if(d->atoms.cbegin(), d->atoms.cend(),
[&name1](Atom *atom) { return atom->name() == name1; });
[&name1](const Atom *atom) { return atom->name() == name1; });
return it != d->atoms.cend() ? (*it)->find(name2, name3, name4) : nullptr;
}
MP4::AtomList
MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4)
MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4) const
{
MP4::AtomList path;
auto it = std::find_if(d->atoms.cbegin(), d->atoms.cend(),
[&name1](Atom *atom) { return atom->name() == name1; });
[&name1](const Atom *atom) { return atom->name() == name1; });
if(it != d->atoms.cend()) {
if(!(*it)->path(path, name2, name3, name4)) {
path.clear();
@@ -271,28 +264,25 @@ namespace
}
} // namespace
bool MP4::Atoms::checkRootLevelAtoms()
{
bool MP4::Atoms::checkRootLevelAtoms() {
bool moovValid = false;
for(auto it = d->atoms.begin(); it != d->atoms.end(); ++it) {
bool invalid = (*it)->length() == 0 || !checkValid((*it)->children());
if(!moovValid && !invalid && (*it)->name() == "moov") {
bool invalid = (*it)->length() == 0 || !checkValid((*it)->children());
if(!moovValid && !invalid && (*it)->name() == "moov") {
moovValid = true;
}
if(invalid) {
if(!moovValid || (*it)->name() == "moof")
return false;
// Only the root level atoms "moov" and (if present) "moof" are
// modified. If they are valid, ignore following invalid root level
// atoms as trailing garbage.
while(it != d->atoms.end()) {
delete *it;
it = d->atoms.erase(it);
}
if(invalid) {
if(moovValid && (*it)->name() != "moof") {
// Only the root level atoms "moov" and (if present) "moof" are
// modified. If they are valid, ignore following invalid root level
// atoms as trailing garbage.
while(it != d->atoms.end()) {
delete *it;
it = d->atoms.erase(it);
}
return true;
}
else {
return false;
}
return true;
}
}

View File

@@ -28,17 +28,11 @@
#ifndef TAGLIB_MP4ATOM_H
#define TAGLIB_MP4ATOM_H
#include <array>
#include "tfile.h"
#include "tlist.h"
#ifndef DO_NOT_DOCUMENT
namespace TagLib {
namespace MP4 {
class Atom;
using AtomList = TagLib::List<Atom *>;
enum AtomDataType {
TypeImplicit = 0, // for use with tags for which no type needs to be indicated because only one type is allowed
@@ -64,14 +58,17 @@ namespace TagLib {
TypeUndefined = 255 // undefined
};
#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;
};
class Atom;
using AtomList = TagLib::List<Atom *>;
using AtomDataList = TagLib::List<AtomData>;
class TAGLIB_EXPORT Atom
@@ -83,7 +80,7 @@ namespace TagLib {
Atom &operator=(const Atom &) = delete;
Atom *find(const char *name1, const char *name2 = nullptr, const char *name3 = nullptr, const char *name4 = nullptr);
bool path(AtomList &path, const char *name1, const char *name2 = nullptr, const char *name3 = nullptr);
AtomList findall(const char *name, bool recursive = false);
AtomList findall(const char *name, bool recursive = false) const;
void addToOffset(offset_t delta);
void prependChild(Atom *atom);
bool removeChild(Atom *meta);
@@ -106,8 +103,8 @@ namespace TagLib {
~Atoms();
Atoms(const Atoms &) = delete;
Atoms &operator=(const Atoms &) = delete;
Atom *find(const char *name1, const char *name2 = nullptr, const char *name3 = nullptr, const char *name4 = nullptr);
AtomList path(const char *name1, const char *name2 = nullptr, const char *name3 = nullptr, const char *name4 = nullptr);
Atom *find(const char *name1, const char *name2 = nullptr, const char *name3 = nullptr, const char *name4 = nullptr) const;
AtomList path(const char *name1, const char *name2 = nullptr, const char *name3 = nullptr, const char *name4 = nullptr) const;
bool checkRootLevelAtoms();
const AtomList &atoms() const;
@@ -116,9 +113,8 @@ namespace TagLib {
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<AtomsPrivate> d;
};
#endif // DO_NOT_DOCUMENT
} // namespace MP4
} // namespace TagLib
#endif
#endif

View File

@@ -69,3 +69,13 @@ MP4::CoverArt::data() const
{
return d->data;
}
bool MP4::CoverArt::operator==(const CoverArt &other) const
{
return format() == other.format() && data() == other.data();
}
bool MP4::CoverArt::operator!=(const CoverArt &other) const
{
return !(*this == other);
}

View File

@@ -33,6 +33,7 @@
namespace TagLib {
namespace MP4 {
//! MP4 picture
class TAGLIB_EXPORT CoverArt
{
public:
@@ -48,7 +49,7 @@ namespace TagLib {
};
CoverArt(Format format, const ByteVector &data);
virtual ~CoverArt();
~CoverArt();
CoverArt(const CoverArt &item);
@@ -58,7 +59,7 @@ namespace TagLib {
CoverArt &operator=(const CoverArt &item);
/*!
* Exchanges the content of the CoverArt by the content of \a item.
* Exchanges the content of the CoverArt with the content of \a item.
*/
void swap(CoverArt &item) noexcept;
@@ -68,6 +69,17 @@ namespace TagLib {
//! The image data
ByteVector data() const;
/*!
* Returns \c true if the CoverArt and \a other are of the same format and
* contain the same data.
*/
bool operator==(const CoverArt &other) const;
/*!
* Returns \c true if the CoverArt and \a other differ in format or data.
*/
bool operator!=(const CoverArt &other) const;
private:
class CoverArtPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE

View File

@@ -36,7 +36,7 @@ using namespace TagLib;
class MP4::File::FilePrivate
{
public:
FilePrivate(MP4::ItemFactory *mp4ItemFactory)
FilePrivate(const MP4::ItemFactory *mp4ItemFactory)
: itemFactory(mp4ItemFactory ? mp4ItemFactory
: MP4::ItemFactory::instance())
{
@@ -174,5 +174,5 @@ MP4::File::strip(int tags)
bool
MP4::File::hasMP4Tag() const
{
return (d->atoms->find("moov", "udta", "meta", "ilst") != nullptr);
return d->atoms->find("moov", "udta", "meta", "ilst") != nullptr;
}

View File

@@ -38,6 +38,7 @@ namespace TagLib {
class Atoms;
class ItemFactory;
//! An implementation of TagLib::File with MP4 specific methods
/*!
* This implements and provides an interface for MP4 files to the
@@ -62,7 +63,7 @@ namespace TagLib {
};
/*!
* Constructs an MP4 file from \a file. If \a readProperties is true the
* Constructs an MP4 file from \a file. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
@@ -74,7 +75,7 @@ namespace TagLib {
ItemFactory *itemFactory = nullptr);
/*!
* Constructs an MP4 file from \a stream. If \a readProperties is true the
* Constructs an MP4 file from \a stream. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
@@ -132,13 +133,13 @@ namespace TagLib {
/*!
* Save the file.
*
* This returns true if the save was successful.
* This returns \c true if the save was successful.
*/
bool save() override;
/*!
* This will strip the tags that match the OR-ed together TagTypes from the
* file. By default it strips all tags. It returns true if the tags are
* file. By default it strips all tags. It returns \c true if the tags are
* successfully stripped.
*
* \note This will update the file immediately.

View File

@@ -30,6 +30,7 @@ using namespace TagLib;
class MP4::Item::ItemPrivate
{
public:
Type type;
bool valid { true };
AtomDataType atomDataType { TypeUndefined };
union {
@@ -48,6 +49,7 @@ public:
MP4::Item::Item() :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::Void;
d->valid = false;
}
@@ -67,36 +69,42 @@ MP4::Item::~Item() = default;
MP4::Item::Item(bool value) :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::Bool;
d->m_bool = value;
}
MP4::Item::Item(int value) :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::Int;
d->m_int = value;
}
MP4::Item::Item(unsigned char value) :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::Byte;
d->m_byte = value;
}
MP4::Item::Item(unsigned int value) :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::UInt;
d->m_uint = value;
}
MP4::Item::Item(long long value) :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::LongLong;
d->m_longlong = value;
}
MP4::Item::Item(int value1, int value2) :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::IntPair;
d->m_intPair.first = value1;
d->m_intPair.second = value2;
}
@@ -104,18 +112,21 @@ MP4::Item::Item(int value1, int value2) :
MP4::Item::Item(const ByteVectorList &value) :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::ByteVectorList;
d->m_byteVectorList = value;
}
MP4::Item::Item(const StringList &value) :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::StringList;
d->m_stringList = value;
}
MP4::Item::Item(const MP4::CoverArtList &value) :
d(std::make_shared<ItemPrivate>())
{
d->type = Type::CoverArtList;
d->m_coverArtList = value;
}
@@ -188,3 +199,47 @@ MP4::Item::isValid() const
{
return d->valid;
}
MP4::Item::Type MP4::Item::type() const
{
return d->type;
}
bool MP4::Item::operator==(const Item &other) const
{
if(isValid() && other.isValid() &&
type() == other.type() &&
atomDataType() == other.atomDataType()) {
switch(type()) {
case Type::Void:
return true;
case Type::Bool:
return toBool() == other.toBool();
case Type::Int:
return toInt() == other.toInt();
case Type::IntPair: {
const auto lhs = toIntPair();
const auto rhs = other.toIntPair();
return lhs.first == rhs.first && lhs.second == rhs.second;
}
case Type::Byte:
return toByte() == other.toByte();
case Type::UInt:
return toUInt() == other.toUInt();
case Type::LongLong:
return toLongLong() == other.toLongLong();
case Type::StringList:
return toStringList() == other.toStringList();
case Type::ByteVectorList:
return toByteVectorList() == other.toByteVectorList();
case Type::CoverArtList:
return toCoverArtList() == other.toCoverArtList();
}
}
return false;
}
bool MP4::Item::operator!=(const Item &other) const
{
return !(*this == other);
}

View File

@@ -32,9 +32,26 @@
namespace TagLib {
namespace MP4 {
//! MP4 item
class TAGLIB_EXPORT Item
{
public:
/*!
* The data type stored in the item.
*/
enum class Type : unsigned char {
Void,
Bool,
Int,
IntPair,
Byte,
UInt,
LongLong,
StringList,
ByteVectorList,
CoverArtList
};
struct IntPair {
int first, second;
};
@@ -48,11 +65,11 @@ namespace TagLib {
Item &operator=(const Item &item);
/*!
* Exchanges the content of the Item by the content of \a item.
* Exchanges the content of the Item with the content of \a item.
*/
void swap(Item &item) noexcept;
virtual ~Item();
~Item();
Item(int value);
Item(unsigned char value);
@@ -79,6 +96,19 @@ namespace TagLib {
bool isValid() const;
Type type() const;
/*!
* Returns \c true if the Item and \a other are of the same type and
* contain the same value.
*/
bool operator==(const Item &other) const;
/*!
* Returns \c true if the Item and \a other differ in type or value.
*/
bool operator!=(const Item &other) const;
private:
class ItemPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE

View File

@@ -35,6 +35,12 @@
using namespace TagLib;
using namespace MP4;
namespace {
constexpr char freeFormPrefix[] = "----:com.apple.iTunes:";
} // namespace
class ItemFactory::ItemFactoryPrivate
{
public:
@@ -57,8 +63,7 @@ ItemFactory *ItemFactory::instance()
std::pair<String, Item> ItemFactory::parseItem(
const Atom *atom, const ByteVector &data) const
{
auto handlerType = handlerTypeForName(atom->name());
switch(handlerType) {
switch(handlerTypeForName(atom->name())) {
case ItemHandlerType::Unknown:
break;
case ItemHandlerType::FreeForm:
@@ -96,40 +101,37 @@ ByteVector ItemFactory::renderItem(
if(itemName.startsWith("----")) {
return renderFreeForm(itemName, item);
}
else {
const ByteVector name = itemName.data(String::Latin1);
auto handlerType = handlerTypeForName(name);
switch(handlerType) {
case ItemHandlerType::Unknown:
debug("MP4: Unknown item name \"" + name + "\"");
break;
case ItemHandlerType::FreeForm:
return renderFreeForm(name, item);
case ItemHandlerType::IntPair:
return renderIntPair(name, item);
case ItemHandlerType::IntPairNoTrailing:
return renderIntPairNoTrailing(name, item);
case ItemHandlerType::Bool:
return renderBool(name, item);
case ItemHandlerType::Int:
return renderInt(name, item);
case ItemHandlerType::TextOrInt:
return renderTextOrInt(name, item);
case ItemHandlerType::UInt:
return renderUInt(name, item);
case ItemHandlerType::LongLong:
return renderLongLong(name, item);
case ItemHandlerType::Byte:
return renderByte(name, item);
case ItemHandlerType::Gnre:
return renderInt(name, item);
case ItemHandlerType::Covr:
return renderCovr(name, item);
case ItemHandlerType::TextImplicit:
return renderText(name, item, TypeImplicit);
case ItemHandlerType::Text:
return renderText(name, item);
}
const ByteVector name = itemName.data(String::Latin1);
switch(handlerTypeForName(name)) {
case ItemHandlerType::Unknown:
debug("MP4: Unknown item name \"" + name + "\"");
break;
case ItemHandlerType::FreeForm:
return renderFreeForm(name, item);
case ItemHandlerType::IntPair:
return renderIntPair(name, item);
case ItemHandlerType::IntPairNoTrailing:
return renderIntPairNoTrailing(name, item);
case ItemHandlerType::Bool:
return renderBool(name, item);
case ItemHandlerType::Int:
return renderInt(name, item);
case ItemHandlerType::TextOrInt:
return renderTextOrInt(name, item);
case ItemHandlerType::UInt:
return renderUInt(name, item);
case ItemHandlerType::LongLong:
return renderLongLong(name, item);
case ItemHandlerType::Byte:
return renderByte(name, item);
case ItemHandlerType::Gnre:
return renderInt(name, item);
case ItemHandlerType::Covr:
return renderCovr(name, item);
case ItemHandlerType::TextImplicit:
return renderText(name, item, TypeImplicit);
case ItemHandlerType::Text:
return renderText(name, item);
}
return ByteVector();
}
@@ -142,10 +144,9 @@ std::pair<ByteVector, Item> ItemFactory::itemFromProperty(
if(values.isEmpty()) {
return {name, values};
}
auto handlerType = name.startsWith("----")
? ItemHandlerType::FreeForm
: handlerTypeForName(name);
switch(handlerType) {
switch(name.startsWith("----")
? ItemHandlerType::FreeForm
: handlerTypeForName(name)) {
case ItemHandlerType::IntPair:
case ItemHandlerType::IntPairNoTrailing:
if(StringList parts = StringList::split(values.front(), "/");
@@ -189,12 +190,10 @@ std::pair<ByteVector, Item> ItemFactory::itemFromProperty(
std::pair<String, StringList> ItemFactory::itemToProperty(
const ByteVector &itemName, const Item &item) const
{
const String key = propertyKeyForName(itemName);
if(!key.isEmpty()) {
auto handlerType = itemName.startsWith("----")
? ItemHandlerType::FreeForm
: handlerTypeForName(itemName);
switch(handlerType) {
if(const String key = propertyKeyForName(itemName); !key.isEmpty()) {
switch(itemName.startsWith("----")
? ItemHandlerType::FreeForm
: handlerTypeForName(itemName)) {
case ItemHandlerType::IntPair:
case ItemHandlerType::IntPairNoTrailing:
{
@@ -238,7 +237,11 @@ String ItemFactory::propertyKeyForName(const ByteVector &name) const
if(d->propertyKeyForName.isEmpty()) {
d->propertyKeyForName = namePropertyMap();
}
return d->propertyKeyForName.value(name);
String key = d->propertyKeyForName.value(name);
if(key.isEmpty() && name.startsWith(freeFormPrefix)) {
key = name.mid(std::size(freeFormPrefix) - 1);
}
return key;
}
ByteVector ItemFactory::nameForPropertyKey(const String &key) const
@@ -251,7 +254,14 @@ ByteVector ItemFactory::nameForPropertyKey(const String &key) const
d->nameForPropertyKey[t] = k;
}
}
return d->nameForPropertyKey.value(key);
ByteVector name = d->nameForPropertyKey.value(key);
if(name.isEmpty() && !key.isEmpty()) {
const auto &firstChar = key[0];
if(firstChar >= 'A' && firstChar <= 'Z') {
name = (freeFormPrefix + key).data(String::UTF8);
}
}
return name;
}
////////////////////////////////////////////////////////////////////////////////
@@ -390,7 +400,7 @@ Map<ByteVector, String> ItemFactory::namePropertyMap() const
}
MP4::AtomDataList ItemFactory::parseData2(
const MP4::Atom *atom, const ByteVector &data, int expectedFlags,
const MP4::Atom *, const ByteVector &data, int expectedFlags,
bool freeForm)
{
AtomDataList result;
@@ -458,8 +468,7 @@ std::pair<String, Item> ItemFactory::parseInt(
std::pair<String, Item> ItemFactory::parseTextOrInt(
const MP4::Atom *atom, const ByteVector &bytes)
{
AtomDataList data = parseData2(atom, bytes);
if(!data.isEmpty()) {
if(AtomDataList data = parseData2(atom, bytes); !data.isEmpty()) {
AtomData val = data[0];
return {
atom->name(),
@@ -503,8 +512,7 @@ std::pair<String, Item> ItemFactory::parseByte(
std::pair<String, Item> ItemFactory::parseGnre(
const MP4::Atom *atom, const ByteVector &bytes)
{
ByteVectorList data = parseData(atom, bytes);
if(!data.isEmpty()) {
if(ByteVectorList data = parseData(atom, bytes); !data.isEmpty()) {
int idx = static_cast<int>(data[0].toShort());
if(idx > 0) {
return {
@@ -519,8 +527,7 @@ std::pair<String, Item> ItemFactory::parseGnre(
std::pair<String, Item> ItemFactory::parseIntPair(
const MP4::Atom *atom, const ByteVector &bytes)
{
ByteVectorList data = parseData(atom, bytes);
if(!data.isEmpty()) {
if(ByteVectorList data = parseData(atom, bytes); !data.isEmpty()) {
const int a = data[0].toShort(2U);
const int b = data[0].toShort(4U);
return {atom->name(), Item(a, b)};
@@ -531,8 +538,7 @@ std::pair<String, Item> ItemFactory::parseIntPair(
std::pair<String, Item> ItemFactory::parseBool(
const MP4::Atom *atom, const ByteVector &bytes)
{
ByteVectorList data = parseData(atom, bytes);
if(!data.isEmpty()) {
if(ByteVectorList data = parseData(atom, bytes); !data.isEmpty()) {
bool value = !data[0].isEmpty() && data[0][0] != '\0';
return {atom->name(), Item(value)};
}
@@ -542,8 +548,8 @@ std::pair<String, Item> ItemFactory::parseBool(
std::pair<String, Item> ItemFactory::parseText(
const MP4::Atom *atom, const ByteVector &bytes, int expectedFlags)
{
const ByteVectorList data = parseData(atom, bytes, expectedFlags);
if(!data.isEmpty()) {
if(const ByteVectorList data = parseData(atom, bytes, expectedFlags);
!data.isEmpty()) {
StringList value;
for(const auto &byte : data) {
value.append(String(byte, String::UTF8));
@@ -556,8 +562,8 @@ std::pair<String, Item> ItemFactory::parseText(
std::pair<String, Item> ItemFactory::parseFreeForm(
const MP4::Atom *atom, const ByteVector &bytes)
{
const AtomDataList data = parseData2(atom, bytes, -1, true);
if(data.size() > 2) {
if(const AtomDataList data = parseData2(atom, bytes, -1, true);
data.size() > 2) {
auto itBegin = data.begin();
String name = "----:";
@@ -582,15 +588,13 @@ std::pair<String, Item> ItemFactory::parseFreeForm(
item.setAtomDataType(type);
return {name, item};
}
else {
ByteVectorList value;
for(auto it = itBegin; it != data.end(); ++it) {
value.append(it->data);
}
Item item(value);
item.setAtomDataType(type);
return {name, item};
ByteVectorList value;
for(auto it = itBegin; it != data.end(); ++it) {
value.append(it->data);
}
Item item(value);
item.setAtomDataType(type);
return {name, item};
}
return {atom->name(), Item()};
}
@@ -659,7 +663,7 @@ ByteVector ItemFactory::renderInt(
const ByteVector &name, const MP4::Item &item)
{
ByteVectorList data;
data.append(ByteVector::fromShort(item.toInt()));
data.append(ByteVector::fromShort(static_cast<short>(item.toInt())));
return renderData(name, TypeInteger, data);
}
@@ -699,8 +703,8 @@ ByteVector ItemFactory::renderIntPair(
{
ByteVectorList data;
data.append(ByteVector(2, '\0') +
ByteVector::fromShort(item.toIntPair().first) +
ByteVector::fromShort(item.toIntPair().second) +
ByteVector::fromShort(static_cast<short>(item.toIntPair().first)) +
ByteVector::fromShort(static_cast<short>(item.toIntPair().second)) +
ByteVector(2, '\0'));
return renderData(name, TypeImplicit, data);
}
@@ -710,8 +714,8 @@ ByteVector ItemFactory::renderIntPairNoTrailing(
{
ByteVectorList data;
data.append(ByteVector(2, '\0') +
ByteVector::fromShort(item.toIntPair().first) +
ByteVector::fromShort(item.toIntPair().second));
ByteVector::fromShort(static_cast<short>(item.toIntPair().first)) +
ByteVector::fromShort(static_cast<short>(item.toIntPair().second)));
return renderData(name, TypeImplicit, data);
}

View File

@@ -158,7 +158,7 @@ namespace TagLib {
/*!
* Destroys the frame factory.
*/
virtual ~ItemFactory();
~ItemFactory();
/*!
* Returns mapping between atom names and handler types.

View File

@@ -69,7 +69,7 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) :
MP4::Properties::Properties(File *file, const MP4::Atoms *atoms, ReadStyle style) :
AudioProperties(style),
d(std::make_unique<PropertiesPrivate>())
{
@@ -125,7 +125,7 @@ MP4::Properties::codec() const
////////////////////////////////////////////////////////////////////////////////
void
MP4::Properties::read(File *file, Atoms *atoms)
MP4::Properties::read(File *file, const Atoms *atoms)
{
MP4::Atom *moov = atoms->find("moov");
if(!moov) {
@@ -138,7 +138,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
const MP4::AtomList trakList = moov->findall("trak");
for(const auto &track : trakList) {
MP4::Atom *hdlr = track->find("mdia", "hdlr");
const MP4::Atom *hdlr = track->find("mdia", "hdlr");
if(!hdlr) {
debug("MP4: Atom 'trak.mdia.hdlr' not found");
return;
@@ -156,7 +156,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
return;
}
MP4::Atom *mdhd = trak->find("mdia", "mdhd");
const MP4::Atom *mdhd = trak->find("mdia", "mdhd");
if(!mdhd) {
debug("MP4: Atom 'trak.mdia.mdhd' not found");
return;
@@ -186,7 +186,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
}
if(length == 0) {
// No length found in the media header (mdhd), try the movie header (mvhd)
if(MP4::Atom *mvhd = moov->find("mvhd")) {
if(const MP4::Atom *mvhd = moov->find("mvhd")) {
file->seek(mvhd->offset());
data = file->readBlock(mvhd->length());
if(data.size() >= 24 + 4) {
@@ -196,7 +196,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
}
}
if(unit > 0 && length > 0)
d->length = static_cast<int>(length * 1000.0 / unit + 0.5);
d->length = static_cast<int>(static_cast<double>(length) * 1000.0 / static_cast<double>(unit) + 0.5);
MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
if(!atom) {
@@ -222,13 +222,13 @@ MP4::Properties::read(File *file, Atoms *atoms)
pos += 3;
}
pos += 10;
const unsigned int bitrateValue = data.toUInt(pos);
if(bitrateValue != 0 || d->length <= 0) {
if(const unsigned int bitrateValue = data.toUInt(pos);
bitrateValue != 0 || d->length <= 0) {
d->bitrate = static_cast<int>((bitrateValue + 500) / 1000.0 + 0.5);
}
else {
d->bitrate = static_cast<int>(
(calculateMdatLength(atoms->atoms()) * 8) / d->length);
calculateMdatLength(atoms->atoms()) * 8 / d->length);
}
}
}
@@ -245,7 +245,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
// There are files which do not contain a nominal bitrate, e.g. those
// generated by refalac64.exe. Calculate the bitrate from the audio
// data size (mdat atoms) and the duration.
d->bitrate = static_cast<int>((calculateMdatLength(atoms->atoms()) * 8) / d->length);
d->bitrate = static_cast<int>(calculateMdatLength(atoms->atoms()) * 8 / d->length);
}
}
}

View File

@@ -44,7 +44,7 @@ namespace TagLib {
ALAC
};
Properties(File *file, Atoms *atoms, ReadStyle style = Average);
Properties(File *file, const Atoms *atoms, ReadStyle style = Average);
~Properties() override;
Properties(const Properties &) = delete;
@@ -88,7 +88,7 @@ namespace TagLib {
Codec codec() const;
private:
void read(File *file, Atoms *atoms);
void read(File *file, const Atoms *atoms);
class PropertiesPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE

View File

@@ -25,7 +25,6 @@
#include "mp4tag.h"
#include <array>
#include <utility>
#include "tdebug.h"
@@ -65,7 +64,7 @@ MP4::Tag::Tag(TagLib::File *file, MP4::Atoms *atoms,
d->file = file;
d->atoms = atoms;
MP4::Atom *ilst = atoms->find("moov", "udta", "meta", "ilst");
const MP4::Atom *ilst = atoms->find("moov", "udta", "meta", "ilst");
if(!ilst) {
//debug("Atom moov.udta.meta.ilst not found.");
return;
@@ -74,8 +73,8 @@ MP4::Tag::Tag(TagLib::File *file, MP4::Atoms *atoms,
for(const auto &atom : ilst->children()) {
file->seek(atom->offset() + 8);
ByteVector data = d->file->readBlock(atom->length() - 8);
const auto &[name, itm] = d->factory->parseItem(atom, data);
if (itm.isValid()) {
if(const auto &[name, itm] = d->factory->parseItem(atom, data);
itm.isValid()) {
addItem(name, itm);
}
}
@@ -162,8 +161,7 @@ MP4::Tag::updateParents(const AtomList &path, offset_t delta, int ignore)
void
MP4::Tag::updateOffsets(offset_t delta, offset_t offset)
{
MP4::Atom *moov = d->atoms->find("moov");
if(moov) {
if(MP4::Atom *moov = d->atoms->find("moov")) {
const MP4::AtomList stco = moov->findall("stco", true);
for(const auto &atom : stco) {
if(atom->offset() > offset) {
@@ -205,8 +203,7 @@ MP4::Tag::updateOffsets(offset_t delta, offset_t offset)
}
}
MP4::Atom *moof = d->atoms->find("moof");
if(moof) {
if(MP4::Atom *moof = d->atoms->find("moof")) {
const MP4::AtomList tfhd = moof->findall("tfhd", true);
for(const auto &atom : tfhd) {
if(atom->offset() > offset) {
@@ -214,8 +211,8 @@ MP4::Tag::updateOffsets(offset_t delta, offset_t offset)
}
d->file->seek(atom->offset() + 9);
ByteVector data = d->file->readBlock(atom->length() - 9);
const unsigned int flags = data.toUInt(0, 3, true);
if(flags & 1) {
if(const unsigned int flags = data.toUInt(0, 3, true);
flags & 1) {
long long o = data.toLongLong(7U);
if(o > offset) {
o += delta;
@@ -268,8 +265,7 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
// check if there is an atom before 'ilst', and possibly use it as padding
if(index != meta->children().cbegin()) {
auto prevIndex = std::prev(index);
MP4::Atom *prev = *prevIndex;
if(prev->name() == "free") {
if(const MP4::Atom *prev = *prevIndex; prev->name() == "free") {
offset = prev->offset();
length += prev->length();
}
@@ -277,8 +273,7 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
// check if there is an atom after 'ilst', and possibly use it as padding
auto nextIndex = std::next(index);
if(nextIndex != meta->children().cend()) {
MP4::Atom *next = *nextIndex;
if(next->name() == "free") {
if(const MP4::Atom *next = *nextIndex; next->name() == "free") {
length += next->length();
}
}
@@ -303,8 +298,7 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
}
else {
// Strip meta if data is empty, only the case when called from strip().
MP4::Atom *udta = *std::prev(it);
if(udta->removeChild(meta)) {
if(MP4::Atom *udta = *std::prev(it); udta->removeChild(meta)) {
offset = meta->offset();
delta = - meta->length();
d->file->removeBlock(meta->offset(), meta->length());
@@ -470,8 +464,8 @@ PropertyMap MP4::Tag::properties() const
{
PropertyMap props;
for(const auto &[k, t] : std::as_const(d->items)) {
auto [key, val] = d->factory->itemToProperty(k.data(String::Latin1), t);
if(!key.isEmpty()) {
if(auto [key, val] = d->factory->itemToProperty(k.data(String::Latin1), t);
!key.isEmpty()) {
props[key] = val;
}
else {
@@ -498,8 +492,8 @@ PropertyMap MP4::Tag::setProperties(const PropertyMap &props)
PropertyMap ignoredProps;
for(const auto &[prop, val] : props) {
auto [name, itm] = d->factory->itemFromProperty(prop, val);
if(itm.isValid()) {
if(auto [name, itm] = d->factory->itemFromProperty(prop, val);
itm.isValid()) {
d->items[name] = itm;
}
else {
@@ -522,8 +516,7 @@ StringList MP4::Tag::complexPropertyKeys() const
List<VariantMap> MP4::Tag::complexProperties(const String &key) const
{
List<VariantMap> props;
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
const CoverArtList pictures = d->items.value("covr").toCoverArtList();
for(const CoverArt &picture : pictures) {
String mimeType = "image/";
@@ -555,8 +548,7 @@ List<VariantMap> MP4::Tag::complexProperties(const String &key) const
bool MP4::Tag::setComplexProperties(const String &key, const List<VariantMap> &value)
{
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
CoverArtList pictures;
for(const auto &property : value) {
auto mimeType = property.value("mimeType").value<String>();

View File

@@ -26,7 +26,6 @@
#ifndef TAGLIB_MP4TAG_H
#define TAGLIB_MP4TAG_H
#include "tbytevectorlist.h"
#include "tfile.h"
#include "tmap.h"
#include "tstringlist.h"
@@ -40,6 +39,7 @@ namespace TagLib {
class ItemFactory;
//! An MP4 tag implementation
class TAGLIB_EXPORT Tag: public TagLib::Tag
{
public:
@@ -91,7 +91,7 @@ namespace TagLib {
void removeItem(const String &key);
/*!
* \return True if the tag contains an entry for \a key.
* \return \c true if the tag contains an entry for \a key.
*/
bool contains(const String &key) const;

View File

@@ -68,7 +68,7 @@ bool MPC::File::isSupported(IOStream *stream)
// have keys to do a quick check. An ID3v2 tag may precede.
const ByteVector id = Utils::readHeader(stream, 4, true);
return (id == "MPCK" || id.startsWith("MP+"));
return id == "MPCK" || id.startsWith("MP+");
}
////////////////////////////////////////////////////////////////////////////////
@@ -186,7 +186,7 @@ bool MPC::File::save()
insert(data, d->APELocation, d->APESize);
if(d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
d->ID3v1Location += static_cast<long>(data.size()) - d->APESize;
d->APESize = data.size();
}
@@ -236,12 +236,12 @@ void MPC::File::strip(int tags)
bool MPC::File::hasID3v1Tag() const
{
return (d->ID3v1Location >= 0);
return d->ID3v1Location >= 0;
}
bool MPC::File::hasAPETag() const
{
return (d->APELocation >= 0);
return d->APELocation >= 0;
}
////////////////////////////////////////////////////////////////////////////////
@@ -295,7 +295,7 @@ void MPC::File::read(bool readProperties)
if(d->ID3v2Location >= 0) {
seek(d->ID3v2Location + d->ID3v2Size);
streamLength -= (d->ID3v2Location + d->ID3v2Size);
streamLength -= d->ID3v2Location + d->ID3v2Size;
}
else {
seek(0);

View File

@@ -27,7 +27,6 @@
#define TAGLIB_MPCFILE_H
#include "tfile.h"
#include "tlist.h"
#include "taglib_export.h"
#include "tag.h"
#include "mpcproperties.h"
@@ -42,7 +41,7 @@ namespace TagLib {
//! An implementation of MPC metadata
/*!
* This is implementation of MPC metadata.
* This is an implementation of MPC metadata.
*
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
* properties from the file. ID3v2 tags are invalid in MPC-files, but will be skipped
@@ -82,7 +81,7 @@ namespace TagLib {
};
/*!
* Constructs an MPC file from \a file. If \a readProperties is true the
* Constructs an MPC file from \a file. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
@@ -91,7 +90,7 @@ namespace TagLib {
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Constructs an MPC file from \a stream. If \a readProperties is true the
* Constructs an MPC file from \a stream. If \a readProperties is \c true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
@@ -141,22 +140,22 @@ namespace TagLib {
/*!
* Saves the file.
*
* This returns true if the save was successful.
* This returns \c true if the save was successful.
*/
bool save() override;
/*!
* Returns a pointer to the ID3v1 tag of the file.
*
* If \a create is false (the default) this returns a null pointer
* if there is no valid APE tag. If \a create is true it will create
* If \a create is \c false (the default) this returns a null pointer
* if there is no valid APE tag. If \a create is \c true it will create
* an APE tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
* on disk actually has an ID3v1 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* \note The Tag <b>is still</b> owned by the MPC::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
@@ -167,16 +166,16 @@ namespace TagLib {
/*!
* Returns a pointer to the APE tag of the file.
*
* If \a create is false (the default) this may return a null pointer
* if there is no valid APE tag. If \a create is true it will create
* If \a create is \c false (the default) this may return a null pointer
* if there is no valid APE tag. If \a create is \c true it will create
* an APE tag if one does not exist and returns a valid pointer. If
* there already be an ID3v1 tag, the new APE tag will be placed before it.
* there already is an ID3v1 tag, the new APE tag will be placed before it.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an APE tag. Use hasAPETag() to check if the file
* on disk actually has an APE tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* \note The Tag <b>is still</b> owned by the MPC::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*

View File

@@ -162,7 +162,7 @@ namespace
do {
tmp = data[pos++];
size = (size << 7) | (tmp & 0x7F);
} while((tmp & 0x80) && (pos < data.size()));
} while((tmp & 0x80) && pos < data.size());
return size;
}
@@ -225,11 +225,11 @@ void MPC::Properties::readSV8(File *file, offset_t streamLength)
d->sampleRate = sftable[(flags >> 13) & 0x07];
d->channels = ((flags >> 4) & 0x0F) + 1;
const auto frameCount = d->sampleFrames - begSilence;
if(frameCount > 0 && d->sampleRate > 0) {
const double length = frameCount * 1000.0 / d->sampleRate;
if(const auto frameCount = d->sampleFrames - begSilence;
frameCount > 0 && d->sampleRate > 0) {
const auto length = static_cast<double>(frameCount) * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
d->bitrate = static_cast<int>(static_cast<double>(streamLength) * 8.0 / length + 0.5);
}
}
else if (packetType == "RG") {
@@ -243,8 +243,7 @@ void MPC::Properties::readSV8(File *file, offset_t streamLength)
readRG = true;
const int replayGainVersion = data[0];
if(replayGainVersion == 1) {
if(const int replayGainVersion = data[0]; replayGainVersion == 1) {
d->trackGain = data.toShort(1, true);
d->trackPeak = data.toShort(3, true);
d->albumGain = data.toShort(5, true);
@@ -304,8 +303,7 @@ void MPC::Properties::readSV7(const ByteVector &data, offset_t streamLength)
if (d->albumPeak != 0)
d->albumPeak = static_cast<int>(log10(static_cast<double>(d->albumPeak)) * 20 * 256 + .5);
bool trueGapless = (gapless >> 31) & 0x0001;
if(trueGapless) {
if((gapless >> 31) & 0x0001) {
unsigned int lastFrameSamples = (gapless >> 20) & 0x07FF;
d->sampleFrames = d->totalFrames * 1152 - lastFrameSamples;
}
@@ -329,10 +327,10 @@ void MPC::Properties::readSV7(const ByteVector &data, offset_t streamLength)
}
if(d->sampleFrames > 0 && d->sampleRate > 0) {
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
const auto length = static_cast<double>(d->sampleFrames) * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
if(d->bitrate == 0)
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
d->bitrate = static_cast<int>(static_cast<double>(streamLength) * 8.0 / length + 0.5);
}
}

View File

@@ -36,7 +36,7 @@ namespace TagLib {
class File;
static const unsigned int HeaderSize = 8 * 7;
static constexpr unsigned int HeaderSize = 8 * 7;
//! An implementation of audio property reading for MPC
@@ -50,7 +50,7 @@ namespace TagLib {
public:
/*!
* Create an instance of MPC::Properties with the data read directly
* from a MPC::File.
* from an MPC::File.
*/
Properties(File *file, offset_t streamLength, ReadStyle style = Average);

View File

@@ -247,10 +247,10 @@ ID3v1::GenreMap ID3v1::genreMap()
return m;
}
String ID3v1::genre(int i)
String ID3v1::genre(int index)
{
if(i >= 0 && static_cast<size_t>(i) < genres.size())
return String(genres[i]); // always make a copy
if(index >= 0 && static_cast<size_t>(index) < genres.size())
return String(genres[index]); // always make a copy
return String();
}

View File

@@ -176,7 +176,7 @@ void ID3v1::Tag::setComment(const String &s)
void ID3v1::Tag::setGenre(const String &s)
{
d->genre = ID3v1::genreIndex(s);
d->genre = static_cast<unsigned char>(ID3v1::genreIndex(s));
}
void ID3v1::Tag::setYear(unsigned int i)
@@ -186,7 +186,7 @@ void ID3v1::Tag::setYear(unsigned int i)
void ID3v1::Tag::setTrack(unsigned int i)
{
d->track = i < 256 ? i : 0;
d->track = static_cast<unsigned char>(i < 256 ? i : 0);
}
unsigned int ID3v1::Tag::genreNumber() const
@@ -196,7 +196,7 @@ unsigned int ID3v1::Tag::genreNumber() const
void ID3v1::Tag::setGenreNumber(unsigned int i)
{
d->genre = i < 256 ? i : 255;
d->genre = static_cast<unsigned char>(i < 256 ? i : 255);
}
void ID3v1::Tag::setStringHandler(const StringHandler *handler)
@@ -216,10 +216,9 @@ void ID3v1::Tag::read()
if(d->file && d->file->isValid()) {
d->file->seek(d->tagOffset);
// read the tag -- always 128 bytes
const ByteVector data = d->file->readBlock(128);
// some initial sanity checking
if(data.size() == 128 && data.startsWith("TAG"))
if(const ByteVector data = d->file->readBlock(128);
data.size() == 128 && data.startsWith("TAG"))
parse(data);
else
debug("ID3v1 tag is not valid or could not be read at the specified offset.");

View File

@@ -27,6 +27,7 @@
#define TAGLIB_ID3V1TAG_H
#include "tbytevector.h"
#include "taglib.h"
#include "taglib_export.h"
#include "tag.h"
@@ -38,7 +39,7 @@ namespace TagLib {
namespace ID3v1 {
//! A abstraction for the string to data encoding in ID3v1 tags.
//! An abstraction for the string to data encoding in ID3v1 tags.
/*!
* ID3v1 should in theory always contain ISO-8859-1 (Latin1) data. In
@@ -196,7 +197,7 @@ namespace TagLib {
*/
void read();
/*!
* Pareses the body of the tag in \a data.
* Parses the body of the tag in \a data.
*/
void parse(const ByteVector &data);

View File

@@ -192,7 +192,7 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
int pos = 1;
String fixedString = String(data.mid(pos, 3), String::Latin1);
auto fixedString = String(data.mid(pos, 3), String::Latin1);
pos += 3;
// convert fixed string image type to mime string
if (fixedString.upper() == "JPG") {

View File

@@ -29,7 +29,6 @@
#include "taglib_export.h"
#include "tpicturetype.h"
#include "id3v2frame.h"
#include "id3v2header.h"
namespace TagLib {
@@ -50,7 +49,7 @@ namespace TagLib {
public:
/*!
/*
* This describes the function or content of the picture.
*/
DECLARE_PICTURE_TYPE_ENUM(Type)
@@ -67,7 +66,7 @@ namespace TagLib {
explicit AttachedPictureFrame(const ByteVector &data);
/*!
* Destroys the AttahcedPictureFrame instance.
* Destroys the AttachedPictureFrame instance.
*/
~AttachedPictureFrame() override;
@@ -150,7 +149,7 @@ namespace TagLib {
/*!
* Returns the image data as a ByteVector.
*
* \note ByteVector has a data() method that returns a const char * which
* \note ByteVector has a data() method that returns a <tt>const char *</tt> which
* should make it easy to export this data to external programs.
*
* \see setPicture()

View File

@@ -57,7 +57,7 @@ namespace TagLib {
* \a startTime, end time \a endTime, start offset \a startOffset,
* end offset \a endOffset and optionally a list of embedded frames,
* whose ownership will then be taken over by this Frame, in
* \a embeddedFrames;
* \a embeddedFrames.
*
* All times are in milliseconds.
*/
@@ -100,7 +100,7 @@ namespace TagLib {
* Returns zero based byte offset (count of bytes from the beginning
* of the audio file) of chapter's start.
*
* \note If returned value is 0xFFFFFFFF, start time should be used instead.
* \note If the returned value is 0xFFFFFFFF, start time should be used instead.
* \see setStartOffset()
*/
unsigned int startOffset() const;
@@ -109,7 +109,7 @@ namespace TagLib {
* Returns zero based byte offset (count of bytes from the beginning
* of the audio file) of chapter's end.
*
* \note If returned value is 0xFFFFFFFF, end time should be used instead.
* \note If the returned value is 0xFFFFFFFF, end time should be used instead.
* \see setEndOffset()
*/
unsigned int endOffset() const;
@@ -153,7 +153,7 @@ namespace TagLib {
void setEndOffset(const unsigned int &eO);
/*!
* Returns a reference to the frame list map. This is an FrameListMap of
* Returns a reference to the frame list map. This is a FrameListMap of
* all of the frames embedded in the CHAP frame.
*
* This is the most convenient structure for accessing the CHAP frame's
@@ -169,11 +169,11 @@ namespace TagLib {
const FrameListMap &embeddedFrameListMap() const;
/*!
* Returns a reference to the embedded frame list. This is an FrameList
* Returns a reference to the embedded frame list. This is a FrameList
* of all of the frames embedded in the CHAP frame in the order that they
* were parsed.
*
* This can be useful if for example you want iterate over the CHAP frame's
* This can be useful if for example you want to iterate over the CHAP frame's
* embedded frames in the order that they occur in the CHAP frame.
*
* \warning You should not modify this data structure directly, instead
@@ -204,8 +204,8 @@ namespace TagLib {
void addEmbeddedFrame(Frame *frame);
/*!
* Remove an embedded frame from the CHAP frame. If \a del is true the frame's
* memory will be freed; if it is false, it must be deleted by the user.
* Remove an embedded frame from the CHAP frame. If \a del is \c true the frame's
* memory will be freed; if it is \c false, it must be deleted by the user.
*
* \note Using this method will invalidate any pointers on the list
* returned by embeddedFrameList()

View File

@@ -148,9 +148,8 @@ void CommentsFrame::parseFields(const ByteVector &data)
int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;
ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);
if(l.size() == 2) {
if(ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);
l.size() == 2) {
if(d->textEncoding == String::Latin1) {
d->description = Tag::latin1StringHandler()->parse(l.front());
d->text = Tag::latin1StringHandler()->parse(l.back());

View File

@@ -153,7 +153,7 @@ namespace TagLib {
/*!
* Comments each have a unique description. This searches for a comment
* frame with the description \a d and returns a pointer to it. If no
* frame is found that matches the given description null is returned.
* frame is found that matches the given description, null is returned.
*
* \see description()
*/

View File

@@ -29,7 +29,6 @@
#include "tbytevectorlist.h"
#include "tdebug.h"
#include "tpropertymap.h"
#include "id3v2tag.h"
using namespace TagLib;

View File

@@ -124,7 +124,7 @@ namespace TagLib {
explicit EventTimingCodesFrame();
/*!
* Construct a event timing codes frame based on the data in \a data.
* Construct an event timing codes frame based on the data in \a data.
*/
explicit EventTimingCodesFrame(const ByteVector &data);
@@ -137,7 +137,7 @@ namespace TagLib {
EventTimingCodesFrame &operator=(const EventTimingCodesFrame &) = delete;
/*!
* Returns a null string.
* Returns an empty string.
*/
String toString() const override;

View File

@@ -31,7 +31,6 @@
#include "taglib_export.h"
#include "id3v2frame.h"
#include "id3v2header.h"
namespace TagLib {
@@ -42,7 +41,7 @@ namespace TagLib {
/*!
* This is an implementation of ID3v2 general encapsulated objects.
* Arbitrary binary data may be included in tags, stored in GEOB frames.
* There may be multiple GEOB frames in a single tag. Each GEOB it
* There may be multiple GEOB frames in a single tag. Each GEOB is
* labelled with a content description (which may be blank), a required
* mime-type, and a file name (may be blank). The content description
* uniquely identifies the GEOB frame in the tag.
@@ -151,7 +150,7 @@ namespace TagLib {
/*!
* Returns the object data as a ByteVector.
*
* \note ByteVector has a data() method that returns a const char * which
* \note ByteVector has a data() method that returns a <tt>const char *</tt> which
* should make it easy to export this data to external programs.
*
* \see setObject()

View File

@@ -95,9 +95,9 @@ String OwnershipFrame::seller() const
return d->seller;
}
void OwnershipFrame::setSeller(const String &s)
void OwnershipFrame::setSeller(const String &seller)
{
d->seller = s;
d->seller = seller;
}
String::Type OwnershipFrame::textEncoding() const
@@ -127,7 +127,7 @@ void OwnershipFrame::parseFields(const ByteVector &data)
d->textEncoding = static_cast<String::Type>(data[0]);
pos += 1;
// Read the price paid this is a null terminate string
// Read the price paid, this is a null terminated string
d->pricePaid = readStringField(data, String::Latin1, &pos);
// If we don't have at least 8 bytes left then don't parse the rest of the

View File

@@ -51,7 +51,7 @@ namespace TagLib {
explicit OwnershipFrame(String::Type encoding = String::Latin1);
/*!
* Construct a ownership based on the data in \a data.
* Construct an ownership frame based on the data in \a data.
*/
explicit OwnershipFrame(const ByteVector &data);

View File

@@ -56,7 +56,7 @@ namespace TagLib {
PodcastFrame &operator=(const PodcastFrame &) = delete;
/*!
* Returns a null string.
* Returns an empty string.
*/
String toString() const override;

View File

@@ -98,7 +98,7 @@ void PrivateFrame::parseFields(const ByteVector &data)
// Owner identifier is assumed to be Latin1
const int byteAlign = 1;
constexpr int byteAlign = 1;
const int endOfOwner = data.find(textDelimiter(String::Latin1), 0, byteAlign);
d->owner = String(data.mid(0, endOfOwner));

View File

@@ -34,7 +34,7 @@ namespace TagLib {
namespace ID3v2 {
//! An implementation of ID3v2 privateframe
//! An implementation of ID3v2 private frame
class TAGLIB_EXPORT PrivateFrame : public Frame
{

View File

@@ -78,7 +78,7 @@ namespace TagLib {
ByteVector elementID() const;
/*!
* Returns true, if the frame is top-level (doesn't have
* Returns \c true, if the frame is top-level (doesn't have
* any parent CTOC frame).
*
* \see setIsTopLevel()
@@ -86,7 +86,7 @@ namespace TagLib {
bool isTopLevel() const;
/*!
* Returns true, if the child elements list entries
* Returns \c true, if the child elements list entries
* are ordered.
*
* \see setIsOrdered()
@@ -94,8 +94,8 @@ namespace TagLib {
bool isOrdered() const;
/*!
* Returns count of child elements of the frame. It always
* corresponds to size of child elements list.
* Returns the count of child elements of the frame. It always
* corresponds to the size of the child elements list.
*
* \see childElements()
*/
@@ -139,7 +139,7 @@ namespace TagLib {
void setChildElements(const ByteVectorList &l);
/*!
* Adds \a cE to list of child elements of the frame.
* Adds \a cE to the list of child elements of the frame.
*
* \see childElements()
*/
@@ -153,7 +153,7 @@ namespace TagLib {
void removeChildElement(const ByteVector &cE);
/*!
* Returns a reference to the frame list map. This is an FrameListMap of
* Returns a reference to the frame list map. This is a FrameListMap of
* all of the frames embedded in the CTOC frame.
*
* This is the most convenient structure for accessing the CTOC frame's
@@ -169,11 +169,11 @@ namespace TagLib {
const FrameListMap &embeddedFrameListMap() const;
/*!
* Returns a reference to the embedded frame list. This is an FrameList
* Returns a reference to the embedded frame list. This is a FrameList
* of all of the frames embedded in the CTOC frame in the order that they
* were parsed.
*
* This can be useful if for example you want iterate over the CTOC frame's
* This can be useful if for example you want to iterate over the CTOC frame's
* embedded frames in the order that they occur in the CTOC frame.
*
* \warning You should not modify this data structure directly, instead
@@ -204,8 +204,8 @@ namespace TagLib {
void addEmbeddedFrame(Frame *frame);
/*!
* Remove an embedded frame from the CTOC frame. If \a del is true the frame's
* memory will be freed; if it is false, it must be deleted by the user.
* Remove an embedded frame from the CTOC frame. If \a del is \c true the frame's
* memory will be freed; if it is \c false, it must be deleted by the user.
*
* \note Using this method will invalidate any pointers on the list
* returned by embeddedFrameList()
@@ -237,7 +237,7 @@ namespace TagLib {
/*!
* CTOC frames each contain a flag that indicates, if CTOC frame is top-level (there isn't
* any frame, which contains this frame in its child elements list). Only a single frame
* within tag can be top-level. This searches for a top-level CTOC frame.
* within the tag can be top-level. This searches for a top-level CTOC frame.
*
* \see isTopLevel()
*/

View File

@@ -173,9 +173,9 @@ PropertyMap TextIdentificationFrame::asProperties() const
return makeTIPLProperties();
if(frameID() == "TMCL")
return makeTMCLProperties();
PropertyMap map;
String tagName = frameIDToKey(frameID());
if(tagName.isEmpty()) {
PropertyMap map;
map.addUnsupportedData(frameID());
return map;
}
@@ -241,7 +241,7 @@ void TextIdentificationFrame::parseFields(const ByteVector &data)
// type is the same specified for this frame
unsigned short firstBom = 0;
for(auto it = l.begin(); it != l.end(); it++) {
for(auto it = l.begin(); it != l.end(); ++it) {
if(!it->isEmpty() || (it == l.begin() && frameID() == "TXXX")) {
if(d->textEncoding == String::Latin1) {
d->fieldList.append(Tag::latin1StringHandler()->parse(*it));
@@ -278,7 +278,7 @@ ByteVector TextIdentificationFrame::renderFields() const
v.append(static_cast<char>(encoding));
for(auto it = d->fieldList.cbegin(); it != d->fieldList.cend(); it++) {
for(auto it = d->fieldList.cbegin(); it != d->fieldList.cend(); ++it) {
// Since the field list is null delimited, if this is not the first
// element in the list, append the appropriate delimiter for this
@@ -287,7 +287,7 @@ ByteVector TextIdentificationFrame::renderFields() const
if(it != d->fieldList.cbegin())
v.append(textDelimiter(encoding));
v.append((*it).data(encoding));
v.append(it->data(encoding));
}
return v;
@@ -315,7 +315,7 @@ PropertyMap TextIdentificationFrame::makeTIPLProperties() const
const StringList l = fieldList();
for(auto it = l.begin(); it != l.end(); ++it) {
auto found = std::find_if(involvedPeople.begin(), involvedPeople.end(),
[=](const auto &person) { return *it == person.first; });
[=](const auto &person) { return it->upper() == person.first; });
if(found != involvedPeople.end()) {
map.insert(found->second, (++it)->split(","));
}
@@ -437,7 +437,7 @@ PropertyMap UserTextIdentificationFrame::asProperties() const
}
UserTextIdentificationFrame *UserTextIdentificationFrame::find(
ID3v2::Tag *tag, const String &description) // static
const ID3v2::Tag *tag, const String &description) // static
{
for(const auto &frame : std::as_const(tag->frameList("TXXX"))) {
auto f = dynamic_cast<UserTextIdentificationFrame *>(frame);

View File

@@ -59,7 +59,7 @@ namespace TagLib {
* <li><b>TDTG</b> Tagging time</li>
* <li><b>TENC</b> Encoded by</li>
* <li><b>TEXT</b> Lyricist/Text writer</li>
* <li><b>TFLT</b> File type</li>
* <li><b>TFLT</b> %File type</li>
* <li><b>TIPL</b> Involved people list</li>
* <li><b>TIT1</b> Content group description</li>
* <li><b>TIT2</b> Title/songname/content description</li>
@@ -74,7 +74,7 @@ namespace TagLib {
* <li><b>TOFN</b> Original filename</li>
* <li><b>TOLY</b> Original lyricist(s)/text writer(s)</li>
* <li><b>TOPE</b> Original artist(s)/performer(s)</li>
* <li><b>TOWN</b> File owner/licensee</li>
* <li><b>TOWN</b> %File owner/licensee</li>
* <li><b>TPE1</b> Lead performer(s)/Soloist(s)</li>
* <li><b>TPE2</b> Band/orchestra/accompaniment</li>
* <li><b>TPE3</b> Conductor/performer refinement</li>
@@ -300,7 +300,7 @@ namespace TagLib {
* Searches for the user defined text frame with the description \a description
* in \a tag. This returns null if no matching frames were found.
*/
static UserTextIdentificationFrame *find(Tag *tag, const String &description);
static UserTextIdentificationFrame *find(const Tag *tag, const String &description);
/*!
* Returns an appropriate TXXX frame description for the given free-form tag key.
@@ -314,7 +314,6 @@ namespace TagLib {
private:
UserTextIdentificationFrame(const ByteVector &data, Header *h);
UserTextIdentificationFrame(const TextIdentificationFrame &);
void checkFields();

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