diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 126264c09..d4af3219a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -122,6 +122,7 @@ set(SOURCES devices/connecteddevice.cpp devices/devicedatabasebackend.cpp + devices/deviceerror.cpp devices/devicelister.cpp devices/devicemanager.cpp devices/deviceproperties.cpp @@ -458,6 +459,7 @@ set(HEADERS devices/connecteddevice.h devices/devicedatabasebackend.h + devices/deviceerror.h devices/devicelister.h devices/devicemanager.h devices/deviceproperties.h diff --git a/src/devices/cddadevice.cpp b/src/devices/cddadevice.cpp index 4bc08cab2..f270e22b1 100644 --- a/src/devices/cddadevice.cpp +++ b/src/devices/cddadevice.cpp @@ -17,6 +17,7 @@ #include "cddadevice.h" +#include "deviceerror.h" #include "library/librarybackend.h" #include "library/librarymodel.h" @@ -41,7 +42,10 @@ CddaDevice::CddaDevice(const QUrl& url, DeviceLister* lister, SLOT(SongsDiscovered(SongList))); // connect(&cd_device_, SIGNAL(DiscChanged()), SLOT(DiscChangeDetected())); cdio_ = cdio_open(url_.path().toLocal8Bit().constData(), DRIVER_DEVICE); - Q_ASSERT(cdio_); // todo: error handling? + if (!cdio_) { + throw DeviceError(url.toString(), + "Cannot open device: cdio_open returned nullptr"); + } connect(&disc_changed_timer_, SIGNAL(timeout()), SLOT(CheckDiscChanged())); WatchForDiscChanges(watch_for_disc_changes); } diff --git a/src/devices/deviceerror.cpp b/src/devices/deviceerror.cpp new file mode 100644 index 000000000..6da437876 --- /dev/null +++ b/src/devices/deviceerror.cpp @@ -0,0 +1,37 @@ +/* This file is part of Clementine. + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#include "deviceerror.h" + +#include + +std::string DeviceError::CreateExceptionMessage(const QString& device_id, + const QString error_message) { + QString exception_message = + QString("Error accessing device <%1>").arg(device_id); + if (!error_message.isEmpty()) exception_message += ": " + error_message; + + return exception_message.toLocal8Bit().toStdString(); +} + +DeviceError::DeviceError(const QString& device_id, const QString& error_message) + : std::runtime_error(CreateExceptionMessage(device_id, error_message)) {} + +DeviceError::DeviceError(const QString& device_id) + : DeviceError(device_id, "") {} + +DeviceError::~DeviceError() {} diff --git a/src/devices/deviceerror.h b/src/devices/deviceerror.h new file mode 100644 index 000000000..8f94f1a3b --- /dev/null +++ b/src/devices/deviceerror.h @@ -0,0 +1,36 @@ +/* This file is part of Clementine. + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#ifndef DEVICEERROR_H +#define DEVICEERROR_H + +#include + +class QString; + +class DeviceError : public std::runtime_error { + private: + static std::string CreateExceptionMessage(const QString& device_id, + const QString error_message); + + public: + DeviceError(const QString& device_id); + DeviceError(const QString& device_id, const QString& error_message); + virtual ~DeviceError(); +}; + +#endif diff --git a/src/devices/devicemanager.cpp b/src/devices/devicemanager.cpp index ea60d72d1..50d9eedfd 100644 --- a/src/devices/devicemanager.cpp +++ b/src/devices/devicemanager.cpp @@ -37,6 +37,7 @@ #include "core/taskmanager.h" #include "core/utilities.h" #include "devicedatabasebackend.h" +#include "deviceerror.h" #include "deviceinfo.h" #include "devicestatefiltermodel.h" #include "filesystemdevice.h" @@ -347,7 +348,7 @@ DeviceInfo* DeviceManager::FindEquivalentDevice(DeviceInfo* info) const { return nullptr; } -QList DeviceManager::FindDeviceByUrlSchemes( +QList DeviceManager::FindDevicesByUrlSchemes( QStringList url_schemes) const { QList matches; for (DeviceInfo* device_info : devices_) { @@ -565,14 +566,19 @@ std::shared_ptr DeviceManager::Connect(DeviceInfo* info) { return ret; } - QMetaObject meta_object = device_classes_.value(device_url.scheme()); - QObject* instance = meta_object.newInstance( - Q_ARG(QUrl, device_url), - Q_ARG(DeviceLister*, info->BestBackend()->lister_), - Q_ARG(QString, info->BestBackend()->unique_id_), - Q_ARG(DeviceManager*, this), Q_ARG(Application*, app_), - Q_ARG(int, info->database_id_), Q_ARG(bool, first_time)); - ret.reset(static_cast(instance)); + try { + QMetaObject meta_object = device_classes_.value(device_url.scheme()); + QObject* instance = meta_object.newInstance( + Q_ARG(QUrl, device_url), + Q_ARG(DeviceLister*, info->BestBackend()->lister_), + Q_ARG(QString, info->BestBackend()->unique_id_), + Q_ARG(DeviceManager*, this), Q_ARG(Application*, app_), + Q_ARG(int, info->database_id_), Q_ARG(bool, first_time)); + ret.reset(static_cast(instance)); + } catch (const DeviceError& e) { + qLog(Warning) << "Could not create device: " << e.what(); + return ret; + } if (!ret) { qLog(Warning) << "Could not create device for" << device_url.toString(); diff --git a/src/devices/devicemanager.h b/src/devices/devicemanager.h index 89eb43bc8..b4dbd7209 100644 --- a/src/devices/devicemanager.h +++ b/src/devices/devicemanager.h @@ -78,7 +78,7 @@ class DeviceManager : public SimpleTreeModel { DeviceInfo* FindDeviceById(const QString& id) const; DeviceInfo* FindDeviceByUrl(const QList& url) const; DeviceInfo* FindEquivalentDevice(DeviceInfo* info) const; - QList FindDeviceByUrlSchemes(QStringList url_schemes) const; + QList FindDevicesByUrlSchemes(QStringList url_schemes) const; // Actions on devices std::shared_ptr Connect(DeviceInfo* info); diff --git a/src/ripper/ripcddialog.cpp b/src/ripper/ripcddialog.cpp index 0d6ca61ad..7c7d6766d 100644 --- a/src/ripper/ripcddialog.cpp +++ b/src/ripper/ripcddialog.cpp @@ -59,7 +59,7 @@ RipCDDialog::RipCDDialog(DeviceManager& device_manager, QWidget* parent) ui_(new Ui_RipCDDialog), device_manager_(device_manager), cdda_devices_( - device_manager.FindDeviceByUrlSchemes(CddaDevice::url_schemes())), + device_manager.FindDevicesByUrlSchemes(CddaDevice::url_schemes())), working_(false), cdda_device_(), loader_(nullptr) {