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;
106 if (p_cdda->i_debug & INPUT_DBG_CDIO)
107 msg_Dbg( p_cdda_input, message);
110 msg_Warn( p_cdda_input, message);
113 case CDIO_LOG_ASSERT:
114 msg_Err( p_cdda_input, message);
117 msg_Warn( p_cdda_input, message,
118 _("The above message had unknown cdio log level"),
126 /*! This routine is called by libcddb routines on error.
127 Setup is done by init_input_plugin.
130 cddb_log_handler (cddb_log_level_t level, const char message[])
132 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
136 if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
137 /* Fall through if to warn case */
139 cdio_log_handler (level, message);
142 #endif /*HAVE_LIBCDDB*/
145 /*! This routine is when xine is not fully set up (before full initialization)
146 or is not around (before finalization).
149 uninit_log_handler (cdio_log_level_t level, const char message[])
151 cdda_data_t *p_cdda = NULL;
154 p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
159 if (!p_cdda || !(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
161 /* Fall through if to warn case */
163 fprintf(stderr, "WARN: %s\n", message);
166 fprintf(stderr, "ERROR: %s\n", message);
168 case CDIO_LOG_ASSERT:
169 fprintf(stderr, "ASSERT ERROR: %s\n", message);
172 fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
174 _("The above message had unknown cdio log level"),
178 /* gl_default_cdio_log_handler (level, message); */
181 /*****************************************************************************
182 * CDDAReadBlocks: reads a group of blocks from the CD-DA and returns
183 * an allocated pointer to the data. NULL is returned if no data
184 * read. It is also possible if we haven't read a RIFF header in which
185 * case one that we creaded during Open/Initialization is returned.
186 *****************************************************************************/
188 CDDAReadBlocks( access_t * p_access )
191 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
192 int i_blocks = p_cdda->i_blocks_per_read;
194 dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called %d",
197 /* Check end of file */
198 if( p_access->info.b_eof ) return NULL;
200 if( !p_cdda->b_header )
202 /* Return only the dummy RIFF header we created in Open/Init */
203 p_block = block_New( p_access, sizeof( WAVEHEADER ) );
204 memcpy( p_block->p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
205 p_cdda->b_header = VLC_TRUE;
209 /* Check end of track */
210 while( p_cdda->i_lsn >= p_cdda->p_lsns[p_access->info.i_title + 1] )
212 if( p_access->info.i_title + 1 >= p_cdda->i_tracks )
214 p_access->info.b_eof = VLC_TRUE;
218 p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE;
219 p_access->info.i_title++;
220 p_access->info.i_size =
221 p_cdda->p_title[p_access->info.i_title]->i_size;
222 p_access->info.i_pos = 0;
226 /* Possibly adjust i_blocks so we don't read past the end of a track. */
227 if( p_cdda->i_lsn + i_blocks >=
228 p_cdda->p_lsns[p_access->info.i_title + 1] )
230 i_blocks = p_cdda->p_lsns[p_access->info.i_title + 1 ] -
234 /* Do the actual reading */
235 p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW );
238 msg_Err( p_access, _("Cannot get a new block of size: %i"),
239 i_blocks * CDIO_CD_FRAMESIZE_RAW );
243 if( cdio_read_audio_sectors( p_cdda->p_cdio, p_block->p_buffer,
244 p_cdda->i_lsn, i_blocks) != 0 )
246 msg_Err( p_access, _("could not read sector %lu"),
247 (long unsigned int) p_cdda->i_lsn );
248 block_Release( p_block );
250 /* If we had problems above, assume the problem is with
251 the first sector of the read and set to skip it. In
252 the future libcdio may have cdparanoia support.
255 p_access->info.i_pos += CDIO_CD_FRAMESIZE_RAW;
259 p_cdda->i_lsn += i_blocks;
260 p_access->info.i_pos += p_block->i_buffer;
265 /****************************************************************************
266 * CDDASeek - change position for subsequent reads. For example, this
267 * can happen if the user moves a position slider bar in a GUI.
268 ****************************************************************************/
270 CDDASeek( access_t * p_access, int64_t i_pos )
272 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
274 p_cdda->i_lsn = p_cdda->p_lsns[p_access->info.i_title]
275 + (i_pos / CDIO_CD_FRAMESIZE_RAW);
276 p_access->info.i_pos = i_pos;
278 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
279 "lsn %lu, offset: %lld",
280 (long unsigned int) p_cdda->i_lsn, i_pos );
286 #define free_and_dup(var, val) \
287 if (var) free(var); \
288 if (val) var=strdup(val);
292 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
295 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
297 if (config_GetInt( p_access, MODULE_STRING "-cddb-enabled" )) {
299 cddb_conn_t *conn = cddb_new();
300 const CdIo *p_cdio = p_cdda->p_cdio;
303 cddb_log_set_handler (uninit_log_handler);
306 msg_Warn( p_access, _("Unable to initialize libcddb") );
310 cddb_set_email_address( conn,
311 config_GetPsz( p_access,
312 MODULE_STRING "-cddb-email") );
314 cddb_set_server_name( conn,
315 config_GetPsz( p_access,
316 MODULE_STRING "-cddb-server") );
318 cddb_set_server_port(conn,
319 config_GetInt( p_access,
320 MODULE_STRING "-cddb-port") );
322 /* Set the location of the local CDDB cache directory.
323 The default location of this directory is */
325 if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
326 cddb_cache_disable(conn);
328 cddb_cache_set_dir(conn,
329 config_GetPsz( p_access,
330 MODULE_STRING "-cddb-cachedir") );
332 cddb_set_timeout(conn,
333 config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
336 if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" )) {
337 cddb_http_enable(conn);
339 cddb_http_disable(conn);
341 p_cdda->cddb.disc = cddb_disc_new();
342 if (!p_cdda->cddb.disc) {
343 msg_Err( p_access, _("Unable to create CDDB disc structure.") );
347 p_cdda->psz_mcn = cdio_get_mcn(p_cdio);
349 for(i = 1; i <= p_cdda->i_tracks; i++) {
350 cddb_track_t *t = cddb_track_new();
351 t->frame_offset = cdio_get_track_lba(p_cdio, i);
352 cddb_disc_add_track(p_cdda->cddb.disc, t);
355 p_cdda->cddb.disc->length =
356 cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
357 / CDIO_CD_FRAMES_PER_SEC;
359 if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
360 msg_Err( p_access, _("CDDB disc ID calculation failed") );
364 i_matches = cddb_query(conn, p_cdda->cddb.disc);
367 msg_Warn( p_access, _("Found %d matches in CDDB. Using first one."),
369 cddb_read(conn, p_cdda->cddb.disc);
371 if (p_cdda->i_debug & INPUT_DBG_CDDB)
372 cddb_disc_print(p_cdda->cddb.disc);
375 msg_Warn( p_access, _("CDDB error: %s"), cddb_error_str(errno));
383 #endif /*HAVE_LIBCDDB*/
385 #define add_meta_val(FIELD, VLC_META, VAL) \
386 if ( p_cdda->p_meta && VAL) { \
387 vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL ); \
388 dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL ); \
391 #define add_cddb_meta(FIELD, VLC_META) \
392 add_meta_val(FIELD, VLC_META, p_cdda->cddb.disc->FIELD);
394 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
397 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
398 p_cdda->cddb.disc->FIELD ); \
399 psz_buf[sizeof(psz_buf)-1] = '\0'; \
400 add_meta_val(FIELD, VLC_META, psz_buf); \
404 Gets and saves CDDA Meta Information. In the Control routine,
405 we handle Meta Information requests and basically copy what we've
408 static void CDDAMetaInfo( access_t *p_access )
410 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
413 if ( p_cdda && p_cdda->i_cddb_enabled ) {
415 GetCDDBInfo(p_access, p_cdda);
417 if ( p_cdda->cddb.disc ) {
419 p_cdda->p_meta = vlc_meta_New();
421 add_cddb_meta(title, VLC_META_CDDB_TITLE);
422 add_cddb_meta(artist, VLC_META_CDDB_ARTIST);
423 add_cddb_meta(genre, VLC_META_CDDB_GENRE);
424 add_cddb_meta(ext_data, VLC_META_CDDB_EXT_DATA);
426 add_cddb_meta_fmt(year, "%d", VLC_META_CDDB_YEAR);
427 add_cddb_meta_fmt(discid, "%x", VLC_META_CDDB_DISCID);
431 #endif /*HAVE_LIBCDDB*/
434 #if UPDATE_TRACK_INFORMATION_FINISHED
436 track_t i_track = p_cdda->i_tracks;
437 char psz_buffer[MSTRTIME_MAX_SIZE];
439 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[0])
440 / CDIO_CD_FRAMES_PER_SEC;
442 dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
443 input_Control( p_access, INPUT_ADD_INFO, _("General"), _("Duration"), "%s",
444 secstotimestr( psz_buffer, i_duration ) );
446 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ ) {
447 char track_str[TITLE_MAX];
449 (p_cdda->p_lsns[i_track+1] - p_cdda->p_lsns[i_track])
450 / CDIO_CD_FRAMES_PER_SEC;
451 snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
452 input_Control( p_access, INPUT_ADD_INFO, track_str, _("Duration"), "%s",
453 secstotimestr( psz_buffer, i_duration ) );
456 if (p_cdda->i_cddb_enabled) {
457 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
460 if ( t->artist != NULL && strlen(t->artist) ) {
461 input_Control( p_access, INPUT_ADD_INFO, track_str,
462 _("Artist"), "%s", t->artist );
464 if ( t->title != NULL && strlen(t->title) ) {
465 input_Control( p_access, INPUT_ADD_INFO, track_str,
466 _("Title"), "%s", t->title );
468 if ( t->ext_data != NULL && strlen(t->ext_data) ) {
469 input_Control( p_access, INPUT_ADD_INFO, track_str,
470 _("Extended Data"), "%s", t->ext_data );
474 #endif /*HAVE_LIBCDDB*/
477 #endif /* UPDATE_TRACK_INFORMATION_FINISHED */
480 #define add_format_str_info(val) \
482 const char *str = val; \
487 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
490 saw_control_prefix = false; \
494 #define add_format_num_info(val, fmt) \
498 sprintf(num_str, fmt, val); \
499 len=strlen(num_str); \
501 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
504 saw_control_prefix = false; \
508 Take a format string and expand escape sequences, that is sequences that
509 begin with %, with information from the current CD.
510 The expanded string is returned. Here is a list of escape sequences:
512 %a : The album artist **
513 %A : The album information **
518 %m : The CD-DA Media Catalog Number (MCN)
519 %n : The number of tracks on the CD
520 %p : The artist/performer/composer in the track **
521 %T : The track number **
522 %s : Number of seconds in this track
524 %Y : The year 19xx or 20xx **
528 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
529 const char format_str[], const char *mrl, int i_track)
531 #define TEMP_STR_SIZE 256
532 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
533 static char temp_str[TEMP_STR_SIZE];
535 char * tp = temp_str;
536 vlc_bool_t saw_control_prefix = false;
537 size_t format_len = strlen(format_str);
539 memset(temp_str, 0, TEMP_STR_SIZE);
541 for (i=0; i<format_len; i++) {
543 if (!saw_control_prefix && format_str[i] != '%') {
544 *tp++ = format_str[i];
545 saw_control_prefix = false;
549 switch(format_str[i]) {
551 if (saw_control_prefix) {
554 saw_control_prefix = !saw_control_prefix;
558 if (!p_cdda->i_cddb_enabled) goto not_special;
559 if (p_cdda->cddb.disc)
560 add_format_str_info(p_cdda->cddb.disc->artist);
563 if (!p_cdda->i_cddb_enabled) goto not_special;
564 if (p_cdda->cddb.disc)
565 add_format_str_info(p_cdda->cddb.disc->title);
568 if (!p_cdda->i_cddb_enabled) goto not_special;
569 if (p_cdda->cddb.disc)
570 add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
573 if (!p_cdda->i_cddb_enabled) goto not_special;
574 if (p_cdda->cddb.disc)
575 add_format_str_info(p_cdda->cddb.disc->genre);
578 if (!p_cdda->i_cddb_enabled) goto not_special;
579 if (p_cdda->cddb.disc)
580 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
583 if (!p_cdda->i_cddb_enabled) goto not_special;
584 if (p_cdda->cddb.disc)
585 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
588 if (p_cdda && p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
589 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
591 if (t != NULL && t->title != NULL)
592 add_format_str_info(t->title);
593 } else goto not_special;
596 if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
597 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
599 if (t != NULL && t->artist != NULL)
600 add_format_str_info(t->artist);
601 } else goto not_special;
604 if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
605 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
607 if (t != NULL && t->ext_data != NULL)
608 add_format_str_info(t->ext_data);
609 } else goto not_special;
614 add_format_str_info(mrl);
618 add_format_str_info(p_cdda->psz_mcn);
622 add_format_num_info(p_cdda->i_tracks, "%d");
626 if (p_cdda->i_cddb_enabled) {
627 char psz_buffer[MSTRTIME_MAX_SIZE];
629 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
630 / CDIO_CD_FRAMES_PER_SEC;
631 add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
632 } else goto not_special;
636 add_format_num_info(i_track, "%02d");
643 *tp++ = format_str[i];
644 saw_control_prefix = false;
647 return strdup(temp_str);
651 CDDACreatePlaylistItem(const access_t *p_access, cdda_data_t *p_cdda,
652 playlist_t *p_playlist, track_t i_track,
653 char *psz_mrl, int psz_mrl_max,
654 const char *psz_source, int playlist_operation,
658 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
659 * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
662 char *config_varname = MODULE_STRING "-title-format";
663 playlist_item_t *p_item;
666 if (p_cdda->i_cddb_enabled) {
667 config_varname = MODULE_STRING "-cddb-title-format";
669 #endif /*HAVE_LIBCDDB*/
671 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
672 CDDA_MRL_PREFIX, psz_source, i_track);
674 p_title = CDDAFormatStr(p_access, p_cdda,
675 config_GetPsz( p_access, config_varname ),
678 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
679 psz_mrl, p_title, (long int) i_duration / 1000000 , i_pos );
680 playlist_AddExt( p_playlist, psz_mrl, p_title, playlist_operation,
681 i_pos, i_duration , NULL, 0);
683 if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
685 vlc_mutex_lock( &p_playlist->object_lock );
686 p_item = playlist_ItemGetByPos( p_playlist, i_pos );
687 vlc_mutex_unlock( &p_playlist->object_lock );
691 vlc_mutex_lock( &p_item->input.lock );
694 CDDAFormatStr( p_access, p_cdda,
695 config_GetPsz( p_access, MODULE_STRING "-author-format" ),
698 playlist_ItemAddInfo( p_item , _("General"),_("Author"), p_author);
701 if (p_cdda->i_cddb_enabled) {
702 const char *psz_general_cat = _("General");
704 playlist_ItemAddInfo( p_item, psz_general_cat, _("Album"),
705 "%s", p_cdda->cddb.disc->title);
706 playlist_ItemAddInfo( p_item, psz_general_cat, _("Disc Artist(s)"),
707 "%s", p_cdda->cddb.disc->artist);
708 playlist_ItemAddInfo( p_item, psz_general_cat,
709 _("CDDB Disc Category"),
710 "%s", CDDB_CATEGORY[p_cdda->cddb.disc->category]);
711 playlist_ItemAddInfo( p_item, psz_general_cat, _("Genre"),
712 "%s", p_cdda->cddb.disc->genre);
713 if ( p_cdda->cddb.disc->discid ) {
714 playlist_ItemAddInfo( p_item, psz_general_cat, _("CDDB Disc ID"),
715 "%x", p_cdda->cddb.disc->discid );
717 if (p_cdda->cddb.disc->year != 0) {
718 playlist_ItemAddInfo( p_item, psz_general_cat,
719 _("Year"), "%5d", p_cdda->cddb.disc->year );
722 if (p_cdda->i_cddb_enabled) {
723 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
725 if (t != NULL && t->artist != NULL) {
726 playlist_ItemAddInfo( p_item, psz_general_cat,
727 _("Track Artist"), "%s", t->artist );
728 playlist_ItemAddInfo( p_item , psz_general_cat,
729 _("Track Title"), "%s", t->title );
734 #endif /*HAVE_LIBCDDB*/
736 vlc_mutex_unlock( &p_item->input.lock );
740 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
741 const char *psz_source, vlc_bool_t b_single_track )
744 playlist_t * p_playlist;
746 unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
747 strlen("@T") + strlen("100") + 1;
750 p_cdda->i_cddb_enabled =
751 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
752 if( b_single_track && !p_cdda->i_cddb_enabled ) return 0;
754 if( b_single_track ) return VLC_SUCCESS;
757 psz_mrl = malloc( psz_mrl_max );
759 if( psz_mrl == NULL )
761 msg_Warn( p_access, "out of memory" );
765 p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
769 msg_Warn( p_access, "can't find playlist" );
774 CDDAMetaInfo(p_access);
776 if (b_single_track) {
777 /* May fill out more information when the playlist user interface becomes
780 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, p_cdda->i_track,
781 psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
782 p_playlist->i_index);
785 for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
787 input_title_t *t = p_cdda->p_title[i-1] = vlc_input_title_New();
789 asprintf( &t->psz_name, _("Track %i"), i );
790 t->i_size = ( p_cdda->p_lsns[i] - p_cdda->p_lsns[i-1] ) *
791 (int64_t)CDIO_CD_FRAMESIZE_RAW;
793 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
794 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i, psz_mrl,
795 psz_mrl_max, psz_source, PLAYLIST_APPEND,
803 /****************************************************************************
805 ****************************************************************************/
807 /*****************************************************************************
808 * Open: open cdda device or image file and initialize structures
809 * for subsequent operations.
810 *****************************************************************************/
812 E_(CDDAOpen)( vlc_object_t *p_this )
814 access_t *p_access = (access_t*)p_this;
815 char * psz_source = NULL;
819 vlc_bool_t b_single_track = false;
820 int i_rc = VLC_EGENERIC;
822 /* Set where to log errors messages from libcdio. */
823 p_cdda_input = p_access;
825 /* parse the options passed in command line : */
827 if( p_access->psz_path && *p_access->psz_path )
829 char *psz_parser = psz_source = strdup( p_access->psz_path );
831 while( *psz_parser && *psz_parser != '@' )
836 if( *psz_parser == '@' )
842 if ('T' == *psz_parser || 't' == *psz_parser )
845 i_track = (int)strtol( psz_parser, NULL, 10 );
846 i_track = i_track ? i_track : 1;
847 b_single_track = true;
851 if (!psz_source || !*psz_source)
853 /* No device/track given. Continue only when this plugin was
855 if( !p_this->b_force ) return VLC_EGENERIC;
857 psz_source = var_CreateGetString( p_this, "cd-audio" );
859 if( !psz_source || !*psz_source ) {
860 /* Scan for a CD-ROM drive with a CD-DA in it. */
862 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
864 if (NULL == cd_drives || NULL == cd_drives[0] ) {
866 _("libcdio couldn't find something with a CD-DA in it") );
867 if (cd_drives) cdio_free_device_list(cd_drives);
871 psz_source = strdup(cd_drives[0]);
872 cdio_free_device_list(cd_drives);
876 cdio_log_set_handler ( cdio_log_handler );
879 if( !(p_cdio = cdio_open( psz_source, DRIVER_UNKNOWN )) )
881 msg_Warn( p_access, "could not open %s", psz_source );
885 p_cdda = malloc( sizeof(cdda_data_t) );
888 msg_Err( p_access, "out of memory" );
892 memset( p_cdda, 0, sizeof(cdda_data_t) );
895 cddb_log_set_handler ( cddb_log_handler );
896 p_cdda->cddb.disc = NULL;
897 p_cdda->i_cddb_enabled =
898 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
901 p_cdda->b_header = VLC_FALSE;
902 p_cdda->p_cdio = p_cdio;
903 p_cdda->i_track = i_track;
904 p_cdda->i_debug = config_GetInt(p_this, MODULE_STRING "-debug");
905 p_cdda->i_blocks_per_read
906 = config_GetInt(p_this, MODULE_STRING "-blocks-per-read");
908 if (0 == p_cdda->i_blocks_per_read)
909 p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
911 if ( p_cdda->i_blocks_per_read < MIN_BLOCKS_PER_READ
912 || p_cdda->i_blocks_per_read > MAX_BLOCKS_PER_READ ) {
913 msg_Warn( p_cdda_input,
914 "Number of blocks (%d) has to be between %d and %d. "
916 p_cdda->i_blocks_per_read,
917 MIN_BLOCKS_PER_READ, MAX_BLOCKS_PER_READ,
918 DEFAULT_BLOCKS_PER_READ );
919 p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
923 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
925 /* Set up p_access */
926 p_access->pf_read = NULL;
927 p_access->pf_block = CDDAReadBlocks;
928 p_access->pf_control = CDDAControl;
929 p_access->pf_seek = CDDASeek;
931 p_access->info.i_update = 0;
932 p_access->info.i_size = 0;
933 p_access->info.i_pos = 0;
934 p_access->info.b_eof = VLC_FALSE;
935 p_access->info.i_title = 0;
936 p_access->info.i_seekpoint = 0;
938 p_access->p_sys = (access_sys_t *) p_cdda;
940 /* We read the Table Of Content information */
941 i_rc = GetCDInfo( p_access, p_cdda );
942 if ( VLC_SUCCESS != i_rc ) goto error;
944 CDDAFixupPlaylist( p_access, p_cdda, psz_source, b_single_track );
946 /* Build a WAV header to put in front of the output data.
947 This gets sent back in the Block (read) routine.
949 memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
950 SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
951 SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
952 p_cdda->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
953 p_cdda->waveheader.Length = 0; /* we just don't know */
954 p_cdda->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
955 p_cdda->waveheader.SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
956 SetDWLE( &p_cdda->waveheader.SubChunkLength, 16);
957 SetWLE( &p_cdda->waveheader.Modus, 2);
958 SetDWLE( &p_cdda->waveheader.SampleFreq, CDDA_FREQUENCY_SAMPLE);
959 SetWLE( &p_cdda->waveheader.BytesPerSample,
960 2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
961 SetDWLE( &p_cdda->waveheader.BytesPerSec,
962 2*16/8 /*BytesPerSample*/ * CDDA_FREQUENCY_SAMPLE );
963 p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
964 p_cdda->waveheader.DataLength = 0; /* we just don't know */
967 var_Create( p_access, MODULE_STRING "-caching",
968 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
972 cdio_destroy( p_cdda->p_cdio );
980 /*****************************************************************************
981 * CDDAClose: closes cdda and frees any resources associded with it.
982 *****************************************************************************/
984 E_(CDDAClose)( vlc_object_t *p_this )
986 access_t *p_access = (access_t *) p_this;
987 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
990 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
992 /* Remove playlist titles */
993 for( i = 0; i < p_cdda->i_tracks; i++ )
995 vlc_input_title_Delete( p_cdda->p_title[i] );
998 cdio_destroy( p_cdda->p_cdio );
1000 cdio_log_set_handler (uninit_log_handler);
1003 cddb_log_set_handler (uninit_log_handler);
1004 if (p_cdda->i_cddb_enabled)
1005 cddb_disc_destroy(p_cdda->cddb.disc);
1008 free( p_cdda->p_lsns );
1009 if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
1011 p_cdda_input = NULL;
1014 /*****************************************************************************
1015 * Control: The front-end or vlc engine calls here to ether get
1016 * information such as meta information or plugin capabilities or to
1017 * issue miscellaneous "set" requests.
1018 *****************************************************************************/
1019 static int CDDAControl( access_t *p_access, int i_query, va_list args )
1021 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
1025 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
1026 "query %d", i_query );
1030 /* Pass back a copy of meta information that was gathered when we
1031 during the Open/Initialize call.
1033 case ACCESS_GET_META:
1035 vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
1036 if ( p_cdda->p_meta ) {
1037 *pp_meta = vlc_meta_Duplicate( p_cdda->p_meta );
1038 dbg_print( INPUT_DBG_META, "%s", _("Meta copied") );
1040 msg_Warn( p_access, _("Tried to copy NULL meta info") );
1044 return VLC_EGENERIC;
1046 case ACCESS_CAN_SEEK:
1047 case ACCESS_CAN_FASTSEEK:
1048 case ACCESS_CAN_PAUSE:
1049 case ACCESS_CAN_CONTROL_PACE:
1051 vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
1052 *pb_bool = VLC_TRUE;
1057 case ACCESS_GET_MTU:
1058 pi_int = (int*)va_arg( args, int * );
1059 *pi_int = p_cdda-> i_blocks_per_read * CDIO_CD_FRAMESIZE_RAW;
1062 case ACCESS_GET_PTS_DELAY:
1064 int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
1065 *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
1066 * MILLISECONDS_PER_SEC;
1071 case ACCESS_SET_PAUSE_STATE:
1074 case ACCESS_GET_TITLE_INFO:
1075 { input_title_t ***ppp_title;
1076 ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
1077 pi_int = (int*)va_arg( args, int* );
1078 *((int*)va_arg( args, int* )) = 1; /* Title offset */
1080 /* Duplicate track info */
1081 *pi_int = p_cdda->i_tracks;
1082 *ppp_title = malloc(sizeof( input_title_t **) * p_cdda->i_tracks );
1084 if (!*ppp_title) return VLC_ENOMEM;
1086 for( i = 0; i < p_cdda->i_tracks; i++ )
1088 if ( p_cdda->p_title[i] )
1090 vlc_input_title_Duplicate( p_cdda->p_title[i] );
1095 case ACCESS_SET_TITLE:
1096 i = (int)va_arg( args, int );
1097 if( i != p_access->info.i_title )
1100 p_access->info.i_update |=
1101 INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1102 p_access->info.i_title = i;
1103 p_access->info.i_size = p_cdda->p_title[i]->i_size;
1104 p_access->info.i_pos = 0;
1106 /* Next sector to read */
1107 p_cdda->i_lsn = p_cdda->p_lsns[i];
1111 case ACCESS_SET_SEEKPOINT:
1112 case ACCESS_SET_PRIVATE_ID_STATE:
1113 return VLC_EGENERIC;
1115 msg_Warn( p_access, _("unimplemented query in control") );
1116 return VLC_EGENERIC;
1122 /*****************************************************************************
1125 Initialize information pertaining to the CD: the number of tracks,
1126 first track number, LSNs for each track and the leadout. The leadout
1127 information is stored after the last track. The LSN array is
1128 0-origin, same as p_access->info. Add first_track to get what track
1129 number this is on the CD. Note: libcdio uses the real track number.
1131 On input we assume p_cdda->p_cdio and p_cdda->i_track have been set.
1133 We return the VLC-type status, e.g. VLC_SUCCESS, VLC_ENOMEM, etc.
1134 *****************************************************************************/
1136 GetCDInfo( access_t *p_access, cdda_data_t *p_cdda )
1139 discmode_t discmode = CDIO_DISC_MODE_NO_INFO;
1141 p_cdda->i_tracks = cdio_get_num_tracks(p_cdda->p_cdio);
1142 p_cdda->i_first_track = cdio_get_first_track_num(p_cdda->p_cdio);
1144 discmode = cdio_get_discmode(p_cdda->p_cdio);
1146 case CDIO_DISC_MODE_CD_DA:
1147 case CDIO_DISC_MODE_CD_MIXED:
1148 /* These are possible for CD-DA */
1151 /* These are not possible for CD-DA */
1153 _("Disc seems not to be CD-DA. libcdio reports it is %s"),
1154 discmode2str[discmode]
1156 return VLC_EGENERIC;
1159 p_cdda->p_lsns = malloc( (p_cdda->i_tracks + 1) * sizeof(lsn_t) );
1161 if( p_cdda->p_lsns == NULL )
1163 msg_Err( p_access, "out of memory" );
1168 /* Fill the p_lsns structure with the track/sector matches.
1169 Note cdio_get_track_lsn when given num_tracks + 1 will return
1172 for( i = 0 ; i <= p_cdda->i_tracks ; i++ )
1174 (p_cdda->p_lsns)[ i ] =
1175 cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_first_track+i);
1178 /* Set reading start LSN. */
1179 p_cdda->i_lsn = p_cdda->p_lsns[p_cdda->i_track - p_cdda->i_first_track];