]> git.sesse.net Git - vlc/blob - modules/access/cdda/info.c
Honor "prefer-cdtext" option.
[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(FIELD, 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(FIELD, 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(FIELD, 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 )
223 {
224     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
225
226     if ( ! p_cdda ) return;
227
228     p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
229
230 #ifdef HAVE_LIBCDDB
231     if ( p_cdda->b_cddb_enabled )
232     {
233         GetCDDBInfo(p_access, p_cdda);
234         if ( p_cdda->cddb.disc )
235         {
236             p_cdda->p_meta = vlc_meta_New();
237             if( i_track == -1 )
238             {
239                 add_cddb_meta(title,    VLC_META_TITLE);
240                 add_cddb_meta(artist,   VLC_META_ARTIST);
241                 input_Control( p_cdda->p_input, INPUT_SET_NAME,
242                                p_cdda->cddb.disc->artist );
243             }
244             else
245             {
246                 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
247                                                     i_track-1);
248                 if (t != NULL )
249                 {
250                     if( t->title != NULL )
251                     {
252                         add_meta_val( NULL, VLC_META_TITLE, t->title );
253                     }
254                     if( t->artist != NULL )
255                     {
256                         add_meta_val( NULL, VLC_META_ARTIST, t->artist );
257                     }
258                 }
259             }
260             add_cddb_meta(genre,    VLC_META_GENRE);
261             add_cddb_meta_fmt(year,   "%d", VLC_META_DATE );
262         }
263     }
264
265 #endif /*HAVE_LIBCDDB*/
266 #define TITLE_MAX 30
267     {
268         track_t i = p_cdda->i_tracks;
269         const int i_first_track = p_cdda->i_first_track;
270         char psz_buffer[MSTRTIME_MAX_SIZE];
271         mtime_t i_duration =
272               (p_cdda->lsn[i_first_track+i] - p_cdda->lsn[i_first_track])
273               / CDIO_CD_FRAMES_PER_SEC;
274
275         dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d", 
276                    (long int) i_duration, p_cdda->i_tracks );
277         input_Control( p_cdda->p_input, INPUT_ADD_INFO,
278                        _("Disc"), _("Duration"), "%s",
279                        secstotimestr( psz_buffer, i_duration ) );
280
281         input_Control( p_cdda->p_input, INPUT_ADD_INFO,
282                        _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
283
284 #ifdef HAVE_LIBCDDB
285         if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
286         {
287           add_cddb_disc_info_str("Artist (CDDB)", artist);
288           add_cddb_disc_info_str("Genre (CDDB)",  genre);
289           add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
290           add_cddb_disc_info_val("Year (CDDB)", "%d", year);
291           add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
292           add_cddb_disc_info_str("Title (CDDB)",  title);
293           add_info_str("Disc", "Category (CDDB)",
294                         CDDB_CATEGORY[p_cdda->cddb.disc->category]);
295
296         }
297 #endif /*HAVE_LIBCDDB*/
298
299         p_cdda->p_cdtext[0] = cdio_get_cdtext(p_cdda->p_cdio, 0);
300         if (p_cdda->p_cdtext[0])
301         {
302             add_cdtext_disc_info_str("Arranger (CD-Text)",    CDTEXT_ARRANGER);
303             add_cdtext_disc_info_str("Composer (CD-Text)",    CDTEXT_COMPOSER);
304             add_cdtext_disc_info_str("Disc ID (CD-Text)",     CDTEXT_DISCID);
305             add_cdtext_disc_info_str("Genre (CD-Text)",       CDTEXT_GENRE);
306             add_cdtext_disc_info_str("Message (CD-Text)",     CDTEXT_MESSAGE);
307             add_cdtext_disc_info_str("Performer (CD-Text)",   CDTEXT_PERFORMER);
308             add_cdtext_disc_info_str("Songwriter (CD-Text)",  CDTEXT_SONGWRITER);
309             add_cdtext_disc_info_str("Title (CD-Text)",       CDTEXT_TITLE);
310         }
311
312         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
313         {
314           char psz_track[TITLE_MAX];
315           const track_t i_track = i_first_track + i;
316           mtime_t i_duration = (p_cdda->lsn[i_track+1] -
317                                 p_cdda->lsn[i_track])
318             / CDIO_CD_FRAMES_PER_SEC;
319           snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
320
321           input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
322                          _("Duration"), "%s",
323                          secstotimestr( psz_buffer, i_duration ) );
324           
325           p_cdda->p_cdtext[i_track] =
326             cdio_get_cdtext(p_cdda->p_cdio, i_track);
327           
328           if (p_cdda->p_cdtext[i_track])
329             {
330               add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
331                                    i_track, CDTEXT_ARRANGER);
332               add_cdtext_info_str( psz_track, "Composer (CD-Text)",
333                                    i_track, CDTEXT_COMPOSER);
334               add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
335                                    i_track, CDTEXT_DISCID);
336               add_cdtext_info_str( psz_track, "Genre (CD-Text)",
337                                    i_track, CDTEXT_GENRE);
338               add_cdtext_info_str( psz_track, "Message (CD-Text)",
339                                    i_track, CDTEXT_MESSAGE);
340               add_cdtext_info_str( psz_track, "Performer (CD-Text)",
341                                    i_track, CDTEXT_PERFORMER);
342               add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
343                                    i_track, CDTEXT_SONGWRITER);
344               add_cdtext_info_str( psz_track, "Title (CD-Text)",
345                                    i_track, CDTEXT_TITLE);
346             }
347           
348 #ifdef HAVE_LIBCDDB
349           if (p_cdda->b_cddb_enabled)
350             {
351               cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
352               if (t != NULL)
353                 {
354                   add_info_str(psz_track, "Artist (CDDB)", t->artist);
355                   add_info_str(psz_track, "Title (CDDB)",  t->title);
356                   add_info_str(psz_track, "Extended Data (CDDB)",
357                                t->ext_data);
358                 }
359             }
360 #endif /*HAVE_LIBCDDB*/
361         }
362     }
363 }
364
365 #define add_format_str_info(val)                         \
366   {                                                      \
367     const char *str = val;                               \
368     unsigned int len;                                    \
369     if (val != NULL) {                                   \
370       len=strlen(str);                                   \
371       if (len != 0) {                                    \
372         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    \
373         tp += len;                                       \
374       }                                                  \
375       saw_control_prefix = false;                        \
376     }                                                    \
377   }
378
379 #define add_format_num_info(val, fmt)                    \
380   {                                                      \
381     char num_str[10];                                    \
382     unsigned int len;                                    \
383     sprintf(num_str, fmt, val);                          \
384     len=strlen(num_str);                                 \
385     if (len != 0) {                                      \
386       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  \
387       tp += len;                                         \
388     }                                                    \
389     saw_control_prefix = false;                          \
390   }
391
392 static inline bool
393 want_cddb_info(
394 cdda_data_t *p_cdda, char *psz_cdtext) 
395 {
396   /* We either don't have CD-Text info, or we do but we prefer to get CDDB
397      which means CDDB has been enabled and we were able to retrieve the info.*/
398   return !psz_cdtext || 
399     (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
400 }
401
402
403 /*!
404    Take a format string and expand escape sequences, that is sequences that
405    begin with %, with information from the current CD.
406    The expanded string is returned. Here is a list of escape sequences:
407
408    %a : The album artist **
409    %A : The album information **
410    %C : Category **
411    %I : CDDB disk ID **
412    %G : Genre **
413    %M : The current MRL
414    %m : The CD-DA Media Catalog Number (MCN)
415    %n : The number of tracks on the CD
416    %p : The artist/performer/composer in the track **
417    %T : The track number **
418    %s : Number of seconds in this track
419    %t : The name **
420    %Y : The year 19xx or 20xx **
421    %% : a %
422 */
423 static char *
424 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
425                const char format_str[], const char *mrl, track_t i_track)
426 {
427 #define TEMP_STR_SIZE 256
428 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
429     static char    temp_str[TEMP_STR_SIZE];
430     size_t i;
431     char * tp = temp_str;
432     vlc_bool_t saw_control_prefix = false;
433     size_t format_len = strlen(format_str);
434
435     memset(temp_str, 0, TEMP_STR_SIZE);
436
437     for (i=0; i<format_len; i++)
438     {
439         char *psz = NULL;
440
441         if (!saw_control_prefix && format_str[i] != '%')
442         {
443             *tp++ = format_str[i];
444             saw_control_prefix = false;
445             continue;
446         }
447
448         switch(format_str[i])
449         {
450             case '%':
451               if (saw_control_prefix)
452               {
453                   *tp++ = '%';
454               }
455               saw_control_prefix = !saw_control_prefix;
456               break;
457 #ifdef HAVE_LIBCDDB
458             case 'a':
459                 if (p_cdda->p_cdtext[0] 
460                     && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
461                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
462                 if (want_cddb_info(p_cdda, psz))
463                   psz = p_cdda->cddb.disc->artist;
464                 goto format_str;
465             case 'A':
466                 if (p_cdda->p_cdtext[0] 
467                     && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
468                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
469                 if (want_cddb_info(p_cdda, psz))
470                   psz =  p_cdda->cddb.disc->title;
471                 goto format_str;
472             case 'C':
473                 if (!p_cdda->b_cddb_enabled) goto not_special;
474                 if (p_cdda->cddb.disc)
475                     add_format_str_info(
476                                   CDDB_CATEGORY[p_cdda->cddb.disc->category]);
477                 break;
478             case 'G':
479                 if (p_cdda->p_cdtext[0] 
480                     && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
481                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
482                 if (want_cddb_info(p_cdda, psz))
483                   psz = p_cdda->cddb.disc->genre;
484                 goto format_str;
485             case 'I':
486                 if (p_cdda->p_cdtext[0] 
487                     && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
488                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
489                 if (want_cddb_info(p_cdda, psz)) {
490                      add_format_num_info(p_cdda->cddb.disc->discid, "%x");
491                 } else if (psz)
492                      add_format_str_info(psz);
493                 break;
494             case 'Y':
495                 if (!p_cdda->b_cddb_enabled) goto not_special;
496                 if (p_cdda->cddb.disc)
497                     add_format_num_info(p_cdda->cddb.disc->year, "%5d");
498                 break;
499             case 't':
500                 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
501                 {
502                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
503                                                         i_track-1);
504                     if (t != NULL && t->title != NULL)
505                       add_format_str_info(t->title);
506                 }
507                 else goto not_special;
508                 break;
509             case 'p':
510                 if (p_cdda->p_cdtext[i_track] 
511                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
512                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
513                 if (want_cddb_info(p_cdda, psz))
514                   {
515                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
516                                                         i_track-1);
517                     if (t != NULL && t->artist != NULL)
518                       psz = t->artist;
519                   }
520                 goto format_str;
521             case 'e':
522                 if (p_cdda->p_cdtext[i_track] 
523                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
524                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
525                 if (want_cddb_info(p_cdda, psz))
526                 {
527                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
528                                                         i_track-1);
529                     if (t != NULL && t->ext_data != NULL)
530                         psz = t->ext_data;
531                 } 
532                 goto format_str;
533                 break;
534             case 's':
535                 if (p_cdda->b_cddb_enabled)
536                 {
537                     char psz_buffer[MSTRTIME_MAX_SIZE];
538                     mtime_t i_duration = (p_cdda->lsn[i_track+1] -
539                                           p_cdda->lsn[i_track])
540                                           / CDIO_CD_FRAMES_PER_SEC;
541                     add_format_str_info(secstotimestr( psz_buffer,
542                                        i_duration ) );
543                 } else goto not_special;
544                 break;
545 #else
546             case 'a':
547                 if (p_cdda->p_cdtext[0] 
548                     && p_cdda->p_cdtext->field[CDTEXT_PERFORMER]
549                     psz = p_cdda->p_cdtext->field[CDTEXT_PERFORMER]);
550                 goto format_str;
551             case 'A':
552                 if (p_cdda->p_cdtext[0] 
553                     && p_cdda->p_cdtext->field[CDTEXT_TITLE]
554                     psz = p_cdda->p_cdtext->field[CDTEXT_TITLE]);
555                 goto format_str;
556             case 'G':
557                 if (p_cdda->p_cdtext[0] 
558                     && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
559                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
560                 goto format_str;
561             case 'I':
562                 if (p_cdda->p_cdtext[0] 
563                     && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
564                   add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
565                 break;
566             case 'p':
567                 if (p_cdda->p_cdtext[i_track] 
568                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
569                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
570                 goto format_str;
571             case 'e':
572                 if (p_cdda->p_cdtext[i_track] 
573                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
574                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
575                 goto format_str;
576                 break;
577 #endif /*HAVE_LIBCDDB*/
578
579             case 'M':
580               add_format_str_info(mrl);
581               break;
582
583             case 'm':
584               add_format_str_info(p_cdda->psz_mcn);
585               break;
586
587             case 'n':
588               add_format_num_info(p_cdda->i_tracks, "%d");
589               break;
590
591             case 'T':
592               add_format_num_info(i_track, "%02d");
593               break;
594             format_str:
595               if (psz)
596                 add_format_str_info(psz);
597               break;
598 #ifdef HAVE_LIBCDDB
599             not_special:
600 #endif
601             default:
602                 *tp++ = '%';
603                 *tp++ = format_str[i];
604                 saw_control_prefix = false;
605         }
606     }
607     return strdup(temp_str);
608 }
609
610 /* Adds a string-valued entry to the playlist information under "Track"
611    if the string is not null or the null string.
612  */
613 #define add_playlist_track_info_str(TITLE, FIELD)                        \
614     if (FIELD && strlen(FIELD))                                          \
615     {                                                                    \
616         playlist_ItemAddInfo( p_item, _("Track"), _(TITLE),              \
617                               "%s", FIELD);                              \
618     }
619
620 playlist_item_t *
621 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
622                         playlist_t *p_playlist, playlist_item_t *p_item, 
623                         track_t i_track, char *psz_mrl, int psz_mrl_max,
624                         const char *psz_source )
625 {
626     mtime_t i_duration = (p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track])
627                          * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
628     char *psz_title;
629     char *config_varname = MODULE_STRING "-title-format";
630
631     playlist_item_t *p_child = NULL;
632
633     if( !p_item )
634     {
635         return NULL;
636     }
637
638 #ifdef HAVE_LIBCDDB
639     if (p_cdda->b_cddb_enabled)
640     {
641         config_varname = MODULE_STRING "-cddb-title-format";
642     }
643 #endif /*HAVE_LIBCDDB*/
644
645
646     psz_title = CDDAFormatStr( p_access, p_cdda,
647                                config_GetPsz( p_access, config_varname ),
648                                psz_mrl, i_track);
649
650     snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
651              CDDA_MRL_PREFIX, psz_source, i_track);
652
653     dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
654                psz_mrl, psz_title, (long int) i_duration / 1000000 );
655
656     p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
657     p_child->input.b_fixed_name = VLC_TRUE;
658
659     if( !p_child ) return NULL;
660
661     playlist_NodeAddItem( p_playlist, p_child,
662                           p_item->pp_parents[0]->i_view,
663                           p_item, PLAYLIST_APPEND, PLAYLIST_END );
664     playlist_CopyParents( p_item, p_child );
665
666     return p_child;
667 }
668
669 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
670                        playlist_item_t *p_item, const char *psz_source,
671                        int i_track, vlc_bool_t b_single )
672 {
673     vlc_mutex_lock( &p_item->input.lock );
674
675     add_playlist_track_info_str("Source",  psz_source);
676     playlist_ItemAddInfo( p_item, _("Track"), _("Track Number"),
677                           "%d", i_track );
678
679     if (p_cdda->p_cdtext[0])
680     {
681         const cdtext_t *p = p_cdda->p_cdtext[0];
682         add_playlist_track_info_str("Disc Arranger (CD-Text)",
683                                      p->field[CDTEXT_ARRANGER]);
684         add_playlist_track_info_str("Disc Composer (CD-Text)",
685                                     p->field[CDTEXT_COMPOSER]);
686         add_playlist_track_info_str("Disc ID (CD-Text)",
687                                     p->field[CDTEXT_DISCID]);
688         add_playlist_track_info_str("Disc Genre (CD-Text)",
689                                     p->field[CDTEXT_GENRE]);
690         add_playlist_track_info_str("Disc Message (CD-Text)",
691                                     p->field[CDTEXT_MESSAGE]);
692         add_playlist_track_info_str("Disc Performer (CD-Text)",
693                                     p->field[CDTEXT_PERFORMER]);
694         add_playlist_track_info_str("Disc Songwriter (CD-Text)",
695                                     p->field[CDTEXT_SONGWRITER]);
696         add_playlist_track_info_str("Disc Title (CD-Text)",
697                                     p->field[CDTEXT_TITLE]);
698     }
699
700     if (p_cdda->p_cdtext[i_track])
701     {
702         const cdtext_t *p = p_cdda->p_cdtext[i_track];
703         add_playlist_track_info_str("Arranger (CD-Text)",
704                                     p->field[CDTEXT_ARRANGER]);
705         add_playlist_track_info_str("Composer (CD-Text)",
706                                     p->field[CDTEXT_COMPOSER]);
707         add_playlist_track_info_str("Genre (CD-Text)",
708                                     p->field[CDTEXT_GENRE]);
709         add_playlist_track_info_str("Message (CD-Text)",
710                                     p->field[CDTEXT_MESSAGE]);
711         add_playlist_track_info_str("Performer (CD-Text)",
712                                     p->field[CDTEXT_PERFORMER]);
713         add_playlist_track_info_str("Songwriter (CD-Text)",
714                                     p->field[CDTEXT_SONGWRITER]);
715         add_playlist_track_info_str("Title (CD-Text)",
716                                     p->field[CDTEXT_TITLE]);
717     }
718
719 #ifdef HAVE_LIBCDDB
720     if (p_cdda->b_cddb_enabled)
721     {
722         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
723                                             i_track-p_cdda->i_first_track);
724
725         add_playlist_track_info_str("Disc Album (CDDB)",
726                                     p_cdda->cddb.disc->title);
727         add_playlist_track_info_str("Disc Artist(s) (CDDB)",
728                                     p_cdda->cddb.disc->artist);
729         add_playlist_track_info_str("Disc Category (CDDB)",
730                                     CDDB_CATEGORY[p_cdda->cddb.disc->category]);
731         add_playlist_track_info_str("Disc Genre (CDDB)",
732                                     p_cdda->cddb.disc->genre);
733
734         if ( p_cdda->cddb.disc->discid )
735         {
736             playlist_ItemAddInfo( p_item, _("Track"), _("Disc ID (CDDB)"),
737                                   "%x", p_cdda->cddb.disc->discid );
738         }
739         if (p_cdda->cddb.disc->year != 0)
740         {
741             playlist_ItemAddInfo( p_item, _("Track"), _("Year (CDDB)"),
742                                  "%5d", p_cdda->cddb.disc->year );
743         }
744
745         if (t)
746         {
747             if (t->artist)
748                 add_playlist_track_info_str("Track Artist (CDDB)",
749                                              t->artist);
750            if (t->title)
751                 add_playlist_track_info_str("Track Title (CDDB)",
752                                             t->title);
753         }
754     }
755 #endif /*HAVE_LIBCDDB*/
756
757     vlc_mutex_unlock( &p_item->input.lock );
758
759     return VLC_SUCCESS;
760 }
761
762 int
763 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
764                    const char *psz_source, vlc_bool_t b_single_track )
765 {
766     int i;
767     playlist_t * p_playlist;
768     char       * psz_mrl;
769     unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
770       strlen("@T") + strlen("100") + 1;
771     const track_t i_first_track = p_cdda->i_first_track;
772     playlist_item_t *p_item;
773     vlc_bool_t b_play = VLC_FALSE;
774
775 #ifdef HAVE_LIBCDDB
776     p_cdda->b_cddb_enabled =
777         config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
778     if( b_single_track && !p_cdda->b_cddb_enabled )
779         return VLC_SUCCESS;
780 #else
781     if( b_single_track )
782         return VLC_SUCCESS;
783 #endif
784
785     psz_mrl = malloc( psz_mrl_max );
786
787     if( psz_mrl == NULL )
788     {
789         msg_Warn( p_access, "out of memory" );
790         return VLC_ENOMEM;
791     }
792
793     p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
794                                                FIND_ANYWHERE );
795     if( !p_playlist )
796     {
797         msg_Warn( p_access, "can't find playlist" );
798         free(psz_mrl);
799         return VLC_EGENERIC;
800     }
801
802     if( b_single_track )
803     {
804         CDDAMetaInfo( p_access, p_cdda->i_track );
805     }
806     else
807     {
808         CDDAMetaInfo( p_access, -1 );
809     }
810
811     p_item = playlist_ItemGetByInput( p_playlist,
812                         ((input_thread_t *)p_access->p_parent)->input.p_item );
813
814     if( p_item == p_playlist->status.p_item && !b_single_track )
815     {
816         b_play = VLC_TRUE;
817     }
818     else
819     {
820         b_play = VLC_FALSE;
821     }
822
823     if( b_single_track )
824     {
825         /*May fill out more information when the playlist user interface becomes
826            more mature.
827          */
828         track_t i_track = p_cdda->i_track;
829
830         input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
831         vlc_input_title_New();
832
833         asprintf( &t->psz_name, _("Track %i"), i_track );
834         t->i_size = p_access->info.i_size =
835                   ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) *
836                              (int64_t) CDIO_CD_FRAMESIZE_RAW;
837
838         t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
839
840
841         CDDAAddMetaToItem( p_access, p_cdda, p_item, psz_source, i_track,
842                            VLC_FALSE );
843
844         p_cdda->i_titles = 1;
845     }
846     else
847     {
848         playlist_ItemToNode( p_playlist, p_item );
849         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
850         {
851             playlist_item_t *p_child;
852             const track_t i_track = i_first_track + i;
853             input_title_t *t = p_cdda->p_title[i] = vlc_input_title_New();
854
855             asprintf( &t->psz_name, _("Track %i"), i_track );
856             t->i_size = ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) *
857                           (int64_t) CDIO_CD_FRAMESIZE_RAW;
858
859             t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
860
861             p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
862                                               p_item,
863                                               i_track, psz_mrl,
864                                               psz_mrl_max, psz_source );
865             CDDAAddMetaToItem( p_access, p_cdda, p_child, psz_source,
866                                i_track, VLC_TRUE );
867         }
868         p_cdda->i_titles = p_cdda->i_tracks; /* should be +1 */
869         p_access->info.i_size =
870                (p_cdda->lsn[i_first_track + p_cdda->i_tracks]
871                - p_cdda->lsn[i_first_track]) * (int64_t) CDIO_CD_FRAMESIZE_RAW;
872     }
873
874     if( b_play )
875     {
876         playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
877                           p_playlist->status.i_view,
878                           p_playlist->status.p_item, NULL );
879     }
880
881     vlc_object_release( p_playlist );
882
883     return VLC_SUCCESS;
884 }
885