Make player robust against having no track loaded at end of queue

This commit is contained in:
Bart De Vries 2021-04-14 11:32:57 +02:00
parent 8c1295372a
commit a624040ef3
5 changed files with 74 additions and 39 deletions

View File

@ -163,25 +163,25 @@ QMediaPlayer::MediaStatus AudioManager::status() const
void AudioManager::setEntry(Entry* entry)
{
if (entry != nullptr) {
d->m_lockPositionSaving = true;
// First check if the previous track needs to be marked as read
// TODO: make grace time a setting in SettingsManager
if (d->m_entry) {
qDebug() << "Checking previous track";
qDebug() << "Left time" << (duration()-position());
qDebug() << "MediaStatus" << d->m_player.mediaStatus();
if (( (duration()-position()) < 15000)
|| (d->m_player.mediaStatus() == QMediaPlayer::EndOfMedia) ) {
qDebug() << "Mark as read:" << d->m_entry->title();
d->m_entry->setRead(true);
d->m_entry->enclosure()->setPlayPosition(0);
DataManager::instance().removeQueueItem(d->m_entry); //TODO: put this behind setting
}
d->m_lockPositionSaving = true;
// First check if the previous track needs to be marked as read
// TODO: make grace time a setting in SettingsManager
if (d->m_entry) {
qDebug() << "Checking previous track";
qDebug() << "Left time" << (duration()-position());
qDebug() << "MediaStatus" << d->m_player.mediaStatus();
if (( (duration()-position()) < 15000)
|| (d->m_player.mediaStatus() == QMediaPlayer::EndOfMedia) ) {
qDebug() << "Mark as read:" << d->m_entry->title();
d->m_entry->setRead(true);
d->m_entry->enclosure()->setPlayPosition(0);
DataManager::instance().removeQueueItem(d->m_entry); //TODO: put this behind setting
}
}
if (entry != nullptr) {
qDebug() << "Going to change source";
d->m_entry = entry;
Q_EMIT entryChanged(entry);
d->m_player.setMedia(QUrl(QStringLiteral("file://")+d->m_entry->enclosure()->path()));
// save the current playing track in the settingsfile for restoring on startup
SettingsManager::self()->setLastPlayingEntry(d->m_entry->id());
@ -218,9 +218,8 @@ void AudioManager::setEntry(Entry* entry)
} qDebug() << "Changing position";
if (startingPosition > 1000) d->m_player.setPosition(startingPosition);
d->m_player.pause();
d->m_lockPositionSaving = false;
d->m_readyToPlay = true;
Q_EMIT entryChanged(entry);
Q_EMIT entryChanged(d->m_entry); // TODO: this is a hack to get MPRIS to show correct duration; should be split off into a separate signal
Q_EMIT canPlayChanged();
Q_EMIT canPauseChanged();
Q_EMIT canSkipForwardChanged();
@ -229,7 +228,12 @@ void AudioManager::setEntry(Entry* entry)
d->m_isSeekable = true;
Q_EMIT seekableChanged(true);
} else {
SettingsManager::self()->setLastPlayingEntry(QStringLiteral("none"));
d->m_entry = nullptr;
Q_EMIT entryChanged(nullptr);
d->m_readyToPlay = false;
Q_EMIT durationChanged(0);
Q_EMIT positionChanged(0);
Q_EMIT canPlayChanged();
Q_EMIT canPauseChanged();
Q_EMIT canSkipForwardChanged();
@ -238,6 +242,8 @@ void AudioManager::setEntry(Entry* entry)
d->m_isSeekable = false;
Q_EMIT seekableChanged(false);
}
// Unlock the position saving lock
d->m_lockPositionSaving = false;
}
void AudioManager::setPlayerOpen(bool state)
@ -339,14 +345,17 @@ void AudioManager::skipBackward()
bool AudioManager::canGoNext() const
{
// TODO: extend with streaming capability
int index = DataManager::instance().getQueue().indexOf(d->m_entry->id());
if (index >= 0) {
// check if there is a next track
if (index < DataManager::instance().getQueue().count()-1) {
Entry* next_entry = DataManager::instance().getEntry(DataManager::instance().getQueue()[index+1]);
if (next_entry->enclosure()) {
if (next_entry->enclosure()->status() == Enclosure::Downloaded) {
return true;
if (d->m_entry) {
int index = DataManager::instance().getQueue().indexOf(d->m_entry->id());
if (index >= 0) {
// check if there is a next track
if (index < DataManager::instance().getQueue().count()-1) {
Entry* next_entry = DataManager::instance().getEntry(DataManager::instance().getQueue()[index+1]);
if (next_entry->enclosure()) {
qDebug() << "Enclosure status" << next_entry->enclosure()->path() << next_entry->enclosure()->status();
if (next_entry->enclosure()->status() == Enclosure::Downloaded) {
return true;
}
}
}
}
@ -356,12 +365,14 @@ bool AudioManager::canGoNext() const
void AudioManager::next()
{
QMediaPlayer::State currentState = playbackState();
int index = DataManager::instance().getQueue().indexOf(d->m_entry->id());
if (canGoNext()) {
QMediaPlayer::State previousTrackState = playbackState();
int index = DataManager::instance().getQueue().indexOf(d->m_entry->id());
qDebug() << "Skipping to" << DataManager::instance().getQueue()[index+1];
setEntry(DataManager::instance().getEntry(DataManager::instance().getQueue()[index+1]));
if (currentState == QMediaPlayer::PlayingState) play();
if (previousTrackState == QMediaPlayer::PlayingState) play();
} else {
qDebug() << "Next track cannot be played, changing entry to nullptr";
setEntry(nullptr);
}
}
@ -413,7 +424,12 @@ void AudioManager::playerMutedChanged()
void AudioManager::savePlayPosition(qint64 position)
{
if (!d->m_lockPositionSaving)
d->m_entry->enclosure()->setPlayPosition(position);
if (!d->m_lockPositionSaving) {
if (d->m_entry) {
if (d->m_entry->enclosure()) {
d->m_entry->enclosure()->setPlayPosition(position);
}
}
}
qDebug() << d->m_player.mediaStatus();
}

View File

@ -81,6 +81,18 @@ class AudioManager : public QObject
READ seekable
NOTIFY seekableChanged)
Q_PROPERTY(bool canPlay
READ canPlay
NOTIFY canPlayChanged)
Q_PROPERTY(bool canSkipForward
READ canSkipForward
NOTIFY canSkipForwardChanged)
Q_PROPERTY(bool canSkipBackward
READ canSkipBackward
NOTIFY canSkipBackwardChanged)
Q_PROPERTY(bool canGoNext
READ canGoNext
NOTIFY canGoNextChanged)

View File

@ -323,6 +323,9 @@ void MediaPlayer2Player::playerCanSeekChanged()
void MediaPlayer2Player::setEntry(Entry* entry)
{
if (entry == nullptr)
return;
if (m_audioPlayer) {
if (m_audioPlayer->entry()) {
if (m_audioPlayer->entry() == entry) {

View File

@ -16,7 +16,7 @@ import org.kde.alligator 1.0
Kirigami.Page {
id: playercontrols
title: audio.entry.title
title: audio.entry ? audio.entry.title : "No track loaded"
clip: true
Layout.margins: 0
@ -38,7 +38,7 @@ Kirigami.Page {
Image {
id: coverImage
asynchronous: true
source: audio.entry.image === "" ? "logo.png" : "file://"+Fetcher.image(audio.entry.image)
source: audio.entry ? (audio.entry.image === "" ? "logo.png" : "file://"+Fetcher.image(audio.entry.image)) : ""
fillMode: Image.PreserveAspectFit
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
@ -54,13 +54,13 @@ Kirigami.Page {
anchors.right: parent.right
anchors.topMargin: parent.textMargin
Controls.Label {
text: audio.entry.title
text: audio.entry ? audio.entry.title : "No title"
elide: Text.ElideRight
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: parent.width
}
Controls.Label {
text: audio.entry.feed.name
text: audio.entry ? audio.entry.feed.name : "No feed"
elide: Text.ElideRight
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: parent.width
@ -78,9 +78,9 @@ Kirigami.Page {
Controls.Label {
width: parent.width
id: text
text: audio.entry.content
text: audio.entry ? audio.entry.content : "No track loaded"
verticalAlignment: Text.AlignTop
baseUrl: audio.entry.baseUrl
baseUrl: audio.entry ? audio.entry.baseUrl : ""
textFormat: Text.RichText
wrapMode: Text.WordWrap
onLinkActivated: Qt.openUrlExternally(link)
@ -112,6 +112,7 @@ Kirigami.Page {
anchors.right: parent.right
Controls.Slider {
enabled: audio.entry
Layout.fillWidth: true
from: 0
to: audio.duration
@ -175,6 +176,7 @@ Kirigami.Page {
flat: true
Layout.alignment: Qt.AlignHCenter
onClicked: audio.skipBackward()
enabled: audio.canSkipBackward
}
Controls.Button {
id: playButton
@ -184,6 +186,7 @@ Kirigami.Page {
flat: true
onClicked: audio.playbackState === Audio.PlayingState ? audio.pause() : audio.play()
Layout.alignment: Qt.AlignHCenter
enabled: audio.canPlay
}
Controls.Button {
icon.name: "media-seek-forward"
@ -192,6 +195,7 @@ Kirigami.Page {
flat: true
Layout.alignment: Qt.AlignHCenter
onClicked: audio.skipForward()
enabled: audio.canSkipForward
}
Controls.Button {
icon.name: "media-skip-forward"

View File

@ -110,8 +110,8 @@ Kirigami.ApplicationWindow {
}
footer: Loader {
active: (audio.entry != undefined) && !audio.playerOpen
visible: (audio.entry != undefined) && !audio.playerOpen
active: (audio.entry) && !audio.playerOpen
visible: (audio.entry) && !audio.playerOpen
sourceComponent: MinimizedPlayerControls { }
}