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