1 /*****************************************************************************
2 * cddax.c : CD digital audio input module for vlc using libcdio
3 *****************************************************************************
4 * Copyright (C) 2000,2003 VideoLAN
5 * $Id: access.c,v 1.10 2003/12/02 04:16:21 rocky Exp $
7 * Authors: Rocky Bernstein <rocky@panix.com>
8 * Laurent Aimar <fenrir@via.ecp.fr>
9 * Gildas Bazin <gbazin@netcourrier.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
35 #include <sys/types.h>
36 #include <cdio/cdio.h>
37 #include <cdio/cd_types.h>
50 /* how many blocks Open will read in each loop */
51 #define CDDA_BLOCKS_ONCE 1
52 #define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW)
54 #define CDDA_MRL_PREFIX "cddax://"
56 /* FIXME: This variable is a hack. Would be nice to eliminate. */
57 static input_thread_t *p_cdda_input = NULL;
59 /*****************************************************************************
61 *****************************************************************************/
62 static int CDDARead ( input_thread_t *, byte_t *, size_t );
63 static void CDDASeek ( input_thread_t *, off_t );
64 static int CDDASetArea ( input_thread_t *, input_area_t * );
65 static int CDDASetProgram ( input_thread_t *, pgrm_descriptor_t * );
67 static int CDDAFixupPlayList( input_thread_t *p_input,
68 cdda_data_t *p_cdda, const char *psz_source,
69 bool play_single_track);
71 /****************************************************************************
73 ****************************************************************************/
75 /* process messages that originate from libcdio. */
77 cdio_log_handler (cdio_log_level_t level, const char message[])
79 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
83 if (p_cdda->i_debug & INPUT_DBG_CDIO)
84 msg_Dbg( p_cdda_input, message);
87 msg_Warn( p_cdda_input, message);
91 msg_Err( p_cdda_input, message);
94 msg_Warn( p_cdda_input, message,
95 _("The above message had unknown vcdimager log level"),
103 /*! This routine is called by libcddb routines on error.
104 Setup is done by init_input_plugin.
107 cddb_log_handler (cddb_log_level_t level, const char message[])
109 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
113 if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
114 /* Fall through if to warn case */
116 cdio_log_handler (level, message);
119 #endif /*HAVE_LIBCDDB*/
122 /*! This routine is when xine is not fully set up (before full initialization)
123 or is not around (before finalization).
126 uninit_log_handler (cdio_log_level_t level, const char message[])
128 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
132 if (!(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
134 /* Fall through if to warn case */
136 fprintf(stderr, "WARN: %s\n", message);
139 fprintf(stderr, "ERROR: %s\n", message);
141 case CDIO_LOG_ASSERT:
142 fprintf(stderr, "ASSERT ERROR: %s\n", message);
145 fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
147 _("The above message had unknown cdio log level"),
151 /* gl_default_cdio_log_handler (level, message); */
154 /*****************************************************************************
155 * CDDAPlay: Arrange things so we play the specified track.
156 * VLC_TRUE is returned if there was no error.
157 *****************************************************************************/
159 CDDAPlay( input_thread_t *p_input, int i_track )
161 cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
163 if( i_track >= p_cdda->i_nb_tracks || i_track < 1 )
166 CDDASetArea( p_input, p_input->stream.pp_areas[i_track] );
170 /*****************************************************************************
171 * CDDARead: reads from the CDDA into PES packets.
172 *****************************************************************************
173 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
175 *****************************************************************************/
176 static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
179 cdda_data_t * p_cdda;
184 p_cdda = (cdda_data_t *)p_input->p_access_data;
188 /* Compute the number of blocks we have to read */
190 i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
192 for ( i_index = 0; i_index < i_blocks; i_index++ )
195 if (cdio_read_audio_sector(p_cdda->p_cddev->cdio, p_buffer,
196 p_cdda->i_sector) != 0)
198 msg_Err( p_input, "could not read sector %d", p_cdda->i_sector );
203 if ( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
205 input_area_t *p_area;
207 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL),
208 "end of track, cur: %u", p_cdda->i_sector );
210 /*???? if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )*/
213 vlc_mutex_lock( &p_input->stream.stream_lock );
214 p_area = p_input->stream.pp_areas[
215 p_input->stream.p_selected_area->i_id + 1 ];
218 CDDASetArea( p_input, p_area );
219 vlc_mutex_unlock( &p_input->stream.stream_lock );
221 i_read += CDIO_CD_FRAMESIZE_RAW;
224 if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
226 msg_Err( p_input, "must read full sectors" );
232 /*****************************************************************************
233 * CDDASetProgram: Does nothing since a CDDA is mono_program
234 *****************************************************************************/
235 static int CDDASetProgram( input_thread_t * p_input,
236 pgrm_descriptor_t * p_program)
238 cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
239 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
243 /*****************************************************************************
244 * CDDASetArea: initialize input data for title x.
245 * It should be called for each user navigation request.
246 ****************************************************************************/
247 static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
249 cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
252 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
254 /* we can't use the interface slider until initilization is complete */
255 p_input->stream.b_seekable = 0;
257 if( p_area != p_input->stream.p_selected_area )
259 /* Change the default area */
260 p_input->stream.p_selected_area = p_area;
262 /* Change the current track */
263 p_cdda->i_track = p_area->i_id - 1;
264 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
266 /* Update the navigation variables without triggering a callback */
267 val.i_int = p_area->i_id;
268 var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
271 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
273 p_input->stream.p_selected_area->i_tell =
274 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
275 - p_input->stream.p_selected_area->i_start;
277 /* warn interface that something has changed */
278 p_input->stream.b_seekable = 1;
279 p_input->stream.b_changed = 1;
284 /****************************************************************************
286 ****************************************************************************/
287 static void CDDASeek( input_thread_t * p_input, off_t i_off )
289 cdda_data_t * p_cdda;
291 p_cdda = (cdda_data_t *) p_input->p_access_data;
293 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
294 + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
296 vlc_mutex_lock( &p_input->stream.stream_lock );
297 p_input->stream.p_selected_area->i_tell =
298 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
299 - p_input->stream.p_selected_area->i_start;
301 vlc_mutex_unlock( &p_input->stream.stream_lock );
303 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
304 "sector %ud, offset: %lld, i_tell: %lld", p_cdda->i_sector, i_off,
305 p_input->stream.p_selected_area->i_tell );
309 #define meta_info_add_str(title, str) \
311 dbg_print( INPUT_DBG_META, "field %s: %s\n", title, str); \
312 input_AddInfo( p_cat, _(title), "%s", str ); \
316 static void InformationCreate( input_thread_t *p_input )
318 cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
319 input_info_category_t *p_cat;
320 int use_cddb = p_cdda->i_cddb_enabled;
322 p_cat = input_InfoCategory( p_input, "General" );
327 if( p_cdda->cddb.disc->length > 1000 )
329 int64_t i_sec = (int64_t) p_cdda->cddb.disc->length;
330 char psz_buffer[MSTRTIME_MAX_SIZE];
331 input_AddInfo( p_cat, _("Duration"), "%s",
332 secstotimestr( psz_buffer, i_sec ) );
338 meta_info_add_str( "Title", p_cdda->cddb.disc->title );
339 meta_info_add_str( "Artist", p_cdda->cddb.disc->artist );
340 meta_info_add_str( "Genre", p_cdda->cddb.disc->genre );
341 meta_info_add_str( "Extended Data", p_cdda->cddb.disc->ext_data );
344 if (p_cdda->cddb.disc->year != 0) {
345 snprintf(year, 5, "%d", p_cdda->cddb.disc->year);
346 meta_info_add_str( "Year", year );
348 if ( p_cdda->cddb.disc->discid ) {
349 input_AddInfo( p_cat, _("CDDB Disc ID"), "%x",
350 p_cdda->cddb.disc->discid );
353 if ( p_cdda->cddb.disc->category != CDDB_CAT_INVALID ) {
354 input_AddInfo( p_cat, _("CDDB Disc Category"), "%s",
355 CDDB_CATEGORY[p_cdda->cddb.disc->category] );
361 #endif /*HAVE_LIBCDDB*/
365 track_t i_track = p_cdda->i_nb_tracks;
366 char psz_buffer[MSTRTIME_MAX_SIZE];
368 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
369 / CDIO_CD_FRAMES_PER_SEC;
371 input_AddInfo( p_cat, _("Duration"), "%s",
372 secstotimestr( psz_buffer, i_duration ) );
379 #define free_and_dup(var, val) \
380 if (var) free(var); \
381 if (val) var=strdup(val);
385 GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
388 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
390 if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
392 cddb_conn_t *conn = cddb_new();
393 const CdIo *cdio = p_cdda->p_cddev->cdio;
396 cddb_log_set_handler (uninit_log_handler);
399 msg_Warn( p_input, "unable to initialize libcddb" );
403 cddb_set_email_address( conn,
404 config_GetPsz( p_input,
405 MODULE_STRING "-cddb-email") );
407 cddb_set_server_name( conn,
408 config_GetPsz( p_input,
409 MODULE_STRING "-cddb-server") );
411 cddb_set_server_port(conn,
412 config_GetInt( p_input,
413 MODULE_STRING "-cddb-port") );
415 /* Set the location of the local CDDB cache directory.
416 The default location of this directory is */
418 if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" ))
419 cddb_cache_disable(conn);
421 cddb_cache_set_dir(conn,
422 config_GetPsz( p_input,
423 MODULE_STRING "-cddb-cachedir") );
425 cddb_set_timeout(conn,
426 config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
429 if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
430 cddb_http_enable(conn);
432 cddb_http_disable(conn);
434 p_cdda->cddb.disc = cddb_disc_new();
435 if (!p_cdda->cddb.disc) {
436 msg_Err( p_input, "Unable to create CDDB disc structure." );
440 for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
441 cddb_track_t *t = cddb_track_new();
442 t->frame_offset = cdio_get_track_lba(cdio, i);
443 cddb_disc_add_track(p_cdda->cddb.disc, t);
446 p_cdda->cddb.disc->length =
447 cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK)
448 / CDIO_CD_FRAMES_PER_SEC;
451 if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
452 msg_Err( p_input, "CDDB disc calc failed" );
456 i_matches = cddb_query(conn, p_cdda->cddb.disc);
459 msg_Warn( p_input, "Found %d matches in CDDB. Using first one.",
461 cddb_read(conn, p_cdda->cddb.disc);
463 if (p_cdda->i_debug & INPUT_DBG_CDDB)
464 cddb_disc_print(p_cdda->cddb.disc);
467 msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
475 #endif /*HAVE_LIBCDDB*/
477 #define add_format_str_info(val) \
479 const char *str = val; \
484 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
487 saw_control_prefix = false; \
491 #define add_format_num_info(val, fmt) \
495 sprintf(num_str, fmt, val); \
496 len=strlen(num_str); \
498 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
501 saw_control_prefix = false; \
505 Take a format string and expand escape sequences, that is sequences that
506 begin with %, with information from the current CD.
507 The expanded string is returned. Here is a list of escape sequences:
509 %a : The album artist **
510 %A : The album information **
515 %m : The CD-DA Media Catalog Number (MCN)
516 %n : The number of tracks on the CD
517 %p : The artist/performer/composer in the track **
518 %T : The track number **
519 %s : Number of seconds in this track
521 %Y : The year 19xx or 20xx **
525 CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
526 const char format_str[], const char *mrl, int i_track)
528 #define TEMP_STR_SIZE 256
529 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
530 static char temp_str[TEMP_STR_SIZE];
532 char * tp = temp_str;
533 bool saw_control_prefix = false;
534 size_t format_len = strlen(format_str);
536 bzero(temp_str, TEMP_STR_SIZE);
538 for (i=0; i<format_len; i++) {
540 if (!saw_control_prefix && format_str[i] != '%') {
541 *tp++ = format_str[i];
542 saw_control_prefix = false;
546 switch(format_str[i]) {
548 if (saw_control_prefix) {
551 saw_control_prefix = !saw_control_prefix;
555 if (!p_cdda->i_cddb_enabled) goto not_special;
556 add_format_str_info(p_cdda->cddb.disc->artist);
559 if (!p_cdda->i_cddb_enabled) goto not_special;
560 add_format_str_info(p_cdda->cddb.disc->title);
563 if (!p_cdda->i_cddb_enabled) goto not_special;
564 add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
567 if (!p_cdda->i_cddb_enabled) goto not_special;
568 add_format_str_info(p_cdda->cddb.disc->genre);
571 if (!p_cdda->i_cddb_enabled) goto not_special;
572 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
575 if (!p_cdda->i_cddb_enabled) goto not_special;
576 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
579 if (p_cdda->i_cddb_enabled) {
580 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
582 if (t != NULL && t->title != NULL)
583 add_format_str_info(t->title);
584 } else goto not_special;
587 if (p_cdda->i_cddb_enabled) {
588 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
590 if (t != NULL && t->artist != NULL)
591 add_format_str_info(t->artist);
592 } else goto not_special;
597 add_format_str_info(mrl);
602 add_format_str_info(p_cdda->mcn);
607 add_format_num_info(p_cdda->i_nb_tracks, "%d");
611 if (p_cdda->i_cddb_enabled) {
612 char psz_buffer[MSTRTIME_MAX_SIZE];
614 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
615 / CDIO_CD_FRAMES_PER_SEC;
616 add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
617 } else goto not_special;
621 add_format_num_info(i_track, "%d");
628 *tp++ = format_str[i];
629 saw_control_prefix = false;
632 return strdup(temp_str);
636 CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
637 playlist_t *p_playlist, unsigned int i_track,
638 char *psz_mrl, int psz_mrl_max,
639 const char *psz_source, int playlist_operation,
643 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
644 / CDIO_CD_FRAMES_PER_SEC;
646 char *config_varname = MODULE_STRING "-title-format";
649 if (p_cdda->i_cddb_enabled) {
650 config_varname = MODULE_STRING "-cddb-title-format";
654 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
655 CDDA_MRL_PREFIX, psz_source, i_track);
657 p_title = CDDAFormatStr(p_input, p_cdda,
658 config_GetPsz( p_input, config_varname ),
661 playlist_AddExt( p_playlist, psz_mrl, p_title, i_duration,
662 0, 0, playlist_operation, i_pos );
666 CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda,
667 const char *psz_source, bool play_single_track)
670 playlist_t * p_playlist;
672 unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
673 strlen("@T") + strlen("100") + 1;
676 p_cdda->i_cddb_enabled =
677 config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
680 if (play_single_track && !p_cdda->i_cddb_enabled) return 0;
682 psz_mrl = malloc( psz_mrl_max );
684 if( psz_mrl == NULL )
686 msg_Warn( p_input, "out of memory" );
690 p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
694 msg_Warn( p_input, "can't find playlist" );
700 if (p_cdda->i_cddb_enabled)
701 GetCDDBInfo(p_input, p_cdda);
703 p_cdda->cddb.disc = NULL;
706 InformationCreate(p_input);
708 if (play_single_track) {
709 /* May fill out more information when the playlist user interface becomes
712 CDDACreatePlayListItem(p_input, p_cdda, p_playlist, p_cdda->i_track+1,
713 psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
714 p_playlist->i_index);
717 playlist_Delete( p_playlist, p_playlist->i_index);
719 for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
721 CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, psz_mrl,
722 psz_mrl_max, psz_source, PLAYLIST_APPEND,
727 playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
731 vlc_object_release( p_playlist );
736 /****************************************************************************
738 ****************************************************************************/
740 E_(DebugCB) ( vlc_object_t *p_this, const char *psz_name,
741 vlc_value_t oldval, vlc_value_t val, void *p_data )
745 if (NULL == p_cdda_input) return VLC_EGENERIC;
747 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
749 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
750 msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
751 p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
753 p_cdda->i_debug = val.i_int;
758 E_(CDDBEnabledCB) ( vlc_object_t *p_this, const char *psz_name,
759 vlc_value_t oldval, vlc_value_t val, void *p_data )
763 if (NULL == p_cdda_input) return VLC_EGENERIC;
765 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
767 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
768 msg_Dbg( p_cdda_input, "Old CDDB Enabled (x%0x) %d, new (x%0x) %d",
769 p_cdda->i_cddb_enabled, p_cdda->i_cddb_enabled,
770 val.i_int, val.i_int);
772 p_cdda->i_cddb_enabled = val.i_int;
777 #if PLAYLIST_INTERFACE_IS_FIXED
779 E_(TitleFormatCB) ( vlc_object_t *p_this, const char *psz_name,
780 vlc_value_t oldval, vlc_value_t val, void *p_data )
784 if (NULL == p_cdda_input) return VLC_EGENERIC;
786 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
788 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
789 msg_Dbg( p_cdda_input, "Old CDDB Enabled (%s), new (%s)",
790 oldval.psz_string, val.psz_string);
797 /*****************************************************************************
799 *****************************************************************************/
801 E_(Open)( vlc_object_t *p_this )
803 input_thread_t * p_input = (input_thread_t *)p_this;
807 cdda_data_t * p_cdda;
811 bool play_single_track = false;
813 /* Set where to log errors messages from libcdio. */
814 p_cdda_input = (input_thread_t *)p_this;
816 /* parse the options passed in command line : */
817 psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
824 while( *psz_parser && *psz_parser != '@' )
829 if( *psz_parser == '@' )
835 if ('T' == *psz_parser || 't' == *psz_parser )
838 i_track = (int)strtol( psz_parser, NULL, 10 );
839 i_track = i_track ? i_track : 1;
840 play_single_track = true;
844 /* No source specified, so figure it out. */
845 if( !p_input->psz_access ) {
849 psz_source = config_GetPsz( p_input, MODULE_STRING "-device" );
851 if( !psz_source || 0==strlen(psz_source) ) {
852 /* Scan for a CD-ROM drive with a CD-DA in it. */
854 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
855 if (NULL == cd_drives) return -1;
856 if (cd_drives[0] == NULL) {
857 cdio_free_device_list(cd_drives);
860 psz_source = strdup(cd_drives[0]);
861 cdio_free_device_list(cd_drives);
866 cdio_log_set_handler ( cdio_log_handler );
868 cddb_log_set_handler ( cddb_log_handler );
871 if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
873 msg_Warn( p_input, "could not open %s", psz_source );
878 p_cdda = malloc( sizeof(cdda_data_t) );
881 msg_Err( p_input, "out of memory" );
886 p_cdda->p_cddev = p_cddev;
887 p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
888 p_input->p_access_data = (void *)p_cdda;
890 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
892 p_input->i_mtu = CDDA_DATA_ONCE;
894 /* We read the Table Of Content information */
895 p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
896 p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
897 if( p_cdda->i_nb_tracks < 0 )
898 msg_Err( p_input, "unable to count tracks" );
899 else if( p_cdda->i_nb_tracks <= 0 )
900 msg_Err( p_input, "no audio tracks found" );
902 if( p_cdda->i_nb_tracks <= 1)
904 ioctl_Close( p_cdda->p_cddev );
910 if( i_track >= p_cdda->i_nb_tracks || i_track < 1 )
913 /* Set stream and area data */
914 vlc_mutex_lock( &p_input->stream.stream_lock );
916 /* Initialize ES structures */
917 input_InitStream( p_input, 0 );
919 /* cdda input method */
920 p_input->stream.i_method = INPUT_METHOD_CDDA;
922 p_input->stream.b_pace_control = 1;
923 p_input->stream.b_seekable = 1;
924 p_input->stream.i_mux_rate = 44100 * 4 / 50;
926 #define area p_input->stream.pp_areas
927 for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
929 input_AddArea( p_input, i, 1 );
931 /* Absolute start offset and size */
933 (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
935 (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
936 * (off_t)CDIO_CD_FRAMESIZE_RAW;
940 CDDAPlay( p_input, i_track);
942 CDDAFixupPlayList(p_input, p_cdda, psz_source, play_single_track);
944 vlc_mutex_unlock( &p_input->stream.stream_lock );
946 if( !p_input->psz_demux || !*p_input->psz_demux )
948 p_input->psz_demux = "cdda";
951 p_input->pf_read = CDDARead;
952 p_input->pf_seek = CDDASeek;
953 p_input->pf_set_area = CDDASetArea;
954 p_input->pf_set_program = CDDASetProgram;
956 /* Update default_pts to a suitable value for cdda access */
957 p_input->i_pts_delay = config_GetInt( p_input,
958 MODULE_STRING "-caching" ) * 1000;
960 p_cdda->p_intf = intf_Create( p_input, "cddax" );
961 intf_RunThread( p_cdda->p_intf );
967 /*****************************************************************************
968 * CDDAClose: closes cdda
969 *****************************************************************************/
971 E_(Close)( vlc_object_t *p_this )
973 input_thread_t * p_input = (input_thread_t *)p_this;
974 cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
976 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
977 ioctl_Close( p_cdda->p_cddev );
979 cdio_log_set_handler (uninit_log_handler);
982 cddb_log_set_handler (uninit_log_handler);
983 if (p_cdda->i_cddb_enabled)
984 cddb_disc_destroy(p_cdda->cddb.disc);