63 Commits

Author SHA1 Message Date
Urs Fleisch
e3de03501f Version 2.0.2 2024-08-24 06:40:41 +02:00
Urs Fleisch
1bd0d711ca Support older utfcpp versions with utf8cpp CMake target (#1243) (#1244)
This affects for example openSUSE Leap 15.6, which installs
utfcpp 3.2.1 in its own folder.
Now not only utf8::cpp, but also utf8cpp is supported as a CMake
target.
2024-08-15 12:44:17 +02:00
nekiwo
7c85fcaa81 Remove 'using namespace std' to avoid potential conflicts in example files (#1241)
Co-authored-by: nekiwo <nekiwo@users.noreply.github.com>
2024-08-05 21:54:33 +02:00
Urs Fleisch
cbe54d2f40 Support free form tags with MP4 properties (#1239) (#1240) 2024-07-29 20:24:33 +02:00
Urs Fleisch
c4ed590032 tagwriter option -p not working properly (#1236) (#1237)
The -p option of tagwriter sample does not work.
This is because the picture file is open in text mode instead of binary.
Also, the isFile function does not work on Windows in 32 bit mode with
large files. Using _stat64 instead of stat solves the problem.
2024-07-19 12:25:46 +02:00
Stephen Booth
f3fb4d83a4 Skip unknown MP4 boxes (#1231) 2024-05-18 06:45:10 +02:00
Urs Fleisch
3d4428726e Fix parsing of ID3v2.2 frames (#1228) 2024-05-18 06:43:00 +02:00
Urs Fleisch
ebf4c5bbb1 Version 2.0.1 2024-04-09 19:55:08 +02:00
Urs Fleisch
20cec27ac0 C bindings: Support UTF-8 for property values 2024-04-01 08:45:52 +02:00
Urs Fleisch
99bc87ccff Fix WASM build by inverting wchar_t size check
When building WASM with emscripten

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1
.gitignore vendored
View File

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

View File

@@ -1,8 +1,30 @@
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 +96,15 @@ TagLib 2.0 (Jan 24, 2024)
- String::null
- TrueAudio::File::setID3v2FrameFactory(): Use constructor
- WavPack::Properties::Properties(const ByteVector &, long, ReadStyle)
* Made methods const: Frame::Header::size(), Frame::headerSize(),
MP4::Atom::findall(), MP4::Atoms::find(), MP4::Atoms::path().
* Made classes non-virtual: APE::Footer, APE::Item, ASF::Attribute,
ASF::Picture, MP4::CoverArt, MP4::Item, ID3v2::ExtendedHeader, ID3v2::Footer,
ID3v2::Header, MPEG::Header, MPEG::XingHeader, Ogg::Page, Ogg::PageHeader.
* Removed type definitions in TagLib namespace: wchar, uchar, ushort, uint,
ulong, ulonglong, wstring: Use the standard types.
* Removed include file taglib_config.h and its defines TAGLIB_WITH_ASF,
TAGLIB_WITH_MP4: They were always 1 since version 1.8.
* Behavioral changes:
- The basic tag methods (e.g. genre()) separate multiple values with " / "
instead of " ".

View File

@@ -93,7 +93,7 @@ endif()
# Patch version: increase it for bug fix releases.
set(TAGLIB_SOVERSION_MAJOR 2)
set(TAGLIB_SOVERSION_MINOR 0)
set(TAGLIB_SOVERSION_PATCH 0)
set(TAGLIB_SOVERSION_PATCH 2)
include(ConfigureChecks.cmake)
@@ -148,21 +148,34 @@ 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()
add_subdirectory(taglib)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,7 +30,6 @@
# include "config.h"
#endif
#include "tstringlist.h"
#include "tbytevectorlist.h"
#include "tbytevectorstream.h"
#include "tiostream.h"
#include "tfile.h"
@@ -236,7 +235,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 +244,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 +253,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 +262,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 +271,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 +280,55 @@ char *taglib_tag_genre(const TagLib_Tag *tag)
unsigned int taglib_tag_year(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
auto t = reinterpret_cast<const Tag *>(tag);
return t->year();
}
unsigned int taglib_tag_track(const TagLib_Tag *tag)
{
const Tag *t = reinterpret_cast<const Tag *>(tag);
auto t = reinterpret_cast<const Tag *>(tag);
return t->track();
}
void taglib_tag_set_title(TagLib_Tag *tag, const char *title)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setTitle(charArrayToString(title));
}
void taglib_tag_set_artist(TagLib_Tag *tag, const char *artist)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setArtist(charArrayToString(artist));
}
void taglib_tag_set_album(TagLib_Tag *tag, const char *album)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setAlbum(charArrayToString(album));
}
void taglib_tag_set_comment(TagLib_Tag *tag, const char *comment)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setComment(charArrayToString(comment));
}
void taglib_tag_set_genre(TagLib_Tag *tag, const char *genre)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setGenre(charArrayToString(genre));
}
void taglib_tag_set_year(TagLib_Tag *tag, unsigned int year)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setYear(year);
}
void taglib_tag_set_track(TagLib_Tag *tag, unsigned int track)
{
Tag *t = reinterpret_cast<Tag *>(tag);
auto t = reinterpret_cast<Tag *>(tag);
t->setTrack(track);
}
@@ -411,14 +410,14 @@ void _taglib_property_set(TagLib_File *file, const char* prop, const char* value
if(value) {
auto property = map.find(prop);
if(property == map.end()) {
map.insert(prop, StringList(value));
map.insert(prop, StringList(charArrayToString(value)));
}
else {
if(append) {
property->second.append(value);
property->second.append(charArrayToString(value));
}
else {
property->second = StringList(value);
property->second = StringList(charArrayToString(value));
}
}
}
@@ -431,17 +430,17 @@ void _taglib_property_set(TagLib_File *file, const char* prop, const char* value
} // namespace
void taglib_property_set(TagLib_File *f, const char *prop, const char *value)
void taglib_property_set(TagLib_File *file, const char *prop, const char *value)
{
_taglib_property_set(f, prop, value, false);
_taglib_property_set(file, prop, value, false);
}
void taglib_property_set_append(TagLib_File *f, const char *prop, const char *value)
void taglib_property_set_append(TagLib_File *file, const char *prop, const char *value)
{
_taglib_property_set(f, prop, value, true);
_taglib_property_set(file, prop, value, true);
}
char** taglib_property_keys(TagLib_File *file)
char** taglib_property_keys(const TagLib_File *file)
{
if(file == NULL)
return NULL;
@@ -461,7 +460,7 @@ char** taglib_property_keys(TagLib_File *file)
return props;
}
char **taglib_property_get(TagLib_File *file, const char *prop)
char **taglib_property_get(const TagLib_File *file, const char *prop)
{
if(file == NULL || prop == NULL)
return NULL;
@@ -520,8 +519,7 @@ bool _taglib_complex_property_set(
while(*attrPtr) {
const TagLib_Complex_Property_Attribute *attr = *attrPtr;
String attrKey(attr->key);
TagLib_Variant_Type type = attr->value.type;
switch(type) {
switch(attr->value.type) {
case TagLib_Variant_Void:
map.insert(attrKey, Variant());
break;
@@ -544,14 +542,14 @@ bool _taglib_complex_property_set(
map.insert(attrKey, attr->value.value.doubleValue);
break;
case TagLib_Variant_String:
map.insert(attrKey, attr->value.value.stringValue);
map.insert(attrKey, charArrayToString(attr->value.value.stringValue));
break;
case TagLib_Variant_StringList: {
StringList strs;
if(attr->value.value.stringListValue) {
char **s = attr->value.value.stringListValue;;
while(*s) {
strs.append(*s++);
strs.append(charArrayToString(*s++));
}
}
map.insert(attrKey, strs);
@@ -585,7 +583,7 @@ BOOL taglib_complex_property_set_append(
return _taglib_complex_property_set(file, key, value, true);
}
char** taglib_complex_property_keys(TagLib_File *file)
char** taglib_complex_property_keys(const TagLib_File *file)
{
if(file == NULL) {
return NULL;
@@ -608,7 +606,7 @@ char** taglib_complex_property_keys(TagLib_File *file)
}
TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
TagLib_File *file, const char *key)
const TagLib_File *file, const char *key)
{
if(file == NULL || key == NULL) {
return NULL;
@@ -619,15 +617,15 @@ TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
return NULL;
}
TagLib_Complex_Property_Attribute ***props = static_cast<TagLib_Complex_Property_Attribute ***>(
auto props = static_cast<TagLib_Complex_Property_Attribute ***>(
malloc(sizeof(TagLib_Complex_Property_Attribute **) * (variantMaps.size() + 1)));
TagLib_Complex_Property_Attribute ***propPtr = props;
for(const auto &variantMap : variantMaps) {
if(!variantMap.isEmpty()) {
TagLib_Complex_Property_Attribute **attrs = static_cast<TagLib_Complex_Property_Attribute **>(
auto attrs = static_cast<TagLib_Complex_Property_Attribute **>(
malloc(sizeof(TagLib_Complex_Property_Attribute *) * (variantMap.size() + 1)));
TagLib_Complex_Property_Attribute *attr = static_cast<TagLib_Complex_Property_Attribute *>(
auto attr = static_cast<TagLib_Complex_Property_Attribute *>(
malloc(sizeof(TagLib_Complex_Property_Attribute) * variantMap.size()));
TagLib_Complex_Property_Attribute **attrPtr = attrs;
// The next assignment is redundant to silence the clang analyzer,
@@ -675,7 +673,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 +725,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 +776,7 @@ void taglib_complex_property_free(
TagLib_Complex_Property_Attribute** attrPtr = *propPtr;
while(*attrPtr) {
TagLib_Complex_Property_Attribute *attr = *attrPtr;
TagLib_Variant_Type type = attr->value.type;
switch(type) {
switch(attr->value.type) {
case TagLib_Variant_String:
free(attr->value.value.stringValue);
break;

View File

@@ -164,7 +164,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 +232,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 +354,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 +362,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 +541,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 +551,7 @@ TAGLIB_C_EXPORT char** taglib_complex_property_keys(TagLib_File *file);
* It must be freed by the client using taglib_complex_property_free().
*/
TAGLIB_C_EXPORT TagLib_Complex_Property_Attribute*** taglib_complex_property_get(
TagLib_File *file, const char *key);
const TagLib_File *file, const char *key);
/*!
* Extract the complex property values of a picture.

View File

@@ -34,7 +34,6 @@
#include "id3v1tag.h"
#include "apetag.h"
using namespace std;
using namespace TagLib;
int main(int argc, char *argv[])
@@ -44,7 +43,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 +51,62 @@ 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;
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;
cout << endl;
std::cout << std::endl;
}
}

View File

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

View File

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

View File

@@ -33,7 +33,6 @@ set(tag_HDRS
fileref.h
audioproperties.h
taglib_export.h
${CMAKE_CURRENT_BINARY_DIR}/../taglib_config.h
toolkit/taglib.h
toolkit/tstring.h
toolkit/tlist.h
@@ -348,7 +347,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>
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -137,7 +137,7 @@ 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);
}
@@ -153,9 +153,8 @@ void APE::Properties::analyzeCurrent(File *file)
return;
}
const unsigned int descriptorBytes = descriptor.toUInt(0, false);
if((descriptorBytes - 52) > 0)
if(const unsigned int descriptorBytes = descriptor.toUInt(0, false);
descriptorBytes - 52 > 0)
file->seek(descriptorBytes - 52, File::Current);
// Read the header

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -472,7 +472,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 +564,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 +681,5 @@ void ASF::File::read()
if(!filePropertiesObject || !streamPropertiesObject) {
debug("ASF::File::read(): Missing mandatory header objects.");
setValid(false);
return;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,12 +31,10 @@
using namespace TagLib;
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
class DSF::File::FilePrivate
{
public:
FilePrivate(ID3v2::FrameFactory *frameFactory)
FilePrivate(const ID3v2::FrameFactory *frameFactory)
: ID3v2FrameFactory(frameFactory ? frameFactory
: ID3v2::FrameFactory::instance())
{

View File

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

View File

@@ -127,7 +127,7 @@ 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)
: 0;

View File

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

View File

@@ -119,8 +119,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
@@ -457,12 +456,12 @@ void FileRef::swap(FileRef &ref) noexcept
bool FileRef::operator==(const FileRef &ref) const
{
return (ref.d->file == d->file);
return ref.d->file == d->file;
}
bool FileRef::operator!=(const FileRef &ref) const
{
return (ref.d->file != d->file);
return ref.d->file != d->file;
}
////////////////////////////////////////////////////////////////////////////////

View File

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

View File

@@ -45,10 +45,10 @@ namespace
{
enum { FlacXiphIndex = 0, FlacID3v2Index = 1, FlacID3v1Index = 2 };
const long MinPaddingLength = 4096;
const long MaxPaddingLegnth = 1024 * 1024;
constexpr long MinPaddingLength = 4096;
constexpr long MaxPaddingLegnth = 1024 * 1024;
const char LastBlockFlag = '\x80';
constexpr char LastBlockFlag = '\x80';
} // namespace
class FLAC::File::FilePrivate
@@ -86,7 +86,7 @@ bool FLAC::File::isSupported(IOStream *stream)
// A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede.
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
return (buffer.find("fLaC") >= 0);
return buffer.find("fLaC") >= 0;
}
////////////////////////////////////////////////////////////////////////////////
@@ -171,8 +171,7 @@ StringList FLAC::File::complexPropertyKeys() const
List<VariantMap> FLAC::File::complexProperties(const String &key) const
{
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
List<VariantMap> props;
for(const auto &block : std::as_const(d->blocks)) {
if(auto picture = dynamic_cast<Picture *>(block)) {
@@ -196,8 +195,7 @@ List<VariantMap> FLAC::File::complexProperties(const String &key) const
bool FLAC::File::setComplexProperties(const String &key, const List<VariantMap> &value)
{
const String uppercaseKey = key.upper();
if(uppercaseKey == "PICTURE") {
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
removePictures();
for(const auto &property : value) {
@@ -303,10 +301,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 +318,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 +447,12 @@ bool FLAC::File::hasXiphComment() const
bool FLAC::File::hasID3v1Tag() const
{
return (d->ID3v1Location >= 0);
return d->ID3v1Location >= 0;
}
bool FLAC::File::hasID3v2Tag() const
{
return (d->ID3v2Location >= 0);
return d->ID3v2Location >= 0;
}
////////////////////////////////////////////////////////////////////////////////

View File

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

View File

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

View File

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

View File

@@ -28,8 +28,6 @@
#include "tstring.h"
#include "tdebug.h"
#include "flacfile.h"
using namespace TagLib;
class FLAC::Properties::PropertiesPrivate
@@ -134,7 +132,7 @@ 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);
}

View File

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

View File

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

View File

@@ -27,7 +27,6 @@
#include "tstringlist.h"
#include "tdebug.h"
#include "tpropertymap.h"
#include "modfileprivate.h"
using namespace TagLib;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -216,10 +216,9 @@ void ID3v1::Tag::read()
if(d->file && d->file->isValid()) {
d->file->seek(d->tagOffset);
// read the tag -- always 128 bytes
const ByteVector data = d->file->readBlock(128);
// some initial sanity checking
if(data.size() == 128 && data.startsWith("TAG"))
if(const ByteVector data = d->file->readBlock(128);
data.size() == 128 && data.startsWith("TAG"))
parse(data);
else
debug("ID3v1 tag is not valid or could not be read at the specified offset.");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -37,7 +37,7 @@ namespace TagLib {
/*!
* This class represents a frame type not known (or more often simply
* unimplemented) in TagLib. This is here provide a basic API for
* unimplemented) in TagLib. This is here to provide a basic API for
* manipulating the binary data of unknown frames and to provide a means
* of rendering such \e unknown frames.
*

View File

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

View File

@@ -50,7 +50,7 @@ namespace TagLib {
explicit UnsynchronizedLyricsFrame(String::Type encoding = String::Latin1);
/*!
* Construct a unsynchronized lyrics frame based on the data in \a data.
* Construct an unsynchronized lyrics frame based on the data in \a data.
*/
explicit UnsynchronizedLyricsFrame(const ByteVector &data);
@@ -153,7 +153,7 @@ namespace TagLib {
/*!
* LyricsFrames each have a unique description. This searches for a lyrics
* frame with the description \a d and returns a pointer to it. If no
* frame is found that matches the given description null is returned.
* frame is found that matches the given description, null is returned.
*
* \see description()
*/

View File

@@ -173,7 +173,7 @@ PropertyMap UserUrlLinkFrame::asProperties() const
return map;
}
UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &description) // static
UserUrlLinkFrame *UserUrlLinkFrame::find(const ID3v2::Tag *tag, const String &description) // static
{
for(const auto &frame : std::as_const(tag->frameList("WXXX"))) {
auto f = dynamic_cast<UserUrlLinkFrame *>(frame);

View File

@@ -158,7 +158,7 @@ namespace TagLib {
/*!
* Parses the UserUrlLinkFrame as PropertyMap. The description() is taken as key,
* and the URL as single value.
* and the URL as a single value.
* - if description() is empty, the key will be "URL".
* - otherwise, if description() is not a valid key (e.g. containing non-ASCII
* characters), the returned map will contain an entry "WXXX/<description>"
@@ -170,7 +170,7 @@ namespace TagLib {
* Searches for the user defined url frame with the description \a description
* in \a tag. This returns null if no matching frames were found.
*/
static UserUrlLinkFrame *find(Tag *tag, const String &description);
static UserUrlLinkFrame *find(const Tag *tag, const String &description);
protected:
void parseFields(const ByteVector &data) override;

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