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., 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 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", VLC_META, VAL ); \
165 #define add_cddb_meta(FIELD, VLC_META) \
166 add_meta_val(VLC_META, p_cdda->cddb.disc->FIELD);
168 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
171 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
172 p_cdda->cddb.disc->FIELD ); \
173 psz_buf[sizeof(psz_buf)-1] = '\0'; \
174 add_meta_val(VLC_META, psz_buf); \
177 /* Adds a string-valued entry to the stream and media information if
178 the string is not null or the null string.
180 #define add_info_str(CATEGORY, TITLE, FIELD) \
181 if (FIELD && strlen(FIELD)) { \
182 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
183 _(TITLE), "%s", FIELD ); \
186 /* Adds a numeric-valued entry to the stream and media information
187 if the number is not zero. */
188 #define add_info_val(CATEGORY, TITLE, FMT, FIELD) \
190 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
191 _(TITLE), FMT, FIELD ); \
194 /* Adds a CDDB string-valued entry to the stream and media information
195 under category "Disc" if the string is not null or the null string.
197 #define add_cddb_disc_info_str(TITLE, FIELD) \
198 add_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
200 /* Adds a CDDB numeric-valued entry to the stream and media information
201 under category "Disc" if the string is not null or the null string.
203 #define add_cddb_disc_info_val(TITLE, FMT, FIELD) \
204 add_info_val("Disc", TITLE, FMT, p_cdda->cddb.disc->FIELD)
206 /* Adds a CD-Text string-valued entry to the stream and media information
207 under category "Disc" if the string is not null or the null string.
209 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD) \
210 add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
212 /* Adds a CD-Text string-valued entry to the stream and media information
213 under category "Disc" if the string is not null or the null string.
215 #define add_cdtext_disc_info_str(TITLE, FIELD) \
216 add_cdtext_info_str("Disc", TITLE, 0, FIELD)
220 Saves Meta Information about the CD-DA.
222 Meta information used in "stream and media info" or in playlist
223 info. The intialization of CD-Text or CDDB is done here though.
224 Therefore, this should be called before CDDAMetaInfo is called.
228 CDDAMetaInfoInit( access_t *p_access )
230 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
232 if ( ! p_cdda ) return;
234 dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d",
237 p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
238 p_cdda->p_meta = vlc_meta_New();
241 if ( p_cdda->b_cddb_enabled )
243 GetCDDBInfo(p_access, p_cdda);
246 #endif /*HAVE_LIBCDDB*/
252 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
254 p_cdda->p_cdtext[i_track] =
255 cdio_get_cdtext(p_cdda->p_cdio, i_track);
261 In the Control routine, we handle Meta Information requests and
262 basically copy what was saved in CDDAMetaInfoInit.
264 If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
268 CDDAMetaInfo( access_t *p_access, track_t i_track )
270 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
271 char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
272 char *psz_meta_artist = NULL;
274 if ( ! p_cdda ) return;
276 dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
280 /* Set up for Meta and name for CDDB access. */
281 if ( p_cdda->b_cddb_enabled && p_cdda->cddb.disc )
283 if( CDIO_INVALID_TRACK == i_track )
286 psz_meta_title = p_cdda->cddb.disc->title;
287 psz_meta_artist = p_cdda->cddb.disc->artist;
288 if ( p_cdda->cddb.disc->genre && strlen(p_cdda->cddb.disc->genre) )
289 add_cddb_meta(genre, VLC_META_GENRE);
290 if ( 0 != p_cdda->cddb.disc->year )
291 add_cddb_meta_fmt(year, "%d", VLC_META_DATE );
295 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
298 if( t->title != NULL && ! p_cdda->b_nav_mode )
300 add_meta_val( VLC_META_TITLE, t->title );
302 if( t->artist != NULL )
304 add_meta_val( VLC_META_ARTIST, t->artist );
310 #endif /*HAVE_LIBCDDB*/
314 track_t i = p_cdda->i_tracks;
315 const int i_first_track = p_cdda->i_first_track;
316 char psz_buffer[MSTRTIME_MAX_SIZE];
317 unsigned int i_track_frames =
318 cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
320 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
322 dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d",
323 (long int) i_duration, p_cdda->i_tracks );
324 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
325 _("Disc"), _("Duration"), "%s",
326 secstotimestr( psz_buffer, i_duration ) );
328 if (p_cdda->psz_mcn) {
329 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
330 _("Disc"), _("Media Catalog Number (MCN)"), "%s",
333 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
334 _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
339 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
341 add_cddb_disc_info_str("Artist (CDDB)", artist);
342 if ( CDDB_CAT_INVALID != p_cdda->cddb.disc->category )
343 add_info_str("Disc", "Category (CDDB)",
344 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
345 add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
346 add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
347 add_cddb_disc_info_str("Genre (CDDB)", genre);
348 add_cddb_disc_info_str("Title (CDDB)", title);
349 if ( 0 != p_cdda->cddb.disc->year )
350 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
353 #endif /*HAVE_LIBCDDB*/
355 if (p_cdda->p_cdtext[0])
359 add_cdtext_disc_info_str("Arranger (CD-Text)", CDTEXT_ARRANGER);
360 add_cdtext_disc_info_str("Composer (CD-Text)", CDTEXT_COMPOSER);
361 add_cdtext_disc_info_str("Disc ID (CD-Text)", CDTEXT_DISCID);
362 add_cdtext_disc_info_str("Genre (CD-Text)", CDTEXT_GENRE);
363 add_cdtext_disc_info_str("Message (CD-Text)", CDTEXT_MESSAGE);
364 add_cdtext_disc_info_str("Performer (CD-Text)", CDTEXT_PERFORMER);
365 add_cdtext_disc_info_str("Songwriter (CD-Text)", CDTEXT_SONGWRITER);
366 add_cdtext_disc_info_str("Title (CD-Text)", CDTEXT_TITLE);
368 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
369 if (psz_field && strlen(psz_field)) {
370 psz_meta_title = psz_field;
372 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
373 if (psz_field && strlen(psz_field)) {
374 psz_meta_artist = psz_field;
379 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
381 char psz_track[TITLE_MAX];
382 const track_t i_track = i_first_track + i;
383 unsigned int i_track_frames =
384 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
385 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
387 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
388 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
390 snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
392 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
394 secstotimestr( psz_buffer, i_duration ) );
396 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
397 _("MRL"), "%s", psz_mrl );
400 if (p_cdda->p_cdtext[i_track])
402 add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
403 i_track, CDTEXT_ARRANGER);
404 add_cdtext_info_str( psz_track, "Composer (CD-Text)",
405 i_track, CDTEXT_COMPOSER);
406 add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
407 i_track, CDTEXT_DISCID);
408 add_cdtext_info_str( psz_track, "Genre (CD-Text)",
409 i_track, CDTEXT_GENRE);
410 add_cdtext_info_str( psz_track, "Message (CD-Text)",
411 i_track, CDTEXT_MESSAGE);
412 add_cdtext_info_str( psz_track, "Performer (CD-Text)",
413 i_track, CDTEXT_PERFORMER);
414 add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
415 i_track, CDTEXT_SONGWRITER);
416 add_cdtext_info_str( psz_track, "Title (CD-Text)",
417 i_track, CDTEXT_TITLE);
421 if (p_cdda->b_cddb_enabled)
423 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
426 add_info_str(psz_track, "Artist (CDDB)", t->artist);
427 add_info_str(psz_track, "Title (CDDB)", t->title);
428 add_info_str(psz_track, "Extended Data (CDDB)",
432 #endif /*HAVE_LIBCDDB*/
435 /* Above we should have set psz_meta_title and psz_meta_artist
436 to CDDB or CD-Text values or the default value depending on
437 availablity and user preferences.
439 So now add the title and artist to VLC's meta, and the name
440 as shown in the status bar and playlist entry.
442 For playlist mode, the meta title is what's seen at the
443 bottom and in the playlist. For nav-mode playing, it is
444 done by input_control. I don't understand why they do
445 different things. In either case, we may have customized to
446 put in the track name.
448 if ( CDIO_INVALID_TRACK != i_track )
450 char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
451 if ( !p_cdda->b_nav_mode ) {
452 add_meta_val( VLC_META_TITLE, psz_name );
455 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
459 add_meta_val( VLC_META_ARTIST, psz_meta_artist );
465 #define add_format_str_info(val) \
467 const char *str = val; \
472 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
475 saw_control_prefix = false; \
479 #define add_format_num_info(val, fmt) \
483 sprintf(num_str, fmt, val); \
484 len=strlen(num_str); \
486 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
489 saw_control_prefix = false; \
494 cdda_data_t *p_cdda, char *psz_cdtext)
496 /* We either don't have CD-Text info, or we do but we prefer to get CDDB
497 which means CDDB has been enabled and we were able to retrieve the info.*/
499 return !psz_cdtext ||
500 (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
508 Take a format string and expand escape sequences, that is sequences that
509 begin with %, with information from the current CD.
510 The expanded string is returned. Here is a list of escape sequences:
512 %a : The album artist **
513 %A : The album information **
515 %e : The extended track data
519 %m : The CD-DA Media Catalog Number (MCN)
520 %n : The number of tracks on the CD
521 %p : The artist/performer/composer in the track **
522 %T : The track number **
523 %s : Number of seconds in this track, or seconds in CD if invalid track
524 %S : Number of seconds on the CD
525 %t : The track name or MRL if no name
526 %Y : The year 19xx or 20xx **
530 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
531 const char format_str[], const char *psz_mrl, track_t i_track)
533 #define TEMP_STR_SIZE 256
534 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
535 static char temp_str[TEMP_STR_SIZE];
537 char * tp = temp_str;
538 vlc_bool_t saw_control_prefix = false;
539 size_t format_len = strlen(format_str);
541 memset(temp_str, 0, TEMP_STR_SIZE);
543 for (i=0; i<format_len; i++)
547 if (!saw_control_prefix && format_str[i] != '%')
549 *tp++ = format_str[i];
550 saw_control_prefix = false;
554 switch(format_str[i])
557 if (saw_control_prefix)
561 saw_control_prefix = !saw_control_prefix;
565 if (p_cdda->p_cdtext[0]
566 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
567 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
568 if (want_cddb_info(p_cdda, psz))
569 psz = p_cdda->cddb.disc->artist;
572 if (p_cdda->p_cdtext[0]
573 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
574 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
575 if (want_cddb_info(p_cdda, psz))
576 psz = p_cdda->cddb.disc->title;
579 if (!p_cdda->b_cddb_enabled) goto not_special;
580 if (p_cdda->cddb.disc)
582 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
585 if (p_cdda->p_cdtext[0]
586 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
587 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
588 if (want_cddb_info(p_cdda, psz))
589 psz = p_cdda->cddb.disc->genre;
592 if (p_cdda->p_cdtext[0]
593 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
594 psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
595 if (want_cddb_info(p_cdda, psz)) {
596 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
598 add_format_str_info(psz);
601 if (!p_cdda->b_cddb_enabled) goto not_special;
602 if (p_cdda->cddb.disc)
603 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
606 if ( CDIO_INVALID_TRACK == i_track ) break;
607 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
609 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
611 if (t != NULL && t->title != NULL) {
612 add_format_str_info(t->title);
614 add_format_str_info(psz_mrl);
617 if (p_cdda->p_cdtext[i_track]
618 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]) {
619 add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
622 add_format_str_info(psz_mrl);
626 if ( CDIO_INVALID_TRACK == i_track ) break;
627 if (p_cdda->p_cdtext[i_track]
628 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
629 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
630 if (want_cddb_info(p_cdda, psz))
632 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
634 if (t != NULL && t->artist != NULL)
639 if ( CDIO_INVALID_TRACK == i_track ) break;
640 if (p_cdda->p_cdtext[i_track]
641 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
642 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
643 if (want_cddb_info(p_cdda, psz))
645 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
647 if (t != NULL && t->ext_data != NULL)
654 if (p_cdda->p_cdtext[0]
655 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
656 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
659 if (p_cdda->p_cdtext[0]
660 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
661 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
664 if (p_cdda->p_cdtext[0]
665 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
666 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
669 if (p_cdda->p_cdtext[0]
670 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
671 add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
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_PERFORMER])
677 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
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_TITLE])
683 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
688 if ( CDIO_INVALID_TRACK == i_track ) break;
689 if (p_cdda->p_cdtext[i_track]
690 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
691 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
694 #endif /*HAVE_LIBCDDB*/
697 if ( CDIO_INVALID_TRACK != i_track )
699 char psz_buffer[MSTRTIME_MAX_SIZE];
700 unsigned int i_track_frames =
701 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
703 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
704 add_format_str_info( secstotimestr( psz_buffer,
709 /* Fall through to disc duration if CDIO_INVALID_TRACK */
712 char psz_buffer[MSTRTIME_MAX_SIZE];
713 unsigned int i_track_frames =
714 cdio_get_track_lba(p_cdda->p_cdio,
715 CDIO_CDROM_LEADOUT_TRACK);
717 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
718 add_format_str_info( secstotimestr( psz_buffer,
724 add_format_str_info(psz_mrl);
728 add_format_str_info(p_cdda->psz_mcn);
732 add_format_num_info(p_cdda->i_tracks, "%d");
736 add_format_num_info(i_track, "%02d");
740 add_format_str_info(psz);
747 *tp++ = format_str[i];
748 saw_control_prefix = false;
751 return strdup(temp_str);
754 /* Return a MRL for the given track. The caller must free the
757 CDDAFormatMRL( const access_t *p_access, track_t i_track )
759 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
760 const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX)
761 + strlen(p_cdda->psz_source) +
762 + strlen("@T") + strlen("100") + 1;
763 char *psz_mrl = calloc( 1, psz_mrl_max );
765 if (CDIO_INVALID_TRACK == i_track)
766 snprintf(psz_mrl, psz_mrl_max, "%s%s",
767 CDDA_MRL_PREFIX, p_cdda->psz_source);
769 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
770 CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
775 /* Return a title string as specified by the titel format string for the
776 given track. The caller must free the allocated string. */
778 CDDAFormatTitle( const access_t *p_access, track_t i_track )
781 char *config_varname = MODULE_STRING "-title-format";
782 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
783 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
789 if (p_cdda->b_cddb_enabled)
791 config_varname = MODULE_STRING "-cddb-title-format";
793 #endif /*HAVE_LIBCDDB*/
795 CDDAFormatStr( p_access, p_cdda,
796 config_GetPsz( p_access, config_varname ),
804 /* Adds a string-valued entry to the playlist information under "Track"
805 if the string is not null or the null string.
807 #define add_playlist_track_info_str(TITLE, FIELD) \
808 if (FIELD && strlen(FIELD)) \
810 vlc_input_item_AddInfo( &p_item->input, _("Track"), _(TITLE), \
814 static playlist_item_t *
815 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
816 playlist_t *p_playlist, playlist_item_t *p_item,
819 unsigned int i_track_frames =
820 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
821 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
822 mtime_t i_mduration =
823 i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
824 char *psz_title = NULL;
825 char *psz_mrl = NULL;
827 playlist_item_t *p_child = NULL;
829 if( !p_item ) return NULL;
831 psz_title = CDDAFormatTitle( p_access, i_track ) ;
832 psz_mrl = CDDAFormatMRL( p_access, i_track ) ;
834 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
835 psz_mrl, psz_title, (long int) i_mduration / 1000000 );
837 p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
838 p_child->input.i_duration = i_mduration;
842 if( !p_child ) return NULL;
844 playlist_NodeAddItem( p_playlist, p_child,
845 p_item->pp_parents[0]->i_view,
846 p_item, PLAYLIST_APPEND, PLAYLIST_END );
847 playlist_CopyParents( p_item, p_child );
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 )
856 add_playlist_track_info_str("Source", p_cdda->psz_source);
857 vlc_input_item_AddInfo( &p_item->input, _("Track"), _("Track Number"),
860 if (p_cdda->p_cdtext[i_track])
862 const cdtext_t *p = p_cdda->p_cdtext[i_track];
863 add_playlist_track_info_str("Arranger (CD-Text)",
864 p->field[CDTEXT_ARRANGER]);
865 add_playlist_track_info_str("Composer (CD-Text)",
866 p->field[CDTEXT_COMPOSER]);
867 add_playlist_track_info_str("Genre (CD-Text)",
868 p->field[CDTEXT_GENRE]);
869 add_playlist_track_info_str("Message (CD-Text)",
870 p->field[CDTEXT_MESSAGE]);
871 add_playlist_track_info_str("Performer (CD-Text)",
872 p->field[CDTEXT_PERFORMER]);
873 add_playlist_track_info_str("Songwriter (CD-Text)",
874 p->field[CDTEXT_SONGWRITER]);
875 add_playlist_track_info_str("Title (CD-Text)",
876 p->field[CDTEXT_TITLE]);
880 if (p_cdda->b_cddb_enabled)
882 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
883 i_track-p_cdda->i_first_track);
888 add_playlist_track_info_str("Artist (CDDB)",
891 add_playlist_track_info_str("Title (CDDB)",
894 add_playlist_track_info_str("Extended information (CDDB)",
898 #endif /*HAVE_LIBCDDB*/
907 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
908 vlc_bool_t b_single_track )
911 playlist_t * p_playlist = NULL;
912 const track_t i_first_track = p_cdda->i_first_track;
913 playlist_item_t *p_item = NULL;
914 vlc_bool_t b_play = VLC_FALSE;
918 p_cdda->b_cddb_enabled =
919 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
920 if( b_single_track && !p_cdda->b_cddb_enabled )
927 if (! p_cdda->b_nav_mode ) {
928 p_playlist = (playlist_t *) vlc_object_find( p_access,
933 msg_Warn( p_access, "can't find playlist" );
938 if( b_single_track || p_cdda->b_nav_mode ) {
939 i_track = p_cdda->i_track;
943 i_track = CDIO_INVALID_TRACK;
945 CDDAMetaInfoInit( p_access );
946 CDDAMetaInfo( p_access, p_cdda->i_track );
950 p_item = playlist_LockItemGetByInput( p_playlist,
951 ((input_thread_t *)p_access->p_parent)->input.p_item );
953 if( p_item == p_playlist->status.p_item && !b_single_track )
963 if( b_single_track && !p_cdda->b_nav_mode )
965 /*May fill out more information when the playlist user interface becomes
968 track_t i_track = p_cdda->i_track;
969 unsigned int i_track_frames =
970 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
972 input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
973 vlc_input_title_New();
975 asprintf( &t->psz_name, _("Track %i"), i_track );
976 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
978 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
983 CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
984 p_item->input.i_duration = i_track_frames
985 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
986 p_item->input.psz_uri = CDDAFormatMRL(p_access, i_track);
989 p_cdda->i_titles = 1;
990 p_access->info.i_update = INPUT_UPDATE_TITLE;
996 if ( !p_cdda->b_nav_mode )
997 playlist_ItemToNode( p_playlist, p_item );
999 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
1001 playlist_item_t *p_child;
1002 const track_t i_track = i_first_track + i;
1003 unsigned int i_track_frames =
1004 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
1006 t = p_cdda->p_title[i] = vlc_input_title_New();
1008 asprintf( &t->psz_name, _("Track %i"), i_track );
1009 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
1011 t->i_length = I64C(1000000) * t->i_size
1012 / CDDA_FREQUENCY_SAMPLE / 4;
1014 if ( ! p_cdda->b_nav_mode ) {
1015 p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
1018 CDDAAddMetaToItem( p_access, p_cdda, p_child, i_track,
1023 p_cdda->i_titles = p_cdda->i_tracks;
1024 p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1026 p_item->input.i_duration =
1027 p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
1028 p_item->input.psz_uri = CDDAFormatMRL(p_access,
1036 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
1037 p_playlist->status.i_view,
1038 p_playlist->status.p_item, NULL );
1041 if (p_playlist) vlc_object_release( p_playlist );