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 #if UPDATE_TRACK_INFORMATION_FINISHED
440 track_t i_track = p_cdda->i_tracks;
441 char psz_buffer[MSTRTIME_MAX_SIZE];
443 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[0])
444 / CDIO_CD_FRAMES_PER_SEC;
446 dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
447 input_Control( p_access, INPUT_ADD_INFO, _("General"), _("Duration"), "%s",
448 secstotimestr( psz_buffer, i_duration ) );
450 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ ) {
451 char track_str[TITLE_MAX];
453 (p_cdda->p_lsns[i_track+1] - p_cdda->p_lsns[i_track])
454 / CDIO_CD_FRAMES_PER_SEC;
455 snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
456 input_Control( p_access, INPUT_ADD_INFO, track_str, _("Duration"), "%s",
457 secstotimestr( psz_buffer, i_duration ) );
460 if (p_cdda->i_cddb_enabled) {
461 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
464 if ( t->artist != NULL && strlen(t->artist) ) {
465 input_Control( p_access, INPUT_ADD_INFO, track_str,
466 _("Artist"), "%s", t->artist );
468 if ( t->title != NULL && strlen(t->title) ) {
469 input_Control( p_access, INPUT_ADD_INFO, track_str,
470 _("Title"), "%s", t->title );
472 if ( t->ext_data != NULL && strlen(t->ext_data) ) {
473 input_Control( p_access, INPUT_ADD_INFO, track_str,
474 _("Extended Data"), "%s", t->ext_data );
478 #endif /*HAVE_LIBCDDB*/
481 #endif /* UPDATE_TRACK_INFORMATION_FINISHED */
484 #define add_format_str_info(val) \
486 const char *str = val; \
491 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
494 saw_control_prefix = false; \
498 #define add_format_num_info(val, fmt) \
502 sprintf(num_str, fmt, val); \
503 len=strlen(num_str); \
505 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
508 saw_control_prefix = false; \
512 Take a format string and expand escape sequences, that is sequences that
513 begin with %, with information from the current CD.
514 The expanded string is returned. Here is a list of escape sequences:
516 %a : The album artist **
517 %A : The album information **
522 %m : The CD-DA Media Catalog Number (MCN)
523 %n : The number of tracks on the CD
524 %p : The artist/performer/composer in the track **
525 %T : The track number **
526 %s : Number of seconds in this track
528 %Y : The year 19xx or 20xx **
532 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
533 const char format_str[], const char *mrl, int i_track)
535 #define TEMP_STR_SIZE 256
536 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
537 static char temp_str[TEMP_STR_SIZE];
539 char * tp = temp_str;
540 vlc_bool_t saw_control_prefix = false;
541 size_t format_len = strlen(format_str);
543 memset(temp_str, 0, TEMP_STR_SIZE);
545 for (i=0; i<format_len; i++) {
547 if (!saw_control_prefix && format_str[i] != '%') {
548 *tp++ = format_str[i];
549 saw_control_prefix = false;
553 switch(format_str[i]) {
555 if (saw_control_prefix) {
558 saw_control_prefix = !saw_control_prefix;
562 if (!p_cdda->i_cddb_enabled) goto not_special;
563 if (p_cdda->cddb.disc)
564 add_format_str_info(p_cdda->cddb.disc->artist);
567 if (!p_cdda->i_cddb_enabled) goto not_special;
568 if (p_cdda->cddb.disc)
569 add_format_str_info(p_cdda->cddb.disc->title);
572 if (!p_cdda->i_cddb_enabled) goto not_special;
573 if (p_cdda->cddb.disc)
574 add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
577 if (!p_cdda->i_cddb_enabled) goto not_special;
578 if (p_cdda->cddb.disc)
579 add_format_str_info(p_cdda->cddb.disc->genre);
582 if (!p_cdda->i_cddb_enabled) goto not_special;
583 if (p_cdda->cddb.disc)
584 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
587 if (!p_cdda->i_cddb_enabled) goto not_special;
588 if (p_cdda->cddb.disc)
589 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
592 if (p_cdda && p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
593 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
595 if (t != NULL && t->title != NULL)
596 add_format_str_info(t->title);
597 } else goto not_special;
600 if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
601 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
603 if (t != NULL && t->artist != NULL)
604 add_format_str_info(t->artist);
605 } else goto not_special;
608 if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
609 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
611 if (t != NULL && t->ext_data != NULL)
612 add_format_str_info(t->ext_data);
613 } else goto not_special;
618 add_format_str_info(mrl);
622 add_format_str_info(p_cdda->psz_mcn);
626 add_format_num_info(p_cdda->i_tracks, "%d");
630 if (p_cdda->i_cddb_enabled) {
631 char psz_buffer[MSTRTIME_MAX_SIZE];
633 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
634 / CDIO_CD_FRAMES_PER_SEC;
635 add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
636 } else goto not_special;
640 add_format_num_info(i_track, "%02d");
647 *tp++ = format_str[i];
648 saw_control_prefix = false;
651 return strdup(temp_str);
655 CDDACreatePlaylistItem(const access_t *p_access, cdda_data_t *p_cdda,
656 playlist_t *p_playlist, track_t i_track,
657 char *psz_mrl, int psz_mrl_max,
658 const char *psz_source, int playlist_operation,
662 (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
663 * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
666 char *config_varname = MODULE_STRING "-title-format";
667 playlist_item_t *p_item;
670 if (p_cdda->i_cddb_enabled) {
671 config_varname = MODULE_STRING "-cddb-title-format";
673 #endif /*HAVE_LIBCDDB*/
675 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
676 CDDA_MRL_PREFIX, psz_source, i_track);
678 p_title = CDDAFormatStr(p_access, p_cdda,
679 config_GetPsz( p_access, config_varname ),
682 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
683 psz_mrl, p_title, (long int) i_duration / 1000000 , i_pos );
684 playlist_AddExt( p_playlist, psz_mrl, p_title, playlist_operation,
685 i_pos, i_duration , NULL, 0);
687 if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
689 vlc_mutex_lock( &p_playlist->object_lock );
690 p_item = playlist_ItemGetByPos( p_playlist, i_pos );
691 vlc_mutex_unlock( &p_playlist->object_lock );
695 vlc_mutex_lock( &p_item->input.lock );
698 CDDAFormatStr( p_access, p_cdda,
699 config_GetPsz( p_access, MODULE_STRING "-author-format" ),
702 playlist_ItemAddInfo( p_item , _("General"),_("Author"), p_author);
705 if (p_cdda->i_cddb_enabled) {
706 const char *psz_general_cat = _("General");
708 playlist_ItemAddInfo( p_item, psz_general_cat, _("Album"),
709 "%s", p_cdda->cddb.disc->title);
710 playlist_ItemAddInfo( p_item, psz_general_cat, _("Disc Artist(s)"),
711 "%s", p_cdda->cddb.disc->artist);
712 playlist_ItemAddInfo( p_item, psz_general_cat,
713 _("CDDB Disc Category"),
714 "%s", CDDB_CATEGORY[p_cdda->cddb.disc->category]);
715 playlist_ItemAddInfo( p_item, psz_general_cat, _("Genre"),
716 "%s", p_cdda->cddb.disc->genre);
717 if ( p_cdda->cddb.disc->discid ) {
718 playlist_ItemAddInfo( p_item, psz_general_cat, _("CDDB Disc ID"),
719 "%x", p_cdda->cddb.disc->discid );
721 if (p_cdda->cddb.disc->year != 0) {
722 playlist_ItemAddInfo( p_item, psz_general_cat,
723 _("Year"), "%5d", p_cdda->cddb.disc->year );
726 if (p_cdda->i_cddb_enabled) {
727 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
729 if (t != NULL && t->artist != NULL) {
730 playlist_ItemAddInfo( p_item, psz_general_cat,
731 _("Track Artist"), "%s", t->artist );
732 playlist_ItemAddInfo( p_item , psz_general_cat,
733 _("Track Title"), "%s", t->title );
738 #endif /*HAVE_LIBCDDB*/
740 vlc_mutex_unlock( &p_item->input.lock );
744 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
745 const char *psz_source, vlc_bool_t b_single_track )
748 playlist_t * p_playlist;
750 unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
751 strlen("@T") + strlen("100") + 1;
754 p_cdda->i_cddb_enabled =
755 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
756 if( b_single_track && !p_cdda->i_cddb_enabled ) return 0;
758 if( b_single_track ) return VLC_SUCCESS;
761 psz_mrl = malloc( psz_mrl_max );
763 if( psz_mrl == NULL )
765 msg_Warn( p_access, "out of memory" );
769 p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
773 msg_Warn( p_access, "can't find playlist" );
778 CDDAMetaInfo(p_access);
780 if (b_single_track) {
781 /* May fill out more information when the playlist user interface becomes
784 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, p_cdda->i_track,
785 psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
786 p_playlist->i_index);
789 for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
791 input_title_t *t = p_cdda->p_title[i-1] = vlc_input_title_New();
793 asprintf( &t->psz_name, _("Track %i"), i );
794 t->i_size = ( p_cdda->p_lsns[i] - p_cdda->p_lsns[i-1] ) *
795 (int64_t)CDIO_CD_FRAMESIZE_RAW;
797 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
798 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i, psz_mrl,
799 psz_mrl_max, psz_source, PLAYLIST_APPEND,
807 /****************************************************************************
809 ****************************************************************************/
811 /*****************************************************************************
812 * Open: open cdda device or image file and initialize structures
813 * for subsequent operations.
814 *****************************************************************************/
816 E_(CDDAOpen)( vlc_object_t *p_this )
818 access_t *p_access = (access_t*)p_this;
819 char * psz_source = NULL;
823 vlc_bool_t b_single_track = false;
824 int i_rc = VLC_EGENERIC;
826 p_access->p_sys = NULL;
828 /* Set where to log errors messages from libcdio. */
829 p_cdda_input = p_access;
831 /* parse the options passed in command line : */
833 if( p_access->psz_path && *p_access->psz_path )
835 char *psz_parser = psz_source = strdup( p_access->psz_path );
837 while( *psz_parser && *psz_parser != '@' )
842 if( *psz_parser == '@' )
848 if ('T' == *psz_parser || 't' == *psz_parser )
851 i_track = (int)strtol( psz_parser, NULL, 10 );
852 i_track = i_track ? i_track : 1;
853 b_single_track = true;
857 if (!psz_source || !*psz_source)
859 /* No device/track given. Continue only when this plugin was
861 if( !p_this->b_force ) return VLC_EGENERIC;
863 psz_source = var_CreateGetString( p_this, "cd-audio" );
865 if( !psz_source || !*psz_source ) {
866 /* Scan for a CD-ROM drive with a CD-DA in it. */
868 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
870 if (NULL == cd_drives || NULL == cd_drives[0] ) {
872 "libcdio couldn't find something with a CD-DA in it" );
873 if (cd_drives) cdio_free_device_list(cd_drives);
877 psz_source = strdup(cd_drives[0]);
878 cdio_free_device_list(cd_drives);
882 cdio_log_set_handler ( cdio_log_handler );
885 if( !(p_cdio = cdio_open( psz_source, DRIVER_UNKNOWN )) )
887 msg_Warn( p_access, "could not open %s", psz_source );
891 p_cdda = malloc( sizeof(cdda_data_t) );
894 msg_Err( p_access, "out of memory" );
898 memset( p_cdda, 0, sizeof(cdda_data_t) );
901 cddb_log_set_handler ( cddb_log_handler );
902 p_cdda->cddb.disc = NULL;
903 p_cdda->i_cddb_enabled =
904 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
907 p_cdda->b_header = VLC_FALSE;
908 p_cdda->p_cdio = p_cdio;
909 p_cdda->i_track = i_track;
910 p_cdda->i_debug = config_GetInt(p_this, MODULE_STRING "-debug");
911 p_cdda->i_blocks_per_read
912 = config_GetInt(p_this, MODULE_STRING "-blocks-per-read");
914 if (0 == p_cdda->i_blocks_per_read)
915 p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
917 if ( p_cdda->i_blocks_per_read < MIN_BLOCKS_PER_READ
918 || p_cdda->i_blocks_per_read > MAX_BLOCKS_PER_READ ) {
919 msg_Warn( p_cdda_input,
920 "Number of blocks (%d) has to be between %d and %d. "
922 p_cdda->i_blocks_per_read,
923 MIN_BLOCKS_PER_READ, MAX_BLOCKS_PER_READ,
924 DEFAULT_BLOCKS_PER_READ );
925 p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
929 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
931 /* Set up p_access */
932 p_access->pf_read = NULL;
933 p_access->pf_block = CDDAReadBlocks;
934 p_access->pf_control = CDDAControl;
935 p_access->pf_seek = CDDASeek;
937 p_access->info.i_update = 0;
938 p_access->info.i_size = 0;
939 p_access->info.i_pos = 0;
940 p_access->info.b_eof = VLC_FALSE;
941 p_access->info.i_title = 0;
942 p_access->info.i_seekpoint = 0;
944 p_access->p_sys = (access_sys_t *) p_cdda;
946 /* We read the Table Of Content information */
947 i_rc = GetCDInfo( p_access, p_cdda );
948 if ( VLC_SUCCESS != i_rc ) goto error;
950 CDDAFixupPlaylist( p_access, p_cdda, psz_source, b_single_track );
952 /* Build a WAV header to put in front of the output data.
953 This gets sent back in the Block (read) routine.
955 memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
956 SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
957 SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
958 p_cdda->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
959 p_cdda->waveheader.Length = 0; /* we just don't know */
960 p_cdda->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
961 p_cdda->waveheader.SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
962 SetDWLE( &p_cdda->waveheader.SubChunkLength, 16);
963 SetWLE( &p_cdda->waveheader.Modus, 2);
964 SetDWLE( &p_cdda->waveheader.SampleFreq, CDDA_FREQUENCY_SAMPLE);
965 SetWLE( &p_cdda->waveheader.BytesPerSample,
966 2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
967 SetDWLE( &p_cdda->waveheader.BytesPerSec,
968 2*16/8 /*BytesPerSample*/ * CDDA_FREQUENCY_SAMPLE );
969 p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
970 p_cdda->waveheader.DataLength = 0; /* we just don't know */
973 var_Create( p_access, MODULE_STRING "-caching",
974 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
978 cdio_destroy( p_cdda->p_cdio );
986 /*****************************************************************************
987 * CDDAClose: closes cdda and frees any resources associded with it.
988 *****************************************************************************/
990 E_(CDDAClose)( vlc_object_t *p_this )
992 access_t *p_access = (access_t *) p_this;
993 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
996 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
998 /* Remove playlist titles */
999 for( i = 0; i < p_cdda->i_tracks; i++ )
1001 vlc_input_title_Delete( p_cdda->p_title[i] );
1004 cdio_destroy( p_cdda->p_cdio );
1006 cdio_log_set_handler (uninit_log_handler);
1009 cddb_log_set_handler (uninit_log_handler);
1010 if (p_cdda->i_cddb_enabled)
1011 cddb_disc_destroy(p_cdda->cddb.disc);
1014 free( p_cdda->p_lsns );
1015 if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
1017 p_cdda_input = NULL;
1020 /*****************************************************************************
1021 * Control: The front-end or vlc engine calls here to ether get
1022 * information such as meta information or plugin capabilities or to
1023 * issue miscellaneous "set" requests.
1024 *****************************************************************************/
1025 static int CDDAControl( access_t *p_access, int i_query, va_list args )
1027 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
1031 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
1032 "query %d", i_query );
1036 /* Pass back a copy of meta information that was gathered when we
1037 during the Open/Initialize call.
1039 case ACCESS_GET_META:
1041 vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
1042 if ( p_cdda->p_meta ) {
1043 *pp_meta = vlc_meta_Duplicate( p_cdda->p_meta );
1044 dbg_print( INPUT_DBG_META, "%s", "Meta copied" );
1046 msg_Warn( p_access, "tried to copy NULL meta info" );
1050 return VLC_EGENERIC;
1052 case ACCESS_CAN_SEEK:
1053 case ACCESS_CAN_FASTSEEK:
1054 case ACCESS_CAN_PAUSE:
1055 case ACCESS_CAN_CONTROL_PACE:
1057 vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
1058 *pb_bool = VLC_TRUE;
1063 case ACCESS_GET_MTU:
1064 pi_int = (int*)va_arg( args, int * );
1065 *pi_int = p_cdda-> i_blocks_per_read * CDIO_CD_FRAMESIZE_RAW;
1068 case ACCESS_GET_PTS_DELAY:
1070 int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
1071 *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
1072 * MILLISECONDS_PER_SEC;
1077 case ACCESS_SET_PAUSE_STATE:
1080 case ACCESS_GET_TITLE_INFO:
1081 { input_title_t ***ppp_title;
1082 ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
1083 pi_int = (int*)va_arg( args, int* );
1084 *((int*)va_arg( args, int* )) = 1; /* Title offset */
1086 /* Duplicate track info */
1087 *pi_int = p_cdda->i_tracks;
1088 *ppp_title = malloc(sizeof( input_title_t **) * p_cdda->i_tracks );
1090 if (!*ppp_title) return VLC_ENOMEM;
1092 for( i = 0; i < p_cdda->i_tracks; i++ )
1094 if ( p_cdda->p_title[i] )
1096 vlc_input_title_Duplicate( p_cdda->p_title[i] );
1101 case ACCESS_SET_TITLE:
1102 i = (int)va_arg( args, int );
1103 if( i != p_access->info.i_title )
1106 p_access->info.i_update |=
1107 INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1108 p_access->info.i_title = i;
1109 p_access->info.i_size = p_cdda->p_title[i]->i_size;
1110 p_access->info.i_pos = 0;
1112 /* Next sector to read */
1113 p_cdda->i_lsn = p_cdda->p_lsns[i];
1117 case ACCESS_SET_SEEKPOINT:
1118 case ACCESS_SET_PRIVATE_ID_STATE:
1119 return VLC_EGENERIC;
1121 msg_Warn( p_access, "unimplemented query in control" );
1122 return VLC_EGENERIC;
1128 /*****************************************************************************
1131 Initialize information pertaining to the CD: the number of tracks,
1132 first track number, LSNs for each track and the leadout. The leadout
1133 information is stored after the last track. The LSN array is
1134 0-origin, same as p_access->info. Add first_track to get what track
1135 number this is on the CD. Note: libcdio uses the real track number.
1137 On input we assume p_cdda->p_cdio and p_cdda->i_track have been set.
1139 We return the VLC-type status, e.g. VLC_SUCCESS, VLC_ENOMEM, etc.
1140 *****************************************************************************/
1142 GetCDInfo( access_t *p_access, cdda_data_t *p_cdda )
1145 discmode_t discmode = CDIO_DISC_MODE_NO_INFO;
1147 p_cdda->i_tracks = cdio_get_num_tracks(p_cdda->p_cdio);
1148 p_cdda->i_first_track = cdio_get_first_track_num(p_cdda->p_cdio);
1150 discmode = cdio_get_discmode(p_cdda->p_cdio);
1152 case CDIO_DISC_MODE_CD_DA:
1153 case CDIO_DISC_MODE_CD_MIXED:
1154 /* These are possible for CD-DA */
1157 /* These are not possible for CD-DA */
1159 "Disc seems not to be CD-DA. libcdio reports it is %s",
1160 discmode2str[discmode]
1162 return VLC_EGENERIC;
1165 p_cdda->p_lsns = malloc( (p_cdda->i_tracks + 1) * sizeof(lsn_t) );
1167 if( p_cdda->p_lsns == NULL )
1169 msg_Err( p_access, "out of memory" );
1174 /* Fill the p_lsns structure with the track/sector matches.
1175 Note cdio_get_track_lsn when given num_tracks + 1 will return
1178 for( i = 0 ; i <= p_cdda->i_tracks ; i++ )
1180 (p_cdda->p_lsns)[ i ] =
1181 cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_first_track+i);
1184 /* Set reading start LSN. */
1185 p_cdda->i_lsn = p_cdda->p_lsns[p_cdda->i_track - p_cdda->i_first_track];