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