📄 cdrom.c
字号:
char *psz_vcdfile = NULL; char *psz_cuefile = NULL; FILE *cuefile; char line[1024]; /* Check if we are dealing with a .cue file */ p_pos = strrchr( psz_dev, '.' ); if( p_pos && !strcmp( p_pos, ".cue" ) ) { psz_cuefile = strdup( psz_dev ); } else { /* psz_dev must be the actual vcd file. Let's assume there's a .cue * file with the same filename */ if( p_pos ) { psz_cuefile = malloc( p_pos - psz_dev + 5 /* ".cue" */ ); strncpy( psz_cuefile, psz_dev, p_pos - psz_dev ); strcpy( psz_cuefile + (p_pos - psz_dev), ".cue"); } else { psz_cuefile = malloc( strlen(psz_dev) + 5 /* ".cue" */ ); sprintf( psz_cuefile, "%s.cue", psz_dev ); } } /* Open the cue file and try to parse it */ msg_Dbg( p_this,"trying .cue file: %s", psz_cuefile ); cuefile = fopen( psz_cuefile, "rt" ); if( cuefile && fscanf( cuefile, "FILE %c", line ) && fgets( line, 1024, cuefile ) ) { p_pos = strchr( line, '"' ); if( p_pos ) { *p_pos = 0; /* Take care of path standardization */ if( *line != '/' && ((p_pos = strrchr( psz_cuefile, '/' )) || (p_pos = strrchr( psz_cuefile, '\\' ) )) ) { psz_vcdfile = malloc( strlen(line) + (p_pos - psz_cuefile + 1) + 1 ); strncpy( psz_vcdfile, psz_cuefile, (p_pos - psz_cuefile + 1) ); strcpy( psz_vcdfile + (p_pos - psz_cuefile + 1), line ); } else psz_vcdfile = strdup( line ); } } if( psz_vcdfile ) { msg_Dbg( p_this,"using vcd image file: %s", psz_vcdfile ); p_vcddev->i_vcdimage_handle = open( psz_vcdfile, O_RDONLY | O_NONBLOCK | O_BINARY ); i_ret = (p_vcddev->i_vcdimage_handle == -1) ? -1 : 0; } /* Try to parse the i_tracks and p_sectors info so we can just forget * about the cuefile */ if( i_ret == 0 ) { int p_sectors[100]; int i_tracks = 0; int i_num; char psz_dummy[10]; while( fgets( line, 1024, cuefile ) ) { /* look for a TRACK line */ if( !sscanf( line, "%9s", psz_dummy ) || strcmp(psz_dummy, "TRACK") ) continue; /* look for an INDEX line */ while( fgets( line, 1024, cuefile ) ) { int i_min, i_sec, i_frame; if( (sscanf( line, "%9s %2u %2u:%2u:%2u", psz_dummy, &i_num, &i_min, &i_sec, &i_frame ) != 5) || (i_num != 1) ) continue; i_tracks++; p_sectors[i_tracks - 1] = MSF_TO_LBA(i_min, i_sec, i_frame); msg_Dbg( p_this, "vcd track %i begins at sector:%i", i_tracks - 1, p_sectors[i_tracks - 1] ); break; } } /* fill in the last entry */ p_sectors[i_tracks] = lseek(p_vcddev->i_vcdimage_handle, 0, SEEK_END) / VCD_SECTOR_SIZE; msg_Dbg( p_this, "vcd track %i, begins at sector:%i", i_tracks, p_sectors[i_tracks] ); p_vcddev->i_tracks = i_tracks; p_vcddev->p_sectors = malloc( (i_tracks + 1) * sizeof(int) ); memcpy( p_vcddev->p_sectors, p_sectors, (i_tracks + 1) * sizeof(int) ); } if( cuefile ) fclose( cuefile ); if( psz_cuefile ) free( psz_cuefile ); if( psz_vcdfile ) free( psz_vcdfile ); return i_ret;}/**************************************************************************** * CloseVCDImage: closes a vcd image opened by OpenVCDImage ****************************************************************************/static void CloseVCDImage( vlc_object_t * p_this, vcddev_t *p_vcddev ){ if( p_vcddev->i_vcdimage_handle != -1 ) close( p_vcddev->i_vcdimage_handle ); else return; if( p_vcddev->p_sectors ) free( p_vcddev->p_sectors );}#if defined( SYS_DARWIN )/**************************************************************************** * darwin_getTOC: get the TOC ****************************************************************************/static CDTOC *darwin_getTOC( vlc_object_t * p_this, const vcddev_t *p_vcddev ){ mach_port_t port; char *psz_devname; kern_return_t ret; CDTOC *pTOC = NULL; io_iterator_t iterator; io_registry_entry_t service; CFMutableDictionaryRef properties; CFDataRef data; /* get the device name */ if( ( psz_devname = strrchr( p_vcddev->psz_dev, '/') ) != NULL ) ++psz_devname; else psz_devname = p_vcddev->psz_dev; /* unraw the device name */ if( *psz_devname == 'r' ) ++psz_devname; /* get port for IOKit communication */ if( ( ret = IOMasterPort( MACH_PORT_NULL, &port ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IOMasterPort: 0x%08x", ret ); return( NULL ); } /* get service iterator for the device */ if( ( ret = IOServiceGetMatchingServices( port, IOBSDNameMatching( port, 0, psz_devname ), &iterator ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IOServiceGetMatchingServices: 0x%08x", ret ); return( NULL ); } /* first service */ service = IOIteratorNext( iterator ); IOObjectRelease( iterator ); /* search for kIOCDMediaClass */ while( service && !IOObjectConformsTo( service, kIOCDMediaClass ) ) { if( ( ret = IORegistryEntryGetParentIterator( service, kIOServicePlane, &iterator ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IORegistryEntryGetParentIterator: 0x%08x", ret ); IOObjectRelease( service ); return( NULL ); } IOObjectRelease( service ); service = IOIteratorNext( iterator ); IOObjectRelease( iterator ); } if( service == NULL ) { msg_Err( p_this, "search for kIOCDMediaClass came up empty" ); return( NULL ); } /* create a CF dictionary containing the TOC */ if( ( ret = IORegistryEntryCreateCFProperties( service, &properties, kCFAllocatorDefault, kNilOptions ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IORegistryEntryCreateCFProperties: 0x%08x", ret ); IOObjectRelease( service ); return( NULL ); } /* get the TOC from the dictionary */ if( ( data = (CFDataRef) CFDictionaryGetValue( properties, CFSTR(kIOCDMediaTOCKey) ) ) != NULL ) { CFRange range; CFIndex buf_len; buf_len = CFDataGetLength( data ) + 1; range = CFRangeMake( 0, buf_len ); if( ( pTOC = (CDTOC *)malloc( buf_len ) ) != NULL ) { CFDataGetBytes( data, range, (u_char *)pTOC ); } } else { msg_Err( p_this, "CFDictionaryGetValue failed" ); } CFRelease( properties ); IOObjectRelease( service ); return( pTOC ); }/**************************************************************************** * darwin_getNumberOfDescriptors: get number of descriptors in TOC ****************************************************************************/static int darwin_getNumberOfDescriptors( CDTOC *pTOC ){ int i_descriptors; /* get TOC length */ i_descriptors = pTOC->length; /* remove the first and last session */ i_descriptors -= ( sizeof(pTOC->sessionFirst) + sizeof(pTOC->sessionLast) ); /* divide the length by the size of a single descriptor */ i_descriptors /= sizeof(CDTOCDescriptor); return( i_descriptors );}/**************************************************************************** * darwin_getNumberOfTracks: get number of tracks in TOC ****************************************************************************/static int darwin_getNumberOfTracks( CDTOC *pTOC, int i_descriptors ){ u_char track; int i, i_tracks = 0; CDTOCDescriptor *pTrackDescriptors; pTrackDescriptors = pTOC->descriptors; for( i = i_descriptors; i >= 0; i-- ) { track = pTrackDescriptors[i].point; if( track > CD_MAX_TRACK_NO || track < CD_MIN_TRACK_NO ) continue; i_tracks++; } return( i_tracks );}#endif /* SYS_DARWIN */#if defined( WIN32 )/***************************************************************************** * win32_vcd_open: open vcd drive ***************************************************************************** * Load and use aspi if it is available, otherwise use IOCTLs on WinNT/2K/XP. *****************************************************************************/static int win32_vcd_open( vlc_object_t * p_this, const char *psz_dev, vcddev_t *p_vcddev ){ /* Initializations */ p_vcddev->h_device_handle = NULL; p_vcddev->i_sid = 0; p_vcddev->hASPI = 0; p_vcddev->lpSendCommand = 0; if( WIN_NT ) { char psz_win32_drive[7]; msg_Dbg( p_this, "using winNT/2K/XP ioctl layer" ); sprintf( psz_win32_drive, "\\\\.\\%c:", psz_dev[0] ); p_vcddev->h_device_handle = CreateFile( psz_win32_drive, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS, NULL ); return (p_vcddev->h_device_handle == NULL) ? -1 : 0; } else { HMODULE hASPI = NULL; long (*lpGetSupport)( void ) = NULL; long (*lpSendCommand)( void* ) = NULL; DWORD dwSupportInfo; int i, j, i_hostadapters; char c_drive = psz_dev[0]; hASPI = LoadLibrary( "wnaspi32.dll" ); if( hASPI != NULL ) { (FARPROC) lpGetSupport = GetProcAddress( hASPI, "GetASPI32SupportInfo" ); (FARPROC) lpSendCommand = GetProcAddress( hASPI, "SendASPI32Command" ); } if( hASPI == NULL || lpGetSupport == NULL || lpSendCommand == NULL ) { msg_Dbg( p_this, "unable to load aspi or get aspi function pointers" ); if( hASPI ) FreeLibrary( hASPI ); return -1; } /* ASPI support seems to be there */ dwSupportInfo = lpGetSupport(); if( HIBYTE( LOWORD ( dwSupportInfo ) ) == SS_NO_ADAPTERS ) { msg_Dbg( p_this, "no host adapters found (aspi)" ); FreeLibrary( hASPI ); return -1; } if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP ) { msg_Dbg( p_this, "unable to initalize aspi layer" ); FreeLibrary( hASPI ); return -1; } i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) ); if( i_hostadapters == 0 ) { FreeLibrary( hASPI ); return -1; } c_drive = c_drive > 'Z' ? c_drive - 'a' : c_drive - 'A'; for( i = 0; i < i_hostadapters; i++ ) { for( j = 0; j < 15; j++ ) { struct SRB_GetDiskInfo srbDiskInfo; srbDiskInfo.SRB_Cmd = SC_GET_DISK_INFO; srbDiskInfo.SRB_HaId = i; srbDiskInfo.SRB_Flags = 0; srbDiskInfo.SRB_Hdr_Rsvd = 0; srbDiskInfo.SRB_Target = j; srbDiskInfo.SRB_Lun = 0; lpSendCommand( (void*) &srbDiskInfo ); if( (srbDiskInfo.SRB_Status == SS_COMP) && (srbDiskInfo.SRB_Int13HDriveInfo == c_drive) ) { /* Make sure this is a cdrom device */ struct SRB_GDEVBlock srbGDEVBlock; memset( &srbGDEVBlock, 0, sizeof(struct SRB_GDEVBlock) ); srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; srbGDEVBlock.SRB_HaId = i; srbGDEVBlock.SRB_Target = j; lpSendCommand( (void*) &srbGDEVBlock ); if( ( srbGDEVBlock.SRB_Status == SS_COMP ) && ( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM ) ) { p_vcddev->i_sid = MAKEWORD( i, j ); p_vcddev->hASPI = (long)hASPI; p_vcddev->lpSendCommand = lpSendCommand; msg_Dbg( p_this, "using aspi layer" ); return 0; } else { FreeLibrary( hASPI ); msg_Dbg( p_this, "%c: is not a cdrom drive", psz_dev[0] ); return -1; } } } } FreeLibrary( hASPI ); msg_Dbg( p_this, "unable to get haid and target (aspi)" ); } return -1;}#endif /* WIN32 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -