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