Ticket #601: hotplug_hdd.diff

File hotplug_hdd.diff, 30.0 KB (added by Aaron McCarthy <mccarthy.aaron@…>, 18 years ago)
  • libs/libmyth/mythmedia.cpp

     
    1717
    1818// end for testing
    1919
     20static const QString PATHTO_PMOUNT("/usr/bin/pmount");
     21static const QString PATHTO_PUMOUNT("/usr/bin/pumount");
    2022static const QString PATHTO_MOUNT("/bin/mount");
    2123static const QString PATHTO_UNMOUNT("/bin/umount");
    2224static const QString PATHTO_MOUNTS("/proc/mounts");
     
    2527{
    2628    "MEDIASTAT_ERROR",
    2729    "MEDIASTAT_UNKNOWN",
     30    "MEDIASTAT_UNPLUGGED",
    2831    "MEDIASTAT_OPEN",
    2932    "MEDIASTAT_USEABLE",
    3033    "MEDIASTAT_NOTMOUNTED",
     
    5760    m_Locked = false;
    5861    m_DeviceHandle = -1;
    5962    m_SuperMount = SuperMount;
    60     m_Status = (isMounted(true)) ? MEDIASTAT_MOUNTED : MEDIASTAT_NOTMOUNTED;
     63    m_Status = MEDIASTAT_UNKNOWN;
     64    m_MediaType = MEDIATYPE_UNKNOWN;
    6165}
    6266
    6367bool MythMediaDevice::openDevice()
     
    98102    if (!m_SuperMount)
    99103    {
    100104        // Build a command line for mount/unmount and execute it...  Is there a better way to do this?
    101         MountCommand = QString("%1 %2")
    102             .arg((DoMount) ? PATHTO_MOUNT : PATHTO_UNMOUNT)
    103             .arg(m_DevicePath);
     105        if (QFile(PATHTO_PMOUNT).exists() && QFile(PATHTO_PUMOUNT).exists())
     106            MountCommand = QString("%1 %2")
     107                .arg((DoMount) ? PATHTO_PMOUNT : PATHTO_PUMOUNT)
     108                .arg(m_DevicePath);
     109        else
     110            MountCommand = QString("%1 %2")
     111                .arg((DoMount) ? PATHTO_MOUNT : PATHTO_UNMOUNT)
     112                .arg(m_DevicePath);
    104113   
    105114        VERBOSE(VB_ALL,  QString("Executing '%1'").arg(MountCommand));
    106115        if (0 == myth_system(MountCommand))
    107116        {
    108117            if (DoMount)
    109118            {
     119                // we cannot tell beforehand what the pmount mount point is
     120                // so verify the mount status of the device
     121                isMounted(true);
    110122                m_Status = MEDIASTAT_MOUNTED;
    111123                onDeviceMounted();
    112124            }
     
    213225            // the disk is not / should not be mounted.
    214226            case MEDIASTAT_ERROR:
    215227            case MEDIASTAT_OPEN:
    216                 if (MEDIASTAT_MOUNTED == OldStatus)
    217                     unmount();
    218                 break;
    219228            case MEDIASTAT_NOTMOUNTED:
    220                 if (MEDIASTAT_MOUNTED == OldStatus)
     229                if (isMounted(true))
    221230                    unmount();
    222                 // If we're here it's possible there's unmounted media in the device so try to mount it.
    223                 // The case of no media in the deivce whould be handeled by derived classes and sent
    224                 // as MEDIASTAT_OPEN, MEDISTAT_ERROR or MEDIASTAT_UNKNOWN.
    225                 mount();
    226231                break;
    227232            case MEDIASTAT_UNKNOWN:
    228233            case MEDIASTAT_USEABLE:
    229234            case MEDIASTAT_MOUNTED:
     235            case MEDIASTAT_UNPLUGGED:
    230236                // get rid of the compiler warning...
    231237                break;
    232238        }
  • libs/libmyth/mythmediamonitor.h

     
    4848{
    4949    Q_OBJECT
    5050  public:
     51    ~MediaMonitor();
     52
    5153    bool addFSTab(void);
     54#ifdef linux
     55    bool addPMountable(void);
     56#endif
    5257    void addDevice(MythMediaDevice* pDevice);
    5358    bool addDevice(const char* dev);
    5459    bool addDevice(struct fstab* mep);
     60#ifdef linux
     61    bool addSysFSDevice(const QString &dev, bool checkPartitions);
     62    bool removeDevice(const QString &dev);
     63    void checkUDev();
     64#endif
    5565
    5666    bool isActive(void) const { return m_Active; }
    5767    void checkDevices(void);
    5868    void startMonitoring(void);
    5969    void stopMonitoring(void);
    6070    QValueList <MythMediaDevice*> getMedias(MediaType mediatype);
     71
     72    void chooseAndEjectMedia();
    6173   
    6274    static MediaMonitor* getMediaMonitor();
    6375   
     
    7082    bool m_Active;
    7183    MonitorThread m_Thread;
    7284    bool m_AllowEject;
     85#ifdef linux
     86    int fifo;
     87#endif
     88
     89  private:
     90#ifdef linux
     91    QString getDeviceFile(QString sysfs);
     92    QStringList getCDROMBlockDevices();
     93#endif
    7394};
    7495
    7596#endif
  • libs/libmyth/mythhdd.h

     
     1#ifndef MYTHHDD_H
     2#define MYTHHDD_H
     3
     4#include "mythmedia.h"
     5
     6class MythHDD : public MythMediaDevice
     7{
     8//    Q_OBJECT
     9  public:
     10    MythHDD(QObject* par, const char* DevicePath, bool SuperMount,
     11            bool AllowEject);
     12    virtual ~MythHDD() {};
     13
     14    // Commented out functions are implemented in MythMediaDevice, so can't
     15    // be abstract here.
     16
     17    //virtual MediaError testMedia(void);
     18    //virtual bool openDevice(void);
     19    virtual MediaStatus checkMedia(void);
     20    //virtual MediaError eject(void) = 0;
     21    //virtual MediaError lock(void) = 0;
     22    //virtual MediaError unlock(void) = 0;
     23
     24    static MythHDD* get(QObject* par, const char* devicePath, bool SuperMount,
     25                          bool AllowEject);
     26
     27  protected:
     28    //virtual void onDeviceMounted();
     29};
     30
     31#endif
  • libs/libmyth/mythcdrom.h

     
    1919    virtual bool checkOK(void) = 0;
    2020    virtual bool openDevice(void);
    2121    virtual MediaStatus checkMedia(void) = 0;
    22     //virtual MediaError eject(void) = 0;
     22    //virtual MediaError eject(bool open_close = true) = 0;
    2323    //virtual MediaError lock(void) = 0;
    2424    //virtual MediaError unlock(void) = 0;
    2525
     
    4242    virtual bool mediaChanged(void);
    4343    virtual bool checkOK(void);
    4444    virtual MediaStatus checkMedia(void);
    45     virtual MediaError eject(void);
     45    virtual MediaError eject(bool open_close = true);
    4646    virtual MediaError lock(void);
    4747    virtual MediaError unlock(void);
    4848};
     
    6060    virtual bool mediaChanged(void);
    6161    virtual bool checkOK(void);
    6262    virtual MediaStatus checkMedia(void);
    63     virtual MediaError eject(void);
     63    virtual MediaError eject(bool open_close = true);
    6464    virtual MediaError lock(void);
    6565    virtual MediaError unlock(void);
    6666};
  • libs/libmyth/mythdialogs.cpp

     
    234234    RegisterKey("Global", "7", "7", "7");
    235235    RegisterKey("Global", "8", "8", "8");
    236236    RegisterKey("Global", "9", "9", "9");
     237
     238    RegisterKey("Global", "EJECT", "Eject Removable Media", "e");
    237239}
    238240
    239241MythMainWindow::~MythMainWindow()
     
    10991101            }
    11001102            else if (action == "MENU")
    11011103                emit menuButtonPressed();
     1104            else if (action == "EJECT")
     1105            {
     1106                MediaMonitor *mon = MediaMonitor::getMediaMonitor();
     1107                if (mon)
     1108                    mon->chooseAndEjectMedia();
     1109            }
    11021110            else
    11031111                handled = false;
    11041112        }
  • libs/libmyth/libmyth.pro

     
    6868}
    6969
    7070unix {
    71     SOURCES += mythcdrom.cpp mythmediamonitor.cpp
    72     HEADERS += mythcdrom.h   mythmediamonitor.h
    73     inc.files += mythcdrom.h mythmediamonitor.h
     71    SOURCES += mythhdd.cpp mythcdrom.cpp mythmediamonitor.cpp
     72    HEADERS += mythhdd.cpp mythcdrom.h   mythmediamonitor.h
     73    inc.files += mythhdd.h mythcdrom.h mythmediamonitor.h
    7474}
    7575
    7676macx {
  • libs/libmyth/mythmediamonitor.cpp

     
    11#include "mythmediamonitor.h"
    22#include "mythcdrom.h"
     3#include "mythhdd.h"
    34#include <qapplication.h>
     5#include <qprocess.h>
     6#include <qdir.h>
     7#include <qfile.h>
    48#include <sys/file.h>
    59#include <fcntl.h>
    610#include <dirent.h>
     
    913#include <iostream>
    1014#include <sys/types.h>
    1115#include <sys/stat.h>
     16#include <sys/wait.h>
    1217#include <unistd.h>
    1318
    1419#include "config.h"
    1520#include "mythcontext.h"
     21#include "mythdialogs.h"
    1622
    1723// For testing
    1824#if 0
     
    4046#endif
    4147#define SUPER_OPT_DEV "dev="
    4248
     49#ifndef UDEV_FIFO
     50#define UDEV_FIFO "/tmp/mythtv_media"
     51#endif
     52
    4353using namespace std;
    4454
    4555MediaMonitor *theMonitor = NULL;
     
    5363        {
    5464            theMonitor = new MediaMonitor(NULL, 500, true);
    5565            theMonitor->addFSTab();
     66#ifdef linux
     67            theMonitor->addPMountable();
     68#endif
    5669        }
    5770    }
    5871
    5972    return theMonitor;
    6073}
    6174
     75/** \fn MediaMonitor::chooseAndEjectMedia()
     76 *  \brief Unmounts and ejects removable media devices.
     77 *
     78 *  If no media devices are known to the MediaMonitor this function does
     79 *  nothing. If a single device is known, it is unmounted and ejected if
     80 *  possible. If mulitple devices are known, a popup box is display so the
     81 *  user can choose which device to eject.
     82 */
     83void MediaMonitor::chooseAndEjectMedia()
     84{
     85    MythMediaDevice *selected = NULL;
     86
     87    if (m_Devices.count() == 1)
     88    {
     89        selected = m_Devices.first();
     90    }
     91    else if (m_Devices.count() > 1)
     92    {
     93        MythPopupBox ejectbox(gContext->GetMainWindow(), "eject media");
     94
     95        ejectbox.addLabel(tr("Select removable media to eject"));
     96
     97        QValueList <MythMediaDevice *>::Iterator it = m_Devices.begin();
     98        while (it != m_Devices.end())
     99        {
     100            if ((*it)->getVolumeID() != "")
     101                ejectbox.addButton((*it)->getVolumeID());
     102            else
     103                ejectbox.addButton((*it)->getDevicePath());
     104
     105            it++;
     106        }
     107
     108        ejectbox.addButton(tr("Cancel"))->setFocus();
     109
     110        int ret = ejectbox.ExecPopup();
     111
     112        if (ret < (int)m_Devices.count())
     113            selected = m_Devices[ret];
     114    }
     115
     116    if (selected)
     117    {
     118        switch (selected->getStatus())
     119        {
     120            case MEDIASTAT_OPEN     : selected->eject(false);
     121                                      break;
     122            case MEDIASTAT_MOUNTED  : cerr << "media is mounted" << endl;
     123                                      selected->unmount();
     124
     125                                      if (selected->isMounted(true))
     126                                      {
     127                                          MythPopupBox::showOkPopup(
     128                                             gContext->GetMainWindow(),
     129                                             "eject unmount fail",
     130                                             QString(tr("Failed unmounting %1"))
     131                                               .arg(selected->getDevicePath()));
     132                                          break;
     133                                      }
     134            default                 : // attempt to unlock and eject media
     135                                      selected->unlock();
     136                                      if (selected->eject() == MEDIAERR_UNSUPPORTED)
     137                                      {
     138                                          MythPopupBox::showOkPopup(
     139                                             gContext->GetMainWindow(),
     140                                             "eject success",
     141                                             QString(tr("You may safely remove %1"))
     142                                               .arg(selected->getDevicePath()));
     143                                      }
     144                                      else if (selected->eject() == MEDIAERR_FAILED)
     145                                      {
     146                                          MythPopupBox::showOkPopup(
     147                                             gContext->GetMainWindow(),
     148                                             "eject fail",
     149                                             QString(tr("Failed Ejecting %1"))
     150                                               .arg(selected->getDevicePath()));
     151                                      }
     152        }
     153    }
     154}
     155
    62156// MonitorThread
    63157MonitorThread::MonitorThread(MediaMonitor* pMon, unsigned long interval)
    64158             : QThread()
     
    88182    m_AllowEject = allowEject;
    89183    m_Active = false;
    90184    m_Thread.setMonitor(this);
     185#ifdef linux
     186    fifo = 0;
     187#endif
    91188}
    92189
     190MediaMonitor::~MediaMonitor()
     191{
     192#ifdef linux
     193    if (fifo)
     194    {
     195        close(fifo);
     196        unlink(UDEV_FIFO);
     197    }
     198#endif
     199}
     200
    93201// Loop through the file system table and add any supported devices.
    94202bool MediaMonitor::addFSTab()
    95203{
     
    119227    return true;
    120228}
    121229
     230#ifdef linux
     231/** \fn MediaMonitor::addPMountable()
     232 *  \brief Search /sys/block for valid removable media devices.
     233 *
     234 *  This function creates MediaDevice instances for valid removable media
     235 *  devices found under the /sys/block filesystem in Linux.  CD and DVD
     236 *  devices are created as MythCDROM instances.  MythHDD instances will be
     237 *  created for each partition on removable hard disc devices, if they exists.
     238 *  Otherwise a single MythHDD instance will be created for the entire disc.
     239 *  Floppy discs are ignored.
     240 */
     241bool MediaMonitor::addPMountable()
     242{
     243    mkfifo(UDEV_FIFO, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
     244    fifo = open(UDEV_FIFO, O_RDONLY | O_NONBLOCK);
     245
     246    QDir sysfs("/sys/block");
     247    sysfs.setFilter(QDir::Dirs);
     248
     249    QStringList devices = sysfs.entryList();
     250
     251    for (QStringList::Iterator it = devices.begin(); it != devices.end(); ++it)
     252    {
     253        if (*it == "." || *it == "..")
     254            continue;
     255
     256        // we don't do floppies.
     257        if ((*it).startsWith("fd"))
     258            continue;
     259
     260        sysfs.cd(*it);
     261
     262        QFile removable(sysfs.absFilePath("removable"));
     263        if (removable.exists())
     264        {
     265            removable.open(IO_ReadOnly);
     266            int c = removable.getch();
     267            removable.close();
     268
     269            if (c == '1')
     270                addSysFSDevice(sysfs.absPath(), true);
     271        }
     272        sysfs.cdUp();
     273    }
     274    return true;
     275}
     276
     277/** \fn MediaMonitor::getDeviceFile(QString)
     278 *  \brief Returns the device special file associated with the /sys/block node.
     279 *  \param [in]sysfs sysfs path of removable block device.
     280 *  \return path to the device special file
     281 */
     282QString MediaMonitor::getDeviceFile(QString sysfs)
     283{
     284    QProcess udevinfo(this);
     285    udevinfo.addArgument("udevinfo");
     286    udevinfo.addArgument("-q");
     287    udevinfo.addArgument("name");
     288    udevinfo.addArgument("-p");
     289    udevinfo.addArgument(sysfs);
     290    udevinfo.setCommunication(QProcess::Stdout);
     291
     292    udevinfo.start();
     293
     294    int status;
     295    waitpid(udevinfo.processIdentifier(), &status, 0);
     296
     297    QString ret = udevinfo.readLineStdout();
     298    if (ret == "device not found in database")
     299        return QString::null;
     300    else
     301        return ret;
     302}
     303
     304/** \fn MediaMonitor::getCDROMBlockDevices()
     305 *  \brief Reads the list devices known to be CD or DVD devices.
     306 *  \return list of CD and DVD device names.
     307 */
     308QStringList MediaMonitor::getCDROMBlockDevices()
     309{
     310    QStringList l;
     311
     312    QFile file("/proc/sys/dev/cdrom/info");
     313    if (file.open(IO_ReadOnly))
     314    {
     315        QTextStream stream(&file);
     316        QString line;
     317        while (!stream.atEnd())
     318        {
     319            line = stream.readLine();
     320            if (line.startsWith("drive name:"))
     321            {
     322                QString s = line.section('\t', 2, 2);
     323                l.append(s);
     324            }
     325        }
     326        file.close();
     327    }
     328    return l;
     329}
     330#endif
     331
    122332// Given a media deivce add it to our collection.
    123333void MediaMonitor::addDevice(MythMediaDevice* pDevice)
    124334{
     
    271481    return false;
    272482}
    273483
     484#ifdef linux
     485/** \fn MediaMonitor::addSysFSDevice(const QString &, bool)
     486 *  \brief Creates MythMedia instances for sysfs removable media devices.
     487 *  \param [in]dev path to sysfs block device.
     488 *  \param [in]checkPartitions check for partitions on block device.
     489 *  \return true if MythMedia instances are created.
     490 *
     491 *  Block devices are represented as directories in sysfs with directories for
     492 *  each partition underneath the parent device directory.
     493 *
     494 *  This function recursively calls itself to find all partitions on a block
     495 *  device and creates a MythHDD instance for each partition found.  If no
     496 *  partitions are found and the device is a CD or DVD device a MythCDROM
     497 *  instance is created.  Otherwise a MythHDD instance is created for the
     498 *  entire block device.
     499 */
     500bool MediaMonitor::addSysFSDevice(const QString &dev, bool checkPartitions)
     501{
     502    if (checkPartitions)
     503    {
     504        // check for partitions
     505        QDir sysfs(dev);
     506        sysfs.setFilter(QDir::Dirs);
     507
     508        bool found_partitions = false;
     509        QStringList parts = sysfs.entryList();
     510        for (QStringList::Iterator pit = parts.begin();
     511             pit != parts.end(); pit++)
     512        {
     513            if (*pit == "." || *pit == "..")
     514                continue;
     515
     516            found_partitions |= addSysFSDevice(sysfs.absFilePath(*pit), false);
     517        }
     518
     519        // no partitions on block device, use main device
     520        if (!found_partitions)
     521            found_partitions |= addSysFSDevice(sysfs.absPath(), false);
     522
     523        return found_partitions;
     524    }
     525    else
     526    {
     527        QStringList cdroms = getCDROMBlockDevices();
     528
     529        if (cdroms.contains(dev.section('/', -1)))
     530        {
     531            // found cdrom device
     532            QString device_file = getDeviceFile(dev);
     533            if (!device_file.isNull())
     534            {
     535                device_file.prepend("/dev/");
     536                //cerr << "cdrom: " << device_file.ascii() << endl;
     537
     538                addDevice(MythCDROM::get(this, device_file, false, m_AllowEject));
     539                return true;
     540            }
     541        }
     542        else
     543        {
     544            // found block or partition device
     545            QString device_file = getDeviceFile(dev);
     546            if (!device_file.isNull())
     547            {
     548                device_file.prepend("/dev/");
     549                //cerr << "block: " << device_file.ascii() << endl;
     550
     551                addDevice(MythHDD::get(this, device_file, false, false));
     552
     553                return true;
     554            }
     555        }
     556    }
     557    return false;
     558}
     559
     560/** \fn MediaMonitor::removeDevice(const QString &)
     561 *  \brief Remove a device from the media monitor.
     562 *  \param [in]dev path to device special file to remove.
     563 *  \return true if device is removed from the Media Monitor.
     564 *
     565 *  This function is usually called after a hotpluggable device is unplugged.
     566 */
     567bool MediaMonitor::removeDevice(const QString &dev)
     568{
     569    QValueList<MythMediaDevice*>::iterator it;
     570    for (it = m_Devices.begin(); it != m_Devices.end(); it++)
     571    {
     572        if ((*it)->getDevicePath() == dev)
     573        {
     574            m_Devices.remove(it);
     575            //cerr << "remove device: " << dev.ascii() << endl;
     576            return true;
     577        }
     578    }
     579    return false;
     580}
     581
     582/** \fn MediaMonitor::checkUDev()
     583 *  \brief Checks the named pipe, UDEV_FIFO, for hotplug events from the udev system.
     584 */
     585void MediaMonitor::checkUDev()
     586{
     587    char buffer[256];
     588    QString qBuffer;
     589
     590    if (fifo)
     591    {
     592        int size = read(fifo, buffer, 255);
     593        while (size > 0)
     594        {
     595            // append buffer to QString
     596            buffer[size] = '\0';
     597
     598            qBuffer.append(buffer);
     599
     600            size = read(fifo, buffer, 255);
     601        }
     602        QStringList devs = QStringList::split('\n', qBuffer);
     603
     604        for (QStringList::Iterator it = devs.begin(); it != devs.end(); it++)
     605        {
     606            if ((*it).startsWith("add"))
     607            {
     608                QString dev = (*it).section(' ', 1, 1);
     609
     610                // check if removeable
     611                QFile removable(dev + "/removable");
     612                if (removable.exists())
     613                {
     614                    removable.open(IO_ReadOnly);
     615                    int c = removable.getch();
     616                    removable.close();
     617
     618                    if (c == '1')
     619                        addSysFSDevice((*it).section(' ', 1, 1), true);
     620                }
     621            }
     622            else if ((*it).startsWith("remove"))
     623            {
     624                removeDevice((*it).section(' ', 2, 2));
     625            }
     626        }
     627    }
     628}
     629#endif
     630
    274631// Poll the devices in our list.
    275632void MediaMonitor::checkDevices()
    276633{
     634#ifdef linux
     635    /* check if new devices have been plugged in */
     636    checkUDev();
     637#endif
     638
    277639    QValueList<MythMediaDevice*>::iterator itr = m_Devices.begin();
    278640    MythMediaDevice* pDev;
    279641    while (itr != m_Devices.end())
     
    317679        pDev = *itr;
    318680        if ((pDev->getMediaType()==mediatype) &&
    319681            ((pDev->getStatus()==MEDIASTAT_USEABLE) ||
    320             (pDev->getStatus()==MEDIASTAT_MOUNTED)))
     682             (pDev->getStatus()==MEDIASTAT_MOUNTED) ||
     683             (pDev->getStatus()==MEDIASTAT_NOTMOUNTED)))
    321684            medias.push_back(pDev);
    322685        itr++;
    323686    }
     
    345708                                new MediaEvent(oldStatus, pMedia));
    346709    }
    347710}
     711
  • libs/libmyth/mythhdd.cpp

     
     1#include "mythhdd.h"
     2
     3#include <iostream>
     4
     5/** \fn MythHDD::get(QObject*, const char*, bool, bool)
     6 *  \brief Helper function used to create a new instance of a hard disc device.
     7 *  \param [in]devicePath path to the device special file representing the device.
     8 *  \return new MythHDD instance.
     9 */
     10MythHDD *MythHDD::get(QObject* par, const char* devicePath, bool SuperMount,
     11                      bool AllowEject)
     12{
     13    return new MythHDD(par, devicePath, SuperMount, AllowEject);
     14}
     15
     16/** \fn MythHDD::MythHDD(QObject *, const char *, bool, bool)
     17 *  \brief Creates a new instance of a hard disc device.
     18 *  \param [in]DevicePath path to the device special file representing the device.
     19 *  \return new MythHDD instance.
     20 */
     21MythHDD::MythHDD(QObject *par, const char *DevicePath, bool SuperMount,
     22                 bool AllowEject)
     23       : MythMediaDevice(par, DevicePath, SuperMount, AllowEject)
     24{
     25    m_Status = MEDIASTAT_UNPLUGGED;
     26    m_MediaType = MEDIATYPE_DATA;       // default type is data
     27}
     28
     29/** \fn MythHDD::checkMedia()
     30 *  \brief Checks the status of this media device.
     31 */
     32MediaStatus MythHDD::checkMedia()
     33{
     34    if (isMounted(true))
     35    {
     36        // device is mounted, trigger event
     37        //std::cerr << "status -> mounted" << std::endl;
     38        return setStatus(MEDIASTAT_MOUNTED);
     39    }
     40    else
     41    {
     42        // device is not mounted
     43        if (m_Status == MEDIASTAT_UNPLUGGED)
     44        {
     45            // a removable device was just plugged in try to mount it.
     46            mount();
     47            if (isMounted(true))
     48            {
     49                m_Status = MEDIASTAT_NOTMOUNTED;
     50                return setStatus(MEDIASTAT_MOUNTED);
     51            }
     52            else
     53                return setStatus(MEDIASTAT_NOTMOUNTED);
     54        }
     55        else if (m_Status == MEDIASTAT_MOUNTED)
     56        {
     57            // device was mounted and someone unmounted it.
     58            // set its status to NOTMOUNTED */
     59            //std::cerr << "status -> useable (via unmount)" << std::endl;
     60            return m_Status = setStatus(MEDIASTAT_NOTMOUNTED);
     61        }
     62        else
     63        {
     64            // leave device state as is
     65            return m_Status;
     66        }
     67    }
     68}
  • libs/libmyth/mythcdrom-linux.cpp

     
    88
    99#define ASSUME_WANT_AUDIO 1
    1010
    11 MediaError MythCDROMLinux::eject()
     11MediaError MythCDROMLinux::eject(bool open_close)
    1212{
    13     return (ioctl(m_DeviceHandle, CDROMEJECT) == 0) ? MEDIAERR_OK :
    14                                                       MEDIAERR_FAILED;
     13    if (open_close)
     14        return (ioctl(m_DeviceHandle, CDROMEJECT) == 0) ? MEDIAERR_OK :
     15                                                          MEDIAERR_FAILED;
     16    else
     17        return (ioctl(m_DeviceHandle, CDROMCLOSETRAY) == 0) ? MEDIAERR_OK :
     18                                                              MEDIAERR_FAILED;
    1519}
    1620
    1721bool MythCDROMLinux::mediaChanged()
     
    8589        {
    8690            case CDS_DISC_OK:
    8791                //cout << "disk ok - ";
    88                 if (isMounted(true))
    89                     //cout << "it's mounted" << endl;
     92                // If the disc is ok and we already know it's mediatype
     93                // returns MOUNTED.
     94                if (isMounted(true) && m_MediaType != MEDIATYPE_UNKNOWN)
    9095                    return setStatus(MEDIASTAT_MOUNTED, OpenedHere);
    9196                // If the disk is ok but not yet mounted we'll test it further down after this switch exits.
    9297                break;
     
    110115        if (mediaChanged())
    111116        {
    112117            //cout << "media changed - ";
    113             // Regardless of the actual status lie here and say it's open for now, so we can over the case of a missed open.
     118            // Regardless of the actual status lie here and say it's open for now, so we can cover the case of a missed open.
    114119            return setStatus(MEDIASTAT_OPEN, OpenedHere);
    115120        }
    116121        else
     
    136141                        this->m_KeyID = QString("%1%2")
    137142                                      .arg(this->m_VolumeID)
    138143                                      .arg(QString(buf.creation_date).left(16));
    139                         // We'll return NOTMOUNTED  here because we're switching media.
    140                         // The base class will try to mount the deivce causing the next pass to pick up the MOUNTED status.
    141                         return setStatus(MEDIASTAT_NOTMOUNTED, OpenedHere);
     144
     145                        // attempt to mount the disc
     146                        // the base class's onDeviceMounted will do fine
     147                        // grained detection of the type of data on this disc
     148                        mount();
     149
     150                        if (isMounted(true))
     151                        {
     152                            // pretend we're NOTMOUNTED so setStatus emits
     153                            // a signal
     154                            m_Status = MEDIASTAT_NOTMOUNTED;
     155                            return setStatus(MEDIASTAT_MOUNTED, OpenedHere);
     156                        }
     157                        else
     158                            return setStatus(MEDIASTAT_NOTMOUNTED, OpenedHere);
    142159                        break;
    143160                    case CDS_AUDIO:
    144161                        //cout << "found an audio disk" << endl;
     
    154171                            return setStatus(MEDIASTAT_USEABLE, OpenedHere);
    155172                        #else
    156173                            mount();
    157                             return setStatus(MEDIASTAT_NOTMOUNTED, OpenedHere);
     174                            if (isMounted(true))
     175                            {
     176                                // pretend we're NOTMOUNTED so setStatus
     177                                // emits a signal
     178                                m_Status = MEDIASTAT_NOTMOUNTED;
     179                                return setStatus(MEDIASTAT_MOUNTED, OpenedHere);
     180                            }
     181                            else
     182                                return setStatus(MEDIASTAT_USEABLE, OpenedHere);
    158183                        #endif
    159184                        break;
    160185                    case CDS_NO_INFO:
     
    174199                     m_Status == MEDIASTAT_NOTMOUNTED)
    175200            {
    176201                //cout << "current status == " << MythMediaDevice::MediaStatusStrings[m_Status] << " setting status to not mounted - ";
    177                 setStatus(MEDIASTAT_NOTMOUNTED, OpenedHere);
     202                if (isMounted(true))
     203                    setStatus(MEDIASTAT_MOUNTED, OpenedHere);
     204                else
     205                    setStatus(MEDIASTAT_NOTMOUNTED, OpenedHere);
    178206            }
    179207
    180208            if (m_AllowEject)
  • libs/libmyth/mythcdrom-freebsd.cpp

     
    77
    88#define ASSUME_WANT_AUDIO 1
    99
    10 MediaError MythCDROMFreeBSD::eject()
     10MediaError MythCDROMFreeBSD::eject(bool open_close)
    1111{
    12     if (ioctl(m_DeviceHandle, CDIOCEJECT) == 0)
    13         return MEDIAERR_OK;
    14     return MEDIAERR_FAILED;
     12    if (open_close)
     13        return (ioctl(m_DeviceHandle, CDIOCEJECT) == 0) ? MEDIAERR_OK :
     14                                                          MEDIAERR_FAILED;
     15    else
     16        return MEDIAERR_UNSUPPORTED;
    1517}
    1618
    1719bool MythCDROMFreeBSD::mediaChanged()
  • libs/libmyth/mythmedia.h

     
    77typedef enum {
    88    MEDIASTAT_ERROR,
    99    MEDIASTAT_UNKNOWN,
     10    MEDIASTAT_UNPLUGGED,
    1011    MEDIASTAT_OPEN,
    1112    MEDIASTAT_USEABLE,   
    1213    MEDIASTAT_NOTMOUNTED,
     
    6566    virtual bool openDevice();
    6667    virtual bool closeDevice();
    6768    virtual MediaStatus checkMedia() = 0; // Derived classes MUST implement this.
    68     virtual MediaError eject() { return MEDIAERR_UNSUPPORTED; }
     69    virtual MediaError eject(bool open_close = true) { return MEDIAERR_UNSUPPORTED; }
    6970    virtual MediaError lock();
    7071    virtual MediaError unlock();
    7172    virtual bool performMountCmd( bool DoMount );   
  • contrib/mythtv_media_monitor.sh

     
     1#!/bin/sh -e
     2
     3MYTH_FIFO=/tmp/mythtv_media
     4
     5if [ -p $MYTH_FIFO ]; then
     6    echo $ACTION /sys$DEVPATH $DEVNAME > $MYTH_FIFO
     7fi
  • contrib/mythtv.rules

     
     1
     2SUBSYSTEM="block", RUN+="/etc/udev/scripts/mythtv.sh"