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