diff --git a/src/audiomanager.cpp b/src/audiomanager.cpp index 7bc68c95..8bff3c19 100644 --- a/src/audiomanager.cpp +++ b/src/audiomanager.cpp @@ -64,6 +64,7 @@ AudioManager::AudioManager(QObject *parent) connect(&d->m_player, &QMediaPlayer::positionChanged, this, &AudioManager::positionChanged); connect(this, &AudioManager::positionChanged, this, &AudioManager::savePlayPosition); + connect(this, &AudioManager::playbackRateChanged, &DataManager::instance(), &DataManager::playbackRateChanged); connect(&DataManager::instance(), &DataManager::queueEntryMoved, this, &AudioManager::canGoNextChanged); connect(&DataManager::instance(), &DataManager::queueEntryAdded, this, &AudioManager::canGoNextChanged); connect(&DataManager::instance(), &DataManager::queueEntryRemoved, this, &AudioManager::canGoNextChanged); @@ -586,7 +587,13 @@ QString AudioManager::formattedDuration() const QString AudioManager::formattedLeftDuration() const { - return m_kformat.formatDuration(duration() - position()); + qreal rate = 1.0; + if (SettingsManager::self()->adjustTimeLeft()) { + rate = playbackRate(); + rate = (rate > 0.0) ? rate : 1.0; + } + qint64 diff = duration() - position(); + return m_kformat.formatDuration(diff / rate); } QString AudioManager::formattedPosition() const diff --git a/src/datamanager.h b/src/datamanager.h index d2b71378..b37d41b3 100644 --- a/src/datamanager.h +++ b/src/datamanager.h @@ -91,6 +91,11 @@ Q_SIGNALS: void bulkReadStatusActionFinished(); void bulkNewStatusActionFinished(); + // this will relay the AudioManager::playbackRateChanged signal; this is + // required to avoid a dependency loop on startup + // TODO: find less hackish solution + void playbackRateChanged(); + private: DataManager(); void loadFeed(const QString &feedurl) const; diff --git a/src/enclosure.cpp b/src/enclosure.cpp index f00e7587..716c4826 100644 --- a/src/enclosure.cpp +++ b/src/enclosure.cpp @@ -39,6 +39,7 @@ Enclosure::Enclosure(Entry *entry) : QObject(entry) , m_entry(entry) { + connect(this, &Enclosure::playPositionChanged, this, &Enclosure::leftDurationChanged); connect(this, &Enclosure::statusChanged, &DownloadModel::instance(), &DownloadModel::monitorDownloadStatus); connect(this, &Enclosure::downloadError, &ErrorLogModel::instance(), &ErrorLogModel::monitorErrorMessages); connect(&Fetcher::instance(), &Fetcher::entryUpdated, this, [this](const QString &url, const QString &id) { @@ -47,6 +48,10 @@ Enclosure::Enclosure(Entry *entry) } }); + // we use the relayed signal from AudioManager::playbackRateChanged by + // DataManager; this is required to avoid a dependency loop on startup + connect(&DataManager::instance(), &DataManager::playbackRateChanged, this, &Enclosure::leftDurationChanged); + QSqlQuery query; query.prepare(QStringLiteral("SELECT * FROM Enclosures WHERE id=:id")); query.bindValue(QStringLiteral(":id"), entry->id()); @@ -489,7 +494,13 @@ QString Enclosure::formattedDuration() const QString Enclosure::formattedLeftDuration() const { - return m_kformat.formatDuration(duration() * 1000 - playPosition()); + qreal rate = 1.0; + if (SettingsManager::self()->adjustTimeLeft()) { + rate = AudioManager::instance().playbackRate(); + rate = (rate > 0.0) ? rate : 1.0; + } + qint64 diff = duration() * 1000 - playPosition(); + return m_kformat.formatDuration(diff / rate); } QString Enclosure::formattedPlayPosition() const diff --git a/src/enclosure.h b/src/enclosure.h index 515e4d70..95d88ff7 100644 --- a/src/enclosure.h +++ b/src/enclosure.h @@ -33,7 +33,7 @@ class Enclosure : public QObject Q_PROPERTY(QString path READ path NOTIFY pathChanged) Q_PROPERTY(QString cachedEmbeddedImage READ cachedEmbeddedImage CONSTANT) Q_PROPERTY(qint64 playPosition READ playPosition WRITE setPlayPosition NOTIFY playPositionChanged) - Q_PROPERTY(QString formattedLeftDuration READ formattedLeftDuration NOTIFY playPositionChanged) + Q_PROPERTY(QString formattedLeftDuration READ formattedLeftDuration NOTIFY leftDurationChanged) Q_PROPERTY(QString formattedPlayPosition READ formattedPlayPosition NOTIFY playPositionChanged) Q_PROPERTY(qint64 duration READ duration WRITE setDuration NOTIFY durationChanged) Q_PROPERTY(QString formattedDuration READ formattedDuration NOTIFY durationChanged) @@ -85,6 +85,7 @@ Q_SIGNALS: void downloadProgressChanged(); void cancelDownload(); void playPositionChanged(); + void leftDurationChanged(); void durationChanged(); void sizeChanged(); void sizeOnDiskChanged(); diff --git a/src/models/queuemodel.cpp b/src/models/queuemodel.cpp index b2897fbe..71961f75 100644 --- a/src/models/queuemodel.cpp +++ b/src/models/queuemodel.cpp @@ -14,6 +14,7 @@ #include "datamanager.h" #include "entry.h" #include "models/episodemodel.h" +#include "settingsmanager.h" QueueModel::QueueModel(QObject *parent) : QAbstractListModel(parent) @@ -91,8 +92,13 @@ int QueueModel::timeLeft() const QString QueueModel::formattedTimeLeft() const { + qreal rate = 1.0; + if (SettingsManager::self()->adjustTimeLeft()) { + rate = AudioManager::instance().playbackRate(); + rate = (rate > 0.0) ? rate : 1.0; + } static KFormat format; - return format.formatDuration(timeLeft()); + return format.formatDuration(timeLeft() / rate); } // Hack to get a QItemSelection in QML diff --git a/src/qml/Settings/GeneralSettingsPage.qml b/src/qml/Settings/GeneralSettingsPage.qml index 60792682..4237496a 100644 --- a/src/qml/Settings/GeneralSettingsPage.qml +++ b/src/qml/Settings/GeneralSettingsPage.qml @@ -41,6 +41,12 @@ Kirigami.ScrollablePage { text: i18n("Continue playing next episode after current one finishes") onToggled: SettingsManager.continuePlayingNextEntry = checked } + Controls.CheckBox { + id: adjustTimeLeft + checked: SettingsManager.adjustTimeLeft + text: i18n("Adjust time left based on current playback speed") + onToggled: SettingsManager.adjustTimeLeft = checked + } Kirigami.Heading { Kirigami.FormData.isSection: true diff --git a/src/settingsmanager.kcfg b/src/settingsmanager.kcfg index 7dfc47d4..52e3afc3 100644 --- a/src/settingsmanager.kcfg +++ b/src/settingsmanager.kcfg @@ -13,6 +13,10 @@ true + + + false + false