]> git.sesse.net Git - vlc/blob - modules/access/cdda/access.c
Add secstotimestr and msecstotimestr to convert (milli)seconds to a
[vlc] / modules / access / cdda / access.c
1 /*****************************************************************************
2  * cddax.c : CD digital audio input module for vlc using libcdio
3  *****************************************************************************
4  * Copyright (C) 2000,2003 VideoLAN
5  * $Id: access.c,v 1.8 2003/12/02 01:54:30 rocky Exp $
6  *
7  * Authors: Rocky Bernstein <rocky@panix.com> 
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *          Gildas Bazin <gbazin@netcourrier.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/intf.h>
34
35 #include <sys/types.h>
36 #include <cdio/cdio.h>
37 #include <cdio/cd_types.h>
38
39 #include "codecs.h"
40 #include "vlc_keys.h"
41
42 #ifdef HAVE_UNISTD_H
43 #   include <unistd.h>
44 #endif
45
46 #include <string.h>
47
48 #include "cdda.h"
49
50 /* how many blocks Open will read in each loop */
51 #define CDDA_BLOCKS_ONCE 1
52 #define CDDA_DATA_ONCE   (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW)
53
54 #define CDDA_MRL_PREFIX "cddax://"
55
56 /* FIXME: This variable is a hack. Would be nice to eliminate. */
57 static input_thread_t *p_cdda_input = NULL;
58
59 /*****************************************************************************
60  * Local prototypes
61  *****************************************************************************/
62 static int  CDDARead         ( input_thread_t *, byte_t *, size_t );
63 static void CDDASeek         ( input_thread_t *, off_t );
64 static int  CDDASetArea      ( input_thread_t *, input_area_t * );
65 static int  CDDASetProgram   ( input_thread_t *, pgrm_descriptor_t * );
66
67 static int  CDDAFixupPlayList( input_thread_t *p_input, 
68                               cdda_data_t *p_cdda, const char *psz_source, 
69                               bool play_single_track);
70
71 /****************************************************************************
72  * Private functions
73  ****************************************************************************/
74
75 int
76 E_(DebugCallback)   ( vlc_object_t *p_this, const char *psz_name,
77                       vlc_value_t oldval, vlc_value_t val, void *p_data )
78 {
79   cdda_data_t *p_cdda;
80
81   if (NULL == p_cdda_input) return VLC_EGENERIC;
82   
83   p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
84
85   if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
86     msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d", 
87              p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
88   }
89   p_cdda->i_debug = val.i_int;
90   return VLC_SUCCESS;
91 }
92
93 /* process messages that originate from libcdio. */
94 static void
95 cdio_log_handler (cdio_log_level_t level, const char message[])
96 {
97   cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
98   switch (level) {
99   case CDIO_LOG_DEBUG:
100   case CDIO_LOG_INFO:
101     if (p_cdda->i_debug & INPUT_DBG_CDIO) 
102       msg_Dbg( p_cdda_input, message);
103     break;
104   case CDIO_LOG_WARN:
105     msg_Warn( p_cdda_input, message);
106     break;
107   case CDIO_LOG_ERROR:
108   case CDIO_LOG_ASSERT:
109     msg_Err( p_cdda_input, message);
110     break;
111   default:
112     msg_Warn( p_cdda_input, message,
113             _("The above message had unknown vcdimager log level"), 
114             level);
115   }
116   return;
117 }
118
119
120 #ifdef HAVE_LIBCDDB
121 /*! This routine is called by libcddb routines on error. 
122    Setup is done by init_input_plugin.
123 */
124 static void 
125 cddb_log_handler (cddb_log_level_t level, const char message[])
126 {
127   cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
128   switch (level) {
129   case CDDB_LOG_DEBUG:
130   case CDDB_LOG_INFO:
131     if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
132     /* Fall through if to warn case */
133   default:
134     cdio_log_handler (level, message);
135   }
136 }
137 #endif /*HAVE_LIBCDDB*/
138
139
140 /*! This routine is when xine is not fully set up (before full initialization)
141    or is not around (before finalization). 
142 */
143 static void 
144 uninit_log_handler (cdio_log_level_t level, const char message[])
145 {
146   cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
147   switch (level) {
148   case CDIO_LOG_DEBUG:
149   case CDIO_LOG_INFO:
150     if (!(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
151       return;
152     /* Fall through if to warn case */
153   case CDIO_LOG_WARN:
154     fprintf(stderr, "WARN: %s\n", message);
155     break;
156   case CDIO_LOG_ERROR:
157     fprintf(stderr, "ERROR: %s\n", message);
158     break;
159   case CDIO_LOG_ASSERT:
160     fprintf(stderr, "ASSERT ERROR: %s\n", message);
161     break;
162   default:
163     fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
164             message, 
165             _("The above message had unknown cdio log level"), 
166             level);
167   }
168   
169   /* gl_default_cdio_log_handler (level, message); */
170 }
171
172 /*****************************************************************************
173  * Open: open cdda
174  *****************************************************************************/
175 int 
176 E_(Open)( vlc_object_t *p_this )
177 {
178     input_thread_t *        p_input = (input_thread_t *)p_this;
179     char *                  psz_orig;
180     char *                  psz_parser;
181     char *                  psz_source;
182     cdda_data_t *           p_cdda;
183     int                     i;
184     int                     i_track = 1;
185     cddev_t                 *p_cddev;
186     bool                    play_single_track = false;
187
188     /* Set where to log errors messages from libcdio. */
189     p_cdda_input = (input_thread_t *)p_this;
190
191     /* parse the options passed in command line : */
192     psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
193
194     if( !psz_orig )
195     {
196         return( -1 );
197     }
198
199     while( *psz_parser && *psz_parser != '@' )
200     {
201         psz_parser++;
202     }
203
204     if( *psz_parser == '@' )
205     {
206         /* Found options */
207         *psz_parser = '\0';
208         ++psz_parser;
209
210         if ('T' == *psz_parser || 't' == *psz_parser ) 
211             ++psz_parser;
212           
213         i_track = (int)strtol( psz_parser, NULL, 10 );
214         i_track = i_track ? i_track : 1;
215         play_single_track = true;
216     }
217
218     if( !*psz_source ) {
219       /* No source specified, so figure it out. */
220       if( !p_input->psz_access ) {
221         free( psz_orig );
222         return -1;
223       }
224       psz_source = config_GetPsz( p_input, MODULE_STRING "-device" );
225       
226       if( !psz_source || 0==strlen(psz_source) ) {
227         /* Scan for a CD-ROM drive with a CD-DA in it. */
228         char **cd_drives = 
229           cdio_get_devices_with_cap(NULL,  CDIO_FS_AUDIO, false);
230         if (NULL == cd_drives) return -1;
231         if (cd_drives[0] == NULL) {
232           cdio_free_device_list(cd_drives);
233           return -1;
234         }
235         psz_source = strdup(cd_drives[0]);
236         cdio_free_device_list(cd_drives);
237       }
238     }
239
240     /* Open CDDA */
241     cdio_log_set_handler ( cdio_log_handler );
242 #ifdef HAVE_LIBCDDB
243     cddb_log_set_handler ( cddb_log_handler );
244 #endif
245
246     if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
247     {
248         msg_Warn( p_input, "could not open %s", psz_source );
249         free( psz_source );
250         return -1;
251     }
252
253     p_cdda = malloc( sizeof(cdda_data_t) );
254     if( p_cdda == NULL )
255     {
256         msg_Err( p_input, "out of memory" );
257         free( psz_source );
258         return -1;
259     }
260
261     p_cdda->p_cddev        = p_cddev;
262     p_cdda->i_debug        = config_GetInt( p_this, MODULE_STRING "-debug" );
263     p_input->p_access_data = (void *)p_cdda;
264
265     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
266
267     p_input->i_mtu = CDDA_DATA_ONCE;
268
269     /* We read the Table Of Content information */
270     p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
271                               p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
272     if( p_cdda->i_nb_tracks < 0 )
273         msg_Err( p_input, "unable to count tracks" );
274     else if( p_cdda->i_nb_tracks <= 0 )
275         msg_Err( p_input, "no audio tracks found" );
276
277     if( p_cdda->i_nb_tracks <= 1)
278     {
279         ioctl_Close( p_cdda->p_cddev );
280         free( p_cdda );
281         free( psz_source );
282         return -1;
283     }
284
285     if( i_track >= p_cdda->i_nb_tracks || i_track < 1 )
286         i_track = 1;
287
288     /* Set stream and area data */
289     vlc_mutex_lock( &p_input->stream.stream_lock );
290
291     /* Initialize ES structures */
292     input_InitStream( p_input, 0 );
293
294     /* cdda input method */
295     p_input->stream.i_method = INPUT_METHOD_CDDA;
296
297     p_input->stream.b_pace_control = 1;
298     p_input->stream.b_seekable = 1;
299     p_input->stream.i_mux_rate = 44100 * 4 / 50;
300
301 #define area p_input->stream.pp_areas
302     for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
303     {
304         input_AddArea( p_input, i, 1 );
305
306         /* Absolute start offset and size */
307         area[i]->i_start =
308             (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
309         area[i]->i_size =
310             (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
311             * (off_t)CDIO_CD_FRAMESIZE_RAW;
312     }
313 #undef area
314
315     CDDAPlay( p_input, i_track);
316
317     CDDAFixupPlayList(p_input, p_cdda, psz_source, play_single_track);
318
319     vlc_mutex_unlock( &p_input->stream.stream_lock );
320
321     if( !p_input->psz_demux || !*p_input->psz_demux )
322     {
323         p_input->psz_demux = "cdda";
324     }
325
326     p_input->pf_read = CDDARead;
327     p_input->pf_seek = CDDASeek;
328     p_input->pf_set_area = CDDASetArea;
329     p_input->pf_set_program = CDDASetProgram;
330
331     /* Update default_pts to a suitable value for cdda access */
332     p_input->i_pts_delay = config_GetInt( p_input, 
333                                           MODULE_STRING "-caching" ) * 1000;
334
335     p_cdda->p_intf = intf_Create( p_input, "cddax" );
336     intf_RunThread( p_cdda->p_intf );
337     free( psz_source );
338
339     return 0;
340 }
341
342 /*****************************************************************************
343  * CDDAPlay: Arrange things so we play the specified track.
344  * VLC_TRUE is returned if there was no error.
345  *****************************************************************************/
346 vlc_bool_t
347 CDDAPlay( input_thread_t *p_input, int i_track )
348 {
349   cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
350
351   if( i_track >= p_cdda->i_nb_tracks || i_track < 1 )
352     return VLC_FALSE;
353
354   CDDASetArea( p_input, p_input->stream.pp_areas[i_track] );
355   return VLC_TRUE;
356 }
357
358 /*****************************************************************************
359  * CDDAClose: closes cdda
360  *****************************************************************************/
361 void 
362 E_(Close)( vlc_object_t *p_this )
363 {
364     input_thread_t *   p_input = (input_thread_t *)p_this;
365     cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
366
367     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
368     ioctl_Close( p_cdda->p_cddev );
369
370     cdio_log_set_handler (uninit_log_handler);
371
372 #ifdef HAVE_LIBCDDB
373     cddb_log_set_handler (uninit_log_handler);
374     if (p_cdda->i_cddb_enabled)
375       cddb_disc_destroy(p_cdda->cddb.disc);
376 #endif
377
378     free( p_cdda );
379     p_cdda_input = NULL;
380 }
381
382 /*****************************************************************************
383  * CDDARead: reads from the CDDA into PES packets.
384  *****************************************************************************
385  * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
386  * bytes.
387  *****************************************************************************/
388 static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
389                      size_t i_len )
390 {
391     cdda_data_t *           p_cdda;
392     int                     i_blocks;
393     int                     i_index;
394     int                     i_read;
395
396     p_cdda = (cdda_data_t *)p_input->p_access_data;
397
398     i_read = 0;
399
400     /* Compute the number of blocks we have to read */
401
402     i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
403
404     for ( i_index = 0; i_index < i_blocks; i_index++ )
405     {
406
407       if (cdio_read_audio_sector(p_cdda->p_cddev->cdio, p_buffer, 
408                                  p_cdda->i_sector) != 0)
409         {
410           msg_Err( p_input, "could not read sector %d", p_cdda->i_sector );
411           return -1;
412         }
413
414         p_cdda->i_sector ++;
415         if ( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
416         {
417             input_area_t *p_area;
418
419             dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL), 
420                        "end of track, cur: %u", p_cdda->i_sector );
421
422             /*???? if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )*/
423                 return 0; /* EOF */
424
425             vlc_mutex_lock( &p_input->stream.stream_lock );
426             p_area = p_input->stream.pp_areas[
427                     p_input->stream.p_selected_area->i_id + 1 ];
428
429             p_area->i_part = 1;
430             CDDASetArea( p_input, p_area );
431             vlc_mutex_unlock( &p_input->stream.stream_lock );
432         }
433         i_read += CDIO_CD_FRAMESIZE_RAW;
434     }
435
436     if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
437     {
438         msg_Err( p_input, "must read full sectors" );
439     }
440
441     return i_read;
442 }
443
444 /*****************************************************************************
445  * CDDASetProgram: Does nothing since a CDDA is mono_program
446  *****************************************************************************/
447 static int CDDASetProgram( input_thread_t * p_input,
448                            pgrm_descriptor_t * p_program)
449 {
450     cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
451     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
452     return 0;
453 }
454
455 /*****************************************************************************
456  * CDDASetArea: initialize input data for title x.
457  * It should be called for each user navigation request.
458  ****************************************************************************/
459 static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
460 {
461     cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
462     vlc_value_t val;
463
464     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
465
466     /* we can't use the interface slider until initilization is complete */
467     p_input->stream.b_seekable = 0;
468
469     if( p_area != p_input->stream.p_selected_area )
470     {
471         /* Change the default area */
472         p_input->stream.p_selected_area = p_area;
473
474         /* Change the current track */
475         p_cdda->i_track = p_area->i_id - 1;
476         p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
477
478         /* Update the navigation variables without triggering a callback */
479         val.i_int = p_area->i_id;
480         var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
481     }
482
483     p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
484
485     p_input->stream.p_selected_area->i_tell =
486         (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
487          - p_input->stream.p_selected_area->i_start;
488
489     /* warn interface that something has changed */
490     p_input->stream.b_seekable = 1;
491     p_input->stream.b_changed = 1;
492
493     return 0;
494 }
495
496 /****************************************************************************
497  * CDDASeek
498  ****************************************************************************/
499 static void CDDASeek( input_thread_t * p_input, off_t i_off )
500 {
501     cdda_data_t * p_cdda;
502
503     p_cdda = (cdda_data_t *) p_input->p_access_data;
504
505     p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
506                        + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
507
508     vlc_mutex_lock( &p_input->stream.stream_lock );
509     p_input->stream.p_selected_area->i_tell =
510         (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
511          - p_input->stream.p_selected_area->i_start;
512
513     vlc_mutex_unlock( &p_input->stream.stream_lock );
514
515     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
516     "sector %ud, offset: %lld, i_tell: %lld",  p_cdda->i_sector, i_off, 
517                p_input->stream.p_selected_area->i_tell );
518
519 }
520
521 #define meta_info_add_str(title, str) \
522   if ( str ) {                                          \
523     printf("field %s str %s\n", title, str);            \
524     input_AddInfo( p_cat, _(title), "%s", str );        \
525   }
526
527
528 static void InformationCreate( input_thread_t *p_input  )
529 {
530   cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
531   input_info_category_t *p_cat;
532   int use_cddb = p_cdda->i_cddb_enabled;
533   
534   p_cat = input_InfoCategory( p_input, "General" );
535
536 #ifdef HAVE_LIBCDDB
537   if (use_cddb) {
538     
539     if( p_cdda->cddb.disc->length > 1000 )
540       {
541         int64_t i_sec = (int64_t) p_cdda->cddb.disc->length;
542         char psz_buffer[MSTRTIME_MAX_SIZE];
543         input_AddInfo( p_cat, _("Duration"), "%s", 
544                        secstotimestr( psz_buffer, i_sec ) );
545       } else 
546       {
547         use_cddb = 0;
548       }
549     
550     meta_info_add_str( "Title", p_cdda->cddb.disc->title );
551     meta_info_add_str( "Artist", p_cdda->cddb.disc->artist );
552     meta_info_add_str( "Genre", p_cdda->cddb.disc->genre );
553     meta_info_add_str( "Extended Data", p_cdda->cddb.disc->ext_data );
554     {
555       char year[5];
556       if (p_cdda->cddb.disc->year != 0) {
557         snprintf(year, 5, "%d", p_cdda->cddb.disc->year);
558         meta_info_add_str( "Year", year );
559       }
560       if ( p_cdda->cddb.disc->discid ) {
561         input_AddInfo( p_cat, _("CDDB Disc ID"), "%x", 
562                        p_cdda->cddb.disc->discid );
563       }
564       
565       if ( p_cdda->cddb.disc->category != CDDB_CAT_INVALID ) {
566         input_AddInfo( p_cat, _("CDDB Disc Category"), "%s", 
567                        CDDB_CATEGORY[p_cdda->cddb.disc->category] );
568       }
569       
570     }
571   }
572
573 #endif /*HAVE_LIBCDDB*/
574
575   if (!use_cddb)
576   {
577     track_t i_track = p_cdda->i_nb_tracks;
578     char psz_buffer[MSTRTIME_MAX_SIZE];
579     mtime_t i_duration = 
580       (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1]) 
581       / CDIO_CD_FRAMES_PER_SEC;
582
583     input_AddInfo( p_cat, _("Duration"), "%s", 
584                    secstotimestr( psz_buffer, i_duration ) );
585   }
586 }
587
588
589 #ifdef HAVE_LIBCDDB
590
591 #define free_and_dup(var, val) \
592   if (var) free(var);          \
593   if (val) var=strdup(val);            
594   
595
596 static void
597 GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
598 {
599
600   dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
601
602   if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
603     int i, i_matches;
604     cddb_conn_t  *conn = cddb_new();
605     const CdIo *cdio = p_cdda->p_cddev->cdio;
606     
607     
608     cddb_log_set_handler (uninit_log_handler);
609
610     if (!conn) {
611       msg_Warn( p_input, "unable to initialize libcddb" );
612       goto cddb_destroy;
613     }
614     
615     cddb_set_email_address( conn, 
616                             config_GetPsz( p_input, 
617                                            MODULE_STRING "-cddb-email") );
618     
619     cddb_set_server_name( conn, 
620                           config_GetPsz( p_input, 
621                                          MODULE_STRING "-cddb-server") );
622
623     cddb_set_server_port(conn, 
624                           config_GetInt( p_input, 
625                                          MODULE_STRING "-cddb-port") );
626
627     /* Set the location of the local CDDB cache directory.
628        The default location of this directory is */
629
630     if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" )) 
631       cddb_cache_disable(conn);
632
633     cddb_cache_set_dir(conn, 
634                        config_GetPsz( p_input, 
635                                       MODULE_STRING "-cddb-cachedir") );
636
637     cddb_set_timeout(conn, 
638                      config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
639
640
641     if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
642       cddb_http_enable(conn);
643     } else
644       cddb_http_disable(conn);
645     
646     p_cdda->cddb.disc = cddb_disc_new();
647     if (!p_cdda->cddb.disc) {
648       msg_Err( p_input, "Unable to create CDDB disc structure." );
649       goto cddb_end;
650     }
651
652     for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
653       cddb_track_t *t = cddb_track_new(); 
654       t->frame_offset = cdio_get_track_lba(cdio, i);
655       cddb_disc_add_track(p_cdda->cddb.disc, t);
656     }
657     
658     p_cdda->cddb.disc->length = 
659       cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK) 
660       / CDIO_CD_FRAMES_PER_SEC;
661
662
663     if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
664       msg_Err( p_input, "CDDB disc calc failed" );
665       goto cddb_destroy;
666     }
667
668     i_matches = cddb_query(conn, p_cdda->cddb.disc);
669     if (i_matches > 0) {
670       if (i_matches > 1)
671         msg_Warn( p_input, "Found %d matches in CDDB. Using first one.", 
672                   i_matches);
673       cddb_read(conn, p_cdda->cddb.disc);
674
675       if (p_cdda->i_debug & INPUT_DBG_CDDB) 
676         cddb_disc_print(p_cdda->cddb.disc);
677
678     } else {
679       msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
680     }
681
682   cddb_destroy:
683     cddb_destroy(conn);
684   }
685   cddb_end: ;
686 }
687 #endif /*HAVE_LIBCDDB*/
688
689 #define add_format_str_info(val)                        \
690   {                                                     \
691     const char *str = val;                              \
692     unsigned int len;                                   \
693     if (val != NULL) {                                  \
694       len=strlen(str);                                  \
695       if (len != 0) {                                   \
696         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));   \
697         tp += len;                                      \
698       }                                                 \
699       saw_control_prefix = false;                       \
700     }                                                   \
701   }
702
703 #define add_format_num_info(val, fmt)                   \
704   {                                                     \
705     char num_str[10];                                   \
706     unsigned int len;                                   \
707     sprintf(num_str, fmt, val);                         \
708     len=strlen(num_str);                                \
709     if (len != 0) {                                     \
710       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
711       tp += len;                                        \
712     }                                                   \
713     saw_control_prefix = false;                         \
714   }
715
716 /*!
717    Take a format string and expand escape sequences, that is sequences that
718    begin with %, with information from the current CD. 
719    The expanded string is returned. Here is a list of escape sequences:
720
721    %a : The album artist **
722    %A : The album information **
723    %C : Category **
724    %I : CDDB disk ID **
725    %G : Genre **
726    %M : The current MRL
727    %m : The CD-DA Media Catalog Number (MCN)
728    %n : The number of tracks on the CD
729    %p : The artist/performer/composer in the track **
730    %T : The track number **
731    %s : Number of seconds in this track
732    %t : The name **
733    %Y : The year 19xx or 20xx **
734    %% : a %
735 */
736 static char *
737 CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
738               const char format_str[], const char *mrl, int i_track)
739 {
740 #define TEMP_STR_SIZE 256
741 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
742   static char    temp_str[TEMP_STR_SIZE];
743   size_t i;
744   char * tp = temp_str;
745   bool saw_control_prefix = false;
746   size_t format_len = strlen(format_str);
747
748   bzero(temp_str, TEMP_STR_SIZE);
749
750   for (i=0; i<format_len; i++) {
751
752     if (!saw_control_prefix && format_str[i] != '%') {
753       *tp++ = format_str[i];
754       saw_control_prefix = false;
755       continue;
756     }
757
758     switch(format_str[i]) {
759     case '%':
760       if (saw_control_prefix) {
761         *tp++ = '%';
762       }
763       saw_control_prefix = !saw_control_prefix;
764       break;
765 #ifdef HAVE_LIBCDDB      
766     case 'a':
767       if (!p_cdda->i_cddb_enabled) goto not_special;
768       add_format_str_info(p_cdda->cddb.disc->artist);
769       break;
770     case 'A':
771       if (!p_cdda->i_cddb_enabled) goto not_special;
772       add_format_str_info(p_cdda->cddb.disc->title);
773       break;
774     case 'C':
775       if (!p_cdda->i_cddb_enabled) goto not_special;
776       add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
777       break;
778     case 'G':
779       if (!p_cdda->i_cddb_enabled) goto not_special;
780       add_format_str_info(p_cdda->cddb.disc->genre);
781       break;
782     case 'I':
783       if (!p_cdda->i_cddb_enabled) goto not_special;
784       add_format_num_info(p_cdda->cddb.disc->discid, "%x");
785       break;
786     case 'Y':
787       if (!p_cdda->i_cddb_enabled) goto not_special;
788       add_format_num_info(p_cdda->cddb.disc->year, "%5d");
789       break;
790     case 't':
791       if (p_cdda->i_cddb_enabled) {
792         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, 
793                                             i_track-1);
794         if (t != NULL && t->title != NULL) 
795           add_format_str_info(t->title);
796       } else goto not_special;
797       break;
798     case 'p':
799       if (p_cdda->i_cddb_enabled) {
800         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, 
801                                             i_track-1);
802         if (t != NULL && t->artist != NULL) 
803           add_format_str_info(t->artist);
804       } else goto not_special;
805       break;
806 #endif
807
808     case 'M':
809       add_format_str_info(mrl);
810       break;
811
812 #if FINISHED
813     case 'm':
814       add_format_str_info(p_cdda->mcn);
815       break;
816 #endif
817
818     case 'n':
819       add_format_num_info(p_cdda->i_nb_tracks, "%d");
820       break;
821
822     case 's':
823       if (p_cdda->i_cddb_enabled) {
824         char psz_buffer[MSTRTIME_MAX_SIZE];
825         mtime_t i_duration = 
826           (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1]) 
827           / CDIO_CD_FRAMES_PER_SEC;
828         add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
829       } else goto not_special;
830       break;
831
832     case 'T':
833       add_format_num_info(i_track, "%d");
834       break;
835 #ifdef HAVE_LIBCDDB      
836     not_special:
837 #endif
838     default:
839       *tp++ = '%'; 
840       *tp++ = format_str[i];
841       saw_control_prefix = false;
842     }
843   }
844   return strdup(temp_str);
845 }
846
847 static void
848 CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda, 
849                        playlist_t *p_playlist, unsigned int i_track, 
850                        char *psz_mrl, int psz_mrl_max, 
851                        const char *psz_source, int playlist_operation, 
852                        unsigned int i_pos)
853 {
854   mtime_t i_duration = 
855     (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1]) 
856     / CDIO_CD_FRAMES_PER_SEC;
857   char *p_title;
858   
859   snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u", 
860            CDDA_MRL_PREFIX, psz_source, i_track);
861
862   p_title = CDDAFormatStr(p_input, p_cdda, 
863                           config_GetPsz( p_input, 
864                                          MODULE_STRING "-title-format" ),
865                           psz_mrl, i_track);
866
867   playlist_AddExt( p_playlist, psz_mrl, p_title, i_duration, 
868                    0, 0, playlist_operation, i_pos );
869 }
870
871 static int
872 CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda, 
873                   const char *psz_source, bool play_single_track) 
874 {
875   int i;
876   playlist_t * p_playlist;
877   char       * psz_mrl;
878   unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) + 
879     strlen("@T") + strlen("100") + 1;
880
881 #ifdef HAVE_LIBCDDB
882   p_cdda->i_cddb_enabled = 
883     config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
884 #endif
885   
886   if (play_single_track && !p_cdda->i_cddb_enabled) return 0;
887
888   psz_mrl = malloc( psz_mrl_max );
889
890   if( psz_mrl == NULL )
891     {
892       msg_Warn( p_input, "out of memory" );
893       return -1;
894     }
895
896   p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
897                                                FIND_ANYWHERE );
898   if( !p_playlist )
899     {
900       msg_Warn( p_input, "can't find playlist" );
901       free(psz_mrl);
902       return -1;
903     }
904
905 #ifdef HAVE_LIBCDDB
906   if (p_cdda->i_cddb_enabled)
907     GetCDDBInfo(p_input, p_cdda);
908   else 
909     p_cdda->cddb.disc = NULL;
910 #endif
911
912   InformationCreate(p_input);
913   
914   if (play_single_track) {
915     /* May fill out more information when the playlist user interface becomes
916        more mature.
917      */
918     CDDACreatePlayListItem(p_input, p_cdda, p_playlist, p_cdda->i_track+1, 
919                            psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE, 
920                            p_playlist->i_index);
921   } else {
922   
923     playlist_Delete( p_playlist, p_playlist->i_index);
924
925     for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
926       {
927         CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, psz_mrl, 
928                                psz_mrl_max, psz_source, PLAYLIST_APPEND, 
929                                PLAYLIST_END);
930
931       }
932
933     playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
934
935   }
936     
937   vlc_object_release( p_playlist );
938   free(psz_mrl);
939   return 0;
940 }