Implement loading chapters from mpeg files
This commit is contained in:
parent
4c73f1c71c
commit
044dbf5f23
@ -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)
|
||||
|
@ -18,6 +18,7 @@ Note: When using versions of kasts built from git-master, it's possible that the
|
||||
- KConfig
|
||||
- Kirigami
|
||||
- Syndication
|
||||
- TagLib
|
||||
|
||||
## Linux
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user