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;
206 Unlocker(
const Unlocker &) =
delete;
207 Unlocker &operator=(
const Unlocker &) =
delete;
223 Releaser(
const Releaser &) =
delete;
224 Releaser &operator=(
const Releaser &) =
delete;
232 static const QString keyTemplate(QStringLiteral(
"solid-disk-info-1-%1-%2"));
239 SharedContentTypesCache()
241 , m_semaphore(getKey() + QStringLiteral(
"sem"), 1)
242 , m_shmem(getKey() + QStringLiteral(
"mem"))
247 Releaser releaser(&m_semaphore);
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);
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()
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();
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
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"
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)
KCALENDARCORE_EXPORT size_t qHash(const KCalendarCore::Period &key, size_t seed=0)
QVariant read(const QByteArray &data, int versionOverride=0)
const char * constData() const const
bool attach(AccessMode mode)
bool create(qsizetype size, AccessMode mode)
QString number(double n, char format, int precision)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
bool toBool() const const
QString toString() const const
uint toUInt(bool *ok) const const
qulonglong toULongLong(bool *ok) const const