Dealing with cdio_open failures in CddaDevice constructor

This commit is contained in:
Lukas Prediger 2021-06-02 19:17:27 +03:00 committed by John Maguire
parent e35e4195c2
commit 2dd566653f
7 changed files with 97 additions and 12 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -0,0 +1,37 @@
/* This file is part of Clementine.
Copyright 2021, Lukas Prediger <lumip@lumip.de>
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 <http://www.gnu.org/licenses/>.
*/
#include "deviceerror.h"
#include <QString>
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() {}

36
src/devices/deviceerror.h Normal file
View File

@ -0,0 +1,36 @@
/* This file is part of Clementine.
Copyright 2021, Lukas Prediger <lumip@lumip.de>
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 <http://www.gnu.org/licenses/>.
*/
#ifndef DEVICEERROR_H
#define DEVICEERROR_H
#include <stdexcept>
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

View File

@ -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<DeviceInfo*> DeviceManager::FindDeviceByUrlSchemes(
QList<DeviceInfo*> DeviceManager::FindDevicesByUrlSchemes(
QStringList url_schemes) const {
QList<DeviceInfo*> matches;
for (DeviceInfo* device_info : devices_) {
@ -565,14 +566,19 @@ std::shared_ptr<ConnectedDevice> 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<ConnectedDevice*>(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<ConnectedDevice*>(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();

View File

@ -78,7 +78,7 @@ class DeviceManager : public SimpleTreeModel<DeviceInfo> {
DeviceInfo* FindDeviceById(const QString& id) const;
DeviceInfo* FindDeviceByUrl(const QList<QUrl>& url) const;
DeviceInfo* FindEquivalentDevice(DeviceInfo* info) const;
QList<DeviceInfo*> FindDeviceByUrlSchemes(QStringList url_schemes) const;
QList<DeviceInfo*> FindDevicesByUrlSchemes(QStringList url_schemes) const;
// Actions on devices
std::shared_ptr<ConnectedDevice> Connect(DeviceInfo* info);

View File

@ -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) {