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