mirror of
https://github.com/taglib/taglib.git
synced 2026-06-13 09:49:18 -04:00
Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebf4c5bbb1 | ||
|
|
20cec27ac0 | ||
|
|
99bc87ccff | ||
|
|
7951f572b5 | ||
|
|
59ff35772e | ||
|
|
3784628155 | ||
|
|
e60df53152 | ||
|
|
1ae8e18db5 | ||
|
|
0896fb9092 | ||
|
|
920d97606b | ||
|
|
0d2c31b102 | ||
|
|
c8c4e5faec | ||
|
|
0ebb14b855 | ||
|
|
89af92333c | ||
|
|
b356fabe12 | ||
|
|
8a65068f3b | ||
|
|
e1ac724cfe | ||
|
|
a08acdcf23 | ||
|
|
1799b98c17 | ||
|
|
e49390c7c5 | ||
|
|
7bcfb96098 | ||
|
|
580b0b0c82 | ||
|
|
5fc3e5c192 | ||
|
|
570b40bdcd | ||
|
|
c3d73a26ff | ||
|
|
790815bcf4 | ||
|
|
1a5c417558 | ||
|
|
d87b2dad48 | ||
|
|
613355665c | ||
|
|
dfe2aa5253 | ||
|
|
5d921c6325 | ||
|
|
710522e6e1 | ||
|
|
6b17aa3694 | ||
|
|
b4f77a4d52 | ||
|
|
c907d8b273 | ||
|
|
98175168f3 | ||
|
|
73aff544b3 | ||
|
|
9cbb6615d5 | ||
|
|
8b7b48cc9b | ||
|
|
be8d71dad8 | ||
|
|
6abbe579a2 | ||
|
|
208fc93aaa | ||
|
|
769feafbe0 | ||
|
|
dfef09f134 | ||
|
|
3a003c1229 | ||
|
|
8b9a260d18 | ||
|
|
c2eb6b59b5 | ||
|
|
99ba7635be | ||
|
|
82b5ded8ee | ||
|
|
0318201fbd | ||
|
|
6c1ba88eab | ||
|
|
fb0f7dfa57 | ||
|
|
c5d798a50d | ||
|
|
ef013b76db | ||
|
|
a6dbc70644 | ||
|
|
9a026976ae |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,7 +22,6 @@ CMakeLists.txt.user*
|
||||
/tests/test_runner
|
||||
/tests/Testing
|
||||
/taglib/libtag.a
|
||||
/taglib_config.h
|
||||
/taglib-config
|
||||
/bindings/c/libtag_c.a
|
||||
/bindings/c/taglib_c.pc
|
||||
|
||||
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,8 +1,21 @@
|
||||
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 +87,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 " ".
|
||||
|
||||
@@ -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 1)
|
||||
|
||||
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)
|
||||
|
||||
@@ -20,7 +20,7 @@ if(NOT ${SIZEOF_LONGLONG} EQUAL 8)
|
||||
endif()
|
||||
|
||||
check_type_size("wchar_t" SIZEOF_WCHAR_T)
|
||||
if(${SIZEOF_WCHAR_T} LESS 2)
|
||||
if(NOT ${SIZEOF_WCHAR_T} GREATER 1)
|
||||
message(FATAL_ERROR "TagLib requires that wchar_t is sufficient to store a UTF-16 char.")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ OUTPUT_DIRECTORY = doc
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
OUTPUT_TEXT_DIRECTION = None
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
@@ -239,7 +238,6 @@ PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
LATEX_EMOJI_DIRECTORY =
|
||||
@@ -252,7 +250,6 @@ COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -273,7 +270,6 @@ XML_NS_MEMB_FILE_SCOPE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -309,7 +305,6 @@ EXTERNAL_PAGES = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -75,7 +75,7 @@ bool APE::File::isSupported(IOStream *stream)
|
||||
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
||||
return (buffer.find("MAC ") >= 0);
|
||||
return buffer.find("MAC ") >= 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -178,7 +178,7 @@ bool APE::File::save()
|
||||
insert(data, d->APELocation, d->APESize);
|
||||
|
||||
if(d->ID3v1Location >= 0)
|
||||
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
|
||||
d->ID3v1Location += static_cast<long>(data.size()) - d->APESize;
|
||||
|
||||
d->APESize = data.size();
|
||||
}
|
||||
@@ -224,12 +224,12 @@ void APE::File::strip(int tags)
|
||||
|
||||
bool APE::File::hasAPETag() const
|
||||
{
|
||||
return (d->APELocation >= 0);
|
||||
return d->APELocation >= 0;
|
||||
}
|
||||
|
||||
bool APE::File::hasID3v1Tag() const
|
||||
{
|
||||
return (d->ID3v1Location >= 0);
|
||||
return d->ID3v1Location >= 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -283,7 +283,7 @@ void APE::File::read(bool readProperties)
|
||||
|
||||
if(d->ID3v2Location >= 0) {
|
||||
seek(d->ID3v2Location + d->ID3v2Size);
|
||||
streamLength -= (d->ID3v2Location + d->ID3v2Size);
|
||||
streamLength -= d->ID3v2Location + d->ID3v2Size;
|
||||
}
|
||||
else {
|
||||
seek(0);
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace TagLib {
|
||||
//! An implementation of APE metadata
|
||||
|
||||
/*!
|
||||
* This is implementation of APE metadata.
|
||||
* This is an implementation of APE metadata.
|
||||
*
|
||||
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
|
||||
* properties from the file.
|
||||
@@ -84,7 +84,7 @@ namespace TagLib {
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constructs an APE file from \a file. If \a readProperties is true the
|
||||
* Constructs an APE file from \a file. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
@@ -93,7 +93,7 @@ namespace TagLib {
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
* Constructs an APE file from \a stream. If \a readProperties is true the
|
||||
* Constructs an APE file from \a stream. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
@@ -155,15 +155,15 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns a pointer to the ID3v1 tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this may return a null pointer
|
||||
* if there is no valid ID3v1 tag. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this may return a null pointer
|
||||
* if there is no valid ID3v1 tag. If \a create is \c true it will create
|
||||
* an ID3v1 tag if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
|
||||
* on disk actually has an ID3v1 tag.
|
||||
*
|
||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||
* \note The Tag <b>is still</b> owned by the APE::File and should not be
|
||||
* deleted by the user. It will be deleted when the file (object) is
|
||||
* destroyed.
|
||||
*
|
||||
@@ -174,15 +174,15 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns a pointer to the APE tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this may return a null pointer
|
||||
* if there is no valid APE tag. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this may return a null pointer
|
||||
* if there is no valid APE tag. If \a create is \c true it will create
|
||||
* an APE tag if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
* file on disk has an APE tag. Use hasAPETag() to check if the file
|
||||
* on disk actually has an APE tag.
|
||||
*
|
||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||
* \note The Tag <b>is still</b> owned by the APE::File and should not be
|
||||
* deleted by the user. It will be deleted when the file (object) is
|
||||
* destroyed.
|
||||
*
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include <bitset>
|
||||
|
||||
#include "taglib.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace APE;
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys the footer.
|
||||
*/
|
||||
virtual ~Footer();
|
||||
~Footer();
|
||||
|
||||
Footer(const Footer &) = delete;
|
||||
Footer &operator=(const Footer &) = delete;
|
||||
@@ -70,17 +70,17 @@ namespace TagLib {
|
||||
unsigned int version() const;
|
||||
|
||||
/*!
|
||||
* Returns true if a header is present in the tag.
|
||||
* Returns \c true if a header is present in the tag.
|
||||
*/
|
||||
bool headerPresent() const;
|
||||
|
||||
/*!
|
||||
* Returns true if a footer is present in the tag.
|
||||
* Returns \c true if a footer is present in the tag.
|
||||
*/
|
||||
bool footerPresent() const;
|
||||
|
||||
/*!
|
||||
* Returns true this is actually the header.
|
||||
* Returns \c true if this is actually the header.
|
||||
*/
|
||||
bool isHeader() const;
|
||||
|
||||
@@ -145,8 +145,8 @@ namespace TagLib {
|
||||
ByteVector renderFooter() const;
|
||||
|
||||
/*!
|
||||
* Renders the header corresponding to the footer. If headerPresent is
|
||||
* set to false, it returns an empty ByteVector.
|
||||
* Renders the header corresponding to the footer. If headerPresent() is
|
||||
* \c false, it returns an empty ByteVector.
|
||||
*/
|
||||
ByteVector renderHeader() const;
|
||||
|
||||
|
||||
@@ -141,10 +141,10 @@ void APE::Item::setValue(const String &value)
|
||||
d->value.clear();
|
||||
}
|
||||
|
||||
void APE::Item::setValues(const StringList &value)
|
||||
void APE::Item::setValues(const StringList &values)
|
||||
{
|
||||
d->type = Text;
|
||||
d->text = value;
|
||||
d->text = values;
|
||||
d->value.clear();
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ void APE::Item::parse(const ByteVector &data)
|
||||
ByteVector APE::Item::render() const
|
||||
{
|
||||
ByteVector data;
|
||||
unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
|
||||
unsigned int flags = (d->readOnly ? 1 : 0) | (d->type << 1);
|
||||
ByteVector val;
|
||||
|
||||
if(isEmpty())
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Constructs an item with \a key and \a value.
|
||||
* If \a binary is true a Binary item will be created, otherwise \a value will be interpreted as text
|
||||
* If \a binary is \c true a Binary item will be created, otherwise \a value will be interpreted as text
|
||||
*/
|
||||
Item(const String &key, const ByteVector &value, bool binary);
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys the item.
|
||||
*/
|
||||
virtual ~Item();
|
||||
~Item();
|
||||
|
||||
/*!
|
||||
* Copies the contents of \a item into this item.
|
||||
@@ -83,7 +83,7 @@ namespace TagLib {
|
||||
Item &operator=(const Item &item);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of this item by the content of \a item.
|
||||
* Exchanges the content of this item with the content of \a item.
|
||||
*/
|
||||
void swap(Item &item) noexcept;
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace TagLib {
|
||||
void setReadOnly(bool readOnly);
|
||||
|
||||
/*!
|
||||
* Return true if the item is read-only.
|
||||
* Return \c true if the item is read-only.
|
||||
*/
|
||||
bool isReadOnly() const;
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace TagLib {
|
||||
ItemTypes type() const;
|
||||
|
||||
/*!
|
||||
* Returns if the item has any real content.
|
||||
* Returns \c false if the item has any real content.
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
|
||||
@@ -137,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
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace TagLib {
|
||||
unsigned int sampleFrames() const;
|
||||
|
||||
/*!
|
||||
* Returns APE version.
|
||||
* Returns the APE version.
|
||||
*/
|
||||
int version() const;
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ using namespace APE;
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned int MinKeyLength = 2;
|
||||
const unsigned int MaxKeyLength = 255;
|
||||
constexpr unsigned int MinKeyLength = 2;
|
||||
constexpr unsigned int MaxKeyLength = 255;
|
||||
|
||||
const String FRONT_COVER("COVER ART (FRONT)");
|
||||
const String BACK_COVER("COVER ART (BACK)");
|
||||
@@ -203,10 +203,10 @@ PropertyMap APE::Tag::properties() const
|
||||
{
|
||||
PropertyMap properties;
|
||||
for(const auto &[tag, item] : std::as_const(itemListMap())) {
|
||||
String tagName = tag.upper();
|
||||
// if the item is Binary or Locator, or if the key is an invalid string,
|
||||
// add to unsupportedData
|
||||
if(item.type() != Item::Text || tagName.isEmpty()) {
|
||||
if(String tagName = tag.upper();
|
||||
item.type() != Item::Text || tagName.isEmpty()) {
|
||||
properties.addUnsupportedData(tag);
|
||||
}
|
||||
else {
|
||||
@@ -241,9 +241,9 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
|
||||
// first check if tags need to be removed completely
|
||||
StringList toRemove;
|
||||
for(const auto &[k, t] : std::as_const(itemListMap())) {
|
||||
String key = k.upper();
|
||||
// only remove if a) key is valid, b) type is text, c) key not contained in new properties
|
||||
if(!key.isEmpty() && t.type() == APE::Item::Text && !props.contains(key))
|
||||
if(String key = k.upper();
|
||||
!key.isEmpty() && t.type() == APE::Item::Text && !props.contains(key))
|
||||
toRemove.append(k);
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
|
||||
for(const auto &[tagName, val] : std::as_const(props)) {
|
||||
if(!checkKey(tagName))
|
||||
invalid.insert(tagName, val);
|
||||
else if(!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == val)) {
|
||||
else if(!itemListMap().contains(tagName) || itemListMap()[tagName].values() != val) {
|
||||
if(val.isEmpty())
|
||||
removeItem(tagName);
|
||||
else {
|
||||
@@ -281,13 +281,12 @@ StringList APE::Tag::complexPropertyKeys() const
|
||||
List<VariantMap> APE::Tag::complexProperties(const String &key) const
|
||||
{
|
||||
List<VariantMap> props;
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
const StringList itemNames = StringList(FRONT_COVER).append(BACK_COVER);
|
||||
for(const auto &itemName: itemNames) {
|
||||
if(d->itemListMap.contains(itemName)) {
|
||||
Item picture = d->itemListMap.value(itemName);
|
||||
if(picture.type() == Item::Binary) {
|
||||
if(Item picture = d->itemListMap.value(itemName);
|
||||
picture.type() == Item::Binary) {
|
||||
ByteVector data = picture.binaryData();
|
||||
// Do not search for a description if the first byte could start JPG or PNG
|
||||
// data.
|
||||
@@ -316,8 +315,7 @@ List<VariantMap> APE::Tag::complexProperties(const String &key) const
|
||||
|
||||
bool APE::Tag::setComplexProperties(const String &key, const List<VariantMap> &value)
|
||||
{
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
removeItem(FRONT_COVER);
|
||||
removeItem(BACK_COVER);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "tbytevector.h"
|
||||
#include "tmap.h"
|
||||
#include "tstring.h"
|
||||
#include "taglib.h"
|
||||
#include "taglib_export.h"
|
||||
#include "tag.h"
|
||||
#include "apeitem.h"
|
||||
@@ -116,6 +117,7 @@ namespace TagLib {
|
||||
*
|
||||
* The only conversion done by this export function is to rename the APE tags
|
||||
* TRACK to TRACKNUMBER, YEAR to DATE, and ALBUM ARTIST to ALBUMARTIST, respectively,
|
||||
* (and a few other keys, see \ref p_propertymapping)
|
||||
* in order to be compliant with the names used in other formats.
|
||||
*/
|
||||
PropertyMap properties() const override;
|
||||
@@ -165,7 +167,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Adds to the text item specified by \a key the data \a value. If \a replace
|
||||
* is true, then all of the other values on the same key will be removed
|
||||
* is \c true, then all of the other values on the same key will be removed
|
||||
* first. If a binary item exists for \a key it will be removed first.
|
||||
*/
|
||||
void addValue(const String &key, const String &value, bool replace = true);
|
||||
@@ -184,7 +186,7 @@ namespace TagLib {
|
||||
void setItem(const String &key, const Item &item);
|
||||
|
||||
/*!
|
||||
* Returns true if the tag does not contain any data.
|
||||
* Returns \c true if the tag does not contain any data.
|
||||
*/
|
||||
bool isEmpty() const override;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
pictureValue(ASF::Picture::fromInvalid())
|
||||
{
|
||||
}
|
||||
AttributeTypes type;
|
||||
AttributeTypes type { UnicodeType };
|
||||
String stringValue;
|
||||
ByteVector byteVectorValue;
|
||||
ASF::Picture pictureValue;
|
||||
@@ -154,7 +154,7 @@ unsigned int ASF::Attribute::toUInt() const
|
||||
|
||||
unsigned long long ASF::Attribute::toULongLong() const
|
||||
{
|
||||
return static_cast<unsigned long long>(d->numericValue);
|
||||
return d->numericValue;
|
||||
}
|
||||
|
||||
ASF::Picture ASF::Attribute::toPicture() const
|
||||
@@ -162,30 +162,30 @@ ASF::Picture ASF::Attribute::toPicture() const
|
||||
return d->pictureValue;
|
||||
}
|
||||
|
||||
String ASF::Attribute::parse(ASF::File &f, int kind)
|
||||
String ASF::Attribute::parse(ASF::File &file, int kind)
|
||||
{
|
||||
unsigned int size, nameLength;
|
||||
String name;
|
||||
d->pictureValue = Picture::fromInvalid();
|
||||
// extended content descriptor
|
||||
if(kind == 0) {
|
||||
nameLength = readWORD(&f);
|
||||
name = readString(&f, nameLength);
|
||||
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&f));
|
||||
size = readWORD(&f);
|
||||
nameLength = readWORD(&file);
|
||||
name = readString(&file, nameLength);
|
||||
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&file));
|
||||
size = readWORD(&file);
|
||||
}
|
||||
// metadata & metadata library
|
||||
else {
|
||||
int temp = readWORD(&f);
|
||||
int temp = readWORD(&file);
|
||||
// metadata library
|
||||
if(kind == 2) {
|
||||
d->language = temp;
|
||||
}
|
||||
d->stream = readWORD(&f);
|
||||
nameLength = readWORD(&f);
|
||||
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&f));
|
||||
size = readDWORD(&f);
|
||||
name = readString(&f, nameLength);
|
||||
d->stream = readWORD(&file);
|
||||
nameLength = readWORD(&file);
|
||||
d->type = static_cast<ASF::Attribute::AttributeTypes>(readWORD(&file));
|
||||
size = readDWORD(&file);
|
||||
name = readString(&file, nameLength);
|
||||
}
|
||||
|
||||
if(kind != 2 && size > 65535) {
|
||||
@@ -194,33 +194,33 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
|
||||
|
||||
switch(d->type) {
|
||||
case WordType:
|
||||
d->numericValue = readWORD(&f);
|
||||
d->numericValue = readWORD(&file);
|
||||
break;
|
||||
|
||||
case BoolType:
|
||||
if(kind == 0) {
|
||||
d->numericValue = (readDWORD(&f) != 0);
|
||||
d->numericValue = readDWORD(&file) != 0;
|
||||
}
|
||||
else {
|
||||
d->numericValue = (readWORD(&f) != 0);
|
||||
d->numericValue = readWORD(&file) != 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case DWordType:
|
||||
d->numericValue = readDWORD(&f);
|
||||
d->numericValue = readDWORD(&file);
|
||||
break;
|
||||
|
||||
case QWordType:
|
||||
d->numericValue = readQWORD(&f);
|
||||
d->numericValue = readQWORD(&file);
|
||||
break;
|
||||
|
||||
case UnicodeType:
|
||||
d->stringValue = readString(&f, size);
|
||||
d->stringValue = readString(&file, size);
|
||||
break;
|
||||
|
||||
case BytesType:
|
||||
case GuidType:
|
||||
d->byteVectorValue = f.readBlock(size);
|
||||
d->byteVectorValue = file.readBlock(size);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -240,7 +240,6 @@ int ASF::Attribute::dataSize() const
|
||||
case WordType:
|
||||
return 2;
|
||||
case BoolType:
|
||||
return 4;
|
||||
case DWordType:
|
||||
return 4;
|
||||
case QWordType:
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
namespace TagLib {
|
||||
//! An implementation of ASF (WMA) metadata
|
||||
namespace ASF {
|
||||
//! An implementation of TagLib::File with ASF specific methods
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for ASF files to the
|
||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||
@@ -112,7 +114,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
* This returns \c true if the save was successful.
|
||||
*/
|
||||
bool save() override;
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "tbytevector.h"
|
||||
#include "tpicturetype.h"
|
||||
#include "taglib_export.h"
|
||||
#include "attachedpictureframe.h"
|
||||
|
||||
namespace TagLib
|
||||
{
|
||||
@@ -40,9 +39,9 @@ namespace TagLib
|
||||
//! An ASF attached picture interface implementation
|
||||
|
||||
/*!
|
||||
* This is an implementation of ASF attached pictures interface. Pictures may be
|
||||
* This is an implementation of ASF attached pictures. Pictures may be
|
||||
* included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture
|
||||
* attribute in a single tag). These pictures are usually in either JPEG or
|
||||
* attributes in a single tag). These pictures are usually in either JPEG or
|
||||
* PNG format.
|
||||
* \see Attribute::toPicture()
|
||||
* \see Attribute::Attribute(const Picture& picture)
|
||||
@@ -50,7 +49,7 @@ namespace TagLib
|
||||
class TAGLIB_EXPORT Picture {
|
||||
public:
|
||||
|
||||
/*!
|
||||
/*
|
||||
* This describes the function or content of the picture.
|
||||
*/
|
||||
DECLARE_PICTURE_TYPE_ENUM(Type)
|
||||
@@ -61,14 +60,14 @@ namespace TagLib
|
||||
Picture();
|
||||
|
||||
/*!
|
||||
* Construct an picture as a copy of \a other.
|
||||
* Construct a picture as a copy of \a other.
|
||||
*/
|
||||
Picture(const Picture& other);
|
||||
|
||||
/*!
|
||||
* Destroys the picture.
|
||||
*/
|
||||
virtual ~Picture();
|
||||
~Picture();
|
||||
|
||||
/*!
|
||||
* Copies the contents of \a other into this picture.
|
||||
@@ -76,12 +75,12 @@ namespace TagLib
|
||||
Picture& operator=(const Picture& other);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the Picture by the content of \a other.
|
||||
* Exchanges the content of the Picture with the content of \a other.
|
||||
*/
|
||||
void swap(Picture &other) noexcept;
|
||||
|
||||
/*!
|
||||
* Returns true if Picture stores valid picture
|
||||
* Returns \c true if Picture stores valid picture
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
@@ -136,7 +135,7 @@ namespace TagLib
|
||||
/*!
|
||||
* Returns the image data as a ByteVector.
|
||||
*
|
||||
* \note ByteVector has a data() method that returns a const char * which
|
||||
* \note ByteVector has a data() method that returns a <tt>const char *</tt> which
|
||||
* should make it easy to export this data to external programs.
|
||||
*
|
||||
* \see setPicture()
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace TagLib {
|
||||
public:
|
||||
|
||||
/*!
|
||||
* Audio codec types can be used in ASF file.
|
||||
* Audio codec types which can be used in ASF files.
|
||||
*/
|
||||
enum Codec
|
||||
{
|
||||
|
||||
@@ -313,8 +313,7 @@ PropertyMap ASF::Tag::properties() const
|
||||
}
|
||||
|
||||
for(const auto &[k, attributes] : std::as_const(d->attributeListMap)) {
|
||||
const String key = translateKey(k);
|
||||
if(!key.isEmpty()) {
|
||||
if(const String key = translateKey(k); !key.isEmpty()) {
|
||||
for(const auto &attr : attributes) {
|
||||
if(key == "TRACKNUMBER") {
|
||||
if(attr.type() == ASF::Attribute::DWordType)
|
||||
@@ -411,8 +410,7 @@ StringList ASF::Tag::complexPropertyKeys() const
|
||||
List<VariantMap> ASF::Tag::complexProperties(const String &key) const
|
||||
{
|
||||
List<VariantMap> props;
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
const AttributeList pictures = d->attributeListMap.value("WM/Picture");
|
||||
for(const Attribute &attr : pictures) {
|
||||
ASF::Picture picture = attr.toPicture();
|
||||
@@ -430,8 +428,7 @@ List<VariantMap> ASF::Tag::complexProperties(const String &key) const
|
||||
|
||||
bool ASF::Tag::setComplexProperties(const String &key, const List<VariantMap> &value)
|
||||
{
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
removeItem("WM/Picture");
|
||||
|
||||
for(const auto &property : value) {
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace TagLib {
|
||||
using AttributeList = List<Attribute>;
|
||||
using AttributeListMap = Map<String, AttributeList>;
|
||||
|
||||
//! An implementation of ASF (WMA) tags
|
||||
|
||||
class TAGLIB_EXPORT Tag : public TagLib::Tag {
|
||||
|
||||
friend class File;
|
||||
@@ -64,7 +66,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Returns the album name; if no album name is present in the tag
|
||||
* String::null will be returned.
|
||||
* an empty string will be returned.
|
||||
*/
|
||||
String album() const override;
|
||||
|
||||
@@ -74,7 +76,7 @@ namespace TagLib {
|
||||
String comment() const override;
|
||||
|
||||
/*!
|
||||
* Returns the genre name; if no genre is present in the tag String::null
|
||||
* Returns the genre name; if no genre is present in the tag an empty string
|
||||
* will be returned.
|
||||
*/
|
||||
String genre() const override;
|
||||
@@ -85,8 +87,8 @@ namespace TagLib {
|
||||
virtual String rating() const;
|
||||
|
||||
/*!
|
||||
* Returns the genre name; if no genre is present in the tag String::null
|
||||
* will be returned.
|
||||
* Returns the copyright information; if no copyright information is
|
||||
* present in the tag an empty string will be returned.
|
||||
*/
|
||||
virtual String copyright() const;
|
||||
|
||||
@@ -112,7 +114,7 @@ namespace TagLib {
|
||||
void setArtist(const String &value) override;
|
||||
|
||||
/*!
|
||||
* Sets the album to \a value. If \a value is String::null then this value will be
|
||||
* Sets the album to \a value. If \a value is an empty string then this value will be
|
||||
* cleared.
|
||||
*/
|
||||
void setAlbum(const String &value) override;
|
||||
@@ -148,7 +150,7 @@ namespace TagLib {
|
||||
void setTrack(unsigned int value) override;
|
||||
|
||||
/*!
|
||||
* Returns true if the tag does not contain any data. This should be
|
||||
* Returns \c true if the tag does not contain any data. This should be
|
||||
* reimplemented in subclasses that provide more than the basic tagging
|
||||
* abilities in this class.
|
||||
*/
|
||||
@@ -168,7 +170,7 @@ namespace TagLib {
|
||||
const AttributeListMap &attributeListMap() const;
|
||||
|
||||
/*!
|
||||
* \return True if a value for \a key is currently set.
|
||||
* \return \c true if a value for \a key is currently set.
|
||||
*/
|
||||
bool contains(const String &key) const;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* The values here are common to most audio formats. For more specific, codec
|
||||
* dependent values, please see see the subclasses APIs. This is meant to
|
||||
* dependent values, please see the subclasses APIs. This is meant to
|
||||
* compliment the TagLib::File and TagLib::Tag APIs in providing a simple
|
||||
* interface that is sufficient for most applications.
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace
|
||||
char padding;
|
||||
};
|
||||
|
||||
typedef std::vector<Chunk64> ChunkList;
|
||||
using ChunkList = std::vector<Chunk64>;
|
||||
|
||||
int chunkIndex(const ChunkList &chunks, const ByteVector &id)
|
||||
{
|
||||
@@ -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);
|
||||
|
||||
@@ -36,20 +36,21 @@ namespace TagLib {
|
||||
//! An implementation of DSDIFF metadata
|
||||
|
||||
/*!
|
||||
* This is implementation of DSDIFF metadata.
|
||||
* This is an implementation of DSDIFF metadata.
|
||||
*
|
||||
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
|
||||
* chunk as well as properties from the file.
|
||||
* Description of the DSDIFF format is available
|
||||
* at http://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf
|
||||
* DSDIFF standard does not explicitly specify the ID3V2 chunk
|
||||
* It can be found at the root level, but also sometimes inside the PROP chunk
|
||||
* In addition, title and artist info are stored as part of the standard
|
||||
* Description of the DSDIFF format is available at
|
||||
* <a href="https://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf">
|
||||
* DSDIFF_1.5_Spec.pdf</a>.
|
||||
* The DSDIFF standard does not explicitly specify the ID3 chunk.
|
||||
* It can be found at the root level, but also sometimes inside the PROP chunk.
|
||||
* In addition, title and artist info are stored as part of the standard.
|
||||
*/
|
||||
|
||||
namespace DSDIFF {
|
||||
|
||||
//! An implementation of TagLib::File with DSDIFF specific methods
|
||||
//! An implementation of TagLib::File with DSDIFF specific methods.
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for DSDIFF files to the
|
||||
@@ -78,7 +79,7 @@ namespace TagLib {
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constructs a DSDIFF file from \a file. If \a readProperties is true
|
||||
* Constructs a DSDIFF file from \a file. If \a readProperties is \c true
|
||||
* the file's audio properties will also be read.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
@@ -91,7 +92,7 @@ namespace TagLib {
|
||||
ID3v2::FrameFactory *frameFactory = nullptr);
|
||||
|
||||
/*!
|
||||
* Constructs an DSDIFF file from \a stream. If \a readProperties is true
|
||||
* Constructs a DSDIFF file from \a stream. If \a readProperties is \c true
|
||||
* the file's audio properties will also be read.
|
||||
*
|
||||
* If this file contains an ID3v2 tag, the frames will be created using
|
||||
@@ -168,7 +169,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Save the file. If at least one tag -- ID3v1 or DIIN -- exists this
|
||||
* will duplicate its content into the other tag. This returns true
|
||||
* will duplicate its content into the other tag. This returns \c true
|
||||
* if saving was successful.
|
||||
*
|
||||
* If neither exists or if both tags are empty, this will strip the tags
|
||||
@@ -177,7 +178,7 @@ namespace TagLib {
|
||||
* This is the same as calling save(AllTags);
|
||||
*
|
||||
* If you would like more granular control over the content of the tags,
|
||||
* with the concession of generality, use paramaterized save call below.
|
||||
* with the concession of generality, use parameterized save call below.
|
||||
*
|
||||
* \see save(int tags)
|
||||
*/
|
||||
@@ -193,7 +194,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* This will strip the tags that match the OR-ed together TagTypes from the
|
||||
* file. By default it strips all tags. It returns true if the tags are
|
||||
* file. By default it strips all tags. It returns \c true if the tags are
|
||||
* successfully stripped.
|
||||
*
|
||||
* \note This will update the file immediately.
|
||||
@@ -227,9 +228,6 @@ namespace TagLib {
|
||||
protected:
|
||||
enum Endianness { BigEndian, LittleEndian };
|
||||
|
||||
File(FileName file, Endianness endianness);
|
||||
File(IOStream *stream, Endianness endianness);
|
||||
|
||||
private:
|
||||
void removeRootChunk(const ByteVector &id);
|
||||
void removeRootChunk(unsigned int i);
|
||||
@@ -237,7 +235,7 @@ namespace TagLib {
|
||||
void removeChildChunk(unsigned int i, unsigned int childChunkNum);
|
||||
|
||||
/*!
|
||||
* Sets the data for the the specified chunk at root level to \a data.
|
||||
* Sets the data for the specified chunk at root level to \a data.
|
||||
*
|
||||
* \warning This will update the file immediately.
|
||||
*/
|
||||
@@ -254,7 +252,7 @@ namespace TagLib {
|
||||
void setRootChunkData(const ByteVector &name, const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* Sets the data for the the specified child chunk to \a data.
|
||||
* Sets the data for the specified child chunk to \a data.
|
||||
*
|
||||
* If data is null, then remove the chunk
|
||||
*
|
||||
@@ -266,7 +264,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Sets the data for the child chunk \a name to \a data. If a chunk with
|
||||
* the given name already exists it will be overwritten, otherwise it will
|
||||
* be created after the existing chunks inside child chunk.
|
||||
* be created after the existing chunks inside the child chunk.
|
||||
*
|
||||
* If data is null, then remove the chunks with \a name name
|
||||
*
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "dsdiffproperties.h"
|
||||
|
||||
#include "tstring.h"
|
||||
#include "tdebug.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@@ -45,10 +44,10 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DSDIFF::Properties::Properties(const unsigned int sampleRate,
|
||||
const unsigned short channels,
|
||||
const unsigned long long samplesCount,
|
||||
const int bitrate,
|
||||
DSDIFF::Properties::Properties(unsigned int sampleRate,
|
||||
unsigned short channels,
|
||||
unsigned long long samplesCount,
|
||||
int bitrate,
|
||||
ReadStyle style) :
|
||||
AudioProperties(style),
|
||||
d(std::make_unique<PropertiesPrivate>())
|
||||
@@ -59,7 +58,7 @@ DSDIFF::Properties::Properties(const unsigned int sampleRate,
|
||||
d->sampleRate = sampleRate;
|
||||
d->bitrate = bitrate;
|
||||
d->length = d->sampleRate > 0
|
||||
? static_cast<int>((d->sampleCount * 1000.0) / d->sampleRate + 0.5)
|
||||
? static_cast<int>(d->sampleCount * 1000.0 / d->sampleRate + 0.5)
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace TagLib {
|
||||
//! An implementation of audio property reading for DSDIFF
|
||||
|
||||
/*!
|
||||
* This reads the data from an DSDIFF stream found in the AudioProperties
|
||||
* This reads the data from a DSDIFF stream found in the AudioProperties
|
||||
* API.
|
||||
*/
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace TagLib {
|
||||
* Create an instance of DSDIFF::Properties with the data read from the
|
||||
* ByteVector \a data.
|
||||
*/
|
||||
Properties(const unsigned int sampleRate, const unsigned short channels,
|
||||
const unsigned long long samplesCount, const int bitrate,
|
||||
Properties(unsigned int sampleRate, unsigned short channels,
|
||||
unsigned long long samplesCount, int bitrate,
|
||||
ReadStyle style);
|
||||
|
||||
/*!
|
||||
|
||||
@@ -31,12 +31,10 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
||||
|
||||
class DSF::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate(ID3v2::FrameFactory *frameFactory)
|
||||
FilePrivate(const ID3v2::FrameFactory *frameFactory)
|
||||
: ID3v2FrameFactory(frameFactory ? frameFactory
|
||||
: ID3v2::FrameFactory::instance())
|
||||
{
|
||||
|
||||
@@ -36,7 +36,27 @@
|
||||
#include "id3v2tag.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
//! An implementation of DSF metadata
|
||||
|
||||
/*!
|
||||
* This is an implementation of DSF metadata using an ID3v2 tag inside the
|
||||
* metadata chunk.
|
||||
* The DSF specification is located at
|
||||
* http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
||||
*/
|
||||
|
||||
namespace DSF {
|
||||
|
||||
//! An implementation of TagLib::File with DSF specific methods
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for DSF files to the
|
||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||
* the abstract TagLib::File API as well as providing some additional
|
||||
* information specific to DSF files.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public TagLib::File {
|
||||
public:
|
||||
/*!
|
||||
@@ -103,7 +123,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
* This returns \c true if the save was successful.
|
||||
*/
|
||||
bool save() override;
|
||||
|
||||
|
||||
@@ -127,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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
105
taglib/fileref.h
105
taglib/fileref.h
@@ -60,34 +60,12 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
|
||||
//! A class for pluggable file type resolution.
|
||||
//! A class for pluggable file type resolution.
|
||||
|
||||
/*!
|
||||
* This class is used to extend TagLib's very basic file name based file
|
||||
* type resolution.
|
||||
*
|
||||
* This can be accomplished with:
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* class MyFileTypeResolver : FileTypeResolver
|
||||
* {
|
||||
* TagLib::File *createFile(TagLib::FileName *fileName, bool, AudioProperties::ReadStyle) const
|
||||
* {
|
||||
* if(someCheckForAnMP3File(fileName))
|
||||
* return new TagLib::MPEG::File(fileName);
|
||||
* return 0;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* FileRef::addFileTypeResolver(new MyFileTypeResolver);
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* Naturally a less contrived example would be slightly more complex. This
|
||||
* can be used to plug in mime-type detection systems or to add new file types
|
||||
* to TagLib.
|
||||
*/
|
||||
/*!
|
||||
* %File type resolver, better implement StreamTypeResolver in order to
|
||||
* support both file and stream resolution.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT FileTypeResolver
|
||||
{
|
||||
@@ -120,6 +98,44 @@ namespace TagLib {
|
||||
std::unique_ptr<FileTypeResolverPrivate> d;
|
||||
};
|
||||
|
||||
//! A class for pluggable stream type resolution.
|
||||
|
||||
/*!
|
||||
* This class is used to extend TagLib's very basic file name based file
|
||||
* type resolution.
|
||||
*
|
||||
* This can be accomplished with:
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* class MyStreamTypeResolver : StreamTypeResolver
|
||||
* {
|
||||
* TagLib::File *createFile(TagLib::FileName *fileName, bool readProps,
|
||||
* AudioProperties::ReadStyle readStyle) const override
|
||||
* {
|
||||
* if(someCheckForAnMP3File(fileName))
|
||||
* return new TagLib::MPEG::File(fileName, readProps, readStyle);
|
||||
* return nullptr;
|
||||
* }
|
||||
*
|
||||
* TagLib::File *createFileFromStream(TagLib::IOStream *s, bool readProps,
|
||||
* AudioProperties::ReadStyle readStyle) const override
|
||||
* {
|
||||
* if(someCheckForAnMP3Stream(s))
|
||||
* return new TagLib::MPEG::File(s, readProps, readStyle);
|
||||
* return nullptr;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* FileRef::addFileTypeResolver(new MyStreamTypeResolver);
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* Naturally a less contrived example would be slightly more complex. This
|
||||
* can be used to plug in mime-type detection systems or to add new file types
|
||||
* to TagLib.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT StreamTypeResolver : public FileTypeResolver
|
||||
{
|
||||
public:
|
||||
@@ -127,11 +143,22 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys this StreamTypeResolver instance.
|
||||
*/
|
||||
~StreamTypeResolver() override = 0;
|
||||
virtual ~StreamTypeResolver() override = 0; // virtual is needed by SWIG
|
||||
|
||||
StreamTypeResolver(const StreamTypeResolver &) = delete;
|
||||
StreamTypeResolver &operator=(const StreamTypeResolver &) = delete;
|
||||
|
||||
/*!
|
||||
* This method must be overridden to provide an additional stream type
|
||||
* resolver. If the resolver is able to determine the file type it should
|
||||
* return a valid File object; if not it should return nullptr.
|
||||
*
|
||||
* \note The created file is then owned by the FileRef and should not be
|
||||
* deleted. Deletion will happen automatically when the FileRef passes
|
||||
* out of scope.
|
||||
*
|
||||
* \see createFile()
|
||||
*/
|
||||
virtual File *createFileFromStream(IOStream *stream,
|
||||
bool readAudioProperties = true,
|
||||
AudioProperties::ReadStyle
|
||||
@@ -148,9 +175,9 @@ namespace TagLib {
|
||||
FileRef();
|
||||
|
||||
/*!
|
||||
* Create a FileRef from \a fileName. If \a readAudioProperties is true then
|
||||
* Create a FileRef from \a fileName. If \a readAudioProperties is \c true then
|
||||
* the audio properties will be read using \a audioPropertiesStyle. If
|
||||
* \a readAudioProperties is false then \a audioPropertiesStyle will be
|
||||
* \a readAudioProperties is \c false then \a audioPropertiesStyle will be
|
||||
* ignored.
|
||||
*
|
||||
* Also see the note in the class documentation about why you may not want to
|
||||
@@ -163,8 +190,8 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Construct a FileRef from an opened \a IOStream. If \a readAudioProperties
|
||||
* is true then the audio properties will be read using \a audioPropertiesStyle.
|
||||
* If \a readAudioProperties is false then \a audioPropertiesStyle will be
|
||||
* is \c true then the audio properties will be read using \a audioPropertiesStyle.
|
||||
* If \a readAudioProperties is \c false then \a audioPropertiesStyle will be
|
||||
* ignored.
|
||||
*
|
||||
* Also see the note in the class documentation about why you may not want to
|
||||
@@ -195,7 +222,7 @@ namespace TagLib {
|
||||
~FileRef();
|
||||
|
||||
/*!
|
||||
* Returns a pointer to represented file's tag.
|
||||
* Returns a pointer to the represented file's tag.
|
||||
*
|
||||
* \warning This pointer will become invalid when this FileRef and all
|
||||
* copies pass out of scope.
|
||||
@@ -287,7 +314,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Returns the audio properties for this FileRef. If no audio properties
|
||||
* were read then this will returns a null pointer.
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
AudioProperties *audioProperties() const;
|
||||
|
||||
@@ -309,7 +336,7 @@ namespace TagLib {
|
||||
File *file() const;
|
||||
|
||||
/*!
|
||||
* Saves the file. Returns true on success.
|
||||
* Saves the file. Returns \c true on success.
|
||||
*/
|
||||
bool save();
|
||||
|
||||
@@ -351,7 +378,7 @@ namespace TagLib {
|
||||
static StringList defaultFileExtensions();
|
||||
|
||||
/*!
|
||||
* Returns true if the file (and as such other pointers) are null.
|
||||
* Returns \c true if the file (and as such other pointers) are null.
|
||||
*/
|
||||
bool isNull() const;
|
||||
|
||||
@@ -361,17 +388,17 @@ namespace TagLib {
|
||||
FileRef &operator=(const FileRef &ref);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the FileRef by the content of \a ref.
|
||||
* Exchanges the content of the FileRef with the content of \a ref.
|
||||
*/
|
||||
void swap(FileRef &ref) noexcept;
|
||||
|
||||
/*!
|
||||
* Returns true if this FileRef and \a ref point to the same File object.
|
||||
* Returns \c true if this FileRef and \a ref point to the same File object.
|
||||
*/
|
||||
bool operator==(const FileRef &ref) const;
|
||||
|
||||
/*!
|
||||
* Returns true if this FileRef and \a ref do not point to the same File
|
||||
* Returns \c true if this FileRef and \a ref do not point to the same File
|
||||
* object.
|
||||
*/
|
||||
bool operator!=(const FileRef &ref) const;
|
||||
|
||||
@@ -45,10 +45,10 @@ namespace
|
||||
{
|
||||
enum { FlacXiphIndex = 0, FlacID3v2Index = 1, FlacID3v1Index = 2 };
|
||||
|
||||
const long MinPaddingLength = 4096;
|
||||
const long MaxPaddingLegnth = 1024 * 1024;
|
||||
constexpr long MinPaddingLength = 4096;
|
||||
constexpr long MaxPaddingLegnth = 1024 * 1024;
|
||||
|
||||
const char LastBlockFlag = '\x80';
|
||||
constexpr char LastBlockFlag = '\x80';
|
||||
} // namespace
|
||||
|
||||
class FLAC::File::FilePrivate
|
||||
@@ -86,7 +86,7 @@ bool FLAC::File::isSupported(IOStream *stream)
|
||||
// A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
||||
return (buffer.find("fLaC") >= 0);
|
||||
return buffer.find("fLaC") >= 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -171,8 +171,7 @@ StringList FLAC::File::complexPropertyKeys() const
|
||||
|
||||
List<VariantMap> FLAC::File::complexProperties(const String &key) const
|
||||
{
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
List<VariantMap> props;
|
||||
for(const auto &block : std::as_const(d->blocks)) {
|
||||
if(auto picture = dynamic_cast<Picture *>(block)) {
|
||||
@@ -196,8 +195,7 @@ List<VariantMap> FLAC::File::complexProperties(const String &key) const
|
||||
|
||||
bool FLAC::File::setComplexProperties(const String &key, const List<VariantMap> &value)
|
||||
{
|
||||
const String uppercaseKey = key.upper();
|
||||
if(uppercaseKey == "PICTURE") {
|
||||
if(const String uppercaseKey = key.upper(); uppercaseKey == "PICTURE") {
|
||||
removePictures();
|
||||
|
||||
for(const auto &property : value) {
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace TagLib {
|
||||
//! An implementation of FLAC metadata
|
||||
|
||||
/*!
|
||||
* This is implementation of FLAC metadata for non-Ogg FLAC files. At some
|
||||
* This is an implementation of FLAC metadata for non-Ogg FLAC files. At some
|
||||
* point when Ogg / FLAC is more common there will be a similar implementation
|
||||
* under the Ogg hierarchy.
|
||||
*
|
||||
@@ -83,7 +83,7 @@ namespace TagLib {
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constructs a FLAC file from \a file. If \a readProperties is true the
|
||||
* Constructs a FLAC file from \a file. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
@@ -96,13 +96,15 @@ namespace TagLib {
|
||||
ID3v2::FrameFactory *frameFactory = nullptr);
|
||||
|
||||
/*!
|
||||
* Constructs an FLAC file from \a file. If \a readProperties is true the
|
||||
* Constructs a FLAC file from \a file. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* If this file contains an ID3v2 tag, the frames will be created using
|
||||
* \a frameFactory.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*
|
||||
* \deprecated Use the constructor above.
|
||||
*/
|
||||
TAGLIB_DEPRECATED
|
||||
File(FileName file, ID3v2::FrameFactory *frameFactory,
|
||||
@@ -110,7 +112,7 @@ namespace TagLib {
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
* Constructs a FLAC file from \a stream. If \a readProperties is true the
|
||||
* Constructs a FLAC file from \a stream. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
@@ -126,7 +128,7 @@ namespace TagLib {
|
||||
ID3v2::FrameFactory *frameFactory = nullptr);
|
||||
|
||||
/*!
|
||||
* Constructs a FLAC file from \a stream. If \a readProperties is true the
|
||||
* Constructs a FLAC file from \a stream. If \a readProperties is \c true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
@@ -136,6 +138,8 @@ namespace TagLib {
|
||||
* \a frameFactory.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*
|
||||
* \deprecated Use the constructor above.
|
||||
*/
|
||||
TAGLIB_DEPRECATED
|
||||
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
||||
@@ -207,22 +211,22 @@ namespace TagLib {
|
||||
* will also keep any old ID3-tags up to date. If the file
|
||||
* has no XiphComment, one will be constructed from the ID3-tags.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
* This returns \c true if the save was successful.
|
||||
*/
|
||||
bool save() override;
|
||||
|
||||
/*!
|
||||
* Returns a pointer to the ID3v2 tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this returns a null pointer
|
||||
* if there is no valid ID3v2 tag. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this returns a null pointer
|
||||
* if there is no valid ID3v2 tag. If \a create is \c true it will create
|
||||
* an ID3v2 tag if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
* file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file
|
||||
* on disk actually has an ID3v2 tag.
|
||||
*
|
||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
|
||||
* deleted by the user. It will be deleted when the file (object) is
|
||||
* destroyed.
|
||||
*
|
||||
@@ -233,15 +237,15 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns a pointer to the ID3v1 tag of the file.
|
||||
*
|
||||
* If \a create is false (the default) this returns a null pointer
|
||||
* if there is no valid APE tag. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this returns a null pointer
|
||||
* if there is no valid APE tag. If \a create is \c true it will create
|
||||
* an APE tag if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
|
||||
* on disk actually has an ID3v1 tag.
|
||||
*
|
||||
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
|
||||
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
|
||||
* deleted by the user. It will be deleted when the file (object) is
|
||||
* destroyed.
|
||||
*
|
||||
@@ -252,8 +256,8 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns a pointer to the XiphComment for the file.
|
||||
*
|
||||
* If \a create is false (the default) this returns a null pointer
|
||||
* if there is no valid XiphComment. If \a create is true it will create
|
||||
* If \a create is \c false (the default) this returns a null pointer
|
||||
* if there is no valid XiphComment. If \a create is \c true it will create
|
||||
* a XiphComment if one does not exist and returns a valid pointer.
|
||||
*
|
||||
* \note This may return a valid pointer regardless of whether or not the
|
||||
@@ -274,8 +278,8 @@ namespace TagLib {
|
||||
List<Picture *> pictureList();
|
||||
|
||||
/*!
|
||||
* Removes an attached picture. If \a del is true the picture's memory
|
||||
* will be freed; if it is false, it must be deleted by the user.
|
||||
* Removes an attached picture. If \a del is \c true the picture's memory
|
||||
* will be freed; if it is \c false, it must be deleted by the user.
|
||||
*/
|
||||
void removePicture(Picture *picture, bool del = true);
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
#ifndef TAGLIB_FLACMETADATABLOCK_H
|
||||
#define TAGLIB_FLACMETADATABLOCK_H
|
||||
|
||||
#include "tlist.h"
|
||||
#include "tbytevector.h"
|
||||
#include "taglib_export.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace FLAC {
|
||||
//! FLAC metadata block
|
||||
class TAGLIB_EXPORT MetadataBlock
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -35,11 +35,12 @@
|
||||
|
||||
namespace TagLib {
|
||||
namespace FLAC {
|
||||
//! FLAC picture
|
||||
class TAGLIB_EXPORT Picture : public MetadataBlock
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
/*
|
||||
* This describes the function or content of the picture.
|
||||
*/
|
||||
DECLARE_PICTURE_TYPE_ENUM(Type)
|
||||
@@ -71,7 +72,7 @@ namespace TagLib {
|
||||
* Sets the mime type of the image. This should in most cases be
|
||||
* "image/png" or "image/jpeg".
|
||||
*/
|
||||
void setMimeType(const String &m);
|
||||
void setMimeType(const String &mimeType);
|
||||
|
||||
/*!
|
||||
* Returns a text description of the image.
|
||||
@@ -80,10 +81,10 @@ namespace TagLib {
|
||||
String description() const;
|
||||
|
||||
/*!
|
||||
* Sets a textual description of the image to \a desc.
|
||||
* Sets a textual description of the image to \a description.
|
||||
*/
|
||||
|
||||
void setDescription(const String &desc);
|
||||
void setDescription(const String &description);
|
||||
|
||||
/*!
|
||||
* Returns the width of the image.
|
||||
@@ -93,7 +94,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Sets the width of the image.
|
||||
*/
|
||||
void setWidth(int w);
|
||||
void setWidth(int width);
|
||||
|
||||
/*!
|
||||
* Returns the height of the image.
|
||||
@@ -103,7 +104,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Sets the height of the image.
|
||||
*/
|
||||
void setHeight(int h);
|
||||
void setHeight(int height);
|
||||
|
||||
/*!
|
||||
* Returns the color depth (in bits-per-pixel) of the image.
|
||||
@@ -113,7 +114,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Sets the color depth (in bits-per-pixel) of the image.
|
||||
*/
|
||||
void setColorDepth(int depth);
|
||||
void setColorDepth(int colorDepth);
|
||||
|
||||
/*!
|
||||
* Returns the number of colors used on the image..
|
||||
@@ -148,7 +149,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Parse the picture data in the FLAC picture block format.
|
||||
*/
|
||||
bool parse(const ByteVector &rawData);
|
||||
bool parse(const ByteVector &data);
|
||||
|
||||
private:
|
||||
class PicturePrivate;
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#include "tstring.h"
|
||||
#include "tdebug.h"
|
||||
|
||||
#include "flacfile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class FLAC::Properties::PropertiesPrivate
|
||||
@@ -134,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);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace TagLib {
|
||||
//! An implementation of audio property reading for FLAC
|
||||
|
||||
/*!
|
||||
* This reads the data from an FLAC stream found in the AudioProperties
|
||||
* This reads the data from a FLAC stream found in the AudioProperties
|
||||
* API.
|
||||
*/
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
namespace TagLib {
|
||||
namespace FLAC {
|
||||
//! Unknown FLAC metadata block
|
||||
class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
#include "tstringlist.h"
|
||||
#include "tdebug.h"
|
||||
#include "tpropertymap.h"
|
||||
#include "modfileprivate.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@@ -31,12 +31,27 @@
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
//! An implementation of Impulse Tracker metadata
|
||||
|
||||
/*!
|
||||
* This is an implementation of Impulse Tracker metadata.
|
||||
*/
|
||||
|
||||
namespace IT {
|
||||
|
||||
//! An implementation of TagLib::File with IT specific methods
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for IT files to the
|
||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||
* the abstract TagLib::File API as well as providing some additional
|
||||
* information specific to IT files.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public Mod::FileBase {
|
||||
public:
|
||||
/*!
|
||||
* Constructs a Impulse Tracker file from \a file.
|
||||
* Constructs an Impulse Tracker file from \a file.
|
||||
*
|
||||
* \note In the current implementation, both \a readProperties and
|
||||
* \a propertiesStyle are ignored. The audio properties are always
|
||||
@@ -47,7 +62,7 @@ namespace TagLib {
|
||||
AudioProperties::Average);
|
||||
|
||||
/*!
|
||||
* Constructs a Impulse Tracker file from \a stream.
|
||||
* Constructs an Impulse Tracker file from \a stream.
|
||||
*
|
||||
* \note In the current implementation, both \a readProperties and
|
||||
* \a propertiesStyle are ignored. The audio properties are always
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
#ifndef TAGLIB_ITPROPERTIES_H
|
||||
#define TAGLIB_ITPROPERTIES_H
|
||||
|
||||
#include "taglib.h"
|
||||
#include "audioproperties.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace IT {
|
||||
//! An implementation of audio property reading for IT
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||
public:
|
||||
/*! Flag bits. */
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -95,8 +96,7 @@ 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') {
|
||||
if(const char ch = d->name.at(i); (ch < ' ' || ch > '~') && ch != '\251') {
|
||||
debug("MP4: Invalid atom type");
|
||||
d->length = 0;
|
||||
file->seek(0, File::End);
|
||||
@@ -143,12 +143,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 +170,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 +240,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 +271,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -57,8 +57,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 +95,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 +138,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 +184,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:
|
||||
{
|
||||
@@ -458,8 +451,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 +495,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 +510,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 +521,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 +531,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 +545,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 +571,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()};
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys the frame factory.
|
||||
*/
|
||||
virtual ~ItemFactory();
|
||||
~ItemFactory();
|
||||
|
||||
/*!
|
||||
* Returns mapping between atom names and handler types.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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") {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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()
|
||||
*/
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include "tbytevectorlist.h"
|
||||
#include "tdebug.h"
|
||||
#include "tpropertymap.h"
|
||||
#include "id3v2tag.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace TagLib {
|
||||
PodcastFrame &operator=(const PodcastFrame &) = delete;
|
||||
|
||||
/*!
|
||||
* Returns a null string.
|
||||
* Returns an empty string.
|
||||
*/
|
||||
String toString() const override;
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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()
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -8,6 +8,16 @@ namespace TagLib {
|
||||
* This is a relatively complete and flexible framework for working with ID3v2
|
||||
* tags.
|
||||
*
|
||||
* More information about ID3v2 tags can be found at
|
||||
* - <a href="https://github.com/taglib/taglib/blob/master/taglib/mpeg/id3v2/id3v2.2.0.txt">
|
||||
* id3v2.2.0.txt</a>
|
||||
* - <a href="https://github.com/taglib/taglib/blob/master/taglib/mpeg/id3v2/id3v2.3.0.txt">
|
||||
* id3v2.3.0.txt</a>
|
||||
* - <a href="https://github.com/taglib/taglib/blob/master/taglib/mpeg/id3v2/id3v2.4.0-structure.txt">
|
||||
* id3v2.4.0-structure.txt</a>
|
||||
* - <a href="https://github.com/taglib/taglib/blob/master/taglib/mpeg/id3v2/id3v2.4.0-frames.txt">
|
||||
* id3v2.4.0-frames.txt</a>
|
||||
*
|
||||
* \see ID3v2::Tag
|
||||
*/
|
||||
namespace ID3v2 {
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "tbytevector.h"
|
||||
#include "taglib_export.h"
|
||||
#include "taglib.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
@@ -42,7 +41,8 @@ namespace TagLib {
|
||||
* the ID3v2 standard. The API is based on the properties of ID3v2 extended
|
||||
* headers specified there. If any of the terms used in this documentation
|
||||
* are unclear please check the specification in the linked section.
|
||||
* (Structure, <a href="id3v2-structure.html#3.2">3.2</a>)
|
||||
* (<a href="https://github.com/taglib/taglib/blob/master/taglib/mpeg/id3v2/id3v2.4.0-structure.txt">
|
||||
* id3v2.4.0-structure.txt</a>, 3.2)
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT ExtendedHeader
|
||||
@@ -56,7 +56,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys the extended header.
|
||||
*/
|
||||
virtual ~ExtendedHeader();
|
||||
~ExtendedHeader();
|
||||
|
||||
ExtendedHeader(const ExtendedHeader &) = delete;
|
||||
ExtendedHeader &operator=(const ExtendedHeader &) = delete;
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Destroys the footer.
|
||||
*/
|
||||
virtual ~Footer();
|
||||
~Footer();
|
||||
|
||||
Footer(const Footer &) = delete;
|
||||
Footer &operator=(const Footer &) = delete;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user