1 /*****************************************************************************
2 * info.c : CD digital audio input information routines
3 *****************************************************************************
4 * Copyright (C) 2004, 2005 the VideoLAN team
7 * Authors: Rocky Bernstein <rocky@panix.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include "callback.h" /* FIXME - reorganize callback.h, cdda.h better */
28 #include "cdda.h" /* private structures. Also #includes vlc things */
29 #include <vlc_playlist.h> /* Has to come *after* cdda.h */
31 #include <cdio/cdio.h>
32 #include <cdio/cdtext.h>
33 #include <cdio/logging.h>
34 #include <cdio/cd_types.h>
41 static char *CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
42 const char format_str[], const char *psz_mrl,
45 static char *CDDAFormatMRL( const access_t *p_access, track_t i_track );
49 #define free_and_dup(var, val) \
51 if (val) var=strdup(val);
54 /* Saves CDDB information about CD-DA via libcddb. */
56 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
59 cddb_conn_t *conn = cddb_new();
60 const CdIo_t *p_cdio = p_cdda->p_cdio;
62 dbg_print( (INPUT_DBG_CALL), "" );
65 cddb_log_set_handler (uninit_log_handler);
70 msg_Warn( p_access, "Unable to initialize libcddb" );
74 cddb_set_email_address( conn,
75 config_GetPsz( p_access,
76 MODULE_STRING "-cddb-email") );
77 cddb_set_server_name( conn,
78 config_GetPsz( p_access,
79 MODULE_STRING "-cddb-server") );
80 cddb_set_server_port(conn,
81 config_GetInt( p_access,
82 MODULE_STRING "-cddb-port") );
84 /* Set the location of the local CDDB cache directory.
85 The default location of this directory is */
87 if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
88 cddb_cache_disable(conn);
90 cddb_cache_set_dir(conn,
91 config_GetPsz( p_access,
92 MODULE_STRING "-cddb-cachedir") );
94 cddb_set_timeout(conn,
95 config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
98 if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" ) )
100 cddb_http_enable(conn);
104 cddb_http_disable(conn);
107 p_cdda->cddb.disc = cddb_disc_new();
109 if (!p_cdda->cddb.disc)
111 msg_Err( p_access, "Unable to create CDDB disc structure." );
115 for(i = 0; i < p_cdda->i_tracks; i++)
117 track_t i_track = p_cdda->i_first_track + i;
118 cddb_track_t *t = cddb_track_new();
119 cddb_track_set_frame_offset(t,
120 cdio_get_track_lba(p_cdio, i_track));
121 cddb_disc_add_track(p_cdda->cddb.disc, t);
124 cddb_disc_set_length(p_cdda->cddb.disc,
125 cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
126 / CDIO_CD_FRAMES_PER_SEC);
128 if (!cddb_disc_calc_discid(p_cdda->cddb.disc))
130 msg_Err( p_access, "CDDB disc ID calculation failed" );
134 i_matches = cddb_query(conn, p_cdda->cddb.disc);
139 msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
141 cddb_read(conn, p_cdda->cddb.disc);
143 if (p_cdda->i_debug & INPUT_DBG_CDDB)
144 cddb_disc_print(p_cdda->cddb.disc);
149 msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
157 #endif /*HAVE_LIBCDDB*/
159 #define add_meta_val(VLC_META, VAL) \
160 if ( p_cdda->p_meta && VAL) { \
161 /*vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL );*/ \
162 dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL ); \
165 #define add_cddb_meta(FIELD, VLC_META) \
166 add_meta_val(VLC_META, cddb_disc_get_##FIELD(p_cdda->cddb.disc));
168 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
171 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
172 cddb_disc_get_##FIELD(p_cdda->cddb.disc)); \
173 psz_buf[sizeof(psz_buf)-1] = '\0'; \
174 add_meta_val(VLC_META, psz_buf); \
177 /* Adds a string-valued entry to the stream and media information if
178 the string is not null or the null string.
180 #define add_info_str(CATEGORY, TITLE, FIELD) \
181 if (FIELD && strlen(FIELD)) { \
182 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
183 _(TITLE), "%s", FIELD ); \
186 /* Adds a numeric-valued entry to the stream and media information
187 if the number is not zero. */
188 #define add_info_val(CATEGORY, TITLE, FMT, FIELD) \
190 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
191 _(TITLE), FMT, FIELD ); \
194 /* Adds a CDDB string-valued entry to the stream and media information
195 under category "Disc" if the string is not null or the null string.
197 #define add_cddb_disc_info_str(TITLE, FIELD) \
198 add_info_str("Disc", TITLE, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
200 /* Adds a CDDB numeric-valued entry to the stream and media information
201 under category "Disc" if the string is not null or the null string.
203 #define add_cddb_disc_info_val(TITLE, FMT, FIELD) \
204 add_info_val("Disc", TITLE, FMT, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
206 /* Adds a CD-Text string-valued entry to the stream and media information
207 under category "Disc" if the string is not null or the null string.
209 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD) \
210 add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
212 /* Adds a CD-Text string-valued entry to the stream and media information
213 under category "Disc" if the string is not null or the null string.
215 #define add_cdtext_disc_info_str(TITLE, FIELD) \
216 add_cdtext_info_str("Disc", TITLE, 0, FIELD)
220 Saves Meta Information about the CD-DA.
222 Meta information used in "stream and media info" or in playlist
223 info. The intialization of CD-Text or CDDB is done here though.
224 Therefore, this should be called before CDDAMetaInfo is called.
228 CDDAMetaInfoInit( access_t *p_access )
230 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
232 if ( ! p_cdda ) return;
234 dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d",
237 p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
239 p_cdda->p_meta = vlc_meta_New();
243 if ( p_cdda->b_cddb_enabled )
245 GetCDDBInfo(p_access, p_cdda);
248 #endif /*HAVE_LIBCDDB*/
254 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
256 p_cdda->p_cdtext[i_track] =
257 cdio_get_cdtext(p_cdda->p_cdio, i_track);
263 In the Control routine, we handle Meta Information requests and
264 basically copy what was saved in CDDAMetaInfoInit.
266 If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
270 CDDAMetaInfo( access_t *p_access, track_t i_track )
272 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
273 char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
274 char *psz_meta_artist = NULL;
276 if ( ! p_cdda ) return;
278 dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
282 /* Set up for Meta and name for CDDB access. */
283 if ( p_cdda->b_cddb_enabled && p_cdda->cddb.disc )
285 if( CDIO_INVALID_TRACK == i_track )
288 psz_meta_title = (char *)cddb_disc_get_title(p_cdda->cddb.disc);
289 psz_meta_artist = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
290 if ( cddb_disc_get_genre(p_cdda->cddb.disc) &&
291 strlen(cddb_disc_get_genre(p_cdda->cddb.disc)) )
292 add_cddb_meta(genre, VLC_META_GENRE);
293 if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc))
294 add_cddb_meta_fmt(year, "%d", VLC_META_DATE );
298 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
301 if( cddb_track_get_title(t) != NULL && ! p_cdda->b_nav_mode )
303 add_meta_val( VLC_META_TITLE, cddb_track_get_title(t) );
305 if( cddb_track_get_artist(t) != NULL )
307 add_meta_val( VLC_META_ARTIST, cddb_track_get_artist(t) );
313 #endif /*HAVE_LIBCDDB*/
317 track_t i = p_cdda->i_tracks;
318 const int i_first_track = p_cdda->i_first_track;
319 char psz_buffer[MSTRTIME_MAX_SIZE];
320 unsigned int i_track_frames =
321 cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
323 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
325 dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d",
326 (long int) i_duration, p_cdda->i_tracks );
327 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
328 _("Disc"), _("Duration"), "%s",
329 secstotimestr( psz_buffer, i_duration ) );
331 if (p_cdda->psz_mcn) {
332 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
333 _("Disc"), _("Media Catalog Number (MCN)"), "%s",
336 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
337 _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
342 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
344 add_cddb_disc_info_str("Artist (CDDB)", artist);
345 if ( CDDB_CAT_INVALID != cddb_disc_get_category(p_cdda->cddb.disc) )
346 add_info_str("Disc", "Category (CDDB)",
347 CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
348 add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
349 add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
350 add_cddb_disc_info_str("Genre (CDDB)", genre);
351 add_cddb_disc_info_str("Title (CDDB)", title);
352 if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc) )
353 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
356 #endif /*HAVE_LIBCDDB*/
358 if (p_cdda->p_cdtext[0])
362 add_cdtext_disc_info_str("Arranger (CD-Text)", CDTEXT_ARRANGER);
363 add_cdtext_disc_info_str("Composer (CD-Text)", CDTEXT_COMPOSER);
364 add_cdtext_disc_info_str("Disc ID (CD-Text)", CDTEXT_DISCID);
365 add_cdtext_disc_info_str("Genre (CD-Text)", CDTEXT_GENRE);
366 add_cdtext_disc_info_str("Message (CD-Text)", CDTEXT_MESSAGE);
367 add_cdtext_disc_info_str("Performer (CD-Text)", CDTEXT_PERFORMER);
368 add_cdtext_disc_info_str("Songwriter (CD-Text)", CDTEXT_SONGWRITER);
369 add_cdtext_disc_info_str("Title (CD-Text)", CDTEXT_TITLE);
371 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
372 if (psz_field && strlen(psz_field)) {
373 psz_meta_title = psz_field;
375 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
376 if (psz_field && strlen(psz_field)) {
377 psz_meta_artist = psz_field;
382 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
384 char psz_track[TITLE_MAX];
385 const track_t i_track = i_first_track + i;
386 unsigned int i_track_frames =
387 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
388 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
390 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
391 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
393 snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
395 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
397 secstotimestr( psz_buffer, i_duration ) );
399 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
400 _("MRL"), "%s", psz_mrl );
403 if (p_cdda->p_cdtext[i_track])
405 add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
406 i_track, CDTEXT_ARRANGER);
407 add_cdtext_info_str( psz_track, "Composer (CD-Text)",
408 i_track, CDTEXT_COMPOSER);
409 add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
410 i_track, CDTEXT_DISCID);
411 add_cdtext_info_str( psz_track, "Genre (CD-Text)",
412 i_track, CDTEXT_GENRE);
413 add_cdtext_info_str( psz_track, "Message (CD-Text)",
414 i_track, CDTEXT_MESSAGE);
415 add_cdtext_info_str( psz_track, "Performer (CD-Text)",
416 i_track, CDTEXT_PERFORMER);
417 add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
418 i_track, CDTEXT_SONGWRITER);
419 add_cdtext_info_str( psz_track, "Title (CD-Text)",
420 i_track, CDTEXT_TITLE);
424 if (p_cdda->b_cddb_enabled)
426 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
429 add_info_str(psz_track, "Artist (CDDB)",
430 cddb_track_get_artist(t));
431 add_info_str(psz_track, "Title (CDDB)",
432 cddb_track_get_title(t));
433 add_info_str(psz_track, "Extended Data (CDDB)",
434 cddb_track_get_ext_data(t));
437 #endif /*HAVE_LIBCDDB*/
440 /* Above we should have set psz_meta_title and psz_meta_artist
441 to CDDB or CD-Text values or the default value depending on
442 availablity and user preferences.
444 So now add the title and artist to VLC's meta, and the name
445 as shown in the status bar and playlist entry.
447 For playlist mode, the meta title is what's seen at the
448 bottom and in the playlist. For nav-mode playing, it is
449 done by input_control. I don't understand why they do
450 different things. In either case, we may have customized to
451 put in the track name.
453 if ( CDIO_INVALID_TRACK != i_track )
455 char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
456 if ( !p_cdda->b_nav_mode ) {
457 add_meta_val( VLC_META_TITLE, psz_name );
460 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
464 add_meta_val( VLC_META_ARTIST, psz_meta_artist );
470 #define add_format_str_info(val) \
472 const char *str = val; \
477 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
480 saw_control_prefix = false; \
484 #define add_format_num_info(val, fmt) \
488 sprintf(num_str, fmt, val); \
489 len=strlen(num_str); \
491 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
494 saw_control_prefix = false; \
499 cdda_data_t *p_cdda, char *psz_cdtext)
501 /* We either don't have CD-Text info, or we do but we prefer to get CDDB
502 which means CDDB has been enabled and we were able to retrieve the info.*/
504 return !psz_cdtext ||
505 (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
513 Take a format string and expand escape sequences, that is sequences that
514 begin with %, with information from the current CD.
515 The expanded string is returned. Here is a list of escape sequences:
517 %a : The album artist **
518 %A : The album information **
520 %e : The extended track data
524 %m : The CD-DA Media Catalog Number (MCN)
525 %n : The number of tracks on the CD
526 %p : The artist/performer/composer in the track **
527 %T : The track number **
528 %s : Number of seconds in this track, or seconds in CD if invalid track
529 %S : Number of seconds on the CD
530 %t : The track name or MRL if no name
531 %Y : The year 19xx or 20xx **
535 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
536 const char format_str[], const char *psz_mrl, track_t i_track)
538 #define TEMP_STR_SIZE 256
539 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
540 static char temp_str[TEMP_STR_SIZE];
542 char * tp = temp_str;
543 vlc_bool_t saw_control_prefix = false;
544 size_t format_len = strlen(format_str);
546 memset(temp_str, 0, TEMP_STR_SIZE);
548 for (i=0; i<format_len; i++)
552 if (!saw_control_prefix && format_str[i] != '%')
554 *tp++ = format_str[i];
555 saw_control_prefix = false;
559 switch(format_str[i])
562 if (saw_control_prefix)
566 saw_control_prefix = !saw_control_prefix;
570 if (p_cdda->p_cdtext[0]
571 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
572 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
573 if (want_cddb_info(p_cdda, psz))
574 psz = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
577 if (p_cdda->p_cdtext[0]
578 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
579 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
580 if (want_cddb_info(p_cdda, psz))
581 psz = (char *)cddb_disc_get_title(p_cdda->cddb.disc);
584 if (!p_cdda->b_cddb_enabled) goto not_special;
585 if (p_cdda->cddb.disc)
586 add_format_str_info(CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
589 if (p_cdda->p_cdtext[0]
590 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
591 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
592 if (want_cddb_info(p_cdda, psz))
593 psz = (char *)cddb_disc_get_genre(p_cdda->cddb.disc);
596 if (p_cdda->p_cdtext[0]
597 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
598 psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
599 if (want_cddb_info(p_cdda, psz)) {
600 add_format_num_info(cddb_disc_get_discid(p_cdda->cddb.disc), "%x");
602 add_format_str_info(psz);
605 if (!p_cdda->b_cddb_enabled) goto not_special;
606 if (p_cdda->cddb.disc)
607 add_format_num_info(cddb_disc_get_year(p_cdda->cddb.disc),
611 if ( CDIO_INVALID_TRACK == i_track ) break;
612 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
614 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
616 if (t != NULL && cddb_track_get_title(t) != NULL) {
617 add_format_str_info(cddb_track_get_title(t));
619 add_format_str_info(psz_mrl);
622 if (p_cdda->p_cdtext[i_track]
623 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]) {
624 add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
627 add_format_str_info(psz_mrl);
631 if ( CDIO_INVALID_TRACK == i_track ) break;
632 if (p_cdda->p_cdtext[i_track]
633 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
634 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
635 if (want_cddb_info(p_cdda, psz))
637 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
639 if (t != NULL && cddb_track_get_artist(t) != NULL)
640 psz = (char *)cddb_track_get_artist(t);
644 if ( CDIO_INVALID_TRACK == i_track ) break;
645 if (p_cdda->p_cdtext[i_track]
646 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
647 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
648 if (want_cddb_info(p_cdda, psz))
650 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
652 if (t != NULL && cddb_track_get_ext_data(t) != NULL)
653 psz = (char *)cddb_track_get_ext_data(t);
659 if (p_cdda->p_cdtext[0]
660 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
661 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
664 if (p_cdda->p_cdtext[0]
665 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
666 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
669 if (p_cdda->p_cdtext[0]
670 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
671 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
674 if (p_cdda->p_cdtext[0]
675 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
676 add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
679 if ( CDIO_INVALID_TRACK == i_track ) break;
680 if (p_cdda->p_cdtext[i_track]
681 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
682 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
685 if ( CDIO_INVALID_TRACK == i_track ) break;
686 if (p_cdda->p_cdtext[i_track]
687 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
688 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
693 if ( CDIO_INVALID_TRACK == i_track ) break;
694 if (p_cdda->p_cdtext[i_track]
695 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
696 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
699 #endif /*HAVE_LIBCDDB*/
702 if ( CDIO_INVALID_TRACK != i_track )
704 char psz_buffer[MSTRTIME_MAX_SIZE];
705 unsigned int i_track_frames =
706 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
708 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
709 add_format_str_info( secstotimestr( psz_buffer,
714 /* Fall through to disc duration if CDIO_INVALID_TRACK */
717 char psz_buffer[MSTRTIME_MAX_SIZE];
718 unsigned int i_track_frames =
719 cdio_get_track_lba(p_cdda->p_cdio,
720 CDIO_CDROM_LEADOUT_TRACK);
722 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
723 add_format_str_info( secstotimestr( psz_buffer,
729 add_format_str_info(psz_mrl);
733 add_format_str_info(p_cdda->psz_mcn);
737 add_format_num_info(p_cdda->i_tracks, "%d");
741 add_format_num_info(i_track, "%02d");
745 add_format_str_info(psz);
752 *tp++ = format_str[i];
753 saw_control_prefix = false;
756 return strdup(temp_str);
759 /* Return a MRL for the given track. The caller must free the
762 CDDAFormatMRL( const access_t *p_access, track_t i_track )
764 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
765 const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX)
766 + strlen(p_cdda->psz_source) +
767 + strlen("@T") + strlen("100") + 1;
768 char *psz_mrl = calloc( 1, psz_mrl_max );
770 if (CDIO_INVALID_TRACK == i_track)
771 snprintf(psz_mrl, psz_mrl_max, "%s%s",
772 CDDA_MRL_PREFIX, p_cdda->psz_source);
774 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
775 CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
780 /* Return a title string as specified by the titel format string for the
781 given track. The caller must free the allocated string. */
783 CDDAFormatTitle( const access_t *p_access, track_t i_track )
786 const char *config_varname = MODULE_STRING "-title-format";
787 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
788 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
794 if (p_cdda->b_cddb_enabled)
796 config_varname = MODULE_STRING "-cddb-title-format";
798 #endif /*HAVE_LIBCDDB*/
800 CDDAFormatStr( p_access, p_cdda,
801 config_GetPsz( p_access, config_varname ),
809 /* Adds a string-valued entry to the playlist information under "Track"
810 if the string is not null or the null string.
812 #define add_playlist_track_info_str(TITLE, FIELD) \
813 if (FIELD && strlen(FIELD)) \
815 input_ItemAddInfo( &p_item->input, _("Track"), _(TITLE), \
819 static playlist_item_t *
820 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
821 playlist_t *p_playlist, playlist_item_t *p_item,
824 unsigned int i_track_frames =
825 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
826 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
827 mtime_t i_mduration = i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
828 char *psz_title = NULL;
829 char *psz_mrl = NULL;
831 playlist_item_t *p_child = NULL;
833 if( !p_item ) return NULL;
835 psz_title = CDDAFormatTitle( p_access, i_track ) ;
836 psz_mrl = CDDAFormatMRL( p_access, i_track ) ;
838 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
839 psz_mrl, psz_title, (long int) i_mduration / 1000000 );
841 p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
842 input_GetItem(p_child->p_input)->i_duration = (mtime_t) i_mduration;
846 if( !p_child ) return NULL;
850 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
851 playlist_item_t *p_item, int i_track,
852 vlc_bool_t b_single )
855 add_playlist_track_info_str("Source", p_cdda->psz_source);
856 input_ItemAddInfo( &p_item->input, _("Track"), _("Track Number"),
859 if (p_cdda->p_cdtext[i_track])
861 const cdtext_t *p = p_cdda->p_cdtext[i_track];
862 add_playlist_track_info_str("Arranger (CD-Text)",
863 p->field[CDTEXT_ARRANGER]);
864 add_playlist_track_info_str("Composer (CD-Text)",
865 p->field[CDTEXT_COMPOSER]);
866 add_playlist_track_info_str("Genre (CD-Text)",
867 p->field[CDTEXT_GENRE]);
868 add_playlist_track_info_str("Message (CD-Text)",
869 p->field[CDTEXT_MESSAGE]);
870 add_playlist_track_info_str("Performer (CD-Text)",
871 p->field[CDTEXT_PERFORMER]);
872 add_playlist_track_info_str("Songwriter (CD-Text)",
873 p->field[CDTEXT_SONGWRITER]);
874 add_playlist_track_info_str("Title (CD-Text)",
875 p->field[CDTEXT_TITLE]);
879 if (p_cdda->b_cddb_enabled)
881 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
882 i_track-p_cdda->i_first_track);
886 if (cddb_track_get_artist(t))
887 add_playlist_track_info_str("Artist (CDDB)",
888 cddb_track_get_artist(t));
889 if (cddb_track_get_title(t))
890 add_playlist_track_info_str("Title (CDDB)",
891 cddb_track_get_title(t));
892 if (cddb_track_get_ext_data(t))
893 add_playlist_track_info_str("Extended information (CDDB)",
894 cddb_track_get_ext_data(t));
897 #endif /*HAVE_LIBCDDB*/
906 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
907 vlc_bool_t b_single_track )
910 playlist_t * p_playlist = NULL;
911 const track_t i_first_track = p_cdda->i_first_track;
912 playlist_item_t *p_item = NULL;
913 vlc_bool_t b_play = VLC_FALSE;
917 p_cdda->b_cddb_enabled =
918 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
919 if( b_single_track && !p_cdda->b_cddb_enabled )
926 if (! p_cdda->b_nav_mode ) {
927 p_playlist = pl_Yield( p_access );
930 if( b_single_track || p_cdda->b_nav_mode ) {
931 i_track = p_cdda->i_track;
935 i_track = CDIO_INVALID_TRACK;
937 CDDAMetaInfoInit( p_access );
938 CDDAMetaInfo( p_access, p_cdda->i_track );
942 input_thread_t *p_input = (input_thread_t*)vlc_object_find( p_access, VLC_OBJECT_INPUT, FIND_PARENT );
945 p_item = playlist_ItemGetByInput( p_playlist, input_GetItem(p_input), VLC_FALSE );
947 if( p_item == p_playlist->status.p_item && !b_single_track )
951 vlc_object_release( p_input );
955 if( b_single_track && !p_cdda->b_nav_mode )
957 /*May fill out more information when the playlist user interface becomes
960 track_t i_track = p_cdda->i_track;
961 unsigned int i_track_frames =
962 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
964 input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
965 vlc_input_title_New();
967 asprintf( &t->psz_name, _("Track %i"), i_track );
968 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
970 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
974 CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
975 p_item->p_input->i_duration = (mtime_t) i_track_frames
976 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
977 p_item->p_input->psz_uri = CDDAFormatMRL( p_access, i_track );
980 p_cdda->i_titles = 1;
981 p_access->info.i_update = INPUT_UPDATE_TITLE;
987 if ( !p_cdda->b_nav_mode )
988 playlist_ItemToNode( p_playlist, p_item, VLC_FALSE );
990 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
992 playlist_item_t *p_child;
993 const track_t i_track = i_first_track + i;
994 unsigned int i_track_frames =
995 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
997 t = p_cdda->p_title[i] = vlc_input_title_New();
999 asprintf( &t->psz_name, _("Track %i"), i_track );
1000 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
1002 t->i_length = I64C(1000000) * t->i_size
1003 / CDDA_FREQUENCY_SAMPLE / 4;
1005 if ( ! p_cdda->b_nav_mode ) {
1006 p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
1009 CDDAAddMetaToItem( p_access, p_cdda, p_child, i_track,
1014 p_cdda->i_titles = p_cdda->i_tracks;
1015 p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1018 p_item->p_input->i_duration = (mtime_t)
1019 p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
1020 p_item->p_input->psz_uri = CDDAFormatMRL( p_access, p_cdda->i_track );
1027 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE,
1028 p_playlist->status.p_item, NULL );
1031 if (p_playlist) vlc_object_release( p_playlist );