static int read_toc(const char *dev)
{
    int first = 0, last = -1;
    int i;
#if defined(__MINGW32__) || defined(__CYGWIN__)
    HANDLE drive;
    DWORD r;
    CDROM_TOC toc;
    char device[10];

    sprintf(device, "\\\\.\\%s", dev);
    drive = CreateFile(device, GENERIC_READ, FILE_SHARE_READ, NULL,
                       OPEN_EXISTING, 0, 0);

    if (!DeviceIoControl(drive, IOCTL_CDROM_READ_TOC, NULL, 0, &toc,
                         sizeof(CDROM_TOC), &r, 0)) {
        mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to read TOC.\n");
        return 0;
    }

    first = toc.FirstTrack - 1; last = toc.LastTrack;
    for (i = first; i <= last; i++) {
        cdtoc[i].min   = toc.TrackData[i].Address[1];
        cdtoc[i].sec   = toc.TrackData[i].Address[2];
        cdtoc[i].frame = toc.TrackData[i].Address[3];
    }
    CloseHandle(drive);

#elif defined(__OS2__)
    UCHAR auchParamDisk[4] = {'C', 'D', '0', '1'};

    struct {
        BYTE    bFirstTrack;
        BYTE    bLastTrack;
        BYTE    bLeadOutF;
        BYTE    bLeadOutS;
        BYTE    bLeadOutM;
        BYTE    bLeadOutReserved;
    } __attribute__((packed)) sDataDisk;

    struct {
        UCHAR   auchSign[4];
        BYTE    bTrack;
    } __attribute__((packed)) sParamTrack = {{'C', 'D', '0', '1'},};

    struct {
        BYTE    bStartF;
        BYTE    bStartS;
        BYTE    bStartM;
        BYTE    bStartReserved;
        BYTE    bControlInfo;
    } __attribute__((packed)) sDataTrack;

    HFILE hcd;
    ULONG ulAction;
    ULONG ulParamLen;
    ULONG ulDataLen;
    ULONG rc;

    rc = DosOpen(dev, &hcd, &ulAction, 0, FILE_NORMAL,
                 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
                 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE | OPEN_FLAGS_DASD,
                 NULL);
    if (rc) {
        mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to read TOC.\n");
        return -1;
    }

    rc = DosDevIOCtl(hcd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIODISK,
                     auchParamDisk, sizeof(auchParamDisk), &ulParamLen,
                     &sDataDisk, sizeof(sDataDisk), &ulDataLen);
    if (!rc) {
        first = sDataDisk.bFirstTrack - 1;
        last  = sDataDisk.bLastTrack;
        for (i = first; i <= last; i++) {
            if (i == last) {
                sDataTrack.bStartM = sDataDisk.bLeadOutM;
                sDataTrack.bStartS = sDataDisk.bLeadOutS;
                sDataTrack.bStartF = sDataDisk.bLeadOutF;
            } else {
                sParamTrack.bTrack = i + 1;
                rc = DosDevIOCtl(hcd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIOTRACK,
                                 &sParamTrack, sizeof(sParamTrack), &ulParamLen,
                                 &sDataTrack, sizeof(sDataTrack), &ulDataLen);
                if (rc)
                    break;
            }

            cdtoc[i].min   = sDataTrack.bStartM;
            cdtoc[i].sec   = sDataTrack.bStartS;
            cdtoc[i].frame = sDataTrack.bStartF;
        }
    }

    DosClose(hcd);

    if (rc) {
        mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to read TOC.\n");
        return -1;
    }
#else
    int drive;
    drive = open(dev, O_RDONLY | O_NONBLOCK);
    if (drive < 0) {
        return drive;
    }

#if defined(__linux__) || defined(__bsdi__)
    {
        struct cdrom_tochdr tochdr;
        ioctl(drive, CDROMREADTOCHDR, &tochdr);
        first = tochdr.cdth_trk0 - 1; last = tochdr.cdth_trk1;
    }
    for (i = first; i <= last; i++) {
        struct cdrom_tocentry tocentry;
        tocentry.cdte_track  = (i == last) ? 0xAA : i + 1;
        tocentry.cdte_format = CDROM_MSF;
        ioctl(drive, CDROMREADTOCENTRY, &tocentry);
        cdtoc[i].min   = tocentry.cdte_addr.msf.minute;
        cdtoc[i].sec   = tocentry.cdte_addr.msf.second;
        cdtoc[i].frame = tocentry.cdte_addr.msf.frame;
    }
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
    {
        struct ioc_toc_header tochdr;
        ioctl(drive, CDIOREADTOCHEADER, &tochdr);
        first = tochdr.starting_track - 1; last = tochdr.ending_track;
    }
    for (i = first; i <= last; i++) {
        struct ioc_read_toc_single_entry tocentry;
        tocentry.track          = (i == last) ? 0xAA : i + 1;
        tocentry.address_format = CD_MSF_FORMAT;
        ioctl(drive, CDIOREADTOCENTRY, &tocentry);
        cdtoc[i].min   = tocentry.entry.addr.msf.minute;
        cdtoc[i].sec   = tocentry.entry.addr.msf.second;
        cdtoc[i].frame = tocentry.entry.addr.msf.frame;
    }
#elif defined(__NetBSD__) || defined(__OpenBSD__)
    {
        struct ioc_toc_header tochdr;
        ioctl(drive, CDIOREADTOCHEADER, &tochdr);
        first = tochdr.starting_track - 1; last = tochdr.ending_track;
    }
    for (i = first; i <= last; i++) {
        struct ioc_read_toc_entry tocentry;
        struct cd_toc_entry toc_buffer;
        tocentry.starting_track = (i == last) ? 0xAA : i + 1;
        tocentry.address_format = CD_MSF_FORMAT;
        tocentry.data           = &toc_buffer;
        tocentry.data_len       = sizeof(toc_buffer);
        ioctl(drive, CDIOREADTOCENTRYS, &tocentry);
        cdtoc[i].min   = toc_buffer.addr.msf.minute;
        cdtoc[i].sec   = toc_buffer.addr.msf.second;
        cdtoc[i].frame = toc_buffer.addr.msf.frame;
    }
#elif defined(__APPLE__) || defined(__DARWIN__)
    {
        dk_cd_read_toc_t tochdr;
        uint8_t buf[4];
        uint8_t buf2[100 * sizeof(CDTOCDescriptor) + sizeof(CDTOC)];
        memset(&tochdr, 0, sizeof(tochdr));
        tochdr.bufferLength = sizeof(buf);
        tochdr.buffer       = &buf;
        if (!ioctl(drive, DKIOCCDREADTOC, &tochdr)
            && tochdr.bufferLength == sizeof(buf)) {
            first = buf[2] - 1;
            last  = buf[3];
        }
        if (last >= 0) {
            memset(&tochdr, 0, sizeof(tochdr));
            tochdr.bufferLength = sizeof(buf2);
            tochdr.buffer       = &buf2;
            tochdr.format       = kCDTOCFormatTOC;
            if (ioctl(drive, DKIOCCDREADTOC, &tochdr)
                || tochdr.bufferLength < sizeof(CDTOC))
                last = -1;
        }
        if (last >= 0) {
            CDTOC *cdToc = (CDTOC *)buf2;
            CDTrackInfo lastTrack;
            dk_cd_read_track_info_t trackInfoParams;
            for (i = first; i < last; ++i) {
                CDMSF msf = CDConvertTrackNumberToMSF(i + 1, cdToc);
                cdtoc[i].min   = msf.minute;
                cdtoc[i].sec   = msf.second;
                cdtoc[i].frame = msf.frame;
            }
            memset(&trackInfoParams, 0, sizeof(trackInfoParams));
            trackInfoParams.addressType  = kCDTrackInfoAddressTypeTrackNumber;
            trackInfoParams.bufferLength = sizeof(lastTrack);
            trackInfoParams.address      = last;
            trackInfoParams.buffer       = &lastTrack;
            if (!ioctl(drive, DKIOCCDREADTRACKINFO, &trackInfoParams)) {
                CDMSF msf = CDConvertLBAToMSF(be2me_32(lastTrack.trackStartAddress)
                            + be2me_32(lastTrack.trackSize));
                cdtoc[last].min   = msf.minute;
                cdtoc[last].sec   = msf.second;
                cdtoc[last].frame = msf.frame;
            }
        }
    }
#endif
    close(drive);
#endif
    for (i = first; i <= last; i++)
        cdtoc[i].frame += (cdtoc[i].min * 60 + cdtoc[i].sec) * 75;
    return last;
}
Exemple #2
0
static int read_toc(const char *dev)
{
    int first = 0, last = -1;
    int i;
#if defined(__MINGW32__) || defined(__CYGWIN__)
    HANDLE drive;
    DWORD r;
    CDROM_TOC toc;
    char device[10];

    snprintf(device, sizeof(device), "\\\\.\\%s", dev);
    drive = CreateFile(device, GENERIC_READ, FILE_SHARE_READ, NULL,
                       OPEN_EXISTING, 0, 0);

    if (!DeviceIoControl(drive, IOCTL_CDROM_READ_TOC, NULL, 0, &toc,
                         sizeof(CDROM_TOC), &r, 0)) {
        mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to read TOC.\n");
        return 0;
    }

    first = toc.FirstTrack - 1; last = toc.LastTrack;
    for (i = first; i <= last; i++) {
        cdtoc[i].min   = toc.TrackData[i].Address[1];
        cdtoc[i].sec   = toc.TrackData[i].Address[2];
        cdtoc[i].frame = toc.TrackData[i].Address[3];
    }
    CloseHandle(drive);

#else
    int drive;
    drive = open(dev, O_RDONLY | O_NONBLOCK);
    if (drive < 0) {
        return drive;
    }

#if defined(__linux__) || defined(__bsdi__)
    {
        struct cdrom_tochdr tochdr;
        ioctl(drive, CDROMREADTOCHDR, &tochdr);
        first = tochdr.cdth_trk0 - 1; last = tochdr.cdth_trk1;
    }
    for (i = first; i <= last; i++) {
        struct cdrom_tocentry tocentry;
        tocentry.cdte_track  = (i == last) ? 0xAA : i + 1;
        tocentry.cdte_format = CDROM_MSF;
        ioctl(drive, CDROMREADTOCENTRY, &tocentry);
        cdtoc[i].min   = tocentry.cdte_addr.msf.minute;
        cdtoc[i].sec   = tocentry.cdte_addr.msf.second;
        cdtoc[i].frame = tocentry.cdte_addr.msf.frame;
    }
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
    {
        struct ioc_toc_header tochdr;
        ioctl(drive, CDIOREADTOCHEADER, &tochdr);
        first = tochdr.starting_track - 1; last = tochdr.ending_track;
    }
    for (i = first; i <= last; i++) {
        struct ioc_read_toc_single_entry tocentry;
        tocentry.track          = (i == last) ? 0xAA : i + 1;
        tocentry.address_format = CD_MSF_FORMAT;
        ioctl(drive, CDIOREADTOCENTRY, &tocentry);
        cdtoc[i].min   = tocentry.entry.addr.msf.minute;
        cdtoc[i].sec   = tocentry.entry.addr.msf.second;
        cdtoc[i].frame = tocentry.entry.addr.msf.frame;
    }
#elif defined(__NetBSD__) || defined(__OpenBSD__)
    {
        struct ioc_toc_header tochdr;
        ioctl(drive, CDIOREADTOCHEADER, &tochdr);
        first = tochdr.starting_track - 1; last = tochdr.ending_track;
    }
    for (i = first; i <= last; i++) {
        struct ioc_read_toc_entry tocentry;
        struct cd_toc_entry toc_buffer;
        tocentry.starting_track = (i == last) ? 0xAA : i + 1;
        tocentry.address_format = CD_MSF_FORMAT;
        tocentry.data           = &toc_buffer;
        tocentry.data_len       = sizeof(toc_buffer);
        ioctl(drive, CDIOREADTOCENTRYS, &tocentry);
        cdtoc[i].min   = toc_buffer.addr.msf.minute;
        cdtoc[i].sec   = toc_buffer.addr.msf.second;
        cdtoc[i].frame = toc_buffer.addr.msf.frame;
    }
#elif defined(__APPLE__) || defined(__DARWIN__)
    {
        dk_cd_read_toc_t tochdr;
        uint8_t buf[4];
        uint8_t buf2[100 * sizeof(CDTOCDescriptor) + sizeof(CDTOC)];
        memset(&tochdr, 0, sizeof(tochdr));
        tochdr.bufferLength = sizeof(buf);
        tochdr.buffer       = &buf;
        if (!ioctl(drive, DKIOCCDREADTOC, &tochdr)
            && tochdr.bufferLength == sizeof(buf)) {
            first = buf[2] - 1;
            last  = buf[3];
        }
        if (last >= 0) {
            memset(&tochdr, 0, sizeof(tochdr));
            tochdr.bufferLength = sizeof(buf2);
            tochdr.buffer       = &buf2;
            tochdr.format       = kCDTOCFormatTOC;
            if (ioctl(drive, DKIOCCDREADTOC, &tochdr)
                || tochdr.bufferLength < sizeof(CDTOC))
                last = -1;
        }
        if (last >= 0) {
            CDTOC *cdToc = (CDTOC *)buf2;
            CDTrackInfo lastTrack;
            dk_cd_read_track_info_t trackInfoParams;
            for (i = first; i < last; ++i) {
                CDMSF msf = CDConvertTrackNumberToMSF(i + 1, cdToc);
                cdtoc[i].min   = msf.minute;
                cdtoc[i].sec   = msf.second;
                cdtoc[i].frame = msf.frame;
            }
            memset(&trackInfoParams, 0, sizeof(trackInfoParams));
            trackInfoParams.addressType  = kCDTrackInfoAddressTypeTrackNumber;
            trackInfoParams.bufferLength = sizeof(lastTrack);
            trackInfoParams.address      = last;
            trackInfoParams.buffer       = &lastTrack;
            if (!ioctl(drive, DKIOCCDREADTRACKINFO, &trackInfoParams)) {
                CDMSF msf = CDConvertLBAToMSF(be2me_32(lastTrack.trackStartAddress)
                            + be2me_32(lastTrack.trackSize));
                cdtoc[last].min   = msf.minute;
                cdtoc[last].sec   = msf.second;
                cdtoc[last].frame = msf.frame;
            }
        }
    }
#endif
    close(drive);
#endif
    for (i = first; i <= last; i++)
        cdtoc[i].frame += (cdtoc[i].min * 60 + cdtoc[i].sec) * 75;
    return last;
}