]> git.sesse.net Git - vlc/blob - modules/access/cdda/access.c
Add CD-DA CDDB support via libcddb.
[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.4 2003/11/30 18:14:20 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(const input_thread_t *p_input, 
68                               cdda_data_t *p_cdda, const char *psz_source, 
69                               bool play_single_track, unsigned int i_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     CDDAFixupPlayList(p_input, p_cdda, psz_source, play_single_track, i_track);
316
317     CDDAPlay( p_input, i_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     cddb_disc_destroy(p_cdda->cddb.disc);
375 #endif
376
377     free( p_cdda );
378     p_cdda_input = NULL;
379 }
380
381 /*****************************************************************************
382  * CDDARead: reads from the CDDA into PES packets.
383  *****************************************************************************
384  * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
385  * bytes.
386  *****************************************************************************/
387 static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
388                      size_t i_len )
389 {
390     cdda_data_t *           p_cdda;
391     int                     i_blocks;
392     int                     i_index;
393     int                     i_read;
394
395     p_cdda = (cdda_data_t *)p_input->p_access_data;
396
397     i_read = 0;
398
399     /* Compute the number of blocks we have to read */
400
401     i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
402
403     for ( i_index = 0; i_index < i_blocks; i_index++ )
404     {
405
406       if (cdio_read_audio_sector(p_cdda->p_cddev->cdio, p_buffer, 
407                                  p_cdda->i_sector) != 0)
408         {
409           msg_Err( p_input, "could not read sector %d", p_cdda->i_sector );
410           return -1;
411         }
412
413         p_cdda->i_sector ++;
414         if ( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
415         {
416             input_area_t *p_area;
417
418             dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL), 
419                        "end of track, cur: %u", p_cdda->i_sector );
420
421             if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )
422                 return 0; /* EOF */
423
424             vlc_mutex_lock( &p_input->stream.stream_lock );
425             p_area = p_input->stream.pp_areas[
426                     p_input->stream.p_selected_area->i_id + 1 ];
427
428             p_area->i_part = 1;
429             CDDASetArea( p_input, p_area );
430             vlc_mutex_unlock( &p_input->stream.stream_lock );
431         }
432         i_read += CDIO_CD_FRAMESIZE_RAW;
433     }
434
435     if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
436     {
437         msg_Err( p_input, "must read full sectors" );
438     }
439
440     return i_read;
441 }
442
443 /*****************************************************************************
444  * CDDASetProgram: Does nothing since a CDDA is mono_program
445  *****************************************************************************/
446 static int CDDASetProgram( input_thread_t * p_input,
447                            pgrm_descriptor_t * p_program)
448 {
449     cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
450     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
451     return 0;
452 }
453
454 /*****************************************************************************
455  * CDDASetArea: initialize input data for title x.
456  * It should be called for each user navigation request.
457  ****************************************************************************/
458 static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
459 {
460     cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
461     vlc_value_t val;
462
463     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
464
465     /* we can't use the interface slider until initilization is complete */
466     p_input->stream.b_seekable = 0;
467
468     if( p_area != p_input->stream.p_selected_area )
469     {
470         /* Change the default area */
471         p_input->stream.p_selected_area = p_area;
472
473         /* Change the current track */
474         p_cdda->i_track = p_area->i_id - 1;
475         p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
476
477         /* Update the navigation variables without triggering a callback */
478         val.i_int = p_area->i_id;
479         var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
480     }
481
482     p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
483
484     p_input->stream.p_selected_area->i_tell =
485         (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
486          - p_input->stream.p_selected_area->i_start;
487
488     /* warn interface that something has changed */
489     p_input->stream.b_seekable = 1;
490     p_input->stream.b_changed = 1;
491
492     return 0;
493 }
494
495 /****************************************************************************
496  * CDDASeek
497  ****************************************************************************/
498 static void CDDASeek( input_thread_t * p_input, off_t i_off )
499 {
500     cdda_data_t * p_cdda;
501
502     p_cdda = (cdda_data_t *) p_input->p_access_data;
503
504     p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
505                        + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
506
507     vlc_mutex_lock( &p_input->stream.stream_lock );
508     p_input->stream.p_selected_area->i_tell =
509         (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
510          - p_input->stream.p_selected_area->i_start;
511
512     vlc_mutex_unlock( &p_input->stream.stream_lock );
513
514     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
515     "sector %ud, offset: %lld, i_tell: %lld",  p_cdda->i_sector, i_off, 
516                p_input->stream.p_selected_area->i_tell );
517
518 }
519
520 #ifdef HAVE_LIBCDDB
521 static void
522 GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
523 {
524
525   dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
526
527   if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
528     int i, i_matches;
529     cddb_conn_t  *conn = cddb_new();
530     const CdIo *cdio = p_cdda->p_cddev->cdio;
531     
532     
533     cddb_log_set_handler (uninit_log_handler);
534
535     if (!conn) {
536       msg_Warn( p_input, "unable to initialize libcddb" );
537       goto cddb_destroy;
538     }
539     
540     cddb_set_email_address( conn, 
541                             config_GetPsz( p_input, 
542                                            MODULE_STRING "-cddb-email") );
543     
544     cddb_set_server_name( conn, 
545                           config_GetPsz( p_input, 
546                                          MODULE_STRING "-cddb-server") );
547
548     cddb_set_server_port(conn, 
549                           config_GetInt( p_input, 
550                                          MODULE_STRING "-cddb-port") );
551
552     /* Set the location of the local CDDB cache directory.
553        The default location of this directory is */
554
555     if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" )) 
556       cddb_cache_disable(conn);
557
558     cddb_cache_set_dir(conn, 
559                        config_GetPsz( p_input, 
560                                       MODULE_STRING "-cddb-cachedir") );
561
562     cddb_set_timeout(conn, 
563                      config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
564
565
566     if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
567       cddb_http_enable(conn);
568     } else
569       cddb_http_disable(conn);
570     
571     p_cdda->cddb.disc = cddb_disc_new();
572     if (!p_cdda->cddb.disc) {
573       msg_Err( p_input, "Unable to create CDDB disc structure." );
574       goto cddb_end;
575     }
576
577     for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
578       cddb_track_t *t = cddb_track_new(); 
579       t->frame_offset = cdio_get_track_lba(cdio, i);
580       cddb_disc_add_track(p_cdda->cddb.disc, t);
581     }
582     
583     p_cdda->cddb.disc->length = 
584       cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK) 
585       / CDIO_CD_FRAMES_PER_SEC;
586
587
588     if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
589       msg_Err( p_input, "CDDB disc calc failed" );
590       goto cddb_destroy;
591     }
592
593     i_matches = cddb_query(conn, p_cdda->cddb.disc);
594     if (i_matches > 0) {
595       if (i_matches > 1)
596         msg_Warn( p_input, "Found %d matches in CDDB. Using first one.", 
597                   i_matches);
598       cddb_read(conn, p_cdda->cddb.disc);
599
600       if (p_cdda->i_debug & INPUT_DBG_CDDB) 
601         cddb_disc_print(p_cdda->cddb.disc);
602
603 #if FIXED
604       if ((_cdda_is_cd_changed(this) == 1)) 
605 #endif
606         /**** _cdda_cddb_set_info(this, this->cddb.disc); ***/
607     } else {
608       msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
609     }
610
611   cddb_destroy:
612     cddb_destroy(conn);
613   }
614   cddb_end: ;
615 }
616 #endif /*HAVE_LIBCDDB*/
617
618 static void
619 CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda, 
620                        playlist_t *p_playlist, unsigned int i_track, 
621                        char *psz_mrl, int psz_mrl_max, 
622                        const char *psz_source, int i_cddb_enabled, 
623                        int playlist_operation, unsigned int i_pos)
624 {
625   mtime_t i_duration = 
626     (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1]) 
627     * 1000 / CDIO_CD_FRAMES_PER_SEC;
628   char *p_title = psz_mrl;
629   
630   snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u", 
631            CDDA_MRL_PREFIX, psz_source, i_track);
632   if (i_cddb_enabled) {
633     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
634     if (t != NULL && t->title != NULL) 
635       p_title = t->title;
636   }
637   playlist_AddExt( p_playlist, psz_mrl, p_title, i_duration, 
638                    0, 0, playlist_operation, i_pos );
639 }
640
641 static int
642 CDDAFixupPlayList(const input_thread_t *p_input, cdda_data_t *p_cdda, 
643                   const char *psz_source, bool play_single_track, 
644                   unsigned int i_track)
645 {
646   int i;
647   playlist_t * p_playlist;
648   char       * psz_mrl;
649   unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) + 
650     strlen("@T") + strlen("100") + 1;
651   int i_cddb_enabled = 
652 #ifdef HAVE_LIBCDDB
653     config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
654 #else
655      0
656 #endif
657   
658   if (play_single_track && !i_cddb_enabled) return 0;
659
660   psz_mrl = malloc( psz_mrl_max );
661
662   if( psz_mrl == NULL )
663     {
664       msg_Warn( p_input, "out of memory" );
665       return -1;
666     }
667
668   p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
669                                                FIND_ANYWHERE );
670   if( !p_playlist )
671     {
672       msg_Warn( p_input, "can't find playlist" );
673       free(psz_mrl);
674       return -1;
675     }
676
677 #ifdef HAVE_LIBCDDB
678   if (i_cddb_enabled)
679     GetCDDBInfo(p_input, p_cdda);
680 #endif
681   
682   if (play_single_track) {
683     /* May fill out more information when the playlist user interface becomes
684        more mature.
685      */
686     CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i_track, 
687                        psz_mrl, psz_mrl_max, 
688                        psz_source, i_cddb_enabled,
689                        PLAYLIST_REPLACE, p_playlist->i_index);
690   } else {
691   
692     playlist_Delete( p_playlist, p_playlist->i_index);
693
694     for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
695       {
696         CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, psz_mrl, 
697                                psz_mrl_max, psz_source, i_cddb_enabled,
698                                PLAYLIST_APPEND, PLAYLIST_END);
699
700       }
701
702     playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
703
704   }
705     
706   vlc_object_release( p_playlist );
707   free(psz_mrl);
708   return 0;
709 }