1 /*****************************************************************************
2 * info.c : CD digital audio input information routines
3 *****************************************************************************
4 * Copyright (C) 2004, 2005 VideoLAN
5 * $Id: info.c 8845 2004-09-29 09:00:41Z rocky $
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., 59 Temple Place - Suite 330, Boston, MA 02111, 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 t->frame_offset = cdio_get_track_lba(p_cdio, i_track);
120 cddb_disc_add_track(p_cdda->cddb.disc, t);
123 p_cdda->cddb.disc->length =
124 cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
125 / CDIO_CD_FRAMES_PER_SEC;
127 if (!cddb_disc_calc_discid(p_cdda->cddb.disc))
129 msg_Err( p_access, "CDDB disc ID calculation failed" );
133 i_matches = cddb_query(conn, p_cdda->cddb.disc);
138 msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
140 cddb_read(conn, p_cdda->cddb.disc);
142 if (p_cdda->i_debug & INPUT_DBG_CDDB)
143 cddb_disc_print(p_cdda->cddb.disc);
148 msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
156 #endif /*HAVE_LIBCDDB*/
158 #define add_meta_val(VLC_META, VAL) \
159 if ( p_cdda->p_meta && VAL) { \
160 vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL ); \
161 dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL ); \
164 #define add_cddb_meta(FIELD, VLC_META) \
165 add_meta_val(VLC_META, p_cdda->cddb.disc->FIELD);
167 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
170 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
171 p_cdda->cddb.disc->FIELD ); \
172 psz_buf[sizeof(psz_buf)-1] = '\0'; \
173 add_meta_val(VLC_META, psz_buf); \
176 /* Adds a string-valued entry to the stream and media information if
177 the string is not null or the null string.
179 #define add_info_str(CATEGORY, TITLE, FIELD) \
180 if (FIELD && strlen(FIELD)) { \
181 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
182 _(TITLE), "%s", FIELD ); \
185 /* Adds a numeric-valued entry to the stream and media information
186 if the number is not zero. */
187 #define add_info_val(CATEGORY, TITLE, FMT, FIELD) \
189 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
190 _(TITLE), FMT, FIELD ); \
193 /* Adds a CDDB string-valued entry to the stream and media information
194 under category "Disc" if the string is not null or the null string.
196 #define add_cddb_disc_info_str(TITLE, FIELD) \
197 add_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
199 /* Adds a CDDB numeric-valued entry to the stream and media information
200 under category "Disc" if the string is not null or the null string.
202 #define add_cddb_disc_info_val(TITLE, FMT, FIELD) \
203 add_info_val("Disc", TITLE, FMT, p_cdda->cddb.disc->FIELD)
205 /* Adds a CD-Text string-valued entry to the stream and media information
206 under category "Disc" if the string is not null or the null string.
208 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD) \
209 add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
211 /* Adds a CD-Text string-valued entry to the stream and media information
212 under category "Disc" if the string is not null or the null string.
214 #define add_cdtext_disc_info_str(TITLE, FIELD) \
215 add_cdtext_info_str("Disc", TITLE, 0, FIELD)
219 Saves Meta Information about the CD-DA.
221 Meta information used in "stream and media info" or in playlist
222 info. The intialization of CD-Text or CDDB is done here though.
223 Therefore, this should be called before CDDAMetaInfo is called.
227 CDDAMetaInfoInit( access_t *p_access )
229 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
231 if ( ! p_cdda ) return;
233 p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
234 p_cdda->p_meta = vlc_meta_New();
237 if ( p_cdda->b_cddb_enabled )
239 GetCDDBInfo(p_access, p_cdda);
242 #endif /*HAVE_LIBCDDB*/
248 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
250 p_cdda->p_cdtext[i_track] =
251 cdio_get_cdtext(p_cdda->p_cdio, i_track);
257 In the Control routine, we handle Meta Information requests and
258 basically copy what was saved in CDDAMetaInfoInit.
260 If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
264 CDDAMetaInfo( access_t *p_access, track_t i_track )
266 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
267 char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
268 char *psz_meta_artist = NULL;
270 if ( ! p_cdda ) return;
274 /* Set up for Meta and name for CDDB access. */
275 if ( p_cdda->b_cddb_enabled && p_cdda->cddb.disc )
277 if( CDIO_INVALID_TRACK == i_track )
280 psz_meta_title = p_cdda->cddb.disc->title;
281 psz_meta_artist = p_cdda->cddb.disc->artist;
282 if ( p_cdda->cddb.disc->genre && strlen(p_cdda->cddb.disc->genre) )
283 add_cddb_meta(genre, VLC_META_GENRE);
284 if ( 0 != p_cdda->cddb.disc->year )
285 add_cddb_meta_fmt(year, "%d", VLC_META_DATE );
289 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
292 if( t->title != NULL && ! p_cdda->b_nav_mode )
294 add_meta_val( VLC_META_TITLE, t->title );
296 if( t->artist != NULL )
298 add_meta_val( VLC_META_ARTIST, t->artist );
304 #endif /*HAVE_LIBCDDB*/
308 track_t i = p_cdda->i_tracks;
309 const int i_first_track = p_cdda->i_first_track;
310 char psz_buffer[MSTRTIME_MAX_SIZE];
311 unsigned int i_track_frames =
312 cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
314 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
316 dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d",
317 (long int) i_duration, p_cdda->i_tracks );
318 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
319 _("Disc"), _("Duration"), "%s",
320 secstotimestr( psz_buffer, i_duration ) );
322 if (p_cdda->psz_mcn) {
323 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
324 _("Disc"), _("Media Catalog Number (MCN)"), "%s",
327 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
328 _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
333 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
335 add_cddb_disc_info_str("Artist (CDDB)", artist);
336 if ( CDDB_CAT_INVALID != p_cdda->cddb.disc->category )
337 add_info_str("Disc", "Category (CDDB)",
338 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
339 add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
340 add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
341 add_cddb_disc_info_str("Genre (CDDB)", genre);
342 add_cddb_disc_info_str("Title (CDDB)", title);
343 if ( 0 != p_cdda->cddb.disc->year )
344 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
347 #endif /*HAVE_LIBCDDB*/
349 if (p_cdda->p_cdtext[0])
353 add_cdtext_disc_info_str("Arranger (CD-Text)", CDTEXT_ARRANGER);
354 add_cdtext_disc_info_str("Composer (CD-Text)", CDTEXT_COMPOSER);
355 add_cdtext_disc_info_str("Disc ID (CD-Text)", CDTEXT_DISCID);
356 add_cdtext_disc_info_str("Genre (CD-Text)", CDTEXT_GENRE);
357 add_cdtext_disc_info_str("Message (CD-Text)", CDTEXT_MESSAGE);
358 add_cdtext_disc_info_str("Performer (CD-Text)", CDTEXT_PERFORMER);
359 add_cdtext_disc_info_str("Songwriter (CD-Text)", CDTEXT_SONGWRITER);
360 add_cdtext_disc_info_str("Title (CD-Text)", CDTEXT_TITLE);
362 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
363 if (psz_field && strlen(psz_field)) {
364 psz_meta_title = psz_field;
366 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
367 if (psz_field && strlen(psz_field)) {
368 psz_meta_artist = psz_field;
373 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
375 char psz_track[TITLE_MAX];
376 const track_t i_track = i_first_track + i;
377 unsigned int i_track_frames =
378 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
379 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
381 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
382 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
384 snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
386 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
388 secstotimestr( psz_buffer, i_duration ) );
390 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
391 _("MRL"), "%s", psz_mrl );
394 if (p_cdda->p_cdtext[i_track])
396 add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
397 i_track, CDTEXT_ARRANGER);
398 add_cdtext_info_str( psz_track, "Composer (CD-Text)",
399 i_track, CDTEXT_COMPOSER);
400 add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
401 i_track, CDTEXT_DISCID);
402 add_cdtext_info_str( psz_track, "Genre (CD-Text)",
403 i_track, CDTEXT_GENRE);
404 add_cdtext_info_str( psz_track, "Message (CD-Text)",
405 i_track, CDTEXT_MESSAGE);
406 add_cdtext_info_str( psz_track, "Performer (CD-Text)",
407 i_track, CDTEXT_PERFORMER);
408 add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
409 i_track, CDTEXT_SONGWRITER);
410 add_cdtext_info_str( psz_track, "Title (CD-Text)",
411 i_track, CDTEXT_TITLE);
415 if (p_cdda->b_cddb_enabled)
417 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
420 add_info_str(psz_track, "Artist (CDDB)", t->artist);
421 add_info_str(psz_track, "Title (CDDB)", t->title);
422 add_info_str(psz_track, "Extended Data (CDDB)",
426 #endif /*HAVE_LIBCDDB*/
429 /* Above we should have set psz_meta_title and psz_meta_artist
430 to CDDB or CD-Text values or the default value depending on
431 availablity and user preferences.
433 So now add the title and artist to VLC's meta, and the name
434 as shown in the status bar and playlist entry.
436 For playlist mode, the meta title is what's seen at the
437 bottom and in the playlist. For nav-mode playing, it is
438 done by input_control. I don't understand why they do
439 different things. In either case, we may have customized to
440 put in the track name.
442 if ( CDIO_INVALID_TRACK != i_track )
444 char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
445 if ( !p_cdda->b_nav_mode ) {
446 add_meta_val( VLC_META_TITLE, psz_name );
449 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
453 add_meta_val( VLC_META_ARTIST, psz_meta_artist );
459 #define add_format_str_info(val) \
461 const char *str = val; \
466 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
469 saw_control_prefix = false; \
473 #define add_format_num_info(val, fmt) \
477 sprintf(num_str, fmt, val); \
478 len=strlen(num_str); \
480 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
483 saw_control_prefix = false; \
488 cdda_data_t *p_cdda, char *psz_cdtext)
490 /* We either don't have CD-Text info, or we do but we prefer to get CDDB
491 which means CDDB has been enabled and we were able to retrieve the info.*/
493 return !psz_cdtext ||
494 (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
502 Take a format string and expand escape sequences, that is sequences that
503 begin with %, with information from the current CD.
504 The expanded string is returned. Here is a list of escape sequences:
506 %a : The album artist **
507 %A : The album information **
509 %e : The extended track data
513 %m : The CD-DA Media Catalog Number (MCN)
514 %n : The number of tracks on the CD
515 %p : The artist/performer/composer in the track **
516 %T : The track number **
517 %s : Number of seconds in this track, or seconds in CD if invalid track
518 %S : Number of seconds on the CD
519 %t : The track name or MRL if no name
520 %Y : The year 19xx or 20xx **
524 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
525 const char format_str[], const char *psz_mrl, track_t i_track)
527 #define TEMP_STR_SIZE 256
528 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
529 static char temp_str[TEMP_STR_SIZE];
531 char * tp = temp_str;
532 vlc_bool_t saw_control_prefix = false;
533 size_t format_len = strlen(format_str);
535 memset(temp_str, 0, TEMP_STR_SIZE);
537 for (i=0; i<format_len; i++)
541 if (!saw_control_prefix && format_str[i] != '%')
543 *tp++ = format_str[i];
544 saw_control_prefix = false;
548 switch(format_str[i])
551 if (saw_control_prefix)
555 saw_control_prefix = !saw_control_prefix;
559 if (p_cdda->p_cdtext[0]
560 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
561 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
562 if (want_cddb_info(p_cdda, psz))
563 psz = p_cdda->cddb.disc->artist;
566 if (p_cdda->p_cdtext[0]
567 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
568 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
569 if (want_cddb_info(p_cdda, psz))
570 psz = p_cdda->cddb.disc->title;
573 if (!p_cdda->b_cddb_enabled) goto not_special;
574 if (p_cdda->cddb.disc)
576 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
579 if (p_cdda->p_cdtext[0]
580 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
581 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
582 if (want_cddb_info(p_cdda, psz))
583 psz = p_cdda->cddb.disc->genre;
586 if (p_cdda->p_cdtext[0]
587 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
588 psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
589 if (want_cddb_info(p_cdda, psz)) {
590 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
592 add_format_str_info(psz);
595 if (!p_cdda->b_cddb_enabled) goto not_special;
596 if (p_cdda->cddb.disc)
597 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
600 if ( CDIO_INVALID_TRACK == i_track ) break;
601 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
603 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
605 if (t != NULL && t->title != NULL) {
606 add_format_str_info(t->title);
608 add_format_str_info(psz_mrl);
611 if (p_cdda->p_cdtext[i_track]
612 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]) {
613 add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
616 add_format_str_info(psz_mrl);
620 if ( CDIO_INVALID_TRACK == i_track ) break;
621 if (p_cdda->p_cdtext[i_track]
622 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
623 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
624 if (want_cddb_info(p_cdda, psz))
626 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
628 if (t != NULL && t->artist != NULL)
633 if ( CDIO_INVALID_TRACK == i_track ) break;
634 if (p_cdda->p_cdtext[i_track]
635 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
636 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
637 if (want_cddb_info(p_cdda, psz))
639 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
641 if (t != NULL && t->ext_data != NULL)
648 if (p_cdda->p_cdtext[0]
649 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
650 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
653 if (p_cdda->p_cdtext[0]
654 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
655 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
658 if (p_cdda->p_cdtext[0]
659 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
660 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
663 if (p_cdda->p_cdtext[0]
664 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
665 add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
668 if ( CDIO_INVALID_TRACK == i_track ) break;
669 if (p_cdda->p_cdtext[i_track]
670 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
671 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
674 if ( CDIO_INVALID_TRACK == i_track ) break;
675 if (p_cdda->p_cdtext[i_track]
676 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
677 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
682 if ( CDIO_INVALID_TRACK == i_track ) break;
683 if (p_cdda->p_cdtext[i_track]
684 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
685 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
688 #endif /*HAVE_LIBCDDB*/
691 if ( CDIO_INVALID_TRACK != i_track )
693 char psz_buffer[MSTRTIME_MAX_SIZE];
694 unsigned int i_track_frames =
695 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
697 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
698 add_format_str_info( secstotimestr( psz_buffer,
703 /* Fall through to disc duration if CDIO_INVALID_TRACK */
706 char psz_buffer[MSTRTIME_MAX_SIZE];
707 unsigned int i_track_frames =
708 cdio_get_track_lba(p_cdda->p_cdio,
709 CDIO_CDROM_LEADOUT_TRACK);
711 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
712 add_format_str_info( secstotimestr( psz_buffer,
718 add_format_str_info(psz_mrl);
722 add_format_str_info(p_cdda->psz_mcn);
726 add_format_num_info(p_cdda->i_tracks, "%d");
730 add_format_num_info(i_track, "%02d");
734 add_format_str_info(psz);
741 *tp++ = format_str[i];
742 saw_control_prefix = false;
745 return strdup(temp_str);
748 /* Return a MRL for the given track. The caller must free the
751 CDDAFormatMRL( const access_t *p_access, track_t i_track )
753 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
754 const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX)
755 + strlen(p_cdda->psz_source) +
756 + strlen("@T") + strlen("100") + 1;
757 char *psz_mrl = calloc( 1, psz_mrl_max );
759 if (CDIO_INVALID_TRACK == i_track)
760 snprintf(psz_mrl, psz_mrl_max, "%s%s",
761 CDDA_MRL_PREFIX, p_cdda->psz_source);
763 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
764 CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
769 /* Return a title string as specified by the titel format string for the
770 given track. The caller must free the allocated string. */
772 CDDAFormatTitle( const access_t *p_access, track_t i_track )
775 char *config_varname = MODULE_STRING "-title-format";
776 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
777 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
783 if (p_cdda->b_cddb_enabled)
785 config_varname = MODULE_STRING "-cddb-title-format";
787 #endif /*HAVE_LIBCDDB*/
789 CDDAFormatStr( p_access, p_cdda,
790 config_GetPsz( p_access, config_varname ),
798 /* Adds a string-valued entry to the playlist information under "Track"
799 if the string is not null or the null string.
801 #define add_playlist_track_info_str(TITLE, FIELD) \
802 if (FIELD && strlen(FIELD)) \
804 vlc_input_item_AddInfo( &p_item->input, _("Track"), _(TITLE), \
808 static playlist_item_t *
809 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
810 playlist_t *p_playlist, playlist_item_t *p_item,
813 unsigned int i_track_frames =
814 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
815 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
816 mtime_t i_mduration =
817 i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
818 char *psz_title = NULL;
819 char *psz_mrl = NULL;
821 playlist_item_t *p_child = NULL;
823 if( !p_item ) return NULL;
825 psz_title = CDDAFormatTitle( p_access, i_track ) ;
826 psz_mrl = CDDAFormatMRL( p_access, i_track ) ;
828 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
829 psz_mrl, psz_title, (long int) i_mduration / 1000000 );
831 p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
832 p_child->input.i_duration = i_mduration;
836 if( !p_child ) return NULL;
838 playlist_NodeAddItem( p_playlist, p_child,
839 p_item->pp_parents[0]->i_view,
840 p_item, PLAYLIST_APPEND, PLAYLIST_END );
841 playlist_CopyParents( p_item, p_child );
846 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
847 playlist_item_t *p_item, int i_track,
848 vlc_bool_t b_single )
850 add_playlist_track_info_str("Source", p_cdda->psz_source);
851 vlc_input_item_AddInfo( &p_item->input, _("Track"), _("Track Number"),
854 if (p_cdda->p_cdtext[i_track])
856 const cdtext_t *p = p_cdda->p_cdtext[i_track];
857 add_playlist_track_info_str("Arranger (CD-Text)",
858 p->field[CDTEXT_ARRANGER]);
859 add_playlist_track_info_str("Composer (CD-Text)",
860 p->field[CDTEXT_COMPOSER]);
861 add_playlist_track_info_str("Genre (CD-Text)",
862 p->field[CDTEXT_GENRE]);
863 add_playlist_track_info_str("Message (CD-Text)",
864 p->field[CDTEXT_MESSAGE]);
865 add_playlist_track_info_str("Performer (CD-Text)",
866 p->field[CDTEXT_PERFORMER]);
867 add_playlist_track_info_str("Songwriter (CD-Text)",
868 p->field[CDTEXT_SONGWRITER]);
869 add_playlist_track_info_str("Title (CD-Text)",
870 p->field[CDTEXT_TITLE]);
874 if (p_cdda->b_cddb_enabled)
876 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
877 i_track-p_cdda->i_first_track);
882 add_playlist_track_info_str("Artist (CDDB)",
885 add_playlist_track_info_str("Title (CDDB)",
888 add_playlist_track_info_str("Extended information (CDDB)",
892 #endif /*HAVE_LIBCDDB*/
901 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
902 vlc_bool_t b_single_track )
905 playlist_t * p_playlist = NULL;
906 const track_t i_first_track = p_cdda->i_first_track;
907 playlist_item_t *p_item = NULL;
908 vlc_bool_t b_play = VLC_FALSE;
912 p_cdda->b_cddb_enabled =
913 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
914 if( b_single_track && !p_cdda->b_cddb_enabled )
921 if (! p_cdda->b_nav_mode ) {
922 p_playlist = (playlist_t *) vlc_object_find( p_access,
927 msg_Warn( p_access, "can't find playlist" );
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 p_item = playlist_LockItemGetByInput( p_playlist,
945 ((input_thread_t *)p_access->p_parent)->input.p_item );
947 if( p_item == p_playlist->status.p_item && !b_single_track )
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;
977 CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
978 p_item->input.i_duration = i_track_frames
979 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
980 p_item->input.psz_uri = 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 );
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;
1020 p_item->input.i_duration =
1021 p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
1022 p_item->input.psz_uri = CDDAFormatMRL(p_access,
1030 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
1031 p_playlist->status.i_view,
1032 p_playlist->status.p_item, NULL );
1035 if (p_playlist) vlc_object_release( p_playlist );