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 // Nice and simple, as long as our monitor is valid and active,
41 // loop and check it's devices.
43 {
44  RunProlog();
45  QMutex mtx;
46  mtx.lock();
47  while (m_monitor && m_monitor->IsActive())
48  {
49  m_monitor->CheckDevices();
50  m_monitor->m_wait.wait(&mtx, m_interval);
51  QDateTime now(QDateTime::currentDateTimeUtc());
52  // if 10 seconds have elapsed instead of 5 seconds
53  // assume the system was suspended and reconnect
54  // sockets
55  if (m_lastCheckTime.secsTo(now) > 120)
56  {
58  if (HasMythMainWindow())
59  {
60  LOG(VB_GENERAL, LOG_INFO, "Restarting LIRC handler");
62  }
63  }
64  m_lastCheckTime = now;
65  }
66  mtx.unlock();
67  RunEpilog();
68 }
69 
71 // MediaMonitor
72 
73 static constexpr unsigned long MONITOR_INTERVAL { 5000 };
74 
76 {
77  if (s_monitor)
78  return s_monitor;
79 
80 #ifdef USING_DARWIN_DA
81  s_monitor = new MediaMonitorDarwin(nullptr, MONITOR_INTERVAL, true);
82 #elif defined(Q_OS_WIN)
83  s_monitor = new MediaMonitorWindows(nullptr, MONITOR_INTERVAL, true);
84 #else
85  s_monitor = new MediaMonitorUnix(nullptr, MONITOR_INTERVAL, true);
86 #endif
87 
88  return s_monitor;
89 }
90 
91 void MediaMonitor::SetCDSpeed(const char *device, int speed)
92 {
94  if (mon)
95  {
96  MythMediaDevice *pMedia = mon->GetMedia(device);
97  if (pMedia && mon->ValidateAndLock(pMedia))
98  {
99  pMedia->setSpeed(speed);
100  mon->Unlock(pMedia);
101  return;
102  }
103  }
104 
105  MythCDROM *cd = MythCDROM::get(nullptr, device, false, false);
106  if (cd)
107  {
108  cd->setDeviceSpeed(device, speed);
109  delete cd;
110  return;
111  }
112 
113  LOG(VB_MEDIA, LOG_INFO,
114  QString("MediaMonitor::setSpeed(%1) - Cannot find/create CDROM?")
115  .arg(device));
116 }
117 
118 // When ejecting one of multiple devices, present a nice name to the user
119 static QString DevName(MythMediaDevice *d)
120 {
121  QString str = d->getVolumeID(); // First choice, the name of the media
122 
123  if (str.isEmpty())
124  {
125  str = d->getDeviceModel(); // otherwise, the drive manufacturer/model
126 
127  if (!str.isEmpty()) // and/or the device node
128  str += " (" + d->getDevicePath() + ')';
129  else
130  str = d->getDevicePath();
131  }
132  // We could add even more information here, but volume names
133  // are usually descriptively unique (i.e. usually good enough)
134  //else
135  // str += " (" + d->getDeviceModel() + ", " + d->getDevicePath() + ')';
136 
137  return str;
138 }
139 
145 QList<MythMediaDevice*> MediaMonitor::GetRemovable(bool showMounted,
146  bool showUsable)
147 {
148  QList <MythMediaDevice *> drives;
149  QList <MythMediaDevice *>::iterator it;
150  QMutexLocker locker(&m_devicesLock);
151 
152  for (it = m_devices.begin(); it != m_devices.end(); ++it)
153  {
154  // By default, we only list CD/DVD devices.
155  // Caller can also request mounted drives to be listed (e.g. USB flash)
156 
157  if (showUsable && !(*it)->isUsable())
158  continue;
159 
160  if (QString(typeid(**it).name()).contains("MythCDROM") ||
161  (showMounted && (*it)->isMounted(false)))
162  drives.append(*it);
163  }
164 
165  return drives;
166 }
167 
174  bool showMounted,
175  bool showUsable)
176 {
177  QList <MythMediaDevice *> drives = GetRemovable(showMounted,
178  showUsable);
179 
180  if (drives.count() == 0)
181  {
182  QString msg = "MediaMonitor::selectDrivePopup() - no removable devices";
183 
184  LOG(VB_MEDIA, LOG_INFO, msg);
185  return nullptr;
186  }
187 
188  if (drives.count() == 1)
189  {
190  LOG(VB_MEDIA, LOG_INFO,
191  "MediaMonitor::selectDrivePopup(" + label +
192  ") - One suitable device");
193  return drives.front();
194  }
195 
197  if (!win)
198  return nullptr;
199 
200  MythScreenStack *stack = win->GetMainStack();
201  if (!stack)
202  return nullptr;
203 
204  // Ignore MENU dialog actions
205  int btnIndex = -2;
206  while (btnIndex < -1)
207  {
208  auto *dlg = new MythDialogBox(label, stack, "select drive");
209  if (!dlg->Create())
210  {
211  delete dlg;
212  return nullptr;
213  }
214 
215  // Add button for each drive
216  for (auto *drive : drives)
217  dlg->AddButton(DevName(drive));
218 
219  dlg->AddButton(tr("Cancel"));
220 
221  stack->AddScreen(dlg);
222 
223  // Wait in local event loop so events are processed
224  QEventLoop block;
225  connect(dlg, &MythDialogBox::Closed,
226  &block, [&](const QString& /*resultId*/, int result) { block.exit(result); });
227 
228  // Block until dialog closes
229  btnIndex = block.exec();
230  }
231 
232  // If the user cancelled, return a special value
233  return btnIndex < 0 || btnIndex >= drives.size() ? (MythMediaDevice *)-1
234  : drives.at(btnIndex);
235 }
236 
237 
247 {
248  MythMediaDevice *selected =
249  selectDrivePopup(tr("Select removable media to eject or insert"), true);
250 
251  // If the user cancelled, no need to display or do anything more
252  if (selected == (MythMediaDevice *) -1)
253  return;
254 
255  if (!selected)
256  {
257  ShowNotification(tr("No devices to eject"), sLocation);
258  return;
259  }
260 
261  AttemptEject(selected);
262 }
263 
264 
265 void MediaMonitor::EjectMedia(const QString &path)
266 {
267  MythMediaDevice *device = GetMedia(path);
268  if (device)
269  AttemptEject(device);
270 }
271 
272 
274 {
275  QString dev = DevName(device);
276 
277  if (device->getStatus() == MEDIASTAT_OPEN)
278  {
279  LOG(VB_MEDIA, LOG_INFO,
280  QString("Disk %1's tray is OPEN. Closing tray").arg(dev));
281 
282  if (device->eject(false) != MEDIAERR_OK)
283  {
284  QString msg =
285  QObject::tr("Unable to open or close the empty drive %1");
286  QString extra =
287  QObject::tr("You may have to use the eject button under its tray");
288  ShowNotificationError(msg.arg(dev), sLocation, extra);
289  }
290  return;
291  }
292 
293  if (device->isMounted())
294  {
295  LOG(VB_MEDIA, LOG_INFO,
296  QString("Disk %1 is mounted? Unmounting").arg(dev));
297  device->unmount();
298 
299 #ifndef Q_OS_DARWIN
300  if (device->isMounted())
301  {
302  ShowNotificationError(tr("Failed to unmount %1").arg(dev),
303  sLocation);
304  return;
305  }
306 #endif
307  }
308 
309  LOG(VB_MEDIA, LOG_INFO,
310  QString("Unlocking disk %1, then ejecting").arg(dev));
311  device->unlock();
312 
313  MythMediaError err = device->eject();
314 
315  if (err == MEDIAERR_UNSUPPORTED)
316  {
317  // Physical ejection isn't possible (there is no tray or slot),
318  // but logically the device is now ejected (ignored by the OS).
319  ShowNotification(tr("You may safely remove %1").arg(dev), sLocation);
320  }
321  else if (err == MEDIAERR_FAILED)
322  {
323  ShowNotificationError(tr("Failed to eject %1").arg(dev), sLocation);
324  }
325 }
326 
333 MediaMonitor::MediaMonitor(QObject* par, unsigned long interval, bool allowEject)
334  : QObject(par),
335  m_monitorPollingInterval(interval),
336  m_allowEject(allowEject)
337 {
338  // User can specify that some devices are not monitored
339  QString ignore = gCoreContext->GetSetting("IgnoreDevices", "");
340 
341  if (!ignore.isEmpty())
342  {
343 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
344  m_ignoreList = ignore.split(',', QString::SkipEmptyParts);
345 #else
346  m_ignoreList = ignore.split(',', Qt::SkipEmptyParts);
347 #endif
348  }
349 
350  LOG(VB_MEDIA, LOG_NOTICE, "Creating MediaMonitor");
351  LOG(VB_MEDIA, LOG_INFO, "IgnoreDevices=" + ignore);
352 
353  // If any of IgnoreDevices are symlinks, also add the real device
354  QStringList symlinked;
355  for (const auto & ignored : qAsConst(m_ignoreList))
356  {
357  if (auto fi = QFileInfo(ignored); fi.isSymLink())
358  {
359  if (auto target = getSymlinkTarget(ignored); m_ignoreList.filter(target).isEmpty())
360  {
361  symlinked += target;
362  LOG(VB_MEDIA, LOG_INFO, QString("Also ignoring %1 (symlinked from %2)")
363  .arg(target, ignored));
364  }
365  }
366  }
367 
368  m_ignoreList += symlinked;
369 }
370 
372 {
373  if (m_thread)
374  {
375  StopMonitoring();
376  delete m_thread;
377  m_thread = nullptr;
378  }
379  QObject::deleteLater();
380 }
381 
390 bool MediaMonitor::RemoveDevice(const QString &dev)
391 {
392  QMutexLocker locker(&m_devicesLock);
393 
394  QList<MythMediaDevice*>::iterator it;
395  for (it = m_devices.begin(); it != m_devices.end(); ++it)
396  {
397  if ((*it)->getDevicePath() == dev)
398  {
399  // Ensure device gets an unmount
400  (*it)->checkMedia();
401 
402  if (m_useCount[*it] == 0)
403  {
404  m_useCount.remove(*it);
405  (*it)->deleteLater();
406  m_devices.erase(it);
407  }
408  else
409  {
410  // Other threads are still using this device
411  // postpone actual delete until they finish.
412  disconnect(*it);
413  m_removedDevices.append(*it);
414  m_devices.erase(it);
415  }
416 
417  return true;
418  }
419  }
420  return false;
421 }
422 
427 {
428  /* check if new devices have been plugged in */
430 
431  QMutexLocker locker(&m_devicesLock);
432 
433  QList<MythMediaDevice*>::iterator itr = m_devices.begin();
434  while (itr != m_devices.end())
435  {
436  MythMediaDevice* pDev = *itr;
437  if (pDev)
438  pDev->checkMedia();
439  ++itr;
440  }
441 }
442 
447 {
448  // Sanity check
449  if (m_active)
450  return;
451  if (!gCoreContext->GetBoolSetting("MonitorDrives", false)) {
452  LOG(VB_MEDIA, LOG_NOTICE, "MediaMonitor disabled by user setting.");
453  return;
454  }
455 
456  if (!m_thread)
458 
459  qRegisterMetaType<MythMediaStatus>("MythMediaStatus");
460 
461  LOG(VB_MEDIA, LOG_NOTICE, "Starting MediaMonitor");
462  m_active = true;
463  m_thread->start();
464 }
465 
470 {
471  // Sanity check
472  if (!m_active)
473  return;
474 
475  LOG(VB_MEDIA, LOG_NOTICE, "Stopping MediaMonitor");
476  m_active = false;
477  m_wait.wakeAll();
478  m_thread->wait();
479  LOG(VB_MEDIA, LOG_NOTICE, "Stopped MediaMonitor");
480 }
481 
493 {
494  QMutexLocker locker(&m_devicesLock);
495 
496  if (!m_devices.contains(pMedia))
497  return false;
498 
499  m_useCount[pMedia]++;
500 
501  return true;
502 }
503 
510 {
511  QMutexLocker locker(&m_devicesLock);
512 
513  if (!m_useCount.contains(pMedia))
514  return;
515 
516  m_useCount[pMedia]--;
517 
518  if (m_useCount[pMedia] == 0 && m_removedDevices.contains(pMedia))
519  {
520  m_removedDevices.removeAll(pMedia);
521  m_useCount.remove(pMedia);
522  pMedia->deleteLater();
523  }
524 }
525 
533 {
534  QMutexLocker locker(&m_devicesLock);
535 
536  for (auto *dev : qAsConst(m_devices))
537  {
538  if (dev->isSameDevice(path) &&
539  ((dev->getStatus() == MEDIASTAT_USEABLE) ||
540  (dev->getStatus() == MEDIASTAT_MOUNTED) ||
541  (dev->getStatus() == MEDIASTAT_NOTMOUNTED)))
542  {
543  return dev;
544  }
545  }
546 
547  return nullptr;
548 }
549 
556 QString MediaMonitor::GetMountPath(const QString& devPath)
557 {
558  QString mountPath;
559 
560  if (s_monitor)
561  {
562  MythMediaDevice *pMedia = s_monitor->GetMedia(devPath);
563  if (pMedia && s_monitor->ValidateAndLock(pMedia))
564  {
565  mountPath = pMedia->getMountPath();
566  s_monitor->Unlock(pMedia);
567  }
568  // The media monitor could be inactive.
569  // Create a fake media device just to lookup mount map:
570  else
571  {
572  pMedia = MythCDROM::get(nullptr, devPath.toLatin1(), true, false);
573  if (pMedia && pMedia->findMountPath())
574  mountPath = pMedia->getMountPath();
575  else
576  LOG(VB_MEDIA, LOG_INFO,
577  "MediaMonitor::GetMountPath() - failed");
578  // need some way to delete the media device.
579  }
580  }
581 
582  return mountPath;
583 }
584 
603 QList<MythMediaDevice*> MediaMonitor::GetMedias(unsigned mediatypes)
604 {
605  QMutexLocker locker(&m_devicesLock);
606 
607  QList<MythMediaDevice*> medias;
608 
609  for (auto *dev : qAsConst(m_devices))
610  {
611  if ((dev->getMediaType() & mediatypes) &&
612  ((dev->getStatus() == MEDIASTAT_USEABLE) ||
613  (dev->getStatus() == MEDIASTAT_MOUNTED) ||
614  (dev->getStatus() == MEDIASTAT_NOTMOUNTED)))
615  {
616  medias.push_back(dev);
617  }
618  }
619 
620  return medias;
621 }
622 
642 void MediaMonitor::RegisterMediaHandler(const QString &destination,
643  const QString &description,
644  void (*callback)
645  (MythMediaDevice*),
646  int mediaType,
647  const QString &extensions)
648 {
649  if (m_handlerMap.count(destination) == 0)
650  {
651  MHData mhd = { callback, mediaType, destination, description };
652  QString msg = MythMediaDevice::MediaTypeString((MythMediaType)mediaType);
653 
654  if (!extensions.isEmpty())
655  msg += QString(", ext(%1)").arg(extensions);
656 
657  LOG(VB_MEDIA, LOG_INFO,
658  "Registering '" + destination + "' as a media handler for " +
659  msg);
660 
661  m_handlerMap[destination] = mhd;
662 
663  if (!extensions.isEmpty())
664  MythMediaDevice::RegisterMediaExtensions(mediaType, extensions);
665  }
666  else
667  {
668  LOG(VB_GENERAL, LOG_INFO,
669  destination + " is already registered as a media handler.");
670  }
671 }
672 
681 {
682  QVector<MHData> handlers;
683  QMap<QString, MHData>::Iterator itr = m_handlerMap.begin();
684 
685  while (itr != m_handlerMap.end())
686  {
687  if (((*itr).MythMediaType & (int)pMedia->getMediaType()))
688  {
689  LOG(VB_GENERAL, LOG_NOTICE,
690  QString("Found a handler for %1 - '%2'")
691  .arg(pMedia->MediaTypeString(), itr.key()));
692  handlers.append(*itr);
693  }
694  itr++;
695  }
696 
697  if (handlers.empty())
698  {
699  LOG(VB_MEDIA, LOG_INFO, "No media handler found for event type");
700  return;
701  }
702 
703 
704  // TODO - Generate a dialog, add buttons for each description,
705  // if user didn't cancel, selected = handlers.at(choice);
706  int selected = 0;
707 
708  handlers.at(selected).callback(pMedia);
709 }
710 
716  MythMediaDevice* pMedia) const
717 {
718  // If we're not active then ignore signal.
719  if (!m_active)
720  return;
721 
722  MythMediaStatus stat = pMedia->getStatus();
723  QString msg = QString(" (%1, %2 -> %3)")
724  .arg(pMedia->MediaTypeString(),
727 
728  // This gets called from outside the main thread so we need
729  // to post an event back to the main thread.
730  // We now send events for all non-error statuses, so plugins get ejects
731  if (stat != MEDIASTAT_ERROR && stat != MEDIASTAT_UNKNOWN &&
732  // Don't send an event for a new device that's not mounted
733  (oldStatus != MEDIASTAT_UNPLUGGED || stat != MEDIASTAT_NOTMOUNTED))
734  {
735  // Should we ValidateAndLock() first?
736  QEvent *e = new MythMediaEvent(stat, pMedia);
737 
738  LOG(VB_MEDIA, LOG_INFO, "Posting MediaEvent" + msg);
739 
740  // sendEvent() is needed here - it waits for the event to be used.
741  // postEvent() would result in pDevice's media type changing
742  // ... before the plugin's event chain would process it.
743  // Another way would be to send an exact copy of pDevice instead.
744  QCoreApplication::sendEvent((QObject*)GetMythMainWindow(), e);
745  delete e;
746  }
747  else
748  LOG(VB_MEDIA, LOG_INFO,
749  "Media status changed, but not sending event" + msg);
750 
751 
752  if (stat == MEDIASTAT_OPEN || stat == MEDIASTAT_NODISK
753  || stat == MEDIASTAT_UNPLUGGED)
754  {
755  pMedia->clearData();
756  }
757 }
758 
763 {
764  if (m_ignoreList.contains(device->getMountPath()) ||
765  m_ignoreList.contains(device->getRealDevice())||
766  m_ignoreList.contains(device->getDevicePath()) )
767  {
768  LOG(VB_MEDIA, LOG_INFO,
769  "Ignoring device: " + device->getDevicePath());
770  return true;
771  }
772 #if 0
773  else
774  {
775  LOG(VB_MEDIA, LOG_DEBUG,
776  "Not ignoring: " + device->getDevicePath() + " / " +
777  device->getMountPath());
778  LOG(VB_MEDIA, LOG_DEBUG,
779  "Paths not in: " + m_ignoreList.join(", "));
780  }
781 #endif
782 
783  return false;
784 }
785 
790 bool MediaMonitor::eventFilter(QObject *obj, QEvent *event)
791 {
792  if (event->type() == MythMediaEvent::kEventType)
793  {
794  auto *me = dynamic_cast<MythMediaEvent *>(event);
795  if (me == nullptr)
796  {
797  LOG(VB_GENERAL, LOG_ALERT,
798  "MediaMonitor::eventFilter() couldn't cast event");
799  return true;
800  }
801 
802  MythMediaDevice *pDev = me->getDevice();
803  if (!pDev)
804  {
805  LOG(VB_GENERAL, LOG_ALERT,
806  "MediaMonitor::eventFilter() got a bad media event?");
807  return true;
808  }
809 
810  if (pDev->isUsable())
811  JumpToMediaHandler(pDev);
812  else
813  {
814  // We don't want to jump around in the menus, but should
815  // call each plugin's callback so it can track this change.
816 
817  QMap<QString, MHData>::Iterator itr = m_handlerMap.begin();
818  while (itr != m_handlerMap.end())
819  {
820  if ((*itr).MythMediaType & (int)pDev->getMediaType() ||
821  pDev->getStatus() == MEDIASTAT_OPEN)
822  (*itr).callback(pDev);
823  itr++;
824  }
825  }
826 
827  return false; // Don't eat the event
828  }
829 
830  // standard event processing
831  return QObject::eventFilter(obj, event);
832 }
833 
834 /*
835  * These methods return the user's preferred devices for playing and burning
836  * CDs and DVDs. Traditionally we had a database setting to remember this,
837  * but that is a bit wasteful when most users only have one drive.
838  *
839  * To make it a bit more beginner friendly, if no database default exists,
840  * or if it contains "default", the code tries to find a monitored drive.
841  * If, still, nothing is suitable, a caller hard-coded default is used.
842  *
843  * Ideally, these would return a MythMediaDevice * instead of a QString
844  */
845 
846 QString MediaMonitor::defaultDevice(const QString &dbSetting,
847  const QString &label,
848  const char *hardCodedDefault)
849 {
850  QString device = gCoreContext->GetSetting(dbSetting);
851 
852  LOG(VB_MEDIA, LOG_DEBUG,
853  QString("MediaMonitor::defaultDevice(%1,..,%2) dbSetting='%3'")
854  .arg(dbSetting, hardCodedDefault, device));
855 
856  // No settings database defaults? Try to choose one:
857  if (device.isEmpty() || device == "default")
858  {
859  device = hardCodedDefault;
860 
861  if (!s_monitor)
863 
864  if (s_monitor)
865  {
866  MythMediaDevice *d = s_monitor->selectDrivePopup(label, false, true);
867 
868  if (d == (MythMediaDevice *) -1) // User cancelled
869  {
870  device.clear(); // If user has explicitly cancelled return empty string
871  d = nullptr;
872  }
873 
874  if (d && s_monitor->ValidateAndLock(d))
875  {
876  device = d->getDevicePath();
877  s_monitor->Unlock(d);
878  }
879  }
880  }
881 
882  LOG(VB_MEDIA, LOG_DEBUG,
883  "MediaMonitor::defaultDevice() returning " + device);
884  return device;
885 }
886 
891 {
892  return defaultDevice("CDDevice", tr("Select a CD drive"), DEFAULT_CD);
893 }
894 
899 {
900  return defaultDevice("VCDDeviceLocation",
901  tr("Select a VCD drive"), DEFAULT_CD);
902 }
903 
908 {
909  return defaultDevice("DVDDeviceLocation",
910  tr("Select a DVD drive"), DEFAULT_DVD);
911 }
912 
917 {
918  return defaultDevice("CDWriterDeviceLocation",
919  tr("Select a CD writer"), DEFAULT_CD);
920 }
921 
929 {
930  QString device = defaultDevice("MythArchiveDVDLocation",
931  tr("Select a DVD writer"), DEFAULT_DVD);
932 
933  return device;
934 }
935 
936 
941 {
942  QStringList list;
943 
944  for (const auto *dev : qAsConst(m_devices))
945  {
946  QString devStr;
947  QString model = dev->getDeviceModel();
948  const QString& path = dev->getDevicePath();
949  const QString& real = dev->getRealDevice();
950 
951  if (path != real)
952  devStr += path + "->";
953  devStr += real;
954 
955  if (model.isEmpty())
956  model = "unknown";
957  devStr += " (" + model + ")";
958 
959  list += devStr;
960  }
961 
962  return list.join(", ");
963 }
964 
972 {
974  if (mon)
975  mon->ChooseAndEjectMedia();
976  else
977  {
978  LOG(VB_MEDIA, LOG_INFO, "CD/DVD Monitor isn't enabled.");
979 #ifdef __linux__
980  LOG(VB_MEDIA, LOG_INFO, "Trying Linux 'eject -T' command");
981  myth_system("eject -T");
982 #elif defined(Q_OS_DARWIN)
983  QString def = DEFAULT_CD;
984  LOG(VB_MEDIA, LOG_INFO, "Trying 'diskutil eject " + def);
985  myth_system("diskutil eject " + def);
986 #endif
987  }
988 }
989 
990 /*
991  * vim:ts=4:sw=4:ai:et:si:sts=4
992  */
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:127
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:318
MediaMonitor::AttemptEject
static void AttemptEject(MythMediaDevice *device)
Definition: mythmediamonitor.cpp:273
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
MediaMonitor::m_wait
QWaitCondition m_wait
Definition: mythmediamonitor.h:135
MONITOR_INTERVAL
static constexpr unsigned long MONITOR_INTERVAL
Definition: mythmediamonitor.cpp:73
MediaMonitor::ejectOpticalDisc
static void ejectOpticalDisc(void)
Eject a disk, unmount a drive, open a tray.
Definition: mythmediamonitor.cpp:971
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:790
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:1426
MediaMonitor::GetMedias
QList< MythMediaDevice * > GetMedias(unsigned mediatypes)
Ask for available media. Must be locked with ValidateAndLock().
Definition: mythmediamonitor.cpp:603
MediaMonitor::m_removedDevices
QList< MythMediaDevice * > m_removedDevices
Definition: mythmediamonitor.h:128
MediaMonitor::selectDrivePopup
MythMediaDevice * selectDrivePopup(const QString &label, bool showMounted=false, bool showUsable=false)
List removable drives, let the user select one.
Definition: mythmediamonitor.cpp:173
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:1437
MythCoreContext::ResetSockets
void ResetSockets(void)
Definition: mythcorecontext.cpp:1795
DevName
static QString DevName(MythMediaDevice *d)
Definition: mythmediamonitor.cpp:119
MediaMonitor::GetMediaMonitor
static MediaMonitor * GetMediaMonitor(void)
Definition: mythmediamonitor.cpp:75
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:42
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:300
mythcdrom.h
MediaMonitor::GetRemovable
QList< MythMediaDevice * > GetRemovable(bool showMounted=false, bool showUsable=false)
Generate a list of removable drives.
Definition: mythmediamonitor.cpp:145
MediaMonitor::StartMonitoring
virtual void StartMonitoring(void)
Start the monitoring thread if needed.
Definition: mythmediamonitor.cpp:446
MediaMonitor::defaultDevice
static QString defaultDevice(const QString &setting, const QString &label, const char *hardCodedDefault)
Definition: mythmediamonitor.cpp:846
MediaMonitor::MediaMonitor
MediaMonitor(QObject *par, unsigned long interval, bool allowEject)
Lookup some settings, and do OS-specific stuff in sub-classes.
Definition: mythmediamonitor.cpp:333
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:451
MythMediaDevice::getDevicePath
const QString & getDevicePath() const
Definition: mythmedia.h:61
MythMediaEvent::kEventType
static const Type kEventType
Definition: mythmedia.h:193
MediaMonitor::m_monitorPollingInterval
unsigned long m_monitorPollingInterval
Definition: mythmediamonitor.h:137
MythMediaDevice::getStatus
MythMediaStatus getStatus() const
Definition: mythmedia.h:70
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::MonitorThread
friend class MonitorThread
Definition: mythmediamonitor.h:52
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:715
MediaMonitor::s_monitor
static MediaMonitor * s_monitor
Definition: mythmediamonitor.h:142
MediaMonitor::GetMedia
MythMediaDevice * GetMedia(const QString &path)
Get media device by pathname. Must be locked with ValidateAndLock().
Definition: mythmediamonitor.cpp:532
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:109
MonitorThread::m_lastCheckTime
QDateTime m_lastCheckTime
Definition: mythmediamonitor.h:46
MediaMonitor::SetCDSpeed
static void SetCDSpeed(const char *device, int speed)
Definition: mythmediamonitor.cpp:91
MediaMonitor::CheckDevices
void CheckDevices(void)
Poll the devices in our list.
Definition: mythmediamonitor.cpp:426
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:356
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:642
mythdate.h
mythlogging.h
MythMediaDevice::setSpeed
virtual void setSpeed(int speed)
Definition: mythmedia.cpp:330
MythMediaDevice::getRealDevice
const QString & getRealDevice() const
Definition: mythmedia.h:63
MediaMonitor::StopMonitoring
void StopMonitoring(void)
Stop the monitoring thread if needed.
Definition: mythmediamonitor.cpp:469
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:166
MythMediaDevice::clearData
void clearData()
Definition: mythmedia.cpp:507
MythMediaEvent
Definition: mythmedia.h:183
MythMediaDevice::unlock
virtual MythMediaError unlock()
Definition: mythmedia.cpp:348
MediaMonitor::CheckDeviceNotifications
virtual void CheckDeviceNotifications(void)
Definition: mythmediamonitor.h:106
MonitorThread::m_monitor
QPointer< MediaMonitor > m_monitor
Definition: mythmediamonitor.h:44
MythMediaDevice::unmount
bool unmount()
Definition: mythmedia.h:108
MediaMonitor::Unlock
void Unlock(MythMediaDevice *pMedia)
decrements the MythMediaDevices reference count
Definition: mythmediamonitor.cpp:509
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:55
MediaMonitor::m_ignoreList
QStringList m_ignoreList
Definition: mythmediamonitor.h:132
MediaMonitor
Definition: mythmediamonitor.h:49
MediaMonitor::m_handlerMap
QMap< QString, MHData > m_handlerMap
Registered Media Handlers.
Definition: mythmediamonitor.h:140
MediaMonitor::listDevices
QString listDevices(void)
A string summarising the current devices, for debugging.
Definition: mythmediamonitor.cpp:940
MediaMonitor::RemoveDevice
bool RemoveDevice(const QString &dev)
Remove a device from the media monitor.
Definition: mythmediamonitor.cpp:390
MediaMonitor::shouldIgnore
bool shouldIgnore(const MythMediaDevice *device)
Check user preferences to see if this device should be monitored.
Definition: mythmediamonitor.cpp:762
MediaMonitorDarwin
Definition: mediamonitor-darwin.h:21
MediaMonitor::defaultDVDWriter
static QString defaultDVDWriter()
MythArchiveDVDLocation, user-selected drive, or /dev/dvd.
Definition: mythmediamonitor.cpp:928
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:905
MediaMonitor::m_thread
MonitorThread * m_thread
Definition: mythmediamonitor.h:136
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:134
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:129
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
MediaMonitor::EjectMedia
void EjectMedia(const QString &path)
Definition: mythmediamonitor.cpp:265
MythMediaDevice::kMediaStatusStrings
static const std::array< const QString, 9 > kMediaStatusStrings
Definition: mythmedia.h:117
MonitorThread::m_interval
unsigned long m_interval
Definition: mythmediamonitor.h:45
MHData
Stores details of media handlers.
Definition: mythmediamonitor.h:24
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:104
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:916
MediaMonitor::defaultDVDdevice
static QString defaultDVDdevice()
DVDDeviceLocation, user-selected drive, or /dev/dvd.
Definition: mythmediamonitor.cpp:907
MediaMonitor::ValidateAndLock
bool ValidateAndLock(MythMediaDevice *pMedia)
Validates the MythMediaDevice and increments its reference count.
Definition: mythmediamonitor.cpp:492
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:371
MediaMonitor::JumpToMediaHandler
void JumpToMediaHandler(MythMediaDevice *pMedia)
Find a relevant jump point for this type of media.
Definition: mythmediamonitor.cpp:680
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:2101
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:52
MediaMonitor::ChooseAndEjectMedia
void ChooseAndEjectMedia(void)
Unmounts and ejects removable media devices.
Definition: mythmediamonitor.cpp:246
MediaMonitor::defaultVCDdevice
static QString defaultVCDdevice()
VCDDeviceLocation, user-selected drive, or /dev/cdrom.
Definition: mythmediamonitor.cpp:898
MythMainWindow
Definition: mythmainwindow.h:28
MediaMonitor::m_devicesLock
QRecursiveMutex m_devicesLock
Definition: mythmediamonitor.h:125
MythMediaDevice::findMountPath
bool findMountPath()
Try to find a mount of m_devicePath in the mounts file.
Definition: mythmedia.cpp:364
MediaMonitor::defaultCDdevice
static QString defaultCDdevice()
CDDevice, user-selected drive, or /dev/cdrom.
Definition: mythmediamonitor.cpp:890
MEDIASTAT_NOTMOUNTED
@ MEDIASTAT_NOTMOUNTED
Definition: mythmedia.h:20
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:897
MediaMonitor::GetMountPath
static QString GetMountPath(const QString &devPath)
If the device is being monitored, return its mountpoint.
Definition: mythmediamonitor.cpp:556
MythMediaDevice::MediaTypeString
QString MediaTypeString()
Definition: mythmedia.cpp:514