C bindings, fileref, fix warnings

This commit is contained in:
Urs Fleisch
2025-08-10 06:10:46 +02:00
parent 4546c00417
commit 6fa3db1e51
23 changed files with 227 additions and 54 deletions

View File

@ -63,6 +63,12 @@ if(WITH_SHORTEN)
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/shorten
)
endif()
if(WITH_MATROSKA)
set(tag_c_HDR_DIRS ${tag_c_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/matroska
${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/matroska/ebml
)
endif()
include_directories(${tag_c_HDR_DIRS})
set(tag_c_HDRS tag_c.h)

View File

@ -80,6 +80,9 @@
#ifdef TAGLIB_WITH_SHORTEN
#include "shortenfile.h"
#endif
#ifdef TAGLIB_WITH_MATROSKA
#include "matroskafile.h"
#endif
using namespace TagLib;
@ -241,6 +244,11 @@ TagLib_File *taglib_file_new_type_any_char(const T *filename, TagLib_File_Type t
case TagLib_File_SHORTEN:
file = new Shorten::File(filename);
break;
#endif
#ifdef TAGLIB_WITH_MATROSKA
case TagLib_File_MATROSKA:
file = new Matroska::File(filename);
break;
#endif
default:
break;

View File

@ -132,7 +132,8 @@ typedef enum {
TagLib_File_Opus,
TagLib_File_DSF,
TagLib_File_DSDIFF,
TagLib_File_SHORTEN
TagLib_File_SHORTEN,
TagLib_File_MATROSKA
} TagLib_File_Type;
/*!

View File

@ -296,6 +296,10 @@ namespace
else if(Shorten::File::isSupported(stream))
file = new Shorten::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
#ifdef TAGLIB_WITH_MATROSKA
else if(Matroska::File::isSupported(stream))
file = new Matroska::File(stream, readAudioProperties, audioPropertiesStyle);
#endif
// isSupported() only does a quick check, so double check the file here.
@ -520,6 +524,11 @@ StringList FileRef::defaultFileExtensions()
#ifdef TAGLIB_WITH_SHORTEN
l.append("shn");
#endif
#ifdef TAGLIB_WITH_MATROSKA
l.append("mkv");
l.append("mka");
l.append("webm");
#endif
return l;
}

View File

@ -51,11 +51,9 @@ namespace TagLib {
Matroska::Segment* parseSegment();
private:
offset_t dataOffset = 0;
MkTags *tags = nullptr;
MkAttachments *attachments = nullptr;
MkSeekHead *seekHead = nullptr;
};
}
}

View File

@ -54,7 +54,7 @@ ByteVector EBML::StringElement<t>::render()
std::string string = value.to8Bit(t == String::UTF8);
dataSize = string.size();
buffer.append(renderVINT(dataSize, 0));
buffer.append(ByteVector(string.data(), dataSize));
buffer.append(ByteVector(string.data(), static_cast<unsigned int>(dataSize)));
return buffer;
}
template ByteVector EBML::StringElement<String::UTF8>::render();

View File

@ -64,7 +64,7 @@ std::pair<int, T> EBML::readVINT(File &file)
if(nb_bytes > 1)
buffer.append(file.readBlock(nb_bytes - 1));
int bits_to_shift = (sizeof(T) * 8) - (7 * nb_bytes);
int bits_to_shift = static_cast<int>(sizeof(T) * 8) - (7 * nb_bytes);
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bits_to_shift;
return { nb_bytes, static_cast<T>(buffer.toLongLong(true)) & mask };
}
@ -83,7 +83,7 @@ std::pair<int, T> EBML::parseVINT(const ByteVector &buffer)
if(!numBytes)
return {0, 0};
int bits_to_shift = (sizeof(T) * 8) - (7 * numBytes);
int bits_to_shift = static_cast<int>(sizeof(T) * 8) - (7 * numBytes);
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bits_to_shift;
return { numBytes, static_cast<T>(buffer.toLongLong(true)) & mask };
}

View File

@ -32,12 +32,12 @@ ByteVector EBML::VoidElement::render()
offset_t bytesNeeded = targetSize;
ByteVector buffer = renderId();
bytesNeeded -= buffer.size();
sizeLength = std::min(bytesNeeded, static_cast<offset_t>(8));
sizeLength = static_cast<int>(std::min(bytesNeeded, static_cast<offset_t>(8)));
bytesNeeded -= sizeLength;
dataSize = bytesNeeded;
buffer.append(renderVINT(dataSize, sizeLength));
if (dataSize)
buffer.append(ByteVector(dataSize, 0));
buffer.append(ByteVector(static_cast<unsigned int>(dataSize), 0));
return buffer;
}

View File

@ -48,10 +48,10 @@ namespace TagLib {
private:
class AttachedFilePrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<AttachedFilePrivate> d;
};
}
}
#endif
#endif

View File

@ -55,10 +55,10 @@ namespace TagLib {
friend class EBML::MkAttachments;
friend class Matroska::File;
class AttachmentsPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<AttachmentsPrivate> d;
};
}
}
#endif
#endif

View File

@ -141,7 +141,7 @@ bool Matroska::Element::sizeChanged(Element &caller, offset_t delta)
return true;
}
bool Matroska::Element::offsetChanged(Element &caller, offset_t delta)
bool Matroska::Element::offsetChanged(Element &, offset_t)
{
// Most elements don't need to handle this
return true;

View File

@ -64,8 +64,8 @@ namespace TagLib {
private:
class ElementPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<ElementPrivate> e;
};
namespace ElementIDs {
inline constexpr Element::ID MkTags = 0x1254C367;

View File

@ -55,7 +55,22 @@ public:
Segment *segment = nullptr;
};
Matroska::File::File(FileName file, bool readProperties)
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
bool Matroska::File::isSupported(IOStream *)
{
// TODO implement
return false;
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
Matroska::File::File(FileName file, bool readProperties,
Properties::ReadStyle readStyle)
: TagLib::File(file),
d(std::make_unique<FilePrivate>())
{
@ -64,10 +79,11 @@ Matroska::File::File(FileName file, bool readProperties)
setValid(false);
return;
}
read(readProperties);
read(readProperties, readStyle);
}
Matroska::File::File(IOStream *stream, bool readProperties)
Matroska::File::File(IOStream *stream, bool readProperties,
Properties::ReadStyle readStyle)
: TagLib::File(stream),
d(std::make_unique<FilePrivate>())
{
@ -76,7 +92,7 @@ Matroska::File::File(IOStream *stream, bool readProperties)
setValid(false);
return;
}
read(readProperties);
read(readProperties, readStyle);
}
Matroska::File::~File() = default;
@ -108,7 +124,7 @@ Matroska::Attachments* Matroska::File::attachments(bool create) const
}
}
void Matroska::File::read(bool readProperties)
void Matroska::File::read(bool, Properties::ReadStyle)
{
offset_t fileLength = length();
@ -139,7 +155,7 @@ void Matroska::File::read(bool readProperties)
setValid(false);
return;
}
// Parse the elements
d->segment = segment->parseSegment();
d->seekHead = segment->parseSeekHead();

View File

@ -24,6 +24,7 @@
#include "taglib_export.h"
#include "tfile.h"
#include "tag.h"
#include "matroskaproperties.h"
namespace TagLib {
@ -34,8 +35,10 @@ namespace TagLib {
class TAGLIB_EXPORT File : public TagLib::File
{
public:
File(FileName file, bool readProperties = true);
File(IOStream *stream, bool readProperties = true);
File(FileName file, bool readProperties = true,
Properties::ReadStyle readStyle = Properties::Average);
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle readStyle = Properties::Average);
~File() override;
File(const File &) = delete;
File &operator=(const File &) = delete;
@ -46,19 +49,23 @@ namespace TagLib {
bool save() override;
//PropertyMap properties() const override { return PropertyMap(); }
//void removeUnsupportedProperties(const StringList &properties) override { }
private:
void read(bool readProperties);
class FilePrivate;
std::unique_ptr<FilePrivate> d;
/*!
* Returns whether or not the given \a stream can be opened as a Matroska
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
void read(bool readProperties, Properties::ReadStyle readStyle);
class FilePrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<FilePrivate> d;
};
}
}
#endif
#endif

View File

@ -0,0 +1,76 @@
/***************************************************************************
copyright : (C) 2025 by Urs Fleisch
email : ufleisch@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "matroskaproperties.h"
using namespace TagLib;
class Matroska::Properties::PropertiesPrivate
{
public:
int length { 0 };
int bitrate { 0 };
int sampleRate { 0 };
int bitsPerSample { 0 };
int channels { 0 };
};
Matroska::Properties::Properties(File *file, ReadStyle style) :
AudioProperties(style),
d(std::make_unique<PropertiesPrivate>())
{
read(file);
}
Matroska::Properties::~Properties() = default;
int Matroska::Properties::lengthInMilliseconds() const
{
return d->length;
}
int Matroska::Properties::bitrate() const
{
return d->bitrate;
}
int Matroska::Properties::sampleRate() const
{
return d->sampleRate;
}
int Matroska::Properties::channels() const
{
return d->channels;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void Matroska::Properties::read(File *file)
{
// TODO implement.
}

View File

@ -27,25 +27,17 @@
namespace TagLib {
namespace MPEG {
namespace Matroska {
class File;
//! An implementation of audio property reading for MP3
/*!
* This reads the data from an MPEG Layer III stream found in the
* AudioProperties API.
*/
//! An implementation of Matroska audio properties
class TAGLIB_EXPORT Properties : public AudioProperties
{
public:
/*!
* Destroys this MPEG Properties instance.
*/
~Properties() override {}
Properties(File *file, ReadStyle style = Average);
~Properties() override;
Properties(const Properties &) = delete;
Properties &operator=(const Properties &) = delete;
@ -55,29 +47,31 @@ namespace TagLib {
*
* \see lengthInSeconds()
*/
int lengthInMilliseconds() const override {}
int lengthInMilliseconds() const override;
/*!
* Returns the average bit rate of the file in kb/s.
*/
int bitrate() const override {}
int bitrate() const override;
/*!
* Returns the sample rate in Hz.
*/
int sampleRate() const override {}
int sampleRate() const override;
/*!
* Returns the number of audio channels.
*/
int channels() const override {}
int channels() const override;
private:
void read(File *file);
class PropertiesPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<PropertiesPrivate> d;
};
} // namespace MPEG
} // namespace Matroska
} // namespace TagLib
#endif

View File

@ -25,12 +25,12 @@ using namespace TagLib;
bool Matroska::Segment::render()
{
auto data = EBML::renderVINT(dataSize, sizeLength);
auto data = EBML::renderVINT(dataSize, static_cast<int>(sizeLength));
if (data.size() != sizeLength) {
sizeLength = 8;
if (!emitSizeChanged(sizeLength - data.size()))
return false;
data = EBML::renderVINT(dataSize, sizeLength);
data = EBML::renderVINT(dataSize, static_cast<int>(sizeLength));
if (data.size() != sizeLength)
return false;
}
@ -38,8 +38,8 @@ bool Matroska::Segment::render()
return true;
}
bool Matroska::Segment::sizeChanged(Element &caller, offset_t delta)
bool Matroska::Segment::sizeChanged(Element &, offset_t delta)
{
dataSize += delta;
return true;
}
}

View File

@ -54,6 +54,7 @@ namespace TagLib {
private:
class SimpleTagPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<SimpleTagPrivate> d;
protected:
@ -70,6 +71,7 @@ namespace TagLib {
private:
class SimpleTagStringPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<SimpleTagStringPrivate> dd;
};
@ -83,6 +85,7 @@ namespace TagLib {
private:
class SimpleTagBinaryPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<SimpleTagBinaryPrivate> dd;
};

View File

@ -125,6 +125,7 @@ namespace TagLib {
bool setTag(const String &key, const String &value);
const String* getTag(const String &key) const;
class TagPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr<TagPrivate> d;
};
}

View File

@ -65,6 +65,11 @@ IF(WITH_SHORTEN)
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/shorten
)
ENDIF()
IF(WITH_MATROSKA)
SET(test_HDR_DIRS ${test_HDR_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/matroska
)
ENDIF()
INCLUDE_DIRECTORIES(${test_HDR_DIRS})
SET(test_runner_SRCS
@ -152,6 +157,11 @@ IF(WITH_SHORTEN)
test_shorten.cpp
)
ENDIF()
IF(WITH_MATROSKA)
SET(test_runner_SRCS ${test_runner_SRCS}
test_matroska.cpp
)
ENDIF()
IF(BUILD_BINDINGS)
SET(test_runner_SRCS ${test_runner_SRCS}
test_tag_c.cpp

View File

@ -472,6 +472,11 @@ public:
#endif
#ifdef TAGLIB_WITH_SHORTEN
CPPUNIT_ASSERT(extensions.contains("shn"));
#endif
#ifdef TAGLIB_WITH_MATROSKA
CPPUNIT_ASSERT(extensions.contains("mkv"));
CPPUNIT_ASSERT(extensions.contains("mka"));
CPPUNIT_ASSERT(extensions.contains("webm"));
#endif
}

28
tests/test_matroska.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <string>
#include <cstdio>
#include "tbytevectorlist.h"
#include "tpropertymap.h"
#include "tag.h"
#include "matroskafile.h"
#include "plainfile.h"
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"
using namespace std;
using namespace TagLib;
class TestMatroska : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestMatroska);
CPPUNIT_TEST(testTags);
CPPUNIT_TEST_SUITE_END();
public:
void testTags()
{
// TODO implement
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestMatroska);

View File

@ -148,6 +148,11 @@
#include "trueaudiofile.h"
#include "trueaudioproperties.h"
#endif
#ifdef TAGLIB_WITH_MATROSKA
#include "matroskafile.h"
#include "matroskaproperties.h"
#include "matroskatag.h"
#endif
#include <cppunit/extensions/HelperMacros.h>
@ -297,6 +302,12 @@ public:
#ifdef TAGLIB_WITH_TRUEAUDIO
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::TrueAudio::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::TrueAudio::Properties));
#endif
#ifdef TAGLIB_WITH_MATROSKA
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Matroska::File));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Matroska::Properties));
// TODO move non pimpl fields into private class.
// CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Matroska::Tag));
#endif
}