1 /*****************************************************************************
2 * cddax.c : CD digital audio input module for vlc using libcdio
3 *****************************************************************************
4 * Copyright (C) 2000, 2003, 2004 VideoLAN
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 20
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);
76 static void CDDAUpdateVar( input_thread_t *p_input, int i_entry, int i_action,
77 const char *p_varname, char *p_label,
78 const char *p_debug_label );
82 /****************************************************************************
84 ****************************************************************************/
86 /* process messages that originate from libcdio. */
88 cdio_log_handler (cdio_log_level_t level, const char message[])
90 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
94 if (p_cdda->i_debug & INPUT_DBG_CDIO)
95 msg_Dbg( p_cdda_input, message);
98 msg_Warn( p_cdda_input, message);
101 case CDIO_LOG_ASSERT:
102 msg_Err( p_cdda_input, message);
105 msg_Warn( p_cdda_input, message,
106 _("The above message had unknown vcdimager log level"),
114 /*! This routine is called by libcddb routines on error.
115 Setup is done by init_input_plugin.
118 cddb_log_handler (cddb_log_level_t level, const char message[])
120 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
124 if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
125 /* Fall through if to warn case */
127 cdio_log_handler (level, message);
130 #endif /*HAVE_LIBCDDB*/
133 /*! This routine is when xine is not fully set up (before full initialization)
134 or is not around (before finalization).
137 uninit_log_handler (cdio_log_level_t level, const char message[])
139 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
143 if (!(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
145 /* Fall through if to warn case */
147 fprintf(stderr, "WARN: %s\n", message);
150 fprintf(stderr, "ERROR: %s\n", message);
152 case CDIO_LOG_ASSERT:
153 fprintf(stderr, "ASSERT ERROR: %s\n", message);
156 fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
158 _("The above message had unknown cdio log level"),
162 /* gl_default_cdio_log_handler (level, message); */
165 /*****************************************************************************
166 * CDDAPlay: Arrange things so we play the specified track.
167 * VLC_TRUE is returned if there was no error.
168 *****************************************************************************/
170 CDDAPlay( input_thread_t *p_input, int i_track )
172 cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
174 if( i_track > p_cdda->i_nb_tracks || i_track < 1 )
177 CDDASetArea( p_input, p_input->stream.pp_areas[i_track] );
181 /*****************************************************************************
182 * CDDARead: reads from the CDDA into PES packets.
183 *****************************************************************************
184 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
186 *****************************************************************************/
187 static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
190 cdda_data_t * p_cdda;
195 p_cdda = (cdda_data_t *)p_input->p_access_data;
197 /* Compute the number of blocks we have to read */
198 i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
201 if( !p_cdda->i_header_pos )
203 p_cdda->i_header_pos = sizeof(WAVEHEADER);
204 i_blocks = (i_len - sizeof(WAVEHEADER)) / CDIO_CD_FRAMESIZE_RAW;
205 memcpy( p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
206 p_buffer += sizeof(WAVEHEADER);
207 i_read += sizeof(WAVEHEADER);
210 for( i_index = 0; i_index < i_blocks; i_index++ )
213 if( cdio_read_audio_sector( p_cdda->p_cddev->cdio, p_buffer,
214 p_cdda->i_sector) != 0 )
216 msg_Err( p_input, "could not read sector %lu",
217 (long unsigned int) p_cdda->i_sector );
222 if( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
224 input_area_t *p_area;
226 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL),
227 "end of track, cur: %lu",
228 (long unsigned int) p_cdda->i_sector );
230 /*???? if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )*/
233 vlc_mutex_lock( &p_input->stream.stream_lock );
234 p_area = p_input->stream.pp_areas[
235 p_input->stream.p_selected_area->i_id + 1 ];
238 CDDASetArea( p_input, p_area );
239 vlc_mutex_unlock( &p_input->stream.stream_lock );
241 i_read += CDIO_CD_FRAMESIZE_RAW;
242 p_buffer += CDIO_CD_FRAMESIZE_RAW;
245 if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
247 msg_Err( p_input, "must read full sectors" );
253 /*****************************************************************************
254 * CDDASetProgram: Does nothing since a CDDA is mono_program
255 *****************************************************************************/
256 static int CDDASetProgram( input_thread_t * p_input,
257 pgrm_descriptor_t * p_program)
259 cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
260 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
264 /*****************************************************************************
265 * CDDASetArea: initialize input data for title x.
266 * It should be called for each user navigation request.
267 ****************************************************************************/
268 static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
270 cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
274 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
276 text.psz_string = _("Track");
277 var_Change( p_input, "title", VLC_VAR_SETTEXT, &text, NULL );
279 /* we can't use the interface slider until initilization is complete */
280 p_input->stream.b_seekable = 0;
282 if( p_area != p_input->stream.p_selected_area )
284 /* Change the default area */
285 p_input->stream.p_selected_area = p_area;
287 /* Change the current track */
288 p_cdda->i_track = p_area->i_id - 1;
289 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
291 /* Update the navigation variables without triggering a callback */
292 val.i_int = p_area->i_id;
293 var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
296 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
298 p_input->stream.p_selected_area->i_tell =
299 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
300 - p_input->stream.p_selected_area->i_start;
302 /* warn interface that something has changed */
303 p_input->stream.b_seekable = 1;
304 p_input->stream.b_changed = 1;
309 /****************************************************************************
311 ****************************************************************************/
312 static void CDDASeek( input_thread_t * p_input, off_t i_off )
314 cdda_data_t * p_cdda;
316 p_cdda = (cdda_data_t *) p_input->p_access_data;
318 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
319 + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
321 vlc_mutex_lock( &p_input->stream.stream_lock );
322 p_input->stream.p_selected_area->i_tell =
323 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
324 - p_input->stream.p_selected_area->i_start;
326 vlc_mutex_unlock( &p_input->stream.stream_lock );
328 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
329 "sector %lu, offset: %lld, i_tell: %lld",
330 (long unsigned int) p_cdda->i_sector, i_off,
331 p_input->stream.p_selected_area->i_tell );
336 /****************************************************************************
337 Update the "varname" variable to i_num without triggering a callback.
338 ****************************************************************************/
340 CDDAUpdateVar( input_thread_t *p_input, int i_num, int i_action,
341 const char *p_varname, char *p_label,
342 const char *p_debug_label)
348 text.psz_string = p_label;
349 var_Change( p_input, p_varname, VLC_VAR_SETTEXT, &text, NULL );
351 var_Change( p_input, p_varname, i_action, &val, NULL );
355 #define meta_info_add_str(title, str) \
357 dbg_print( INPUT_DBG_META, "field %s: %s\n", title, str); \
358 input_AddInfo( p_cat, _(title), "%s", str ); \
359 vlc_mutex_lock( &p_playlist->object_lock ); \
360 p_item = playlist_ItemGetByPos( p_playlist, -1 ); \
361 vlc_mutex_unlock( &p_playlist->object_lock ); \
362 vlc_mutex_lock( &p_item->lock ); \
363 playlist_ItemAddInfo( p_item, p_cat->psz_name, \
364 _(title), "%s" , str ); \
365 vlc_mutex_unlock( &p_item->lock ); \
369 static void InformationCreate( input_thread_t *p_input )
371 cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
372 playlist_t *p_playlist = vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
374 input_info_category_t *p_cat;
376 p_cat = input_InfoCategory( p_input, "General" );
380 if (p_cdda->i_cddb_enabled) {
381 playlist_item_t *p_item;
383 meta_info_add_str( "Title", p_cdda->cddb.disc->title );
384 meta_info_add_str( "Artist", p_cdda->cddb.disc->artist );
385 meta_info_add_str( "Genre", p_cdda->cddb.disc->genre );
386 meta_info_add_str( "Extended Data", p_cdda->cddb.disc->ext_data );
389 if (p_cdda->cddb.disc->year != 0) {
390 snprintf(year, 5, "%d", p_cdda->cddb.disc->year);
391 meta_info_add_str( "Year", year );
393 if ( p_cdda->cddb.disc->discid ) {
394 input_AddInfo( p_cat, _("CDDB Disc ID"), "%x",
395 p_cdda->cddb.disc->discid );
398 if ( p_cdda->cddb.disc->category != CDDB_CAT_INVALID ) {
399 input_AddInfo( p_cat, _("CDDB Disc Category"), "%s",
400 CDDB_CATEGORY[p_cdda->cddb.disc->category] );
406 #endif /*HAVE_LIBCDDB*/
410 track_t i_track = p_cdda->i_nb_tracks;
411 char psz_buffer[MSTRTIME_MAX_SIZE];
413 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[0])
414 / CDIO_CD_FRAMES_PER_SEC;
416 dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
417 input_AddInfo( p_cat, _("Duration"), "%s",
418 secstotimestr( psz_buffer, i_duration ) );
420 for( i_track = 0 ; i_track < p_cdda->i_nb_tracks ; i_track++ ) {
421 char track_str[TITLE_MAX];
423 (p_cdda->p_sectors[i_track+1] - p_cdda->p_sectors[i_track])
424 / CDIO_CD_FRAMES_PER_SEC;
425 snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
426 p_cat = input_InfoCategory( p_input, track_str );
427 input_AddInfo( p_cat, _("Duration"), "%s",
428 secstotimestr( psz_buffer, i_duration ) );
431 if (p_cdda->i_cddb_enabled) {
432 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
435 if ( t->artist != NULL && strlen(t->artist) ) {
436 input_AddInfo( p_cat, _("Artist"), "%s", t->artist );
438 if ( t->title != NULL && strlen(t->title) ) {
439 input_AddInfo( p_cat, _("Title"), "%s", t->title );
441 if ( t->ext_data != NULL && strlen(t->ext_data) ) {
442 input_AddInfo( p_cat, _("Extended Data"), "%s", t->ext_data );
450 if( p_playlist ) vlc_object_release( p_playlist );
456 #define free_and_dup(var, val) \
457 if (var) free(var); \
458 if (val) var=strdup(val);
462 GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
465 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
467 if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
469 cddb_conn_t *conn = cddb_new();
470 const CdIo *cdio = p_cdda->p_cddev->cdio;
473 cddb_log_set_handler (uninit_log_handler);
476 msg_Warn( p_input, "unable to initialize libcddb" );
480 cddb_set_email_address( conn,
481 config_GetPsz( p_input,
482 MODULE_STRING "-cddb-email") );
484 cddb_set_server_name( conn,
485 config_GetPsz( p_input,
486 MODULE_STRING "-cddb-server") );
488 cddb_set_server_port(conn,
489 config_GetInt( p_input,
490 MODULE_STRING "-cddb-port") );
492 /* Set the location of the local CDDB cache directory.
493 The default location of this directory is */
495 if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" ))
496 cddb_cache_disable(conn);
498 cddb_cache_set_dir(conn,
499 config_GetPsz( p_input,
500 MODULE_STRING "-cddb-cachedir") );
502 cddb_set_timeout(conn,
503 config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
506 if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
507 cddb_http_enable(conn);
509 cddb_http_disable(conn);
511 p_cdda->cddb.disc = cddb_disc_new();
512 if (!p_cdda->cddb.disc) {
513 msg_Err( p_input, "Unable to create CDDB disc structure." );
517 for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
518 cddb_track_t *t = cddb_track_new();
519 t->frame_offset = cdio_get_track_lba(cdio, i);
520 cddb_disc_add_track(p_cdda->cddb.disc, t);
523 p_cdda->cddb.disc->length =
524 cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK)
525 / CDIO_CD_FRAMES_PER_SEC;
527 if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
528 msg_Err( p_input, "CDDB disc calc failed" );
532 i_matches = cddb_query(conn, p_cdda->cddb.disc);
535 msg_Warn( p_input, "Found %d matches in CDDB. Using first one.",
537 cddb_read(conn, p_cdda->cddb.disc);
539 if (p_cdda->i_debug & INPUT_DBG_CDDB)
540 cddb_disc_print(p_cdda->cddb.disc);
543 msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
551 #endif /*HAVE_LIBCDDB*/
553 #define add_format_str_info(val) \
555 const char *str = val; \
560 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
563 saw_control_prefix = false; \
567 #define add_format_num_info(val, fmt) \
571 sprintf(num_str, fmt, val); \
572 len=strlen(num_str); \
574 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
577 saw_control_prefix = false; \
581 Take a format string and expand escape sequences, that is sequences that
582 begin with %, with information from the current CD.
583 The expanded string is returned. Here is a list of escape sequences:
585 %a : The album artist **
586 %A : The album information **
591 %m : The CD-DA Media Catalog Number (MCN)
592 %n : The number of tracks on the CD
593 %p : The artist/performer/composer in the track **
594 %T : The track number **
595 %s : Number of seconds in this track
597 %Y : The year 19xx or 20xx **
601 CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
602 const char format_str[], const char *mrl, int i_track)
604 #define TEMP_STR_SIZE 256
605 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
606 static char temp_str[TEMP_STR_SIZE];
608 char * tp = temp_str;
609 bool saw_control_prefix = false;
610 size_t format_len = strlen(format_str);
612 memset(temp_str, 0, TEMP_STR_SIZE);
614 for (i=0; i<format_len; i++) {
616 if (!saw_control_prefix && format_str[i] != '%') {
617 *tp++ = format_str[i];
618 saw_control_prefix = false;
622 switch(format_str[i]) {
624 if (saw_control_prefix) {
627 saw_control_prefix = !saw_control_prefix;
631 if (!p_cdda->i_cddb_enabled) goto not_special;
632 add_format_str_info(p_cdda->cddb.disc->artist);
635 if (!p_cdda->i_cddb_enabled) goto not_special;
636 add_format_str_info(p_cdda->cddb.disc->title);
639 if (!p_cdda->i_cddb_enabled) goto not_special;
640 add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
643 if (!p_cdda->i_cddb_enabled) goto not_special;
644 add_format_str_info(p_cdda->cddb.disc->genre);
647 if (!p_cdda->i_cddb_enabled) goto not_special;
648 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
651 if (!p_cdda->i_cddb_enabled) goto not_special;
652 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
655 if (p_cdda->i_cddb_enabled) {
656 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
658 if (t != NULL && t->title != NULL)
659 add_format_str_info(t->title);
660 } else goto not_special;
663 if (p_cdda->i_cddb_enabled) {
664 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
666 if (t != NULL && t->artist != NULL)
667 add_format_str_info(t->artist);
668 } else goto not_special;
671 if (p_cdda->i_cddb_enabled) {
672 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
674 if (t != NULL && t->ext_data != NULL)
675 add_format_str_info(t->ext_data);
676 } else goto not_special;
681 add_format_str_info(mrl);
686 add_format_str_info(p_cdda->mcn);
691 add_format_num_info(p_cdda->i_nb_tracks, "%d");
696 if (p_cdda->i_cddb_enabled) {
697 char psz_buffer[MSTRTIME_MAX_SIZE];
699 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
700 / CDIO_CD_FRAMES_PER_SEC;
701 add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
702 } else goto not_special;
707 add_format_num_info(i_track, "%02d");
714 *tp++ = format_str[i];
715 saw_control_prefix = false;
718 return strdup(temp_str);
722 CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
723 playlist_t *p_playlist, unsigned int i_track,
724 char *psz_mrl, int psz_mrl_max,
725 const char *psz_source, int playlist_operation,
729 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
730 * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
733 char *config_varname = MODULE_STRING "-title-format";
734 playlist_item_t *p_item;
737 if (p_cdda->i_cddb_enabled) {
738 config_varname = MODULE_STRING "-cddb-title-format";
740 #endif /*HAVE_LIBCDDB*/
742 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
743 CDDA_MRL_PREFIX, psz_source, i_track);
745 p_title = CDDAFormatStr(p_input, p_cdda,
746 config_GetPsz( p_input, config_varname ),
749 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
750 psz_mrl, p_title, (long int) i_duration / 1000000 , i_pos );
751 playlist_AddExt( p_playlist, psz_mrl, p_title, playlist_operation,
752 i_pos, i_duration , NULL, 0);
754 if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
756 vlc_mutex_lock( &p_playlist->object_lock );
757 p_item = playlist_ItemGetByPos( p_playlist, i_pos );
758 vlc_mutex_unlock( &p_playlist->object_lock );
762 vlc_mutex_lock( &p_item->lock );
765 CDDAFormatStr( p_input, p_cdda,
766 config_GetPsz( p_input, MODULE_STRING "-author-format" ),
769 playlist_ItemAddInfo( p_item , _("General"),_("Author"), p_author);
772 if (p_cdda->i_cddb_enabled) {
773 const char *psz_general_cat = _("General");
775 playlist_ItemAddInfo( p_item, psz_general_cat, _("Album"),
776 "%s", p_cdda->cddb.disc->title);
777 playlist_ItemAddInfo( p_item, psz_general_cat, _("Disc Artist(s)"),
778 "%s", p_cdda->cddb.disc->artist);
779 playlist_ItemAddInfo( p_item, psz_general_cat,
780 _("CDDB Disc Category"),
781 "%s", CDDB_CATEGORY[p_cdda->cddb.disc->category]);
782 playlist_ItemAddInfo( p_item, psz_general_cat, _("Genre"),
783 "%s", p_cdda->cddb.disc->genre);
784 if ( p_cdda->cddb.disc->discid ) {
785 playlist_ItemAddInfo( p_item, psz_general_cat, _("CDDB Disc ID"),
786 "%x", p_cdda->cddb.disc->discid );
788 if (p_cdda->cddb.disc->year != 0) {
789 playlist_ItemAddInfo( p_item, psz_general_cat,
790 _("Year"), "%5d", p_cdda->cddb.disc->year );
793 if (p_cdda->i_cddb_enabled) {
794 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
796 if (t != NULL && t->artist != NULL) {
797 playlist_ItemAddInfo( p_item, psz_general_cat,
798 _("Track Artist"), "%s", t->artist );
799 playlist_ItemAddInfo( p_item , psz_general_cat,
800 _("Track Title"), "%s", t->title );
805 #endif /*HAVE_LIBCDDB*/
807 vlc_mutex_unlock( &p_item->lock );
811 CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda,
812 const char *psz_source, bool play_single_track)
815 playlist_t * p_playlist;
817 unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
818 strlen("@T") + strlen("100") + 1;
821 p_cdda->i_cddb_enabled =
822 config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
823 if( play_single_track && !p_cdda->i_cddb_enabled ) return 0;
825 if( play_single_track ) return 0;
829 psz_mrl = malloc( psz_mrl_max );
831 if( psz_mrl == NULL )
833 msg_Warn( p_input, "out of memory" );
837 p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
841 msg_Warn( p_input, "can't find playlist" );
847 if (p_cdda->i_cddb_enabled)
848 GetCDDBInfo(p_input, p_cdda);
850 p_cdda->cddb.disc = NULL;
853 InformationCreate(p_input);
855 if (play_single_track) {
856 /* May fill out more information when the playlist user interface becomes
859 CDDACreatePlayListItem(p_input, p_cdda, p_playlist, p_cdda->i_track+1,
860 psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
861 p_playlist->i_index);
864 playlist_Delete( p_playlist, p_playlist->i_index);
866 for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
868 CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, psz_mrl,
869 psz_mrl_max, psz_source, PLAYLIST_APPEND,
873 playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
877 vlc_object_release( p_playlist );
882 /****************************************************************************
884 ****************************************************************************/
886 E_(DebugCB) ( vlc_object_t *p_this, const char *psz_name,
887 vlc_value_t oldval, vlc_value_t val, void *p_data )
891 if (NULL == p_cdda_input) return VLC_EGENERIC;
893 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
895 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
896 msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
897 p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
899 p_cdda->i_debug = val.i_int;
904 E_(CDDBEnabledCB) ( vlc_object_t *p_this, const char *psz_name,
905 vlc_value_t oldval, vlc_value_t val, void *p_data )
909 if (NULL == p_cdda_input) return VLC_EGENERIC;
911 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
914 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
915 msg_Dbg( p_cdda_input, "Old CDDB Enabled (x%0x) %d, new (x%0x) %d",
916 p_cdda->i_cddb_enabled, p_cdda->i_cddb_enabled,
917 val.i_int, val.i_int);
919 p_cdda->i_cddb_enabled = val.i_int;
925 #if PLAYLIST_INTERFACE_IS_FIXED
927 E_(TitleFormatCB) ( vlc_object_t *p_this, const char *psz_name,
928 vlc_value_t oldval, vlc_value_t val, void *p_data )
932 if (NULL == p_cdda_input) return VLC_EGENERIC;
934 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
936 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
937 msg_Dbg( p_cdda_input, "Old CDDB Enabled (%s), new (%s)",
938 oldval.psz_string, val.psz_string);
945 /*****************************************************************************
947 *****************************************************************************/
949 E_(Open)( vlc_object_t *p_this )
951 input_thread_t * p_input = (input_thread_t *)p_this;
955 cdda_data_t * p_cdda;
960 bool play_single_track = false;
962 /* Set where to log errors messages from libcdio. */
963 p_cdda_input = (input_thread_t *)p_this;
965 /* parse the options passed in command line : */
966 psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
973 while( *psz_parser && *psz_parser != '@' )
978 if( *psz_parser == '@' )
984 if ('T' == *psz_parser || 't' == *psz_parser )
987 i_track = (int)strtol( psz_parser, NULL, 10 );
988 i_track = i_track ? i_track : 1;
989 play_single_track = true;
993 /* No source specified, so figure it out. */
994 if( !p_input->psz_access ) {
998 psz_source = config_GetPsz( p_input, "cd-audio" );
1000 if( !psz_source || 0==strlen(psz_source) ) {
1001 /* Scan for a CD-ROM drive with a CD-DA in it. */
1003 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
1004 if (NULL == cd_drives) return -1;
1005 if (cd_drives[0] == NULL) {
1006 cdio_free_device_list(cd_drives);
1009 psz_source = strdup(cd_drives[0]);
1010 cdio_free_device_list(cd_drives);
1015 cdio_log_set_handler ( cdio_log_handler );
1017 cddb_log_set_handler ( cddb_log_handler );
1020 if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
1022 msg_Warn( p_input, "could not open %s", psz_source );
1024 return VLC_EGENERIC;
1027 p_cdda = malloc( sizeof(cdda_data_t) );
1028 if( p_cdda == NULL )
1030 msg_Err( p_input, "out of memory" );
1035 p_cdda->p_cddev = p_cddev;
1036 p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
1037 p_input->p_access_data = (void *)p_cdda;
1039 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
1041 p_input->i_mtu = CDDA_DATA_ONCE;
1043 /* We read the Table Of Content information */
1044 p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
1045 p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
1046 if( p_cdda->i_nb_tracks < 0 )
1047 msg_Err( p_input, "unable to count tracks" );
1048 else if( p_cdda->i_nb_tracks <= 0 )
1049 msg_Err( p_input, "no audio tracks found" );
1051 if( p_cdda->i_nb_tracks <= 0 )
1053 ioctl_Close( p_cdda->p_cddev );
1056 return VLC_EGENERIC;
1059 if( i_track > p_cdda->i_nb_tracks || i_track < 1 )
1062 /* Set stream and area data */
1063 vlc_mutex_lock( &p_input->stream.stream_lock );
1065 /* Initialize ES structures */
1066 input_InitStream( p_input, 0 );
1068 /* cdda input method */
1069 p_input->stream.i_method = INPUT_METHOD_CDDA;
1071 p_input->stream.b_pace_control = 1;
1072 p_input->stream.b_seekable = 1;
1073 p_input->stream.i_mux_rate = 44100 * 4 / 50;
1075 #define area p_input->stream.pp_areas
1076 for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
1078 input_AddArea( p_input, i, 1 );
1080 /* Absolute start offset and size */
1082 (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
1084 (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
1085 * (off_t)CDIO_CD_FRAMESIZE_RAW;
1089 CDDAPlay( p_input, i_track);
1090 vlc_mutex_unlock( &p_input->stream.stream_lock );
1092 CDDAFixupPlayList(p_input, p_cdda, psz_source, play_single_track);
1094 p_input->pf_read = CDDARead;
1095 p_input->pf_seek = CDDASeek;
1096 p_input->pf_set_area = CDDASetArea;
1097 p_input->pf_set_program = CDDASetProgram;
1099 /* Update default_pts to a suitable value for cdda access */
1100 var_Create( p_input, MODULE_STRING "-caching",
1101 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
1102 var_Get( p_input, MODULE_STRING "-caching", &val );
1103 p_input->i_pts_delay = val.i_int * 1000;
1107 /* Build a WAV header for the output data */
1108 memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
1109 SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
1110 SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
1111 p_cdda->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
1112 p_cdda->waveheader.Length = 0; /* we just don't know */
1113 p_cdda->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
1114 p_cdda->waveheader.SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
1115 SetDWLE( &p_cdda->waveheader.SubChunkLength, 16);
1116 SetWLE( &p_cdda->waveheader.Modus, 2);
1117 SetDWLE( &p_cdda->waveheader.SampleFreq, 44100);
1118 SetWLE( &p_cdda->waveheader.BytesPerSample,
1119 2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
1120 SetDWLE( &p_cdda->waveheader.BytesPerSec,
1121 16 /*BytesPerSample*/ * 44100 /*SampleFreq*/ );
1122 p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
1123 p_cdda->waveheader.DataLength = 0; /* we just don't know */
1124 p_cdda->i_header_pos = 0;
1129 /*****************************************************************************
1130 * CDDAClose: closes cdda
1131 *****************************************************************************/
1133 E_(Close)( vlc_object_t *p_this )
1135 input_thread_t * p_input = (input_thread_t *)p_this;
1136 cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
1138 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
1139 ioctl_Close( p_cdda->p_cddev );
1141 cdio_log_set_handler (uninit_log_handler);
1144 cddb_log_set_handler (uninit_log_handler);
1145 if (p_cdda->i_cddb_enabled)
1146 cddb_disc_destroy(p_cdda->cddb.disc);
1149 free( p_cdda->p_sectors );
1151 p_cdda_input = NULL;