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