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 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 vlc_input_item_AddInfo( &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 p_child->p_input->i_duration = (mtime_t) i_mduration;
846 if( !p_child ) return NULL;
848 playlist_NodeAddItem( p_playlist, p_child,
849 p_item->p_parent->i_view,
850 p_item, PLAYLIST_APPEND, PLAYLIST_END );
851 playlist_CopyParents( p_item, p_child );
856 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
857 playlist_item_t *p_item, int i_track,
858 vlc_bool_t b_single )
861 add_playlist_track_info_str("Source", p_cdda->psz_source);
862 vlc_input_item_AddInfo( &p_item->input, _("Track"), _("Track Number"),
865 if (p_cdda->p_cdtext[i_track])
867 const cdtext_t *p = p_cdda->p_cdtext[i_track];
868 add_playlist_track_info_str("Arranger (CD-Text)",
869 p->field[CDTEXT_ARRANGER]);
870 add_playlist_track_info_str("Composer (CD-Text)",
871 p->field[CDTEXT_COMPOSER]);
872 add_playlist_track_info_str("Genre (CD-Text)",
873 p->field[CDTEXT_GENRE]);
874 add_playlist_track_info_str("Message (CD-Text)",
875 p->field[CDTEXT_MESSAGE]);
876 add_playlist_track_info_str("Performer (CD-Text)",
877 p->field[CDTEXT_PERFORMER]);
878 add_playlist_track_info_str("Songwriter (CD-Text)",
879 p->field[CDTEXT_SONGWRITER]);
880 add_playlist_track_info_str("Title (CD-Text)",
881 p->field[CDTEXT_TITLE]);
885 if (p_cdda->b_cddb_enabled)
887 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
888 i_track-p_cdda->i_first_track);
892 if (cddb_track_get_artist(t))
893 add_playlist_track_info_str("Artist (CDDB)",
894 cddb_track_get_artist(t));
895 if (cddb_track_get_title(t))
896 add_playlist_track_info_str("Title (CDDB)",
897 cddb_track_get_title(t));
898 if (cddb_track_get_ext_data(t))
899 add_playlist_track_info_str("Extended information (CDDB)",
900 cddb_track_get_ext_data(t));
903 #endif /*HAVE_LIBCDDB*/
912 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
913 vlc_bool_t b_single_track )
916 playlist_t * p_playlist = NULL;
917 const track_t i_first_track = p_cdda->i_first_track;
918 playlist_item_t *p_item = NULL;
919 vlc_bool_t b_play = VLC_FALSE;
923 p_cdda->b_cddb_enabled =
924 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
925 if( b_single_track && !p_cdda->b_cddb_enabled )
932 if (! p_cdda->b_nav_mode ) {
933 p_playlist = (playlist_t *) vlc_object_find( p_access,
938 msg_Warn( p_access, "can't find playlist" );
943 if( b_single_track || p_cdda->b_nav_mode ) {
944 i_track = p_cdda->i_track;
948 i_track = CDIO_INVALID_TRACK;
950 CDDAMetaInfoInit( p_access );
951 CDDAMetaInfo( p_access, p_cdda->i_track );
955 p_item = playlist_LockItemGetByInput( p_playlist,
956 ((input_thread_t *)p_access->p_parent)->input.p_item );
958 if( p_item == p_playlist->status.p_item && !b_single_track )
968 if( b_single_track && !p_cdda->b_nav_mode )
970 /*May fill out more information when the playlist user interface becomes
973 track_t i_track = p_cdda->i_track;
974 unsigned int i_track_frames =
975 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
977 input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
978 vlc_input_title_New();
980 asprintf( &t->psz_name, _("Track %i"), i_track );
981 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
983 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
987 CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
988 p_item->p_input->i_duration = (mtime_t) i_track_frames
989 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
990 p_item->p_input->psz_uri = CDDAFormatMRL( p_access, i_track );
993 p_cdda->i_titles = 1;
994 p_access->info.i_update = INPUT_UPDATE_TITLE;
1000 if ( !p_cdda->b_nav_mode )
1001 playlist_ItemToNode( p_playlist, p_item );
1003 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
1005 playlist_item_t *p_child;
1006 const track_t i_track = i_first_track + i;
1007 unsigned int i_track_frames =
1008 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
1010 t = p_cdda->p_title[i] = vlc_input_title_New();
1012 asprintf( &t->psz_name, _("Track %i"), i_track );
1013 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
1015 t->i_length = I64C(1000000) * t->i_size
1016 / CDDA_FREQUENCY_SAMPLE / 4;
1018 if ( ! p_cdda->b_nav_mode ) {
1019 p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
1022 CDDAAddMetaToItem( p_access, p_cdda, p_child, i_track,
1027 p_cdda->i_titles = p_cdda->i_tracks;
1028 p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1031 p_item->p_input->i_duration = (mtime_t)
1032 p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
1033 p_item->p_input->psz_uri = CDDAFormatMRL( p_access, p_cdda->i_track );
1040 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, 0,
1041 p_playlist->status.p_item, NULL );
1044 if (p_playlist) vlc_object_release( p_playlist );