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