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