MythTV  master
mythmediamonitor.cpp
Go to the documentation of this file.
1 
2 // Standard C headers
3 #include <cstdio>
4 
5 // C++ headers
6 #include <iostream>
7 #include <typeinfo>
8 
9 // Qt headers
10 #include <QtGlobal>
11 #include <QCoreApplication>
12 #include <QFile>
13 #include <QList>
14 #include <QDir>
15 
16 // MythTV headers
17 #include "libmythbase/mythcdrom.h"
18 #include "libmythbase/mythconfig.h"
20 #include "libmythbase/mythdate.h"
26 
27 #include "mythmediamonitor.h"
28 #ifdef USING_DARWIN_DA
29 #include "mediamonitor-darwin.h"
30 #elif defined(Q_OS_WIN)
31 #include "mediamonitor-windows.h"
32 #else
33 #include "mediamonitor-unix.h"
34 #endif
35 
36 static const QString sLocation = QObject::tr("Media Monitor");
37 
39 
40 // MonitorThread
41 MonitorThread::MonitorThread(MediaMonitor* pMon, unsigned long interval) :
42  MThread("Monitor")
43 {
44  m_monitor = pMon;
45  m_interval = interval;
46  m_lastCheckTime = QDateTime::currentDateTimeUtc();
47 }
48 
49 // Nice and simple, as long as our monitor is valid and active,
50 // loop and check it's devices.
52 {
53  RunProlog();
54  QMutex mtx;
55  mtx.lock();
56  while (m_monitor && m_monitor->IsActive())
57  {
58  m_monitor->CheckDevices();
59  m_monitor->m_wait.wait(&mtx, m_interval);
60  QDateTime now(QDateTime::currentDateTimeUtc());
61  // if 10 seconds have elapsed instead of 5 seconds
62  // assume the system was suspended and reconnect
63  // sockets
64  if (m_lastCheckTime.secsTo(now) > 120)
65  {
67  if (HasMythMainWindow())
68  {
69  LOG(VB_GENERAL, LOG_INFO, "Restarting LIRC handler");
71  }
72  }
73  m_lastCheckTime = now;
74  }
75  mtx.unlock();
76  RunEpilog();
77 }
78 
80 // MediaMonitor
81 
82 #define MONITOR_INTERVAL 5000
83 
85 {
86  if (s_monitor)
87  return s_monitor;
88 
89 #ifdef USING_DARWIN_DA
90  s_monitor = new MediaMonitorDarwin(nullptr, MONITOR_INTERVAL, true);
91 #elif defined(Q_OS_WIN)
92  s_monitor = new MediaMonitorWindows(nullptr, MONITOR_INTERVAL, true);
93 #else
94  s_monitor = new MediaMonitorUnix(nullptr, MONITOR_INTERVAL, true);
95 #endif
96 
97  return s_monitor;
98 }
99 
100 void MediaMonitor::SetCDSpeed(const char *device, int speed)
101 {
102  MediaMonitor *mon = GetMediaMonitor();
103  if (mon)
104  {
105  MythMediaDevice *pMedia = mon->GetMedia(device);
106  if (pMedia && mon->ValidateAndLock(pMedia))
107  {
108  pMedia->setSpeed(speed);
109  mon->Unlock(pMedia);
110  return;
111  }
112  }
113 
114  MythCDROM *cd = MythCDROM::get(nullptr, device, false, false);
115  if (cd)
116  {
117  cd->setDeviceSpeed(device, speed);
118  delete cd;
119  return;
120  }
121 
122  LOG(VB_MEDIA, LOG_INFO,
123  QString("MediaMonitor::setSpeed(%1) - Cannot find/create CDROM?")
124  .arg(device));
125 }
126 
127 // When ejecting one of multiple devices, present a nice name to the user
128 static QString DevName(MythMediaDevice *d)
129 {
130  QString str = d->getVolumeID(); // First choice, the name of the media
131 
132  if (str.isEmpty())
133  {
134  str = d->getDeviceModel(); // otherwise, the drive manufacturer/model
135 
136  if (!str.isEmpty()) // and/or the device node
137  str += " (" + d->getDevicePath() + ')';
138  else
139  str = d->getDevicePath();
140  }
141  // We could add even more information here, but volume names
142  // are usually descriptively unique (i.e. usually good enough)
143  //else
144  // str += " (" + d->getDeviceModel() + ", " + d->getDevicePath() + ')';
145 
146  return str;
147 }
148 
154 QList<MythMediaDevice*> MediaMonitor::GetRemovable(bool showMounted,
155  bool showUsable)
156 {
157  QList <MythMediaDevice *> drives;
158  QList <MythMediaDevice *>::iterator it;
159  QMutexLocker locker(&m_devicesLock);
160 
161  for (it = m_devices.begin(); it != m_devices.end(); ++it)
162  {
163  // By default, we only list CD/DVD devices.
164  // Caller can also request mounted drives to be listed (e.g. USB flash)
165 
166  if (showUsable && !(*it)->isUsable())
167  continue;
168 
169  if (QString(typeid(**it).name()).contains("MythCDROM") ||
170  (showMounted && (*it)->isMounted(false)))
171  drives.append(*it);
172  }
173 
174  return drives;
175 }
176 
183  bool showMounted,
184  bool showUsable)
185 {
186  QList <MythMediaDevice *> drives = GetRemovable(showMounted,
187  showUsable);
188 
189  if (drives.count() == 0)
190  {
191  QString msg = "MediaMonitor::selectDrivePopup() - no removable devices";
192 
193  LOG(VB_MEDIA, LOG_INFO, msg);
194  return nullptr;
195  }
196 
197  if (drives.count() == 1)
198  {
199  LOG(VB_MEDIA, LOG_INFO,
200  "MediaMonitor::selectDrivePopup(" + label +
201  ") - One suitable device");
202  return drives.front();
203  }
204 
206  if (!win)
207  return nullptr;
208 
209  MythScreenStack *stack = win->GetMainStack();
210  if (!stack)
211  return nullptr;
212 
213  // Ignore MENU dialog actions
214  int btnIndex = -2;
215  while (btnIndex < -1)
216  {
217  auto *dlg = new MythDialogBox(label, stack, "select drive");
218  if (!dlg->Create())
219  {
220  delete dlg;
221  return nullptr;
222  }
223 
224  // Add button for each drive
225  for (auto *drive : drives)
226  dlg->AddButton(DevName(drive));
227 
228  dlg->AddButton(tr("Cancel"));
229 
230  stack->AddScreen(dlg);
231 
232  // Wait in local event loop so events are processed
233  QEventLoop block;
234  connect(dlg, &MythDialogBox::Closed,
235  &block, [&](const QString& /*resultId*/, int result) { block.exit(result); });
236 
237  // Block until dialog closes
238  btnIndex = block.exec();
239  }
240 
241  // If the user cancelled, return a special value
242  return btnIndex < 0 || btnIndex >= drives.size() ? (MythMediaDevice *)-1
243  : drives.at(btnIndex);
244 }
245 
246 
256 {
257  MythMediaDevice *selected =
258  selectDrivePopup(tr("Select removable media to eject or insert"), true);
259 
260  // If the user cancelled, no need to display or do anything more
261  if (selected == (MythMediaDevice *) -1)
262  return;
263 
264  if (!selected)
265  {
266  ShowNotification(tr("No devices to eject"), sLocation);
267  return;
268  }
269 
270  AttemptEject(selected);
271 }
272 
273 
274 void MediaMonitor::EjectMedia(const QString &path)
275 {
276  MythMediaDevice *device = GetMedia(path);
277  if (device)
278  AttemptEject(device);
279 }
280 
281 
283 {
284  QString dev = DevName(device);
285 
286  if (device->getStatus() == MEDIASTAT_OPEN)
287  {
288  LOG(VB_MEDIA, LOG_INFO,
289  QString("Disk %1's tray is OPEN. Closing tray").arg(dev));
290 
291  if (device->eject(false) != MEDIAERR_OK)
292  {
293  QString msg =
294  QObject::tr("Unable to open or close the empty drive %1");
295  QString extra =
296  QObject::tr("You may have to use the eject button under its tray");
297  ShowNotificationError(msg.arg(dev), sLocation, extra);
298  }
299  return;
300  }
301 
302  if (device->isMounted())
303  {
304  LOG(VB_MEDIA, LOG_INFO,
305  QString("Disk %1 is mounted? Unmounting").arg(dev));
306  device->unmount();
307 
308 #ifndef Q_OS_DARWIN
309  if (device->isMounted())
310  {
311  ShowNotificationError(tr("Failed to unmount %1").arg(dev),
312  sLocation);
313  return;
314  }
315 #endif
316  }
317 
318  LOG(VB_MEDIA, LOG_INFO,
319  QString("Unlocking disk %1, then ejecting").arg(dev));
320  device->unlock();
321 
322  MythMediaError err = device->eject();
323 
324  if (err == MEDIAERR_UNSUPPORTED)
325  {
326  // Physical ejection isn't possible (there is no tray or slot),
327  // but logically the device is now ejected (ignored by the OS).
328  ShowNotification(tr("You may safely remove %1").arg(dev), sLocation);
329  }
330  else if (err == MEDIAERR_FAILED)
331  {
332  ShowNotificationError(tr("Failed to eject %1").arg(dev), sLocation);
333  }
334 }
335 
342 MediaMonitor::MediaMonitor(QObject* par, unsigned long interval, bool allowEject)
343  : QObject(par),
344  m_monitorPollingInterval(interval),
345  m_allowEject(allowEject)
346 {
347  // User can specify that some devices are not monitored
348  QString ignore = gCoreContext->GetSetting("IgnoreDevices", "");
349 
350  if (!ignore.isEmpty())
351  {
352 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
353  m_ignoreList = ignore.split(',', QString::SkipEmptyParts);
354 #else
355  m_ignoreList = ignore.split(',', Qt::SkipEmptyParts);
356 #endif
357  }
358 
359  LOG(VB_MEDIA, LOG_NOTICE, "Creating MediaMonitor");
360  LOG(VB_MEDIA, LOG_INFO, "IgnoreDevices=" + ignore);
361 
362  // If any of IgnoreDevices are symlinks, also add the real device
363  QStringList symlinked;
364  for (const auto & ignored : qAsConst(m_ignoreList))
365  {
366  if (auto fi = QFileInfo(ignored); fi.isSymLink())
367  {
368  if (auto target = getSymlinkTarget(ignored); m_ignoreList.filter(target).isEmpty())
369  {
370  symlinked += target;
371  LOG(VB_MEDIA, LOG_INFO, QString("Also ignoring %1 (symlinked from %2)")
372  .arg(target, ignored));
373  }
374  }
375  }
376 
377  m_ignoreList += symlinked;
378 }
379 
381 {
382  if (m_thread)
383  {
384  StopMonitoring();
385  delete m_thread;
386  m_thread = nullptr;
387  }
388  QObject::deleteLater();
389 }
390 
399 bool MediaMonitor::RemoveDevice(const QString &dev)
400 {
401  QMutexLocker locker(&m_devicesLock);
402 
403  QList<MythMediaDevice*>::iterator it;
404  for (it = m_devices.begin(); it != m_devices.end(); ++it)
405  {
406  if ((*it)->getDevicePath() == dev)
407  {
408  // Ensure device gets an unmount
409  (*it)->checkMedia();
410 
411  if (m_useCount[*it] == 0)
412  {
413  m_useCount.remove(*it);
414  (*it)->deleteLater();
415  m_devices.erase(it);
416  }
417  else
418  {
419  // Other threads are still using this device
420  // postpone actual delete until they finish.
421  disconnect(*it);
422  m_removedDevices.append(*it);
423  m_devices.erase(it);
424  }
425 
426  return true;
427  }
428  }
429  return false;
430 }
431 
436 {
437  /* check if new devices have been plugged in */
439 
440  QMutexLocker locker(&m_devicesLock);
441 
442  QList<MythMediaDevice*>::iterator itr = m_devices.begin();
443  while (itr != m_devices.end())
444  {
445  MythMediaDevice* pDev = *itr;
446  if (pDev)
447  pDev->checkMedia();
448  ++itr;
449  }
450 }
451 
456 {
457  // Sanity check
458  if (m_active)
459  return;
460  if (!gCoreContext->GetBoolSetting("MonitorDrives", false)) {
461  LOG(VB_MEDIA, LOG_NOTICE, "MediaMonitor disabled by user setting.");
462  return;
463  }
464 
465  if (!m_thread)
467 
468  qRegisterMetaType<MythMediaStatus>("MythMediaStatus");
469 
470  LOG(VB_MEDIA, LOG_NOTICE, "Starting MediaMonitor");
471  m_active = true;
472  m_thread->start();
473 }
474 
479 {
480  // Sanity check
481  if (!m_active)
482  return;
483 
484  LOG(VB_MEDIA, LOG_NOTICE, "Stopping MediaMonitor");
485  m_active = false;
486  m_wait.wakeAll();
487  m_thread->wait();
488  LOG(VB_MEDIA, LOG_NOTICE, "Stopped MediaMonitor");
489 }
490 
502 {
503  QMutexLocker locker(&m_devicesLock);
504 
505  if (!m_devices.contains(pMedia))
506  return false;
507 
508  m_useCount[pMedia]++;
509 
510  return true;
511 }
512 
519 {
520  QMutexLocker locker(&m_devicesLock);
521 
522  if (!m_useCount.contains(pMedia))
523  return;
524 
525  m_useCount[pMedia]--;
526 
527  if (m_useCount[pMedia] == 0 && m_removedDevices.contains(pMedia))
528  {
529  m_removedDevices.removeAll(pMedia);
530  m_useCount.remove(pMedia);
531  pMedia->deleteLater();
532  }
533 }
534 
542 {
543  QMutexLocker locker(&m_devicesLock);
544 
545  for (auto *dev : qAsConst(m_devices))
546  {
547  if (dev->isSameDevice(path) &&
548  ((dev->getStatus() == MEDIASTAT_USEABLE) ||
549  (dev->getStatus() == MEDIASTAT_MOUNTED) ||
550  (dev->getStatus() == MEDIASTAT_NOTMOUNTED)))
551  {
552  return dev;
553  }
554  }
555 
556  return nullptr;
557 }
558 
565 QString MediaMonitor::GetMountPath(const QString& devPath)
566 {
567  QString mountPath;
568 
569  if (s_monitor)
570  {
571  MythMediaDevice *pMedia = s_monitor->GetMedia(devPath);
572  if (pMedia && s_monitor->ValidateAndLock(pMedia))
573  {
574  mountPath = pMedia->getMountPath();
575  s_monitor->Unlock(pMedia);
576  }
577  // The media monitor could be inactive.
578  // Create a fake media device just to lookup mount map:
579  else
580  {
581  pMedia = MythCDROM::get(nullptr, devPath.toLatin1(), true, false);
582  if (pMedia && pMedia->findMountPath())
583  mountPath = pMedia->getMountPath();
584  else
585  LOG(VB_MEDIA, LOG_INFO,
586  "MediaMonitor::GetMountPath() - failed");
587  // need some way to delete the media device.
588  }
589  }
590 
591  return mountPath;
592 }
593 
612 QList<MythMediaDevice*> MediaMonitor::GetMedias(unsigned mediatypes)
613 {
614  QMutexLocker locker(&m_devicesLock);
615 
616  QList<MythMediaDevice*> medias;
617 
618  for (auto *dev : qAsConst(m_devices))
619  {
620  if ((dev->getMediaType() & mediatypes) &&
621  ((dev->getStatus() == MEDIASTAT_USEABLE) ||
622  (dev->getStatus() == MEDIASTAT_MOUNTED) ||
623  (dev->getStatus() == MEDIASTAT_NOTMOUNTED)))
624  {
625  medias.push_back(dev);
626  }
627  }
628 
629  return medias;
630 }
631 
651 void MediaMonitor::RegisterMediaHandler(const QString &destination,
652  const QString &description,
653  void (*callback)
654  (MythMediaDevice*),
655  int mediaType,
656  const QString &extensions)
657 {
658  if (m_handlerMap.count(destination) == 0)
659  {
660  MHData mhd = { callback, mediaType, destination, description };
661  QString msg = MythMediaDevice::MediaTypeString((MythMediaType)mediaType);
662 
663  if (!extensions.isEmpty())
664  msg += QString(", ext(%1)").arg(extensions);
665 
666  LOG(VB_MEDIA, LOG_INFO,
667  "Registering '" + destination + "' as a media handler for " +
668  msg);
669 
670  m_handlerMap[destination] = mhd;
671 
672  if (!extensions.isEmpty())
673  MythMediaDevice::RegisterMediaExtensions(mediaType, extensions);
674  }
675  else
676  {
677  LOG(VB_GENERAL, LOG_INFO,
678  destination + " is already registered as a media handler.");
679  }
680 }
681 
690 {
691  QVector<MHData> handlers;
692  QMap<QString, MHData>::Iterator itr = m_handlerMap.begin();
693 
694  while (itr != m_handlerMap.end())
695  {
696  if (((*itr).MythMediaType & (int)pMedia->getMediaType()))
697  {
698  LOG(VB_GENERAL, LOG_NOTICE,
699  QString("Found a handler for %1 - '%2'")
700  .arg(pMedia->MediaTypeString(), itr.key()));
701  handlers.append(*itr);
702  }
703  itr++;
704  }
705 
706  if (handlers.empty())
707  {
708  LOG(VB_MEDIA, LOG_INFO, "No media handler found for event type");
709  return;
710  }
711 
712 
713  // TODO - Generate a dialog, add buttons for each description,
714  // if user didn't cancel, selected = handlers.at(choice);
715  int selected = 0;
716 
717  handlers.at(selected).callback(pMedia);
718 }
719 
725  MythMediaDevice* pMedia) const
726 {
727  // If we're not active then ignore signal.
728  if (!m_active)
729  return;
730 
731  MythMediaStatus stat = pMedia->getStatus();
732  QString msg = QString(" (%1, %2 -> %3)")
733  .arg(pMedia->MediaTypeString(),
736 
737  // This gets called from outside the main thread so we need
738  // to post an event back to the main thread.
739  // We now send events for all non-error statuses, so plugins get ejects
740  if (stat != MEDIASTAT_ERROR && stat != MEDIASTAT_UNKNOWN &&
741  // Don't send an event for a new device that's not mounted
742  !(oldStatus == MEDIASTAT_UNPLUGGED && stat == MEDIASTAT_NOTMOUNTED))
743  {
744  // Should we ValidateAndLock() first?
745  QEvent *e = new MythMediaEvent(stat, pMedia);
746 
747  LOG(VB_MEDIA, LOG_INFO, "Posting MediaEvent" + msg);
748 
749  // sendEvent() is needed here - it waits for the event to be used.
750  // postEvent() would result in pDevice's media type changing
751  // ... before the plugin's event chain would process it.
752  // Another way would be to send an exact copy of pDevice instead.
753  QCoreApplication::sendEvent((QObject*)GetMythMainWindow(), e);
754  delete e;
755  }
756  else
757  LOG(VB_MEDIA, LOG_INFO,
758  "Media status changed, but not sending event" + msg);
759 
760 
761  if (stat == MEDIASTAT_OPEN || stat == MEDIASTAT_NODISK
762  || stat == MEDIASTAT_UNPLUGGED)
763  {
764  pMedia->clearData();
765  }
766 }
767 
772 {
773  if (m_ignoreList.contains(device->getMountPath()) ||
774  m_ignoreList.contains(device->getRealDevice())||
775  m_ignoreList.contains(device->getDevicePath()) )
776  {
777  LOG(VB_MEDIA, LOG_INFO,
778  "Ignoring device: " + device->getDevicePath());
779  return true;
780  }
781 #if 0
782  else
783  {
784  LOG(VB_MEDIA, LOG_DEBUG,
785  "Not ignoring: " + device->getDevicePath() + " / " +
786  device->getMountPath());
787  LOG(VB_MEDIA, LOG_DEBUG,
788  "Paths not in: " + m_ignoreList.join(", "));
789  }
790 #endif
791 
792  return false;
793 }
794 
799 bool MediaMonitor::eventFilter(QObject *obj, QEvent *event)
800 {
801  if (event->type() == MythMediaEvent::kEventType)
802  {
803  auto *me = dynamic_cast<MythMediaEvent *>(event);
804  if (me == nullptr)
805  {
806  LOG(VB_GENERAL, LOG_ALERT,
807  "MediaMonitor::eventFilter() couldn't cast event");
808  return true;
809  }
810 
811  MythMediaDevice *pDev = me->getDevice();
812  if (!pDev)
813  {
814  LOG(VB_GENERAL, LOG_ALERT,
815  "MediaMonitor::eventFilter() got a bad media event?");
816  return true;
817  }
818 
819  if (pDev->isUsable())
820  JumpToMediaHandler(pDev);
821  else
822  {
823  // We don't want to jump around in the menus, but should
824  // call each plugin's callback so it can track this change.
825 
826  QMap<QString, MHData>::Iterator itr = m_handlerMap.begin();
827  while (itr != m_handlerMap.end())
828  {
829  if ((*itr).MythMediaType & (int)pDev->getMediaType() ||
830  pDev->getStatus() == MEDIASTAT_OPEN)
831  (*itr).callback(pDev);
832  itr++;
833  }
834  }
835 
836  return false; // Don't eat the event
837  }
838 
839  // standard event processing
840  return QObject::eventFilter(obj, event);
841 }
842 
843 /*
844  * These methods return the user's preferred devices for playing and burning
845  * CDs and DVDs. Traditionally we had a database setting to remember this,
846  * but that is a bit wasteful when most users only have one drive.
847  *
848  * To make it a bit more beginner friendly, if no database default exists,
849  * or if it contains "default", the code tries to find a monitored drive.
850  * If, still, nothing is suitable, a caller hard-coded default is used.
851  *
852  * Ideally, these would return a MythMediaDevice * instead of a QString
853  */
854 
855 QString MediaMonitor::defaultDevice(const QString &dbSetting,
856  const QString &label,
857  const char *hardCodedDefault)
858 {
859  QString device = gCoreContext->GetSetting(dbSetting);
860 
861  LOG(VB_MEDIA, LOG_DEBUG,
862  QString("MediaMonitor::defaultDevice(%1,..,%2) dbSetting='%3'")
863  .arg(dbSetting, hardCodedDefault, device));
864 
865  // No settings database defaults? Try to choose one:
866  if (device.isEmpty() || device == "default")
867  {
868  device = hardCodedDefault;
869 
870  if (!s_monitor)
872 
873  if (s_monitor)
874  {
875  MythMediaDevice *d = s_monitor->selectDrivePopup(label, false, true);
876 
877  if (d == (MythMediaDevice *) -1) // User cancelled
878  {
879  device.clear(); // If user has explicitly cancelled return empty string
880  d = nullptr;
881  }
882 
883  if (d && s_monitor->ValidateAndLock(d))
884  {
885  device = d->getDevicePath();
886  s_monitor->Unlock(d);
887  }
888  }
889  }
890 
891  LOG(VB_MEDIA, LOG_DEBUG,
892  "MediaMonitor::defaultDevice() returning " + device);
893  return device;
894 }
895 
900 {
901  return defaultDevice("CDDevice", tr("Select a CD drive"), DEFAULT_CD);
902 }
903 
908 {
909  return defaultDevice("VCDDeviceLocation",
910  tr("Select a VCD drive"), DEFAULT_CD);
911 }
912 
917 {
918  return defaultDevice("DVDDeviceLocation",
919  tr("Select a DVD drive"), DEFAULT_DVD);
920 }
921 
926 {
927  return defaultDevice("CDWriterDeviceLocation",
928  tr("Select a CD writer"), DEFAULT_CD);
929 }
930 
938 {
939  QString device = defaultDevice("MythArchiveDVDLocation",
940  tr("Select a DVD writer"), DEFAULT_DVD);
941 
942  return device;
943 }
944 
945 
950 {
951  QStringList list;
952 
953  for (const auto *dev : qAsConst(m_devices))
954  {
955  QString devStr;
956  QString model = dev->getDeviceModel();
957  const QString& path = dev->getDevicePath();
958  const QString& real = dev->getRealDevice();
959 
960  if (path != real)
961  devStr += path + "->";
962  devStr += real;
963 
964  if (model.isEmpty())
965  model = "unknown";
966  devStr += " (" + model + ")";
967 
968  list += devStr;
969  }
970 
971  return list.join(", ");
972 }
973 
981 {
983  if (mon)
984  mon->ChooseAndEjectMedia();
985  else
986  {
987  LOG(VB_MEDIA, LOG_INFO, "CD/DVD Monitor isn't enabled.");
988 #ifdef __linux__
989  LOG(VB_MEDIA, LOG_INFO, "Trying Linux 'eject -T' command");
990  myth_system("eject -T");
991 #elif defined(Q_OS_DARWIN)
992  QString def = DEFAULT_CD;
993  LOG(VB_MEDIA, LOG_INFO, "Trying 'diskutil eject " + def);
994  myth_system("diskutil eject " + def);
995 #endif
996  }
997 }
998 
999 /*
1000  * vim:ts=4:sw=4:ai:et:si:sts=4
1001  */
MythMediaDevice::isUsable
bool isUsable() const
Is this device "ready", for a plugin to access?
Definition: mythmedia.h:84
MythMediaDevice::getMountPath
const QString & getMountPath() const
Definition: mythmedia.h:58
MediaMonitor::m_devices
QList< MythMediaDevice * > m_devices
Definition: mythmediamonitor.h:125
MonitorThread::MonitorThread
MonitorThread(MediaMonitor *pMon, unsigned long interval)
Definition: mythmediamonitor.cpp:41
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:315
MediaMonitor::AttemptEject
static void AttemptEject(MythMediaDevice *device)
Definition: mythmediamonitor.cpp:282
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:286
MediaMonitor::m_wait
QWaitCondition m_wait
Definition: mythmediamonitor.h:133
MediaMonitor::ejectOpticalDisc
static void ejectOpticalDisc(void)
Eject a disk, unmount a drive, open a tray.
Definition: mythmediamonitor.cpp:980
MediaMonitor::eventFilter
bool eventFilter(QObject *obj, QEvent *event) override
Installed into the main window's event chain, so that the main thread can safely jump to plugin code.
Definition: mythmediamonitor.cpp:799
ShowNotificationError
void ShowNotificationError(const QString &msg, const QString &from, const QString &detail, const VNMask visibility, const MythNotification::Priority priority)
convenience utility to display error message as notification
Definition: mythnotificationcenter.cpp:1427
MediaMonitor::GetMedias
QList< MythMediaDevice * > GetMedias(unsigned mediatypes)
Ask for available media. Must be locked with ValidateAndLock().
Definition: mythmediamonitor.cpp:612
MediaMonitor::m_removedDevices
QList< MythMediaDevice * > m_removedDevices
Definition: mythmediamonitor.h:126
MediaMonitor::selectDrivePopup
MythMediaDevice * selectDrivePopup(const QString &label, bool showMounted=false, bool showUsable=false)
List removable drives, let the user select one.
Definition: mythmediamonitor.cpp:182
mediamonitor-windows.h
ShowNotification
void ShowNotification(const QString &msg, const QString &from, const QString &detail, const VNMask visibility, const MythNotification::Priority priority)
Definition: mythnotificationcenter.cpp:1438
MythCoreContext::ResetSockets
void ResetSockets(void)
Definition: mythcorecontext.cpp:1821
DevName
static QString DevName(MythMediaDevice *d)
Definition: mythmediamonitor.cpp:128
MediaMonitor::GetMediaMonitor
static MediaMonitor * GetMediaMonitor(void)
Definition: mythmediamonitor.cpp:84
MonitorThread::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: mythmediamonitor.cpp:51
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:303
mythcdrom.h
MediaMonitor::GetRemovable
QList< MythMediaDevice * > GetRemovable(bool showMounted=false, bool showUsable=false)
Generate a list of removable drives.
Definition: mythmediamonitor.cpp:154
MediaMonitor::StartMonitoring
virtual void StartMonitoring(void)
Start the monitoring thread if needed.
Definition: mythmediamonitor.cpp:455
MediaMonitor::defaultDevice
static QString defaultDevice(const QString &setting, const QString &label, const char *hardCodedDefault)
Definition: mythmediamonitor.cpp:855
MediaMonitor::MediaMonitor
MediaMonitor(QObject *par, unsigned long interval, bool allowEject)
Lookup some settings, and do OS-specific stuff in sub-classes.
Definition: mythmediamonitor.cpp:342
MEDIASTAT_ERROR
@ MEDIASTAT_ERROR
Unable to mount, but could be usable.
Definition: mythmedia.h:13
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
mythmediamonitor.h
MEDIASTAT_USEABLE
@ MEDIASTAT_USEABLE
Definition: mythmedia.h:19
getSymlinkTarget
QString getSymlinkTarget(const QString &start_file, QStringList *intermediaries, unsigned maxLinks)
Definition: mythmiscutil.cpp:457
MythMediaDevice::getDevicePath
const QString & getDevicePath() const
Definition: mythmedia.h:61
MediaMonitor::m_monitorPollingInterval
unsigned long m_monitorPollingInterval
Definition: mythmediamonitor.h:135
MythMediaDevice::getStatus
MythMediaStatus getStatus() const
Definition: mythmedia.h:70
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
MediaMonitor::MonitorThread
friend class MonitorThread
Definition: mythmediamonitor.h:50
MythDialogBox::Closed
void Closed(QString, int)
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:724
MediaMonitor::s_monitor
static MediaMonitor * s_monitor
Definition: mythmediamonitor.h:140
MediaMonitor::GetMedia
MythMediaDevice * GetMedia(const QString &path)
Get media device by pathname. Must be locked with ValidateAndLock().
Definition: mythmediamonitor.cpp:541
MEDIASTAT_MOUNTED
@ MEDIASTAT_MOUNTED
Definition: mythmedia.h:21
myth_system
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
Definition: mythsystemlegacy.cpp:506
sLocation
static const QString sLocation
Definition: mythmediamonitor.cpp:36
HasMythMainWindow
bool HasMythMainWindow(void)
Definition: mythmainwindow.cpp:107
MonitorThread::m_lastCheckTime
QDateTime m_lastCheckTime
Definition: mythmediamonitor.h:44
MediaMonitor::SetCDSpeed
static void SetCDSpeed(const char *device, int speed)
Definition: mythmediamonitor.cpp:100
MythMediaEvent::kEventType
static Type kEventType
Definition: mythmedia.h:193
MediaMonitor::CheckDevices
void CheckDevices(void)
Poll the devices in our list.
Definition: mythmediamonitor.cpp:435
MEDIASTAT_UNPLUGGED
@ MEDIASTAT_UNPLUGGED
Definition: mythmedia.h:15
mythsystemlegacy.h
MythMediaDevice::isMounted
bool isMounted(bool bVerify=true)
Tells us if m_devicePath is a mounted device.
Definition: mythmedia.cpp:358
MediaMonitor::RegisterMediaHandler
void RegisterMediaHandler(const QString &destination, const QString &description, void(*callback)(MythMediaDevice *), int mediaType, const QString &extensions)
Register a handler for media related events.
Definition: mythmediamonitor.cpp:651
mythdate.h
mythlogging.h
MythMediaDevice::setSpeed
virtual void setSpeed(int speed)
Definition: mythmedia.cpp:332
MythMediaDevice::getRealDevice
const QString & getRealDevice() const
Definition: mythmedia.h:63
MediaMonitor::StopMonitoring
void StopMonitoring(void)
Stop the monitoring thread if needed.
Definition: mythmediamonitor.cpp:478
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:166
MythMediaDevice::clearData
void clearData()
Definition: mythmedia.cpp:509
MythMediaEvent
Definition: mythmedia.h:183
MythMediaDevice::unlock
virtual MythMediaError unlock()
Definition: mythmedia.cpp:350
MediaMonitor::CheckDeviceNotifications
virtual void CheckDeviceNotifications(void)
Definition: mythmediamonitor.h:104
MonitorThread::m_monitor
QPointer< MediaMonitor > m_monitor
Definition: mythmediamonitor.h:42
MythMediaDevice::unmount
bool unmount()
Definition: mythmedia.h:108
MediaMonitor::Unlock
void Unlock(MythMediaDevice *pMedia)
decrements the MythMediaDevices reference count
Definition: mythmediamonitor.cpp:518
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
MythCDROM
Definition: mythcdrom.h:6
handlers
static QList< GameHandler * > * handlers
Definition: gamehandler.cpp:27
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:61
MediaMonitor::m_ignoreList
QStringList m_ignoreList
Definition: mythmediamonitor.h:130
MediaMonitor
Definition: mythmediamonitor.h:47
MediaMonitor::m_handlerMap
QMap< QString, MHData > m_handlerMap
Registered Media Handlers.
Definition: mythmediamonitor.h:138
MediaMonitor::listDevices
QString listDevices(void)
A string summarising the current devices, for debugging.
Definition: mythmediamonitor.cpp:949
MediaMonitor::RemoveDevice
bool RemoveDevice(const QString &dev)
Remove a device from the media monitor.
Definition: mythmediamonitor.cpp:399
MediaMonitor::shouldIgnore
bool shouldIgnore(const MythMediaDevice *device)
Check user preferences to see if this device should be monitored.
Definition: mythmediamonitor.cpp:771
MediaMonitorDarwin
Definition: mediamonitor-darwin.h:21
MediaMonitor::defaultDVDWriter
static QString defaultDVDWriter()
MythArchiveDVDLocation, user-selected drive, or /dev/dvd.
Definition: mythmediamonitor.cpp:937
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:929
MediaMonitor::m_thread
MonitorThread * m_thread
Definition: mythmediamonitor.h:134
MythMediaDevice::eject
virtual MythMediaError eject(bool open_close=true)
Definition: mythmedia.cpp:307
MythMediaDevice::RegisterMediaExtensions
static void RegisterMediaExtensions(uint mediatype, const QString &extensions)
Used to register media types with extensions.
Definition: mythmedia.cpp:299
MediaMonitor::m_active
bool volatile m_active
Was MonitorThread started?
Definition: mythmediamonitor.h:132
MythCDROM::get
static MythCDROM * get(QObject *par, const QString &devicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom.cpp:43
MythMediaType
MythMediaType
Definition: mythmedia.h:24
MediaMonitor::m_useCount
QMap< MythMediaDevice *, int > m_useCount
Definition: mythmediamonitor.h:127
mythmiscutil.h
MEDIASTAT_NODISK
@ MEDIASTAT_NODISK
CD/DVD tray closed but empty, device unusable.
Definition: mythmedia.h:17
mythcorecontext.h
DEFAULT_DVD
#define DEFAULT_DVD
Definition: mediamonitor-darwin.h:4
MONITOR_INTERVAL
#define MONITOR_INTERVAL
Definition: mythmediamonitor.cpp:82
MediaMonitor::EjectMedia
void EjectMedia(const QString &path)
Definition: mythmediamonitor.cpp:274
MythMediaDevice::kMediaStatusStrings
static const std::array< const QString, 9 > kMediaStatusStrings
Definition: mythmedia.h:117
MonitorThread::m_interval
unsigned long m_interval
Definition: mythmediamonitor.h:43
MHData
Stores details of media handlers.
Definition: mythmediamonitor.h:24
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
MythMediaDevice::checkMedia
virtual MythMediaStatus checkMedia()=0
MythCDROM::setDeviceSpeed
void setDeviceSpeed(const char *devicePath, int speed) override
Definition: mythcdrom.cpp:140
MythMediaDevice::getMediaType
MythMediaType getMediaType() const
Definition: mythmedia.h:91
MediaMonitorWindows
Definition: mediamonitor-windows.h:9
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:102
MEDIASTAT_OPEN
@ MEDIASTAT_OPEN
CD/DVD tray open (meaningless for non-CDs?)
Definition: mythmedia.h:16
MediaMonitor::defaultCDWriter
static QString defaultCDWriter()
CDWriterDeviceLocation, user-selected drive, or /dev/cdrom.
Definition: mythmediamonitor.cpp:925
MediaMonitor::defaultDVDdevice
static QString defaultDVDdevice()
DVDDeviceLocation, user-selected drive, or /dev/dvd.
Definition: mythmediamonitor.cpp:916
MediaMonitor::ValidateAndLock
bool ValidateAndLock(MythMediaDevice *pMedia)
Validates the MythMediaDevice and increments its reference count.
Definition: mythmediamonitor.cpp:501
MEDIAERR_FAILED
@ MEDIAERR_FAILED
Definition: mythmedia.h:41
MythMediaError
MythMediaError
Definition: mythmedia.h:39
MythMediaDevice
Definition: mythmedia.h:48
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
mediamonitor-unix.h
MediaMonitor::deleteLater
virtual void deleteLater(void)
Definition: mythmediamonitor.cpp:380
MediaMonitor::JumpToMediaHandler
void JumpToMediaHandler(MythMediaDevice *pMedia)
Find a relevant jump point for this type of media.
Definition: mythmediamonitor.cpp:689
MEDIAERR_OK
@ MEDIAERR_OK
Definition: mythmedia.h:40
MEDIASTAT_UNKNOWN
@ MEDIASTAT_UNKNOWN
Definition: mythmedia.h:14
MEDIAERR_UNSUPPORTED
@ MEDIAERR_UNSUPPORTED
Definition: mythmedia.h:42
MythMainWindow::RestartInputHandlers
void RestartInputHandlers()
Definition: mythmainwindow.cpp:2094
mediamonitor-darwin.h
MediaMonitorUnix
Definition: mediamonitor-unix.h:16
MythMediaStatus
MythMediaStatus
Definition: mythmedia.h:12
mythmainwindow.h
DEFAULT_CD
#define DEFAULT_CD
Definition: mediamonitor-darwin.h:5
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:50
MediaMonitor::ChooseAndEjectMedia
void ChooseAndEjectMedia(void)
Unmounts and ejects removable media devices.
Definition: mythmediamonitor.cpp:255
MediaMonitor::defaultVCDdevice
static QString defaultVCDdevice()
VCDDeviceLocation, user-selected drive, or /dev/cdrom.
Definition: mythmediamonitor.cpp:907
MythMainWindow
Definition: mythmainwindow.h:35
MediaMonitor::m_devicesLock
QRecursiveMutex m_devicesLock
Definition: mythmediamonitor.h:123
MythMediaDevice::findMountPath
bool findMountPath()
Try to find a mount of m_devicePath in the mounts file.
Definition: mythmedia.cpp:366
MediaMonitor::defaultCDdevice
static QString defaultCDdevice()
CDDevice, user-selected drive, or /dev/cdrom.
Definition: mythmediamonitor.cpp:899
MEDIASTAT_NOTMOUNTED
@ MEDIASTAT_NOTMOUNTED
Definition: mythmedia.h:20
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:921
MediaMonitor::GetMountPath
static QString GetMountPath(const QString &devPath)
If the device is being monitored, return its mountpoint.
Definition: mythmediamonitor.cpp:565
MythMediaDevice::MediaTypeString
QString MediaTypeString()
Definition: mythmedia.cpp:516