diff --git a/example/sample8.c b/example/sample8.c index 16c94340..95b9141f 100644 --- a/example/sample8.c +++ b/example/sample8.c @@ -1,5 +1,5 @@ /* - $Id: sample8.c,v 1.2 2004/07/11 14:25:07 rocky Exp $ + $Id: sample8.c,v 1.3 2004/07/13 03:45:15 rocky Exp $ Copyright (C) 2003 Rocky Bernstein @@ -52,5 +52,28 @@ main(int argc, const char *argv[]) cdio_destroy(cdio); + cdio = cdio_open (NULL, DRIVER_UNKNOWN); + + if (NULL == cdio) { + printf("Couldn't find CD\n"); + return 1; + } else { + const cdtext_t *cdtext = cdio_get_cdtext(cdio); + + if (NULL != cdtext) { + printf("CD-TEXT Title: %s\n", + cdtext->field[CDTEXT_TITLE] ? + cdtext->field[CDTEXT_TITLE] : "not set"); + printf("CD-TEXT Performer: %s\n", + cdtext->field[CDTEXT_PERFORMER] ? + cdtext->field[CDTEXT_PERFORMER] : "not set" + ); + } else { + printf("Didn't get CD-TEXT info.\n"); + } + } + + cdio_destroy(cdio); + return 0; } diff --git a/lib/MSWindows/aspi32.c b/lib/MSWindows/aspi32.c index decfdbb9..87f8e66f 100644 --- a/lib/MSWindows/aspi32.c +++ b/lib/MSWindows/aspi32.c @@ -1,5 +1,5 @@ /* - $Id: aspi32.c,v 1.15 2004/07/12 03:34:14 rocky Exp $ + $Id: aspi32.c,v 1.16 2004/07/13 03:45:25 rocky Exp $ Copyright (C) 2004 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: aspi32.c,v 1.15 2004/07/12 03:34:14 rocky Exp $"; +static const char _rcsid[] = "$Id: aspi32.c,v 1.16 2004/07/13 03:45:25 rocky Exp $"; #include #include @@ -52,6 +52,12 @@ static const char _rcsid[] = "$Id: aspi32.c,v 1.15 2004/07/12 03:34:14 rocky Exp #include #include #include "aspi32.h" +#include "cdtext_private.h" + +/* Amount of time we are willing to wait for an operation to complete. + 10 seconds? +*/ +#define OP_TIMEOUT_MS 10000 static const char *aspierror(int nErrorCode) @@ -89,7 +95,7 @@ char *aspierror(int nErrorCode) return "ASPI manager doesn't support"; break; case SS_ILLEGAL_MODE: - return "Unsupported Windows mode"; + return "Unsupported MS Windows mode"; break; case SS_NO_ASPI: return "No ASPI managers"; @@ -98,10 +104,10 @@ char *aspierror(int nErrorCode) return "ASPI for windows failed init"; break; case SS_ASPI_IS_BUSY: - return "No resources available to execute command"; + return "No resources available to execute command."; break; case SS_BUFFER_TOO_BIG: - return "Buffer size too big to handle"; + return "Buffer size is too big to handle."; break; case SS_MISMATCHED_COMPONENTS: return "The DLLs/EXEs of ASPI don't version check"; @@ -116,10 +122,10 @@ char *aspierror(int nErrorCode) return "Call came to ASPI after PROCESS_DETACH"; break; case SS_BAD_INSTALL: - return "The DLL or other components are installed wrong"; + return "The DLL or other components are installed wrong."; break; default: - return "Unknown ASPI error"; + return "Unknown ASPI error."; } } @@ -460,7 +466,7 @@ mmc_read_sectors_aspi (const _img_private_t *env, void *data, lsn_t lsn, /* If the command has still not been processed, wait until it's * finished */ if( ssc.SRB_Status == SS_PENDING ) { - WaitForSingleObject( hEvent, INFINITE ); + WaitForSingleObject( hEvent, OP_TIMEOUT_MS ); } CloseHandle( hEvent ); @@ -551,10 +557,9 @@ read_toc_aspi (_img_private_t *env) CDIO_MMC_SET_START_TRACK(ssc.CDBByte, 0); /* Allocation length and buffer */ - ssc.SRB_BufLen = sizeof( p_tocheader ); + ssc.SRB_BufLen = sizeof( p_tocheader ); ssc.SRB_BufPointer = p_tocheader; - ssc.CDBByte[ 7 ] = (unsigned char) ( ssc.SRB_BufLen >> 8 ) & 0xff; - ssc.CDBByte[ 8 ] = (unsigned char) ( ssc.SRB_BufLen ) & 0xff; + CDIO_MMC_SET_READ_LENGTH(ssc.CDBByte, ssc.SRB_BufLen); /* Initiate transfer */ ResetEvent( hEvent ); @@ -563,7 +568,7 @@ read_toc_aspi (_img_private_t *env) /* If the command has still not been processed, wait until it's * finished */ if( ssc.SRB_Status == SS_PENDING ) - WaitForSingleObject( hEvent, INFINITE ); + WaitForSingleObject( hEvent, OP_TIMEOUT_MS ); /* check that the transfer went as planned */ if( ssc.SRB_Status != SS_COMP ) { @@ -573,7 +578,7 @@ read_toc_aspi (_img_private_t *env) } env->i_first_track = p_tocheader[2]; - env->total_tracks = p_tocheader[3] - p_tocheader[2] + 1; + env->i_tracks = p_tocheader[3] - p_tocheader[2] + 1; { int i, i_toclength; @@ -603,15 +608,15 @@ read_toc_aspi (_img_private_t *env) /* If the command has still not been processed, wait until it's * finished */ if( ssc.SRB_Status == SS_PENDING ) - WaitForSingleObject( hEvent, INFINITE ); + WaitForSingleObject( hEvent, OP_TIMEOUT_MS ); /* check that the transfer went as planned */ if( ssc.SRB_Status != SS_COMP ) { cdio_info("ASPI: %s", aspierror(ssc.SRB_Status)); - env->total_tracks = 0; + env->i_tracks = 0; } - for( i = 0 ; i <= env->total_tracks ; i++ ) { + for( i = 0 ; i <= env->i_tracks ; i++ ) { int i_index = 8 + 8 * i; env->tocent[ i ].start_lsn = ((int)p_fulltoc[ i_index ] << 24) + ((int)p_fulltoc[ i_index+1 ] << 16) + @@ -672,6 +677,172 @@ wnaspi32_eject_media (void *user_data) { } #endif +/*! + Return the value associated with the key "arg". +*/ +const cdtext_t * +get_cdtext_aspi (_img_private_t *env) +{ + uint8_t bigbuffer[5000]; + HANDLE hEvent; + struct SRB_ExecSCSICmd ssc; + + /* Create the transfer completion event */ + hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + if( hEvent == NULL ) { + return NULL; + } + + 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( env->i_sid ); + ssc.SRB_Target = HIBYTE( env->i_sid ); + ssc.SRB_Lun = env->i_lun; + ssc.SRB_SenseLen = SENSE_LEN; + + ssc.SRB_PostProc = (LPVOID) hEvent; + ssc.SRB_CDBLen = 10; + + CDIO_MMC_SET_COMMAND(ssc.CDBByte, CDIO_MMC_GPCMD_READ_TOC); + ssc.CDBByte[1] = 0x02; // MSF mode + ssc.CDBByte[2] = 0x05; // CD text + CDIO_MMC_SET_READ_LENGTH(ssc.CDBByte, sizeof(bigbuffer)); + + /* Result buffer */ + ssc.SRB_BufPointer = bigbuffer; + ssc.SRB_BufLen = sizeof(bigbuffer); + + memset ( bigbuffer, 0, sizeof(bigbuffer) ); + + /* Initiate transfer */ + ResetEvent( hEvent ); + env->lpSendCommand( (void*) &ssc ); + + /* If the command has still not been processed, wait until it's + * finished */ + if( ssc.SRB_Status == SS_PENDING ) { + WaitForSingleObject( hEvent, OP_TIMEOUT_MS ); + } + CloseHandle( hEvent ); + + /* check that the transfer went as planned */ + if( ssc.SRB_Status != SS_COMP ) { + cdio_info("ASPI: %s", aspierror(ssc.SRB_Status)); + return NULL; + } + + { + CDText_data_t *pdata; + int i; + int j; + char buffer[256]; + int idx; + int track; + + memset( buffer, 0x00, sizeof(buffer) ); + idx = 0; + + pdata = (CDText_data_t *) (&bigbuffer[4]); + for( i=0; i<0xFF; i++ ) { + if( pdata->seq != i ) + break; + + if( (pdata->type >= 0x80) + && (pdata->type <= 0x85) && (pdata->block == 0) ) { + track = pdata->i_track; + + for( j=0; j<12; j++ ) { + if( pdata->text[j] == 0x00 ) + { + switch( pdata->type) { + case CDIO_CDTEXT_TITLE: + if( track == 0 ) + env->cdtext.field[CDTEXT_TITLE] = strdup(buffer); + else + env->tocent[track-1].cdtext.field[CDTEXT_TITLE] + = strdup(buffer); + track++; + idx = 0; + break; + + case CDIO_CDTEXT_PERFORMER: // artist + if( track == 0 ) + env->cdtext.field[CDTEXT_PERFORMER] = strdup(buffer); + else + env->tocent[track-1].cdtext.field[CDTEXT_PERFORMER] = + strdup(buffer); + track++; + idx = 0; + break; + case CDIO_CDTEXT_SONGWRITER: + if( track == 0 ) + env->cdtext.field[CDTEXT_SONGWRITER]= strdup(buffer); + else + env->tocent[track-1].cdtext.field[CDTEXT_SONGWRITER] = + strdup( buffer ); + track++; + idx = 0; + break; + case CDIO_CDTEXT_COMPOSER: + if( track == 0 ) + env->cdtext.field[CDTEXT_COMPOSER] = strdup(buffer); + else + env->tocent[track-1].cdtext.field[CDTEXT_COMPOSER] = + strdup(buffer); + track++; + idx = 0; + break; + case CDIO_CDTEXT_ARRANGER: + if( track == 0 ) + env->cdtext.field[CDTEXT_ARRANGER] = strdup(buffer); + else + env->tocent[track-1].cdtext.field[CDTEXT_ARRANGER] = + strdup(buffer); + track++; + idx = 0; + break; + case CDIO_CDTEXT_MESSAGE: + if( track == 0 ) + env->cdtext.field[CDTEXT_MESSAGE] = strdup(buffer); + else + env->tocent[track-1].cdtext.field[CDTEXT_MESSAGE] = + strdup(buffer); + track++; + idx = 0; + break; + case CDIO_CDTEXT_DISCID: + if( track == 0 ) + env->cdtext.field[CDTEXT_DISCID] = strdup(buffer); + else + env->tocent[track-1].cdtext.field[CDTEXT_DISCID] = + strdup(buffer); + track++; + idx = 0; + break; + case CDIO_CDTEXT_GENRE: + if( track == 0 ) + env->cdtext.field[CDTEXT_GENRE] = strdup(buffer); + else + env->tocent[track-1].cdtext.field[CDTEXT_GENRE] = + strdup(buffer); + track++; + idx = 0; + break; + } + } + else { + buffer[idx++] = pdata->text[j]; + } + buffer[idx] = 0x00; + } + } + pdata++; + } + } + return NULL; +} /*! Return the the kind of drive capabilities of device. @@ -724,7 +895,7 @@ get_drive_cap_aspi (const _img_private_t *env) /* If the command has still not been processed, wait until it's * finished */ if( ssc.SRB_Status == SS_PENDING ) - WaitForSingleObject( hEvent, INFINITE ); + WaitForSingleObject( hEvent, OP_TIMEOUT_MS ); CloseHandle( hEvent ); diff --git a/lib/MSWindows/aspi32.h b/lib/MSWindows/aspi32.h index 2315a6ab..5e939d23 100644 --- a/lib/MSWindows/aspi32.h +++ b/lib/MSWindows/aspi32.h @@ -1,6 +1,6 @@ /* Win32 aspi specific */ /* - $Id: aspi32.h,v 1.4 2004/07/08 06:30:17 rocky Exp $ + $Id: aspi32.h,v 1.5 2004/07/13 03:45:26 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein @@ -185,6 +185,11 @@ track_format_t get_track_format_aspi(const _img_private_t *env, */ bool init_aspi (_img_private_t *env); +/*! + Return the value associated with the key "arg". +*/ +const cdtext_t *get_cdtext_aspi (_img_private_t *env); + const char *is_cdrom_aspi(const char drive_letter); /*! diff --git a/lib/MSWindows/win32.c b/lib/MSWindows/win32.c index e9f5885c..f00da737 100644 --- a/lib/MSWindows/win32.c +++ b/lib/MSWindows/win32.c @@ -1,5 +1,5 @@ /* - $Id: win32.c,v 1.17 2004/06/20 15:06:42 rocky Exp $ + $Id: win32.c,v 1.18 2004/07/13 03:45:26 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein @@ -26,7 +26,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: win32.c,v 1.17 2004/06/20 15:06:42 rocky Exp $"; +static const char _rcsid[] = "$Id: win32.c,v 1.18 2004/07/13 03:45:26 rocky Exp $"; #include #include @@ -135,7 +135,6 @@ _cdio_init_win32 (void *user_data) env->gen.init = true; env->toc_init = false; - /* Initializations */ env->h_device_handle = NULL; env->i_sid = 0; @@ -143,6 +142,7 @@ _cdio_init_win32 (void *user_data) env->lpSendCommand = 0; env->b_aspi_init = false; env->b_ioctl_init = false; + env->b_cdtext_init = false; if ( _AM_IOCTL == env->access_mode ) { return init_win32ioctl(env); @@ -317,7 +317,7 @@ _cdio_stat_size (void *user_data) { _img_private_t *env = user_data; - return env->tocent[env->total_tracks].start_lsn; + return env->tocent[env->i_tracks].start_lsn; } /*! @@ -412,7 +412,7 @@ _cdio_eject_media (void *user_data) { Return the value associated with the key "arg". */ static const char * -_cdio_get_arg (void *user_data, const char key[]) +_get_arg_win32 (void *user_data, const char key[]) { _img_private_t *env = user_data; @@ -427,6 +427,25 @@ _cdio_get_arg (void *user_data, const char key[]) return NULL; } +/*! + Return the value associated with the key "arg". +*/ +static const cdtext_t * +_get_cdtext_win32 (void *user_data) +{ + _img_private_t *env = user_data; + + if (NULL == env) return NULL; + if (env->b_cdtext_init) + return &(env->cdtext); + + if (env->hASPI) { + get_cdtext_aspi(env); + } + + return &(env->cdtext); +} + /*! Return the number of of the first track. CDIO_INVALID_TRACK is returned on error. @@ -470,7 +489,7 @@ _cdio_get_num_tracks(void *user_data) if (!env->toc_init) _cdio_read_toc (env) ; - return env->total_tracks; + return env->i_tracks; } /*! @@ -483,7 +502,7 @@ _cdio_get_track_format(void *obj, track_t track_num) if (!env->gen.toc_init) _cdio_read_toc (env) ; - if (track_num > env->total_tracks || track_num == 0) + if (track_num > env->i_tracks || track_num == 0) return TRACK_FORMAT_ERROR; if( env->hASPI ) { @@ -508,9 +527,9 @@ _cdio_get_track_green(void *obj, track_t i_track) if (!env->toc_init) _cdio_read_toc (env) ; - if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = env->total_tracks+1; + if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = env->i_tracks+1; - if (i_track > env->total_tracks+1 || i_track == 0) + if (i_track > env->i_tracks+1 || i_track == 0) return false; switch (_cdio_get_track_format(env, i_track)) { @@ -549,9 +568,9 @@ _cdio_get_track_msf(void *env, track_t track_num, msf_t *msf) if (!_obj->toc_init) _cdio_read_toc (_obj) ; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = _obj->total_tracks+1; + if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = _obj->i_tracks+1; - if (track_num > _obj->total_tracks+1 || track_num == 0) { + if (track_num > _obj->i_tracks+1 || track_num == 0) { return false; } else { cdio_lsn_to_msf(_obj->tocent[track_num-1].start_lsn, msf); @@ -692,7 +711,8 @@ cdio_open_am_win32 (const char *psz_orig_source, const char *psz_access_mode) cdio_funcs _funcs = { .eject_media = _cdio_eject_media, .free = _free_win32, - .get_arg = _cdio_get_arg, + .get_arg = _get_arg_win32, + .get_cdtext = _get_cdtext_win32, .get_default_device = cdio_get_default_device_win32, .get_devices = cdio_get_devices_win32, .get_drive_cap = _cdio_get_drive_cap, diff --git a/lib/MSWindows/win32.h b/lib/MSWindows/win32.h index 388717c4..c451f796 100644 --- a/lib/MSWindows/win32.h +++ b/lib/MSWindows/win32.h @@ -1,5 +1,5 @@ /* - $Id: win32.h,v 1.7 2004/06/25 01:47:06 rocky Exp $ + $Id: win32.h,v 1.8 2004/07/13 03:45:26 rocky Exp $ Copyright (C) 2004 Rocky Bernstein @@ -26,6 +26,7 @@ typedef struct { lsn_t start_lsn; UCHAR Control : 4; UCHAR Format; + cdtext_t cdtext; /* CD-TEXT */ } track_info_t; typedef enum { @@ -39,22 +40,25 @@ typedef struct { This must be first. */ generic_img_private_t gen; + /* Things generally common to all image drivers. */ + track_info_t tocent[100]; /* entry info for each track */ + track_t i_tracks; /* number of tracks in image */ + track_t i_first_track; /* track number of first track */ + cdtext_t cdtext; /* CD-TEXT */ + access_mode_t access_mode; - bool b_ioctl_init; - bool b_aspi_init; - + /* Some of the more OS specific things. */ + bool toc_init; /* if true, info below is valid. */ HANDLE h_device_handle; /* device descriptor */ long hASPI; short i_sid; short i_lun; long (*lpSendCommand)( void* ); - /* Track information */ - bool toc_init; /* if true, info below is valid. */ - track_info_t tocent[100]; /* entry info for each track */ - track_t total_tracks; /* number of tracks in image */ - track_t i_first_track; /* track number of first track */ + bool b_ioctl_init; + bool b_aspi_init; + bool b_cdtext_init; } _img_private_t; diff --git a/lib/MSWindows/win32_ioctl.c b/lib/MSWindows/win32_ioctl.c index 7fc65b11..60efcf7a 100644 --- a/lib/MSWindows/win32_ioctl.c +++ b/lib/MSWindows/win32_ioctl.c @@ -1,5 +1,5 @@ /* - $Id: win32_ioctl.c,v 1.8 2004/07/12 03:34:14 rocky Exp $ + $Id: win32_ioctl.c,v 1.9 2004/07/13 03:45:26 rocky Exp $ Copyright (C) 2004 Rocky Bernstein @@ -26,7 +26,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: win32_ioctl.c,v 1.8 2004/07/12 03:34:14 rocky Exp $"; +static const char _rcsid[] = "$Id: win32_ioctl.c,v 1.9 2004/07/13 03:45:26 rocky Exp $"; #include #include @@ -373,10 +373,10 @@ read_toc_win32ioctl (_img_private_t *env) } env->i_first_track = cdrom_toc.FirstTrack; - env->total_tracks = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1; + env->i_tracks = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1; - for( i = 0 ; i <= env->total_tracks ; i++ ) { + for( i = 0 ; i <= env->i_tracks ; i++ ) { env->tocent[ i ].start_lsn = cdio_msf3_to_lba( cdrom_toc.TrackData[i].Address[1], cdrom_toc.TrackData[i].Address[2], diff --git a/lib/cdio_private.h b/lib/cdio_private.h index 65721e1a..707a397d 100644 --- a/lib/cdio_private.h +++ b/lib/cdio_private.h @@ -1,5 +1,5 @@ /* - $Id: cdio_private.h,v 1.27 2004/07/11 14:25:07 rocky Exp $ + $Id: cdio_private.h,v 1.28 2004/07/13 03:45:15 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein @@ -59,7 +59,7 @@ extern "C" { /*! Return cdtext information. */ - const cdtext_t * (*get_cdtext) (const void *env); + const cdtext_t * (*get_cdtext) (void *env); /*! Return an array of device names. if CdIo is NULL (we haven't diff --git a/lib/image_common.h b/lib/image_common.h index 55b9a7b5..755d6eea 100644 --- a/lib/image_common.h +++ b/lib/image_common.h @@ -1,5 +1,5 @@ /* - $Id: image_common.h,v 1.9 2004/07/11 14:25:07 rocky Exp $ + $Id: image_common.h,v 1.10 2004/07/13 03:45:25 rocky Exp $ Copyright (C) 2004 Rocky Bernstein @@ -93,7 +93,7 @@ _get_arg_image (void *user_data, const char key[]) Return the value associated with the key "arg". */ static const cdtext_t * -_get_cdtext_image (const void *user_data) +_get_cdtext_image (void *user_data) { const _img_private_t *env = user_data;