]> git.sesse.net Git - vlc/blob - modules/access/cdda/access.c
Add CDDB CD Info in File Info section (via input_AddInfo and
[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.6 2003/12/01 01:08:42 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 static 
522 char * secs2TimeStr( int64_t i_sec )
523 {
524   int h = i_sec / 3600;
525   int m = ( i_sec / 60 ) % 60;
526   int s = i_sec % 60;
527   static char buffer[20];
528
529   snprintf(buffer, 20, "%d:%2.2d:%2.2d", h, m, s);
530   return buffer;
531 }
532
533 #define meta_info_add_str(title, str) \
534   if ( str ) {                                          \
535     printf("field %s str %s\n", title, str);            \
536     input_AddInfo( p_cat, _(title), "%s", str );        \
537   }
538
539
540 static void InformationCreate( input_thread_t *p_input  )
541 {
542   cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
543   input_info_category_t *p_cat;
544   int use_cddb = p_cdda->i_cddb_enabled;
545   
546   p_cat = input_InfoCategory( p_input, "General" );
547
548 #ifdef HAVE_LIBCDDB
549   if (use_cddb) {
550     
551     if( p_cdda->cddb.disc->length > 1000 )
552       {
553         int64_t i_sec = (int64_t) p_cdda->cddb.disc->length;
554         input_AddInfo( p_cat, _("Duration"), "%s", secs2TimeStr( i_sec ) );
555       } else 
556       {
557         use_cddb = 0;
558       }
559     
560     meta_info_add_str( "Title", p_cdda->cddb.disc->title );
561     meta_info_add_str( "Artist", p_cdda->cddb.disc->artist );
562     meta_info_add_str( "Genre", p_cdda->cddb.disc->genre );
563     meta_info_add_str( "Extended Data", p_cdda->cddb.disc->ext_data );
564     {
565       char year[5];
566       if (p_cdda->cddb.disc->year != 0) {
567         snprintf(year, 5, "%d", p_cdda->cddb.disc->year);
568         meta_info_add_str( "Year", year );
569       }
570       if ( p_cdda->cddb.disc->discid ) {
571         input_AddInfo( p_cat, _("CDDB Disc ID"), "%x", 
572                        p_cdda->cddb.disc->discid );
573       }
574       
575       if ( p_cdda->cddb.disc->category != CDDB_CAT_INVALID ) {
576         input_AddInfo( p_cat, _("CDDB Disc Category"), "%s", 
577                        CDDB_CATEGORY[p_cdda->cddb.disc->category] );
578       }
579       
580     }
581   }
582
583 #endif /*HAVE_LIBCDDB*/
584
585   if (!use_cddb)
586   {
587     lba_t i_sec = cdio_get_track_lba(p_cdda->p_cddev->cdio, 
588                                        CDIO_CDROM_LEADOUT_TRACK) ;
589
590     i_sec /= CDIO_CD_FRAMES_PER_SEC;
591
592     if ( i_sec > 1000 )
593       input_AddInfo( p_cat, _("Duration"), "%s", secs2TimeStr( i_sec ) );
594   }
595 }
596
597
598 #ifdef HAVE_LIBCDDB
599
600 #define free_and_dup(var, val) \
601   if (var) free(var);          \
602   if (val) var=strdup(val);            
603   
604
605 static void
606 GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
607 {
608
609   dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
610
611   if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
612     int i, i_matches;
613     cddb_conn_t  *conn = cddb_new();
614     const CdIo *cdio = p_cdda->p_cddev->cdio;
615     
616     
617     cddb_log_set_handler (uninit_log_handler);
618
619     if (!conn) {
620       msg_Warn( p_input, "unable to initialize libcddb" );
621       goto cddb_destroy;
622     }
623     
624     cddb_set_email_address( conn, 
625                             config_GetPsz( p_input, 
626                                            MODULE_STRING "-cddb-email") );
627     
628     cddb_set_server_name( conn, 
629                           config_GetPsz( p_input, 
630                                          MODULE_STRING "-cddb-server") );
631
632     cddb_set_server_port(conn, 
633                           config_GetInt( p_input, 
634                                          MODULE_STRING "-cddb-port") );
635
636     /* Set the location of the local CDDB cache directory.
637        The default location of this directory is */
638
639     if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" )) 
640       cddb_cache_disable(conn);
641
642     cddb_cache_set_dir(conn, 
643                        config_GetPsz( p_input, 
644                                       MODULE_STRING "-cddb-cachedir") );
645
646     cddb_set_timeout(conn, 
647                      config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
648
649
650     if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
651       cddb_http_enable(conn);
652     } else
653       cddb_http_disable(conn);
654     
655     p_cdda->cddb.disc = cddb_disc_new();
656     if (!p_cdda->cddb.disc) {
657       msg_Err( p_input, "Unable to create CDDB disc structure." );
658       goto cddb_end;
659     }
660
661     for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
662       cddb_track_t *t = cddb_track_new(); 
663       t->frame_offset = cdio_get_track_lba(cdio, i);
664       cddb_disc_add_track(p_cdda->cddb.disc, t);
665     }
666     
667     p_cdda->cddb.disc->length = 
668       cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK) 
669       / CDIO_CD_FRAMES_PER_SEC;
670
671
672     if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
673       msg_Err( p_input, "CDDB disc calc failed" );
674       goto cddb_destroy;
675     }
676
677     i_matches = cddb_query(conn, p_cdda->cddb.disc);
678     if (i_matches > 0) {
679       if (i_matches > 1)
680         msg_Warn( p_input, "Found %d matches in CDDB. Using first one.", 
681                   i_matches);
682       cddb_read(conn, p_cdda->cddb.disc);
683
684       if (p_cdda->i_debug & INPUT_DBG_CDDB) 
685         cddb_disc_print(p_cdda->cddb.disc);
686
687     } else {
688       msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
689     }
690
691   cddb_destroy:
692     cddb_destroy(conn);
693   }
694   cddb_end: ;
695 }
696 #endif /*HAVE_LIBCDDB*/
697
698 #define add_format_str_info(val)                        \
699   {                                                     \
700     const char *str = val;                              \
701     unsigned int len;                                   \
702     if (val != NULL) {                                  \
703       len=strlen(str);                                  \
704       if (len != 0) {                                   \
705         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));   \
706         tp += len;                                      \
707       }                                                 \
708       saw_control_prefix = false;                       \
709     }                                                   \
710   }
711
712 #define add_format_num_info(val, fmt)                   \
713   {                                                     \
714     char num_str[10];                                   \
715     unsigned int len;                                   \
716     sprintf(num_str, fmt, val);                         \
717     len=strlen(num_str);                                \
718     if (len != 0) {                                     \
719       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
720       tp += len;                                        \
721     }                                                   \
722     saw_control_prefix = false;                         \
723   }
724
725 /*!
726    Take a format string and expand escape sequences, that is sequences that
727    begin with %, with information from the current CD. 
728    The expanded string is returned. Here is a list of escape sequences:
729
730    %a : The album artist
731    %A : The album information 
732    %C : Category
733    %I : CDDB disk ID
734    %G : Genre
735    %M : The current MRL
736    %m : The CD-DA Media Catalog Number (MCN)
737    %p : The artist/performer/composer in the track
738    %T : The track number
739    %s : Number of seconds in this track
740    %t : The name
741    %Y : The year 19xx or 20xx
742    %% : a %
743 */
744 static char *
745 CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
746               const char format_str[], const char *mrl, int i_track)
747 {
748 #define TEMP_STR_SIZE 256
749 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
750   static char    temp_str[TEMP_STR_SIZE];
751   size_t i;
752   char * tp = temp_str;
753   bool saw_control_prefix = false;
754   size_t format_len = strlen(format_str);
755
756   bzero(temp_str, TEMP_STR_SIZE);
757
758   for (i=0; i<format_len; i++) {
759
760     if (!saw_control_prefix && format_str[i] != '%') {
761       *tp++ = format_str[i];
762       saw_control_prefix = false;
763       continue;
764     }
765
766     switch(format_str[i]) {
767     case '%':
768       if (saw_control_prefix) {
769         *tp++ = '%';
770       }
771       saw_control_prefix = !saw_control_prefix;
772       break;
773 #ifdef HAVE_LIBCDDB      
774     case 'a':
775       if (!p_cdda->i_cddb_enabled) goto not_special;
776       add_format_str_info(p_cdda->cddb.disc->artist);
777       break;
778     case 'A':
779       if (!p_cdda->i_cddb_enabled) goto not_special;
780       add_format_str_info(p_cdda->cddb.disc->title);
781       break;
782     case 'C':
783       if (!p_cdda->i_cddb_enabled) goto not_special;
784       add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
785       break;
786     case 'G':
787       if (!p_cdda->i_cddb_enabled) goto not_special;
788       add_format_str_info(p_cdda->cddb.disc->genre);
789       break;
790     case 'I':
791       if (!p_cdda->i_cddb_enabled) goto not_special;
792       add_format_num_info(p_cdda->cddb.disc->discid, "%x");
793       break;
794     case 'Y':
795       if (!p_cdda->i_cddb_enabled) goto not_special;
796       add_format_num_info(p_cdda->cddb.disc->year, "%5d");
797       break;
798     case 't':
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->title != NULL) 
803           add_format_str_info(t->title);
804       } else goto not_special;
805       break;
806     case 'p':
807       if (p_cdda->i_cddb_enabled) {
808         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, 
809                                             i_track-1);
810         if (t != NULL && t->artist != NULL) 
811           add_format_str_info(t->artist);
812       } else goto not_special;
813       break;
814     case 's':
815       if (p_cdda->i_cddb_enabled) {
816         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, 
817                                             i_track-1);
818         if (t != NULL && t->length > 1000 ) {
819           add_format_str_info(secs2TimeStr(t->length));
820         }
821       } else goto not_special;
822       break;
823
824 #endif
825
826     case 'M':
827       add_format_str_info(mrl);
828       break;
829 #if FINISHED
830     case 'm':
831       add_format_str_info(p_cdda->mcn);
832       break;
833 #endif
834     case 'T':
835       add_format_num_info(i_track, "%d");
836       break;
837 #ifdef HAVE_LIBCDDB      
838     not_special:
839 #endif
840     default:
841       *tp++ = '%'; 
842       *tp++ = format_str[i];
843       saw_control_prefix = false;
844     }
845   }
846   return strdup(temp_str);
847 }
848
849 static void
850 CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda, 
851                        playlist_t *p_playlist, unsigned int i_track, 
852                        char *psz_mrl, int psz_mrl_max, 
853                        const char *psz_source, int playlist_operation, 
854                        unsigned int i_pos)
855 {
856   mtime_t i_duration = 
857     (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1]) 
858     * 1000 / CDIO_CD_FRAMES_PER_SEC;
859   char *p_title;
860   
861   snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u", 
862            CDDA_MRL_PREFIX, psz_source, i_track);
863
864   p_title = CDDAFormatStr(p_input, p_cdda, 
865                           config_GetPsz( p_input, 
866                                          MODULE_STRING "-title-format" ),
867                           psz_mrl, i_track);
868
869   playlist_AddExt( p_playlist, psz_mrl, p_title, i_duration, 
870                    0, 0, playlist_operation, i_pos );
871 }
872
873 static int
874 CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda, 
875                   const char *psz_source, bool play_single_track) 
876 {
877   int i;
878   playlist_t * p_playlist;
879   char       * psz_mrl;
880   unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) + 
881     strlen("@T") + strlen("100") + 1;
882
883 #ifdef HAVE_LIBCDDB
884   p_cdda->i_cddb_enabled = 
885     config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
886 #endif
887   
888   if (play_single_track && !p_cdda->i_cddb_enabled) return 0;
889
890   psz_mrl = malloc( psz_mrl_max );
891
892   if( psz_mrl == NULL )
893     {
894       msg_Warn( p_input, "out of memory" );
895       return -1;
896     }
897
898   p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
899                                                FIND_ANYWHERE );
900   if( !p_playlist )
901     {
902       msg_Warn( p_input, "can't find playlist" );
903       free(psz_mrl);
904       return -1;
905     }
906
907 #ifdef HAVE_LIBCDDB
908   if (p_cdda->i_cddb_enabled)
909     GetCDDBInfo(p_input, p_cdda);
910   else 
911     p_cdda->cddb.disc = NULL;
912 #endif
913
914   InformationCreate(p_input);
915   
916   if (play_single_track) {
917     /* May fill out more information when the playlist user interface becomes
918        more mature.
919      */
920     CDDACreatePlayListItem(p_input, p_cdda, p_playlist, p_cdda->i_track+1, 
921                            psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE, 
922                            p_playlist->i_index);
923   } else {
924   
925     playlist_Delete( p_playlist, p_playlist->i_index);
926
927     for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
928       {
929         CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, psz_mrl, 
930                                psz_mrl_max, psz_source, PLAYLIST_APPEND, 
931                                PLAYLIST_END);
932
933       }
934
935     playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
936
937   }
938     
939   vlc_object_release( p_playlist );
940   free(psz_mrl);
941   return 0;
942 }