MythTV  master
mediamonitor-darwin.cpp
Go to the documentation of this file.
1 
8 #include <QDir>
9 #include <QMetaType>
10 
11 #include "libmythbase/mythcdrom.h"
12 #include "libmythbase/mythhdd.h"
14 
15 #include "mediamonitor-darwin.h"
16 #include "mythmediamonitor.h"
17 
18 #include <IOKit/IOKitLib.h>
19 #include <IOKit/storage/IOMedia.h>
20 #include <IOKit/storage/IOCDMedia.h>
21 #include <IOKit/storage/IODVDMedia.h>
22 #include <IOKit/storage/IOBlockStorageDevice.h>
23 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
24 #include <IOKit/storage/IOStorageProtocolCharacteristics.h>
25 #include <DiskArbitration/DiskArbitration.h>
26 
27 
28 // These aren't external, they are defined in this file.
29 // The 'extern "C"' forces them in the C namespace, not the C++
30 extern "C" void diskAppearedCallback(DADiskRef disk, void *context);
31 extern "C" void diskDisappearedCallback(DADiskRef disk, void *context);
32 extern "C" void diskChangedCallback(DADiskRef disk,
33  CFArrayRef keys, void *context);
34 extern "C" MythMediaType MediaTypeForBSDName(const char *bsdName);
35 
36 static mach_port_t sMasterPort;
37 
38 
42 MythMediaType FindMediaType(io_service_t service)
43 {
44  kern_return_t kernResult;
45  io_iterator_t iter;
46  MythMediaType mediaType = MEDIATYPE_UNKNOWN;
47  QString msg = QString("FindMediaType() - ");
48 
49  // Create an iterator across all parents of the service object passed in.
50  kernResult = IORegistryEntryCreateIterator(service,
51  kIOServicePlane,
52  kIORegistryIterateRecursively
53  | kIORegistryIterateParents,
54  &iter);
55 
56  if (KERN_SUCCESS != kernResult)
57  {
58  LOG(VB_GENERAL, LOG_CRIT, msg +
59  QString("IORegistryEntryCreateIterator returned %1")
60  .arg(kernResult));
61  }
62  else if (!iter)
63  {
64  LOG(VB_GENERAL, LOG_CRIT, msg +
65  "IORegistryEntryCreateIterator returned NULL iterator");
66  }
67  else
68  {
69  // A reference on the initial service object is released in
70  // the do-while loop below, so add a reference to balance
71  IOObjectRetain(service);
72 
73  do
74  {
75  bool isWholeMedia = false;
76  if (IOObjectConformsTo(service, kIOMediaClass))
77  {
78  CFTypeRef wholeMedia;
79 
80  wholeMedia = IORegistryEntryCreateCFProperty
81  (service, CFSTR(kIOMediaWholeKey),
82  kCFAllocatorDefault, 0);
83 
84  if (!wholeMedia)
85  {
86  LOG(VB_GENERAL, LOG_ALERT, msg +
87  "Could not retrieve Whole property");
88  }
89  else
90  {
91  isWholeMedia = CFBooleanGetValue((CFBooleanRef)wholeMedia);
92  CFRelease(wholeMedia);
93  }
94  }
95 
96  if (isWholeMedia)
97  {
98  if (IOObjectConformsTo(service, kIODVDMediaClass))
99  mediaType = MEDIATYPE_DVD;
100  else if (IOObjectConformsTo(service, kIOCDMediaClass))
101  mediaType = MEDIATYPE_AUDIO;
102  }
103 
104  IOObjectRelease(service);
105 
106  } while ((service = IOIteratorNext(iter))
107  && (mediaType == MEDIATYPE_UNKNOWN));
108 
109  IOObjectRelease(iter);
110  }
111  return mediaType;
112 }
113 
117 MythMediaType MediaTypeForBSDName(const char *bsdName)
118 {
119  CFMutableDictionaryRef matchingDict;
120  kern_return_t kernResult;
121  io_iterator_t iter;
122  io_service_t service;
123  QString msg = QString("MediaTypeForBSDName(%1)")
124  .arg(bsdName);
125  MythMediaType mediaType;
126 
127 
128  if (!bsdName || !*bsdName)
129  {
130  LOG(VB_GENERAL, LOG_ALERT, msg + " - No name supplied?");
131  return MEDIATYPE_UNKNOWN;
132  }
133 
134  matchingDict = IOBSDNameMatching(sMasterPort, 0, bsdName);
135  if (!matchingDict)
136  {
137  LOG(VB_GENERAL, LOG_ALERT,
138  msg + " - IOBSDNameMatching() returned a NULL dictionary.");
139  return MEDIATYPE_UNKNOWN;
140  }
141 
142  // Return an iterator across all objects with the matching
143  // BSD node name. Note that there should only be one match!
144  kernResult = IOServiceGetMatchingServices(sMasterPort, matchingDict, &iter);
145 
146  if (KERN_SUCCESS != kernResult)
147  {
148  LOG(VB_GENERAL, LOG_ALERT,
149  QString(msg + " - IOServiceGetMatchingServices() returned %2")
150  .arg(kernResult));
151  return MEDIATYPE_UNKNOWN;
152  }
153  if (!iter)
154  {
155  LOG(VB_GENERAL, LOG_ALERT,
156  msg + " - IOServiceGetMatchingServices() returned a NULL "
157  "iterator");
158  return MEDIATYPE_UNKNOWN;
159  }
160 
161  service = IOIteratorNext(iter);
162 
163  // Release this now because we only expect
164  // the iterator to contain a single io_service_t.
165  IOObjectRelease(iter);
166 
167  if (!service)
168  {
169  LOG(VB_GENERAL, LOG_ALERT,
170  msg + " - IOIteratorNext() returned a NULL iterator");
171  return MEDIATYPE_UNKNOWN;
172  }
173  mediaType = FindMediaType(service);
174  IOObjectRelease(service);
175  return mediaType;
176 }
177 
178 
182 static char * getVolName(CFDictionaryRef diskDetails)
183 {
184  CFStringRef name;
185  CFIndex size;
186  char *volName;
187 
188  name = (CFStringRef)
189  CFDictionaryGetValue(diskDetails, kDADiskDescriptionVolumeNameKey);
190 
191  if (!name)
192  return nullptr;
193 
194  size = CFStringGetLength(name) + 1;
195  volName = (char *) malloc(size);
196  if (!volName)
197  {
198  LOG(VB_GENERAL, LOG_ALERT,
199  QString("getVolName() - Can't malloc(%1)?").arg(size));
200  return nullptr;
201  }
202 
203  if (!CFStringGetCString(name, volName, size, kCFStringEncodingUTF8))
204  {
205  free(volName);
206  return nullptr;
207  }
208 
209  return volName;
210 }
211 
212 /*
213  * Given a DA description, return a compound description to help identify it.
214  */
215 static QString getModel(CFDictionaryRef diskDetails)
216 {
217  QString desc;
218  const void *strRef;
219 
220  // Location
221  if (kCFBooleanTrue ==
222  CFDictionaryGetValue(diskDetails,
223  kDADiskDescriptionDeviceInternalKey))
224  desc.append("Internal ");
225 
226  // Manufacturer
227  strRef = CFDictionaryGetValue(diskDetails,
228  kDADiskDescriptionDeviceVendorKey);
229  if (strRef)
230  {
231  desc.append(CFStringGetCStringPtr((CFStringRef)strRef,
232  kCFStringEncodingMacRoman));
233  desc.append(' ');
234  }
235 
236  // Product
237  strRef = CFDictionaryGetValue(diskDetails,
238  kDADiskDescriptionDeviceModelKey);
239  if (strRef)
240  {
241  desc.append(CFStringGetCStringPtr((CFStringRef)strRef,
242  kCFStringEncodingMacRoman));
243  desc.append(' ');
244  }
245 
246  // Remove the trailing space
247  desc.truncate(desc.length() - 1);
248 
249  // and multiple spaces
250  desc.remove(" ");
251 
252  return desc;
253 }
254 
255 
256 /*
257  * Callbacks which the Disk Arbitration session invokes
258  * whenever a disk comes or goes, or is renamed
259  */
260 
261 void diskAppearedCallback(DADiskRef disk, void *context)
262 {
263  const char *BSDname = DADiskGetBSDName(disk);
264  CFDictionaryRef details;
265  bool isCDorDVD;
266  MythMediaType mediaType;
267  QString model;
268  MonitorThreadDarwin *mtd;
269  QString msg = "diskAppearedCallback() - ";
270  char *volName;
271 
272 
273  if (!BSDname)
274  {
275  LOG(VB_MEDIA, LOG_INFO, msg + "Skipping non-local device");
276  return;
277  }
278 
279  if (!context)
280  {
281  LOG(VB_GENERAL, LOG_ALERT, msg + "Error. Invoked with a NULL context.");
282  return;
283  }
284 
285  mtd = reinterpret_cast<MonitorThreadDarwin*>(context);
286 
287 
288  // We want to monitor CDs/DVDs and USB cameras or flash drives,
289  // but probably not hard disk or network drives. For now, ignore
290  // any disk or partitions that are not on removable media.
291  // Seems OK for hot-plug USB/FireWire disks (i.e. they are removable)
292 
293  details = DADiskCopyDescription(disk);
294 
295  if (kCFBooleanFalse ==
296  CFDictionaryGetValue(details, kDADiskDescriptionMediaRemovableKey))
297  {
298  LOG(VB_MEDIA, LOG_INFO, msg + QString("Skipping non-removable %1")
299  .arg(BSDname));
300  CFRelease(details);
301  return;
302  }
303 
304  // Get the volume and model name for more user-friendly interaction
305  volName = getVolName(details);
306  if (!volName)
307  {
308  LOG(VB_MEDIA, LOG_INFO, msg + QString("No volume name for dev %1")
309  .arg(BSDname));
310  CFRelease(details);
311  return;
312  }
313 
314  model = getModel(details);
315 
316  if (model.contains("Disk Image"))
317  {
318  LOG(VB_MEDIA, LOG_INFO, msg + QString("DMG %1 mounted, ignoring")
319  .arg(BSDname));
320  CFRelease(details);
321  free(volName);
322  return;
323  }
324 
325  mediaType = MediaTypeForBSDName(BSDname);
326  isCDorDVD = (mediaType == MEDIATYPE_DVD) || (mediaType == MEDIATYPE_AUDIO);
327 
328 
329  // We know it is removable, and have guessed the type.
330  // Call a helper function to create appropriate objects and insert
331 
332  LOG(VB_MEDIA, LOG_INFO, QString("Found disk %1 - volume name '%2'.")
333  .arg(BSDname).arg(volName));
334 
335  mtd->diskInsert(BSDname, volName, model, isCDorDVD);
336 
337  CFRelease(details);
338  free(volName);
339 }
340 
341 void diskDisappearedCallback(DADiskRef disk, void *context)
342 {
343  const char *BSDname = DADiskGetBSDName(disk);
344 
345  if (context)
346  reinterpret_cast<MonitorThreadDarwin *>(context)->diskRemove(BSDname);
347 }
348 
349 void diskChangedCallback(DADiskRef disk, CFArrayRef keys, void *context)
350 {
351  if (CFArrayContainsValue(keys, CFRangeMake(0, CFArrayGetCount(keys)),
352  kDADiskDescriptionVolumeNameKey))
353  {
354  const char *BSDname = DADiskGetBSDName(disk);
355  CFDictionaryRef details = DADiskCopyDescription(disk);
356  char *volName = getVolName(details);
357 
358  LOG(VB_MEDIA, LOG_INFO, QString("Disk %1 - changed name to '%2'.")
359  .arg(BSDname).arg(volName));
360 
361  reinterpret_cast<MonitorThreadDarwin *>(context)
362  ->diskRename(BSDname, volName);
363  CFRelease(details);
364  free(volName);
365  }
366 }
367 
368 
373 {
374  RunProlog();
375  CFDictionaryRef match = kDADiskDescriptionMatchVolumeMountable;
376  DASessionRef daSession = DASessionCreate(kCFAllocatorDefault);
377 
378  IOMasterPort(MACH_PORT_NULL, &sMasterPort);
379 
380  DARegisterDiskAppearedCallback(daSession, match,
381  diskAppearedCallback, this);
382  DARegisterDiskDisappearedCallback(daSession, match,
384  DARegisterDiskDescriptionChangedCallback(daSession, match,
385  kDADiskDescriptionWatchVolumeName,
386  diskChangedCallback, this);
387 
388  DASessionScheduleWithRunLoop(daSession,
389  CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
390 
391 
392  // Nice and simple, as long as our monitor is valid and active,
393  // loop and let daSession check the devices.
394  while (m_monitor && m_monitor->IsActive())
395  {
396  // Run the run loop for interval (milliseconds) - this will
397  // handle any disk arbitration appeared/dissappeared events
398  CFRunLoopRunInMode(kCFRunLoopDefaultMode,
399  (float) m_interval / 1000.0F, false );
400  }
401 
402  DAUnregisterCallback(daSession, (void(*))diskChangedCallback, this);
403  DAUnregisterCallback(daSession, (void(*))diskDisappearedCallback, this);
404  DAUnregisterCallback(daSession, (void(*))diskAppearedCallback, this);
405  CFRelease(daSession);
406  RunEpilog();
407 }
408 
415 void MonitorThreadDarwin::diskInsert(const char *devName,
416  const char *volName,
417  QString model, bool isCDorDVD)
418 {
419  MythMediaDevice *media;
420  QString msg = "MonitorThreadDarwin::diskInsert";
421 
422  LOG(VB_MEDIA, LOG_DEBUG, msg + QString("(%1,%2,'%3',%4)")
423  .arg(devName).arg(volName).arg(model).arg(isCDorDVD));
424 
425  if (isCDorDVD)
426  media = MythCDROM::get(nullptr, devName, true, m_monitor->m_allowEject);
427  else
428  media = MythHDD::Get(nullptr, devName, true, false);
429 
430  if (!media)
431  {
432  LOG(VB_GENERAL, LOG_ALERT, msg + "Couldn't create MythMediaDevice.");
433  return;
434  }
435 
436  // We store the volume name for user activities like ChooseAndEjectMedia().
437  media->setVolumeID(volName);
438  media->setDeviceModel(model.toLatin1()); // Same for the Manufacturer and model
439 
440  // Mac OS X devices are pre-mounted here:
441  QString mnt = "/Volumes/"; mnt += volName;
442  media->setMountPath(mnt.toLatin1());
443 
444  int attempts = 0;
445  QDir d(mnt);
446  while (!d.exists())
447  {
448  LOG(VB_MEDIA, LOG_WARNING,
449  (msg + "() - Waiting for mount '%1' to become stable.").arg(mnt));
450  usleep(std::chrono::microseconds(120000)); // cppcheck-suppress usleepCalled
451  if ( ++attempts > 4 )
452  usleep(std::chrono::microseconds(200000)); // cppcheck-suppress usleepCalled
453  if ( attempts > 8 )
454  {
455  delete media;
456  LOG(VB_MEDIA, LOG_ALERT, msg + "() - Giving up");
457  return;
458  }
459  }
460 
462 
463  // This is checked in AddDevice(), but checking earlier means
464  // we can avoid scanning all the files to determine its type
465  if (m_monitor->shouldIgnore(media))
466  return;
467 
468  // We want to use MythMedia's code to work out the mediaType.
469  // media->onDeviceMounted() is protected,
470  // so to call it indirectly, we pretend to mount it here.
471  media->mount();
472 
473  m_monitor->AddDevice(media);
474 }
475 
476 void MonitorThreadDarwin::diskRemove(QString devName)
477 {
478  LOG(VB_MEDIA, LOG_DEBUG,
479  QString("MonitorThreadDarwin::diskRemove(%1)").arg(devName));
480 
481  MythMediaDevice *pDevice = m_monitor->GetMedia(devName);
482 
483  if (pDevice) // Probably should ValidateAndLock() here?
484  pDevice->setStatus(MEDIASTAT_NODISK);
485  else
486  LOG(VB_MEDIA, LOG_INFO, "Couldn't find MythMediaDevice: " + devName);
487 
488  m_monitor->RemoveDevice(devName);
489 }
490 
497 void MonitorThreadDarwin::diskRename(const char *devName, const char *volName)
498 {
499  LOG(VB_MEDIA, LOG_DEBUG,
500  QString("MonitorThreadDarwin::diskRename(%1,%2)")
501  .arg(devName).arg(volName));
502 
503  MythMediaDevice *pDevice = m_monitor->GetMedia(devName);
504 
505  if (m_monitor->ValidateAndLock(pDevice))
506  {
507  // Send message to plugins to ignore this drive:
508  pDevice->setStatus(MEDIASTAT_NODISK);
509 
510  pDevice->setVolumeID(volName);
511  pDevice->setMountPath((QString("/Volumes/") + volName).toLatin1());
512 
513  // Plugins can now use it again:
514  pDevice->setStatus(MEDIASTAT_USEABLE);
515 
516  m_monitor->Unlock(pDevice);
517  }
518  else
519  LOG(VB_MEDIA, LOG_INFO,
520  QString("Couldn't find MythMediaDevice: %1").arg(devName));
521 }
522 
530 {
531  // Sanity check
532  if (m_active)
533  return;
534 
535  // If something (like the MythMusic plugin) stops and starts monitoring,
536  // DiskArbitration would re-add the same drives several times over.
537  // So, we make sure the device list is deleted.
538  m_devices.clear();
539 
540 
541  if (!m_thread)
543 
544  qRegisterMetaType<MythMediaStatus>("MythMediaStatus");
545 
546  LOG(VB_MEDIA, LOG_NOTICE, "Starting MediaMonitor");
547  m_active = true;
548  m_thread->start();
549 }
550 
557 {
558  if ( !pDevice )
559  {
560  LOG(VB_GENERAL, LOG_ERR, "MediaMonitor::AddDevice(null)");
561  return false;
562  }
563 
564  // If the user doesn't want this device to be monitored, stop now:
565  if (shouldIgnore(pDevice))
566  return false;
567 
568  m_devices.push_back( pDevice );
569  m_useCount[pDevice] = 0;
570 
571 
572  // Devices on Mac OS X don't change status the way Linux ones do,
573  // so we force a status change for mediaStatusChanged() to send an event
574  pDevice->setStatus(MEDIASTAT_NODISK);
575  connect(pDevice, &MythMediaDevice::statusChanged,
577  pDevice->setStatus(MEDIASTAT_USEABLE);
578 
579 
580  return true;
581 }
582 
583 /*
584  * Given a device, return a compound description to help identify it.
585  * We try to find out if it is internal, its manufacturer, and model.
586  */
587 static QString getModel(io_object_t drive)
588 {
589  QString desc;
590  CFMutableDictionaryRef props = nullptr;
591 
592  props = (CFMutableDictionaryRef) IORegistryEntrySearchCFProperty(drive, kIOServicePlane, CFSTR(kIOPropertyProtocolCharacteristicsKey), kCFAllocatorDefault, kIORegistryIterateParents | kIORegistryIterateRecursively);
593 CFShow(props);
594  if (props)
595  {
596  const void *location = CFDictionaryGetValue(props, CFSTR(kIOPropertyPhysicalInterconnectLocationKey));
597  if (CFEqual(location, CFSTR("Internal")))
598  desc.append("Internal ");
599  }
600 
601  props = (CFMutableDictionaryRef) IORegistryEntrySearchCFProperty(drive, kIOServicePlane, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kIORegistryIterateParents | kIORegistryIterateRecursively);
602  if (props)
603  {
604  const void *product = CFDictionaryGetValue(props, CFSTR(kIOPropertyProductNameKey));
605  const void *vendor = CFDictionaryGetValue(props, CFSTR(kIOPropertyVendorNameKey));
606  if (vendor)
607  {
608  desc.append(CFStringGetCStringPtr((CFStringRef)vendor, kCFStringEncodingMacRoman));
609  desc.append(" ");
610  }
611  if (product)
612  {
613  desc.append(CFStringGetCStringPtr((CFStringRef)product, kCFStringEncodingMacRoman));
614  desc.append(" ");
615  }
616  }
617 
618  // Omit the trailing space
619  desc.truncate(desc.length() - 1);
620 
621  return desc;
622 }
623 
634 {
635  kern_return_t kernResult;
636  CFMutableDictionaryRef devices;
637  io_iterator_t iter;
638  QStringList list;
639  QString msg = QString("GetCDRomBlockDevices() - ");
640 
641 
642  devices = IOServiceMatching(kIOBlockStorageDeviceClass);
643  if (!devices)
644  {
645  LOG(VB_GENERAL, LOG_ALERT, msg + "No Storage Devices? Unlikely!");
646  return list;
647  }
648 
649  // Create an iterator across all parents of the service object passed in.
650  kernResult = IOServiceGetMatchingServices(sMasterPort, devices, &iter);
651 
652  if (KERN_SUCCESS != kernResult)
653  {
654  LOG(VB_GENERAL, LOG_ALERT, msg +
655  QString("IORegistryEntryCreateIterator returned %1")
656  .arg(kernResult));
657  return list;
658  }
659  if (!iter)
660  {
661  LOG(VB_GENERAL, LOG_ALERT, msg +
662  "IORegistryEntryCreateIterator returned a NULL iterator");
663  return list;
664  }
665 
666  io_object_t drive;
667 
668  while ((drive = IOIteratorNext(iter)))
669  {
670  CFMutableDictionaryRef p = nullptr; // properties of drive
671 
672  IORegistryEntryCreateCFProperties(drive, &p, kCFAllocatorDefault, 0);
673  if (p)
674  {
675  const void *type = CFDictionaryGetValue(p, CFSTR("device-type"));
676 
677  if (CFEqual(type, CFSTR("DVD")) || CFEqual(type, CFSTR("CD")))
678  {
679  QString desc = getModel(drive);
680 
681  list.append(desc);
682  LOG(VB_MEDIA, LOG_INFO, desc.prepend("Found CD/DVD: "));
683  CFRelease(p);
684  }
685  }
686  else
687  LOG(VB_GENERAL, LOG_ALERT,
688  msg + "Could not retrieve drive properties");
689 
690  IOObjectRelease(drive);
691  }
692 
693  IOObjectRelease(iter);
694 
695  return list;
696 }
MediaMonitor::m_devices
QList< MythMediaDevice * > m_devices
Definition: mythmediamonitor.h:119
MythMediaDevice::mount
bool mount()
Definition: mythmedia.h:107
MEDIATYPE_DVD
@ MEDIATYPE_DVD
Definition: mythmedia.h:29
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
diskAppearedCallback
void diskAppearedCallback(DADiskRef disk, void *context)
Definition: mediamonitor-darwin.cpp:261
sMasterPort
static mach_port_t sMasterPort
Definition: mediamonitor-darwin.cpp:36
MEDIATYPE_UNKNOWN
@ MEDIATYPE_UNKNOWN
Definition: mythmedia.h:25
MediaMonitor::MonitorThreadDarwin
friend class MonitorThreadDarwin
Definition: mythmediamonitor.h:49
MythMediaDevice::setVolumeID
void setVolumeID(const char *vol)
Definition: mythmedia.h:73
MediaMonitorDarwin::AddDevice
bool AddDevice(MythMediaDevice *pDevice) override
Simpler version of MediaMonitorUnix::AddDevice()
Definition: mediamonitor-darwin.cpp:556
mythcdrom.h
MThread::usleep
static void usleep(std::chrono::microseconds time)
Definition: mthread.cpp:335
mythmediamonitor.h
MEDIASTAT_USEABLE
@ MEDIASTAT_USEABLE
Definition: mythmedia.h:19
getVolName
static char * getVolName(CFDictionaryRef diskDetails)
Given a description of a disk, copy and return the volume name.
Definition: mediamonitor-darwin.cpp:182
MediaMonitor::m_monitorPollingInterval
unsigned long m_monitorPollingInterval
Definition: mythmediamonitor.h:129
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
MediaMonitor::mediaStatusChanged
void mediaStatusChanged(MythMediaStatus oldStatus, MythMediaDevice *pMedia) const
Slot which is called when the device status changes and posts a media event to the mainwindow.
Definition: mythmediamonitor.cpp:711
MEDIASTAT_MOUNTED
@ MEDIASTAT_MOUNTED
Definition: mythmedia.h:21
MythMediaDevice::statusChanged
void statusChanged(MythMediaStatus oldStatus, MythMediaDevice *pMedia)
MediaMonitorDarwin::GetCDROMBlockDevices
QStringList GetCDROMBlockDevices(void) override
List of CD/DVD devices.
Definition: mediamonitor-darwin.cpp:633
mythlogging.h
MythMediaDevice::setDeviceModel
void setDeviceModel(const char *model)
Definition: mythmedia.h:68
hardwareprofile.config.p
p
Definition: config.py:33
MonitorThreadDarwin::diskRemove
void diskRemove(QString devName)
Definition: mediamonitor-darwin.cpp:476
MonitorThread::m_monitor
QPointer< MediaMonitor > m_monitor
Definition: mythmediamonitor.h:40
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
MythHDD::Get
static MythHDD * Get(QObject *par, const char *devicePath, bool SuperMount, bool AllowEject)
Helper function used to create a new instance of a hard disk device.
Definition: mythhdd.cpp:15
MythMediaDevice::setMountPath
void setMountPath(const char *path)
Definition: mythmedia.h:59
MonitorThreadDarwin::diskRename
void diskRename(const char *devName, const char *volName)
Deal with the user, or another program, renaming a volume.
Definition: mediamonitor-darwin.cpp:497
FindMediaType
MythMediaType FindMediaType(io_service_t service)
Guess the media that a volume/partition is on.
Definition: mediamonitor-darwin.cpp:42
MEDIATYPE_AUDIO
@ MEDIATYPE_AUDIO
Definition: mythmedia.h:28
MythMediaDevice::setStatus
MythMediaStatus setStatus(MythMediaStatus newStat, bool CloseIt=false)
Definition: mythmedia.cpp:461
MediaMonitor::shouldIgnore
bool shouldIgnore(const MythMediaDevice *device)
Check user preferences to see if this device should be monitored.
Definition: mythmediamonitor.cpp:758
MediaMonitor::m_thread
MonitorThread * m_thread
Definition: mythmediamonitor.h:128
MediaMonitor::m_active
bool volatile m_active
Was MonitorThread started?
Definition: mythmediamonitor.h:126
MythCDROM::get
static MythCDROM * get(QObject *par, const QString &devicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom.cpp:43
diskDisappearedCallback
void diskDisappearedCallback(DADiskRef disk, void *context)
Definition: mediamonitor-darwin.cpp:341
MythMediaType
MythMediaType
Definition: mythmedia.h:24
MediaMonitor::m_useCount
QMap< MythMediaDevice *, int > m_useCount
Definition: mythmediamonitor.h:121
MEDIASTAT_NODISK
@ MEDIASTAT_NODISK
CD/DVD tray closed but empty, device unusable.
Definition: mythmedia.h:17
MediaTypeForBSDName
MythMediaType MediaTypeForBSDName(const char *bsdName)
Given a BSD device node name, guess its media type.
Definition: mediamonitor-darwin.cpp:117
MonitorThreadDarwin
Definition: mediamonitor-darwin.h:7
MonitorThread::m_interval
unsigned long m_interval
Definition: mythmediamonitor.h:41
MonitorThreadDarwin::run
void run(void) override
Use the DiskArbitration Daemon to inform us of media changes.
Definition: mediamonitor-darwin.cpp:372
MythMediaDevice
Definition: mythmedia.h:48
MediaMonitorDarwin::StartMonitoring
void StartMonitoring(void) override
Start the monitoring thread if needed.
Definition: mediamonitor-darwin.cpp:529
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
mediamonitor-darwin.h
getModel
static QString getModel(CFDictionaryRef diskDetails)
Definition: mediamonitor-darwin.cpp:215
diskChangedCallback
void diskChangedCallback(DADiskRef disk, CFArrayRef keys, void *context)
Definition: mediamonitor-darwin.cpp:349
mythhdd.h
MonitorThreadDarwin::diskInsert
void diskInsert(const char *devName, const char *volName, QString model, bool isCDorDVD=1)
Create a MythMedia instance and insert in MythMediaMonitor list.
Definition: mediamonitor-darwin.cpp:415