60 Commits
v1.12 ... v1.13

Author SHA1 Message Date
Urs Fleisch
15ff32b685 Version 1.13 2022-10-26 15:44:33 +02:00
Urs Fleisch
084108a908 Document replacements for deprecated functions (#1001) 2022-10-26 15:42:49 +02:00
Urs Fleisch
decc0fa50a Fix Doxygen API documentation
Since the Doxygen output changed quite a bit since the styling was adapted for
TagLib, the API documentation generated with Doxygen 1.9.1 has several problems:

- In the namespaces and classes lists, the nodes cannot be expanded,
  'N' and 'C' characters are prepended to the namespaces and classes instead
  of displaying icons.
- Class members are only accessible for the letter 'a'.
- No "Deprecated" sections are displayed (only the "TAGLIB_DEPRECATED"
  definition in the signature).
- Some things are strangely styled (e.g. an empty box on the left of the
  "Introduction" title).

Now most of the custom styling is removed to get it running again and to avoid
nasty surprises with doxygen changes.
2022-10-24 07:06:23 +02:00
Urs Fleisch
02c7e34681 MSVC: Disable warnings for internal invocations of API functions
https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/taglib/msvc-disable-deprecated-warnings.patch
from Uwe Klotz (uklotzde)
2022-10-23 15:37:06 +02:00
Urs Fleisch
5f079d6992 Use GitHub Actions instead of Travis CI 2022-10-23 11:01:26 +02:00
Daniel Chabrowski
2e90ec0ef0 FileStream: seek only when length exceeds buffer size 2022-10-09 19:50:12 +02:00
Urs Fleisch
9914519d43 Update NEWS for v1.13beta 2022-09-19 18:07:31 +02:00
Urs Fleisch
f80d11ed2a MP4: Fix heap-buffer-overflow in mp4properties.cpp (#1058) 2022-09-05 06:32:53 +02:00
Urs Fleisch
4e7f844ea6 Correctly parse ID3v2.4.0 multiple strings with single BOM (#1055)
Some ID3v2.4.0 frames such as text information frames support multiple strings
separated by the termination code of the character encoding. If the encoding
is $01 UTF-16 with BOM, all strings shall have the same byte order. In the
multi strings written by TagLib, all string elements of such a multi string
have a BOM. However, I have often seen tags where a BOM exists only at the
beginning, i.e. at the start of the first string. In such a case, TagLib will
only return a list with the first string and a second empty string. This
commit will detect such cases and parse the strings without BOM according to
the BOM of the first string.
2022-08-01 09:27:35 +02:00
Stephen F. Booth
50b89ad19a Fix ID3v2 version handling for embedded frames 2022-07-24 15:28:45 +02:00
Urs Fleisch
0470c2894d Use property "WORK" instead of "CONTENTGROUP" for ID3v2 "TIT1" frame
Also use "WORK" for ASF "WM/ContentGroupDescription", as it corresponds
to "TIT1" according to
https://docs.microsoft.com/en-us/windows/win32/wmformat/id3-tag-support.
Add property "COMPILATION" for ID3v2 "TCMP" to be consistent with
MP4 "cpil".
2022-03-15 17:52:44 +01:00
James D. Smith
10721b4b41 Test for ID3v1 false positives. 2022-03-13 08:11:23 +01:00
James D. Smith
cebaf9a8e2 Utils: Fix potential ID3v1 false positive in the presence of an APE tag. 2022-03-13 08:11:23 +01:00
Urs Fleisch
197d2a684b Correctly parse MP4 non-full meta atoms (#1041)
There are m4a files with regular (non-full) meta atoms. When such
a meta atom is not correctly parsed, the subsequent atoms are not
recognized and offsets will not be adjusted when atoms are added,
which will corrupt the MP4 file.

This change will look behind the meta atom to check if the next
atom follows directly, i.e. without the four bytes with version
and flags as they exist in full atoms. In such a case, these
four bytes will not be skipped.

Witnesses of this strange format specification are
https://leo-van-stee.github.io/
https://github.com/axiomatic-systems/Bento4/blob/v1.6.0-639/Source/C%2B%2B/Core/Ap4ContainerAtom.cpp#L60
2022-03-12 07:33:32 +01:00
Urs Fleisch
e255e749e8 fileref: Adapt formatting to TagLib code style 2022-02-27 07:11:53 +01:00
Hugo Beauzée-Luyssen
a7eb7735ee fileref: Reduce variables scope 2022-02-27 07:11:53 +01:00
Hugo Beauzée-Luyssen
0de8b45612 tests: Fix stream based resolver test 2022-02-27 07:11:53 +01:00
Hugo Beauzée-Luyssen
bdd8ff2af0 fileref: Fall back on file name resolvers
when no stream resolver is available
2022-02-27 07:11:53 +01:00
Hugo Beauzée-Luyssen
82964ba176 detectByResolvers: Don't mandate an actual file to be present
The main point of IOStream is to be able to use taglib with some content
that can't be fopen()'ed, for instance a network file, or a local file
on a system that doesn't support opening a file directly through fopen
& such.
This commit adds an overload for detectByResolvers that will stick to
using an IOStream all the way.
2022-02-27 07:11:53 +01:00
Hugo Beauzée-Luyssen
f7887e7235 FileTypeResolver: Add a StreamTypeResolver interface 2022-02-27 07:11:53 +01:00
Urs Fleisch
8ab618da18 Add tests checking if looking up tags creates map entries (#931) 2022-02-09 20:07:13 +01:00
Urs Fleisch
c98fba7cc4 APE: Do not create map entry if looked up tag does not exist (#931) 2022-02-09 20:07:13 +01:00
whatdoineed2do/Ray
52bf85f8ca FLAC: Do not create map entry if looked up tag does not exist (#931) 2022-02-09 20:07:13 +01:00
Urs Fleisch
a4bb904a01 Map: Add method value() to look up without creating entry 2022-02-09 20:07:13 +01:00
Scott Wheeler
05486d00bf We don't need to export these symbols 2022-01-15 13:52:05 +01:00
Urs Fleisch
c4a0855f42 Add MP4::File::strip() to remove meta atom from file
This changes the modifications from the last commit in order to
achieve the following behavior: MP4::File::save() works in the
same way as before, i.e. it will never shrink the file and will
make space from removed items available as padding in the form of
a "free" atom. To completely remove the "meta" atom from the file,
a new method strip() is introduced, which can be used in the same
way as its MPEG::File::strip() counterpart.
2022-01-06 18:07:15 +01:00
Urs Fleisch
2cb7973162 Remove MP4 meta atom when empty tag is saved
Currently, MP4 tags can only grow. If items are removed, they are
just replaced by padding in the form of "free" atoms. This change
will remove the whole "meta" atom when an MP4 tag without items
is saved. This will make it possible, to bring the file back to
its pristine state without metadata.
2022-01-06 18:07:15 +01:00
Dzmitry Neviadomski
ff8a9ea831 Add -Wall compiler flag to Clang compilers.
Use CMAKE's `CMAKE_<LANG>_COMPILER_ID`, available from 3.0.2.
See: https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
2021-12-31 07:51:38 +01:00
ivan tkachenko
fd66b0d3b6 Add compile_commands.json to gitignore
Other entries were copied from KDE/marble repo as well.

See also: https://invent.kde.org/sdk/kdesrc-build/-/issues/86
2021-12-08 19:24:52 +01:00
Rosen Penev
f581615110 clang-tidy: replace static_cast with dynamic_cast (#1021)
* clang-tidy: replace static_cast with dynamic_cast

Found with cppcoreguidelines-pro-type-static-cast-downcast

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-07-09 21:47:36 +02:00
Rosen Penev
07eb81e88a add missing const
Avoids using a non const global variable.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-07-08 20:38:27 +02:00
Rosen Penev
c6f1e2750e use std::pair instead of 2D C array (#1020)
* use std::pair instead of 2D C array

Mostly the same. Except there's now an association between both values.

make_pair has to be used since there's no uniform initialization.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-06-21 08:16:46 +02:00
Rosen Penev
a8884c2b17 clang-tidy: don't use else after return
Found with readability-else-after-return

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-06-21 06:49:32 +02:00
Rosen Penev
76f00c5a8a clang-tidy: simplify boolean return
Found with readability-simplify-boolean-expr

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-06-21 06:49:32 +02:00
Rosen Penev
68ac7c3106 clang-tidy: use C++ casting
Found with google-readability-casting

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-06-21 06:49:32 +02:00
Rosen Penev
38d1d4c21c clang-tidy: add ending namespace comments
Found with google-readability-namespace-comments

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-06-21 06:49:32 +02:00
Rosen Penev
b77e828d4b clang-tidy: remove redundant initializations
Found with readability-redundant-member-init

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2021-06-21 06:49:32 +02:00
Urs Fleisch
17e299350a Detect by contents if file detected by extension is invalid (#1011)
This is the case for Opus files with an ogg extension.
2021-05-28 20:25:05 +02:00
Oleg Antonyan
1d24bd3399 Fix "error: duplicate ‘volatile’" on systems without HAVE_GCC_ATOMIC in 1.12 (#1012)
* fix error: duplicate volatile

* fix volatile ATOMIC_INT in constructor
2021-05-13 16:41:35 +02:00
bobsayshilol
4971f8fb03 ID3v2: Address review comments
Change the size check to use isEmpty() as requested.
2021-05-02 12:14:27 +02:00
bobsayshilol
d74689cb93 ASF: Bounds check the size of each header object
UBSan spotted an integer overflow on the line `dataPos += size`, so add
a bounds check to the size that we read.
2021-05-02 12:14:27 +02:00
bobsayshilol
51ae5748cb ID3v2: Return early from decode() on invalid data
The while loop in this function assumes that `data.end() - 1` is less
than `data.end()`, which isn't the case if `data` is empty since
`data.end()` can be a nullptr.
2021-05-02 12:14:27 +02:00
bobsayshilol
f2eb331696 MPC: Fix heap-buffer-overflow in readSV7()
If `data` is an allocation of only 3 bytes (MP+) then `data[3]` is a
read past the end of the buffer.
2021-05-02 12:14:27 +02:00
bobsayshilol
5f6bbb20e7 APE: Fix typo in valLength 2021-05-02 12:14:27 +02:00
bobsayshilol
03d03f782e APE: Bounds check the length of values
`pos`, `valLegnth`, and `data.size()` are all unsigned types so we have
to do a little dance to correctly bounds check them without overflow.

Without this we can get stuck in an infinite loop due to 'pos'
overflowing back to the start of the data.
2021-05-02 12:14:27 +02:00
bobsayshilol
1d3e080f04 ID3v2: Bounds check a vector's size
If the provided vector is empty then `data[0]` dereferences a nullptr,
so add a check that this won't be the case before reading the encoding.
2021-05-02 12:14:27 +02:00
bobsayshilol
3391bd80c4 FLAC: Validate the size of a read
Without this we can crash trying to dereference parts of `header`.
2021-05-02 12:14:27 +02:00
Julius Brüggemann
1644c0dd87 Add CMake option for building with ZLib 2021-03-29 20:21:59 +02:00
Scott Wheeler
85cc41082c Update to more modern macOS instructions.
Closes #1005
2021-03-22 11:36:36 +00:00
Jörg Krause
b5cd4c40e2 Drop leftovers WITH_ASF and WITH_MP4
The options WITH_ASF and WITH_MP4 where remove in commit
dd846904cb back in 2011. It's time to
remove the leftovers :-)
2021-03-06 14:54:31 +01:00
Urs Fleisch
932d45259c Fix taglib-config for cross compiling (#998) 2021-03-06 14:52:25 +01:00
Urs Fleisch
844f07d32d Make tests work with BUILD_SHARED_LIBS=ON on Windows 2021-03-06 14:52:25 +01:00
Andreas Sturmlechner
304ab20174 Install taglib.png icon into html folder structure
Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
2021-03-06 14:52:25 +01:00
Andreas Sturmlechner
243dd863d7 Install examples after we selected to build them
Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
2021-03-06 14:52:25 +01:00
Andreas Sturmlechner
d77e2aee0b Just set CMAKE_MODULE_PATH instead of list(APPEND), drop ENABLE_STATIC err
ENABLE_STATIC error has been there since 2014, that is long enough.

Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
2021-03-06 14:52:25 +01:00
Andreas Sturmlechner
1e636957ab Use FeatureSummary for a nice CMake summary output
Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
2021-03-06 14:52:25 +01:00
Andreas Sturmlechner
507a42871c Use GNUInstallDirs
Well-established CMake standard for installation directories.

Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
2021-03-06 14:52:25 +01:00
Andreas Sturmlechner
01348fb619 Move finding ZLIB to root CMakeLists.txt
Small line decrease, but also easier to read what is happening.
Now all dependencies can be read from the root CMakeLists.txt file.

Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
2021-03-06 14:52:25 +01:00
Andreas Sturmlechner
9e0a7f7adb Use CMake's CTest which includes BUILD_TESTING option
BUILD_TESTING is default enabled, which is a good default anyway.
Move the CppUnit check to the root CMakeLists.txt, simpler and clearer.
BUILD_TESTS is obsolete.

The need for BUILD_SHARED_LIBS=OFF for testing is not clear, it works on Linux.
But I kept it in the instructions for now.

Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>
2021-03-06 14:52:25 +01:00
Scott Wheeler
340ec9932a SVG for API doc diagrams makes a lot more sense in 2021
This also makes things look non-crappy on high-DPI monitors.
2021-02-16 12:00:52 +00:00
121 changed files with 1620 additions and 1332 deletions

54
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: Build
on: [push, pull_request, workflow_dispatch]
env:
BUILD_TYPE: Release
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
include:
- os: windows-latest
cmake_extra_args: '-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"'
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Ubuntu
run: sudo apt install -y libcppunit-dev zlib1g-dev
if: matrix.os == 'ubuntu-latest'
- name: Set up macOS
run: brew install cppunit
if: matrix.os == 'macos-latest'
- name: Set up Windows
run: vcpkg install cppunit --triplet x64-windows
if: matrix.os == 'windows-latest'
- name: Configure
run: >
cmake -B${{github.workspace}}/build
-DBUILD_SHARED_LIBS=ON -DVISIBILITY_HIDDEN=ON
-DBUILD_TESTING=ON -DBUILD_EXAMPLES=ON -DBUILD_BINDINGS=ON
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
${{ matrix.cmake_extra_args }}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Test
working-directory: ${{github.workspace}}/build
run: ctest -C ${{env.BUILD_TYPE}} -V --no-tests=error
if: matrix.os != 'windows-latest'
- name: Test Windows
working-directory: ${{github.workspace}}/build
run: |
$env:Path += ";$env:VCPKG_INSTALLATION_ROOT\packages\cppunit_x64-windows\bin;$PWD\taglib\Release"
ctest -C ${{env.BUILD_TYPE}} -V --no-tests=error
if: matrix.os == 'windows-latest'

6
.gitignore vendored
View File

@@ -12,6 +12,7 @@ CMakeFiles/
*.suo
*.user
.*
!.github/workflows/
*~
/CMakeCache.txt
/Doxyfile
@@ -47,3 +48,8 @@ CMakeFiles/
taglib.h.stamp
taglib.xcodeproj
CMakeScripts
/.clang-format
/compile_commands.json
.clangd
.cache
.idea

View File

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

View File

@@ -2,11 +2,11 @@ cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
project(taglib)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
if(DEFINED ENABLE_STATIC)
message(FATAL_ERROR "This option is no longer available, use BUILD_SHARED_LIBS instead")
endif()
include(CTest)
include(FeatureSummary)
include(GNUInstallDirs)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
if(APPLE)
@@ -32,7 +32,6 @@ if(ENABLE_CCACHE)
endif()
option(VISIBILITY_HIDDEN "Build with -fvisibility=hidden" OFF)
option(BUILD_TESTS "Build the test suite" OFF)
option(BUILD_EXAMPLES "Build the examples" OFF)
option(BUILD_BINDINGS "Build the bindings" ON)
@@ -46,22 +45,25 @@ endif()
add_definitions(-DHAVE_CONFIG_H)
set(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
## the following are directories where stuff will be installed to
set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)")
set(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH "Base directory for executables and libraries")
set(BIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" CACHE PATH "The subdirectory to the binaries prefix (default prefix/bin)")
set(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})")
set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The subdirectory to the header prefix")
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
if(CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif()
if(MSVC AND ENABLE_STATIC_RUNTIME)
foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endforeach(flag_var)
if(MSVC)
if(ENABLE_STATIC_RUNTIME)
foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endforeach(flag_var)
endif()
# Disable warnings for internal invocations of API functions
# that have been marked with TAGLIB_DEPRECATED
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4996
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996")
endif()
# Read version information from file taglib/toolkit/taglib.h into variables
@@ -90,9 +92,9 @@ endif()
# 2. If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0.
# 3. If any interfaces have been added since the last public release, then increment age.
# 4. If any interfaces have been removed since the last public release, then set age to 0.
set(TAGLIB_SOVERSION_CURRENT 19)
set(TAGLIB_SOVERSION_CURRENT 20)
set(TAGLIB_SOVERSION_REVISION 0)
set(TAGLIB_SOVERSION_AGE 18)
set(TAGLIB_SOVERSION_AGE 19)
math(EXPR TAGLIB_SOVERSION_MAJOR "${TAGLIB_SOVERSION_CURRENT} - ${TAGLIB_SOVERSION_AGE}")
math(EXPR TAGLIB_SOVERSION_MINOR "${TAGLIB_SOVERSION_AGE}")
@@ -100,40 +102,46 @@ math(EXPR TAGLIB_SOVERSION_PATCH "${TAGLIB_SOVERSION_REVISION}")
include(ConfigureChecks.cmake)
if(${ZLIB_FOUND})
set(ZLIB_LIBRARIES_FLAGS -lz)
# Determine whether zlib is installed.
option(WITH_ZLIB "Build with ZLIB" ON)
if(WITH_ZLIB)
if(NOT ZLIB_SOURCE)
find_package(ZLIB)
if(ZLIB_FOUND)
set(HAVE_ZLIB 1)
set(ZLIB_LIBRARIES_FLAGS -lz)
else()
set(HAVE_ZLIB 0)
endif()
endif()
if(NOT HAVE_ZLIB AND ZLIB_SOURCE)
set(HAVE_ZLIB 1)
set(HAVE_ZLIB_SOURCE 1)
endif()
else()
set(HAVE_ZLIB 0)
endif()
if(NOT WIN32)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/taglib-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/taglib-config" @ONLY)
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/taglib-config" DESTINATION "${BIN_INSTALL_DIR}")
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/taglib-config" DESTINATION "${CMAKE_INSTALL_BINDIR}")
endif()
if(WIN32)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/taglib-config.cmd.cmake" "${CMAKE_CURRENT_BINARY_DIR}/taglib-config.cmd")
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/taglib-config.cmd" DESTINATION "${BIN_INSTALL_DIR}")
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/taglib-config.cmd" DESTINATION "${CMAKE_INSTALL_BINDIR}")
endif()
if(NOT BUILD_FRAMEWORK)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/taglib.pc.cmake" "${CMAKE_CURRENT_BINARY_DIR}/taglib.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/taglib.pc" DESTINATION "${LIB_INSTALL_DIR}/pkgconfig")
endif()
if(NOT HAVE_ZLIB AND ZLIB_SOURCE)
set(HAVE_ZLIB 1)
set(HAVE_ZLIB_SOURCE 1)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/taglib.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
configure_file(config.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/config.h")
if(WITH_ASF)
set(TAGLIB_WITH_ASF TRUE)
endif()
if(WITH_MP4)
set(TAGLIB_WITH_MP4 TRUE)
endif()
option(TRACE_IN_RELEASE "Output debug messages even in release mode" OFF)
if(TRACE_IN_RELEASE)
set(TRACE_IN_RELEASE TRUE)
@@ -147,9 +155,13 @@ if(BUILD_BINDINGS)
add_subdirectory(bindings)
endif()
if(BUILD_TESTS AND NOT BUILD_SHARED_LIBS)
enable_testing()
add_subdirectory(tests)
if(BUILD_TESTING)
find_package(CppUnit)
if(CppUnit_FOUND)
add_subdirectory(tests)
else()
message(WARNING "BUILD_TESTING requested, but CppUnit not found, skipping tests.")
endif()
endif()
if(BUILD_EXAMPLES)
@@ -157,7 +169,6 @@ if(BUILD_EXAMPLES)
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.cmake" "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
file(COPY doc/taglib.png DESTINATION doc)
add_custom_target(docs doxygen)
# uninstall target
@@ -166,3 +177,5 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_C
if(NOT TARGET uninstall)
add_custom_target(uninstall COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
endif()
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)

View File

@@ -176,27 +176,6 @@ check_cxx_source_compiles("
}
" HAVE_ISO_STRDUP)
# Determine whether zlib is installed.
if(NOT ZLIB_SOURCE)
find_package(ZLIB)
if(ZLIB_FOUND)
set(HAVE_ZLIB 1)
else()
set(HAVE_ZLIB 0)
endif()
endif()
# Determine whether CppUnit is installed.
if(BUILD_TESTS AND NOT BUILD_SHARED_LIBS)
find_package(CppUnit)
if(NOT CppUnit_FOUND)
message(STATUS "CppUnit not found, disabling tests.")
set(BUILD_TESTS OFF)
endif()
endif()
# Detect WinRT mode
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
set(PLATFORM WINRT 1)

View File

@@ -1,37 +1,79 @@
# Doxyfile 1.3.4
# Doxyfile 1.9.1
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = TagLib
PROJECT_NUMBER = ${TAGLIB_LIB_VERSION_STRING}
PROJECT_BRIEF =
PROJECT_LOGO = @CMAKE_SOURCE_DIR@/doc/taglib.svg
OUTPUT_DIRECTORY = doc
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
OUTPUT_TEXT_DIRECTION = None
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
JAVADOC_BANNER = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
PYTHON_DOCSTRING = YES
INHERIT_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
ALIASES =
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 5
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
NUM_PROC_THREADS = 1
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
EXTRACT_PRIV_VIRTUAL = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = NO
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
RESOLVE_UNNAMED_PARAMS = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
@@ -39,172 +81,267 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = YES
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
GENERATE_BUGLIST = NO
GENERATE_DEPRECATEDLIST= NO
ENABLED_SECTIONS =
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = @CMAKE_SOURCE_DIR@/taglib
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.h \
*.hh \
*.H
RECURSIVE = YES
EXCLUDE =
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# configuration options related to source browsing
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
CLANG_ASSISTED_PARSING = NO
CLANG_ADD_INC_PATHS = YES
CLANG_OPTIONS =
CLANG_DATABASE_PATH =
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER = @CMAKE_SOURCE_DIR@/doc/api-header.html
HTML_FOOTER = @CMAKE_SOURCE_DIR@/doc/api-footer.html
HTML_STYLESHEET = @CMAKE_SOURCE_DIR@/doc/taglib-api.css
HTML_ALIGN_MEMBERS = YES
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = YES
ENUM_VALUES_PER_LINE = 4
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
FORMULA_MACROFILE =
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = NO
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
LATEX_MAKEINDEX_CMD = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = letter
EXTRA_PACKAGES =
LATEX_HEADER =
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
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 =
#---------------------------------------------------------------------------
# configuration options related to the RTF output
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# configuration options related to the man page output
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = DO_NOT_DOCUMENT \
DOXYGEN \
WITH_MP4 \
WITH_ASF
EXPAND_AS_DEFINED =
DOXYGEN
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
DOT_UML_DETAILS = NO
DOT_WRAP_THRESHOLD = 17
TEMPLATE_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = svg
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 100
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

View File

@@ -13,6 +13,12 @@ In order to build the included examples, use the `BUILD_EXAMPLES` option:
cmake -DBUILD_EXAMPLES=ON [...]
If you want to build TagLib without ZLib, you can use
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release -DWITH_ZLIB=OFF .
make
sudo make install
See http://www.cmake.org/cmake/help/runningcmake.html for generic help on
running CMake.
@@ -22,23 +28,25 @@ Mac OS X
On Mac OS X, you might want to build a framework that can be easily integrated
into your application. If you set the BUILD_FRAMEWORK option on, it will compile
TagLib as a framework. For example, the following command can be used to build
an Universal Binary framework with Mac OS X 10.4 as the deployment target:
a framework with Mac OS X 10.10 as the deployment target:
cmake -DCMAKE_BUILD_TYPE=Release \
mkdir build; cd build
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF \
-DBUILD_FRAMEWORK=ON \
-DCMAKE_C_COMPILER=/usr/bin/gcc-4.0 \
-DCMAKE_CXX_COMPILER=/usr/bin/c++-4.0 \
-DCMAKE_OSX_SYSROOT=/Developer/SDKs/MacOSX10.4u.sdk/ \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.4 \
-DCMAKE_OSX_ARCHITECTURES="ppc;i386;x86_64"
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.10 \
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"
make
For a 10.6 Snow Leopard static library with both 32-bit and 64-bit code, use:
For a 10.10 static library, use:
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.6 \
-DCMAKE_OSX_ARCHITECTURES="i386;x86_64" \
mkdir build; cd build
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_INSTALL_PREFIX="<folder you want to install to>"
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.10 \
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"
make
After `make`, and `make install`, add `libtag.` to your XCode project, and add
the include folder to the project's User Header Search Paths.
@@ -72,6 +80,7 @@ Useful configuration options used with CMake (GUI and/or command line):
| option | description |
| ----------------------- | ----------- |
| `WITH_ZLIB=` | Whether to build with ZLib |
| `ZLIB_ROOT=` | Where to find ZLib's root directory. Assumes parent of: `\include` and `\lib.`|
| `ZLIB_INCLUDE_DIR=` | Where to find ZLib's Include directory.|
| `ZLIB_LIBRARY=` | Where to find ZLib's Library.
@@ -167,7 +176,7 @@ Unit Tests
If you want to run the test suite to make sure TagLib works properly on your
system, you need to have cppunit installed. To build the tests, include
the option `-DBUILD_TESTS=ON -DBUILD_SHARED_LIBS=OFF` when running cmake.
the option `-DBUILD_TESTING=ON` when running cmake.
The test suite has a custom target in the build system, so you can run
the tests using make:
@@ -183,7 +192,7 @@ Windows MinGW:
- `mingw32-make; mingw32-make install DESTDIR=/path/to/install/dir`
* Build TagLib with testing enabled:
- ```
cmake -G "MinGW Makefiles" -DBUILD_TESTS=ON -DBUILD_EXAMPLES=ON -DBUILD_SHARED_LIBS=OFF \
cmake -G "MinGW Makefiles" -DBUILD_TESTING=ON -DBUILD_EXAMPLES=ON -DBUILD_SHARED_LIBS=OFF \
-DCPPUNIT_INCLUDE_DIR=/path/to/cppunit/include \
-DCPPUNIT_LIBRARIES=/path/to/cppunit/lib/libcppunit.a \
-DCPPUNIT_INSTALLED_VERSION=1.15.1
@@ -200,7 +209,7 @@ Windows MSVS:
- It may fail, but the needed libraries should be available in src\cppunit\DebugDll.
* Build TagLib with testing enabled:
- ```
cmake -G "Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON -DBUILD_EXAMPLES=ON
cmake -G "Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DBUILD_EXAMPLES=ON
-DBUILD_SHARED_LIBS=OFF -DENABLE_STATIC_RUNTIME=ON
-DCPPUNIT_INCLUDE_DIR=\path\to\cppunit\include
-DCPPUNIT_LIBRARIES=\path\to\cppunit\DebugDll\cppunitd_dll.lib

25
NEWS
View File

@@ -1,3 +1,28 @@
TagLib 1.13 (Oct 27, 2022)
==========================
* Added interface StreamTypeResolver to support streams which cannot be
fopen()'ed, e.g. network files.
* Added MP4::File::strip() to remove meta atom from MP4 file.
* Added Map::value() to look up without creating entry.
* Use property "WORK" instead of "CONTENTGROUP" for ID3v2 "TIT1" frame,
use property "WORK" for ASF "WM/ContentGroupDescription",
use property "COMPILATION" for ID3v2 "TCMP" frame.
* Build system improvements: option WITH_ZLIB, BUILD_TESTING instead of
BUILD_TESTS, GNUInstallDirs, FeatureSummary, tests with BUILD_SHARED_LIBS,
cross compilation with Buildroot, systems without HAVE_GCC_ATOMIC, Clang.
* Fixed heap-buffer-overflows when handling ASF, APE, FLAC, ID3v2, MP4, MPC
tags.
* Fixed detection of invalid file by extension when correct type can be
detected by contents.
* Fixed unnecessary creation of map entries in APE and FLAC tags if looked up
tag does not exist.
* Fixed parsing of MP4 non-full meta atoms.
* Fixed potential ID3v1 false positive in the presence of an APE tag.
* Fixed ID3v2 version handling for frames embedded in CHAP or CTOC frames.
* Fixed parsing of multiple strings with a single BOM in ID3v2.4.0.
* Fixed several smaller issues reported by clang-tidy.
TagLib 1.12 (Feb 16, 2021)
==========================

View File

@@ -1,6 +1,6 @@
# TagLib
[![Build Status](https://travis-ci.org/taglib/taglib.svg?branch=master)](https://travis-ci.org/taglib/taglib)
[![Build Status](../../actions/workflows/build.yml/badge.svg)](../../actions)
### TagLib Audio Metadata Library
@@ -23,4 +23,3 @@ licenses if you are considering using TagLib in your project.
[FLAC]: https://xiph.org/flac/
[GNU Lesser General Public License]: https://www.gnu.org/licenses/lgpl.html
[Mozilla Public License]: https://www.mozilla.org/MPL/MPL-1.1.html

View File

@@ -58,18 +58,18 @@ set_target_properties(tag_c PROPERTIES
VERSION 0.0.0
SOVERSION 0
DEFINE_SYMBOL MAKE_TAGLIB_C_LIB
INSTALL_NAME_DIR ${LIB_INSTALL_DIR}
INSTALL_NAME_DIR ${CMAKE_INSTALL_LIBDIR}
)
install(TARGETS tag_c
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/taglib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/taglib
)
if(NOT BUILD_FRAMEWORK)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/taglib_c.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib_c.pc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/taglib_c.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/taglib_c.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()

View File

@@ -69,7 +69,7 @@ namespace
{
return String(s, unicodeStrings ? String::UTF8 : String::Latin1);
}
}
} // namespace
void taglib_set_strings_unicode(BOOL unicode)
{

View File

@@ -1,12 +1,12 @@
prefix=${CMAKE_INSTALL_PREFIX}
exec_prefix=${CMAKE_INSTALL_PREFIX}
libdir=${LIB_INSTALL_DIR}
includedir=${INCLUDE_INSTALL_DIR}
libdir=${CMAKE_INSTALL_FULL_LIBDIR}
includedir=${CMAKE_INSTALL_FULL_INCLUDEDIR}
Name: TagLib C Bindings
Description: Audio meta-data library (C bindings)
Requires: taglib
Version: ${TAGLIB_LIB_VERSION_STRING}
Libs: -L${LIB_INSTALL_DIR} -ltag_c
Cflags: -I${INCLUDE_INSTALL_DIR}/taglib
Libs: -L${CMAKE_INSTALL_FULL_LIBDIR} -ltag_c
Cflags: -I${CMAKE_INSTALL_FULL_INCLUDEDIR}/taglib

View File

@@ -33,7 +33,7 @@ ELSE(CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARIES)
FIND_PATH(CPPUNIT_CFLAGS cppunit/TestRunner.h PATHS /usr/include /usr/local/include )
FIND_LIBRARY(CPPUNIT_LIBRARIES NAMES cppunit PATHS /usr/lib /usr/local/lib )
# how can we find cppunit version?
MESSAGE (STATUS "Ensure you cppunit installed version is at least ${CPPUNIT_MIN_VERSION}")
MESSAGE (STATUS "Ensure your cppunit installed version is at least ${CPPUNIT_MIN_VERSION}")
SET (CPPUNIT_INSTALLED_VERSION ${CPPUNIT_MIN_VERSION})
ENDIF(CPPUNIT_CONFIG_EXECUTABLE)

View File

@@ -1,4 +1,2 @@
</div>
</div>
</body>
</html>

View File

@@ -1,41 +1,38 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>$title ($projectname)</title>
<link href="taglib-api.css" rel="stylesheet" type="text/css">
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview
$search
$mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
</head>
<body>
<div id="container">
<table border="0" width="100%">
<tr>
<td width="1">
<img src="../taglib.png">
</td>
<td>
<div id="intro">
<table border="0" height="119" cellpadding="0" cellspacing="0" width="100%">
<tr><td valign="top"><h1>TagLib $projectnumber ($title)</h1></td></tr>
<tr>
<td valign="bottom">
<div id="links">
<a href="index.html">Home</a>
<a href="inherits.html">Class&nbsp;Hierarchy</a>
<a href="namespaces.html">Namespaces</a>
<a href="annotated.html">Classes</a>
<a href="files.html">Headers</a>
<a href="namespacemembers.html">Namespace&nbsp;Members</a>
<a href="functions.html">Class&nbsp;Members</a>
<a href="globals.html">File&nbsp;Members</a>
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
<div id="text">
<div id="top">
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo" width="200px"/></td>
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">$projectname
&#160;<span id="projectnumber">$projectnumber</span>
</div>
<div id="projectbrief">$projectbrief</div>
</td>
<td style="padding-left: 0.5em;">
<div id="projectbrief">$projectbrief</div>
</td>
<td>$searchbox</td>
</tr>
</tbody>
</table>
</div>

View File

@@ -1,395 +0,0 @@
body {
font-family: sans-serif;
background: white;
color: black;
margin: 0px;
padding: 15px;
}
a:link {
font-weight: bold;
text-decoration: none;
color: gray;
}
a:visited {
font-weight: bold;
text-decoration: none;
color: gray;
}
a:hover {
color: #cccccc;
text-decoration: underline;
}
a:active {
color: #cccccc;
text-decoration: underline;
}
img {
border-style: none;
}
h1 {
font-family: sans-serif;
}
h2 {
font-family: sans-serif;
}
h3 {
font-family: sans-serif;
}
/* container */
#container {
position: absolute;
border-width: thin;
border-style: solid;
width: 95%;
}
/* intro */
#intro {
padding: 5px;
margin: 0px;
background: #cccccc;
border-width: medium;
border-style: solid;
}
#intro h1 {
margin: 5px;
padding: 5px;
}
/* links */
#links {
font-size: x-small;
vertical-align: bottom;
}
#links a {
border-width: thin;
border-style: dotted;
border-color: white;
/* margin: 0px 10px 0px 0px; */
margin: 1px;
padding: 3px;
line-height: 230%
}
#links a:hover {
color: black;
text-decoration: underline;
}
#links h3 {
outline-width: thin;
border-style: solid;
padding: 2px;
margin: 3px 0px 3px 0px;
}
/* menu */
#menu h3 {
text-align: center;
}
/* text */
#text {
margin: 0px;
padding: 5px 5px 0px 5px;
float: left;
}
#text h3 {
border-width: thin;
border-style: solid;
padding: 2px;
margin: 3px 0px 3px 0px;
}
#text li {
margin: 0px 0px 10px 0px;
}
#text ul {
margin: 5px;
padding: 0px 0px 0px 20px;
}
#leftcolumn {
float: left;
width: 300px;
margin: 0px 10px 0px 0px;
padding: 0px;
}
#rightcolumn {
float: right;
width: 210px;
margin: 0px;
padding: 0px;
}
/* vspacer */
.vspacer {
height: 10px;
}
.silver {
border-width: thin;
border-color: black;
border-style: solid;
background: #cccccc;
}
a.code {
text-decoration: none;
font-weight: normal;
color: #4444ee
}
a.codeRef {
font-weight: normal;
color: #4444ee
}
div.fragment {
width: 98%;
border: 1px solid #CCCCCC;
background-color: #f5f5f5;
padding-left: 4px;
margin: 4px;
}
div.ah {
background-color: black;
font-weight: bold; color: #ffffff;
margin-bottom: 3px;
margin-top: 3px
}
#text td {
width: auto;
}
div.memdoc {
margin-top: 0px;
margin-bottom: 20px;
padding: 10px 10px 10px 40px;
}
div.memproto {
border: thin solid black;
background-color: #f2f2ff;
width: 100%;
margin-top: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
td.paramtype {
color: #602020;
}
table.memname {
font-weight: bold;
}
div.groupHeader {
margin-left: 16px;
margin-top: 12px;
margin-bottom: 6px;
font-weight: bold
}
div.groupText {
margin-left: 16px;
font-style: italic;
font-size: smaller
}
body {
background: white;
color: black;
margin-right: 20px;
margin-left: 20px;
}
td.indexkey {
background-color: #eeeeff;
font-weight: bold;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px
}
td.indexvalue {
background-color: #eeeeff;
font-style: italic;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px
}
tr.memlist {
background-color: #f0f0f0;
}
p.formulaDsp {
text-align: center;
}
img.formulaDsp {
}
img.formulaInl {
vertical-align: middle;
}
span.keyword {
color: #008000
}
span.keywordtype {
color: #604020
}
span.keywordflow {
color: #e08000
}
span.comment {
color: #800000
}
span.preprocessor {
color: #806020
}
span.stringliteral {
color: #002080
}
span.charliteral {
color: #008080
}
.mdTable {
border: 1px solid #868686;
background-color: #f2f2ff;
}
.mdRow {
padding: 8px 20px;
}
.mdescLeft {
font-size: smaller;
font-family: Arial, Helvetica, sans-serif;
background-color: #FAFAFA;
padding-left: 8px;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.mdescRight {
font-size: smaller;
font-family: Arial, Helvetica, sans-serif;
font-style: italic;
background-color: #FAFAFA;
padding-left: 4px;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
padding-bottom: 0px;
padding-right: 8px;
}
.memItemLeft {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-style: solid;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-family: Geneva, Arial, Helvetica, sans-serif;
font-size: 12px;
}
.memItemRight {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-style: solid;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-family: Geneva, Arial, Helvetica, sans-serif;
font-size: 13px;
}
.search {
color: #0000ee;
font-weight: bold;
}
form.search {
margin-bottom: 0px;
margin-top: 0px;
}
input.search {
font-size: 75%;
color: #000080;
font-weight: normal;
background-color: #eeeeff;
}
td.tiny {
font-size: 75%;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

58
doc/taglib.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -38,3 +38,8 @@ target_link_libraries(framelist tag)
add_executable(strip-id3v1 strip-id3v1.cpp)
target_link_libraries(strip-id3v1 tag)
install(TARGETS tagreader tagreader_c tagwriter framelist strip-id3v1
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

View File

@@ -14,10 +14,20 @@ EOH
exit 1;
}
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@LIB_INSTALL_DIR@
includedir=@INCLUDE_INSTALL_DIR@
# Looks useless as it is, but could be replaced with a "pcfiledir" by Buildroot.
prefix=
exec_prefix=
if test -z "$prefix"; then
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
else
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
fi
if test -z "$exec_prefix"; then
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
else
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
fi
flags=""
@@ -38,7 +48,7 @@ do
echo @TAGLIB_LIB_VERSION_STRING@
;;
--prefix)
echo $prefix
echo ${prefix:-@CMAKE_INSTALL_PREFIX@}
;;
*)
echo "$0: unknown option $1"

View File

@@ -27,8 +27,8 @@ goto theend
* to allow for static, shared or debug builds.
* It would be preferable if the top level CMakeLists.txt provided the library name during config. ??
:doit
if /i "%1#" == "--libs#" echo -L${LIB_INSTALL_DIR} -llibtag
if /i "%1#" == "--cflags#" echo -I${INCLUDE_INSTALL_DIR} -I${INCLUDE_INSTALL_DIR}/taglib
if /i "%1#" == "--libs#" echo -L${CMAKE_INSTALL_FULL_LIBDIR} -llibtag
if /i "%1#" == "--cflags#" echo -I${CMAKE_INSTALL_FULL_INCLUDEDIR} -I${CMAKE_INSTALL_FULL_INCLUDEDIR}/taglib
if /i "%1#" == "--version#" echo ${TAGLIB_LIB_VERSION_STRING}
if /i "%1#" == "--prefix#" echo ${CMAKE_INSTALL_PREFIX}

View File

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

View File

@@ -344,7 +344,7 @@ endif()
set_target_properties(tag PROPERTIES
VERSION ${TAGLIB_SOVERSION_MAJOR}.${TAGLIB_SOVERSION_MINOR}.${TAGLIB_SOVERSION_PATCH}
SOVERSION ${TAGLIB_SOVERSION_MAJOR}
INSTALL_NAME_DIR ${LIB_INSTALL_DIR}
INSTALL_NAME_DIR ${CMAKE_INSTALL_LIBDIR}
DEFINE_SYMBOL MAKE_TAGLIB_LIB
LINK_INTERFACE_LIBRARIES ""
PUBLIC_HEADER "${tag_HDRS}"
@@ -365,8 +365,8 @@ endif()
install(TARGETS tag
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/taglib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/taglib
)

View File

@@ -135,8 +135,7 @@ unsigned int APE::Footer::completeTagSize() const
{
if(d->headerPresent)
return d->tagSize + size();
else
return d->tagSize;
return d->tagSize;
}
void APE::Footer::setTagSize(unsigned int s)
@@ -158,8 +157,7 @@ ByteVector APE::Footer::renderHeader() const
{
if(!d->headerPresent)
return ByteVector();
else
return render(true);
return render(true);
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -219,8 +219,7 @@ String APE::Item::toString() const
{
if(d->type == Text && !isEmpty())
return d->text.front();
else
return String();
return String();
}
bool APE::Item::isEmpty() const
@@ -229,9 +228,7 @@ bool APE::Item::isEmpty() const
case Text:
if(d->text.isEmpty())
return true;
if(d->text.size() == 1 && d->text.front().isEmpty())
return true;
return false;
return d->text.size() == 1 && d->text.front().isEmpty();
case Binary:
case Locator:
return d->value.isEmpty();

View File

@@ -53,7 +53,7 @@ namespace TagLib {
* Create an instance of APE::Properties with the data read from the
* APE::File \a file.
*
* \deprecated
* \deprecated Use Properties(File *, long, ReadStyle).
*/
TAGLIB_DEPRECATED Properties(File *file, ReadStyle style = Average);
@@ -74,7 +74,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;

View File

@@ -70,7 +70,7 @@ namespace
return true;
}
}
} // namespace
class APE::Tag::TagPrivate
{
@@ -91,13 +91,11 @@ public:
////////////////////////////////////////////////////////////////////////////////
APE::Tag::Tag() :
TagLib::Tag(),
d(new TagPrivate())
{
}
APE::Tag::Tag(TagLib::File *file, long footerLocation) :
TagLib::Tag(),
d(new TagPrivate())
{
d->file = file;
@@ -118,51 +116,44 @@ ByteVector APE::Tag::fileIdentifier()
String APE::Tag::title() const
{
if(d->itemListMap["TITLE"].isEmpty())
return String();
return d->itemListMap["TITLE"].values().toString();
Item value = d->itemListMap.value("TITLE");
return value.isEmpty() ? String() : value.values().toString();
}
String APE::Tag::artist() const
{
if(d->itemListMap["ARTIST"].isEmpty())
return String();
return d->itemListMap["ARTIST"].values().toString();
Item value = d->itemListMap.value("ARTIST");
return value.isEmpty() ? String() : value.values().toString();
}
String APE::Tag::album() const
{
if(d->itemListMap["ALBUM"].isEmpty())
return String();
return d->itemListMap["ALBUM"].values().toString();
Item value = d->itemListMap.value("ALBUM");
return value.isEmpty() ? String() : value.values().toString();
}
String APE::Tag::comment() const
{
if(d->itemListMap["COMMENT"].isEmpty())
return String();
return d->itemListMap["COMMENT"].values().toString();
Item value = d->itemListMap.value("COMMENT");
return value.isEmpty() ? String() : value.values().toString();
}
String APE::Tag::genre() const
{
if(d->itemListMap["GENRE"].isEmpty())
return String();
return d->itemListMap["GENRE"].values().toString();
Item value = d->itemListMap.value("GENRE");
return value.isEmpty() ? String() : value.values().toString();
}
unsigned int APE::Tag::year() const
{
if(d->itemListMap["YEAR"].isEmpty())
return 0;
return d->itemListMap["YEAR"].toString().toInt();
Item value = d->itemListMap.value("YEAR");
return value.isEmpty() ? 0 : value.toString().toInt();
}
unsigned int APE::Tag::track() const
{
if(d->itemListMap["TRACK"].isEmpty())
return 0;
return d->itemListMap["TRACK"].toString().toInt();
Item value = d->itemListMap.value("TRACK");
return value.isEmpty() ? 0 : value.toString().toInt();
}
void APE::Tag::setTitle(const String &s)
@@ -210,16 +201,18 @@ namespace
{
// conversions of tag keys between what we use in PropertyMap and what's usual
// for APE tags
// usual, APE
const char *keyConversions[][2] = {{"TRACKNUMBER", "TRACK" },
{"DATE", "YEAR" },
{"ALBUMARTIST", "ALBUM ARTIST"},
{"DISCNUMBER", "DISC" },
{"REMIXER", "MIXARTIST" },
{"RELEASESTATUS", "MUSICBRAINZ_ALBUMSTATUS" },
{"RELEASETYPE", "MUSICBRAINZ_ALBUMTYPE" }};
// usual, APE
const std::pair<const char *, const char *> keyConversions[] = {
std::make_pair("TRACKNUMBER", "TRACK"),
std::make_pair("DATE", "YEAR"),
std::make_pair("ALBUMARTIST", "ALBUM ARTIST"),
std::make_pair("DISCNUMBER", "DISC"),
std::make_pair("REMIXER", "MIXARTIST"),
std::make_pair("RELEASESTATUS", "MUSICBRAINZ_ALBUMSTATUS"),
std::make_pair("RELEASETYPE", "MUSICBRAINZ_ALBUMTYPE"),
};
const size_t keyConversionsSize = sizeof(keyConversions) / sizeof(keyConversions[0]);
}
} // namespace
PropertyMap APE::Tag::properties() const
{
@@ -235,8 +228,8 @@ PropertyMap APE::Tag::properties() const
else {
// Some tags need to be handled specially
for(size_t i = 0; i < keyConversionsSize; ++i) {
if(tagName == keyConversions[i][1])
tagName = keyConversions[i][0];
if(tagName == keyConversions[i].second)
tagName = keyConversions[i].first;
}
properties[tagName].append(it->second.toStringList());
}
@@ -257,9 +250,9 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
// see comment in properties()
for(size_t i = 0; i < keyConversionsSize; ++i)
if(properties.contains(keyConversions[i][0])) {
properties.insert(keyConversions[i][1], properties[keyConversions[i][0]]);
properties.erase(keyConversions[i][0]);
if(properties.contains(keyConversions[i].first)) {
properties.insert(keyConversions[i].second, properties[keyConversions[i].first]);
properties.erase(keyConversions[i].first);
}
// first check if tags need to be removed completely
@@ -419,7 +412,12 @@ void APE::Tag::parse(const ByteVector &data)
}
const unsigned int keyLength = nullPos - pos - 8;
const unsigned int valLegnth = data.toUInt(pos, false);
const unsigned int valLength = data.toUInt(pos, false);
if(valLength >= data.size() || pos > data.size() - valLength) {
debug("APE::Tag::parse() - Invalid val length. Stopped parsing.");
return;
}
if(keyLength >= MinKeyLength
&& keyLength <= MaxKeyLength
@@ -434,6 +432,6 @@ void APE::Tag::parse(const ByteVector &data)
debug("APE::Tag::parse() - Skipped an item due to an invalid key.");
}
pos += keyLength + valLegnth + 9;
pos += keyLength + valLength + 9;
}
}

View File

@@ -312,7 +312,7 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
if(kind == 0) {
data = renderString(name, true) +
ByteVector::fromShort((int)d->type, false) +
ByteVector::fromShort(static_cast<int>(d->type), false) +
ByteVector::fromShort(data.size(), false) +
data;
}
@@ -321,7 +321,7 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
ByteVector::fromShort(d->stream, false) +
ByteVector::fromShort(nameData.size(), false) +
ByteVector::fromShort((int)d->type, false) +
ByteVector::fromShort(static_cast<int>(d->type), false) +
ByteVector::fromUInt(data.size(), false) +
nameData +
data;

View File

@@ -97,7 +97,7 @@ namespace
const ByteVector contentEncryptionGuid("\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E", 16);
const ByteVector extendedContentEncryptionGuid("\x14\xE6\x8A\x29\x22\x26 \x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C", 16);
const ByteVector advancedContentEncryptionGuid("\xB6\x9B\x07\x7A\xA4\xDA\x12\x4E\xA5\xCA\x91\xD3\x8D\xC1\x1A\x8D", 16);
}
} // namespace
class ASF::File::FilePrivate::BaseObject
{
@@ -194,7 +194,7 @@ private:
void ASF::File::FilePrivate::BaseObject::parse(ASF::File *file, unsigned int size)
{
data.clear();
if(size > 24 && size <= (unsigned int)(file->length()))
if(size > 24 && size <= static_cast<unsigned int>(file->length()))
data = file->readBlock(size - 24);
else
data = ByteVector();
@@ -384,7 +384,7 @@ void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsig
}
bool ok;
long long size = readQWORD(file, &ok);
if(!ok) {
if(!ok || size < 0 || size > dataSize - dataPos) {
file->setValid(false);
break;
}
@@ -400,7 +400,7 @@ void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsig
else {
obj = new UnknownObject(guid);
}
obj->parse(file, (unsigned int)size);
obj->parse(file, static_cast<unsigned int>(size));
objects.append(obj);
dataPos += size;
}
@@ -656,7 +656,7 @@ void ASF::File::read()
setValid(false);
break;
}
long size = (long)readQWORD(this, &ok);
long size = static_cast<long>(readQWORD(this, &ok));
if(!ok) {
setValid(false);
break;

View File

@@ -137,7 +137,7 @@ ByteVector ASF::Picture::render() const
return ByteVector();
return
ByteVector((char)d->type) +
ByteVector(static_cast<char>(d->type)) +
ByteVector::fromUInt(d->picture.size(), false) +
renderString(d->mimeType) +
renderString(d->description) +
@@ -150,7 +150,7 @@ void ASF::Picture::parse(const ByteVector& bytes)
if(bytes.size() < 9)
return;
int pos = 0;
d->type = (Type)bytes[0]; ++pos;
d->type = static_cast<Type>(bytes[0]); ++pos;
const unsigned int dataLen = bytes.toUInt(pos, false); pos+=4;
const ByteVector nullStringTerminator(2, 0);

View File

@@ -86,7 +86,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;

View File

@@ -40,7 +40,6 @@ public:
};
ASF::Tag::Tag() :
TagLib::Tag(),
d(new TagPrivate())
{
}
@@ -95,8 +94,7 @@ unsigned int ASF::Tag::track() const
const ASF::Attribute attr = d->attributeListMap["WM/TrackNumber"][0];
if(attr.type() == ASF::Attribute::DWordType)
return attr.toUInt();
else
return attr.toString().toInt();
return attr.toString().toInt();
}
if(d->attributeListMap.contains("WM/Track"))
return d->attributeListMap["WM/Track"][0].toUInt();
@@ -212,65 +210,65 @@ bool ASF::Tag::isEmpty() const
namespace
{
const char *keyTranslation[][2] = {
{ "WM/AlbumTitle", "ALBUM" },
{ "WM/AlbumArtist", "ALBUMARTIST" },
{ "WM/Composer", "COMPOSER" },
{ "WM/Writer", "LYRICIST" },
{ "WM/Conductor", "CONDUCTOR" },
{ "WM/ModifiedBy", "REMIXER" },
{ "WM/Year", "DATE" },
{ "WM/OriginalReleaseYear", "ORIGINALDATE" },
{ "WM/Producer", "PRODUCER" },
{ "WM/ContentGroupDescription", "GROUPING" },
{ "WM/SubTitle", "SUBTITLE" },
{ "WM/SetSubTitle", "DISCSUBTITLE" },
{ "WM/TrackNumber", "TRACKNUMBER" },
{ "WM/PartOfSet", "DISCNUMBER" },
{ "WM/Genre", "GENRE" },
{ "WM/BeatsPerMinute", "BPM" },
{ "WM/Mood", "MOOD" },
{ "WM/ISRC", "ISRC" },
{ "WM/Lyrics", "LYRICS" },
{ "WM/Media", "MEDIA" },
{ "WM/Publisher", "LABEL" },
{ "WM/CatalogNo", "CATALOGNUMBER" },
{ "WM/Barcode", "BARCODE" },
{ "WM/EncodedBy", "ENCODEDBY" },
{ "WM/AlbumSortOrder", "ALBUMSORT" },
{ "WM/AlbumArtistSortOrder", "ALBUMARTISTSORT" },
{ "WM/ArtistSortOrder", "ARTISTSORT" },
{ "WM/TitleSortOrder", "TITLESORT" },
{ "WM/Script", "SCRIPT" },
{ "WM/Language", "LANGUAGE" },
{ "WM/ARTISTS", "ARTISTS" },
{ "ASIN", "ASIN" },
{ "MusicBrainz/Track Id", "MUSICBRAINZ_TRACKID" },
{ "MusicBrainz/Artist Id", "MUSICBRAINZ_ARTISTID" },
{ "MusicBrainz/Album Id", "MUSICBRAINZ_ALBUMID" },
{ "MusicBrainz/Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
{ "MusicBrainz/Album Release Country", "RELEASECOUNTRY" },
{ "MusicBrainz/Album Status", "RELEASESTATUS" },
{ "MusicBrainz/Album Type", "RELEASETYPE" },
{ "MusicBrainz/Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
{ "MusicBrainz/Release Track Id", "MUSICBRAINZ_RELEASETRACKID" },
{ "MusicBrainz/Work Id", "MUSICBRAINZ_WORKID" },
{ "MusicIP/PUID", "MUSICIP_PUID" },
{ "Acoustid/Id", "ACOUSTID_ID" },
{ "Acoustid/Fingerprint", "ACOUSTID_FINGERPRINT" },
const std::pair<const char *, const char *> keyTranslation[] = {
std::make_pair("WM/AlbumTitle", "ALBUM"),
std::make_pair("WM/AlbumArtist", "ALBUMARTIST"),
std::make_pair("WM/Composer", "COMPOSER"),
std::make_pair("WM/Writer", "LYRICIST"),
std::make_pair("WM/Conductor", "CONDUCTOR"),
std::make_pair("WM/ModifiedBy", "REMIXER"),
std::make_pair("WM/Year", "DATE"),
std::make_pair("WM/OriginalReleaseYear", "ORIGINALDATE"),
std::make_pair("WM/Producer", "PRODUCER"),
std::make_pair("WM/ContentGroupDescription", "WORK"),
std::make_pair("WM/SubTitle", "SUBTITLE"),
std::make_pair("WM/SetSubTitle", "DISCSUBTITLE"),
std::make_pair("WM/TrackNumber", "TRACKNUMBER"),
std::make_pair("WM/PartOfSet", "DISCNUMBER"),
std::make_pair("WM/Genre", "GENRE"),
std::make_pair("WM/BeatsPerMinute", "BPM"),
std::make_pair("WM/Mood", "MOOD"),
std::make_pair("WM/ISRC", "ISRC"),
std::make_pair("WM/Lyrics", "LYRICS"),
std::make_pair("WM/Media", "MEDIA"),
std::make_pair("WM/Publisher", "LABEL"),
std::make_pair("WM/CatalogNo", "CATALOGNUMBER"),
std::make_pair("WM/Barcode", "BARCODE"),
std::make_pair("WM/EncodedBy", "ENCODEDBY"),
std::make_pair("WM/AlbumSortOrder", "ALBUMSORT"),
std::make_pair("WM/AlbumArtistSortOrder", "ALBUMARTISTSORT"),
std::make_pair("WM/ArtistSortOrder", "ARTISTSORT"),
std::make_pair("WM/TitleSortOrder", "TITLESORT"),
std::make_pair("WM/Script", "SCRIPT"),
std::make_pair("WM/Language", "LANGUAGE"),
std::make_pair("WM/ARTISTS", "ARTISTS"),
std::make_pair("ASIN", "ASIN"),
std::make_pair("MusicBrainz/Track Id", "MUSICBRAINZ_TRACKID"),
std::make_pair("MusicBrainz/Artist Id", "MUSICBRAINZ_ARTISTID"),
std::make_pair("MusicBrainz/Album Id", "MUSICBRAINZ_ALBUMID"),
std::make_pair("MusicBrainz/Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID"),
std::make_pair("MusicBrainz/Album Release Country", "RELEASECOUNTRY"),
std::make_pair("MusicBrainz/Album Status", "RELEASESTATUS"),
std::make_pair("MusicBrainz/Album Type", "RELEASETYPE"),
std::make_pair("MusicBrainz/Release Group Id", "MUSICBRAINZ_RELEASEGROUPID"),
std::make_pair("MusicBrainz/Release Track Id", "MUSICBRAINZ_RELEASETRACKID"),
std::make_pair("MusicBrainz/Work Id", "MUSICBRAINZ_WORKID"),
std::make_pair("MusicIP/PUID", "MUSICIP_PUID"),
std::make_pair("Acoustid/Id", "ACOUSTID_ID"),
std::make_pair("Acoustid/Fingerprint", "ACOUSTID_FINGERPRINT"),
};
const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
String translateKey(const String &key)
{
for(size_t i = 0; i < keyTranslationSize; ++i) {
if(key == keyTranslation[i][0])
return keyTranslation[i][1];
if(key == keyTranslation[i].first)
return keyTranslation[i].second;
}
return String();
}
}
} // namespace
PropertyMap ASF::Tag::properties() const
{
@@ -324,9 +322,8 @@ PropertyMap ASF::Tag::setProperties(const PropertyMap &props)
{
static Map<String, String> reverseKeyMap;
if(reverseKeyMap.isEmpty()) {
int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
for(int i = 0; i < numKeys; i++) {
reverseKeyMap[keyTranslation[i][1]] = keyTranslation[i][0];
for(size_t i = 0; i < keyTranslationSize; i++) {
reverseKeyMap[keyTranslation[i].second] = keyTranslation[i].first;
}
}

View File

@@ -152,7 +152,8 @@ namespace TagLib {
virtual bool isEmpty() const;
/*!
* \deprecated
* \deprecated Use attributeListMap() const, contains(), removeItem(),
* attribute(), setAttribute(), addAttribute().
*/
AttributeListMap &attributeListMap();

View File

@@ -49,32 +49,31 @@ using namespace TagLib;
#define VIRTUAL_FUNCTION_WORKAROUND(function_name, default_value) \
if(dynamic_cast<const APE::Properties*>(this)) \
return dynamic_cast<const APE::Properties*>(this)->function_name(); \
else if(dynamic_cast<const ASF::Properties*>(this)) \
if(dynamic_cast<const ASF::Properties*>(this)) \
return dynamic_cast<const ASF::Properties*>(this)->function_name(); \
else if(dynamic_cast<const FLAC::Properties*>(this)) \
if(dynamic_cast<const FLAC::Properties*>(this)) \
return dynamic_cast<const FLAC::Properties*>(this)->function_name(); \
else if(dynamic_cast<const MP4::Properties*>(this)) \
if(dynamic_cast<const MP4::Properties*>(this)) \
return dynamic_cast<const MP4::Properties*>(this)->function_name(); \
else if(dynamic_cast<const MPC::Properties*>(this)) \
if(dynamic_cast<const MPC::Properties*>(this)) \
return dynamic_cast<const MPC::Properties*>(this)->function_name(); \
else if(dynamic_cast<const MPEG::Properties*>(this)) \
if(dynamic_cast<const MPEG::Properties*>(this)) \
return dynamic_cast<const MPEG::Properties*>(this)->function_name(); \
else if(dynamic_cast<const Ogg::Opus::Properties*>(this)) \
if(dynamic_cast<const Ogg::Opus::Properties*>(this)) \
return dynamic_cast<const Ogg::Opus::Properties*>(this)->function_name(); \
else if(dynamic_cast<const Ogg::Speex::Properties*>(this)) \
if(dynamic_cast<const Ogg::Speex::Properties*>(this)) \
return dynamic_cast<const Ogg::Speex::Properties*>(this)->function_name(); \
else if(dynamic_cast<const TrueAudio::Properties*>(this)) \
if(dynamic_cast<const TrueAudio::Properties*>(this)) \
return dynamic_cast<const TrueAudio::Properties*>(this)->function_name(); \
else if(dynamic_cast<const RIFF::AIFF::Properties*>(this)) \
if(dynamic_cast<const RIFF::AIFF::Properties*>(this)) \
return dynamic_cast<const RIFF::AIFF::Properties*>(this)->function_name(); \
else if(dynamic_cast<const RIFF::WAV::Properties*>(this)) \
if(dynamic_cast<const RIFF::WAV::Properties*>(this)) \
return dynamic_cast<const RIFF::WAV::Properties*>(this)->function_name(); \
else if(dynamic_cast<const Vorbis::Properties*>(this)) \
if(dynamic_cast<const Vorbis::Properties*>(this)) \
return dynamic_cast<const Vorbis::Properties*>(this)->function_name(); \
else if(dynamic_cast<const WavPack::Properties*>(this)) \
if(dynamic_cast<const WavPack::Properties*>(this)) \
return dynamic_cast<const WavPack::Properties*>(this)->function_name(); \
else \
return (default_value);
return (default_value);
class AudioProperties::AudioPropertiesPrivate
{

View File

@@ -84,6 +84,22 @@ namespace
return 0;
}
File *detectByResolvers(IOStream* stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
for(ResolverList::ConstIterator it = fileTypeResolvers.begin();
it != fileTypeResolvers.end(); ++it) {
if(const FileRef::StreamTypeResolver *streamResolver =
dynamic_cast<const FileRef::StreamTypeResolver*>(*it)) {
if(File *file = streamResolver->createFileFromStream(
stream, readAudioProperties, audioPropertiesStyle))
return file;
}
}
return 0;
}
// Detect the file type based on the file extension.
File* detectByExtension(IOStream *stream, bool readAudioProperties,
@@ -109,41 +125,51 @@ namespace
// .oga can be any audio in the Ogg container. So leave it to content-based detection.
File *file = 0;
if(ext == "MP3")
return new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
if(ext == "OGG")
return new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "FLAC")
return new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
if(ext == "MPC")
return new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WV")
return new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "SPX")
return new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "OPUS")
return new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "TTA")
return new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
return new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WMA" || ext == "ASF")
return new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
return new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WAV")
return new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "APE")
return new APE::File(stream, readAudioProperties, audioPropertiesStyle);
file = new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
else if(ext == "OGG")
file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "FLAC")
file = new FLAC::File(stream, ID3v2::FrameFactory::instance(), 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);
else if(ext == "TTA")
file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "WMA" || ext == "ASF")
file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
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);
// module, nst and wow are possible but uncommon extensions
if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
return new Mod::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "S3M")
return new S3M::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "IT")
return new IT::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "XM")
return new XM::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
file = new Mod::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "S3M")
file = new S3M::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "IT")
file = new IT::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ext == "XM")
file = new XM::File(stream, readAudioProperties, audioPropertiesStyle);
// if file is not valid, leave it to content-based detection.
if(file) {
if(file->isValid())
return file;
delete file;
}
return 0;
}
@@ -189,8 +215,7 @@ namespace
if(file) {
if(file->isValid())
return file;
else
delete file;
delete file;
}
return 0;
@@ -267,13 +292,12 @@ namespace
return 0;
}
}
} // namespace
class FileRef::FileRefPrivate : public RefCounter
{
public:
FileRefPrivate() :
RefCounter(),
file(0),
stream(0) {}
@@ -472,6 +496,12 @@ void FileRef::parse(FileName fileName, bool readAudioProperties,
void FileRef::parse(IOStream *stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
// Try user-defined stream resolvers.
d->file = detectByResolvers(stream, readAudioProperties, audioPropertiesStyle);
if(d->file)
return;
// Try user-defined resolvers.
d->file = detectByResolvers(stream->name(), readAudioProperties, audioPropertiesStyle);

View File

@@ -108,6 +108,16 @@ namespace TagLib {
audioPropertiesStyle = AudioProperties::Average) const = 0;
};
class TAGLIB_EXPORT StreamTypeResolver : public FileTypeResolver
{
TAGLIB_IGNORE_MISSING_DESTRUCTOR
public:
virtual File *createFileFromStream(IOStream *stream,
bool readAudioProperties = true,
AudioProperties::ReadStyle
audioPropertiesStyle = AudioProperties::Average) const = 0;
};
/*!
* Creates a null FileRef.
*/
@@ -268,7 +278,7 @@ namespace TagLib {
* \note You generally shouldn't use this method, but instead the constructor
* directly.
*
* \deprecated
* \deprecated Use FileRef(FileName, bool, AudioProperties::ReadStyle).
*/
static File *create(FileName fileName,
bool readAudioProperties = true,

View File

@@ -55,7 +55,7 @@ namespace
const long MaxPaddingLegnth = 1024 * 1024;
const char LastBlockFlag = '\x80';
}
} // namespace
class FLAC::File::FilePrivate
{
@@ -497,6 +497,11 @@ void FLAC::File::scan()
seek(nextBlockOffset);
const ByteVector header = readBlock(4);
if(header.size() != 4) {
debug("FLAC::File::scan() -- Failed to read a block header");
setValid(false);
return;
}
// Header format (from spec):
// <1> Last-metadata-block flag

View File

@@ -238,7 +238,7 @@ namespace TagLib {
* when
*
* \see ID3v2FrameFactory
* \deprecated This value should be passed in via the constructor
* \deprecated This value should be passed in via the constructor.
*/
TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);

View File

@@ -70,7 +70,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;
@@ -118,7 +118,7 @@ namespace TagLib {
*
* \note This method is just an alias of bitsPerSample().
*
* \deprecated
* \deprecated Use bitsPerSample().
*/
TAGLIB_DEPRECATED int sampleWidth() const;

View File

@@ -37,7 +37,7 @@ class IT::File::FilePrivate
{
public:
FilePrivate(AudioProperties::ReadStyle propertiesStyle)
: tag(), properties(propertiesStyle)
: properties(propertiesStyle)
{
}
@@ -113,7 +113,7 @@ bool IT::File::save()
// write comment as instrument and sample names:
StringList lines = d->tag.comment().split("\n");
for(unsigned short i = 0; i < instrumentCount; ++ i) {
seek(192L + length + ((long)i << 2));
seek(192L + length + (static_cast<long>(i) << 2));
unsigned long instrumentOffset = 0;
if(!readU32L(instrumentOffset))
return false;
@@ -128,14 +128,14 @@ bool IT::File::save()
}
for(unsigned short i = 0; i < sampleCount; ++ i) {
seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
seek(192L + length + (static_cast<long>(instrumentCount) << 2) + (static_cast<long>(i) << 2));
unsigned long sampleOffset = 0;
if(!readU32L(sampleOffset))
return false;
seek(sampleOffset + 20);
if((unsigned int)(i + instrumentCount) < lines.size())
if(static_cast<unsigned int>(i + instrumentCount) < lines.size())
writeString(lines[i + instrumentCount], 25);
else
writeString(String(), 25);
@@ -152,7 +152,7 @@ bool IT::File::save()
// terminating NUL but it does not hurt to add one:
if(message.size() > 7999)
message.resize(7999);
message.append((char)0);
message.append(static_cast<char>(0));
unsigned short special = 0;
unsigned short messageLength = 0;
@@ -239,7 +239,7 @@ void IT::File::read(bool)
seek(messageOffset);
ByteVector messageBytes = readBlock(messageLength);
READ_ASSERT(messageBytes.size() == messageLength);
int index = messageBytes.find((char) 0);
int index = messageBytes.find(static_cast<char>(0));
if(index > -1)
messageBytes.resize(index, 0);
messageBytes.replace('\r', '\n');
@@ -258,7 +258,7 @@ void IT::File::read(bool)
// But this always gives 64 channels for all my files anyway.
// Strangely VLC does report other values. I wonder how VLC
// gets it's values.
if((unsigned char) pannings[i] < 128 && volumes[i] > 0)
if(static_cast<unsigned char>(pannings[i]) < 128 && volumes[i] > 0)
++channels;
}
d->properties.setChannels(channels);
@@ -280,7 +280,7 @@ void IT::File::read(bool)
// e.g. VLC seems to interpret a nil as a space. I
// don't know what is the proper behaviour.
for(unsigned short i = 0; i < instrumentCount; ++ i) {
seek(192L + length + ((long)i << 2));
seek(192L + length + (static_cast<long>(i) << 2));
READ_U32L_AS(instrumentOffset);
seek(instrumentOffset);
@@ -296,7 +296,7 @@ void IT::File::read(bool)
}
for(unsigned short i = 0; i < sampleCount; ++ i) {
seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
seek(192L + length + (static_cast<long>(instrumentCount) << 2) + (static_cast<long>(i) << 2));
READ_U32L_AS(sampleOffset);
seek(sampleOffset);

View File

@@ -49,7 +49,7 @@ bool Mod::FileBase::readString(String &s, unsigned long size)
{
ByteVector data(readBlock(size));
if(data.size() < size) return false;
int index = data.find((char) 0);
int index = data.find(static_cast<char>(0));
if(index > -1)
{
data.resize(index);

View File

@@ -44,7 +44,6 @@ public:
};
Mod::Tag::Tag() :
TagLib::Tag(),
d(new TagPrivate())
{
}

View File

@@ -31,7 +31,7 @@
using namespace TagLib;
const char *MP4::Atom::containers[11] = {
const char *const MP4::Atom::containers[11] = {
"moov", "udta", "mdia", "meta", "ilst",
"stbl", "minf", "moof", "traf", "trak",
"stsd"
@@ -85,7 +85,25 @@ MP4::Atom::Atom(File *file)
for(int i = 0; i < numContainers; i++) {
if(name == containers[i]) {
if(name == "meta") {
file->seek(4, File::Current);
long posAfterMeta = file->tell();
ByteVector nextSize = file->readBlock(8).mid(4, 4);
static const char *const metaChildrenNames[] = {
"hdlr", "ilst", "mhdr", "ctry", "lang"
};
bool metaIsFullAtom = true;
for(size_t j = 0;
j < sizeof(metaChildrenNames) / sizeof(metaChildrenNames[0]);
++j) {
if(nextSize == metaChildrenNames[j]) {
// meta is not a full atom (i.e. not followed by version, flags). It
// is followed by the size and type of the first child atom.
metaIsFullAtom = false;
break;
}
}
// Only skip next four bytes, which contain version and flags, if meta
// is a full atom.
file->seek(posAfterMeta + (metaIsFullAtom ? 4 : 0));
}
else if(name == "stsd") {
file->seek(8, File::Current);

View File

@@ -74,7 +74,7 @@ namespace TagLib {
typedef TagLib::List<AtomData> AtomDataList;
class Atom
class TAGLIB_EXPORT Atom
{
public:
Atom(File *file);
@@ -88,11 +88,11 @@ namespace TagLib {
AtomList children;
private:
static const int numContainers = 11;
static const char *containers[11];
static const char *const containers[11];
};
//! Root-level atoms
class Atoms
class TAGLIB_EXPORT Atoms
{
public:
Atoms(File *file);

View File

@@ -34,7 +34,6 @@ class MP4::CoverArt::CoverArtPrivate : public RefCounter
{
public:
CoverArtPrivate() :
RefCounter(),
format(MP4::CoverArt::JPEG) {}
Format format;

View File

@@ -49,7 +49,7 @@ namespace
return true;
}
}
} // namespace
class MP4::File::FilePrivate
{
@@ -175,6 +175,26 @@ MP4::File::save()
return d->tag->save();
}
bool
MP4::File::strip(int tags)
{
if(readOnly()) {
debug("MP4::File::strip() - Cannot strip tags from a read only file.");
return false;
}
if(!isValid()) {
debug("MP4::File::strip() -- Cannot strip tags from an invalid file.");
return false;
}
if(tags & MP4) {
return d->tag->strip();
}
return true;
}
bool
MP4::File::hasMP4Tag() const
{

View File

@@ -48,6 +48,19 @@ namespace TagLib {
class TAGLIB_EXPORT File : public TagLib::File
{
public:
/*!
* This set of flags is used for strip() and is suitable for
* being OR-ed together.
*/
enum TagTypes {
//! Empty set. Matches no tag types.
NoTags = 0x0000,
//! Matches MP4 tags.
MP4 = 0x0001,
//! Matches all tag types.
AllTags = 0xffff
};
/*!
* Constructs an MP4 file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
@@ -114,6 +127,15 @@ namespace TagLib {
*/
bool save();
/*!
* 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
* successfully stripped.
*
* \note This will update the file immediately.
*/
bool strip(int tags = AllTags);
/*!
* Returns whether or not the file on disk actually has an MP4 tag, or the
* file has a Metadata Item List (ilst) atom.

View File

@@ -34,7 +34,6 @@ class MP4::Item::ItemPrivate : public RefCounter
{
public:
ItemPrivate() :
RefCounter(),
valid(true),
atomDataType(TypeUndefined) {}

View File

@@ -50,7 +50,7 @@ namespace
return totalLength;
}
}
} // namespace
class MP4::Properties::PropertiesPrivate
{
@@ -188,7 +188,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
file->seek(mdhd->offset);
data = file->readBlock(mdhd->length);
const unsigned int version = data[8];
const unsigned int version = data.at(8);
long long unit;
long long length;
if(version == 1) {
@@ -222,13 +222,13 @@ MP4::Properties::read(File *file, Atoms *atoms)
d->channels = data.toShort(40U);
d->bitsPerSample = data.toShort(42U);
d->sampleRate = data.toUInt(46U);
if(data.containsAt("esds", 56) && data[64] == 0x03) {
if(data.containsAt("esds", 56) && data.at(64) == 0x03) {
unsigned int pos = 65;
if(data.containsAt("\x80\x80\x80", pos)) {
pos += 3;
}
pos += 4;
if(data[pos] == 0x04) {
if(data.at(pos) == 0x04) {
pos += 1;
if(data.containsAt("\x80\x80\x80", pos)) {
pos += 3;

View File

@@ -55,7 +55,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;

View File

@@ -84,7 +84,7 @@ MP4::Tag::Tag(TagLib::File *file, MP4::Atoms *atoms) :
if (val.type == TypeUTF8) {
addItem(atom->name, StringList(String(val.data, String::UTF8)));
} else {
addItem(atom->name, (int)(val.data.toShort()));
addItem(atom->name, static_cast<int>(val.data.toShort()));
}
}
}
@@ -140,7 +140,7 @@ MP4::Tag::parseData2(const MP4::Atom *atom, int expectedFlags, bool freeForm)
debug("MP4: Unexpected atom \"" + name + "\", expecting \"mean\"");
return result;
}
else if(i == 1 && name != "name") {
if(i == 1 && name != "name") {
debug("MP4: Unexpected atom \"" + name + "\", expecting \"name\"");
return result;
}
@@ -177,7 +177,7 @@ MP4::Tag::parseInt(const MP4::Atom *atom)
{
ByteVectorList data = parseData(atom);
if(!data.isEmpty()) {
addItem(atom->name, (int)data[0].toShort());
addItem(atom->name, static_cast<int>(data[0].toShort()));
}
}
@@ -213,7 +213,7 @@ MP4::Tag::parseGnre(const MP4::Atom *atom)
{
ByteVectorList data = parseData(atom);
if(!data.isEmpty()) {
int idx = (int)data[0].toShort();
int idx = static_cast<int>(data[0].toShort());
if(idx > 0) {
addItem("\251gen", StringList(ID3v1::genre(idx - 1)));
}
@@ -541,6 +541,19 @@ MP4::Tag::save()
return true;
}
bool
MP4::Tag::strip()
{
d->items.clear();
AtomList path = d->atoms->path("moov", "udta", "meta", "ilst");
if(path.size() == 4) {
saveExisting(ByteVector(), path);
}
return true;
}
void
MP4::Tag::updateParents(const AtomList &path, long delta, int ignore)
{
@@ -699,20 +712,40 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
}
long delta = data.size() - length;
if(delta > 0 || (delta < 0 && delta > -8)) {
data.append(padIlst(data));
delta = data.size() - length;
}
else if(delta < 0) {
data.append(padIlst(data, -delta - 8));
delta = 0;
}
if(!data.isEmpty()) {
if(delta > 0 || (delta < 0 && delta > -8)) {
data.append(padIlst(data));
delta = data.size() - length;
}
else if(delta < 0) {
data.append(padIlst(data, -delta - 8));
delta = 0;
}
d->file->insert(data, offset, length);
d->file->insert(data, offset, length);
if(delta) {
updateParents(path, delta, 1);
updateOffsets(delta, offset);
if(delta) {
updateParents(path, delta, 1);
updateOffsets(delta, offset);
}
}
else {
// Strip meta if data is empty, only the case when called from strip().
MP4::Atom *udta = *(--it);
AtomList &udtaChildren = udta->children;
AtomList::Iterator metaIt = udtaChildren.find(meta);
if(metaIt != udtaChildren.end()) {
offset = meta->offset;
delta = - meta->length;
udtaChildren.erase(metaIt);
d->file->removeBlock(meta->offset, meta->length);
delete meta;
if(delta) {
updateParents(path, delta, 2);
updateOffsets(delta, offset);
}
}
}
}
@@ -871,89 +904,89 @@ bool MP4::Tag::contains(const String &key) const
namespace
{
const char *keyTranslation[][2] = {
{ "\251nam", "TITLE" },
{ "\251ART", "ARTIST" },
{ "\251alb", "ALBUM" },
{ "\251cmt", "COMMENT" },
{ "\251gen", "GENRE" },
{ "\251day", "DATE" },
{ "\251wrt", "COMPOSER" },
{ "\251grp", "GROUPING" },
{ "aART", "ALBUMARTIST" },
{ "trkn", "TRACKNUMBER" },
{ "disk", "DISCNUMBER" },
{ "cpil", "COMPILATION" },
{ "tmpo", "BPM" },
{ "cprt", "COPYRIGHT" },
{ "\251lyr", "LYRICS" },
{ "\251too", "ENCODEDBY" },
{ "soal", "ALBUMSORT" },
{ "soaa", "ALBUMARTISTSORT" },
{ "soar", "ARTISTSORT" },
{ "sonm", "TITLESORT" },
{ "soco", "COMPOSERSORT" },
{ "sosn", "SHOWSORT" },
{ "shwm", "SHOWWORKMOVEMENT" },
{ "pgap", "GAPLESSPLAYBACK" },
{ "pcst", "PODCAST" },
{ "catg", "PODCASTCATEGORY" },
{ "desc", "PODCASTDESC" },
{ "egid", "PODCASTID" },
{ "purl", "PODCASTURL" },
{ "tves", "TVEPISODE" },
{ "tven", "TVEPISODEID" },
{ "tvnn", "TVNETWORK" },
{ "tvsn", "TVSEASON" },
{ "tvsh", "TVSHOW" },
{ "\251wrk", "WORK" },
{ "\251mvn", "MOVEMENTNAME" },
{ "\251mvi", "MOVEMENTNUMBER" },
{ "\251mvc", "MOVEMENTCOUNT" },
{ "----:com.apple.iTunes:MusicBrainz Track Id", "MUSICBRAINZ_TRACKID" },
{ "----:com.apple.iTunes:MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID" },
{ "----:com.apple.iTunes:MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID" },
{ "----:com.apple.iTunes:MusicBrainz Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
{ "----:com.apple.iTunes:MusicBrainz Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
{ "----:com.apple.iTunes:MusicBrainz Release Track Id", "MUSICBRAINZ_RELEASETRACKID" },
{ "----:com.apple.iTunes:MusicBrainz Work Id", "MUSICBRAINZ_WORKID" },
{ "----:com.apple.iTunes:MusicBrainz Album Release Country", "RELEASECOUNTRY" },
{ "----:com.apple.iTunes:MusicBrainz Album Status", "RELEASESTATUS" },
{ "----:com.apple.iTunes:MusicBrainz Album Type", "RELEASETYPE" },
{ "----:com.apple.iTunes:ARTISTS", "ARTISTS" },
{ "----:com.apple.iTunes:originaldate", "ORIGINALDATE" },
{ "----:com.apple.iTunes:ASIN", "ASIN" },
{ "----:com.apple.iTunes:LABEL", "LABEL" },
{ "----:com.apple.iTunes:LYRICIST", "LYRICIST" },
{ "----:com.apple.iTunes:CONDUCTOR", "CONDUCTOR" },
{ "----:com.apple.iTunes:REMIXER", "REMIXER" },
{ "----:com.apple.iTunes:ENGINEER", "ENGINEER" },
{ "----:com.apple.iTunes:PRODUCER", "PRODUCER" },
{ "----:com.apple.iTunes:DJMIXER", "DJMIXER" },
{ "----:com.apple.iTunes:MIXER", "MIXER" },
{ "----:com.apple.iTunes:SUBTITLE", "SUBTITLE" },
{ "----:com.apple.iTunes:DISCSUBTITLE", "DISCSUBTITLE" },
{ "----:com.apple.iTunes:MOOD", "MOOD" },
{ "----:com.apple.iTunes:ISRC", "ISRC" },
{ "----:com.apple.iTunes:CATALOGNUMBER", "CATALOGNUMBER" },
{ "----:com.apple.iTunes:BARCODE", "BARCODE" },
{ "----:com.apple.iTunes:SCRIPT", "SCRIPT" },
{ "----:com.apple.iTunes:LANGUAGE", "LANGUAGE" },
{ "----:com.apple.iTunes:LICENSE", "LICENSE" },
{ "----:com.apple.iTunes:MEDIA", "MEDIA" },
const std::pair<const char *, const char *> keyTranslation[] = {
std::make_pair("\251nam", "TITLE"),
std::make_pair("\251ART", "ARTIST"),
std::make_pair("\251alb", "ALBUM"),
std::make_pair("\251cmt", "COMMENT"),
std::make_pair("\251gen", "GENRE"),
std::make_pair("\251day", "DATE"),
std::make_pair("\251wrt", "COMPOSER"),
std::make_pair("\251grp", "GROUPING"),
std::make_pair("aART", "ALBUMARTIST"),
std::make_pair("trkn", "TRACKNUMBER"),
std::make_pair("disk", "DISCNUMBER"),
std::make_pair("cpil", "COMPILATION"),
std::make_pair("tmpo", "BPM"),
std::make_pair("cprt", "COPYRIGHT"),
std::make_pair("\251lyr", "LYRICS"),
std::make_pair("\251too", "ENCODEDBY"),
std::make_pair("soal", "ALBUMSORT"),
std::make_pair("soaa", "ALBUMARTISTSORT"),
std::make_pair("soar", "ARTISTSORT"),
std::make_pair("sonm", "TITLESORT"),
std::make_pair("soco", "COMPOSERSORT"),
std::make_pair("sosn", "SHOWSORT"),
std::make_pair("shwm", "SHOWWORKMOVEMENT"),
std::make_pair("pgap", "GAPLESSPLAYBACK"),
std::make_pair("pcst", "PODCAST"),
std::make_pair("catg", "PODCASTCATEGORY"),
std::make_pair("desc", "PODCASTDESC"),
std::make_pair("egid", "PODCASTID"),
std::make_pair("purl", "PODCASTURL"),
std::make_pair("tves", "TVEPISODE"),
std::make_pair("tven", "TVEPISODEID"),
std::make_pair("tvnn", "TVNETWORK"),
std::make_pair("tvsn", "TVSEASON"),
std::make_pair("tvsh", "TVSHOW"),
std::make_pair("\251wrk", "WORK"),
std::make_pair("\251mvn", "MOVEMENTNAME"),
std::make_pair("\251mvi", "MOVEMENTNUMBER"),
std::make_pair("\251mvc", "MOVEMENTCOUNT"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Track Id", "MUSICBRAINZ_TRACKID"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Release Group Id", "MUSICBRAINZ_RELEASEGROUPID"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Release Track Id", "MUSICBRAINZ_RELEASETRACKID"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Work Id", "MUSICBRAINZ_WORKID"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Album Release Country", "RELEASECOUNTRY"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Album Status", "RELEASESTATUS"),
std::make_pair("----:com.apple.iTunes:MusicBrainz Album Type", "RELEASETYPE"),
std::make_pair("----:com.apple.iTunes:ARTISTS", "ARTISTS"),
std::make_pair("----:com.apple.iTunes:originaldate", "ORIGINALDATE"),
std::make_pair("----:com.apple.iTunes:ASIN", "ASIN"),
std::make_pair("----:com.apple.iTunes:LABEL", "LABEL"),
std::make_pair("----:com.apple.iTunes:LYRICIST", "LYRICIST"),
std::make_pair("----:com.apple.iTunes:CONDUCTOR", "CONDUCTOR"),
std::make_pair("----:com.apple.iTunes:REMIXER", "REMIXER"),
std::make_pair("----:com.apple.iTunes:ENGINEER", "ENGINEER"),
std::make_pair("----:com.apple.iTunes:PRODUCER", "PRODUCER"),
std::make_pair("----:com.apple.iTunes:DJMIXER", "DJMIXER"),
std::make_pair("----:com.apple.iTunes:MIXER", "MIXER"),
std::make_pair("----:com.apple.iTunes:SUBTITLE", "SUBTITLE"),
std::make_pair("----:com.apple.iTunes:DISCSUBTITLE", "DISCSUBTITLE"),
std::make_pair("----:com.apple.iTunes:MOOD", "MOOD"),
std::make_pair("----:com.apple.iTunes:ISRC", "ISRC"),
std::make_pair("----:com.apple.iTunes:CATALOGNUMBER", "CATALOGNUMBER"),
std::make_pair("----:com.apple.iTunes:BARCODE", "BARCODE"),
std::make_pair("----:com.apple.iTunes:SCRIPT", "SCRIPT"),
std::make_pair("----:com.apple.iTunes:LANGUAGE", "LANGUAGE"),
std::make_pair("----:com.apple.iTunes:LICENSE", "LICENSE"),
std::make_pair("----:com.apple.iTunes:MEDIA", "MEDIA"),
};
const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
String translateKey(const String &key)
{
for(size_t i = 0; i < keyTranslationSize; ++i) {
if(key == keyTranslation[i][0])
return keyTranslation[i][1];
if(key == keyTranslation[i].first)
return keyTranslation[i].second;
}
return String();
}
}
} // namespace
PropertyMap MP4::Tag::properties() const
{
@@ -998,9 +1031,8 @@ PropertyMap MP4::Tag::setProperties(const PropertyMap &props)
{
static Map<String, String> reverseKeyMap;
if(reverseKeyMap.isEmpty()) {
int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
for(int i = 0; i < numKeys; i++) {
reverseKeyMap[keyTranslation[i][1]] = keyTranslation[i][0];
for(size_t i = 0; i < keyTranslationSize; i++) {
reverseKeyMap[keyTranslation[i].second] = keyTranslation[i].first;
}
}

View File

@@ -40,7 +40,7 @@ namespace TagLib {
namespace MP4 {
/*!
* \deprecated
* \deprecated Use ItemMap.
*/
TAGLIB_DEPRECATED typedef TagLib::Map<String, Item> ItemListMap;
typedef TagLib::Map<String, Item> ItemMap;
@@ -72,7 +72,7 @@ namespace TagLib {
virtual bool isEmpty() const;
/*!
* \deprecated Use the item() and setItem() API instead
* \deprecated Use the item() and setItem() API instead.
*/
TAGLIB_DEPRECATED ItemMap &itemListMap();
@@ -102,6 +102,11 @@ namespace TagLib {
*/
bool contains(const String &key) const;
/*!
* Saves the associated file with the tag stripped.
*/
bool strip();
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList& properties);
PropertyMap setProperties(const PropertyMap &properties);

View File

@@ -195,7 +195,7 @@ namespace TagLib {
void strip(int tags = AllTags);
/*!
* \deprecated
* \deprecated Use strip().
* \see strip
*/
TAGLIB_DEPRECATED void remove(int tags = AllTags);

View File

@@ -201,7 +201,7 @@ namespace
// This array looks weird, but the same as original MusePack code found at:
// https://www.musepack.net/index.php?pg=src
const unsigned short sftable [8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
}
} // namespace
void MPC::Properties::readSV8(File *file, long streamLength)
{
@@ -298,6 +298,9 @@ void MPC::Properties::readSV8(File *file, long streamLength)
void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
{
if(data.startsWith("MP+")) {
if(data.size() < 4)
return;
d->version = data[3] & 15;
if(d->version < 7)
return;
@@ -317,22 +320,22 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
// convert gain info
if(d->trackGain != 0) {
int tmp = (int)((64.82 - (short)d->trackGain / 100.) * 256. + .5);
int tmp = static_cast<int>((64.82 - static_cast<short>(d->trackGain) / 100.) * 256. + .5);
if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
d->trackGain = tmp;
}
if(d->albumGain != 0) {
int tmp = (int)((64.82 - d->albumGain / 100.) * 256. + .5);
int tmp = static_cast<int>((64.82 - d->albumGain / 100.) * 256. + .5);
if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
d->albumGain = tmp;
}
if (d->trackPeak != 0)
d->trackPeak = (int)(log10((double)d->trackPeak) * 20 * 256 + .5);
d->trackPeak = static_cast<int>(log10(static_cast<double>(d->trackPeak)) * 20 * 256 + .5);
if (d->albumPeak != 0)
d->albumPeak = (int)(log10((double)d->albumPeak) * 20 * 256 + .5);
d->albumPeak = static_cast<int>(log10(static_cast<double>(d->albumPeak)) * 20 * 256 + .5);
bool trueGapless = (gapless >> 31) & 0x0001;
if(trueGapless) {

View File

@@ -72,7 +72,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;

View File

@@ -29,7 +29,7 @@ using namespace TagLib;
namespace
{
const wchar_t *genres[] = {
const wchar_t *const genres[] = {
L"Blues",
L"Classic Rock",
L"Country",
@@ -224,7 +224,7 @@ namespace
L"Psybient"
};
const int genresSize = sizeof(genres) / sizeof(genres[0]);
}
} // namespace
StringList ID3v1::genreList()
{
@@ -250,8 +250,7 @@ String ID3v1::genre(int i)
{
if(i >= 0 && i < genresSize)
return String(genres[i]); // always make a copy
else
return String();
return String();
}
int ID3v1::genreIndex(const String &name)

View File

@@ -76,8 +76,7 @@ ByteVector ID3v1::StringHandler::render(const String &s) const
{
if(s.isLatin1())
return s.data(String::Latin1);
else
return ByteVector();
return ByteVector();
}
////////////////////////////////////////////////////////////////////////////////
@@ -85,13 +84,11 @@ ByteVector ID3v1::StringHandler::render(const String &s) const
////////////////////////////////////////////////////////////////////////////////
ID3v1::Tag::Tag() :
TagLib::Tag(),
d(new TagPrivate())
{
}
ID3v1::Tag::Tag(File *file, long tagOffset) :
TagLib::Tag(),
d(new TagPrivate())
{
d->file = file;

View File

@@ -144,7 +144,7 @@ void AttachedPictureFrame::parseFields(const ByteVector &data)
return;
}
d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
d->type = static_cast<TagLib::ID3v2::AttachedPictureFrame::Type>(data[pos++]);
d->description = readStringField(data, d->textEncoding, &pos);
d->data = data.mid(pos);
@@ -205,7 +205,7 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
d->mimeType = "image/" + fixedString;
}
d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
d->type = static_cast<TagLib::ID3v2::AttachedPictureFrame::Type>(data[pos++]);
d->description = readStringField(data, d->textEncoding, &pos);
d->data = data.mid(pos);

View File

@@ -294,8 +294,10 @@ ByteVector ChapterFrame::renderFields() const
data.append(ByteVector::fromUInt(d->startOffset, true));
data.append(ByteVector::fromUInt(d->endOffset, true));
FrameList l = d->embeddedFrameList;
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) {
(*it)->header()->setVersion(header()->version());
data.append((*it)->render());
}
return data;
}

View File

@@ -117,6 +117,11 @@ void OwnershipFrame::parseFields(const ByteVector &data)
{
int pos = 0;
// Need at least 1 byte for the encoding
if(data.isEmpty()) {
return;
}
// Get the text encoding
d->textEncoding = String::Type(data[0]);
pos += 1;

View File

@@ -109,7 +109,7 @@ void PopularimeterFrame::parseFields(const ByteVector &data)
d->rating = 0;
d->counter = 0;
if(pos < size) {
d->rating = (unsigned char)(data[pos++]);
d->rating = static_cast<unsigned char>(data[pos++]);
if(pos < size) {
d->counter = data.toUInt(static_cast<unsigned int>(pos));
}

View File

@@ -180,7 +180,7 @@ void RelativeVolumeFrame::parseFields(const ByteVector &data)
// Each channel is at least 4 bytes.
while(pos <= (int)data.size() - 4) {
while(pos <= static_cast<int>(data.size()) - 4) {
ChannelType type = ChannelType(data[pos]);
pos += 1;

View File

@@ -75,7 +75,7 @@ namespace {
}
return l;
}
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// public methods
@@ -274,7 +274,7 @@ TableOfContentsFrame *TableOfContentsFrame::findTopLevel(const ID3v2::Tag *tag)
++it)
{
TableOfContentsFrame *frame = dynamic_cast<TableOfContentsFrame *>(*it);
if(frame && frame->isTopLevel() == true)
if(frame && frame->isTopLevel())
return frame;
}
@@ -336,7 +336,7 @@ ByteVector TableOfContentsFrame::renderFields() const
if(d->isOrdered)
flags += 1;
data.append(flags);
data.append((char)(entryCount()));
data.append(static_cast<char>(entryCount()));
ByteVectorList::ConstIterator it = d->childElements.begin();
while(it != d->childElements.end()) {
data.append(*it);
@@ -344,8 +344,10 @@ ByteVector TableOfContentsFrame::renderFields() const
it++;
}
FrameList l = d->embeddedFrameList;
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) {
(*it)->header()->setVersion(header()->version());
data.append((*it)->render());
}
return data;
}

View File

@@ -125,22 +125,22 @@ void TextIdentificationFrame::setTextEncoding(String::Type encoding)
namespace
{
// array of allowed TIPL prefixes and their corresponding key value
const char* involvedPeople[][2] = {
{"ARRANGER", "ARRANGER"},
{"ENGINEER", "ENGINEER"},
{"PRODUCER", "PRODUCER"},
{"DJ-MIX", "DJMIXER"},
{"MIX", "MIXER"},
const std::pair<const char *, const char *> involvedPeople[] = {
std::make_pair("ARRANGER", "ARRANGER"),
std::make_pair("ENGINEER", "ENGINEER"),
std::make_pair("PRODUCER", "PRODUCER"),
std::make_pair("DJ-MIX", "DJMIXER"),
std::make_pair("MIX", "MIXER"),
};
const size_t involvedPeopleSize = sizeof(involvedPeople) / sizeof(involvedPeople[0]);
}
} // namespace
const KeyConversionMap &TextIdentificationFrame::involvedPeopleMap() // static
{
static KeyConversionMap m;
if(m.isEmpty()) {
for(size_t i = 0; i < involvedPeopleSize; ++i)
m.insert(involvedPeople[i][1], involvedPeople[i][0]);
m.insert(involvedPeople[i].second, involvedPeople[i].first);
}
return m;
}
@@ -218,12 +218,32 @@ void TextIdentificationFrame::parseFields(const ByteVector &data)
// append those split values to the list and make sure that the new string's
// type is the same specified for this frame
unsigned short firstBom = 0;
for(ByteVectorList::ConstIterator it = l.begin(); it != l.end(); it++) {
if(!(*it).isEmpty()) {
if(d->textEncoding == String::Latin1)
if(d->textEncoding == String::Latin1) {
d->fieldList.append(Tag::latin1StringHandler()->parse(*it));
else
d->fieldList.append(String(*it, d->textEncoding));
}
else {
String::Type textEncoding = d->textEncoding;
if(textEncoding == String::UTF16) {
if(it == l.begin()) {
firstBom = it->mid(0, 2).toUShort();
}
else {
unsigned short subsequentBom = it->mid(0, 2).toUShort();
if(subsequentBom != 0xfeff && subsequentBom != 0xfffe) {
if(firstBom == 0xfeff) {
textEncoding = String::UTF16BE;
}
else if(firstBom == 0xfffe) {
textEncoding = String::UTF16LE;
}
}
}
}
d->fieldList.append(String(*it, textEncoding));
}
}
}
}
@@ -274,8 +294,8 @@ PropertyMap TextIdentificationFrame::makeTIPLProperties() const
for(StringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
bool found = false;
for(size_t i = 0; i < involvedPeopleSize; ++i)
if(*it == involvedPeople[i][0]) {
map.insert(involvedPeople[i][1], (++it)->split(","));
if(*it == involvedPeople[i].first) {
map.insert(involvedPeople[i].second, (++it)->split(","));
found = true;
break;
}

View File

@@ -74,7 +74,7 @@ namespace
}
return true;
}
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// static methods
@@ -94,8 +94,7 @@ ByteVector Frame::textDelimiter(String::Type t)
{
if(t == String::UTF16 || t == String::UTF16BE || t == String::UTF16LE)
return ByteVector(2, '\0');
else
return ByteVector(1, '\0');
return ByteVector(1, '\0');
}
const String Frame::instrumentPrefix("PERFORMER:");
@@ -117,11 +116,11 @@ Frame *Frame::createTextualFrame(const String &key, const StringList &values) //
TextIdentificationFrame *frame = new TextIdentificationFrame(frameID, String::UTF8);
frame->setText(values);
return frame;
} else if((frameID[0] == 'W') && (values.size() == 1)){ // URL frame (not WXXX); support only one value
} if((frameID[0] == 'W') && (values.size() == 1)){ // URL frame (not WXXX); support only one value
UrlLinkFrame* frame = new UrlLinkFrame(frameID);
frame->setUrl(values.front());
return frame;
} else if(frameID == "PCST") {
} if(frameID == "PCST") {
return new PodcastFrame();
}
}
@@ -166,16 +165,14 @@ ByteVector Frame::frameID() const
{
if(d->header)
return d->header->frameID();
else
return ByteVector();
return ByteVector();
}
unsigned int Frame::size() const
{
if(d->header)
return d->header->frameSize();
else
return 0;
return 0;
}
void Frame::setData(const ByteVector &data)
@@ -309,10 +306,8 @@ String::Type Frame::checkEncoding(const StringList &fields, String::Type encodin
debug("Frame::checkEncoding() -- Rendering using UTF8.");
return String::UTF8;
}
else {
debug("Frame::checkEncoding() -- Rendering using UTF16.");
return String::UTF16;
}
debug("Frame::checkEncoding() -- Rendering using UTF16.");
return String::UTF16;
}
}
@@ -326,120 +321,121 @@ String::Type Frame::checkTextEncoding(const StringList &fields, String::Type enc
namespace
{
const char *frameTranslation[][2] = {
const std::pair<const char *, const char *> frameTranslation[] = {
// Text information frames
{ "TALB", "ALBUM"},
{ "TBPM", "BPM" },
{ "TCOM", "COMPOSER" },
{ "TCON", "GENRE" },
{ "TCOP", "COPYRIGHT" },
{ "TDEN", "ENCODINGTIME" },
{ "TDLY", "PLAYLISTDELAY" },
{ "TDOR", "ORIGINALDATE" },
{ "TDRC", "DATE" },
// { "TRDA", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
// { "TDAT", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
// { "TYER", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
// { "TIME", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
{ "TDRL", "RELEASEDATE" },
{ "TDTG", "TAGGINGDATE" },
{ "TENC", "ENCODEDBY" },
{ "TEXT", "LYRICIST" },
{ "TFLT", "FILETYPE" },
//{ "TIPL", "INVOLVEDPEOPLE" }, handled separately
{ "TIT1", "CONTENTGROUP" }, // 'Work' in iTunes
{ "TIT2", "TITLE"},
{ "TIT3", "SUBTITLE" },
{ "TKEY", "INITIALKEY" },
{ "TLAN", "LANGUAGE" },
{ "TLEN", "LENGTH" },
//{ "TMCL", "MUSICIANCREDITS" }, handled separately
{ "TMED", "MEDIA" },
{ "TMOO", "MOOD" },
{ "TOAL", "ORIGINALALBUM" },
{ "TOFN", "ORIGINALFILENAME" },
{ "TOLY", "ORIGINALLYRICIST" },
{ "TOPE", "ORIGINALARTIST" },
{ "TOWN", "OWNER" },
{ "TPE1", "ARTIST"},
{ "TPE2", "ALBUMARTIST" }, // id3's spec says 'PERFORMER', but most programs use 'ALBUMARTIST'
{ "TPE3", "CONDUCTOR" },
{ "TPE4", "REMIXER" }, // could also be ARRANGER
{ "TPOS", "DISCNUMBER" },
{ "TPRO", "PRODUCEDNOTICE" },
{ "TPUB", "LABEL" },
{ "TRCK", "TRACKNUMBER" },
{ "TRSN", "RADIOSTATION" },
{ "TRSO", "RADIOSTATIONOWNER" },
{ "TSOA", "ALBUMSORT" },
{ "TSOC", "COMPOSERSORT" },
{ "TSOP", "ARTISTSORT" },
{ "TSOT", "TITLESORT" },
{ "TSO2", "ALBUMARTISTSORT" }, // non-standard, used by iTunes
{ "TSRC", "ISRC" },
{ "TSSE", "ENCODING" },
std::make_pair("TALB", "ALBUM"),
std::make_pair("TBPM", "BPM"),
std::make_pair("TCOM", "COMPOSER"),
std::make_pair("TCON", "GENRE"),
std::make_pair("TCOP", "COPYRIGHT"),
std::make_pair("TDEN", "ENCODINGTIME"),
std::make_pair("TDLY", "PLAYLISTDELAY"),
std::make_pair("TDOR", "ORIGINALDATE"),
std::make_pair("TDRC", "DATE"),
// std::make_pair("TRDA", "DATE"), // id3 v2.3, replaced by TDRC in v2.4
// std::make_pair("TDAT", "DATE"), // id3 v2.3, replaced by TDRC in v2.4
// std::make_pair("TYER", "DATE"), // id3 v2.3, replaced by TDRC in v2.4
// std::make_pair("TIME", "DATE"), // id3 v2.3, replaced by TDRC in v2.4
std::make_pair("TDRL", "RELEASEDATE"),
std::make_pair("TDTG", "TAGGINGDATE"),
std::make_pair("TENC", "ENCODEDBY"),
std::make_pair("TEXT", "LYRICIST"),
std::make_pair("TFLT", "FILETYPE"),
//std::make_pair("TIPL", "INVOLVEDPEOPLE"), handled separately
std::make_pair("TIT1", "WORK"), // 'Work' in iTunes
std::make_pair("TIT2", "TITLE"),
std::make_pair("TIT3", "SUBTITLE"),
std::make_pair("TKEY", "INITIALKEY"),
std::make_pair("TLAN", "LANGUAGE"),
std::make_pair("TLEN", "LENGTH"),
//std::make_pair("TMCL", "MUSICIANCREDITS"), handled separately
std::make_pair("TMED", "MEDIA"),
std::make_pair("TMOO", "MOOD"),
std::make_pair("TOAL", "ORIGINALALBUM"),
std::make_pair("TOFN", "ORIGINALFILENAME"),
std::make_pair("TOLY", "ORIGINALLYRICIST"),
std::make_pair("TOPE", "ORIGINALARTIST"),
std::make_pair("TOWN", "OWNER"),
std::make_pair("TPE1", "ARTIST"),
std::make_pair("TPE2", "ALBUMARTIST"), // id3's spec says 'PERFORMER', but most programs use 'ALBUMARTIST'
std::make_pair("TPE3", "CONDUCTOR"),
std::make_pair("TPE4", "REMIXER"), // could also be ARRANGER
std::make_pair("TPOS", "DISCNUMBER"),
std::make_pair("TPRO", "PRODUCEDNOTICE"),
std::make_pair("TPUB", "LABEL"),
std::make_pair("TRCK", "TRACKNUMBER"),
std::make_pair("TRSN", "RADIOSTATION"),
std::make_pair("TRSO", "RADIOSTATIONOWNER"),
std::make_pair("TSOA", "ALBUMSORT"),
std::make_pair("TSOC", "COMPOSERSORT"),
std::make_pair("TSOP", "ARTISTSORT"),
std::make_pair("TSOT", "TITLESORT"),
std::make_pair("TSO2", "ALBUMARTISTSORT"), // non-standard, used by iTunes
std::make_pair("TSRC", "ISRC"),
std::make_pair("TSSE", "ENCODING"),
// URL frames
{ "WCOP", "COPYRIGHTURL" },
{ "WOAF", "FILEWEBPAGE" },
{ "WOAR", "ARTISTWEBPAGE" },
{ "WOAS", "AUDIOSOURCEWEBPAGE" },
{ "WORS", "RADIOSTATIONWEBPAGE" },
{ "WPAY", "PAYMENTWEBPAGE" },
{ "WPUB", "PUBLISHERWEBPAGE" },
//{ "WXXX", "URL"}, handled specially
std::make_pair("WCOP", "COPYRIGHTURL"),
std::make_pair("WOAF", "FILEWEBPAGE"),
std::make_pair("WOAR", "ARTISTWEBPAGE"),
std::make_pair("WOAS", "AUDIOSOURCEWEBPAGE"),
std::make_pair("WORS", "RADIOSTATIONWEBPAGE"),
std::make_pair("WPAY", "PAYMENTWEBPAGE"),
std::make_pair("WPUB", "PUBLISHERWEBPAGE"),
//std::make_pair("WXXX", "URL"), handled specially
// Other frames
{ "COMM", "COMMENT" },
//{ "USLT", "LYRICS" }, handled specially
std::make_pair("COMM", "COMMENT"),
//std::make_pair("USLT", "LYRICS"), handled specially
// Apple iTunes proprietary frames
{ "PCST", "PODCAST" },
{ "TCAT", "PODCASTCATEGORY" },
{ "TDES", "PODCASTDESC" },
{ "TGID", "PODCASTID" },
{ "WFED", "PODCASTURL" },
{ "MVNM", "MOVEMENTNAME" },
{ "MVIN", "MOVEMENTNUMBER" },
{ "GRP1", "GROUPING" },
std::make_pair("PCST", "PODCAST"),
std::make_pair("TCAT", "PODCASTCATEGORY"),
std::make_pair("TDES", "PODCASTDESC"),
std::make_pair("TGID", "PODCASTID"),
std::make_pair("WFED", "PODCASTURL"),
std::make_pair("MVNM", "MOVEMENTNAME"),
std::make_pair("MVIN", "MOVEMENTNUMBER"),
std::make_pair("GRP1", "GROUPING"),
std::make_pair("TCMP", "COMPILATION"),
};
const size_t frameTranslationSize = sizeof(frameTranslation) / sizeof(frameTranslation[0]);
const char *txxxFrameTranslation[][2] = {
{ "MUSICBRAINZ ALBUM ID", "MUSICBRAINZ_ALBUMID" },
{ "MUSICBRAINZ ARTIST ID", "MUSICBRAINZ_ARTISTID" },
{ "MUSICBRAINZ ALBUM ARTIST ID", "MUSICBRAINZ_ALBUMARTISTID" },
{ "MUSICBRAINZ ALBUM RELEASE COUNTRY", "RELEASECOUNTRY" },
{ "MUSICBRAINZ ALBUM STATUS", "RELEASESTATUS" },
{ "MUSICBRAINZ ALBUM TYPE", "RELEASETYPE" },
{ "MUSICBRAINZ RELEASE GROUP ID", "MUSICBRAINZ_RELEASEGROUPID" },
{ "MUSICBRAINZ RELEASE TRACK ID", "MUSICBRAINZ_RELEASETRACKID" },
{ "MUSICBRAINZ WORK ID", "MUSICBRAINZ_WORKID" },
{ "ACOUSTID ID", "ACOUSTID_ID" },
{ "ACOUSTID FINGERPRINT", "ACOUSTID_FINGERPRINT" },
{ "MUSICIP PUID", "MUSICIP_PUID" },
const std::pair<const char *, const char *> txxxFrameTranslation[] = {
std::make_pair("MUSICBRAINZ ALBUM ID", "MUSICBRAINZ_ALBUMID"),
std::make_pair("MUSICBRAINZ ARTIST ID", "MUSICBRAINZ_ARTISTID"),
std::make_pair("MUSICBRAINZ ALBUM ARTIST ID", "MUSICBRAINZ_ALBUMARTISTID"),
std::make_pair("MUSICBRAINZ ALBUM RELEASE COUNTRY", "RELEASECOUNTRY"),
std::make_pair("MUSICBRAINZ ALBUM STATUS", "RELEASESTATUS"),
std::make_pair("MUSICBRAINZ ALBUM TYPE", "RELEASETYPE"),
std::make_pair("MUSICBRAINZ RELEASE GROUP ID", "MUSICBRAINZ_RELEASEGROUPID"),
std::make_pair("MUSICBRAINZ RELEASE TRACK ID", "MUSICBRAINZ_RELEASETRACKID"),
std::make_pair("MUSICBRAINZ WORK ID", "MUSICBRAINZ_WORKID"),
std::make_pair("ACOUSTID ID", "ACOUSTID_ID"),
std::make_pair("ACOUSTID FINGERPRINT", "ACOUSTID_FINGERPRINT"),
std::make_pair("MUSICIP PUID", "MUSICIP_PUID"),
};
const size_t txxxFrameTranslationSize = sizeof(txxxFrameTranslation) / sizeof(txxxFrameTranslation[0]);
// list of deprecated frames and their successors
const char *deprecatedFrames[][2] = {
{"TRDA", "TDRC"}, // 2.3 -> 2.4 (http://en.wikipedia.org/wiki/ID3)
{"TDAT", "TDRC"}, // 2.3 -> 2.4
{"TYER", "TDRC"}, // 2.3 -> 2.4
{"TIME", "TDRC"}, // 2.3 -> 2.4
const std::pair<const char *, const char *> deprecatedFrames[] = {
std::make_pair("TRDA", "TDRC"), // 2.3 -> 2.4 (http://en.wikipedia.org/wiki/ID3)
std::make_pair("TDAT", "TDRC"), // 2.3 -> 2.4
std::make_pair("TYER", "TDRC"), // 2.3 -> 2.4
std::make_pair("TIME", "TDRC"), // 2.3 -> 2.4
};
const size_t deprecatedFramesSize = sizeof(deprecatedFrames) / sizeof(deprecatedFrames[0]);
}
} // namespace
String Frame::frameIDToKey(const ByteVector &id)
{
ByteVector id24 = id;
for(size_t i = 0; i < deprecatedFramesSize; ++i) {
if(id24 == deprecatedFrames[i][0]) {
id24 = deprecatedFrames[i][1];
if(id24 == deprecatedFrames[i].first) {
id24 = deprecatedFrames[i].second;
break;
}
}
for(size_t i = 0; i < frameTranslationSize; ++i) {
if(id24 == frameTranslation[i][0])
return frameTranslation[i][1];
if(id24 == frameTranslation[i].first)
return frameTranslation[i].second;
}
return String();
}
@@ -448,8 +444,8 @@ ByteVector Frame::keyToFrameID(const String &s)
{
const String key = s.upper();
for(size_t i = 0; i < frameTranslationSize; ++i) {
if(key == frameTranslation[i][1])
return frameTranslation[i][0];
if(key == frameTranslation[i].second)
return frameTranslation[i].first;
}
return ByteVector();
}
@@ -458,8 +454,8 @@ String Frame::txxxToKey(const String &description)
{
const String d = description.upper();
for(size_t i = 0; i < txxxFrameTranslationSize; ++i) {
if(d == txxxFrameTranslation[i][0])
return txxxFrameTranslation[i][1];
if(d == txxxFrameTranslation[i].first)
return txxxFrameTranslation[i].second;
}
return d;
}
@@ -468,8 +464,8 @@ String Frame::keyToTXXX(const String &s)
{
const String key = s.upper();
for(size_t i = 0; i < txxxFrameTranslationSize; ++i) {
if(key == txxxFrameTranslation[i][1])
return txxxFrameTranslation[i][0];
if(key == txxxFrameTranslation[i].second)
return txxxFrameTranslation[i].first;
}
return s;
}
@@ -486,19 +482,19 @@ PropertyMap Frame::asProperties() const
if(id == "TXXX")
return dynamic_cast< const UserTextIdentificationFrame* >(this)->asProperties();
// Apple proprietary WFED (Podcast URL), MVNM (Movement Name), MVIN (Movement Number), GRP1 (Grouping) are in fact text frames.
else if(id[0] == 'T' || id == "WFED" || id == "MVNM" || id == "MVIN" || id == "GRP1")
if(id[0] == 'T' || id == "WFED" || id == "MVNM" || id == "MVIN" || id == "GRP1")
return dynamic_cast< const TextIdentificationFrame* >(this)->asProperties();
else if(id == "WXXX")
if(id == "WXXX")
return dynamic_cast< const UserUrlLinkFrame* >(this)->asProperties();
else if(id[0] == 'W')
if(id[0] == 'W')
return dynamic_cast< const UrlLinkFrame* >(this)->asProperties();
else if(id == "COMM")
if(id == "COMM")
return dynamic_cast< const CommentsFrame* >(this)->asProperties();
else if(id == "USLT")
if(id == "USLT")
return dynamic_cast< const UnsynchronizedLyricsFrame* >(this)->asProperties();
else if(id == "UFID")
if(id == "UFID")
return dynamic_cast< const UniqueFileIdentifierFrame* >(this)->asProperties();
else if(id == "PCST")
if(id == "PCST")
return dynamic_cast< const PodcastFrame* >(this)->asProperties();
PropertyMap m;
m.unsupportedData().append(id);

View File

@@ -55,6 +55,8 @@ namespace TagLib {
{
friend class Tag;
friend class FrameFactory;
friend class TableOfContentsFrame;
friend class ChapterFrame;
public:
@@ -503,7 +505,7 @@ namespace TagLib {
ByteVector render() const;
/*!
* \deprecated
* \deprecated Use fileAlterPreservation().
*/
TAGLIB_DEPRECATED bool frameAlterPreservation() const;

View File

@@ -85,7 +85,7 @@ namespace
frame->setText(newfields);
}
}
} // namespace
class FrameFactory::FrameFactoryPrivate
{
@@ -268,11 +268,9 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
if(frameID != "WXXX") {
return new UrlLinkFrame(data, header);
}
else {
UserUrlLinkFrame *f = new UserUrlLinkFrame(data, header);
d->setTextEncoding(f);
return f;
}
UserUrlLinkFrame *f = new UserUrlLinkFrame(data, header);
d->setTextEncoding(f);
return f;
}
// Unsynchronized lyric/text transcription (frames 4.8)
@@ -342,19 +340,20 @@ void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const
{
TextIdentificationFrame *tdrc =
dynamic_cast<TextIdentificationFrame *>(tag->frameList("TDRC").front());
UnknownFrame *tdat = static_cast<UnknownFrame *>(tag->frameList("TDAT").front());
UnknownFrame *tdat = dynamic_cast<UnknownFrame *>(tag->frameList("TDAT").front());
if(tdrc &&
tdrc->fieldList().size() == 1 &&
tdrc->fieldList().front().size() == 4 &&
tdat &&
tdat->data().size() >= 5)
{
String date(tdat->data().mid(1), String::Type(tdat->data()[0]));
if(date.length() == 4) {
tdrc->setText(tdrc->toString() + '-' + date.substr(2, 2) + '-' + date.substr(0, 2));
if(tag->frameList("TIME").size() == 1) {
UnknownFrame *timeframe = static_cast<UnknownFrame *>(tag->frameList("TIME").front());
if(timeframe->data().size() >= 5) {
UnknownFrame *timeframe = dynamic_cast<UnknownFrame *>(tag->frameList("TIME").front());
if(timeframe && timeframe->data().size() >= 5) {
String time(timeframe->data().mid(1), String::Type(timeframe->data()[0]));
if(time.length() == 4) {
tdrc->setText(tdrc->toString() + 'T' + time.substr(0, 2) + ':' + time.substr(2, 2));
@@ -394,90 +393,90 @@ FrameFactory::~FrameFactory()
namespace
{
// Frame conversion table ID3v2.2 -> 2.4
const char *frameConversion2[][2] = {
{ "BUF", "RBUF" },
{ "CNT", "PCNT" },
{ "COM", "COMM" },
{ "CRA", "AENC" },
{ "ETC", "ETCO" },
{ "GEO", "GEOB" },
{ "IPL", "TIPL" },
{ "MCI", "MCDI" },
{ "MLL", "MLLT" },
{ "POP", "POPM" },
{ "REV", "RVRB" },
{ "SLT", "SYLT" },
{ "STC", "SYTC" },
{ "TAL", "TALB" },
{ "TBP", "TBPM" },
{ "TCM", "TCOM" },
{ "TCO", "TCON" },
{ "TCP", "TCMP" },
{ "TCR", "TCOP" },
{ "TDY", "TDLY" },
{ "TEN", "TENC" },
{ "TFT", "TFLT" },
{ "TKE", "TKEY" },
{ "TLA", "TLAN" },
{ "TLE", "TLEN" },
{ "TMT", "TMED" },
{ "TOA", "TOAL" },
{ "TOF", "TOFN" },
{ "TOL", "TOLY" },
{ "TOR", "TDOR" },
{ "TOT", "TOAL" },
{ "TP1", "TPE1" },
{ "TP2", "TPE2" },
{ "TP3", "TPE3" },
{ "TP4", "TPE4" },
{ "TPA", "TPOS" },
{ "TPB", "TPUB" },
{ "TRC", "TSRC" },
{ "TRD", "TDRC" },
{ "TRK", "TRCK" },
{ "TS2", "TSO2" },
{ "TSA", "TSOA" },
{ "TSC", "TSOC" },
{ "TSP", "TSOP" },
{ "TSS", "TSSE" },
{ "TST", "TSOT" },
{ "TT1", "TIT1" },
{ "TT2", "TIT2" },
{ "TT3", "TIT3" },
{ "TXT", "TOLY" },
{ "TXX", "TXXX" },
{ "TYE", "TDRC" },
{ "UFI", "UFID" },
{ "ULT", "USLT" },
{ "WAF", "WOAF" },
{ "WAR", "WOAR" },
{ "WAS", "WOAS" },
{ "WCM", "WCOM" },
{ "WCP", "WCOP" },
{ "WPB", "WPUB" },
{ "WXX", "WXXX" },
const std::pair<const char *, const char *> frameConversion2[] = {
std::make_pair("BUF", "RBUF"),
std::make_pair("CNT", "PCNT"),
std::make_pair("COM", "COMM"),
std::make_pair("CRA", "AENC"),
std::make_pair("ETC", "ETCO"),
std::make_pair("GEO", "GEOB"),
std::make_pair("IPL", "TIPL"),
std::make_pair("MCI", "MCDI"),
std::make_pair("MLL", "MLLT"),
std::make_pair("POP", "POPM"),
std::make_pair("REV", "RVRB"),
std::make_pair("SLT", "SYLT"),
std::make_pair("STC", "SYTC"),
std::make_pair("TAL", "TALB"),
std::make_pair("TBP", "TBPM"),
std::make_pair("TCM", "TCOM"),
std::make_pair("TCO", "TCON"),
std::make_pair("TCP", "TCMP"),
std::make_pair("TCR", "TCOP"),
std::make_pair("TDY", "TDLY"),
std::make_pair("TEN", "TENC"),
std::make_pair("TFT", "TFLT"),
std::make_pair("TKE", "TKEY"),
std::make_pair("TLA", "TLAN"),
std::make_pair("TLE", "TLEN"),
std::make_pair("TMT", "TMED"),
std::make_pair("TOA", "TOAL"),
std::make_pair("TOF", "TOFN"),
std::make_pair("TOL", "TOLY"),
std::make_pair("TOR", "TDOR"),
std::make_pair("TOT", "TOAL"),
std::make_pair("TP1", "TPE1"),
std::make_pair("TP2", "TPE2"),
std::make_pair("TP3", "TPE3"),
std::make_pair("TP4", "TPE4"),
std::make_pair("TPA", "TPOS"),
std::make_pair("TPB", "TPUB"),
std::make_pair("TRC", "TSRC"),
std::make_pair("TRD", "TDRC"),
std::make_pair("TRK", "TRCK"),
std::make_pair("TS2", "TSO2"),
std::make_pair("TSA", "TSOA"),
std::make_pair("TSC", "TSOC"),
std::make_pair("TSP", "TSOP"),
std::make_pair("TSS", "TSSE"),
std::make_pair("TST", "TSOT"),
std::make_pair("TT1", "TIT1"),
std::make_pair("TT2", "TIT2"),
std::make_pair("TT3", "TIT3"),
std::make_pair("TXT", "TOLY"),
std::make_pair("TXX", "TXXX"),
std::make_pair("TYE", "TDRC"),
std::make_pair("UFI", "UFID"),
std::make_pair("ULT", "USLT"),
std::make_pair("WAF", "WOAF"),
std::make_pair("WAR", "WOAR"),
std::make_pair("WAS", "WOAS"),
std::make_pair("WCM", "WCOM"),
std::make_pair("WCP", "WCOP"),
std::make_pair("WPB", "WPUB"),
std::make_pair("WXX", "WXXX"),
// Apple iTunes nonstandard frames
{ "PCS", "PCST" },
{ "TCT", "TCAT" },
{ "TDR", "TDRL" },
{ "TDS", "TDES" },
{ "TID", "TGID" },
{ "WFD", "WFED" },
{ "MVN", "MVNM" },
{ "MVI", "MVIN" },
{ "GP1", "GRP1" },
std::make_pair("PCS", "PCST"),
std::make_pair("TCT", "TCAT"),
std::make_pair("TDR", "TDRL"),
std::make_pair("TDS", "TDES"),
std::make_pair("TID", "TGID"),
std::make_pair("WFD", "WFED"),
std::make_pair("MVN", "MVNM"),
std::make_pair("MVI", "MVIN"),
std::make_pair("GP1", "GRP1"),
};
const size_t frameConversion2Size = sizeof(frameConversion2) / sizeof(frameConversion2[0]);
// Frame conversion table ID3v2.3 -> 2.4
const char *frameConversion3[][2] = {
{ "TORY", "TDOR" },
{ "TYER", "TDRC" },
{ "IPLS", "TIPL" },
const std::pair<const char *, const char *> frameConversion3[] = {
std::make_pair("TORY", "TDOR"),
std::make_pair("TYER", "TDRC"),
std::make_pair("IPLS", "TIPL"),
};
const size_t frameConversion3Size = sizeof(frameConversion3) / sizeof(frameConversion3[0]);
}
} // namespace
bool FrameFactory::updateFrame(Frame::Header *header) const
{
@@ -504,8 +503,8 @@ bool FrameFactory::updateFrame(Frame::Header *header) const
// the frames to their 4 byte ID3v2.4 equivalent.
for(size_t i = 0; i < frameConversion2Size; ++i) {
if(frameID == frameConversion2[i][0]) {
header->setFrameID(frameConversion2[i][1]);
if(frameID == frameConversion2[i].first) {
header->setFrameID(frameConversion2[i].second);
break;
}
}
@@ -528,8 +527,8 @@ bool FrameFactory::updateFrame(Frame::Header *header) const
}
for(size_t i = 0; i < frameConversion3Size; ++i) {
if(frameID == frameConversion3[i][0]) {
header->setFrameID(frameConversion3[i][1]);
if(frameID == frameConversion3[i].first) {
header->setFrameID(frameConversion3[i].second);
break;
}
}

View File

@@ -87,7 +87,7 @@ namespace TagLib {
TAGLIB_DEPRECATED Frame *createFrame(const ByteVector &data, unsigned int version = 4) const;
/*!
* \deprecated
* \deprecated Use createFrame(const ByteVector &, const Header *) const.
*/
// BIC: remove
Frame *createFrame(const ByteVector &data, Header *tagHeader) const;

View File

@@ -137,8 +137,7 @@ unsigned int Header::completeTagSize() const
{
if(d->footerPresent)
return d->tagSize + size() + Footer::size();
else
return d->tagSize + size();
return d->tagSize + size();
}
void Header::setTagSize(unsigned int s)

View File

@@ -74,6 +74,10 @@ ByteVector SynchData::fromUInt(unsigned int value)
ByteVector SynchData::decode(const ByteVector &data)
{
if (data.size() == 0) {
return ByteVector();
}
// We have this optimized method instead of using ByteVector::replace(),
// since it makes a great difference when decoding huge unsynchronized frames.

View File

@@ -64,7 +64,7 @@ namespace
}
return false;
}
}
} // namespace
class ID3v2::Tag::TagPrivate
{
@@ -120,14 +120,12 @@ String Latin1StringHandler::parse(const ByteVector &data) const
////////////////////////////////////////////////////////////////////////////////
ID3v2::Tag::Tag() :
TagLib::Tag(),
d(new TagPrivate())
{
d->factory = FrameFactory::instance();
}
ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) :
TagLib::Tag(),
d(new TagPrivate())
{
d->factory = factory;
@@ -187,8 +185,10 @@ String ID3v2::Tag::genre() const
// should be separated by " / " instead of " ". For the moment to keep
// the behavior the same as released versions it is being left with " ".
if(d->frameListMap["TCON"].isEmpty() ||
!dynamic_cast<TextIdentificationFrame *>(d->frameListMap["TCON"].front()))
const FrameList &tconFrames = d->frameListMap["TCON"];
TextIdentificationFrame *f;
if(tconFrames.isEmpty() ||
!(f = dynamic_cast<TextIdentificationFrame *>(tconFrames.front())))
{
return String();
}
@@ -199,9 +199,6 @@ String ID3v2::Tag::genre() const
// appended to the genre string. Multiple fields will be appended as the
// string is built.
TextIdentificationFrame *f = static_cast<TextIdentificationFrame *>(
d->frameListMap["TCON"].front());
StringList fields = f->fieldList();
StringList genres;

View File

@@ -338,7 +338,7 @@ namespace TagLib {
ByteVector render() const;
/*!
* \deprecated
* \deprecated Use render(Version) const.
*/
TAGLIB_DEPRECATED ByteVector render(int version) const;

View File

@@ -93,7 +93,7 @@ namespace
AudioProperties *audioProperties() const { return 0; }
bool save() { return false; }
};
}
} // namespace
bool MPEG::File::isSupported(IOStream *stream)
{

View File

@@ -193,19 +193,19 @@ namespace TagLib {
bool save(int tags);
/*!
* \deprecated
* \deprecated Use save(int, StripTags, ID3v2::Version, DuplicateTags).
*/
// BIC: combine with the above method
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers);
/*!
* \deprecated
* \deprecated Use save(int, StripTags, ID3v2::Version, DuplicateTags).
*/
// BIC: combine with the above method
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version);
/*!
* \deprecated
* \deprecated Use save(int, StripTags, ID3v2::Version, DuplicateTags).
*/
// BIC: combine with the above method
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags);
@@ -315,7 +315,7 @@ namespace TagLib {
* Set the ID3v2::FrameFactory to something other than the default.
*
* \see ID3v2FrameFactory
* \deprecated This value should be passed in via the constructor
* \deprecated This value should be passed in via the constructor.
*/
TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);

View File

@@ -50,7 +50,7 @@ namespace TagLib {
/*!
* Parses an MPEG header based on \a data.
*
* \deprecated
* \deprecated Use Header(File *, long, bool).
*/
TAGLIB_DEPRECATED Header(const ByteVector &data);

View File

@@ -65,7 +65,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;

View File

@@ -41,10 +41,9 @@ namespace
{
if(page->header()->lastPacketCompleted())
return page->firstPacketIndex() + page->packetCount();
else
return page->firstPacketIndex() + page->packetCount() - 1;
return page->firstPacketIndex() + page->packetCount() - 1;
}
}
} // namespace
class Ogg::File::FilePrivate
{

View File

@@ -67,7 +67,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;

View File

@@ -67,7 +67,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;

View File

@@ -73,7 +73,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;

View File

@@ -61,13 +61,11 @@ public:
////////////////////////////////////////////////////////////////////////////////
Ogg::XiphComment::XiphComment() :
TagLib::Tag(),
d(new XiphCommentPrivate())
{
}
Ogg::XiphComment::XiphComment(const ByteVector &data) :
TagLib::Tag(),
d(new XiphCommentPrivate())
{
parse(data);
@@ -80,35 +78,34 @@ Ogg::XiphComment::~XiphComment()
String Ogg::XiphComment::title() const
{
if(d->fieldListMap["TITLE"].isEmpty())
return String();
return d->fieldListMap["TITLE"].toString();
StringList value = d->fieldListMap.value("TITLE");
return value.isEmpty() ? String() : value.toString();
}
String Ogg::XiphComment::artist() const
{
if(d->fieldListMap["ARTIST"].isEmpty())
return String();
return d->fieldListMap["ARTIST"].toString();
StringList value = d->fieldListMap.value("ARTIST");
return value.isEmpty() ? String() : value.toString();
}
String Ogg::XiphComment::album() const
{
if(d->fieldListMap["ALBUM"].isEmpty())
return String();
return d->fieldListMap["ALBUM"].toString();
StringList value = d->fieldListMap.value("ALBUM");
return value.isEmpty() ? String() : value.toString();
}
String Ogg::XiphComment::comment() const
{
if(!d->fieldListMap["DESCRIPTION"].isEmpty()) {
StringList value = d->fieldListMap.value("DESCRIPTION");
if(!value.isEmpty()) {
d->commentField = "DESCRIPTION";
return d->fieldListMap["DESCRIPTION"].toString();
return value.toString();
}
if(!d->fieldListMap["COMMENT"].isEmpty()) {
value = d->fieldListMap.value("COMMENT");
if(!value.isEmpty()) {
d->commentField = "COMMENT";
return d->fieldListMap["COMMENT"].toString();
return value.toString();
}
return String();
@@ -116,26 +113,29 @@ String Ogg::XiphComment::comment() const
String Ogg::XiphComment::genre() const
{
if(d->fieldListMap["GENRE"].isEmpty())
return String();
return d->fieldListMap["GENRE"].toString();
StringList value = d->fieldListMap.value("GENRE");
return value.isEmpty() ? String() : value.toString();
}
unsigned int Ogg::XiphComment::year() const
{
if(!d->fieldListMap["DATE"].isEmpty())
return d->fieldListMap["DATE"].front().toInt();
if(!d->fieldListMap["YEAR"].isEmpty())
return d->fieldListMap["YEAR"].front().toInt();
StringList value = d->fieldListMap.value("DATE");
if(!value.isEmpty())
return value.front().toInt();
value = d->fieldListMap.value("YEAR");
if(!value.isEmpty())
return value.front().toInt();
return 0;
}
unsigned int Ogg::XiphComment::track() const
{
if(!d->fieldListMap["TRACKNUMBER"].isEmpty())
return d->fieldListMap["TRACKNUMBER"].front().toInt();
if(!d->fieldListMap["TRACKNUM"].isEmpty())
return d->fieldListMap["TRACKNUM"].front().toInt();
StringList value = d->fieldListMap.value("TRACKNUMBER");
if(!value.isEmpty())
return value.front().toInt();
value = d->fieldListMap.value("TRACKNUM");
if(!value.isEmpty())
return value.front().toInt();
return 0;
}
@@ -157,7 +157,7 @@ void Ogg::XiphComment::setAlbum(const String &s)
void Ogg::XiphComment::setComment(const String &s)
{
if(d->commentField.isEmpty()) {
if(!d->fieldListMap["DESCRIPTION"].isEmpty())
if(!d->fieldListMap.value("DESCRIPTION").isEmpty())
d->commentField = "DESCRIPTION";
else
d->commentField = "COMMENT";
@@ -324,7 +324,7 @@ void Ogg::XiphComment::removeAllFields()
bool Ogg::XiphComment::contains(const String &key) const
{
return !d->fieldListMap[key.upper()].isEmpty();
return !d->fieldListMap.value(key.upper()).isEmpty();
}
void Ogg::XiphComment::removePicture(FLAC::Picture *picture, bool del)

View File

@@ -35,6 +35,11 @@
#include "flacpicture.h"
#include "taglib_export.h"
#ifdef _MSC_VER
// Explained at end of tpropertymap.cpp
extern template class TAGLIB_EXPORT TagLib::Map<TagLib::String, TagLib::StringList>;
#endif
namespace TagLib {
namespace Ogg {

View File

@@ -50,7 +50,7 @@ namespace TagLib {
* Create an instance of AIFF::Properties with the data read from the
* ByteVector \a data.
*
* \deprecated
* \deprecated Use Properties(File *, ReadStyle).
*/
TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style);
@@ -71,7 +71,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;
@@ -117,7 +117,7 @@ namespace TagLib {
*
* \note This method is just an alias of bitsPerSample().
*
* \deprecated
* \deprecated Use bitsPerSample().
*/
TAGLIB_DEPRECATED int sampleWidth() const;

View File

@@ -71,14 +71,12 @@ ByteVector RIFF::Info::StringHandler::render(const String &s) const
////////////////////////////////////////////////////////////////////////////////
RIFF::Info::Tag::Tag(const ByteVector &data) :
TagLib::Tag(),
d(new TagPrivate())
{
parse(data);
}
RIFF::Info::Tag::Tag() :
TagLib::Tag(),
d(new TagPrivate())
{
}
@@ -178,8 +176,7 @@ String RIFF::Info::Tag::fieldText(const ByteVector &id) const
{
if(d->fieldListMap.contains(id))
return String(d->fieldListMap[id]);
else
return String();
return String();
}
void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s)
@@ -221,8 +218,7 @@ ByteVector RIFF::Info::Tag::render() const
if(data.size() == 4)
return ByteVector();
else
return data;
return data;
}
void RIFF::Info::Tag::setStringHandler(const StringHandler *handler)

View File

@@ -160,7 +160,7 @@ namespace TagLib {
virtual bool save();
/*!
* \deprecated
* \deprecated Use save(TagTypes, StripTags, ID3v2::Version).
*/
TAGLIB_DEPRECATED bool save(TagTypes tags, bool stripOthers, int id3v2Version = 4);

View File

@@ -53,7 +53,7 @@ namespace TagLib {
* Create an instance of WAV::Properties with the data read from the
* ByteVector \a data.
*
* \deprecated
* \deprecated Use Properties(File *, ReadStyle).
*/
TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style);
@@ -61,7 +61,7 @@ namespace TagLib {
* Create an instance of WAV::Properties with the data read from the
* ByteVector \a data and the length calculated using \a streamLength.
*
* \deprecated
* \deprecated Use Properties(File *, ReadStyle).
*/
TAGLIB_DEPRECATED Properties(const ByteVector &data, unsigned int streamLength, ReadStyle style);
@@ -82,7 +82,7 @@ namespace TagLib {
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
* \deprecated Use lengthInSeconds().
*/
TAGLIB_DEPRECATED virtual int length() const;
@@ -128,7 +128,7 @@ namespace TagLib {
*
* \note This method is just an alias of bitsPerSample().
*
* \deprecated
* \deprecated Use bitsPerSample().
*/
TAGLIB_DEPRECATED int sampleWidth() const;

View File

@@ -129,12 +129,12 @@ bool S3M::File::save()
StringList lines = d->tag.comment().split("\n");
// write comment as sample names:
for(unsigned short i = 0; i < sampleCount; ++ i) {
seek(96L + length + ((long)i << 1));
seek(96L + length + (static_cast<long>(i) << 1));
unsigned short instrumentOffset = 0;
if(!readU16L(instrumentOffset))
return false;
seek(((long)instrumentOffset << 4) + 48);
seek((static_cast<long>(instrumentOffset) << 4) + 48);
if(i < lines.size())
writeString(lines[i], 27);
@@ -214,10 +214,10 @@ void S3M::File::read(bool)
// instead samples (SCRS).
StringList comment;
for(unsigned short i = 0; i < sampleCount; ++ i) {
seek(96L + length + ((long)i << 1));
seek(96L + length + (static_cast<long>(i) << 1));
READ_U16L_AS(sampleHeaderOffset);
seek((long)sampleHeaderOffset << 4);
seek(static_cast<long>(sampleHeaderOffset) << 4);
READ_BYTE_AS(sampleType);
READ_STRING_AS(dosFileName, 13);

View File

@@ -120,16 +120,16 @@ PropertyMap TagUnion::properties() const
if(dynamic_cast<const ID3v1::Tag *>(d->tags[i]))
return dynamic_cast<const ID3v1::Tag *>(d->tags[i])->properties();
else if(dynamic_cast<const ID3v2::Tag *>(d->tags[i]))
if(dynamic_cast<const ID3v2::Tag *>(d->tags[i]))
return dynamic_cast<const ID3v2::Tag *>(d->tags[i])->properties();
else if(dynamic_cast<const APE::Tag *>(d->tags[i]))
if(dynamic_cast<const APE::Tag *>(d->tags[i]))
return dynamic_cast<const APE::Tag *>(d->tags[i])->properties();
else if(dynamic_cast<const Ogg::XiphComment *>(d->tags[i]))
if(dynamic_cast<const Ogg::XiphComment *>(d->tags[i]))
return dynamic_cast<const Ogg::XiphComment *>(d->tags[i])->properties();
else if(dynamic_cast<const RIFF::Info::Tag *>(d->tags[i]))
if(dynamic_cast<const RIFF::Info::Tag *>(d->tags[i]))
return dynamic_cast<const RIFF::Info::Tag *>(d->tags[i])->properties();
}
}

View File

@@ -38,11 +38,22 @@ long Utils::findID3v1(File *file)
if(!file->isValid())
return -1;
file->seek(-128, File::End);
const long p = file->tell();
// Differentiate between a match of APEv2 magic and a match of ID3v1 magic.
if(file->readBlock(3) == ID3v1::Tag::fileIdentifier())
return p;
if (file->length() >= 131) {
file->seek(-131, File::End);
const long p = file->tell() + 3;
const TagLib::ByteVector data = file->readBlock(8);
if(data.containsAt(ID3v1::Tag::fileIdentifier(), 3) && (data != APE::Tag::fileIdentifier()))
return p;
} else {
file->seek(-128, File::End);
const long p = file->tell();
if(file->readBlock(3) == ID3v1::Tag::fileIdentifier())
return p;
}
return -1;
}

View File

@@ -29,7 +29,7 @@
#include "taglib_config.h"
#define TAGLIB_MAJOR_VERSION 1
#define TAGLIB_MINOR_VERSION 12
#define TAGLIB_MINOR_VERSION 13
#define TAGLIB_PATCH_VERSION 0
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) || defined(__clang__)

View File

@@ -145,8 +145,7 @@ T toNumber(const ByteVector &v, size_t offset, bool mostSignificantByteFirst)
if(swap)
return Utils::byteSwap(tmp);
else
return tmp;
return tmp;
}
template <class T>
@@ -242,14 +241,12 @@ long double toFloat80(const ByteVector &v, size_t offset)
debug("toFloat80() - can't handle the infinity or NaN. Returning 0.");
return 0.0;
}
else
val = ::ldexp(static_cast<long double>(fraction), exponent - 16383 - 63);
val = ::ldexp(static_cast<long double>(fraction), exponent - 16383 - 63);
}
if(negative)
return -val;
else
return val;
return val;
}
class ByteVector::ByteVectorPrivate
@@ -300,8 +297,7 @@ ByteVector ByteVector::fromCString(const char *s, unsigned int length)
{
if(length == 0xffffffff)
return ByteVector(s, static_cast<unsigned int>(::strlen(s)));
else
return ByteVector(s, length);
return ByteVector(s, length);
}
ByteVector ByteVector::fromUInt(unsigned int value, bool mostSignificantByteFirst)
@@ -443,8 +439,7 @@ int ByteVector::rfind(const ByteVector &pattern, unsigned int offset, int byteAl
if(pos == -1)
return -1;
else
return size() - pos - pattern.size();
return size() - pos - pattern.size();
}
bool ByteVector::containsAt(const ByteVector &pattern, unsigned int offset, unsigned int patternOffset, unsigned int patternLength) const
@@ -843,8 +838,7 @@ bool ByteVector::operator<(const ByteVector &v) const
const int result = ::memcmp(data(), v.data(), std::min(size(), v.size()));
if(result != 0)
return result < 0;
else
return size() < v.size();
return size() < v.size();
}
bool ByteVector::operator>(const ByteVector &v) const
@@ -925,8 +919,8 @@ ByteVector ByteVector::fromBase64(const ByteVector & input)
ByteVector output(len);
const unsigned char * src = (const unsigned char*) input.data();
unsigned char * dst = (unsigned char*) output.data();
const unsigned char * src = reinterpret_cast<const unsigned char*>(input.data());
unsigned char * dst = reinterpret_cast<unsigned char*>(output.data());
while(4 <= len) {
@@ -976,7 +970,7 @@ ByteVector ByteVector::fromBase64(const ByteVector & input)
// Only return output if we processed all bytes
if(len == 0) {
output.resize(static_cast<unsigned int>(dst - (unsigned char*) output.data()));
output.resize(static_cast<unsigned int>(dst - reinterpret_cast<unsigned char*>(output.data())));
return output;
}
return ByteVector();
@@ -1030,7 +1024,7 @@ void ByteVector::detach()
ByteVector().swap(*this);
}
}
}
} // namespace TagLib
////////////////////////////////////////////////////////////////////////////////
// related functions

View File

@@ -278,7 +278,7 @@ namespace TagLib {
*
* \see isEmpty()
*
* \deprecated
* \deprecated Use isEmpty(), do not differentiate between null and empty.
*/
// BIC: remove
TAGLIB_DEPRECATED bool isNull() const;
@@ -592,7 +592,7 @@ namespace TagLib {
* \warning Do not modify this variable. It will mess up the internal state
* of TagLib.
*
* \deprecated
* \deprecated Use ByteVector().
*/
// BIC: remove
TAGLIB_DEPRECATED static ByteVector null;

View File

@@ -70,7 +70,7 @@ ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &patt
// public members
////////////////////////////////////////////////////////////////////////////////
ByteVectorList::ByteVectorList() : List<ByteVector>()
ByteVectorList::ByteVectorList()
{
}

View File

@@ -59,6 +59,6 @@ namespace TagLib
debugListener->printMessage(msg);
}
}
}
} // namespace TagLib
#endif

View File

@@ -61,7 +61,7 @@ namespace
};
DefaultListener defaultListener;
}
} // namespace
namespace TagLib
{
@@ -82,4 +82,4 @@ namespace TagLib
else
debugListener = &defaultListener;
}
}
} // namespace TagLib

View File

@@ -185,42 +185,41 @@ PropertyMap File::setProperties(const PropertyMap &properties)
{
if(dynamic_cast<APE::File* >(this))
return dynamic_cast<APE::File* >(this)->setProperties(properties);
else if(dynamic_cast<FLAC::File* >(this))
if(dynamic_cast<FLAC::File* >(this))
return dynamic_cast<FLAC::File* >(this)->setProperties(properties);
else if(dynamic_cast<IT::File* >(this))
if(dynamic_cast<IT::File* >(this))
return dynamic_cast<IT::File* >(this)->setProperties(properties);
else if(dynamic_cast<Mod::File* >(this))
if(dynamic_cast<Mod::File* >(this))
return dynamic_cast<Mod::File* >(this)->setProperties(properties);
else if(dynamic_cast<MPC::File* >(this))
if(dynamic_cast<MPC::File* >(this))
return dynamic_cast<MPC::File* >(this)->setProperties(properties);
else if(dynamic_cast<MPEG::File* >(this))
if(dynamic_cast<MPEG::File* >(this))
return dynamic_cast<MPEG::File* >(this)->setProperties(properties);
else if(dynamic_cast<Ogg::FLAC::File* >(this))
if(dynamic_cast<Ogg::FLAC::File* >(this))
return dynamic_cast<Ogg::FLAC::File* >(this)->setProperties(properties);
else if(dynamic_cast<Ogg::Speex::File* >(this))
if(dynamic_cast<Ogg::Speex::File* >(this))
return dynamic_cast<Ogg::Speex::File* >(this)->setProperties(properties);
else if(dynamic_cast<Ogg::Opus::File* >(this))
if(dynamic_cast<Ogg::Opus::File* >(this))
return dynamic_cast<Ogg::Opus::File* >(this)->setProperties(properties);
else if(dynamic_cast<Ogg::Vorbis::File* >(this))
if(dynamic_cast<Ogg::Vorbis::File* >(this))
return dynamic_cast<Ogg::Vorbis::File* >(this)->setProperties(properties);
else if(dynamic_cast<RIFF::AIFF::File* >(this))
if(dynamic_cast<RIFF::AIFF::File* >(this))
return dynamic_cast<RIFF::AIFF::File* >(this)->setProperties(properties);
else if(dynamic_cast<RIFF::WAV::File* >(this))
if(dynamic_cast<RIFF::WAV::File* >(this))
return dynamic_cast<RIFF::WAV::File* >(this)->setProperties(properties);
else if(dynamic_cast<S3M::File* >(this))
if(dynamic_cast<S3M::File* >(this))
return dynamic_cast<S3M::File* >(this)->setProperties(properties);
else if(dynamic_cast<TrueAudio::File* >(this))
if(dynamic_cast<TrueAudio::File* >(this))
return dynamic_cast<TrueAudio::File* >(this)->setProperties(properties);
else if(dynamic_cast<WavPack::File* >(this))
if(dynamic_cast<WavPack::File* >(this))
return dynamic_cast<WavPack::File* >(this)->setProperties(properties);
else if(dynamic_cast<XM::File* >(this))
if(dynamic_cast<XM::File* >(this))
return dynamic_cast<XM::File* >(this)->setProperties(properties);
else if(dynamic_cast<MP4::File* >(this))
if(dynamic_cast<MP4::File* >(this))
return dynamic_cast<MP4::File* >(this)->setProperties(properties);
else if(dynamic_cast<ASF::File* >(this))
if(dynamic_cast<ASF::File* >(this))
return dynamic_cast<ASF::File* >(this)->setProperties(properties);
else
return tag()->setProperties(properties);
return tag()->setProperties(properties);
}
ByteVector File::readBlock(unsigned long length)

View File

@@ -261,14 +261,14 @@ namespace TagLib {
* Returns true if \a file can be opened for reading. If the file does not
* exist, this will return false.
*
* \deprecated
* \deprecated Use system functions, e.g. access() (_access_s() on Windows).
*/
TAGLIB_DEPRECATED static bool isReadable(const char *file);
/*!
* Returns true if \a file can be opened for writing.
*
* \deprecated
* \deprecated Use system functions, e.g. access() (_access_s() on Windows).
*/
TAGLIB_DEPRECATED static bool isWritable(const char *name);

View File

@@ -124,7 +124,7 @@ namespace
}
#endif // _WIN32
}
} // namespace
class FileStream::FileStreamPrivate
{
@@ -206,9 +206,12 @@ ByteVector FileStream::readBlock(unsigned long length)
if(length == 0)
return ByteVector();
const unsigned long streamLength = static_cast<unsigned long>(FileStream::length());
if(length > bufferSize() && length > streamLength)
length = streamLength;
if(length > bufferSize()) {
const unsigned long streamLength = static_cast<unsigned long>(FileStream::length());
if(length > streamLength) {
length = streamLength;
}
}
ByteVector buffer(static_cast<unsigned int>(length));
@@ -250,7 +253,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
writeBlock(data);
return;
}
else if(data.size() < replace) {
if(data.size() < replace) {
seek(start);
writeBlock(data);
removeBlock(start + data.size(), replace - data.size());

View File

@@ -153,6 +153,14 @@ namespace TagLib {
*/
Map<Key, T> &erase(const Key &key);
/*!
* Returns the value associated with \a key.
*
* If the map does not contain \a key, it returns defaultValue.
* If no defaultValue is specified, it returns a default-constructed value.
*/
const T value(const Key &key, const T &defaultValue = T()) const;
/*!
* Returns a reference to the value associated with \a key.
*

View File

@@ -155,6 +155,13 @@ unsigned int Map<Key, T>::size() const
return static_cast<unsigned int>(d->map.size());
}
template <class Key, class T>
const T Map<Key, T>::value(const Key &key, const T &defaultValue) const
{
ConstIterator it = d->map.find(key);
return it != d->map.end() ? it->second : defaultValue;
}
template <class Key, class T>
const T &Map<Key, T>::operator[](const Key &key) const
{

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