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