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