File clementine-taglib2.patch of Package clementine
From 4d29a0959bc30e55fa682d19c9e832227b68ad98 Mon Sep 17 00:00:00 2001
From: Jonas Kvinge <jonas@jkvinge.net>
Date: Sun, 17 Mar 2024 15:32:40 +0100
Subject: [PATCH 3/3] Fix build with TagLib 2
Signed-off-by: Jonas Kvinge <jonas@jkvinge.net>
---
CMakeLists.txt | 43 ++-----------------
ext/libclementine-tagreader/cloudstream.cpp | 46 ++++++++++++++++++++-
ext/libclementine-tagreader/cloudstream.h | 44 +++++++++++++++-----
ext/libclementine-tagreader/tagreader.cpp | 34 ++++++++-------
include/clementine-config.h.in | 2 +-
5 files changed, 102 insertions(+), 67 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 20e5a71..f063d3e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -82,7 +82,10 @@ pkg_check_modules(LIBMYGPO_QT5 libmygpo-qt5>=1.0.9)
pkg_check_modules(LIBPULSE libpulse)
pkg_check_modules(LIBXML libxml-2.0)
pkg_check_modules(LIBSPOTIFY libspotify>=12.1.45)
-pkg_check_modules(TAGLIB taglib)
+pkg_check_modules(TAGLIB REQUIRED taglib>=1.11.1)
+if (TAGLIB_VERSION VERSION_GREATER_EQUAL 2.0)
+ set(HAVE_TAGLIB2 ON)
+endif()
if (WIN32)
find_package(ZLIB REQUIRED)
@@ -129,44 +132,6 @@ if (Qt5LinguistTools_FOUND)
set(QT_LCONVERT_EXECUTABLE Qt5::lconvert)
endif()
-
-# Only use system taglib if it's greater than 1.11.1
-# There is a bug in version 1.11.1 corrupting Ogg files, see: https://github.com/taglib/taglib/issues/864
-# If you decide to use the systems taglib, make sure it has been patched with the following commit:
-# https://github.com/taglib/taglib/commit/9336c82da3a04552168f208cd7a5fa4646701ea4
-# The current taglib in 3rdparty also has the following features used by Clementine:
-# - Audio file detection by content.
-#
-if (TAGLIB_VERSION VERSION_GREATER 1.11.1)
- option(USE_SYSTEM_TAGLIB "Use system taglib" ON)
-else()
- option(USE_SYSTEM_TAGLIB "Use system taglib" OFF)
-endif()
-
-if (TAGLIB_FOUND AND USE_SYSTEM_TAGLIB)
- if (TAGLIB_VERSION VERSION_GREATER 1.11.1)
- message(STATUS "Using system taglib library")
- else()
- message(WARNING "Using system taglib library. Version 1.11.1 or less has a bug corrupting Ogg files, make sure your systems version has been patched!")
- endif()
- set(CMAKE_REQUIRED_INCLUDES "${TAGLIB_INCLUDE_DIRS}")
- set(CMAKE_REQUIRED_LIBRARIES "${TAGLIB_LIBRARIES}")
- check_cxx_source_compiles("#include <opusfile.h>
- int main() { char *s; TagLib::Ogg::Opus::File opusfile(s); return 0;}" TAGLIB_HAS_OPUS)
- set(CMAKE_REQUIRED_INCLUDES)
- set(CMAKE_REQUIRED_LIBRARIES)
-else()
- message(STATUS "Using builtin taglib library")
- set(TAGLIB_VERSION 1.11.1)
- set(TAGLIB_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/3rdparty/taglib/headers/taglib/;${CMAKE_BINARY_DIR}/3rdparty/taglib/headers/")
- set(TAGLIB_LIBRARY_DIRS "")
- set(TAGLIB_LIBRARIES tag)
- set(TAGLIB_HAS_OPUS ON)
- add_subdirectory(3rdparty/utf8-cpp)
- add_subdirectory(3rdparty/taglib)
- add_definitions(-DTAGLIB_STATIC)
-endif()
-
if(LASTFM5_INCLUDE_DIRS AND LASTFM51_INCLUDE_DIRS)
set(HAVE_LIBLASTFM1 ON)
endif()
diff --git a/ext/libclementine-tagreader/cloudstream.cpp b/ext/libclementine-tagreader/cloudstream.cpp
index 60786fa..3e568f8 100644
--- a/ext/libclementine-tagreader/cloudstream.cpp
+++ b/ext/libclementine-tagreader/cloudstream.cpp
@@ -15,6 +15,8 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "clementine-config.h"
+
#include "cloudstream.h"
#include <taglib/id3v2framefactory.h>
@@ -32,8 +34,14 @@ static const int kTaglibPrefixCacheBytes = 64 * 1024; // Should be enough.
static const int kTaglibSuffixCacheBytes = 8 * 1024;
} // namespace
-CloudStream::CloudStream(const QUrl& url, const QString& filename,
- const long length, const QString& auth)
+CloudStream::CloudStream(const QUrl& url,
+ const QString& filename,
+#ifdef HAVE_TAGLIB2
+ const size_t length,
+#else
+ const long length,
+#endif
+ const QString& auth)
: url_(url),
filename_(filename),
encoded_filename_(filename_.toUtf8()),
@@ -91,7 +99,11 @@ void CloudStream::Precache() {
clear();
}
+#ifdef HAVE_TAGLIB2
+TagLib::ByteVector CloudStream::readBlock(size_t length) {
+#else
TagLib::ByteVector CloudStream::readBlock(ulong length) {
+#endif
const uint start = cursor_;
const uint end = qMin(cursor_ + length - 1, length_ - 1);
@@ -144,11 +156,19 @@ void CloudStream::writeBlock(const TagLib::ByteVector&) {
qLog(Debug) << Q_FUNC_INFO << "not implemented";
}
+#ifdef HAVE_TAGLIB2
+void CloudStream::insert(const TagLib::ByteVector&, TagLib::offset_t, size_t) {
+#else
void CloudStream::insert(const TagLib::ByteVector&, ulong, ulong) {
+#endif
qLog(Debug) << Q_FUNC_INFO << "not implemented";
}
+#ifdef HAVE_TAGLIB2
+void CloudStream::removeBlock(TagLib::offset_t, size_t) {
+#else
void CloudStream::removeBlock(ulong, ulong) {
+#endif
qLog(Debug) << Q_FUNC_INFO << "not implemented";
}
@@ -159,14 +179,22 @@ bool CloudStream::readOnly() const {
bool CloudStream::isOpen() const { return true; }
+#ifdef HAVE_TAGLIB2
+void CloudStream::seek(TagLib::offset_t offset, TagLib::IOStream::Position p) {
+#else
void CloudStream::seek(long offset, TagLib::IOStream::Position p) {
+#endif
switch (p) {
case TagLib::IOStream::Beginning:
cursor_ = offset;
break;
case TagLib::IOStream::Current:
+#ifdef HAVE_TAGLIB2
+ cursor_ = qMin(static_cast<size_t>(cursor_ + offset), length_);
+#else
cursor_ = qMin(ulong(cursor_ + offset), length_);
+#endif
break;
case TagLib::IOStream::End:
@@ -178,11 +206,25 @@ void CloudStream::seek(long offset, TagLib::IOStream::Position p) {
void CloudStream::clear() { cursor_ = 0; }
+#ifdef HAVE_TAGLIB2
+
+TagLib::offset_t CloudStream::tell() const { return cursor_; }
+
+TagLib::offset_t CloudStream::length() { return length_; }
+
+#else
+
long CloudStream::tell() const { return cursor_; }
long CloudStream::length() { return length_; }
+#endif
+
+#ifdef HAVE_TAGLIB2
+void CloudStream::truncate(TagLib::offset_t) {
+#else
void CloudStream::truncate(long) {
+#endif
qLog(Debug) << Q_FUNC_INFO << "not implemented";
}
diff --git a/ext/libclementine-tagreader/cloudstream.h b/ext/libclementine-tagreader/cloudstream.h
index 7002b3a..24e31c2 100644
--- a/ext/libclementine-tagreader/cloudstream.h
+++ b/ext/libclementine-tagreader/cloudstream.h
@@ -18,6 +18,8 @@
#ifndef GOOGLEDRIVESTREAM_H
#define GOOGLEDRIVESTREAM_H
+#include "clementine-config.h"
+
#include <QList>
#include <QNetworkAccessManager>
#include <QObject>
@@ -30,22 +32,38 @@
class CloudStream : public QObject, public TagLib::IOStream {
Q_OBJECT
public:
- CloudStream(const QUrl& url, const QString& filename, const long length,
+ CloudStream(const QUrl& url,
+ const QString& filename,
+#ifdef HAVE_TAGLIB2
+ const size_t length,
+#else
+ const long length,
+#endif
const QString& auth);
// Taglib::IOStream
virtual TagLib::FileName name() const;
- virtual TagLib::ByteVector readBlock(ulong length);
- virtual void writeBlock(const TagLib::ByteVector&);
- virtual void insert(const TagLib::ByteVector&, ulong, ulong);
+#ifdef HAVE_TAGLIB2
+ virtual TagLib::ByteVector readBlock(size_t length) override;
+ virtual void insert(const TagLib::ByteVector&, TagLib::offset_t, size_t) override;
+ virtual void removeBlock(TagLib::offset_t, size_t) override;
+ virtual void seek(TagLib::offset_t offset, TagLib::IOStream::Position p) override;
+ virtual void truncate(TagLib::offset_t) override;
+ virtual TagLib::offset_t tell() const override;
+ virtual TagLib::offset_t length() override;
+#else
+ virtual TagLib::ByteVector readBlock(ulong length) override;
+ virtual void insert(const TagLib::ByteVector&, ulong, ulong) override;
virtual void removeBlock(ulong, ulong);
- virtual bool readOnly() const;
- virtual bool isOpen() const;
- virtual void seek(long offset, TagLib::IOStream::Position p);
- virtual void clear();
- virtual long tell() const;
- virtual long length();
- virtual void truncate(long);
+ virtual void seek(long offset, TagLib::IOStream::Position p) override;
+ virtual void truncate(long) override;
+ virtual long tell() const override;
+ virtual long length() override;
+#endif
+ virtual void writeBlock(const TagLib::ByteVector&) override;
+ virtual bool readOnly() const override;
+ virtual bool isOpen() const override;
+ virtual void clear() override;
google::sparsetable<char>::size_type cached_bytes() const {
return cache_.num_nonempty();
@@ -68,7 +86,11 @@ class CloudStream : public QObject, public TagLib::IOStream {
const QUrl url_;
const QString filename_;
const QByteArray encoded_filename_;
+#ifdef HAVE_TAGLIB2
+ const size_t length_;
+#else
const ulong length_;
+#endif
const QString auth_;
int cursor_;
diff --git a/ext/libclementine-tagreader/tagreader.cpp b/ext/libclementine-tagreader/tagreader.cpp
index e6fc559..c4e861b 100644
--- a/ext/libclementine-tagreader/tagreader.cpp
+++ b/ext/libclementine-tagreader/tagreader.cpp
@@ -38,9 +38,7 @@
#include <QUrl>
#include <QVector>
#include <memory>
-#ifdef TAGLIB_HAS_OPUS
#include <opusfile.h>
-#endif
#include <apetag.h>
#include <oggflacfile.h>
#include <popularimeterframe.h>
@@ -198,7 +196,7 @@ void TagReader::ReadFile(const QString& filename,
// Find album artists
TagLib::APE::ItemListMap::ConstIterator it = items.find("ALBUM ARTIST");
if (it != items.end()) {
- TagLib::StringList album_artists = it->second.toStringList();
+ TagLib::StringList album_artists = it->second.values();
if (!album_artists.isEmpty()) {
Decode(album_artists.front(), nullptr, song->mutable_albumartist());
}
@@ -243,22 +241,22 @@ void TagReader::ReadFile(const QString& filename,
}
if (items.contains("BPM")) {
- Decode(items["BPM"].toStringList().toString(", "), nullptr,
+ Decode(items["BPM"].values().toString(", "), nullptr,
song->mutable_performer());
}
if (items.contains("PERFORMER")) {
- Decode(items["PERFORMER"].toStringList().toString(", "), nullptr,
+ Decode(items["PERFORMER"].values().toString(", "), nullptr,
song->mutable_performer());
}
if (items.contains("COMPOSER")) {
- Decode(items["COMPOSER"].toStringList().toString(", "), nullptr,
+ Decode(items["COMPOSER"].values().toString(", "), nullptr,
song->mutable_composer());
}
if (items.contains("GROUPING")) {
- Decode(items["GROUPING"].toStringList().toString(" "), nullptr,
+ Decode(items["GROUPING"].values().toString(" "), nullptr,
song->mutable_grouping());
}
@@ -565,8 +563,8 @@ void TagReader::ReadFile(const QString& filename,
if (fileref->audioProperties()) {
song->set_bitrate(fileref->audioProperties()->bitrate());
song->set_samplerate(fileref->audioProperties()->sampleRate());
- song->set_length_nanosec(fileref->audioProperties()->length() *
- kNsecPerSec);
+ song->set_length_nanosec(fileref->audioProperties()->lengthInMilliseconds() *
+ kNsecPerMsec);
}
// Get the filetype if we can
@@ -789,10 +787,8 @@ cpb::tagreader::SongMetadata_Type TagReader::GuessFileType(
return cpb::tagreader::SongMetadata_Type_OGGSPEEX;
if (dynamic_cast<TagLib::Ogg::Vorbis::File*>(fileref->file()))
return cpb::tagreader::SongMetadata_Type_OGGVORBIS;
-#ifdef TAGLIB_HAS_OPUS
if (dynamic_cast<TagLib::Ogg::Opus::File*>(fileref->file()))
return cpb::tagreader::SongMetadata_Type_OGGOPUS;
-#endif
if (dynamic_cast<TagLib::RIFF::AIFF::File*>(fileref->file()))
return cpb::tagreader::SongMetadata_Type_AIFF;
if (dynamic_cast<TagLib::RIFF::WAV::File*>(fileref->file()))
@@ -1376,31 +1372,41 @@ bool TagReader::ReadCloudFile(const QUrl& download_url, const QString& title,
std::unique_ptr<TagLib::File> tag;
if (mime_type == "audio/mpeg" &&
title.endsWith(".mp3", Qt::CaseInsensitive)) {
+#ifdef HAVE_TAGLIB2
+ tag.reset(new TagLib::MPEG::File(stream.get(), true,
+ TagLib::AudioProperties::Accurate,
+ TagLib::ID3v2::FrameFactory::instance()));
+#else
tag.reset(new TagLib::MPEG::File(stream.get(),
TagLib::ID3v2::FrameFactory::instance(),
TagLib::AudioProperties::Accurate));
+#endif
} else if (mime_type == "audio/mp4" ||
(mime_type == "audio/mpeg" &&
title.endsWith(".m4a", Qt::CaseInsensitive))) {
tag.reset(new TagLib::MP4::File(stream.get(), true,
TagLib::AudioProperties::Accurate));
}
-#ifdef TAGLIB_HAS_OPUS
else if ((mime_type == "application/opus" || mime_type == "audio/opus" ||
mime_type == "application/ogg" || mime_type == "audio/ogg") &&
title.endsWith(".opus", Qt::CaseInsensitive)) {
tag.reset(new TagLib::Ogg::Opus::File(stream.get(), true,
TagLib::AudioProperties::Accurate));
}
-#endif
else if (mime_type == "application/ogg" || mime_type == "audio/ogg") {
tag.reset(new TagLib::Ogg::Vorbis::File(stream.get(), true,
TagLib::AudioProperties::Accurate));
} else if (mime_type == "application/x-flac" || mime_type == "audio/flac" ||
mime_type == "audio/x-flac") {
+#ifdef HAVE_TAGLIB2
+ tag.reset(new TagLib::FLAC::File(stream.get(), true,
+ TagLib::AudioProperties::Accurate,
+ TagLib::ID3v2::FrameFactory::instance()));
+#else
tag.reset(new TagLib::FLAC::File(stream.get(),
TagLib::ID3v2::FrameFactory::instance(),
true, TagLib::AudioProperties::Accurate));
+#endif
} else if (mime_type == "audio/x-ms-wma") {
tag.reset(new TagLib::ASF::File(stream.get(), true,
TagLib::AudioProperties::Accurate));
@@ -1431,7 +1437,7 @@ bool TagReader::ReadCloudFile(const QUrl& download_url, const QString& title,
song->set_type(cpb::tagreader::SongMetadata_Type_STREAM);
if (tag->audioProperties()) {
- song->set_length_nanosec(tag->audioProperties()->length() * kNsecPerSec);
+ song->set_length_nanosec(tag->audioProperties()->lengthInMilliseconds() * kNsecPerMsec);
}
return true;
}
diff --git a/include/clementine-config.h.in b/include/clementine-config.h.in
index eb6dbfc..8fa8772 100644
--- a/include/clementine-config.h.in
+++ b/include/clementine-config.h.in
@@ -48,11 +48,11 @@
#cmakedefine HAVE_OPENGL
#cmakedefine HAVE_TRANSLATIONS
#cmakedefine HAVE_SPOTIFY
-#cmakedefine TAGLIB_HAS_OPUS
#cmakedefine USE_INSTALL_PREFIX
#cmakedefine USE_SYSTEM_PROJECTM
#cmakedefine USE_SYSTEM_SHA2
#cmakedefine USE_BUNDLE
+#cmakedefine HAVE_TAGLIB2
#define USE_BUNDLE_DIR "${USE_BUNDLE_DIR}"
--
2.44.0