Ui improvements

This commit is contained in:
Carl Philipp Klemm 2026-03-04 19:53:04 +01:00
parent 5fcb6a4149
commit 56660fe0b5
4 changed files with 122 additions and 7 deletions

View file

@ -4,7 +4,8 @@
AudioPlayer::AudioPlayer(QObject *parent) AudioPlayer::AudioPlayer(QObject *parent)
: QObject(parent), : QObject(parent),
mediaPlayer(new QMediaPlayer(this)), mediaPlayer(new QMediaPlayer(this)),
audioOutput(new QAudioOutput(this)) audioOutput(new QAudioOutput(this)),
positionTimer(new QTimer(this))
{ {
// Set up audio output with default device // Set up audio output with default device
mediaPlayer->setAudioOutput(audioOutput); mediaPlayer->setAudioOutput(audioOutput);
@ -13,6 +14,14 @@ AudioPlayer::AudioPlayer(QObject *parent)
this, &AudioPlayer::handlePlaybackStateChanged); this, &AudioPlayer::handlePlaybackStateChanged);
connect(mediaPlayer, &QMediaPlayer::mediaStatusChanged, connect(mediaPlayer, &QMediaPlayer::mediaStatusChanged,
this, &AudioPlayer::handleMediaStatusChanged); this, &AudioPlayer::handleMediaStatusChanged);
// Set up position timer for updating playback position
positionTimer->setInterval(500); // Update every 500ms
connect(positionTimer, &QTimer::timeout, [this]() {
if (isPlaying()) {
emit positionChanged(mediaPlayer->position());
}
});
} }
AudioPlayer::~AudioPlayer() AudioPlayer::~AudioPlayer()
@ -28,11 +37,36 @@ void AudioPlayer::play(const QString &filePath)
mediaPlayer->setSource(QUrl::fromLocalFile(filePath)); mediaPlayer->setSource(QUrl::fromLocalFile(filePath));
mediaPlayer->play(); mediaPlayer->play();
// Start position timer
positionTimer->start();
}
void AudioPlayer::play()
{
if (!isPlaying()) {
mediaPlayer->play();
positionTimer->start();
}
}
void AudioPlayer::pause()
{
if (isPlaying()) {
mediaPlayer->pause();
positionTimer->stop();
}
}
void AudioPlayer::setPosition(int position)
{
mediaPlayer->setPosition(position);
} }
void AudioPlayer::stop() void AudioPlayer::stop()
{ {
mediaPlayer->stop(); mediaPlayer->stop();
positionTimer->stop();
} }
bool AudioPlayer::isPlaying() const bool AudioPlayer::isPlaying() const
@ -69,7 +103,11 @@ void AudioPlayer::handleMediaStatusChanged(QMediaPlayer::MediaStatus status)
emit playbackFinished(); emit playbackFinished();
} else if (status == QMediaPlayer::LoadedMedia || } else if (status == QMediaPlayer::LoadedMedia ||
status == QMediaPlayer::BufferedMedia) { status == QMediaPlayer::BufferedMedia) {
// Media loaded successfully // Media loaded successfully, emit duration
int duration = mediaPlayer->duration();
if (duration > 0) {
emit durationChanged(duration);
}
} else if (status == QMediaPlayer::InvalidMedia) { } else if (status == QMediaPlayer::InvalidMedia) {
emit playbackError(mediaPlayer->errorString()); emit playbackError(mediaPlayer->errorString());
} }

View file

@ -8,6 +8,7 @@
#include <QString> #include <QString>
#include <QMediaDevices> #include <QMediaDevices>
#include <QAudioDevice> #include <QAudioDevice>
#include <QTimer>
class AudioPlayer : public QObject class AudioPlayer : public QObject
{ {
@ -17,7 +18,10 @@ public:
~AudioPlayer(); ~AudioPlayer();
void play(const QString &filePath); void play(const QString &filePath);
void play();
void stop(); void stop();
void pause();
void setPosition(int position);
bool isPlaying() const; bool isPlaying() const;
int duration() const; int duration() const;
int position() const; int position() const;
@ -26,6 +30,8 @@ signals:
void playbackStarted(); void playbackStarted();
void playbackFinished(); void playbackFinished();
void playbackError(const QString &error); void playbackError(const QString &error);
void positionChanged(int position);
void durationChanged(int duration);
private slots: private slots:
void handlePlaybackStateChanged(QMediaPlayer::PlaybackState state); void handlePlaybackStateChanged(QMediaPlayer::PlaybackState state);
@ -34,6 +40,7 @@ private slots:
private: private:
QMediaPlayer *mediaPlayer; QMediaPlayer *mediaPlayer;
QAudioOutput *audioOutput; QAudioOutput *audioOutput;
QTimer *positionTimer;
}; };
#endif // AUDIOPLAYER_H #endif // AUDIOPLAYER_H

View file

@ -22,6 +22,7 @@ MainWindow::MainWindow(QWidget *parent)
playbackTimer(new QTimer(this)), playbackTimer(new QTimer(this)),
currentSongIndex(-1), currentSongIndex(-1),
isPlaying(false), isPlaying(false),
isPaused(false),
shuffleMode(false) shuffleMode(false)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -111,11 +112,42 @@ void MainWindow::saveSettings()
settings.setValue("vaeModelPath", vaeModelPath); settings.setValue("vaeModelPath", vaeModelPath);
} }
QString MainWindow::formatTime(int milliseconds)
{
if (milliseconds < 0) return "0:00";
int seconds = milliseconds / 1000;
int minutes = seconds / 60;
seconds = seconds % 60;
return QString("%1:%2").arg(minutes).arg(seconds, 2, 10, QChar('0'));
}
void MainWindow::updatePosition(int position)
{
if (position < 0) return;
// Update slider and time labels
ui->positionSlider->setValue(position);
ui->elapsedTimeLabel->setText(formatTime(position));
}
void MainWindow::updateDuration(int duration)
{
if (duration <= 0) return;
// Set slider range and update duration label
ui->positionSlider->setRange(0, duration);
ui->durationLabel->setText(formatTime(duration));
}
void MainWindow::updateControls() void MainWindow::updateControls()
{ {
bool hasSongs = songModel->rowCount() > 0; bool hasSongs = songModel->rowCount() > 0;
ui->playButton->setEnabled(hasSongs && !isPlaying); // Play button is enabled when not playing, or can be used to resume when paused
ui->playButton->setEnabled(hasSongs && (!isPlaying || isPaused));
ui->pauseButton->setEnabled(isPlaying && !isPaused);
ui->skipButton->setEnabled(isPlaying); ui->skipButton->setEnabled(isPlaying);
ui->stopButton->setEnabled(isPlaying); ui->stopButton->setEnabled(isPlaying);
ui->addSongButton->setEnabled(true); ui->addSongButton->setEnabled(true);
@ -125,9 +157,18 @@ void MainWindow::updateControls()
void MainWindow::on_playButton_clicked() void MainWindow::on_playButton_clicked()
{ {
if (isPaused) {
// Resume playback
audioPlayer->play();
isPaused = false;
updateControls();
return;
}
if (isPlaying) { if (isPlaying) {
audioPlayer->stop(); audioPlayer->stop();
isPlaying = false; isPlaying = false;
isPaused = false;
updateControls(); updateControls();
return; return;
} }
@ -141,11 +182,22 @@ void MainWindow::on_playButton_clicked()
generateAndPlayNext(); generateAndPlayNext();
} }
void MainWindow::on_pauseButton_clicked()
{
if (isPlaying && !isPaused) {
// Pause playback
audioPlayer->pause();
isPaused = true;
updateControls();
}
}
void MainWindow::on_skipButton_clicked() void MainWindow::on_skipButton_clicked()
{ {
if (isPlaying) { if (isPlaying) {
// Stop current playback and move to next song // Stop current playback and move to next song
audioPlayer->stop(); audioPlayer->stop();
isPaused = false;
playNextSong(); playNextSong();
} }
} }
@ -156,11 +208,20 @@ void MainWindow::on_stopButton_clicked()
// Stop current playback completely // Stop current playback completely
audioPlayer->stop(); audioPlayer->stop();
isPlaying = false; isPlaying = false;
isPaused = false;
ui->statusLabel->setText("Stopped"); ui->statusLabel->setText("Stopped");
updateControls(); updateControls();
} }
} }
void MainWindow::on_positionSlider_sliderMoved(int position)
{
if (isPlaying && audioPlayer->isPlaying()) {
// Seek to the new position when slider is moved
audioPlayer->setPosition(position);
}
}
void MainWindow::on_shuffleButton_clicked() void MainWindow::on_shuffleButton_clicked()
{ {
shuffleMode = ui->shuffleButton->isChecked(); shuffleMode = ui->shuffleButton->isChecked();
@ -258,10 +319,6 @@ void MainWindow::on_advancedSettingsButton_clicked()
jsonTemplateEdit->setMinimumHeight(200); jsonTemplateEdit->setMinimumHeight(200);
jsonLayout->addWidget(jsonTemplateEdit); jsonLayout->addWidget(jsonTemplateEdit);
QLabel *fieldsLabel = new QLabel("Available fields: caption, lyrics, instrumental, bpm, duration, keyscale, timesignature,\nvocal_language, seed, lm_temperature, lm_cfg_scale, lm_top_p, lm_top_k, lm_negative_prompt,\naudio_codes, inference_steps, guidance_scale, shift");
fieldsLabel->setWordWrap(true);
jsonLayout->addWidget(fieldsLabel);
tabWidget->addTab(jsonTab, "JSON Template"); tabWidget->addTab(jsonTab, "JSON Template");
// Path Settings tab // Path Settings tab
@ -405,6 +462,10 @@ void MainWindow::songGenerated(const QString &filePath)
// Play the generated song // Play the generated song
audioPlayer->play(filePath); audioPlayer->play(filePath);
// Connect position and duration updates for the slider
connect(audioPlayer, &AudioPlayer::positionChanged, this, &MainWindow::updatePosition);
connect(audioPlayer, &AudioPlayer::durationChanged, this, &MainWindow::updateDuration);
} }
void MainWindow::playNextSong() void MainWindow::playNextSong()
@ -420,6 +481,7 @@ void MainWindow::playNextSong()
} else { } else {
// No more songs // No more songs
isPlaying = false; isPlaying = false;
isPaused = false;
ui->statusLabel->setText("Finished playback"); ui->statusLabel->setText("Finished playback");
updateControls(); updateControls();
} }
@ -453,6 +515,7 @@ void MainWindow::generationError(const QString &error)
dialog.exec(); dialog.exec();
isPlaying = false; isPlaying = false;
isPaused = false;
updateControls(); updateControls();
} }

View file

@ -23,9 +23,13 @@ public:
private slots: private slots:
void on_playButton_clicked(); void on_playButton_clicked();
void on_pauseButton_clicked();
void on_skipButton_clicked(); void on_skipButton_clicked();
void on_stopButton_clicked(); void on_stopButton_clicked();
void on_shuffleButton_clicked(); void on_shuffleButton_clicked();
void on_positionSlider_sliderMoved(int position);
void updatePosition(int position);
void updateDuration(int duration);
void on_addSongButton_clicked(); void on_addSongButton_clicked();
void on_editSongButton_clicked(); void on_editSongButton_clicked();
void on_removeSongButton_clicked(); void on_removeSongButton_clicked();
@ -44,8 +48,11 @@ private:
AceStepWorker *aceStepWorker; AceStepWorker *aceStepWorker;
QTimer *playbackTimer; QTimer *playbackTimer;
QString formatTime(int milliseconds);
int currentSongIndex; int currentSongIndex;
bool isPlaying; bool isPlaying;
bool isPaused;
bool shuffleMode; bool shuffleMode;
QString jsonTemplate; QString jsonTemplate;