]> git.sesse.net Git - vlc/blob - modules/access/cdda/access.c
* src/input/control.c: added INPUT_ADD_INFO/INPUT_SET_NAME to input_Control().
[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 static void InformationCreate( input_thread_t *p_input  )
356 {
357   cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
358
359 #ifdef HAVE_LIBCDDB
360   if (p_cdda->i_cddb_enabled) {
361
362     dbg_print( INPUT_DBG_META, "field %s: %s\n", "Title",
363                p_cdda->cddb.disc->title );
364     input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Title"),
365                    "%s", p_cdda->cddb.disc->title );
366
367     dbg_print( INPUT_DBG_META, "field %s: %s\n", "Artist",
368                p_cdda->cddb.disc->artist );
369     input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Artist"),
370                    "%s", p_cdda->cddb.disc->artist );
371
372     dbg_print( INPUT_DBG_META, "field %s: %s\n", "Genre",
373                p_cdda->cddb.disc->genre );
374     input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Genre"),
375                    "%s", p_cdda->cddb.disc->genre );
376
377     dbg_print( INPUT_DBG_META, "field %s: %s\n", "Extended Data",
378                p_cdda->cddb.disc->ext_data );
379     input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Extended Data"),
380                    "%s", p_cdda->cddb.disc->ext_data );
381
382     if (p_cdda->cddb.disc->year != 0)
383       input_Control( p_input, INPUT_ADD_INFO, _("General"),
384                      _("Year"), "%d", p_cdda->cddb.disc->year );
385     if ( p_cdda->cddb.disc->discid )
386       input_Control( p_input, INPUT_ADD_INFO, _("General"),
387                      _("CDDB Disc ID"), "%x", p_cdda->cddb.disc->discid );
388
389     if ( p_cdda->cddb.disc->category != CDDB_CAT_INVALID )
390       input_Control( p_input, INPUT_ADD_INFO, _("General"),
391                      _("CDDB Disc Category"), "%s",
392                      CDDB_CATEGORY[p_cdda->cddb.disc->category] );
393   }
394
395 #endif /*HAVE_LIBCDDB*/
396 #define TITLE_MAX 30
397
398   {
399     track_t i_track = p_cdda->i_nb_tracks;
400     char psz_buffer[MSTRTIME_MAX_SIZE];
401     mtime_t i_duration =
402       (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[0])
403       / CDIO_CD_FRAMES_PER_SEC;
404
405     dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
406     input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Duration"), "%s",
407                    secstotimestr( psz_buffer, i_duration ) );
408
409     for( i_track = 0 ; i_track < p_cdda->i_nb_tracks ; i_track++ ) {
410       char track_str[TITLE_MAX];
411       mtime_t i_duration =
412         (p_cdda->p_sectors[i_track+1] - p_cdda->p_sectors[i_track])
413         / CDIO_CD_FRAMES_PER_SEC;
414       snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
415       input_Control( p_input, INPUT_ADD_INFO, track_str, _("Duration"), "%s",
416                      secstotimestr( psz_buffer, i_duration ) );
417
418 #ifdef HAVE_LIBCDDB
419       if (p_cdda->i_cddb_enabled) {
420         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
421                                             i_track);
422         if (t != NULL) {
423           if ( t->artist != NULL && strlen(t->artist) ) {
424             input_Control( p_input, INPUT_ADD_INFO, track_str,
425                            _("Artist"), "%s", t->artist );
426           }
427           if ( t->title != NULL && strlen(t->title) ) {
428             input_Control( p_input, INPUT_ADD_INFO, track_str,
429                            _("Title"), "%s",  t->title );
430           }
431           if ( t->ext_data != NULL && strlen(t->ext_data) ) {
432             input_Control( p_input, INPUT_ADD_INFO, track_str,
433                            _("Extended Data"), "%s",  t->ext_data );
434           }
435         }
436       }
437 #endif
438     }
439   }
440 }
441
442
443 #ifdef HAVE_LIBCDDB
444
445 #define free_and_dup(var, val) \
446   if (var) free(var);          \
447   if (val) var=strdup(val);
448
449
450 static void
451 GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
452 {
453
454   dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
455
456   if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
457     int i, i_matches;
458     cddb_conn_t  *conn = cddb_new();
459     const CdIo *cdio = p_cdda->p_cddev->cdio;
460
461
462     cddb_log_set_handler (uninit_log_handler);
463
464     if (!conn) {
465       msg_Warn( p_input, "unable to initialize libcddb" );
466       goto cddb_destroy;
467     }
468
469     cddb_set_email_address( conn,
470                             config_GetPsz( p_input,
471                                            MODULE_STRING "-cddb-email") );
472
473     cddb_set_server_name( conn,
474                           config_GetPsz( p_input,
475                                          MODULE_STRING "-cddb-server") );
476
477     cddb_set_server_port(conn,
478                           config_GetInt( p_input,
479                                          MODULE_STRING "-cddb-port") );
480
481     /* Set the location of the local CDDB cache directory.
482        The default location of this directory is */
483
484     if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" ))
485       cddb_cache_disable(conn);
486
487     cddb_cache_set_dir(conn,
488                        config_GetPsz( p_input,
489                                       MODULE_STRING "-cddb-cachedir") );
490
491     cddb_set_timeout(conn,
492                      config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
493
494
495     if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
496       cddb_http_enable(conn);
497     } else
498       cddb_http_disable(conn);
499
500     p_cdda->cddb.disc = cddb_disc_new();
501     if (!p_cdda->cddb.disc) {
502       msg_Err( p_input, "Unable to create CDDB disc structure." );
503       goto cddb_end;
504     }
505
506     for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
507       cddb_track_t *t = cddb_track_new();
508       t->frame_offset = cdio_get_track_lba(cdio, i);
509       cddb_disc_add_track(p_cdda->cddb.disc, t);
510     }
511
512     p_cdda->cddb.disc->length =
513       cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK)
514       / CDIO_CD_FRAMES_PER_SEC;
515
516     if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
517       msg_Err( p_input, "CDDB disc calc failed" );
518       goto cddb_destroy;
519     }
520
521     i_matches = cddb_query(conn, p_cdda->cddb.disc);
522     if (i_matches > 0) {
523       if (i_matches > 1)
524         msg_Warn( p_input, "Found %d matches in CDDB. Using first one.",
525                   i_matches);
526       cddb_read(conn, p_cdda->cddb.disc);
527
528       if (p_cdda->i_debug & INPUT_DBG_CDDB)
529         cddb_disc_print(p_cdda->cddb.disc);
530
531     } else {
532       msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
533     }
534
535   cddb_destroy:
536     cddb_destroy(conn);
537   }
538   cddb_end: ;
539 }
540 #endif /*HAVE_LIBCDDB*/
541
542 #define add_format_str_info(val)                         \
543   {                                                      \
544     const char *str = val;                               \
545     unsigned int len;                                    \
546     if (val != NULL) {                                   \
547       len=strlen(str);                                   \
548       if (len != 0) {                                    \
549         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    \
550         tp += len;                                       \
551       }                                                  \
552       saw_control_prefix = false;                        \
553     }                                                    \
554   }
555
556 #define add_format_num_info(val, fmt)                    \
557   {                                                      \
558     char num_str[10];                                    \
559     unsigned int len;                                    \
560     sprintf(num_str, fmt, val);                          \
561     len=strlen(num_str);                                 \
562     if (len != 0) {                                      \
563       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  \
564       tp += len;                                         \
565     }                                                    \
566     saw_control_prefix = false;                          \
567   }
568
569 /*!
570    Take a format string and expand escape sequences, that is sequences that
571    begin with %, with information from the current CD.
572    The expanded string is returned. Here is a list of escape sequences:
573
574    %a : The album artist **
575    %A : The album information **
576    %C : Category **
577    %I : CDDB disk ID **
578    %G : Genre **
579    %M : The current MRL
580    %m : The CD-DA Media Catalog Number (MCN)
581    %n : The number of tracks on the CD
582    %p : The artist/performer/composer in the track **
583    %T : The track number **
584    %s : Number of seconds in this track
585    %t : The name **
586    %Y : The year 19xx or 20xx **
587    %% : a %
588 */
589 static char *
590 CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
591               const char format_str[], const char *mrl, int i_track)
592 {
593 #define TEMP_STR_SIZE 256
594 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
595   static char    temp_str[TEMP_STR_SIZE];
596   size_t i;
597   char * tp = temp_str;
598   bool saw_control_prefix = false;
599   size_t format_len = strlen(format_str);
600
601   memset(temp_str, 0, TEMP_STR_SIZE);
602
603   for (i=0; i<format_len; i++) {
604
605     if (!saw_control_prefix && format_str[i] != '%') {
606       *tp++ = format_str[i];
607       saw_control_prefix = false;
608       continue;
609     }
610
611     switch(format_str[i]) {
612     case '%':
613       if (saw_control_prefix) {
614         *tp++ = '%';
615       }
616       saw_control_prefix = !saw_control_prefix;
617       break;
618 #ifdef HAVE_LIBCDDB
619     case 'a':
620       if (!p_cdda->i_cddb_enabled) goto not_special;
621       add_format_str_info(p_cdda->cddb.disc->artist);
622       break;
623     case 'A':
624       if (!p_cdda->i_cddb_enabled) goto not_special;
625       add_format_str_info(p_cdda->cddb.disc->title);
626       break;
627     case 'C':
628       if (!p_cdda->i_cddb_enabled) goto not_special;
629       add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
630       break;
631     case 'G':
632       if (!p_cdda->i_cddb_enabled) goto not_special;
633       add_format_str_info(p_cdda->cddb.disc->genre);
634       break;
635     case 'I':
636       if (!p_cdda->i_cddb_enabled) goto not_special;
637       add_format_num_info(p_cdda->cddb.disc->discid, "%x");
638       break;
639     case 'Y':
640       if (!p_cdda->i_cddb_enabled) goto not_special;
641       add_format_num_info(p_cdda->cddb.disc->year, "%5d");
642       break;
643     case 't':
644       if (p_cdda->i_cddb_enabled) {
645         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
646                                             i_track-1);
647         if (t != NULL && t->title != NULL)
648           add_format_str_info(t->title);
649       } else goto not_special;
650       break;
651     case 'p':
652       if (p_cdda->i_cddb_enabled) {
653         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
654                                             i_track-1);
655         if (t != NULL && t->artist != NULL)
656           add_format_str_info(t->artist);
657       } else goto not_special;
658       break;
659     case 'e':
660       if (p_cdda->i_cddb_enabled) {
661         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
662                                             i_track-1);
663         if (t != NULL && t->ext_data != NULL)
664           add_format_str_info(t->ext_data);
665       } else goto not_special;
666       break;
667 #endif
668
669     case 'M':
670       add_format_str_info(mrl);
671       break;
672
673 #if FINISHED
674     case 'm':
675       add_format_str_info(p_cdda->mcn);
676       break;
677 #endif
678
679     case 'n':
680       add_format_num_info(p_cdda->i_nb_tracks, "%d");
681       break;
682
683 #ifdef HAVE_LIBCDDB
684     case 's':
685       if (p_cdda->i_cddb_enabled) {
686         char psz_buffer[MSTRTIME_MAX_SIZE];
687         mtime_t i_duration =
688           (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
689           / CDIO_CD_FRAMES_PER_SEC;
690         add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
691       } else goto not_special;
692       break;
693 #endif
694
695     case 'T':
696       add_format_num_info(i_track, "%02d");
697       break;
698 #ifdef HAVE_LIBCDDB
699     not_special:
700 #endif
701     default:
702       *tp++ = '%';
703       *tp++ = format_str[i];
704       saw_control_prefix = false;
705     }
706   }
707   return strdup(temp_str);
708 }
709
710 static void
711 CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
712                        playlist_t *p_playlist, unsigned int i_track,
713                        char *psz_mrl, int psz_mrl_max,
714                        const char *psz_source, int playlist_operation,
715                        int i_pos)
716 {
717   mtime_t i_duration =
718     (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[i_track-1])
719     * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
720   char *p_author;
721   char *p_title;
722   char *config_varname = MODULE_STRING "-title-format";
723   playlist_item_t *p_item;
724
725 #ifdef HAVE_LIBCDDB
726   if (p_cdda->i_cddb_enabled) {
727     config_varname = MODULE_STRING "-cddb-title-format";
728   }
729 #endif /*HAVE_LIBCDDB*/
730
731   snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
732            CDDA_MRL_PREFIX, psz_source, i_track);
733
734   p_title = CDDAFormatStr(p_input, p_cdda,
735                           config_GetPsz( p_input, config_varname ),
736                           psz_mrl, i_track);
737
738   dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
739              psz_mrl, p_title, (long int) i_duration / 1000000 , i_pos );
740   playlist_AddExt( p_playlist, psz_mrl, p_title, playlist_operation,
741                          i_pos, i_duration , NULL, 0);
742
743   if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
744
745   vlc_mutex_lock( &p_playlist->object_lock );
746   p_item = playlist_ItemGetByPos( p_playlist, i_pos );
747   vlc_mutex_unlock( &p_playlist->object_lock );
748   if( !p_item )
749       return;
750
751   vlc_mutex_lock( &p_item->input.lock );
752
753   p_author =
754     CDDAFormatStr( p_input, p_cdda,
755                    config_GetPsz( p_input, MODULE_STRING "-author-format" ),
756                    psz_mrl, i_track );
757
758   playlist_ItemAddInfo( p_item ,  _("General"),_("Author"), p_author);
759
760 #ifdef HAVE_LIBCDDB
761   if (p_cdda->i_cddb_enabled) {
762     const char *psz_general_cat = _("General");
763
764     playlist_ItemAddInfo( p_item, psz_general_cat, _("Album"),
765                       "%s", p_cdda->cddb.disc->title);
766     playlist_ItemAddInfo( p_item, psz_general_cat, _("Disc Artist(s)"),
767                       "%s", p_cdda->cddb.disc->artist);
768     playlist_ItemAddInfo( p_item, psz_general_cat,
769                         _("CDDB Disc Category"),
770                       "%s", CDDB_CATEGORY[p_cdda->cddb.disc->category]);
771     playlist_ItemAddInfo( p_item, psz_general_cat, _("Genre"),
772                       "%s", p_cdda->cddb.disc->genre);
773     if ( p_cdda->cddb.disc->discid ) {
774       playlist_ItemAddInfo( p_item, psz_general_cat, _("CDDB Disc ID"),
775                         "%x", p_cdda->cddb.disc->discid );
776     }
777     if (p_cdda->cddb.disc->year != 0) {
778       playlist_ItemAddInfo( p_item, psz_general_cat,
779                         _("Year"), "%5d", p_cdda->cddb.disc->year );
780     }
781
782     if (p_cdda->i_cddb_enabled) {
783       cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
784                                           i_track-1);
785       if (t != NULL && t->artist != NULL) {
786         playlist_ItemAddInfo( p_item, psz_general_cat,
787                           _("Track Artist"), "%s", t->artist );
788         playlist_ItemAddInfo( p_item , psz_general_cat,
789                           _("Track Title"), "%s",  t->title );
790       }
791     }
792
793   }
794 #endif /*HAVE_LIBCDDB*/
795
796   vlc_mutex_unlock( &p_item->input.lock );
797 }
798
799 static int
800 CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda,
801                    const char *psz_source, bool play_single_track)
802 {
803   int i;
804   playlist_t * p_playlist;
805   char       * psz_mrl;
806   unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
807     strlen("@T") + strlen("100") + 1;
808
809 #ifdef HAVE_LIBCDDB
810   p_cdda->i_cddb_enabled =
811     config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
812   if( play_single_track && !p_cdda->i_cddb_enabled ) return 0;
813 #else
814   if( play_single_track ) return 0;
815 #endif
816
817
818   psz_mrl = malloc( psz_mrl_max );
819
820   if( psz_mrl == NULL )
821     {
822       msg_Warn( p_input, "out of memory" );
823       return -1;
824     }
825
826   p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
827                                                FIND_ANYWHERE );
828   if( !p_playlist )
829     {
830       msg_Warn( p_input, "can't find playlist" );
831       free(psz_mrl);
832       return -1;
833     }
834
835 #ifdef HAVE_LIBCDDB
836   if (p_cdda->i_cddb_enabled)
837     GetCDDBInfo(p_input, p_cdda);
838   else
839     p_cdda->cddb.disc = NULL;
840 #endif
841
842   InformationCreate(p_input);
843
844   if (play_single_track) {
845     /* May fill out more information when the playlist user interface becomes
846        more mature.
847      */
848     CDDACreatePlayListItem(p_input, p_cdda, p_playlist, p_cdda->i_track+1,
849                            psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
850                            p_playlist->i_index);
851   } else {
852
853     playlist_Delete( p_playlist, p_playlist->i_index);
854
855     for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
856       {
857         CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, psz_mrl,
858                                psz_mrl_max, psz_source, PLAYLIST_APPEND,
859                                PLAYLIST_END);
860       }
861
862     playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
863
864   }
865
866   vlc_object_release( p_playlist );
867   free(psz_mrl);
868   return 0;
869 }
870
871 /****************************************************************************
872  * Public functions
873  ****************************************************************************/
874 int
875 E_(DebugCB)   ( vlc_object_t *p_this, const char *psz_name,
876                 vlc_value_t oldval, vlc_value_t val, void *p_data )
877 {
878   cdda_data_t *p_cdda;
879
880   if (NULL == p_cdda_input) return VLC_EGENERIC;
881
882   p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
883
884   if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
885     msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
886              p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
887   }
888   p_cdda->i_debug = val.i_int;
889   return VLC_SUCCESS;
890 }
891
892 int
893 E_(CDDBEnabledCB)   ( vlc_object_t *p_this, const char *psz_name,
894                       vlc_value_t oldval, vlc_value_t val, void *p_data )
895 {
896   cdda_data_t *p_cdda;
897
898   if (NULL == p_cdda_input) return VLC_EGENERIC;
899
900   p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
901
902 #ifdef HAVE_LIBCDDB
903   if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
904     msg_Dbg( p_cdda_input, "Old CDDB Enabled (x%0x) %d, new (x%0x) %d",
905              p_cdda->i_cddb_enabled, p_cdda->i_cddb_enabled,
906              val.i_int, val.i_int);
907   }
908   p_cdda->i_cddb_enabled = val.i_int;
909 #endif
910   return VLC_SUCCESS;
911 }
912
913 /*FIXME*/
914 #if PLAYLIST_INTERFACE_IS_FIXED
915 int
916 E_(TitleFormatCB)   ( vlc_object_t *p_this, const char *psz_name,
917                       vlc_value_t oldval, vlc_value_t val, void *p_data )
918 {
919   cdda_data_t *p_cdda;
920
921   if (NULL == p_cdda_input) return VLC_EGENERIC;
922
923   p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
924
925   if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
926     msg_Dbg( p_cdda_input, "Old CDDB Enabled (%s), new (%s)",
927              oldval.psz_string, val.psz_string);
928   }
929   ????
930   return VLC_SUCCESS;
931 }
932 #endif
933
934 /*****************************************************************************
935  * Open: open cdda
936  *****************************************************************************/
937 int
938 E_(Open)( vlc_object_t *p_this )
939 {
940     input_thread_t *        p_input = (input_thread_t *)p_this;
941     char *                  psz_orig;
942     char *                  psz_parser;
943     char *                  psz_source;
944     cdda_data_t *           p_cdda;
945     int                     i;
946     int                     i_track = 1;
947     cddev_t                 *p_cddev;
948     vlc_value_t             val;
949     bool                    play_single_track = false;
950
951     /* Set where to log errors messages from libcdio. */
952     p_cdda_input = (input_thread_t *)p_this;
953
954     /* parse the options passed in command line : */
955     psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
956
957     if( !psz_orig )
958     {
959         return( -1 );
960     }
961
962     while( *psz_parser && *psz_parser != '@' )
963     {
964         psz_parser++;
965     }
966
967     if( *psz_parser == '@' )
968     {
969         /* Found options */
970         *psz_parser = '\0';
971         ++psz_parser;
972
973         if ('T' == *psz_parser || 't' == *psz_parser )
974             ++psz_parser;
975
976         i_track = (int)strtol( psz_parser, NULL, 10 );
977         i_track = i_track ? i_track : 1;
978         play_single_track = true;
979     }
980
981     if( !*psz_source ) {
982       /* No source specified, so figure it out. */
983       if( !p_input->psz_access ) {
984         free( psz_orig );
985         return -1;
986       }
987       psz_source = config_GetPsz( p_input, "cd-audio" );
988
989       if( !psz_source || 0==strlen(psz_source) ) {
990         /* Scan for a CD-ROM drive with a CD-DA in it. */
991         char **cd_drives =
992           cdio_get_devices_with_cap(NULL,  CDIO_FS_AUDIO, false);
993         if (NULL == cd_drives) return -1;
994         if (cd_drives[0] == NULL) {
995           cdio_free_device_list(cd_drives);
996           return -1;
997         }
998         psz_source = strdup(cd_drives[0]);
999         cdio_free_device_list(cd_drives);
1000       }
1001     }
1002
1003     /* Open CDDA */
1004     cdio_log_set_handler ( cdio_log_handler );
1005 #ifdef HAVE_LIBCDDB
1006     cddb_log_set_handler ( cddb_log_handler );
1007 #endif
1008
1009     if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
1010     {
1011         msg_Warn( p_input, "could not open %s", psz_source );
1012         free( psz_source );
1013         return VLC_EGENERIC;
1014     }
1015
1016     p_cdda = malloc( sizeof(cdda_data_t) );
1017     if( p_cdda == NULL )
1018     {
1019         msg_Err( p_input, "out of memory" );
1020         free( psz_source );
1021         return VLC_ENOMEM;
1022     }
1023
1024     p_cdda->p_cddev        = p_cddev;
1025     p_cdda->i_debug        = config_GetInt( p_this, MODULE_STRING "-debug" );
1026     p_input->p_access_data = (void *)p_cdda;
1027
1028     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
1029
1030     p_input->i_mtu = CDDA_DATA_ONCE;
1031
1032     /* We read the Table Of Content information */
1033     p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
1034                               p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
1035     if( p_cdda->i_nb_tracks < 0 )
1036         msg_Err( p_input, "unable to count tracks" );
1037     else if( p_cdda->i_nb_tracks <= 0 )
1038         msg_Err( p_input, "no audio tracks found" );
1039
1040     if( p_cdda->i_nb_tracks <= 0 )
1041     {
1042         ioctl_Close( p_cdda->p_cddev );
1043         free( p_cdda );
1044         free( psz_source );
1045         return VLC_EGENERIC;
1046     }
1047
1048     if( i_track > p_cdda->i_nb_tracks || i_track < 1 )
1049         i_track = 1;
1050
1051     /* Set stream and area data */
1052     vlc_mutex_lock( &p_input->stream.stream_lock );
1053
1054     /* Initialize ES structures */
1055     input_InitStream( p_input, 0 );
1056
1057     /* cdda input method */
1058     p_input->stream.i_method = INPUT_METHOD_CDDA;
1059
1060     p_input->stream.b_pace_control = 1;
1061     p_input->stream.b_seekable = 1;
1062     p_input->stream.i_mux_rate = 44100 * 4 / 50;
1063
1064 #define area p_input->stream.pp_areas
1065     for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
1066     {
1067         input_AddArea( p_input, i, 1 );
1068
1069         /* Absolute start offset and size */
1070         area[i]->i_start =
1071             (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
1072         area[i]->i_size =
1073             (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
1074             * (off_t)CDIO_CD_FRAMESIZE_RAW;
1075     }
1076 #undef area
1077
1078     CDDAPlay( p_input, i_track);
1079     vlc_mutex_unlock( &p_input->stream.stream_lock );
1080
1081     CDDAFixupPlayList(p_input, p_cdda, psz_source, play_single_track);
1082
1083     p_input->pf_read = CDDARead;
1084     p_input->pf_seek = CDDASeek;
1085     p_input->pf_set_area = CDDASetArea;
1086     p_input->pf_set_program = CDDASetProgram;
1087
1088     /* Update default_pts to a suitable value for cdda access */
1089     var_Create( p_input, MODULE_STRING "-caching",
1090                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
1091     var_Get( p_input, MODULE_STRING "-caching", &val );
1092     p_input->i_pts_delay = val.i_int * 1000;
1093
1094     free( psz_source );
1095
1096     /* Build a WAV header for the output data */
1097     memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
1098     SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
1099     SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
1100     p_cdda->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
1101     p_cdda->waveheader.Length = 0;                     /* we just don't know */
1102     p_cdda->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
1103     p_cdda->waveheader.SubChunkID  = VLC_FOURCC('f', 'm', 't', ' ');
1104     SetDWLE( &p_cdda->waveheader.SubChunkLength, 16);
1105     SetWLE( &p_cdda->waveheader.Modus, 2);
1106     SetDWLE( &p_cdda->waveheader.SampleFreq, 44100);
1107     SetWLE( &p_cdda->waveheader.BytesPerSample,
1108             2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
1109     SetDWLE( &p_cdda->waveheader.BytesPerSec,
1110              16 /*BytesPerSample*/ * 44100 /*SampleFreq*/ );
1111     p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
1112     p_cdda->waveheader.DataLength = 0;                 /* we just don't know */
1113     p_cdda->i_header_pos = 0;
1114
1115     return VLC_SUCCESS;
1116 }
1117
1118 /*****************************************************************************
1119  * CDDAClose: closes cdda
1120  *****************************************************************************/
1121 void
1122 E_(Close)( vlc_object_t *p_this )
1123 {
1124     input_thread_t *   p_input = (input_thread_t *)p_this;
1125     cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
1126
1127     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
1128     ioctl_Close( p_cdda->p_cddev );
1129
1130     cdio_log_set_handler (uninit_log_handler);
1131
1132 #ifdef HAVE_LIBCDDB
1133     cddb_log_set_handler (uninit_log_handler);
1134     if (p_cdda->i_cddb_enabled)
1135       cddb_disc_destroy(p_cdda->cddb.disc);
1136 #endif
1137
1138     free( p_cdda->p_sectors );
1139     free( p_cdda );
1140     p_cdda_input = NULL;
1141 }