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 */
30 #warning playlist code must not be used here.
31 #include <vlc_playlist.h> /* Has to come *after* cdda.h */
33 #include <cdio/cdio.h>
34 #include <cdio/cdtext.h>
35 #include <cdio/logging.h>
36 #include <cdio/cd_types.h>
43 static char *CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
44 const char format_str[], const char *psz_mrl,
47 static char *CDDAFormatMRL( const access_t *p_access, track_t i_track );
51 #define free_and_dup(var, val) \
53 if (val) var=strdup(val);
56 /* Saves CDDB information about CD-DA via libcddb. */
58 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
61 cddb_conn_t *conn = cddb_new();
62 const CdIo_t *p_cdio = p_cdda->p_cdio;
64 dbg_print( (INPUT_DBG_CALL), "" );
67 cddb_log_set_handler (uninit_log_handler);
72 msg_Warn( p_access, "Unable to initialize libcddb" );
76 char* psz_email = config_GetPsz( p_access, MODULE_STRING "-cddb-email");
77 char* psz_srv_name = config_GetPsz( p_access, MODULE_STRING "-cddb-server");
78 cddb_set_email_address( conn, psz_email );
79 cddb_set_server_name( conn, psz_srv_name );
80 cddb_set_server_port(conn,
81 config_GetInt( p_access,
82 MODULE_STRING "-cddb-port") );
86 /* Set the location of the local CDDB cache directory.
87 The default location of this directory is */
89 if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
90 cddb_cache_disable(conn);
92 char* psz_cache = config_GetPsz( p_access, MODULE_STRING "-cddb-cachedir");
93 cddb_cache_set_dir(conn, psz_cache );
96 cddb_set_timeout(conn,
97 config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
100 if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" ) )
102 cddb_http_enable(conn);
106 cddb_http_disable(conn);
109 p_cdda->cddb.disc = cddb_disc_new();
111 if (!p_cdda->cddb.disc)
113 msg_Err( p_access, "Unable to create CDDB disc structure." );
117 for(i = 0; i < p_cdda->i_tracks; i++)
119 track_t i_track = p_cdda->i_first_track + i;
120 cddb_track_t *t = cddb_track_new();
121 cddb_track_set_frame_offset(t,
122 cdio_get_track_lba(p_cdio, i_track));
123 cddb_disc_add_track(p_cdda->cddb.disc, t);
126 cddb_disc_set_length(p_cdda->cddb.disc,
127 cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
128 / CDIO_CD_FRAMES_PER_SEC);
130 if (!cddb_disc_calc_discid(p_cdda->cddb.disc))
132 msg_Err( p_access, "CDDB disc ID calculation failed" );
136 i_matches = cddb_query(conn, p_cdda->cddb.disc);
141 msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
143 cddb_read(conn, p_cdda->cddb.disc);
145 if (p_cdda->i_debug & INPUT_DBG_CDDB)
146 cddb_disc_print(p_cdda->cddb.disc);
151 msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
159 #endif /*HAVE_LIBCDDB*/
161 #define add_meta_val(VLC_META, VAL) \
162 if ( p_cdda->p_meta && VAL) { \
163 /*vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL );*/ \
164 dbg_print( INPUT_DBG_META, "field %s: %s\n", \
165 input_MetaTypeToLocalizedString(VLC_META), VAL ); \
168 #define add_cddb_meta(FIELD, VLC_META) \
169 add_meta_val(VLC_META, cddb_disc_get_##FIELD(p_cdda->cddb.disc));
171 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
174 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
175 cddb_disc_get_##FIELD(p_cdda->cddb.disc)); \
176 psz_buf[sizeof(psz_buf)-1] = '\0'; \
177 add_meta_val(VLC_META, psz_buf); \
180 /* Adds a string-valued entry to the stream and media information if
181 the string is not null or the null string.
183 #define add_info_str(CATEGORY, TITLE, FIELD) \
184 if (FIELD && strlen(FIELD)) { \
185 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
186 _(TITLE), "%s", FIELD ); \
189 /* Adds a numeric-valued entry to the stream and media information
190 if the number is not zero. */
191 #define add_info_val(CATEGORY, TITLE, FMT, FIELD) \
193 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
194 _(TITLE), FMT, FIELD ); \
197 /* Adds a CDDB string-valued entry to the stream and media information
198 under category "Disc" if the string is not null or the null string.
200 #define add_cddb_disc_info_str(TITLE, FIELD) \
201 add_info_str("Disc", TITLE, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
203 /* Adds a CDDB numeric-valued entry to the stream and media information
204 under category "Disc" if the string is not null or the null string.
206 #define add_cddb_disc_info_val(TITLE, FMT, FIELD) \
207 add_info_val("Disc", TITLE, FMT, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
209 /* Adds a CD-Text string-valued entry to the stream and media information
210 under category "Disc" if the string is not null or the null string.
212 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD) \
213 add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
215 /* Adds a CD-Text string-valued entry to the stream and media information
216 under category "Disc" if the string is not null or the null string.
218 #define add_cdtext_disc_info_str(TITLE, FIELD) \
219 add_cdtext_info_str("Disc", TITLE, 0, FIELD)
223 Saves Meta Information about the CD-DA.
225 Meta information used in "stream and media info" or in playlist
226 info. The intialization of CD-Text or CDDB is done here though.
227 Therefore, this should be called before CDDAMetaInfo is called.
231 CDDAMetaInfoInit( access_t *p_access )
233 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
235 if ( ! p_cdda ) return;
237 dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d",
240 p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
242 p_cdda->p_meta = vlc_meta_New();
246 if ( p_cdda->b_cddb_enabled )
248 GetCDDBInfo(p_access, p_cdda);
251 #endif /*HAVE_LIBCDDB*/
257 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
259 p_cdda->p_cdtext[i_track] =
260 cdio_get_cdtext(p_cdda->p_cdio, i_track);
266 In the Control routine, we handle Meta Information requests and
267 basically copy what was saved in CDDAMetaInfoInit.
269 If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
273 CDDAMetaInfo( access_t *p_access, track_t i_track )
275 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
276 char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
277 char *psz_meta_artist = NULL;
279 if ( ! p_cdda ) return;
281 dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
285 /* Set up for Meta and name for CDDB access. */
286 if ( p_cdda->b_cddb_enabled && p_cdda->cddb.disc )
288 if( CDIO_INVALID_TRACK == i_track )
291 psz_meta_title = (char *)cddb_disc_get_title(p_cdda->cddb.disc);
292 psz_meta_artist = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
293 if ( cddb_disc_get_genre(p_cdda->cddb.disc) &&
294 strlen(cddb_disc_get_genre(p_cdda->cddb.disc)) )
295 add_cddb_meta(genre, vlc_meta_Genre);
296 if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc))
297 add_cddb_meta_fmt(year, "%d", vlc_meta_Date );
301 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
304 if( cddb_track_get_title(t) != NULL && ! p_cdda->b_nav_mode )
306 add_meta_val( vlc_meta_Title, cddb_track_get_title(t) );
308 if( cddb_track_get_artist(t) != NULL )
310 add_meta_val( vlc_meta_Artist, cddb_track_get_artist(t) );
315 #endif /*HAVE_LIBCDDB*/
319 track_t i = p_cdda->i_tracks;
320 const int i_first_track = p_cdda->i_first_track;
321 char psz_buffer[MSTRTIME_MAX_SIZE];
322 unsigned int i_track_frames =
323 cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
325 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
327 dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d",
328 (long int) i_duration, p_cdda->i_tracks );
329 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
330 _("Disc"), _("Duration"), "%s",
331 secstotimestr( psz_buffer, i_duration ) );
335 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
336 _("Disc"), _("Media Catalog Number (MCN)"), "%s",
338 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
339 _("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;
381 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
383 char psz_track[TITLE_MAX];
384 const track_t i_track = i_first_track + i;
385 unsigned int i_track_frames =
386 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
387 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
389 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
390 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
392 snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
394 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
396 secstotimestr( psz_buffer, i_duration ) );
398 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
399 _("MRL"), "%s", psz_mrl );
402 if (p_cdda->p_cdtext[i_track])
404 add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
405 i_track, CDTEXT_ARRANGER);
406 add_cdtext_info_str( psz_track, "Composer (CD-Text)",
407 i_track, CDTEXT_COMPOSER);
408 add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
409 i_track, CDTEXT_DISCID);
410 add_cdtext_info_str( psz_track, "Genre (CD-Text)",
411 i_track, CDTEXT_GENRE);
412 add_cdtext_info_str( psz_track, "Message (CD-Text)",
413 i_track, CDTEXT_MESSAGE);
414 add_cdtext_info_str( psz_track, "Performer (CD-Text)",
415 i_track, CDTEXT_PERFORMER);
416 add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
417 i_track, CDTEXT_SONGWRITER);
418 add_cdtext_info_str( psz_track, "Title (CD-Text)",
419 i_track, CDTEXT_TITLE);
423 if (p_cdda->b_cddb_enabled)
425 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
428 add_info_str(psz_track, "Artist (CDDB)",
429 cddb_track_get_artist(t));
430 add_info_str(psz_track, "Title (CDDB)",
431 cddb_track_get_title(t));
432 add_info_str(psz_track, "Extended Data (CDDB)",
433 cddb_track_get_ext_data(t));
436 #endif /*HAVE_LIBCDDB*/
439 /* Above we should have set psz_meta_title and psz_meta_artist
440 to CDDB or CD-Text values or the default value depending on
441 availablity and user preferences.
443 So now add the title and artist to VLC's meta, and the name
444 as shown in the status bar and playlist entry.
446 For playlist mode, the meta title is what's seen at the
447 bottom and in the playlist. For nav-mode playing, it is
448 done by input_control. I don't understand why they do
449 different things. In either case, we may have customized to
450 put in the track name.
452 if ( CDIO_INVALID_TRACK != i_track )
454 char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
455 if ( !p_cdda->b_nav_mode ) {
456 add_meta_val( vlc_meta_Title, psz_name );
459 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
463 add_meta_val( vlc_meta_Artist, psz_meta_artist );
468 #define add_format_str_info(val) \
470 const char *str = val; \
475 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
478 saw_control_prefix = false; \
482 #define add_format_num_info(val, fmt) \
486 sprintf(num_str, fmt, val); \
487 len=strlen(num_str); \
489 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
492 saw_control_prefix = false; \
497 cdda_data_t *p_cdda, char *psz_cdtext)
499 /* We either don't have CD-Text info, or we do but we prefer to get CDDB
500 which means CDDB has been enabled and we were able to retrieve the info.*/
502 return !psz_cdtext ||
503 (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
511 Take a format string and expand escape sequences, that is sequences that
512 begin with %, with information from the current CD.
513 The expanded string is returned. Here is a list of escape sequences:
515 %a : The album artist **
516 %A : The album information **
518 %e : The extended track data
522 %m : The CD-DA Media Catalog Number (MCN)
523 %n : The number of tracks on the CD
524 %p : The artist/performer/composer in the track **
525 %T : The track number **
526 %s : Number of seconds in this track, or seconds in CD if invalid track
527 %S : Number of seconds on the CD
528 %t : The track name or MRL if no name
529 %Y : The year 19xx or 20xx **
533 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
534 const char format_str[], const char *psz_mrl, track_t i_track)
536 #define TEMP_STR_SIZE 256
537 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
538 static char temp_str[TEMP_STR_SIZE];
540 char * tp = temp_str;
541 bool saw_control_prefix = false;
542 size_t format_len = strlen(format_str);
544 memset(temp_str, 0, TEMP_STR_SIZE);
546 for (i=0; i<format_len; i++)
550 if (!saw_control_prefix && format_str[i] != '%')
552 *tp++ = format_str[i];
553 saw_control_prefix = false;
557 switch(format_str[i])
560 if (saw_control_prefix)
564 saw_control_prefix = !saw_control_prefix;
568 if (p_cdda->p_cdtext[0]
569 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
570 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
571 if (want_cddb_info(p_cdda, psz))
572 psz = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
575 if (p_cdda->p_cdtext[0]
576 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
577 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
578 if (want_cddb_info(p_cdda, psz))
579 psz = (char *)cddb_disc_get_title(p_cdda->cddb.disc);
582 if (!p_cdda->b_cddb_enabled) goto not_special;
583 if (p_cdda->cddb.disc)
584 add_format_str_info(CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
587 if (p_cdda->p_cdtext[0]
588 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
589 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
590 if (want_cddb_info(p_cdda, psz))
591 psz = (char *)cddb_disc_get_genre(p_cdda->cddb.disc);
594 if (p_cdda->p_cdtext[0]
595 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
596 psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
597 if (want_cddb_info(p_cdda, psz)) {
598 add_format_num_info(cddb_disc_get_discid(p_cdda->cddb.disc), "%x");
600 add_format_str_info(psz);
603 if (!p_cdda->b_cddb_enabled) goto not_special;
604 if (p_cdda->cddb.disc)
605 add_format_num_info(cddb_disc_get_year(p_cdda->cddb.disc),
609 if ( CDIO_INVALID_TRACK == i_track ) break;
610 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
612 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
614 if (t != NULL && cddb_track_get_title(t) != NULL) {
615 add_format_str_info(cddb_track_get_title(t));
617 add_format_str_info(psz_mrl);
622 if (p_cdda->p_cdtext[i_track]
623 && 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*/
800 char* psz_config_varname = config_GetPsz( p_access, config_varname );
801 psz_name = CDDAFormatStr( p_access, p_cdda, psz_config_varname,
803 free( psz_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( 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_Hold( 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), pl_Unlocked );
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 if( asprintf( &t->psz_name, _("Track %i"), i_track ) == -1 )
909 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, pl_Unlocked );
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 if( asprintf( &t->psz_name, _("Track %i"), i_track ) == -1 )
941 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
943 t->i_length = INT64_C(1000000) * t->i_size
944 / CDDA_FREQUENCY_SAMPLE / 4;
946 if ( ! p_cdda->b_nav_mode )
948 p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
953 p_cdda->i_titles = p_cdda->i_tracks;
954 p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
957 input_item_SetDuration( p_item->p_input, (mtime_t) p_access->info.i_size
958 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
959 input_item_SetURI( p_item->p_input,
960 CDDAFormatMRL( p_access, p_cdda->i_track ) );
966 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, pl_Unlocked,
967 p_playlist->status.p_item, NULL );
970 if (p_playlist) pl_Release( p_access );