Adjust time left on episodes according to current playback rate

This new feature is implemented behind a switch in the settings (default
is off).

FEATURE: 452135
This commit is contained in:
Bart De Vries 2022-05-31 22:10:06 +02:00
parent f717473a8b
commit e62d17f9b0
7 changed files with 44 additions and 4 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -13,6 +13,10 @@
<label>Continue playing next episode after current one finishes</label>
<default>true</default>
</entry>
<entry name="adjustTimeLeft" type="Bool">
<label>Adjust time left based on the current playback speed</label>
<default>false</default>
</entry>
<entry name="refreshOnStartup" type="Bool">
<label>Automatically fetch feed updates on startup</label>
<default>false</default>