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