Пример #1
0
Файл: vcd.c Проект: Ackhuman/vlc
/*****************************************************************************
 * EntryPoints: Reads the information about the entry points on the disc.
 *****************************************************************************/
static int EntryPoints( access_t *p_access )
{
    access_sys_t *p_sys = p_access->p_sys;
    uint8_t      sector[VCD_DATA_SIZE];

    entries_sect_t entries;
    int i_nb;

    /* Read the entry point sector */
    if( ioctl_ReadSectors( VLC_OBJECT(p_access), p_sys->vcddev,
        VCD_ENTRIES_SECTOR, sector, 1, VCD_TYPE ) < 0 )
    {
        msg_Err( p_access, "could not read entry points sector" );
        return VLC_EGENERIC;
    }
    memcpy( &entries, sector, CD_SECTOR_SIZE );

    i_nb = GetWBE( &entries.i_entries_nb );
    if( i_nb > 500 )
    {
        msg_Err( p_access, "invalid entry points number" );
        return VLC_EGENERIC;
    }

    if( strncmp( entries.psz_id, "ENTRYVCD", sizeof( entries.psz_id ) ) &&
        strncmp( entries.psz_id, "ENTRYSVD", sizeof( entries.psz_id ) ) )
    {
        msg_Err( p_access, "unrecognized entry points format" );
        return VLC_EGENERIC;
    }

    for( int i = 0; i < i_nb; i++ )
    {
        const int i_title = BCD_TO_BIN(entries.entry[i].i_track) - 2;
        const int i_sector =
            (MSF_TO_LBA2( BCD_TO_BIN( entries.entry[i].msf.minute ),
                          BCD_TO_BIN( entries.entry[i].msf.second ),
                          BCD_TO_BIN( entries.entry[i].msf.frame  ) ));
        seekpoint_t *s;

        if( i_title < 0 ) continue;   /* Should not occur */
        if( i_title >= p_sys->i_titles ) continue;

        msg_Dbg( p_access, "Entry[%d] title=%d sector=%d",
                 i, i_title, i_sector );

        s = vlc_seekpoint_New();
        s->i_byte_offset = (i_sector - p_sys->p_sectors[i_title+1]) *
            VCD_DATA_SIZE;

        TAB_APPEND( p_sys->title[i_title]->i_seekpoint,
                    p_sys->title[i_title]->seekpoint, s );
    }

    return VLC_SUCCESS;
}
Пример #2
0
Файл: cdrom.c Проект: Geal/vlc
/*****************************************************************************
 * ioctl_GetTracksMap: Read the Table of Content, fill in the pp_sectors map
 *                     if pp_sectors is not null and return the number of
 *                     tracks available.
 *****************************************************************************/
int ioctl_GetTracksMap( vlc_object_t *p_this, const vcddev_t *p_vcddev,
                        int **pp_sectors )
{
    int i_tracks = 0;

    if( p_vcddev->i_vcdimage_handle != -1 )
    {
        /*
         *  vcd image mode
         */

        i_tracks = p_vcddev->i_tracks;

        if( pp_sectors )
        {
            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
            if( *pp_sectors == NULL )
                return 0;
            memcpy( *pp_sectors, p_vcddev->p_sectors,
                    (i_tracks + 1) * sizeof(**pp_sectors) );
        }

        return i_tracks;
    }
    else
    {

        /*
         *  vcd device mode
         */

#if defined( __APPLE__ )

        CDTOC *pTOC;
        int i_descriptors;

        if( ( pTOC = darwin_getTOC( p_this, p_vcddev ) ) == NULL )
        {
            msg_Err( p_this, "failed to get the TOC" );
            return 0;
        }

        i_descriptors = CDTOCGetDescriptorCount( pTOC );
        i_tracks = darwin_getNumberOfTracks( pTOC, i_descriptors );

        if( pp_sectors )
        {
            int i, i_leadout = -1;
            CDTOCDescriptor *pTrackDescriptors;
            u_char track;

            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
            if( *pp_sectors == NULL )
            {
                darwin_freeTOC( pTOC );
                return 0;
            }

            pTrackDescriptors = pTOC->descriptors;

            for( i_tracks = 0, i = 0; i < i_descriptors; i++ )
            {
                track = pTrackDescriptors[i].point;

                if( track == 0xA2 )
                    i_leadout = i;

                if( track > CD_MAX_TRACK_NO || track < CD_MIN_TRACK_NO )
                    continue;

                (*pp_sectors)[i_tracks++] =
                    CDConvertMSFToLBA( pTrackDescriptors[i].p );
            }

            if( i_leadout == -1 )
            {
                msg_Err( p_this, "leadout not found" );
                free( *pp_sectors );
                darwin_freeTOC( pTOC );
                return 0;
            }

            /* set leadout sector */
            (*pp_sectors)[i_tracks] =
                CDConvertMSFToLBA( pTrackDescriptors[i_leadout].p );
        }

        darwin_freeTOC( pTOC );

#elif defined( _WIN32 )
        DWORD dwBytesReturned;
        CDROM_TOC cdrom_toc;

        if( DeviceIoControl( p_vcddev->h_device_handle, IOCTL_CDROM_READ_TOC,
                             NULL, 0, &cdrom_toc, sizeof(CDROM_TOC),
                             &dwBytesReturned, NULL ) == 0 )
        {
            msg_Err( p_this, "could not read TOCHDR" );
            return 0;
        }

        i_tracks = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1;

        if( pp_sectors )
        {
            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
            if( *pp_sectors == NULL )
                return 0;

            for( int i = 0 ; i <= i_tracks ; i++ )
            {
                (*pp_sectors)[ i ] = MSF_TO_LBA2(
                                           cdrom_toc.TrackData[i].Address[1],
                                           cdrom_toc.TrackData[i].Address[2],
                                           cdrom_toc.TrackData[i].Address[3] );
                msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]);
             }
        }

#elif defined( __OS2__ )
        cdrom_get_tochdr_t get_tochdr = {{'C', 'D', '0', '1'}};
        cdrom_tochdr_t     tochdr;

        ULONG param_len;
        ULONG data_len;
        ULONG rc;

        rc = DosDevIOCtl( p_vcddev->hcd, IOCTL_CDROMAUDIO,
                          CDROMAUDIO_GETAUDIODISK,
                          &get_tochdr, sizeof( get_tochdr ), &param_len,
                          &tochdr, sizeof( tochdr ), &data_len );
        if( rc )
        {
            msg_Err( p_this, "could not read TOCHDR" );
            return 0;
        }

        i_tracks = tochdr.last_track - tochdr.first_track + 1;

        if( pp_sectors )
        {
            cdrom_get_track_t get_track = {{'C', 'D', '0', '1'}, };
            cdrom_track_t track;
            int i;

            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
            if( *pp_sectors == NULL )
                return 0;

            for( i = 0 ; i < i_tracks ; i++ )
            {
                get_track.track = tochdr.first_track + i;
                rc = DosDevIOCtl( p_vcddev->hcd, IOCTL_CDROMAUDIO,
                                  CDROMAUDIO_GETAUDIOTRACK,
                                  &get_track, sizeof(get_track), &param_len,
                                  &track, sizeof(track), &data_len );
                if (rc)
                {
                    msg_Err( p_this, "could not read %d track",
                             get_track.track );
                    return 0;
                }

                (*pp_sectors)[ i ] = MSF_TO_LBA2(
                                       track.start.minute,
                                       track.start.second,
                                       track.start.frame );
                msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]);
            }

            /* for lead-out track */
            (*pp_sectors)[ i ] = MSF_TO_LBA2(
                                   tochdr.lead_out.minute,
                                   tochdr.lead_out.second,
                                   tochdr.lead_out.frame );
            msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]);
        }

#elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H ) \
       || defined( HAVE_SCSIREQ_IN_SYS_SCSIIO_H )
        struct ioc_toc_header tochdr;
        struct ioc_read_toc_entry toc_entries;

        if( ioctl( p_vcddev->i_device_handle, CDIOREADTOCHEADER, &tochdr )
            == -1 )
        {
            msg_Err( p_this, "could not read TOCHDR" );
            return 0;
        }

        i_tracks = tochdr.ending_track - tochdr.starting_track + 1;

        if( pp_sectors )
        {
             *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
             if( *pp_sectors == NULL )
                 return 0;

             toc_entries.address_format = CD_LBA_FORMAT;
             toc_entries.starting_track = 0;
             toc_entries.data_len = ( i_tracks + 1 ) *
                                        sizeof( struct cd_toc_entry );
             toc_entries.data = (struct cd_toc_entry *)
                                    malloc( toc_entries.data_len );
             if( toc_entries.data == NULL )
             {
                 free( *pp_sectors );
                 return 0;
             }

             /* Read the TOC */
             if( ioctl( p_vcddev->i_device_handle, CDIOREADTOCENTRYS,
                        &toc_entries ) == -1 )
             {
                 msg_Err( p_this, "could not read the TOC" );
                 free( *pp_sectors );
                 free( toc_entries.data );
                 return 0;
             }

             /* Fill the p_sectors structure with the track/sector matches */
             for( int i = 0 ; i <= i_tracks ; i++ )
             {
#if defined( HAVE_SCSIREQ_IN_SYS_SCSIIO_H )
                 /* FIXME: is this ok? */
                 (*pp_sectors)[ i ] = toc_entries.data[i].addr.lba;
#else
                 (*pp_sectors)[ i ] = ntohl( toc_entries.data[i].addr.lba );
#endif
             }
        }
#else
        struct cdrom_tochdr   tochdr;
        struct cdrom_tocentry tocent;

        /* First we read the TOC header */
        if( ioctl( p_vcddev->i_device_handle, CDROMREADTOCHDR, &tochdr )
            == -1 )
        {
            msg_Err( p_this, "could not read TOCHDR" );
            return 0;
        }

        i_tracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;

        if( pp_sectors )
        {
            *pp_sectors = calloc( i_tracks + 1, sizeof(**pp_sectors) );
            if( *pp_sectors == NULL )
                return 0;

            /* Fill the p_sectors structure with the track/sector matches */
            for( int i = 0 ; i <= i_tracks ; i++ )
            {
                tocent.cdte_format = CDROM_LBA;
                tocent.cdte_track =
                    ( i == i_tracks ) ? CDROM_LEADOUT : tochdr.cdth_trk0 + i;

                if( ioctl( p_vcddev->i_device_handle, CDROMREADTOCENTRY,
                           &tocent ) == -1 )
                {
                    msg_Err( p_this, "could not read TOCENTRY" );
                    free( *pp_sectors );
                    return 0;
                }

                (*pp_sectors)[ i ] = tocent.cdte_addr.lba;
            }
        }
#endif

        return i_tracks;
    }
}