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 vlc_bool_t 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 /* Adds a string-valued entry to the playlist information under "Track"
811 if the string is not null or the null string.
813 #define add_playlist_track_info_str(TITLE, FIELD) \
814 if (FIELD && strlen(FIELD)) \
816 input_ItemAddInfo( &p_item->input, _("Track"), _(TITLE), \
820 static playlist_item_t *
821 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
822 playlist_t *p_playlist, playlist_item_t *p_item,
825 unsigned int i_track_frames =
826 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
827 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
828 mtime_t i_mduration = i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
829 char *psz_title = NULL;
830 char *psz_mrl = NULL;
832 playlist_item_t *p_child = NULL;
834 if( !p_item ) return NULL;
836 psz_title = CDDAFormatTitle( p_access, i_track ) ;
837 psz_mrl = CDDAFormatMRL( p_access, i_track ) ;
839 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
840 psz_mrl, psz_title, (long int) i_mduration / 1000000 );
842 p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
843 input_item_SetDuration( input_GetItem( p_child->p_input ),
844 (mtime_t) i_mduration );
848 if( !p_child ) return NULL;
852 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
853 playlist_item_t *p_item, int i_track,
854 vlc_bool_t b_single )
857 add_playlist_track_info_str("Source", p_cdda->psz_source);
858 input_ItemAddInfo( &p_item->input, _("Track"), _("Track Number"),
861 if (p_cdda->p_cdtext[i_track])
863 const cdtext_t *p = p_cdda->p_cdtext[i_track];
864 add_playlist_track_info_str("Arranger (CD-Text)",
865 p->field[CDTEXT_ARRANGER]);
866 add_playlist_track_info_str("Composer (CD-Text)",
867 p->field[CDTEXT_COMPOSER]);
868 add_playlist_track_info_str("Genre (CD-Text)",
869 p->field[CDTEXT_GENRE]);
870 add_playlist_track_info_str("Message (CD-Text)",
871 p->field[CDTEXT_MESSAGE]);
872 add_playlist_track_info_str("Performer (CD-Text)",
873 p->field[CDTEXT_PERFORMER]);
874 add_playlist_track_info_str("Songwriter (CD-Text)",
875 p->field[CDTEXT_SONGWRITER]);
876 add_playlist_track_info_str("Title (CD-Text)",
877 p->field[CDTEXT_TITLE]);
881 if (p_cdda->b_cddb_enabled)
883 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
884 i_track-p_cdda->i_first_track);
888 if (cddb_track_get_artist(t))
889 add_playlist_track_info_str("Artist (CDDB)",
890 cddb_track_get_artist(t));
891 if (cddb_track_get_title(t))
892 add_playlist_track_info_str("Title (CDDB)",
893 cddb_track_get_title(t));
894 if (cddb_track_get_ext_data(t))
895 add_playlist_track_info_str("Extended information (CDDB)",
896 cddb_track_get_ext_data(t));
899 #endif /*HAVE_LIBCDDB*/
908 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
909 vlc_bool_t b_single_track )
912 playlist_t * p_playlist = NULL;
913 const track_t i_first_track = p_cdda->i_first_track;
914 playlist_item_t *p_item = NULL;
915 vlc_bool_t b_play = VLC_FALSE;
919 p_cdda->b_cddb_enabled =
920 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
921 if( b_single_track && !p_cdda->b_cddb_enabled )
928 if (! p_cdda->b_nav_mode ) {
929 p_playlist = pl_Yield( p_access );
932 if( b_single_track || p_cdda->b_nav_mode ) {
933 i_track = p_cdda->i_track;
937 i_track = CDIO_INVALID_TRACK;
939 CDDAMetaInfoInit( p_access );
940 CDDAMetaInfo( p_access, p_cdda->i_track );
944 input_thread_t *p_input = (input_thread_t*)vlc_object_find( p_access, VLC_OBJECT_INPUT, FIND_PARENT );
947 p_item = playlist_ItemGetByInput( p_playlist, input_GetItem(p_input), VLC_FALSE );
949 if( p_item == p_playlist->status.p_item && !b_single_track )
953 vlc_object_release( p_input );
957 if( b_single_track && !p_cdda->b_nav_mode )
959 /*May fill out more information when the playlist user interface becomes
962 track_t i_track = p_cdda->i_track;
963 unsigned int i_track_frames =
964 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
966 input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
967 vlc_input_title_New();
969 asprintf( &t->psz_name, _("Track %i"), i_track );
970 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
972 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
976 CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
977 input_item_SetDuration( p_item->p_input, (mtime_t) i_track_frames
978 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
979 input_item_SetURI( p_item->p_input,
980 CDDAFormatMRL( p_access, i_track ) );
983 p_cdda->i_titles = 1;
984 p_access->info.i_update = INPUT_UPDATE_TITLE;
990 if ( !p_cdda->b_nav_mode )
991 playlist_ItemToNode( p_playlist, p_item, VLC_FALSE );
993 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
995 playlist_item_t *p_child;
996 const track_t i_track = i_first_track + i;
997 unsigned int i_track_frames =
998 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
1000 t = p_cdda->p_title[i] = vlc_input_title_New();
1002 asprintf( &t->psz_name, _("Track %i"), i_track );
1003 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
1005 t->i_length = I64C(1000000) * t->i_size
1006 / CDDA_FREQUENCY_SAMPLE / 4;
1008 if ( ! p_cdda->b_nav_mode ) {
1009 p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
1012 CDDAAddMetaToItem( p_access, p_cdda, p_child, i_track,
1017 p_cdda->i_titles = p_cdda->i_tracks;
1018 p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1021 input_item_SetDuration( p_item->p_input, (mtime_t) p_access->info.i_size
1022 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
1023 input_item_SetURI( p_item->p_input,
1024 CDDAFormatMRL( p_access, p_cdda->i_track ) );
1031 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE,
1032 p_playlist->status.p_item, NULL );
1035 if (p_playlist) vlc_object_release( p_playlist );