From f35e1b543d7d59909f505f3fb114ceef8d8e5c3c Mon Sep 17 00:00:00 2001 From: Lukas Prediger Date: Sun, 23 Jan 2022 18:07:15 +0200 Subject: [PATCH] Regular progress bar updates for CD ripping. Previously the progress bar of the CD ripping dialog would only update after a track completed, now it gets updated continuously during the ripping process. --- src/ripper/ripcddialog.cpp | 54 +++++++++++++++++++++++--------------- src/ripper/ripcddialog.h | 10 ++++--- src/ripper/ripper.cpp | 26 ++++++------------ src/ripper/ripper.h | 10 +++++-- 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/ripper/ripcddialog.cpp b/src/ripper/ripcddialog.cpp index 48e8d0d67..e7cfbdfe0 100644 --- a/src/ripper/ripcddialog.cpp +++ b/src/ripper/ripcddialog.cpp @@ -55,6 +55,7 @@ const int kTrackFilenamePreviewColumn = 4; const char* RipCDDialog::kSettingsGroup = "Transcoder"; const int RipCDDialog::kMaxDestinationItems = 10; +const int RipCDDialog::kTranscodingProgressIntervalMs = 500; RipCDDialog::RipCDDialog(DeviceManager* device_manager, QWidget* parent) : QDialog(parent), @@ -63,7 +64,8 @@ RipCDDialog::RipCDDialog(DeviceManager* device_manager, QWidget* parent) cdda_devices_( device_manager->FindDevicesByUrlSchemes(CddaDevice::url_schemes())), working_(false), - cdda_device_() { + cdda_device_(), + transcoding_progress_timer_(this) { Q_ASSERT(device_manager); // Init ui_->setupUi(this); @@ -211,15 +213,24 @@ void RipCDDialog::ClickedRipButton() { // create and connect Ripper instance for this task Ripper* ripper = new Ripper(cdda_device_->song_count(), this); + if (!ripper) { + qLog(Error) << "Could not create Ripper instance"; + return; + } + connect(cancel_button_, SIGNAL(clicked()), ripper, SLOT(Cancel())); - connect(ripper, &Ripper::Finished, this, - [this, ripper]() { this->Finished(ripper); }); - connect(ripper, &Ripper::Cancelled, this, - [this, ripper]() { this->Cancelled(ripper); }); - connect(ripper, SIGNAL(ProgressInterval(int, int)), - SLOT(SetupProgressBarLimits(int, int))); - connect(ripper, SIGNAL(Progress(int)), SLOT(UpdateProgressBar(int))); + connect(ripper, &Ripper::Finished, this, [this, ripper]() { + this->Finished(*ripper, /*progress_to_display = */ 1.0f); + }); + connect(ripper, &Ripper::Cancelled, this, [this, ripper]() { + this->Finished(*ripper, /*progress_to_display = */ 0.0f); + }); + + ui_->progress_bar->setRange(0, 100); + transcoding_progress_timer_connection_ = + connect(&transcoding_progress_timer_, &QTimer::timeout, this, + [this, ripper]() { this->TranscodingProgressTimeout(*ripper); }); // Add tracks and album information to the ripper. ripper->ClearTracks(); @@ -243,6 +254,7 @@ void RipCDDialog::ClickedRipButton() { SetWorking(true); ripper->Start(); + transcoding_progress_timer_.start(kTranscodingProgressIntervalMs); // store settings QSettings s; @@ -343,21 +355,13 @@ void RipCDDialog::DeviceSelected(int device_index) { SLOT(SongsLoaded(SongList))); } -void RipCDDialog::Finished(Ripper* ripper) { +void RipCDDialog::Finished(Ripper& ripper, float progress_to_display) { SetWorking(false); - ripper->deleteLater(); -} + ripper.deleteLater(); + transcoding_progress_timer_.stop(); + disconnect(transcoding_progress_timer_connection_); -void RipCDDialog::Cancelled(Ripper* ripper) { - ui_->progress_bar->setValue(0); - Finished(ripper); -} - -void RipCDDialog::SetupProgressBarLimits(int min, int max) { - ui_->progress_bar->setRange(min, max); -} - -void RipCDDialog::UpdateProgressBar(int progress) { + int progress = qBound(0, static_cast(progress_to_display * 100.0f), 100); ui_->progress_bar->setValue(progress); } @@ -530,3 +534,11 @@ void RipCDDialog::UpdateMetadataFromGUI() { } UpdateFileNamePreviews(); } + +void RipCDDialog::TranscodingProgressTimeout(Ripper& ripper) { + if (working_) { + int progress = + qBound(0, static_cast(ripper.GetProgress() * 100.0f), 100); + ui_->progress_bar->setValue(progress); + } +} diff --git a/src/ripper/ripcddialog.h b/src/ripper/ripcddialog.h index 6ced2e438..e5b32af7a 100644 --- a/src/ripper/ripcddialog.h +++ b/src/ripper/ripcddialog.h @@ -20,6 +20,7 @@ #define SRC_RIPPER_RIPCDDIALOG_H_ #include +#include #include #include "core/song.h" @@ -55,10 +56,7 @@ class RipCDDialog : public QDialog { void SelectNone(); void InvertSelection(); void DeviceSelected(int device_index); - void Finished(Ripper* ripper); - void Cancelled(Ripper* ripper); - void SetupProgressBarLimits(int min, int max); - void UpdateProgressBar(int progress); + void Finished(Ripper& ripper, float progress_to_display); void SongsLoaded(const SongList& songs); void DiscChanged(); void FormatStringUpdated(); @@ -67,10 +65,12 @@ class RipCDDialog : public QDialog { void YearEditChanged(const QString& year_string); void UpdateMetadataEdits(); void UpdateMetadataFromGUI(); + void TranscodingProgressTimeout(Ripper& ripper); private: static const char* kSettingsGroup; static const int kMaxDestinationItems; + static const int kTranscodingProgressIntervalMs; void AddDestinationDirectory(QString dir); void SetWorking(bool working); @@ -90,5 +90,7 @@ class RipCDDialog : public QDialog { bool working_; std::shared_ptr cdda_device_; SongList songs_; + QTimer transcoding_progress_timer_; + QMetaObject::Connection transcoding_progress_timer_connection_; }; #endif // SRC_RIPPER_RIPCDDIALOG_H_ diff --git a/src/ripper/ripper.cpp b/src/ripper/ripper.cpp index 8f0b6d4c7..b07ffa99a 100644 --- a/src/ripper/ripper.cpp +++ b/src/ripper/ripper.cpp @@ -95,7 +95,6 @@ void Ripper::Start() { QMutexLocker l(&mutex_); cancel_requested_ = false; } - SetupProgressInterval(); qLog(Debug) << "Ripping" << AddedTracks() << "tracks."; QtConcurrent::run(this, &Ripper::Rip); @@ -116,7 +115,6 @@ void Ripper::TranscodingJobComplete(const QUrl& input, const QString& output, finished_success_++; else finished_failed_++; - UpdateProgress(); // The transcoder does not necessarily overwrite files. If not, it changes // the name of the output file. We need to update the transcoded @@ -145,9 +143,6 @@ void Ripper::Rip() { finished_success_ = 0; finished_failed_ = 0; - // Set up progress bar - UpdateProgress(); - for (QList::iterator it = tracks_.begin(); it != tracks_.end(); ++it) { QUrl track_url = @@ -158,20 +153,15 @@ void Ripper::Rip() { emit RippingComplete(); } -// The progress interval is [0, 100*AddedTracks()]. -void Ripper::SetupProgressInterval() { - int max = AddedTracks() * 100; - emit ProgressInterval(0, max); -} +float Ripper::GetProgress() const { + float progress = finished_success_ + finished_failed_; + QList current_job_progress_ = transcoder_->GetProgress().values(); + progress += std::accumulate(current_job_progress_.begin(), + current_job_progress_.end(), 0.0f); + progress /= AddedTracks(); -void Ripper::UpdateProgress() { - int progress = (finished_success_ + finished_failed_) * 100; - QMap current_jobs = transcoder_->GetProgress(); - for (float value : current_jobs.values()) { - progress += qBound(0, static_cast(value * 100), 99); - } - emit Progress(progress); - qLog(Debug) << "Progress:" << progress; + qLog(Debug) << "Progress: " << progress; + return progress; } void Ripper::TagFiles() { diff --git a/src/ripper/ripper.h b/src/ripper/ripper.h index e03a1f91b..1aa5d9262 100644 --- a/src/ripper/ripper.h +++ b/src/ripper/ripper.h @@ -22,6 +22,7 @@ #include #include +#include #include "core/song.h" #include "core/tagreaderclient.h" @@ -60,12 +61,17 @@ class Ripper : public QObject { int AddedTracks() const; // Clears the rip list. void ClearTracks(); + // Returns the current progress of the ripping process for all tracks as a + // floating point number between 0 and 1. + float GetProgress() const; signals: + // Emitted when the full process, i.e., ripping, transcoding and tagging, is + // completed or has failed. void Finished(); void Cancelled(); - void ProgressInterval(int min, int max); - void Progress(int progress); + // Emitted when ripping and transcoding files is completed, but files still + // need to be tagged. void RippingComplete(); public slots: