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 dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d",
236 p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
237 p_cdda->p_meta = vlc_meta_New();
240 if ( p_cdda->b_cddb_enabled )
242 GetCDDBInfo(p_access, p_cdda);
245 #endif /*HAVE_LIBCDDB*/
251 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
253 p_cdda->p_cdtext[i_track] =
254 cdio_get_cdtext(p_cdda->p_cdio, i_track);
260 In the Control routine, we handle Meta Information requests and
261 basically copy what was saved in CDDAMetaInfoInit.
263 If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
267 CDDAMetaInfo( access_t *p_access, track_t i_track )
269 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
270 char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
271 char *psz_meta_artist = NULL;
273 if ( ! p_cdda ) return;
275 dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
279 /* Set up for Meta and name for CDDB access. */
280 if ( p_cdda->b_cddb_enabled && p_cdda->cddb.disc )
282 if( CDIO_INVALID_TRACK == i_track )
285 psz_meta_title = p_cdda->cddb.disc->title;
286 psz_meta_artist = p_cdda->cddb.disc->artist;
287 if ( p_cdda->cddb.disc->genre && strlen(p_cdda->cddb.disc->genre) )
288 add_cddb_meta(genre, VLC_META_GENRE);
289 if ( 0 != p_cdda->cddb.disc->year )
290 add_cddb_meta_fmt(year, "%d", VLC_META_DATE );
294 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
297 if( t->title != NULL && ! p_cdda->b_nav_mode )
299 add_meta_val( VLC_META_TITLE, t->title );
301 if( t->artist != NULL )
303 add_meta_val( VLC_META_ARTIST, t->artist );
309 #endif /*HAVE_LIBCDDB*/
313 track_t i = p_cdda->i_tracks;
314 const int i_first_track = p_cdda->i_first_track;
315 char psz_buffer[MSTRTIME_MAX_SIZE];
316 unsigned int i_track_frames =
317 cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
319 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
321 dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d",
322 (long int) i_duration, p_cdda->i_tracks );
323 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
324 _("Disc"), _("Duration"), "%s",
325 secstotimestr( psz_buffer, i_duration ) );
327 if (p_cdda->psz_mcn) {
328 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
329 _("Disc"), _("Media Catalog Number (MCN)"), "%s",
332 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
333 _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
338 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
340 add_cddb_disc_info_str("Artist (CDDB)", artist);
341 if ( CDDB_CAT_INVALID != p_cdda->cddb.disc->category )
342 add_info_str("Disc", "Category (CDDB)",
343 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
344 add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
345 add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
346 add_cddb_disc_info_str("Genre (CDDB)", genre);
347 add_cddb_disc_info_str("Title (CDDB)", title);
348 if ( 0 != p_cdda->cddb.disc->year )
349 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
352 #endif /*HAVE_LIBCDDB*/
354 if (p_cdda->p_cdtext[0])
358 add_cdtext_disc_info_str("Arranger (CD-Text)", CDTEXT_ARRANGER);
359 add_cdtext_disc_info_str("Composer (CD-Text)", CDTEXT_COMPOSER);
360 add_cdtext_disc_info_str("Disc ID (CD-Text)", CDTEXT_DISCID);
361 add_cdtext_disc_info_str("Genre (CD-Text)", CDTEXT_GENRE);
362 add_cdtext_disc_info_str("Message (CD-Text)", CDTEXT_MESSAGE);
363 add_cdtext_disc_info_str("Performer (CD-Text)", CDTEXT_PERFORMER);
364 add_cdtext_disc_info_str("Songwriter (CD-Text)", CDTEXT_SONGWRITER);
365 add_cdtext_disc_info_str("Title (CD-Text)", CDTEXT_TITLE);
367 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
368 if (psz_field && strlen(psz_field)) {
369 psz_meta_title = psz_field;
371 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
372 if (psz_field && strlen(psz_field)) {
373 psz_meta_artist = psz_field;
378 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
380 char psz_track[TITLE_MAX];
381 const track_t i_track = i_first_track + i;
382 unsigned int i_track_frames =
383 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
384 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
386 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
387 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
389 snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
391 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
393 secstotimestr( psz_buffer, i_duration ) );
395 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
396 _("MRL"), "%s", psz_mrl );
399 if (p_cdda->p_cdtext[i_track])
401 add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
402 i_track, CDTEXT_ARRANGER);
403 add_cdtext_info_str( psz_track, "Composer (CD-Text)",
404 i_track, CDTEXT_COMPOSER);
405 add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
406 i_track, CDTEXT_DISCID);
407 add_cdtext_info_str( psz_track, "Genre (CD-Text)",
408 i_track, CDTEXT_GENRE);
409 add_cdtext_info_str( psz_track, "Message (CD-Text)",
410 i_track, CDTEXT_MESSAGE);
411 add_cdtext_info_str( psz_track, "Performer (CD-Text)",
412 i_track, CDTEXT_PERFORMER);
413 add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
414 i_track, CDTEXT_SONGWRITER);
415 add_cdtext_info_str( psz_track, "Title (CD-Text)",
416 i_track, CDTEXT_TITLE);
420 if (p_cdda->b_cddb_enabled)
422 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
425 add_info_str(psz_track, "Artist (CDDB)", t->artist);
426 add_info_str(psz_track, "Title (CDDB)", t->title);
427 add_info_str(psz_track, "Extended Data (CDDB)",
431 #endif /*HAVE_LIBCDDB*/
434 /* Above we should have set psz_meta_title and psz_meta_artist
435 to CDDB or CD-Text values or the default value depending on
436 availablity and user preferences.
438 So now add the title and artist to VLC's meta, and the name
439 as shown in the status bar and playlist entry.
441 For playlist mode, the meta title is what's seen at the
442 bottom and in the playlist. For nav-mode playing, it is
443 done by input_control. I don't understand why they do
444 different things. In either case, we may have customized to
445 put in the track name.
447 if ( CDIO_INVALID_TRACK != i_track )
449 char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
450 if ( !p_cdda->b_nav_mode ) {
451 add_meta_val( VLC_META_TITLE, psz_name );
454 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
458 add_meta_val( VLC_META_ARTIST, psz_meta_artist );
464 #define add_format_str_info(val) \
466 const char *str = val; \
471 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
474 saw_control_prefix = false; \
478 #define add_format_num_info(val, fmt) \
482 sprintf(num_str, fmt, val); \
483 len=strlen(num_str); \
485 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
488 saw_control_prefix = false; \
493 cdda_data_t *p_cdda, char *psz_cdtext)
495 /* We either don't have CD-Text info, or we do but we prefer to get CDDB
496 which means CDDB has been enabled and we were able to retrieve the info.*/
498 return !psz_cdtext ||
499 (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
507 Take a format string and expand escape sequences, that is sequences that
508 begin with %, with information from the current CD.
509 The expanded string is returned. Here is a list of escape sequences:
511 %a : The album artist **
512 %A : The album information **
514 %e : The extended track data
518 %m : The CD-DA Media Catalog Number (MCN)
519 %n : The number of tracks on the CD
520 %p : The artist/performer/composer in the track **
521 %T : The track number **
522 %s : Number of seconds in this track, or seconds in CD if invalid track
523 %S : Number of seconds on the CD
524 %t : The track name or MRL if no name
525 %Y : The year 19xx or 20xx **
529 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
530 const char format_str[], const char *psz_mrl, track_t i_track)
532 #define TEMP_STR_SIZE 256
533 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
534 static char temp_str[TEMP_STR_SIZE];
536 char * tp = temp_str;
537 vlc_bool_t saw_control_prefix = false;
538 size_t format_len = strlen(format_str);
540 memset(temp_str, 0, TEMP_STR_SIZE);
542 for (i=0; i<format_len; i++)
546 if (!saw_control_prefix && format_str[i] != '%')
548 *tp++ = format_str[i];
549 saw_control_prefix = false;
553 switch(format_str[i])
556 if (saw_control_prefix)
560 saw_control_prefix = !saw_control_prefix;
564 if (p_cdda->p_cdtext[0]
565 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
566 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
567 if (want_cddb_info(p_cdda, psz))
568 psz = p_cdda->cddb.disc->artist;
571 if (p_cdda->p_cdtext[0]
572 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
573 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
574 if (want_cddb_info(p_cdda, psz))
575 psz = p_cdda->cddb.disc->title;
578 if (!p_cdda->b_cddb_enabled) goto not_special;
579 if (p_cdda->cddb.disc)
581 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
584 if (p_cdda->p_cdtext[0]
585 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
586 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
587 if (want_cddb_info(p_cdda, psz))
588 psz = p_cdda->cddb.disc->genre;
591 if (p_cdda->p_cdtext[0]
592 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
593 psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
594 if (want_cddb_info(p_cdda, psz)) {
595 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
597 add_format_str_info(psz);
600 if (!p_cdda->b_cddb_enabled) goto not_special;
601 if (p_cdda->cddb.disc)
602 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
605 if ( CDIO_INVALID_TRACK == i_track ) break;
606 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
608 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
610 if (t != NULL && t->title != NULL) {
611 add_format_str_info(t->title);
613 add_format_str_info(psz_mrl);
616 if (p_cdda->p_cdtext[i_track]
617 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]) {
618 add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
621 add_format_str_info(psz_mrl);
625 if ( CDIO_INVALID_TRACK == i_track ) break;
626 if (p_cdda->p_cdtext[i_track]
627 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
628 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
629 if (want_cddb_info(p_cdda, psz))
631 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
633 if (t != NULL && t->artist != NULL)
638 if ( CDIO_INVALID_TRACK == i_track ) break;
639 if (p_cdda->p_cdtext[i_track]
640 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
641 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
642 if (want_cddb_info(p_cdda, psz))
644 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
646 if (t != NULL && t->ext_data != NULL)
653 if (p_cdda->p_cdtext[0]
654 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
655 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
658 if (p_cdda->p_cdtext[0]
659 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
660 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
663 if (p_cdda->p_cdtext[0]
664 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
665 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
668 if (p_cdda->p_cdtext[0]
669 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
670 add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
673 if ( CDIO_INVALID_TRACK == i_track ) break;
674 if (p_cdda->p_cdtext[i_track]
675 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
676 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
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_TITLE])
682 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
687 if ( CDIO_INVALID_TRACK == i_track ) break;
688 if (p_cdda->p_cdtext[i_track]
689 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
690 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
693 #endif /*HAVE_LIBCDDB*/
696 if ( CDIO_INVALID_TRACK != i_track )
698 char psz_buffer[MSTRTIME_MAX_SIZE];
699 unsigned int i_track_frames =
700 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
702 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
703 add_format_str_info( secstotimestr( psz_buffer,
708 /* Fall through to disc duration if CDIO_INVALID_TRACK */
711 char psz_buffer[MSTRTIME_MAX_SIZE];
712 unsigned int i_track_frames =
713 cdio_get_track_lba(p_cdda->p_cdio,
714 CDIO_CDROM_LEADOUT_TRACK);
716 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
717 add_format_str_info( secstotimestr( psz_buffer,
723 add_format_str_info(psz_mrl);
727 add_format_str_info(p_cdda->psz_mcn);
731 add_format_num_info(p_cdda->i_tracks, "%d");
735 add_format_num_info(i_track, "%02d");
739 add_format_str_info(psz);
746 *tp++ = format_str[i];
747 saw_control_prefix = false;
750 return strdup(temp_str);
753 /* Return a MRL for the given track. The caller must free the
756 CDDAFormatMRL( const access_t *p_access, track_t i_track )
758 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
759 const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX)
760 + strlen(p_cdda->psz_source) +
761 + strlen("@T") + strlen("100") + 1;
762 char *psz_mrl = calloc( 1, psz_mrl_max );
764 if (CDIO_INVALID_TRACK == i_track)
765 snprintf(psz_mrl, psz_mrl_max, "%s%s",
766 CDDA_MRL_PREFIX, p_cdda->psz_source);
768 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
769 CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
774 /* Return a title string as specified by the titel format string for the
775 given track. The caller must free the allocated string. */
777 CDDAFormatTitle( const access_t *p_access, track_t i_track )
780 char *config_varname = MODULE_STRING "-title-format";
781 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
782 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
788 if (p_cdda->b_cddb_enabled)
790 config_varname = MODULE_STRING "-cddb-title-format";
792 #endif /*HAVE_LIBCDDB*/
794 CDDAFormatStr( p_access, p_cdda,
795 config_GetPsz( p_access, config_varname ),
803 /* Adds a string-valued entry to the playlist information under "Track"
804 if the string is not null or the null string.
806 #define add_playlist_track_info_str(TITLE, FIELD) \
807 if (FIELD && strlen(FIELD)) \
809 vlc_input_item_AddInfo( &p_item->input, _("Track"), _(TITLE), \
813 static playlist_item_t *
814 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
815 playlist_t *p_playlist, playlist_item_t *p_item,
818 unsigned int i_track_frames =
819 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
820 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
821 mtime_t i_mduration =
822 i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
823 char *psz_title = NULL;
824 char *psz_mrl = NULL;
826 playlist_item_t *p_child = NULL;
828 if( !p_item ) return NULL;
830 psz_title = CDDAFormatTitle( p_access, i_track ) ;
831 psz_mrl = CDDAFormatMRL( p_access, i_track ) ;
833 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
834 psz_mrl, psz_title, (long int) i_mduration / 1000000 );
836 p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
837 p_child->input.i_duration = i_mduration;
841 if( !p_child ) return NULL;
843 playlist_NodeAddItem( p_playlist, p_child,
844 p_item->pp_parents[0]->i_view,
845 p_item, PLAYLIST_APPEND, PLAYLIST_END );
846 playlist_CopyParents( p_item, p_child );
851 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
852 playlist_item_t *p_item, int i_track,
853 vlc_bool_t b_single )
855 add_playlist_track_info_str("Source", p_cdda->psz_source);
856 vlc_input_item_AddInfo( &p_item->input, _("Track"), _("Track Number"),
859 if (p_cdda->p_cdtext[i_track])
861 const cdtext_t *p = p_cdda->p_cdtext[i_track];
862 add_playlist_track_info_str("Arranger (CD-Text)",
863 p->field[CDTEXT_ARRANGER]);
864 add_playlist_track_info_str("Composer (CD-Text)",
865 p->field[CDTEXT_COMPOSER]);
866 add_playlist_track_info_str("Genre (CD-Text)",
867 p->field[CDTEXT_GENRE]);
868 add_playlist_track_info_str("Message (CD-Text)",
869 p->field[CDTEXT_MESSAGE]);
870 add_playlist_track_info_str("Performer (CD-Text)",
871 p->field[CDTEXT_PERFORMER]);
872 add_playlist_track_info_str("Songwriter (CD-Text)",
873 p->field[CDTEXT_SONGWRITER]);
874 add_playlist_track_info_str("Title (CD-Text)",
875 p->field[CDTEXT_TITLE]);
879 if (p_cdda->b_cddb_enabled)
881 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
882 i_track-p_cdda->i_first_track);
887 add_playlist_track_info_str("Artist (CDDB)",
890 add_playlist_track_info_str("Title (CDDB)",
893 add_playlist_track_info_str("Extended information (CDDB)",
897 #endif /*HAVE_LIBCDDB*/
906 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
907 vlc_bool_t b_single_track )
910 playlist_t * p_playlist = NULL;
911 const track_t i_first_track = p_cdda->i_first_track;
912 playlist_item_t *p_item = NULL;
913 vlc_bool_t b_play = VLC_FALSE;
917 p_cdda->b_cddb_enabled =
918 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
919 if( b_single_track && !p_cdda->b_cddb_enabled )
926 if (! p_cdda->b_nav_mode ) {
927 p_playlist = (playlist_t *) vlc_object_find( p_access,
932 msg_Warn( p_access, "can't find playlist" );
937 if( b_single_track || p_cdda->b_nav_mode ) {
938 i_track = p_cdda->i_track;
942 i_track = CDIO_INVALID_TRACK;
944 CDDAMetaInfoInit( p_access );
945 CDDAMetaInfo( p_access, p_cdda->i_track );
949 p_item = playlist_LockItemGetByInput( p_playlist,
950 ((input_thread_t *)p_access->p_parent)->input.p_item );
952 if( p_item == p_playlist->status.p_item && !b_single_track )
962 if( b_single_track && !p_cdda->b_nav_mode )
964 /*May fill out more information when the playlist user interface becomes
967 track_t i_track = p_cdda->i_track;
968 unsigned int i_track_frames =
969 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
971 input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
972 vlc_input_title_New();
974 asprintf( &t->psz_name, _("Track %i"), i_track );
975 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
977 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
982 CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
983 p_item->input.i_duration = i_track_frames
984 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
985 p_item->input.psz_uri = CDDAFormatMRL(p_access, i_track);
988 p_cdda->i_titles = 1;
989 p_access->info.i_update = INPUT_UPDATE_TITLE;
995 if ( !p_cdda->b_nav_mode )
996 playlist_ItemToNode( p_playlist, p_item );
998 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
1000 playlist_item_t *p_child;
1001 const track_t i_track = i_first_track + i;
1002 unsigned int i_track_frames =
1003 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
1005 t = p_cdda->p_title[i] = vlc_input_title_New();
1007 asprintf( &t->psz_name, _("Track %i"), i_track );
1008 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
1010 t->i_length = I64C(1000000) * t->i_size
1011 / CDDA_FREQUENCY_SAMPLE / 4;
1013 if ( ! p_cdda->b_nav_mode ) {
1014 p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
1017 CDDAAddMetaToItem( p_access, p_cdda, p_child, i_track,
1022 p_cdda->i_titles = p_cdda->i_tracks;
1023 p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1025 p_item->input.i_duration =
1026 p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
1027 p_item->input.psz_uri = CDDAFormatMRL(p_access,
1035 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
1036 p_playlist->status.i_view,
1037 p_playlist->status.p_item, NULL );
1040 if (p_playlist) vlc_object_release( p_playlist );