mirror of
https://github.com/taglib/taglib.git
synced 2026-06-13 09:49:18 -04:00
Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de6e2b15c8 | ||
|
|
b7f0225f0d | ||
|
|
f4117f873c | ||
|
|
cf86f20b36 | ||
|
|
74d93db166 | ||
|
|
397b6c1de3 | ||
|
|
51f431c96a | ||
|
|
11e3eb05bd | ||
|
|
2c01b63433 | ||
|
|
d83d751443 | ||
|
|
f4e7a742c3 | ||
|
|
68a514f4a0 | ||
|
|
607cd5bdf4 | ||
|
|
b625be5690 | ||
|
|
d2bf7e72d2 | ||
|
|
280d6306d2 | ||
|
|
aef78068b3 | ||
|
|
81815e1091 | ||
|
|
b9122afaca | ||
|
|
1d3a375765 | ||
|
|
241b3b2921 | ||
|
|
48104959b2 | ||
|
|
c817cc0a47 | ||
|
|
7a5a10102e | ||
|
|
d47d28f0f8 | ||
|
|
3566b00596 | ||
|
|
98bc68d16e | ||
|
|
8d02484804 | ||
|
|
cfade6d082 | ||
|
|
f7ab162514 | ||
|
|
5a6f1f96f8 | ||
|
|
6fa3db1e51 | ||
|
|
4546c00417 | ||
|
|
f94843614f | ||
|
|
975eaac3ca | ||
|
|
6d019a894c | ||
|
|
6342f00e8b | ||
|
|
b4e79a4a27 | ||
|
|
80837485cf | ||
|
|
47e9b9a17c | ||
|
|
8c7d3368da | ||
|
|
b4a4b42254 | ||
|
|
70c6a0c75f | ||
|
|
c67e434939 | ||
|
|
5d44f3eeac | ||
|
|
9c042984d2 | ||
|
|
49be371caa | ||
|
|
cbb3de6836 | ||
|
|
11efd2dd10 | ||
|
|
ab31d11c8d | ||
|
|
3c917caf52 | ||
|
|
fa96a6458e | ||
|
|
e831f0929f | ||
|
|
7d86716194 | ||
|
|
eb749ac55b | ||
|
|
148cc9a921 | ||
|
|
88d6b18b4f | ||
|
|
d61a333f27 | ||
|
|
e73517d058 | ||
|
|
6563ceaafa | ||
|
|
c57431e903 | ||
|
|
42dcfec86b | ||
|
|
d48f02030d | ||
|
|
3ccc390155 | ||
|
|
fbbead3efd | ||
|
|
ee1931b811 | ||
|
|
648f5e5882 | ||
|
|
c1c60ebeea | ||
|
|
3bc0ea0ecb | ||
|
|
225c73e181 | ||
|
|
90f62a3c94 | ||
|
|
5b6f9ef848 | ||
|
|
e3de03501f | ||
|
|
1bd0d711ca | ||
|
|
7c85fcaa81 | ||
|
|
cbe54d2f40 | ||
|
|
c4ed590032 | ||
|
|
f3fb4d83a4 | ||
|
|
3d4428726e | ||
|
|
ebf4c5bbb1 | ||
|
|
20cec27ac0 | ||
|
|
99bc87ccff | ||
|
|
7951f572b5 | ||
|
|
59ff35772e | ||
|
|
3784628155 | ||
|
|
e60df53152 | ||
|
|
1ae8e18db5 | ||
|
|
0896fb9092 | ||
|
|
920d97606b | ||
|
|
0d2c31b102 | ||
|
|
c8c4e5faec | ||
|
|
0ebb14b855 | ||
|
|
89af92333c | ||
|
|
b356fabe12 | ||
|
|
8a65068f3b | ||
|
|
e1ac724cfe | ||
|
|
a08acdcf23 | ||
|
|
1799b98c17 | ||
|
|
e49390c7c5 | ||
|
|
7bcfb96098 | ||
|
|
580b0b0c82 | ||
|
|
5fc3e5c192 | ||
|
|
570b40bdcd | ||
|
|
c3d73a26ff | ||
|
|
790815bcf4 | ||
|
|
1a5c417558 | ||
|
|
d87b2dad48 | ||
|
|
613355665c | ||
|
|
dfe2aa5253 | ||
|
|
5d921c6325 | ||
|
|
710522e6e1 | ||
|
|
6b17aa3694 | ||
|
|
b4f77a4d52 | ||
|
|
c907d8b273 | ||
|
|
98175168f3 | ||
|
|
73aff544b3 | ||
|
|
9cbb6615d5 | ||
|
|
8b7b48cc9b | ||
|
|
be8d71dad8 | ||
|
|
6abbe579a2 | ||
|
|
208fc93aaa | ||
|
|
769feafbe0 | ||
|
|
dfef09f134 | ||
|
|
3a003c1229 | ||
|
|
8b9a260d18 | ||
|
|
c2eb6b59b5 | ||
|
|
99ba7635be | ||
|
|
82b5ded8ee | ||
|
|
0318201fbd | ||
|
|
6c1ba88eab | ||
|
|
fb0f7dfa57 | ||
|
|
c5d798a50d | ||
|
|
ef013b76db | ||
|
|
a6dbc70644 | ||
|
|
9a026976ae |
37
.github/workflows/build.yml
vendored
37
.github/workflows/build.yml
vendored
@@ -9,14 +9,18 @@ jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest, windows-2025]
|
||||
include:
|
||||
- os: windows-latest
|
||||
cmake_extra_args: '-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake"'
|
||||
- os: windows-2025
|
||||
cmake_extra_args: '-G "MinGW Makefiles" -DCPPUNIT_INCLUDE_DIR="$env:GITHUB_WORKSPACE/pkg/usr/local/include" -DCPPUNIT_LIBRARIES="$($env:GITHUB_WORKSPACE -replace "\\", "/")/pkg/usr/local/lib/libcppunit.dll.a" -DCPPUNIT_INSTALLED_VERSION="1.15.1"'
|
||||
# The windows-2025 runner is used for MinGW.
|
||||
name: ${{ matrix.os == 'windows-2025' && 'mingw' || matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Ubuntu
|
||||
run: sudo apt install -y libcppunit-dev libutfcpp-dev zlib1g-dev
|
||||
@@ -32,6 +36,24 @@ jobs:
|
||||
run: vcpkg install cppunit utfcpp zlib --triplet x64-windows
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
||||
- name: Set up MinGW
|
||||
shell: bash
|
||||
run: |
|
||||
# Fetch utf8cpp, build cppunit
|
||||
git submodule update --init
|
||||
# Fails with fatal error: cppunit/config-auto.h: No such file or directory
|
||||
# vcpkg install cppunit utfcpp zlib --triplet x64-mingw-dynamic
|
||||
# Probably not working with CMake and MinGW, so we have to build it ourselves.
|
||||
curl -sL "https://dev-www.libreoffice.org/src/cppunit-1.15.1.tar.gz" | tar xz
|
||||
mkdir -p build_cppunit
|
||||
(cd build_cppunit && MAKE=mingw32-make ../cppunit-1.15.1/configure \
|
||||
--enable-shared=yes --enable-static=no \
|
||||
--disable-dependency-tracking --disable-doxygen)
|
||||
find build_cppunit -name Makefile -exec sed -i 's/\($[({]SHELL[)}]\)/"\1"/' {} \;
|
||||
sed -i 's/^\(SUBDIRS.*\) examples\(.*\)$/\1\2/' build_cppunit/Makefile
|
||||
(cd build_cppunit && mingw32-make -j$(nproc) install DESTDIR=$(cd .. && pwd)/pkg)
|
||||
if: matrix.os == 'windows-2025'
|
||||
|
||||
- name: Configure
|
||||
run: >
|
||||
cmake -B${{github.workspace}}/build
|
||||
@@ -41,12 +63,12 @@ jobs:
|
||||
${{ matrix.cmake_extra_args }}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: ctest -C ${{env.BUILD_TYPE}} -V --no-tests=error
|
||||
if: matrix.os != 'windows-latest'
|
||||
if: matrix.os != 'windows-latest' && matrix.os != 'windows-2025'
|
||||
|
||||
- name: Test Windows
|
||||
working-directory: ${{github.workspace}}/build
|
||||
@@ -57,3 +79,10 @@ jobs:
|
||||
$env:Path += ";$env:VCPKG_INSTALLATION_ROOT\packages\zlib_x64-windows\bin"
|
||||
ctest -C ${{env.BUILD_TYPE}} -V --no-tests=error
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
||||
- name: Test MinGW
|
||||
working-directory: ${{github.workspace}}/build
|
||||
run: |
|
||||
$env:Path += ";$PWD/taglib;$PWD/bindings/c;${{github.workspace}}/pkg/usr/local/bin"
|
||||
ctest -C ${{env.BUILD_TYPE}} -V --no-tests=error
|
||||
if: matrix.os == 'windows-2025'
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,7 +22,6 @@ CMakeLists.txt.user*
|
||||
/tests/test_runner
|
||||
/tests/Testing
|
||||
/taglib/libtag.a
|
||||
/taglib_config.h
|
||||
/taglib-config
|
||||
/bindings/c/libtag_c.a
|
||||
/bindings/c/taglib_c.pc
|
||||
|
||||
68
CHANGELOG.md
68
CHANGELOG.md
@@ -1,8 +1,63 @@
|
||||
TagLib 2.2 (Feb 18, 2026)
|
||||
=========================
|
||||
|
||||
* Support for Matroska (MKA, MKV) and WebM files.
|
||||
* Support for NI STEM in MP4 files.
|
||||
* New method isDsd() in WavPack Properties.
|
||||
* Stricter verification of ID3v2 frames.
|
||||
* Fix setting the last header flag in Ogg FLAC files.
|
||||
* Fix reading of the last page in Ogg streams.
|
||||
* Avoid corrupting invalid Ogg FLAC files without Vorbis comment.
|
||||
* Windows: Support MP4 files with 64-bit atoms.
|
||||
* Fix use of property keys with non-ASCII characters in C bindings.
|
||||
* Fix building with Android NDK 29.
|
||||
|
||||
TagLib 2.1.1 (June 30, 2025)
|
||||
============================
|
||||
|
||||
* Map ID3v2.3 IPLS frames to both ID3v2.4 TIPL and TMCL to have a consistent
|
||||
behavior when using MusicBrainz tags with the property map interface.
|
||||
* Fix missing include for `wchar_t` when using C bindings with MinGW.
|
||||
|
||||
TagLib 2.1 (May 31, 2025)
|
||||
=========================
|
||||
|
||||
* Support for Shorten (SHN) files.
|
||||
* Compile time configuration of supported formats: WITH_APE, WITH_ASF, ...
|
||||
* Compile time configuration of data and temporary directories for unit tests:
|
||||
TESTS_DIR and TESTS_TMPDIR.
|
||||
* C bindings: Added taglib_file_new_wchar() and taglib_file_new_type_wchar().
|
||||
* Preserve unicode encoding when downgrading to ID3v2.3.
|
||||
* Do not store FLAC metadata blocks which are too large.
|
||||
* Fix segfaults with String and ByteVector nullptr arguments.
|
||||
|
||||
TagLib 2.0.2 (Aug 24, 2024)
|
||||
===========================
|
||||
|
||||
* Fix parsing of ID3v2.2 frames.
|
||||
* Tolerate MP4 files with unknown atom types as generated by Android tools.
|
||||
* Support setting properties with arbitrary names in MP4 tags.
|
||||
* Windows: Fix "-p" option in tagwriter example.
|
||||
* Support building with older utfcpp versions.
|
||||
|
||||
TagLib 2.0.1 (Apr 9, 2024)
|
||||
==========================
|
||||
|
||||
* Fix aborting when _GLIBCXX_ASSERTIONS are enabled.
|
||||
* Fall back to utf8cpp header detection in the case that its CMake
|
||||
configuration is removed.
|
||||
* Improve compatibility with the SWIG interface compiler.
|
||||
* Build system fixes for testing without bindings, Emscripten and Illumos.
|
||||
* C bindings: Fix setting UTF-8 encoded property values.
|
||||
* Windows: Fix opening long paths.
|
||||
|
||||
TagLib 2.0 (Jan 24, 2024)
|
||||
=========================
|
||||
|
||||
* New major version, binary incompatible, but source-compatible with the
|
||||
latest 1.x release if no deprecated features are used.
|
||||
* New major version, binary incompatible, but mostly source-compatible
|
||||
with the latest 1.x release if no deprecated features are used.
|
||||
Simple applications should build without changes, more complex
|
||||
applications (e.g. extending classes of TagLib) will have to be adapted.
|
||||
* Requires a C++17 compiler and uses features of C++17.
|
||||
* Major code cleanup, fixed warnings issued by compilers and static analyzers.
|
||||
* Made methods virtual which should have been virtual but could not be
|
||||
@@ -74,6 +129,15 @@ TagLib 2.0 (Jan 24, 2024)
|
||||
- String::null
|
||||
- TrueAudio::File::setID3v2FrameFactory(): Use constructor
|
||||
- WavPack::Properties::Properties(const ByteVector &, long, ReadStyle)
|
||||
* Made methods const: Frame::Header::size(), Frame::headerSize(),
|
||||
MP4::Atom::findall(), MP4::Atoms::find(), MP4::Atoms::path().
|
||||
* Made classes non-virtual: APE::Footer, APE::Item, ASF::Attribute,
|
||||
ASF::Picture, MP4::CoverArt, MP4::Item, ID3v2::ExtendedHeader, ID3v2::Footer,
|
||||
ID3v2::Header, MPEG::Header, MPEG::XingHeader, Ogg::Page, Ogg::PageHeader.
|
||||
* Removed type definitions in TagLib namespace: wchar, uchar, ushort, uint,
|
||||
ulong, ulonglong, wstring: Use the standard types.
|
||||
* Removed include file taglib_config.h and its defines TAGLIB_WITH_ASF,
|
||||
TAGLIB_WITH_MP4: They were always 1 since version 1.8.
|
||||
* Behavioral changes:
|
||||
- The basic tag methods (e.g. genre()) separate multiple values with " / "
|
||||
instead of " ".
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.5.0 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 3.10...3.31)
|
||||
|
||||
project(taglib)
|
||||
|
||||
@@ -12,16 +12,13 @@ include(CMakePackageConfigHelpers)
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
||||
if(APPLE)
|
||||
option(BUILD_FRAMEWORK "Build an OS X framework" OFF)
|
||||
option(BUILD_FRAMEWORK "Build a macOS framework" OFF)
|
||||
if(BUILD_FRAMEWORK)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
#set(CMAKE_MACOSX_RPATH 1)
|
||||
set(FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
add_definitions(-DTAGLIB_STATIC)
|
||||
endif()
|
||||
option(ENABLE_STATIC_RUNTIME "Visual Studio, link with runtime statically" OFF)
|
||||
|
||||
option(ENABLE_CCACHE "Use ccache when building libtag" OFF)
|
||||
@@ -48,7 +45,10 @@ set(TAGLIB_INSTALL_SUFFIX "" CACHE STRING
|
||||
"Suffix added to installed files (include directory, libraries, .pc)")
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
set(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
|
||||
set(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/" CACHE STRING
|
||||
"Tests directory, is path to unit test data when 'data' is appended")
|
||||
set(TESTS_TMPDIR "" CACHE STRING
|
||||
"Directory for temporary files created during unit tests, system tmpdir is used if undefined")
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
@@ -92,11 +92,22 @@ endif()
|
||||
# Minor version: increase it if you add ABI compatible features.
|
||||
# Patch version: increase it for bug fix releases.
|
||||
set(TAGLIB_SOVERSION_MAJOR 2)
|
||||
set(TAGLIB_SOVERSION_MINOR 0)
|
||||
set(TAGLIB_SOVERSION_MINOR 2)
|
||||
set(TAGLIB_SOVERSION_PATCH 0)
|
||||
|
||||
include(ConfigureChecks.cmake)
|
||||
|
||||
option(WITH_APE "Build with APE, MPC, WavPack" ON)
|
||||
option(WITH_ASF "Build with ASF" ON)
|
||||
option(WITH_DSF "Build with DSF" ON)
|
||||
option(WITH_MATROSKA "Build with Matroska" ON)
|
||||
option(WITH_MOD "Build with Tracker modules" ON)
|
||||
option(WITH_MP4 "Build with MP4" ON)
|
||||
option(WITH_RIFF "Build with AIFF, RIFF, WAV" ON)
|
||||
option(WITH_SHORTEN "Build with Shorten" ON)
|
||||
option(WITH_TRUEAUDIO "Build with TrueAudio" ON)
|
||||
option(WITH_VORBIS "Build with Vorbis, FLAC, Ogg, Opus" ON)
|
||||
|
||||
# Determine whether zlib is installed.
|
||||
option(WITH_ZLIB "Build with ZLIB" ON)
|
||||
|
||||
@@ -148,23 +159,69 @@ if(TRACE_IN_RELEASE)
|
||||
set(TRACE_IN_RELEASE TRUE)
|
||||
endif()
|
||||
|
||||
configure_file(taglib/taglib_config.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/taglib_config.h")
|
||||
|
||||
find_package(utf8cpp QUIET)
|
||||
if(NOT utf8cpp_FOUND)
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/utfcpp/CMakeLists.txt)
|
||||
add_subdirectory("3rdparty/utfcpp")
|
||||
message(STATUS "Using utfcpp from ${utf8cpp_SOURCE_DIR}")
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"utfcpp not found. Either install package (probably utfcpp, utf8cpp, or libutfcpp-dev) "
|
||||
"or fetch the git submodule using\n"
|
||||
"git submodule update --init")
|
||||
endif()
|
||||
else()
|
||||
if(utf8cpp_FOUND)
|
||||
message(STATUS "Using utfcpp ${utf8cpp_VERSION} from ${utf8cpp_CONFIG}")
|
||||
else()
|
||||
find_path(utf8cpp_INCLUDE_DIR NAMES utf8.h PATH_SUFFIXES utf8cpp
|
||||
DOC "utf8cpp include directory")
|
||||
mark_as_advanced(utf8cpp_INCLUDE_DIR)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(utf8cpp REQUIRED_VARS utf8cpp_INCLUDE_DIR)
|
||||
if(utf8cpp_FOUND)
|
||||
set(utf8cpp_INCLUDE_DIRS "${utf8cpp_INCLUDE_DIR}")
|
||||
if(NOT TARGET utf8::cpp)
|
||||
add_library(utf8::cpp INTERFACE IMPORTED)
|
||||
set_target_properties(utf8::cpp PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${utf8cpp_INCLUDE_DIR}")
|
||||
endif()
|
||||
message(STATUS "Using utfcpp from ${utf8cpp_INCLUDE_DIR}")
|
||||
else()
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/utfcpp/CMakeLists.txt)
|
||||
add_subdirectory("3rdparty/utfcpp")
|
||||
message(STATUS "Using utfcpp from ${utf8cpp_SOURCE_DIR}")
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"utfcpp not found. Either install package (probably utfcpp, utf8cpp, or libutfcpp-dev) "
|
||||
"or fetch the git submodule using\n"
|
||||
"git submodule update --init")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_APE)
|
||||
set(TAGLIB_WITH_APE TRUE)
|
||||
endif()
|
||||
if(WITH_ASF)
|
||||
set(TAGLIB_WITH_ASF TRUE)
|
||||
endif()
|
||||
if(WITH_DSF)
|
||||
set(TAGLIB_WITH_DSF TRUE)
|
||||
endif()
|
||||
if(WITH_MATROSKA)
|
||||
set(TAGLIB_WITH_MATROSKA TRUE)
|
||||
endif()
|
||||
if(WITH_MOD)
|
||||
set(TAGLIB_WITH_MOD TRUE)
|
||||
endif()
|
||||
if(WITH_MP4)
|
||||
set(TAGLIB_WITH_MP4 TRUE)
|
||||
endif()
|
||||
if(WITH_RIFF)
|
||||
set(TAGLIB_WITH_RIFF TRUE)
|
||||
endif()
|
||||
if(WITH_SHORTEN)
|
||||
set(TAGLIB_WITH_SHORTEN TRUE)
|
||||
endif()
|
||||
if(WITH_TRUEAUDIO)
|
||||
set(TAGLIB_WITH_TRUEAUDIO TRUE)
|
||||
endif()
|
||||
if(WITH_VORBIS)
|
||||
set(TAGLIB_WITH_VORBIS TRUE)
|
||||
endif()
|
||||
|
||||
configure_file(taglib/taglib_config.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/taglib_config.h")
|
||||
|
||||
add_subdirectory(taglib)
|
||||
|
||||
if(BUILD_BINDINGS)
|
||||
|
||||
@@ -20,7 +20,7 @@ if(NOT ${SIZEOF_LONGLONG} EQUAL 8)
|
||||
endif()
|
||||
|
||||
check_type_size("wchar_t" SIZEOF_WCHAR_T)
|
||||
if(${SIZEOF_WCHAR_T} LESS 2)
|
||||
if(NOT ${SIZEOF_WCHAR_T} GREATER 1)
|
||||
message(FATAL_ERROR "TagLib requires that wchar_t is sufficient to store a UTF-16 char.")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ OUTPUT_DIRECTORY = doc
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
OUTPUT_TEXT_DIRECTION = None
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
@@ -239,7 +238,6 @@ PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
LATEX_EMOJI_DIRECTORY =
|
||||
@@ -252,7 +250,6 @@ COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -273,7 +270,6 @@ XML_NS_MEMB_FILE_SCOPE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -309,7 +305,6 @@ EXTERNAL_PAGES = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
|
||||
81
INSTALL.md
81
INSTALL.md
@@ -27,7 +27,7 @@ These are the most important build options. For details, have a look into the
|
||||
CMakeLists.txt file.
|
||||
|
||||
| Option | Description |
|
||||
| ----------------------- | -------------------------------------------------- |
|
||||
|-------------------------|----------------------------------------------------|
|
||||
| `BUILD_SHARED_LIBS` | Build shared libraries |
|
||||
| `CMAKE_BUILD_TYPE` | Debug, Release, RelWithDebInfo, MinSizeRel |
|
||||
| `BUILD_EXAMPLES` | Build examples |
|
||||
@@ -42,6 +42,9 @@ CMakeLists.txt file.
|
||||
| `TAGLIB_INSTALL_SUFFIX` | Suffix added to installed libraries, includes, ... |
|
||||
| `ENABLE_STATIC_RUNTIME` | Link with MSVC runtime statically |
|
||||
| `BUILD_FRAMEWORK` | Build a macOS framework |
|
||||
| `TESTS_DIR` | Where to find unit test data (with data appended) |
|
||||
| `TESTS_TMPDIR` | Where to create temporary files in unit tests |
|
||||
|
||||
|
||||
If you want to install TagLib 2 alongside TagLib 1, you can use
|
||||
`-DTAGLIB_INSTALL_SUFFIX=-2` and make sure that `BUILD_EXAMPLES` is not `ON`
|
||||
@@ -49,6 +52,31 @@ for both versions. The installed files will then include bin/taglib-2-config,
|
||||
include/taglib-2, cmake/taglib-2, pkgconfig/taglib-2.pc,
|
||||
pkgconfig/taglib_c-2.pc and the libraries have a suffix "-2".
|
||||
|
||||
### Compile Time Configuration of Supported Formats
|
||||
|
||||
To reduce the size of the library, it is possible to switch off supported file
|
||||
formats. By default, all formats are enabled. Support for MPEG files (MP3, AAC)
|
||||
and ID3 tags cannot be disabled. The following CMake options are available:
|
||||
|
||||
| Option | Description |
|
||||
|-------------------------|----------------------------------------------------|
|
||||
| `WITH_APE` | Build with APE, MPC, WavPack (default ON) |
|
||||
| `WITH_ASF` | Build with ASF (default ON) |
|
||||
| `WITH_DSF` | Build with DSF (default ON) |
|
||||
| `WITH_MATROSKA` | Build with Matroska, WebM (default ON) |
|
||||
| `WITH_MOD` | Build with Tracker modules (default ON) |
|
||||
| `WITH_MP4` | Build with MP4 (default ON) |
|
||||
| `WITH_RIFF` | Build with AIFF, RIFF, WAV (default ON) |
|
||||
| `WITH_SHORTEN` | Build with Shorten (default ON) |
|
||||
| `WITH_TRUEAUDIO` | Build with TrueAudio (default ON) |
|
||||
| `WITH_VORBIS` | Build with FLAC, Ogg, Opus, Speex (default ON) |
|
||||
|
||||
Note that disabling formats will remove exported symbols from the library and
|
||||
thus break binary compatibility. These options should therefore only be used
|
||||
if the library is built specifically for a certain project. The public header
|
||||
files still contain the full API, if you use TagLib with a reduced set of
|
||||
formats, you can include taglib_config.h and use its definitions (prefixed with
|
||||
`TAGLIB_`, e.g. `TAGLIB_WITH_APE`), as it is done in examples/framelist.cpp.
|
||||
|
||||
## Dependencies
|
||||
|
||||
@@ -438,3 +466,54 @@ cmake --build build_mingw --config Release
|
||||
PATH=$PATH:$TAGLIB_PREFIX/bin
|
||||
build_mingw/tagreader /path/to/audio-file
|
||||
```
|
||||
|
||||
## Android
|
||||
|
||||
### Using vcpkg
|
||||
|
||||
The bash script below can be used to build TagLib for Android using vcpkg.
|
||||
It must be started in the parent folder of the taglib source folder and will
|
||||
build in a folder _android_build_ and install into _android_pkg_.
|
||||
The package and the unit tests are then transferred to an Android device
|
||||
and the unit tests are run on the device.
|
||||
|
||||
Note that `TESTS_TMPDIR` is set because there is no system-wide temporary folder
|
||||
on Android. `TESTS_DIR` is set to run the tests on the target.
|
||||
|
||||
```
|
||||
# You may have to adapt the NDK and vcpkg paths and the ABI/triplet.
|
||||
|
||||
export ANDROID_NDK_HOME=$HOME/Development/android-sdk/ndk/23.1.7779620
|
||||
export VCPKG_ROOT=$HOME/Development/vcpkg
|
||||
PATH=$PATH:$VCPKG_ROOT
|
||||
|
||||
# armeabi-v7a/arm-android or arm64-v8a/arm64-android or x86/x86-android or x86_64/x64-android
|
||||
android_abi=armeabi-v7a
|
||||
vcpkg_target_triplet=arm-android
|
||||
|
||||
vcpkg_toolchain_file=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
|
||||
android_toolchain_file=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake
|
||||
|
||||
vcpkg install --triplet $vcpkg_target_triplet utfcpp zlib cppunit
|
||||
|
||||
cmake -B android_build -S taglib \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$vcpkg_toolchain_file \
|
||||
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=$android_toolchain_file \
|
||||
-DVCPKG_TARGET_TRIPLET=$vcpkg_target_triplet \
|
||||
-DANDROID_ABI=$android_abi \
|
||||
-GNinja -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release \
|
||||
-DVISIBILITY_HIDDEN=ON -DENABLE_CCACHE=ON -DBUILD_EXAMPLES=ON -DBUILD_TESTING=ON \
|
||||
-DTESTS_DIR=/data/local/tmp/tests/ -DTESTS_TMPDIR=/data/local/tmp
|
||||
cmake --build android_build --config Release
|
||||
cmake --install android_build --config Release --prefix android_pkg --strip
|
||||
cp -a android_build/tests/test_runner android_pkg/bin/
|
||||
|
||||
if hash adb 2>/dev/null; then
|
||||
adb push android_pkg /data/local/tmp/
|
||||
adb push android_build/tests/test_runner /data/local/tmp/tests/test_runner
|
||||
adb push taglib/tests/data /data/local/tmp/tests/
|
||||
adb shell "env LD_LIBRARY_PATH=/data/local/tmp/android_pkg/lib /data/local/tmp/tests/test_runner"
|
||||
# You could also try an example binary:
|
||||
# adb shell "env LD_LIBRARY_PATH=/data/local/tmp/android_pkg/lib /data/local/tmp/android_pkg/bin/tagreader '/sdcard/Music/Some Album/A Track.mp3'"
|
||||
fi
|
||||
```
|
||||
|
||||
25
README.md
25
README.md
@@ -7,10 +7,11 @@
|
||||
https://taglib.org/
|
||||
|
||||
TagLib is a library for reading and editing the metadata of several
|
||||
popular audio formats. Currently, it supports both ID3v1 and [ID3v2][]
|
||||
for MP3 files, [Ogg Vorbis][] comments and ID3 tags
|
||||
in [FLAC][], MPC, Speex, WavPack, TrueAudio, WAV, AIFF, MP4, APE,
|
||||
and ASF files.
|
||||
popular audio formats. Currently, it supports various metadata containers such
|
||||
as [ID3v1][], [ID3v2][] and [Vorbis][] comments for MP3, MP4, AAC,
|
||||
[Ogg][], [Opus][], [FLAC][], [Speex][], [APE][], [MPC][], [WavPack][],
|
||||
[WAV][], [AIFF][], [TrueAudio][], [Matroska][], [WebM][], ASF, WMA, DSF, DFF and
|
||||
tracker (MOD, XM, S3M, IT) files.
|
||||
|
||||
TagLib is distributed under the [GNU Lesser General Public License][]
|
||||
(LGPL) and [Mozilla Public License][] (MPL). Essentially that means that
|
||||
@@ -18,8 +19,20 @@ it may be used in proprietary applications, but if changes are made to
|
||||
TagLib they must be contributed back to the project. Please review the
|
||||
licenses if you are considering using TagLib in your project.
|
||||
|
||||
[ID3v2]: https://id3.org/
|
||||
[Ogg Vorbis]: https://xiph.org/vorbis/
|
||||
[ID3v1]: https://id3.org/ID3v1
|
||||
[ID3v2]: https://id3.org/Home
|
||||
[Vorbis]: https://xiph.org/vorbis/
|
||||
[Ogg]: https://www.xiph.org/ogg/
|
||||
[Opus]: https://opus-codec.org/
|
||||
[FLAC]: https://xiph.org/flac/
|
||||
[Speex]: https://www.speex.org/
|
||||
[APE]: https://www.monkeysaudio.com/
|
||||
[MPC]: https://musepack.net/
|
||||
[WavPack]: https://www.wavpack.com/
|
||||
[WAV]: https://www.mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
|
||||
[AIFF]: https://www.mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/AIFF.html
|
||||
[TrueAudio]: https://sourceforge.net/projects/tta/
|
||||
[Matroska]: https://www.matroska.org/
|
||||
[WebM]: https://www.webmproject.org/
|
||||
[GNU Lesser General Public License]: https://www.gnu.org/licenses/lgpl.html
|
||||
[Mozilla Public License]: https://www.mozilla.org/MPL/MPL-1.1.html
|
||||
|
||||
@@ -2,5 +2,4 @@ There are a few other people that have done bindings externally that I have
|
||||
been made aware of. I have not personally reviewed these bindings, but I'm
|
||||
listing them here so that those who find them useful are able to find them:
|
||||
|
||||
http://developer.kde.org/~wheeler/taglib.html#bindings
|
||||
|
||||
https://taglib.org/#language-bindings
|
||||
|
||||
@@ -1,31 +1,75 @@
|
||||
include_directories(
|
||||
set(tag_c_HDR_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/toolkit
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/asf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpeg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/vorbis
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/flac
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/flac
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mp4
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpeg/id3v2
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpeg/id3v2/frames
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/wavpack
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/speex
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/trueaudio
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff/aiff
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff/wav
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ape
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/it
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mod
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/s3m
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/xm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/opus
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/dsf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/dsdiff
|
||||
)
|
||||
if(WITH_ASF)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/asf
|
||||
)
|
||||
endif()
|
||||
if(WITH_VORBIS)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/vorbis
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/flac
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/flac
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/speex
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/opus
|
||||
)
|
||||
endif()
|
||||
if(WITH_APE)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/wavpack
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ape
|
||||
)
|
||||
endif()
|
||||
if(WITH_MP4)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mp4
|
||||
)
|
||||
endif()
|
||||
if(WITH_TRUEAUDIO)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/trueaudio
|
||||
)
|
||||
endif()
|
||||
if(WITH_RIFF)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff/aiff
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/riff/wav
|
||||
)
|
||||
endif()
|
||||
if(WITH_MOD)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/it
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mod
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/s3m
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/xm
|
||||
)
|
||||
endif()
|
||||
if(WITH_DSF)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/dsf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/dsdiff
|
||||
)
|
||||
endif()
|
||||
if(WITH_SHORTEN)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/shorten
|
||||
)
|
||||
endif()
|
||||
if(WITH_MATROSKA)
|
||||
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/matroska
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/matroska/ebml
|
||||
)
|
||||
endif()
|
||||
include_directories(${tag_c_HDR_DIRS})
|
||||
|
||||
set(tag_c_HDRS tag_c.h)
|
||||
|
||||
@@ -74,6 +118,9 @@ set_target_properties(tag_c PROPERTIES
|
||||
DEFINE_SYMBOL MAKE_TAGLIB_C_LIB
|
||||
INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR}
|
||||
)
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(tag_c PUBLIC TAGLIB_STATIC)
|
||||
endif()
|
||||
|
||||
if(TAGLIB_INSTALL_SUFFIX)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
|
||||
@@ -29,35 +29,60 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "taglib_config.h"
|
||||
#include "tstringlist.h"
|
||||
#include "tbytevectorlist.h"
|
||||
#include "tbytevectorstream.h"
|
||||
#include "tiostream.h"
|
||||
#include "tfile.h"
|
||||
#include "tpropertymap.h"
|
||||
#include "fileref.h"
|
||||
#include "asffile.h"
|
||||
#include "vorbisfile.h"
|
||||
#include "mpegfile.h"
|
||||
#include "tag.h"
|
||||
#include "id3v2framefactory.h"
|
||||
#ifdef TAGLIB_WITH_ASF
|
||||
#include "asffile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_VORBIS
|
||||
#include "vorbisfile.h"
|
||||
#include "flacfile.h"
|
||||
#include "oggflacfile.h"
|
||||
#include "speexfile.h"
|
||||
#include "opusfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_APE
|
||||
#include "mpcfile.h"
|
||||
#include "wavpackfile.h"
|
||||
#include "speexfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_TRUEAUDIO
|
||||
#include "trueaudiofile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MP4
|
||||
#include "mp4file.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_RIFF
|
||||
#include "aifffile.h"
|
||||
#include "wavfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_APE
|
||||
#include "apefile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MOD
|
||||
#include "itfile.h"
|
||||
#include "modfile.h"
|
||||
#include "s3mfile.h"
|
||||
#include "xmfile.h"
|
||||
#include "opusfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_DSF
|
||||
#include "dsffile.h"
|
||||
#include "dsdifffile.h"
|
||||
#include "tag.h"
|
||||
#include "id3v2framefactory.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_SHORTEN
|
||||
#include "shortenfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MATROSKA
|
||||
#include "matroskafile.h"
|
||||
#endif
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@@ -127,49 +152,73 @@ TagLib_File *taglib_file_new(const char *filename)
|
||||
return reinterpret_cast<TagLib_File *>(new FileRef(filename));
|
||||
}
|
||||
|
||||
TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
|
||||
#ifdef _WIN32
|
||||
TagLib_File *taglib_file_new_wchar(const wchar_t *filename)
|
||||
{
|
||||
return reinterpret_cast<TagLib_File *>(new FileRef(filename));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
TagLib_File *taglib_file_new_type_any_char(const T *filename, TagLib_File_Type type)
|
||||
{
|
||||
File *file = NULL;
|
||||
switch(type) {
|
||||
case TagLib_File_MPEG:
|
||||
file = new MPEG::File(filename);
|
||||
break;
|
||||
#ifdef TAGLIB_WITH_VORBIS
|
||||
case TagLib_File_OggVorbis:
|
||||
file = new Ogg::Vorbis::File(filename);
|
||||
break;
|
||||
case TagLib_File_FLAC:
|
||||
file = new FLAC::File(filename);
|
||||
break;
|
||||
case TagLib_File_MPC:
|
||||
file = new MPC::File(filename);
|
||||
break;
|
||||
case TagLib_File_OggFlac:
|
||||
file = new Ogg::FLAC::File(filename);
|
||||
break;
|
||||
case TagLib_File_WavPack:
|
||||
file = new WavPack::File(filename);
|
||||
break;
|
||||
case TagLib_File_Speex:
|
||||
file = new Ogg::Speex::File(filename);
|
||||
break;
|
||||
case TagLib_File_Opus:
|
||||
file = new Ogg::Opus::File(filename);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_APE
|
||||
case TagLib_File_MPC:
|
||||
file = new MPC::File(filename);
|
||||
break;
|
||||
case TagLib_File_WavPack:
|
||||
file = new WavPack::File(filename);
|
||||
break;
|
||||
case TagLib_File_APE:
|
||||
file = new APE::File(filename);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_TRUEAUDIO
|
||||
case TagLib_File_TrueAudio:
|
||||
file = new TrueAudio::File(filename);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MP4
|
||||
case TagLib_File_MP4:
|
||||
file = new MP4::File(filename);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_ASF
|
||||
case TagLib_File_ASF:
|
||||
file = new ASF::File(filename);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_RIFF
|
||||
case TagLib_File_AIFF:
|
||||
file = new RIFF::AIFF::File(filename);
|
||||
break;
|
||||
case TagLib_File_WAV:
|
||||
file = new RIFF::WAV::File(filename);
|
||||
break;
|
||||
case TagLib_File_APE:
|
||||
file = new APE::File(filename);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MOD
|
||||
case TagLib_File_IT:
|
||||
file = new IT::File(filename);
|
||||
break;
|
||||
@@ -182,21 +231,43 @@ TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
|
||||
case TagLib_File_XM:
|
||||
file = new XM::File(filename);
|
||||
break;
|
||||
case TagLib_File_Opus:
|
||||
file = new Ogg::Opus::File(filename);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_DSF
|
||||
case TagLib_File_DSF:
|
||||
file = new DSF::File(filename);
|
||||
break;
|
||||
case TagLib_File_DSDIFF:
|
||||
file = new DSDIFF::File(filename);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_SHORTEN
|
||||
case TagLib_File_SHORTEN:
|
||||
file = new Shorten::File(filename);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MATROSKA
|
||||
case TagLib_File_MATROSKA:
|
||||
file = new Matroska::File(filename);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return file ? reinterpret_cast<TagLib_File *>(new FileRef(file)) : NULL;
|
||||
}
|
||||
|
||||
TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
|
||||
{
|
||||
return taglib_file_new_type_any_char(filename, type);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
TagLib_File *taglib_file_new_type_wchar(const wchar_t *filename, TagLib_File_Type type)
|
||||
{
|
||||
return taglib_file_new_type_any_char(filename, type);
|
||||
}
|
||||
#endif
|
||||
|
||||
TagLib_File *taglib_file_new_iostream(TagLib_IOStream *stream)
|
||||
{
|
||||
return reinterpret_cast<TagLib_File *>(
|
||||
@@ -236,7 +307,7 @@ BOOL taglib_file_save(TagLib_File *file)
|
||||
|
||||
char *taglib_tag_title(const TagLib_Tag *tag)
|
||||
{
|
||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
||||
auto t = reinterpret_cast<const Tag *>(tag);
|
||||
char *s = stringToCharArray(t->title());
|
||||
if(stringManagementEnabled)
|
||||
strings.append(s);
|
||||
@@ -245,7 +316,7 @@ char *taglib_tag_title(const TagLib_Tag *tag)
|
||||
|
||||
char *taglib_tag_artist(const TagLib_Tag *tag)
|
||||
{
|
||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
||||
auto t = reinterpret_cast<const Tag *>(tag);
|
||||
char *s = stringToCharArray(t->artist());
|
||||
if(stringManagementEnabled)
|
||||
strings.append(s);
|
||||
@@ -254,7 +325,7 @@ char *taglib_tag_artist(const TagLib_Tag *tag)
|
||||
|
||||
char *taglib_tag_album(const TagLib_Tag *tag)
|
||||
{
|
||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
||||
auto t = reinterpret_cast<const Tag *>(tag);
|
||||
char *s = stringToCharArray(t->album());
|
||||
if(stringManagementEnabled)
|
||||
strings.append(s);
|
||||
@@ -263,7 +334,7 @@ char *taglib_tag_album(const TagLib_Tag *tag)
|
||||
|
||||
char *taglib_tag_comment(const TagLib_Tag *tag)
|
||||
{
|
||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
||||
auto t = reinterpret_cast<const Tag *>(tag);
|
||||
char *s = stringToCharArray(t->comment());
|
||||
if(stringManagementEnabled)
|
||||
strings.append(s);
|
||||
@@ -272,7 +343,7 @@ char *taglib_tag_comment(const TagLib_Tag *tag)
|
||||
|
||||
char *taglib_tag_genre(const TagLib_Tag *tag)
|
||||
{
|
||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
||||
auto t = reinterpret_cast<const Tag *>(tag);
|
||||
char *s = stringToCharArray(t->genre());
|
||||
if(stringManagementEnabled)
|
||||
strings.append(s);
|
||||
@@ -281,55 +352,55 @@ char *taglib_tag_genre(const TagLib_Tag *tag)
|
||||
|
||||
unsigned int taglib_tag_year(const TagLib_Tag *tag)
|
||||
{
|
||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
||||
auto t = reinterpret_cast<const Tag *>(tag);
|
||||
return t->year();
|
||||
}
|
||||
|
||||
unsigned int taglib_tag_track(const TagLib_Tag *tag)
|
||||
{
|
||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
||||
auto t = reinterpret_cast<const Tag *>(tag);
|
||||
return t->track();
|
||||
}
|
||||
|
||||
void taglib_tag_set_title(TagLib_Tag *tag, const char *title)
|
||||
{
|
||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
||||
auto t = reinterpret_cast<Tag *>(tag);
|
||||
t->setTitle(charArrayToString(title));
|
||||
}
|
||||
|
||||
void taglib_tag_set_artist(TagLib_Tag *tag, const char *artist)
|
||||
{
|
||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
||||
auto t = reinterpret_cast<Tag *>(tag);
|
||||
t->setArtist(charArrayToString(artist));
|
||||
}
|
||||
|
||||
void taglib_tag_set_album(TagLib_Tag *tag, const char *album)
|
||||
{
|
||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
||||
auto t = reinterpret_cast<Tag *>(tag);
|
||||
t->setAlbum(charArrayToString(album));
|
||||
}
|
||||
|
||||
void taglib_tag_set_comment(TagLib_Tag *tag, const char *comment)
|
||||
{
|
||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
||||
auto t = reinterpret_cast<Tag *>(tag);
|
||||
t->setComment(charArrayToString(comment));
|
||||
}
|
||||
|
||||
void taglib_tag_set_genre(TagLib_Tag *tag, const char *genre)
|
||||
{
|
||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
||||
auto t = reinterpret_cast<Tag *>(tag);
|
||||
t->setGenre(charArrayToString(genre));
|
||||
}
|
||||
|
||||
void taglib_tag_set_year(TagLib_Tag *tag, unsigned int year)
|
||||
{
|
||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
||||
auto t = reinterpret_cast<Tag *>(tag);
|
||||
t->setYear(year);
|
||||
}
|
||||
|
||||
void taglib_tag_set_track(TagLib_Tag *tag, unsigned int track)
|
||||
{
|
||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
||||
auto t = reinterpret_cast<Tag *>(tag);
|
||||
t->setTrack(track);
|
||||
}
|
||||
|
||||
@@ -406,24 +477,25 @@ void _taglib_property_set(TagLib_File *file, const char* prop, const char* value
|
||||
return;
|
||||
|
||||
auto tfile = reinterpret_cast<FileRef *>(file);
|
||||
auto propStr = charArrayToString(prop);
|
||||
PropertyMap map = tfile->tag()->properties();
|
||||
|
||||
if(value) {
|
||||
auto property = map.find(prop);
|
||||
auto property = map.find(propStr);
|
||||
if(property == map.end()) {
|
||||
map.insert(prop, StringList(value));
|
||||
map.insert(propStr, StringList(charArrayToString(value)));
|
||||
}
|
||||
else {
|
||||
if(append) {
|
||||
property->second.append(value);
|
||||
property->second.append(charArrayToString(value));
|
||||
}
|
||||
else {
|
||||
property->second = StringList(value);
|
||||
property->second = StringList(charArrayToString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
map.erase(prop);
|
||||
map.erase(propStr);
|
||||
}
|
||||
|
||||
tfile->setProperties(map);
|
||||
@@ -431,17 +503,17 @@ void _taglib_property_set(TagLib_File *file, const char* prop, const char* value
|
||||
|
||||
} // namespace
|
||||
|
||||
void taglib_property_set(TagLib_File *f, const char *prop, const char *value)
|
||||
void taglib_property_set(TagLib_File *file, const char *prop, const char *value)
|
||||
{
|
||||
_taglib_property_set(f, prop, value, false);
|
||||
_taglib_property_set(file, prop, value, false);
|
||||
}
|
||||
|
||||
void taglib_property_set_append(TagLib_File *f, const char *prop, const char *value)
|
||||
void taglib_property_set_append(TagLib_File *file, const char *prop, const char *value)
|
||||
{
|
||||
_taglib_property_set(f, prop, value, true);
|
||||
_taglib_property_set(file, prop, value, true);
|
||||
}
|
||||
|
||||
char** taglib_property_keys(TagLib_File *file)
|
||||
char** taglib_property_keys(const TagLib_File *file)
|
||||
{
|
||||
if(file == NULL)
|
||||
return NULL;
|
||||
@@ -461,14 +533,14 @@ char** taglib_property_keys(TagLib_File *file)
|
||||
return props;
|
||||
}
|
||||
|
||||
char **taglib_property_get(TagLib_File *file, const char *prop)
|
||||
char **taglib_property_get(const TagLib_File *file, const char *prop)
|
||||
{
|
||||
if(file == NULL || prop == NULL)
|
||||
return NULL;
|
||||
|
||||
const PropertyMap map = reinterpret_cast<const FileRef *>(file)->properties();
|
||||
|
||||
auto property = map.find(prop);
|
||||
auto property = map.find(charArrayToString(prop));
|
||||
if(property == map.end())
|
||||
return NULL;
|
||||
|
||||
@@ -510,18 +582,18 @@ bool _taglib_complex_property_set(
|
||||
return false;
|
||||
|
||||
auto tfile = reinterpret_cast<FileRef *>(file);
|
||||
auto keyStr = charArrayToString(key);
|
||||
|
||||
if(value == NULL) {
|
||||
return tfile->setComplexProperties(key, {});
|
||||
return tfile->setComplexProperties(keyStr, {});
|
||||
}
|
||||
|
||||
VariantMap map;
|
||||
const TagLib_Complex_Property_Attribute** attrPtr = value;
|
||||
while(*attrPtr) {
|
||||
const TagLib_Complex_Property_Attribute *attr = *attrPtr;
|
||||
String attrKey(attr->key);
|
||||
TagLib_Variant_Type type = attr->value.type;
|
||||
switch(type) {
|
||||
auto attrKey = charArrayToString(attr->key);
|
||||
switch(attr->value.type) {
|
||||
case TagLib_Variant_Void:
|
||||
map.insert(attrKey, Variant());
|
||||
break;
|
||||
@@ -544,14 +616,14 @@ bool _taglib_complex_property_set(
|
||||
map.insert(attrKey, attr->value.value.doubleValue);
|
||||
break;
|
||||
case TagLib_Variant_String:
|
||||
map.insert(attrKey, attr->value.value.stringValue);
|
||||
map.insert(attrKey, charArrayToString(attr->value.value.stringValue));
|
||||
break;
|
||||
case TagLib_Variant_StringList: {
|
||||
StringList strs;
|
||||
if(attr->value.value.stringListValue) {
|
||||
char **s = attr->value.value.stringListValue;;
|
||||
while(*s) {
|
||||
strs.append(*s++);
|
||||
strs.append(charArrayToString(*s++));
|
||||
}
|
||||
}
|
||||
map.insert(attrKey, strs);
|
||||
@@ -565,8 +637,8 @@ bool _taglib_complex_property_set(
|
||||
++attrPtr;
|
||||
}
|
||||
|
||||
return append ? tfile->setComplexProperties(key, tfile->complexProperties(key).append(map))
|
||||
: tfile->setComplexProperties(key, {map});
|
||||
return append ? tfile->setComplexProperties(keyStr, tfile->complexProperties(keyStr).append(map))
|
||||
: tfile->setComplexProperties(keyStr, {map});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -585,7 +657,7 @@ BOOL taglib_complex_property_set_append(
|
||||
return _taglib_complex_property_set(file, key, value, true);
|
||||
}
|
||||
|
||||
char** taglib_complex_property_keys(TagLib_File *file)
|
||||
char** taglib_complex_property_keys(const TagLib_File *file)
|
||||
{
|
||||
if(file == NULL) {
|
||||
return NULL;
|
||||
@@ -608,26 +680,26 @@ char** taglib_complex_property_keys(TagLib_File *file)
|
||||
}
|
||||
|
||||
TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
|
||||
TagLib_File *file, const char *key)
|
||||
const TagLib_File *file, const char *key)
|
||||
{
|
||||
if(file == NULL || key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const auto variantMaps = reinterpret_cast<const FileRef *>(file)->complexProperties(key);
|
||||
const auto variantMaps = reinterpret_cast<const FileRef *>(file)->complexProperties(charArrayToString(key));
|
||||
if(variantMaps.isEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TagLib_Complex_Property_Attribute ***props = static_cast<TagLib_Complex_Property_Attribute ***>(
|
||||
auto props = static_cast<TagLib_Complex_Property_Attribute ***>(
|
||||
malloc(sizeof(TagLib_Complex_Property_Attribute **) * (variantMaps.size() + 1)));
|
||||
TagLib_Complex_Property_Attribute ***propPtr = props;
|
||||
|
||||
for(const auto &variantMap : variantMaps) {
|
||||
if(!variantMap.isEmpty()) {
|
||||
TagLib_Complex_Property_Attribute **attrs = static_cast<TagLib_Complex_Property_Attribute **>(
|
||||
auto attrs = static_cast<TagLib_Complex_Property_Attribute **>(
|
||||
malloc(sizeof(TagLib_Complex_Property_Attribute *) * (variantMap.size() + 1)));
|
||||
TagLib_Complex_Property_Attribute *attr = static_cast<TagLib_Complex_Property_Attribute *>(
|
||||
auto attr = static_cast<TagLib_Complex_Property_Attribute *>(
|
||||
malloc(sizeof(TagLib_Complex_Property_Attribute) * variantMap.size()));
|
||||
TagLib_Complex_Property_Attribute **attrPtr = attrs;
|
||||
// The next assignment is redundant to silence the clang analyzer,
|
||||
@@ -675,7 +747,7 @@ TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
|
||||
}
|
||||
case Variant::StringList: {
|
||||
attr->value.type = TagLib_Variant_StringList;
|
||||
StringList strs = v.value<StringList>();
|
||||
auto strs = v.value<StringList>();
|
||||
auto strPtr = static_cast<char **>(malloc(sizeof(char *) * (strs.size() + 1)));
|
||||
attr->value.value.stringListValue = strPtr;
|
||||
attr->value.size = strs.size();
|
||||
@@ -727,8 +799,7 @@ void taglib_picture_from_complex_property(
|
||||
TagLib_Complex_Property_Attribute** attrPtr = *propPtr;
|
||||
while(*attrPtr) {
|
||||
TagLib_Complex_Property_Attribute *attr = *attrPtr;
|
||||
TagLib_Variant_Type type = attr->value.type;
|
||||
switch(type) {
|
||||
switch(attr->value.type) {
|
||||
case TagLib_Variant_String:
|
||||
if(strcmp("mimeType", attr->key) == 0) {
|
||||
picture->mimeType = attr->value.value.stringValue;
|
||||
@@ -779,8 +850,7 @@ void taglib_complex_property_free(
|
||||
TagLib_Complex_Property_Attribute** attrPtr = *propPtr;
|
||||
while(*attrPtr) {
|
||||
TagLib_Complex_Property_Attribute *attr = *attrPtr;
|
||||
TagLib_Variant_Type type = attr->value.type;
|
||||
switch(type) {
|
||||
switch(attr->value.type) {
|
||||
case TagLib_Variant_String:
|
||||
free(attr->value.value.stringValue);
|
||||
break;
|
||||
|
||||
@@ -43,6 +43,7 @@ extern "C" {
|
||||
#define TAGLIB_C_EXPORT
|
||||
#endif
|
||||
|
||||
#include <wchar.h>
|
||||
#ifdef _MSC_VER
|
||||
/* minwindef.h contains typedef int BOOL */
|
||||
#include <windows.h>
|
||||
@@ -130,7 +131,9 @@ typedef enum {
|
||||
TagLib_File_XM,
|
||||
TagLib_File_Opus,
|
||||
TagLib_File_DSF,
|
||||
TagLib_File_DSDIFF
|
||||
TagLib_File_DSDIFF,
|
||||
TagLib_File_SHORTEN,
|
||||
TagLib_File_MATROSKA
|
||||
} TagLib_File_Type;
|
||||
|
||||
/*!
|
||||
@@ -141,12 +144,18 @@ typedef enum {
|
||||
* be opened.
|
||||
*/
|
||||
TAGLIB_C_EXPORT TagLib_File *taglib_file_new(const char *filename);
|
||||
#ifdef _WIN32
|
||||
TAGLIB_C_EXPORT TagLib_File *taglib_file_new_wchar(const wchar_t *filename);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Creates a TagLib file based on \a filename. Rather than attempting to guess
|
||||
* the type, it will use the one specified by \a type.
|
||||
*/
|
||||
TAGLIB_C_EXPORT TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type);
|
||||
#ifdef _WIN32
|
||||
TAGLIB_C_EXPORT TagLib_File *taglib_file_new_type_wchar(const wchar_t *filename, TagLib_File_Type type);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Creates a TagLib file from a \a stream.
|
||||
@@ -164,7 +173,7 @@ TAGLIB_C_EXPORT TagLib_File *taglib_file_new_iostream(TagLib_IOStream *stream);
|
||||
TAGLIB_C_EXPORT void taglib_file_free(TagLib_File *file);
|
||||
|
||||
/*!
|
||||
* Returns true if the file is open and readable and valid information for
|
||||
* Returns \c true if the file is open and readable and valid information for
|
||||
* the Tag and / or AudioProperties was found.
|
||||
*/
|
||||
|
||||
@@ -232,12 +241,12 @@ TAGLIB_C_EXPORT char *taglib_tag_comment(const TagLib_Tag *tag);
|
||||
TAGLIB_C_EXPORT char *taglib_tag_genre(const TagLib_Tag *tag);
|
||||
|
||||
/*!
|
||||
* Returns the tag's year or 0 if year is not set.
|
||||
* Returns the tag's year or 0 if the year is not set.
|
||||
*/
|
||||
TAGLIB_C_EXPORT unsigned int taglib_tag_year(const TagLib_Tag *tag);
|
||||
|
||||
/*!
|
||||
* Returns the tag's track number or 0 if track number is not set.
|
||||
* Returns the tag's track number or 0 if the track number is not set.
|
||||
*/
|
||||
TAGLIB_C_EXPORT unsigned int taglib_tag_track(const TagLib_Tag *tag);
|
||||
|
||||
@@ -354,7 +363,7 @@ TAGLIB_C_EXPORT void taglib_property_set_append(TagLib_File *file, const char *p
|
||||
* \return NULL terminated array of C-strings (char *), only NULL if empty.
|
||||
* It must be freed by the client using taglib_property_free().
|
||||
*/
|
||||
TAGLIB_C_EXPORT char** taglib_property_keys(TagLib_File *file);
|
||||
TAGLIB_C_EXPORT char** taglib_property_keys(const TagLib_File *file);
|
||||
|
||||
/*!
|
||||
* Get value(s) of property \a prop.
|
||||
@@ -362,7 +371,7 @@ TAGLIB_C_EXPORT char** taglib_property_keys(TagLib_File *file);
|
||||
* \return NULL terminated array of C-strings (char *), only NULL if empty.
|
||||
* It must be freed by the client using taglib_property_free().
|
||||
*/
|
||||
TAGLIB_C_EXPORT char** taglib_property_get(TagLib_File *file, const char *prop);
|
||||
TAGLIB_C_EXPORT char** taglib_property_get(const TagLib_File *file, const char *prop);
|
||||
|
||||
/*!
|
||||
* Frees the NULL terminated array \a props and the C-strings it contains.
|
||||
@@ -541,7 +550,7 @@ TAGLIB_C_EXPORT BOOL taglib_complex_property_set_append(
|
||||
* \return NULL terminated array of C-strings (char *), only NULL if empty.
|
||||
* It must be freed by the client using taglib_complex_property_free_keys().
|
||||
*/
|
||||
TAGLIB_C_EXPORT char** taglib_complex_property_keys(TagLib_File *file);
|
||||
TAGLIB_C_EXPORT char** taglib_complex_property_keys(const TagLib_File *file);
|
||||
|
||||
/*!
|
||||
* Get value(s) of complex property \a key.
|
||||
@@ -551,7 +560,7 @@ TAGLIB_C_EXPORT char** taglib_complex_property_keys(TagLib_File *file);
|
||||
* It must be freed by the client using taglib_complex_property_free().
|
||||
*/
|
||||
TAGLIB_C_EXPORT TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
|
||||
TagLib_File *file, const char *key);
|
||||
const TagLib_File *file, const char *key);
|
||||
|
||||
/*!
|
||||
* Extract the complex property values of a picture.
|
||||
|
||||
@@ -20,5 +20,6 @@
|
||||
#cmakedefine TRACE_IN_RELEASE 1
|
||||
|
||||
#cmakedefine TESTS_DIR "@TESTS_DIR@"
|
||||
#cmakedefine TESTS_TMPDIR "@TESTS_TMPDIR@"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,7 @@ include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/toolkit
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ape
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/matroska
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v1
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2
|
||||
@@ -38,6 +39,18 @@ target_link_libraries(framelist tag)
|
||||
add_executable(strip-id3v1 strip-id3v1.cpp)
|
||||
target_link_libraries(strip-id3v1 tag)
|
||||
|
||||
if(WITH_MATROSKA)
|
||||
########### next target ###############
|
||||
|
||||
add_executable(matroskareader matroskareader.cpp)
|
||||
target_link_libraries(matroskareader tag)
|
||||
|
||||
########### next target ###############
|
||||
|
||||
add_executable(matroskawriter matroskawriter.cpp)
|
||||
target_link_libraries(matroskawriter tag)
|
||||
endif()
|
||||
|
||||
install(TARGETS tagreader tagreader_c tagwriter framelist strip-id3v1
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "taglib_config.h"
|
||||
#include "tbytevector.h"
|
||||
#include "mpegfile.h"
|
||||
#include "id3v2tag.h"
|
||||
@@ -32,9 +33,10 @@
|
||||
#include "id3v2header.h"
|
||||
#include "commentsframe.h"
|
||||
#include "id3v1tag.h"
|
||||
#ifdef TAGLIB_WITH_APE
|
||||
#include "apetag.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace TagLib;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -44,7 +46,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
for(int i = 1; i < argc; i++) {
|
||||
|
||||
cout << "******************** \"" << argv[i] << "\"********************" << endl;
|
||||
std::cout << "******************** \"" << argv[i] << "\"********************" << std::endl;
|
||||
|
||||
MPEG::File f(argv[i]);
|
||||
|
||||
@@ -52,62 +54,64 @@ int main(int argc, char *argv[])
|
||||
|
||||
if(id3v2tag) {
|
||||
|
||||
cout << "ID3v2."
|
||||
std::cout << "ID3v2."
|
||||
<< id3v2tag->header()->majorVersion()
|
||||
<< "."
|
||||
<< id3v2tag->header()->revisionNumber()
|
||||
<< ", "
|
||||
<< id3v2tag->header()->tagSize()
|
||||
<< " bytes in tag"
|
||||
<< endl;
|
||||
<< std::endl;
|
||||
|
||||
const auto &frames = id3v2tag->frameList();
|
||||
for(auto it = frames.begin(); it != frames.end(); it++) {
|
||||
cout << (*it)->frameID();
|
||||
std::cout << (*it)->frameID();
|
||||
|
||||
if(auto comment = dynamic_cast<ID3v2::CommentsFrame *>(*it))
|
||||
if(!comment->description().isEmpty())
|
||||
cout << " [" << comment->description() << "]";
|
||||
std::cout << " [" << comment->description() << "]";
|
||||
|
||||
cout << " - \"" << (*it)->toString() << "\"" << endl;
|
||||
std::cout << " - \"" << (*it)->toString() << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
cout << "file does not have a valid id3v2 tag" << endl;
|
||||
std::cout << "file does not have a valid id3v2 tag" << std::endl;
|
||||
|
||||
cout << endl << "ID3v1" << endl;
|
||||
std::cout << std::endl << "ID3v1" << std::endl;
|
||||
|
||||
ID3v1::Tag *id3v1tag = f.ID3v1Tag();
|
||||
|
||||
if(id3v1tag) {
|
||||
cout << "title - \"" << id3v1tag->title() << "\"" << endl;
|
||||
cout << "artist - \"" << id3v1tag->artist() << "\"" << endl;
|
||||
cout << "album - \"" << id3v1tag->album() << "\"" << endl;
|
||||
cout << "year - \"" << id3v1tag->year() << "\"" << endl;
|
||||
cout << "comment - \"" << id3v1tag->comment() << "\"" << endl;
|
||||
cout << "track - \"" << id3v1tag->track() << "\"" << endl;
|
||||
cout << "genre - \"" << id3v1tag->genre() << "\"" << endl;
|
||||
std::cout << "title - \"" << id3v1tag->title() << "\"" << std::endl;
|
||||
std::cout << "artist - \"" << id3v1tag->artist() << "\"" << std::endl;
|
||||
std::cout << "album - \"" << id3v1tag->album() << "\"" << std::endl;
|
||||
std::cout << "year - \"" << id3v1tag->year() << "\"" << std::endl;
|
||||
std::cout << "comment - \"" << id3v1tag->comment() << "\"" << std::endl;
|
||||
std::cout << "track - \"" << id3v1tag->track() << "\"" << std::endl;
|
||||
std::cout << "genre - \"" << id3v1tag->genre() << "\"" << std::endl;
|
||||
}
|
||||
else
|
||||
cout << "file does not have a valid id3v1 tag" << endl;
|
||||
std::cout << "file does not have a valid id3v1 tag" << std::endl;
|
||||
|
||||
#ifdef TAGLIB_WITH_APE
|
||||
APE::Tag *ape = f.APETag();
|
||||
|
||||
cout << endl << "APE" << endl;
|
||||
std::cout << std::endl << "APE" << std::endl;
|
||||
|
||||
if(ape) {
|
||||
const auto &items = ape->itemListMap();
|
||||
for(auto it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
if((*it).second.type() != APE::Item::Binary)
|
||||
cout << (*it).first << " - \"" << (*it).second.toString() << "\"" << endl;
|
||||
std::cout << (*it).first << " - \"" << (*it).second.toString() << "\"" << std::endl;
|
||||
else
|
||||
cout << (*it).first << " - Binary data (" << (*it).second.binaryData().size() << " bytes)" << endl;
|
||||
std::cout << (*it).first << " - Binary data (" << (*it).second.binaryData().size() << " bytes)" << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
cout << "file does not have a valid APE tag" << endl;
|
||||
std::cout << "file does not have a valid APE tag" << std::endl;
|
||||
#endif
|
||||
|
||||
cout << endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
124
examples/matroskareader.cpp
Normal file
124
examples/matroskareader.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include <cstdio>
|
||||
#include "matroskafile.h"
|
||||
#include "matroskatag.h"
|
||||
#include "matroskasimpletag.h"
|
||||
#include "matroskaattachments.h"
|
||||
#include "matroskaattachedfile.h"
|
||||
#include "matroskachapters.h"
|
||||
#include "matroskachapteredition.h"
|
||||
#include "tstring.h"
|
||||
#include "tutils.h"
|
||||
#include "tbytevector.h"
|
||||
#define GREEN_TEXT(s) "[1;32m" s "[0m"
|
||||
#define PRINT_PRETTY(label, value) printf(" " GREEN_TEXT(label) ": %s\n", value)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc != 2) {
|
||||
printf("Usage: matroskareader FILE\n");
|
||||
return 1;
|
||||
}
|
||||
TagLib::Matroska::File file(argv[1]);
|
||||
if(!file.isValid()) {
|
||||
printf("File is not valid\n");
|
||||
return 1;
|
||||
}
|
||||
auto tag = dynamic_cast<TagLib::Matroska::Tag*>(file.tag());
|
||||
if(!tag) {
|
||||
printf("File has no tag\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const TagLib::Matroska::SimpleTagsList &list = tag->simpleTagsList();
|
||||
printf("Found %u tag(s):\n", list.size());
|
||||
|
||||
for(const TagLib::Matroska::SimpleTag &t : list) {
|
||||
PRINT_PRETTY("Tag Name", t.name().toCString(true));
|
||||
|
||||
if(t.type() == TagLib::Matroska::SimpleTag::StringType)
|
||||
PRINT_PRETTY("Tag Value", t.toString().toCString(true));
|
||||
else if(t.type() == TagLib::Matroska::SimpleTag::BinaryType)
|
||||
PRINT_PRETTY("Tag Value",
|
||||
TagLib::Utils::formatString("Binary with size %i", t.toByteVector().size()).toCString(false)
|
||||
);
|
||||
|
||||
auto targetTypeValue = static_cast<unsigned int>(t.targetTypeValue());
|
||||
PRINT_PRETTY("Target Type Value",
|
||||
targetTypeValue == 0 ? "None" : TagLib::Utils::formatString("%i", targetTypeValue).toCString(false)
|
||||
);
|
||||
if(auto trackUid = t.trackUid()) {
|
||||
PRINT_PRETTY("Track UID",
|
||||
TagLib::Utils::formatString("%llu",trackUid).toCString(false)
|
||||
);
|
||||
}
|
||||
const TagLib::String &language = t.language();
|
||||
PRINT_PRETTY("Language", !language.isEmpty() ? language.toCString(false) : "Not set");
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
TagLib::Matroska::Attachments *attachments = file.attachments();
|
||||
if(attachments) {
|
||||
const TagLib::Matroska::Attachments::AttachedFileList &list = attachments->attachedFileList();
|
||||
printf("Found %u attachment(s)\n", list.size());
|
||||
for(const auto &attachedFile : list) {
|
||||
PRINT_PRETTY("Filename", attachedFile.fileName().toCString(true));
|
||||
const TagLib::String &description = attachedFile.description();
|
||||
PRINT_PRETTY("Description", !description.isEmpty() ? description.toCString(true) : "None");
|
||||
const TagLib::String &mediaType = attachedFile.mediaType();
|
||||
PRINT_PRETTY("Media Type", !mediaType.isEmpty() ? mediaType.toCString(false) : "None");
|
||||
PRINT_PRETTY("Data Size",
|
||||
TagLib::Utils::formatString("%u byte(s)", attachedFile.data().size()).toCString(false)
|
||||
);
|
||||
PRINT_PRETTY("UID",
|
||||
TagLib::Utils::formatString("%llu", attachedFile.uid()).toCString(false)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("File has no attachments\n");
|
||||
|
||||
TagLib::Matroska::Chapters *chapters = file.chapters();
|
||||
if(chapters) {
|
||||
printf("Chapters:\n");
|
||||
const TagLib::Matroska::Chapters::ChapterEditionList &editions = chapters->chapterEditionList();
|
||||
for(const auto &edition : editions) {
|
||||
if(edition.uid()) {
|
||||
PRINT_PRETTY("Edition UID", TagLib::Utils::formatString("%llu", edition.uid())
|
||||
.toCString(false));
|
||||
}
|
||||
PRINT_PRETTY("Edition Flags", TagLib::Utils::formatString("default=%d, ordered=%d",
|
||||
edition.isDefault(), edition.isOrdered())
|
||||
.toCString(false));
|
||||
printf("\n");
|
||||
for(const auto &chapter : edition.chapterList()) {
|
||||
PRINT_PRETTY("Chapter UID", TagLib::Utils::formatString("%llu", chapter.uid())
|
||||
.toCString(false));
|
||||
PRINT_PRETTY("Chapter flags", TagLib::Utils::formatString("hidden=%d", chapter.isHidden())
|
||||
.toCString(false));
|
||||
PRINT_PRETTY("Start-End", TagLib::Utils::formatString("%llu-%llu",
|
||||
chapter.timeStart(), chapter.timeEnd()).toCString(false));
|
||||
for(const auto &display : chapter.displayList()) {
|
||||
PRINT_PRETTY("Display", display.string().toCString(false));
|
||||
PRINT_PRETTY("Language", !display.language().isEmpty()
|
||||
? display.language().toCString(false) : "Not set");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("File has no chapters\n");
|
||||
|
||||
if(auto properties = dynamic_cast<const TagLib::Matroska::Properties *>(file.audioProperties())) {
|
||||
printf("Properties:\n");
|
||||
PRINT_PRETTY("Doc Type", properties->docType().toCString(false));
|
||||
PRINT_PRETTY("Doc Type Version", TagLib::String::number(properties->docTypeVersion()).toCString(false));
|
||||
PRINT_PRETTY("Codec Name", properties->codecName().toCString(true));
|
||||
PRINT_PRETTY("Bitrate", TagLib::String::number(properties->bitrate()).toCString(false));
|
||||
PRINT_PRETTY("Sample Rate", TagLib::String::number(properties->sampleRate()).toCString(false));
|
||||
PRINT_PRETTY("Channels", TagLib::String::number(properties->channels()).toCString(false));
|
||||
PRINT_PRETTY("Length [ms]", TagLib::String::number(properties->lengthInMilliseconds()).toCString(false));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
45
examples/matroskawriter.cpp
Normal file
45
examples/matroskawriter.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <cstdio>
|
||||
#include "matroskafile.h"
|
||||
#include "matroskatag.h"
|
||||
#include "matroskasimpletag.h"
|
||||
#include "matroskaattachments.h"
|
||||
#include "matroskaattachedfile.h"
|
||||
#include "tfilestream.h"
|
||||
#include "tstring.h"
|
||||
#include "tutils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc != 3) {
|
||||
printf("Usage: matroskawriter FILE ARTWORK\n");
|
||||
return 1;
|
||||
}
|
||||
TagLib::Matroska::File file(argv[1]);
|
||||
if(!file.isValid()) {
|
||||
printf("File is not valid\n");
|
||||
return 1;
|
||||
}
|
||||
auto tag = file.tag(true);
|
||||
tag->clearSimpleTags();
|
||||
|
||||
tag->addSimpleTag(TagLib::Matroska::SimpleTag(
|
||||
"Test Name 1", TagLib::String("Test Value 1"),
|
||||
TagLib::Matroska::SimpleTag::TargetTypeValue::Track, "en"));
|
||||
|
||||
tag->addSimpleTag(TagLib::Matroska::SimpleTag(
|
||||
"Test Name 2", TagLib::String("Test Value 2"),
|
||||
TagLib::Matroska::SimpleTag::TargetTypeValue::Album));
|
||||
tag->setTitle("Test title");
|
||||
tag->setArtist("Test artist");
|
||||
tag->setYear(1969);
|
||||
|
||||
TagLib::FileStream image(argv[2]);
|
||||
auto data = image.readBlock(image.length());
|
||||
auto attachments = file.attachments(true);
|
||||
attachments->addAttachedFile(TagLib::Matroska::AttachedFile(
|
||||
data, "cover.jpg", "image/jpeg"));
|
||||
|
||||
file.save();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -32,13 +32,11 @@
|
||||
#include "fileref.h"
|
||||
#include "tag.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
for(int i = 1; i < argc; i++) {
|
||||
|
||||
cout << "******************** \"" << argv[i] << "\" ********************" << endl;
|
||||
std::cout << "******************** \"" << argv[i] << "\" ********************" << std::endl;
|
||||
|
||||
TagLib::FileRef f(argv[i]);
|
||||
|
||||
@@ -46,14 +44,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
TagLib::Tag *tag = f.tag();
|
||||
|
||||
cout << "-- TAG (basic) --" << endl;
|
||||
cout << "title - \"" << tag->title() << "\"" << endl;
|
||||
cout << "artist - \"" << tag->artist() << "\"" << endl;
|
||||
cout << "album - \"" << tag->album() << "\"" << endl;
|
||||
cout << "year - \"" << tag->year() << "\"" << endl;
|
||||
cout << "comment - \"" << tag->comment() << "\"" << endl;
|
||||
cout << "track - \"" << tag->track() << "\"" << endl;
|
||||
cout << "genre - \"" << tag->genre() << "\"" << endl;
|
||||
std::cout << "-- TAG (basic) --" << std::endl;
|
||||
std::cout << "title - \"" << tag->title() << "\"" << std::endl;
|
||||
std::cout << "artist - \"" << tag->artist() << "\"" << std::endl;
|
||||
std::cout << "album - \"" << tag->album() << "\"" << std::endl;
|
||||
std::cout << "year - \"" << tag->year() << "\"" << std::endl;
|
||||
std::cout << "comment - \"" << tag->comment() << "\"" << std::endl;
|
||||
std::cout << "track - \"" << tag->track() << "\"" << std::endl;
|
||||
std::cout << "genre - \"" << tag->genre() << "\"" << std::endl;
|
||||
|
||||
TagLib::PropertyMap tags = f.properties();
|
||||
if(!tags.isEmpty()) {
|
||||
@@ -64,10 +62,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
cout << "-- TAG (properties) --" << endl;
|
||||
std::cout << "-- TAG (properties) --" << std::endl;
|
||||
for(auto j = tags.cbegin(); j != tags.cend(); ++j) {
|
||||
for(auto k = j->second.begin(); k != j->second.end(); ++k) {
|
||||
cout << left << std::setfill(' ') << std::setw(longest) << j->first << " - " << '"' << *k << '"' << endl;
|
||||
std::cout << std::left << std::setfill(' ') << std::setw(longest) << j->first << " - " << '"' << *k << '"' << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,13 +74,13 @@ int main(int argc, char *argv[])
|
||||
for(const auto &name : names) {
|
||||
const auto& properties = f.complexProperties(name);
|
||||
for(const auto &property : properties) {
|
||||
cout << name << ":" << endl;
|
||||
std::cout << name << ":" << std::endl;
|
||||
for(const auto &[key, value] : property) {
|
||||
cout << " " << left << std::setfill(' ') << std::setw(11) << key << " - ";
|
||||
std::cout << " " << std::left << std::setfill(' ') << std::setw(11) << key << " - ";
|
||||
if(value.type() == TagLib::Variant::ByteVector) {
|
||||
cout << "(" << value.value<TagLib::ByteVector>().size() << " bytes)" << endl;
|
||||
std::cout << "(" << value.value<TagLib::ByteVector>().size() << " bytes)" << std::endl;
|
||||
/* The picture could be extracted using:
|
||||
ofstream picture;
|
||||
std::ofstream picture;
|
||||
TagLib::String fn(argv[i]);
|
||||
int slashPos = fn.rfind('/');
|
||||
int dotPos = fn.rfind('.');
|
||||
@@ -90,13 +88,13 @@ int main(int argc, char *argv[])
|
||||
fn = fn.substr(slashPos + 1, dotPos - slashPos - 1);
|
||||
}
|
||||
fn += ".jpg";
|
||||
picture.open(fn.toCString(), ios_base::out | ios_base::binary);
|
||||
picture.open(fn.toCString(), std::ios_base::out | std::ios_base::binary);
|
||||
picture << value.value<TagLib::ByteVector>();
|
||||
picture.close();
|
||||
*/
|
||||
}
|
||||
else {
|
||||
cout << value << endl;
|
||||
std::cout << value << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,12 +108,13 @@ int main(int argc, char *argv[])
|
||||
int seconds = properties->lengthInSeconds() % 60;
|
||||
int minutes = (properties->lengthInSeconds() - seconds) / 60;
|
||||
|
||||
cout << "-- AUDIO --" << endl;
|
||||
cout << "bitrate - " << properties->bitrate() << endl;
|
||||
cout << "sample rate - " << properties->sampleRate() << endl;
|
||||
cout << "channels - " << properties->channels() << endl;
|
||||
cout << "length - " << minutes << ":" << setfill('0') << setw(2) << right << seconds << endl;
|
||||
std::cout << "-- AUDIO --" << std::endl;
|
||||
std::cout << "bitrate - " << properties->bitrate() << std::endl;
|
||||
std::cout << "sample rate - " << properties->sampleRate() << std::endl;
|
||||
std::cout << "channels - " << properties->channels() << std::endl;
|
||||
std::cout << "length - " << minutes << ":" << std::setfill('0') << std::setw(2) << std::right << seconds << std::endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "tag_c.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tag_c.h"
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
#include "fileref.h"
|
||||
#include "tag.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool isArgument(const char *s)
|
||||
{
|
||||
return strlen(s) == 2 && s[0] == '-';
|
||||
@@ -48,32 +46,34 @@ bool isArgument(const char *s)
|
||||
|
||||
bool isFile(const char *s)
|
||||
{
|
||||
struct stat st;
|
||||
#ifdef _WIN32
|
||||
return ::stat(s, &st) == 0 && (st.st_mode & (S_IFREG));
|
||||
struct _stat64 st;
|
||||
return ::_stat64(s, &st) == 0 && (st.st_mode & S_IFREG);
|
||||
#else
|
||||
struct stat st;
|
||||
return ::stat(s, &st) == 0 && (st.st_mode & (S_IFREG | S_IFLNK));
|
||||
#endif
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
cout << endl;
|
||||
cout << "Usage: tagwriter <fields> <files>" << endl;
|
||||
cout << endl;
|
||||
cout << "Where the valid fields are:" << endl;
|
||||
cout << " -t <title>" << endl;
|
||||
cout << " -a <artist>" << endl;
|
||||
cout << " -A <album>" << endl;
|
||||
cout << " -c <comment>" << endl;
|
||||
cout << " -g <genre>" << endl;
|
||||
cout << " -y <year>" << endl;
|
||||
cout << " -T <track>" << endl;
|
||||
cout << " -R <tagname> <tagvalue>" << endl;
|
||||
cout << " -I <tagname> <tagvalue>" << endl;
|
||||
cout << " -D <tagname>" << endl;
|
||||
cout << " -p <picturefile> <description> (\"\" \"\" to remove)" << endl;
|
||||
cout << endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "Usage: tagwriter <fields> <files>" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "Where the valid fields are:" << std::endl;
|
||||
std::cout << " -t <title>" << std::endl;
|
||||
std::cout << " -a <artist>" << std::endl;
|
||||
std::cout << " -A <album>" << std::endl;
|
||||
std::cout << " -c <comment>" << std::endl;
|
||||
std::cout << " -g <genre>" << std::endl;
|
||||
std::cout << " -y <year>" << std::endl;
|
||||
std::cout << " -T <track>" << std::endl;
|
||||
std::cout << " -R <tagname> <tagvalue>" << std::endl;
|
||||
std::cout << " -I <tagname> <tagvalue>" << std::endl;
|
||||
std::cout << " -D <tagname>" << std::endl;
|
||||
std::cout << " -C <complex-property-key> <key1=val1,key2=val2,...>" << std::endl;
|
||||
std::cout << " -p <picturefile> <description> (\"\" \"\" to remove)" << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
exit(1);
|
||||
}
|
||||
@@ -87,15 +87,111 @@ void checkForRejectedProperties(const TagLib::PropertyMap &tags)
|
||||
longest = i->first.size();
|
||||
}
|
||||
}
|
||||
cout << "-- rejected TAGs (properties) --" << endl;
|
||||
std::cout << "-- rejected TAGs (properties) --" << std::endl;
|
||||
for(auto i = tags.begin(); i != tags.end(); ++i) {
|
||||
for(auto j = i->second.begin(); j != i->second.end(); ++j) {
|
||||
cout << left << std::setw(longest) << i->first << " - " << '"' << *j << '"' << endl;
|
||||
std::cout << std::left << std::setw(longest) << i->first << " - " << '"' << *j << '"' << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Create a list of variant maps from a string.
|
||||
* The shorthand syntax in the string is kept simple, but should be sufficient
|
||||
* for testing. Multiple maps are separated by ';', values within a map are
|
||||
* assigned with key=value and separated by a ','. Types are detected, use
|
||||
* double quotes to force a string. A ByteVector can be constructed from the
|
||||
* contents of a file, the path is given after "file://". There is no escape
|
||||
* character, use hex codes for ',' (\x2C) or ';' (\x3B).
|
||||
*/
|
||||
TagLib::List<TagLib::VariantMap> parseComplexPropertyValues(const TagLib::String &str)
|
||||
{
|
||||
if(str.isEmpty() || str == "\"\"" || str == "''") {
|
||||
return {};
|
||||
}
|
||||
TagLib::List<TagLib::VariantMap> values;
|
||||
const auto valueStrs = str.split(";");
|
||||
for(const auto &valueStr : valueStrs) {
|
||||
TagLib::VariantMap value;
|
||||
const auto keyValStrs = valueStr.split(",");
|
||||
for(const auto &keyValStr : keyValStrs) {
|
||||
if(int equalPos = keyValStr.find('='); equalPos != -1) {
|
||||
TagLib::String key = keyValStr.substr(0, equalPos);
|
||||
TagLib::String valStr = keyValStr.substr(equalPos + 1);
|
||||
bool hasDot = false;
|
||||
bool hasNonNumeric = false;
|
||||
bool hasSign = false;
|
||||
for(auto it = valStr.cbegin(); it != valStr.cend(); ++it) {
|
||||
if(it == valStr.cbegin() && (*it == '-' || *it == '+')) {
|
||||
hasSign = true;
|
||||
}
|
||||
else if(*it == '.') {
|
||||
hasDot = true;
|
||||
}
|
||||
else if(*it < '0' || *it > '9') {
|
||||
hasNonNumeric = true;
|
||||
}
|
||||
}
|
||||
TagLib::Variant val;
|
||||
if(valStr == "null") {
|
||||
// keep empty variant
|
||||
}
|
||||
else if(valStr == "true" || valStr == "false") {
|
||||
val = TagLib::Variant(valStr == "true");
|
||||
}
|
||||
else if(!hasNonNumeric && hasDot) {
|
||||
val = TagLib::Variant(std::stod(valStr.to8Bit()));
|
||||
}
|
||||
else if(!hasNonNumeric && hasSign) {
|
||||
val = valStr.toLongLong(nullptr);
|
||||
}
|
||||
else if(!hasNonNumeric) {
|
||||
val = valStr.toULongLong(nullptr);
|
||||
}
|
||||
else if(valStr.startsWith("file://")) {
|
||||
auto filePath = valStr.substr(7 );
|
||||
if(isFile(filePath.toCString())) {
|
||||
std::ifstream fs;
|
||||
fs.open(filePath.toCString(), std::ios::in | std::ios::binary);
|
||||
std::stringstream buffer;
|
||||
buffer << fs.rdbuf();
|
||||
fs.close();
|
||||
TagLib::String buf(buffer.str());
|
||||
val = TagLib::Variant(buf.data(TagLib::String::Latin1));
|
||||
}
|
||||
else {
|
||||
std::cout << filePath.toCString() << " not found." << std::endl;
|
||||
val = TagLib::Variant(TagLib::ByteVector());
|
||||
}
|
||||
}
|
||||
else {
|
||||
int len = valStr.size();
|
||||
if(len >= 2 && valStr[0] == '"' && valStr[len - 1] == '"') {
|
||||
valStr = valStr.substr(1, len - 2);
|
||||
}
|
||||
int hexPos = 0;
|
||||
while((hexPos = valStr.find("\\x", hexPos)) != -1) {
|
||||
char ch;
|
||||
bool ok;
|
||||
if(static_cast<int>(valStr.length()) < hexPos + 4 ||
|
||||
(ch = static_cast<char>(
|
||||
valStr.substr(hexPos + 2, 2).toLongLong(&ok, 16)), !ok)) {
|
||||
break;
|
||||
}
|
||||
valStr = valStr.substr(0, hexPos) + ch + valStr.substr(hexPos + 4);
|
||||
++hexPos;
|
||||
}
|
||||
val = TagLib::Variant(valStr);
|
||||
}
|
||||
value.insert(key, val);
|
||||
}
|
||||
}
|
||||
values.append(value);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TagLib::List<TagLib::FileRef> fileList;
|
||||
@@ -171,17 +267,30 @@ int main(int argc, char *argv[])
|
||||
checkForRejectedProperties(f.setProperties(map));
|
||||
break;
|
||||
}
|
||||
case 'C': {
|
||||
if(i + 2 < argc) {
|
||||
numArgsConsumed = 3;
|
||||
if(!value.isEmpty()) {
|
||||
TagLib::List<TagLib::VariantMap> values = parseComplexPropertyValues(argv[i + 2]);
|
||||
f.setComplexProperties(value, values);
|
||||
}
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
if(i + 2 < argc) {
|
||||
numArgsConsumed = 3;
|
||||
if(!value.isEmpty()) {
|
||||
if(!isFile(value.toCString())) {
|
||||
cout << value.toCString() << " not found." << endl;
|
||||
std::cout << value.toCString() << " not found." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
ifstream picture;
|
||||
picture.open(value.toCString());
|
||||
stringstream buffer;
|
||||
std::ifstream picture;
|
||||
picture.open(value.toCString(), std::ios::in | std::ios::binary);
|
||||
std::stringstream buffer;
|
||||
buffer << picture.rdbuf();
|
||||
picture.close();
|
||||
TagLib::String buf(buffer.str());
|
||||
|
||||
@@ -1,33 +1,78 @@
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
include_directories(
|
||||
set(tag_HDR_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/toolkit
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/asf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mpeg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg/flac
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/flac
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mpc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mp4
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg/vorbis
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg/speex
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg/opus
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v2
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v2/frames
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v1
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ape
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wavpack
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/trueaudio
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/riff
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/riff/aiff
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/riff/wav
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mod
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/s3m
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/it
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dsf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dsdiff
|
||||
)
|
||||
if(WITH_ASF)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/asf
|
||||
)
|
||||
endif()
|
||||
if(WITH_VORBIS)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg/flac
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/flac
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg/vorbis
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg/speex
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ogg/opus
|
||||
)
|
||||
endif()
|
||||
if(WITH_APE)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mpc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ape
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/wavpack
|
||||
)
|
||||
endif()
|
||||
if(WITH_MP4)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mp4
|
||||
)
|
||||
endif()
|
||||
if(WITH_TRUEAUDIO)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/trueaudio
|
||||
)
|
||||
endif()
|
||||
if(WITH_RIFF)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/riff
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/riff/aiff
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/riff/wav
|
||||
)
|
||||
endif()
|
||||
if(WITH_MOD)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mod
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/s3m
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/it
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xm
|
||||
)
|
||||
endif()
|
||||
if(WITH_DSF)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dsf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dsdiff
|
||||
)
|
||||
endif()
|
||||
if(WITH_SHORTEN)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shorten
|
||||
)
|
||||
endif()
|
||||
if(WITH_MATROSKA)
|
||||
set(tag_HDR_DIRS ${tag_HDR_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/matroska
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/matroska/ebml
|
||||
)
|
||||
endif()
|
||||
include_directories(${tag_HDR_DIRS})
|
||||
|
||||
set(tag_PRIVATE_HDRS)
|
||||
set(tag_HDRS
|
||||
tag.h
|
||||
fileref.h
|
||||
@@ -83,66 +128,141 @@ set(tag_HDRS
|
||||
mpeg/id3v2/frames/chapterframe.h
|
||||
mpeg/id3v2/frames/tableofcontentsframe.h
|
||||
mpeg/id3v2/frames/podcastframe.h
|
||||
ogg/oggfile.h
|
||||
ogg/oggpage.h
|
||||
ogg/oggpageheader.h
|
||||
ogg/xiphcomment.h
|
||||
ogg/vorbis/vorbisfile.h
|
||||
ogg/vorbis/vorbisproperties.h
|
||||
ogg/flac/oggflacfile.h
|
||||
ogg/speex/speexfile.h
|
||||
ogg/speex/speexproperties.h
|
||||
ogg/opus/opusfile.h
|
||||
ogg/opus/opusproperties.h
|
||||
flac/flacfile.h
|
||||
flac/flacpicture.h
|
||||
flac/flacproperties.h
|
||||
flac/flacmetadatablock.h
|
||||
ape/apefile.h
|
||||
ape/apeproperties.h
|
||||
ape/apetag.h
|
||||
ape/apefooter.h
|
||||
ape/apeitem.h
|
||||
mpc/mpcfile.h
|
||||
mpc/mpcproperties.h
|
||||
wavpack/wavpackfile.h
|
||||
wavpack/wavpackproperties.h
|
||||
trueaudio/trueaudiofile.h
|
||||
trueaudio/trueaudioproperties.h
|
||||
riff/rifffile.h
|
||||
riff/aiff/aifffile.h
|
||||
riff/aiff/aiffproperties.h
|
||||
riff/wav/wavfile.h
|
||||
riff/wav/wavproperties.h
|
||||
riff/wav/infotag.h
|
||||
asf/asffile.h
|
||||
asf/asfproperties.h
|
||||
asf/asftag.h
|
||||
asf/asfattribute.h
|
||||
asf/asfpicture.h
|
||||
mp4/mp4file.h
|
||||
mp4/mp4atom.h
|
||||
mp4/mp4tag.h
|
||||
mp4/mp4item.h
|
||||
mp4/mp4properties.h
|
||||
mp4/mp4coverart.h
|
||||
mp4/mp4itemfactory.h
|
||||
mod/modfilebase.h
|
||||
mod/modfile.h
|
||||
mod/modtag.h
|
||||
mod/modproperties.h
|
||||
it/itfile.h
|
||||
it/itproperties.h
|
||||
s3m/s3mfile.h
|
||||
s3m/s3mproperties.h
|
||||
xm/xmfile.h
|
||||
xm/xmproperties.h
|
||||
dsf/dsffile.h
|
||||
dsf/dsfproperties.h
|
||||
dsdiff/dsdifffile.h
|
||||
dsdiff/dsdiffproperties.h
|
||||
dsdiff/dsdiffdiintag.h
|
||||
)
|
||||
if(WITH_VORBIS)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
ogg/oggfile.h
|
||||
ogg/oggpage.h
|
||||
ogg/oggpageheader.h
|
||||
ogg/xiphcomment.h
|
||||
ogg/vorbis/vorbisfile.h
|
||||
ogg/vorbis/vorbisproperties.h
|
||||
ogg/flac/oggflacfile.h
|
||||
ogg/speex/speexfile.h
|
||||
ogg/speex/speexproperties.h
|
||||
ogg/opus/opusfile.h
|
||||
ogg/opus/opusproperties.h
|
||||
flac/flacfile.h
|
||||
flac/flacpicture.h
|
||||
flac/flacproperties.h
|
||||
flac/flacmetadatablock.h
|
||||
)
|
||||
endif()
|
||||
if(WITH_APE)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
ape/apefile.h
|
||||
ape/apeproperties.h
|
||||
ape/apetag.h
|
||||
ape/apefooter.h
|
||||
ape/apeitem.h
|
||||
mpc/mpcfile.h
|
||||
mpc/mpcproperties.h
|
||||
wavpack/wavpackfile.h
|
||||
wavpack/wavpackproperties.h
|
||||
)
|
||||
endif()
|
||||
if(WITH_TRUEAUDIO)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
trueaudio/trueaudiofile.h
|
||||
trueaudio/trueaudioproperties.h
|
||||
)
|
||||
endif()
|
||||
if(WITH_RIFF)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
riff/rifffile.h
|
||||
riff/aiff/aifffile.h
|
||||
riff/aiff/aiffproperties.h
|
||||
riff/wav/wavfile.h
|
||||
riff/wav/wavproperties.h
|
||||
riff/wav/infotag.h
|
||||
)
|
||||
endif()
|
||||
if(WITH_ASF)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
asf/asffile.h
|
||||
asf/asfproperties.h
|
||||
asf/asftag.h
|
||||
asf/asfattribute.h
|
||||
asf/asfpicture.h
|
||||
)
|
||||
endif()
|
||||
if(WITH_MP4)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
mp4/mp4file.h
|
||||
mp4/mp4atom.h
|
||||
mp4/mp4tag.h
|
||||
mp4/mp4item.h
|
||||
mp4/mp4properties.h
|
||||
mp4/mp4coverart.h
|
||||
mp4/mp4stem.h
|
||||
mp4/mp4itemfactory.h
|
||||
)
|
||||
endif()
|
||||
if(WITH_MOD)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
mod/modfilebase.h
|
||||
mod/modfile.h
|
||||
mod/modtag.h
|
||||
mod/modproperties.h
|
||||
it/itfile.h
|
||||
it/itproperties.h
|
||||
s3m/s3mfile.h
|
||||
s3m/s3mproperties.h
|
||||
xm/xmfile.h
|
||||
xm/xmproperties.h
|
||||
)
|
||||
endif()
|
||||
if(WITH_DSF)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
dsf/dsffile.h
|
||||
dsf/dsfproperties.h
|
||||
dsdiff/dsdifffile.h
|
||||
dsdiff/dsdiffproperties.h
|
||||
dsdiff/dsdiffdiintag.h
|
||||
)
|
||||
endif()
|
||||
if(WITH_SHORTEN)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
shorten/shortenfile.h
|
||||
shorten/shortenproperties.h
|
||||
shorten/shortentag.h
|
||||
)
|
||||
endif()
|
||||
if(WITH_MATROSKA)
|
||||
set(tag_HDRS ${tag_HDRS}
|
||||
matroska/matroskaattachedfile.h
|
||||
matroska/matroskaattachments.h
|
||||
matroska/matroskachapter.h
|
||||
matroska/matroskachapteredition.h
|
||||
matroska/matroskachapters.h
|
||||
matroska/matroskaelement.h
|
||||
matroska/matroskafile.h
|
||||
matroska/matroskaproperties.h
|
||||
matroska/matroskasimpletag.h
|
||||
matroska/matroskatag.h
|
||||
)
|
||||
set(tag_PRIVATE_HDRS ${tag_PRIVATE_HDRS}
|
||||
matroska/ebml/ebmlbinaryelement.h
|
||||
matroska/ebml/ebmlelement.h
|
||||
matroska/ebml/ebmlmasterelement.h
|
||||
matroska/ebml/ebmlmkattachments.h
|
||||
matroska/ebml/ebmlmkchapters.h
|
||||
matroska/ebml/ebmlmkcues.h
|
||||
matroska/ebml/ebmlmkseekhead.h
|
||||
matroska/ebml/ebmlmksegment.h
|
||||
matroska/ebml/ebmlmkinfo.h
|
||||
matroska/ebml/ebmlmktracks.h
|
||||
matroska/ebml/ebmlmktags.h
|
||||
matroska/ebml/ebmlstringelement.h
|
||||
matroska/ebml/ebmluintelement.h
|
||||
matroska/ebml/ebmlfloatelement.h
|
||||
matroska/ebml/ebmlutils.h
|
||||
matroska/ebml/ebmlvoidelement.h
|
||||
matroska/matroskacues.h
|
||||
matroska/matroskaseekhead.h
|
||||
matroska/matroskasegment.h
|
||||
)
|
||||
endif()
|
||||
|
||||
set(mpeg_SRCS
|
||||
mpeg/mpegfile.cpp
|
||||
@@ -186,128 +306,190 @@ set(frames_SRCS
|
||||
mpeg/id3v2/frames/podcastframe.cpp
|
||||
)
|
||||
|
||||
set(ogg_SRCS
|
||||
ogg/oggfile.cpp
|
||||
ogg/oggpage.cpp
|
||||
ogg/oggpageheader.cpp
|
||||
ogg/xiphcomment.cpp
|
||||
)
|
||||
if(WITH_VORBIS)
|
||||
set(ogg_SRCS
|
||||
ogg/oggfile.cpp
|
||||
ogg/oggpage.cpp
|
||||
ogg/oggpageheader.cpp
|
||||
ogg/xiphcomment.cpp
|
||||
)
|
||||
|
||||
set(vorbis_SRCS
|
||||
ogg/vorbis/vorbisfile.cpp
|
||||
ogg/vorbis/vorbisproperties.cpp
|
||||
)
|
||||
set(vorbis_SRCS
|
||||
ogg/vorbis/vorbisfile.cpp
|
||||
ogg/vorbis/vorbisproperties.cpp
|
||||
)
|
||||
|
||||
set(flacs_SRCS
|
||||
flac/flacfile.cpp
|
||||
flac/flacpicture.cpp
|
||||
flac/flacproperties.cpp
|
||||
flac/flacmetadatablock.cpp
|
||||
flac/flacunknownmetadatablock.cpp
|
||||
)
|
||||
set(flacs_SRCS
|
||||
flac/flacfile.cpp
|
||||
flac/flacpicture.cpp
|
||||
flac/flacproperties.cpp
|
||||
flac/flacmetadatablock.cpp
|
||||
flac/flacunknownmetadatablock.cpp
|
||||
)
|
||||
|
||||
set(oggflacs_SRCS
|
||||
ogg/flac/oggflacfile.cpp
|
||||
)
|
||||
set(oggflacs_SRCS
|
||||
ogg/flac/oggflacfile.cpp
|
||||
)
|
||||
|
||||
set(mpc_SRCS
|
||||
mpc/mpcfile.cpp
|
||||
mpc/mpcproperties.cpp
|
||||
)
|
||||
set(speex_SRCS
|
||||
ogg/speex/speexfile.cpp
|
||||
ogg/speex/speexproperties.cpp
|
||||
)
|
||||
|
||||
set(mp4_SRCS
|
||||
mp4/mp4file.cpp
|
||||
mp4/mp4atom.cpp
|
||||
mp4/mp4tag.cpp
|
||||
mp4/mp4item.cpp
|
||||
mp4/mp4properties.cpp
|
||||
mp4/mp4coverart.cpp
|
||||
mp4/mp4itemfactory.cpp
|
||||
)
|
||||
set(opus_SRCS
|
||||
ogg/opus/opusfile.cpp
|
||||
ogg/opus/opusproperties.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(ape_SRCS
|
||||
ape/apetag.cpp
|
||||
ape/apefooter.cpp
|
||||
ape/apeitem.cpp
|
||||
ape/apefile.cpp
|
||||
ape/apeproperties.cpp
|
||||
)
|
||||
if(WITH_APE)
|
||||
set(mpc_SRCS
|
||||
mpc/mpcfile.cpp
|
||||
mpc/mpcproperties.cpp
|
||||
)
|
||||
|
||||
set(wavpack_SRCS
|
||||
wavpack/wavpackfile.cpp
|
||||
wavpack/wavpackproperties.cpp
|
||||
)
|
||||
set(ape_SRCS
|
||||
ape/apetag.cpp
|
||||
ape/apefooter.cpp
|
||||
ape/apeitem.cpp
|
||||
ape/apefile.cpp
|
||||
ape/apeproperties.cpp
|
||||
)
|
||||
|
||||
set(speex_SRCS
|
||||
ogg/speex/speexfile.cpp
|
||||
ogg/speex/speexproperties.cpp
|
||||
)
|
||||
set(wavpack_SRCS
|
||||
wavpack/wavpackfile.cpp
|
||||
wavpack/wavpackproperties.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(opus_SRCS
|
||||
ogg/opus/opusfile.cpp
|
||||
ogg/opus/opusproperties.cpp
|
||||
)
|
||||
if(WITH_MP4)
|
||||
set(mp4_SRCS
|
||||
mp4/mp4file.cpp
|
||||
mp4/mp4atom.cpp
|
||||
mp4/mp4tag.cpp
|
||||
mp4/mp4item.cpp
|
||||
mp4/mp4properties.cpp
|
||||
mp4/mp4coverart.cpp
|
||||
mp4/mp4stem.cpp
|
||||
mp4/mp4itemfactory.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(trueaudio_SRCS
|
||||
trueaudio/trueaudiofile.cpp
|
||||
trueaudio/trueaudioproperties.cpp
|
||||
)
|
||||
if(WITH_TRUEAUDIO)
|
||||
set(trueaudio_SRCS
|
||||
trueaudio/trueaudiofile.cpp
|
||||
trueaudio/trueaudioproperties.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(asf_SRCS
|
||||
asf/asftag.cpp
|
||||
asf/asffile.cpp
|
||||
asf/asfproperties.cpp
|
||||
asf/asfattribute.cpp
|
||||
asf/asfpicture.cpp
|
||||
)
|
||||
if(WITH_ASF)
|
||||
set(asf_SRCS
|
||||
asf/asftag.cpp
|
||||
asf/asffile.cpp
|
||||
asf/asfproperties.cpp
|
||||
asf/asfattribute.cpp
|
||||
asf/asfpicture.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(riff_SRCS
|
||||
riff/rifffile.cpp
|
||||
)
|
||||
if(WITH_RIFF)
|
||||
set(riff_SRCS
|
||||
riff/rifffile.cpp
|
||||
)
|
||||
|
||||
set(aiff_SRCS
|
||||
riff/aiff/aifffile.cpp
|
||||
riff/aiff/aiffproperties.cpp
|
||||
)
|
||||
set(aiff_SRCS
|
||||
riff/aiff/aifffile.cpp
|
||||
riff/aiff/aiffproperties.cpp
|
||||
)
|
||||
|
||||
set(wav_SRCS
|
||||
riff/wav/wavfile.cpp
|
||||
riff/wav/wavproperties.cpp
|
||||
riff/wav/infotag.cpp
|
||||
)
|
||||
set(wav_SRCS
|
||||
riff/wav/wavfile.cpp
|
||||
riff/wav/wavproperties.cpp
|
||||
riff/wav/infotag.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(mod_SRCS
|
||||
mod/modfilebase.cpp
|
||||
mod/modfile.cpp
|
||||
mod/modtag.cpp
|
||||
mod/modproperties.cpp
|
||||
)
|
||||
if(WITH_MOD)
|
||||
set(mod_SRCS
|
||||
mod/modfilebase.cpp
|
||||
mod/modfile.cpp
|
||||
mod/modtag.cpp
|
||||
mod/modproperties.cpp
|
||||
)
|
||||
|
||||
set(s3m_SRCS
|
||||
s3m/s3mfile.cpp
|
||||
s3m/s3mproperties.cpp
|
||||
)
|
||||
set(s3m_SRCS
|
||||
s3m/s3mfile.cpp
|
||||
s3m/s3mproperties.cpp
|
||||
)
|
||||
|
||||
set(it_SRCS
|
||||
it/itfile.cpp
|
||||
it/itproperties.cpp
|
||||
)
|
||||
set(it_SRCS
|
||||
it/itfile.cpp
|
||||
it/itproperties.cpp
|
||||
)
|
||||
|
||||
set(xm_SRCS
|
||||
xm/xmfile.cpp
|
||||
xm/xmproperties.cpp
|
||||
)
|
||||
set(xm_SRCS
|
||||
xm/xmfile.cpp
|
||||
xm/xmproperties.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(dsf_SRCS
|
||||
dsf/dsffile.cpp
|
||||
dsf/dsfproperties.cpp
|
||||
)
|
||||
if(WITH_DSF)
|
||||
set(dsf_SRCS
|
||||
dsf/dsffile.cpp
|
||||
dsf/dsfproperties.cpp
|
||||
)
|
||||
|
||||
set(dsdiff_SRCS
|
||||
dsdiff/dsdifffile.cpp
|
||||
dsdiff/dsdiffproperties.cpp
|
||||
dsdiff/dsdiffdiintag.cpp
|
||||
)
|
||||
set(dsdiff_SRCS
|
||||
dsdiff/dsdifffile.cpp
|
||||
dsdiff/dsdiffproperties.cpp
|
||||
dsdiff/dsdiffdiintag.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_SHORTEN)
|
||||
set(shorten_SRCS
|
||||
shorten/shortenfile.cpp
|
||||
shorten/shortenproperties.cpp
|
||||
shorten/shortentag.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_MATROSKA)
|
||||
set(matroska_SRCS
|
||||
matroska/matroskaattachedfile.cpp
|
||||
matroska/matroskaattachments.cpp
|
||||
matroska/matroskachapter.cpp
|
||||
matroska/matroskachapteredition.cpp
|
||||
matroska/matroskachapters.cpp
|
||||
matroska/matroskacues.cpp
|
||||
matroska/matroskaelement.cpp
|
||||
matroska/matroskafile.cpp
|
||||
matroska/matroskaproperties.cpp
|
||||
matroska/matroskaseekhead.cpp
|
||||
matroska/matroskasegment.cpp
|
||||
matroska/matroskasimpletag.cpp
|
||||
matroska/matroskatag.cpp
|
||||
)
|
||||
|
||||
set(ebml_SRCS
|
||||
matroska/ebml/ebmlbinaryelement.cpp
|
||||
matroska/ebml/ebmlelement.cpp
|
||||
matroska/ebml/ebmlmasterelement.cpp
|
||||
matroska/ebml/ebmlmkattachments.cpp
|
||||
matroska/ebml/ebmlmkchapters.cpp
|
||||
matroska/ebml/ebmlmkcues.cpp
|
||||
matroska/ebml/ebmlmkseekhead.cpp
|
||||
matroska/ebml/ebmlmksegment.cpp
|
||||
matroska/ebml/ebmlmkinfo.cpp
|
||||
matroska/ebml/ebmlmktracks.cpp
|
||||
matroska/ebml/ebmlmktags.cpp
|
||||
matroska/ebml/ebmlstringelement.cpp
|
||||
matroska/ebml/ebmluintelement.cpp
|
||||
matroska/ebml/ebmlfloatelement.cpp
|
||||
matroska/ebml/ebmlutils.cpp
|
||||
matroska/ebml/ebmlvoidelement.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(toolkit_SRCS
|
||||
toolkit/tstring.cpp
|
||||
@@ -332,7 +514,7 @@ set(tag_LIB_SRCS
|
||||
${vorbis_SRCS} ${oggflacs_SRCS} ${mpc_SRCS} ${ape_SRCS} ${toolkit_SRCS} ${flacs_SRCS}
|
||||
${wavpack_SRCS} ${speex_SRCS} ${trueaudio_SRCS} ${riff_SRCS} ${aiff_SRCS} ${wav_SRCS}
|
||||
${asf_SRCS} ${mp4_SRCS} ${mod_SRCS} ${s3m_SRCS} ${it_SRCS} ${xm_SRCS} ${opus_SRCS}
|
||||
${dsf_SRCS} ${dsdiff_SRCS}
|
||||
${dsf_SRCS} ${dsdiff_SRCS} ${shorten_SRCS} ${matroska_SRCS} ${ebml_SRCS}
|
||||
tag.cpp
|
||||
tagunion.cpp
|
||||
fileref.cpp
|
||||
@@ -340,7 +522,7 @@ set(tag_LIB_SRCS
|
||||
tagutils.cpp
|
||||
)
|
||||
|
||||
add_library(tag ${tag_LIB_SRCS} ${tag_HDRS})
|
||||
add_library(tag ${tag_LIB_SRCS} ${tag_HDRS} ${tag_PRIVATE_HDRS})
|
||||
|
||||
target_include_directories(tag INTERFACE
|
||||
$<INSTALL_INTERFACE:include>
|
||||
@@ -348,7 +530,7 @@ target_include_directories(tag INTERFACE
|
||||
)
|
||||
|
||||
target_link_libraries(tag
|
||||
PRIVATE $<$<TARGET_EXISTS:utf8::cpp>:utf8::cpp>
|
||||
PRIVATE $<IF:$<TARGET_EXISTS:utf8::cpp>,utf8::cpp,$<$<TARGET_EXISTS:utf8cpp>:utf8cpp>>
|
||||
$<$<TARGET_EXISTS:ZLIB::ZLIB>:ZLIB::ZLIB>
|
||||
)
|
||||
|
||||
@@ -360,6 +542,9 @@ set_target_properties(tag PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "${ZLIB_INTERFACE_LINK_LIBRARIES}"
|
||||
PUBLIC_HEADER "${tag_HDRS}"
|
||||
)
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(tag PUBLIC TAGLIB_STATIC)
|
||||
endif()
|
||||
if(VISIBILITY_HIDDEN)
|
||||
set_target_properties(tag PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
set_target_properties(tag PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
|
||||
@@ -75,7 +75,7 @@ bool APE::File::isSupported(IOStream *stream)
|
||||
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
||||
return (buffer.find("MAC ") >= 0);
|
||||
return buffer.find("MAC ") >= 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -178,7 +178,7 @@ bool APE::File::save()
|
||||
insert(data, d->APELocation, d->APESize);
|
||||
|
||||
if(d->ID3v1Location >= 0)
|
||||
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
|
||||
d->ID3v1Location += static_cast<long>(data.size()) - d->APESize;
|
||||
|
||||
d->APESize = data.size();
|
||||
}
|
||||
@@ -224,12 +224,12 @@ void APE::File::strip(int tags)
|
||||
|
||||
bool APE::File::hasAPETag() const
|
||||
{
|
||||
return (d->APELocation >= 0);
|
||||
return d->APELocation >= 0;
|
||||
}
|
||||
|
||||
bool APE::File::hasID3v1Tag() const
|
||||
{
|
||||
return (d->ID3v1Location >= 0);
|
||||
return d->ID3v1Location >= 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -283,7 +283,7 @@ void APE::File::read(bool readProperties)
|
||||
|
||||
if(d->ID3v2Location >= 0) {
|
||||
seek(d->ID3v2Location + d->ID3v2Size);
|
||||
streamLength -= (d->ID3v2Location + d->ID3v2Size);
|
||||
streamLength -= d->ID3v2Location + d->ID3v2Size;
|
||||
}
|
||||
else {
|
||||
seek(0);
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace TagLib {
|
||||
//! An implementation of APE metadata
|
||||
|
||||
/*!
|
||||
* This is implementation of APE metadata.
|
||||
* This is an implementation of APE metadata.
|
||||
*
|
||||
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
|
||||
* properties from the file.
|
||||
@@ -84,7 +84,7 @@ namespace TagLib {
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constructs an APE file from \a file. If \a readProperties is true the
|
||||
* Constructs an APE file from \a file. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
@@ -93,7 +93,7 @@ namespace TagLib {
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
* Constructs an APE file from \a stream. If \a readProperties is true the
|
||||
* Constructs an APE file from \a stream. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
@@ -155,15 +155,15 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns a pointer to the ID3v1 tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this may return a null pointer
|
||||
* if there is no valid ID3v1 tag. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this may return a null pointer
|
||||
* if there is no valid ID3v1 tag. If \a create is \c true it will create
|
||||
* an ID3v1 tag if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
|
||||
* on disk actually has an ID3v1 tag.
|
||||
*
|
||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||
* \note The Tag <b>is still</b> owned by the APE::File and should not be
|
||||
* deleted by the user. It will be deleted when the file (object) is
|
||||
* destroyed.
|
||||
*
|
||||
@@ -174,15 +174,15 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns a pointer to the APE tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this may return a null pointer
|
||||
* if there is no valid APE tag. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this may return a null pointer
|
||||
* if there is no valid APE tag. If \a create is \c true it will create
|
||||
* an APE tag if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
* file on disk has an APE tag. Use hasAPETag() to check if the file
|
||||
* on disk actually has an APE tag.
|
||||
*
|
||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||
* \note The Tag <b>is still</b> owned by the APE::File and should not be
|
||||
* deleted by the user. It will be deleted when the file (object) is
|
||||
* destroyed.
|
||||
*
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include <bitset>
|
||||
|
||||
#include "taglib.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace APE;
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys the footer.
|
||||
*/
|
||||
virtual ~Footer();
|
||||
~Footer();
|
||||
|
||||
Footer(const Footer &) = delete;
|
||||
Footer &operator=(const Footer &) = delete;
|
||||
@@ -70,17 +70,17 @@ namespace TagLib {
|
||||
unsigned int version() const;
|
||||
|
||||
/*!
|
||||
* Returns true if a header is present in the tag.
|
||||
* Returns \c true if a header is present in the tag.
|
||||
*/
|
||||
bool headerPresent() const;
|
||||
|
||||
/*!
|
||||
* Returns true if a footer is present in the tag.
|
||||
* Returns \c true if a footer is present in the tag.
|
||||
*/
|
||||
bool footerPresent() const;
|
||||
|
||||
/*!
|
||||
* Returns true this is actually the header.
|
||||
* Returns \c true if this is actually the header.
|
||||
*/
|
||||
bool isHeader() const;
|
||||
|
||||
@@ -145,8 +145,8 @@ namespace TagLib {
|
||||
ByteVector renderFooter() const;
|
||||
|
||||
/*!
|
||||
* Renders the header corresponding to the footer. If headerPresent is
|
||||
* set to false, it returns an empty ByteVector.
|
||||
* Renders the header corresponding to the footer. If headerPresent() is
|
||||
* \c false, it returns an empty ByteVector.
|
||||
*/
|
||||
ByteVector renderHeader() const;
|
||||
|
||||
|
||||
@@ -141,10 +141,10 @@ void APE::Item::setValue(const String &value)
|
||||
d->value.clear();
|
||||
}
|
||||
|
||||
void APE::Item::setValues(const StringList &value)
|
||||
void APE::Item::setValues(const StringList &values)
|
||||
{
|
||||
d->type = Text;
|
||||
d->text = value;
|
||||
d->text = values;
|
||||
d->value.clear();
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ void APE::Item::parse(const ByteVector &data)
|
||||
ByteVector APE::Item::render() const
|
||||
{
|
||||
ByteVector data;
|
||||
unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
|
||||
unsigned int flags = (d->readOnly ? 1 : 0) | (d->type << 1);
|
||||
ByteVector val;
|
||||
|
||||
if(isEmpty())
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Constructs an item with \a key and \a value.
|
||||
* If \a binary is true a Binary item will be created, otherwise \a value will be interpreted as text
|
||||
* If \a binary is \c true a Binary item will be created, otherwise \a value will be interpreted as text
|
||||
*/
|
||||
Item(const String &key, const ByteVector &value, bool binary);
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys the item.
|
||||
*/
|
||||
virtual ~Item();
|
||||
~Item();
|
||||
|
||||
/*!
|
||||
* Copies the contents of \a item into this item.
|
||||
@@ -83,7 +83,7 @@ namespace TagLib {
|
||||
Item &operator=(const Item &item);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of this item by the content of \a item.
|
||||
* Exchanges the content of this item with the content of \a item.
|
||||
*/
|
||||
void swap(Item &item) noexcept;
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace TagLib {
|
||||
void setReadOnly(bool readOnly);
|
||||
|
||||
/*!
|
||||
* Return true if the item is read-only.
|
||||
* Return \c true if the item is read-only.
|
||||
*/
|
||||
bool isReadOnly() const;
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace TagLib {
|
||||
ItemTypes type() const;
|
||||
|
||||
/*!
|
||||
* Returns if the item has any real content.
|
||||
* Returns \c false if the item has any real content.
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
|
||||
@@ -137,9 +137,9 @@ void APE::Properties::read(File *file, offset_t streamLength)
|
||||
analyzeOld(file);
|
||||
|
||||
if(d->sampleFrames > 0 && d->sampleRate > 0) {
|
||||
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
|
||||
const auto length = static_cast<double>(d->sampleFrames) * 1000.0 / d->sampleRate;
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
|
||||
d->bitrate = static_cast<int>(static_cast<double>(streamLength) * 8.0 / length + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,9 +153,8 @@ void APE::Properties::analyzeCurrent(File *file)
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned int descriptorBytes = descriptor.toUInt(0, false);
|
||||
|
||||
if((descriptorBytes - 52) > 0)
|
||||
if(const unsigned int descriptorBytes = descriptor.toUInt(0, false);
|
||||
descriptorBytes - 52 > 0)
|
||||
file->seek(descriptorBytes - 52, File::Current);
|
||||
|
||||
// Read the header
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace TagLib {
|
||||
unsigned int sampleFrames() const;
|
||||
|
||||
/*!
|
||||
* Returns APE version.
|
||||
* Returns the APE version.
|
||||
*/
|
||||
int version() const;
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ using namespace APE;
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned int MinKeyLength = 2;
|
||||
const unsigned int MaxKeyLength = 255;
|
||||
constexpr unsigned int MinKeyLength = 2;
|
||||
constexpr unsigned int MaxKeyLength = 255;
|
||||
|
||||
const String FRONT_COVER("COVER ART (FRONT)");
|
||||
const String BACK_COVER("COVER ART (BACK)");
|
||||
@@ -203,10 +203,10 @@ PropertyMap APE::Tag::properties() const
|
||||
{
|
||||
PropertyMap properties;
|
||||
for(const auto &[tag, item] : std::as_const(itemListMap())) {
|
||||
String tagName = tag.upper();
|
||||
// if the item is Binary or Locator, or if the key is an invalid string,
|
||||
// add to unsupportedData
|
||||
if(item.type() != Item::Text || tagName.isEmpty()) {
|
||||
if(String tagName = tag.upper();
|
||||
item.type() != Item::Text || tagName.isEmpty()) {
|
||||
properties.addUnsupportedData(tag);
|
||||
}
|
||||
else {
|
||||
@@ -241,9 +241,9 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
|
||||
// first check if tags need to be removed completely
|
||||
StringList toRemove;
|
||||
for(const auto &[k, t] : std::as_const(itemListMap())) {
|
||||
String key = k.upper();
|
||||
// only remove if a) key is valid, b) type is text, c) key not contained in new properties
|
||||
if(!key.isEmpty() && t.type() == APE::Item::Text && !props.contains(key))
|
||||
if(String key = k.upper();
|
||||
!key.isEmpty() && t.type() == APE::Item::Text && !props.contains(key))
|
||||
toRemove.append(k);
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
|
||||
for(const auto &[tagName, val] : std::as_const(props)) {
|
||||
if(!checkKey(tagName))
|
||||
invalid.insert(tagName, val);
|
||||
else if(!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == val)) {
|
||||
else if(!itemListMap().contains(tagName) || itemListMap()[tagName].values() != val) {
|
||||
if(val.isEmpty())
|
||||
removeItem(tagName);
|
||||
else {
|
||||
@@ -281,13 +281,12 @@ StringList APE::Tag::complexPropertyKeys() const
|
||||
List<VariantMap> APE::Tag::complexProperties(const String &key) const
|
||||
{
|
||||
List<VariantMap> props;
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
const StringList itemNames = StringList(FRONT_COVER).append(BACK_COVER);
|
||||
for(const auto &itemName: itemNames) {
|
||||
if(d->itemListMap.contains(itemName)) {
|
||||
Item picture = d->itemListMap.value(itemName);
|
||||
if(picture.type() == Item::Binary) {
|
||||
if(Item picture = d->itemListMap.value(itemName);
|
||||
picture.type() == Item::Binary) {
|
||||
ByteVector data = picture.binaryData();
|
||||
// Do not search for a description if the first byte could start JPG or PNG
|
||||
// data.
|
||||
@@ -316,8 +315,7 @@ List<VariantMap> APE::Tag::complexProperties(const String &key) const
|
||||
|
||||
bool APE::Tag::setComplexProperties(const String &key, const List<VariantMap> &value)
|
||||
{
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
removeItem(FRONT_COVER);
|
||||
removeItem(BACK_COVER);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "tbytevector.h"
|
||||
#include "tmap.h"
|
||||
#include "tstring.h"
|
||||
#include "taglib.h"
|
||||
#include "taglib_export.h"
|
||||
#include "tag.h"
|
||||
#include "apeitem.h"
|
||||
@@ -116,6 +117,7 @@ namespace TagLib {
|
||||
*
|
||||
* The only conversion done by this export function is to rename the APE tags
|
||||
* TRACK to TRACKNUMBER, YEAR to DATE, and ALBUM ARTIST to ALBUMARTIST, respectively,
|
||||
* (and a few other keys, see \ref p_propertymapping)
|
||||
* in order to be compliant with the names used in other formats.
|
||||
*/
|
||||
PropertyMap properties() const override;
|
||||
@@ -165,7 +167,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Adds to the text item specified by \a key the data \a value. If \a replace
|
||||
* is true, then all of the other values on the same key will be removed
|
||||
* is \c true, then all of the other values on the same key will be removed
|
||||
* first. If a binary item exists for \a key it will be removed first.
|
||||
*/
|
||||
void addValue(const String &key, const String &value, bool replace = true);
|
||||
@@ -184,7 +186,7 @@ namespace TagLib {
|
||||
void setItem(const String &key, const Item &item);
|
||||
|
||||
/*!
|
||||
* Returns true if the tag does not contain any data.
|
||||
* Returns \c true if the tag does not contain any data.
|
||||
*/
|
||||
bool isEmpty() const override;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
pictureValue(ASF::Picture::fromInvalid())
|
||||
{
|
||||
}
|
||||
AttributeTypes type;
|
||||
AttributeTypes type { UnicodeType };
|
||||
String stringValue;
|
||||
ByteVector byteVectorValue;
|
||||
ASF::Picture pictureValue;
|
||||
@@ -154,7 +154,7 @@ unsigned int ASF::Attribute::toUInt() const
|
||||
|
||||
unsigned long long ASF::Attribute::toULongLong() const
|
||||
{
|
||||
return static_cast<unsigned long long>(d->numericValue);
|
||||
return d->numericValue;
|
||||
}
|
||||
|
||||
ASF::Picture ASF::Attribute::toPicture() const
|
||||
@@ -162,30 +162,30 @@ ASF::Picture ASF::Attribute::toPicture() const
|
||||
return d->pictureValue;
|
||||
}
|
||||
|
||||
String ASF::Attribute::parse(ASF::File &f, int kind)
|
||||
String ASF::Attribute::parse(ASF::File &file, int kind)
|
||||
{
|
||||
unsigned int size, nameLength;
|
||||
String name;
|
||||
d->pictureValue = Picture::fromInvalid();
|
||||
// extended content descriptor
|
||||
if(kind == 0) {
|
||||
nameLength = readWORD(&f);
|
||||
name = readString(&f, nameLength);
|
||||
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&f));
|
||||
size = readWORD(&f);
|
||||
nameLength = readWORD(&file);
|
||||
name = readString(&file, nameLength);
|
||||
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&file));
|
||||
size = readWORD(&file);
|
||||
}
|
||||
// metadata & metadata library
|
||||
else {
|
||||
int temp = readWORD(&f);
|
||||
int temp = readWORD(&file);
|
||||
// metadata library
|
||||
if(kind == 2) {
|
||||
d->language = temp;
|
||||
}
|
||||
d->stream = readWORD(&f);
|
||||
nameLength = readWORD(&f);
|
||||
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&f));
|
||||
size = readDWORD(&f);
|
||||
name = readString(&f, nameLength);
|
||||
d->stream = readWORD(&file);
|
||||
nameLength = readWORD(&file);
|
||||
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&file));
|
||||
size = readDWORD(&file);
|
||||
name = readString(&file, nameLength);
|
||||
}
|
||||
|
||||
if(kind != 2 && size > 65535) {
|
||||
@@ -194,33 +194,33 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
|
||||
|
||||
switch(d->type) {
|
||||
case WordType:
|
||||
d->numericValue = readWORD(&f);
|
||||
d->numericValue = readWORD(&file);
|
||||
break;
|
||||
|
||||
case BoolType:
|
||||
if(kind == 0) {
|
||||
d->numericValue = (readDWORD(&f) != 0);
|
||||
d->numericValue = readDWORD(&file) != 0;
|
||||
}
|
||||
else {
|
||||
d->numericValue = (readWORD(&f) != 0);
|
||||
d->numericValue = readWORD(&file) != 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case DWordType:
|
||||
d->numericValue = readDWORD(&f);
|
||||
d->numericValue = readDWORD(&file);
|
||||
break;
|
||||
|
||||
case QWordType:
|
||||
d->numericValue = readQWORD(&f);
|
||||
d->numericValue = readQWORD(&file);
|
||||
break;
|
||||
|
||||
case UnicodeType:
|
||||
d->stringValue = readString(&f, size);
|
||||
d->stringValue = readString(&file, size);
|
||||
break;
|
||||
|
||||
case BytesType:
|
||||
case GuidType:
|
||||
d->byteVectorValue = f.readBlock(size);
|
||||
d->byteVectorValue = file.readBlock(size);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -240,7 +240,6 @@ int ASF::Attribute::dataSize() const
|
||||
case WordType:
|
||||
return 2;
|
||||
case BoolType:
|
||||
return 4;
|
||||
case DWordType:
|
||||
return 4;
|
||||
case QWordType:
|
||||
@@ -303,16 +302,16 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
|
||||
|
||||
if(kind == 0) {
|
||||
data = renderString(name, true) +
|
||||
ByteVector::fromShort(static_cast<int>(d->type), false) +
|
||||
ByteVector::fromShort(data.size(), false) +
|
||||
ByteVector::fromShort(static_cast<short>(d->type), false) +
|
||||
ByteVector::fromShort(static_cast<short>(data.size()), false) +
|
||||
data;
|
||||
}
|
||||
else {
|
||||
ByteVector nameData = renderString(name);
|
||||
data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
|
||||
ByteVector::fromShort(d->stream, false) +
|
||||
ByteVector::fromShort(nameData.size(), false) +
|
||||
ByteVector::fromShort(static_cast<int>(d->type), false) +
|
||||
data = ByteVector::fromShort(static_cast<short>(kind == 2 ? d->language : 0), false) +
|
||||
ByteVector::fromShort(static_cast<short>(d->stream), false) +
|
||||
ByteVector::fromShort(static_cast<short>(nameData.size()), false) +
|
||||
ByteVector::fromShort(static_cast<short>(d->type), false) +
|
||||
ByteVector::fromUInt(data.size(), false) +
|
||||
nameData +
|
||||
data;
|
||||
|
||||
@@ -38,6 +38,8 @@ namespace TagLib
|
||||
class File;
|
||||
class Picture;
|
||||
|
||||
//! Attribute of ASF (WMA) metadata
|
||||
|
||||
class TAGLIB_EXPORT Attribute
|
||||
{
|
||||
public:
|
||||
@@ -114,17 +116,17 @@ namespace TagLib
|
||||
Attribute &operator=(const Attribute &other);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the Attribute by the content of \a other.
|
||||
* Exchanges the content of the Attribute with the content of \a other.
|
||||
*/
|
||||
void swap(Attribute &other) noexcept;
|
||||
|
||||
/*!
|
||||
* Destroys the attribute.
|
||||
*/
|
||||
virtual ~Attribute();
|
||||
~Attribute();
|
||||
|
||||
/*!
|
||||
* Returns type of the value.
|
||||
* Returns the type of the value.
|
||||
*/
|
||||
AttributeTypes type() const;
|
||||
|
||||
|
||||
@@ -221,7 +221,8 @@ void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, long l
|
||||
|
||||
const long long duration = data.toLongLong(40, false);
|
||||
const long long preroll = data.toLongLong(56, false);
|
||||
file->d->properties->setLengthInMilliseconds(static_cast<int>(duration / 10000.0 - preroll + 0.5));
|
||||
file->d->properties->setLengthInMilliseconds(
|
||||
static_cast<int>(static_cast<double>(duration) / 10000.0 - static_cast<double>(preroll) + 0.5));
|
||||
}
|
||||
|
||||
ByteVector ASF::File::FilePrivate::StreamPropertiesObject::guid() const
|
||||
@@ -271,11 +272,11 @@ ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *f
|
||||
const ByteVector v4 = renderString(file->d->tag->comment());
|
||||
const ByteVector v5 = renderString(file->d->tag->rating());
|
||||
data.clear();
|
||||
data.append(ByteVector::fromShort(v1.size(), false));
|
||||
data.append(ByteVector::fromShort(v2.size(), false));
|
||||
data.append(ByteVector::fromShort(v3.size(), false));
|
||||
data.append(ByteVector::fromShort(v4.size(), false));
|
||||
data.append(ByteVector::fromShort(v5.size(), false));
|
||||
data.append(ByteVector::fromShort(static_cast<short>(v1.size()), false));
|
||||
data.append(ByteVector::fromShort(static_cast<short>(v2.size()), false));
|
||||
data.append(ByteVector::fromShort(static_cast<short>(v3.size()), false));
|
||||
data.append(ByteVector::fromShort(static_cast<short>(v4.size()), false));
|
||||
data.append(ByteVector::fromShort(static_cast<short>(v5.size()), false));
|
||||
data.append(v1);
|
||||
data.append(v2);
|
||||
data.append(v3);
|
||||
@@ -302,7 +303,7 @@ void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *
|
||||
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::render(ASF::File *file)
|
||||
{
|
||||
data.clear();
|
||||
data.append(ByteVector::fromShort(attributeData.size(), false));
|
||||
data.append(ByteVector::fromShort(static_cast<short>(attributeData.size()), false));
|
||||
data.append(attributeData.toByteVector(""));
|
||||
return BaseObject::render(file);
|
||||
}
|
||||
@@ -325,7 +326,7 @@ void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, long long /*
|
||||
ByteVector ASF::File::FilePrivate::MetadataObject::render(ASF::File *file)
|
||||
{
|
||||
data.clear();
|
||||
data.append(ByteVector::fromShort(attributeData.size(), false));
|
||||
data.append(ByteVector::fromShort(static_cast<short>(attributeData.size()), false));
|
||||
data.append(attributeData.toByteVector(""));
|
||||
return BaseObject::render(file);
|
||||
}
|
||||
@@ -348,7 +349,7 @@ void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, long
|
||||
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::render(ASF::File *file)
|
||||
{
|
||||
data.clear();
|
||||
data.append(ByteVector::fromShort(attributeData.size(), false));
|
||||
data.append(ByteVector::fromShort(static_cast<short>(attributeData.size()), false));
|
||||
data.append(attributeData.toByteVector(""));
|
||||
return BaseObject::render(file);
|
||||
}
|
||||
@@ -472,7 +473,7 @@ bool ASF::File::isSupported(IOStream *stream)
|
||||
// An ASF file has to start with the designated GUID.
|
||||
|
||||
const ByteVector id = Utils::readHeader(stream, 16, false);
|
||||
return (id == headerGuid);
|
||||
return id == headerGuid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -564,8 +565,8 @@ bool ASF::File::save()
|
||||
bool inMetadataObject = false;
|
||||
|
||||
for(const auto &attribute : attributes) {
|
||||
const bool largeValue = (attribute.dataSize() > 65535);
|
||||
const bool guid = (attribute.type() == Attribute::GuidType);
|
||||
const bool largeValue = attribute.dataSize() > 65535;
|
||||
const bool guid = attribute.type() == Attribute::GuidType;
|
||||
|
||||
if(!inExtendedContentDescriptionObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
|
||||
d->extendedContentDescriptionObject->attributeData.append(attribute.render(name));
|
||||
@@ -681,6 +682,5 @@ void ASF::File::read()
|
||||
if(!filePropertiesObject || !streamPropertiesObject) {
|
||||
debug("ASF::File::read(): Missing mandatory header objects.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
namespace TagLib {
|
||||
//! An implementation of ASF (WMA) metadata
|
||||
namespace ASF {
|
||||
//! An implementation of TagLib::File with ASF specific methods
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for ASF files to the
|
||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||
@@ -112,7 +114,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
* This returns \c true if the save was successful.
|
||||
*/
|
||||
bool save() override;
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "tbytevector.h"
|
||||
#include "tpicturetype.h"
|
||||
#include "taglib_export.h"
|
||||
#include "attachedpictureframe.h"
|
||||
|
||||
namespace TagLib
|
||||
{
|
||||
@@ -40,9 +39,9 @@ namespace TagLib
|
||||
//! An ASF attached picture interface implementation
|
||||
|
||||
/*!
|
||||
* This is an implementation of ASF attached pictures interface. Pictures may be
|
||||
* This is an implementation of ASF attached pictures. Pictures may be
|
||||
* included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture
|
||||
* attribute in a single tag). These pictures are usually in either JPEG or
|
||||
* attributes in a single tag). These pictures are usually in either JPEG or
|
||||
* PNG format.
|
||||
* \see Attribute::toPicture()
|
||||
* \see Attribute::Attribute(const Picture& picture)
|
||||
@@ -50,7 +49,7 @@ namespace TagLib
|
||||
class TAGLIB_EXPORT Picture {
|
||||
public:
|
||||
|
||||
/*!
|
||||
/*
|
||||
* This describes the function or content of the picture.
|
||||
*/
|
||||
DECLARE_PICTURE_TYPE_ENUM(Type)
|
||||
@@ -61,14 +60,14 @@ namespace TagLib
|
||||
Picture();
|
||||
|
||||
/*!
|
||||
* Construct an picture as a copy of \a other.
|
||||
* Construct a picture as a copy of \a other.
|
||||
*/
|
||||
Picture(const Picture& other);
|
||||
|
||||
/*!
|
||||
* Destroys the picture.
|
||||
*/
|
||||
virtual ~Picture();
|
||||
~Picture();
|
||||
|
||||
/*!
|
||||
* Copies the contents of \a other into this picture.
|
||||
@@ -76,12 +75,12 @@ namespace TagLib
|
||||
Picture& operator=(const Picture& other);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the Picture by the content of \a other.
|
||||
* Exchanges the content of the Picture with the content of \a other.
|
||||
*/
|
||||
void swap(Picture &other) noexcept;
|
||||
|
||||
/*!
|
||||
* Returns true if Picture stores valid picture
|
||||
* Returns \c true if Picture stores valid picture
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
@@ -136,7 +135,7 @@ namespace TagLib
|
||||
/*!
|
||||
* Returns the image data as a ByteVector.
|
||||
*
|
||||
* \note ByteVector has a data() method that returns a const char * which
|
||||
* \note ByteVector has a data() method that returns a <tt>const char *</tt> which
|
||||
* should make it easy to export this data to external programs.
|
||||
*
|
||||
* \see setPicture()
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace TagLib {
|
||||
public:
|
||||
|
||||
/*!
|
||||
* Audio codec types can be used in ASF file.
|
||||
* Audio codec types which can be used in ASF files.
|
||||
*/
|
||||
enum Codec
|
||||
{
|
||||
|
||||
@@ -313,8 +313,7 @@ PropertyMap ASF::Tag::properties() const
|
||||
}
|
||||
|
||||
for(const auto &[k, attributes] : std::as_const(d->attributeListMap)) {
|
||||
const String key = translateKey(k);
|
||||
if(!key.isEmpty()) {
|
||||
if(const String key = translateKey(k); !key.isEmpty()) {
|
||||
for(const auto &attr : attributes) {
|
||||
if(key == "TRACKNUMBER") {
|
||||
if(attr.type() == ASF::Attribute::DWordType)
|
||||
@@ -411,8 +410,7 @@ StringList ASF::Tag::complexPropertyKeys() const
|
||||
List<VariantMap> ASF::Tag::complexProperties(const String &key) const
|
||||
{
|
||||
List<VariantMap> props;
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
const AttributeList pictures = d->attributeListMap.value("WM/Picture");
|
||||
for(const Attribute &attr : pictures) {
|
||||
ASF::Picture picture = attr.toPicture();
|
||||
@@ -430,8 +428,7 @@ List<VariantMap> ASF::Tag::complexProperties(const String &key) const
|
||||
|
||||
bool ASF::Tag::setComplexProperties(const String &key, const List<VariantMap> &value)
|
||||
{
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
removeItem("WM/Picture");
|
||||
|
||||
for(const auto &property : value) {
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace TagLib {
|
||||
using AttributeList = List<Attribute>;
|
||||
using AttributeListMap = Map<String, AttributeList>;
|
||||
|
||||
//! An implementation of ASF (WMA) tags
|
||||
|
||||
class TAGLIB_EXPORT Tag : public TagLib::Tag {
|
||||
|
||||
friend class File;
|
||||
@@ -64,7 +66,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Returns the album name; if no album name is present in the tag
|
||||
* String::null will be returned.
|
||||
* an empty string will be returned.
|
||||
*/
|
||||
String album() const override;
|
||||
|
||||
@@ -74,7 +76,7 @@ namespace TagLib {
|
||||
String comment() const override;
|
||||
|
||||
/*!
|
||||
* Returns the genre name; if no genre is present in the tag String::null
|
||||
* Returns the genre name; if no genre is present in the tag an empty string
|
||||
* will be returned.
|
||||
*/
|
||||
String genre() const override;
|
||||
@@ -85,8 +87,8 @@ namespace TagLib {
|
||||
virtual String rating() const;
|
||||
|
||||
/*!
|
||||
* Returns the genre name; if no genre is present in the tag String::null
|
||||
* will be returned.
|
||||
* Returns the copyright information; if no copyright information is
|
||||
* present in the tag an empty string will be returned.
|
||||
*/
|
||||
virtual String copyright() const;
|
||||
|
||||
@@ -112,7 +114,7 @@ namespace TagLib {
|
||||
void setArtist(const String &value) override;
|
||||
|
||||
/*!
|
||||
* Sets the album to \a value. If \a value is String::null then this value will be
|
||||
* Sets the album to \a value. If \a value is an empty string then this value will be
|
||||
* cleared.
|
||||
*/
|
||||
void setAlbum(const String &value) override;
|
||||
@@ -148,7 +150,7 @@ namespace TagLib {
|
||||
void setTrack(unsigned int value) override;
|
||||
|
||||
/*!
|
||||
* Returns true if the tag does not contain any data. This should be
|
||||
* Returns \c true if the tag does not contain any data. This should be
|
||||
* reimplemented in subclasses that provide more than the basic tagging
|
||||
* abilities in this class.
|
||||
*/
|
||||
@@ -168,7 +170,7 @@ namespace TagLib {
|
||||
const AttributeListMap &attributeListMap() const;
|
||||
|
||||
/*!
|
||||
* \return True if a value for \a key is currently set.
|
||||
* \return \c true if a value for \a key is currently set.
|
||||
*/
|
||||
bool contains(const String &key) const;
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace TagLib
|
||||
{
|
||||
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false);
|
||||
if(includeLength) {
|
||||
data = ByteVector::fromShort(data.size(), false) + data;
|
||||
data = ByteVector::fromShort(static_cast<short>(data.size()), false) + data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* The values here are common to most audio formats. For more specific, codec
|
||||
* dependent values, please see see the subclasses APIs. This is meant to
|
||||
* dependent values, please see the subclasses APIs. This is meant to
|
||||
* compliment the TagLib::File and TagLib::Tag APIs in providing a simple
|
||||
* interface that is sufficient for most applications.
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace
|
||||
char padding;
|
||||
};
|
||||
|
||||
typedef std::vector<Chunk64> ChunkList;
|
||||
using ChunkList = std::vector<Chunk64>;
|
||||
|
||||
int chunkIndex(const ChunkList &chunks, const ByteVector &id)
|
||||
{
|
||||
@@ -65,12 +65,8 @@ namespace
|
||||
if(name.size() != 4)
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(name[i] < 32 || name[i] > 126)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return std::none_of(name.cbegin(), name.cend(),
|
||||
[](unsigned char c) { return c < 32 || c > 126; });
|
||||
}
|
||||
|
||||
enum {
|
||||
@@ -86,7 +82,7 @@ namespace
|
||||
class DSDIFF::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate(ID3v2::FrameFactory *frameFactory)
|
||||
FilePrivate(const ID3v2::FrameFactory *frameFactory)
|
||||
: ID3v2FrameFactory(frameFactory ? frameFactory
|
||||
: ID3v2::FrameFactory::instance())
|
||||
{
|
||||
@@ -130,7 +126,7 @@ bool DSDIFF::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// A DSDIFF file has to start with "FRM8????????DSD ".
|
||||
const ByteVector id = Utils::readHeader(stream, 16, false);
|
||||
return (id.startsWith("FRM8") && id.containsAt("DSD ", 12));
|
||||
return id.startsWith("FRM8") && id.containsAt("DSD ", 12);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -189,9 +185,9 @@ PropertyMap DSDIFF::File::properties() const
|
||||
return d->tag.properties();
|
||||
}
|
||||
|
||||
void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported)
|
||||
void DSDIFF::File::removeUnsupportedProperties(const StringList &properties)
|
||||
{
|
||||
d->tag.removeUnsupportedProperties(unsupported);
|
||||
d->tag.removeUnsupportedProperties(properties);
|
||||
}
|
||||
|
||||
PropertyMap DSDIFF::File::setProperties(const PropertyMap &properties)
|
||||
@@ -226,9 +222,7 @@ bool DSDIFF::File::save(int tags, StripTags strip, ID3v2::Version version)
|
||||
|
||||
// First: save ID3V2 chunk
|
||||
|
||||
ID3v2::Tag *id3v2Tag = ID3v2Tag();
|
||||
|
||||
if((tags & ID3v2) && id3v2Tag) {
|
||||
if(const ID3v2::Tag *id3v2Tag = ID3v2Tag(); (tags & ID3v2) && id3v2Tag) {
|
||||
if(d->isID3InPropChunk) {
|
||||
if(!id3v2Tag->isEmpty()) {
|
||||
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(version), PROPChunk);
|
||||
@@ -255,9 +249,7 @@ bool DSDIFF::File::save(int tags, StripTags strip, ID3v2::Version version)
|
||||
|
||||
// Second: save the DIIN chunk
|
||||
|
||||
DSDIFF::DIIN::Tag *diinTag = DIINTag();
|
||||
|
||||
if((tags & DIIN) && diinTag) {
|
||||
if(const DSDIFF::DIIN::Tag *diinTag = DIINTag(); (tags & DIIN) && diinTag) {
|
||||
if(!diinTag->title().isEmpty()) {
|
||||
ByteVector diinTitle;
|
||||
diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian));
|
||||
@@ -433,7 +425,7 @@ void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum)
|
||||
// Update the internal offsets
|
||||
// For child chunks
|
||||
|
||||
if((i + 1) < childChunks.size()) {
|
||||
if(i + 1 < childChunks.size()) {
|
||||
childChunks[i + 1].offset = childChunks[i].offset;
|
||||
for(unsigned int c = i + 2; c < childChunks.size(); ++c)
|
||||
childChunks[c].offset = childChunks[c - 1].offset + 12
|
||||
@@ -527,8 +519,8 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
||||
int i = d->childChunkIndex[DIINChunk];
|
||||
if(i < 0) {
|
||||
setRootChunkData("DIIN", ByteVector());
|
||||
const int lastChunkIndex = static_cast<int>(d->chunks.size()) - 1;
|
||||
if(lastChunkIndex >= 0 && d->chunks[lastChunkIndex].name == "DIIN") {
|
||||
if(const int lastChunkIndex = static_cast<int>(d->chunks.size()) - 1;
|
||||
lastChunkIndex >= 0 && d->chunks[lastChunkIndex].name == "DIIN") {
|
||||
i = lastChunkIndex;
|
||||
d->childChunkIndex[DIINChunk] = lastChunkIndex;
|
||||
d->hasDiin = true;
|
||||
@@ -559,13 +551,13 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
||||
// Now add the chunk to the file
|
||||
|
||||
unsigned long long nextRootChunkIdx = length();
|
||||
if((d->childChunkIndex[childChunkNum] + 1) < static_cast<int>(d->chunks.size()))
|
||||
if(d->childChunkIndex[childChunkNum] + 1 < static_cast<int>(d->chunks.size()))
|
||||
nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12;
|
||||
|
||||
writeChunk(name, data, offset,
|
||||
static_cast<unsigned long>(
|
||||
nextRootChunkIdx > offset ? nextRootChunkIdx - offset : 0),
|
||||
(offset & 1) ? 1 : 0);
|
||||
offset & 1 ? 1 : 0);
|
||||
|
||||
// For root chunks
|
||||
|
||||
@@ -575,7 +567,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
||||
chunk.name = name;
|
||||
chunk.size = data.size();
|
||||
chunk.offset = offset + 12;
|
||||
chunk.padding = (data.size() & 0x01) ? 1 : 0;
|
||||
chunk.padding = data.size() & 0x01 ? 1 : 0;
|
||||
|
||||
childChunks.push_back(chunk);
|
||||
}
|
||||
@@ -589,8 +581,8 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
|
||||
// Update child chunks structure as well
|
||||
|
||||
if(d->childChunkIndex[PROPChunk] >= static_cast<int>(startingChunk)) {
|
||||
ChunkList &childChunksToUpdate = d->childChunks[PROPChunk];
|
||||
if(!childChunksToUpdate.empty()) {
|
||||
if(ChunkList &childChunksToUpdate = d->childChunks[PROPChunk];
|
||||
!childChunksToUpdate.empty()) {
|
||||
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[PROPChunk]].offset + 12;
|
||||
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
||||
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
|
||||
@@ -599,8 +591,8 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
|
||||
|
||||
}
|
||||
if(d->childChunkIndex[DIINChunk] >= static_cast<int>(startingChunk)) {
|
||||
ChunkList &childChunksToUpdate = d->childChunks[DIINChunk];
|
||||
if(!childChunksToUpdate.empty()) {
|
||||
if(ChunkList &childChunksToUpdate = d->childChunks[DIINChunk];
|
||||
!childChunksToUpdate.empty()) {
|
||||
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[DIINChunk]].offset + 12;
|
||||
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
||||
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
|
||||
@@ -647,10 +639,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
||||
// Check padding
|
||||
|
||||
chunk.padding = 0;
|
||||
offset_t uPosNotPadded = tell();
|
||||
if((uPosNotPadded & 0x01) != 0) {
|
||||
ByteVector iByte = readBlock(1);
|
||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
||||
if(offset_t uPosNotPadded = tell(); (uPosNotPadded & 0x01) != 0) {
|
||||
if(ByteVector iByte = readBlock(1);
|
||||
iByte.size() != 1 || iByte[0] != 0)
|
||||
// Not well formed, re-seek
|
||||
seek(uPosNotPadded, Beginning);
|
||||
else
|
||||
@@ -708,10 +699,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
||||
seek(dstChunkSize, Current);
|
||||
|
||||
// Check padding
|
||||
offset_t uPosNotPadded = tell();
|
||||
if((uPosNotPadded & 0x01) != 0) {
|
||||
ByteVector iByte = readBlock(1);
|
||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
||||
if(offset_t uPosNotPadded = tell(); (uPosNotPadded & 0x01) != 0) {
|
||||
if(ByteVector iByte = readBlock(1);
|
||||
iByte.size() != 1 || iByte[0] != 0)
|
||||
// Not well formed, re-seek
|
||||
seek(uPosNotPadded, Beginning);
|
||||
}
|
||||
@@ -749,10 +739,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
||||
|
||||
// Check padding
|
||||
chunk.padding = 0;
|
||||
offset_t uPosNotPadded = tell();
|
||||
if((uPosNotPadded & 0x01) != 0) {
|
||||
ByteVector iByte = readBlock(1);
|
||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
||||
if(offset_t uPosNotPadded = tell(); (uPosNotPadded & 0x01) != 0) {
|
||||
if(ByteVector iByte = readBlock(1);
|
||||
iByte.size() != 1 || iByte[0] != 0)
|
||||
// Not well formed, re-seek
|
||||
seek(uPosNotPadded, Beginning);
|
||||
else
|
||||
@@ -797,11 +786,10 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
||||
// Check padding
|
||||
|
||||
chunk.padding = 0;
|
||||
offset_t uPosNotPadded = tell();
|
||||
|
||||
if((uPosNotPadded & 0x01) != 0) {
|
||||
ByteVector iByte = readBlock(1);
|
||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
||||
if(offset_t uPosNotPadded = tell(); (uPosNotPadded & 0x01) != 0) {
|
||||
if(ByteVector iByte = readBlock(1);
|
||||
iByte.size() != 1 || iByte[0] != 0)
|
||||
// Not well formed, re-seek
|
||||
seek(uPosNotPadded, Beginning);
|
||||
else
|
||||
@@ -867,16 +855,16 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
||||
for(unsigned int i = 0; i < d->childChunks[DIINChunk].size(); i++) {
|
||||
if(d->childChunks[DIINChunk][i].name == "DITI") {
|
||||
seek(d->childChunks[DIINChunk][i].offset);
|
||||
unsigned int titleStrLength = readBlock(4).toUInt(0, 4, bigEndian);
|
||||
if(titleStrLength <= d->childChunks[DIINChunk][i].size) {
|
||||
if(unsigned int titleStrLength = readBlock(4).toUInt(0, 4, bigEndian);
|
||||
titleStrLength <= d->childChunks[DIINChunk][i].size) {
|
||||
ByteVector titleStr = readBlock(titleStrLength);
|
||||
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setTitle(titleStr);
|
||||
}
|
||||
}
|
||||
else if(d->childChunks[DIINChunk][i].name == "DIAR") {
|
||||
seek(d->childChunks[DIINChunk][i].offset);
|
||||
unsigned int artistStrLength = readBlock(4).toUInt(0, 4, bigEndian);
|
||||
if(artistStrLength <= d->childChunks[DIINChunk][i].size) {
|
||||
if(unsigned int artistStrLength = readBlock(4).toUInt(0, 4, bigEndian);
|
||||
artistStrLength <= d->childChunks[DIINChunk][i].size) {
|
||||
ByteVector artistStr = readBlock(artistStrLength);
|
||||
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setArtist(artistStr);
|
||||
}
|
||||
@@ -902,7 +890,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
||||
int bitrate = 0;
|
||||
if(lengthDSDSamplesTimeChannels > 0)
|
||||
bitrate = static_cast<int>(
|
||||
(audioDataSizeinBytes * 8 * sampleRate) / lengthDSDSamplesTimeChannels / 1000);
|
||||
audioDataSizeinBytes * 8 * sampleRate / lengthDSDSamplesTimeChannels / 1000);
|
||||
|
||||
d->properties = std::make_unique<Properties>(sampleRate, channels,
|
||||
lengthDSDSamplesTimeChannels, bitrate, propertiesStyle);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef TAGLIB_DSDIFFFILE_H
|
||||
#define TAGLIB_DSDIFFFILE_H
|
||||
|
||||
#include "rifffile.h"
|
||||
#include "tfile.h"
|
||||
#include "id3v2tag.h"
|
||||
#include "dsdiffproperties.h"
|
||||
#include "dsdiffdiintag.h"
|
||||
@@ -36,20 +36,21 @@ namespace TagLib {
|
||||
//! An implementation of DSDIFF metadata
|
||||
|
||||
/*!
|
||||
* This is implementation of DSDIFF metadata.
|
||||
* This is an implementation of DSDIFF metadata.
|
||||
*
|
||||
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
|
||||
* chunk as well as properties from the file.
|
||||
* Description of the DSDIFF format is available
|
||||
* at http://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf
|
||||
* DSDIFF standard does not explicitly specify the ID3V2 chunk
|
||||
* It can be found at the root level, but also sometimes inside the PROP chunk
|
||||
* In addition, title and artist info are stored as part of the standard
|
||||
* Description of the DSDIFF format is available at
|
||||
* <a href="https://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf">
|
||||
* DSDIFF_1.5_Spec.pdf</a>.
|
||||
* The DSDIFF standard does not explicitly specify the ID3 chunk.
|
||||
* It can be found at the root level, but also sometimes inside the PROP chunk.
|
||||
* In addition, title and artist info are stored as part of the standard.
|
||||
*/
|
||||
|
||||
namespace DSDIFF {
|
||||
|
||||
//! An implementation of TagLib::File with DSDIFF specific methods
|
||||
//! An implementation of TagLib::File with DSDIFF specific methods.
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for DSDIFF files to the
|
||||
@@ -78,7 +79,7 @@ namespace TagLib {
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constructs a DSDIFF file from \a file. If \a readProperties is true
|
||||
* Constructs a DSDIFF file from \a file. If \a readProperties is \c true
|
||||
* the file's audio properties will also be read.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
@@ -91,7 +92,7 @@ namespace TagLib {
|
||||
ID3v2::FrameFactory *frameFactory = nullptr);
|
||||
|
||||
/*!
|
||||
* Constructs an DSDIFF file from \a stream. If \a readProperties is true
|
||||
* Constructs a DSDIFF file from \a stream. If \a readProperties is \c true
|
||||
* the file's audio properties will also be read.
|
||||
*
|
||||
* If this file contains an ID3v2 tag, the frames will be created using
|
||||
@@ -168,7 +169,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Save the file. If at least one tag -- ID3v1 or DIIN -- exists this
|
||||
* will duplicate its content into the other tag. This returns true
|
||||
* will duplicate its content into the other tag. This returns \c true
|
||||
* if saving was successful.
|
||||
*
|
||||
* If neither exists or if both tags are empty, this will strip the tags
|
||||
@@ -177,7 +178,7 @@ namespace TagLib {
|
||||
* This is the same as calling save(AllTags);
|
||||
*
|
||||
* If you would like more granular control over the content of the tags,
|
||||
* with the concession of generality, use paramaterized save call below.
|
||||
* with the concession of generality, use parameterized save call below.
|
||||
*
|
||||
* \see save(int tags)
|
||||
*/
|
||||
@@ -193,7 +194,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* This will strip the tags that match the OR-ed together TagTypes from the
|
||||
* file. By default it strips all tags. It returns true if the tags are
|
||||
* file. By default it strips all tags. It returns \c true if the tags are
|
||||
* successfully stripped.
|
||||
*
|
||||
* \note This will update the file immediately.
|
||||
@@ -227,9 +228,6 @@ namespace TagLib {
|
||||
protected:
|
||||
enum Endianness { BigEndian, LittleEndian };
|
||||
|
||||
File(FileName file, Endianness endianness);
|
||||
File(IOStream *stream, Endianness endianness);
|
||||
|
||||
private:
|
||||
void removeRootChunk(const ByteVector &id);
|
||||
void removeRootChunk(unsigned int i);
|
||||
@@ -237,7 +235,7 @@ namespace TagLib {
|
||||
void removeChildChunk(unsigned int i, unsigned int childChunkNum);
|
||||
|
||||
/*!
|
||||
* Sets the data for the the specified chunk at root level to \a data.
|
||||
* Sets the data for the specified chunk at root level to \a data.
|
||||
*
|
||||
* \warning This will update the file immediately.
|
||||
*/
|
||||
@@ -254,7 +252,7 @@ namespace TagLib {
|
||||
void setRootChunkData(const ByteVector &name, const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* Sets the data for the the specified child chunk to \a data.
|
||||
* Sets the data for the specified child chunk to \a data.
|
||||
*
|
||||
* If data is null, then remove the chunk
|
||||
*
|
||||
@@ -266,7 +264,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Sets the data for the child chunk \a name to \a data. If a chunk with
|
||||
* the given name already exists it will be overwritten, otherwise it will
|
||||
* be created after the existing chunks inside child chunk.
|
||||
* be created after the existing chunks inside the child chunk.
|
||||
*
|
||||
* If data is null, then remove the chunks with \a name name
|
||||
*
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "dsdiffproperties.h"
|
||||
|
||||
#include "tstring.h"
|
||||
#include "tdebug.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@@ -45,10 +44,10 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DSDIFF::Properties::Properties(const unsigned int sampleRate,
|
||||
const unsigned short channels,
|
||||
const unsigned long long samplesCount,
|
||||
const int bitrate,
|
||||
DSDIFF::Properties::Properties(unsigned int sampleRate,
|
||||
unsigned short channels,
|
||||
unsigned long long samplesCount,
|
||||
int bitrate,
|
||||
ReadStyle style) :
|
||||
AudioProperties(style),
|
||||
d(std::make_unique<PropertiesPrivate>())
|
||||
@@ -59,7 +58,7 @@ DSDIFF::Properties::Properties(const unsigned int sampleRate,
|
||||
d->sampleRate = sampleRate;
|
||||
d->bitrate = bitrate;
|
||||
d->length = d->sampleRate > 0
|
||||
? static_cast<int>((d->sampleCount * 1000.0) / d->sampleRate + 0.5)
|
||||
? static_cast<int>(static_cast<double>(d->sampleCount) * 1000.0 / d->sampleRate + 0.5)
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace TagLib {
|
||||
//! An implementation of audio property reading for DSDIFF
|
||||
|
||||
/*!
|
||||
* This reads the data from an DSDIFF stream found in the AudioProperties
|
||||
* This reads the data from a DSDIFF stream found in the AudioProperties
|
||||
* API.
|
||||
*/
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace TagLib {
|
||||
* Create an instance of DSDIFF::Properties with the data read from the
|
||||
* ByteVector \a data.
|
||||
*/
|
||||
Properties(const unsigned int sampleRate, const unsigned short channels,
|
||||
const unsigned long long samplesCount, const int bitrate,
|
||||
Properties(unsigned int sampleRate, unsigned short channels,
|
||||
unsigned long long samplesCount, int bitrate,
|
||||
ReadStyle style);
|
||||
|
||||
/*!
|
||||
|
||||
@@ -31,12 +31,10 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
||||
|
||||
class DSF::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate(ID3v2::FrameFactory *frameFactory)
|
||||
FilePrivate(const ID3v2::FrameFactory *frameFactory)
|
||||
: ID3v2FrameFactory(frameFactory ? frameFactory
|
||||
: ID3v2::FrameFactory::instance())
|
||||
{
|
||||
@@ -61,7 +59,7 @@ bool DSF::File::isSupported(IOStream *stream)
|
||||
return id.startsWith("DSD ");
|
||||
}
|
||||
|
||||
DSF::File::File(FileName file, bool readProperties,
|
||||
DSF::File::File(FileName file, bool,
|
||||
AudioProperties::ReadStyle propertiesStyle,
|
||||
ID3v2::FrameFactory *frameFactory) :
|
||||
TagLib::File(file),
|
||||
@@ -71,7 +69,7 @@ DSF::File::File(FileName file, bool readProperties,
|
||||
read(propertiesStyle);
|
||||
}
|
||||
|
||||
DSF::File::File(IOStream *stream, bool readProperties,
|
||||
DSF::File::File(IOStream *stream, bool,
|
||||
AudioProperties::ReadStyle propertiesStyle,
|
||||
ID3v2::FrameFactory *frameFactory) :
|
||||
TagLib::File(stream),
|
||||
|
||||
@@ -36,7 +36,27 @@
|
||||
#include "id3v2tag.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
//! An implementation of DSF metadata
|
||||
|
||||
/*!
|
||||
* This is an implementation of DSF metadata using an ID3v2 tag inside the
|
||||
* metadata chunk.
|
||||
* The DSF specification is located at
|
||||
* http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
||||
*/
|
||||
|
||||
namespace DSF {
|
||||
|
||||
//! An implementation of TagLib::File with DSF specific methods
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for DSF files to the
|
||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||
* the abstract TagLib::File API as well as providing some additional
|
||||
* information specific to DSF files.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public TagLib::File {
|
||||
public:
|
||||
/*!
|
||||
@@ -103,7 +123,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
* This returns \c true if the save was successful.
|
||||
*/
|
||||
bool save() override;
|
||||
|
||||
|
||||
@@ -127,8 +127,8 @@ void DSF::Properties::read(const ByteVector &data)
|
||||
d->blockSizePerChannel = data.toUInt(32U,false);
|
||||
|
||||
d->bitrate = static_cast<unsigned int>(
|
||||
(d->samplingFrequency * d->bitsPerSample * d->channelNum) / 1000.0 + 0.5);
|
||||
d->samplingFrequency * d->bitsPerSample * d->channelNum / 1000.0 + 0.5);
|
||||
d->length = d->samplingFrequency > 0
|
||||
? static_cast<unsigned int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5)
|
||||
? static_cast<unsigned int>(static_cast<double>(d->sampleCount) * 1000.0 / d->samplingFrequency + 0.5)
|
||||
: 0;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
namespace TagLib {
|
||||
namespace DSF {
|
||||
//! An implementation of audio properties for DSF
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||
public:
|
||||
Properties(const ByteVector &data, ReadStyle style);
|
||||
|
||||
@@ -32,31 +32,54 @@
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include "taglib_config.h"
|
||||
#include "tfilestream.h"
|
||||
#include "tpropertymap.h"
|
||||
#include "tstringlist.h"
|
||||
#include "tvariant.h"
|
||||
#include "tdebug.h"
|
||||
#include "aifffile.h"
|
||||
#include "apefile.h"
|
||||
#include "asffile.h"
|
||||
#include "flacfile.h"
|
||||
#include "itfile.h"
|
||||
#include "modfile.h"
|
||||
#include "mp4file.h"
|
||||
#include "mpcfile.h"
|
||||
#include "mpegfile.h"
|
||||
#ifdef TAGLIB_WITH_RIFF
|
||||
#include "aifffile.h"
|
||||
#include "wavfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_APE
|
||||
#include "apefile.h"
|
||||
#include "mpcfile.h"
|
||||
#include "wavpackfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_ASF
|
||||
#include "asffile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_VORBIS
|
||||
#include "flacfile.h"
|
||||
#include "speexfile.h"
|
||||
#include "vorbisfile.h"
|
||||
#include "oggflacfile.h"
|
||||
#include "opusfile.h"
|
||||
#include "s3mfile.h"
|
||||
#include "speexfile.h"
|
||||
#include "trueaudiofile.h"
|
||||
#include "vorbisfile.h"
|
||||
#include "wavfile.h"
|
||||
#include "wavpackfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MOD
|
||||
#include "itfile.h"
|
||||
#include "modfile.h"
|
||||
#include "xmfile.h"
|
||||
#include "s3mfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MP4
|
||||
#include "mp4file.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_TRUEAUDIO
|
||||
#include "trueaudiofile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_DSF
|
||||
#include "dsffile.h"
|
||||
#include "dsdifffile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_SHORTEN
|
||||
#include "shortenfile.h"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MATROSKA
|
||||
#include "matroskafile.h"
|
||||
#endif
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@@ -119,8 +142,7 @@ namespace
|
||||
#endif
|
||||
|
||||
String ext;
|
||||
const int pos = s.rfind(".");
|
||||
if(pos != -1)
|
||||
if(const int pos = s.rfind("."); pos != -1)
|
||||
ext = s.substr(pos + 1).upper();
|
||||
|
||||
// If this list is updated, the method defaultFileExtensions() should also be
|
||||
@@ -136,6 +158,7 @@ namespace
|
||||
|
||||
if(ext == "MP3" || ext == "MP2" || ext == "AAC")
|
||||
file = new MPEG::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#ifdef TAGLIB_WITH_VORBIS
|
||||
else if(ext == "OGG")
|
||||
file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "OGA") {
|
||||
@@ -148,26 +171,38 @@ namespace
|
||||
}
|
||||
else if(ext == "FLAC")
|
||||
file = new FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "MPC")
|
||||
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "WV")
|
||||
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "SPX")
|
||||
file = new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "OPUS")
|
||||
file = new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_APE
|
||||
else if(ext == "MPC")
|
||||
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "WV")
|
||||
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "APE")
|
||||
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_TRUEAUDIO
|
||||
else if(ext == "TTA")
|
||||
file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MP4
|
||||
else if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
|
||||
file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_ASF
|
||||
else if(ext == "WMA" || ext == "ASF")
|
||||
file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_RIFF
|
||||
else if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
|
||||
file = new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "WAV")
|
||||
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "APE")
|
||||
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MOD
|
||||
// module, nst and wow are possible but uncommon extensions
|
||||
else if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
|
||||
file = new Mod::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
@@ -177,10 +212,21 @@ namespace
|
||||
file = new IT::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "XM")
|
||||
file = new XM::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_DSF
|
||||
else if(ext == "DSF")
|
||||
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "DFF" || ext == "DSDIFF")
|
||||
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_SHORTEN
|
||||
else if(ext == "SHN")
|
||||
file = new Shorten::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MATROSKA
|
||||
else if(ext == "MKA" || ext == "MKV" || ext == "WEBM")
|
||||
file = new Matroska::File(stream, readAudioProperties);
|
||||
#endif
|
||||
|
||||
// if file is not valid, leave it to content-based detection.
|
||||
|
||||
@@ -202,36 +248,58 @@ namespace
|
||||
|
||||
if(MPEG::File::isSupported(stream))
|
||||
file = new MPEG::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#ifdef TAGLIB_WITH_VORBIS
|
||||
else if(Ogg::Vorbis::File::isSupported(stream))
|
||||
file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(Ogg::FLAC::File::isSupported(stream))
|
||||
file = new Ogg::FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(FLAC::File::isSupported(stream))
|
||||
file = new FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(MPC::File::isSupported(stream))
|
||||
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(WavPack::File::isSupported(stream))
|
||||
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(Ogg::Speex::File::isSupported(stream))
|
||||
file = new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(Ogg::Opus::File::isSupported(stream))
|
||||
file = new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_APE
|
||||
else if(MPC::File::isSupported(stream))
|
||||
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(WavPack::File::isSupported(stream))
|
||||
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(APE::File::isSupported(stream))
|
||||
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_TRUEAUDIO
|
||||
else if(TrueAudio::File::isSupported(stream))
|
||||
file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MP4
|
||||
else if(MP4::File::isSupported(stream))
|
||||
file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_ASF
|
||||
else if(ASF::File::isSupported(stream))
|
||||
file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_RIFF
|
||||
else if(RIFF::AIFF::File::isSupported(stream))
|
||||
file = new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(RIFF::WAV::File::isSupported(stream))
|
||||
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(APE::File::isSupported(stream))
|
||||
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_DSF
|
||||
else if(DSF::File::isSupported(stream))
|
||||
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(DSDIFF::File::isSupported(stream))
|
||||
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_SHORTEN
|
||||
else if(Shorten::File::isSupported(stream))
|
||||
file = new Shorten::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MATROSKA
|
||||
else if(Matroska::File::isSupported(stream))
|
||||
file = new Matroska::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
#endif
|
||||
|
||||
// isSupported() only does a quick check, so double check the file here.
|
||||
|
||||
@@ -264,7 +332,7 @@ public:
|
||||
return !file || !file->isValid();
|
||||
}
|
||||
|
||||
bool isNullWithDebugMessage(const String &methodName) const
|
||||
bool isNullWithDebugMessage([[maybe_unused]] const String &methodName) const
|
||||
{
|
||||
if(isNull()) {
|
||||
debug("FileRef::" + methodName + "() - Called without a valid file.");
|
||||
@@ -401,17 +469,25 @@ StringList FileRef::defaultFileExtensions()
|
||||
{
|
||||
StringList l;
|
||||
|
||||
l.append("mp3");
|
||||
l.append("mp2");
|
||||
l.append("aac");
|
||||
#ifdef TAGLIB_WITH_VORBIS
|
||||
l.append("ogg");
|
||||
l.append("flac");
|
||||
l.append("oga");
|
||||
l.append("opus");
|
||||
l.append("mp3");
|
||||
l.append("mp2");
|
||||
l.append("spx");
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_APE
|
||||
l.append("mpc");
|
||||
l.append("wv");
|
||||
l.append("spx");
|
||||
l.append("ape");
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_TRUEAUDIO
|
||||
l.append("tta");
|
||||
l.append("aac");
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MP4
|
||||
l.append("m4a");
|
||||
l.append("m4r");
|
||||
l.append("m4b");
|
||||
@@ -419,14 +495,19 @@ StringList FileRef::defaultFileExtensions()
|
||||
l.append("3g2");
|
||||
l.append("mp4");
|
||||
l.append("m4v");
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_ASF
|
||||
l.append("wma");
|
||||
l.append("asf");
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_RIFF
|
||||
l.append("aif");
|
||||
l.append("aiff");
|
||||
l.append("afc");
|
||||
l.append("aifc");
|
||||
l.append("wav");
|
||||
l.append("ape");
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MOD
|
||||
l.append("mod");
|
||||
l.append("module"); // alias for "mod"
|
||||
l.append("nst"); // alias for "mod"
|
||||
@@ -434,9 +515,20 @@ StringList FileRef::defaultFileExtensions()
|
||||
l.append("s3m");
|
||||
l.append("it");
|
||||
l.append("xm");
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_DSF
|
||||
l.append("dsf");
|
||||
l.append("dff");
|
||||
l.append("dsdiff"); // alias for "dff"
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_SHORTEN
|
||||
l.append("shn");
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_MATROSKA
|
||||
l.append("mkv");
|
||||
l.append("mka");
|
||||
l.append("webm");
|
||||
#endif
|
||||
|
||||
return l;
|
||||
}
|
||||
@@ -457,12 +549,12 @@ void FileRef::swap(FileRef &ref) noexcept
|
||||
|
||||
bool FileRef::operator==(const FileRef &ref) const
|
||||
{
|
||||
return (ref.d->file == d->file);
|
||||
return ref.d->file == d->file;
|
||||
}
|
||||
|
||||
bool FileRef::operator!=(const FileRef &ref) const
|
||||
{
|
||||
return (ref.d->file != d->file);
|
||||
return ref.d->file != d->file;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
105
taglib/fileref.h
105
taglib/fileref.h
@@ -60,34 +60,12 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
|
||||
//! A class for pluggable file type resolution.
|
||||
//! A class for pluggable file type resolution.
|
||||
|
||||
/*!
|
||||
* This class is used to extend TagLib's very basic file name based file
|
||||
* type resolution.
|
||||
*
|
||||
* This can be accomplished with:
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* class MyFileTypeResolver : FileTypeResolver
|
||||
* {
|
||||
* TagLib::File *createFile(TagLib::FileName *fileName, bool, AudioProperties::ReadStyle) const
|
||||
* {
|
||||
* if(someCheckForAnMP3File(fileName))
|
||||
* return new TagLib::MPEG::File(fileName);
|
||||
* return 0;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* FileRef::addFileTypeResolver(new MyFileTypeResolver);
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* Naturally a less contrived example would be slightly more complex. This
|
||||
* can be used to plug in mime-type detection systems or to add new file types
|
||||
* to TagLib.
|
||||
*/
|
||||
/*!
|
||||
* %File type resolver, better implement StreamTypeResolver in order to
|
||||
* support both file and stream resolution.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT FileTypeResolver
|
||||
{
|
||||
@@ -120,6 +98,44 @@ namespace TagLib {
|
||||
std::unique_ptr<FileTypeResolverPrivate> d;
|
||||
};
|
||||
|
||||
//! A class for pluggable stream type resolution.
|
||||
|
||||
/*!
|
||||
* This class is used to extend TagLib's very basic file name based file
|
||||
* type resolution.
|
||||
*
|
||||
* This can be accomplished with:
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* class MyStreamTypeResolver : StreamTypeResolver
|
||||
* {
|
||||
* TagLib::File *createFile(TagLib::FileName *fileName, bool readProps,
|
||||
* AudioProperties::ReadStyle readStyle) const override
|
||||
* {
|
||||
* if(someCheckForAnMP3File(fileName))
|
||||
* return new TagLib::MPEG::File(fileName, readProps, readStyle);
|
||||
* return nullptr;
|
||||
* }
|
||||
*
|
||||
* TagLib::File *createFileFromStream(TagLib::IOStream *s, bool readProps,
|
||||
* AudioProperties::ReadStyle readStyle) const override
|
||||
* {
|
||||
* if(someCheckForAnMP3Stream(s))
|
||||
* return new TagLib::MPEG::File(s, readProps, readStyle);
|
||||
* return nullptr;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* FileRef::addFileTypeResolver(new MyStreamTypeResolver);
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* Naturally a less contrived example would be slightly more complex. This
|
||||
* can be used to plug in mime-type detection systems or to add new file types
|
||||
* to TagLib.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT StreamTypeResolver : public FileTypeResolver
|
||||
{
|
||||
public:
|
||||
@@ -127,11 +143,22 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys this StreamTypeResolver instance.
|
||||
*/
|
||||
~StreamTypeResolver() override = 0;
|
||||
virtual ~StreamTypeResolver() override = 0; // virtual is needed by SWIG
|
||||
|
||||
StreamTypeResolver(const StreamTypeResolver &) = delete;
|
||||
StreamTypeResolver &operator=(const StreamTypeResolver &) = delete;
|
||||
|
||||
/*!
|
||||
* This method must be overridden to provide an additional stream type
|
||||
* resolver. If the resolver is able to determine the file type it should
|
||||
* return a valid File object; if not it should return nullptr.
|
||||
*
|
||||
* \note The created file is then owned by the FileRef and should not be
|
||||
* deleted. Deletion will happen automatically when the FileRef passes
|
||||
* out of scope.
|
||||
*
|
||||
* \see createFile()
|
||||
*/
|
||||
virtual File *createFileFromStream(IOStream *stream,
|
||||
bool readAudioProperties = true,
|
||||
AudioProperties::ReadStyle
|
||||
@@ -148,9 +175,9 @@ namespace TagLib {
|
||||
FileRef();
|
||||
|
||||
/*!
|
||||
* Create a FileRef from \a fileName. If \a readAudioProperties is true then
|
||||
* Create a FileRef from \a fileName. If \a readAudioProperties is \c true then
|
||||
* the audio properties will be read using \a audioPropertiesStyle. If
|
||||
* \a readAudioProperties is false then \a audioPropertiesStyle will be
|
||||
* \a readAudioProperties is \c false then \a audioPropertiesStyle will be
|
||||
* ignored.
|
||||
*
|
||||
* Also see the note in the class documentation about why you may not want to
|
||||
@@ -163,8 +190,8 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Construct a FileRef from an opened \a IOStream. If \a readAudioProperties
|
||||
* is true then the audio properties will be read using \a audioPropertiesStyle.
|
||||
* If \a readAudioProperties is false then \a audioPropertiesStyle will be
|
||||
* is \c true then the audio properties will be read using \a audioPropertiesStyle.
|
||||
* If \a readAudioProperties is \c false then \a audioPropertiesStyle will be
|
||||
* ignored.
|
||||
*
|
||||
* Also see the note in the class documentation about why you may not want to
|
||||
@@ -195,7 +222,7 @@ namespace TagLib {
|
||||
~FileRef();
|
||||
|
||||
/*!
|
||||
* Returns a pointer to represented file's tag.
|
||||
* Returns a pointer to the represented file's tag.
|
||||
*
|
||||
* \warning This pointer will become invalid when this FileRef and all
|
||||
* copies pass out of scope.
|
||||
@@ -287,7 +314,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Returns the audio properties for this FileRef. If no audio properties
|
||||
* were read then this will returns a null pointer.
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
AudioProperties *audioProperties() const;
|
||||
|
||||
@@ -309,7 +336,7 @@ namespace TagLib {
|
||||
File *file() const;
|
||||
|
||||
/*!
|
||||
* Saves the file. Returns true on success.
|
||||
* Saves the file. Returns \c true on success.
|
||||
*/
|
||||
bool save();
|
||||
|
||||
@@ -351,7 +378,7 @@ namespace TagLib {
|
||||
static StringList defaultFileExtensions();
|
||||
|
||||
/*!
|
||||
* Returns true if the file (and as such other pointers) are null.
|
||||
* Returns \c true if the file (and as such other pointers) are null.
|
||||
*/
|
||||
bool isNull() const;
|
||||
|
||||
@@ -361,17 +388,17 @@ namespace TagLib {
|
||||
FileRef &operator=(const FileRef &ref);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the FileRef by the content of \a ref.
|
||||
* Exchanges the content of the FileRef with the content of \a ref.
|
||||
*/
|
||||
void swap(FileRef &ref) noexcept;
|
||||
|
||||
/*!
|
||||
* Returns true if this FileRef and \a ref point to the same File object.
|
||||
* Returns \c true if this FileRef and \a ref point to the same File object.
|
||||
*/
|
||||
bool operator==(const FileRef &ref) const;
|
||||
|
||||
/*!
|
||||
* Returns true if this FileRef and \a ref do not point to the same File
|
||||
* Returns \c true if this FileRef and \a ref do not point to the same File
|
||||
* object.
|
||||
*/
|
||||
bool operator!=(const FileRef &ref) const;
|
||||
|
||||
@@ -45,10 +45,10 @@ namespace
|
||||
{
|
||||
enum { FlacXiphIndex = 0, FlacID3v2Index = 1, FlacID3v1Index = 2 };
|
||||
|
||||
const long MinPaddingLength = 4096;
|
||||
const long MaxPaddingLegnth = 1024 * 1024;
|
||||
constexpr long MinPaddingLength = 4096;
|
||||
constexpr long MaxPaddingLegnth = 1024 * 1024;
|
||||
|
||||
const char LastBlockFlag = '\x80';
|
||||
constexpr char LastBlockFlag = '\x80';
|
||||
} // namespace
|
||||
|
||||
class FLAC::File::FilePrivate
|
||||
@@ -86,7 +86,7 @@ bool FLAC::File::isSupported(IOStream *stream)
|
||||
// A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
||||
return (buffer.find("fLaC") >= 0);
|
||||
return buffer.find("fLaC") >= 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -171,8 +171,7 @@ StringList FLAC::File::complexPropertyKeys() const
|
||||
|
||||
List<VariantMap> FLAC::File::complexProperties(const String &key) const
|
||||
{
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
List<VariantMap> props;
|
||||
for(const auto &block : std::as_const(d->blocks)) {
|
||||
if(auto picture = dynamic_cast<Picture *>(block)) {
|
||||
@@ -196,8 +195,7 @@ List<VariantMap> FLAC::File::complexProperties(const String &key) const
|
||||
|
||||
bool FLAC::File::setComplexProperties(const String &key, const List<VariantMap> &value)
|
||||
{
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
removePictures();
|
||||
|
||||
for(const auto &property : value) {
|
||||
@@ -267,12 +265,19 @@ bool FLAC::File::save()
|
||||
// Render data for the metadata blocks
|
||||
|
||||
ByteVector data;
|
||||
for(const auto &block : std::as_const(d->blocks)) {
|
||||
ByteVector blockData = block->render();
|
||||
for(auto it = d->blocks.begin(); it != d->blocks.end();) {
|
||||
ByteVector blockData = (*it)->render();
|
||||
ByteVector blockHeader = ByteVector::fromUInt(blockData.size());
|
||||
blockHeader[0] = block->code();
|
||||
if(blockHeader[0] != 0) {
|
||||
debug("FLAC::File::save() -- Removing too large block.");
|
||||
delete *it;
|
||||
it = d->blocks.erase(it);
|
||||
continue;
|
||||
}
|
||||
blockHeader[0] = static_cast<char>((*it)->code());
|
||||
data.append(blockHeader);
|
||||
data.append(blockData);
|
||||
++it;
|
||||
}
|
||||
|
||||
// Compute the amount of padding, and append that to data.
|
||||
@@ -303,10 +308,10 @@ bool FLAC::File::save()
|
||||
|
||||
insert(data, d->flacStart, originalLength);
|
||||
|
||||
d->streamStart += (static_cast<long>(data.size()) - originalLength);
|
||||
d->streamStart += static_cast<long>(data.size()) - originalLength;
|
||||
|
||||
if(d->ID3v1Location >= 0)
|
||||
d->ID3v1Location += (static_cast<long>(data.size()) - originalLength);
|
||||
d->ID3v1Location += static_cast<long>(data.size()) - originalLength;
|
||||
|
||||
// Update ID3 tags
|
||||
|
||||
@@ -320,11 +325,11 @@ bool FLAC::File::save()
|
||||
data = ID3v2Tag()->render();
|
||||
insert(data, d->ID3v2Location, d->ID3v2OriginalSize);
|
||||
|
||||
d->flacStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
|
||||
d->streamStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
|
||||
d->flacStart += static_cast<long>(data.size()) - d->ID3v2OriginalSize;
|
||||
d->streamStart += static_cast<long>(data.size()) - d->ID3v2OriginalSize;
|
||||
|
||||
if(d->ID3v1Location >= 0)
|
||||
d->ID3v1Location += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
|
||||
d->ID3v1Location += static_cast<long>(data.size()) - d->ID3v2OriginalSize;
|
||||
|
||||
d->ID3v2OriginalSize = data.size();
|
||||
}
|
||||
@@ -449,12 +454,12 @@ bool FLAC::File::hasXiphComment() const
|
||||
|
||||
bool FLAC::File::hasID3v1Tag() const
|
||||
{
|
||||
return (d->ID3v1Location >= 0);
|
||||
return d->ID3v1Location >= 0;
|
||||
}
|
||||
|
||||
bool FLAC::File::hasID3v2Tag() const
|
||||
{
|
||||
return (d->ID3v2Location >= 0);
|
||||
return d->ID3v2Location >= 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace TagLib {
|
||||
//! An implementation of FLAC metadata
|
||||
|
||||
/*!
|
||||
* This is implementation of FLAC metadata for non-Ogg FLAC files. At some
|
||||
* This is an implementation of FLAC metadata for non-Ogg FLAC files. At some
|
||||
* point when Ogg / FLAC is more common there will be a similar implementation
|
||||
* under the Ogg hierarchy.
|
||||
*
|
||||
@@ -83,7 +83,7 @@ namespace TagLib {
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constructs a FLAC file from \a file. If \a readProperties is true the
|
||||
* Constructs a FLAC file from \a file. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
@@ -96,13 +96,15 @@ namespace TagLib {
|
||||
ID3v2::FrameFactory *frameFactory = nullptr);
|
||||
|
||||
/*!
|
||||
* Constructs an FLAC file from \a file. If \a readProperties is true the
|
||||
* Constructs a FLAC file from \a file. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* If this file contains an ID3v2 tag, the frames will be created using
|
||||
* \a frameFactory.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*
|
||||
* \deprecated Use the constructor above.
|
||||
*/
|
||||
TAGLIB_DEPRECATED
|
||||
File(FileName file, ID3v2::FrameFactory *frameFactory,
|
||||
@@ -110,7 +112,7 @@ namespace TagLib {
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
* Constructs a FLAC file from \a stream. If \a readProperties is true the
|
||||
* Constructs a FLAC file from \a stream. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
@@ -126,7 +128,7 @@ namespace TagLib {
|
||||
ID3v2::FrameFactory *frameFactory = nullptr);
|
||||
|
||||
/*!
|
||||
* Constructs a FLAC file from \a stream. If \a readProperties is true the
|
||||
* Constructs a FLAC file from \a stream. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
@@ -136,6 +138,8 @@ namespace TagLib {
|
||||
* \a frameFactory.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*
|
||||
* \deprecated Use the constructor above.
|
||||
*/
|
||||
TAGLIB_DEPRECATED
|
||||
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
||||
@@ -207,22 +211,22 @@ namespace TagLib {
|
||||
* will also keep any old ID3-tags up to date. If the file
|
||||
* has no XiphComment, one will be constructed from the ID3-tags.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
* This returns \c true if the save was successful.
|
||||
*/
|
||||
bool save() override;
|
||||
|
||||
/*!
|
||||
* Returns a pointer to the ID3v2 tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this returns a null pointer
|
||||
* if there is no valid ID3v2 tag. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this returns a null pointer
|
||||
* if there is no valid ID3v2 tag. If \a create is \c true it will create
|
||||
* an ID3v2 tag if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
* file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file
|
||||
* on disk actually has an ID3v2 tag.
|
||||
*
|
||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
|
||||
* deleted by the user. It will be deleted when the file (object) is
|
||||
* destroyed.
|
||||
*
|
||||
@@ -233,15 +237,15 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns a pointer to the ID3v1 tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this returns a null pointer
|
||||
* if there is no valid APE tag. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this returns a null pointer
|
||||
* if there is no valid APE tag. If \a create is \c true it will create
|
||||
* an APE tag if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
|
||||
* on disk actually has an ID3v1 tag.
|
||||
*
|
||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
|
||||
* deleted by the user. It will be deleted when the file (object) is
|
||||
* destroyed.
|
||||
*
|
||||
@@ -252,8 +256,8 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns a pointer to the XiphComment for the file.
|
||||
*
|
||||
* If \a create is false (the default) this returns a null pointer
|
||||
* if there is no valid XiphComment. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this returns a null pointer
|
||||
* if there is no valid XiphComment. If \a create is \c true it will create
|
||||
* a XiphComment if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
@@ -274,8 +278,8 @@ namespace TagLib {
|
||||
List<Picture *> pictureList();
|
||||
|
||||
/*!
|
||||
* Removes an attached picture. If \a del is true the picture's memory
|
||||
* will be freed; if it is false, it must be deleted by the user.
|
||||
* Removes an attached picture. If \a del is \c true the picture's memory
|
||||
* will be freed; if it is \c false, it must be deleted by the user.
|
||||
*/
|
||||
void removePicture(Picture *picture, bool del = true);
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
#ifndef TAGLIB_FLACMETADATABLOCK_H
|
||||
#define TAGLIB_FLACMETADATABLOCK_H
|
||||
|
||||
#include "tlist.h"
|
||||
#include "tbytevector.h"
|
||||
#include "taglib_export.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace FLAC {
|
||||
//! FLAC metadata block
|
||||
class TAGLIB_EXPORT MetadataBlock
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -35,11 +35,12 @@
|
||||
|
||||
namespace TagLib {
|
||||
namespace FLAC {
|
||||
//! FLAC picture
|
||||
class TAGLIB_EXPORT Picture : public MetadataBlock
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
/*
|
||||
* This describes the function or content of the picture.
|
||||
*/
|
||||
DECLARE_PICTURE_TYPE_ENUM(Type)
|
||||
@@ -71,7 +72,7 @@ namespace TagLib {
|
||||
* Sets the mime type of the image. This should in most cases be
|
||||
* "image/png" or "image/jpeg".
|
||||
*/
|
||||
void setMimeType(const String &m);
|
||||
void setMimeType(const String &mimeType);
|
||||
|
||||
/*!
|
||||
* Returns a text description of the image.
|
||||
@@ -80,10 +81,10 @@ namespace TagLib {
|
||||
String description() const;
|
||||
|
||||
/*!
|
||||
* Sets a textual description of the image to \a desc.
|
||||
* Sets a textual description of the image to \a description.
|
||||
*/
|
||||
|
||||
void setDescription(const String &desc);
|
||||
void setDescription(const String &description);
|
||||
|
||||
/*!
|
||||
* Returns the width of the image.
|
||||
@@ -93,7 +94,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Sets the width of the image.
|
||||
*/
|
||||
void setWidth(int w);
|
||||
void setWidth(int width);
|
||||
|
||||
/*!
|
||||
* Returns the height of the image.
|
||||
@@ -103,7 +104,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Sets the height of the image.
|
||||
*/
|
||||
void setHeight(int h);
|
||||
void setHeight(int height);
|
||||
|
||||
/*!
|
||||
* Returns the color depth (in bits-per-pixel) of the image.
|
||||
@@ -113,7 +114,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Sets the color depth (in bits-per-pixel) of the image.
|
||||
*/
|
||||
void setColorDepth(int depth);
|
||||
void setColorDepth(int colorDepth);
|
||||
|
||||
/*!
|
||||
* Returns the number of colors used on the image..
|
||||
@@ -148,7 +149,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Parse the picture data in the FLAC picture block format.
|
||||
*/
|
||||
bool parse(const ByteVector &rawData);
|
||||
bool parse(const ByteVector &data);
|
||||
|
||||
private:
|
||||
class PicturePrivate;
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#include "tstring.h"
|
||||
#include "tdebug.h"
|
||||
|
||||
#include "flacfile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class FLAC::Properties::PropertiesPrivate
|
||||
@@ -134,9 +132,9 @@ void FLAC::Properties::read(const ByteVector &data, offset_t streamLength)
|
||||
d->sampleFrames = (hi << 32) | lo;
|
||||
|
||||
if(d->sampleFrames > 0 && d->sampleRate > 0) {
|
||||
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
|
||||
const auto length = static_cast<double>(d->sampleFrames) * 1000.0 / d->sampleRate;
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
|
||||
d->bitrate = static_cast<int>(static_cast<double>(streamLength) * 8.0 / length + 0.5);
|
||||
}
|
||||
|
||||
if(data.size() >= pos + 16)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace TagLib {
|
||||
//! An implementation of audio property reading for FLAC
|
||||
|
||||
/*!
|
||||
* This reads the data from an FLAC stream found in the AudioProperties
|
||||
* This reads the data from a FLAC stream found in the AudioProperties
|
||||
* API.
|
||||
*/
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
namespace TagLib {
|
||||
namespace FLAC {
|
||||
//! Unknown FLAC metadata block
|
||||
class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
#include "tstringlist.h"
|
||||
#include "tdebug.h"
|
||||
#include "tpropertymap.h"
|
||||
#include "modfileprivate.h"
|
||||
|
||||
using namespace TagLib;
|
||||
@@ -168,7 +167,7 @@ bool IT::File::save()
|
||||
if(messageOffset + messageLength >= fileSize) {
|
||||
// append new message
|
||||
seek(54);
|
||||
writeU16L(message.size());
|
||||
writeU16L(static_cast<unsigned short>(message.size()));
|
||||
writeU32L(messageOffset);
|
||||
seek(messageOffset);
|
||||
writeBlock(message);
|
||||
|
||||
@@ -31,12 +31,27 @@
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
//! An implementation of Impulse Tracker metadata
|
||||
|
||||
/*!
|
||||
* This is an implementation of Impulse Tracker metadata.
|
||||
*/
|
||||
|
||||
namespace IT {
|
||||
|
||||
//! An implementation of TagLib::File with IT specific methods
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for IT files to the
|
||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||
* the abstract TagLib::File API as well as providing some additional
|
||||
* information specific to IT files.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public Mod::FileBase {
|
||||
public:
|
||||
/*!
|
||||
* Constructs a Impulse Tracker file from \a file.
|
||||
* Constructs an Impulse Tracker file from \a file.
|
||||
*
|
||||
* \note In the current implementation, both \a readProperties and
|
||||
* \a propertiesStyle are ignored. The audio properties are always
|
||||
@@ -47,7 +62,7 @@ namespace TagLib {
|
||||
AudioProperties::Average);
|
||||
|
||||
/*!
|
||||
* Constructs a Impulse Tracker file from \a stream.
|
||||
* Constructs an Impulse Tracker file from \a stream.
|
||||
*
|
||||
* \note In the current implementation, both \a readProperties and
|
||||
* \a propertiesStyle are ignored. The audio properties are always
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
#ifndef TAGLIB_ITPROPERTIES_H
|
||||
#define TAGLIB_ITPROPERTIES_H
|
||||
|
||||
#include "taglib.h"
|
||||
#include "audioproperties.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace IT {
|
||||
//! An implementation of audio property reading for IT
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||
public:
|
||||
/*! Flag bits. */
|
||||
|
||||
70
taglib/matroska/ebml/ebmlbinaryelement.cpp
Normal file
70
taglib/matroska/ebml/ebmlbinaryelement.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlbinaryelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "tfile.h"
|
||||
#include "tdebug.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::BinaryElement::BinaryElement(Id id, int sizeLength, offset_t dataSize):
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::BinaryElement::BinaryElement(Id id, int sizeLength, offset_t dataSize, offset_t):
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::BinaryElement::BinaryElement(Id id):
|
||||
Element(id, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
const ByteVector& EBML::BinaryElement::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void EBML::BinaryElement::setValue(const ByteVector& val)
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
|
||||
bool EBML::BinaryElement::read(File &file)
|
||||
{
|
||||
value = file.readBlock(dataSize);
|
||||
if(value.size() != dataSize) {
|
||||
debug("Failed to read binary element");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ByteVector EBML::BinaryElement::render()
|
||||
{
|
||||
ByteVector buffer = renderId();
|
||||
dataSize = value.size();
|
||||
buffer.append(renderVINT(dataSize, 0));
|
||||
buffer.append(value);
|
||||
return buffer;
|
||||
}
|
||||
51
taglib/matroska/ebml/ebmlbinaryelement.h
Normal file
51
taglib/matroska/ebml/ebmlbinaryelement.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLBINARYELEMENT_H
|
||||
#define TAGLIB_EBMLBINARYELEMENT_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlelement.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
|
||||
namespace EBML {
|
||||
class BinaryElement : public Element
|
||||
{
|
||||
public:
|
||||
BinaryElement(Id id, int sizeLength, offset_t dataSize);
|
||||
BinaryElement(Id id, int sizeLength, offset_t dataSize, offset_t);
|
||||
explicit BinaryElement(Id id);
|
||||
|
||||
const ByteVector &getValue() const;
|
||||
void setValue(const ByteVector &val);
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
|
||||
private:
|
||||
ByteVector value;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
213
taglib/matroska/ebml/ebmlelement.cpp
Normal file
213
taglib/matroska/ebml/ebmlelement.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlelement.h"
|
||||
#include "ebmlvoidelement.h"
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlbinaryelement.h"
|
||||
#include "ebmlfloatelement.h"
|
||||
#include "ebmlmkseekhead.h"
|
||||
#include "ebmlmksegment.h"
|
||||
#include "ebmlmktags.h"
|
||||
#include "ebmlmkattachments.h"
|
||||
#include "ebmlmkchapters.h"
|
||||
#include "ebmlmktracks.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "tfile.h"
|
||||
#include "tdebug.h"
|
||||
#include "tutils.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
#define RETURN_ELEMENT_FOR_CASE(eid) \
|
||||
case (eid): return make_unique_element<eid>(id, sizeLength, dataSize, offset)
|
||||
|
||||
std::unique_ptr<EBML::Element> EBML::Element::factory(File &file)
|
||||
{
|
||||
// Get the element ID
|
||||
const offset_t offset = file.tell();
|
||||
unsigned int uintId = readId(file);
|
||||
if(!uintId) {
|
||||
debug("Failed to parse EMBL ElementID");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get the size length and data length
|
||||
const auto &[sizeLength, dataSize] = readVINT(file);
|
||||
if(!sizeLength)
|
||||
return nullptr;
|
||||
|
||||
// Return the subclass
|
||||
// The enum switch without default will give us a warning if an ID is missing
|
||||
auto id = static_cast<Id>(uintId);
|
||||
switch(id) {
|
||||
RETURN_ELEMENT_FOR_CASE(Id::EBMLHeader);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::DocType);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::DocTypeVersion);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSegment);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkInfo);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTracks);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTags);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkAttachments);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTag);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTagTargets);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSimpleTag);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFile);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSeek);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTrackEntry);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkAudio);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTagName);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTagString);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileName);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileDescription);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTagLanguage);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileMediaType);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCodecID);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTagTargetTypeValue);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTagTrackUID);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTagsLanguageDefault);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileUID);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSeekPosition);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTimestampScale);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkBitDepth);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChannels);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileData);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSeekID);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkDuration);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTitle);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSamplingFrequency);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSeekHead);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::VoidElement);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCluster);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCodecState);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTagBinary);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCues);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCuePoint);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueTime);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueTrackPositions);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueTrack);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueClusterPosition);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueRelativePosition);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueDuration);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueBlockNumber);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueCodecState);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueReference);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkCueRefTime);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChapters);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkEditionEntry);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkEditionUID);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkEditionFlagDefault);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkEditionFlagOrdered);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChapterAtom);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChapterUID);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChapterTimeStart);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChapterTimeEnd);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChapterFlagHidden);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChapterDisplay);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChapString);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkChapLanguage);
|
||||
}
|
||||
return std::make_unique<Element>(id, sizeLength, dataSize);
|
||||
}
|
||||
|
||||
unsigned int EBML::Element::readId(File &file)
|
||||
{
|
||||
auto buffer = file.readBlock(1);
|
||||
if(buffer.size() != 1) {
|
||||
debug("Failed to read VINT size");
|
||||
return 0;
|
||||
}
|
||||
const unsigned int numBytes = VINTSizeLength<4>(*buffer.begin());
|
||||
if(!numBytes)
|
||||
return 0;
|
||||
if(numBytes > 1)
|
||||
buffer.append(file.readBlock(numBytes - 1));
|
||||
if(buffer.size() != numBytes) {
|
||||
debug("Failed to read VINT data");
|
||||
return 0;
|
||||
}
|
||||
return buffer.toUInt(true);
|
||||
}
|
||||
|
||||
EBML::Element::Element(Id id, int sizeLength, offset_t dataSize):
|
||||
id(id), sizeLength(sizeLength), dataSize(dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::Element::Element(Id id, int sizeLength, offset_t dataSize, offset_t):
|
||||
id(id), sizeLength(sizeLength), dataSize(dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::Element::~Element() = default;
|
||||
|
||||
bool EBML::Element::read(File& file)
|
||||
{
|
||||
skipData(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EBML::Element::skipData(File &file)
|
||||
{
|
||||
file.seek(dataSize, File::Position::Current);
|
||||
}
|
||||
|
||||
EBML::Element::Id EBML::Element::getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
offset_t EBML::Element::headSize() const
|
||||
{
|
||||
return idSize(id) + sizeLength;
|
||||
}
|
||||
|
||||
offset_t EBML::Element::getSize() const
|
||||
{
|
||||
return headSize() + dataSize;
|
||||
}
|
||||
|
||||
int EBML::Element::getSizeLength() const
|
||||
{
|
||||
return sizeLength;
|
||||
}
|
||||
|
||||
int64_t EBML::Element::getDataSize() const
|
||||
{
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
ByteVector EBML::Element::render()
|
||||
{
|
||||
ByteVector buffer = renderId();
|
||||
buffer.append(renderVINT(0, 0));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
ByteVector EBML::Element::renderId() const
|
||||
{
|
||||
const int numBytes = idSize(id);
|
||||
static const auto byteOrder = Utils::systemByteOrder();
|
||||
const auto uintId = static_cast<uint32_t>(id);
|
||||
uint32_t data = byteOrder == Utils::LittleEndian ? Utils::byteSwap(uintId) : uintId;
|
||||
return ByteVector(reinterpret_cast<char *>(&data) + (4 - numBytes), numBytes);
|
||||
}
|
||||
249
taglib/matroska/ebml/ebmlelement.h
Normal file
249
taglib/matroska/ebml/ebmlelement.h
Normal file
@@ -0,0 +1,249 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLELEMENT_H
|
||||
#define TAGLIB_EBMLELEMENT_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib
|
||||
{
|
||||
class File;
|
||||
class ByteVector;
|
||||
|
||||
namespace EBML {
|
||||
|
||||
class Element
|
||||
{
|
||||
public:
|
||||
enum class Id : unsigned int
|
||||
{
|
||||
EBMLHeader = 0x1A45DFA3,
|
||||
DocType = 0x4282,
|
||||
DocTypeVersion = 0x4287,
|
||||
VoidElement = 0xEC,
|
||||
MkSegment = 0x18538067,
|
||||
MkTags = 0x1254C367,
|
||||
MkTag = 0x7373,
|
||||
MkTagTargets = 0x63C0,
|
||||
MkTagTargetTypeValue = 0x68CA,
|
||||
MkTagTrackUID = 0x63C5,
|
||||
MkSimpleTag = 0x67C8,
|
||||
MkTagName = 0x45A3,
|
||||
MkTagLanguage = 0x447A,
|
||||
MkTagBinary = 0x4485,
|
||||
MkTagString = 0x4487,
|
||||
MkTagsTagLanguage = 0x447A,
|
||||
MkTagsLanguageDefault = 0x4484,
|
||||
MkAttachments = 0x1941A469,
|
||||
MkAttachedFile = 0x61A7,
|
||||
MkAttachedFileDescription = 0x467E,
|
||||
MkAttachedFileName = 0x466E,
|
||||
MkAttachedFileMediaType = 0x4660,
|
||||
MkAttachedFileData = 0x465C,
|
||||
MkAttachedFileUID = 0x46AE,
|
||||
MkSeekHead = 0x114D9B74,
|
||||
MkSeek = 0x4DBB,
|
||||
MkSeekID = 0x53AB,
|
||||
MkSeekPosition = 0x53AC,
|
||||
MkCluster = 0x1F43B675,
|
||||
MkCodecState = 0xA4,
|
||||
MkCues = 0x1C53BB6B,
|
||||
MkCuePoint = 0xBB,
|
||||
MkCueTime = 0xB3,
|
||||
MkCueTrackPositions = 0xB7,
|
||||
MkCueTrack = 0xF7,
|
||||
MkCueClusterPosition = 0xF1,
|
||||
MkCueRelativePosition = 0xF0,
|
||||
MkCueDuration = 0xB2,
|
||||
MkCueBlockNumber = 0x5378,
|
||||
MkCueCodecState = 0xEA,
|
||||
MkCueReference = 0xDB,
|
||||
MkCueRefTime = 0x96,
|
||||
MkInfo = 0x1549A966,
|
||||
MkTimestampScale = 0x2AD7B1,
|
||||
MkDuration = 0x4489,
|
||||
MkTitle = 0x7BA9,
|
||||
MkTracks = 0x1654AE6B,
|
||||
MkTrackEntry = 0xAE,
|
||||
MkCodecID = 0x86,
|
||||
MkAudio = 0xE1,
|
||||
MkSamplingFrequency = 0xB5,
|
||||
MkBitDepth = 0x6264,
|
||||
MkChannels = 0x9F,
|
||||
MkChapters = 0x1043A770,
|
||||
MkEditionEntry = 0x45B9,
|
||||
MkEditionUID = 0x45BC,
|
||||
MkEditionFlagDefault = 0x45DB,
|
||||
MkEditionFlagOrdered = 0x45DD,
|
||||
MkChapterAtom = 0xB6,
|
||||
MkChapterUID = 0x73C4,
|
||||
MkChapterTimeStart = 0x91,
|
||||
MkChapterTimeEnd = 0x92,
|
||||
MkChapterFlagHidden = 0x98,
|
||||
MkChapterDisplay = 0x80,
|
||||
MkChapString = 0x85,
|
||||
MkChapLanguage = 0x437C,
|
||||
};
|
||||
|
||||
Element(Id id, int sizeLength, offset_t dataSize);
|
||||
Element(Id id, int sizeLength, offset_t dataSize, offset_t);
|
||||
virtual ~Element();
|
||||
|
||||
virtual bool read(File &file);
|
||||
void skipData(File &file);
|
||||
Id getId() const;
|
||||
offset_t headSize() const;
|
||||
offset_t getSize() const;
|
||||
int getSizeLength() const;
|
||||
int64_t getDataSize() const;
|
||||
ByteVector renderId() const;
|
||||
virtual ByteVector render();
|
||||
static std::unique_ptr<Element> factory(File &file);
|
||||
static unsigned int readId(File &file);
|
||||
|
||||
protected:
|
||||
Id id;
|
||||
int sizeLength;
|
||||
offset_t dataSize;
|
||||
};
|
||||
|
||||
// Template specializations to ensure that elements for the different IDs
|
||||
// are consistently created and cast. They provide a mapping between IDs
|
||||
// and Element subclasses. The switch in factory() makes sure that the
|
||||
// template for all IDs are instantiated, i.e. that every ID has its Element
|
||||
// subclass mapped.
|
||||
class MasterElement;
|
||||
class UIntElement;
|
||||
class BinaryElement;
|
||||
class FloatElement;
|
||||
class MkSegment;
|
||||
class MkInfo;
|
||||
class MkTracks;
|
||||
class MkTags;
|
||||
class MkAttachments;
|
||||
class MkSeekHead;
|
||||
class MkChapters;
|
||||
class MkCues;
|
||||
class VoidElement;
|
||||
class UTF8StringElement;
|
||||
class Latin1StringElement;
|
||||
|
||||
template <Element::Id ID>
|
||||
struct GetElementTypeById;
|
||||
|
||||
template <> struct GetElementTypeById<Element::Id::EBMLHeader> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::DocType> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::DocTypeVersion> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSegment> { using type = MkSegment; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkInfo> { using type = MkInfo; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTracks> { using type = MkTracks; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTags> { using type = MkTags; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachments> { using type = MkAttachments; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTag> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagTargets> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSimpleTag> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFile> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeek> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTrackEntry> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAudio> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCuePoint> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueTrackPositions> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueReference> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCluster> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCues> { using type = MkCues; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagName> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagString> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileName> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileDescription> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagLanguage> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileMediaType> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCodecID> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagTargetTypeValue> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagTrackUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekPosition> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTimestampScale> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkBitDepth> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChannels> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueTime> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueTrack> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueClusterPosition> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueRelativePosition> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueDuration> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueBlockNumber> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueCodecState> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCueRefTime> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagsLanguageDefault> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkAttachedFileData> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekID> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagBinary> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCodecState> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkDuration> { using type = FloatElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTitle> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSamplingFrequency> { using type = FloatElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekHead> { using type = MkSeekHead; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapters> { using type = MkChapters; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionEntry> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionFlagDefault> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkEditionFlagOrdered> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterAtom> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterUID> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterTimeStart> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterTimeEnd> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterFlagHidden> { using type = UIntElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapterDisplay> { using type = MasterElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapString> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkChapLanguage> { using type = Latin1StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::VoidElement> { using type = VoidElement; };
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
const T *element_cast(const std::unique_ptr<Element> &ptr)
|
||||
{
|
||||
return static_cast<const T *>(ptr.get());
|
||||
}
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
std::unique_ptr<T> element_cast(std::unique_ptr<Element> &&ptr)
|
||||
{
|
||||
return std::unique_ptr<T>(static_cast<T *>(ptr.release()));
|
||||
}
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
std::unique_ptr<T> make_unique_element(Element::Id id, int sizeLength, offset_t dataSize, offset_t offset)
|
||||
{
|
||||
return std::make_unique<T>(id, sizeLength, dataSize, offset);
|
||||
}
|
||||
|
||||
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
|
||||
std::unique_ptr<T> make_unique_element()
|
||||
{
|
||||
return std::make_unique<T>(ID, 0, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
109
taglib/matroska/ebml/ebmlfloatelement.cpp
Normal file
109
taglib/matroska/ebml/ebmlfloatelement.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlfloatelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "tbytevector.h"
|
||||
#include "tfile.h"
|
||||
#include "tdebug.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::FloatElement::FloatElement(Id id, int sizeLength, offset_t dataSize):
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::FloatElement::FloatElement(Id id, int sizeLength, offset_t dataSize, offset_t):
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::FloatElement::FloatElement(Id id):
|
||||
FloatElement(id, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::FloatElement::FloatVariantType EBML::FloatElement::getValue() const
|
||||
{ return value; }
|
||||
|
||||
double EBML::FloatElement::getValueAsDouble(double defaultValue) const
|
||||
{
|
||||
if(std::holds_alternative<double>(value)) {
|
||||
// get_if() used instead of get() to support restricted compilers
|
||||
return *std::get_if<double>(&value);
|
||||
}
|
||||
if(std::holds_alternative<float>(value)) {
|
||||
// get_if() used instead of get() to support restricted compilers
|
||||
return *std::get_if<float>(&value);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
void EBML::FloatElement::setValue(FloatVariantType val)
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
|
||||
bool EBML::FloatElement::read(File &file)
|
||||
{
|
||||
const ByteVector buffer = file.readBlock(dataSize);
|
||||
if(buffer.size() != dataSize) {
|
||||
debug("Failed to read EBML Float element");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(dataSize == 0) {
|
||||
value = std::monostate();
|
||||
}
|
||||
else if(dataSize == 4) {
|
||||
value = buffer.toFloat32BE(0);
|
||||
}
|
||||
else if(dataSize == 8) {
|
||||
value = buffer.toFloat64BE(0);
|
||||
}
|
||||
else {
|
||||
debug("Invalid size for EBML Float element");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ByteVector EBML::FloatElement::render()
|
||||
{
|
||||
ByteVector data;
|
||||
if(std::holds_alternative<double>(value)) {
|
||||
// get_if() used instead of get() to support restricted compilers
|
||||
data = ByteVector::fromFloat64BE(*std::get_if<double>(&value));
|
||||
}
|
||||
else if(std::holds_alternative<float>(value)) {
|
||||
// get_if() used instead of get() to support restricted compilers
|
||||
data = ByteVector::fromFloat32BE(*std::get_if<float>(&value));
|
||||
}
|
||||
ByteVector buffer = renderId();
|
||||
buffer.append(renderVINT(data.size(), 0));
|
||||
buffer.append(data);
|
||||
return buffer;
|
||||
}
|
||||
59
taglib/matroska/ebml/ebmlfloatelement.h
Normal file
59
taglib/matroska/ebml/ebmlfloatelement.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLFLOATELEMENT_H
|
||||
#define TAGLIB_EBMLFLOATELEMENT_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include <variant>
|
||||
#include "ebmlelement.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
|
||||
namespace EBML {
|
||||
class FloatElement : public Element
|
||||
{
|
||||
public:
|
||||
using FloatVariantType = std::variant<std::monostate, float, double>;
|
||||
|
||||
FloatElement(Id id, int sizeLength, offset_t dataSize);
|
||||
FloatElement(Id id, int sizeLength, offset_t dataSize, offset_t);
|
||||
explicit FloatElement(Id id);
|
||||
|
||||
FloatVariantType getValue() const;
|
||||
double getValueAsDouble(double defaultValue = 0.0) const;
|
||||
void setValue(FloatVariantType val);
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
|
||||
private:
|
||||
FloatVariantType value;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
127
taglib/matroska/ebml/ebmlmasterelement.cpp
Normal file
127
taglib/matroska/ebml/ebmlmasterelement.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlvoidelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "tfile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::MasterElement::MasterElement(Id id, int sizeLength, offset_t dataSize, offset_t offset):
|
||||
Element(id, sizeLength, dataSize), offset(offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MasterElement::MasterElement(Id id):
|
||||
Element(id, 0, 0), offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MasterElement::~MasterElement() = default;
|
||||
|
||||
offset_t EBML::MasterElement::getOffset() const
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
void EBML::MasterElement::appendElement(std::unique_ptr<Element> &&element)
|
||||
{
|
||||
elements.push_back(std::move(element));
|
||||
}
|
||||
|
||||
std::list<std::unique_ptr<EBML::Element>>::iterator EBML::MasterElement::begin()
|
||||
{
|
||||
return elements.begin();
|
||||
}
|
||||
|
||||
std::list<std::unique_ptr<EBML::Element>>::iterator EBML::MasterElement::end()
|
||||
{
|
||||
return elements.end();
|
||||
}
|
||||
|
||||
std::list<std::unique_ptr<EBML::Element>>::const_iterator EBML::MasterElement::begin() const
|
||||
{
|
||||
return elements.begin();
|
||||
}
|
||||
|
||||
std::list<std::unique_ptr<EBML::Element>>::const_iterator EBML::MasterElement::end() const
|
||||
{
|
||||
return elements.end();
|
||||
}
|
||||
|
||||
std::list<std::unique_ptr<EBML::Element>>::const_iterator EBML::MasterElement::cbegin() const
|
||||
{
|
||||
return elements.cbegin();
|
||||
}
|
||||
|
||||
std::list<std::unique_ptr<EBML::Element>>::const_iterator EBML::MasterElement::cend() const
|
||||
{
|
||||
return elements.cend();
|
||||
}
|
||||
|
||||
offset_t EBML::MasterElement::getPadding() const
|
||||
{
|
||||
return padding;
|
||||
}
|
||||
|
||||
void EBML::MasterElement::setPadding(offset_t numBytes)
|
||||
{
|
||||
padding = numBytes;
|
||||
}
|
||||
|
||||
offset_t EBML::MasterElement::getMinRenderSize() const
|
||||
{
|
||||
return minRenderSize;
|
||||
}
|
||||
|
||||
void EBML::MasterElement::setMinRenderSize(offset_t minimumSize)
|
||||
{
|
||||
minRenderSize = minimumSize;
|
||||
}
|
||||
|
||||
bool EBML::MasterElement::read(File &file)
|
||||
{
|
||||
const offset_t maxOffset = file.tell() + dataSize;
|
||||
std::unique_ptr<Element> element;
|
||||
while((element = findNextElement(file, maxOffset))) {
|
||||
if(!element->read(file))
|
||||
return false;
|
||||
elements.push_back(std::move(element));
|
||||
}
|
||||
return file.tell() == maxOffset;
|
||||
}
|
||||
|
||||
ByteVector EBML::MasterElement::render()
|
||||
{
|
||||
ByteVector buffer = renderId();
|
||||
ByteVector data;
|
||||
for(const auto &element : elements)
|
||||
data.append(element->render());
|
||||
dataSize = data.size();
|
||||
buffer.append(renderVINT(dataSize, 0));
|
||||
buffer.append(data);
|
||||
if(minRenderSize) {
|
||||
if(const auto bufferSize = buffer.size();
|
||||
minRenderSize >= bufferSize + MIN_VOID_ELEMENT_SIZE)
|
||||
buffer.append(VoidElement::renderSize(minRenderSize - bufferSize));
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
68
taglib/matroska/ebml/ebmlmasterelement.h
Normal file
68
taglib/matroska/ebml/ebmlmasterelement.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLMASTERELEMENT_H
|
||||
#define TAGLIB_EBMLMASTERELEMENT_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "ebmlelement.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib
|
||||
{
|
||||
class ByteVector;
|
||||
|
||||
namespace EBML {
|
||||
class MasterElement : public Element
|
||||
{
|
||||
public:
|
||||
MasterElement(Id id, int sizeLength, offset_t dataSize, offset_t offset);
|
||||
explicit MasterElement(Id id);
|
||||
~MasterElement() override;
|
||||
|
||||
offset_t getOffset() const;
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
void appendElement(std::unique_ptr<Element> &&element);
|
||||
std::list<std::unique_ptr<Element>>::iterator begin();
|
||||
std::list<std::unique_ptr<Element>>::iterator end();
|
||||
std::list<std::unique_ptr<Element>>::const_iterator begin() const;
|
||||
std::list<std::unique_ptr<Element>>::const_iterator end() const;
|
||||
std::list<std::unique_ptr<Element>>::const_iterator cbegin() const;
|
||||
std::list<std::unique_ptr<Element>>::const_iterator cend() const;
|
||||
offset_t getPadding() const;
|
||||
void setPadding(offset_t numBytes);
|
||||
offset_t getMinRenderSize() const;
|
||||
void setMinRenderSize(offset_t minimumSize);
|
||||
|
||||
protected:
|
||||
offset_t offset;
|
||||
offset_t padding = 0;
|
||||
offset_t minRenderSize = 0;
|
||||
std::list<std::unique_ptr<Element>> elements;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
81
taglib/matroska/ebml/ebmlmkattachments.cpp
Normal file
81
taglib/matroska/ebml/ebmlmkattachments.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmkattachments.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlbinaryelement.h"
|
||||
#include "matroskaattachments.h"
|
||||
#include "matroskaattachedfile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::MkAttachments::MkAttachments(int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkAttachments::MkAttachments(Id, int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkAttachments::MkAttachments():
|
||||
MasterElement(Id::MkAttachments, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Attachments> EBML::MkAttachments::parse() const
|
||||
{
|
||||
auto attachments = std::make_unique<Matroska::Attachments>();
|
||||
attachments->setOffset(offset);
|
||||
attachments->setSize(getSize());
|
||||
|
||||
for(const auto &element : elements) {
|
||||
if(element->getId() != Id::MkAttachedFile)
|
||||
continue;
|
||||
|
||||
const String *filename = nullptr;
|
||||
const String *description = nullptr;
|
||||
const String *mediaType = nullptr;
|
||||
const ByteVector *data = nullptr;
|
||||
Matroska::AttachedFile::UID uid = 0;
|
||||
const auto attachedFile = element_cast<Id::MkAttachedFile>(element);
|
||||
for(const auto &attachedFileChild : *attachedFile) {
|
||||
if(const Id id = attachedFileChild->getId(); id == Id::MkAttachedFileName)
|
||||
filename = &element_cast<Id::MkAttachedFileName>(attachedFileChild)->getValue();
|
||||
else if(id == Id::MkAttachedFileData)
|
||||
data = &element_cast<Id::MkAttachedFileData>(attachedFileChild)->getValue();
|
||||
else if(id == Id::MkAttachedFileDescription)
|
||||
description = &element_cast<Id::MkAttachedFileDescription>(attachedFileChild)->getValue();
|
||||
else if(id == Id::MkAttachedFileMediaType)
|
||||
mediaType = &element_cast<Id::MkAttachedFileMediaType>(attachedFileChild)->getValue();
|
||||
else if(id == Id::MkAttachedFileUID)
|
||||
uid = element_cast<Id::MkAttachedFileUID>(attachedFileChild)->getValue();
|
||||
}
|
||||
if(!(filename && data))
|
||||
continue;
|
||||
|
||||
attachments->addAttachedFile(Matroska::AttachedFile(
|
||||
*data, *filename, mediaType ? *mediaType : String(),
|
||||
uid, description ? *description : String()));
|
||||
}
|
||||
return attachments;
|
||||
}
|
||||
47
taglib/matroska/ebml/ebmlmkattachments.h
Normal file
47
taglib/matroska/ebml/ebmlmkattachments.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLMKATTACHMENTS_H
|
||||
#define TAGLIB_EBMLMKATTACHMENTS_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Attachments;
|
||||
}
|
||||
|
||||
namespace EBML {
|
||||
class MkAttachments : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkAttachments(int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkAttachments(Id, int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkAttachments();
|
||||
|
||||
std::unique_ptr<Matroska::Attachments> parse() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
114
taglib/matroska/ebml/ebmlmkchapters.cpp
Normal file
114
taglib/matroska/ebml/ebmlmkchapters.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmkchapters.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "matroskachapters.h"
|
||||
#include "matroskachapteredition.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::MkChapters::MkChapters(int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkChapters, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkChapters::MkChapters(Id, int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkChapters, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkChapters::MkChapters():
|
||||
MasterElement(Id::MkChapters, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse() const
|
||||
{
|
||||
auto chapters = std::make_unique<Matroska::Chapters>();
|
||||
chapters->setOffset(offset);
|
||||
chapters->setSize(getSize());
|
||||
|
||||
for(const auto &element : elements) {
|
||||
if(element->getId() != Id::MkEditionEntry)
|
||||
continue;
|
||||
|
||||
List<Matroska::Chapter> editionChapters;
|
||||
Matroska::ChapterEdition::UID editionUid = 0;
|
||||
bool editionIsDefault = false;
|
||||
bool editionIsOrdered = false;
|
||||
const auto edition = element_cast<Id::MkEditionEntry>(element);
|
||||
for(const auto &editionChild : *edition) {
|
||||
if(const Id id = editionChild->getId(); id == Id::MkEditionUID)
|
||||
editionUid = element_cast<Id::MkEditionUID>(editionChild)->getValue();
|
||||
else if(id == Id::MkEditionFlagDefault)
|
||||
editionIsDefault = element_cast<Id::MkEditionFlagDefault>(editionChild)->getValue() != 0;
|
||||
else if(id == Id::MkEditionFlagOrdered)
|
||||
editionIsOrdered = element_cast<Id::MkEditionFlagOrdered>(editionChild)->getValue() != 0;
|
||||
else if(id == Id::MkChapterAtom) {
|
||||
Matroska::Chapter::UID chapterUid = 0;
|
||||
Matroska::Chapter::Time chapterTimeStart = 0;
|
||||
Matroska::Chapter::Time chapterTimeEnd = 0;
|
||||
List<Matroska::Chapter::Display> chapterDisplays;
|
||||
bool chapterHidden = false;
|
||||
const auto chapterAtom = element_cast<Id::MkChapterAtom>(editionChild);
|
||||
for(const auto &chapterChild : *chapterAtom) {
|
||||
if(const Id cid = chapterChild->getId(); cid == Id::MkChapterUID)
|
||||
chapterUid = element_cast<Id::MkChapterUID>(chapterChild)->getValue();
|
||||
else if(cid == Id::MkChapterTimeStart)
|
||||
chapterTimeStart = element_cast<Id::MkChapterTimeStart>(chapterChild)->getValue();
|
||||
else if(cid == Id::MkChapterTimeEnd)
|
||||
chapterTimeEnd = element_cast<Id::MkChapterTimeEnd>(chapterChild)->getValue();
|
||||
else if(cid == Id::MkChapterFlagHidden)
|
||||
chapterHidden = element_cast<Id::MkChapterFlagHidden>(chapterChild)->getValue() != 0;
|
||||
else if(cid == Id::MkChapterDisplay) {
|
||||
const auto display = element_cast<Id::MkChapterDisplay>(chapterChild);
|
||||
String displayString;
|
||||
String displayLanguage;
|
||||
for(const auto &displayChild : *display) {
|
||||
if(const Id did = displayChild->getId(); did == Id::MkChapString)
|
||||
displayString = element_cast<Id::MkChapString>(displayChild)->getValue();
|
||||
else if(did == Id::MkChapLanguage)
|
||||
displayLanguage = element_cast<Id::MkChapLanguage>(displayChild)->getValue();
|
||||
}
|
||||
if(!displayString.isEmpty()) {
|
||||
chapterDisplays.append(Matroska::Chapter::Display(displayString, displayLanguage));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(chapterUid) {
|
||||
editionChapters.append(Matroska::Chapter(
|
||||
chapterTimeStart, chapterTimeEnd, chapterDisplays, chapterUid, chapterHidden));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!editionChapters.isEmpty()) {
|
||||
chapters->addChapterEdition(Matroska::ChapterEdition(
|
||||
editionChapters, editionIsDefault, editionIsOrdered, editionUid));
|
||||
}
|
||||
}
|
||||
return chapters;
|
||||
}
|
||||
52
taglib/matroska/ebml/ebmlmkchapters.h
Normal file
52
taglib/matroska/ebml/ebmlmkchapters.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLMKCHAPTERS_H
|
||||
#define TAGLIB_EBMLMKCHAPTERS_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Chapters;
|
||||
}
|
||||
|
||||
namespace EBML {
|
||||
class MkChapters : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkChapters(int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkChapters(Id, int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkChapters();
|
||||
|
||||
std::unique_ptr<Matroska::Chapters> parse() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
89
taglib/matroska/ebml/ebmlmkcues.cpp
Normal file
89
taglib/matroska/ebml/ebmlmkcues.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmkcues.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "matroskacues.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::MkCues::MkCues(int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkCues, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkCues::MkCues(Id, int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkCues, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkCues::MkCues():
|
||||
MasterElement(Id::MkCues, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset) const
|
||||
{
|
||||
auto cues = std::make_unique<Matroska::Cues>(segmentDataOffset);
|
||||
cues->setOffset(offset);
|
||||
cues->setSize(getSize());
|
||||
cues->setID(static_cast<Matroska::Element::ID>(id));
|
||||
|
||||
for(const auto &cuesChild : elements) {
|
||||
if(cuesChild->getId() != Id::MkCuePoint)
|
||||
continue;
|
||||
const auto cuePointElement = element_cast<Id::MkCuePoint>(cuesChild);
|
||||
auto cuePoint = std::make_unique<Matroska::CuePoint>();
|
||||
|
||||
for(const auto &cuePointChild : *cuePointElement) {
|
||||
if(const Id id = cuePointChild->getId(); id == Id::MkCueTime)
|
||||
cuePoint->setTime(element_cast<Id::MkCueTime>(cuePointChild)->getValue());
|
||||
else if(id == Id::MkCueTrackPositions) {
|
||||
auto cueTrack = std::make_unique<Matroska::CueTrack>();
|
||||
const auto cueTrackElement = element_cast<Id::MkCueTrackPositions>(cuePointChild);
|
||||
for(const auto &cueTrackChild : *cueTrackElement) {
|
||||
if(const Id trackId = cueTrackChild->getId(); trackId == Id::MkCueTrack)
|
||||
cueTrack->setTrackNumber(element_cast<Id::MkCueTrack>(cueTrackChild)->getValue());
|
||||
else if(trackId == Id::MkCueClusterPosition)
|
||||
cueTrack->setClusterPosition(element_cast<Id::MkCueClusterPosition>(cueTrackChild)->getValue());
|
||||
else if(trackId == Id::MkCueRelativePosition)
|
||||
cueTrack->setRelativePosition(element_cast<Id::MkCueRelativePosition>(cueTrackChild)->getValue());
|
||||
else if(trackId == Id::MkCueDuration)
|
||||
cueTrack->setDuration(element_cast<Id::MkCueDuration>(cueTrackChild)->getValue());
|
||||
else if(trackId == Id::MkCueBlockNumber)
|
||||
cueTrack->setBlockNumber(element_cast<Id::MkCueBlockNumber>(cueTrackChild)->getValue());
|
||||
else if(trackId == Id::MkCueCodecState)
|
||||
cueTrack->setCodecState(element_cast<Id::MkCueCodecState>(cueTrackChild)->getValue());
|
||||
else if(trackId == Id::MkCueReference) {
|
||||
const auto cueReference = element_cast<Id::MkCueReference>(cueTrackChild);
|
||||
for(const auto &cueReferenceChild : *cueReference) {
|
||||
if(cueReferenceChild->getId() != Id::MkCueRefTime)
|
||||
continue;
|
||||
cueTrack->addReferenceTime(element_cast<Id::MkCueRefTime>(cueReferenceChild)->getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
cuePoint->addCueTrack(std::move(cueTrack));
|
||||
}
|
||||
}
|
||||
cues->addCuePoint(std::move(cuePoint));
|
||||
}
|
||||
return cues;
|
||||
}
|
||||
47
taglib/matroska/ebml/ebmlmkcues.h
Normal file
47
taglib/matroska/ebml/ebmlmkcues.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLMKCUES_H
|
||||
#define TAGLIB_EBMLMKCUES_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Cues;
|
||||
}
|
||||
|
||||
namespace EBML {
|
||||
class MkCues : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkCues(int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkCues(Id, int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkCues();
|
||||
|
||||
std::unique_ptr<Matroska::Cues> parse(offset_t segmentDataOffset) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
72
taglib/matroska/ebml/ebmlmkinfo.cpp
Normal file
72
taglib/matroska/ebml/ebmlmkinfo.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmkinfo.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlfloatelement.h"
|
||||
#include "matroskaproperties.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::MkInfo::MkInfo(int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkInfo, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkInfo::MkInfo(Id, int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkInfo, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkInfo::MkInfo():
|
||||
MasterElement(Id::MkInfo, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
void EBML::MkInfo::parse(Matroska::Properties *properties) const
|
||||
{
|
||||
if(!properties)
|
||||
return;
|
||||
|
||||
unsigned long long timestampScale = 1000000;
|
||||
double duration = 0.0;
|
||||
String title;
|
||||
for(const auto &element : elements) {
|
||||
if(const Id id = element->getId(); id == Id::MkTimestampScale) {
|
||||
timestampScale = element_cast<Id::MkTimestampScale>(element)->getValue();
|
||||
}
|
||||
else if(id == Id::MkDuration) {
|
||||
duration = element_cast<Id::MkDuration>(element)->getValueAsDouble();
|
||||
}
|
||||
else if(id == Id::MkTitle) {
|
||||
title = element_cast<Id::MkTitle>(element)->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
properties->setLengthInMilliseconds(
|
||||
static_cast<int>(duration * static_cast<double>(timestampScale) / 1000000.0));
|
||||
properties->setTitle(title);
|
||||
}
|
||||
52
taglib/matroska/ebml/ebmlmkinfo.h
Normal file
52
taglib/matroska/ebml/ebmlmkinfo.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLMKINFO_H
|
||||
#define TAGLIB_EBMLMKINFO_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Properties;
|
||||
}
|
||||
|
||||
namespace EBML {
|
||||
class MkInfo : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkInfo(int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkInfo(Id, int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkInfo();
|
||||
|
||||
void parse(Matroska::Properties * properties) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
73
taglib/matroska/ebml/ebmlmkseekhead.cpp
Normal file
73
taglib/matroska/ebml/ebmlmkseekhead.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmkseekhead.h"
|
||||
#include "matroskaseekhead.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlbinaryelement.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::MkSeekHead::MkSeekHead(int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkSeekHead::MkSeekHead(Id, int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkSeekHead::MkSeekHead():
|
||||
MasterElement(Id::MkSeekHead, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse(offset_t segmentDataOffset) const
|
||||
{
|
||||
auto seekHead = std::make_unique<Matroska::SeekHead>(segmentDataOffset);
|
||||
seekHead->setOffset(offset);
|
||||
seekHead->setSize(getSize() + padding);
|
||||
|
||||
for(const auto &element : elements) {
|
||||
if(element->getId() != Id::MkSeek)
|
||||
continue;
|
||||
const auto seekElement = element_cast<Id::MkSeek>(element);
|
||||
Matroska::Element::ID entryId = 0;
|
||||
offset_t offset = 0;
|
||||
for(const auto &seekElementChild : *seekElement) {
|
||||
if(const Id id = seekElementChild->getId(); id == Id::MkSeekID && !entryId) {
|
||||
if(auto data = element_cast<Id::MkSeekID>(seekElementChild)->getValue();
|
||||
data.size() == 4)
|
||||
entryId = data.toUInt(true);
|
||||
}
|
||||
else if(id == Id::MkSeekPosition && !offset)
|
||||
offset = element_cast<Id::MkSeekPosition>(seekElementChild)->getValue();
|
||||
}
|
||||
if(entryId && offset)
|
||||
seekHead->addEntry(entryId, offset);
|
||||
else {
|
||||
seekHead.reset();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return seekHead;
|
||||
}
|
||||
47
taglib/matroska/ebml/ebmlmkseekhead.h
Normal file
47
taglib/matroska/ebml/ebmlmkseekhead.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLMKSEEKHEAD_H
|
||||
#define TAGLIB_EBMLMKSEEKHEAD_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class SeekHead;
|
||||
}
|
||||
|
||||
namespace EBML {
|
||||
class MkSeekHead : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkSeekHead(int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkSeekHead(Id, int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkSeekHead();
|
||||
|
||||
std::unique_ptr<Matroska::SeekHead> parse(offset_t segmentDataOffset) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
148
taglib/matroska/ebml/ebmlmksegment.cpp
Normal file
148
taglib/matroska/ebml/ebmlmksegment.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmksegment.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "matroskafile.h"
|
||||
#include "matroskatag.h"
|
||||
#include "matroskaattachments.h"
|
||||
#include "matroskachapters.h"
|
||||
#include "matroskacues.h"
|
||||
#include "matroskaseekhead.h"
|
||||
#include "matroskasegment.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::MkSegment::MkSegment(int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkSegment, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkSegment::MkSegment(Id, int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkSegment, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkSegment::~MkSegment() = default;
|
||||
|
||||
offset_t EBML::MkSegment::segmentDataOffset() const
|
||||
{
|
||||
return offset + idSize(id) + sizeLength;
|
||||
}
|
||||
|
||||
bool EBML::MkSegment::read(File &file)
|
||||
{
|
||||
const offset_t maxOffset = file.tell() + dataSize;
|
||||
std::unique_ptr<Element> element;
|
||||
int i = 0;
|
||||
int seekHeadIndex = -1;
|
||||
while((element = findNextElement(file, maxOffset))) {
|
||||
if(const Id id = element->getId(); id == Id::MkSeekHead) {
|
||||
seekHeadIndex = i;
|
||||
seekHead = element_cast<Id::MkSeekHead>(std::move(element));
|
||||
if(!seekHead->read(file))
|
||||
return false;
|
||||
}
|
||||
else if(id == Id::MkCues) {
|
||||
cues = element_cast<Id::MkCues>(std::move(element));
|
||||
if(!cues->read(file))
|
||||
return false;
|
||||
}
|
||||
else if(id == Id::MkInfo) {
|
||||
info = element_cast<Id::MkInfo>(std::move(element));
|
||||
if(!info->read(file))
|
||||
return false;
|
||||
}
|
||||
else if(id == Id::MkTracks) {
|
||||
tracks = element_cast<Id::MkTracks>(std::move(element));
|
||||
if(!tracks->read(file))
|
||||
return false;
|
||||
}
|
||||
else if(id == Id::MkTags) {
|
||||
tags = element_cast<Id::MkTags>(std::move(element));
|
||||
if(!tags->read(file))
|
||||
return false;
|
||||
}
|
||||
else if(id == Id::MkAttachments) {
|
||||
attachments = element_cast<Id::MkAttachments>(std::move(element));
|
||||
if(!attachments->read(file))
|
||||
return false;
|
||||
}
|
||||
else if(id == Id::MkChapters) {
|
||||
chapters = element_cast<Id::MkChapters>(std::move(element));
|
||||
if(!chapters->read(file))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(id == Id::VoidElement
|
||||
&& seekHead
|
||||
&& seekHeadIndex == i - 1)
|
||||
seekHead->setPadding(element->getSize());
|
||||
|
||||
element->skipData(file);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Tag> EBML::MkSegment::parseTag() const
|
||||
{
|
||||
return tags ? tags->parse() : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Attachments> EBML::MkSegment::parseAttachments() const
|
||||
{
|
||||
return attachments ? attachments->parse() : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Chapters> EBML::MkSegment::parseChapters() const
|
||||
{
|
||||
return chapters ? chapters->parse() : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::SeekHead> EBML::MkSegment::parseSeekHead() const
|
||||
{
|
||||
return seekHead ? seekHead->parse(segmentDataOffset()) : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Cues> EBML::MkSegment::parseCues() const
|
||||
{
|
||||
return cues ? cues->parse(segmentDataOffset()) : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Segment> EBML::MkSegment::parseSegment() const
|
||||
{
|
||||
return std::make_unique<Matroska::Segment>(sizeLength, dataSize, offset + idSize(id));
|
||||
}
|
||||
|
||||
void EBML::MkSegment::parseInfo(Matroska::Properties *properties) const
|
||||
{
|
||||
if(info) {
|
||||
info->parse(properties);
|
||||
}
|
||||
}
|
||||
|
||||
void EBML::MkSegment::parseTracks(Matroska::Properties *properties) const
|
||||
{
|
||||
if(tracks) {
|
||||
tracks->parse(properties);
|
||||
}
|
||||
}
|
||||
76
taglib/matroska/ebml/ebmlmksegment.h
Normal file
76
taglib/matroska/ebml/ebmlmksegment.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLMKSEGMENT_H
|
||||
#define TAGLIB_EBMLMKSEGMENT_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlmktags.h"
|
||||
#include "ebmlmkattachments.h"
|
||||
#include "ebmlmkchapters.h"
|
||||
#include "ebmlmkseekhead.h"
|
||||
#include "ebmlmkcues.h"
|
||||
#include "ebmlmkinfo.h"
|
||||
#include "ebmlmktracks.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Tag;
|
||||
class Attachments;
|
||||
class Chapters;
|
||||
class SeekHead;
|
||||
class Segment;
|
||||
}
|
||||
|
||||
namespace EBML {
|
||||
class MkSegment : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkSegment(int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkSegment(Id, int sizeLength, offset_t dataSize, offset_t offset);
|
||||
~MkSegment() override;
|
||||
|
||||
offset_t segmentDataOffset() const;
|
||||
bool read(File &file) override;
|
||||
std::unique_ptr<Matroska::Tag> parseTag() const;
|
||||
std::unique_ptr<Matroska::Attachments> parseAttachments() const;
|
||||
std::unique_ptr<Matroska::Chapters> parseChapters() const;
|
||||
std::unique_ptr<Matroska::SeekHead> parseSeekHead() const;
|
||||
std::unique_ptr<Matroska::Cues> parseCues() const;
|
||||
std::unique_ptr<Matroska::Segment> parseSegment() const;
|
||||
void parseInfo(Matroska::Properties *properties) const;
|
||||
void parseTracks(Matroska::Properties *properties) const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<MkTags> tags;
|
||||
std::unique_ptr<MkAttachments> attachments;
|
||||
std::unique_ptr<MkChapters> chapters;
|
||||
std::unique_ptr<MkSeekHead> seekHead;
|
||||
std::unique_ptr<MkCues> cues;
|
||||
std::unique_ptr<MkInfo> info;
|
||||
std::unique_ptr<MkTracks> tracks;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
119
taglib/matroska/ebml/ebmlmktags.cpp
Normal file
119
taglib/matroska/ebml/ebmlmktags.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmktags.h"
|
||||
#include "ebmlbinaryelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "matroskatag.h"
|
||||
#include "matroskasimpletag.h"
|
||||
#include "tlist.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::MkTags::MkTags(int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkTags, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkTags::MkTags(Id, int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkTags, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkTags::MkTags():
|
||||
MasterElement(Id::MkTags, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<Matroska::Tag> EBML::MkTags::parse() const
|
||||
{
|
||||
auto mTag = std::make_unique<Matroska::Tag>();
|
||||
mTag->setOffset(offset);
|
||||
mTag->setSize(getSize());
|
||||
mTag->setID(static_cast<Matroska::Element::ID>(id));
|
||||
|
||||
// Loop through each <Tag> element
|
||||
for(const auto &tagsChild : elements) {
|
||||
if(tagsChild->getId() != Id::MkTag)
|
||||
continue;
|
||||
const auto tag = element_cast<Id::MkTag>(tagsChild);
|
||||
List<const MasterElement *> simpleTags;
|
||||
const MasterElement *targets = nullptr;
|
||||
|
||||
// Identify the <Targets> element and the <SimpleTag> elements
|
||||
for(const auto &tagChild : *tag) {
|
||||
if(const Id tagChildId = tagChild->getId(); !targets && tagChildId == Id::MkTagTargets)
|
||||
targets = element_cast<Id::MkTagTargets>(tagChild);
|
||||
else if(tagChildId == Id::MkSimpleTag)
|
||||
simpleTags.append(element_cast<Id::MkSimpleTag>(tagChild));
|
||||
}
|
||||
|
||||
// Parse the <Targets> element
|
||||
Matroska::SimpleTag::TargetTypeValue targetTypeValue = Matroska::SimpleTag::TargetTypeValue::None;
|
||||
unsigned long long trackUid = 0;
|
||||
if(targets) {
|
||||
for(const auto &targetsChild : *targets) {
|
||||
if(const Id id = targetsChild->getId(); id == Id::MkTagTargetTypeValue
|
||||
&& targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None) {
|
||||
targetTypeValue = static_cast<Matroska::SimpleTag::TargetTypeValue>(
|
||||
element_cast<Id::MkTagTargetTypeValue>(targetsChild)->getValue()
|
||||
);
|
||||
}
|
||||
else if(id == Id::MkTagTrackUID) {
|
||||
trackUid = element_cast<Id::MkTagTrackUID>(targetsChild)->getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse each <SimpleTag>
|
||||
for(const auto simpleTag : simpleTags) {
|
||||
const String *tagValueString = nullptr;
|
||||
const ByteVector *tagValueBinary = nullptr;
|
||||
String tagName;
|
||||
String language;
|
||||
bool defaultLanguageFlag = true;
|
||||
|
||||
for(const auto &simpleTagChild : *simpleTag) {
|
||||
if(const Id id = simpleTagChild->getId(); id == Id::MkTagName && tagName.isEmpty())
|
||||
tagName = element_cast<Id::MkTagName>(simpleTagChild)->getValue();
|
||||
else if(id == Id::MkTagString && !tagValueString)
|
||||
tagValueString = &element_cast<Id::MkTagString>(simpleTagChild)->getValue();
|
||||
else if(id == Id::MkTagBinary && !tagValueBinary)
|
||||
tagValueBinary = &element_cast<Id::MkTagBinary>(simpleTagChild)->getValue();
|
||||
else if(id == Id::MkTagsTagLanguage && language.isEmpty())
|
||||
language = element_cast<Id::MkTagsTagLanguage>(simpleTagChild)->getValue();
|
||||
else if(id == Id::MkTagsLanguageDefault)
|
||||
defaultLanguageFlag = element_cast<Id::MkTagsLanguageDefault>(simpleTagChild)->getValue() ? true : false;
|
||||
}
|
||||
if(tagName.isEmpty() || (tagValueString && tagValueBinary) || (!tagValueString && !tagValueBinary))
|
||||
continue;
|
||||
|
||||
mTag->addSimpleTag(tagValueString
|
||||
? Matroska::SimpleTag(tagName, *tagValueString,
|
||||
targetTypeValue, language, defaultLanguageFlag,
|
||||
trackUid)
|
||||
: Matroska::SimpleTag(tagName, *tagValueBinary,
|
||||
targetTypeValue, language, defaultLanguageFlag,
|
||||
trackUid));
|
||||
}
|
||||
}
|
||||
return mTag;
|
||||
}
|
||||
47
taglib/matroska/ebml/ebmlmktags.h
Normal file
47
taglib/matroska/ebml/ebmlmktags.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLMKTAGS_H
|
||||
#define TAGLIB_EBMLMKTAGS_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Tag;
|
||||
}
|
||||
|
||||
namespace EBML {
|
||||
class MkTags : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkTags(int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkTags(Id, int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkTags();
|
||||
|
||||
std::unique_ptr<Matroska::Tag> parse() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
86
taglib/matroska/ebml/ebmlmktracks.cpp
Normal file
86
taglib/matroska/ebml/ebmlmktracks.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlmktracks.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlfloatelement.h"
|
||||
#include "matroskaproperties.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::MkTracks::MkTracks(int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkTracks, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkTracks::MkTracks(Id, int sizeLength, offset_t dataSize, offset_t offset):
|
||||
MasterElement(Id::MkTracks, sizeLength, dataSize, offset)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::MkTracks::MkTracks():
|
||||
MasterElement(Id::MkTracks, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
void EBML::MkTracks::parse(Matroska::Properties *properties) const
|
||||
{
|
||||
if(!properties)
|
||||
return;
|
||||
|
||||
for(const auto &element : elements) {
|
||||
if(element->getId() != Id::MkTrackEntry)
|
||||
continue;
|
||||
|
||||
String codecId;
|
||||
double samplingFrequency = 0.0;
|
||||
unsigned long long bitDepth = 0;
|
||||
unsigned long long channels = 0;
|
||||
const auto trackEntry = element_cast<Id::MkTrackEntry>(element);
|
||||
for(const auto &trackEntryChild : *trackEntry) {
|
||||
if(const Id trackEntryChildId = trackEntryChild->getId(); trackEntryChildId == Id::MkCodecID)
|
||||
codecId = element_cast<Id::MkCodecID>(trackEntryChild)->getValue();
|
||||
else if(trackEntryChildId == Id::MkAudio) {
|
||||
const auto audio = element_cast<Id::MkAudio>(trackEntryChild);
|
||||
for(const auto &audioChild : *audio) {
|
||||
if(const Id audioChildId = audioChild->getId(); audioChildId == Id::MkSamplingFrequency)
|
||||
samplingFrequency = element_cast<Id::MkSamplingFrequency>(audioChild)->getValueAsDouble();
|
||||
else if(audioChildId == Id::MkBitDepth)
|
||||
bitDepth = element_cast<Id::MkBitDepth>(audioChild)->getValue();
|
||||
else if(audioChildId == Id::MkChannels)
|
||||
channels = element_cast<Id::MkChannels>(audioChild)->getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bitDepth || channels) {
|
||||
properties->setSampleRate(static_cast<int>(samplingFrequency));
|
||||
properties->setBitsPerSample(static_cast<int>(bitDepth));
|
||||
properties->setChannels(static_cast<int>(channels));
|
||||
properties->setCodecName(codecId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
taglib/matroska/ebml/ebmlmktracks.h
Normal file
52
taglib/matroska/ebml/ebmlmktracks.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLMKTRACKS_H
|
||||
#define TAGLIB_EBMLMKTRACKS_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace Matroska {
|
||||
class Properties;
|
||||
}
|
||||
|
||||
namespace EBML {
|
||||
class MkTracks : public MasterElement
|
||||
{
|
||||
public:
|
||||
MkTracks(int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkTracks(Id, int sizeLength, offset_t dataSize, offset_t offset);
|
||||
MkTracks();
|
||||
|
||||
void parse(Matroska::Properties *properties) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
100
taglib/matroska/ebml/ebmlstringelement.cpp
Normal file
100
taglib/matroska/ebml/ebmlstringelement.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlstringelement.h"
|
||||
#include <string>
|
||||
#include "tfile.h"
|
||||
#include "tbytevector.h"
|
||||
#include "tdebug.h"
|
||||
#include "ebmlutils.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::StringElement::StringElement(
|
||||
String::Type stringEncoding, Id id, int sizeLength, offset_t dataSize):
|
||||
Element(id, sizeLength, dataSize), encoding(stringEncoding)
|
||||
{
|
||||
}
|
||||
|
||||
const String& EBML::StringElement::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void EBML::StringElement::setValue(const String& val)
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
|
||||
bool EBML::StringElement::read(File &file)
|
||||
{
|
||||
ByteVector buffer = file.readBlock(dataSize);
|
||||
if(buffer.size() != dataSize) {
|
||||
debug("Failed to read string");
|
||||
return false;
|
||||
}
|
||||
|
||||
// The EBML strings aren't supposed to be null-terminated,
|
||||
// but we'll check for it and strip the null terminator if found
|
||||
if(const int nullByte = buffer.find('\0'); nullByte >= 0)
|
||||
buffer = ByteVector(buffer.data(), nullByte);
|
||||
value = String(buffer, encoding);
|
||||
return true;
|
||||
}
|
||||
|
||||
ByteVector EBML::StringElement::render()
|
||||
{
|
||||
ByteVector buffer = renderId();
|
||||
const std::string string = value.to8Bit(encoding == String::UTF8);
|
||||
dataSize = string.size();
|
||||
buffer.append(renderVINT(dataSize, 0));
|
||||
buffer.append(ByteVector(string.data(), static_cast<unsigned int>(dataSize)));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
EBML::UTF8StringElement::UTF8StringElement(Id id, int sizeLength, offset_t dataSize):
|
||||
StringElement(String::UTF8, id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::UTF8StringElement::UTF8StringElement(Id id, int sizeLength, offset_t dataSize, offset_t):
|
||||
UTF8StringElement(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::UTF8StringElement::UTF8StringElement(Id id):
|
||||
UTF8StringElement(id, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::Latin1StringElement::Latin1StringElement(Id id, int sizeLength, offset_t dataSize):
|
||||
StringElement(String::Latin1, id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::Latin1StringElement::Latin1StringElement(Id id, int sizeLength, offset_t dataSize, offset_t):
|
||||
Latin1StringElement(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::Latin1StringElement::Latin1StringElement(Id id):
|
||||
Latin1StringElement(id, 0, 0)
|
||||
{
|
||||
}
|
||||
65
taglib/matroska/ebml/ebmlstringelement.h
Normal file
65
taglib/matroska/ebml/ebmlstringelement.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLSTRINGELEMENT_H
|
||||
#define TAGLIB_EBMLSTRINGELEMENT_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlelement.h"
|
||||
#include "tstring.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
class ByteVector;
|
||||
|
||||
namespace EBML {
|
||||
class StringElement : public Element
|
||||
{
|
||||
public:
|
||||
StringElement(String::Type stringEncoding, Id id, int sizeLength, offset_t dataSize);
|
||||
|
||||
const String &getValue() const;
|
||||
void setValue(const String &val);
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
|
||||
private:
|
||||
String value;
|
||||
String::Type encoding;
|
||||
};
|
||||
|
||||
class UTF8StringElement : public StringElement {
|
||||
public:
|
||||
UTF8StringElement(Id id, int sizeLength, offset_t dataSize);
|
||||
UTF8StringElement(Id id, int sizeLength, offset_t dataSize, offset_t);
|
||||
explicit UTF8StringElement(Id id);
|
||||
};
|
||||
|
||||
class Latin1StringElement : public StringElement {
|
||||
public:
|
||||
Latin1StringElement(Id id, int sizeLength, offset_t dataSize);
|
||||
Latin1StringElement(Id id, int sizeLength, offset_t dataSize, offset_t);
|
||||
explicit Latin1StringElement(Id id);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
95
taglib/matroska/ebml/ebmluintelement.cpp
Normal file
95
taglib/matroska/ebml/ebmluintelement.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "tbytevector.h"
|
||||
#include "tfile.h"
|
||||
#include "tutils.h"
|
||||
#include "tdebug.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::UIntElement::UIntElement(Id id, int sizeLength, offset_t dataSize):
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::UIntElement::UIntElement(Id id, int sizeLength, offset_t dataSize, offset_t):
|
||||
Element(id, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::UIntElement::UIntElement(Id id):
|
||||
UIntElement(id, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long long EBML::UIntElement::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void EBML::UIntElement::setValue(unsigned long long val)
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
|
||||
bool EBML::UIntElement::read(File &file)
|
||||
{
|
||||
const ByteVector buffer = file.readBlock(dataSize);
|
||||
if(buffer.size() != dataSize) {
|
||||
debug("Failed to read EBML Uint element");
|
||||
return false;
|
||||
}
|
||||
value = buffer.toULongLong(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
ByteVector EBML::UIntElement::render()
|
||||
{
|
||||
int dataSize = 0;
|
||||
if(value <= 0xFFull)
|
||||
dataSize = 1;
|
||||
else if(value <= 0xFFFFull)
|
||||
dataSize = 2;
|
||||
else if(value <= 0xFFFFFFull)
|
||||
dataSize = 3;
|
||||
else if(value <= 0xFFFFFFFFull)
|
||||
dataSize = 4;
|
||||
else if(value <= 0xFFFFFFFFFFull)
|
||||
dataSize = 5;
|
||||
else if(value <= 0xFFFFFFFFFFFFull)
|
||||
dataSize = 6;
|
||||
else if(value <= 0xFFFFFFFFFFFFFFull)
|
||||
dataSize = 7;
|
||||
else if(value <= 0xFFFFFFFFFFFFFFFFull)
|
||||
dataSize = 8;
|
||||
|
||||
ByteVector buffer = renderId();
|
||||
buffer.append(renderVINT(dataSize, 0));
|
||||
uint64_t val = value;
|
||||
static const auto byteOrder = Utils::systemByteOrder();
|
||||
if(byteOrder == Utils::LittleEndian)
|
||||
val = Utils::byteSwap(val);
|
||||
|
||||
buffer.append(ByteVector(reinterpret_cast<char *>(&val) + (sizeof(val) - dataSize), dataSize));
|
||||
return buffer;
|
||||
}
|
||||
50
taglib/matroska/ebml/ebmluintelement.h
Normal file
50
taglib/matroska/ebml/ebmluintelement.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLUINTELEMENT_H
|
||||
#define TAGLIB_EBMLUINTELEMENT_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlelement.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
|
||||
namespace EBML {
|
||||
class UIntElement : public Element
|
||||
{
|
||||
public:
|
||||
UIntElement(Id id, int sizeLength, offset_t dataSize);
|
||||
UIntElement(Id id, int sizeLength, offset_t dataSize, offset_t);
|
||||
explicit UIntElement(Id id);
|
||||
|
||||
unsigned long long getValue() const;
|
||||
void setValue(unsigned long long val);
|
||||
bool read(File &file) override;
|
||||
ByteVector render() override;
|
||||
|
||||
private:
|
||||
unsigned long long value = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
122
taglib/matroska/ebml/ebmlutils.cpp
Normal file
122
taglib/matroska/ebml/ebmlutils.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlutils.h"
|
||||
#include <random>
|
||||
#include "tbytevector.h"
|
||||
#include "matroskafile.h"
|
||||
#include "tutils.h"
|
||||
#include "tdebug.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
std::unique_ptr<EBML::Element> EBML::findElement(File &file, Element::Id id, offset_t maxOffset)
|
||||
{
|
||||
std::unique_ptr<Element> element;
|
||||
while(file.tell() < maxOffset) {
|
||||
element = Element::factory(file);
|
||||
if(!element || element->getId() == id)
|
||||
return element;
|
||||
element->skipData(file);
|
||||
element.reset();
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
std::unique_ptr<EBML::Element> EBML::findNextElement(File &file, offset_t maxOffset)
|
||||
{
|
||||
return file.tell() < maxOffset ? Element::factory(file) : nullptr;
|
||||
}
|
||||
|
||||
template <int maxSizeLength>
|
||||
unsigned int EBML::VINTSizeLength(uint8_t firstByte)
|
||||
{
|
||||
static_assert(maxSizeLength >= 1 && maxSizeLength <= 8);
|
||||
if(!firstByte) {
|
||||
debug("VINT with greater than 8 bytes not allowed");
|
||||
return 0;
|
||||
}
|
||||
uint8_t mask = 0b10000000;
|
||||
unsigned int numBytes = 1;
|
||||
while(!(mask & firstByte)) {
|
||||
numBytes++;
|
||||
mask >>= 1;
|
||||
}
|
||||
if(numBytes > maxSizeLength) {
|
||||
debug(Utils::formatString("VINT size length exceeds %i bytes", maxSizeLength));
|
||||
return 0;
|
||||
}
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
namespace TagLib::EBML {
|
||||
template unsigned int VINTSizeLength<4>(uint8_t firstByte);
|
||||
template unsigned int VINTSizeLength<8>(uint8_t firstByte);
|
||||
}
|
||||
|
||||
std::pair<unsigned int, uint64_t> EBML::readVINT(File &file)
|
||||
{
|
||||
auto buffer = file.readBlock(1);
|
||||
if(buffer.size() != 1) {
|
||||
debug("Failed to read VINT size");
|
||||
return {0, 0};
|
||||
}
|
||||
unsigned int numBytes = VINTSizeLength<8>(*buffer.begin());
|
||||
if(!numBytes)
|
||||
return {0, 0};
|
||||
|
||||
if(numBytes > 1)
|
||||
buffer.append(file.readBlock(numBytes - 1));
|
||||
const int bitsToShift = static_cast<int>(sizeof(uint64_t) * 8) - 7 * numBytes;
|
||||
const uint64_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift;
|
||||
return { numBytes, buffer.toULongLong(true) & mask };
|
||||
}
|
||||
|
||||
std::pair<unsigned int, uint64_t> EBML::parseVINT(const ByteVector &buffer)
|
||||
{
|
||||
if(buffer.isEmpty())
|
||||
return {0, 0};
|
||||
|
||||
unsigned int numBytes = VINTSizeLength<8>(*buffer.begin());
|
||||
if(!numBytes)
|
||||
return {0, 0};
|
||||
|
||||
const int bitsToShift = static_cast<int>(sizeof(uint64_t) * 8) - 7 * numBytes;
|
||||
const uint64_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift;
|
||||
return { numBytes, buffer.toULongLong(true) & mask };
|
||||
}
|
||||
|
||||
ByteVector EBML::renderVINT(uint64_t number, int minSizeLength)
|
||||
{
|
||||
const int numBytes = std::max(minSizeLength, minSize(number));
|
||||
number |= 1ULL << (numBytes * 7);
|
||||
static const auto byteOrder = Utils::systemByteOrder();
|
||||
if(byteOrder == Utils::LittleEndian)
|
||||
number = Utils::byteSwap(number);
|
||||
return ByteVector(reinterpret_cast<char *>(&number) + (sizeof(number) - numBytes), numBytes);
|
||||
}
|
||||
|
||||
unsigned long long EBML::randomUID()
|
||||
{
|
||||
static std::random_device device;
|
||||
static std::mt19937 generator(device());
|
||||
static std::uniform_int_distribution<unsigned long long> distribution;
|
||||
return distribution(generator);
|
||||
}
|
||||
78
taglib/matroska/ebml/ebmlutils.h
Normal file
78
taglib/matroska/ebml/ebmlutils.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLUTILS_H
|
||||
#define TAGLIB_EBMLUTILS_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include <utility>
|
||||
#include "taglib.h"
|
||||
#include "ebmlelement.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
class ByteVector;
|
||||
|
||||
namespace EBML {
|
||||
std::unique_ptr<Element> findElement(File &file, Element::Id id, offset_t maxOffset);
|
||||
std::unique_ptr<Element> findNextElement(File &file, offset_t maxOffset);
|
||||
|
||||
template <int maxSizeLength>
|
||||
unsigned int VINTSizeLength(uint8_t firstByte);
|
||||
|
||||
std::pair<unsigned int, uint64_t> readVINT(File &file);
|
||||
|
||||
std::pair<unsigned int, uint64_t> parseVINT(const ByteVector &buffer);
|
||||
|
||||
ByteVector renderVINT(uint64_t number, int minSizeLength);
|
||||
|
||||
unsigned long long randomUID();
|
||||
|
||||
constexpr int minSize(uint64_t data)
|
||||
{
|
||||
if(data <= 0x7Fu)
|
||||
return 1;
|
||||
if(data <= 0x3FFFu)
|
||||
return 2;
|
||||
if(data <= 0x1FFFFFu)
|
||||
return 3;
|
||||
if(data <= 0xFFFFFFFu)
|
||||
return 4;
|
||||
if(data <= 0x7FFFFFFFFu)
|
||||
return 5;
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr int idSize(Element::Id id)
|
||||
{
|
||||
const auto uintId = static_cast<unsigned int>(id);
|
||||
if(uintId <= 0xFF)
|
||||
return 1;
|
||||
if(uintId <= 0xFFFF)
|
||||
return 2;
|
||||
if(uintId <= 0xFFFFFF)
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
73
taglib/matroska/ebml/ebmlvoidelement.cpp
Normal file
73
taglib/matroska/ebml/ebmlvoidelement.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "ebmlvoidelement.h"
|
||||
#include <algorithm>
|
||||
#include "ebmlutils.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
EBML::VoidElement::VoidElement(int sizeLength, offset_t dataSize):
|
||||
Element(Id::VoidElement, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::VoidElement::VoidElement(Id, int sizeLength, offset_t dataSize, offset_t):
|
||||
Element(Id::VoidElement, sizeLength, dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
EBML::VoidElement::VoidElement():
|
||||
Element(Id::VoidElement, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
ByteVector EBML::VoidElement::render()
|
||||
{
|
||||
offset_t bytesNeeded = targetSize;
|
||||
ByteVector buffer = renderId();
|
||||
bytesNeeded -= buffer.size();
|
||||
sizeLength = static_cast<int>(std::min(bytesNeeded, static_cast<offset_t>(8)));
|
||||
bytesNeeded -= sizeLength;
|
||||
dataSize = bytesNeeded;
|
||||
buffer.append(renderVINT(dataSize, sizeLength));
|
||||
if(dataSize)
|
||||
buffer.append(ByteVector(static_cast<unsigned int>(dataSize), 0));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
offset_t EBML::VoidElement::getTargetSize() const
|
||||
{
|
||||
return targetSize;
|
||||
}
|
||||
|
||||
void EBML::VoidElement::setTargetSize(offset_t size)
|
||||
{
|
||||
this->targetSize = std::max(size, MIN_VOID_ELEMENT_SIZE);
|
||||
}
|
||||
|
||||
ByteVector EBML::VoidElement::renderSize(offset_t targetSize)
|
||||
{
|
||||
VoidElement element;
|
||||
element.setTargetSize(targetSize);
|
||||
return element.render();
|
||||
}
|
||||
51
taglib/matroska/ebml/ebmlvoidelement.h
Normal file
51
taglib/matroska/ebml/ebmlvoidelement.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_EBMLVOIDELEMENT_H
|
||||
#define TAGLIB_EBMLVOIDELEMENT_H
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
|
||||
#include "ebmlelement.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
|
||||
namespace EBML {
|
||||
inline constexpr offset_t MIN_VOID_ELEMENT_SIZE = 2;
|
||||
class VoidElement : public Element
|
||||
{
|
||||
public:
|
||||
VoidElement(int sizeLength, offset_t dataSize);
|
||||
VoidElement(Id, int sizeLength, offset_t dataSize, offset_t);
|
||||
VoidElement();
|
||||
|
||||
ByteVector render() override;
|
||||
offset_t getTargetSize() const;
|
||||
void setTargetSize(offset_t size);
|
||||
static ByteVector renderSize(offset_t targetSize);
|
||||
|
||||
private:
|
||||
offset_t targetSize = MIN_VOID_ELEMENT_SIZE;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
99
taglib/matroska/matroskaattachedfile.cpp
Normal file
99
taglib/matroska/matroskaattachedfile.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "matroskaattachedfile.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class Matroska::AttachedFile::AttachedFilePrivate
|
||||
{
|
||||
public:
|
||||
AttachedFilePrivate(const ByteVector &data, const String &fileName,
|
||||
const String &mediaType, UID uid, const String &description) :
|
||||
fileName(fileName), description(description), mediaType(mediaType),
|
||||
data(data), uid(uid) {}
|
||||
~AttachedFilePrivate() = default;
|
||||
String fileName;
|
||||
String description;
|
||||
String mediaType;
|
||||
ByteVector data;
|
||||
UID uid = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Matroska::AttachedFile::AttachedFile(const ByteVector &data,
|
||||
const String &fileName, const String &mediaType, UID uid,
|
||||
const String &description) :
|
||||
d(std::make_unique<AttachedFilePrivate>(data, fileName, mediaType, uid, description))
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::AttachedFile::AttachedFile(const AttachedFile &other) :
|
||||
d(std::make_unique<AttachedFilePrivate>(*other.d))
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::AttachedFile::AttachedFile(AttachedFile &&other) noexcept = default;
|
||||
|
||||
Matroska::AttachedFile::~AttachedFile() = default;
|
||||
|
||||
Matroska::AttachedFile &Matroska::AttachedFile::operator=(AttachedFile &&other) noexcept = default;
|
||||
|
||||
Matroska::AttachedFile &Matroska::AttachedFile::operator=(const AttachedFile &other)
|
||||
{
|
||||
AttachedFile(other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Matroska::AttachedFile::swap(AttachedFile &other) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
swap(d, other.d);
|
||||
}
|
||||
|
||||
const String &Matroska::AttachedFile::fileName() const
|
||||
{
|
||||
return d->fileName;
|
||||
}
|
||||
|
||||
const String &Matroska::AttachedFile::description() const
|
||||
{
|
||||
return d->description;
|
||||
}
|
||||
|
||||
const String &Matroska::AttachedFile::mediaType() const
|
||||
{
|
||||
return d->mediaType;
|
||||
}
|
||||
|
||||
const ByteVector &Matroska::AttachedFile::data() const
|
||||
{
|
||||
return d->data;
|
||||
}
|
||||
|
||||
Matroska::AttachedFile::UID Matroska::AttachedFile::uid() const
|
||||
{
|
||||
return d->uid;
|
||||
}
|
||||
110
taglib/matroska/matroskaattachedfile.h
Normal file
110
taglib/matroska/matroskaattachedfile.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_MATROSKAATTACHEDFILE_H
|
||||
#define TAGLIB_MATROSKAATTACHEDFILE_H
|
||||
|
||||
#include <memory>
|
||||
#include "tstring.h"
|
||||
#include "taglib_export.h"
|
||||
|
||||
namespace TagLib {
|
||||
class String;
|
||||
class ByteVector;
|
||||
|
||||
namespace Matroska {
|
||||
//! Attached file embedded into a Matroska file.
|
||||
class TAGLIB_EXPORT AttachedFile
|
||||
{
|
||||
public:
|
||||
//! Unique identifier.
|
||||
using UID = unsigned long long;
|
||||
|
||||
/*!
|
||||
* Construct an attached file.
|
||||
*/
|
||||
AttachedFile(const ByteVector &data, const String &fileName,
|
||||
const String &mediaType, UID uid = 0,
|
||||
const String &description = String());
|
||||
|
||||
/*!
|
||||
* Construct an attached file as a copy of \a other.
|
||||
*/
|
||||
AttachedFile(const AttachedFile &other);
|
||||
|
||||
/*!
|
||||
* Construct an attached file moving from \a other.
|
||||
*/
|
||||
AttachedFile(AttachedFile &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Destroys this attached file.
|
||||
*/
|
||||
~AttachedFile();
|
||||
|
||||
/*!
|
||||
* Copies the contents of \a other into this object.
|
||||
*/
|
||||
AttachedFile &operator=(const AttachedFile &other);
|
||||
|
||||
/*!
|
||||
* Moves the contents of \a other into this object.
|
||||
*/
|
||||
AttachedFile &operator=(AttachedFile &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the object with the content of \a other.
|
||||
*/
|
||||
void swap(AttachedFile &other) noexcept;
|
||||
|
||||
/*!
|
||||
* Returns the filename of the attached file.
|
||||
*/
|
||||
const String &fileName() const;
|
||||
|
||||
/*!
|
||||
* Returns the human-friendly description for the attached file.
|
||||
*/
|
||||
const String &description() const;
|
||||
|
||||
/*!
|
||||
* Returns the media type of the attached file.
|
||||
*/
|
||||
const String &mediaType() const;
|
||||
|
||||
/*!
|
||||
* Returns the data of the attached file.
|
||||
*/
|
||||
const ByteVector &data() const;
|
||||
|
||||
/*!
|
||||
* Returns the UID of the attached file.
|
||||
*/
|
||||
UID uid() const;
|
||||
|
||||
private:
|
||||
class AttachedFilePrivate;
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
std::unique_ptr<AttachedFilePrivate> d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
141
taglib/matroska/matroskaattachments.cpp
Normal file
141
taglib/matroska/matroskaattachments.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "matroskaattachments.h"
|
||||
#include "matroskaattachedfile.h"
|
||||
#include "ebmlmkattachments.h"
|
||||
#include "ebmlmasterelement.h"
|
||||
#include "ebmlstringelement.h"
|
||||
#include "ebmlbinaryelement.h"
|
||||
#include "ebmluintelement.h"
|
||||
#include "ebmlutils.h"
|
||||
#include "tlist.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class Matroska::Attachments::AttachmentsPrivate
|
||||
{
|
||||
public:
|
||||
AttachmentsPrivate() = default;
|
||||
~AttachmentsPrivate() = default;
|
||||
AttachmentsPrivate(const AttachmentsPrivate &) = delete;
|
||||
AttachmentsPrivate &operator=(const AttachmentsPrivate &) = delete;
|
||||
AttachedFileList files;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Matroska::Attachments::Attachments() :
|
||||
Element(static_cast<ID>(EBML::Element::Id::MkAttachments)),
|
||||
d(std::make_unique<AttachmentsPrivate>())
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::Attachments::~Attachments() = default;
|
||||
|
||||
void Matroska::Attachments::addAttachedFile(const AttachedFile &file)
|
||||
{
|
||||
d->files.append(file);
|
||||
setNeedsRender(true);
|
||||
}
|
||||
|
||||
void Matroska::Attachments::removeAttachedFile(unsigned long long uid)
|
||||
{
|
||||
const auto it = std::find_if(d->files.begin(), d->files.end(),
|
||||
[uid](const AttachedFile &file) {
|
||||
return file.uid() == uid;
|
||||
});
|
||||
if(it != d->files.end()) {
|
||||
d->files.erase(it);
|
||||
setNeedsRender(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Matroska::Attachments::clear()
|
||||
{
|
||||
d->files.clear();
|
||||
setNeedsRender(true);
|
||||
}
|
||||
|
||||
const Matroska::Attachments::AttachedFileList &Matroska::Attachments::attachedFileList() const
|
||||
{
|
||||
return d->files;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Matroska::Attachments::AttachedFileList &Matroska::Attachments::attachedFiles()
|
||||
{
|
||||
setNeedsRender(true);
|
||||
return d->files;
|
||||
}
|
||||
|
||||
ByteVector Matroska::Attachments::renderInternal()
|
||||
{
|
||||
if(d->files.isEmpty()) {
|
||||
// Avoid writing an Attachments element without AttachedFile element.
|
||||
return {};
|
||||
}
|
||||
|
||||
EBML::MkAttachments attachments;
|
||||
for(const auto &attachedFile : std::as_const(d->files)) {
|
||||
auto attachedFileElement = EBML::make_unique_element<EBML::Element::Id::MkAttachedFile>();
|
||||
|
||||
// Filename
|
||||
auto fileNameElement = EBML::make_unique_element<EBML::Element::Id::MkAttachedFileName>();
|
||||
fileNameElement->setValue(attachedFile.fileName());
|
||||
attachedFileElement->appendElement(std::move(fileNameElement));
|
||||
|
||||
// Media/MIME type
|
||||
auto mediaTypeElement =
|
||||
EBML::make_unique_element<EBML::Element::Id::MkAttachedFileMediaType>();
|
||||
mediaTypeElement->setValue(attachedFile.mediaType());
|
||||
attachedFileElement->appendElement(std::move(mediaTypeElement));
|
||||
|
||||
// Description
|
||||
if(const String &description = attachedFile.description(); !description.isEmpty()) {
|
||||
auto descriptionElement =
|
||||
EBML::make_unique_element<EBML::Element::Id::MkAttachedFileDescription>();
|
||||
descriptionElement->setValue(description);
|
||||
attachedFileElement->appendElement(std::move(descriptionElement));
|
||||
}
|
||||
|
||||
// Data
|
||||
auto dataElement = EBML::make_unique_element<EBML::Element::Id::MkAttachedFileData>();
|
||||
dataElement->setValue(attachedFile.data());
|
||||
attachedFileElement->appendElement(std::move(dataElement));
|
||||
|
||||
// UID
|
||||
auto uidElement = EBML::make_unique_element<EBML::Element::Id::MkAttachedFileUID>();
|
||||
AttachedFile::UID uid = attachedFile.uid();
|
||||
if(!uid)
|
||||
uid = EBML::randomUID();
|
||||
uidElement->setValue(uid);
|
||||
attachedFileElement->appendElement(std::move(uidElement));
|
||||
|
||||
attachments.appendElement(std::move(attachedFileElement));
|
||||
}
|
||||
return attachments.render();
|
||||
}
|
||||
83
taglib/matroska/matroskaattachments.h
Normal file
83
taglib/matroska/matroskaattachments.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_MATROSKAATTACHMENTS_H
|
||||
#define TAGLIB_MATROSKAATTACHMENTS_H
|
||||
|
||||
#include <memory>
|
||||
#include "taglib_export.h"
|
||||
#include "tlist.h"
|
||||
#include "matroskaelement.h"
|
||||
|
||||
namespace TagLib {
|
||||
class File;
|
||||
|
||||
namespace EBML {
|
||||
class MkAttachments;
|
||||
}
|
||||
|
||||
namespace Matroska {
|
||||
class AttachedFile;
|
||||
class File;
|
||||
|
||||
//! Collection of attached files.
|
||||
class TAGLIB_EXPORT Attachments
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
: private Element
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
//! List of attached files.
|
||||
using AttachedFileList = List<AttachedFile>;
|
||||
|
||||
//! Construct attachments.
|
||||
Attachments();
|
||||
|
||||
//! Destroy attachments.
|
||||
virtual ~Attachments();
|
||||
|
||||
//! Add an attached file.
|
||||
void addAttachedFile(const AttachedFile &file);
|
||||
|
||||
//! Remove an attached file.
|
||||
void removeAttachedFile(unsigned long long uid);
|
||||
|
||||
//! Remove all attached files.
|
||||
void clear();
|
||||
|
||||
//! Get list of all attached files.
|
||||
const AttachedFileList &attachedFileList() const;
|
||||
|
||||
private:
|
||||
friend class EBML::MkAttachments;
|
||||
friend class File;
|
||||
class AttachmentsPrivate;
|
||||
|
||||
// private Element implementation
|
||||
ByteVector renderInternal() override;
|
||||
AttachedFileList &attachedFiles();
|
||||
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
std::unique_ptr<AttachmentsPrivate> d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
157
taglib/matroska/matroskachapter.cpp
Normal file
157
taglib/matroska/matroskachapter.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "matroskachapter.h"
|
||||
#include "tstring.h"
|
||||
#include "tbytevector.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class Matroska::Chapter::Display::DisplayPrivate
|
||||
{
|
||||
public:
|
||||
DisplayPrivate() = default;
|
||||
~DisplayPrivate() = default;
|
||||
String string;
|
||||
String language;
|
||||
};
|
||||
|
||||
class Matroska::Chapter::ChapterPrivate
|
||||
{
|
||||
public:
|
||||
ChapterPrivate() = default;
|
||||
~ChapterPrivate() = default;
|
||||
UID uid = 0;
|
||||
Time timeStart = 0;
|
||||
Time timeEnd = 0;
|
||||
List<Display> displayList;
|
||||
bool hidden = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Matroska::Chapter::Chapter(Time timeStart, Time timeEnd,
|
||||
const List<Display> &displayList, UID uid, bool hidden) :
|
||||
d(std::make_unique<ChapterPrivate>())
|
||||
{
|
||||
d->uid = uid;
|
||||
d->timeStart = timeStart;
|
||||
d->timeEnd = timeEnd;
|
||||
d->displayList = displayList;
|
||||
d->hidden = hidden;
|
||||
}
|
||||
|
||||
Matroska::Chapter::Chapter(const Chapter &other) :
|
||||
d(std::make_unique<ChapterPrivate>(*other.d))
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::Chapter::Chapter(Chapter &&other) noexcept = default;
|
||||
|
||||
Matroska::Chapter::~Chapter() = default;
|
||||
|
||||
Matroska::Chapter &Matroska::Chapter::operator=(Chapter &&other) noexcept = default;
|
||||
|
||||
Matroska::Chapter &Matroska::Chapter::operator=(const Chapter &other)
|
||||
{
|
||||
Chapter(other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Matroska::Chapter::swap(Chapter &other) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
swap(d, other.d);
|
||||
}
|
||||
|
||||
Matroska::Chapter::UID Matroska::Chapter::uid() const
|
||||
{
|
||||
return d->uid;
|
||||
}
|
||||
|
||||
Matroska::Chapter::Time Matroska::Chapter::timeStart() const
|
||||
{
|
||||
return d->timeStart;
|
||||
}
|
||||
|
||||
Matroska::Chapter::Time Matroska::Chapter::timeEnd() const
|
||||
{
|
||||
return d->timeEnd;
|
||||
}
|
||||
|
||||
bool Matroska::Chapter::isHidden() const
|
||||
{
|
||||
return d->hidden;
|
||||
}
|
||||
|
||||
const List<Matroska::Chapter::Display> &Matroska::Chapter::displayList() const
|
||||
{
|
||||
return d->displayList;
|
||||
}
|
||||
|
||||
Matroska::Chapter::Display::Display(const String &string, const String &language) :
|
||||
d(std::make_unique<DisplayPrivate>())
|
||||
{
|
||||
d->string = string;
|
||||
d->language = language;
|
||||
}
|
||||
|
||||
Matroska::Chapter::Display::Display(const Display &other) :
|
||||
d(std::make_unique<DisplayPrivate>(*other.d))
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::Chapter::Display::Display(Display &&other) noexcept = default;
|
||||
|
||||
Matroska::Chapter::Display::~Display() = default;
|
||||
|
||||
Matroska::Chapter::Display &Matroska::Chapter::Display::operator=(const Display &other)
|
||||
{
|
||||
Display(other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matroska::Chapter::Display &Matroska::Chapter::Display::operator=(
|
||||
Display &&other) noexcept = default;
|
||||
|
||||
void Matroska::Chapter::Display::swap(Display &other) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
swap(d, other.d);
|
||||
}
|
||||
|
||||
const String &Matroska::Chapter::Display::string() const
|
||||
{
|
||||
return d->string;
|
||||
}
|
||||
|
||||
const String &Matroska::Chapter::Display::language() const
|
||||
{
|
||||
return d->language;
|
||||
}
|
||||
178
taglib/matroska/matroskachapter.h
Normal file
178
taglib/matroska/matroskachapter.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_MATROSKACHAPTER_H
|
||||
#define TAGLIB_MATROSKACHAPTER_H
|
||||
|
||||
#include <memory>
|
||||
#include "taglib_export.h"
|
||||
#include "tlist.h"
|
||||
|
||||
namespace TagLib {
|
||||
class String;
|
||||
class ByteVector;
|
||||
|
||||
namespace EBML {
|
||||
class MkChapters;
|
||||
}
|
||||
|
||||
namespace Matroska {
|
||||
//! Matroska chapter.
|
||||
class TAGLIB_EXPORT Chapter
|
||||
{
|
||||
public:
|
||||
//! Unique identifier.
|
||||
using UID = unsigned long long;
|
||||
|
||||
//! Timestamp in nanoseconds.
|
||||
using Time = unsigned long long;
|
||||
|
||||
/*!
|
||||
* Contains all possible strings to use for the chapter display.
|
||||
*/
|
||||
class TAGLIB_EXPORT Display
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Construct a chapter display.
|
||||
*/
|
||||
Display(const String &string, const String &language);
|
||||
|
||||
/*!
|
||||
* Construct a chapter display as a copy of \a other.
|
||||
*/
|
||||
Display(const Display &other);
|
||||
|
||||
/*!
|
||||
* Construct a chapter display moving from \a other.
|
||||
*/
|
||||
Display(Display &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Destroys this chapter display.
|
||||
*/
|
||||
~Display();
|
||||
|
||||
/*!
|
||||
* Copies the contents of \a other into this object.
|
||||
*/
|
||||
Display &operator=(const Display &other);
|
||||
|
||||
/*!
|
||||
* Moves the contents of \a other into this object.
|
||||
*/
|
||||
Display &operator=(Display &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the object with the content of \a other.
|
||||
*/
|
||||
void swap(Display &other) noexcept;
|
||||
|
||||
/*!
|
||||
* Returns string representing the chapter.
|
||||
*/
|
||||
const String &string() const;
|
||||
|
||||
/*!
|
||||
* Returns language corresponding to the string.
|
||||
*/
|
||||
const String &language() const;
|
||||
|
||||
private:
|
||||
class DisplayPrivate;
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
std::unique_ptr<DisplayPrivate> d;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Construct a chapter.
|
||||
*/
|
||||
Chapter(Time timeStart, Time timeEnd, const List<Display> &displayList,
|
||||
UID uid, bool hidden = false);
|
||||
|
||||
/*!
|
||||
* Construct a chapter as a copy of \a other.
|
||||
*/
|
||||
Chapter(const Chapter &other);
|
||||
|
||||
/*!
|
||||
* Construct a chapter moving from \a other.
|
||||
*/
|
||||
Chapter(Chapter &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Destroys this chapter.
|
||||
*/
|
||||
~Chapter();
|
||||
|
||||
/*!
|
||||
* Copies the contents of \a other into this object.
|
||||
*/
|
||||
Chapter &operator=(const Chapter &other);
|
||||
|
||||
/*!
|
||||
* Moves the contents of \a other into this object.
|
||||
*/
|
||||
Chapter &operator=(Chapter &&other) noexcept;
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the object with the content of \a other.
|
||||
*/
|
||||
void swap(Chapter &other) noexcept;
|
||||
|
||||
/*!
|
||||
* Returns the UID of the chapter.
|
||||
*/
|
||||
UID uid() const;
|
||||
|
||||
/*!
|
||||
* Returns the timestamp of the start of the chapter in nanoseconds.
|
||||
*/
|
||||
Time timeStart() const;
|
||||
|
||||
/*!
|
||||
* Returns the timestamp of the start of the chapter in nanoseconds.
|
||||
*/
|
||||
Time timeEnd() const;
|
||||
|
||||
/*!
|
||||
* Check if chapter is hidden.
|
||||
*/
|
||||
bool isHidden() const;
|
||||
|
||||
/*!
|
||||
* Returns strings with language.
|
||||
*/
|
||||
const List<Display> &displayList() const;
|
||||
|
||||
private:
|
||||
class ChapterPrivate;
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
std::unique_ptr<ChapterPrivate> d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
102
taglib/matroska/matroskachapteredition.cpp
Normal file
102
taglib/matroska/matroskachapteredition.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2025 by Urs Fleisch
|
||||
email : ufleisch@users.sourceforge.net
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "matroskachapter.h"
|
||||
#include "matroskachapteredition.h"
|
||||
#include "tstring.h"
|
||||
#include "tbytevector.h"
|
||||
#include "tlist.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class Matroska::ChapterEdition::ChapterEditionPrivate
|
||||
{
|
||||
public:
|
||||
ChapterEditionPrivate() = default;
|
||||
~ChapterEditionPrivate() = default;
|
||||
List<Chapter> chapters;
|
||||
UID uid = 0;
|
||||
bool flagDefault = false;
|
||||
bool flagOrdered = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Matroska::ChapterEdition::ChapterEdition(const List<Chapter> &chapterList,
|
||||
bool isDefault, bool isOrdered, UID uid) :
|
||||
d(std::make_unique<ChapterEditionPrivate>())
|
||||
{
|
||||
d->chapters = chapterList;
|
||||
d->uid = uid;
|
||||
d->flagDefault = isDefault;
|
||||
d->flagOrdered = isOrdered;
|
||||
}
|
||||
|
||||
Matroska::ChapterEdition::ChapterEdition(const ChapterEdition &other) :
|
||||
d(std::make_unique<ChapterEditionPrivate>(*other.d))
|
||||
{
|
||||
}
|
||||
|
||||
Matroska::ChapterEdition::ChapterEdition(ChapterEdition &&other) noexcept = default;
|
||||
|
||||
Matroska::ChapterEdition::~ChapterEdition() = default;
|
||||
|
||||
Matroska::ChapterEdition &Matroska::ChapterEdition::operator=(
|
||||
ChapterEdition &&other) noexcept = default;
|
||||
|
||||
Matroska::ChapterEdition &Matroska::ChapterEdition::operator=(const ChapterEdition &other)
|
||||
{
|
||||
ChapterEdition(other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Matroska::ChapterEdition::swap(ChapterEdition &other) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
swap(d, other.d);
|
||||
}
|
||||
|
||||
Matroska::ChapterEdition::UID Matroska::ChapterEdition::uid() const
|
||||
{
|
||||
return d->uid;
|
||||
}
|
||||
|
||||
bool Matroska::ChapterEdition::isDefault() const
|
||||
{
|
||||
return d->flagDefault;
|
||||
}
|
||||
|
||||
bool Matroska::ChapterEdition::isOrdered() const
|
||||
{
|
||||
return d->flagOrdered;
|
||||
}
|
||||
|
||||
const List<Matroska::Chapter> &Matroska::ChapterEdition::chapterList() const
|
||||
{
|
||||
return d->chapters;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user