From 6eebc7fe816ec23c8a5061ddf07dd8a319c8487a Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Thu, 15 Aug 2024 00:21:20 +0800 Subject: [PATCH] playback: support 'replay' mode --- player/player.cpp | 9 ++++++--- player/player.h | 3 +++ widget/mainwindow.cpp | 29 +++++++++++++++++++++++++++++ widget/mainwindow.h | 16 ++++++++++++++++ widget/mainwindow.ui | 11 +++++++++-- 5 files changed, 63 insertions(+), 5 deletions(-) diff --git a/player/player.cpp b/player/player.cpp index ad02b31..5c5c3e0 100644 --- a/player/player.cpp +++ b/player/player.cpp @@ -22,6 +22,7 @@ QDebug& operator<<(QDebug& out, const std::string& str) Player::Player(QObject *parent) : QObject{parent} , m_isPlaying(false) + , m_restartAfterFinished(false) { Pa_Initialize(); setupAndStartStream(); @@ -92,9 +93,11 @@ int Player::streamCallback(const void *inputBuffer, void *outputBuffer, unsigned // api like get_current_order() will return as it rewinded to the beginning of the song // but read() will still return 0 frame and won't write to the buffer... seek(0); - m_isPlaying = false; - emit playbackStatusChanged(); - emit endOfSongReached(); + if (!m_restartAfterFinished) { + m_isPlaying = false; + emit playbackStatusChanged(); + emit endOfSongReached(); + } } } else { std::fill(buffer, buffer + numFrames * 2, 0); diff --git a/player/player.h b/player/player.h index 842c3ea..f57e670 100644 --- a/player/player.h +++ b/player/player.h @@ -41,6 +41,7 @@ class Player : public QObject Q_PROPERTY(int repeatCount READ repeatCount WRITE setRepeatCount NOTIFY repeatCountChanged) Q_PROPERTY(int gain READ gain WRITE setGain NOTIFY gainChanged) Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY playbackStatusChanged) + Q_PROPERTY(bool restartAfterFinished MEMBER m_restartAfterFinished NOTIFY restartAfterFinishedChanged) Q_INVOKABLE bool load(const QUrl &filename); Q_INVOKABLE void play(); @@ -91,6 +92,7 @@ class Player : public QObject void playbackStatusChanged(); // can be emitted even if it's not changed void repeatCountChanged(); void gainChanged(); + void restartAfterFinishedChanged(); private: void updateCachedState(); @@ -103,5 +105,6 @@ class Player : public QObject CachedPlaybackState m_cachedState; PlaybackOptions m_options; bool m_isPlaying; + bool m_restartAfterFinished; }; diff --git a/widget/mainwindow.cpp b/widget/mainwindow.cpp index ea9ca1e..b6e191f 100644 --- a/widget/mainwindow.cpp +++ b/widget/mainwindow.cpp @@ -90,6 +90,25 @@ MainWindow::MainWindow(QWidget *parent) ui->muteButton->setIcon(QIcon::fromTheme(iconText)); }); + connect(this, &MainWindow::repeatModeChanged, this, [this](RepeatMode mode){ + switch (mode) { + case DisableRepeat: + m_player->setRepeatCount(1); + m_player->setProperty("restartAfterFinished", false); + ui->playbackModeButton->setText("Single"); + break; + case Repeat: + m_player->setRepeatCount(0); + ui->playbackModeButton->setText("Repeat"); + break; + case Replay: + m_player->setRepeatCount(1); + m_player->setProperty("restartAfterFinished", true); + ui->playbackModeButton->setText("Replay"); + break; + } + }); + connect(ui->playbackSlider, &QSlider::valueChanged, this, [this](int value){ m_player->seek(ui->playbackSlider->value()); QToolTip::showText(QCursor::pos(), QString::number(value), nullptr); @@ -222,3 +241,13 @@ void MainWindow::on_muteButton_clicked() m_player->setGain(isMuted ? ui->volumeSlider->value() : std::numeric_limits::min()); } + +void MainWindow::on_playbackModeButton_clicked() +{ + RepeatMode targetMode = FirstRepeatMode; + if (m_repeatMode != LastRepeatMode) { + targetMode = static_cast(m_repeatMode + 1); + } + setProperty("repeatMode", targetMode); +} + diff --git a/widget/mainwindow.h b/widget/mainwindow.h index 6656cd8..332a4ed 100644 --- a/widget/mainwindow.h +++ b/widget/mainwindow.h @@ -17,6 +17,17 @@ class MainWindow : public QMainWindow Q_OBJECT public: + enum RepeatMode { + DisableRepeat, + Repeat, + Replay, + FirstRepeatMode = DisableRepeat, + LastRepeatMode = Replay, + }; + Q_ENUM(RepeatMode) + + Q_PROPERTY(RepeatMode repeatMode MEMBER m_repeatMode NOTIFY repeatModeChanged) + MainWindow(QWidget *parent = nullptr); ~MainWindow(); @@ -26,6 +37,9 @@ class MainWindow : public QMainWindow void dragEnterEvent(QDragEnterEvent *event) override; void dropEvent(QDropEvent *event) override; +signals: + void repeatModeChanged(RepeatMode mode); + private slots: void on_instrumentsBtn_clicked(); void on_messageBtn_clicked(); @@ -34,6 +48,7 @@ private slots: void on_actionAbout_triggered(); void on_filterEdit_textChanged(const QString &arg1); void on_muteButton_clicked(); + void on_playbackModeButton_clicked(); private: Ui::MainWindow *ui; @@ -41,4 +56,5 @@ private slots: PlaylistManager * m_playlistManager = nullptr; InstrumentsModel * m_instrumentsModel = nullptr; QSortFilterProxyModel * m_playlistFilderModel = nullptr; + RepeatMode m_repeatMode = Repeat; }; diff --git a/widget/mainwindow.ui b/widget/mainwindow.ui index f4eaf51..1ab057d 100644 --- a/widget/mainwindow.ui +++ b/widget/mainwindow.ui @@ -40,7 +40,7 @@ - + @@ -48,6 +48,13 @@ + + + + Repeat + + + @@ -256,7 +263,7 @@ 0 0 600 - 24 + 20