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", qPrintable(device_file));
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", qPrintable(device_file));
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", qPrintable(device_file));
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", qPrintable(device_file));
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", qPrintable(device_file));
90 if (
read(fd, dirname, len_di) != len_di) {
91 qCDebug(UDISKS2,
"Advanced probing on %s failed, couldn't read the entry name", qPrintable(device_file));
99 if (!strcasecmp(dirname,
"VIDEO_TS")) {
100 qCDebug(UDISKS2,
"Disc in %s is a Video DVD", qPrintable(device_file));
101 result = Solid::OpticalDisc::VideoDvd;
103 }
else if (!strcasecmp(dirname,
"BDMV")) {
104 qCDebug(UDISKS2,
"Disc in %s is a Blu-ray video disc", qPrintable(device_file));
105 result = Solid::OpticalDisc::VideoBluRay;
107 }
else if (!strcasecmp(dirname,
"VCD")) {
108 qCDebug(UDISKS2,
"Disc in %s is a Video CD", qPrintable(device_file));
109 result = Solid::OpticalDisc::VideoCd;
111 }
else if (!strcasecmp(dirname,
"SVCD")) {
112 qCDebug(UDISKS2,
"Disc in %s is a Super Video CD", qPrintable(device_file));
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(
"solid-disk-info-1-%1-%2");
239 SharedContentTypesCache()
241 , m_semaphore(getKey() +
"sem", 1)
242 , m_shmem(getKey() +
"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(
"TimeMediaDetected").toLongLong())
310 , m_size(device.prop(
"Size").toLongLong())
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
347bool OpticalDisc::isRewritable()
const
350 const QString mediaType = media();
352 return mediaType ==
"optical_cd_rw"
353 || mediaType ==
"optical_dvd_rw"
354 || mediaType ==
"optical_dvd_ram"
355 || mediaType ==
"optical_dvd_plus_rw"
356 || mediaType ==
"optical_dvd_plus_rw_dl"
357 || mediaType ==
"optical_bd_re"
358 || mediaType ==
"optical_hddvd_rw";
362bool OpticalDisc::isBlank()
const
364 return m_drive->prop(
"OpticalBlank").
toBool();
367bool OpticalDisc::isAppendable()
const
371 return m_udevDevice.deviceProperty(
"ID_CDROM_MEDIA_STATE").toString() ==
QLatin1String(
"appendable");
372#elif defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
373 return m_device->prop(
"bsdisks_IsAppendable").
toBool();
375#error Implement this or stub this out for your platform
382 map[Solid::OpticalDisc::CdRom] =
"optical_cd";
383 map[Solid::OpticalDisc::CdRecordable] =
"optical_cd_r";
384 map[Solid::OpticalDisc::CdRewritable] =
"optical_cd_rw";
385 map[Solid::OpticalDisc::DvdRom] =
"optical_dvd";
386 map[Solid::OpticalDisc::DvdRecordable] =
"optical_dvd_r";
387 map[Solid::OpticalDisc::DvdRewritable] =
"optical_dvd_rw";
388 map[Solid::OpticalDisc::DvdRam] =
"optical_dvd_ram";
389 map[Solid::OpticalDisc::DvdPlusRecordable] =
"optical_dvd_plus_r";
390 map[Solid::OpticalDisc::DvdPlusRewritable] =
"optical_dvd_plus_rw";
391 map[Solid::OpticalDisc::DvdPlusRecordableDuallayer] =
"optical_dvd_plus_r_dl";
392 map[Solid::OpticalDisc::DvdPlusRewritableDuallayer] =
"optical_dvd_plus_rw_dl";
393 map[Solid::OpticalDisc::BluRayRom] =
"optical_bd";
394 map[Solid::OpticalDisc::BluRayRecordable] =
"optical_bd_r";
395 map[Solid::OpticalDisc::BluRayRewritable] =
"optical_bd_re";
396 map[Solid::OpticalDisc::HdDvdRom] =
"optical_hddvd";
397 map[Solid::OpticalDisc::HdDvdRecordable] =
"optical_hddvd_r";
398 map[Solid::OpticalDisc::HdDvdRewritable] =
"optical_hddvd_rw";
404 return map.key(media(), Solid::OpticalDisc::UnknownDiscType);
410 return Solid::OpticalDisc::NoContent;
414 const bool hasData = m_drive->prop(
"OpticalNumDataTracks").
toUInt() > 0;
415 const bool hasAudio = m_drive->prop(
"OpticalNumAudioTracks").
toUInt() > 0;
418 content |= Solid::OpticalDisc::Data;
420 Identity newIdentity(*m_device, *m_drive);
421 if (!(m_identity == newIdentity)) {
423 m_cachedContent = sharedContentTypesCache->localData().getContent(newIdentity, deviceFile);
424 m_identity = newIdentity;
427 content |= m_cachedContent;
430 content |= Solid::OpticalDisc::Audio;
436QString OpticalDisc::media()
const
438 return m_drive->prop(
"Media").
toString();
441#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)
QVariant read(const QByteArray &data, int versionOverride=0)
const QList< QKeySequence > & close()
const QList< QKeySequence > & open()
KTEXTEDITOR_EXPORT size_t qHash(KTextEditor::Cursor cursor, size_t seed=0) noexcept
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
QByteArray toByteArray() const const
QString toString() const const
uint toUInt(bool *ok) const const
qulonglong toULongLong(bool *ok) const const