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