Clean up code. Remove commented debug rubbish. Clarify conditions/loops where needed.
This commit is contained in:
parent
480974b45d
commit
abaa35d85a
17 changed files with 141 additions and 176 deletions
|
|
@ -121,16 +121,13 @@ Item {
|
|||
}
|
||||
|
||||
function setPosition(pos) {
|
||||
console.log(`setPosition(${pos})`);
|
||||
MPV.position = pos;
|
||||
}
|
||||
|
||||
// Library functions:
|
||||
function bookPlay(bookid, position) {
|
||||
console.log(`Manager.bookPlay(${bookid}, ${position})`);
|
||||
if( m_currentBook && m_currentBook["id"] === bookid)
|
||||
{
|
||||
console.log(`On current book, taking shortcut...`);
|
||||
if( position )
|
||||
setPosition(position);
|
||||
|
||||
|
|
@ -171,7 +168,6 @@ Item {
|
|||
const cachedPath = "image://thumbnails/" + encodeURIComponent(m_currentBook["path"]);
|
||||
let thumber = thumbnail.createObject(manager, {"source":cachedPath, "destination":newUrl});
|
||||
thumber.done.connect(function(success) {
|
||||
console.log("Thumber done.");
|
||||
if( success )
|
||||
m_currentBook["artUrl"] = newUrl;
|
||||
|
||||
|
|
@ -187,7 +183,7 @@ Item {
|
|||
return;
|
||||
}
|
||||
}
|
||||
console.log(`Couldn't find book with ID ${bookid}!`);
|
||||
console.warn(`Couldn't find book with ID ${bookid}!`);
|
||||
}
|
||||
|
||||
Component {
|
||||
|
|
@ -206,13 +202,12 @@ Item {
|
|||
{
|
||||
image.grabToImage(function(result) {
|
||||
result.saveToFile(destination);
|
||||
console.log(`image captured to ${destination}!`);
|
||||
image.done(true);
|
||||
});
|
||||
}
|
||||
else if( status === Image.Error )
|
||||
{
|
||||
console.log("image.grab failed.");
|
||||
console.warn("Loading image for image.grabToImage failed while attempting thumbnail generation!");
|
||||
image.done(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -575,6 +570,5 @@ Item {
|
|||
}
|
||||
|
||||
manager.m_library = books;
|
||||
//console.log(JSON.stringify(books,null,4));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ Kirigami.Page {
|
|||
|
||||
property bool searchMode: false
|
||||
property alias bookListModel: bookListView.model
|
||||
//property var bookListModel
|
||||
|
||||
signal cardClicked(variant cardInfo)
|
||||
|
||||
|
|
|
|||
|
|
@ -28,11 +28,6 @@ Kirigami.Page {
|
|||
Flickable {
|
||||
id: scrollView
|
||||
anchors.fill: parent
|
||||
/*
|
||||
QQC2.ScrollBar.vertical.policy: QQC2.ScrollBar.AlwaysOff
|
||||
QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
|
||||
contentWidth: -1 // disable horizontal scroll
|
||||
*/
|
||||
contentWidth: parent.width
|
||||
contentHeight: column.height
|
||||
|
||||
|
|
@ -233,30 +228,17 @@ Kirigami.Page {
|
|||
}
|
||||
|
||||
Kirigami.Separator {
|
||||
//visible: nowPlayingPageItem.isPlaying
|
||||
weight: Kirigami.Separator.Weight.Light
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Kirigami.Heading {
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
level: 3
|
||||
text: qsTr("Chapters")
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
*/
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 0
|
||||
Repeater {
|
||||
id: listviewChapters
|
||||
//Layout.fillWidth: true
|
||||
//Layout.preferredHeight: contentHeight > scrollView.height ? scrollView.height : contentHeight
|
||||
|
||||
model: nowPlayingPageItem.m_book ? nowPlayingPageItem.m_book["chapters"] : []
|
||||
|
||||
Kirigami.AbstractCard {
|
||||
//height: innerLayout.height
|
||||
//width: listviewChapters.width
|
||||
|
|
|
|||
|
|
@ -35,10 +35,6 @@ Kirigami.ApplicationWindow {
|
|||
// TODO: This is a dumb hack. Our "initialPage" is Library.
|
||||
root.showingNowPlaying = false;
|
||||
}
|
||||
|
||||
onContentsChanged: function(newlist) {
|
||||
//console.log(`New contents: ${JSON.stringify(newlist,null,4)}`);
|
||||
}
|
||||
}
|
||||
|
||||
property variant pagesModel: [
|
||||
|
|
@ -83,7 +79,6 @@ Kirigami.ApplicationWindow {
|
|||
contentItem: ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
//padding: Kirigami.Units.largeSpacing
|
||||
|
||||
Kirigami.AbstractApplicationHeader {
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -103,7 +98,7 @@ Kirigami.ApplicationWindow {
|
|||
|
||||
QQC2.ScrollBar.vertical.policy: QQC2.ScrollBar.AlwaysOff
|
||||
QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
|
||||
contentWidth: -1 // disable horizontal scroll
|
||||
contentWidth: -1
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
|
|
@ -112,7 +107,7 @@ Kirigami.ApplicationWindow {
|
|||
|
||||
Repeater {
|
||||
model: root.pagesModel
|
||||
delegate: QQC2.Button { //Kirigami.NavigationTabButton {
|
||||
delegate: QQC2.Button {
|
||||
display: Kirigami.NavigationTabButton.TextBesideIcon
|
||||
text: modelData["name"]
|
||||
icon.name: modelData["icon"]
|
||||
|
|
|
|||
|
|
@ -44,8 +44,7 @@ QByteArray File::readFile(const QString &path)
|
|||
QFile f(filepath);
|
||||
if( !f.open(QIODevice::ReadOnly) )
|
||||
{
|
||||
qDebug() << "Failed to read file: " << filepath;
|
||||
//qmlEngine(this)->throwError(tr("Failed to read file!"));
|
||||
qWarning() << "Failed to read file: " << filepath;
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
|
|
@ -60,8 +59,7 @@ bool File::writeFile(const QString &path, const QByteArray &data)
|
|||
QFile f(filepath);
|
||||
if( !f.open(QIODevice::WriteOnly) )
|
||||
{
|
||||
qDebug() << "Failed to open file: " << filepath;
|
||||
//qmlEngine(this)->throwError(tr("Failed to read file!"));
|
||||
qWarning() << "Failed to open file: " << filepath << f.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,16 +27,16 @@ QString LibraryDb::makeDbPath() {
|
|||
}
|
||||
|
||||
void LibraryDb::ensureDirExists(const QString &dirPath) {
|
||||
if (!dirPath.isEmpty() && !QDir(dirPath).exists())
|
||||
if( !dirPath.isEmpty() && !QDir(dirPath).exists() )
|
||||
QDir().mkpath(dirPath);
|
||||
}
|
||||
|
||||
bool LibraryDb::open() {
|
||||
if (m_db.isOpen())
|
||||
if( m_db.isOpen() )
|
||||
return true;
|
||||
|
||||
m_dbPath = makeDbPath();
|
||||
if (m_dbPath.isEmpty())
|
||||
if( m_dbPath.isEmpty() )
|
||||
return false;
|
||||
|
||||
ensureDirExists(QFileInfo(m_dbPath).absolutePath());
|
||||
|
|
@ -52,10 +52,10 @@ bool LibraryDb::open() {
|
|||
}
|
||||
|
||||
void LibraryDb::close() {
|
||||
if (m_connName.isEmpty())
|
||||
if( m_connName.isEmpty() )
|
||||
return;
|
||||
|
||||
if (m_db.isOpen())
|
||||
if( m_db.isOpen() )
|
||||
m_db.close();
|
||||
|
||||
m_db = QSqlDatabase();
|
||||
|
|
@ -64,11 +64,11 @@ void LibraryDb::close() {
|
|||
}
|
||||
|
||||
int LibraryDb::exec(const QString &sql) {
|
||||
if (!m_db.isOpen() && !open())
|
||||
if( !m_db.isOpen() && !open() )
|
||||
return -1;
|
||||
|
||||
QSqlQuery q(m_db);
|
||||
if (!q.exec(sql))
|
||||
if( !q.exec(sql) )
|
||||
return -1;
|
||||
|
||||
return q.numRowsAffected();
|
||||
|
|
@ -77,17 +77,17 @@ int LibraryDb::exec(const QString &sql) {
|
|||
QVariantList LibraryDb::query(const QString &sql) {
|
||||
QVariantList rows;
|
||||
|
||||
if (!m_db.isOpen() && !open())
|
||||
if( !m_db.isOpen() && !open() )
|
||||
return rows;
|
||||
|
||||
QSqlQuery q(m_db);
|
||||
if (!q.exec(sql))
|
||||
if( !q.exec(sql) )
|
||||
return rows;
|
||||
|
||||
const QSqlRecord rec = q.record();
|
||||
const int cols = rec.count();
|
||||
|
||||
while (q.next()) {
|
||||
while( q.next() ) {
|
||||
QVariantMap row;
|
||||
for (int i = 0; i < cols; ++i)
|
||||
row.insert(rec.fieldName(i), q.value(i));
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#pragma once
|
||||
#ifndef LIBRARYDB_H
|
||||
#define LIBRARYDB_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSqlDatabase>
|
||||
|
|
@ -22,7 +23,7 @@ public:
|
|||
Q_INVOKABLE bool isOpen() const { return m_db.isOpen(); }
|
||||
Q_INVOKABLE QString dbPath() const { return m_dbPath; }
|
||||
|
||||
Q_INVOKABLE int exec(const QString &sql); // rows affected, -1 on failure
|
||||
Q_INVOKABLE int exec(const QString &sql);
|
||||
Q_INVOKABLE QVariantList query(const QString &sql);
|
||||
|
||||
Q_INVOKABLE QString escape(const QString &s);
|
||||
|
|
@ -35,3 +36,5 @@ private:
|
|||
QString m_connName;
|
||||
QString m_dbPath;
|
||||
};
|
||||
|
||||
#endif // LIBRARYDB_H
|
||||
|
|
|
|||
11
src/main.cpp
11
src/main.cpp
|
|
@ -26,17 +26,12 @@ int main(int argc, char *argv[])
|
|||
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
|
||||
// set up for db:
|
||||
QString dir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
QDir().mkpath(dir);
|
||||
// QString dbPath = dir + "/library.sqlite3";
|
||||
|
||||
// set up for audiobooks:
|
||||
// set up audiobooks location:
|
||||
QStringList docLocations = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
|
||||
dir = docLocations[0] + QDir::separator() + "Audiobooks";
|
||||
QString dir = docLocations[0] + QDir::separator() + "Audiobooks";
|
||||
QDir().mkpath(dir);
|
||||
|
||||
// qml time:
|
||||
// qml hooks:
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
engine.addImageProvider("thumbnails", new ThumbnailProvider);
|
||||
|
|
|
|||
|
|
@ -16,20 +16,14 @@ MprisContainer::MprisContainer(Mpris *mpris)
|
|||
m_adaptor = new MprisAdaptor(this);
|
||||
m_player = new MprisPlayer(this, mpris);
|
||||
|
||||
auto bus = QDBusConnection::sessionBus();
|
||||
QDBusConnection bus = QDBusConnection::sessionBus();
|
||||
|
||||
bus.registerService("org.mpris.MediaPlayer2.audiobookplayer");
|
||||
|
||||
auto success = bus.registerObject(
|
||||
bool success = bus.registerObject(
|
||||
"/org/mpris/MediaPlayer2",
|
||||
this, QDBusConnection::ExportAdaptors
|
||||
/*
|
||||
QDBusConnection::ExportAllSlots |
|
||||
QDBusConnection::ExportAllProperties |
|
||||
QDBusConnection::ExportAllSignals |
|
||||
QDBusConnection::ExportAdaptors
|
||||
*/
|
||||
);
|
||||
);
|
||||
|
||||
qDebug() << "Registration of MPRIS object:" << success;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#define MPRISADAPTOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QVariantMap>
|
||||
#include <QDBusAbstractAdaptor>
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ void MprisPlayer::updateMetadata(const QVariantMap &metadata)
|
|||
};
|
||||
if( metadata.contains("artUrl") )
|
||||
m_metadata["mpris:artUrl"] = QUrl(metadata.value("artUrl").toString()).toString(QUrl::FullyEncoded);
|
||||
//m_metadata["xesam:artUrl"] = metadata.value("artUrl").toString();
|
||||
|
||||
qDebug() << m_metadata;
|
||||
|
||||
emit metadataChanged();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#define MPRISPLAYER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVariantMap>
|
||||
#include <QDBusObjectPath>
|
||||
#include <QDBusAbstractAdaptor>
|
||||
|
|
|
|||
184
src/mpvaudio.cpp
184
src/mpvaudio.cpp
|
|
@ -13,7 +13,6 @@ static constexpr int PROP_SPEED = 4;
|
|||
static constexpr int PROP_VOLUME = 5;
|
||||
static constexpr int PROP_MEDIA_TITLE = 6;
|
||||
static constexpr int PROP_CORE_IDLE = 7;
|
||||
//static constexpr int PROP_MEDIA_ARTIST = 8;
|
||||
|
||||
static constexpr int PROP_METADATA = 20; // "metadata" (map)
|
||||
static constexpr int PROP_CHAPTER_LIST = 21; // "chapter-list" (array)
|
||||
|
|
@ -66,13 +65,7 @@ void MpvAudio::initMpv() {
|
|||
}
|
||||
|
||||
mpv_set_wakeup_callback(m_mpv, &MpvAudio::mpvWakeup, this);
|
||||
/*
|
||||
int fd = mpv_get_wakeup_pipe(m_mpv);
|
||||
if (fd >= 0) {
|
||||
m_notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
|
||||
connect(m_notifier, &QSocketNotifier::activated, this, &MpvAudio::drainMpvEvents);
|
||||
}
|
||||
*/
|
||||
|
||||
observeProperties();
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +78,6 @@ void MpvAudio::observeProperties() {
|
|||
mpv_observe_property(m_mpv, PROP_SPEED, "speed", MPV_FORMAT_DOUBLE);
|
||||
mpv_observe_property(m_mpv, PROP_VOLUME, "volume", MPV_FORMAT_DOUBLE);
|
||||
mpv_observe_property(m_mpv, PROP_MEDIA_TITLE, "media-title", MPV_FORMAT_STRING);
|
||||
//mpv_observe_property(m_mpv, PROP_MEDIA_ARTIST,"media-artist", MPV_FORMAT_STRING);
|
||||
mpv_observe_property(m_mpv, PROP_CORE_IDLE, "core-idle", MPV_FORMAT_FLAG);
|
||||
|
||||
mpv_observe_property(m_mpv, PROP_METADATA, "metadata", MPV_FORMAT_NODE);
|
||||
|
|
@ -101,11 +93,12 @@ void MpvAudio::mpvWakeup(void *ctx) {
|
|||
}
|
||||
|
||||
void MpvAudio::drainMpvEvents() {
|
||||
if (!m_mpv) return;
|
||||
if( !m_mpv ) return;
|
||||
|
||||
while (true) {
|
||||
mpv_event *ev = mpv_wait_event(m_mpv, 0);
|
||||
if (!ev || ev->event_id == MPV_EVENT_NONE) break;
|
||||
if( !ev || MPV_EVENT_NONE == ev->event_id )
|
||||
break;
|
||||
handleEvent(ev);
|
||||
}
|
||||
}
|
||||
|
|
@ -122,10 +115,10 @@ static inline bool notableTimeGap(double a, double b) {
|
|||
|
||||
QVariantMap MpvAudio::pullNodeMap(const char *prop) {
|
||||
QVariantMap out;
|
||||
if (!m_mpv) return out;
|
||||
if( !m_mpv ) return out;
|
||||
|
||||
mpv_node n{};
|
||||
if (mpv_get_property(m_mpv, prop, MPV_FORMAT_NODE, &n) >= 0) {
|
||||
if( mpv_get_property(m_mpv, prop, MPV_FORMAT_NODE, &n) >= 0 ) {
|
||||
out = nodeToMap(n);
|
||||
mpv_free_node_contents(&n);
|
||||
}
|
||||
|
|
@ -134,10 +127,10 @@ QVariantMap MpvAudio::pullNodeMap(const char *prop) {
|
|||
|
||||
QVariantList MpvAudio::pullNodeList(const char *prop) {
|
||||
QVariantList out;
|
||||
if (!m_mpv) return out;
|
||||
if( !m_mpv ) return out;
|
||||
|
||||
mpv_node n{};
|
||||
if (mpv_get_property(m_mpv, prop, MPV_FORMAT_NODE, &n) >= 0) {
|
||||
if( mpv_get_property(m_mpv, prop, MPV_FORMAT_NODE, &n) >= 0 ) {
|
||||
out = nodeToList(n);
|
||||
mpv_free_node_contents(&n);
|
||||
}
|
||||
|
|
@ -147,13 +140,14 @@ QVariantList MpvAudio::pullNodeList(const char *prop) {
|
|||
void MpvAudio::handleEvent(mpv_event *ev) {
|
||||
switch( ev->event_id ) {
|
||||
case MPV_EVENT_START_FILE: {
|
||||
if (m_loaded) { m_loaded = false; emit loadedChanged(); }
|
||||
if( m_loaded ) {
|
||||
m_loaded = false;
|
||||
emit loadedChanged();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MPV_EVENT_FILE_LOADED: {
|
||||
// Force refresh: mpv_observe_property is fine, but this guarantees immediate population.
|
||||
// (Implement pullNodeProperty below.)
|
||||
m_metadata = pullNodeMap("metadata");
|
||||
emit metadataChanged();
|
||||
|
||||
|
|
@ -163,7 +157,10 @@ void MpvAudio::handleEvent(mpv_event *ev) {
|
|||
m_chapterMetadata = pullNodeMap("chapter-metadata");
|
||||
emit chapterMetadataChanged();
|
||||
|
||||
if (!m_loaded) { m_loaded = true; emit loadedChanged(); }
|
||||
if( !m_loaded ) {
|
||||
m_loaded = true;
|
||||
emit loadedChanged();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -177,97 +174,90 @@ void MpvAudio::handleEvent(mpv_event *ev) {
|
|||
auto *p = static_cast<mpv_event_property*>(ev->data);
|
||||
if (!p) return;
|
||||
|
||||
switch (ev->reply_userdata) {
|
||||
switch( ev->reply_userdata ) {
|
||||
case PROP_TIME_POS: {
|
||||
if (!p->data) break;
|
||||
if( !p->data ) break;
|
||||
double v = *static_cast<double*>(p->data);
|
||||
if (!notableTimeGap(m_position, v)) { m_position = v; emit positionChanged(); }
|
||||
if( !notableTimeGap(m_position, v) ) { m_position = v; emit positionChanged(); }
|
||||
break;
|
||||
}
|
||||
case PROP_DURATION: {
|
||||
if (!p->data) break;
|
||||
if( !p->data ) break;
|
||||
double v = *static_cast<double*>(p->data);
|
||||
if (!fuzzySame(m_duration, v)) { m_duration = v; emit durationChanged(); }
|
||||
if( !fuzzySame(m_duration, v) ) { m_duration = v; emit durationChanged(); }
|
||||
break;
|
||||
}
|
||||
case PROP_PAUSE: {
|
||||
if (!p->data) break;
|
||||
if( !p->data ) break;
|
||||
bool v = (*static_cast<int*>(p->data)) != 0;
|
||||
if (m_paused != v) { m_paused = v; emit pausedChanged(); }
|
||||
if( m_paused != v ) { m_paused = v; emit pausedChanged(); }
|
||||
break;
|
||||
}
|
||||
case PROP_SPEED: {
|
||||
if (!p->data) break;
|
||||
if( !p->data ) break;
|
||||
double v = *static_cast<double*>(p->data);
|
||||
if (!fuzzySame(m_speed, v)) { m_speed = v; emit speedChanged(); }
|
||||
if( !fuzzySame(m_speed, v) ) { m_speed = v; emit speedChanged(); }
|
||||
break;
|
||||
}
|
||||
case PROP_VOLUME: {
|
||||
if (!p->data) break;
|
||||
if( !p->data ) break;
|
||||
double v = *static_cast<double*>(p->data);
|
||||
if (!fuzzySame(m_volume, v)) { m_volume = v; emit volumeChanged(); }
|
||||
if( !fuzzySame(m_volume, v) ) { m_volume = v; emit volumeChanged(); }
|
||||
break;
|
||||
}
|
||||
case PROP_MEDIA_TITLE: {
|
||||
const char *s = p->data ? *static_cast<const char**>(p->data) : nullptr;
|
||||
QString v = s ? QString::fromUtf8(s) : QString();
|
||||
if (m_mediaTitle != v) { m_mediaTitle = v; emit mediaTitleChanged(); }
|
||||
if( m_mediaTitle != v ) { m_mediaTitle = v; emit mediaTitleChanged(); }
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case PROP_MEDIA_ARTIST: {
|
||||
const char *s = p->data ? *static_cast<const char**>(p->data) : nullptr;
|
||||
QString v = s ? QString::fromUtf8(s) : QString();
|
||||
if (m_mediaArtist != v) { m_mediaArtist = v; emit mediaArtistChanged(); }
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case PROP_CORE_IDLE: {
|
||||
if (!p->data) break;
|
||||
if( !p->data ) break;
|
||||
bool idle = (*static_cast<int*>(p->data)) != 0;
|
||||
bool newPlaying = !idle && !m_paused;
|
||||
if (m_playing != newPlaying) { m_playing = newPlaying; emit playingChanged(); }
|
||||
if( m_playing != newPlaying ) { m_playing = newPlaying; emit playingChanged(); }
|
||||
break;
|
||||
}
|
||||
|
||||
case PROP_METADATA: {
|
||||
if (!p->data) { // cleared
|
||||
if (!m_metadata.isEmpty()) { m_metadata.clear(); emit metadataChanged(); }
|
||||
if( !p->data ) { // cleared
|
||||
if( !m_metadata.isEmpty() ) { m_metadata.clear(); emit metadataChanged(); }
|
||||
break;
|
||||
}
|
||||
const mpv_node &n = *static_cast<mpv_node*>(p->data);
|
||||
QVariantMap v = nodeToMap(n);
|
||||
if (m_metadata != v) { m_metadata = std::move(v); emit metadataChanged(); }
|
||||
if( m_metadata != v ) { m_metadata = std::move(v); emit metadataChanged(); }
|
||||
break;
|
||||
}
|
||||
|
||||
case PROP_CHAPTER_LIST: {
|
||||
if (!p->data) {
|
||||
if (!m_chapters.isEmpty()) { m_chapters.clear(); emit chaptersChanged(); }
|
||||
if( !p->data ) {
|
||||
if( !m_chapters.isEmpty() ) { m_chapters.clear(); emit chaptersChanged(); }
|
||||
break;
|
||||
}
|
||||
const mpv_node &n = *static_cast<mpv_node*>(p->data);
|
||||
QVariantList v = nodeToList(n);
|
||||
if (m_chapters != v) { m_chapters = std::move(v); emit chaptersChanged(); }
|
||||
if( m_chapters != v ) { m_chapters = std::move(v); emit chaptersChanged(); }
|
||||
break;
|
||||
}
|
||||
|
||||
case PROP_CHAPTER: {
|
||||
if (!p->data) break;
|
||||
if( !p->data ) break;
|
||||
qint64 v = *static_cast<qint64*>(p->data);
|
||||
int vi = (v < 0) ? -1 : int(v);
|
||||
if (m_currentChapter != vi) { m_currentChapter = vi; emit currentChapterChanged(); }
|
||||
if( m_currentChapter != vi ) { m_currentChapter = vi; emit currentChapterChanged(); }
|
||||
break;
|
||||
}
|
||||
|
||||
case PROP_CHAPTER_META: {
|
||||
if (!p->data) {
|
||||
if (!m_chapterMetadata.isEmpty()) { m_chapterMetadata.clear(); emit chapterMetadataChanged(); }
|
||||
if( !p->data ) {
|
||||
if( !m_chapterMetadata.isEmpty() ) { m_chapterMetadata.clear(); emit chapterMetadataChanged(); }
|
||||
break;
|
||||
}
|
||||
const mpv_node &n = *static_cast<mpv_node*>(p->data);
|
||||
QVariantMap v = nodeToMap(n);
|
||||
if (m_chapterMetadata != v) { m_chapterMetadata = std::move(v); emit chapterMetadataChanged(); }
|
||||
if( m_chapterMetadata != v ) { m_chapterMetadata = std::move(v); emit chapterMetadataChanged(); }
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -277,49 +267,54 @@ void MpvAudio::handleEvent(mpv_event *ev) {
|
|||
}
|
||||
|
||||
void MpvAudio::setPropBool(const char *name, bool v) {
|
||||
if (!m_mpv) return;
|
||||
if( !m_mpv ) return;
|
||||
int flag = v ? 1 : 0;
|
||||
if (mpv_set_property(m_mpv, name, MPV_FORMAT_FLAG, &flag) < 0)
|
||||
emit errorOccurred(QStringLiteral("Failed to set %1").arg(QString::fromLatin1(name)));
|
||||
if( mpv_set_property(m_mpv, name, MPV_FORMAT_FLAG, &flag) < 0 )
|
||||
emit errorOccurred(QStringLiteral("MpvAudio::setPropBool: Failed to set %1").arg(QString::fromLatin1(name)));
|
||||
}
|
||||
|
||||
void MpvAudio::setPropDouble(const char *name, double v) {
|
||||
if (!m_mpv) return;
|
||||
if (mpv_set_property(m_mpv, name, MPV_FORMAT_DOUBLE, &v) < 0)
|
||||
emit errorOccurred(QStringLiteral("Failed to set %1").arg(QString::fromLatin1(name)));
|
||||
if( !m_mpv ) return;
|
||||
if( mpv_set_property(m_mpv, name, MPV_FORMAT_DOUBLE, &v) < 0 )
|
||||
emit errorOccurred(QStringLiteral("MpvAudio::setPropDouble: Failed to set %1").arg(QString::fromLatin1(name)));
|
||||
}
|
||||
|
||||
void MpvAudio::setPropInt64(const char *name, qint64 v) {
|
||||
if (!m_mpv) return;
|
||||
if (mpv_set_property(m_mpv, name, MPV_FORMAT_INT64, &v) < 0)
|
||||
emit errorOccurred(QStringLiteral("Failed to set %1").arg(QString::fromLatin1(name)));
|
||||
if( !m_mpv ) return;
|
||||
if( mpv_set_property(m_mpv, name, MPV_FORMAT_INT64, &v) < 0 )
|
||||
emit errorOccurred(QStringLiteral("MpvAudio::setPropInt64: Failed to set %1").arg(QString::fromLatin1(name)));
|
||||
}
|
||||
|
||||
// === node conversion ===
|
||||
|
||||
QVariant MpvAudio::nodeToVariant(const mpv_node &n) {
|
||||
switch (n.format) {
|
||||
case MPV_FORMAT_STRING: return n.u.string ? QString::fromUtf8(n.u.string) : QVariant();
|
||||
case MPV_FORMAT_FLAG: return bool(n.u.flag);
|
||||
case MPV_FORMAT_INT64: return qint64(n.u.int64);
|
||||
case MPV_FORMAT_DOUBLE: return double(n.u.double_);
|
||||
case MPV_FORMAT_NODE_MAP: return nodeToMap(n);
|
||||
case MPV_FORMAT_NODE_ARRAY:return nodeToList(n);
|
||||
case MPV_FORMAT_STRING: return n.u.string ? QString::fromUtf8(n.u.string) : QVariant();
|
||||
case MPV_FORMAT_FLAG: return bool(n.u.flag);
|
||||
case MPV_FORMAT_INT64: return qint64(n.u.int64);
|
||||
case MPV_FORMAT_DOUBLE: return double(n.u.double_);
|
||||
case MPV_FORMAT_NODE_MAP: return nodeToMap(n);
|
||||
case MPV_FORMAT_NODE_ARRAY: return nodeToList(n);
|
||||
case MPV_FORMAT_NONE:
|
||||
default: return QVariant();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariantMap MpvAudio::nodeToMap(const mpv_node &n) {
|
||||
QVariantMap out;
|
||||
if (n.format != MPV_FORMAT_NODE_MAP) return out;
|
||||
if( MPV_FORMAT_NODE_MAP != n.format )
|
||||
return out;
|
||||
|
||||
const mpv_node_list *lst = n.u.list;
|
||||
if (!lst) return out;
|
||||
if( !lst )
|
||||
return out;
|
||||
|
||||
for (int i = 0; i < lst->num; ++i) {
|
||||
for( int i=0; i < lst->num; i++ ) {
|
||||
const char *k = lst->keys ? lst->keys[i] : nullptr;
|
||||
if (!k) continue;
|
||||
if( !k )
|
||||
continue;
|
||||
out.insert(QString::fromUtf8(k), nodeToVariant(lst->values[i]));
|
||||
}
|
||||
return out;
|
||||
|
|
@ -327,13 +322,15 @@ QVariantMap MpvAudio::nodeToMap(const mpv_node &n) {
|
|||
|
||||
QVariantList MpvAudio::nodeToList(const mpv_node &n) {
|
||||
QVariantList out;
|
||||
if (n.format != MPV_FORMAT_NODE_ARRAY) return out;
|
||||
if( MPV_FORMAT_NODE_ARRAY != n.format )
|
||||
return out;
|
||||
|
||||
const mpv_node_list *lst = n.u.list;
|
||||
if (!lst) return out;
|
||||
if( !lst )
|
||||
return out;
|
||||
|
||||
out.reserve(lst->num);
|
||||
for (int i = 0; i < lst->num; ++i)
|
||||
for( int i=0; i < lst->num; i++ )
|
||||
out.push_back(nodeToVariant(lst->values[i]));
|
||||
return out;
|
||||
}
|
||||
|
|
@ -341,15 +338,19 @@ QVariantList MpvAudio::nodeToList(const mpv_node &n) {
|
|||
/*** Controls ***/
|
||||
|
||||
void MpvAudio::load(const QUrl &url) {
|
||||
if (!m_mpv) return;
|
||||
if( !m_mpv ) return;
|
||||
|
||||
const QString s = url.isLocalFile() ? url.toLocalFile() : url.toString();
|
||||
if (s.isEmpty()) { emit errorOccurred(QStringLiteral("Empty URL")); return; }
|
||||
if( s.isEmpty() ) {
|
||||
emit errorOccurred(QStringLiteral("Empty URL"));
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray u8 = s.toUtf8();
|
||||
const char *cmd[] = { "loadfile", u8.constData(), "replace", nullptr };
|
||||
int r = mpv_command(m_mpv, cmd);
|
||||
if (r < 0) emit errorOccurred(QStringLiteral("loadfile failed: %1").arg(QString::fromUtf8(mpv_error_string(r))));
|
||||
if( r < 0 )
|
||||
emit errorOccurred(QStringLiteral("MpvAudio::load failed: %1").arg(QString::fromUtf8(mpv_error_string(r))));
|
||||
|
||||
//setPaused(false);
|
||||
m_source = url;
|
||||
|
|
@ -361,18 +362,21 @@ void MpvAudio::pause() { setPaused(true); }
|
|||
void MpvAudio::togglePause() { setPaused(!m_paused); }
|
||||
|
||||
void MpvAudio::stop() {
|
||||
if (!m_mpv) return;
|
||||
if( !m_mpv ) return;
|
||||
|
||||
const char *cmd[] = { "stop", nullptr };
|
||||
mpv_command(m_mpv, cmd);
|
||||
}
|
||||
|
||||
void MpvAudio::seek(double seconds, bool absolute) {
|
||||
if (!m_mpv) return;
|
||||
if( !m_mpv ) return;
|
||||
|
||||
QByteArray t = QByteArray::number(seconds, 'f', 3);
|
||||
const char *mode = absolute ? "absolute" : "relative";
|
||||
const char *cmd[] = { "seek", t.constData(), mode, nullptr };
|
||||
int r = mpv_command(m_mpv, cmd);
|
||||
if (r < 0) emit errorOccurred(QStringLiteral("seek failed: %1").arg(QString::fromUtf8(mpv_error_string(r))));
|
||||
if( r < 0 )
|
||||
emit errorOccurred(QStringLiteral("seek failed: %1").arg(QString::fromUtf8(mpv_error_string(r))));
|
||||
}
|
||||
|
||||
void MpvAudio::seekBy(double deltaSeconds) { seek(deltaSeconds, false); }
|
||||
|
|
@ -383,26 +387,32 @@ void MpvAudio::setLoop(bool enabled) {
|
|||
}
|
||||
|
||||
void MpvAudio::setPaused(bool v) {
|
||||
if (m_paused == v) return;
|
||||
if( m_paused == v )
|
||||
return;
|
||||
|
||||
setPropBool("pause", v);
|
||||
}
|
||||
|
||||
void MpvAudio::setPosition(double seconds) { seek(seconds, true); }
|
||||
|
||||
void MpvAudio::setSpeed(double v) {
|
||||
if (v < 0.25) v = 0.25;
|
||||
if (v > 4.0) v = 4.0;
|
||||
if( v < 0.25 ) v = 0.25;
|
||||
if( v > 4.0 ) v = 4.0;
|
||||
|
||||
setPropDouble("speed", v);
|
||||
}
|
||||
|
||||
void MpvAudio::setVolume(double v) {
|
||||
if (v < 0.0) v = 0.0;
|
||||
if (v > 130.0) v = 130.0;
|
||||
if( v < 0.0 ) v = 0.0;
|
||||
if( v > 130.0 ) v = 130.0;
|
||||
|
||||
setPropDouble("volume", v);
|
||||
}
|
||||
|
||||
void MpvAudio::setCurrentChapter(int idx) {
|
||||
if (idx < -1) idx = -1;
|
||||
if( idx < -1 )
|
||||
idx = -1;
|
||||
|
||||
setPropInt64("chapter", idx);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QVariant>
|
||||
#include <QVariantMap>
|
||||
#include <QVariantList>
|
||||
#include <QSocketNotifier>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
Screen::Screen(QObject *parent)
|
||||
|
|
@ -10,10 +14,10 @@ Screen::Screen(QObject *parent)
|
|||
|
||||
void Screen::setInhibited(bool on, const QString &reason)
|
||||
{
|
||||
if(on == m_inhibited)
|
||||
if( on == m_inhibited )
|
||||
return;
|
||||
|
||||
if(on)
|
||||
if( on )
|
||||
enableInhibit(reason);
|
||||
else
|
||||
disableInhibit();
|
||||
|
|
@ -22,10 +26,10 @@ void Screen::setInhibited(bool on, const QString &reason)
|
|||
void Screen::enableInhibit(const QString &reason)
|
||||
{
|
||||
// Try org.freedesktop.ScreenSaver first
|
||||
if (tryInhibit("org.freedesktop.ScreenSaver",
|
||||
if( tryInhibit("org.freedesktop.ScreenSaver",
|
||||
"/ScreenSaver",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
reason))
|
||||
reason) )
|
||||
return;
|
||||
|
||||
// Fallback: KDE power management
|
||||
|
|
@ -41,13 +45,11 @@ bool Screen::tryInhibit(const QString &service,
|
|||
const QString &reason)
|
||||
{
|
||||
QDBusInterface iface(service, path, ifaceName, QDBusConnection::sessionBus());
|
||||
if (!iface.isValid())
|
||||
if( !iface.isValid() )
|
||||
return false;
|
||||
|
||||
QDBusReply<uint> reply = iface.call("Inhibit",
|
||||
qApp->applicationName(),
|
||||
reason);
|
||||
if (!reply.isValid())
|
||||
QDBusReply<uint> reply = iface.call("Inhibit", qApp->applicationName(), reason);
|
||||
if( !reply.isValid() )
|
||||
return false;
|
||||
|
||||
m_cookie = reply.value();
|
||||
|
|
@ -60,11 +62,11 @@ bool Screen::tryInhibit(const QString &service,
|
|||
|
||||
void Screen::disableInhibit()
|
||||
{
|
||||
if (!m_inhibited || m_cookie == 0)
|
||||
if( !m_inhibited || m_cookie == 0 )
|
||||
return;
|
||||
|
||||
QDBusInterface iface(m_service, m_path, m_iface, QDBusConnection::sessionBus());
|
||||
if (iface.isValid())
|
||||
if( iface.isValid() )
|
||||
iface.call("UnInhibit", m_cookie);
|
||||
|
||||
m_cookie = 0;
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@
|
|||
#ifndef SCREEN_H
|
||||
#define SCREEN_H
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QObject>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
|
||||
class Screen : public QObject
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,14 +33,12 @@ void AsyncThumbnailResponse::fetch() {
|
|||
QObject::connect(job, &KIO::PreviewJob::gotPreview, this,
|
||||
[this](const KFileItem &, const QPixmap &pixmap) {
|
||||
m_image = pixmap.toImage();
|
||||
//qDebug() << "Done:" << m_image.size();
|
||||
emit finished();
|
||||
});
|
||||
|
||||
QObject::connect(job, &KIO::PreviewJob::failed, this,
|
||||
[this](const KFileItem &item) {
|
||||
qDebug() << QStringLiteral("Failed to load thumbnail for %1").arg(item.url().toString());
|
||||
//m_error = QStringLiteral("Failed to load thumbnail for %1").arg(item.url().toString());
|
||||
qWarning() << QStringLiteral("ThumbnailProvider: Failed to load thumbnail for %1").arg(item.url().toString());
|
||||
emit finished();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue