]> git.sesse.net Git - vlc/blob - modules/access/cdda/info.c
Support for UDP-Lite (with full checksum coverage only atm)
[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 #include <vlc_playlist.h>  /* Has to come *after* cdda.h */
30
31 #include <cdio/cdio.h>
32 #include <cdio/cdtext.h>
33 #include <cdio/logging.h>
34 #include <cdio/cd_types.h>
35 #include "info.h"
36
37 #ifdef HAVE_ERRNO_H
38 #   include <errno.h>
39 #endif
40
41 static char *CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
42                             const char format_str[], const char *psz_mrl, 
43                             track_t i_track);
44
45 static char *CDDAFormatMRL( const access_t *p_access, track_t i_track );
46
47 #ifdef HAVE_LIBCDDB
48
49 #define free_and_dup(var, val) \
50   if (var) free(var);          \
51   if (val) var=strdup(val);
52
53
54 /* Saves CDDB information about CD-DA via libcddb. */
55 static void 
56 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
57 {
58     int i, i_matches;
59     cddb_conn_t  *conn = cddb_new();
60     const CdIo_t *p_cdio = p_cdda->p_cdio;
61
62     dbg_print( (INPUT_DBG_CALL), "" );
63
64 #ifdef FIXME_NOW
65     cddb_log_set_handler (uninit_log_handler);
66 #endif
67
68     if (!conn)
69     {
70         msg_Warn( p_access, "Unable to initialize libcddb" );
71         goto cddb_destroy;
72     }
73
74     cddb_set_email_address( conn,
75                             config_GetPsz( p_access,
76                                            MODULE_STRING "-cddb-email") );
77     cddb_set_server_name( conn,
78                           config_GetPsz( p_access,
79                                          MODULE_STRING "-cddb-server") );
80     cddb_set_server_port(conn,
81                          config_GetInt( p_access,
82                                         MODULE_STRING "-cddb-port") );
83
84   /* Set the location of the local CDDB cache directory.
85      The default location of this directory is */
86
87     if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
88         cddb_cache_disable(conn);
89
90     cddb_cache_set_dir(conn,
91                      config_GetPsz( p_access,
92                                     MODULE_STRING "-cddb-cachedir") );
93
94     cddb_set_timeout(conn,
95                    config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
96
97
98     if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" ) )
99     {
100         cddb_http_enable(conn);
101     }
102     else
103     {
104         cddb_http_disable(conn);
105     }
106
107     p_cdda->cddb.disc = cddb_disc_new();
108
109     if (!p_cdda->cddb.disc)
110     {
111         msg_Err( p_access, "Unable to create CDDB disc structure." );
112         goto cddb_end;
113     }
114
115     for(i = 0; i < p_cdda->i_tracks; i++)
116     {
117         track_t i_track =  p_cdda->i_first_track + i;
118         cddb_track_t *t = cddb_track_new();
119         cddb_track_set_frame_offset(t, 
120                                     cdio_get_track_lba(p_cdio, i_track));
121         cddb_disc_add_track(p_cdda->cddb.disc, t);
122     }
123
124     cddb_disc_set_length(p_cdda->cddb.disc,
125                          cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
126                          / CDIO_CD_FRAMES_PER_SEC);
127
128     if (!cddb_disc_calc_discid(p_cdda->cddb.disc))
129     {
130         msg_Err( p_access, "CDDB disc ID calculation failed" );
131         goto cddb_destroy;
132     }
133
134     i_matches = cddb_query(conn, p_cdda->cddb.disc);
135
136     if (i_matches > 0)
137     {
138         if (i_matches > 1)
139              msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
140                                  i_matches);
141         cddb_read(conn, p_cdda->cddb.disc);
142
143         if (p_cdda->i_debug & INPUT_DBG_CDDB)
144             cddb_disc_print(p_cdda->cddb.disc);
145
146     }
147     else
148     {
149         msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
150     }
151
152 cddb_destroy:
153     cddb_destroy(conn);
154
155 cddb_end: ;
156 }
157 #endif /*HAVE_LIBCDDB*/
158
159 #define add_meta_val(VLC_META, VAL)                           \
160   if ( p_cdda->p_meta && VAL) {                               \
161     /*vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL );*/        \
162     dbg_print( INPUT_DBG_META, "field %s: %s\n",              \
163             input_MetaTypeToLocalizedString(VLC_META), VAL ); \
164   }                                                           \
165
166 #define add_cddb_meta(FIELD, VLC_META)                                  \
167   add_meta_val(VLC_META, cddb_disc_get_##FIELD(p_cdda->cddb.disc));
168
169 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META)                 \
170   {                                                                     \
171     char psz_buf[100];                                                  \
172     snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC,                  \
173               cddb_disc_get_##FIELD(p_cdda->cddb.disc));                               \
174     psz_buf[sizeof(psz_buf)-1] = '\0';                                  \
175     add_meta_val(VLC_META, psz_buf);                                    \
176   }
177
178 /* Adds a string-valued entry to the stream and media information if
179    the string is not null or the null string.
180  */
181 #define add_info_str(CATEGORY, TITLE, FIELD)                      \
182   if (FIELD && strlen(FIELD)) {                                   \
183     input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY,     \
184                    _(TITLE), "%s", FIELD );                       \
185   }
186
187 /* Adds a numeric-valued entry to the stream and media information
188    if the number is not zero. */
189 #define add_info_val(CATEGORY, TITLE, FMT, FIELD)                 \
190   if (FIELD) {                                                    \
191     input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY,     \
192                    _(TITLE), FMT, FIELD );                        \
193   }
194
195 /* Adds a CDDB string-valued entry to the stream and media information
196    under category "Disc" if the string is not null or the null string.
197  */
198 #define add_cddb_disc_info_str(TITLE, FIELD)                    \
199   add_info_str("Disc", TITLE, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
200
201 /* Adds a CDDB numeric-valued entry to the stream and media information
202    under category "Disc" if the string is not null or the null string.
203  */
204 #define add_cddb_disc_info_val(TITLE, FMT, FIELD)               \
205   add_info_val("Disc", TITLE, FMT, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
206
207 /* Adds a CD-Text string-valued entry to the stream and media information
208    under category "Disc" if the string is not null or the null string.
209  */
210 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD)              \
211     add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
212
213 /* Adds a CD-Text string-valued entry to the stream and media information
214    under category "Disc" if the string is not null or the null string.
215  */
216 #define add_cdtext_disc_info_str(TITLE, FIELD) \
217   add_cdtext_info_str("Disc", TITLE, 0, FIELD)
218
219
220 /*
221   Saves Meta Information about the CD-DA.
222
223   Meta information used in "stream and media info" or in playlist
224   info. The intialization of CD-Text or CDDB is done here though.
225   Therefore, this should be called before CDDAMetaInfo is called.
226
227  */
228 void 
229 CDDAMetaInfoInit( access_t *p_access )
230 {
231     cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
232     
233     if ( ! p_cdda ) return;
234
235     dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d", 
236                p_cdda->i_tracks );
237
238     p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
239 #if 0
240     p_cdda->p_meta = vlc_meta_New();
241 #endif
242
243 #ifdef HAVE_LIBCDDB
244     if ( p_cdda->b_cddb_enabled )
245     {
246         GetCDDBInfo(p_access, p_cdda);
247     }
248
249 #endif /*HAVE_LIBCDDB*/
250     
251 #define TITLE_MAX 30
252     {
253         track_t i_track;
254
255         for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
256         {
257             p_cdda->p_cdtext[i_track] =
258               cdio_get_cdtext(p_cdda->p_cdio, i_track);
259         }
260     }
261 }
262
263 /*
264  In the Control routine, we handle Meta Information requests and
265  basically copy what was saved in CDDAMetaInfoInit.
266
267  If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
268  CD.
269  */
270 void 
271 CDDAMetaInfo( access_t *p_access, track_t i_track )
272 {
273     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
274     char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
275     char *psz_meta_artist = NULL;
276     
277     if ( ! p_cdda ) return;
278
279     dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
280
281 #ifdef HAVE_LIBCDDB
282
283     /* Set up for Meta and name for CDDB access. */
284     if ( p_cdda->b_cddb_enabled &&  p_cdda->cddb.disc )
285     {
286         if( CDIO_INVALID_TRACK == i_track )
287         {
288
289             psz_meta_title  = (char *)cddb_disc_get_title(p_cdda->cddb.disc);
290             psz_meta_artist = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
291             if ( cddb_disc_get_genre(p_cdda->cddb.disc) && 
292                      strlen(cddb_disc_get_genre(p_cdda->cddb.disc)) )
293                 add_cddb_meta(genre, vlc_meta_Genre);
294             if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc))
295                 add_cddb_meta_fmt(year, "%d", vlc_meta_Date );
296         }
297         else
298         {
299           cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
300           if (t != NULL )
301           {
302               if( cddb_track_get_title(t) != NULL && ! p_cdda->b_nav_mode )
303               {
304             add_meta_val( vlc_meta_Title, cddb_track_get_title(t) );
305               }
306               if( cddb_track_get_artist(t) != NULL )
307               {
308             add_meta_val( vlc_meta_Artist, cddb_track_get_artist(t) );
309               }
310           }
311         }
312     }
313
314 #endif /*HAVE_LIBCDDB*/
315     
316 #define TITLE_MAX 30
317     {
318         track_t i = p_cdda->i_tracks;
319         const int i_first_track = p_cdda->i_first_track;
320         char psz_buffer[MSTRTIME_MAX_SIZE];
321         unsigned int i_track_frames = 
322           cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
323           
324         mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
325
326         dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d", 
327                    (long int) i_duration, p_cdda->i_tracks );
328         input_Control( p_cdda->p_input, INPUT_ADD_INFO,
329                        _("Disc"), _("Duration"), "%s",
330                        secstotimestr( psz_buffer, i_duration ) );
331
332         if (p_cdda->psz_mcn) {
333             input_Control( p_cdda->p_input, INPUT_ADD_INFO,
334                            _("Disc"), _("Media Catalog Number (MCN)"), "%s", 
335                            p_cdda->psz_mcn );
336             
337             input_Control( p_cdda->p_input, INPUT_ADD_INFO,
338                            _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
339         }
340         
341
342 #ifdef HAVE_LIBCDDB
343         if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
344         {
345           add_cddb_disc_info_str("Artist (CDDB)", artist);
346           if ( CDDB_CAT_INVALID != cddb_disc_get_category(p_cdda->cddb.disc) )
347             add_info_str("Disc", "Category (CDDB)",
348                          CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
349           add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
350           add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
351           add_cddb_disc_info_str("Genre (CDDB)",  genre);
352           add_cddb_disc_info_str("Title (CDDB)",  title);
353           if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc) ) 
354             add_cddb_disc_info_val("Year (CDDB)", "%d", year);
355
356         }
357 #endif /*HAVE_LIBCDDB*/
358
359         if (p_cdda->p_cdtext[0])
360         {
361             char *psz_field;
362           
363             add_cdtext_disc_info_str("Arranger (CD-Text)",    CDTEXT_ARRANGER);
364             add_cdtext_disc_info_str("Composer (CD-Text)",    CDTEXT_COMPOSER);
365             add_cdtext_disc_info_str("Disc ID (CD-Text)",     CDTEXT_DISCID);
366             add_cdtext_disc_info_str("Genre (CD-Text)",       CDTEXT_GENRE);
367             add_cdtext_disc_info_str("Message (CD-Text)",     CDTEXT_MESSAGE);
368             add_cdtext_disc_info_str("Performer (CD-Text)",   CDTEXT_PERFORMER);
369             add_cdtext_disc_info_str("Songwriter (CD-Text)",  CDTEXT_SONGWRITER);
370             add_cdtext_disc_info_str("Title (CD-Text)",       CDTEXT_TITLE);
371
372             psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
373             if (psz_field && strlen(psz_field)) {   
374               psz_meta_title = psz_field;
375             }
376             psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
377             if (psz_field && strlen(psz_field)) {   
378               psz_meta_artist = psz_field;
379             }
380             
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( 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( vlc_meta_Artist, psz_meta_artist );
466         }
467         
468     }
469 }
470
471 #define add_format_str_info(val)                         \
472   {                                                      \
473     const char *str = val;                               \
474     unsigned int len;                                    \
475     if (val != NULL) {                                   \
476       len=strlen(str);                                   \
477       if (len != 0) {                                    \
478         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    \
479         tp += len;                                       \
480       }                                                  \
481       saw_control_prefix = false;                        \
482     }                                                    \
483   }
484
485 #define add_format_num_info(val, fmt)                    \
486   {                                                      \
487     char num_str[10];                                    \
488     unsigned int len;                                    \
489     sprintf(num_str, fmt, val);                          \
490     len=strlen(num_str);                                 \
491     if (len != 0) {                                      \
492       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  \
493       tp += len;                                         \
494     }                                                    \
495     saw_control_prefix = false;                          \
496   }
497
498 static inline bool
499 want_cddb_info(
500 cdda_data_t *p_cdda, char *psz_cdtext) 
501 {
502   /* We either don't have CD-Text info, or we do but we prefer to get CDDB
503      which means CDDB has been enabled and we were able to retrieve the info.*/
504 #ifdef HAVE_LIBCDDB
505   return !psz_cdtext || 
506     (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
507 #else
508   return false;
509 #endif
510 }
511
512
513 /*!
514    Take a format string and expand escape sequences, that is sequences that
515    begin with %, with information from the current CD.
516    The expanded string is returned. Here is a list of escape sequences:
517
518    %a : The album artist **
519    %A : The album information **
520    %C : Category **
521    %e : The extended track data
522    %I : CDDB disk ID **
523    %G : Genre **
524    %M : The current MRL
525    %m : The CD-DA Media Catalog Number (MCN)
526    %n : The number of tracks on the CD
527    %p : The artist/performer/composer in the track **
528    %T : The track number **
529    %s : Number of seconds in this track, or seconds in CD if invalid track
530    %S : Number of seconds on the CD
531    %t : The track name or MRL if no name 
532    %Y : The year 19xx or 20xx **
533    %% : a %
534 */
535 char *
536 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
537                const char format_str[], const char *psz_mrl, track_t i_track)
538 {
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     vlc_bool_t 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                 } else {
623                   if (p_cdda->p_cdtext[i_track]
624                       && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]) {
625                     add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
626                   
627                   } else 
628                     add_format_str_info(psz_mrl);
629                 }
630                 break;
631             case 'p':
632                 if ( CDIO_INVALID_TRACK == i_track ) break;
633                 if (p_cdda->p_cdtext[i_track] 
634                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
635                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
636                 if (want_cddb_info(p_cdda, psz))
637                   {
638                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
639                                                         i_track-1);
640                     if (t != NULL && cddb_track_get_artist(t) != NULL)
641                       psz = (char *)cddb_track_get_artist(t);
642                   }
643                 goto format_str;
644             case 'e':
645                 if ( CDIO_INVALID_TRACK == i_track ) break;
646                 if (p_cdda->p_cdtext[i_track] 
647                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
648                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
649                 if (want_cddb_info(p_cdda, psz))
650                 {
651                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
652                                                         i_track-1);
653                     if (t != NULL && cddb_track_get_ext_data(t) != NULL)
654                         psz = (char *)cddb_track_get_ext_data(t);
655                 } 
656                 goto format_str;
657                 break;
658 #else
659             case 'a':
660                 if (p_cdda->p_cdtext[0] 
661                     && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
662                     psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
663                 goto format_str;
664             case 'A':
665                 if (p_cdda->p_cdtext[0] 
666                     && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
667                     psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
668                 goto format_str;
669             case 'G':
670                 if (p_cdda->p_cdtext[0] 
671                     && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
672                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
673                 goto format_str;
674             case 'I':
675                 if (p_cdda->p_cdtext[0] 
676                     && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
677                   add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
678                 break;
679             case 'p':
680                 if ( CDIO_INVALID_TRACK == i_track ) break;
681                 if (p_cdda->p_cdtext[i_track] 
682                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
683                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
684                 goto format_str;
685             case 't':
686                 if ( CDIO_INVALID_TRACK == i_track ) break;
687                 if (p_cdda->p_cdtext[i_track] 
688                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
689                     psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
690                 else 
691                     psz = psz_mrl;
692                 goto format_str;
693             case 'e':
694                 if ( CDIO_INVALID_TRACK == i_track ) break;
695                 if (p_cdda->p_cdtext[i_track] 
696                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
697                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
698                 goto format_str;
699                 break;
700 #endif /*HAVE_LIBCDDB*/
701
702             case 's':
703                 if ( CDIO_INVALID_TRACK != i_track )
704                 {
705                     char psz_buffer[MSTRTIME_MAX_SIZE];
706                     unsigned int i_track_frames = 
707                       cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
708                     mtime_t i_duration = 
709                       i_track_frames / CDIO_CD_FRAMES_PER_SEC;
710                     add_format_str_info( secstotimestr( psz_buffer, 
711                                                         i_duration ) );
712                     break;
713                 }
714
715                 /* Fall through to disc duration if CDIO_INVALID_TRACK  */
716             case 'S':
717                 {
718                     char psz_buffer[MSTRTIME_MAX_SIZE];
719                     unsigned int i_track_frames = 
720                       cdio_get_track_lba(p_cdda->p_cdio, 
721                                          CDIO_CDROM_LEADOUT_TRACK);
722                     mtime_t i_duration = 
723                       i_track_frames / CDIO_CD_FRAMES_PER_SEC;
724                     add_format_str_info( secstotimestr( psz_buffer, 
725                                                         i_duration ) );
726                     break;
727                 }
728
729             case 'M':
730               add_format_str_info(psz_mrl);
731               break;
732
733             case 'm':
734               add_format_str_info(p_cdda->psz_mcn);
735               break;
736
737             case 'n':
738               add_format_num_info(p_cdda->i_tracks, "%d");
739               break;
740
741             case 'T':
742               add_format_num_info(i_track, "%02d");
743               break;
744             format_str:
745               if (psz)
746                 add_format_str_info(psz);
747               break;
748 #ifdef HAVE_LIBCDDB
749             not_special:
750 #endif
751             default:
752                 *tp++ = '%';
753                 *tp++ = format_str[i];
754                 saw_control_prefix = false;
755         }
756     }
757     return strdup(temp_str);
758 }
759
760 /* Return a MRL for the given track. The caller must free the 
761    allocated string. */
762 static char *
763 CDDAFormatMRL( const access_t *p_access, track_t i_track )
764 {
765     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
766     const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) 
767       + strlen(p_cdda->psz_source) +
768       + strlen("@T") + strlen("100") + 1;
769     char *psz_mrl = calloc( 1, psz_mrl_max );
770     
771     if (CDIO_INVALID_TRACK == i_track)
772       snprintf(psz_mrl, psz_mrl_max, "%s%s",
773                CDDA_MRL_PREFIX, p_cdda->psz_source);
774     else 
775       snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
776                CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
777     return psz_mrl;
778 }
779
780
781 /* Return a title string as specified by the titel format string for the 
782    given track. The caller must free the allocated string. */
783 char *
784 CDDAFormatTitle( const access_t *p_access, track_t i_track )
785
786
787     const char *config_varname = MODULE_STRING "-title-format";
788     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
789     char *psz_mrl = CDDAFormatMRL( p_access, i_track );
790
791     if( psz_mrl ) 
792     {
793         char *psz_name;
794 #ifdef HAVE_LIBCDDB
795         if (p_cdda->b_cddb_enabled)
796         {
797             config_varname = MODULE_STRING "-cddb-title-format";
798         }
799 #endif /*HAVE_LIBCDDB*/
800         psz_name = 
801           CDDAFormatStr( p_access, p_cdda,
802                          config_GetPsz( p_access, config_varname ),
803                          psz_mrl, i_track );
804         free(psz_mrl);
805         return psz_name;
806     }
807     return(NULL);
808 }
809
810 /* Adds a string-valued entry to the playlist information under "Track"
811    if the string is not null or the null string.
812  */
813 #define add_playlist_track_info_str(TITLE, FIELD)                        \
814     if (FIELD && strlen(FIELD))                                          \
815     {                                                                    \
816         input_ItemAddInfo( &p_item->input, _("Track"), _(TITLE),    \
817                               "%s", FIELD);                              \
818     }
819
820 static playlist_item_t *
821 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
822                         playlist_t *p_playlist, playlist_item_t *p_item, 
823                         track_t i_track )
824 {
825     unsigned int i_track_frames = 
826         cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) - 
827         cdio_get_track_lsn(p_cdda->p_cdio, i_track);
828     mtime_t i_mduration = i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
829     char *psz_title = NULL;
830     char *psz_mrl   = NULL;
831
832     playlist_item_t *p_child = NULL;
833
834     if( !p_item ) return NULL;
835
836     psz_title = CDDAFormatTitle( p_access, i_track ) ;
837     psz_mrl = CDDAFormatMRL( p_access, i_track  ) ;
838
839     dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
840                psz_mrl, psz_title, (long int) i_mduration / 1000000 );
841
842     p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
843     input_item_SetDuration( input_GetItem( p_child->p_input ),
844             (mtime_t) i_mduration );
845     free(psz_mrl);
846     free(psz_title);
847
848     if( !p_child ) return NULL;
849     return p_child;
850 }
851
852 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
853                        playlist_item_t *p_item, int i_track,
854                        vlc_bool_t b_single )
855 {
856 #if 0
857     add_playlist_track_info_str("Source",  p_cdda->psz_source);
858     input_ItemAddInfo( &p_item->input, _("Track"), _("Track Number"),
859                            "%d", i_track );
860
861     if (p_cdda->p_cdtext[i_track])
862     {
863         const cdtext_t *p = p_cdda->p_cdtext[i_track];
864         add_playlist_track_info_str("Arranger (CD-Text)",
865                                     p->field[CDTEXT_ARRANGER]);
866         add_playlist_track_info_str("Composer (CD-Text)",
867                                     p->field[CDTEXT_COMPOSER]);
868         add_playlist_track_info_str("Genre (CD-Text)",
869                                     p->field[CDTEXT_GENRE]);
870         add_playlist_track_info_str("Message (CD-Text)",
871                                     p->field[CDTEXT_MESSAGE]);
872         add_playlist_track_info_str("Performer (CD-Text)",
873                                     p->field[CDTEXT_PERFORMER]);
874         add_playlist_track_info_str("Songwriter (CD-Text)",
875                                     p->field[CDTEXT_SONGWRITER]);
876         add_playlist_track_info_str("Title (CD-Text)",
877                                     p->field[CDTEXT_TITLE]);
878     }
879
880 #ifdef HAVE_LIBCDDB
881     if (p_cdda->b_cddb_enabled)
882     {
883         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
884                                             i_track-p_cdda->i_first_track);
885
886         if (t)
887         {
888             if (cddb_track_get_artist(t))
889                 add_playlist_track_info_str("Artist (CDDB)",
890                                              cddb_track_get_artist(t));
891             if (cddb_track_get_title(t))
892                 add_playlist_track_info_str("Title (CDDB)",
893                                             cddb_track_get_title(t));
894             if (cddb_track_get_ext_data(t))
895                 add_playlist_track_info_str("Extended information (CDDB)",
896                                             cddb_track_get_ext_data(t));
897         }
898     }
899 #endif /*HAVE_LIBCDDB*/
900 #endif
901     return VLC_SUCCESS;
902 }
903
904 /* 
905    Fixes up playlist. 
906 */
907 int
908 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda, 
909                    vlc_bool_t b_single_track )
910 {
911     int i;
912     playlist_t * p_playlist = NULL;
913     const track_t i_first_track = p_cdda->i_first_track;
914     playlist_item_t *p_item = NULL;
915     vlc_bool_t b_play = VLC_FALSE;
916     track_t    i_track;
917
918 #ifdef HAVE_LIBCDDB
919     p_cdda->b_cddb_enabled =
920         config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
921     if( b_single_track && !p_cdda->b_cddb_enabled )
922         return VLC_SUCCESS;
923 #else
924     if( b_single_track )
925         return VLC_SUCCESS;
926 #endif
927
928     if (! p_cdda->b_nav_mode ) {
929         p_playlist = pl_Yield( p_access );
930     }
931
932     if( b_single_track || p_cdda->b_nav_mode ) {
933         i_track = p_cdda->i_track;
934     }
935     else
936     {
937         i_track = CDIO_INVALID_TRACK;
938     }
939     CDDAMetaInfoInit( p_access );
940     CDDAMetaInfo( p_access, p_cdda->i_track );
941
942     if( p_playlist )
943     {
944         input_thread_t *p_input = (input_thread_t*)vlc_object_find( p_access, VLC_OBJECT_INPUT, FIND_PARENT );
945         if( p_input )
946         {
947             p_item = playlist_ItemGetByInput( p_playlist, input_GetItem(p_input), VLC_FALSE );
948
949             if( p_item == p_playlist->status.p_item && !b_single_track )
950                 b_play = VLC_TRUE;
951             else
952                 b_play = VLC_FALSE;
953             vlc_object_release( p_input );
954         }
955     }
956
957     if( b_single_track && !p_cdda->b_nav_mode )
958     {
959         /*May fill out more information when the playlist user interface becomes
960            more mature.
961          */
962         track_t i_track = p_cdda->i_track;
963         unsigned int i_track_frames = 
964           cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
965         
966         input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
967         vlc_input_title_New();
968
969         asprintf( &t->psz_name, _("Track %i"), i_track );
970         t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
971
972         t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
973
974         if( p_item ) 
975         {
976             CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
977             input_item_SetDuration( p_item->p_input, (mtime_t) i_track_frames 
978               * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
979             input_item_SetURI( p_item->p_input, 
980                     CDDAFormatMRL( p_access, i_track ) );
981         }
982         
983         p_cdda->i_titles = 1;
984         p_access->info.i_update = INPUT_UPDATE_TITLE;
985     }
986     else
987     {
988         input_title_t *t;
989
990         if ( !p_cdda->b_nav_mode )
991           playlist_ItemToNode( p_playlist, p_item, VLC_FALSE );
992
993         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
994         {
995             playlist_item_t *p_child;
996             const track_t i_track = i_first_track + i;
997             unsigned int i_track_frames = 
998               cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
999
1000             t = p_cdda->p_title[i] = vlc_input_title_New();
1001
1002             asprintf( &t->psz_name, _("Track %i"), i_track );
1003             t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
1004
1005             t->i_length = I64C(1000000) * t->i_size 
1006               / CDDA_FREQUENCY_SAMPLE / 4;
1007
1008             if ( ! p_cdda->b_nav_mode ) {
1009               p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
1010                                                 p_item,
1011                                                 i_track );
1012               CDDAAddMetaToItem( p_access, p_cdda, p_child, i_track, 
1013                                  VLC_TRUE );
1014             }
1015         }
1016
1017         p_cdda->i_titles = p_cdda->i_tracks;
1018         p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1019         if( p_item )
1020         {
1021             input_item_SetDuration( p_item->p_input, (mtime_t) p_access->info.i_size
1022                     * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
1023             input_item_SetURI( p_item->p_input,
1024                     CDDAFormatMRL( p_access, p_cdda->i_track ) );
1025         }
1026     }
1027     
1028
1029     if( b_play )
1030     {
1031         playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE,
1032                           p_playlist->status.p_item, NULL );
1033     }
1034
1035     if (p_playlist) vlc_object_release( p_playlist );
1036     return VLC_SUCCESS;
1037 }
1038
1039
1040 /* 
1041  * Local variables:
1042  *  mode: C
1043  *  style: gnu
1044  * End:
1045  */