]> git.sesse.net Git - vlc/blob - modules/access/cdda/info.c
7d5467ebbbed4f4ed610572f4248a98a04a8ce39
[vlc] / modules / access / cdda / info.c
1 /*****************************************************************************
2  * info.c : CD digital audio input information routines
3  *****************************************************************************
4  * Copyright (C) 2004, 2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Rocky Bernstein <rocky@panix.com>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "callback.h"      /* FIXME - reorganize callback.h, cdda.h better */
28 #include "cdda.h"          /* private structures. Also #includes vlc things */
29
30 #include <cdio/cdio.h>
31 #include <cdio/cdtext.h>
32 #include <cdio/logging.h>
33 #include <cdio/cd_types.h>
34 #include "info.h"
35
36 #include <errno.h>
37 #include <assert.h>
38
39 static char *CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
40                 const char format_str[], const char *psz_mrl,
41                 track_t i_track);
42
43 static char *CDDAFormatMRL( const access_t *p_access, track_t i_track );
44
45 #ifdef HAVE_LIBCDDB
46
47 #define free_and_dup(var, val) \
48   free( var );          \
49   if (val) var = strdup( val );
50
51
52 /* Saves CDDB information about CD-DA via libcddb. */
53 static void
54 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
55 {
56     int i, i_matches;
57     cddb_conn_t  *conn = cddb_new();
58     const CdIo_t *p_cdio = p_cdda->p_cdio;
59
60     dbg_print( (INPUT_DBG_CALL), "" );
61
62 #ifdef FIXME_NOW
63     cddb_log_set_handler (uninit_log_handler);
64 #endif
65
66     if (!conn)
67     {
68         msg_Warn( p_access, "Unable to initialize libcddb" );
69         goto cddb_destroy;
70     }
71
72     char* psz_email = config_GetPsz( p_access, MODULE_STRING "-cddb-email");
73     char* psz_srv_name = config_GetPsz( p_access, MODULE_STRING "-cddb-server");
74     cddb_set_email_address( conn, psz_email );
75     cddb_set_server_name( conn, psz_srv_name );
76     cddb_set_server_port(conn,
77                          config_GetInt( p_access,
78                                         MODULE_STRING "-cddb-port") );
79     free( psz_email );
80     free( psz_srv_name );
81
82   /* Set the location of the local CDDB cache directory.
83      The default location of this directory is */
84
85     if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
86         cddb_cache_disable(conn);
87
88     char* psz_cache = config_GetPsz( p_access, MODULE_STRING "-cddb-cachedir");
89     cddb_cache_set_dir(conn, psz_cache );
90     free( psz_cache );
91
92     cddb_set_timeout(conn,
93                    config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
94
95
96     if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" ) )
97     {
98         cddb_http_enable(conn);
99     }
100     else
101     {
102         cddb_http_disable(conn);
103     }
104
105     p_cdda->cddb.disc = cddb_disc_new();
106
107     if (!p_cdda->cddb.disc)
108     {
109         msg_Err( p_access, "Unable to create CDDB disc structure." );
110         goto cddb_end;
111     }
112
113     for(i = 0; i < p_cdda->i_tracks; i++)
114     {
115         track_t i_track =  p_cdda->i_first_track + i;
116         cddb_track_t *t = cddb_track_new();
117     cddb_track_set_frame_offset(t,
118                     cdio_get_track_lba(p_cdio, i_track));
119         cddb_disc_add_track(p_cdda->cddb.disc, t);
120     }
121
122     cddb_disc_set_length(p_cdda->cddb.disc,
123              cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
124              / CDIO_CD_FRAMES_PER_SEC);
125
126     if (!cddb_disc_calc_discid(p_cdda->cddb.disc))
127     {
128         msg_Err( p_access, "CDDB disc ID calculation failed" );
129         goto cddb_destroy;
130     }
131
132     i_matches = cddb_query(conn, p_cdda->cddb.disc);
133
134     if (i_matches > 0)
135     {
136         if (i_matches > 1)
137              msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
138                                  i_matches);
139         cddb_read(conn, p_cdda->cddb.disc);
140
141         if (p_cdda->i_debug & INPUT_DBG_CDDB)
142             cddb_disc_print(p_cdda->cddb.disc);
143
144     }
145     else
146     {
147         msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
148     }
149
150 cddb_destroy:
151     cddb_destroy(conn);
152
153 cddb_end: ;
154 }
155 #endif /*HAVE_LIBCDDB*/
156
157 static inline void add_meta_val(access_t *p_access, vlc_meta_type_t meta, const char * val)
158 {
159     cdda_data_t *p_cdda = (cdda_data_t *)p_access->p_sys;
160     if (p_cdda->p_meta && val)
161         dbg_print( INPUT_DBG_META, "field %s: %s\n", input_MetaTypeToLocalizedString(meta), val);
162 }
163
164 #define add_cddb_meta(FIELD, VLC_META)                            \
165   add_meta_val(p_access, VLC_META, cddb_disc_get_##FIELD(p_cdda->cddb.disc));
166
167 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META)                 \
168   {                                                                     \
169     char psz_buf[100];                                                  \
170     snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC,                  \
171               cddb_disc_get_##FIELD(p_cdda->cddb.disc));                               \
172     psz_buf[sizeof(psz_buf)-1] = '\0';                                  \
173     add_meta_val(p_access, VLC_META, psz_buf);                    \
174   }
175
176 /* Adds a string-valued entry to the stream and media information if
177    the string is not null or the null string.
178  */
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 );                       \
183   }
184
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)                 \
188   if (FIELD) {                                                    \
189     input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY,     \
190                    _(TITLE), FMT, FIELD );                        \
191   }
192
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.
195  */
196 #define add_cddb_disc_info_str(TITLE, FIELD)                    \
197   add_info_str("Disc", TITLE, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
198
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.
201  */
202 #define add_cddb_disc_info_val(TITLE, FMT, FIELD)               \
203   add_info_val("Disc", TITLE, FMT, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
204
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.
207  */
208 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD)              \
209     add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
210
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.
213  */
214 #define add_cdtext_disc_info_str(TITLE, FIELD) \
215   add_cdtext_info_str("Disc", TITLE, 0, FIELD)
216
217
218 /*
219   Saves Meta Information about the CD-DA.
220
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.
224
225  */
226 static void
227 CDDAMetaInfoInit( access_t *p_access )
228 {
229     cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
230
231     if ( ! p_cdda ) return;
232
233     dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d",
234            p_cdda->i_tracks );
235
236     p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
237 #if 0
238     p_cdda->p_meta = vlc_meta_New();
239 #endif
240
241 #ifdef HAVE_LIBCDDB
242     if ( p_cdda->b_cddb_enabled )
243     {
244         GetCDDBInfo(p_access, p_cdda);
245     }
246
247 #endif /*HAVE_LIBCDDB*/
248  
249 #define TITLE_MAX 30
250     {
251         track_t i_track;
252
253         for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
254         {
255             p_cdda->p_cdtext[i_track] =
256             cdio_get_cdtext(p_cdda->p_cdio, i_track);
257         }
258     }
259 }
260
261 /*
262  In the Control routine, we handle Meta Information requests and
263  basically copy what was saved in CDDAMetaInfoInit.
264
265  If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
266  CD.
267  */
268 void
269 CDDAMetaInfo( access_t *p_access, track_t i_track )
270 {
271     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
272     char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
273     char *psz_meta_artist = NULL;
274
275     if ( ! p_cdda ) return;
276
277     dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
278
279 #ifdef HAVE_LIBCDDB
280
281     /* Set up for Meta and name for CDDB access. */
282     if ( p_cdda->b_cddb_enabled &&  p_cdda->cddb.disc )
283     {
284         if( CDIO_INVALID_TRACK == i_track )
285         {
286
287             psz_meta_title  = (char *)cddb_disc_get_title(p_cdda->cddb.disc);
288             psz_meta_artist = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
289             if ( cddb_disc_get_genre(p_cdda->cddb.disc) &&
290                 strlen(cddb_disc_get_genre(p_cdda->cddb.disc)) )
291                 add_cddb_meta(genre, vlc_meta_Genre);
292             if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc))
293                 add_cddb_meta_fmt(year, "%d", vlc_meta_Date );
294         }
295         else
296         {
297             cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
298             if (t != NULL )
299             {
300                 if( cddb_track_get_title(t) != NULL && ! p_cdda->b_nav_mode )
301                 {
302                     add_meta_val( p_access, vlc_meta_Title, cddb_track_get_title(t) );
303                 }
304                 if( cddb_track_get_artist(t) != NULL )
305                 {
306                     add_meta_val( p_access, vlc_meta_Artist, cddb_track_get_artist(t) );
307                 }
308             }
309         }
310     }
311 #endif /*HAVE_LIBCDDB*/
312
313 #define TITLE_MAX 30
314     {
315         track_t i = p_cdda->i_tracks;
316         const int i_first_track = p_cdda->i_first_track;
317         char psz_buffer[MSTRTIME_MAX_SIZE];
318         unsigned int i_track_frames =
319         cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
320
321         mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
322
323         dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d",
324            (long int) i_duration, p_cdda->i_tracks );
325         input_Control( p_cdda->p_input, INPUT_ADD_INFO,
326                        _("Disc"), _("Duration"), "%s",
327                        secstotimestr( psz_buffer, i_duration ) );
328
329         if (p_cdda->psz_mcn)
330         {
331             input_Control( p_cdda->p_input, INPUT_ADD_INFO,
332                 _("Disc"), _("Media Catalog Number (MCN)"), "%s",
333                 p_cdda->psz_mcn );
334             input_Control( p_cdda->p_input, INPUT_ADD_INFO,
335                 _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
336         }
337
338 #ifdef HAVE_LIBCDDB
339         if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
340         {
341             add_cddb_disc_info_str("Artist (CDDB)", artist);
342             if ( CDDB_CAT_INVALID != cddb_disc_get_category(p_cdda->cddb.disc) )
343                 add_info_str("Disc", "Category (CDDB)",
344                         CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
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 != cddb_disc_get_year(p_cdda->cddb.disc) )
350                 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
351
352         }
353 #endif /*HAVE_LIBCDDB*/
354
355         if (p_cdda->p_cdtext[0])
356         {
357             char *psz_field;
358
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);
367
368             psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
369             if (psz_field && strlen(psz_field))
370                 psz_meta_title = psz_field;
371
372             psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
373             if (psz_field && strlen(psz_field))
374                 psz_meta_artist = psz_field;
375         }
376
377         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
378         {
379             char psz_track[TITLE_MAX];
380             const track_t i_track = i_first_track + i;
381             unsigned int i_track_frames =
382             cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
383             cdio_get_track_lsn(p_cdda->p_cdio, i_track);
384
385             mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
386             char *psz_mrl = CDDAFormatMRL( p_access, i_track );
387
388             snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
389
390             input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
391                 _("Duration"), "%s",
392                 secstotimestr( psz_buffer, i_duration ) );
393
394             input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
395                 _("MRL"), "%s", psz_mrl );
396             free(psz_mrl);
397
398             if (p_cdda->p_cdtext[i_track])
399             {
400                 add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
401                         i_track, CDTEXT_ARRANGER);
402                 add_cdtext_info_str( psz_track, "Composer (CD-Text)",
403                         i_track, CDTEXT_COMPOSER);
404                 add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
405                         i_track, CDTEXT_DISCID);
406                 add_cdtext_info_str( psz_track, "Genre (CD-Text)",
407                         i_track, CDTEXT_GENRE);
408                 add_cdtext_info_str( psz_track, "Message (CD-Text)",
409                         i_track, CDTEXT_MESSAGE);
410                 add_cdtext_info_str( psz_track, "Performer (CD-Text)",
411                         i_track, CDTEXT_PERFORMER);
412                 add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
413                         i_track, CDTEXT_SONGWRITER);
414                 add_cdtext_info_str( psz_track, "Title (CD-Text)",
415                         i_track, CDTEXT_TITLE);
416             }
417
418 #ifdef HAVE_LIBCDDB
419             if (p_cdda->b_cddb_enabled)
420             {
421                 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
422                 if (t != NULL)
423                 {
424                     add_info_str(psz_track, "Artist (CDDB)",
425                             cddb_track_get_artist(t));
426                     add_info_str(psz_track, "Title (CDDB)",
427                             cddb_track_get_title(t));
428                     add_info_str(psz_track, "Extended Data (CDDB)",
429                             cddb_track_get_ext_data(t));
430                 }
431             }
432 #endif /*HAVE_LIBCDDB*/
433         }
434
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.
438
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.
441
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.
447      */
448         if ( CDIO_INVALID_TRACK != i_track )
449         {
450             char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
451             if ( !p_cdda->b_nav_mode ) {
452                 add_meta_val( p_access, vlc_meta_Title, psz_name );
453             } else
454             {
455                 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
456                 free(psz_name);
457             }
458             if (psz_meta_artist)
459             add_meta_val( p_access, vlc_meta_Artist, psz_meta_artist );
460         }
461     }
462 }
463
464 #define add_format_str_info(val)                         \
465   {                                                      \
466     const char *str = val;                               \
467     unsigned int len;                                    \
468     if (val != NULL) {                                   \
469       len=strlen(str);                                   \
470       if (len != 0) {                                    \
471         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    \
472         tp += len;                                       \
473       }                                                  \
474       saw_control_prefix = false;                        \
475     }                                                    \
476   }
477
478 #define add_format_num_info(val, fmt)                    \
479   {                                                      \
480     char num_str[10];                                    \
481     unsigned int len;                                    \
482     sprintf(num_str, fmt, val);                          \
483     len=strlen(num_str);                                 \
484     if (len != 0) {                                      \
485       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  \
486       tp += len;                                         \
487     }                                                    \
488     saw_control_prefix = false;                          \
489   }
490
491 static inline bool
492 want_cddb_info(
493 cdda_data_t *p_cdda, char *psz_cdtext)
494 {
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.*/
497 #ifdef HAVE_LIBCDDB
498     return !psz_cdtext ||
499         (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
500 #else
501     return false;
502 #endif
503 }
504
505
506 /*!
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:
510
511    %a : The album artist **
512    %A : The album information **
513    %C : Category **
514    %e : The extended track data
515    %I : CDDB disk ID **
516    %G : Genre **
517    %M : The current MRL
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 **
526    %% : a %
527 */
528 char *
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)
531 {
532     VLC_UNUSED(p_access);
533 #define TEMP_STR_SIZE 256
534 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
535     static char temp_str[TEMP_STR_SIZE];
536     size_t i;
537     char * tp = temp_str;
538     bool saw_control_prefix = false;
539     size_t format_len = strlen(format_str);
540
541     memset(temp_str, 0, TEMP_STR_SIZE);
542
543     for (i=0; i<format_len; i++)
544     {
545         char *psz = NULL;
546
547         if (!saw_control_prefix && format_str[i] != '%')
548         {
549             *tp++ = format_str[i];
550             saw_control_prefix = false;
551             continue;
552         }
553
554         switch(format_str[i])
555         {
556             case '%':
557               if (saw_control_prefix)
558               {
559                   *tp++ = '%';
560               }
561               saw_control_prefix = !saw_control_prefix;
562               break;
563 #ifdef HAVE_LIBCDDB
564             case 'a':
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 = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
570                 goto format_str;
571             case 'A':
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 =  (char *)cddb_disc_get_title(p_cdda->cddb.disc);
577                 goto format_str;
578             case 'C':
579                 if (!p_cdda->b_cddb_enabled) goto not_special;
580                 if (p_cdda->cddb.disc)
581                     add_format_str_info(CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
582                 break;
583             case 'G':
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 = (char *)cddb_disc_get_genre(p_cdda->cddb.disc);
589                 goto format_str;
590             case 'I':
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(cddb_disc_get_discid(p_cdda->cddb.disc), "%x");
596                 } else if (psz)
597                     add_format_str_info(psz);
598                 break;
599             case 'Y':
600                 if (!p_cdda->b_cddb_enabled) goto not_special;
601                 if (p_cdda->cddb.disc)
602                     add_format_num_info(cddb_disc_get_year(p_cdda->cddb.disc),
603                     "%5d");
604                 break;
605             case 't':
606                 if ( CDIO_INVALID_TRACK == i_track ) break;
607                 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
608                 {
609                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
610                                                         i_track-1);
611                     if (t != NULL && cddb_track_get_title(t) != NULL) {
612                       add_format_str_info(cddb_track_get_title(t));
613                     } else {
614                       add_format_str_info(psz_mrl);
615                     }
616                 }
617                 else
618                 {
619                     if (p_cdda->p_cdtext[i_track]
620                         && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
621                     {
622                         add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
623                     }
624                     else
625                         add_format_str_info(psz_mrl);
626                 }
627                 break;
628             case 'p':
629                 if ( CDIO_INVALID_TRACK == i_track ) break;
630                 if (p_cdda->p_cdtext[i_track]
631                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
632                     psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
633                 if (want_cddb_info(p_cdda, psz))
634                 {
635                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
636                                 i_track-1);
637                     if (t != NULL && cddb_track_get_artist(t) != NULL)
638                     psz = (char *)cddb_track_get_artist(t);
639                 }
640                 goto format_str;
641             case 'e':
642                     if ( CDIO_INVALID_TRACK == i_track ) break;
643                     if (p_cdda->p_cdtext[i_track]
644                         && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
645                     psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
646                     if (want_cddb_info(p_cdda, psz))
647                     {
648                         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
649                                                             i_track-1);
650                         if (t != NULL && cddb_track_get_ext_data(t) != NULL)
651                             psz = (char *)cddb_track_get_ext_data(t);
652                     }
653                     goto format_str;
654                 break;
655 #else
656             case 'a':
657                 if (p_cdda->p_cdtext[0]
658                 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
659                 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
660                     goto format_str;
661             case 'A':
662                 if (p_cdda->p_cdtext[0]
663                     && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
664                 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
665                 goto format_str;
666             case 'G':
667                 if (p_cdda->p_cdtext[0]
668                 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
669                     psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
670                 goto format_str;
671             case 'I':
672                 if (p_cdda->p_cdtext[0]
673                     && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
674                     add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
675                 break;
676             case 'p':
677                 if ( CDIO_INVALID_TRACK == i_track ) break;
678                 if (p_cdda->p_cdtext[i_track]
679                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
680                 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
681                 goto format_str;
682             case 't':
683                 if ( CDIO_INVALID_TRACK == i_track ) break;
684                 if (p_cdda->p_cdtext[i_track]
685                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
686                     psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
687                 else
688                     psz = psz_mrl;
689                 goto format_str;
690             case 'e':
691                 if ( CDIO_INVALID_TRACK == i_track ) break;
692                 if (p_cdda->p_cdtext[i_track]
693                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
694                 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
695                 goto format_str;
696                 break;
697 #endif /*HAVE_LIBCDDB*/
698
699             case 's':
700                 if ( CDIO_INVALID_TRACK != i_track )
701                 {
702                     char psz_buffer[MSTRTIME_MAX_SIZE];
703                     unsigned int i_track_frames =
704                     cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
705                     mtime_t i_duration =
706                         i_track_frames / CDIO_CD_FRAMES_PER_SEC;
707                     add_format_str_info( secstotimestr( psz_buffer,
708                             i_duration ) );
709                     break;
710                 }
711
712             /* Fall through to disc duration if CDIO_INVALID_TRACK  */
713             case 'S':
714                 {
715                     char psz_buffer[MSTRTIME_MAX_SIZE];
716                     unsigned int i_track_frames =
717                     cdio_get_track_lba(p_cdda->p_cdio,
718                         CDIO_CDROM_LEADOUT_TRACK);
719                     mtime_t i_duration =
720                     i_track_frames / CDIO_CD_FRAMES_PER_SEC;
721                     add_format_str_info( secstotimestr( psz_buffer,
722                             i_duration ) );
723                     break;
724                 }
725
726             case 'M':
727                 add_format_str_info(psz_mrl);
728                 break;
729
730             case 'm':
731                 add_format_str_info(p_cdda->psz_mcn);
732                 break;
733
734             case 'n':
735                 add_format_num_info(p_cdda->i_tracks, "%d");
736                 break;
737
738             case 'T':
739                 add_format_num_info(i_track, "%02d");
740                 break;
741             format_str:
742                 if (psz)
743                     add_format_str_info(psz);
744                 break;
745 #ifdef HAVE_LIBCDDB
746             not_special:
747 #endif
748             default:
749                 *tp++ = '%';
750                 *tp++ = format_str[i];
751                 saw_control_prefix = false;
752         }
753     }
754     return strdup(temp_str);
755 }
756
757 /* Return a MRL for the given track. The caller must free the
758    allocated string. */
759 static char *
760 CDDAFormatMRL( const access_t *p_access, track_t i_track )
761 {
762     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
763     const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX)
764       + strlen(p_cdda->psz_source) +
765       + strlen("@T") + strlen("100") + 1;
766     char *psz_mrl = calloc( 1, psz_mrl_max );
767
768     if (CDIO_INVALID_TRACK == i_track)
769       snprintf(psz_mrl, psz_mrl_max, "%s%s",
770            CDDA_MRL_PREFIX, p_cdda->psz_source);
771     else
772       snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
773            CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
774     return psz_mrl;
775 }
776
777
778 /* Return a title string as specified by the titel format string for the
779    given track. The caller must free the allocated string. */
780 char *
781 CDDAFormatTitle( const access_t *p_access, track_t i_track )
782 {
783
784     const char *config_varname = MODULE_STRING "-title-format";
785     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
786     char *psz_mrl = CDDAFormatMRL( p_access, i_track );
787
788     if( psz_mrl )
789     {
790         char *psz_name;
791 #ifdef HAVE_LIBCDDB
792         if (p_cdda->b_cddb_enabled)
793         {
794             config_varname = MODULE_STRING "-cddb-title-format";
795         }
796 #endif /*HAVE_LIBCDDB*/
797         char* psz_config_varname = config_GetPsz( p_access, config_varname );
798         psz_name = CDDAFormatStr( p_access, p_cdda, psz_config_varname,
799                                   psz_mrl, i_track );
800         free( psz_config_varname );
801         free( psz_mrl );
802         return psz_name;
803     }
804     return NULL;
805 }
806
807 /*
808    Fixes up playlist.
809 */
810 int
811 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
812                    bool b_single_track )
813 {
814     int i;
815     const track_t i_first_track = p_cdda->i_first_track;
816     track_t    i_track;
817
818 #ifdef HAVE_LIBCDDB
819     p_cdda->b_cddb_enabled =
820         config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
821     if( b_single_track && !p_cdda->b_cddb_enabled )
822         return VLC_SUCCESS;
823 #else
824     if( b_single_track )
825         return VLC_SUCCESS;
826 #endif
827
828     if( b_single_track || p_cdda->b_nav_mode ) {
829         i_track = p_cdda->i_track;
830     }
831     else
832     {
833         i_track = CDIO_INVALID_TRACK;
834     }
835     CDDAMetaInfoInit( p_access );
836     CDDAMetaInfo( p_access, p_cdda->i_track );
837
838     if( b_single_track && !p_cdda->b_nav_mode )
839     {
840         /*May fill out more information when the playlist user interface becomes
841            more mature.
842          */
843         track_t i_track = p_cdda->i_track;
844         unsigned int i_track_frames =
845         cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
846
847         input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
848         vlc_input_title_New();
849
850         if( asprintf( &t->psz_name, _("Track %i"), i_track ) == -1 )
851             t->psz_name = NULL;
852         t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
853         t->i_length = INT64_C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
854
855         p_cdda->i_titles = 1;
856         p_access->info.i_update = INPUT_UPDATE_TITLE;
857     }
858     else
859     {
860         input_thread_t *p_input = access_GetParentInput( p_access );
861         if( !p_input )
862             return VLC_EGENERIC;
863
864         input_item_t *p_current = input_GetItem( p_input );
865         assert( p_current );
866
867         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
868         {
869             const track_t i_track = i_first_track + i;
870             unsigned int i_track_frames =
871                 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
872             input_title_t *t;
873
874             t = p_cdda->p_title[i] = vlc_input_title_New();
875
876             if( asprintf( &t->psz_name, _("Track %i"), i_track ) == -1 )
877                 t->psz_name = NULL;
878             t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
879
880             t->i_length = INT64_C(1000000) * t->i_size
881                 / CDDA_FREQUENCY_SAMPLE / 4;
882
883             if( !p_cdda->b_nav_mode )
884             {
885                 input_item_t *p_child;
886                 char *psz_mrl = CDDAFormatMRL( p_access, i_track  );
887                 char *psz_title = CDDAFormatTitle( p_access, i_track );
888                 unsigned int i_track_frames =
889                     cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
890                     cdio_get_track_lsn(p_cdda->p_cdio, i_track);
891                 mtime_t i_mduration = i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
892
893                 p_child = input_item_NewWithType( VLC_OBJECT( p_access ),
894                                                   psz_mrl, psz_title, 0, NULL, 0, i_mduration,
895                                                   ITEM_TYPE_DISC );
896                 if( p_child )
897                 {
898                     input_item_CopyOptions( p_current, p_child );
899
900                     input_item_AddSubItem( p_current, p_child );
901
902                     vlc_gc_decref( p_child );
903                 }
904                 free( psz_mrl );
905                 free( psz_title );
906             }
907         }
908
909         p_cdda->i_titles = p_cdda->i_tracks;
910         p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
911         if( p_current )
912         {
913             input_item_SetDuration( p_current,
914                                     (mtime_t) p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
915             input_item_SetURI( p_current, CDDAFormatMRL( p_access, p_cdda->i_track ) );
916         }
917
918         vlc_object_release( p_input );
919     }
920
921     return VLC_SUCCESS;
922 }
923
924
925 /*
926  * Local variables:
927  *  mode: C
928  *  style: gnu
929  * End:
930  */