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 *****************************************************************************/
33 #include <vlc/input.h>
34 #include <vlc_playlist.h>
36 #include <sys/types.h>
37 #include <cdio/cdio.h>
38 #include <cdio/logging.h>
39 #include <cdio/cd_types.h>
56 #define CDDA_MRL_PREFIX "cddax://"
58 /* how many blocks Open will read in each loop. Note libcdio and
59 SCSI MMC devices can read at most 25 blocks.
61 #define CDDA_BLOCKS_ONCE 20
62 #define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW)
64 /* Frequency of sample in bits per second. */
65 #define CDDA_FREQUENCY_SAMPLE 44100
67 /* FIXME: This variable is a hack. Would be nice to eliminate. */
68 static access_t *p_cdda_input = NULL;
70 /*****************************************************************************
72 *****************************************************************************/
73 static block_t *CDDABlock( access_t * p_access );
74 static int CDDASeek( access_t * p_access, int64_t i_pos );
75 static int CDDAControl( access_t *p_access, int i_query,
77 static void CDDAMetaInfo( access_t *p_access );
78 static int CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
79 const char *psz_source,
80 vlc_bool_t b_single_track );
81 static void CDDACreatePlaylistItem(const access_t *p_access,
83 playlist_t *p_playlist,
85 char *psz_mrl, int psz_mrl_max,
86 const char *psz_source,
87 int playlist_operation,
90 static int GetCDInfo( access_t *p_access, cdda_data_t *p_cdda ) ;
95 /****************************************************************************
97 ****************************************************************************/
99 /* process messages that originate from libcdio. */
101 cdio_log_handler (cdio_log_level_t level, const char message[])
103 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
107 if (p_cdda->i_debug & INPUT_DBG_CDIO)
108 msg_Dbg( p_cdda_input, message);
111 msg_Warn( p_cdda_input, message);
114 case CDIO_LOG_ASSERT:
115 msg_Err( p_cdda_input, message);
118 msg_Warn( p_cdda_input, message,
119 _("The above message had unknown cdio log level"),
127 /*! This routine is called by libcddb routines on error.
128 Setup is done by init_input_plugin.
131 cddb_log_handler (cddb_log_level_t level, const char message[])
133 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
137 if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
138 /* Fall through if to warn case */
140 cdio_log_handler (level, message);
143 #endif /*HAVE_LIBCDDB*/
146 /*! This routine is when xine is not fully set up (before full initialization)
147 or is not around (before finalization).
150 uninit_log_handler (cdio_log_level_t level, const char message[])
152 cdda_data_t *p_cdda = NULL;
155 p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
160 if (!p_cdda || !(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
162 /* Fall through if to warn case */
164 fprintf(stderr, "WARN: %s\n", message);
167 fprintf(stderr, "ERROR: %s\n", message);
169 case CDIO_LOG_ASSERT:
170 fprintf(stderr, "ASSERT ERROR: %s\n", message);
173 fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
175 _("The above message had unknown cdio log level"),
179 /* gl_default_cdio_log_handler (level, message); */
182 /*****************************************************************************
183 * CDDARead: reads CDDA_BLOCKS_ONCE from the CD-DA and returns an
184 * allocated pointer to the data. NULL is returned if no data read. It
185 * is also possible if we haven't read a RIFF header in which case one
186 * that we creaded during Open/Initialization is returned.
187 *****************************************************************************/
189 CDDABlock( access_t * p_access )
192 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
193 int i_blocks = CDDA_BLOCKS_ONCE;
195 dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called %d",
198 /* Check end of file */
199 if( p_access->info.b_eof ) return NULL;
201 if( !p_cdda->b_header )
203 /* Return only the dummy RIFF header we created in Open/Init */
204 p_block = block_New( p_access, sizeof( WAVEHEADER ) );
205 memcpy( p_block->p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
206 p_cdda->b_header = VLC_TRUE;
210 /* Check end of track */
211 while( p_cdda->i_lsn >= p_cdda->p_lsns[p_access->info.i_title + 1] )
213 if( p_access->info.i_title + 1 >= p_cdda->i_tracks )
215 p_access->info.b_eof = VLC_TRUE;
219 p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE;
220 p_access->info.i_title++;
221 p_access->info.i_size =
222 p_cdda->p_title[p_access->info.i_title]->i_size;
223 p_access->info.i_pos = 0;
227 /* Don't read after the end of a title */
228 if( p_cdda->i_lsn + i_blocks >=
229 p_cdda->p_lsns[p_access->info.i_title + 1] )
231 i_blocks = p_cdda->p_lsns[p_access->info.i_title + 1 ] -
235 /* Do the actual reading */
236 p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW );
239 msg_Err( p_access, "cannot get a new block of size: %i",
240 i_blocks * CDIO_CD_FRAMESIZE_RAW );
244 if( cdio_read_audio_sectors( p_cdda->p_cdio, p_block->p_buffer,
245 p_cdda->i_lsn, i_blocks) != 0 )
247 msg_Err( p_access, "could not read sector %lu",
248 (long unsigned int) p_cdda->i_lsn );
249 block_Release( p_block );
251 /* If we had problems above, assume the problem is with
252 the first sector of the read and set to skip it. In
253 the future libcdio may have cdparanoia support.
256 p_access->info.i_pos += CDIO_CD_FRAMESIZE_RAW;
260 p_cdda->i_lsn += i_blocks;
261 p_access->info.i_pos += p_block->i_buffer;
266 /****************************************************************************
267 * CDDASeek - change position for subsequent reads. For example, this
268 * can happen if the user moves a position slider bar in a GUI.
269 ****************************************************************************/
271 CDDASeek( access_t * p_access, int64_t i_pos )
273 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
275 p_cdda->i_lsn = p_cdda->p_lsns[p_access->info.i_title]
276 + i_pos / CDIO_CD_FRAMESIZE_RAW;
277 p_access->info.i_pos = i_pos;
279 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
280 "lsn %lu, offset: %lld",
281 (long unsigned int) p_cdda->i_lsn, i_pos );
287 #define free_and_dup(var, val) \
288 if (var) free(var); \
289 if (val) var=strdup(val);
293 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
296 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
298 if (config_GetInt( p_access, MODULE_STRING "-cddb-enabled" )) {
300 cddb_conn_t *conn = cddb_new();
301 const CdIo *p_cdio = p_cdda->p_cdio;
304 cddb_log_set_handler (uninit_log_handler);
307 msg_Warn( p_access, _("Unable to initialize libcddb") );
311 cddb_set_email_address( conn,
312 config_GetPsz( p_access,
313 MODULE_STRING "-cddb-email") );
315 cddb_set_server_name( conn,
316 config_GetPsz( p_access,
317 MODULE_STRING "-cddb-server") );
319 cddb_set_server_port(conn,
320 config_GetInt( p_access,
321 MODULE_STRING "-cddb-port") );
323 /* Set the location of the local CDDB cache directory.
324 The default location of this directory is */
326 if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
327 cddb_cache_disable(conn);
329 cddb_cache_set_dir(conn,
330 config_GetPsz( p_access,
331 MODULE_STRING "-cddb-cachedir") );
333 cddb_set_timeout(conn,
334 config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
337 if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" )) {
338 cddb_http_enable(conn);
340 cddb_http_disable(conn);
342 p_cdda->cddb.disc = cddb_disc_new();
343 if (!p_cdda->cddb.disc) {
344 msg_Err( p_access, _("Unable to create CDDB disc structure.") );
348 p_cdda->psz_mcn = cdio_get_mcn(p_cdio);
350 for(i = 1; i <= p_cdda->i_tracks; i++) {
351 cddb_track_t *t = cddb_track_new();
352 t->frame_offset = cdio_get_track_lba(p_cdio, i);
353 cddb_disc_add_track(p_cdda->cddb.disc, t);
356 p_cdda->cddb.disc->length =
357 cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
358 / CDIO_CD_FRAMES_PER_SEC;
360 if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
361 msg_Err( p_access, _("CDDB disc ID calculation failed") );
365 i_matches = cddb_query(conn, p_cdda->cddb.disc);
368 msg_Warn( p_access, _("Found %d matches in CDDB. Using first one."),
370 cddb_read(conn, p_cdda->cddb.disc);
372 if (p_cdda->i_debug & INPUT_DBG_CDDB)
373 cddb_disc_print(p_cdda->cddb.disc);
376 msg_Warn( p_access, _("CDDB error: %s"), cddb_error_str(errno));
384 #endif /*HAVE_LIBCDDB*/
386 #define add_meta_val(FIELD, VLC_META, VAL) \
387 if ( p_cdda->p_meta && VAL) { \
388 vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL ); \
389 dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL ); \
392 #define add_cddb_meta(FIELD, VLC_META) \
393 add_meta_val(FIELD, VLC_META, p_cdda->cddb.disc->FIELD);
395 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
398 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
399 p_cdda->cddb.disc->FIELD ); \
400 psz_buf[sizeof(psz_buf)-1] = '\0'; \
401 add_meta_val(FIELD, VLC_META, psz_buf); \
405 Gets and saves CDDA Meta Information. In the Control routine,
406 we handle Meta Information requests and basically copy what we've
409 static void CDDAMetaInfo( access_t *p_access )
411 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
414 if ( p_cdda && p_cdda->i_cddb_enabled ) {
416 GetCDDBInfo(p_access, p_cdda);
418 if ( p_cdda->cddb.disc ) {
420 p_cdda->p_meta = vlc_meta_New();
422 add_cddb_meta(title, VLC_META_CDDB_TITLE);
423 add_cddb_meta(artist, VLC_META_CDDB_ARTIST);
424 add_cddb_meta(genre, VLC_META_CDDB_GENRE);
425 add_cddb_meta(ext_data, VLC_META_CDDB_EXT_DATA);
427 add_cddb_meta_fmt(year, "%d", VLC_META_CDDB_YEAR);
428 add_cddb_meta_fmt(discid, "%x", VLC_META_CDDB_DISCID);
432 #endif /*HAVE_LIBCDDB*/
435 #if UPDATE_TRACK_INFORMATION_FINISHED
437 track_t i_track = p_cdda->i_tracks;
438 char psz_buffer[MSTRTIME_MAX_SIZE];
440 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[0])
441 / CDIO_CD_FRAMES_PER_SEC;
443 dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
444 input_Control( p_access, INPUT_ADD_INFO, _("General"), _("Duration"), "%s",
445 secstotimestr( psz_buffer, i_duration ) );
447 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ ) {
448 char track_str[TITLE_MAX];
450 (p_cdda->p_lsns[i_track+1] - p_cdda->p_lsns[i_track])
451 / CDIO_CD_FRAMES_PER_SEC;
452 snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
453 input_Control( p_access, INPUT_ADD_INFO, track_str, _("Duration"), "%s",
454 secstotimestr( psz_buffer, i_duration ) );
457 if (p_cdda->i_cddb_enabled) {
458 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
461 if ( t->artist != NULL && strlen(t->artist) ) {
462 input_Control( p_access, INPUT_ADD_INFO, track_str,
463 _("Artist"), "%s", t->artist );
465 if ( t->title != NULL && strlen(t->title) ) {
466 input_Control( p_access, INPUT_ADD_INFO, track_str,
467 _("Title"), "%s", t->title );
469 if ( t->ext_data != NULL && strlen(t->ext_data) ) {
470 input_Control( p_access, INPUT_ADD_INFO, track_str,
471 _("Extended Data"), "%s", t->ext_data );
475 #endif /*HAVE_LIBCDDB*/
478 #endif /* UPDATE_TRACK_INFORMATION_FINISHED */
481 #define add_format_str_info(val) \
483 const char *str = val; \
488 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
491 saw_control_prefix = false; \
495 #define add_format_num_info(val, fmt) \
499 sprintf(num_str, fmt, val); \
500 len=strlen(num_str); \
502 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
505 saw_control_prefix = false; \
509 Take a format string and expand escape sequences, that is sequences that
510 begin with %, with information from the current CD.
511 The expanded string is returned. Here is a list of escape sequences:
513 %a : The album artist **
514 %A : The album information **
519 %m : The CD-DA Media Catalog Number (MCN)
520 %n : The number of tracks on the CD
521 %p : The artist/performer/composer in the track **
522 %T : The track number **
523 %s : Number of seconds in this track
525 %Y : The year 19xx or 20xx **
529 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
530 const char format_str[], const char *mrl, int i_track)
532 #define TEMP_STR_SIZE 256
533 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
534 static char temp_str[TEMP_STR_SIZE];
536 char * tp = temp_str;
537 vlc_bool_t saw_control_prefix = false;
538 size_t format_len = strlen(format_str);
540 memset(temp_str, 0, TEMP_STR_SIZE);
542 for (i=0; i<format_len; i++) {
544 if (!saw_control_prefix && format_str[i] != '%') {
545 *tp++ = format_str[i];
546 saw_control_prefix = false;
550 switch(format_str[i]) {
552 if (saw_control_prefix) {
555 saw_control_prefix = !saw_control_prefix;
559 if (!p_cdda->i_cddb_enabled) goto not_special;
560 if (p_cdda->cddb.disc)
561 add_format_str_info(p_cdda->cddb.disc->artist);
564 if (!p_cdda->i_cddb_enabled) goto not_special;
565 if (p_cdda->cddb.disc)
566 add_format_str_info(p_cdda->cddb.disc->title);
569 if (!p_cdda->i_cddb_enabled) goto not_special;
570 if (p_cdda->cddb.disc)
571 add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
574 if (!p_cdda->i_cddb_enabled) goto not_special;
575 if (p_cdda->cddb.disc)
576 add_format_str_info(p_cdda->cddb.disc->genre);
579 if (!p_cdda->i_cddb_enabled) goto not_special;
580 if (p_cdda->cddb.disc)
581 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
584 if (!p_cdda->i_cddb_enabled) goto not_special;
585 if (p_cdda->cddb.disc)
586 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
589 if (p_cdda && p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
590 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
592 if (t != NULL && t->title != NULL)
593 add_format_str_info(t->title);
594 } else goto not_special;
597 if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
598 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
600 if (t != NULL && t->artist != NULL)
601 add_format_str_info(t->artist);
602 } else goto not_special;
605 if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
606 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
608 if (t != NULL && t->ext_data != NULL)
609 add_format_str_info(t->ext_data);
610 } else goto not_special;
615 add_format_str_info(mrl);
619 add_format_str_info(p_cdda->psz_mcn);
623 add_format_num_info(p_cdda->i_tracks, "%d");
627 if (p_cdda->i_cddb_enabled) {
628 char psz_buffer[MSTRTIME_MAX_SIZE];
630 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
631 / CDIO_CD_FRAMES_PER_SEC;
632 add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
633 } else goto not_special;
637 add_format_num_info(i_track, "%02d");
644 *tp++ = format_str[i];
645 saw_control_prefix = false;
648 return strdup(temp_str);
652 CDDACreatePlaylistItem(const access_t *p_access, cdda_data_t *p_cdda,
653 playlist_t *p_playlist, track_t i_track,
654 char *psz_mrl, int psz_mrl_max,
655 const char *psz_source, int playlist_operation,
659 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
660 * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
663 char *config_varname = MODULE_STRING "-title-format";
664 playlist_item_t *p_item;
667 if (p_cdda->i_cddb_enabled) {
668 config_varname = MODULE_STRING "-cddb-title-format";
670 #endif /*HAVE_LIBCDDB*/
672 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
673 CDDA_MRL_PREFIX, psz_source, i_track);
675 p_title = CDDAFormatStr(p_access, p_cdda,
676 config_GetPsz( p_access, config_varname ),
679 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
680 psz_mrl, p_title, (long int) i_duration / 1000000 , i_pos );
681 playlist_AddExt( p_playlist, psz_mrl, p_title, playlist_operation,
682 i_pos, i_duration , NULL, 0);
684 if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
686 vlc_mutex_lock( &p_playlist->object_lock );
687 p_item = playlist_ItemGetByPos( p_playlist, i_pos );
688 vlc_mutex_unlock( &p_playlist->object_lock );
692 vlc_mutex_lock( &p_item->input.lock );
695 CDDAFormatStr( p_access, p_cdda,
696 config_GetPsz( p_access, MODULE_STRING "-author-format" ),
699 playlist_ItemAddInfo( p_item , _("General"),_("Author"), p_author);
702 if (p_cdda->i_cddb_enabled) {
703 const char *psz_general_cat = _("General");
705 playlist_ItemAddInfo( p_item, psz_general_cat, _("Album"),
706 "%s", p_cdda->cddb.disc->title);
707 playlist_ItemAddInfo( p_item, psz_general_cat, _("Disc Artist(s)"),
708 "%s", p_cdda->cddb.disc->artist);
709 playlist_ItemAddInfo( p_item, psz_general_cat,
710 _("CDDB Disc Category"),
711 "%s", CDDB_CATEGORY[p_cdda->cddb.disc->category]);
712 playlist_ItemAddInfo( p_item, psz_general_cat, _("Genre"),
713 "%s", p_cdda->cddb.disc->genre);
714 if ( p_cdda->cddb.disc->discid ) {
715 playlist_ItemAddInfo( p_item, psz_general_cat, _("CDDB Disc ID"),
716 "%x", p_cdda->cddb.disc->discid );
718 if (p_cdda->cddb.disc->year != 0) {
719 playlist_ItemAddInfo( p_item, psz_general_cat,
720 _("Year"), "%5d", p_cdda->cddb.disc->year );
723 if (p_cdda->i_cddb_enabled) {
724 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
726 if (t != NULL && t->artist != NULL) {
727 playlist_ItemAddInfo( p_item, psz_general_cat,
728 _("Track Artist"), "%s", t->artist );
729 playlist_ItemAddInfo( p_item , psz_general_cat,
730 _("Track Title"), "%s", t->title );
735 #endif /*HAVE_LIBCDDB*/
737 vlc_mutex_unlock( &p_item->input.lock );
741 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
742 const char *psz_source, vlc_bool_t b_single_track )
745 playlist_t * p_playlist;
747 unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
748 strlen("@T") + strlen("100") + 1;
751 p_cdda->i_cddb_enabled =
752 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
753 if( b_single_track && !p_cdda->i_cddb_enabled ) return 0;
755 if( b_single_track ) return VLC_SUCCESS;
758 psz_mrl = malloc( psz_mrl_max );
760 if( psz_mrl == NULL )
762 msg_Warn( p_access, "out of memory" );
766 p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
770 msg_Warn( p_access, "can't find playlist" );
775 CDDAMetaInfo(p_access);
777 if (b_single_track) {
778 /* May fill out more information when the playlist user interface becomes
781 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, p_cdda->i_track,
782 psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
783 p_playlist->i_index);
786 for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
788 input_title_t *t = p_cdda->p_title[i-1] = vlc_input_title_New();
790 asprintf( &t->psz_name, _("Track %i"), i );
791 t->i_size = ( p_cdda->p_lsns[i] - p_cdda->p_lsns[i-1] ) *
792 (int64_t)CDIO_CD_FRAMESIZE_RAW;
794 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
795 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i, psz_mrl,
796 psz_mrl_max, psz_source, PLAYLIST_APPEND,
804 /****************************************************************************
806 ****************************************************************************/
808 E_(CDDADebugCB) ( vlc_object_t *p_this, const char *psz_name,
809 vlc_value_t oldval, vlc_value_t val, void *p_data )
813 if (NULL == p_cdda_input) return VLC_EGENERIC;
815 p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
817 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
818 msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
819 p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
821 p_cdda->i_debug = val.i_int;
826 E_(CDDBEnabledCB) ( vlc_object_t *p_this, const char *psz_name,
827 vlc_value_t oldval, vlc_value_t val, void *p_data )
831 if (NULL == p_cdda_input) return VLC_EGENERIC;
833 p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
836 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
837 msg_Dbg( p_cdda_input, "Old CDDB Enabled (x%0x) %d, new (x%0x) %d",
838 p_cdda->i_cddb_enabled, p_cdda->i_cddb_enabled,
839 val.i_int, val.i_int);
841 p_cdda->i_cddb_enabled = val.i_int;
846 /*****************************************************************************
847 * Open: open cdda device or image file and initialize structures
848 * for subsequent operations.
849 *****************************************************************************/
851 E_(CDDAOpen)( vlc_object_t *p_this )
853 access_t *p_access = (access_t*)p_this;
854 char * psz_source = NULL;
858 vlc_bool_t b_single_track = false;
859 int i_rc = VLC_EGENERIC;
861 /* Set where to log errors messages from libcdio. */
862 p_cdda_input = p_access;
864 /* parse the options passed in command line : */
866 if( p_access->psz_path && *p_access->psz_path )
868 char *psz_parser = psz_source = strdup( p_access->psz_path );
870 while( *psz_parser && *psz_parser != '@' )
875 if( *psz_parser == '@' )
881 if ('T' == *psz_parser || 't' == *psz_parser )
884 i_track = (int)strtol( psz_parser, NULL, 10 );
885 i_track = i_track ? i_track : 1;
886 b_single_track = true;
890 /* No device/track given. Continue only when this plugin was
892 if( !p_this->b_force ) return VLC_EGENERIC;
894 psz_source = var_CreateGetString( p_this, "cd-audio" );
896 if( !psz_source || !*psz_source ) {
897 /* Scan for a CD-ROM drive with a CD-DA in it. */
899 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
901 if (NULL == cd_drives || NULL == cd_drives[0] ) {
903 _("libcdio couldn't find something with a CD-DA in it") );
904 if (cd_drives) cdio_free_device_list(cd_drives);
908 psz_source = strdup(cd_drives[0]);
909 cdio_free_device_list(cd_drives);
913 cdio_log_set_handler ( cdio_log_handler );
916 if( !(p_cdio = cdio_open( psz_source, DRIVER_UNKNOWN )) )
918 msg_Warn( p_access, "could not open %s", psz_source );
922 p_cdda = malloc( sizeof(cdda_data_t) );
925 msg_Err( p_access, "out of memory" );
929 memset( p_cdda, 0, sizeof(cdda_data_t) );
932 cddb_log_set_handler ( cddb_log_handler );
933 p_cdda->cddb.disc = NULL;
934 p_cdda->i_cddb_enabled =
935 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
938 p_cdda->b_header = VLC_FALSE;
939 p_cdda->p_cdio = p_cdio;
940 p_cdda->i_track = i_track;
941 p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
943 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
945 /* Set up p_access */
946 p_access->pf_read = NULL;
947 p_access->pf_block = CDDABlock;
948 p_access->pf_control = CDDAControl;
949 p_access->pf_seek = CDDASeek;
951 p_access->info.i_update = 0;
952 p_access->info.i_size = 0;
953 p_access->info.i_pos = 0;
954 p_access->info.b_eof = VLC_FALSE;
955 p_access->info.i_title = 0;
956 p_access->info.i_seekpoint = 0;
958 p_access->p_sys = (access_sys_t *) p_cdda;
960 /* We read the Table Of Content information */
961 i_rc = GetCDInfo( p_access, p_cdda );
962 if ( VLC_SUCCESS != i_rc ) goto error;
964 CDDAFixupPlaylist( p_access, p_cdda, psz_source, b_single_track );
966 /* Build a WAV header to put in front of the output data.
967 This gets sent back in the Block (read) routine.
969 memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
970 SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
971 SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
972 p_cdda->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
973 p_cdda->waveheader.Length = 0; /* we just don't know */
974 p_cdda->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
975 p_cdda->waveheader.SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
976 SetDWLE( &p_cdda->waveheader.SubChunkLength, 16);
977 SetWLE( &p_cdda->waveheader.Modus, 2);
978 SetDWLE( &p_cdda->waveheader.SampleFreq, CDDA_FREQUENCY_SAMPLE);
979 SetWLE( &p_cdda->waveheader.BytesPerSample,
980 2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
981 SetDWLE( &p_cdda->waveheader.BytesPerSec,
982 2*16/8 /*BytesPerSample*/ * CDDA_FREQUENCY_SAMPLE );
983 p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
984 p_cdda->waveheader.DataLength = 0; /* we just don't know */
987 var_Create( p_access, MODULE_STRING "-caching",
988 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
992 cdio_destroy( p_cdda->p_cdio );
1000 /*****************************************************************************
1001 * CDDAClose: closes cdda and frees any resources associded with it.
1002 *****************************************************************************/
1004 E_(CDDAClose)( vlc_object_t *p_this )
1006 access_t *p_access = (access_t *) p_this;
1007 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
1010 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
1012 /* Remove playlist titles */
1013 for( i = 0; i < p_cdda->i_tracks; i++ )
1015 vlc_input_title_Delete( p_cdda->p_title[i] );
1018 cdio_destroy( p_cdda->p_cdio );
1020 cdio_log_set_handler (uninit_log_handler);
1023 cddb_log_set_handler (uninit_log_handler);
1024 if (p_cdda->i_cddb_enabled)
1025 cddb_disc_destroy(p_cdda->cddb.disc);
1028 free( p_cdda->p_lsns );
1029 if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
1031 p_cdda_input = NULL;
1034 /*****************************************************************************
1035 * Control: The front-end or vlc engine calls here to ether get
1036 * information such as meta information or plugin capabilities or to
1037 * issue miscellaneous "set" requests.
1038 *****************************************************************************/
1039 static int CDDAControl( access_t *p_access, int i_query, va_list args )
1041 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
1045 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
1046 "query %d", i_query );
1050 /* Pass back a copy of meta information that was gathered when we
1051 during the Open/Initialize call.
1053 case ACCESS_GET_META:
1055 vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
1056 if ( p_cdda->p_meta ) {
1057 *pp_meta = vlc_meta_Duplicate( p_cdda->p_meta );
1058 dbg_print( INPUT_DBG_META, "%s", _("Meta copied") );
1060 msg_Warn( p_access, _("Tried to copy NULL meta info") );
1064 return VLC_EGENERIC;
1066 case ACCESS_CAN_SEEK:
1067 case ACCESS_CAN_FASTSEEK:
1068 case ACCESS_CAN_PAUSE:
1069 case ACCESS_CAN_CONTROL_PACE:
1071 vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
1072 *pb_bool = VLC_TRUE;
1077 case ACCESS_GET_MTU:
1078 pi_int = (int*)va_arg( args, int * );
1079 *pi_int = CDDA_DATA_ONCE;
1082 case ACCESS_GET_PTS_DELAY:
1084 int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
1085 *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
1086 * MILLISECONDS_PER_SEC;
1091 case ACCESS_SET_PAUSE_STATE:
1094 case ACCESS_GET_TITLE_INFO:
1095 { input_title_t ***ppp_title;
1096 ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
1097 pi_int = (int*)va_arg( args, int* );
1098 *((int*)va_arg( args, int* )) = 1; /* Title offset */
1100 /* Duplicate track info */
1101 *pi_int = p_cdda->i_tracks;
1102 *ppp_title = malloc(sizeof( input_title_t **) * p_cdda->i_tracks );
1104 if (!*ppp_title) return VLC_ENOMEM;
1106 for( i = 0; i < p_cdda->i_tracks; i++ )
1108 if ( p_cdda->p_title[i] )
1110 vlc_input_title_Duplicate( p_cdda->p_title[i] );
1115 case ACCESS_SET_TITLE:
1116 i = (int)va_arg( args, int );
1117 if( i != p_access->info.i_title )
1120 p_access->info.i_update |=
1121 INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1122 p_access->info.i_title = i;
1123 p_access->info.i_size = p_cdda->p_title[i]->i_size;
1124 p_access->info.i_pos = 0;
1126 /* Next sector to read */
1127 p_cdda->i_lsn = p_cdda->p_lsns[i];
1131 case ACCESS_SET_SEEKPOINT:
1132 case ACCESS_SET_PRIVATE_ID_STATE:
1133 return VLC_EGENERIC;
1135 msg_Warn( p_access, _("unimplemented query in control") );
1136 return VLC_EGENERIC;
1142 /*****************************************************************************
1145 Initialize information pertaining to the CD: the number of tracks,
1146 first track number, LSNs for each track and the leadout. The leadout
1147 information is stored after the last track. The LSN array is
1148 0-origin, same as p_access->info. Add first_track to get what track
1149 number this is on the CD. Note: libcdio uses the real track number.
1151 We return the VLC-type status, e.g. VLC_SUCCESS, VLC_ENOMEM, etc.
1152 *****************************************************************************/
1154 GetCDInfo( access_t *p_access, cdda_data_t *p_cdda )
1157 discmode_t discmode = CDIO_DISC_MODE_NO_INFO;
1159 p_cdda->i_tracks = cdio_get_num_tracks(p_cdda->p_cdio);
1160 p_cdda->i_first_track = cdio_get_first_track_num(p_cdda->p_cdio);
1162 discmode = cdio_get_discmode(p_cdda->p_cdio);
1164 case CDIO_DISC_MODE_CD_DA:
1165 case CDIO_DISC_MODE_CD_MIXED:
1166 /* These are possible for CD-DA */
1169 /* These are not possible for CD-DA */
1171 _("Disc seems not to be CD-DA. libcdio reports it is %s"),
1172 discmode2str[discmode]
1174 return VLC_EGENERIC;
1177 p_cdda->p_lsns = malloc( (p_cdda->i_tracks + 1) * sizeof(lsn_t) );
1179 if( p_cdda->p_lsns == NULL )
1181 msg_Err( p_access, "out of memory" );
1187 /* Fill the p_lsns structure with the track/sector matches.
1188 Note cdio_get_track_lsn when given num_tracks + 1 will return
1191 for( i = 0 ; i <= p_cdda->i_tracks ; i++ )
1193 (p_cdda->p_lsns)[ i ] =
1194 cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_first_track+i);