]> git.sesse.net Git - vlc/blob - modules/access/cdda/info.c
CDDAX:
[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(FIELD, 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(FIELD, 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(FIELD, 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 CDDA Meta Information about the CD.
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 )
223 {
224     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
225
226     if ( ! p_cdda ) return;
227
228     p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
229
230 #ifdef HAVE_LIBCDDB
231     if ( p_cdda->b_cddb_enabled )
232     {
233         GetCDDBInfo(p_access, p_cdda);
234         if ( p_cdda->cddb.disc )
235         {
236             p_cdda->p_meta = vlc_meta_New();
237             if( i_track == -1 )
238             {
239                 add_cddb_meta(title,    VLC_META_TITLE);
240                 add_cddb_meta(artist,   VLC_META_ARTIST);
241                 input_Control( p_cdda->p_input, INPUT_SET_NAME,
242                                p_cdda->cddb.disc->artist );
243             }
244             else
245             {
246                 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
247                                                     i_track-1);
248                 if (t != NULL )
249                 {
250                     if( t->title != NULL )
251                     {
252                         add_meta_val( NULL, VLC_META_TITLE, t->title );
253                     }
254                     if( t->artist != NULL )
255                     {
256                         add_meta_val( NULL, VLC_META_ARTIST, t->artist );
257                     }
258                 }
259             }
260             add_cddb_meta(genre,    VLC_META_GENRE);
261             add_cddb_meta_fmt(year,   "%d", VLC_META_DATE );
262         }
263     }
264
265 #endif /*HAVE_LIBCDDB*/
266 #define TITLE_MAX 30
267     {
268         track_t i = p_cdda->i_tracks;
269         const int i_first_track = p_cdda->i_first_track;
270         char psz_buffer[MSTRTIME_MAX_SIZE];
271         mtime_t i_duration =
272               (p_cdda->lsn[i_first_track+i] - p_cdda->lsn[i_first_track])
273               / CDIO_CD_FRAMES_PER_SEC;
274
275         dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
276         input_Control( p_cdda->p_input, INPUT_ADD_INFO,
277                        _("Disc"), _("Duration"), "%s",
278                        secstotimestr( psz_buffer, i_duration ) );
279
280 #ifdef HAVE_LIBCDDB
281         if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
282         {
283           add_cddb_disc_info_str("Artist (CDDB)", artist);
284           add_cddb_disc_info_str("Genre (CDDB)",  genre);
285           add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
286           add_cddb_disc_info_val("Year (CDDB)", "%d", year);
287           add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
288           add_cddb_disc_info_str("Title (CDDB)",  title);
289           add_info_str("Disc", "Category (CDDB)",
290                         CDDB_CATEGORY[p_cdda->cddb.disc->category]);
291
292         }
293 #endif /*HAVE_LIBCDDB*/
294
295         p_cdda->p_cdtext[0] = cdio_get_cdtext(p_cdda->p_cdio, 0);
296         if (p_cdda->p_cdtext[0])
297         {
298             add_cdtext_disc_info_str("Arranger (CD-Text)",    CDTEXT_ARRANGER);
299             add_cdtext_disc_info_str("Composer (CD-Text)",    CDTEXT_COMPOSER);
300             add_cdtext_disc_info_str("Disc ID (CD-Text)",     CDTEXT_DISCID);
301             add_cdtext_disc_info_str("Genre (CD-Text)",       CDTEXT_GENRE);
302             add_cdtext_disc_info_str("Message (CD-Text)",     CDTEXT_MESSAGE);
303             add_cdtext_disc_info_str("Performer (CD-Text)",   CDTEXT_PERFORMER);
304             add_cdtext_disc_info_str("Songwriter (CD-Text)",  CDTEXT_SONGWRITER);
305             add_cdtext_disc_info_str("Title (CD-Text)",       CDTEXT_TITLE);
306         }
307
308         if( i_track == -1 )
309         {
310             for( i = 0 ; i < p_cdda->i_tracks ; i++ )
311             {
312                 char psz_track[TITLE_MAX];
313                 const track_t i_track = i_first_track + i;
314                 mtime_t i_duration = (p_cdda->lsn[i_track+1] -
315                                       p_cdda->lsn[i_track])
316                                       / CDIO_CD_FRAMES_PER_SEC;
317                 snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
318                 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
319                                _("Duration"), "%s",
320                                secstotimestr( psz_buffer, i_duration ) );
321
322                 p_cdda->p_cdtext[i_track] =
323                                 cdio_get_cdtext(p_cdda->p_cdio, i_track);
324
325                 if (p_cdda->p_cdtext[i_track])
326                 {
327                     add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
328                                          i_track, CDTEXT_ARRANGER);
329                     add_cdtext_info_str( psz_track, "Composer (CD-Text)",
330                                          i_track, CDTEXT_COMPOSER);
331                     add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
332                                          i_track, CDTEXT_DISCID);
333                     add_cdtext_info_str( psz_track, "Genre (CD-Text)",
334                                          i_track, CDTEXT_GENRE);
335                     add_cdtext_info_str( psz_track, "Message (CD-Text)",
336                                          i_track, CDTEXT_MESSAGE);
337                     add_cdtext_info_str( psz_track, "Performer (CD-Text)",
338                                          i_track, CDTEXT_PERFORMER);
339                     add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
340                                          i_track, CDTEXT_SONGWRITER);
341                     add_cdtext_info_str( psz_track, "Title (CD-Text)",
342                                          i_track, CDTEXT_TITLE);
343                 }
344
345 #ifdef HAVE_LIBCDDB
346                 if (p_cdda->b_cddb_enabled)
347                 {
348                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
349                     if (t != NULL)
350                     {
351                         add_info_str(psz_track, "Artist (CDDB)", t->artist);
352                         add_info_str(psz_track, "Title (CDDB)",  t->title);
353                         add_info_str(psz_track, "Extended Data (CDDB)",
354                                                 t->ext_data);
355                     }
356                 }
357 #endif /*HAVE_LIBCDDB*/
358             }
359         }
360     }
361 }
362
363 #define add_format_str_info(val)                         \
364   {                                                      \
365     const char *str = val;                               \
366     unsigned int len;                                    \
367     if (val != NULL) {                                   \
368       len=strlen(str);                                   \
369       if (len != 0) {                                    \
370         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    \
371         tp += len;                                       \
372       }                                                  \
373       saw_control_prefix = false;                        \
374     }                                                    \
375   }
376
377 #define add_format_num_info(val, fmt)                    \
378   {                                                      \
379     char num_str[10];                                    \
380     unsigned int len;                                    \
381     sprintf(num_str, fmt, val);                          \
382     len=strlen(num_str);                                 \
383     if (len != 0) {                                      \
384       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  \
385       tp += len;                                         \
386     }                                                    \
387     saw_control_prefix = false;                          \
388   }
389
390 /*!
391    Take a format string and expand escape sequences, that is sequences that
392    begin with %, with information from the current CD.
393    The expanded string is returned. Here is a list of escape sequences:
394
395    %a : The album artist **
396    %A : The album information **
397    %C : Category **
398    %I : CDDB disk ID **
399    %G : Genre **
400    %M : The current MRL
401    %m : The CD-DA Media Catalog Number (MCN)
402    %n : The number of tracks on the CD
403    %p : The artist/performer/composer in the track **
404    %T : The track number **
405    %s : Number of seconds in this track
406    %t : The name **
407    %Y : The year 19xx or 20xx **
408    %% : a %
409 */
410 static char *
411 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
412                const char format_str[], const char *mrl, track_t i_track)
413 {
414 #define TEMP_STR_SIZE 256
415 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
416     static char    temp_str[TEMP_STR_SIZE];
417     size_t i;
418     char * tp = temp_str;
419     vlc_bool_t saw_control_prefix = false;
420     size_t format_len = strlen(format_str);
421
422     memset(temp_str, 0, TEMP_STR_SIZE);
423
424     for (i=0; i<format_len; i++)
425     {
426
427         if (!saw_control_prefix && format_str[i] != '%')
428         {
429             *tp++ = format_str[i];
430             saw_control_prefix = false;
431             continue;
432         }
433
434         switch(format_str[i])
435         {
436             case '%':
437               if (saw_control_prefix)
438               {
439                   *tp++ = '%';
440               }
441               saw_control_prefix = !saw_control_prefix;
442               break;
443 #ifdef HAVE_LIBCDDB
444             case 'a':
445                 if (!p_cdda->b_cddb_enabled) goto not_special;
446                 if (p_cdda->cddb.disc)
447                     add_format_str_info(p_cdda->cddb.disc->artist);
448                 break;
449             case 'A':
450                 if (!p_cdda->b_cddb_enabled) goto not_special;
451                 if (p_cdda->cddb.disc)
452                     add_format_str_info(p_cdda->cddb.disc->title);
453                     break;
454             case 'C':
455                 if (!p_cdda->b_cddb_enabled) goto not_special;
456                 if (p_cdda->cddb.disc)
457                     add_format_str_info(
458                                   CDDB_CATEGORY[p_cdda->cddb.disc->category]);
459                 break;
460             case 'G':
461                 if (!p_cdda->b_cddb_enabled) goto not_special;
462                 if (p_cdda->cddb.disc)
463                     add_format_str_info(p_cdda->cddb.disc->genre);
464                 break;
465             case 'I':
466                 if (!p_cdda->b_cddb_enabled) goto not_special;
467                 if (p_cdda->cddb.disc)
468                      add_format_num_info(p_cdda->cddb.disc->discid, "%x");
469                 break;
470             case 'Y':
471                 if (!p_cdda->b_cddb_enabled) goto not_special;
472                 if (p_cdda->cddb.disc)
473                     add_format_num_info(p_cdda->cddb.disc->year, "%5d");
474                 break;
475             case 't':
476                 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
477                 {
478                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
479                                                         i_track-1);
480                     if (t != NULL && t->title != NULL)
481                       add_format_str_info(t->title);
482                 }
483                 else goto not_special;
484                 break;
485             case 'p':
486                 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
487                 {
488                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
489                                                         i_track-1);
490                     if (t != NULL && t->artist != NULL)
491                     add_format_str_info(t->artist);
492                 } else goto not_special;
493                 break;
494             case 'e':
495                 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
496                 {
497                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
498                                                         i_track-1);
499                     if (t != NULL && t->ext_data != NULL)
500                         add_format_str_info(t->ext_data);
501                 } else goto not_special;
502                 break;
503             case 's':
504                 if (p_cdda->b_cddb_enabled)
505                 {
506                     char psz_buffer[MSTRTIME_MAX_SIZE];
507                     mtime_t i_duration = (p_cdda->lsn[i_track+1] -
508                                           p_cdda->lsn[i_track])
509                                           / CDIO_CD_FRAMES_PER_SEC;
510                     add_format_str_info(secstotimestr( psz_buffer,
511                                        i_duration ) );
512                 } else goto not_special;
513                 break;
514 #endif /*HAVE_LIBCDDB*/
515
516             case 'M':
517               add_format_str_info(mrl);
518               break;
519
520             case 'm':
521               add_format_str_info(p_cdda->psz_mcn);
522               break;
523
524             case 'n':
525               add_format_num_info(p_cdda->i_tracks, "%d");
526               break;
527
528             case 'T':
529               add_format_num_info(i_track, "%02d");
530               break;
531 #ifdef HAVE_LIBCDDB
532             not_special:
533 #endif
534             default:
535                 *tp++ = '%';
536                 *tp++ = format_str[i];
537                 saw_control_prefix = false;
538         }
539     }
540     return strdup(temp_str);
541 }
542
543 /* Adds a string-valued entry to the playlist information under "Track"
544    if the string is not null or the null string.
545  */
546 #define add_playlist_track_info_str(TITLE, FIELD)                        \
547     if (FIELD && strlen(FIELD))                                          \
548     {                                                                    \
549         playlist_ItemAddInfo( p_item, _("Track"), _(TITLE),              \
550                               "%s", FIELD);                              \
551     }
552
553 playlist_item_t *
554 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
555                         playlist_t *p_playlist, playlist_item_t *p_item, 
556                         track_t i_track, char *psz_mrl, int psz_mrl_max,
557                         const char *psz_source )
558 {
559     mtime_t i_duration = (p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track])
560                          * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
561     char *psz_title;
562     char *config_varname = MODULE_STRING "-title-format";
563
564     playlist_item_t *p_child = NULL;
565
566     if( !p_item )
567     {
568         return NULL;
569     }
570
571 #ifdef HAVE_LIBCDDB
572     if (p_cdda->b_cddb_enabled)
573     {
574         config_varname = MODULE_STRING "-cddb-title-format";
575     }
576 #endif /*HAVE_LIBCDDB*/
577
578
579     psz_title = CDDAFormatStr( p_access, p_cdda,
580                                config_GetPsz( p_access, config_varname ),
581                                psz_mrl, i_track);
582
583     snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
584              CDDA_MRL_PREFIX, psz_source, i_track);
585
586     dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
587                psz_mrl, psz_title, (long int) i_duration / 1000000 );
588
589     p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
590     p_child->input.b_fixed_name = VLC_TRUE;
591
592     if( !p_child ) return NULL;
593
594     playlist_NodeAddItem( p_playlist, p_child,
595                           p_item->pp_parents[0]->i_view,
596                           p_item, PLAYLIST_APPEND, PLAYLIST_END );
597     playlist_CopyParents( p_item, p_child );
598
599     return p_child;
600 }
601
602 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
603                        playlist_item_t *p_item, const char *psz_source,
604                        int i_track, vlc_bool_t b_single )
605 {
606     vlc_mutex_lock( &p_item->input.lock );
607
608     add_playlist_track_info_str("Source",  psz_source);
609     playlist_ItemAddInfo( p_item, _("Track"), _("Track Number"),
610                           "%d", i_track );
611
612     if (p_cdda->p_cdtext[0])
613     {
614         const cdtext_t *p = p_cdda->p_cdtext[0];
615         add_playlist_track_info_str("Disc Arranger (CD-Text)",
616                                      p->field[CDTEXT_ARRANGER]);
617         add_playlist_track_info_str("Disc Composer (CD-Text)",
618                                     p->field[CDTEXT_COMPOSER]);
619         add_playlist_track_info_str("Disc ID (CD-Text)",
620                                     p->field[CDTEXT_DISCID]);
621         add_playlist_track_info_str("Disc Genre (CD-Text)",
622                                     p->field[CDTEXT_GENRE]);
623         add_playlist_track_info_str("Disc Message (CD-Text)",
624                                     p->field[CDTEXT_MESSAGE]);
625         add_playlist_track_info_str("Disc Performer (CD-Text)",
626                                     p->field[CDTEXT_PERFORMER]);
627         add_playlist_track_info_str("Disc Songwriter (CD-Text)",
628                                     p->field[CDTEXT_SONGWRITER]);
629         add_playlist_track_info_str("Disc Title (CD-Text)",
630                                     p->field[CDTEXT_TITLE]);
631     }
632
633     if (p_cdda->p_cdtext[i_track])
634     {
635         const cdtext_t *p = p_cdda->p_cdtext[i_track];
636         add_playlist_track_info_str("Arranger (CD-Text)",
637                                     p->field[CDTEXT_ARRANGER]);
638         add_playlist_track_info_str("Composer (CD-Text)",
639                                     p->field[CDTEXT_COMPOSER]);
640         add_playlist_track_info_str("Genre (CD-Text)",
641                                     p->field[CDTEXT_GENRE]);
642         add_playlist_track_info_str("Message (CD-Text)",
643                                     p->field[CDTEXT_MESSAGE]);
644         add_playlist_track_info_str("Performer (CD-Text)",
645                                     p->field[CDTEXT_PERFORMER]);
646         add_playlist_track_info_str("Songwriter (CD-Text)",
647                                     p->field[CDTEXT_SONGWRITER]);
648         add_playlist_track_info_str("Title (CD-Text)",
649                                     p->field[CDTEXT_TITLE]);
650     }
651
652 #ifdef HAVE_LIBCDDB
653     if (p_cdda->b_cddb_enabled)
654     {
655         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
656                                             i_track-p_cdda->i_first_track);
657
658         add_playlist_track_info_str("Disc Album (CDDB)",
659                                     p_cdda->cddb.disc->title);
660         add_playlist_track_info_str("Disc Artist(s) (CDDB)",
661                                     p_cdda->cddb.disc->artist);
662         add_playlist_track_info_str("Disc Category (CDDB)",
663                                     CDDB_CATEGORY[p_cdda->cddb.disc->category]);
664         add_playlist_track_info_str("Disc Genre (CDDB)",
665                                     p_cdda->cddb.disc->genre);
666
667         if ( p_cdda->cddb.disc->discid )
668         {
669             playlist_ItemAddInfo( p_item, _("Track"), _("Disc ID (CDDB)"),
670                                   "%x", p_cdda->cddb.disc->discid );
671         }
672         if (p_cdda->cddb.disc->year != 0)
673         {
674             playlist_ItemAddInfo( p_item, _("Track"), _("Year (CDDB)"),
675                                  "%5d", p_cdda->cddb.disc->year );
676         }
677
678         if (t)
679         {
680             if (t->artist)
681                 add_playlist_track_info_str("Track Artist (CDDB)",
682                                              t->artist);
683            if (t->title)
684                 add_playlist_track_info_str("Track Title (CDDB)",
685                                             t->title);
686         }
687     }
688 #endif /*HAVE_LIBCDDB*/
689
690     vlc_mutex_unlock( &p_item->input.lock );
691
692     return VLC_SUCCESS;
693 }
694
695 int
696 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
697                    const char *psz_source, vlc_bool_t b_single_track )
698 {
699     int i;
700     playlist_t * p_playlist;
701     char       * psz_mrl;
702     unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
703       strlen("@T") + strlen("100") + 1;
704     const track_t i_first_track = p_cdda->i_first_track;
705     playlist_item_t *p_item;
706     vlc_bool_t b_play = VLC_FALSE;
707
708 #ifdef HAVE_LIBCDDB
709     p_cdda->b_cddb_enabled =
710         config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
711     if( b_single_track && !p_cdda->b_cddb_enabled )
712         return VLC_SUCCESS;
713 #else
714     if( b_single_track )
715         return VLC_SUCCESS;
716 #endif
717
718     psz_mrl = malloc( psz_mrl_max );
719
720     if( psz_mrl == NULL )
721     {
722         msg_Warn( p_access, "out of memory" );
723         return VLC_ENOMEM;
724     }
725
726     p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
727                                                FIND_ANYWHERE );
728     if( !p_playlist )
729     {
730         msg_Warn( p_access, "can't find playlist" );
731         free(psz_mrl);
732         return VLC_EGENERIC;
733     }
734
735     if( b_single_track )
736     {
737         CDDAMetaInfo( p_access, p_cdda->i_track );
738     }
739     else
740     {
741         CDDAMetaInfo( p_access, -1 );
742     }
743
744     p_item = playlist_ItemGetByInput( p_playlist,
745                         ((input_thread_t *)p_access->p_parent)->input.p_item );
746
747     if( p_item == p_playlist->status.p_item && !b_single_track )
748     {
749         b_play = VLC_TRUE;
750     }
751     else
752     {
753         b_play = VLC_FALSE;
754     }
755
756     if( b_single_track )
757     {
758         /*May fill out more information when the playlist user interface becomes
759            more mature.
760          */
761         track_t i_track = p_cdda->i_track;
762
763         input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
764         vlc_input_title_New();
765
766         asprintf( &t->psz_name, _("Track %i"), i_track );
767         t->i_size = p_access->info.i_size =
768                   ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) *
769                              (int64_t) CDIO_CD_FRAMESIZE_RAW;
770
771         t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
772
773
774         CDDAAddMetaToItem( p_access, p_cdda, p_item, psz_source, i_track,
775                            VLC_FALSE );
776
777         p_cdda->i_titles = 1;
778     }
779     else
780     {
781         playlist_ItemToNode( p_playlist, p_item );
782         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
783         {
784             playlist_item_t *p_child;
785             const track_t i_track = i_first_track + i;
786             input_title_t *t = p_cdda->p_title[i] = vlc_input_title_New();
787
788             asprintf( &t->psz_name, _("Track %i"), i_track );
789             t->i_size = ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) *
790                           (int64_t) CDIO_CD_FRAMESIZE_RAW;
791
792             t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
793
794             p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
795                                               p_item,
796                                               i_track, psz_mrl,
797                                               psz_mrl_max, psz_source );
798             CDDAAddMetaToItem( p_access, p_cdda, p_child, psz_source,
799                                i_track, VLC_TRUE );
800         }
801         p_cdda->i_titles = p_cdda->i_tracks; /* should be +1 */
802         p_access->info.i_size =
803                (p_cdda->lsn[i_first_track + p_cdda->i_tracks]
804                - p_cdda->lsn[i_first_track]) * (int64_t) CDIO_CD_FRAMESIZE_RAW;
805     }
806
807     if( b_play )
808     {
809         playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
810                           p_playlist->status.i_view,
811                           p_playlist->status.p_item, NULL );
812     }
813
814     vlc_object_release( p_playlist );
815
816     return VLC_SUCCESS;
817 }
818