Esempio n. 1
0
/**
 * \brief Deal with the user, or another program, renaming a volume
 *
 * iTunes has a habit of renaming the disk volumes and track files
 * after it looks up a disk on the GraceNote CDDB.
 */
void MonitorThreadDarwin::diskRename(const char *devName, const char *volName)
{
    LOG(VB_MEDIA, LOG_DEBUG,
             QString("MonitorThreadDarwin::diskRename(%1,%2)")
                      .arg(devName).arg(volName));

    MythMediaDevice *pDevice = m_Monitor->GetMedia(devName);

    if (m_Monitor->ValidateAndLock(pDevice))
    {
        // Send message to plugins to ignore this drive:
        if (m_Monitor->m_SendEvent)
            pDevice->setStatus(MEDIASTAT_NODISK);

        pDevice->setVolumeID(volName);
        pDevice->setMountPath((QString("/Volumes/") + volName).toLatin1());

        // Plugins can now use it again:
        if (m_Monitor->m_SendEvent)
            pDevice->setStatus(MEDIASTAT_USEABLE);

        m_Monitor->Unlock(pDevice);
    }
    else
        LOG(VB_MEDIA, LOG_INFO,
                 QString("Couldn't find MythMediaDevice: %1").arg(devName));
}
Esempio n. 2
0
void Ripper::ejectCD()
{
    LOG(VB_MEDIA, LOG_INFO, __PRETTY_FUNCTION__);
    bool bEjectCD = gCoreContext->GetNumSetting("EjectCDAfterRipping",1);
    if (bEjectCD)
    {
#ifdef HAVE_CDIO
        LOG(VB_MEDIA, LOG_INFO, QString("Ripper::%1 '%2'").
            arg(__func__).arg(m_CDdevice));
        (void)cdio_eject_media_drive(m_CDdevice.toLatin1().constData());
#else
        MediaMonitor *mon = MediaMonitor::GetMediaMonitor();
        if (mon)
        {
            QByteArray devname = m_CDdevice.toLatin1();
            MythMediaDevice *pMedia = mon->GetMedia(devname.constData());
            if (pMedia && mon->ValidateAndLock(pMedia))
            {
                pMedia->eject();
                mon->Unlock(pMedia);
            }
        }
#endif // HAVE_CDIO
    }
}
Esempio n. 3
0
/**
 * \copydoc MythUIType::mediaEvent()
 */
void MythThemedMenu::mediaEvent(MythMediaEvent* event)
{
    if (!event)
        return;

    MythMediaDevice *device = event->getDevice();

    if (!device)
        return;

    MythMediaType type = device->getMediaType();
    MythMediaStatus status = device->getStatus();

    if ((status & ~MEDIASTAT_USEABLE) &&
        (status & ~MEDIASTAT_MOUNTED))
        return;

    switch (type)
    {
        case MEDIATYPE_DVD :
            // DVD Available
            break;
        case MEDIATYPE_BD :
            // Blu-ray Available
            break;
        default :
            return;
    }
}
void MediaMonitor::SetCDSpeed(const char *device, int speed)
{
    MediaMonitor *mon = GetMediaMonitor();
    if (mon)
    {
        MythMediaDevice *pMedia = mon->GetMedia(device);
        if (pMedia && mon->ValidateAndLock(pMedia))
        {
            pMedia->setSpeed(speed);
            mon->Unlock(pMedia);
            return;
        }
    }

    MythCDROM *cd = MythCDROM::get(NULL, device, false, false);
    if (cd)
    {
        cd->setDeviceSpeed(device, speed);
        delete cd;
        return;
    }

    LOG(VB_MEDIA, LOG_INFO, 
             QString("MediaMonitor::setSpeed(%1) - Cannot find/create CDROM?")
                  .arg(device));
}
/**
 * If the device is being monitored, return its mountpoint.
 *
 * A convenience function for plugins.
 * (Only currently needed for Mac OS X, which mounts Audio CDs)
 */
QString MediaMonitor::GetMountPath(const QString& devPath)
{
    QString mountPath;

    if (c_monitor)
    {
        MythMediaDevice *pMedia = c_monitor->GetMedia(devPath);
        if (pMedia && c_monitor->ValidateAndLock(pMedia))
        {
            mountPath = pMedia->getMountPath();
            c_monitor->Unlock(pMedia);
        }
        // The media monitor could be inactive.
        // Create a fake media device just to lookup mount map:
        else
        {
            pMedia = MythCDROM::get(NULL, devPath.toLatin1(), true, false);
            if (pMedia && pMedia->findMountPath())
                mountPath = pMedia->getMountPath();
            else
                LOG(VB_MEDIA, LOG_INFO,
                         "MediaMonitor::GetMountPath() - failed");
            // need some way to delete the media device.
        }
    }

    return mountPath;
}
Esempio n. 6
0
void Ripper::ejectCD()
{
    bool bEjectCD = gCoreContext->GetNumSetting("EjectCDAfterRipping",1);
    if (bEjectCD)
    {
#ifdef HAVE_CDAUDIO
        QByteArray devname = m_CDdevice.toAscii();
        int cdrom_fd = cd_init_device(const_cast<char*>(devname.constData()));
        VERBOSE(VB_MEDIA, "Ripper::ejectCD() - dev " + m_CDdevice);
        if (cdrom_fd != -1)
        {
            if (cd_eject(cdrom_fd) == -1)
                perror("Failed on cd_eject");

            cd_finish(cdrom_fd);
        }
        else
            perror("Failed on cd_init_device");
#else
        MediaMonitor *mon = MediaMonitor::GetMediaMonitor();
        if (mon)
        {
            QByteArray devname = m_CDdevice.toAscii();
            MythMediaDevice *pMedia = mon->GetMedia(devname.constData());
            if (pMedia && mon->ValidateAndLock(pMedia))
            {
                pMedia->eject();
                mon->Unlock(pMedia);
            }
        }
#endif
    }
}
Esempio n. 7
0
/**
 * Installed into the main window's event chain,
 * so that the main thread can safely jump to plugin code.
 */
bool MediaMonitor::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == MythMediaEvent::kEventType)
    {
        MythMediaDevice *pDev = ((MythMediaEvent*)event)->getDevice();

        if (!pDev)
        {
            VERBOSE(VB_IMPORTANT,
                   "MediaMonitor::eventFilter() got a bad media event?");
            return true;
        }

        if (pDev->isUsable())
            JumpToMediaHandler(pDev);
        else
        {
            // We don't want to jump around in the menus, but should
            // call each plugin's callback so it can track this change.

            QMap<QString, MHData>::Iterator itr = m_handlerMap.begin();
            while (itr != m_handlerMap.end())
            {
                if ((*itr).MythMediaType & (int)pDev->getMediaType())
                    (*itr).callback(pDev);
                itr++;
            }
        }

        return false;  // Don't eat the event
    }

    // standard event processing
    return QObject::eventFilter(obj, event);
}
/** \fn MediaMonitor::CheckDevices(void)
 *  \brief Poll the devices in our list.
 */
void MediaMonitor::CheckDevices(void)
{
    /* check if new devices have been plugged in */
    CheckDeviceNotifications();

    QList<MythMediaDevice*>::iterator itr = m_Devices.begin();
    MythMediaDevice* pDev;
    while (itr != m_Devices.end())
    {
        pDev = *itr;
        if (pDev)
            pDev->checkMedia();
        ++itr;
    }
}
Esempio n. 9
0
void MonitorThreadDarwin::diskRemove(QString devName)
{
    LOG(VB_MEDIA, LOG_DEBUG,
            QString("MonitorThreadDarwin::diskRemove(%1)").arg(devName));

    if (m_Monitor->m_SendEvent)
    {
        MythMediaDevice *pDevice = m_Monitor->GetMedia(devName);

        if (pDevice)  // Probably should ValidateAndLock() here?
            pDevice->setStatus(MEDIASTAT_NODISK);
        else
            LOG(VB_MEDIA, LOG_INFO,
                     "Couldn't find MythMediaDevice: " + devName);
    }

    m_Monitor->RemoveDevice(devName);
}
Esempio n. 10
0
/**
 * \class MediaMonitorWindows
 *
 * I am assuming, for now, that everything on Windows uses drive letters
 * (e.g. C:, D:). That is probably wrong, though. (other APIs?)
 */
MediaMonitorWindows::MediaMonitorWindows(QObject* par,
                                         unsigned long interval,
                                         bool allowEject)
                   : MediaMonitor(par, interval, allowEject)
{
    char strDrives[128];
    if (!::GetLogicalDriveStrings(sizeof(strDrives), strDrives))
        return;

    for (char *driveName = strDrives; *driveName;
         driveName += strlen(driveName) + 1)
    {
        uint type = ::GetDriveType(driveName);
        if (type != DRIVE_REMOVABLE && type != DRIVE_CDROM)
            continue;

        MythMediaDevice *media = NULL;

        if (type == DRIVE_CDROM)
            media = MythCDROM::get(this, driveName, false, allowEject);
        else
            media = MythHDD::Get(this, driveName, false, allowEject);

        if (!media)
        {
            VERBOSE(VB_IMPORTANT,
                    "Error. Couldn't create MythMediaDevice.");
            return;
        }

        // We store the volume name to improve
        // user activities like ChooseAndEjectMedia().
        char volumeName[MAX_PATH];
        if (GetVolumeInformation(driveName, volumeName, MAX_PATH,
                                 NULL, NULL, NULL, NULL, NULL))
        {
            media->setVolumeID(volumeName);
        }

        AddDevice(media);
    }

    VERBOSE(VB_MEDIA, "Initial device list: " + listDevices());
}
Esempio n. 11
0
/*
 * DBus UDisk AddDevice handler
 */
void MediaMonitorUnix::deviceAdded( QDBusObjectPath o)
{
    LOG(VB_MEDIA, LOG_INFO, LOC + ":deviceAdded " + o.path());

    // Don't add devices with partition tables, just the partitions
    if (!DeviceProperty(o, "DeviceIsPartitionTable").toBool())
    {
        QString dev = DeviceProperty(o, "DeviceFile").toString();

        MythMediaDevice* pDevice;
        if (DeviceProperty(o, "DeviceIsRemovable").toBool())
            pDevice = MythCDROM::get(this, dev.toLatin1(), false, m_AllowEject);
        else
            pDevice = MythHDD::Get(this, dev.toLatin1(), false, false);

        if (pDevice && !AddDevice(pDevice))
            pDevice->deleteLater();
    }
}
QString MediaMonitor::defaultDevice(QString dbSetting,
                                    QString label,
                                    const char *hardCodedDefault)
{
    QString device = gCoreContext->GetSetting(dbSetting);

    LOG(VB_MEDIA, LOG_DEBUG,
             QString("MediaMonitor::defaultDevice(%1,..,%2) dbSetting='%3'")
                 .arg(dbSetting).arg(hardCodedDefault).arg(device));

    // No settings database defaults? Try to choose one:
    if (device.isEmpty() || device == "default")
    {
        device = hardCodedDefault;

        if (!c_monitor)
            c_monitor = GetMediaMonitor();

        if (c_monitor)
        {
            MythMediaDevice *d = c_monitor->selectDrivePopup(label, false, true);

            if (d == (MythMediaDevice *) -1)    // User cancelled
            {
                device.clear(); // If user has explicitly cancelled return empty string
                d = NULL;
            }

            if (d && c_monitor->ValidateAndLock(d))
            {
                device = d->getDevicePath();
                c_monitor->Unlock(d);
            }
        }
    }

    LOG(VB_MEDIA, LOG_DEBUG,
             "MediaMonitor::defaultDevice() returning " + device);
    return device;
}
Esempio n. 13
0
/**
 * \brief Create a MythMedia instance and insert in MythMediaMonitor list
 *
 * We are a friend class of MythMediaMonitor,
 * so that we can add or remove from its list of media objects.
 */
void MonitorThreadDarwin::diskInsert(const char *devName,
                                     const char *volName,
                                     QString model, bool isCDorDVD)
{
    MythMediaDevice  *media;
    QString           msg = "MonitorThreadDarwin::diskInsert";

    LOG(VB_MEDIA, LOG_DEBUG, msg + QString("(%1,%2,'%3',%4)")
                      .arg(devName).arg(volName).arg(model).arg(isCDorDVD));

    if (isCDorDVD)
        media = MythCDROM::get(NULL, devName, true, m_Monitor->m_AllowEject);
    else
        media = MythHDD::Get(NULL, devName, true, false);

    if (!media)
    {
        LOG(VB_GENERAL, LOG_ALERT, msg + "Couldn't create MythMediaDevice.");
        return;
    }

    // We store the volume name for user activities like ChooseAndEjectMedia().
    media->setVolumeID(volName);
    media->setDeviceModel(model.toLatin1());  // Same for the Manufacturer and model

    // Mac OS X devices are pre-mounted here:
    QString mnt = "/Volumes/"; mnt += volName;
    media->setMountPath(mnt.toLatin1());

    int  attempts = 0;
    QDir d(mnt);
    while (!d.exists())
    {
        LOG(VB_MEDIA, LOG_WARNING,
            (msg + "() - Waiting for mount '%1' to become stable.").arg(mnt));
        usleep(120000);
        if ( ++attempts > 4 )
            usleep(200000);
        if ( attempts > 8 )
        {
            delete media;
            LOG(VB_MEDIA, LOG_ALERT, msg + "() - Giving up");
            return;
        }
    }

    media->setStatus(MEDIASTAT_MOUNTED);

    // This is checked in AddDevice(), but checking earlier means
    // we can avoid scanning all the files to determine its type
    if (m_Monitor->shouldIgnore(media))
        return;

    // We want to use MythMedia's code to work out the mediaType.
    // media->onDeviceMounted() is protected,
    // so to call it indirectly, we pretend to mount it here.
    media->mount();

    m_Monitor->AddDevice(media);
}
Esempio n. 14
0
QString MediaMonitor::defaultDevice(QString dbSetting,
                                    QString label,
                                    const char *hardCodedDefault)
{
    QString device = gCoreContext->GetSetting(dbSetting);

    VERBOSE(VB_MEDIA+VB_EXTRA,
            QString("MediaMonitor::defaultDevice(%1,..,%2) dbSetting='%3'")
            .arg(dbSetting).arg(hardCodedDefault).arg(device));

    // No settings database defaults? Try to choose one:
    if (device.isEmpty() || device == "default")
    {
        device = hardCodedDefault;

        if (!c_monitor)
            c_monitor = GetMediaMonitor();

        if (c_monitor)
        {
            MythMediaDevice *d = c_monitor->selectDrivePopup(label);

            if (d == (MythMediaDevice *) -1)    // User cancelled
                d = NULL;

            if (d && c_monitor->ValidateAndLock(d))
            {
                device = d->getDevicePath();
                c_monitor->Unlock(d);
            }
        }
    }

    VERBOSE(VB_MEDIA+VB_EXTRA,
            "MediaMonitor::defaultDevice() returning " + device);
    return device;
}
Esempio n. 15
0
/**
 *  \brief Search /sys/block for valid removable media devices.
 *
 *   This function creates MediaDevice instances for valid removable media
 *   devices found under the /sys/block filesystem in Linux.  CD and DVD
 *   devices are created as MythCDROM instances.  MythHDD instances will be
 *   created for each partition on removable hard disk devices, if they exist.
 *   Otherwise a single MythHDD instance will be created for the entire disc.
 *
 *   NOTE: Floppy disks are ignored.
 */
bool MediaMonitorUnix::CheckMountable(void)
{
#if CONFIG_QTDBUS
    for (int i = 0; i < 10; ++i, usleep(500000))
    {
        // Connect to UDisks.  This can sometimes fail if mythfrontend
        // is started during system init
        QDBusInterface iface(UDISKS_SVC, UDISKS_PATH, UDISKS_IFACE,
            QDBusConnection::systemBus() );
        if (!iface.isValid())
        {
            LOG(VB_GENERAL, LOG_ALERT, LOC +
                "CheckMountable: DBus interface error: " +
                     iface.lastError().message() );
            continue;
        }

        // Enumerate devices
        typedef QList<QDBusObjectPath> QDBusObjectPathList;
        QDBusReply<QDBusObjectPathList> reply = iface.call("EnumerateDevices");
        if (!reply.isValid())
        {
            LOG(VB_GENERAL, LOG_ALERT, LOC +
                "CheckMountable DBus EnumerateDevices error: " +
                     reply.error().message() );
            continue;
        }

        // Listen on DBus for UDisk add/remove device messages
        (void)QDBusConnection::systemBus().connect(
            UDISKS_SVC, UDISKS_PATH, UDISKS_IFACE, UDISKS_DEVADD, UDISKS_DEVSIG,
            this, SLOT(deviceAdded(QDBusObjectPath)) );
        (void)QDBusConnection::systemBus().connect(
            UDISKS_SVC, UDISKS_PATH, UDISKS_IFACE, UDISKS_DEVRMV, UDISKS_DEVSIG,
            this, SLOT(deviceRemoved(QDBusObjectPath)) );

        // Parse the returned device array
        const QDBusObjectPathList& list(reply.value());
        for (QDBusObjectPathList::const_iterator it = list.begin();
            it != list.end(); ++it)
        {
            if (!DeviceProperty(*it, "DeviceIsSystemInternal").toBool() &&
                !DeviceProperty(*it, "DeviceIsPartitionTable").toBool() )
            {
                QString dev = DeviceProperty(*it, "DeviceFile").toString();

                // ignore floppies, too slow
                if (dev.startsWith("/dev/fd"))
                    continue;

                MythMediaDevice* pDevice;
                if (DeviceProperty(*it, "DeviceIsRemovable").toBool())
                    pDevice = MythCDROM::get(this, dev.toLatin1(), false, m_AllowEject);
                else
                    pDevice = MythHDD::Get(this, dev.toLatin1(), false, false);

                if (pDevice && !AddDevice(pDevice))
                    pDevice->deleteLater();
            }
        }

        // Success
        return true;
    }

    // Timed out
    return false;

#elif defined linux
    // NB needs script in /etc/udev/rules.d
    mkfifo(kUDEV_FIFO, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
    m_fifo = open(kUDEV_FIFO, O_RDONLY | O_NONBLOCK);

    QDir sysfs("/sys/block");
    sysfs.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);

    QStringList devices = sysfs.entryList();

    for (QStringList::iterator it = devices.begin(); it != devices.end(); ++it)
    {
        // ignore floppies, too slow
        if ((*it).startsWith("fd"))
            continue;

        sysfs.cd(*it);
        QString path = sysfs.absolutePath();
        if (CheckRemovable(path))
            FindPartitions(path, true);
        sysfs.cdUp();
    }
    return true;
#else // linux
    return false;
#endif
}
Esempio n. 16
0
// Given a fstab entry to a media device determine what type of device it is
bool MediaMonitorUnix::AddDevice(struct fstab * mep)
{
    if (!mep)
        return false;

#ifndef Q_OS_ANDROID
    QString devicePath( mep->fs_spec );
#if 0
    LOG(VB_GENERAL, LOG_DEBUG, "AddDevice - " + devicePath);
#endif

    MythMediaDevice* pDevice = NULL;
    struct stat sbuf;

    bool is_supermount = false;
    bool is_cdrom = false;

    if (stat(mep->fs_spec, &sbuf) < 0)
       return false;

    //  Can it be mounted?
    if ( ! ( ((strstr(mep->fs_mntops, "owner") &&
        (sbuf.st_mode & S_IRUSR)) || strstr(mep->fs_mntops, "user")) &&
        (strstr(mep->fs_vfstype, MNTTYPE_ISO9660) ||
         strstr(mep->fs_vfstype, MNTTYPE_UDF) ||
         strstr(mep->fs_vfstype, MNTTYPE_AUTO)) ) )
    {
        if (strstr(mep->fs_mntops, MNTTYPE_ISO9660) &&
            strstr(mep->fs_vfstype, MNTTYPE_SUPERMOUNT))
        {
            is_supermount = true;
        }
        else
        {
            return false;
        }
    }

    if (strstr(mep->fs_mntops, MNTTYPE_ISO9660)  ||
        strstr(mep->fs_vfstype, MNTTYPE_ISO9660) ||
        strstr(mep->fs_vfstype, MNTTYPE_UDF)     ||
        strstr(mep->fs_vfstype, MNTTYPE_AUTO))
    {
        is_cdrom = true;
#if 0
        LOG(VB_GENERAL, LOG_DEBUG, "Device is a CDROM");
#endif
    }

    if (!is_supermount)
    {
        if (is_cdrom)
            pDevice = MythCDROM::get(this, mep->fs_spec,
                                     is_supermount, m_AllowEject);
    }
    else
    {
        char *dev = 0;
        int len = 0;
        dev = strstr(mep->fs_mntops, SUPER_OPT_DEV);
        if (dev == NULL)
            return false;

        dev += sizeof(SUPER_OPT_DEV)-1;
        while (dev[len] != ',' && dev[len] != ' ' && dev[len] != 0)
            len++;

        if (dev[len] != 0)
        {
            char devstr[256];
            strncpy(devstr, dev, len);
            devstr[len] = 0;
            if (is_cdrom)
                pDevice = MythCDROM::get(this, devstr,
                                         is_supermount, m_AllowEject);
        }
        else
            return false;
    }

    if (pDevice)
    {
        pDevice->setMountPath(mep->fs_file);
        if (pDevice->testMedia() == MEDIAERR_OK)
        {
            if (AddDevice(pDevice))
                return true;
        }
        pDevice->deleteLater();
    }
#endif

    return false;
}
Esempio n. 17
0
/**
 *  \brief Creates MythMedia instances for sysfs removable media devices.
 *
 *   Block devices are represented as directories in sysfs with directories
 *   for each partition underneath the parent device directory.
 *
 *   This function recursively calls itself to find all partitions on a block
 *   device and creates a MythHDD instance for each partition found.  If no
 *   partitions are found and the device is a CD or DVD device a MythCDROM
 *   instance is created.  Otherwise a MythHDD instance is created for the
 *   entire block device.
 *
 *  \param dev path to sysfs block device.
 *  \param checkPartitions check for partitions on block device.
 *  \return true if MythMedia instances are created.
 */
bool MediaMonitorUnix::FindPartitions(const QString &dev, bool checkPartitions)
{
    LOG(VB_MEDIA, LOG_DEBUG,
             LOC + ":FindPartitions(" + dev +
             QString(",%1").arg(checkPartitions ? " true" : " false" ) + ")");
    MythMediaDevice* pDevice = NULL;

    if (checkPartitions)
    {
        // check for partitions
        QDir sysfs(dev);
        sysfs.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);

        bool found_partitions = false;
        QStringList parts = sysfs.entryList();
        for (QStringList::iterator pit = parts.begin();
             pit != parts.end(); ++pit)
        {
            // skip some sysfs dirs that are _not_ sub-partitions
            if (*pit == "device" || *pit == "holders" || *pit == "queue"
                                 || *pit == "slaves"  || *pit == "subsystem"
                                 || *pit == "bdi"     || *pit == "power")
                continue;

            found_partitions |= FindPartitions(
                sysfs.absoluteFilePath(*pit), false);
        }

        // no partitions on block device, use main device
        if (!found_partitions)
            found_partitions |= FindPartitions(sysfs.absolutePath(), false);

        return found_partitions;
    }

    QString device_file = GetDeviceFile(dev);

    if (device_file.isEmpty())
        return false;

    QStringList cdroms = GetCDROMBlockDevices();

    if (cdroms.contains(dev.section('/', -1)))
    {
        // found cdrom device
            pDevice = MythCDROM::get(
                this, device_file.toLatin1().constData(), false, m_AllowEject);
    }
    else
    {
        // found block or partition device
            pDevice = MythHDD::Get(
                this, device_file.toLatin1().constData(), false, false);
    }

    if (AddDevice(pDevice))
        return true;

    if (pDevice)
        pDevice->deleteLater();

    return false;
}