|
MythTV
0.26-pre
|
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 */
1.7.6.1