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