MythTV  0.26-pre
mythmediamonitor.cpp
Go to the documentation of this file.
00001 
00002 // Standard C headers
00003 #include <cstdio>
00004 
00005 // C++ headers
00006 #include <iostream>
00007 #include <typeinfo>
00008 using namespace std;
00009 
00010 // Qt headers
00011 #include <QCoreApplication>
00012 #include <QFile>
00013 #include <QList>
00014 #include <QDir>
00015 
00016 // MythTV headers
00017 #include "mythmediamonitor.h"
00018 #include "mythcdrom.h"
00019 #include "mythcorecontext.h"
00020 #include "mythdialogs.h"
00021 #include "mythconfig.h"
00022 #include "mythdialogbox.h"
00023 #include "mythmiscutil.h"
00024 #include "mythlogging.h"
00025 #include "mythmainwindow.h"
00026 
00027 #ifdef USING_DARWIN_DA
00028 #include "mediamonitor-darwin.h"
00029 #elif CONFIG_CYGWIN || defined(_WIN32)
00030 #include "mediamonitor-windows.h"
00031 #else
00032 #include "mediamonitor-unix.h"
00033 #endif
00034 
00035 MediaMonitor *MediaMonitor::c_monitor = NULL;
00036 
00037 // MonitorThread
00038 MonitorThread::MonitorThread(MediaMonitor* pMon, unsigned long interval) :
00039     MThread("Monitor")
00040 {
00041     m_Monitor = pMon;
00042     m_Interval = interval;
00043 }
00044 
00045 // Nice and simple, as long as our monitor is valid and active,
00046 // loop and check it's devices.
00047 void MonitorThread::run(void)
00048 {
00049     RunProlog();
00050     while (m_Monitor && m_Monitor->IsActive())
00051     {
00052         m_Monitor->CheckDevices();
00053         msleep(m_Interval);
00054     }
00055     RunEpilog();
00056 }
00057 
00059 // MediaMonitor
00060 
00061 #define MONITOR_INTERVAL 5000
00062 
00063 MediaMonitor* MediaMonitor::GetMediaMonitor(void)
00064 {
00065     if (c_monitor)
00066         return c_monitor;
00067 
00068 #ifdef USING_DARWIN_DA
00069     c_monitor = new MediaMonitorDarwin(NULL, MONITOR_INTERVAL, true);
00070 #else
00071   #if CONFIG_CYGWIN || defined(_WIN32)
00072     c_monitor = new MediaMonitorWindows(NULL, MONITOR_INTERVAL, true);
00073   #else
00074     c_monitor = new MediaMonitorUnix(NULL, MONITOR_INTERVAL, true);
00075   #endif
00076 #endif
00077 
00078     return c_monitor;
00079 }
00080 
00081 void MediaMonitor::SetCDSpeed(const char *device, int speed)
00082 {
00083     MediaMonitor *mon = GetMediaMonitor();
00084     if (mon)
00085     {
00086         MythMediaDevice *pMedia = mon->GetMedia(device);
00087         if (pMedia && mon->ValidateAndLock(pMedia))
00088         {
00089             pMedia->setSpeed(speed);
00090             mon->Unlock(pMedia);
00091             return;
00092         }
00093     }
00094 
00095     MythCDROM *cd = MythCDROM::get(NULL, device, false, false);
00096     if (cd)
00097     {
00098         cd->setSpeed(device, speed);
00099         delete cd;
00100         return;
00101     }
00102 
00103     LOG(VB_MEDIA, LOG_INFO, 
00104              QString("MediaMonitor::setSpeed(%1) - Cannot find/create CDROM?")
00105                   .arg(device));
00106 }
00107 
00108 // When ejecting one of multiple devices, present a nice name to the user
00109 static const QString DevName(MythMediaDevice *d)
00110 {
00111     QString str = d->getVolumeID();  // First choice, the name of the media
00112 
00113     if (str.isEmpty())
00114     {
00115         str = d->getDeviceModel();   // otherwise, the drive manufacturer/model
00116 
00117         if (!str.isEmpty())                     // and/or the device node
00118             str += " (" + d->getDevicePath() + ')';
00119         else
00120             str = d->getDevicePath();
00121     }
00122     //     We could add even more information here, but volume names
00123     //     are usually descriptively unique (i.e. usually good enough)
00124     //else
00125     //    str += " (" + d->getDeviceModel() + ", " + d->getDevicePath() + ')';
00126 
00127     return str;
00128 }
00129 
00135 QList<MythMediaDevice*> MediaMonitor::GetRemovable(bool showMounted)
00136 {
00137     QList <MythMediaDevice *>           drives;
00138     QList <MythMediaDevice *>::iterator it;
00139     QMutexLocker                        locker(&m_DevicesLock);
00140 
00141     for (it = m_Devices.begin(); it != m_Devices.end(); ++it)
00142     {
00143         // By default, we only list CD/DVD devices.
00144         // Caller can also request mounted drives to be listed (e.g. USB flash)
00145 
00146         if (QString(typeid(**it).name()).contains("MythCDROM") ||
00147                (showMounted && (*it)->isMounted(false)))
00148             drives.append(*it);
00149     }
00150 
00151     return drives;
00152 }
00153 
00159 MythMediaDevice * MediaMonitor::selectDrivePopup(const QString label,
00160                                                  bool          showMounted)
00161 {
00162     QList <MythMediaDevice *> drives = GetRemovable(showMounted);
00163 
00164     if (drives.count() == 0)
00165     {
00166         QString msg = "MediaMonitor::selectDrivePopup() ";
00167         if (m_StartThread)
00168             msg += "- no removable devices";
00169         else
00170             msg += "MonitorDrives is disabled - no device list";
00171 
00172         LOG(VB_MEDIA, LOG_INFO, msg);
00173         return NULL;
00174     }
00175 
00176     if (drives.count() == 1)
00177     {
00178         LOG(VB_MEDIA, LOG_INFO, 
00179                  "MediaMonitor::selectDrivePopup(" + label +
00180                  ") - One suitable device");
00181         return drives.front();
00182     }
00183 
00184     QStringList buttonmsgs;
00185     QList <MythMediaDevice *>::iterator it;
00186     for (it = drives.begin(); it != drives.end(); ++it)
00187         buttonmsgs += DevName(*it);
00188     buttonmsgs += tr("Cancel");
00189     const DialogCode cancelbtn = (DialogCode)
00190         (((int)kDialogCodeButton0) + buttonmsgs.size() - 1);
00191 
00192     DialogCode ret = MythPopupBox::ShowButtonPopup(
00193         GetMythMainWindow(), "select drive", label,
00194         buttonmsgs, cancelbtn);
00195 
00196     // If the user cancelled, return a special value
00197     if ((kDialogCodeRejected == ret) || (cancelbtn == ret))
00198         return (MythMediaDevice *)-1;
00199 
00200     int idx = MythDialog::CalcItemIndex(ret);
00201     if (idx < drives.count())
00202         return drives[idx];
00203 
00204     return NULL;
00205 }
00206 
00207 
00216 void MediaMonitor::ChooseAndEjectMedia(void)
00217 {
00218     MythMediaDevice *selected;
00219 
00220 
00221     selected = selectDrivePopup(tr("Select removable media"
00222                                    " to eject or insert"), true);
00223 
00224     // If the user cancelled, no need to display or do anything more
00225     if (selected == (MythMediaDevice *) -1)
00226         return;
00227 
00228     if (!selected)
00229     {
00230         ShowOkPopup(tr("No devices to eject"));
00231         return;
00232     }
00233 
00234     AttemptEject(selected);
00235 }
00236 
00237 void MediaMonitor::AttemptEject(MythMediaDevice *device)
00238 {
00239     QString  dev = DevName(device);
00240 
00241     if (device->getStatus() == MEDIASTAT_OPEN)
00242     {
00243         LOG(VB_MEDIA, LOG_INFO,
00244                  QString("Disk %1's tray is OPEN. Closing tray").arg(dev));
00245 
00246         if (device->eject(false) != MEDIAERR_OK)
00247         {
00248             QString msg = QObject::tr(
00249                 "Unable to open or close the empty drive %1.\n\n"
00250                 "You may have to use the eject button under its tray.");
00251             ShowOkPopup(msg.arg(dev));
00252         }
00253 
00254         return;
00255     }
00256 
00257     if (device->isMounted())
00258     {
00259         LOG(VB_MEDIA, LOG_INFO,
00260                  QString("Disk %1 is mounted? Unmounting").arg(dev));
00261         device->unmount();
00262 
00263         if (device->isMounted())
00264         {
00265             ShowOkPopup(tr("Failed to unmount %1").arg(dev));
00266             return;
00267         }
00268     }
00269 
00270     LOG(VB_MEDIA, LOG_INFO,
00271              QString("Unlocking disk %1, then ejecting").arg(dev));
00272     device->unlock();
00273 
00274     MythMediaError err = device->eject();
00275 
00276     if (err == MEDIAERR_UNSUPPORTED)
00277     {
00278         // Physical ejection isn't possible (there is no tray or slot),
00279         // but logically the device is now ejected (ignored by the OS).
00280         ShowOkPopup(tr("You may safely remove %1").arg(dev));
00281     }
00282     else if (err == MEDIAERR_FAILED)
00283     {
00284         ShowOkPopup(tr("Failed to eject %1").arg(dev));
00285     }
00286 }
00287 
00294 MediaMonitor::MediaMonitor(QObject* par, unsigned long interval,
00295                            bool allowEject)
00296     : QObject(par), m_Active(false), m_Thread(NULL),
00297       m_MonitorPollingInterval(interval), m_AllowEject(allowEject)
00298 {
00299     // MediaMonitor object is always created,
00300     // but the user can elect not to actually do monitoring:
00301     m_StartThread = gCoreContext->GetNumSetting("MonitorDrives");
00302 
00303     // User can specify that some devices are not monitored
00304     QString ignore = gCoreContext->GetSetting("IgnoreDevices", "");
00305 
00306     if (ignore.length())
00307         m_IgnoreList = ignore.split(',', QString::SkipEmptyParts);
00308     else
00309         m_IgnoreList = QStringList();  // Force empty list
00310 
00311     if (m_StartThread)
00312         LOG(VB_MEDIA, LOG_NOTICE, "Creating MediaMonitor");
00313     else
00314 #ifdef USING_DARWIN_DA
00315         LOG(VB_MEDIA, LOG_INFO,
00316                  "MediaMonitor is disabled. Eject will not work");
00317 #else
00318         LOG(VB_MEDIA, LOG_INFO,
00319                  "Creating inactive MediaMonitor and static device list");
00320 #endif
00321     LOG(VB_MEDIA, LOG_INFO, "IgnoreDevices=" + ignore);
00322 
00323     // If any of IgnoreDevices are symlinks, also add the real device
00324     QStringList::Iterator dev;
00325     for (dev = m_IgnoreList.begin(); dev != m_IgnoreList.end(); ++dev)
00326     {
00327         QFileInfo *fi = new QFileInfo(*dev);
00328 
00329         if (fi && fi->isSymLink())
00330         {
00331             QString target = getSymlinkTarget(*dev);
00332 
00333             if (m_IgnoreList.filter(target).isEmpty())
00334             {
00335                 LOG(VB_MEDIA, LOG_INFO,
00336                          "Also ignoring " + target + " (symlinked from " + 
00337                          *dev + ").");
00338                 m_IgnoreList += target;
00339             }
00340         }
00341         delete fi;
00342     }
00343 }
00344 
00345 void MediaMonitor::deleteLater(void)
00346 {
00347     if (m_Thread)
00348     {
00349         StopMonitoring();
00350         delete m_Thread;
00351         m_Thread = NULL;
00352     }
00353     QObject::deleteLater();
00354 }
00355 
00364 bool MediaMonitor::RemoveDevice(const QString &dev)
00365 {
00366     QMutexLocker locker(&m_DevicesLock);
00367 
00368     QList<MythMediaDevice*>::iterator it;
00369     for (it = m_Devices.begin(); it != m_Devices.end(); ++it)
00370     {
00371         if ((*it)->getDevicePath() == dev)
00372         {
00373             if (m_UseCount[*it] == 0)
00374             {
00375                 (*it)->deleteLater();
00376                 m_Devices.erase(it);
00377                 m_UseCount.remove(*it);
00378             }
00379             else
00380             {
00381                 // Other threads are still using this device
00382                 // postpone actual delete until they finish.
00383                 disconnect(*it);
00384                 m_RemovedDevices.append(*it);
00385                 m_Devices.erase(it);
00386             }
00387 
00388             return true;
00389         }
00390     }
00391     return false;
00392 }
00393 
00397 void MediaMonitor::CheckDevices(void)
00398 {
00399     /* check if new devices have been plugged in */
00400     CheckDeviceNotifications();
00401 
00402     QList<MythMediaDevice*>::iterator itr = m_Devices.begin();
00403     MythMediaDevice* pDev;
00404     while (itr != m_Devices.end())
00405     {
00406         pDev = *itr;
00407         if (pDev)
00408             pDev->checkMedia();
00409         ++itr;
00410     }
00411 }
00412 
00416 void MediaMonitor::StartMonitoring(void)
00417 {
00418     // Sanity check
00419     if (m_Active)
00420         return;
00421 
00422     if (!m_StartThread)
00423         return;
00424 
00425     if (!m_Thread)
00426         m_Thread = new MonitorThread(this, m_MonitorPollingInterval);
00427 
00428     qRegisterMetaType<MythMediaStatus>("MythMediaStatus");
00429 
00430     LOG(VB_MEDIA, LOG_NOTICE, "Starting MediaMonitor");
00431     m_Active = true;
00432     m_Thread->start();
00433 }
00434 
00438 void MediaMonitor::StopMonitoring(void)
00439 {
00440     // Sanity check
00441     if (!m_Active)
00442         return;
00443 
00444     LOG(VB_MEDIA, LOG_NOTICE, "Stopping MediaMonitor");
00445     m_Active = false;
00446     m_Thread->wait();
00447 }
00448 
00459 bool MediaMonitor::ValidateAndLock(MythMediaDevice *pMedia)
00460 {
00461     QMutexLocker locker(&m_DevicesLock);
00462 
00463     if (!m_Devices.contains(pMedia))
00464         return false;
00465 
00466     m_UseCount[pMedia]++;
00467 
00468     return true;
00469 }
00470 
00476 void MediaMonitor::Unlock(MythMediaDevice *pMedia)
00477 {
00478     QMutexLocker locker(&m_DevicesLock);
00479 
00480     if (!m_UseCount.contains(pMedia))
00481         return;
00482 
00483     m_UseCount[pMedia]--;
00484 
00485     if (m_UseCount[pMedia] == 0 && m_RemovedDevices.contains(pMedia))
00486     {
00487         m_RemovedDevices.removeAll(pMedia);
00488         m_UseCount.remove(pMedia);
00489         pMedia->deleteLater();
00490     }
00491 }
00492 
00499 MythMediaDevice* MediaMonitor::GetMedia(const QString& path)
00500 {
00501     QMutexLocker locker(&m_DevicesLock);
00502 
00503     QList<MythMediaDevice*>::iterator it = m_Devices.begin();
00504     for (;it != m_Devices.end(); ++it)
00505     {
00506         if ((*it)->isSameDevice(path) &&
00507             (((*it)->getStatus() == MEDIASTAT_USEABLE) ||
00508              ((*it)->getStatus() == MEDIASTAT_MOUNTED) ||
00509              ((*it)->getStatus() == MEDIASTAT_NOTMOUNTED)))
00510         {
00511             return(*it);
00512         }
00513     }
00514 
00515     return NULL;
00516 }
00517 
00524 QString MediaMonitor::GetMountPath(const QString& devPath)
00525 {
00526     QString mountPath;
00527 
00528     if (c_monitor)
00529     {
00530         MythMediaDevice *pMedia = c_monitor->GetMedia(devPath);
00531         if (pMedia && c_monitor->ValidateAndLock(pMedia))
00532         {
00533             mountPath = pMedia->getMountPath();
00534             c_monitor->Unlock(pMedia);
00535         }
00536         // The media monitor could be inactive.
00537         // Create a fake media device just to lookup mount map:
00538         else
00539         {
00540             pMedia = MythCDROM::get(NULL, devPath.toAscii(), true, false);
00541             if (pMedia && pMedia->findMountPath())
00542                 mountPath = pMedia->getMountPath();
00543             else
00544                 LOG(VB_MEDIA, LOG_INFO,
00545                          "MediaMonitor::GetMountPath() - failed");
00546             // need some way to delete the media device.
00547         }
00548     }
00549 
00550     return mountPath;
00551 }
00552 
00571 QList<MythMediaDevice*> MediaMonitor::GetMedias(MythMediaType mediatype)
00572 {
00573     QMutexLocker locker(&m_DevicesLock);
00574 
00575     QList<MythMediaDevice*> medias;
00576 
00577     QList<MythMediaDevice*>::iterator it = m_Devices.begin();
00578     for (;it != m_Devices.end(); ++it)
00579     {
00580         if (((*it)->getMediaType() & mediatype) &&
00581             (((*it)->getStatus() == MEDIASTAT_USEABLE) ||
00582              ((*it)->getStatus() == MEDIASTAT_MOUNTED) ||
00583              ((*it)->getStatus() == MEDIASTAT_NOTMOUNTED)))
00584         {
00585             medias.push_back(*it);
00586         }
00587     }
00588 
00589     return medias;
00590 }
00591 
00595 void MediaMonitor::MonitorRegisterExtensions(uint mediatype,
00596                                              const QString &extensions)
00597 {
00598     LOG(VB_GENERAL, LOG_DEBUG, 
00599              QString("MonitorRegisterExtensions(0x%1, %2)")
00600                  .arg(mediatype, 0, 16).arg(extensions));
00601 
00602     QList<MythMediaDevice*>::iterator it = m_Devices.begin();
00603     for (; it != m_Devices.end(); ++it)
00604     {
00605         if (*it)
00606             (*it)->RegisterMediaExtensions(mediatype, extensions);
00607     }
00608 }
00609 
00610 void MediaMonitor::RegisterMediaHandler(const QString  &destination,
00611                                         const QString  &description,
00612                                         const QString  &key,
00613                                         void          (*callback)
00614                                               (MythMediaDevice*),
00615                                         int             mediaType,
00616                                         const QString  &extensions)
00617 {
00618     if (m_handlerMap.count(destination) == 0)
00619     {
00620         MHData  mhd = { callback, mediaType, destination, description };
00621         QString msg = MythMediaDevice::MediaTypeString((MythMediaType)mediaType);
00622 
00623         if (extensions.length())
00624             msg += QString(", ext(%1)").arg(extensions);
00625 
00626         LOG(VB_MEDIA, LOG_INFO, 
00627                  "Registering '" + destination + "' as a media handler for " +
00628                  msg);
00629 
00630         m_handlerMap[destination] = mhd;
00631 
00632         if (extensions.length())
00633             MonitorRegisterExtensions(mediaType, extensions);
00634     }
00635     else
00636     {
00637        LOG(VB_GENERAL, LOG_INFO,
00638                 destination + " is already registered as a media handler.");
00639     }
00640 }
00641 
00649 void MediaMonitor::JumpToMediaHandler(MythMediaDevice* pMedia)
00650 {
00651     QList<MHData>                    handlers;
00652     QMap<QString, MHData>::Iterator  itr = m_handlerMap.begin();
00653 
00654     while (itr != m_handlerMap.end())
00655     {
00656         if (((*itr).MythMediaType & (int)pMedia->getMediaType()))
00657         {
00658             LOG(VB_GENERAL, LOG_NOTICE,
00659                 QString("Found a handler for %1 - '%2'")
00660                 .arg(pMedia->MediaTypeString()) .arg(itr.key())); 
00661             handlers.append(*itr);
00662         }
00663         itr++;
00664     }
00665 
00666     if (handlers.empty())
00667     {
00668         LOG(VB_MEDIA, LOG_INFO, "No media handler found for event type");
00669         return;
00670     }
00671 
00672 
00673     // TODO - Generate a dialog, add buttons for each description,
00674     // if user didn't cancel, selected = handlers.at(choice);
00675     int selected = 0;
00676 
00677     handlers.at(selected).callback(pMedia);
00678 }
00679 
00684 void MediaMonitor::mediaStatusChanged(MythMediaStatus oldStatus,
00685                                       MythMediaDevice* pMedia)
00686 {
00687     // If we're not active then ignore signal.
00688     if (!m_Active)
00689         return;
00690 
00691     MythMediaStatus  stat = pMedia->getStatus();
00692     QString      msg  = QString(" (%1, %2 -> %3)")
00693                         .arg(pMedia->MediaTypeString())
00694                         .arg(MythMediaDevice::MediaStatusStrings[oldStatus])
00695                         .arg(MythMediaDevice::MediaStatusStrings[stat]);
00696 
00697     // This gets called from outside the main thread so we need
00698     // to post an event back to the main thread.
00699     // We now send events for all non-error statuses, so plugins get ejects
00700     if (stat != MEDIASTAT_ERROR && stat != MEDIASTAT_UNKNOWN)
00701     {
00702         // Should we ValidateAndLock() first?
00703         QEvent *e = new MythMediaEvent(stat, pMedia);
00704 
00705         LOG(VB_MEDIA, LOG_INFO, "Posting MediaEvent" + msg);
00706 
00707         // sendEvent() is needed here - it waits for the event to be used.
00708         // postEvent() would result in pDevice's media type changing
00709         // ... before the plugin's event chain would process it.
00710         // Another way would be to send an exact copy of pDevice instead.
00711         QCoreApplication::sendEvent((QObject*)GetMythMainWindow(), e);
00712         delete e;
00713     }
00714     else
00715         LOG(VB_MEDIA, LOG_INFO,
00716                  "Media status changed, but not sending event" + msg);
00717 
00718 
00719     if (stat == MEDIASTAT_OPEN || stat == MEDIASTAT_NODISK
00720                                || stat == MEDIASTAT_UNPLUGGED)
00721     {
00722         pMedia->clearData();
00723     }
00724 }
00725 
00729 bool MediaMonitor::shouldIgnore(const MythMediaDevice* device)
00730 {
00731     if (m_IgnoreList.contains(device->getMountPath()) ||
00732         m_IgnoreList.contains(device->getRealDevice())||
00733         m_IgnoreList.contains(device->getDevicePath()) )
00734     {
00735         LOG(VB_MEDIA, LOG_INFO,
00736                  "Ignoring device: " + device->getDevicePath());
00737         return true;
00738     }
00739 #if 0
00740     else
00741     {
00742         LOG(VB_MEDIA, LOG_DEBUG,
00743                  "Not ignoring: " + device->getDevicePath() + " / " +
00744                  device->getMountPath());
00745         LOG(VB_MEDIA, LOG_DEBUG, 
00746                  "Paths not in: " + m_IgnoreList.join(", "));
00747     }
00748 #endif
00749 
00750     return false;
00751 }
00752 
00757 bool MediaMonitor::eventFilter(QObject *obj, QEvent *event)
00758 {
00759     if (event->type() == MythMediaEvent::kEventType)
00760     {
00761         MythMediaDevice *pDev = ((MythMediaEvent*)event)->getDevice();
00762 
00763         if (!pDev)
00764         {
00765             LOG(VB_GENERAL, LOG_ALERT,
00766                      "MediaMonitor::eventFilter() got a bad media event?");
00767             return true;
00768         }
00769 
00770         if (pDev->isUsable())
00771             JumpToMediaHandler(pDev);
00772         else
00773         {
00774             // We don't want to jump around in the menus, but should
00775             // call each plugin's callback so it can track this change.
00776 
00777             QMap<QString, MHData>::Iterator itr = m_handlerMap.begin();
00778             while (itr != m_handlerMap.end())
00779             {
00780                 if ((*itr).MythMediaType & (int)pDev->getMediaType())
00781                     (*itr).callback(pDev);
00782                 itr++;
00783             }
00784         }
00785 
00786         return false;  // Don't eat the event
00787     }
00788 
00789     // standard event processing
00790     return QObject::eventFilter(obj, event);
00791 }
00792 
00793 /*
00794  * These methods return the user's preferred devices for playing and burning
00795  * CDs and DVDs. Traditionally we had a database setting to remember this,
00796  * but that is a bit wasteful when most users only have one drive.
00797  *
00798  * To make it a bit more beginner friendly, if no database default exists,
00799  * or if it contains "default", the code tries to find a monitored drive.
00800  * If, still, nothing is suitable, a caller hard-coded default is used.
00801  *
00802  * Ideally, these would return a MythMediaDevice * instead of a QString
00803  */
00804 
00805 QString MediaMonitor::defaultDevice(QString dbSetting,
00806                                     QString label,
00807                                     const char *hardCodedDefault)
00808 {
00809     QString device = gCoreContext->GetSetting(dbSetting);
00810 
00811     LOG(VB_MEDIA, LOG_DEBUG,
00812              QString("MediaMonitor::defaultDevice(%1,..,%2) dbSetting='%3'")
00813                  .arg(dbSetting).arg(hardCodedDefault).arg(device));
00814 
00815     // No settings database defaults? Try to choose one:
00816     if (device.isEmpty() || device == "default")
00817     {
00818         device = hardCodedDefault;
00819 
00820         if (!c_monitor)
00821             c_monitor = GetMediaMonitor();
00822 
00823         if (c_monitor)
00824         {
00825             MythMediaDevice *d = c_monitor->selectDrivePopup(label);
00826 
00827             if (d == (MythMediaDevice *) -1)    // User cancelled
00828                 d = NULL;
00829 
00830             if (d && c_monitor->ValidateAndLock(d))
00831             {
00832                 device = d->getDevicePath();
00833                 c_monitor->Unlock(d);
00834             }
00835         }
00836     }
00837 
00838     LOG(VB_MEDIA, LOG_DEBUG,
00839              "MediaMonitor::defaultDevice() returning " + device);
00840     return device;
00841 }
00842 
00846 QString MediaMonitor::defaultCDdevice()
00847 {
00848     return defaultDevice("CDDevice", tr("Select a CD drive"), DEFAULT_CD);
00849 }
00850 
00854 QString MediaMonitor::defaultVCDdevice()
00855 {
00856     return defaultDevice("VCDDeviceLocation",
00857                          tr("Select a VCD drive"), DEFAULT_CD);
00858 }
00859 
00863 QString MediaMonitor::defaultDVDdevice()
00864 {
00865     return defaultDevice("DVDDeviceLocation",
00866                          tr("Select a DVD drive"), DEFAULT_DVD);
00867 }
00868 
00872 QString MediaMonitor::defaultCDWriter()
00873 {
00874     return defaultDevice("CDWriterDeviceLocation",
00875                          tr("Select a CD writer"), DEFAULT_CD);
00876 }
00877 
00884 QString MediaMonitor::defaultDVDWriter()
00885 {
00886     QString device = defaultDevice("MythArchiveDVDLocation",
00887                                    tr("Select a DVD writer"), DEFAULT_DVD);
00888 
00889     return device;
00890 }
00891 
00892 
00896 const QString MediaMonitor::listDevices(void)
00897 {
00898     QList<MythMediaDevice*>::const_iterator dev;
00899     QStringList list;
00900 
00901     for (dev = m_Devices.begin(); dev != m_Devices.end(); ++dev)
00902     {
00903         QString devStr;
00904         QString model = (*dev)->getDeviceModel();
00905         QString path  = (*dev)->getDevicePath();
00906         QString real  = (*dev)->getRealDevice();
00907 
00908         if (path != real)
00909             devStr += path + "->";
00910         devStr += real;
00911 
00912         if (!model.length())
00913             model = "unknown";
00914         devStr += " (" + model + ")";
00915 
00916         list += devStr;
00917     }
00918 
00919     return list.join(", ");
00920 }
00921 
00928 void MediaMonitor::ejectOpticalDisc()
00929 {
00930     MediaMonitor *mon = MediaMonitor::GetMediaMonitor();
00931     if (mon)
00932         mon->ChooseAndEjectMedia();
00933     else
00934     {
00935         LOG(VB_MEDIA, LOG_INFO, "CD/DVD Monitor isn't enabled.");
00936 #ifdef __linux__
00937         LOG(VB_MEDIA, LOG_INFO, "Trying Linux 'eject -T' command");
00938         myth_system("eject -T");
00939 #elif CONFIG_DARWIN
00940         QString def = DEFAULT_CD;
00941         LOG(VB_MEDIA, LOG_INFO, "Trying 'disktool -e " + def);
00942         myth_system("disktool -e " + def);
00943 #endif
00944     }
00945 }
00946 
00947 /*
00948  * vim:ts=4:sw=4:ai:et:si:sts=4
00949  */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends