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.4 2003/11/30 18:14:20 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(const input_thread_t *p_input,
68 cdda_data_t *p_cdda, const char *psz_source,
69 bool play_single_track, unsigned int i_track);
71 /****************************************************************************
73 ****************************************************************************/
76 E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name,
77 vlc_value_t oldval, vlc_value_t val, void *p_data )
81 if (NULL == p_cdda_input) return VLC_EGENERIC;
83 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
85 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
86 msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
87 p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
89 p_cdda->i_debug = val.i_int;
93 /* process messages that originate from libcdio. */
95 cdio_log_handler (cdio_log_level_t level, const char message[])
97 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
101 if (p_cdda->i_debug & INPUT_DBG_CDIO)
102 msg_Dbg( p_cdda_input, message);
105 msg_Warn( p_cdda_input, message);
108 case CDIO_LOG_ASSERT:
109 msg_Err( p_cdda_input, message);
112 msg_Warn( p_cdda_input, message,
113 _("The above message had unknown vcdimager log level"),
121 /*! This routine is called by libcddb routines on error.
122 Setup is done by init_input_plugin.
125 cddb_log_handler (cddb_log_level_t level, const char message[])
127 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
131 if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
132 /* Fall through if to warn case */
134 cdio_log_handler (level, message);
137 #endif /*HAVE_LIBCDDB*/
140 /*! This routine is when xine is not fully set up (before full initialization)
141 or is not around (before finalization).
144 uninit_log_handler (cdio_log_level_t level, const char message[])
146 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
150 if (!(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
152 /* Fall through if to warn case */
154 fprintf(stderr, "WARN: %s\n", message);
157 fprintf(stderr, "ERROR: %s\n", message);
159 case CDIO_LOG_ASSERT:
160 fprintf(stderr, "ASSERT ERROR: %s\n", message);
163 fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
165 _("The above message had unknown cdio log level"),
169 /* gl_default_cdio_log_handler (level, message); */
172 /*****************************************************************************
174 *****************************************************************************/
176 E_(Open)( vlc_object_t *p_this )
178 input_thread_t * p_input = (input_thread_t *)p_this;
182 cdda_data_t * p_cdda;
186 bool play_single_track = false;
188 /* Set where to log errors messages from libcdio. */
189 p_cdda_input = (input_thread_t *)p_this;
191 /* parse the options passed in command line : */
192 psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
199 while( *psz_parser && *psz_parser != '@' )
204 if( *psz_parser == '@' )
210 if ('T' == *psz_parser || 't' == *psz_parser )
213 i_track = (int)strtol( psz_parser, NULL, 10 );
214 i_track = i_track ? i_track : 1;
215 play_single_track = true;
219 /* No source specified, so figure it out. */
220 if( !p_input->psz_access ) {
224 psz_source = config_GetPsz( p_input, MODULE_STRING "-device" );
226 if( !psz_source || 0==strlen(psz_source) ) {
227 /* Scan for a CD-ROM drive with a CD-DA in it. */
229 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
230 if (NULL == cd_drives) return -1;
231 if (cd_drives[0] == NULL) {
232 cdio_free_device_list(cd_drives);
235 psz_source = strdup(cd_drives[0]);
236 cdio_free_device_list(cd_drives);
241 cdio_log_set_handler ( cdio_log_handler );
243 cddb_log_set_handler ( cddb_log_handler );
246 if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
248 msg_Warn( p_input, "could not open %s", psz_source );
253 p_cdda = malloc( sizeof(cdda_data_t) );
256 msg_Err( p_input, "out of memory" );
261 p_cdda->p_cddev = p_cddev;
262 p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
263 p_input->p_access_data = (void *)p_cdda;
265 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
267 p_input->i_mtu = CDDA_DATA_ONCE;
269 /* We read the Table Of Content information */
270 p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
271 p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
272 if( p_cdda->i_nb_tracks < 0 )
273 msg_Err( p_input, "unable to count tracks" );
274 else if( p_cdda->i_nb_tracks <= 0 )
275 msg_Err( p_input, "no audio tracks found" );
277 if( p_cdda->i_nb_tracks <= 1)
279 ioctl_Close( p_cdda->p_cddev );
285 if( i_track >= p_cdda->i_nb_tracks || i_track < 1 )
288 /* Set stream and area data */
289 vlc_mutex_lock( &p_input->stream.stream_lock );
291 /* Initialize ES structures */
292 input_InitStream( p_input, 0 );
294 /* cdda input method */
295 p_input->stream.i_method = INPUT_METHOD_CDDA;
297 p_input->stream.b_pace_control = 1;
298 p_input->stream.b_seekable = 1;
299 p_input->stream.i_mux_rate = 44100 * 4 / 50;
301 #define area p_input->stream.pp_areas
302 for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
304 input_AddArea( p_input, i, 1 );
306 /* Absolute start offset and size */
308 (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
310 (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
311 * (off_t)CDIO_CD_FRAMESIZE_RAW;
315 CDDAFixupPlayList(p_input, p_cdda, psz_source, play_single_track, i_track);
317 CDDAPlay( p_input, i_track);
319 vlc_mutex_unlock( &p_input->stream.stream_lock );
321 if( !p_input->psz_demux || !*p_input->psz_demux )
323 p_input->psz_demux = "cdda";
326 p_input->pf_read = CDDARead;
327 p_input->pf_seek = CDDASeek;
328 p_input->pf_set_area = CDDASetArea;
329 p_input->pf_set_program = CDDASetProgram;
331 /* Update default_pts to a suitable value for cdda access */
332 p_input->i_pts_delay = config_GetInt( p_input,
333 MODULE_STRING "-caching" ) * 1000;
335 p_cdda->p_intf = intf_Create( p_input, "cddax" );
336 intf_RunThread( p_cdda->p_intf );
342 /*****************************************************************************
343 * CDDAPlay: Arrange things so we play the specified track.
344 * VLC_TRUE is returned if there was no error.
345 *****************************************************************************/
347 CDDAPlay( input_thread_t *p_input, int i_track )
349 cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
351 if( i_track >= p_cdda->i_nb_tracks || i_track < 1 )
354 CDDASetArea( p_input, p_input->stream.pp_areas[i_track] );
358 /*****************************************************************************
359 * CDDAClose: closes cdda
360 *****************************************************************************/
362 E_(Close)( vlc_object_t *p_this )
364 input_thread_t * p_input = (input_thread_t *)p_this;
365 cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
367 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
368 ioctl_Close( p_cdda->p_cddev );
370 cdio_log_set_handler (uninit_log_handler);
373 cddb_log_set_handler (uninit_log_handler);
374 cddb_disc_destroy(p_cdda->cddb.disc);
381 /*****************************************************************************
382 * CDDARead: reads from the CDDA into PES packets.
383 *****************************************************************************
384 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
386 *****************************************************************************/
387 static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
390 cdda_data_t * p_cdda;
395 p_cdda = (cdda_data_t *)p_input->p_access_data;
399 /* Compute the number of blocks we have to read */
401 i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
403 for ( i_index = 0; i_index < i_blocks; i_index++ )
406 if (cdio_read_audio_sector(p_cdda->p_cddev->cdio, p_buffer,
407 p_cdda->i_sector) != 0)
409 msg_Err( p_input, "could not read sector %d", p_cdda->i_sector );
414 if ( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
416 input_area_t *p_area;
418 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL),
419 "end of track, cur: %u", p_cdda->i_sector );
421 if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )
424 vlc_mutex_lock( &p_input->stream.stream_lock );
425 p_area = p_input->stream.pp_areas[
426 p_input->stream.p_selected_area->i_id + 1 ];
429 CDDASetArea( p_input, p_area );
430 vlc_mutex_unlock( &p_input->stream.stream_lock );
432 i_read += CDIO_CD_FRAMESIZE_RAW;
435 if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
437 msg_Err( p_input, "must read full sectors" );
443 /*****************************************************************************
444 * CDDASetProgram: Does nothing since a CDDA is mono_program
445 *****************************************************************************/
446 static int CDDASetProgram( input_thread_t * p_input,
447 pgrm_descriptor_t * p_program)
449 cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
450 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
454 /*****************************************************************************
455 * CDDASetArea: initialize input data for title x.
456 * It should be called for each user navigation request.
457 ****************************************************************************/
458 static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
460 cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
463 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
465 /* we can't use the interface slider until initilization is complete */
466 p_input->stream.b_seekable = 0;
468 if( p_area != p_input->stream.p_selected_area )
470 /* Change the default area */
471 p_input->stream.p_selected_area = p_area;
473 /* Change the current track */
474 p_cdda->i_track = p_area->i_id - 1;
475 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
477 /* Update the navigation variables without triggering a callback */
478 val.i_int = p_area->i_id;
479 var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
482 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
484 p_input->stream.p_selected_area->i_tell =
485 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
486 - p_input->stream.p_selected_area->i_start;
488 /* warn interface that something has changed */
489 p_input->stream.b_seekable = 1;
490 p_input->stream.b_changed = 1;
495 /****************************************************************************
497 ****************************************************************************/
498 static void CDDASeek( input_thread_t * p_input, off_t i_off )
500 cdda_data_t * p_cdda;
502 p_cdda = (cdda_data_t *) p_input->p_access_data;
504 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
505 + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
507 vlc_mutex_lock( &p_input->stream.stream_lock );
508 p_input->stream.p_selected_area->i_tell =
509 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
510 - p_input->stream.p_selected_area->i_start;
512 vlc_mutex_unlock( &p_input->stream.stream_lock );
514 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
515 "sector %ud, offset: %lld, i_tell: %lld", p_cdda->i_sector, i_off,
516 p_input->stream.p_selected_area->i_tell );
522 GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
525 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
527 if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
529 cddb_conn_t *conn = cddb_new();
530 const CdIo *cdio = p_cdda->p_cddev->cdio;
533 cddb_log_set_handler (uninit_log_handler);
536 msg_Warn( p_input, "unable to initialize libcddb" );
540 cddb_set_email_address( conn,
541 config_GetPsz( p_input,
542 MODULE_STRING "-cddb-email") );
544 cddb_set_server_name( conn,
545 config_GetPsz( p_input,
546 MODULE_STRING "-cddb-server") );
548 cddb_set_server_port(conn,
549 config_GetInt( p_input,
550 MODULE_STRING "-cddb-port") );
552 /* Set the location of the local CDDB cache directory.
553 The default location of this directory is */
555 if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" ))
556 cddb_cache_disable(conn);
558 cddb_cache_set_dir(conn,
559 config_GetPsz( p_input,
560 MODULE_STRING "-cddb-cachedir") );
562 cddb_set_timeout(conn,
563 config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
566 if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
567 cddb_http_enable(conn);
569 cddb_http_disable(conn);
571 p_cdda->cddb.disc = cddb_disc_new();
572 if (!p_cdda->cddb.disc) {
573 msg_Err( p_input, "Unable to create CDDB disc structure." );
577 for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
578 cddb_track_t *t = cddb_track_new();
579 t->frame_offset = cdio_get_track_lba(cdio, i);
580 cddb_disc_add_track(p_cdda->cddb.disc, t);
583 p_cdda->cddb.disc->length =
584 cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK)
585 / CDIO_CD_FRAMES_PER_SEC;
588 if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
589 msg_Err( p_input, "CDDB disc calc failed" );
593 i_matches = cddb_query(conn, p_cdda->cddb.disc);
596 msg_Warn( p_input, "Found %d matches in CDDB. Using first one.",
598 cddb_read(conn, p_cdda->cddb.disc);
600 if (p_cdda->i_debug & INPUT_DBG_CDDB)
601 cddb_disc_print(p_cdda->cddb.disc);
604 if ((_cdda_is_cd_changed(this) == 1))
606 /**** _cdda_cddb_set_info(this, this->cddb.disc); ***/
608 msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
616 #endif /*HAVE_LIBCDDB*/
619 CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
620 playlist_t *p_playlist, unsigned int i_track,
621 char *psz_mrl, int psz_mrl_max,
622 const char *psz_source, int i_cddb_enabled,
623 int playlist_operation, unsigned int i_pos)
626 (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
627 * 1000 / CDIO_CD_FRAMES_PER_SEC;
628 char *p_title = psz_mrl;
630 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
631 CDDA_MRL_PREFIX, psz_source, i_track);
632 if (i_cddb_enabled) {
633 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
634 if (t != NULL && t->title != NULL)
637 playlist_AddExt( p_playlist, psz_mrl, p_title, i_duration,
638 0, 0, playlist_operation, i_pos );
642 CDDAFixupPlayList(const input_thread_t *p_input, cdda_data_t *p_cdda,
643 const char *psz_source, bool play_single_track,
644 unsigned int i_track)
647 playlist_t * p_playlist;
649 unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
650 strlen("@T") + strlen("100") + 1;
653 config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
658 if (play_single_track && !i_cddb_enabled) return 0;
660 psz_mrl = malloc( psz_mrl_max );
662 if( psz_mrl == NULL )
664 msg_Warn( p_input, "out of memory" );
668 p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
672 msg_Warn( p_input, "can't find playlist" );
679 GetCDDBInfo(p_input, p_cdda);
682 if (play_single_track) {
683 /* May fill out more information when the playlist user interface becomes
686 CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i_track,
687 psz_mrl, psz_mrl_max,
688 psz_source, i_cddb_enabled,
689 PLAYLIST_REPLACE, p_playlist->i_index);
692 playlist_Delete( p_playlist, p_playlist->i_index);
694 for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
696 CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, psz_mrl,
697 psz_mrl_max, psz_source, i_cddb_enabled,
698 PLAYLIST_APPEND, PLAYLIST_END);
702 playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
706 vlc_object_release( p_playlist );