]> git.sesse.net Git - vlc/blob - modules/access/cdda/info.c
Fix indentation.
[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 #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         {
333             input_Control( p_cdda->p_input, INPUT_ADD_INFO,
334                 _("Disc"), _("Media Catalog Number (MCN)"), "%s",
335                 p_cdda->psz_mcn );
336             input_Control( p_cdda->p_input, INPUT_ADD_INFO,
337                 _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
338         }
339
340 #ifdef HAVE_LIBCDDB
341         if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
342         {
343             add_cddb_disc_info_str("Artist (CDDB)", artist);
344             if ( CDDB_CAT_INVALID != cddb_disc_get_category(p_cdda->cddb.disc) )
345                 add_info_str("Disc", "Category (CDDB)",
346                         CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
347             add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
348             add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
349             add_cddb_disc_info_str("Genre (CDDB)",  genre);
350             add_cddb_disc_info_str("Title (CDDB)",  title);
351             if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc) )
352                 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
353
354         }
355 #endif /*HAVE_LIBCDDB*/
356
357         if (p_cdda->p_cdtext[0])
358         {
359             char *psz_field;
360
361             add_cdtext_disc_info_str("Arranger (CD-Text)",    CDTEXT_ARRANGER);
362             add_cdtext_disc_info_str("Composer (CD-Text)",    CDTEXT_COMPOSER);
363             add_cdtext_disc_info_str("Disc ID (CD-Text)",     CDTEXT_DISCID);
364             add_cdtext_disc_info_str("Genre (CD-Text)",       CDTEXT_GENRE);
365             add_cdtext_disc_info_str("Message (CD-Text)",     CDTEXT_MESSAGE);
366             add_cdtext_disc_info_str("Performer (CD-Text)",   CDTEXT_PERFORMER);
367             add_cdtext_disc_info_str("Songwriter (CD-Text)",  CDTEXT_SONGWRITER);
368             add_cdtext_disc_info_str("Title (CD-Text)",       CDTEXT_TITLE);
369
370             psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
371             if (psz_field && strlen(psz_field))
372                 psz_meta_title = psz_field;
373
374             psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
375             if (psz_field && strlen(psz_field))
376                 psz_meta_artist = psz_field;
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)",
427                             cddb_track_get_artist(t));
428                     add_info_str(psz_track, "Title (CDDB)",
429                             cddb_track_get_title(t));
430                     add_info_str(psz_track, "Extended Data (CDDB)",
431                             cddb_track_get_ext_data(t));
432                 }
433             }
434 #endif /*HAVE_LIBCDDB*/
435         }
436
437     /* Above we should have set psz_meta_title and psz_meta_artist
438        to CDDB or CD-Text values or the default value depending on
439        availablity and user preferences.
440
441        So now add the title and artist to VLC's meta, and the name
442        as shown in the status bar and playlist entry.
443
444        For playlist mode, the meta title is what's seen at the
445        bottom and in the playlist. For nav-mode playing, it is
446        done by input_control. I don't understand why they do
447        different things. In either case, we may have customized to
448        put in the track name.
449      */
450         if ( CDIO_INVALID_TRACK != i_track )
451         {
452             char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
453             if ( !p_cdda->b_nav_mode ) {
454                 add_meta_val( vlc_meta_Title, psz_name );
455             } else
456             {
457                 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
458                 free(psz_name);
459             }
460             if (psz_meta_artist)
461             add_meta_val( vlc_meta_Artist, psz_meta_artist );
462         }
463     }
464 }
465
466 #define add_format_str_info(val)                         \
467   {                                                      \
468     const char *str = val;                               \
469     unsigned int len;                                    \
470     if (val != NULL) {                                   \
471       len=strlen(str);                                   \
472       if (len != 0) {                                    \
473         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    \
474         tp += len;                                       \
475       }                                                  \
476       saw_control_prefix = false;                        \
477     }                                                    \
478   }
479
480 #define add_format_num_info(val, fmt)                    \
481   {                                                      \
482     char num_str[10];                                    \
483     unsigned int len;                                    \
484     sprintf(num_str, fmt, val);                          \
485     len=strlen(num_str);                                 \
486     if (len != 0) {                                      \
487       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  \
488       tp += len;                                         \
489     }                                                    \
490     saw_control_prefix = false;                          \
491   }
492
493 static inline bool
494 want_cddb_info(
495 cdda_data_t *p_cdda, char *psz_cdtext)
496 {
497   /* We either don't have CD-Text info, or we do but we prefer to get CDDB
498      which means CDDB has been enabled and we were able to retrieve the info.*/
499 #ifdef HAVE_LIBCDDB
500     return !psz_cdtext ||
501         (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
502 #else
503     return false;
504 #endif
505 }
506
507
508 /*!
509    Take a format string and expand escape sequences, that is sequences that
510    begin with %, with information from the current CD.
511    The expanded string is returned. Here is a list of escape sequences:
512
513    %a : The album artist **
514    %A : The album information **
515    %C : Category **
516    %e : The extended track data
517    %I : CDDB disk ID **
518    %G : Genre **
519    %M : The current MRL
520    %m : The CD-DA Media Catalog Number (MCN)
521    %n : The number of tracks on the CD
522    %p : The artist/performer/composer in the track **
523    %T : The track number **
524    %s : Number of seconds in this track, or seconds in CD if invalid track
525    %S : Number of seconds on the CD
526    %t : The track name or MRL if no name
527    %Y : The year 19xx or 20xx **
528    %% : a %
529 */
530 char *
531 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
532                const char format_str[], const char *psz_mrl, track_t i_track)
533 {
534 #define TEMP_STR_SIZE 256
535 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
536     static char temp_str[TEMP_STR_SIZE];
537     size_t i;
538     char * tp = temp_str;
539     bool saw_control_prefix = false;
540     size_t format_len = strlen(format_str);
541
542     memset(temp_str, 0, TEMP_STR_SIZE);
543
544     for (i=0; i<format_len; i++)
545     {
546         char *psz = NULL;
547
548         if (!saw_control_prefix && format_str[i] != '%')
549         {
550             *tp++ = format_str[i];
551             saw_control_prefix = false;
552             continue;
553         }
554
555         switch(format_str[i])
556         {
557             case '%':
558               if (saw_control_prefix)
559               {
560                   *tp++ = '%';
561               }
562               saw_control_prefix = !saw_control_prefix;
563               break;
564 #ifdef HAVE_LIBCDDB
565             case 'a':
566                 if (p_cdda->p_cdtext[0]
567                     && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
568                     psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
569                 if (want_cddb_info(p_cdda, psz))
570                     psz = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
571                 goto format_str;
572             case 'A':
573                 if (p_cdda->p_cdtext[0]
574                     && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
575                     psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
576                 if (want_cddb_info(p_cdda, psz))
577                     psz =  (char *)cddb_disc_get_title(p_cdda->cddb.disc);
578                 goto format_str;
579             case 'C':
580                 if (!p_cdda->b_cddb_enabled) goto not_special;
581                 if (p_cdda->cddb.disc)
582                     add_format_str_info(CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
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 = (char *)cddb_disc_get_genre(p_cdda->cddb.disc);
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(cddb_disc_get_discid(p_cdda->cddb.disc), "%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(cddb_disc_get_year(p_cdda->cddb.disc),
604                     "%5d");
605                 break;
606             case 't':
607                 if ( CDIO_INVALID_TRACK == i_track ) break;
608                 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
609                 {
610                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
611                                                         i_track-1);
612                     if (t != NULL && cddb_track_get_title(t) != NULL) {
613                       add_format_str_info(cddb_track_get_title(t));
614                     } else {
615                       add_format_str_info(psz_mrl);
616                     }
617                 }
618                 else
619                 {
620                     if (p_cdda->p_cdtext[i_track]
621                         && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
622                     {
623                         add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
624                     }
625                     else
626                         add_format_str_info(psz_mrl);
627                 }
628                 break;
629             case 'p':
630                 if ( CDIO_INVALID_TRACK == i_track ) break;
631                 if (p_cdda->p_cdtext[i_track]
632                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
633                     psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
634                 if (want_cddb_info(p_cdda, psz))
635                 {
636                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
637                                 i_track-1);
638                     if (t != NULL && cddb_track_get_artist(t) != NULL)
639                     psz = (char *)cddb_track_get_artist(t);
640                 }
641                 goto format_str;
642             case 'e':
643                     if ( CDIO_INVALID_TRACK == i_track ) break;
644                     if (p_cdda->p_cdtext[i_track]
645                         && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
646                     psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
647                     if (want_cddb_info(p_cdda, psz))
648                     {
649                         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
650                                                             i_track-1);
651                         if (t != NULL && cddb_track_get_ext_data(t) != NULL)
652                             psz = (char *)cddb_track_get_ext_data(t);
653                     }
654                     goto format_str;
655                 break;
656 #else
657             case 'a':
658                 if (p_cdda->p_cdtext[0]
659                 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
660                 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
661                     goto format_str;
662             case 'A':
663                 if (p_cdda->p_cdtext[0]
664                     && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
665                 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
666                 goto format_str;
667             case 'G':
668                 if (p_cdda->p_cdtext[0]
669                 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
670                     psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
671                 goto format_str;
672             case 'I':
673                 if (p_cdda->p_cdtext[0]
674                     && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
675                     add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
676                 break;
677             case 'p':
678                 if ( CDIO_INVALID_TRACK == i_track ) break;
679                 if (p_cdda->p_cdtext[i_track]
680                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
681                 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
682                 goto format_str;
683             case 't':
684                 if ( CDIO_INVALID_TRACK == i_track ) break;
685                 if (p_cdda->p_cdtext[i_track]
686                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
687                     psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
688                 else
689                     psz = psz_mrl;
690                 goto format_str;
691             case 'e':
692                 if ( CDIO_INVALID_TRACK == i_track ) break;
693                 if (p_cdda->p_cdtext[i_track]
694                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
695                 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
696                 goto format_str;
697                 break;
698 #endif /*HAVE_LIBCDDB*/
699
700             case 's':
701                 if ( CDIO_INVALID_TRACK != i_track )
702                 {
703                     char psz_buffer[MSTRTIME_MAX_SIZE];
704                     unsigned int i_track_frames =
705                     cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
706                     mtime_t i_duration =
707                         i_track_frames / CDIO_CD_FRAMES_PER_SEC;
708                     add_format_str_info( secstotimestr( psz_buffer,
709                             i_duration ) );
710                     break;
711                 }
712
713             /* Fall through to disc duration if CDIO_INVALID_TRACK  */
714             case 'S':
715                 {
716                     char psz_buffer[MSTRTIME_MAX_SIZE];
717                     unsigned int i_track_frames =
718                     cdio_get_track_lba(p_cdda->p_cdio,
719                         CDIO_CDROM_LEADOUT_TRACK);
720                     mtime_t i_duration =
721                     i_track_frames / CDIO_CD_FRAMES_PER_SEC;
722                     add_format_str_info( secstotimestr( psz_buffer,
723                             i_duration ) );
724                     break;
725                 }
726
727             case 'M':
728                 add_format_str_info(psz_mrl);
729                 break;
730
731             case 'm':
732                 add_format_str_info(p_cdda->psz_mcn);
733                 break;
734
735             case 'n':
736                 add_format_num_info(p_cdda->i_tracks, "%d");
737                 break;
738
739             case 'T':
740                 add_format_num_info(i_track, "%02d");
741                 break;
742             format_str:
743                 if (psz)
744                     add_format_str_info(psz);
745                 break;
746 #ifdef HAVE_LIBCDDB
747             not_special:
748 #endif
749             default:
750                 *tp++ = '%';
751                 *tp++ = format_str[i];
752                 saw_control_prefix = false;
753         }
754     }
755     return strdup(temp_str);
756 }
757
758 /* Return a MRL for the given track. The caller must free the
759    allocated string. */
760 static char *
761 CDDAFormatMRL( const access_t *p_access, track_t i_track )
762 {
763     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
764     const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX)
765       + strlen(p_cdda->psz_source) +
766       + strlen("@T") + strlen("100") + 1;
767     char *psz_mrl = calloc( 1, psz_mrl_max );
768
769     if (CDIO_INVALID_TRACK == i_track)
770       snprintf(psz_mrl, psz_mrl_max, "%s%s",
771            CDDA_MRL_PREFIX, p_cdda->psz_source);
772     else
773       snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
774            CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
775     return psz_mrl;
776 }
777
778
779 /* Return a title string as specified by the titel format string for the
780    given track. The caller must free the allocated string. */
781 char *
782 CDDAFormatTitle( const access_t *p_access, track_t i_track )
783 {
784
785     const char *config_varname = MODULE_STRING "-title-format";
786     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
787     char *psz_mrl = CDDAFormatMRL( p_access, i_track );
788
789     if( psz_mrl )
790     {
791         char *psz_name;
792 #ifdef HAVE_LIBCDDB
793         if (p_cdda->b_cddb_enabled)
794         {
795             config_varname = MODULE_STRING "-cddb-title-format";
796         }
797 #endif /*HAVE_LIBCDDB*/
798         psz_name =
799             CDDAFormatStr( p_access, p_cdda,
800                 config_GetPsz( p_access, config_varname ),
801                 psz_mrl, i_track );
802         free(psz_mrl);
803         return psz_name;
804     }
805     return(NULL);
806 }
807
808 static playlist_item_t *
809 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
810                         playlist_t *p_playlist, playlist_item_t *p_item,
811                         track_t i_track )
812 {
813     unsigned int i_track_frames =
814     cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
815     cdio_get_track_lsn(p_cdda->p_cdio, i_track);
816     mtime_t i_mduration = i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
817     char *psz_title = NULL;
818     char *psz_mrl   = NULL;
819
820     playlist_item_t *p_child = NULL;
821
822     if( !p_item ) return NULL;
823
824     psz_title = CDDAFormatTitle( p_access, i_track ) ;
825     psz_mrl = CDDAFormatMRL( p_access, i_track  ) ;
826
827     dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
828                psz_mrl, psz_title, (long int) i_mduration / 1000000 );
829
830     p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
831     input_item_SetDuration( input_GetItem( p_child->p_input ),
832             (mtime_t) i_mduration );
833     free(psz_mrl);
834     free(psz_title);
835
836     if( !p_child ) return NULL;
837     return p_child;
838 }
839
840 /*
841    Fixes up playlist.
842 */
843 int
844 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
845                    bool b_single_track )
846 {
847     int i;
848     playlist_t * p_playlist = NULL;
849     const track_t i_first_track = p_cdda->i_first_track;
850     playlist_item_t *p_item = NULL;
851     bool b_play = false;
852     track_t    i_track;
853
854 #ifdef HAVE_LIBCDDB
855     p_cdda->b_cddb_enabled =
856         config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
857     if( b_single_track && !p_cdda->b_cddb_enabled )
858         return VLC_SUCCESS;
859 #else
860     if( b_single_track )
861         return VLC_SUCCESS;
862 #endif
863
864     if (! p_cdda->b_nav_mode ) {
865         p_playlist = pl_Yield( p_access );
866     }
867
868     if( b_single_track || p_cdda->b_nav_mode ) {
869         i_track = p_cdda->i_track;
870     }
871     else
872     {
873         i_track = CDIO_INVALID_TRACK;
874     }
875     CDDAMetaInfoInit( p_access );
876     CDDAMetaInfo( p_access, p_cdda->i_track );
877
878     if( p_playlist )
879     {
880         input_thread_t *p_input = (input_thread_t*)vlc_object_find( p_access, VLC_OBJECT_INPUT, FIND_PARENT );
881         if( p_input )
882         {
883             p_item = playlist_ItemGetByInput( p_playlist, input_GetItem(p_input), false );
884
885             if( p_item == p_playlist->status.p_item && !b_single_track )
886                 b_play = true;
887             else
888                 b_play = false;
889             vlc_object_release( p_input );
890         }
891     }
892
893     if( b_single_track && !p_cdda->b_nav_mode )
894     {
895         /*May fill out more information when the playlist user interface becomes
896            more mature.
897          */
898         track_t i_track = p_cdda->i_track;
899         unsigned int i_track_frames =
900         cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
901
902         input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
903         vlc_input_title_New();
904
905         asprintf( &t->psz_name, _("Track %i"), i_track );
906         t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
907         t->i_length = INT64_C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
908
909         if( p_item )
910         {
911             input_item_SetDuration( p_item->p_input, (mtime_t) i_track_frames
912             * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
913                 input_item_SetURI( p_item->p_input,
914                         CDDAFormatMRL( p_access, i_track ) );
915         }
916
917         p_cdda->i_titles = 1;
918         p_access->info.i_update = INPUT_UPDATE_TITLE;
919     }
920     else
921     {
922         input_title_t *t;
923
924         if( !p_cdda->b_nav_mode )
925             playlist_ItemToNode( p_playlist, p_item, false );
926
927         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
928         {
929             playlist_item_t *p_child;
930             const track_t i_track = i_first_track + i;
931             unsigned int i_track_frames =
932                 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
933
934             t = p_cdda->p_title[i] = vlc_input_title_New();
935
936             asprintf( &t->psz_name, _("Track %i"), i_track );
937             t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
938
939             t->i_length = INT64_C(1000000) * t->i_size
940                 / CDDA_FREQUENCY_SAMPLE / 4;
941
942             if ( ! p_cdda->b_nav_mode )
943             {
944                 p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
945                                                   p_item, i_track );
946             }
947         }
948
949         p_cdda->i_titles = p_cdda->i_tracks;
950         p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
951         if( p_item )
952         {
953             input_item_SetDuration( p_item->p_input, (mtime_t) p_access->info.i_size
954                     * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) );
955             input_item_SetURI( p_item->p_input,
956                     CDDAFormatMRL( p_access, p_cdda->i_track ) );
957         }
958     }
959
960     if( b_play )
961     {
962         playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, true,
963                           p_playlist->status.p_item, NULL );
964     }
965
966     if (p_playlist) vlc_object_release( p_playlist );
967     return VLC_SUCCESS;
968 }
969
970
971 /*
972  * Local variables:
973  *  mode: C
974  *  style: gnu
975  * End:
976  */