8#include "udisksopticaldisc.h"
15#include <QSharedMemory>
16#include <QSystemSemaphore>
17#include <QThreadStorage>
19#include "soliddefs_p.h"
21#include "udisks_debug.h"
33 unsigned char len_di = 0;
35 unsigned int parent = 0;
43 using Solid::Backends::UDisks2::UDISKS2;
50 lseek(fd, 0x8080, SEEK_CUR);
51 if (
read(fd, &bs, 2) != 2) {
52 qCDebug(UDISKS2,
"Advanced probing on %s failed while reading block size", device_file.
constData());
57 lseek(fd, 2, SEEK_CUR);
58 if (
read(fd, &ts, 2) != 2) {
59 qCDebug(UDISKS2,
"Advanced probing on %s failed while reading path table size", device_file.
constData());
64 lseek(fd, 6, SEEK_CUR);
65 if (
read(fd, &tl, 4) != 4) {
66 qCDebug(UDISKS2,
"Advanced probing on %s failed while reading path table block", device_file.
constData());
71 lseek(fd, bs * tl, SEEK_SET);
76 if (
read(fd, &len_di, 1) != 1) {
77 qCDebug(UDISKS2,
"Advanced probing on %s failed, cannot read more entries", device_file.
constData());
83 lseek(fd, 5, SEEK_CUR);
84 if (
read(fd, &parent, 2) != 2) {
85 qCDebug(UDISKS2,
"Advanced probing on %s failed, couldn't read parent entry", device_file.
constData());
90 if (
read(fd, dirname, len_di) != len_di) {
91 qCDebug(UDISKS2,
"Advanced probing on %s failed, couldn't read the entry name", device_file.
constData());
99 if (!strcasecmp(dirname,
"VIDEO_TS")) {
100 qCDebug(UDISKS2,
"Disc in %s is a Video DVD", device_file.
constData());
101 result = Solid::OpticalDisc::VideoDvd;
103 }
else if (!strcasecmp(dirname,
"BDMV")) {
104 qCDebug(UDISKS2,
"Disc in %s is a Blu-ray video disc", device_file.
constData());
105 result = Solid::OpticalDisc::VideoBluRay;
107 }
else if (!strcasecmp(dirname,
"VCD")) {
108 qCDebug(UDISKS2,
"Disc in %s is a Video CD", device_file.
constData());
109 result = Solid::OpticalDisc::VideoCd;
111 }
else if (!strcasecmp(dirname,
"SVCD")) {
112 qCDebug(UDISKS2,
"Disc in %s is a Super Video CD", device_file.
constData());
113 result = Solid::OpticalDisc::SuperVideoCd;
120 if (len_di % 2 == 1) {
121 lseek(fd, 1, SEEK_CUR);
135 lseek(fd, 0, SEEK_SET);
140using namespace Solid::Backends::UDisks2;
142class ContentTypesCache
153 m_n = qMin(m_n + 1,
sizeof(m_info) /
sizeof(*m_info));
154 moveToFront(m_n - 1);
157 front().second = content;
160 bool find(
const OpticalDisc::Identity &key)
162 for (
size_t i = 0; i < m_n; i++) {
163 if (m_info[i].first == key) {
171 QPair<OpticalDisc::Identity, Solid::OpticalDisc::ContentTypes> &front()
177 void moveToFront(
size_t i)
180 qSwap(m_info[i - 1], m_info[i]);
186 QPair<OpticalDisc::Identity, Solid::OpticalDisc::ContentTypes> m_info[100];
189class SharedContentTypesCache
192 ContentTypesCache *m_pointer;
193 QSystemSemaphore m_semaphore;
194 QSharedMemory m_shmem;
198 Unlocker(QSharedMemory *mem)
206 Unlocker(
const Unlocker &) =
delete;
207 Unlocker &operator=(
const Unlocker &) =
delete;
210 QSharedMemory *m_mem;
215 Releaser(QSystemSemaphore *sem)
223 Releaser(
const Releaser &) =
delete;
224 Releaser &operator=(
const Releaser &) =
delete;
227 QSystemSemaphore *m_sem;
230 static QString getKey()
232 static const QString keyTemplate(QStringLiteral(
"solid-disk-info-1-%1-%2"));
233 static const QString tableSize(
QString::number(
sizeof(ContentTypesCache)));
239 SharedContentTypesCache()
241 , m_semaphore(getKey() + QStringLiteral(
"sem"), 1)
242 , m_shmem(getKey() + QStringLiteral(
"mem"))
244 if (!m_semaphore.acquire()) {
247 Releaser releaser(&m_semaphore);
249 if (m_shmem.attach()) {
250 m_pointer = reinterpret_cast<ContentTypesCache *>(m_shmem.data());
254 if (!m_shmem.create(
sizeof(ContentTypesCache))) {
258 if (!m_shmem.lock()) {
262 Unlocker unlocker(&m_shmem);
264 m_pointer =
new (m_shmem.data()) ContentTypesCache;
270 return advancedDiscDetect(file);
273 if (!m_semaphore.acquire()) {
274 return advancedDiscDetect(file);
276 Releaser releaser(&m_semaphore);
278 if (!m_shmem.lock()) {
279 return advancedDiscDetect(file);
281 Unlocker unlocker(&m_shmem);
283 if (!m_pointer->find(info)) {
284 m_pointer->add(info, advancedDiscDetect(file));
291 ~SharedContentTypesCache()
293 m_semaphore.acquire();
294 Releaser releaser(&m_semaphore);
301OpticalDisc::Identity::Identity()
308OpticalDisc::Identity::Identity(
const Device &device,
const Device &drive)
309 : m_detectTime(drive.prop(QStringLiteral(
"TimeMediaDetected")).toLongLong())
310 , m_size(device.prop(QStringLiteral(
"Size")).toLongLong())
311 , m_labelHash(
qHash(device.prop(QStringLiteral(
"IdLabel")).
toString()))
315bool OpticalDisc::Identity::operator==(
const OpticalDisc::Identity &b)
const
318 return m_detectTime == b.m_detectTime
319 && m_size == b.m_size
320 && m_labelHash == b.m_labelHash;
324OpticalDisc::OpticalDisc(Device *dev)
328 UdevQt::Client client(
this);
329 m_udevDevice = client.deviceByDeviceFile(device());
331 m_udevDevice.deviceProperties();
334 m_drive =
new Device(m_device->drivePath());
337OpticalDisc::~OpticalDisc()
342qulonglong OpticalDisc::capacity()
const
344 return m_device->prop(QStringLiteral(
"Size")).toULongLong();
347bool OpticalDisc::isRewritable()
const
350 const QString mediaType = media();
352 return mediaType == QLatin1String(
"optical_cd_rw")
353 || mediaType == QLatin1String(
"optical_dvd_rw")
354 || mediaType == QLatin1String(
"optical_dvd_ram")
355 || mediaType == QLatin1String(
"optical_dvd_plus_rw")
356 || mediaType == QLatin1String(
"optical_dvd_plus_rw_dl")
357 || mediaType == QLatin1String(
"optical_bd_re")
358 || mediaType == QLatin1String(
"optical_hddvd_rw");
362bool OpticalDisc::isBlank()
const
364 return m_drive->prop(QStringLiteral(
"OpticalBlank")).toBool();
367bool OpticalDisc::isAppendable()
const
371 return m_udevDevice.deviceProperty(QStringLiteral(
"ID_CDROM_MEDIA_STATE")).toString() == QLatin1String(
"appendable");
372#elif defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
373 return m_device->prop(QStringLiteral(
"bsdisks_IsAppendable")).toBool();
375#error Implement this or stub this out for your platform
381 const QMap<Solid::OpticalDisc::DiscType, QString>
map{
382 {Solid::OpticalDisc::CdRom, QStringLiteral(
"optical_cd")},
383 {Solid::OpticalDisc::CdRecordable, QStringLiteral(
"optical_cd_r")},
384 {Solid::OpticalDisc::CdRewritable, QStringLiteral(
"optical_cd_rw")},
385 {Solid::OpticalDisc::DvdRom, QStringLiteral(
"optical_dvd")},
386 {Solid::OpticalDisc::DvdRecordable, QStringLiteral(
"optical_dvd_r")},
387 {Solid::OpticalDisc::DvdRewritable, QStringLiteral(
"optical_dvd_rw")},
388 {Solid::OpticalDisc::DvdRam, QStringLiteral(
"optical_dvd_ram")},
389 {Solid::OpticalDisc::DvdPlusRecordable, QStringLiteral(
"optical_dvd_plus_r")},
390 {Solid::OpticalDisc::DvdPlusRewritable, QStringLiteral(
"optical_dvd_plus_rw")},
391 {Solid::OpticalDisc::DvdPlusRecordableDuallayer, QStringLiteral(
"optical_dvd_plus_r_dl")},
392 {Solid::OpticalDisc::DvdPlusRewritableDuallayer, QStringLiteral(
"optical_dvd_plus_rw_dl")},
393 {Solid::OpticalDisc::BluRayRom, QStringLiteral(
"optical_bd")},
394 {Solid::OpticalDisc::BluRayRecordable, QStringLiteral(
"optical_bd_r")},
395 {Solid::OpticalDisc::BluRayRewritable, QStringLiteral(
"optical_bd_re")},
396 {Solid::OpticalDisc::HdDvdRom, QStringLiteral(
"optical_hddvd")},
397 {Solid::OpticalDisc::HdDvdRecordable, QStringLiteral(
"optical_hddvd_r")},
398 {Solid::OpticalDisc::HdDvdRewritable, QStringLiteral(
"optical_hddvd_rw")},
405 return map.key(media(), Solid::OpticalDisc::UnknownDiscType);
411 return Solid::OpticalDisc::NoContent;
415 const bool hasData = m_drive->prop(QStringLiteral(
"OpticalNumDataTracks")).toUInt() > 0;
416 const bool hasAudio = m_drive->prop(QStringLiteral(
"OpticalNumAudioTracks")).toUInt() > 0;
419 content |= Solid::OpticalDisc::Data;
421 Identity newIdentity(*m_device, *m_drive);
422 if (!(m_identity == newIdentity)) {
423 QByteArray deviceFile(m_device->prop(QStringLiteral(
"Device")).toByteArray());
424 m_cachedContent = sharedContentTypesCache->localData().getContent(newIdentity, deviceFile);
425 m_identity = newIdentity;
428 content |= m_cachedContent;
431 content |= Solid::OpticalDisc::Audio;
437QString OpticalDisc::media()
const
439 return m_drive->prop(QStringLiteral(
"Media")).toString();
442#include "moc_udisksopticaldisc.cpp"
QFlags< ContentType > ContentTypes
Stores a combination of ContentType values.
DiscType
This enum type defines the type of optical disc it can be.
ContentType
This enum type defines the type of content available in an optical disc.
char * toString(const EngineQuery &query)
QVariant read(const QByteArray &data, int versionOverride=0)
QAction * close(const QObject *recvr, const char *slot, QObject *parent)
QAction * open(const QObject *recvr, const char *slot, QObject *parent)
KTEXTEDITOR_EXPORT size_t qHash(KTextEditor::Cursor cursor, size_t seed=0) noexcept
const char * constData() const const
QString number(double n, char format, int precision)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)