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.22 2004/01/07 07:21:31 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>
54 /* how many blocks Open will read in each loop */
55 #define CDDA_BLOCKS_ONCE 1
56 #define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW)
58 #define CDDA_MRL_PREFIX "cddax://"
60 /* FIXME: This variable is a hack. Would be nice to eliminate. */
61 static input_thread_t *p_cdda_input = NULL;
63 /*****************************************************************************
65 *****************************************************************************/
66 static int CDDARead ( input_thread_t *, byte_t *, size_t );
67 static void CDDASeek ( input_thread_t *, off_t );
68 static int CDDASetArea ( input_thread_t *, input_area_t * );
69 static int CDDASetProgram ( input_thread_t *, pgrm_descriptor_t * );
71 static int CDDAFixupPlayList( input_thread_t *p_input,
72 cdda_data_t *p_cdda, const char *psz_source,
73 bool play_single_track);
75 /****************************************************************************
77 ****************************************************************************/
79 /* process messages that originate from libcdio. */
81 cdio_log_handler (cdio_log_level_t level, const char message[])
83 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
87 if (p_cdda->i_debug & INPUT_DBG_CDIO)
88 msg_Dbg( p_cdda_input, message);
91 msg_Warn( p_cdda_input, message);
95 msg_Err( p_cdda_input, message);
98 msg_Warn( p_cdda_input, message,
99 _("The above message had unknown vcdimager log level"),
107 /*! This routine is called by libcddb routines on error.
108 Setup is done by init_input_plugin.
111 cddb_log_handler (cddb_log_level_t level, const char message[])
113 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
117 if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
118 /* Fall through if to warn case */
120 cdio_log_handler (level, message);
123 #endif /*HAVE_LIBCDDB*/
126 /*! This routine is when xine is not fully set up (before full initialization)
127 or is not around (before finalization).
130 uninit_log_handler (cdio_log_level_t level, const char message[])
132 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
136 if (!(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
138 /* Fall through if to warn case */
140 fprintf(stderr, "WARN: %s\n", message);
143 fprintf(stderr, "ERROR: %s\n", message);
145 case CDIO_LOG_ASSERT:
146 fprintf(stderr, "ASSERT ERROR: %s\n", message);
149 fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
151 _("The above message had unknown cdio log level"),
155 /* gl_default_cdio_log_handler (level, message); */
158 /*****************************************************************************
159 * CDDAPlay: Arrange things so we play the specified track.
160 * VLC_TRUE is returned if there was no error.
161 *****************************************************************************/
163 CDDAPlay( input_thread_t *p_input, int i_track )
165 cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
167 if( i_track >= p_cdda->i_nb_tracks || i_track < 1 )
170 CDDASetArea( p_input, p_input->stream.pp_areas[i_track] );
174 /*****************************************************************************
175 * CDDARead: reads from the CDDA into PES packets.
176 *****************************************************************************
177 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
179 *****************************************************************************/
180 static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
183 cdda_data_t * p_cdda;
188 p_cdda = (cdda_data_t *)p_input->p_access_data;
192 /* Compute the number of blocks we have to read */
194 i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
196 for ( i_index = 0; i_index < i_blocks; i_index++ )
199 if (cdio_read_audio_sector(p_cdda->p_cddev->cdio, p_buffer,
200 p_cdda->i_sector) != 0)
202 msg_Err( p_input, "could not read sector %d", p_cdda->i_sector );
207 if ( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
209 input_area_t *p_area;
211 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL),
212 "end of track, cur: %u", p_cdda->i_sector );
214 /*???? if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )*/
217 vlc_mutex_lock( &p_input->stream.stream_lock );
218 p_area = p_input->stream.pp_areas[
219 p_input->stream.p_selected_area->i_id + 1 ];
222 CDDASetArea( p_input, p_area );
223 vlc_mutex_unlock( &p_input->stream.stream_lock );
225 i_read += CDIO_CD_FRAMESIZE_RAW;
228 if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
230 msg_Err( p_input, "must read full sectors" );
236 /*****************************************************************************
237 * CDDASetProgram: Does nothing since a CDDA is mono_program
238 *****************************************************************************/
239 static int CDDASetProgram( input_thread_t * p_input,
240 pgrm_descriptor_t * p_program)
242 cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
243 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
247 /*****************************************************************************
248 * CDDASetArea: initialize input data for title x.
249 * It should be called for each user navigation request.
250 ****************************************************************************/
251 static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
253 cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
256 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
258 /* we can't use the interface slider until initilization is complete */
259 p_input->stream.b_seekable = 0;
261 if( p_area != p_input->stream.p_selected_area )
263 /* Change the default area */
264 p_input->stream.p_selected_area = p_area;
266 /* Change the current track */
267 p_cdda->i_track = p_area->i_id - 1;
268 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
270 /* Update the navigation variables without triggering a callback */
271 val.i_int = p_area->i_id;
272 var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
275 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
277 p_input->stream.p_selected_area->i_tell =
278 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
279 - p_input->stream.p_selected_area->i_start;
281 /* warn interface that something has changed */
282 p_input->stream.b_seekable = 1;
283 p_input->stream.b_changed = 1;
288 /****************************************************************************
290 ****************************************************************************/
291 static void CDDASeek( input_thread_t * p_input, off_t i_off )
293 cdda_data_t * p_cdda;
295 p_cdda = (cdda_data_t *) p_input->p_access_data;
297 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
298 + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
300 vlc_mutex_lock( &p_input->stream.stream_lock );
301 p_input->stream.p_selected_area->i_tell =
302 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
303 - p_input->stream.p_selected_area->i_start;
305 vlc_mutex_unlock( &p_input->stream.stream_lock );
307 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
308 "sector %ud, offset: %lld, i_tell: %lld", p_cdda->i_sector, i_off,
309 p_input->stream.p_selected_area->i_tell );
313 #define meta_info_add_str(title, str) \
315 dbg_print( INPUT_DBG_META, "field %s: %s\n", title, str); \
316 input_AddInfo( p_cat, _(title), "%s", str ); \
317 playlist_AddInfo( p_playlist, -1, p_cat->psz_name, \
318 _(title), "%s" , str ); \
322 static void InformationCreate( input_thread_t *p_input )
324 cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
325 playlist_t *p_playlist = vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
327 input_info_category_t *p_cat;
329 p_cat = input_InfoCategory( p_input, "General" );
333 if (p_cdda->i_cddb_enabled) {
335 meta_info_add_str( "Title", p_cdda->cddb.disc->title );
336 meta_info_add_str( "Artist", p_cdda->cddb.disc->artist );
337 meta_info_add_str( "Genre", p_cdda->cddb.disc->genre );
338 meta_info_add_str( "Extended Data", p_cdda->cddb.disc->ext_data );
341 if (p_cdda->cddb.disc->year != 0) {
342 snprintf(year, 5, "%d", p_cdda->cddb.disc->year);
343 meta_info_add_str( "Year", year );
345 if ( p_cdda->cddb.disc->discid ) {
346 input_AddInfo( p_cat, _("CDDB Disc ID"), "%x",
347 p_cdda->cddb.disc->discid );
350 if ( p_cdda->cddb.disc->category != CDDB_CAT_INVALID ) {
351 input_AddInfo( p_cat, _("CDDB Disc Category"), "%s",
352 CDDB_CATEGORY[p_cdda->cddb.disc->category] );
358 #endif /*HAVE_LIBCDDB*/
362 track_t i_track = p_cdda->i_nb_tracks;
363 char psz_buffer[MSTRTIME_MAX_SIZE];
365 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[0])
366 / CDIO_CD_FRAMES_PER_SEC;
368 dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
369 input_AddInfo( p_cat, _("Duration"), "%s",
370 secstotimestr( psz_buffer, i_duration ) );
372 for( i_track = 0 ; i_track < p_cdda->i_nb_tracks ; i_track++ ) {
373 char track_str[TITLE_MAX];
375 (p_cdda->p_sectors[i_track+1] - p_cdda->p_sectors[i_track])
376 / CDIO_CD_FRAMES_PER_SEC;
377 snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
378 p_cat = input_InfoCategory( p_input, track_str );
379 input_AddInfo( p_cat, _("Duration"), "%s",
380 secstotimestr( psz_buffer, i_duration ) );
383 if (p_cdda->i_cddb_enabled) {
384 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
386 if (t != NULL && t->artist != NULL) {
387 input_AddInfo( p_cat, _("Artist"), "%s", t->artist );
388 input_AddInfo( p_cat, _("Title"), "%s", t->title );
395 if( p_playlist ) vlc_object_release( p_playlist );
401 #define free_and_dup(var, val) \
402 if (var) free(var); \
403 if (val) var=strdup(val);
407 GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
410 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
412 if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
414 cddb_conn_t *conn = cddb_new();
415 const CdIo *cdio = p_cdda->p_cddev->cdio;
418 cddb_log_set_handler (uninit_log_handler);
421 msg_Warn( p_input, "unable to initialize libcddb" );
425 cddb_set_email_address( conn,
426 config_GetPsz( p_input,
427 MODULE_STRING "-cddb-email") );
429 cddb_set_server_name( conn,
430 config_GetPsz( p_input,
431 MODULE_STRING "-cddb-server") );
433 cddb_set_server_port(conn,
434 config_GetInt( p_input,
435 MODULE_STRING "-cddb-port") );
437 /* Set the location of the local CDDB cache directory.
438 The default location of this directory is */
440 if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" ))
441 cddb_cache_disable(conn);
443 cddb_cache_set_dir(conn,
444 config_GetPsz( p_input,
445 MODULE_STRING "-cddb-cachedir") );
447 cddb_set_timeout(conn,
448 config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
451 if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
452 cddb_http_enable(conn);
454 cddb_http_disable(conn);
456 p_cdda->cddb.disc = cddb_disc_new();
457 if (!p_cdda->cddb.disc) {
458 msg_Err( p_input, "Unable to create CDDB disc structure." );
462 for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
463 cddb_track_t *t = cddb_track_new();
464 t->frame_offset = cdio_get_track_lba(cdio, i);
465 cddb_disc_add_track(p_cdda->cddb.disc, t);
468 p_cdda->cddb.disc->length =
469 cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK)
470 / CDIO_CD_FRAMES_PER_SEC;
473 if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
474 msg_Err( p_input, "CDDB disc calc failed" );
478 i_matches = cddb_query(conn, p_cdda->cddb.disc);
481 msg_Warn( p_input, "Found %d matches in CDDB. Using first one.",
483 cddb_read(conn, p_cdda->cddb.disc);
485 if (p_cdda->i_debug & INPUT_DBG_CDDB)
486 cddb_disc_print(p_cdda->cddb.disc);
489 msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
497 #endif /*HAVE_LIBCDDB*/
499 #define add_format_str_info(val) \
501 const char *str = val; \
506 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
509 saw_control_prefix = false; \
513 #define add_format_num_info(val, fmt) \
517 sprintf(num_str, fmt, val); \
518 len=strlen(num_str); \
520 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
523 saw_control_prefix = false; \
527 Take a format string and expand escape sequences, that is sequences that
528 begin with %, with information from the current CD.
529 The expanded string is returned. Here is a list of escape sequences:
531 %a : The album artist **
532 %A : The album information **
537 %m : The CD-DA Media Catalog Number (MCN)
538 %n : The number of tracks on the CD
539 %p : The artist/performer/composer in the track **
540 %T : The track number **
541 %s : Number of seconds in this track
543 %Y : The year 19xx or 20xx **
547 CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
548 const char format_str[], const char *mrl, int i_track)
550 #define TEMP_STR_SIZE 256
551 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
552 static char temp_str[TEMP_STR_SIZE];
554 char * tp = temp_str;
555 bool saw_control_prefix = false;
556 size_t format_len = strlen(format_str);
558 bzero(temp_str, TEMP_STR_SIZE);
560 for (i=0; i<format_len; i++) {
562 if (!saw_control_prefix && format_str[i] != '%') {
563 *tp++ = format_str[i];
564 saw_control_prefix = false;
568 switch(format_str[i]) {
570 if (saw_control_prefix) {
573 saw_control_prefix = !saw_control_prefix;
577 if (!p_cdda->i_cddb_enabled) goto not_special;
578 add_format_str_info(p_cdda->cddb.disc->artist);
581 if (!p_cdda->i_cddb_enabled) goto not_special;
582 add_format_str_info(p_cdda->cddb.disc->title);
585 if (!p_cdda->i_cddb_enabled) goto not_special;
586 add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
589 if (!p_cdda->i_cddb_enabled) goto not_special;
590 add_format_str_info(p_cdda->cddb.disc->genre);
593 if (!p_cdda->i_cddb_enabled) goto not_special;
594 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
597 if (!p_cdda->i_cddb_enabled) goto not_special;
598 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
601 if (p_cdda->i_cddb_enabled) {
602 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
604 if (t != NULL && t->title != NULL)
605 add_format_str_info(t->title);
606 } else goto not_special;
609 if (p_cdda->i_cddb_enabled) {
610 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
612 if (t != NULL && t->artist != NULL)
613 add_format_str_info(t->artist);
614 } else goto not_special;
619 add_format_str_info(mrl);
624 add_format_str_info(p_cdda->mcn);
629 add_format_num_info(p_cdda->i_nb_tracks, "%d");
634 if (p_cdda->i_cddb_enabled) {
635 char psz_buffer[MSTRTIME_MAX_SIZE];
637 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
638 / CDIO_CD_FRAMES_PER_SEC;
639 add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
640 } else goto not_special;
645 add_format_num_info(i_track, "%02d");
652 *tp++ = format_str[i];
653 saw_control_prefix = false;
656 return strdup(temp_str);
660 CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
661 playlist_t *p_playlist, unsigned int i_track,
662 char *psz_mrl, int psz_mrl_max,
663 const char *psz_source, int playlist_operation,
667 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
668 * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
671 char *config_varname = MODULE_STRING "-title-format";
674 if (p_cdda->i_cddb_enabled) {
675 config_varname = MODULE_STRING "-cddb-title-format";
677 #endif /*HAVE_LIBCDDB*/
679 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
680 CDDA_MRL_PREFIX, psz_source, i_track);
682 p_title = CDDAFormatStr(p_input, p_cdda,
683 config_GetPsz( p_input, config_varname ),
686 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
687 psz_mrl, p_title, (long int) i_duration / 1000000 , i_pos );
688 playlist_AddWDuration( p_playlist, psz_mrl, p_title, playlist_operation,
691 if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
694 CDDAFormatStr( p_input, p_cdda,
695 config_GetPsz( p_input, MODULE_STRING "-author-format" ),
698 playlist_AddInfo( p_playlist, i_pos, _("General"),_("Author"), p_author);
701 if (p_cdda->i_cddb_enabled) {
702 const char *psz_general_cat = _("General");
704 playlist_AddInfo( p_playlist, i_pos, psz_general_cat, _("Album"),
705 "%s", p_cdda->cddb.disc->title);
706 playlist_AddInfo( p_playlist, i_pos, psz_general_cat, _("Disc Artist(s)"),
707 "%s", p_cdda->cddb.disc->artist);
708 playlist_AddInfo( p_playlist, i_pos, psz_general_cat,
709 _("CDDB Disc Category"),
710 "%s", CDDB_CATEGORY[p_cdda->cddb.disc->category]);
711 playlist_AddInfo( p_playlist, i_pos, psz_general_cat, _("Genre"),
712 "%s", p_cdda->cddb.disc->genre);
713 if ( p_cdda->cddb.disc->discid ) {
714 playlist_AddInfo( p_playlist, i_pos, psz_general_cat, _("CDDB Disc ID"),
715 "%x", p_cdda->cddb.disc->discid );
717 if (p_cdda->cddb.disc->year != 0) {
718 playlist_AddInfo( p_playlist, i_pos, psz_general_cat,
719 _("Year"), "%5d", p_cdda->cddb.disc->year );
722 if (p_cdda->i_cddb_enabled) {
723 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
725 if (t != NULL && t->artist != NULL) {
726 playlist_AddInfo( p_playlist, i_pos, psz_general_cat,
727 _("Track Artist"), "%s", t->artist );
728 playlist_AddInfo( p_playlist, i_pos, psz_general_cat,
729 _("Track Title"), "%s", t->title );
734 #endif /*HAVE_LIBCDDB*/
739 CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda,
740 const char *psz_source, bool play_single_track)
743 playlist_t * p_playlist;
745 unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
746 strlen("@T") + strlen("100") + 1;
749 p_cdda->i_cddb_enabled =
750 config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
751 if( play_single_track && !p_cdda->i_cddb_enabled ) return 0;
753 if( play_single_track ) return 0;
757 psz_mrl = malloc( psz_mrl_max );
759 if( psz_mrl == NULL )
761 msg_Warn( p_input, "out of memory" );
765 p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
769 msg_Warn( p_input, "can't find playlist" );
775 if (p_cdda->i_cddb_enabled)
776 GetCDDBInfo(p_input, p_cdda);
778 p_cdda->cddb.disc = NULL;
781 InformationCreate(p_input);
783 if (play_single_track) {
784 /* May fill out more information when the playlist user interface becomes
787 CDDACreatePlayListItem(p_input, p_cdda, p_playlist, p_cdda->i_track+1,
788 psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
789 p_playlist->i_index);
792 playlist_Delete( p_playlist, p_playlist->i_index);
794 for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
796 CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, psz_mrl,
797 psz_mrl_max, psz_source, PLAYLIST_APPEND,
802 playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
806 vlc_object_release( p_playlist );
811 /****************************************************************************
813 ****************************************************************************/
815 E_(DebugCB) ( vlc_object_t *p_this, const char *psz_name,
816 vlc_value_t oldval, vlc_value_t val, void *p_data )
820 if (NULL == p_cdda_input) return VLC_EGENERIC;
822 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
824 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
825 msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
826 p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
828 p_cdda->i_debug = val.i_int;
833 E_(CDDBEnabledCB) ( vlc_object_t *p_this, const char *psz_name,
834 vlc_value_t oldval, vlc_value_t val, void *p_data )
838 if (NULL == p_cdda_input) return VLC_EGENERIC;
840 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
843 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
844 msg_Dbg( p_cdda_input, "Old CDDB Enabled (x%0x) %d, new (x%0x) %d",
845 p_cdda->i_cddb_enabled, p_cdda->i_cddb_enabled,
846 val.i_int, val.i_int);
848 p_cdda->i_cddb_enabled = val.i_int;
854 #if PLAYLIST_INTERFACE_IS_FIXED
856 E_(TitleFormatCB) ( vlc_object_t *p_this, const char *psz_name,
857 vlc_value_t oldval, vlc_value_t val, void *p_data )
861 if (NULL == p_cdda_input) return VLC_EGENERIC;
863 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
865 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
866 msg_Dbg( p_cdda_input, "Old CDDB Enabled (%s), new (%s)",
867 oldval.psz_string, val.psz_string);
874 /*****************************************************************************
876 *****************************************************************************/
878 E_(Open)( vlc_object_t *p_this )
880 input_thread_t * p_input = (input_thread_t *)p_this;
884 cdda_data_t * p_cdda;
888 bool play_single_track = false;
890 /* Set where to log errors messages from libcdio. */
891 p_cdda_input = (input_thread_t *)p_this;
893 /* parse the options passed in command line : */
894 psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
901 while( *psz_parser && *psz_parser != '@' )
906 if( *psz_parser == '@' )
912 if ('T' == *psz_parser || 't' == *psz_parser )
915 i_track = (int)strtol( psz_parser, NULL, 10 );
916 i_track = i_track ? i_track : 1;
917 play_single_track = true;
921 /* No source specified, so figure it out. */
922 if( !p_input->psz_access ) {
926 psz_source = config_GetPsz( p_input, "cd-audio" );
928 if( !psz_source || 0==strlen(psz_source) ) {
929 /* Scan for a CD-ROM drive with a CD-DA in it. */
931 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
932 if (NULL == cd_drives) return -1;
933 if (cd_drives[0] == NULL) {
934 cdio_free_device_list(cd_drives);
937 psz_source = strdup(cd_drives[0]);
938 cdio_free_device_list(cd_drives);
943 cdio_log_set_handler ( cdio_log_handler );
945 cddb_log_set_handler ( cddb_log_handler );
948 if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
950 msg_Warn( p_input, "could not open %s", psz_source );
955 p_cdda = malloc( sizeof(cdda_data_t) );
958 msg_Err( p_input, "out of memory" );
963 p_cdda->p_cddev = p_cddev;
964 p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
965 p_input->p_access_data = (void *)p_cdda;
967 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
969 p_input->i_mtu = CDDA_DATA_ONCE;
971 /* We read the Table Of Content information */
972 p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
973 p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
974 if( p_cdda->i_nb_tracks < 0 )
975 msg_Err( p_input, "unable to count tracks" );
976 else if( p_cdda->i_nb_tracks <= 0 )
977 msg_Err( p_input, "no audio tracks found" );
979 if( p_cdda->i_nb_tracks <= 1)
981 ioctl_Close( p_cdda->p_cddev );
987 if( i_track >= p_cdda->i_nb_tracks || i_track < 1 )
990 /* Set stream and area data */
991 vlc_mutex_lock( &p_input->stream.stream_lock );
993 /* Initialize ES structures */
994 input_InitStream( p_input, 0 );
996 /* cdda input method */
997 p_input->stream.i_method = INPUT_METHOD_CDDA;
999 p_input->stream.b_pace_control = 1;
1000 p_input->stream.b_seekable = 1;
1001 p_input->stream.i_mux_rate = 44100 * 4 / 50;
1003 #define area p_input->stream.pp_areas
1004 for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
1006 input_AddArea( p_input, i, 1 );
1008 /* Absolute start offset and size */
1010 (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
1012 (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
1013 * (off_t)CDIO_CD_FRAMESIZE_RAW;
1017 CDDAPlay( p_input, i_track);
1019 CDDAFixupPlayList(p_input, p_cdda, psz_source, play_single_track);
1021 vlc_mutex_unlock( &p_input->stream.stream_lock );
1023 if( !p_input->psz_demux || !*p_input->psz_demux )
1025 p_input->psz_demux = "cdda";
1028 p_input->pf_read = CDDARead;
1029 p_input->pf_seek = CDDASeek;
1030 p_input->pf_set_area = CDDASetArea;
1031 p_input->pf_set_program = CDDASetProgram;
1033 /* Update default_pts to a suitable value for cdda access */
1034 p_input->i_pts_delay = config_GetInt( p_input,
1035 MODULE_STRING "-caching" ) * 1000;
1042 /*****************************************************************************
1043 * CDDAClose: closes cdda
1044 *****************************************************************************/
1046 E_(Close)( vlc_object_t *p_this )
1048 input_thread_t * p_input = (input_thread_t *)p_this;
1049 cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
1051 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
1052 ioctl_Close( p_cdda->p_cddev );
1054 cdio_log_set_handler (uninit_log_handler);
1057 cddb_log_set_handler (uninit_log_handler);
1058 if (p_cdda->i_cddb_enabled)
1059 cddb_disc_destroy(p_cdda->cddb.disc);
1063 p_cdda_input = NULL;