From 63953e10457e39d622074d6931f41e86e554b5d5 Mon Sep 17 00:00:00 2001 From: Lukas Prediger Date: Tue, 1 Jun 2021 18:51:00 +0300 Subject: [PATCH] RipCDDialog now allows selecting the CD drive --- src/ripper/ripcddialog.cpp | 136 +++++++++++++++++++++++++++++-------- src/ripper/ripcddialog.h | 10 ++- src/ripper/ripcddialog.ui | 127 +++++++++++++++++++++++----------- src/translations/de.po | 4 ++ src/ui/mainwindow.cpp | 30 +------- 5 files changed, 207 insertions(+), 100 deletions(-) diff --git a/src/ripper/ripcddialog.cpp b/src/ripper/ripcddialog.cpp index bc23ad2df..03c532a0e 100644 --- a/src/ripper/ripcddialog.cpp +++ b/src/ripper/ripcddialog.cpp @@ -1,5 +1,6 @@ /* This file is part of Clementine. Copyright 2014, Andre Siviero + Copyright 2021, Lukas Prediger Clementine is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,6 +33,7 @@ #include "core/tagreaderclient.h" #include "devices/cddadevice.h" #include "devices/cddasongloader.h" +#include "devices/devicemanager.h" #include "ripper/ripper.h" #include "transcoder/transcoder.h" #include "transcoder/transcoderoptionsdialog.h" @@ -52,15 +54,15 @@ const int kTrackDurationColumn = 3; const char* RipCDDialog::kSettingsGroup = "Transcoder"; const int RipCDDialog::kMaxDestinationItems = 10; -RipCDDialog::RipCDDialog(std::shared_ptr cdda_device, - QWidget* parent) +RipCDDialog::RipCDDialog(DeviceManager& device_manager, QWidget* parent) : QDialog(parent), ui_(new Ui_RipCDDialog), + device_manager_(device_manager), + cdda_devices_( + device_manager.FindDeviceByUrlSchemes(CddaDevice::url_schemes())), working_(false), - cdda_device_(std::move(cdda_device)), - loader_(cdda_device_->loader()), - ripper_(new Ripper(cdda_device_->raw_cdio(), this)) { - Q_ASSERT(cdda_device_); + cdda_device_(), + loader_(nullptr) { // Init ui_->setupUi(this); @@ -82,30 +84,21 @@ RipCDDialog::RipCDDialog(std::shared_ptr cdda_device, cancel_button_->hide(); ui_->progress_group->hide(); + rip_button_->setEnabled(false); // will be enabled by DeviceSelected if a + // valid device is selected + + InitializeDevices(); + connect(ui_->select_all_button, SIGNAL(clicked()), SLOT(SelectAll())); connect(ui_->select_none_button, SIGNAL(clicked()), SLOT(SelectNone())); connect(ui_->invert_selection_button, SIGNAL(clicked()), SLOT(InvertSelection())); connect(rip_button_, SIGNAL(clicked()), SLOT(ClickedRipButton())); - connect(cancel_button_, SIGNAL(clicked()), ripper_, SLOT(Cancel())); connect(close_button_, SIGNAL(clicked()), SLOT(hide())); connect(ui_->options, SIGNAL(clicked()), SLOT(Options())); connect(ui_->select, SIGNAL(clicked()), SLOT(AddDestination())); - connect(loader_, SIGNAL(SongsDurationLoaded(SongList)), - SLOT(BuildTrackListTable(SongList))); - connect(loader_, SIGNAL(SongsMetadataLoaded(SongList)), - SLOT(UpdateTrackListTable(SongList))); - connect(loader_, SIGNAL(SongsMetadataLoaded(SongList)), - SLOT(AddAlbumMetadataFromMusicBrainz(SongList))); - - connect(ripper_, SIGNAL(Finished()), SLOT(Finished())); - connect(ripper_, SIGNAL(Cancelled()), SLOT(Cancelled())); - connect(ripper_, SIGNAL(ProgressInterval(int, int)), - SLOT(SetupProgressBarLimits(int, int))); - connect(ripper_, SIGNAL(Progress(int)), SLOT(UpdateProgressBar(int))); - setWindowTitle(tr("Rip CD")); AddDestinationDirectory(QDir::homePath()); @@ -131,8 +124,6 @@ RipCDDialog::RipCDDialog(std::shared_ptr cdda_device, break; } } - - connect(cdda_device_.get(), SIGNAL(DiscChanged()), SLOT(DiscChanged())); } RipCDDialog::~RipCDDialog() {} @@ -145,15 +136,56 @@ void RipCDDialog::closeEvent(QCloseEvent* event) { void RipCDDialog::showEvent(QShowEvent* event) { ResetDialog(); - loader_->LoadSongs(); + if (loader_) loader_->LoadSongs(); if (!working_) { ui_->progress_group->hide(); } } +void RipCDDialog::InitializeDevices() { + Q_ASSERT(!cdda_device_); + + // add all devices to drop down selection + for (const DeviceInfo* device_info : cdda_devices_) { + ui_->cd_drive_selection->addItem(device_info->friendly_name_); + } + // ensure that selecting the first device below will emit a + // currentIndexChanged signal + ui_->cd_drive_selection->setCurrentIndex(-1); + + connect(ui_->cd_drive_selection, SIGNAL(currentIndexChanged(int)), + SLOT(DeviceSelected(int))); + + // look for any already connected device, guess that might be the one the user + // is interested in and make it the active selection + for (int i = 0; i < cdda_devices_.size(); ++i) { + DeviceInfo* device_info = cdda_devices_[i]; + if (device_info->device_) { + // found one! + ui_->cd_drive_selection->setCurrentIndex(i); + return; + } + } + + // there is no device that is already connected; just select the first one + if (!cdda_devices_.isEmpty()) ui_->cd_drive_selection->setCurrentIndex(0); +} + void RipCDDialog::ClickedRipButton() { + Q_ASSERT(cdda_device_); + + // create and connect Ripper instance for this task + Ripper* ripper = new Ripper(cdda_device_->raw_cdio(), this); + connect(cancel_button_, SIGNAL(clicked()), ripper, SLOT(Cancel())); + + connect(ripper, SIGNAL(Finished()), SLOT(Finished())); + connect(ripper, SIGNAL(Cancelled()), SLOT(Cancelled())); + connect(ripper, SIGNAL(ProgressInterval(int, int)), + SLOT(SetupProgressBarLimits(int, int))); + connect(ripper, SIGNAL(Progress(int)), SLOT(UpdateProgressBar(int))); + // Add tracks and album information to the ripper. - ripper_->ClearTracks(); + ripper->ClearTracks(); TranscoderPreset preset = ui_->format->itemData(ui_->format->currentIndex()) .value(); for (int i = 1; i <= ui_->tableWidget->rowCount(); ++i) { @@ -163,15 +195,15 @@ void RipCDDialog::ClickedRipButton() { QString transcoded_filename = GetOutputFileName( ParseFileFormatString(ui_->format_filename->text(), i)); QString title = track_names_.value(i - 1)->text(); - ripper_->AddTrack(i, title, transcoded_filename, preset); + ripper->AddTrack(i, title, transcoded_filename, preset); } - ripper_->SetAlbumInformation( + ripper->SetAlbumInformation( ui_->albumLineEdit->text(), ui_->artistLineEdit->text(), ui_->genreLineEdit->text(), ui_->yearLineEdit->text().toInt(), ui_->discLineEdit->text().toInt(), preset.type_); SetWorking(true); - ripper_->Start(); + ripper->Start(); } void RipCDDialog::Options() { @@ -233,11 +265,57 @@ void RipCDDialog::InvertSelection() { } } -void RipCDDialog::Finished() { SetWorking(false); } +void RipCDDialog::DeviceSelected(int device_index) { + // disconnecting from previous loader and device, if any + if (loader_) disconnect(loader_, nullptr, this, nullptr); + if (cdda_device_) disconnect(cdda_device_.get(), nullptr, this, nullptr); + + ResetDialog(); + if (device_index < 0) + return; // Invalid selection, probably no devices around + + Q_ASSERT(device_index < cdda_devices_.size()); + + DeviceInfo* device_info = cdda_devices_[device_index]; + std::shared_ptr device = + device_manager_.Connect(device_info); + cdda_device_ = std::dynamic_pointer_cast(device); + if (!cdda_device_) { + rip_button_->setEnabled(false); + QMessageBox cdio_fail(QMessageBox::Critical, tr("Error"), + tr("Failed reading CD drive")); + cdio_fail.exec(); + return; + } + + connect(cdda_device_.get(), SIGNAL(DiscChanged()), SLOT(DiscChanged())); + + // get SongLoader from device and connect signals + loader_ = cdda_device_->loader(); + Q_ASSERT(loader_); + + connect(loader_, SIGNAL(SongsDurationLoaded(SongList)), + SLOT(BuildTrackListTable(SongList))); + connect(loader_, SIGNAL(SongsMetadataLoaded(SongList)), + SLOT(UpdateTrackListTable(SongList))); + connect(loader_, SIGNAL(SongsMetadataLoaded(SongList)), + SLOT(AddAlbumMetadataFromMusicBrainz(SongList))); + + // load songs from new SongLoader + loader_->LoadSongs(); + rip_button_->setEnabled(true); +} + +void RipCDDialog::Finished() { + SetWorking(false); + Ripper* ripper = dynamic_cast(sender()); + Q_ASSERT(ripper); + ripper->deleteLater(); +} void RipCDDialog::Cancelled() { ui_->progress_bar->setValue(0); - SetWorking(false); + Finished(); } void RipCDDialog::SetupProgressBarLimits(int min, int max) { diff --git a/src/ripper/ripcddialog.h b/src/ripper/ripcddialog.h index 2da0a1ee0..b5577c70a 100644 --- a/src/ripper/ripcddialog.h +++ b/src/ripper/ripcddialog.h @@ -1,5 +1,6 @@ /* This file is part of Clementine. Copyright 2014, Andre Siviero + Copyright 2021, Lukas Prediger Clementine is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,12 +35,14 @@ class CddaSongLoader; class Ripper; class Ui_RipCDDialog; class CddaDevice; +class DeviceManager; +class DeviceInfo; class RipCDDialog : public QDialog { Q_OBJECT public: - explicit RipCDDialog(std::shared_ptr cdda_device, + explicit RipCDDialog(DeviceManager& device_manager, QWidget* parent = nullptr); ~RipCDDialog(); @@ -54,6 +57,7 @@ class RipCDDialog : public QDialog { void SelectAll(); void SelectNone(); void InvertSelection(); + void DeviceSelected(int device_index); void Finished(); void Cancelled(); void SetupProgressBarLimits(int min, int max); @@ -79,6 +83,7 @@ class RipCDDialog : public QDialog { QString ParseFileFormatString(const QString& file_format, int track_no) const; void SetWorking(bool working); void ResetDialog(); + void InitializeDevices(); QList checkboxes_; QList track_names_; @@ -87,9 +92,10 @@ class RipCDDialog : public QDialog { QPushButton* close_button_; QPushButton* rip_button_; std::unique_ptr ui_; + DeviceManager& device_manager_; + QList cdda_devices_; bool working_; std::shared_ptr cdda_device_; CddaSongLoader* loader_; - Ripper* ripper_; }; #endif // SRC_RIPPER_RIPCDDIALOG_H_ diff --git a/src/ripper/ripcddialog.ui b/src/ripper/ripcddialog.ui index 66213f454..e67478c71 100644 --- a/src/ripper/ripcddialog.ui +++ b/src/ripper/ripcddialog.ui @@ -10,14 +10,14 @@ 0 0 522 - 563 + 575 Dialog - + :/icon.png:/icon.png @@ -27,9 +27,90 @@ Input options + + + + QLayout::SetMinimumSize + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + CD Drive + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Select All + + + + + + + Select None + + + + + + + Invert Selection + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + @@ -74,44 +155,6 @@ - - - - - - Select All - - - - - - - Select None - - - - - - - Invert Selection - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - @@ -296,6 +339,8 @@ select button_box - + + + diff --git a/src/translations/de.po b/src/translations/de.po index e0399fa3b..75e26dc9c 100644 --- a/src/translations/de.po +++ b/src/translations/de.po @@ -1129,6 +1129,10 @@ msgstr "Tasten" msgid "CBC Podcasts" msgstr "CBC Podcasts" +#: ../build/src/ui_ripcddialog.h:329 +msgid "CD Drive" +msgstr "CD-Laufwerk" + #: core/song.cpp:453 msgid "CDDA" msgstr "CDDA" diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index a416e4bef..1fe084db9 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -57,9 +57,6 @@ #include "core/taskmanager.h" #include "core/timeconstants.h" #include "core/utilities.h" -#ifdef HAVE_AUDIOCD -#include "devices/cddadevice.h" -#endif #include "devices/devicemanager.h" #include "devices/devicestatefiltermodel.h" #include "devices/deviceview.h" @@ -2223,31 +2220,8 @@ void MainWindow::AddStreamAccepted() { void MainWindow::OpenRipCDDialog() { #ifdef HAVE_AUDIOCD if (!rip_cd_dialog_) { - QList cd_device_infos = - app_->device_manager()->FindDeviceByUrlSchemes( - CddaDevice::url_schemes()); - std::shared_ptr device; - if (!cd_device_infos.isEmpty()) { - DeviceInfo* device_info = - cd_device_infos[0]; // TODO: currently just picking the first cd - // drive; what if there are several? - device = app_->device_manager()->Connect( - device_info); // connect the device; will do nothing if already - // connected - } - - if (!device) { - QMessageBox cdio_fail(QMessageBox::Critical, tr("Error"), - tr("Failed reading CD drive")); - cdio_fail.exec(); - return; - } - - std::shared_ptr cdda_device = - std::dynamic_pointer_cast(device); - Q_ASSERT(cdda_device); // since we are requesting for cdda devices, the - // cast must work; assert it - rip_cd_dialog_.reset(new RipCDDialog(std::move(cdda_device))); + Q_ASSERT(app_->device_manager()); + rip_cd_dialog_ = std::make_unique(*(app_->device_manager())); } rip_cd_dialog_->show(); #endif