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