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