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.
This commit is contained in:
Lukas Prediger 2022-01-23 18:07:15 +02:00 committed by John Maguire
parent 497552aab2
commit f35e1b543d
4 changed files with 55 additions and 45 deletions

View File

@ -55,6 +55,7 @@ const int kTrackFilenamePreviewColumn = 4;
const char* RipCDDialog::kSettingsGroup = "Transcoder"; const char* RipCDDialog::kSettingsGroup = "Transcoder";
const int RipCDDialog::kMaxDestinationItems = 10; const int RipCDDialog::kMaxDestinationItems = 10;
const int RipCDDialog::kTranscodingProgressIntervalMs = 500;
RipCDDialog::RipCDDialog(DeviceManager* device_manager, QWidget* parent) RipCDDialog::RipCDDialog(DeviceManager* device_manager, QWidget* parent)
: QDialog(parent), : QDialog(parent),
@ -63,7 +64,8 @@ RipCDDialog::RipCDDialog(DeviceManager* device_manager, QWidget* parent)
cdda_devices_( cdda_devices_(
device_manager->FindDevicesByUrlSchemes(CddaDevice::url_schemes())), device_manager->FindDevicesByUrlSchemes(CddaDevice::url_schemes())),
working_(false), working_(false),
cdda_device_() { cdda_device_(),
transcoding_progress_timer_(this) {
Q_ASSERT(device_manager); Q_ASSERT(device_manager);
// Init // Init
ui_->setupUi(this); ui_->setupUi(this);
@ -211,15 +213,24 @@ void RipCDDialog::ClickedRipButton() {
// create and connect Ripper instance for this task // create and connect Ripper instance for this task
Ripper* ripper = new Ripper(cdda_device_->song_count(), this); 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(cancel_button_, SIGNAL(clicked()), ripper, SLOT(Cancel()));
connect(ripper, &Ripper::Finished, this, connect(ripper, &Ripper::Finished, this, [this, ripper]() {
[this, ripper]() { this->Finished(ripper); }); this->Finished(*ripper, /*progress_to_display = */ 1.0f);
connect(ripper, &Ripper::Cancelled, this, });
[this, ripper]() { this->Cancelled(ripper); }); connect(ripper, &Ripper::Cancelled, this, [this, ripper]() {
connect(ripper, SIGNAL(ProgressInterval(int, int)), this->Finished(*ripper, /*progress_to_display = */ 0.0f);
SLOT(SetupProgressBarLimits(int, int))); });
connect(ripper, SIGNAL(Progress(int)), SLOT(UpdateProgressBar(int)));
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. // Add tracks and album information to the ripper.
ripper->ClearTracks(); ripper->ClearTracks();
@ -243,6 +254,7 @@ void RipCDDialog::ClickedRipButton() {
SetWorking(true); SetWorking(true);
ripper->Start(); ripper->Start();
transcoding_progress_timer_.start(kTranscodingProgressIntervalMs);
// store settings // store settings
QSettings s; QSettings s;
@ -343,21 +355,13 @@ void RipCDDialog::DeviceSelected(int device_index) {
SLOT(SongsLoaded(SongList))); SLOT(SongsLoaded(SongList)));
} }
void RipCDDialog::Finished(Ripper* ripper) { void RipCDDialog::Finished(Ripper& ripper, float progress_to_display) {
SetWorking(false); SetWorking(false);
ripper->deleteLater(); ripper.deleteLater();
} transcoding_progress_timer_.stop();
disconnect(transcoding_progress_timer_connection_);
void RipCDDialog::Cancelled(Ripper* ripper) { int progress = qBound(0, static_cast<int>(progress_to_display * 100.0f), 100);
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) {
ui_->progress_bar->setValue(progress); ui_->progress_bar->setValue(progress);
} }
@ -530,3 +534,11 @@ void RipCDDialog::UpdateMetadataFromGUI() {
} }
UpdateFileNamePreviews(); UpdateFileNamePreviews();
} }
void RipCDDialog::TranscodingProgressTimeout(Ripper& ripper) {
if (working_) {
int progress =
qBound(0, static_cast<int>(ripper.GetProgress() * 100.0f), 100);
ui_->progress_bar->setValue(progress);
}
}

View File

@ -20,6 +20,7 @@
#define SRC_RIPPER_RIPCDDIALOG_H_ #define SRC_RIPPER_RIPCDDIALOG_H_
#include <QDialog> #include <QDialog>
#include <QTimer>
#include <memory> #include <memory>
#include "core/song.h" #include "core/song.h"
@ -55,10 +56,7 @@ class RipCDDialog : public QDialog {
void SelectNone(); void SelectNone();
void InvertSelection(); void InvertSelection();
void DeviceSelected(int device_index); void DeviceSelected(int device_index);
void Finished(Ripper* ripper); void Finished(Ripper& ripper, float progress_to_display);
void Cancelled(Ripper* ripper);
void SetupProgressBarLimits(int min, int max);
void UpdateProgressBar(int progress);
void SongsLoaded(const SongList& songs); void SongsLoaded(const SongList& songs);
void DiscChanged(); void DiscChanged();
void FormatStringUpdated(); void FormatStringUpdated();
@ -67,10 +65,12 @@ class RipCDDialog : public QDialog {
void YearEditChanged(const QString& year_string); void YearEditChanged(const QString& year_string);
void UpdateMetadataEdits(); void UpdateMetadataEdits();
void UpdateMetadataFromGUI(); void UpdateMetadataFromGUI();
void TranscodingProgressTimeout(Ripper& ripper);
private: private:
static const char* kSettingsGroup; static const char* kSettingsGroup;
static const int kMaxDestinationItems; static const int kMaxDestinationItems;
static const int kTranscodingProgressIntervalMs;
void AddDestinationDirectory(QString dir); void AddDestinationDirectory(QString dir);
void SetWorking(bool working); void SetWorking(bool working);
@ -90,5 +90,7 @@ class RipCDDialog : public QDialog {
bool working_; bool working_;
std::shared_ptr<CddaDevice> cdda_device_; std::shared_ptr<CddaDevice> cdda_device_;
SongList songs_; SongList songs_;
QTimer transcoding_progress_timer_;
QMetaObject::Connection transcoding_progress_timer_connection_;
}; };
#endif // SRC_RIPPER_RIPCDDIALOG_H_ #endif // SRC_RIPPER_RIPCDDIALOG_H_

View File

@ -95,7 +95,6 @@ void Ripper::Start() {
QMutexLocker l(&mutex_); QMutexLocker l(&mutex_);
cancel_requested_ = false; cancel_requested_ = false;
} }
SetupProgressInterval();
qLog(Debug) << "Ripping" << AddedTracks() << "tracks."; qLog(Debug) << "Ripping" << AddedTracks() << "tracks.";
QtConcurrent::run(this, &Ripper::Rip); QtConcurrent::run(this, &Ripper::Rip);
@ -116,7 +115,6 @@ void Ripper::TranscodingJobComplete(const QUrl& input, const QString& output,
finished_success_++; finished_success_++;
else else
finished_failed_++; finished_failed_++;
UpdateProgress();
// The transcoder does not necessarily overwrite files. If not, it changes // The transcoder does not necessarily overwrite files. If not, it changes
// the name of the output file. We need to update the transcoded // the name of the output file. We need to update the transcoded
@ -145,9 +143,6 @@ void Ripper::Rip() {
finished_success_ = 0; finished_success_ = 0;
finished_failed_ = 0; finished_failed_ = 0;
// Set up progress bar
UpdateProgress();
for (QList<TrackInformation>::iterator it = tracks_.begin(); for (QList<TrackInformation>::iterator it = tracks_.begin();
it != tracks_.end(); ++it) { it != tracks_.end(); ++it) {
QUrl track_url = QUrl track_url =
@ -158,20 +153,15 @@ void Ripper::Rip() {
emit RippingComplete(); emit RippingComplete();
} }
// The progress interval is [0, 100*AddedTracks()]. float Ripper::GetProgress() const {
void Ripper::SetupProgressInterval() { float progress = finished_success_ + finished_failed_;
int max = AddedTracks() * 100; QList<float> current_job_progress_ = transcoder_->GetProgress().values();
emit ProgressInterval(0, max); progress += std::accumulate(current_job_progress_.begin(),
} current_job_progress_.end(), 0.0f);
progress /= AddedTracks();
void Ripper::UpdateProgress() { qLog(Debug) << "Progress: " << progress;
int progress = (finished_success_ + finished_failed_) * 100; return progress;
QMap<QUrl, float> current_jobs = transcoder_->GetProgress();
for (float value : current_jobs.values()) {
progress += qBound(0, static_cast<int>(value * 100), 99);
}
emit Progress(progress);
qLog(Debug) << "Progress:" << progress;
} }
void Ripper::TagFiles() { void Ripper::TagFiles() {

View File

@ -22,6 +22,7 @@
#include <QMutex> #include <QMutex>
#include <QObject> #include <QObject>
#include <QTimer>
#include "core/song.h" #include "core/song.h"
#include "core/tagreaderclient.h" #include "core/tagreaderclient.h"
@ -60,12 +61,17 @@ class Ripper : public QObject {
int AddedTracks() const; int AddedTracks() const;
// Clears the rip list. // Clears the rip list.
void ClearTracks(); 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: signals:
// Emitted when the full process, i.e., ripping, transcoding and tagging, is
// completed or has failed.
void Finished(); void Finished();
void Cancelled(); void Cancelled();
void ProgressInterval(int min, int max); // Emitted when ripping and transcoding files is completed, but files still
void Progress(int progress); // need to be tagged.
void RippingComplete(); void RippingComplete();
public slots: public slots: