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