00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "callback.h"
00030 #include "cdda.h"
00031 #include "info.h"
00032 #include <vlc_playlist.h>
00033 #include "vlc_keys.h"
00034
00035 #include <cdio/cdio.h>
00036 #include <cdio/logging.h>
00037 #include <cdio/cd_types.h>
00038
00039 #include <stdio.h>
00040
00041
00042 #ifdef HAVE_STDLIB_H
00043 #include <stdlib.h>
00044 #endif
00045
00046 #ifdef HAVE_SYS_TYPES_H
00047 #include <sys/types.h>
00048 #endif
00049
00050 #ifdef HAVE_STRING_H
00051 #include <string.h>
00052 #endif
00053
00054 #ifdef HAVE_UNISTD_H
00055 # include <unistd.h>
00056 #endif
00057
00058
00059 access_t *p_cdda_input = NULL;
00060
00061
00062
00063
00064 static int CDDARead( access_t *, uint8_t *, int );
00065 static block_t *CDDAReadBlocks( access_t * p_access );
00066 static int CDDASeek( access_t * p_access, int64_t i_pos );
00067 static int CDDAControl( access_t *p_access, int i_query,
00068 va_list args );
00069
00070 static int CDDAInit( access_t *p_access, cdda_data_t *p_cdda ) ;
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 static void
00081 cdio_log_handler (cdio_log_level_t level, const char message[])
00082 {
00083 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
00084
00085 if( p_cdda == NULL )
00086 return;
00087
00088 switch (level) {
00089 case CDIO_LOG_DEBUG:
00090 case CDIO_LOG_INFO:
00091 if (p_cdda->i_debug & INPUT_DBG_CDIO)
00092 msg_Dbg( p_cdda_input, message);
00093 break;
00094 case CDIO_LOG_WARN:
00095 msg_Warn( p_cdda_input, message);
00096 break;
00097 case CDIO_LOG_ERROR:
00098 case CDIO_LOG_ASSERT:
00099 msg_Err( p_cdda_input, message);
00100 break;
00101 default:
00102 msg_Warn( p_cdda_input, message,
00103 "The above message had unknown cdio log level",
00104 level);
00105 }
00106 return;
00107 }
00108
00109
00110 #ifdef HAVE_LIBCDDB
00111
00114 static void
00115 cddb_log_handler (cddb_log_level_t level, const char message[])
00116 {
00117 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
00118 switch (level)
00119 {
00120 case CDDB_LOG_DEBUG:
00121 case CDDB_LOG_INFO:
00122 if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
00123
00124
00125 default:
00126 cdio_log_handler (level, message);
00127 }
00128 }
00129 #endif
00130
00131
00135 static void
00136 uninit_log_handler (cdio_log_level_t level, const char message[])
00137 {
00138 cdda_data_t *p_cdda = NULL;
00139
00140 if (p_cdda_input)
00141 p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
00142
00143 switch (level)
00144 {
00145 case CDIO_LOG_DEBUG:
00146 case CDIO_LOG_INFO:
00147 if (!p_cdda || !(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
00148 return;
00149
00150
00151 case CDIO_LOG_WARN:
00152 fprintf(stderr, "WARN: %s\n", message);
00153 break;
00154 case CDIO_LOG_ERROR:
00155 fprintf(stderr, "ERROR: %s\n", message);
00156 break;
00157 case CDIO_LOG_ASSERT:
00158 fprintf(stderr, "ASSERT ERROR: %s\n", message);
00159 break;
00160 default:
00161 fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n", message,
00162 "The above message had unknown cdio log level",
00163 level);
00164 }
00165
00166
00167 }
00168
00169
00170
00171 static int64_t
00172 get_audio_position ( access_t *p_access )
00173 {
00174 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00175 lsn_t i_offset;
00176
00177 #if LIBCDIO_VERSION_NUM >= 73
00178 if (p_cdda->b_audio_ctl)
00179 {
00180 cdio_subchannel_t sub;
00181 CdIo_t *p_cdio = p_cdda->p_cdio;
00182 if (DRIVER_OP_SUCCESS == cdio_audio_read_subchannel(p_cdio, &sub)) {
00183 if (sub.audio_status != CDIO_MMC_READ_SUB_ST_PAUSED &&
00184 sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY)
00185 return CDIO_INVALID_LSN;
00186
00187 if ( ! p_cdda->b_nav_mode ) {
00188
00189
00190
00191 i_offset = cdio_msf_to_lba((&sub.abs_addr));
00192
00193 } else {
00194
00195
00196
00197 i_offset = cdio_msf_to_lba((&sub.rel_addr));
00198
00199 }
00200 } else {
00201
00202 i_offset = p_cdda->i_lsn;
00203 }
00204 } else
00205 i_offset = p_cdda->i_lsn;
00206 #else
00207 i_offset = p_cdda->i_lsn;
00208 ;
00209 #endif
00210 return i_offset;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219 static block_t * CDDAReadBlocks( access_t * p_access )
00220 {
00221 block_t *p_block;
00222 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00223 int i_blocks = p_cdda->i_blocks_per_read;
00224
00225 dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN),
00226 "called i_lsn: %d i_pos: %lld, size: %lld",
00227 p_cdda->i_lsn, p_access->info.i_pos, p_access->info.i_size);
00228
00229
00230 if( p_access->info.b_eof ) return NULL;
00231
00232 if( !p_cdda->b_header )
00233 {
00234
00235 p_block = block_New( p_access, sizeof( WAVEHEADER ) );
00236 memcpy( p_block->p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
00237 p_cdda->b_header = VLC_TRUE;
00238 return p_block;
00239 }
00240
00241
00242 while( p_cdda->i_lsn > cdio_get_track_last_lsn(p_cdda->p_cdio,
00243 p_cdda->i_track) )
00244 {
00245 bool go_on;
00246
00247 if( p_cdda->b_nav_mode )
00248 go_on = p_cdda->i_lsn > p_cdda->last_disc_frame;
00249 else
00250 go_on = p_cdda->i_track >= p_cdda->i_first_track+p_cdda->i_titles-1 ;
00251
00252 if( go_on )
00253 {
00254 dbg_print( (INPUT_DBG_LSN), "EOF");
00255 p_access->info.b_eof = VLC_TRUE;
00256 return NULL;
00257 }
00258
00259 p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_META;
00260 p_access->info.i_title++;
00261 p_cdda->i_track++;
00262
00263 if ( p_cdda-> b_nav_mode ) {
00264 char *psz_title = CDDAFormatTitle( p_access, p_cdda->i_track );
00265 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_title );
00266 free(psz_title);
00267 } else {
00268 p_access->info.i_size =
00269 p_cdda->p_title[p_access->info.i_title]->i_size;
00270 p_access->info.i_pos = 0;
00271 p_access->info.i_update |= INPUT_UPDATE_SIZE;
00272 }
00273 }
00274
00275
00276 if( p_cdda->i_lsn + i_blocks >=
00277 cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_track+1) )
00278 {
00279 i_blocks = cdio_get_track_lsn( p_cdda->p_cdio, p_cdda->i_track+1 )
00280 - p_cdda->i_lsn;
00281 }
00282
00283
00284 p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW );
00285 if( !p_block)
00286 {
00287 msg_Err( p_access, "Cannot get a new block of size: %i",
00288 i_blocks * CDIO_CD_FRAMESIZE_RAW );
00289 return NULL;
00290 }
00291
00292 {
00293 #if LIBCDIO_VERSION_NUM >= 72
00294 driver_return_code_t rc = DRIVER_OP_SUCCESS;
00295
00296 if ( p_cdda->e_paranoia && p_cdda->paranoia )
00297 {
00298 int i;
00299 for( i = 0; i < i_blocks; i++ )
00300 {
00301 int16_t *p_readbuf = cdio_paranoia_read(p_cdda->paranoia, NULL);
00302 char *psz_err=cdio_cddap_errors(p_cdda->paranoia_cd);
00303 char *psz_mes=cdio_cddap_messages(p_cdda->paranoia_cd);
00304
00305 if (psz_mes || psz_err)
00306 msg_Err( p_access, "%s%s\n", psz_mes ? psz_mes: "",
00307 psz_err ? psz_err: "" );
00308
00309 if (psz_err) free(psz_err);
00310 if (psz_mes) free(psz_mes);
00311 if( !p_readbuf ) {
00312 msg_Err( p_access, "paranoia read error on frame %i\n",
00313 p_cdda->i_lsn+i );
00314 } else
00315 memcpy(p_block->p_buffer + i * CDIO_CD_FRAMESIZE_RAW,
00316 p_readbuf, CDIO_CD_FRAMESIZE_RAW);
00317 }
00318 }
00319 else
00320 rc = cdio_read_audio_sectors( p_cdda->p_cdio, p_block->p_buffer,
00321 p_cdda->i_lsn, i_blocks);
00322 #else
00323 #define DRIVER_OP_SUCCESS 0
00324 int rc;
00325 rc = cdio_read_audio_sectors( p_cdda->p_cdio, p_block->p_buffer,
00326 p_cdda->i_lsn, i_blocks);
00327 #endif
00328 if( rc != DRIVER_OP_SUCCESS )
00329 {
00330 msg_Err( p_access, "could not read %d sectors starting from %lu",
00331 i_blocks, (long unsigned int) p_cdda->i_lsn );
00332 block_Release( p_block );
00333
00334
00335
00336
00337
00338 p_cdda->i_lsn++;
00339 p_access->info.i_pos += CDIO_CD_FRAMESIZE_RAW;
00340 return NULL;
00341 }
00342 }
00343
00344 p_cdda->i_lsn += i_blocks;
00345 p_access->info.i_pos += i_blocks * CDIO_CD_FRAMESIZE_RAW;
00346
00347 return p_block;
00348 }
00349
00350
00351
00352
00353 static int
00354 CDDARead( access_t * p_access, uint8_t *p_buffer, int i_len )
00355 {
00356 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00357
00358 dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN),
00359 "called lsn: %d pos: %lld, size: %lld",
00360 p_cdda->i_lsn, p_access->info.i_pos, p_access->info.i_size);
00361
00362
00363 if( p_access->info.b_eof ) return 0;
00364
00365 {
00366 lsn_t i_lsn = get_audio_position(p_access);
00367 if (CDIO_INVALID_LSN == i_lsn) {
00368 dbg_print((INPUT_DBG_LSN), "invalid lsn");
00369 memset( p_buffer, 0, i_len );
00370 return i_len;
00371 }
00372
00373 p_cdda->i_lsn = i_lsn;
00374 p_access->info.i_pos = p_cdda->i_lsn * CDIO_CD_FRAMESIZE_RAW;
00375 }
00376
00377 dbg_print((INPUT_DBG_LSN), "updated lsn: %d", p_cdda->i_lsn);
00378
00379
00380 while( p_cdda->i_lsn > cdio_get_track_last_lsn(p_cdda->p_cdio,
00381 p_cdda->i_track) )
00382 {
00383 if( p_cdda->i_track >= p_cdda->i_first_track + p_cdda->i_titles - 1 )
00384 {
00385 dbg_print( (INPUT_DBG_LSN), "EOF");
00386 p_access->info.b_eof = VLC_TRUE;
00387 return 0;
00388 }
00389
00390 p_access->info.i_update |= INPUT_UPDATE_TITLE;
00391 p_access->info.i_title++;
00392 p_cdda->i_track++;
00393
00394 if ( p_cdda-> b_nav_mode ) {
00395 char *psz_title = CDDAFormatTitle( p_access, p_cdda->i_track );
00396 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_title );
00397 free(psz_title);
00398 } else {
00399 p_access->info.i_size =
00400 p_cdda->p_title[p_access->info.i_title]->i_size;
00401 p_access->info.i_pos = 0;
00402 p_access->info.i_update |= INPUT_UPDATE_SIZE;
00403 }
00404 }
00405
00406 memset( p_buffer, 0, i_len );
00407 return i_len;
00408 }
00409
00411 static bool
00412 cdda_audio_pause(CdIo_t *p_cdio)
00413 {
00414 bool b_ok = true;
00415 #if LIBCDIO_VERSION_NUM >= 73
00416 cdio_subchannel_t sub;
00417 if (DRIVER_OP_SUCCESS == cdio_audio_read_subchannel(p_cdio, &sub)) {
00418 if (sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) {
00419 b_ok = DRIVER_OP_SUCCESS == cdio_audio_pause(p_cdio);
00420 }
00421 } else
00422 b_ok = false;
00423 #endif
00424 return b_ok;
00425 }
00426
00427 #if LIBCDIO_VERSION_NUM >= 73
00428
00429 static driver_return_code_t
00430 cdda_audio_play(CdIo_t *p_cdio, lsn_t start_lsn, lsn_t end_lsn)
00431 {
00432 msf_t start_msf;
00433 msf_t last_msf;
00434 cdio_lsn_to_msf(start_lsn, &start_msf);
00435 cdio_lsn_to_msf(end_lsn, &last_msf);
00436 cdda_audio_pause(p_cdio);
00437 return cdio_audio_play_msf (p_cdio, &start_msf, &last_msf);
00438 }
00439 #endif
00440
00441
00442
00443
00444
00445 static int
00446 CDDASeek( access_t * p_access, int64_t i_pos )
00447 {
00448 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00449
00450 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
00451 "lsn %lu, offset: %lld",
00452 (long unsigned int) p_cdda->i_lsn, i_pos );
00453
00454 p_cdda->i_lsn = (i_pos / CDIO_CD_FRAMESIZE_RAW);
00455
00456 #if LIBCDIO_VERSION_NUM >= 72
00457 if ( p_cdda->e_paranoia && p_cdda->paranoia )
00458 cdio_paranoia_seek(p_cdda->paranoia, p_cdda->i_lsn, SEEK_SET);
00459 #endif
00460
00461 #if LIBCDIO_VERSION_NUM >= 73
00462 if ( p_cdda->b_audio_ctl ) {
00463 track_t i_track = cdio_get_track(p_cdda->p_cdio, p_cdda->i_lsn);
00464 lsn_t i_last_lsn;
00465
00466 if ( p_cdda->b_nav_mode )
00467 i_last_lsn = p_cdda->last_disc_frame;
00468 else
00469 i_last_lsn = cdio_get_track_last_lsn(p_cdda->p_cdio, i_track);
00470
00471 cdda_audio_play(p_cdda->p_cdio, p_cdda->i_lsn, i_last_lsn);
00472 }
00473 #endif
00474
00475 if ( ! p_cdda->b_nav_mode )
00476 p_cdda->i_lsn += cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_track);
00477
00478
00479 if ( p_cdda->b_nav_mode && p_access->info.i_pos > i_pos ) {
00480 track_t i_track;
00481 char *psz_title;
00482
00483 for( i_track = p_cdda->i_track;
00484 i_track > 1 &&
00485 p_cdda->i_lsn < cdio_get_track_lsn(p_cdda->p_cdio, i_track);
00486 i_track--, p_access->info.i_title-- ) ;
00487
00488 p_cdda->i_track = i_track;
00489 p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_META ;
00490 psz_title = CDDAFormatTitle( p_access, p_cdda->i_track );
00491 input_Control( p_cdda->p_input, INPUT_SET_NAME,
00492 psz_title );
00493 free(psz_title);
00494
00495 }
00496
00497 p_access->info.i_pos = i_pos;
00498
00499 return VLC_SUCCESS;
00500 }
00501
00502
00503
00504
00505
00506
00507 static bool
00508 cdda_play_track( access_t *p_access, track_t i_track )
00509 {
00510 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00511
00512 dbg_print((INPUT_DBG_CALL), "called track: %d\n", i_track);
00513
00514 if (i_track > p_cdda->i_tracks)
00515 {
00516 msg_Err( p_access, "CD has %d tracks, and you requested track %d",
00517 p_cdda->i_tracks, i_track );
00518 return false;
00519 }
00520
00521 p_cdda->i_track = i_track;
00522
00523
00524 p_cdda->first_frame = p_cdda->i_lsn =
00525 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
00526
00527 p_cdda->last_frame = cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) - 1;
00528
00529 #if LIBCDIO_VERSION_NUM >= 73
00530 if (p_cdda->b_audio_ctl)
00531 {
00532 lsn_t i_last_lsn;
00533 if ( p_cdda->b_nav_mode )
00534 i_last_lsn = p_cdda->last_disc_frame;
00535 else
00536 i_last_lsn = cdio_get_track_last_lsn(p_cdda->p_cdio, i_track);
00537 cdda_audio_play(p_cdda->p_cdio, p_cdda->i_lsn, i_last_lsn);
00538 }
00539 #endif
00540
00541 return true;
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 int
00553 CDDAOpen( vlc_object_t *p_this )
00554 {
00555 access_t *p_access = (access_t*)p_this;
00556 char * psz_source = NULL;
00557 cdda_data_t *p_cdda = NULL;
00558 CdIo_t *p_cdio;
00559 track_t i_track = 1;
00560 vlc_bool_t b_single_track = false;
00561 int i_rc = VLC_EGENERIC;
00562
00563 p_access->p_sys = NULL;
00564
00565
00566 p_cdda_input = p_access;
00567
00568
00569
00570 if( p_access->psz_path && *p_access->psz_path )
00571 {
00572 char *psz_parser = psz_source = strdup( p_access->psz_path );
00573
00574 while( *psz_parser && *psz_parser != '@' )
00575 {
00576 psz_parser++;
00577 }
00578
00579 if( *psz_parser == '@' )
00580 {
00581
00582 *psz_parser = '\0';
00583 ++psz_parser;
00584
00585 if ('T' == *psz_parser || 't' == *psz_parser )
00586 ++psz_parser;
00587
00588 i_track = (int)strtol( psz_parser, NULL, 10 );
00589 i_track = i_track ? i_track : 1;
00590 b_single_track = true;
00591 }
00592 }
00593
00594 if (!psz_source || !*psz_source)
00595 {
00596
00597
00598 if( !p_this->b_force ) return VLC_EGENERIC;
00599
00600 psz_source = var_CreateGetString( p_this, "cd-audio" );
00601
00602 if( !psz_source || !*psz_source )
00603 {
00604
00605 char **ppsz_drives =
00606 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
00607
00608 if (NULL == ppsz_drives || NULL == ppsz_drives[0] )
00609 {
00610 msg_Err( p_access,
00611 "libcdio couldn't find something with a CD-DA in it" );
00612 if (ppsz_drives) cdio_free_device_list(ppsz_drives);
00613 return VLC_EGENERIC;
00614 }
00615
00616 psz_source = strdup(ppsz_drives[0]);
00617 cdio_free_device_list(ppsz_drives);
00618 }
00619 }
00620
00621 cdio_log_set_handler ( cdio_log_handler );
00622
00623
00624 if( !(p_cdio = cdio_open( psz_source, DRIVER_UNKNOWN )) )
00625 {
00626 msg_Warn( p_access, "could not open %s", psz_source );
00627 if (psz_source) free( psz_source );
00628 return VLC_EGENERIC;
00629 }
00630
00631 p_cdda = calloc( 1, sizeof(cdda_data_t) );
00632 if( p_cdda == NULL )
00633 {
00634 msg_Err( p_access, "out of memory" );
00635 free( psz_source );
00636 return VLC_ENOMEM;
00637 }
00638
00639 #ifdef HAVE_LIBCDDB
00640 cddb_log_set_handler ( cddb_log_handler );
00641 p_cdda->cddb.disc = NULL;
00642 p_cdda->b_cddb_enabled =
00643 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
00644 #endif
00645
00646 p_cdda->b_cdtext =
00647 config_GetInt( p_access, MODULE_STRING "-cdtext-enabled" );
00648
00649 p_cdda->b_cdtext_prefer =
00650 config_GetInt( p_access, MODULE_STRING "-cdtext-prefer" );
00651
00652 #if LIBCDIO_VERSION_NUM >= 73
00653 p_cdda->b_audio_ctl =
00654 config_GetInt( p_access, MODULE_STRING "-analog-output" );
00655 #endif
00656
00657 p_cdda->psz_source = strdup(psz_source);
00658 p_cdda->b_header = VLC_FALSE;
00659 p_cdda->p_cdio = p_cdio;
00660 p_cdda->i_tracks = 0;
00661 p_cdda->i_titles = 0;
00662 p_cdda->i_debug = config_GetInt(p_this, MODULE_STRING
00663 "-debug");
00664 p_cdda->b_nav_mode = config_GetInt(p_this, MODULE_STRING
00665 "-navigation-mode" );
00666 p_cdda->i_blocks_per_read
00667 = config_GetInt(p_this, MODULE_STRING "-blocks-per-read");
00668
00669 p_cdda->last_disc_frame =
00670 cdio_get_track_lsn(p_cdio, CDIO_CDROM_LEADOUT_TRACK);
00671
00672 p_cdda->p_input = vlc_object_find( p_access, VLC_OBJECT_INPUT,
00673 FIND_PARENT );
00674
00675 if (0 == p_cdda->i_blocks_per_read)
00676 p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
00677
00678 if ( p_cdda->i_blocks_per_read < MIN_BLOCKS_PER_READ
00679 || p_cdda->i_blocks_per_read > MAX_BLOCKS_PER_READ )
00680 {
00681 msg_Warn( p_cdda_input,
00682 "Number of blocks (%d) has to be between %d and %d. "
00683 "Using %d.",
00684 p_cdda->i_blocks_per_read,
00685 MIN_BLOCKS_PER_READ, MAX_BLOCKS_PER_READ,
00686 DEFAULT_BLOCKS_PER_READ );
00687 p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
00688 }
00689
00690 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
00691
00692
00693 if (p_cdda->b_audio_ctl)
00694 {
00695 p_access->pf_read = CDDARead;
00696 p_access->pf_block = NULL;
00697 } else
00698 {
00699 p_access->pf_read = NULL;
00700 p_access->pf_block = CDDAReadBlocks;
00701 }
00702
00703 p_access->pf_control = CDDAControl;
00704 p_access->pf_seek = CDDASeek;
00705
00706 {
00707 lsn_t i_last_lsn;
00708
00709 if (p_cdda->b_nav_mode)
00710 i_last_lsn = p_cdda->last_disc_frame;
00711 else
00712 i_last_lsn = cdio_get_track_last_lsn(p_cdio, i_track);
00713
00714 if (CDIO_INVALID_LSN != i_last_lsn)
00715 p_access->info.i_size = i_last_lsn * (uint64_t) CDIO_CD_FRAMESIZE_RAW;
00716 else
00717 p_access->info.i_size = 0;
00718 }
00719
00720 p_access->info.i_update = 0;
00721 p_access->info.b_eof = VLC_FALSE;
00722 p_access->info.i_title = 0;
00723 p_access->info.i_seekpoint = 0;
00724
00725 p_access->p_sys = (access_sys_t *) p_cdda;
00726
00727
00728 i_rc = CDDAInit( p_access, p_cdda );
00729 if ( VLC_SUCCESS != i_rc ) goto error;
00730
00731 cdda_play_track( p_access, i_track );
00732
00733 CDDAFixupPlaylist( p_access, p_cdda, b_single_track );
00734
00735 #if LIBCDIO_VERSION_NUM >= 72
00736 {
00737
00738 char *psz_paranoia = config_GetPsz( p_access,
00739 MODULE_STRING "-paranoia" );
00740 p_cdda->e_paranoia = paranoia_none;
00741 if( psz_paranoia && *psz_paranoia )
00742 {
00743
00744 if( !strncmp( psz_paranoia, "full", strlen("full") ) )
00745 p_cdda->e_paranoia = paranoia_full;
00746 else if( !strncmp( psz_paranoia, "overlap", strlen("overlap") ) )
00747 p_cdda->e_paranoia = paranoia_overlap;
00748
00749
00750 if ( p_cdda->e_paranoia ) {
00751 p_cdda->paranoia_cd = cdio_cddap_identify_cdio(p_cdio, 1, NULL);
00752
00753 cdio_cddap_verbose_set(p_cdda->paranoia_cd, CDDA_MESSAGE_PRINTIT,
00754 CDDA_MESSAGE_PRINTIT);
00755 if ( 0 != cdio_cddap_open(p_cdda->paranoia_cd) ) {
00756 msg_Warn( p_cdda_input, "Unable to get paranoia support - "
00757 "continuing without it." );
00758 p_cdda->e_paranoia = paranoia_none;
00759 } else {
00760 p_cdda->paranoia = cdio_paranoia_init(p_cdda->paranoia_cd);
00761 cdio_paranoia_seek(p_cdda->paranoia, p_cdda->i_lsn, SEEK_SET);
00762
00763
00764
00765 cdio_paranoia_modeset(p_cdda->paranoia,
00766 paranoia_full == p_cdda->e_paranoia ?
00767 PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP :
00768 PARANOIA_MODE_OVERLAP^PARANOIA_MODE_NEVERSKIP
00769 );
00770 }
00771 }
00772 }
00773 }
00774 #endif
00775
00776
00777
00778
00779 memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
00780 SetWLE( &p_cdda->waveheader.Format, 1 );
00781 SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
00782 p_cdda->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
00783 p_cdda->waveheader.Length = 0;
00784 p_cdda->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
00785 p_cdda->waveheader.SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
00786 SetDWLE( &p_cdda->waveheader.SubChunkLength, 16);
00787 SetWLE( &p_cdda->waveheader.Modus, 2);
00788 SetDWLE( &p_cdda->waveheader.SampleFreq, CDDA_FREQUENCY_SAMPLE);
00789 SetWLE( &p_cdda->waveheader.BytesPerSample,
00790 2 * 16 / 8 );
00791 SetDWLE( &p_cdda->waveheader.BytesPerSec,
00792 2*16/8 * CDDA_FREQUENCY_SAMPLE );
00793 p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
00794 p_cdda->waveheader.DataLength = 0;
00795
00796
00797 var_Create( p_access, MODULE_STRING "-caching",
00798 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
00799 vlc_object_release( p_cdda->p_input );
00800 return VLC_SUCCESS;
00801
00802 error:
00803 cdio_destroy( p_cdda->p_cdio );
00804 if( psz_source) free( psz_source );
00805 if( p_cdda ) {
00806 if ( p_cdda->p_input )
00807 vlc_object_release( p_cdda->p_input );
00808 free(p_cdda);
00809 }
00810
00811 return i_rc;
00812
00813 }
00814
00815
00816
00817
00818 void
00819 CDDAClose (vlc_object_t *p_this )
00820 {
00821 access_t *p_access = (access_t *) p_this;
00822 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00823 track_t i;
00824
00825 #if LIBCDIO_VERSION_NUM >= 73
00826 if (p_cdda->b_audio_ctl)
00827 cdio_audio_stop(p_cdda->p_cdio);
00828 #endif
00829
00830 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
00831
00832
00833 for( i = 0; i < p_cdda->i_titles; i++ )
00834 {
00835 vlc_input_title_Delete( p_cdda->p_title[i] );
00836 }
00837
00838 #ifdef HAVE_LIBCDDB
00839 cddb_log_set_handler ((cddb_log_handler_t) uninit_log_handler);
00840 if (p_cdda->b_cddb_enabled)
00841 cddb_disc_destroy(p_cdda->cddb.disc);
00842 #endif
00843
00844 cdio_destroy( p_cdda->p_cdio );
00845 cdio_log_set_handler (uninit_log_handler);
00846
00847 #if LIBCDIO_VERSION_NUM >= 72
00848 if (p_cdda->paranoia)
00849 cdio_paranoia_free(p_cdda->paranoia);
00850 if (p_cdda->paranoia_cd)
00851 cdio_cddap_close_no_free_cdio(p_cdda->paranoia_cd);
00852 #endif
00853
00854 if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
00855 if (p_cdda->psz_source) free( p_cdda->psz_source );
00856
00857 #if LIBCDDB_VERSION_NUM >= 1
00858 libcddb_shutdown();
00859 #endif
00860 free( p_cdda );
00861 p_cdda = NULL;
00862 p_cdda_input = NULL;
00863 }
00864
00865
00866
00867
00868
00869
00870 static int CDDAControl( access_t *p_access, int i_query, va_list args )
00871 {
00872 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00873 int *pi_int;
00874 int i;
00875
00876 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
00877 "query %d", i_query );
00878
00879 switch( i_query )
00880 {
00881
00882
00883
00884 case ACCESS_GET_META:
00885 {
00886 vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
00887 if ( p_cdda->p_meta )
00888 {
00889 *pp_meta = vlc_meta_Duplicate( p_cdda->p_meta );
00890 dbg_print( INPUT_DBG_META, "%s", "Meta copied" );
00891 return VLC_SUCCESS;
00892 }
00893 else {
00894 msg_Warn( p_access, "tried to copy NULL meta info" );
00895 return VLC_EGENERIC;
00896 }
00897 }
00898
00899 case ACCESS_CAN_CONTROL_PACE:
00900 {
00901 vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
00902 *pb_bool = p_cdda->b_audio_ctl ? VLC_FALSE : VLC_TRUE;
00903 dbg_print( INPUT_DBG_META, "can control pace? %d", *pb_bool);
00904 return VLC_SUCCESS;
00905 }
00906
00907 case ACCESS_CAN_FASTSEEK:
00908 dbg_print( INPUT_DBG_META, "can fast seek?");
00909 goto common;
00910 case ACCESS_CAN_SEEK:
00911 dbg_print( INPUT_DBG_META, "can seek?");
00912 goto common;
00913 case ACCESS_CAN_PAUSE:
00914 dbg_print( INPUT_DBG_META, "can pause?");
00915 common:
00916 {
00917 vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
00918 *pb_bool = VLC_TRUE;
00919 return VLC_SUCCESS;
00920 }
00921
00922
00923 case ACCESS_GET_MTU:
00924 {
00925 pi_int = (int*)va_arg( args, int * );
00926 *pi_int = p_cdda-> i_blocks_per_read * CDIO_CD_FRAMESIZE_RAW;
00927 dbg_print( INPUT_DBG_META, "Get MTU %d", *pi_int);
00928 break;
00929 }
00930
00931 case ACCESS_GET_PTS_DELAY:
00932 {
00933 int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
00934 *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
00935 * MILLISECONDS_PER_SEC;
00936 break;
00937 }
00938
00939 case ACCESS_GET_TITLE_INFO:
00940 {
00941 input_title_t ***ppp_title =
00942 (input_title_t***)va_arg( args, input_title_t*** );
00943
00944 pi_int = (int*)va_arg( args, int* );
00945 *((int*)va_arg( args, int* )) = 1;
00946
00947 dbg_print ( INPUT_DBG_EVENT,
00948 "GET TITLE: i_tracks %d, i_tracks %d",
00949 p_cdda->i_tracks, p_cdda->i_tracks );
00950
00951 CDDAMetaInfo( p_access, CDIO_INVALID_TRACK );
00952
00953 if ( p_cdda->b_nav_mode) {
00954 char *psz_title =
00955 CDDAFormatTitle( p_access, p_cdda->i_track );
00956 input_Control( p_cdda->p_input, INPUT_SET_NAME,
00957 psz_title );
00958 free(psz_title);
00959 }
00960
00961
00962 if( p_cdda->i_titles == 0 )
00963 {
00964 *pi_int = 0; ppp_title = NULL;
00965 return VLC_SUCCESS;
00966 }
00967 *pi_int = p_cdda->i_titles;
00968 *ppp_title = calloc(1,
00969 sizeof( input_title_t **) * p_cdda->i_titles );
00970
00971 if (!*ppp_title) return VLC_ENOMEM;
00972
00973 for( i = 0; i < p_cdda->i_titles; i++ )
00974 {
00975 if ( p_cdda->p_title[i] ) {
00976 (*ppp_title)[i] =
00977 vlc_input_title_Duplicate( p_cdda->p_title[i] );
00978 }
00979 }
00980 break;
00981 }
00982
00983 case ACCESS_SET_TITLE:
00984 {
00985 i = (int)va_arg( args, int );
00986
00987 dbg_print( INPUT_DBG_EVENT, "set title %d", i );
00988 if( i != p_access->info.i_title )
00989 {
00990 const track_t i_track = p_cdda->i_first_track + i;
00991
00992 p_access->info.i_title = i;
00993 if ( p_cdda->b_nav_mode)
00994 {
00995 lsn_t i_last_lsn;
00996 char *psz_title = CDDAFormatTitle( p_access, i_track );
00997 input_Control( p_cdda->p_input, INPUT_SET_NAME,
00998 psz_title );
00999 free(psz_title);
01000 p_cdda->i_track = i_track;
01001 i_last_lsn = cdio_get_track_lsn(p_cdda->p_cdio,
01002 CDIO_CDROM_LEADOUT_TRACK);
01003 if (CDIO_INVALID_LSN != i_last_lsn)
01004 p_access->info.i_size = (int64_t) CDIO_CD_FRAMESIZE_RAW
01005 * i_last_lsn ;
01006 p_access->info.i_pos = (int64_t)
01007 cdio_get_track_lsn( p_cdda->p_cdio, i_track )
01008 * CDIO_CD_FRAMESIZE_RAW;
01009 } else {
01010 p_access->info.i_size = p_cdda->p_title[i]->i_size;
01011 p_access->info.i_pos = 0;
01012 }
01013 p_access->info.i_update =
01014 INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE;
01015
01016
01017 p_cdda->i_lsn = cdio_get_track_lsn(p_cdda->p_cdio, i_track);
01018 }
01019 break;
01020 }
01021
01022 case ACCESS_SET_PAUSE_STATE:
01023 dbg_print( INPUT_DBG_META, "Pause");
01024 if (p_cdda->b_audio_ctl)
01025 cdda_audio_pause(p_cdda->p_cdio);
01026 break;
01027
01028 case ACCESS_SET_SEEKPOINT:
01029 dbg_print( INPUT_DBG_META, "set seekpoint");
01030 return VLC_EGENERIC;
01031
01032 case ACCESS_SET_PRIVATE_ID_STATE:
01033 dbg_print( INPUT_DBG_META, "set private id state");
01034 return VLC_EGENERIC;
01035
01036 default:
01037 msg_Warn( p_access, "unimplemented query in control" );
01038 return VLC_EGENERIC;
01039
01040 }
01041 return VLC_SUCCESS;
01042 }
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057 static int CDDAInit( access_t *p_access, cdda_data_t *p_cdda )
01058 {
01059 discmode_t discmode = CDIO_DISC_MODE_NO_INFO;
01060
01061 p_cdda->i_tracks = cdio_get_num_tracks(p_cdda->p_cdio);
01062 p_cdda->i_first_track = cdio_get_first_track_num(p_cdda->p_cdio);
01063
01064 discmode = cdio_get_discmode(p_cdda->p_cdio);
01065 switch(discmode) {
01066 case CDIO_DISC_MODE_CD_DA:
01067 case CDIO_DISC_MODE_CD_MIXED:
01068
01069 break;
01070 default:
01071
01072 msg_Err( p_access,
01073 "Disc seems not to be CD-DA. libcdio reports it is %s",
01074 discmode2str[discmode]
01075 );
01076 return VLC_EGENERIC;
01077 }
01078
01079
01080 p_cdda->i_lsn = cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_track);
01081
01082 return VLC_SUCCESS;
01083 }
01084
01085
01086
01087
01088
01089
01090