Ticket #4877: CDefficiency.fixes.patch

File CDefficiency.fixes.patch, 17.7 KB (added by Nigel, 12 years ago)

0-21 fixes checkMedia optimisation

  • mythcdrom-linux.cpp

     
    2020#define ASSUME_WANT_AUDIO 1
    2121
    2222// This class is verbose enough, but if you really need more output:
    23 //#define EXTRA_VERBOSITY   1
     23#define EXTRA_VERBOSITY   1
    2424
    2525
    2626// Some features cannot be detected (reliably) using the standard
     
    162162{
    163163    int drive_status = ioctl(m_DeviceHandle, CDROM_DRIVE_STATUS, CDSL_CURRENT);
    164164
    165     if (drive_status == CDS_TRAY_OPEN && getDevicePath().contains("/dev/scd"))
     165    if (drive_status == -1)   // Very unlikely, but we should check
     166    {
     167        VERBOSE(VB_MEDIA, LOC + ":driveStatus() - ioctl() failed: " + ENO);
     168        return CDS_NO_INFO;
     169    }
     170
     171    if (drive_status == CDS_TRAY_OPEN && m_DevicePath.contains("/dev/scd"))
    166172        return SCSIstatus();
    167173
    168174    return drive_status;
     
    193199        VERBOSE(VB_MEDIA,
    194200                LOC + ":hasWritableMedia() - failed to send packet to "
    195201                    + m_DevicePath);
    196         return 0;
     202        return false;
    197203    }
    198204
    199205    di = (CDROMdiscInfo *) buffer;
     
    327333        {
    328334#ifdef EXTRA_VERBOSITY
    329335            VERBOSE(VB_MEDIA, LOC + ":testMedia - failed to open "
    330                               + getDevicePath() + ENO);
     336                              + m_DevicePath + ENO);
    331337#endif
    332338            if (errno == EBUSY)
    333339                return isMounted(true) ? MEDIAERR_OK : MEDIAERR_FAILED;
     
    350356
    351357    if (Stat == -1)
    352358    {
    353         VERBOSE(VB_MEDIA, LOC + ":testMedia - Failed to get drive status of "
    354                           + getDevicePath() + ENO);
     359        VERBOSE(VB_MEDIA, LOC + ":testMedia - Failed to get drive status of '"
     360                          + m_DevicePath + "' : " + ENO);
    355361        return MEDIAERR_FAILED;
    356362    }
    357363
     
    362368{
    363369    bool OpenedHere = false;
    364370
    365     if (testMedia() != MEDIAERR_OK)
    366     {
    367         m_MediaType = MEDIATYPE_UNKNOWN;
    368         return setStatus(MEDIASTAT_UNKNOWN, OpenedHere);
    369     }
    370 
    371371    // If it's not already open we need to at least
    372372    // TRY to open it for most of these checks to work.
    373373    if (!isDeviceOpen())
     374    {
    374375        OpenedHere = openDevice();
    375376
    376     if (isDeviceOpen())
     377        if (!OpenedHere)
     378        {
     379            VERBOSE(VB_MEDIA, LOC + ":checkMedia() - cannot open device '"
     380                                  + m_DevicePath + "' : "
     381                                  + ENO + "- returning UNKNOWN");
     382            m_MediaType = MEDIATYPE_UNKNOWN;
     383            return setStatus(MEDIASTAT_UNKNOWN, false);
     384        }
     385    }
     386
     387    switch (driveStatus())
    377388    {
     389        case CDS_DISC_OK:
     390            VERBOSE(VB_MEDIA, m_DevicePath + " Disk OK, type = "
     391                              + MediaTypeString(m_MediaType) );
     392            // further checking is required
     393            break;
     394        case CDS_TRAY_OPEN:
     395            VERBOSE(VB_MEDIA, m_DevicePath + " Tray open or no disc");
     396            // If there was media previously, this will
     397            // send a message to the plugins to forget it
     398            setStatus(MEDIASTAT_OPEN, OpenedHere);
     399            // then reset
     400            m_MediaType = MEDIATYPE_UNKNOWN;
     401            return MEDIASTAT_OPEN;
     402            break;
     403        case CDS_NO_DISC:
     404            VERBOSE(VB_MEDIA, m_DevicePath + " No disc");
     405            m_MediaType = MEDIATYPE_UNKNOWN;
     406            return setStatus(MEDIASTAT_NODISK, OpenedHere);
     407            break;
     408        case CDS_NO_INFO:
     409        case CDS_DRIVE_NOT_READY:
     410            VERBOSE(VB_MEDIA, m_DevicePath + " No info or drive not ready");
     411            m_MediaType = MEDIATYPE_UNKNOWN;
     412            return setStatus(MEDIASTAT_UNKNOWN, OpenedHere);
     413        default:
     414            VERBOSE(VB_IMPORTANT, "Failed to get drive status of "
     415                                  + m_DevicePath + " : " + ENO);
     416            m_MediaType = MEDIATYPE_UNKNOWN;
     417            return setStatus(MEDIASTAT_UNKNOWN, OpenedHere);
     418    }
     419
     420    if (mediaChanged())
     421    {
     422        VERBOSE(VB_MEDIA, m_DevicePath + " Media changed");
     423        // Regardless of the actual status lie here and say
     424        // it's open for now, so we can cover the case of a missed open.
     425        return setStatus(MEDIASTAT_OPEN, OpenedHere);
     426    }
     427
     428
     429    if (isUsable())
     430    {
    378431#ifdef EXTRA_VERBOSITY
    379         VERBOSE(VB_MEDIA, LOC + ":checkMedia - Device is open...");
     432        VERBOSE(VB_MEDIA, "Disc useable, media unchanged. All good!");
    380433#endif
    381         switch (driveStatus())
     434        if (OpenedHere)
     435            closeDevice();
     436        return MEDIASTAT_USEABLE;
     437    }
     438
     439    // If we have tried to mount and failed, don't keep trying
     440    if (m_Status == MEDIASTAT_ERROR)
     441    {
     442#ifdef EXTRA_VERBOSITY
     443        VERBOSE(VB_MEDIA, "Disc is unmountable?");
     444#endif
     445        if (OpenedHere)
     446            closeDevice();
     447        return m_Status;
     448    }
     449
     450    if ((m_Status == MEDIASTAT_OPEN) ||
     451        (m_Status == MEDIASTAT_UNKNOWN))
     452    {
     453        VERBOSE(VB_MEDIA, m_DevicePath + " Current status " +
     454                MythMediaDevice::MediaStatusStrings[m_Status]);
     455        int type = ioctl(m_DeviceHandle, CDROM_DISC_STATUS, CDSL_CURRENT);
     456        switch (type)
    382457        {
    383             case CDS_DISC_OK:
    384                 VERBOSE(VB_MEDIA, getDevicePath() + " Disk OK, type = "
    385                                   + MediaTypeString(m_MediaType) );
    386                 // 1. Audio CDs are not mounted
    387                 // 2. If we don't know the media type yet,
    388                 //    test the disk after this switch exits
    389                 if (m_MediaType == MEDIATYPE_AUDIO ||
    390                     m_MediaType == MEDIATYPE_UNKNOWN)
    391                     break;
    392                 // If we have tried to mount and failed, don't keep trying:
    393                 if (m_Status == MEDIASTAT_ERROR)
    394                     return m_Status;
    395                 // If the disc is ok and we already know it's mediatype
    396                 // returns MOUNTED.
     458            case CDS_DATA_1:
     459            case CDS_DATA_2:
     460                m_MediaType = MEDIATYPE_DATA;
     461                VERBOSE(VB_MEDIA, "Found a data disk");
     462                //grab information from iso9660 (& udf)
     463                struct iso_primary_descriptor buf;
     464                lseek(this->m_DeviceHandle,(off_t) 2048*16,SEEK_SET);
     465                read(this->m_DeviceHandle, &buf,2048);
     466                this->m_VolumeID = QString(buf.volume_id).stripWhiteSpace();
     467                this->m_KeyID = QString("%1%2").arg(this->m_VolumeID)
     468                                .arg(QString(buf.creation_date).left(16));
     469
     470                // the base class's onDeviceMounted will do fine
     471                // grained detection of the type of data on this disc
    397472                if (isMounted(true))
     473                    onDeviceMounted();
     474                else
     475                    if (mount())
     476                        ;    // onDeviceMounted() called as side-effect
     477                    else
     478                        return setStatus(MEDIASTAT_ERROR, OpenedHere);
     479
     480                if (isMounted(true))
     481                {
     482                    // pretend we're NOTMOUNTED so setStatus emits a signal
     483                    m_Status = MEDIASTAT_NOTMOUNTED;
    398484                    return setStatus(MEDIASTAT_MOUNTED, OpenedHere);
     485                }
     486                else if (m_MediaType == MEDIATYPE_DVD)
     487                {
     488                    // pretend we're NOTMOUNTED so setStatus emits a signal
     489                    m_Status = MEDIASTAT_NOTMOUNTED;
     490                    return setStatus(MEDIASTAT_USEABLE, OpenedHere);
     491                }
     492                else
     493                    return setStatus(MEDIASTAT_NOTMOUNTED, OpenedHere);
    399494                break;
    400             case CDS_TRAY_OPEN:
    401                 VERBOSE(VB_MEDIA, getDevicePath() + " Tray open or no disc");
    402                 setStatus(MEDIASTAT_OPEN, OpenedHere);
    403                 m_MediaType = MEDIATYPE_UNKNOWN;
    404                 return MEDIASTAT_OPEN;
     495            case CDS_AUDIO:
     496                VERBOSE(VB_MEDIA, "found an audio disk");
     497                m_MediaType = MEDIATYPE_AUDIO;
     498                return setStatus(MEDIASTAT_USEABLE, OpenedHere);
    405499                break;
    406             case CDS_NO_DISC:
    407                 VERBOSE(VB_MEDIA, getDevicePath() + " No disc");
    408                 m_MediaType = MEDIATYPE_UNKNOWN;
    409                 return setStatus(MEDIASTAT_NODISK, OpenedHere);
     500            case CDS_MIXED:
     501                m_MediaType = MEDIATYPE_MIXED;
     502                VERBOSE(VB_MEDIA, "found a mixed CD");
     503                // Note: Mixed mode CDs require an explixit mount call
     504                //       since we'll usually want the audio portion.
     505                // undefine ASSUME_WANT_AUDIO to change this behavior.
     506                #ifdef ASSUME_WANT_AUDIO
     507                    return setStatus(MEDIASTAT_USEABLE, OpenedHere);
     508                #else
     509                    mount();
     510                    if (isMounted(true))
     511                    {
     512                        // pretend we're NOTMOUNTED so setStatus
     513                        // emits a signal
     514                        m_Status = MEDIASTAT_NOTMOUNTED;
     515                        return setStatus(MEDIASTAT_MOUNTED, OpenedHere);
     516                    }
     517                    else
     518                    {
     519                        return setStatus(MEDIASTAT_USEABLE, OpenedHere);
     520                    }
     521                #endif
    410522                break;
    411523            case CDS_NO_INFO:
    412             case CDS_DRIVE_NOT_READY:
    413                 VERBOSE(VB_MEDIA, getDevicePath()
    414                                   + " No info or drive not ready");
     524            case CDS_NO_DISC:
     525                if (hasWritableMedia())
     526                {
     527                    VERBOSE(VB_MEDIA, "found a blank or writable disk");
     528                    return setStatus(MEDIASTAT_UNFORMATTED, OpenedHere);
     529                }
     530
     531                VERBOSE(VB_MEDIA, "found no disk");
    415532                m_MediaType = MEDIATYPE_UNKNOWN;
    416533                return setStatus(MEDIASTAT_UNKNOWN, OpenedHere);
     534                break;
    417535            default:
    418                 VERBOSE(VB_IMPORTANT, "Failed to get drive status of "
    419                                       + getDevicePath() + " : " + ENO);
     536                VERBOSE(VB_MEDIA, "found unknown disk type: "
     537                                  + QString().setNum(type));
    420538                m_MediaType = MEDIATYPE_UNKNOWN;
    421539                return setStatus(MEDIASTAT_UNKNOWN, OpenedHere);
    422540        }
     541    }
    423542
    424         if (mediaChanged())
    425         {
    426             VERBOSE(VB_MEDIA, getDevicePath() + " Media changed");
    427             // Regardless of the actual status lie here and say
    428             // it's open for now, so we can cover the case of a missed open.
    429             return setStatus(MEDIASTAT_OPEN, OpenedHere);
    430         }
    431         else
    432         {
    433 #ifdef EXTRA_VERBOSITY
    434             VERBOSE(VB_MEDIA, getDevicePath() + " Media unchanged...");
    435 #endif
    436             if ((m_Status == MEDIASTAT_OPEN) ||
    437                 (m_Status == MEDIASTAT_UNKNOWN))
    438             {
    439                 VERBOSE(VB_MEDIA, getDevicePath() + " Current status " +
    440                         MythMediaDevice::MediaStatusStrings[m_Status]);
    441                 int type = ioctl(m_DeviceHandle,
    442                                  CDROM_DISC_STATUS, CDSL_CURRENT);
    443                 switch (type)
    444                 {
    445                     case CDS_DATA_1:
    446                     case CDS_DATA_2:
    447                         m_MediaType = MEDIATYPE_DATA;
    448                         VERBOSE(VB_MEDIA, "Found a data disk");
    449                         //grab information from iso9660 (& udf)
    450                         struct iso_primary_descriptor buf;
    451                         lseek(this->m_DeviceHandle,(off_t) 2048*16,SEEK_SET);
    452                         read(this->m_DeviceHandle, &buf,2048);
    453                         this->m_VolumeID = QString(buf.volume_id)
    454                                                        .stripWhiteSpace();
    455                         this->m_KeyID = QString("%1%2")
    456                                       .arg(this->m_VolumeID)
    457                                       .arg(QString(buf.creation_date).left(16));
    458 
    459                         // the base class's onDeviceMounted will do fine
    460                         // grained detection of the type of data on this disc
    461                         if (isMounted(true))
    462                             onDeviceMounted();
    463                         else
    464                             if (mount())
    465                                 ;    // onDeviceMounted() called as side-effect
    466                             else
    467                                 return setStatus(MEDIASTAT_ERROR, OpenedHere);
    468 
    469                         if (isMounted(true))
    470                         {
    471                             // pretend we're NOTMOUNTED so setStatus emits
    472                             // a signal
    473                             m_Status = MEDIASTAT_NOTMOUNTED;
    474                             return setStatus(MEDIASTAT_MOUNTED, OpenedHere);
    475                         }
    476                         else if (m_MediaType == MEDIATYPE_DVD)
    477                         {
    478                             // pretend we're NOTMOUNTED so setStatus emits
    479                             // a signal
    480                             m_Status = MEDIASTAT_NOTMOUNTED;
    481                             return setStatus(MEDIASTAT_USEABLE, OpenedHere);
    482                         }
    483                         else
    484                             return setStatus(MEDIASTAT_NOTMOUNTED, OpenedHere);
    485                         break;
    486                     case CDS_AUDIO:
    487                         VERBOSE(VB_MEDIA, "found an audio disk");
    488                         m_MediaType = MEDIATYPE_AUDIO;
    489                         return setStatus(MEDIASTAT_USEABLE, OpenedHere);
    490                         break;
    491                     case CDS_MIXED:
    492                         m_MediaType = MEDIATYPE_MIXED;
    493                         VERBOSE(VB_MEDIA, "found a mixed CD");
    494                         // Note: Mixed mode CDs require an explixit mount call
    495                         //       since we'll usually want the audio portion.
    496                         // undefine ASSUME_WANT_AUDIO to change this behavior.
    497                         #ifdef ASSUME_WANT_AUDIO
    498                             return setStatus(MEDIASTAT_USEABLE, OpenedHere);
    499                         #else
    500                             mount();
    501                             if (isMounted(true))
    502                             {
    503                                 // pretend we're NOTMOUNTED so setStatus
    504                                 // emits a signal
    505                                 m_Status = MEDIASTAT_NOTMOUNTED;
    506                                 return setStatus(MEDIASTAT_MOUNTED,
    507                                                  OpenedHere);
    508                             }
    509                             else
    510                             {
    511                                 return setStatus(MEDIASTAT_USEABLE,
    512                                                  OpenedHere);
    513                             }
    514                         #endif
    515                         break;
    516                     case CDS_NO_INFO:
    517                     case CDS_NO_DISC:
    518                         if (hasWritableMedia())
    519                         {
    520                             VERBOSE(VB_MEDIA, "found a blank or writable disk");
    521                             return setStatus(MEDIASTAT_UNFORMATTED, OpenedHere);
    522                         }
    523 
    524                         VERBOSE(VB_MEDIA, "found no disk");
    525                         m_MediaType = MEDIATYPE_UNKNOWN;
    526                         return setStatus(MEDIASTAT_UNKNOWN, OpenedHere);
    527                         break;
    528                     default:
    529                         VERBOSE(VB_MEDIA, "found unknown disk type: "
    530                                           + QString().setNum(type));
    531                         m_MediaType = MEDIATYPE_UNKNOWN;
    532                         return setStatus(MEDIASTAT_UNKNOWN, OpenedHere);
    533                 }
    534             }
    535             else if (m_Status == MEDIASTAT_MOUNTED ||
    536                      m_Status == MEDIASTAT_NOTMOUNTED)
    537             {
    538                 VERBOSE(VB_MEDIA, QString("Current status == ") +
    539                         MythMediaDevice::MediaStatusStrings[m_Status]);
    540                 VERBOSE(VB_MEDIA, "Setting status to not mounted?");
    541                 if (isMounted(true))
    542                     setStatus(MEDIASTAT_MOUNTED, OpenedHere);
    543                 else
    544                     setStatus(MEDIASTAT_NOTMOUNTED, OpenedHere);
    545             }
    546 
    547             if (m_AllowEject)
    548                 ioctl(m_DeviceHandle, CDROM_LOCKDOOR, 0);
    549         }// mediaChanged()
    550     } // isDeviceOpen();
     543    if (m_AllowEject)
     544        unlock();
    551545    else
    552     {
    553         VERBOSE(VB_MEDIA, "Device not open - returning UNKNOWN");
    554         m_MediaType = MEDIATYPE_UNKNOWN;
    555         return setStatus(MEDIASTAT_UNKNOWN, OpenedHere);
    556     }
     546        lock();
    557547
    558548    if (OpenedHere)
    559549        closeDevice();
  • mythcdrom.h

     
    1414
    1515    virtual bool mediaChanged(void) { return false; }
    1616    virtual bool checkOK(void)      { return true; }
    17     virtual bool openDevice(void);
    1817    virtual MediaStatus checkMedia(void)
    1918    {
    2019        return setStatus(MEDIASTAT_UNKNOWN, false);
  • mythcdrom.cpp

     
    4747{
    4848}
    4949
    50 bool MythCDROM::openDevice()
    51 {
    52     if (MythMediaDevice::openDevice())
    53     {
    54         // If allow eject is on, unlock the door.
    55         if (m_AllowEject)
    56             unlock();
    57        
    58         return true;
    59     }
    60 
    61     return false;
    62 }
    63 
    6450void MythCDROM::onDeviceMounted()
    6551{
    6652    if (!QDir(m_MountPath).exists())