📄 cdrom.c
字号:
/**************************************************************************** * cdrom.c: cdrom tools ***************************************************************************** * Copyright (C) 1998-2001 the VideoLAN team * $Id: 5fa97052ee8b4f440db88fbc6f8a47fd475d50fc $ * * Authors: Johan Bilien <jobi@via.ecp.fr> * Gildas Bazin <gbazin@netcourrier.com> * Jon Lech Johansen <jon-vl@nanocrew.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_access.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <errno.h>#ifdef HAVE_SYS_TYPES_H# include <sys/types.h>#endif#ifdef HAVE_SYS_STAT_H# include <sys/stat.h>#endif#ifdef HAVE_FCNTL_H# include <fcntl.h>#endif#if defined( SYS_BSDI )# include <dvd.h>#elif defined ( __APPLE__ )# include <CoreFoundation/CFBase.h># include <IOKit/IOKitLib.h># include <IOKit/storage/IOCDTypes.h># include <IOKit/storage/IOCDMedia.h># include <IOKit/storage/IOCDMediaBSDClient.h>#elif defined( HAVE_SCSIREQ_IN_SYS_SCSIIO_H )# include <sys/inttypes.h># include <sys/cdio.h># include <sys/scsiio.h>#elif defined( HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H )# include <sys/cdio.h># include <sys/cdrio.h>#elif defined( WIN32 )# include <windows.h># include <winioctl.h>#elif defined (__linux__)# include <sys/ioctl.h># include <linux/cdrom.h>#else# error FIXME#endif#include "cdrom_internals.h"#include "cdrom.h"#include <vlc_charset.h>/***************************************************************************** * ioctl_Open: Opens a VCD device or file and returns an opaque handle *****************************************************************************/vcddev_t *ioctl_Open( vlc_object_t *p_this, const char *psz_dev ){ int i_ret; int b_is_file; vcddev_t *p_vcddev;#ifndef WIN32 struct stat fileinfo;#endif if( !psz_dev ) return NULL; /* * Initialize structure with default values */ p_vcddev = (vcddev_t *)malloc( sizeof(vcddev_t) ); if( p_vcddev == NULL ) return NULL; p_vcddev->i_vcdimage_handle = -1; p_vcddev->psz_dev = NULL; b_is_file = 1; /* * Check if we are dealing with a device or a file (vcd image) */#ifdef WIN32 if( (strlen( psz_dev ) == 2 && psz_dev[1] == ':') ) { b_is_file = 0; }#else if( utf8_stat( psz_dev, &fileinfo ) < 0 ) { free( p_vcddev ); return NULL; } /* Check if this is a block/char device */ if( S_ISBLK( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) ) b_is_file = 0;#endif if( b_is_file ) { i_ret = OpenVCDImage( p_this, psz_dev, p_vcddev ); } else { /* * open the vcd device */#ifdef WIN32 i_ret = win32_vcd_open( p_this, psz_dev, p_vcddev );#else p_vcddev->i_device_handle = -1; p_vcddev->i_device_handle = open( psz_dev, O_RDONLY | O_NONBLOCK ); i_ret = (p_vcddev->i_device_handle == -1) ? -1 : 0;#endif } if( i_ret == 0 ) { p_vcddev->psz_dev = (char *)strdup( psz_dev ); } else { free( p_vcddev ); p_vcddev = NULL; } return p_vcddev;}/***************************************************************************** * ioctl_Close: Closes an already opened VCD device or file. *****************************************************************************/void ioctl_Close( vlc_object_t * p_this, vcddev_t *p_vcddev ){ free( p_vcddev->psz_dev ); if( p_vcddev->i_vcdimage_handle != -1 ) { /* * vcd image mode */ CloseVCDImage( p_this, p_vcddev ); return; } /* * vcd device mode */#ifdef WIN32 if( p_vcddev->h_device_handle ) CloseHandle( p_vcddev->h_device_handle ); if( p_vcddev->hASPI ) FreeLibrary( (HMODULE)p_vcddev->hASPI );#else if( p_vcddev->i_device_handle != -1 ) close( p_vcddev->i_device_handle );#endif}/***************************************************************************** * 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 = malloc( (i_tracks + 1) * sizeof(int) ); if( *pp_sectors == NULL ) return 0; memcpy( *pp_sectors, p_vcddev->p_sectors, (i_tracks + 1) * sizeof(int) ); } 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 = malloc( (i_tracks + 1) * sizeof(int) ); 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 ) if( p_vcddev->hASPI ) { HANDLE hEvent; struct SRB_ExecSCSICmd ssc; uint8_t p_tocheader[ 4 ]; /* Create the transfer completion event */ hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); if( hEvent == NULL ) { 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 = 10; /* Operation code */ ssc.CDBByte[ 0 ] = READ_TOC; /* Format */ ssc.CDBByte[ 2 ] = READ_TOC_FORMAT_TOC; /* Starting track */ ssc.CDBByte[ 6 ] = 0; /* Allocation length and buffer */ ssc.SRB_BufLen = sizeof( p_tocheader ); ssc.SRB_BufPointer = p_tocheader; ssc.CDBByte[ 7 ] = ( ssc.SRB_BufLen >> 8 ) & 0xff; ssc.CDBByte[ 8 ] = ( ssc.SRB_BufLen ) & 0xff; /* 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 ); /* check that the transfer went as planned */ if( ssc.SRB_Status != SS_COMP ) { CloseHandle( hEvent ); return 0; } i_tracks = p_tocheader[3] - p_tocheader[2] + 1; if( pp_sectors ) { int i, i_toclength; uint8_t *p_fulltoc; i_toclength = 4 /* header */ + p_tocheader[0] + ((unsigned int)p_tocheader[1] << 8); p_fulltoc = malloc( i_toclength ); *pp_sectors = malloc( (i_tracks + 1) * sizeof(int) ); if( *pp_sectors == NULL || p_fulltoc == NULL ) { free( *pp_sectors ); free( p_fulltoc ); CloseHandle( hEvent ); return 0; } /* Allocation length and buffer */ ssc.SRB_BufLen = i_toclength; ssc.SRB_BufPointer = p_fulltoc; ssc.CDBByte[ 7 ] = ( ssc.SRB_BufLen >> 8 ) & 0xff; ssc.CDBByte[ 8 ] = ( ssc.SRB_BufLen ) & 0xff; /* 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 ); /* check that the transfer went as planned */ if( ssc.SRB_Status != SS_COMP ) i_tracks = 0; for( i = 0 ; i <= i_tracks ; i++ ) { int i_index = 8 + 8 * i; (*pp_sectors)[ i ] = ((int)p_fulltoc[ i_index ] << 24) + ((int)p_fulltoc[ i_index+1 ] << 16) + ((int)p_fulltoc[ i_index+2 ] << 8) + (int)p_fulltoc[ i_index+3 ]; msg_Dbg( p_this, "p_sectors: %i, %i", i, (*pp_sectors)[i]); } free( p_fulltoc ); } CloseHandle( hEvent ); } else { 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 ) { int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -