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", \
163 input_MetaTypeToLocalizedString(VLC_META), VAL ); \
166 #define add_cddb_meta(FIELD, VLC_META) \
167 add_meta_val(VLC_META, cddb_disc_get_##FIELD(p_cdda->cddb.disc));
169 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
172 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
173 cddb_disc_get_##FIELD(p_cdda->cddb.disc)); \
174 psz_buf[sizeof(psz_buf)-1] = '\0'; \
175 add_meta_val(VLC_META, psz_buf); \
178 /* Adds a string-valued entry to the stream and media information if
179 the string is not null or the null string.
181 #define add_info_str(CATEGORY, TITLE, FIELD) \
182 if (FIELD && strlen(FIELD)) { \
183 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
184 _(TITLE), "%s", FIELD ); \
187 /* Adds a numeric-valued entry to the stream and media information
188 if the number is not zero. */
189 #define add_info_val(CATEGORY, TITLE, FMT, FIELD) \
191 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
192 _(TITLE), FMT, FIELD ); \
195 /* Adds a CDDB string-valued entry to the stream and media information
196 under category "Disc" if the string is not null or the null string.
198 #define add_cddb_disc_info_str(TITLE, FIELD) \
199 add_info_str("Disc", TITLE, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
201 /* Adds a CDDB numeric-valued entry to the stream and media information
202 under category "Disc" if the string is not null or the null string.
204 #define add_cddb_disc_info_val(TITLE, FMT, FIELD) \
205 add_info_val("Disc", TITLE, FMT, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
207 /* Adds a CD-Text string-valued entry to the stream and media information
208 under category "Disc" if the string is not null or the null string.
210 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD) \
211 add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
213 /* Adds a CD-Text string-valued entry to the stream and media information
214 under category "Disc" if the string is not null or the null string.
216 #define add_cdtext_disc_info_str(TITLE, FIELD) \
217 add_cdtext_info_str("Disc", TITLE, 0, FIELD)
221 Saves Meta Information about the CD-DA.
223 Meta information used in "stream and media info" or in playlist
224 info. The intialization of CD-Text or CDDB is done here though.
225 Therefore, this should be called before CDDAMetaInfo is called.
229 CDDAMetaInfoInit( access_t *p_access )
231 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
233 if ( ! p_cdda ) return;
235 dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d",
238 p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
240 p_cdda->p_meta = vlc_meta_New();
244 if ( p_cdda->b_cddb_enabled )
246 GetCDDBInfo(p_access, p_cdda);
249 #endif /*HAVE_LIBCDDB*/
255 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
257 p_cdda->p_cdtext[i_track] =
258 cdio_get_cdtext(p_cdda->p_cdio, i_track);
264 In the Control routine, we handle Meta Information requests and
265 basically copy what was saved in CDDAMetaInfoInit.
267 If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
271 CDDAMetaInfo( access_t *p_access, track_t i_track )
273 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
274 char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
275 char *psz_meta_artist = NULL;
277 if ( ! p_cdda ) return;
279 dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
283 /* Set up for Meta and name for CDDB access. */
284 if ( p_cdda->b_cddb_enabled && p_cdda->cddb.disc )
286 if( CDIO_INVALID_TRACK == i_track )
289 psz_meta_title = (char *)cddb_disc_get_title(p_cdda->cddb.disc);
290 psz_meta_artist = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
291 if ( cddb_disc_get_genre(p_cdda->cddb.disc) &&
292 strlen(cddb_disc_get_genre(p_cdda->cddb.disc)) )
293 add_cddb_meta(genre, vlc_meta_Genre);
294 if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc))
295 add_cddb_meta_fmt(year, "%d", vlc_meta_Date );
299 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
302 if( cddb_track_get_title(t) != NULL && ! p_cdda->b_nav_mode )
304 add_meta_val( vlc_meta_Title, cddb_track_get_title(t) );
306 if( cddb_track_get_artist(t) != NULL )
308 add_meta_val( vlc_meta_Artist, cddb_track_get_artist(t) );
314 #endif /*HAVE_LIBCDDB*/
318 track_t i = p_cdda->i_tracks;
319 const int i_first_track = p_cdda->i_first_track;
320 char psz_buffer[MSTRTIME_MAX_SIZE];
321 unsigned int i_track_frames =
322 cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
324 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
326 dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d",
327 (long int) i_duration, p_cdda->i_tracks );
328 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
329 _("Disc"), _("Duration"), "%s",
330 secstotimestr( psz_buffer, i_duration ) );
332 if (p_cdda->psz_mcn) {
333 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
334 _("Disc"), _("Media Catalog Number (MCN)"), "%s",
337 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
338 _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
343 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
345 add_cddb_disc_info_str("Artist (CDDB)", artist);
346 if ( CDDB_CAT_INVALID != cddb_disc_get_category(p_cdda->cddb.disc) )
347 add_info_str("Disc", "Category (CDDB)",
348 CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
349 add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
350 add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
351 add_cddb_disc_info_str("Genre (CDDB)", genre);
352 add_cddb_disc_info_str("Title (CDDB)", title);
353 if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc) )
354 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
357 #endif /*HAVE_LIBCDDB*/
359 if (p_cdda->p_cdtext[0])
363 add_cdtext_disc_info_str("Arranger (CD-Text)", CDTEXT_ARRANGER);
364 add_cdtext_disc_info_str("Composer (CD-Text)", CDTEXT_COMPOSER);
365 add_cdtext_disc_info_str("Disc ID (CD-Text)", CDTEXT_DISCID);
366 add_cdtext_disc_info_str("Genre (CD-Text)", CDTEXT_GENRE);
367 add_cdtext_disc_info_str("Message (CD-Text)", CDTEXT_MESSAGE);
368 add_cdtext_disc_info_str("Performer (CD-Text)", CDTEXT_PERFORMER);
369 add_cdtext_disc_info_str("Songwriter (CD-Text)", CDTEXT_SONGWRITER);
370 add_cdtext_disc_info_str("Title (CD-Text)", CDTEXT_TITLE);
372 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
373 if (psz_field && strlen(psz_field)) {
374 psz_meta_title = psz_field;
376 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
377 if (psz_field && strlen(psz_field)) {
378 psz_meta_artist = psz_field;
383 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
385 char psz_track[TITLE_MAX];
386 const track_t i_track = i_first_track + i;
387 unsigned int i_track_frames =
388 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
389 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
391 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
392 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
394 snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
396 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
398 secstotimestr( psz_buffer, i_duration ) );
400 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
401 _("MRL"), "%s", psz_mrl );
404 if (p_cdda->p_cdtext[i_track])
406 add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
407 i_track, CDTEXT_ARRANGER);
408 add_cdtext_info_str( psz_track, "Composer (CD-Text)",
409 i_track, CDTEXT_COMPOSER);
410 add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
411 i_track, CDTEXT_DISCID);
412 add_cdtext_info_str( psz_track, "Genre (CD-Text)",
413 i_track, CDTEXT_GENRE);
414 add_cdtext_info_str( psz_track, "Message (CD-Text)",
415 i_track, CDTEXT_MESSAGE);
416 add_cdtext_info_str( psz_track, "Performer (CD-Text)",
417 i_track, CDTEXT_PERFORMER);
418 add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
419 i_track, CDTEXT_SONGWRITER);
420 add_cdtext_info_str( psz_track, "Title (CD-Text)",
421 i_track, CDTEXT_TITLE);
425 if (p_cdda->b_cddb_enabled)
427 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
430 add_info_str(psz_track, "Artist (CDDB)",
431 cddb_track_get_artist(t));
432 add_info_str(psz_track, "Title (CDDB)",
433 cddb_track_get_title(t));
434 add_info_str(psz_track, "Extended Data (CDDB)",
435 cddb_track_get_ext_data(t));
438 #endif /*HAVE_LIBCDDB*/
441 /* Above we should have set psz_meta_title and psz_meta_artist
442 to CDDB or CD-Text values or the default value depending on
443 availablity and user preferences.
445 So now add the title and artist to VLC's meta, and the name
446 as shown in the status bar and playlist entry.
448 For playlist mode, the meta title is what's seen at the
449 bottom and in the playlist. For nav-mode playing, it is
450 done by input_control. I don't understand why they do
451 different things. In either case, we may have customized to
452 put in the track name.
454 if ( CDIO_INVALID_TRACK != i_track )
456 char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
457 if ( !p_cdda->b_nav_mode ) {
458 add_meta_val( vlc_meta_Title, psz_name );
461 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
465 add_meta_val( vlc_meta_Artist, psz_meta_artist );
471 #define add_format_str_info(val) \
473 const char *str = val; \
478 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
481 saw_control_prefix = false; \
485 #define add_format_num_info(val, fmt) \
489 sprintf(num_str, fmt, val); \
490 len=strlen(num_str); \
492 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
495 saw_control_prefix = false; \
500 cdda_data_t *p_cdda, char *psz_cdtext)
502 /* We either don't have CD-Text info, or we do but we prefer to get CDDB
503 which means CDDB has been enabled and we were able to retrieve the info.*/
505 return !psz_cdtext ||
506 (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
514 Take a format string and expand escape sequences, that is sequences that
515 begin with %, with information from the current CD.
516 The expanded string is returned. Here is a list of escape sequences:
518 %a : The album artist **
519 %A : The album information **
521 %e : The extended track data
525 %m : The CD-DA Media Catalog Number (MCN)
526 %n : The number of tracks on the CD
527 %p : The artist/performer/composer in the track **
528 %T : The track number **
529 %s : Number of seconds in this track, or seconds in CD if invalid track
530 %S : Number of seconds on the CD
531 %t : The track name or MRL if no name
532 %Y : The year 19xx or 20xx **
536 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
537 const char format_str[], const char *psz_mrl, track_t i_track)
539 #define TEMP_STR_SIZE 256
540 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
541 static char temp_str[TEMP_STR_SIZE];
543 char * tp = temp_str;
544 bool saw_control_prefix = false;
545 size_t format_len = strlen(format_str);
547 memset(temp_str, 0, TEMP_STR_SIZE);
549 for (i=0; i<format_len; i++)
553 if (!saw_control_prefix && format_str[i] != '%')
555 *tp++ = format_str[i];
556 saw_control_prefix = false;
560 switch(format_str[i])
563 if (saw_control_prefix)
567 saw_control_prefix = !saw_control_prefix;
571 if (p_cdda->p_cdtext[0]
572 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
573 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
574 if (want_cddb_info(p_cdda, psz))
575 psz = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
578 if (p_cdda->p_cdtext[0]
579 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
580 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
581 if (want_cddb_info(p_cdda, psz))
582 psz = (char *)cddb_disc_get_title(p_cdda->cddb.disc);
585 if (!p_cdda->b_cddb_enabled) goto not_special;
586 if (p_cdda->cddb.disc)
587 add_format_str_info(CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
590 if (p_cdda->p_cdtext[0]
591 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
592 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
593 if (want_cddb_info(p_cdda, psz))
594 psz = (char *)cddb_disc_get_genre(p_cdda->cddb.disc);
597 if (p_cdda->p_cdtext[0]
598 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
599 psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
600 if (want_cddb_info(p_cdda, psz)) {
601 add_format_num_info(cddb_disc_get_discid(p_cdda->cddb.disc), "%x");
603 add_format_str_info(psz);
606 if (!p_cdda->b_cddb_enabled) goto not_special;
607 if (p_cdda->cddb.disc)
608 add_format_num_info(cddb_disc_get_year(p_cdda->cddb.disc),
612 if ( CDIO_INVALID_TRACK == i_track ) break;
613 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
615 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
617 if (t != NULL && cddb_track_get_title(t) != NULL) {
618 add_format_str_info(cddb_track_get_title(t));
620 add_format_str_info(psz_mrl);
623 if (p_cdda->p_cdtext[i_track]
624 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]) {
625 add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
628 add_format_str_info(psz_mrl);
632 if ( CDIO_INVALID_TRACK == i_track ) break;
633 if (p_cdda->p_cdtext[i_track]
634 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
635 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
636 if (want_cddb_info(p_cdda, psz))
638 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
640 if (t != NULL && cddb_track_get_artist(t) != NULL)
641 psz = (char *)cddb_track_get_artist(t);
645 if ( CDIO_INVALID_TRACK == i_track ) break;
646 if (p_cdda->p_cdtext[i_track]
647 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
648 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
649 if (want_cddb_info(p_cdda, psz))
651 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
653 if (t != NULL && cddb_track_get_ext_data(t) != NULL)
654 psz = (char *)cddb_track_get_ext_data(t);
660 if (p_cdda->p_cdtext[0]
661 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
662 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
665 if (p_cdda->p_cdtext[0]
666 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
667 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
670 if (p_cdda->p_cdtext[0]
671 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
672 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
675 if (p_cdda->p_cdtext[0]
676 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
677 add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
680 if ( CDIO_INVALID_TRACK == i_track ) break;
681 if (p_cdda->p_cdtext[i_track]
682 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
683 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
686 if ( CDIO_INVALID_TRACK == i_track ) break;
687 if (p_cdda->p_cdtext[i_track]
688 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
689 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
694 if ( CDIO_INVALID_TRACK == i_track ) break;
695 if (p_cdda->p_cdtext[i_track]
696 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
697 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
700 #endif /*HAVE_LIBCDDB*/
703 if ( CDIO_INVALID_TRACK != i_track )
705 char psz_buffer[MSTRTIME_MAX_SIZE];
706 unsigned int i_track_frames =
707 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
709 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
710 add_format_str_info( secstotimestr( psz_buffer,
715 /* Fall through to disc duration if CDIO_INVALID_TRACK */
718 char psz_buffer[MSTRTIME_MAX_SIZE];
719 unsigned int i_track_frames =
720 cdio_get_track_lba(p_cdda->p_cdio,
721 CDIO_CDROM_LEADOUT_TRACK);
723 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
724 add_format_str_info( secstotimestr( psz_buffer,
730 add_format_str_info(psz_mrl);
734 add_format_str_info(p_cdda->psz_mcn);
738 add_format_num_info(p_cdda->i_tracks, "%d");
742 add_format_num_info(i_track, "%02d");
746 add_format_str_info(psz);
753 *tp++ = format_str[i];
754 saw_control_prefix = false;
757 return strdup(temp_str);
760 /* Return a MRL for the given track. The caller must free the
763 CDDAFormatMRL( const access_t *p_access, track_t i_track )
765 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
766 const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX)
767 + strlen(p_cdda->psz_source) +
768 + strlen("@T") + strlen("100") + 1;
769 char *psz_mrl = calloc( 1, psz_mrl_max );
771 if (CDIO_INVALID_TRACK == i_track)
772 snprintf(psz_mrl, psz_mrl_max, "%s%s",
773 CDDA_MRL_PREFIX, p_cdda->psz_source);
775 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
776 CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
781 /* Return a title string as specified by the titel format string for the
782 given track. The caller must free the allocated string. */
784 CDDAFormatTitle( const access_t *p_access, track_t i_track )
787 const char *config_varname = MODULE_STRING "-title-format";
788 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
789 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
795 if (p_cdda->b_cddb_enabled)
797 config_varname = MODULE_STRING "-cddb-title-format";
799 #endif /*HAVE_LIBCDDB*/
801 CDDAFormatStr( p_access, p_cdda,
802 config_GetPsz( p_access, config_varname ),
810 static playlist_item_t *
811 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
812 playlist_t *p_playlist, playlist_item_t *p_item,
815 unsigned int i_track_frames =
816 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
817 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
818 mtime_t i_mduration = i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
819 char *psz_title = NULL;
820 char *psz_mrl = NULL;
822 playlist_item_t *p_child = NULL;
824 if( !p_item ) return NULL;
826 psz_title = CDDAFormatTitle( p_access, i_track ) ;
827 psz_mrl = CDDAFormatMRL( p_access, i_track ) ;
829 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
830 psz_mrl, psz_title, (long int) i_mduration / 1000000 );
832 p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
833 input_item_SetDuration( input_GetItem( p_child->p_input ),
834 (mtime_t) i_mduration );
838 if( !p_child ) return NULL;
846 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
847 bool b_single_track )
850 playlist_t * p_playlist = NULL;
851 const track_t i_first_track = p_cdda->i_first_track;
852 playlist_item_t *p_item = NULL;
857 p_cdda->b_cddb_enabled =
858 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
859 if( b_single_track && !p_cdda->b_cddb_enabled )
866 if (! p_cdda->b_nav_mode ) {
867 p_playlist = pl_Yield( p_access );
870 if( b_single_track || p_cdda->b_nav_mode ) {
871 i_track = p_cdda->i_track;
875 i_track = CDIO_INVALID_TRACK;
877 CDDAMetaInfoInit( p_access );
878 CDDAMetaInfo( p_access, p_cdda->i_track );
882 input_thread_t *p_input = (input_thread_t*)vlc_object_find( p_access, VLC_OBJECT_INPUT, FIND_PARENT );
885 p_item = playlist_ItemGetByInput( p_playlist, input_GetItem(p_input), false );
887 if( p_item == p_playlist->status.p_item && !b_single_track )
891 vlc_object_release( p_input );
895 if( b_single_track && !p_cdda->b_nav_mode )
897 /*May fill out more information when the playlist user interface becomes
900 track_t i_track = p_cdda->i_track;
901 unsigned int i_track_frames =
902 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
904 input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
905 vlc_input_title_New();
907 asprintf( &t->psz_name, _("Track %i"), i_track );
908 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
910 t->i_length = INT64_C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
914 input_item_SetDuration( p_item->p_input, (mtime_t) i_track_frames
915 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
916 input_item_SetURI( p_item->p_input,
917 CDDAFormatMRL( p_access, i_track ) );
920 p_cdda->i_titles = 1;
921 p_access->info.i_update = INPUT_UPDATE_TITLE;
927 if ( !p_cdda->b_nav_mode )
928 playlist_ItemToNode( p_playlist, p_item, false );
930 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
932 playlist_item_t *p_child;
933 const track_t i_track = i_first_track + i;
934 unsigned int i_track_frames =
935 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
937 t = p_cdda->p_title[i] = vlc_input_title_New();
939 asprintf( &t->psz_name, _("Track %i"), i_track );
940 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
942 t->i_length = INT64_C(1000000) * t->i_size
943 / CDDA_FREQUENCY_SAMPLE / 4;
945 if ( ! p_cdda->b_nav_mode ) {
946 p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
952 p_cdda->i_titles = p_cdda->i_tracks;
953 p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
956 input_item_SetDuration( p_item->p_input, (mtime_t) p_access->info.i_size
957 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
958 input_item_SetURI( p_item->p_input,
959 CDDAFormatMRL( p_access, p_cdda->i_track ) );
966 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, true,
967 p_playlist->status.p_item, NULL );
970 if (p_playlist) vlc_object_release( p_playlist );