Source: https://invent.kde.org/multimedia/audiocd-kio/-/merge_requests/28 From 4f86ae11babd27e8cecddbb8c1e74402eceea0c9 Mon Sep 17 00:00:00 2001 From: Nicolas Fella Date: Thu, 6 Nov 2025 20:32:31 +0100 Subject: [PATCH] Port away from KCompactDisk We don't really need it, we can do everything with cdda_interface and Solid --- .kde-ci.yml | 1 - CMakeLists.txt | 10 +--- audiocd.cpp | 128 ++++++++++++++++++++++++++++--------------------- 3 files changed, 76 insertions(+), 63 deletions(-) diff --git a/.kde-ci.yml b/.kde-ci.yml index ce7482a6..dc9d5ec6 100644 --- a/.kde-ci.yml +++ b/.kde-ci.yml @@ -11,4 +11,3 @@ Dependencies: 'frameworks/kio': '@latest-kf6' 'frameworks/kcmutils': '@latest-kf6' 'multimedia/libkcddb': '@same' - 'multimedia/libkcompactdisc': '@same' diff --git a/CMakeLists.txt b/CMakeLists.txt index c860b65d..1a364b14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,13 +36,7 @@ find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS KIO KCMUtils WidgetsAddons -) -find_package(KCompactDisc6) -set_package_properties(KCompactDisc6 PROPERTIES - DESCRIPTION "KCompactDisc library" - URL "https://commits.kde.org/libkcompactdisc" - TYPE REQUIRED - PURPOSE "libkcompactdisc is used to access CD drives." + Solid ) find_package(KCddb6 5.1) set_package_properties(KCddb6 PROPERTIES @@ -109,8 +103,8 @@ set_target_properties(kio_audiocd PROPERTIES OUTPUT_NAME "audiocd") target_link_libraries(kio_audiocd audiocdplugins - KCompactDisc6 KF6::I18n + KF6::Solid Qt::Widgets Cdparanoia::Cdparanoia ) diff --git a/audiocd.cpp b/audiocd.cpp index 58a28930..a3d1ef74 100644 --- a/audiocd.cpp +++ b/audiocd.cpp @@ -59,9 +59,12 @@ int Q_DECL_EXPORT kdemain(int argc, char **argv); #include #include +#include +#include +#include + // CDDB #include -#include // Pseudo plugin class to embed metadata class KIOPluginForMetaData : public QObject @@ -231,45 +234,6 @@ AudioCDEncoder *AudioCDProtocol::determineEncoder(const QString &filename) return encoderFromExtension(filename.mid(pos)); } -static void setDeviceToCd(KCompactDisc *cd, struct cdrom_drive *drive) -{ -#if defined(HAVE_CDDA_IOCTL_DEVICE) - cd->setDevice(QLatin1String(drive->ioctl_device_name), 50, false); -#elif defined(__FreeBSD__) || defined(__DragonFly__) - // FreeBSD's cdparanoia as of January 5th 2006 has rather broken - // support for non-SCSI devices. Although it finds ATA cdroms just - // fine, there is no straightforward way to discover the device - // name associated with the device, which throws the rest of audiocd - // for a loop. - // - if (!(drive->dev) || (COOKED_IOCTL == drive->interface)) { - // For ATAPI devices, we have no real choice. Use the - // user selected value, even if there is none. - // - qCWarning(AUDIOCD_KIO_LOG) << "Found an ATAPI device, assuming it is the " - "one specified by the user."; - cd->setDevice(QString::fromLatin1(drive->cdda_device_name)); - } else { - qCDebug(AUDIOCD_KIO_LOG) << "Found a SCSI or ATAPICAM device."; - if (strlen(drive->dev->device_path) > 0) { - cd->setDevice(QString::fromLatin1(drive->dev->device_path)); - } else { - // But the device_path can be empty under some - // circumstances, so build a representation from - // the unit number and SCSI device name. - // - QString devname = QStringLiteral("/dev/%1%2").arg(QString::fromLatin1(drive->dev->given_dev_name)).arg(drive->dev->given_unit_number); - qCDebug(AUDIOCD_KIO_LOG) << " Using derived name " << devname; - cd->setDevice(devname); - } - } -#else -#ifdef __GNUC__ -#warning audiocd KIO worker is not going to work for you -#endif -#endif -} - // Initiate a request to access the CD drive. If there is no valid drive // specified or there is a problem, then error() must be (or have been) // called before returning a null pointer. @@ -287,15 +251,19 @@ KIO::WorkerResult AudioCDProtocol::initRequest(const QUrl &url, struct cdrom_dri if (d->tocsAreDifferent(*drive)) { // Update our knowledge of the disc - KCompactDisc cd(KCompactDisc::Asynchronous); - setDeviceToCd(&cd, *drive); d->setToc(*drive); - d->tracks = cd.tracks(); - for (uint i = 0; i < cd.tracks(); i++) - d->trackIsAudio[i] = cd.isAudio(i + 1); + d->tracks = (*drive)->tracks; + + KCDDB::TrackOffsetList signature; + for (uint i = 0; i < d->tracks; i++) { + d->trackIsAudio[i] = IS_AUDIO((*drive), i); + signature << d->disc_toc[i].dwStartSector + 150; + } + + signature << cdda_disc_lastsector(*drive) - cdda_disc_firstsector(*drive) + 1 + 150; KCDDB::Client c; - d->cddbResult = c.lookup(cd.discSignature()); + d->cddbResult = c.lookup(signature); if (d->cddbResult == Success) { d->cddbList = c.lookupResponse(); // FIXME: not always the best choice, see bug 279485 @@ -626,6 +594,59 @@ static void app_file(UDSEntry &e, const QString &n, size_t s, const QString &mim e.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, mimetype); } +struct DeviceListing { + QString device; + QString displayName; +}; + +QList cdromDevices() +{ + QList ret; + + const auto devices = Solid::Device::listFromType(Solid::DeviceInterface::OpticalDrive); + for (const Solid::Device &device : devices) { + qDebug() << device.udi().toLatin1().constData(); + const Solid::Block *b = device.as(); + + if (!b) { + continue; + } + + QString name; + QString type; + + const Solid::OpticalDrive *o = device.as(); + Solid::OpticalDrive::MediumTypes mediumType = o->supportedMedia(); + + // TODO translate them ? + if (mediumType < Solid::OpticalDrive::Cdrw) { + type = QLatin1String("CD-ROM"); + } else if (mediumType < Solid::OpticalDrive::Dvd) { + type = QLatin1String("CDRW"); + } else if (mediumType < Solid::OpticalDrive::Dvdr) { + type = QLatin1String("DVD-ROM"); + } else if (mediumType < Solid::OpticalDrive::Bd) { + type = QLatin1String("DVDRW"); + } else if (mediumType < Solid::OpticalDrive::HdDvd) { + type = QLatin1String("Blu-ray"); + } else { + type = QLatin1String("High Density DVD"); + } + + if (!device.vendor().isEmpty()) + name = (QLatin1Char('[') + type + QLatin1String(" - ") + device.vendor() + QLatin1String(" - ") + device.product() + QLatin1Char(']')); + else + name = (QLatin1Char('[') + type + QLatin1String(" - unknown vendor - ") + device.product() + QLatin1Char(']')); + + ret << DeviceListing{ + b->device(), + name, + }; + } + + return ret; +} + KIO::WorkerResult AudioCDProtocol::stat(const QUrl &url) { const KIO::WorkerResult result = checkNoHost(url); @@ -639,8 +660,8 @@ KIO::WorkerResult AudioCDProtocol::stat(const QUrl &url) UDSEntry entry; // One subdirectory for each drive - const QStringList &deviceNames = KCompactDisc::cdromDeviceNames(); - app_dir(entry, escapePath(QStringLiteral("/")), deviceNames.count()); + const auto devices = cdromDevices(); + app_dir(entry, escapePath(QStringLiteral("/")), devices.count()); statEntry(entry); return KIO::WorkerResult::pass(); } @@ -716,17 +737,16 @@ KIO::WorkerResult AudioCDProtocol::listDir(const QUrl &url) if (whichFromUrl(url) == Base) { // The top level directory with CDROM devices only. - const QStringList deviceNames = KCompactDisc::cdromDeviceNames(); - for (const QString &deviceName : deviceNames) { - const QString &device = KCompactDisc::urlToDevice(KCompactDisc::cdromDeviceUrl(deviceName)); + const auto devices = cdromDevices(); + for (const auto &device : devices) { QUrl targetUrl = url; QUrlQuery targetQuery; - targetQuery.addQueryItem(QStringLiteral("device"), device); + targetQuery.addQueryItem(QStringLiteral("device"), device.device); targetUrl.setQuery(targetQuery); - app_dir(entry, escapePath(device), 2 + encoders.count()); + app_dir(entry, escapePath(device.device), 2 + encoders.count()); entry.fastInsert(KIO::UDSEntry::UDS_TARGET_URL, targetUrl.url()); - entry.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, deviceName); + entry.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, device.displayName); listEntry(entry); } totalSize(entry.count()); -- GitLab