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 *****************************************************************************/
29 #include "callback.h" /* FIXME - reorganize callback.h, cdda.h better */
30 #include "cdda.h" /* private structures. Also #includes vlc things */
31 #include <vlc_playlist.h> /* Has to come *after* cdda.h */
34 #include <cdio/cdio.h>
35 #include <cdio/logging.h>
36 #include <cdio/cd_types.h>
40 /* #ifdef variables below are defined via config.h via #include vlc above. */
45 #ifdef HAVE_SYS_TYPES_H
46 #include <sys/types.h>
61 #define CDDA_MRL_PREFIX "cddax://"
63 /* Frequency of sample in bits per second. */
64 #define CDDA_FREQUENCY_SAMPLE 44100
66 /* FIXME: This variable is a hack. Would be nice to eliminate. */
67 access_t *p_cdda_input = NULL;
69 /*****************************************************************************
71 *****************************************************************************/
72 static block_t *CDDAReadBlocks( access_t * p_access );
73 static int CDDASeek( access_t * p_access, int64_t i_pos );
74 static int CDDAControl( access_t *p_access, int i_query,
76 static void CDDAMetaInfo( access_t *p_access );
77 static int CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
78 const char *psz_source,
79 vlc_bool_t b_single_track );
80 static void CDDACreatePlaylistItem(const access_t *p_access,
82 playlist_t *p_playlist,
84 char *psz_mrl, int psz_mrl_max,
85 const char *psz_source,
86 int playlist_operation,
89 static int GetCDInfo( access_t *p_access, cdda_data_t *p_cdda ) ;
94 /****************************************************************************
96 ****************************************************************************/
98 /* process messages that originate from libcdio. */
100 cdio_log_handler (cdio_log_level_t level, const char message[])
102 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
110 if (p_cdda->i_debug & INPUT_DBG_CDIO)
111 msg_Dbg( p_cdda_input, message);
114 msg_Warn( p_cdda_input, message);
117 case CDIO_LOG_ASSERT:
118 msg_Err( p_cdda_input, message);
121 msg_Warn( p_cdda_input, message,
122 "The above message had unknown cdio log level",
130 /*! This routine is called by libcddb routines on error.
131 Setup is done by init_input_plugin.
134 cddb_log_handler (cddb_log_level_t level, const char message[])
136 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
140 if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
141 /* Fall through if to warn case */
143 cdio_log_handler (level, message);
146 #endif /*HAVE_LIBCDDB*/
149 /*! This routine is when xine is not fully set up (before full initialization)
150 or is not around (before finalization).
153 uninit_log_handler (cdio_log_level_t level, const char message[])
155 cdda_data_t *p_cdda = NULL;
158 p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
163 if (!p_cdda || !(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
165 /* Fall through if to warn case */
167 fprintf(stderr, "WARN: %s\n", message);
170 fprintf(stderr, "ERROR: %s\n", message);
172 case CDIO_LOG_ASSERT:
173 fprintf(stderr, "ASSERT ERROR: %s\n", message);
176 fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
178 "The above message had unknown cdio log level",
182 /* gl_default_cdio_log_handler (level, message); */
185 /*****************************************************************************
186 * CDDAReadBlocks: reads a group of blocks from the CD-DA and returns
187 * an allocated pointer to the data. NULL is returned if no data
188 * read. It is also possible if we haven't read a RIFF header in which
189 * case one that we creaded during Open/Initialization is returned.
190 *****************************************************************************/
192 CDDAReadBlocks( access_t * p_access )
195 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
196 int i_blocks = p_cdda->i_blocks_per_read;
198 dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called %d",
201 /* Check end of file */
202 if( p_access->info.b_eof ) return NULL;
204 if( !p_cdda->b_header )
206 /* Return only the dummy RIFF header we created in Open/Init */
207 p_block = block_New( p_access, sizeof( WAVEHEADER ) );
208 memcpy( p_block->p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
209 p_cdda->b_header = VLC_TRUE;
213 /* Check end of track */
214 while( p_cdda->i_lsn >= p_cdda->p_lsns[p_access->info.i_title + 1] )
216 if( p_access->info.i_title + 1 >= p_cdda->i_tracks )
218 p_access->info.b_eof = VLC_TRUE;
222 p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE;
223 p_access->info.i_title++;
224 p_access->info.i_size =
225 p_cdda->p_title[p_access->info.i_title]->i_size;
226 p_access->info.i_pos = 0;
230 /* Possibly adjust i_blocks so we don't read past the end of a track. */
231 if( p_cdda->i_lsn + i_blocks >=
232 p_cdda->p_lsns[p_access->info.i_title + 1] )
234 i_blocks = p_cdda->p_lsns[p_access->info.i_title + 1 ] -
238 /* Do the actual reading */
239 p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW );
242 msg_Err( p_access, "Cannot get a new block of size: %i",
243 i_blocks * CDIO_CD_FRAMESIZE_RAW );
247 if( cdio_read_audio_sectors( p_cdda->p_cdio, p_block->p_buffer,
248 p_cdda->i_lsn, i_blocks) != 0 )
250 msg_Err( p_access, "could not read sector %lu",
251 (long unsigned int) p_cdda->i_lsn );
252 block_Release( p_block );
254 /* If we had problems above, assume the problem is with
255 the first sector of the read and set to skip it. In
256 the future libcdio may have cdparanoia support.
259 p_access->info.i_pos += CDIO_CD_FRAMESIZE_RAW;
263 p_cdda->i_lsn += i_blocks;
264 p_access->info.i_pos += p_block->i_buffer;
269 /****************************************************************************
270 * CDDASeek - change position for subsequent reads. For example, this
271 * can happen if the user moves a position slider bar in a GUI.
272 ****************************************************************************/
274 CDDASeek( access_t * p_access, int64_t i_pos )
276 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
278 p_cdda->i_lsn = p_cdda->p_lsns[p_access->info.i_title]
279 + (i_pos / CDIO_CD_FRAMESIZE_RAW);
280 p_access->info.i_pos = i_pos;
282 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
283 "lsn %lu, offset: %lld",
284 (long unsigned int) p_cdda->i_lsn, i_pos );
290 #define free_and_dup(var, val) \
291 if (var) free(var); \
292 if (val) var=strdup(val);
296 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
299 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
301 if (config_GetInt( p_access, MODULE_STRING "-cddb-enabled" )) {
303 cddb_conn_t *conn = cddb_new();
304 const CdIo *p_cdio = p_cdda->p_cdio;
307 cddb_log_set_handler (uninit_log_handler);
310 msg_Warn( p_access, "Unable to initialize libcddb" );
314 cddb_set_email_address( conn,
315 config_GetPsz( p_access,
316 MODULE_STRING "-cddb-email") );
318 cddb_set_server_name( conn,
319 config_GetPsz( p_access,
320 MODULE_STRING "-cddb-server") );
322 cddb_set_server_port(conn,
323 config_GetInt( p_access,
324 MODULE_STRING "-cddb-port") );
326 /* Set the location of the local CDDB cache directory.
327 The default location of this directory is */
329 if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
330 cddb_cache_disable(conn);
332 cddb_cache_set_dir(conn,
333 config_GetPsz( p_access,
334 MODULE_STRING "-cddb-cachedir") );
336 cddb_set_timeout(conn,
337 config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
340 if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" )) {
341 cddb_http_enable(conn);
343 cddb_http_disable(conn);
345 p_cdda->cddb.disc = cddb_disc_new();
346 if (!p_cdda->cddb.disc) {
347 msg_Err( p_access, "Unable to create CDDB disc structure." );
351 p_cdda->psz_mcn = cdio_get_mcn(p_cdio);
353 for(i = 1; i <= p_cdda->i_tracks; i++) {
354 cddb_track_t *t = cddb_track_new();
355 t->frame_offset = cdio_get_track_lba(p_cdio, i);
356 cddb_disc_add_track(p_cdda->cddb.disc, t);
359 p_cdda->cddb.disc->length =
360 cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
361 / CDIO_CD_FRAMES_PER_SEC;
363 if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
364 msg_Err( p_access, "CDDB disc ID calculation failed" );
368 i_matches = cddb_query(conn, p_cdda->cddb.disc);
371 msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
373 cddb_read(conn, p_cdda->cddb.disc);
375 if (p_cdda->i_debug & INPUT_DBG_CDDB)
376 cddb_disc_print(p_cdda->cddb.disc);
379 msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
387 #endif /*HAVE_LIBCDDB*/
389 #define add_meta_val(FIELD, VLC_META, VAL) \
390 if ( p_cdda->p_meta && VAL) { \
391 vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL ); \
392 dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL ); \
395 #define add_cddb_meta(FIELD, VLC_META) \
396 add_meta_val(FIELD, VLC_META, p_cdda->cddb.disc->FIELD);
398 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
401 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
402 p_cdda->cddb.disc->FIELD ); \
403 psz_buf[sizeof(psz_buf)-1] = '\0'; \
404 add_meta_val(FIELD, VLC_META, psz_buf); \
408 Gets and saves CDDA Meta Information. In the Control routine,
409 we handle Meta Information requests and basically copy what we've
412 static void CDDAMetaInfo( access_t *p_access )
414 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
417 if ( p_cdda && p_cdda->i_cddb_enabled ) {
419 GetCDDBInfo(p_access, p_cdda);
421 if ( p_cdda->cddb.disc ) {
423 p_cdda->p_meta = vlc_meta_New();
425 add_cddb_meta(title, VLC_META_CDDB_TITLE);
426 add_cddb_meta(artist, VLC_META_CDDB_ARTIST);
427 add_cddb_meta(genre, VLC_META_CDDB_GENRE);
428 add_cddb_meta(ext_data, VLC_META_CDDB_EXT_DATA);
430 add_cddb_meta_fmt(year, "%d", VLC_META_CDDB_YEAR);
431 add_cddb_meta_fmt(discid, "%x", VLC_META_CDDB_DISCID);
435 #endif /*HAVE_LIBCDDB*/
438 /* Adds a string-valued entry to the stream and media information if
439 the string is not null or the null string.
441 #define add_cddb_info_str(CATEGORY, TITLE, FIELD) \
442 if (FIELD && strlen(FIELD)) { \
443 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
444 _(TITLE), "%s", FIELD ); \
447 /* Adds a numeric-valued entry to the stream and media information */
448 #define add_cddb_info_val(CATEGORY, TITLE, FMT, FIELD) \
450 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
451 _(TITLE), FMT, FIELD ); \
454 #define add_cddb_disc_info_str(TITLE, FIELD) \
455 add_cddb_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
457 #define add_cddb_disc_info_val(TITLE, FMT, FIELD) \
458 add_cddb_info_val("Disc", TITLE, FMT, p_cdda->cddb.disc->FIELD)
460 /*#if UPDATE_TRACK_INFORMATION_FINISHED*/
463 track_t i_track = p_cdda->i_tracks;
464 char psz_buffer[MSTRTIME_MAX_SIZE];
466 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[0])
467 / CDIO_CD_FRAMES_PER_SEC;
469 dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
470 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
471 _("Disc"), _("Duration"), "%s",
472 secstotimestr( psz_buffer, i_duration ) );
475 if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
476 add_cddb_disc_info_str("Artist (CDDB)", artist);
477 add_cddb_disc_info_str("Genre (CDDB)", genre);
478 add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
479 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
480 add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
481 add_cddb_disc_info_str("Title (CDDB)", title);
482 add_cddb_info_str("Disc", "Category (CDDB)",
483 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
485 #endif /*HAVE_LIBCDDB*/
487 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ ) {
489 char track_str[TITLE_MAX];
491 (p_cdda->p_lsns[i_track+1] - p_cdda->p_lsns[i_track])
492 / CDIO_CD_FRAMES_PER_SEC;
493 snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
494 input_Control( p_cdda->p_input, INPUT_ADD_INFO, track_str,
496 secstotimestr( psz_buffer, i_duration ) );
499 if (p_cdda->i_cddb_enabled) {
500 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track);
502 add_cddb_info_str(track_str, "Artist (CDDB)", t->artist);
503 add_cddb_info_str(track_str, "Title (CDDB)", t->title);
504 add_cddb_info_str(track_str, "Extended Data (CDDB)", t->ext_data);
507 #endif /*HAVE_LIBCDDB*/
510 #endif /* UPDATE_TRACK_INFORMATION_FINISHED */
513 #define add_format_str_info(val) \
515 const char *str = val; \
520 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
523 saw_control_prefix = false; \
527 #define add_format_num_info(val, fmt) \
531 sprintf(num_str, fmt, val); \
532 len=strlen(num_str); \
534 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
537 saw_control_prefix = false; \
541 Take a format string and expand escape sequences, that is sequences that
542 begin with %, with information from the current CD.
543 The expanded string is returned. Here is a list of escape sequences:
545 %a : The album artist **
546 %A : The album information **
551 %m : The CD-DA Media Catalog Number (MCN)
552 %n : The number of tracks on the CD
553 %p : The artist/performer/composer in the track **
554 %T : The track number **
555 %s : Number of seconds in this track
557 %Y : The year 19xx or 20xx **
561 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
562 const char format_str[], const char *mrl, int i_track)
564 #define TEMP_STR_SIZE 256
565 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
566 static char temp_str[TEMP_STR_SIZE];
568 char * tp = temp_str;
569 vlc_bool_t saw_control_prefix = false;
570 size_t format_len = strlen(format_str);
572 memset(temp_str, 0, TEMP_STR_SIZE);
574 for (i=0; i<format_len; i++) {
576 if (!saw_control_prefix && format_str[i] != '%') {
577 *tp++ = format_str[i];
578 saw_control_prefix = false;
582 switch(format_str[i]) {
584 if (saw_control_prefix) {
587 saw_control_prefix = !saw_control_prefix;
591 if (!p_cdda->i_cddb_enabled) goto not_special;
592 if (p_cdda->cddb.disc)
593 add_format_str_info(p_cdda->cddb.disc->artist);
596 if (!p_cdda->i_cddb_enabled) goto not_special;
597 if (p_cdda->cddb.disc)
598 add_format_str_info(p_cdda->cddb.disc->title);
601 if (!p_cdda->i_cddb_enabled) goto not_special;
602 if (p_cdda->cddb.disc)
603 add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
606 if (!p_cdda->i_cddb_enabled) goto not_special;
607 if (p_cdda->cddb.disc)
608 add_format_str_info(p_cdda->cddb.disc->genre);
611 if (!p_cdda->i_cddb_enabled) goto not_special;
612 if (p_cdda->cddb.disc)
613 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
616 if (!p_cdda->i_cddb_enabled) goto not_special;
617 if (p_cdda->cddb.disc)
618 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
621 if (p_cdda && p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
622 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
624 if (t != NULL && t->title != NULL)
625 add_format_str_info(t->title);
626 } else goto not_special;
629 if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
630 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
632 if (t != NULL && t->artist != NULL)
633 add_format_str_info(t->artist);
634 } else goto not_special;
637 if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
638 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
640 if (t != NULL && t->ext_data != NULL)
641 add_format_str_info(t->ext_data);
642 } else goto not_special;
647 add_format_str_info(mrl);
651 add_format_str_info(p_cdda->psz_mcn);
655 add_format_num_info(p_cdda->i_tracks, "%d");
659 if (p_cdda->i_cddb_enabled) {
660 char psz_buffer[MSTRTIME_MAX_SIZE];
662 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
663 / CDIO_CD_FRAMES_PER_SEC;
664 add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
665 } else goto not_special;
669 add_format_num_info(i_track, "%02d");
676 *tp++ = format_str[i];
677 saw_control_prefix = false;
680 return strdup(temp_str);
683 /* Adds a string-valued entry to the playlist information under "Disc"
684 if the string is not null or the null string.
686 #define add_playlist_disc_info_str(TITLE, FIELD) \
687 if (FIELD && strlen(FIELD)) { \
688 playlist_ItemAddInfo( p_item, _("Disc"), _(TITLE), \
693 CDDACreatePlaylistItem(const access_t *p_access, cdda_data_t *p_cdda,
694 playlist_t *p_playlist, track_t i_track,
695 char *psz_mrl, int psz_mrl_max,
696 const char *psz_source, int playlist_operation,
700 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
701 * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
704 char *config_varname = MODULE_STRING "-title-format";
705 playlist_item_t *p_item;
708 if (p_cdda->i_cddb_enabled) {
709 config_varname = MODULE_STRING "-cddb-title-format";
711 #endif /*HAVE_LIBCDDB*/
713 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
714 CDDA_MRL_PREFIX, psz_source, i_track);
716 psz_title = CDDAFormatStr(p_access, p_cdda,
717 config_GetPsz( p_access, config_varname ),
720 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
721 psz_mrl, psz_title, (long int) i_duration / 1000000 , i_pos );
722 playlist_AddExt( p_playlist, psz_mrl, psz_title, playlist_operation,
723 i_pos, i_duration , NULL, 0);
725 if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
727 vlc_mutex_lock( &p_playlist->object_lock );
728 p_item = playlist_ItemGetByPos( p_playlist, i_pos );
729 vlc_mutex_unlock( &p_playlist->object_lock );
733 vlc_mutex_lock( &p_item->input.lock );
736 CDDAFormatStr( p_access, p_cdda,
737 config_GetPsz( p_access, MODULE_STRING "-title-format" ),
740 playlist_ItemAddInfo( p_item , _("Disc"),_("Title"), psz_disc_info);
743 if (p_cdda->i_cddb_enabled) {
744 const char *psz_general_cat = _("Disc");
745 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
747 add_playlist_disc_info_str("Disc Album (CDDB)",
748 p_cdda->cddb.disc->title);
749 add_playlist_disc_info_str("Disc Artist(s) (CDDB)",
750 p_cdda->cddb.disc->artist);
751 add_playlist_disc_info_str("Disc Category (CDDB)",
752 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
753 add_playlist_disc_info_str("Disc Genre (CDDB)",
754 p_cdda->cddb.disc->genre);
755 if ( p_cdda->cddb.disc->discid ) {
756 playlist_ItemAddInfo( p_item, psz_general_cat, _("Disc ID (CDDB)"),
757 "%x", p_cdda->cddb.disc->discid );
759 if (p_cdda->cddb.disc->year != 0) {
760 playlist_ItemAddInfo( p_item, psz_general_cat,
761 _("Year"), "%5d", p_cdda->cddb.disc->year );
766 add_playlist_disc_info_str("Track Artist (CDDB)",
769 add_playlist_disc_info_str("Track Title (CDDB)",
773 #endif /*HAVE_LIBCDDB*/
775 vlc_mutex_unlock( &p_item->input.lock );
779 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
780 const char *psz_source, vlc_bool_t b_single_track )
783 playlist_t * p_playlist;
785 unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
786 strlen("@T") + strlen("100") + 1;
789 p_cdda->i_cddb_enabled =
790 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
791 if( b_single_track && !p_cdda->i_cddb_enabled ) return VLC_SUCCESS;
793 if( b_single_track ) return VLC_SUCCESS;
796 psz_mrl = malloc( psz_mrl_max );
798 if( psz_mrl == NULL )
800 msg_Warn( p_access, "out of memory" );
804 p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
808 msg_Warn( p_access, "can't find playlist" );
813 CDDAMetaInfo(p_access);
815 if (b_single_track) {
816 /* May fill out more information when the playlist user interface becomes
819 track_t i_track = p_cdda->i_track;
821 input_title_t *t = p_cdda->p_title[i_track-1] = vlc_input_title_New();
823 asprintf( &t->psz_name, _("Track %i"), i_track );
824 t->i_size = ( p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1] ) *
825 (int64_t)CDIO_CD_FRAMESIZE_RAW;
827 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
828 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i_track,
829 psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
830 p_playlist->i_index);
831 p_access->info.i_size =
832 ( p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1] ) *
833 (int64_t)CDIO_CD_FRAMESIZE_RAW;
837 for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
839 input_title_t *t = p_cdda->p_title[i-1] = vlc_input_title_New();
841 asprintf( &t->psz_name, _("Track %i"), i );
842 t->i_size = ( p_cdda->p_lsns[i] - p_cdda->p_lsns[i-1] ) *
843 (int64_t)CDIO_CD_FRAMESIZE_RAW;
845 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
846 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i, psz_mrl,
847 psz_mrl_max, psz_source, PLAYLIST_APPEND,
850 p_access->info.i_size =
851 (p_cdda->p_lsns[p_cdda->i_tracks] - p_cdda->p_lsns[0]) *
852 (int64_t)CDIO_CD_FRAMESIZE_RAW;
858 /****************************************************************************
860 ****************************************************************************/
862 /*****************************************************************************
863 * Open: open cdda device or image file and initialize structures
864 * for subsequent operations.
865 *****************************************************************************/
867 E_(CDDAOpen)( vlc_object_t *p_this )
869 access_t *p_access = (access_t*)p_this;
870 char * psz_source = NULL;
874 vlc_bool_t b_single_track = false;
875 int i_rc = VLC_EGENERIC;
877 p_access->p_sys = NULL;
879 /* Set where to log errors messages from libcdio. */
880 p_cdda_input = p_access;
882 /* parse the options passed in command line : */
884 if( p_access->psz_path && *p_access->psz_path )
886 char *psz_parser = psz_source = strdup( p_access->psz_path );
888 while( *psz_parser && *psz_parser != '@' )
893 if( *psz_parser == '@' )
899 if ('T' == *psz_parser || 't' == *psz_parser )
902 i_track = (int)strtol( psz_parser, NULL, 10 );
903 i_track = i_track ? i_track : 1;
904 b_single_track = true;
908 if (!psz_source || !*psz_source)
910 /* No device/track given. Continue only when this plugin was
912 if( !p_this->b_force ) return VLC_EGENERIC;
914 psz_source = var_CreateGetString( p_this, "cd-audio" );
916 if( !psz_source || !*psz_source ) {
917 /* Scan for a CD-ROM drive with a CD-DA in it. */
919 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
921 if (NULL == cd_drives || NULL == cd_drives[0] ) {
923 "libcdio couldn't find something with a CD-DA in it" );
924 if (cd_drives) cdio_free_device_list(cd_drives);
928 psz_source = strdup(cd_drives[0]);
929 cdio_free_device_list(cd_drives);
933 cdio_log_set_handler ( cdio_log_handler );
936 if( !(p_cdio = cdio_open( psz_source, DRIVER_UNKNOWN )) )
938 msg_Warn( p_access, "could not open %s", psz_source );
942 p_cdda = malloc( sizeof(cdda_data_t) );
945 msg_Err( p_access, "out of memory" );
949 memset( p_cdda, 0, sizeof(cdda_data_t) );
952 cddb_log_set_handler ( cddb_log_handler );
953 p_cdda->cddb.disc = NULL;
954 p_cdda->i_cddb_enabled =
955 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
958 p_cdda->b_header = VLC_FALSE;
959 p_cdda->p_cdio = p_cdio;
960 p_cdda->i_track = i_track;
961 p_cdda->i_debug = config_GetInt(p_this, MODULE_STRING "-debug");
962 p_cdda->i_blocks_per_read
963 = config_GetInt(p_this, MODULE_STRING "-blocks-per-read");
965 p_cdda->p_input = vlc_object_find( p_access, VLC_OBJECT_INPUT,
968 if (0 == p_cdda->i_blocks_per_read)
969 p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
971 if ( p_cdda->i_blocks_per_read < MIN_BLOCKS_PER_READ
972 || p_cdda->i_blocks_per_read > MAX_BLOCKS_PER_READ ) {
973 msg_Warn( p_cdda_input,
974 "Number of blocks (%d) has to be between %d and %d. "
976 p_cdda->i_blocks_per_read,
977 MIN_BLOCKS_PER_READ, MAX_BLOCKS_PER_READ,
978 DEFAULT_BLOCKS_PER_READ );
979 p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
983 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
985 /* Set up p_access */
986 p_access->pf_read = NULL;
987 p_access->pf_block = CDDAReadBlocks;
988 p_access->pf_control = CDDAControl;
989 p_access->pf_seek = CDDASeek;
991 p_access->info.i_size = 0;
993 p_access->info.i_update = 0;
994 p_access->info.b_eof = VLC_FALSE;
995 p_access->info.i_title = 0;
996 p_access->info.i_seekpoint = 0;
998 p_access->p_sys = (access_sys_t *) p_cdda;
1000 /* We read the Table Of Content information */
1001 i_rc = GetCDInfo( p_access, p_cdda );
1002 if ( VLC_SUCCESS != i_rc ) goto error;
1004 CDDAFixupPlaylist( p_access, p_cdda, psz_source, b_single_track );
1006 /* Build a WAV header to put in front of the output data.
1007 This gets sent back in the Block (read) routine.
1009 memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
1010 SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
1011 SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
1012 p_cdda->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
1013 p_cdda->waveheader.Length = 0; /* we just don't know */
1014 p_cdda->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
1015 p_cdda->waveheader.SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
1016 SetDWLE( &p_cdda->waveheader.SubChunkLength, 16);
1017 SetWLE( &p_cdda->waveheader.Modus, 2);
1018 SetDWLE( &p_cdda->waveheader.SampleFreq, CDDA_FREQUENCY_SAMPLE);
1019 SetWLE( &p_cdda->waveheader.BytesPerSample,
1020 2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
1021 SetDWLE( &p_cdda->waveheader.BytesPerSec,
1022 2*16/8 /*BytesPerSample*/ * CDDA_FREQUENCY_SAMPLE );
1023 p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
1024 p_cdda->waveheader.DataLength = 0; /* we just don't know */
1027 var_Create( p_access, MODULE_STRING "-caching",
1028 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
1032 cdio_destroy( p_cdda->p_cdio );
1040 /*****************************************************************************
1041 * CDDAClose: closes cdda and frees any resources associded with it.
1042 *****************************************************************************/
1044 E_(CDDAClose)( vlc_object_t *p_this )
1046 access_t *p_access = (access_t *) p_this;
1047 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
1050 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
1052 /* Remove playlist titles */
1053 for( i = 0; i < p_cdda->i_tracks; i++ )
1055 vlc_input_title_Delete( p_cdda->p_title[i] );
1058 cdio_destroy( p_cdda->p_cdio );
1060 cdio_log_set_handler (uninit_log_handler);
1063 cddb_log_set_handler (uninit_log_handler);
1064 if (p_cdda->i_cddb_enabled)
1065 cddb_disc_destroy(p_cdda->cddb.disc);
1068 free( p_cdda->p_lsns );
1069 if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
1071 p_cdda_input = NULL;
1074 /*****************************************************************************
1075 * Control: The front-end or vlc engine calls here to ether get
1076 * information such as meta information or plugin capabilities or to
1077 * issue miscellaneous "set" requests.
1078 *****************************************************************************/
1079 static int CDDAControl( access_t *p_access, int i_query, va_list args )
1081 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
1085 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
1086 "query %d", i_query );
1090 /* Pass back a copy of meta information that was gathered when we
1091 during the Open/Initialize call.
1093 case ACCESS_GET_META:
1095 vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
1096 if ( p_cdda->p_meta ) {
1097 *pp_meta = vlc_meta_Duplicate( p_cdda->p_meta );
1098 dbg_print( INPUT_DBG_META, "%s", "Meta copied" );
1100 msg_Warn( p_access, "tried to copy NULL meta info" );
1104 return VLC_EGENERIC;
1106 case ACCESS_CAN_SEEK:
1107 case ACCESS_CAN_FASTSEEK:
1108 case ACCESS_CAN_PAUSE:
1109 case ACCESS_CAN_CONTROL_PACE:
1111 vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
1112 *pb_bool = VLC_TRUE;
1117 case ACCESS_GET_MTU:
1118 pi_int = (int*)va_arg( args, int * );
1119 *pi_int = p_cdda-> i_blocks_per_read * CDIO_CD_FRAMESIZE_RAW;
1122 case ACCESS_GET_PTS_DELAY:
1124 int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
1125 *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
1126 * MILLISECONDS_PER_SEC;
1131 case ACCESS_SET_PAUSE_STATE:
1134 case ACCESS_GET_TITLE_INFO:
1135 { input_title_t ***ppp_title;
1136 ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
1137 pi_int = (int*)va_arg( args, int* );
1138 *((int*)va_arg( args, int* )) = 1; /* Title offset */
1140 /* Duplicate track info */
1141 *pi_int = p_cdda->i_tracks;
1142 *ppp_title = malloc(sizeof( input_title_t **) * p_cdda->i_tracks );
1144 if (!*ppp_title) return VLC_ENOMEM;
1146 for( i = 0; i < p_cdda->i_tracks; i++ )
1148 if ( p_cdda->p_title[i] )
1150 vlc_input_title_Duplicate( p_cdda->p_title[i] );
1155 case ACCESS_SET_TITLE:
1156 i = (int)va_arg( args, int );
1157 if( i != p_access->info.i_title )
1160 p_access->info.i_update |=
1161 INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1162 p_access->info.i_title = i;
1163 p_access->info.i_size = p_cdda->p_title[i]->i_size;
1164 p_access->info.i_pos = 0;
1166 /* Next sector to read */
1167 p_cdda->i_lsn = p_cdda->p_lsns[i];
1171 case ACCESS_SET_SEEKPOINT:
1172 case ACCESS_SET_PRIVATE_ID_STATE:
1173 return VLC_EGENERIC;
1176 msg_Warn( p_access, "unimplemented query in control" );
1177 return VLC_EGENERIC;
1183 /*****************************************************************************
1186 Initialize information pertaining to the CD: the number of tracks,
1187 first track number, LSNs for each track and the leadout. The leadout
1188 information is stored after the last track. The LSN array is
1189 0-origin, same as p_access->info. Add first_track to get what track
1190 number this is on the CD. Note: libcdio uses the real track number.
1192 On input we assume p_cdda->p_cdio and p_cdda->i_track have been set.
1194 We return the VLC-type status, e.g. VLC_SUCCESS, VLC_ENOMEM, etc.
1195 *****************************************************************************/
1197 GetCDInfo( access_t *p_access, cdda_data_t *p_cdda )
1200 discmode_t discmode = CDIO_DISC_MODE_NO_INFO;
1202 p_cdda->i_tracks = cdio_get_num_tracks(p_cdda->p_cdio);
1203 p_cdda->i_first_track = cdio_get_first_track_num(p_cdda->p_cdio);
1205 discmode = cdio_get_discmode(p_cdda->p_cdio);
1207 case CDIO_DISC_MODE_CD_DA:
1208 case CDIO_DISC_MODE_CD_MIXED:
1209 /* These are possible for CD-DA */
1212 /* These are not possible for CD-DA */
1214 "Disc seems not to be CD-DA. libcdio reports it is %s",
1215 discmode2str[discmode]
1217 return VLC_EGENERIC;
1220 p_cdda->p_lsns = malloc( (p_cdda->i_tracks + 1) * sizeof(lsn_t) );
1222 if( p_cdda->p_lsns == NULL )
1224 msg_Err( p_access, "out of memory" );
1229 /* Fill the p_lsns structure with the track/sector matches.
1230 Note cdio_get_track_lsn when given num_tracks + 1 will return
1233 for( i = 0 ; i <= p_cdda->i_tracks ; i++ )
1235 (p_cdda->p_lsns)[ i ] =
1236 cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_first_track+i);
1239 /* Set reading start LSN. */
1240 p_cdda->i_lsn = p_cdda->p_lsns[p_cdda->i_track - p_cdda->i_first_track];