Implement loading chapters from mpeg files

This commit is contained in:
Tobias Fella 2021-10-05 21:34:19 +02:00
parent 4c73f1c71c
commit 044dbf5f23
7 changed files with 74 additions and 5 deletions

View File

@ -36,6 +36,7 @@ ecm_setup_version(${PROJECT_VERSION}
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui QuickControls2 Sql Multimedia)
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS CoreAddons Syndication Config I18n)
find_package(Taglib REQUIRED)
if (ANDROID)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Svg)

View File

@ -18,6 +18,7 @@ Note: When using versions of kasts built from git-master, it's possible that the
- KConfig
- Kirigami
- Syndication
- TagLib
## Linux

View File

@ -122,7 +122,7 @@ add_executable(kasts ${SRCS})
kconfig_add_kcfg_files(kasts settingsmanager.kcfgc GENERATE_MOC)
target_include_directories(kasts PRIVATE ${CMAKE_BINARY_DIR})
target_link_libraries(kasts PRIVATE Qt::Core Qt::Qml Qt::Quick Qt::QuickControls2 Qt::Sql Qt::Multimedia KF5::Syndication KF5::CoreAddons KF5::ConfigGui KF5::I18n)
target_link_libraries(kasts PRIVATE Qt::Core Qt::Qml Qt::Quick Qt::QuickControls2 Qt::Sql Qt::Multimedia KF5::Syndication KF5::CoreAddons KF5::ConfigGui KF5::I18n Taglib::Taglib)
if(ANDROID)
target_link_libraries(kasts PRIVATE

View File

@ -7,9 +7,12 @@
#include "models/chaptermodel.h"
#include <QDebug>
#include <QMimeDatabase>
#include <QObject>
#include <QSqlQuery>
#include <taglib/chapterframe.h>
#include "database.h"
ChapterModel::ChapterModel(QObject *parent)
@ -69,15 +72,24 @@ QString ChapterModel::enclosureId() const
void ChapterModel::setEnclosureId(QString newEnclosureId)
{
m_enclosureId = newEnclosureId;
loadFromDatabase();
load();
Q_EMIT enclosureIdChanged();
}
void ChapterModel::loadFromDatabase()
void ChapterModel::load()
{
beginResetModel();
m_chapters = {};
loadFromDatabase();
if (m_chapters.isEmpty()) {
loadChaptersFromFile();
}
endResetModel();
}
void ChapterModel::loadFromDatabase()
{
QSqlQuery query;
query.prepare(QStringLiteral("SELECT * FROM Chapters WHERE id=:id"));
query.bindValue(QStringLiteral(":id"), enclosureId());
@ -90,6 +102,48 @@ void ChapterModel::loadFromDatabase()
chapter.start = query.value(QStringLiteral("start")).toInt();
m_chapters << chapter;
}
endResetModel();
}
void ChapterModel::loadMPEGChapters(TagLib::MPEG::File &f)
{
if (!f.hasID3v2Tag()) {
return;
}
for (const auto &frame : f.ID3v2Tag()->frameListMap()["CHAP"]) {
auto chapterFrame = dynamic_cast<TagLib::ID3v2::ChapterFrame *>(frame);
ChapterEntry chapter{};
chapter.title = QString::fromStdString(chapterFrame->embeddedFrameListMap()["TIT2"].front()->toString().to8Bit(true));
chapter.link = QString();
chapter.image = QString();
chapter.start = chapterFrame->startTime() / 1000;
m_chapters << chapter;
}
std::sort(m_chapters.begin(), m_chapters.end(), [](const ChapterEntry &a, const ChapterEntry &b) {
return a.start < b.start;
});
}
void ChapterModel::loadChaptersFromFile()
{
if (m_enclosurePath.isEmpty()) {
return;
}
const auto mime = QMimeDatabase().mimeTypeForFile(m_enclosurePath).name();
if (mime == QStringLiteral("audio/mpeg")) {
TagLib::MPEG::File f(m_enclosurePath.toLatin1().data());
loadMPEGChapters(f);
} // TODO else...
}
void ChapterModel::setEnclosurePath(const QString &enclosurePath)
{
m_enclosurePath = enclosurePath;
Q_EMIT enclosureIdChanged();
load();
}
QString ChapterModel::enclosurePath() const
{
return m_enclosurePath;
}

View File

@ -9,6 +9,8 @@
#include <KFormat>
#include <QAbstractListModel>
#include <taglib/mpegfile.h>
struct ChapterEntry {
QString title;
QString link;
@ -21,6 +23,7 @@ class ChapterModel : public QAbstractListModel
Q_OBJECT
Q_PROPERTY(QString enclosureId READ enclosureId WRITE setEnclosureId NOTIFY enclosureIdChanged)
Q_PROPERTY(QString enclosurePath READ enclosurePath WRITE setEnclosurePath NOTIFY enclosurePathChanged)
public:
enum RoleNames {
@ -40,13 +43,21 @@ public:
void setEnclosureId(QString newEnclosureId);
QString enclosureId() const;
void setEnclosurePath(const QString &enclosurePath);
QString enclosurePath() const;
Q_SIGNALS:
void enclosureIdChanged();
void enclosurePathChanged();
private:
void load();
void loadFromDatabase();
void loadChaptersFromFile();
void loadMPEGChapters(TagLib::MPEG::File &f);
QString m_enclosureId;
QVector<ChapterEntry> m_chapters;
KFormat m_kformat;
QString m_enclosurePath;
};

View File

@ -97,6 +97,7 @@ Kirigami.ScrollablePage {
Layout.bottomMargin: Kirigami.Units.gridUnit
model: ChapterModel {
enclosureId: entry.id
enclosurePath: entry.enclosure.path
}
delegate: ChapterListDelegate {
entry: page.entry

View File

@ -123,6 +123,7 @@ Kirigami.Page {
id: chapterList
model: ChapterModel {
enclosureId: AudioManager.entry.id
enclosurePath: AudioManager.entry.enclosure.path
}
clip: true
visible: chapterList.count !== 0