📄 cdrom.c
字号:
*pp_sectors = malloc( (i_tracks + 1) * sizeof(int) ); if( *pp_sectors == NULL ) return 0; for( 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( 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 ) { int i; *pp_sectors = malloc( (i_tracks + 1) * sizeof(int) ); 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( 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 ) { int i; *pp_sectors = malloc( (i_tracks + 1) * sizeof(int) ); if( *pp_sectors == NULL ) return 0; /* Fill the p_sectors structure with the track/sector matches */ for( 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; }}/**************************************************************************** * ioctl_ReadSector: Read VCD or CDDA sectors ****************************************************************************/int ioctl_ReadSectors( vlc_object_t *p_this, const vcddev_t *p_vcddev, int i_sector, uint8_t *p_buffer, int i_nb, int i_type ){ uint8_t *p_block; int i; if( i_type == VCD_TYPE ) p_block = malloc( VCD_SECTOR_SIZE * i_nb ); else p_block = p_buffer; if( p_vcddev->i_vcdimage_handle != -1 ) { /* * vcd image mode */ if( lseek( p_vcddev->i_vcdimage_handle, i_sector * VCD_SECTOR_SIZE, SEEK_SET ) == -1 ) { msg_Err( p_this, "Could not lseek to sector %d", i_sector ); if( i_type == VCD_TYPE ) free( p_block ); return -1; } if( read( p_vcddev->i_vcdimage_handle, p_block, VCD_SECTOR_SIZE * i_nb) == -1 ) { msg_Err( p_this, "Could not read sector %d", i_sector ); if( i_type == VCD_TYPE ) free( p_block ); return -1; } } else { /* * vcd device mode */#if defined( __APPLE__ ) dk_cd_read_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); cd_read.offset = i_sector * VCD_SECTOR_SIZE; cd_read.sectorArea = kCDSectorAreaSync | kCDSectorAreaHeader | kCDSectorAreaSubHeader | kCDSectorAreaUser | kCDSectorAreaAuxiliary; cd_read.sectorType = kCDSectorTypeUnknown; cd_read.buffer = p_block; cd_read.bufferLength = VCD_SECTOR_SIZE * i_nb; if( ioctl( p_vcddev->i_device_handle, DKIOCCDREAD, &cd_read ) == -1 ) { msg_Err( p_this, "could not read block %d", i_sector ); if( i_type == VCD_TYPE ) free( p_block ); return -1; }#elif defined( WIN32 ) if( p_vcddev->hASPI ) { HANDLE hEvent; struct SRB_ExecSCSICmd ssc; /* Create the transfer completion event */ hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); if( hEvent == NULL ) { if( i_type == VCD_TYPE ) free( p_block ); return -1; } memset( &ssc, 0, sizeof( ssc ) ); ssc.SRB_Cmd = SC_EXEC_SCSI_CMD; ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; ssc.SRB_HaId = LOBYTE( p_vcddev->i_sid ); ssc.SRB_Target = HIBYTE( p_vcddev->i_sid ); ssc.SRB_SenseLen = SENSE_LEN; ssc.SRB_PostProc = (LPVOID) hEvent; ssc.SRB_CDBLen = 12; /* Operation code */ ssc.CDBByte[ 0 ] = READ_CD; /* Sector type */ ssc.CDBByte[ 1 ] = i_type == VCD_TYPE ? SECTOR_TYPE_MODE2_FORM2 : SECTOR_TYPE_CDDA; /* Start of LBA */ ssc.CDBByte[ 2 ] = ( i_sector >> 24 ) & 0xff; ssc.CDBByte[ 3 ] = ( i_sector >> 16 ) & 0xff; ssc.CDBByte[ 4 ] = ( i_sector >> 8 ) & 0xff; ssc.CDBByte[ 5 ] = ( i_sector ) & 0xff; /* Transfer length */ ssc.CDBByte[ 6 ] = ( i_nb >> 16 ) & 0xff; ssc.CDBByte[ 7 ] = ( i_nb >> 8 ) & 0xff; ssc.CDBByte[ 8 ] = ( i_nb ) & 0xff; /* Data selection */ ssc.CDBByte[ 9 ] = i_type == VCD_TYPE ? READ_CD_RAW_MODE2 : READ_CD_USERDATA; /* Result buffer */ ssc.SRB_BufPointer = p_block; ssc.SRB_BufLen = VCD_SECTOR_SIZE * i_nb; /* Initiate transfer */ ResetEvent( hEvent ); p_vcddev->lpSendCommand( (void*) &ssc ); /* If the command has still not been processed, wait until it's * finished */ if( ssc.SRB_Status == SS_PENDING ) { WaitForSingleObject( hEvent, INFINITE ); } CloseHandle( hEvent ); /* check that the transfer went as planned */ if( ssc.SRB_Status != SS_COMP ) { if( i_type == VCD_TYPE ) free( p_block ); return -1; } } else { DWORD dwBytesReturned; RAW_READ_INFO cdrom_raw; /* Initialize CDROM_RAW_READ structure */ cdrom_raw.DiskOffset.QuadPart = CD_SECTOR_SIZE * i_sector; cdrom_raw.SectorCount = i_nb; cdrom_raw.TrackMode = i_type == VCD_TYPE ? XAForm2 : CDDA; if( DeviceIoControl( p_vcddev->h_device_handle, IOCTL_CDROM_RAW_READ, &cdrom_raw, sizeof(RAW_READ_INFO), p_block, VCD_SECTOR_SIZE * i_nb, &dwBytesReturned, NULL ) == 0 ) { if( i_type == VCD_TYPE ) { /* Retry in YellowMode2 */ cdrom_raw.TrackMode = YellowMode2; if( DeviceIoControl( p_vcddev->h_device_handle, IOCTL_CDROM_RAW_READ, &cdrom_raw, sizeof(RAW_READ_INFO), p_block, VCD_SECTOR_SIZE * i_nb, &dwBytesReturned, NULL ) == 0 ) { free( p_block ); return -1; } } else return -1; } }#elif defined( HAVE_SCSIREQ_IN_SYS_SCSIIO_H ) struct scsireq sc; int i_ret; memset( &sc, 0, sizeof(sc) ); sc.cmd[0] = 0xBE; sc.cmd[1] = i_type == VCD_TYPE ? SECTOR_TYPE_MODE2_FORM2: SECTOR_TYPE_CDDA; sc.cmd[2] = (i_sector >> 24) & 0xff; sc.cmd[3] = (i_sector >> 16) & 0xff; sc.cmd[4] = (i_sector >> 8) & 0xff; sc.cmd[5] = (i_sector >> 0) & 0xff; sc.cmd[6] = (i_nb >> 16) & 0xff; sc.cmd[7] = (i_nb >> 8) & 0xff; sc.cmd[8] = (i_nb ) & 0xff; sc.cmd[9] = i_type == VCD_TYPE ? READ_CD_RAW_MODE2 : READ_CD_USERDATA; sc.cmd[10] = 0; /* sub channel */ sc.cmdlen = 12; sc.databuf = (caddr_t)p_block; sc.datalen = VCD_SECTOR_SIZE * i_nb; sc.senselen = sizeof( sc.sense ); sc.flags = SCCMD_READ; sc.timeout = 10000; i_ret = ioctl( i_fd, SCIOCCOMMAND, &sc ); if( i_ret == -1 ) { msg_Err( p_this, "SCIOCCOMMAND failed" ); if( i_type == VCD_TYPE ) free( p_block ); return -1; } if( sc.retsts || sc.error ) { msg_Err( p_this, "SCSI command failed: status %d error %d\n", sc.retsts, sc.error ); if( i_type == VCD_TYPE ) free( p_block ); return -1; }#elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H ) int i_size = VCD_SECTOR_SIZE; if( ioctl( p_vcddev->i_device_handle, CDRIOCSETBLOCKSIZE, &i_size ) == -1 ) { msg_Err( p_this, "Could not set block size" ); if( i_type == VCD_TYPE ) free( p_block ); return( -1 ); } if( lseek( p_vcddev->i_device_handle, i_sector * VCD_SECTOR_SIZE, SEEK_SET ) == -1 ) { msg_Err( p_this, "Could not lseek to sector %d", i_sector ); if( i_type == VCD_TYPE ) free( p_block ); return( -1 ); } if( read( p_vcddev->i_device_handle, p_block, VCD_SECTOR_SIZE * i_nb ) == -1 ) { msg_Err( p_this, "Could not read sector %d", i_sector ); if( i_type == VCD_TYPE ) free( p_block ); return( -1 ); }#else for( i = 0; i < i_nb; i++ ) { int i_dummy = i_sector + i + 2 * CD_FRAMES;#define p_msf ((struct cdrom_msf0 *)(p_block + i * VCD_SECTOR_SIZE)) p_msf->minute = i_dummy / (CD_FRAMES * CD_SECS); p_msf->second = ( i_dummy % (CD_FRAMES * CD_SECS) ) / CD_FRAMES; p_msf->frame = ( i_dummy % (CD_FRAMES * CD_SECS) ) % CD_FRAMES;#undef p_msf if( ioctl( p_vcddev->i_device_handle, CDROMREADRAW, p_block + i * VCD_SECTOR_SIZE ) == -1 ) { msg_Err( p_this, "could not read block %i from disc", i_sector ); if( i == 0 ) { if( i_type == VCD_TYPE ) free( p_block ); return( -1 ); } else break; } }#endif } /* For VCDs, we don't want to keep the header and footer of the * sectors read */ if( i_type == VCD_TYPE ) { for( i = 0; i < i_nb; i++ ) { memcpy( p_buffer + i * VCD_DATA_SIZE, p_block + i * VCD_SECTOR_SIZE + VCD_DATA_START, VCD_DATA_SIZE ); } free( p_block ); } return( 0 );}/**************************************************************************** * Private functions ****************************************************************************//**************************************************************************** * OpenVCDImage: try to open a vcd image from a .cue file ****************************************************************************/static int OpenVCDImage( vlc_object_t * p_this, const char *psz_dev, vcddev_t *p_vcddev ){ int i_ret = -1; char *p_pos; char *psz_vcdfile = NULL; char *psz_cuefile = NULL; FILE *cuefile = NULL; int *p_sectors = NULL; char line[1024]; bool b_found = false; /* Check if we are dealing with a .cue file */ p_pos = strrchr( psz_dev, '.' );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -