]> git.sesse.net Git - vlc/blob - modules/access/cdda/access.c
2nd attempt to get libcdio cdda working.
[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/input.h>
34 #include <vlc_playlist.h>
35
36 #include <sys/types.h>
37 #include <cdio/cdio.h>
38 #include <cdio/logging.h>
39 #include <cdio/cd_types.h>
40
41 #include "codecs.h"
42 #include "vlc_keys.h"
43
44 #ifdef HAVE_UNISTD_H
45 #   include <unistd.h>
46 #endif
47
48 #ifdef HAVE_ERRNO_H
49 #   include <errno.h>
50 #endif
51
52 #include <string.h>
53
54 #include "cdda.h"
55
56 #define CDDA_MRL_PREFIX "cddax://"
57
58 /* how many blocks Open will read in each loop. Note libcdio and
59    SCSI MMC devices can read at most 25 blocks.
60 */
61 #define CDDA_BLOCKS_ONCE 20
62 #define CDDA_DATA_ONCE   (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW)
63
64 /* Frequency of sample in bits per second. */
65 #define CDDA_FREQUENCY_SAMPLE 44100
66
67 /* FIXME: This variable is a hack. Would be nice to eliminate. */
68 static access_t *p_cdda_input = NULL;
69
70 /*****************************************************************************
71  * Local prototypes
72  *****************************************************************************/
73 static block_t *CDDABlock( access_t * p_access );
74 static int      CDDASeek( access_t * p_access, int64_t i_pos );
75 static int      CDDAControl( access_t *p_access, int i_query, 
76                              va_list args );
77 static void     CDDAMetaInfo( access_t *p_access  );
78 static int      CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda, 
79                                    const char *psz_source, 
80                                    vlc_bool_t b_single_track );
81 static void     CDDACreatePlaylistItem(const access_t *p_access, 
82                                        cdda_data_t *p_cdda,
83                                        playlist_t *p_playlist, 
84                                        track_t i_track,
85                                        char *psz_mrl, int psz_mrl_max,
86                                        const char *psz_source, 
87                                        int playlist_operation,
88                                        int i_pos);
89
90 static int      GetCDInfo( access_t *p_access, cdda_data_t *p_cdda ) ;
91
92
93
94
95 /****************************************************************************
96  * Private functions
97  ****************************************************************************/
98
99 /* process messages that originate from libcdio. */
100 static void
101 cdio_log_handler (cdio_log_level_t level, const char message[])
102 {
103   cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
104   switch (level) {
105   case CDIO_LOG_DEBUG:
106   case CDIO_LOG_INFO:
107     if (p_cdda->i_debug & INPUT_DBG_CDIO)
108       msg_Dbg( p_cdda_input, message);
109     break;
110   case CDIO_LOG_WARN:
111     msg_Warn( p_cdda_input, message);
112     break;
113   case CDIO_LOG_ERROR:
114   case CDIO_LOG_ASSERT:
115     msg_Err( p_cdda_input, message);
116     break;
117   default:
118     msg_Warn( p_cdda_input, message,
119             _("The above message had unknown cdio log level"),
120             level);
121   }
122   return;
123 }
124
125
126 #ifdef HAVE_LIBCDDB
127 /*! This routine is called by libcddb routines on error.
128    Setup is done by init_input_plugin.
129 */
130 static void
131 cddb_log_handler (cddb_log_level_t level, const char message[])
132 {
133   cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
134   switch (level) {
135   case CDDB_LOG_DEBUG:
136   case CDDB_LOG_INFO:
137     if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
138     /* Fall through if to warn case */
139   default:
140     cdio_log_handler (level, message);
141   }
142 }
143 #endif /*HAVE_LIBCDDB*/
144
145
146 /*! This routine is when xine is not fully set up (before full initialization)
147    or is not around (before finalization).
148 */
149 static void
150 uninit_log_handler (cdio_log_level_t level, const char message[])
151 {
152   cdda_data_t *p_cdda = NULL;
153
154   if (p_cdda_input)
155     p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
156
157   switch (level) {
158   case CDIO_LOG_DEBUG:
159   case CDIO_LOG_INFO:
160     if (!p_cdda || !(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
161       return;
162     /* Fall through if to warn case */
163   case CDIO_LOG_WARN:
164     fprintf(stderr, "WARN: %s\n", message);
165     break;
166   case CDIO_LOG_ERROR:
167     fprintf(stderr, "ERROR: %s\n", message);
168     break;
169   case CDIO_LOG_ASSERT:
170     fprintf(stderr, "ASSERT ERROR: %s\n", message);
171     break;
172   default:
173     fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
174             message,
175             _("The above message had unknown cdio log level"),
176             level);
177   }
178
179   /* gl_default_cdio_log_handler (level, message); */
180 }
181
182 /*****************************************************************************
183  * CDDARead: reads CDDA_BLOCKS_ONCE from the CD-DA and returns an
184  * allocated pointer to the data. NULL is returned if no data read. It
185  * is also possible if we haven't read a RIFF header in which case one 
186  * that we creaded during Open/Initialization is returned.
187  *****************************************************************************/
188 static block_t *
189 CDDABlock( access_t * p_access )
190 {
191     block_t     *p_block;
192     cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
193     int          i_blocks = CDDA_BLOCKS_ONCE;
194
195     dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called %d", 
196               p_cdda->i_lsn);
197
198     /* Check end of file */
199     if( p_access->info.b_eof ) return NULL;
200
201     if( !p_cdda->b_header )
202       {
203         /* Return only the dummy RIFF header we created in Open/Init */
204         p_block = block_New( p_access, sizeof( WAVEHEADER ) );
205         memcpy( p_block->p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
206         p_cdda->b_header = VLC_TRUE;
207         return p_block;
208     }
209
210     /* Check end of track */
211     while( p_cdda->i_lsn >= p_cdda->p_lsns[p_access->info.i_title + 1] )
212     {
213         if( p_access->info.i_title + 1 >= p_cdda->i_tracks )
214         {
215             p_access->info.b_eof = VLC_TRUE;
216             return NULL;
217         }
218
219         p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE;
220         p_access->info.i_title++;
221         p_access->info.i_size = 
222           p_cdda->p_title[p_access->info.i_title]->i_size;
223         p_access->info.i_pos = 0;
224         p_cdda->i_track++;
225     }
226
227     /* Don't read after the end of a title */
228     if( p_cdda->i_lsn + i_blocks >=
229         p_cdda->p_lsns[p_access->info.i_title + 1] )
230     {
231         i_blocks = p_cdda->p_lsns[p_access->info.i_title + 1 ] -
232                    p_cdda->i_lsn;
233     }
234
235     /* Do the actual reading */
236     p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW );
237     if( !p_block)
238     {
239         msg_Err( p_access, "cannot get a new block of size: %i",
240                  i_blocks * CDIO_CD_FRAMESIZE_RAW );
241         return NULL;
242     }
243
244     if( cdio_read_audio_sectors( p_cdda->p_cdio, p_block->p_buffer,
245                                  p_cdda->i_lsn, i_blocks) != 0 )
246         {
247             msg_Err( p_access, "could not read sector %lu", 
248                      (long unsigned int) p_cdda->i_lsn );
249             block_Release( p_block );
250
251             /* If we had problems above, assume the problem is with
252                the first sector of the read and set to skip it.  In
253                the future libcdio may have cdparanoia support.
254              */
255             p_cdda->i_lsn++;
256             p_access->info.i_pos += CDIO_CD_FRAMESIZE_RAW;
257             return NULL;
258         }
259
260     p_cdda->i_lsn     += i_blocks;
261     p_access->info.i_pos += p_block->i_buffer;
262
263     return p_block;
264 }
265
266 /****************************************************************************
267  * CDDASeek - change position for subsequent reads. For example, this
268  * can happen if the user moves a position slider bar in a GUI.
269  ****************************************************************************/
270 static int 
271 CDDASeek( access_t * p_access, int64_t i_pos )
272 {
273     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
274
275     p_cdda->i_lsn = p_cdda->p_lsns[p_access->info.i_title]
276                        + i_pos / CDIO_CD_FRAMESIZE_RAW;
277     p_access->info.i_pos = i_pos;
278
279     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
280                "lsn %lu, offset: %lld",  
281                (long unsigned int) p_cdda->i_lsn, i_pos );
282     return VLC_SUCCESS;
283 }
284
285 #ifdef HAVE_LIBCDDB
286
287 #define free_and_dup(var, val) \
288   if (var) free(var);          \
289   if (val) var=strdup(val);
290
291
292 static void
293 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
294 {
295
296   dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
297
298   if (config_GetInt( p_access, MODULE_STRING "-cddb-enabled" )) {
299     int i, i_matches;
300     cddb_conn_t  *conn = cddb_new();
301     const CdIo *p_cdio = p_cdda->p_cdio;
302
303
304     cddb_log_set_handler (uninit_log_handler);
305
306     if (!conn) {
307       msg_Warn( p_access, _("Unable to initialize libcddb") );
308       goto cddb_destroy;
309     }
310
311     cddb_set_email_address( conn,
312                             config_GetPsz( p_access,
313                                            MODULE_STRING "-cddb-email") );
314
315     cddb_set_server_name( conn,
316                           config_GetPsz( p_access,
317                                          MODULE_STRING "-cddb-server") );
318
319     cddb_set_server_port(conn,
320                           config_GetInt( p_access,
321                                          MODULE_STRING "-cddb-port") );
322
323     /* Set the location of the local CDDB cache directory.
324        The default location of this directory is */
325
326     if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
327       cddb_cache_disable(conn);
328
329     cddb_cache_set_dir(conn,
330                        config_GetPsz( p_access,
331                                       MODULE_STRING "-cddb-cachedir") );
332
333     cddb_set_timeout(conn,
334                      config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
335
336
337     if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" )) {
338       cddb_http_enable(conn);
339     } else
340       cddb_http_disable(conn);
341
342     p_cdda->cddb.disc = cddb_disc_new();
343     if (!p_cdda->cddb.disc) {
344       msg_Err( p_access, _("Unable to create CDDB disc structure.") );
345       goto cddb_end;
346     }
347
348     p_cdda->psz_mcn = cdio_get_mcn(p_cdio);
349
350     for(i = 1; i <= p_cdda->i_tracks; i++) {
351       cddb_track_t *t = cddb_track_new();
352       t->frame_offset = cdio_get_track_lba(p_cdio, i);
353       cddb_disc_add_track(p_cdda->cddb.disc, t);
354     }
355
356     p_cdda->cddb.disc->length =
357       cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
358       / CDIO_CD_FRAMES_PER_SEC;
359
360     if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
361       msg_Err( p_access, _("CDDB disc ID calculation failed") );
362       goto cddb_destroy;
363     }
364
365     i_matches = cddb_query(conn, p_cdda->cddb.disc);
366     if (i_matches > 0) {
367       if (i_matches > 1)
368         msg_Warn( p_access, _("Found %d matches in CDDB. Using first one."),
369                   i_matches);
370       cddb_read(conn, p_cdda->cddb.disc);
371
372       if (p_cdda->i_debug & INPUT_DBG_CDDB)
373         cddb_disc_print(p_cdda->cddb.disc);
374
375     } else {
376       msg_Warn( p_access, _("CDDB error: %s"), cddb_error_str(errno));
377     }
378
379   cddb_destroy:
380     cddb_destroy(conn);
381   }
382   cddb_end: ;
383 }
384 #endif /*HAVE_LIBCDDB*/
385
386 #define add_meta_val(FIELD, VLC_META, VAL)                              \
387   if ( p_cdda->p_meta && VAL) {                                         \
388     vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL );                      \
389     dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL );       \
390   }                                                                     \
391     
392 #define add_cddb_meta(FIELD, VLC_META)                                  \
393   add_meta_val(FIELD, VLC_META, p_cdda->cddb.disc->FIELD);
394     
395 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META)                 \
396   {                                                                     \
397     char psz_buf[100];                                                  \
398     snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC,                  \
399               p_cdda->cddb.disc->FIELD );                               \
400     psz_buf[sizeof(psz_buf)-1] = '\0';                                  \
401     add_meta_val(FIELD, VLC_META, psz_buf);                             \
402   }    
403
404 /*
405  Gets and saves CDDA Meta Information. In the Control routine, 
406  we handle Meta Information requests and basically copy what we've
407  saved here. 
408  */    
409 static void CDDAMetaInfo( access_t *p_access  )
410 {
411   cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
412
413 #ifdef HAVE_LIBCDDB
414   if ( p_cdda && p_cdda->i_cddb_enabled ) {
415
416     GetCDDBInfo(p_access, p_cdda);
417
418     if ( p_cdda->cddb.disc ) {
419
420       p_cdda->p_meta = vlc_meta_New();
421
422       add_cddb_meta(title,    VLC_META_CDDB_TITLE);
423       add_cddb_meta(artist,   VLC_META_CDDB_ARTIST);
424       add_cddb_meta(genre,    VLC_META_CDDB_GENRE);
425       add_cddb_meta(ext_data, VLC_META_CDDB_EXT_DATA);
426
427       add_cddb_meta_fmt(year,   "%d", VLC_META_CDDB_YEAR);
428       add_cddb_meta_fmt(discid, "%x", VLC_META_CDDB_DISCID);
429     }
430   }
431
432 #endif /*HAVE_LIBCDDB*/
433 #define TITLE_MAX 30
434
435 #if UPDATE_TRACK_INFORMATION_FINISHED
436   {
437     track_t i_track = p_cdda->i_tracks;
438     char psz_buffer[MSTRTIME_MAX_SIZE];
439     mtime_t i_duration =
440       (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[0])
441       / CDIO_CD_FRAMES_PER_SEC;
442
443     dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
444     input_Control( p_access, INPUT_ADD_INFO, _("General"), _("Duration"), "%s",
445                    secstotimestr( psz_buffer, i_duration ) );
446
447     for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ ) {
448       char track_str[TITLE_MAX];
449       mtime_t i_duration =
450         (p_cdda->p_lsns[i_track+1] - p_cdda->p_lsns[i_track])
451         / CDIO_CD_FRAMES_PER_SEC;
452       snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
453       input_Control( p_access, INPUT_ADD_INFO, track_str, _("Duration"), "%s",
454                      secstotimestr( psz_buffer, i_duration ) );
455
456 #ifdef HAVE_LIBCDDB
457       if (p_cdda->i_cddb_enabled) {
458         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
459                                             i_track);
460         if (t != NULL) {
461           if ( t->artist != NULL && strlen(t->artist) ) {
462             input_Control( p_access, INPUT_ADD_INFO, track_str,
463                            _("Artist"), "%s", t->artist );
464           }
465           if ( t->title != NULL && strlen(t->title) ) {
466             input_Control( p_access, INPUT_ADD_INFO, track_str,
467                            _("Title"), "%s",  t->title );
468           }
469           if ( t->ext_data != NULL && strlen(t->ext_data) ) {
470             input_Control( p_access, INPUT_ADD_INFO, track_str,
471                            _("Extended Data"), "%s",  t->ext_data );
472           }
473         }
474       }
475 #endif /*HAVE_LIBCDDB*/
476     }
477   }
478 #endif /* UPDATE_TRACK_INFORMATION_FINISHED */
479 }
480
481 #define add_format_str_info(val)                         \
482   {                                                      \
483     const char *str = val;                               \
484     unsigned int len;                                    \
485     if (val != NULL) {                                   \
486       len=strlen(str);                                   \
487       if (len != 0) {                                    \
488         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    \
489         tp += len;                                       \
490       }                                                  \
491       saw_control_prefix = false;                        \
492     }                                                    \
493   }
494
495 #define add_format_num_info(val, fmt)                    \
496   {                                                      \
497     char num_str[10];                                    \
498     unsigned int len;                                    \
499     sprintf(num_str, fmt, val);                          \
500     len=strlen(num_str);                                 \
501     if (len != 0) {                                      \
502       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  \
503       tp += len;                                         \
504     }                                                    \
505     saw_control_prefix = false;                          \
506   }
507
508 /*!
509    Take a format string and expand escape sequences, that is sequences that
510    begin with %, with information from the current CD.
511    The expanded string is returned. Here is a list of escape sequences:
512
513    %a : The album artist **
514    %A : The album information **
515    %C : Category **
516    %I : CDDB disk ID **
517    %G : Genre **
518    %M : The current MRL
519    %m : The CD-DA Media Catalog Number (MCN)
520    %n : The number of tracks on the CD
521    %p : The artist/performer/composer in the track **
522    %T : The track number **
523    %s : Number of seconds in this track
524    %t : The name **
525    %Y : The year 19xx or 20xx **
526    %% : a %
527 */
528 static char *
529 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
530                const char format_str[], const char *mrl, int i_track)
531 {
532 #define TEMP_STR_SIZE 256
533 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
534   static char    temp_str[TEMP_STR_SIZE];
535   size_t i;
536   char * tp = temp_str;
537   vlc_bool_t saw_control_prefix = false;
538   size_t format_len = strlen(format_str);
539
540   memset(temp_str, 0, TEMP_STR_SIZE);
541
542   for (i=0; i<format_len; i++) {
543
544     if (!saw_control_prefix && format_str[i] != '%') {
545       *tp++ = format_str[i];
546       saw_control_prefix = false;
547       continue;
548     }
549
550     switch(format_str[i]) {
551     case '%':
552       if (saw_control_prefix) {
553         *tp++ = '%';
554       }
555       saw_control_prefix = !saw_control_prefix;
556       break;
557 #ifdef HAVE_LIBCDDB
558     case 'a':
559       if (!p_cdda->i_cddb_enabled) goto not_special;
560       if (p_cdda->cddb.disc)
561         add_format_str_info(p_cdda->cddb.disc->artist);
562       break;
563     case 'A':
564       if (!p_cdda->i_cddb_enabled) goto not_special;
565       if (p_cdda->cddb.disc)
566         add_format_str_info(p_cdda->cddb.disc->title);
567       break;
568     case 'C':
569       if (!p_cdda->i_cddb_enabled) goto not_special;
570       if (p_cdda->cddb.disc)
571         add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
572       break;
573     case 'G':
574       if (!p_cdda->i_cddb_enabled) goto not_special;
575       if (p_cdda->cddb.disc)
576         add_format_str_info(p_cdda->cddb.disc->genre);
577       break;
578     case 'I':
579       if (!p_cdda->i_cddb_enabled) goto not_special;
580       if (p_cdda->cddb.disc)
581         add_format_num_info(p_cdda->cddb.disc->discid, "%x");
582       break;
583     case 'Y':
584       if (!p_cdda->i_cddb_enabled) goto not_special;
585       if (p_cdda->cddb.disc)
586         add_format_num_info(p_cdda->cddb.disc->year, "%5d");
587       break;
588     case 't':
589       if (p_cdda && p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
590         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
591                                             i_track-1);
592         if (t != NULL && t->title != NULL)
593           add_format_str_info(t->title);
594       } else goto not_special;
595       break;
596     case 'p':
597       if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
598         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
599                                             i_track-1);
600         if (t != NULL && t->artist != NULL)
601           add_format_str_info(t->artist);
602       } else goto not_special;
603       break;
604     case 'e':
605       if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
606         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
607                                             i_track-1);
608         if (t != NULL && t->ext_data != NULL)
609           add_format_str_info(t->ext_data);
610       } else goto not_special;
611       break;
612 #endif
613
614     case 'M':
615       add_format_str_info(mrl);
616       break;
617
618     case 'm':
619       add_format_str_info(p_cdda->psz_mcn);
620       break;
621
622     case 'n':
623       add_format_num_info(p_cdda->i_tracks, "%d");
624       break;
625
626     case 's':
627       if (p_cdda->i_cddb_enabled) {
628         char psz_buffer[MSTRTIME_MAX_SIZE];
629         mtime_t i_duration =
630           (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
631           / CDIO_CD_FRAMES_PER_SEC;
632         add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
633       } else goto not_special;
634       break;
635
636     case 'T':
637       add_format_num_info(i_track, "%02d");
638       break;
639 #ifdef HAVE_LIBCDDB
640     not_special:
641 #endif
642     default:
643       *tp++ = '%';
644       *tp++ = format_str[i];
645       saw_control_prefix = false;
646     }
647   }
648   return strdup(temp_str);
649 }
650
651 static void
652 CDDACreatePlaylistItem(const access_t *p_access, cdda_data_t *p_cdda,
653                        playlist_t *p_playlist, track_t i_track,
654                        char *psz_mrl, int psz_mrl_max,
655                        const char *psz_source, int playlist_operation,
656                        int i_pos)
657 {
658   mtime_t i_duration =
659     (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
660     * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
661   char *p_author;
662   char *p_title;
663   char *config_varname = MODULE_STRING "-title-format";
664   playlist_item_t *p_item;
665
666 #ifdef HAVE_LIBCDDB
667   if (p_cdda->i_cddb_enabled) {
668     config_varname = MODULE_STRING "-cddb-title-format";
669   }
670 #endif /*HAVE_LIBCDDB*/
671
672   snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
673            CDDA_MRL_PREFIX, psz_source, i_track);
674
675   p_title = CDDAFormatStr(p_access, p_cdda,
676                           config_GetPsz( p_access, config_varname ),
677                           psz_mrl, i_track);
678
679   dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
680              psz_mrl, p_title, (long int) i_duration / 1000000 , i_pos );
681   playlist_AddExt( p_playlist, psz_mrl, p_title, playlist_operation,
682                          i_pos, i_duration , NULL, 0);
683
684   if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
685
686   vlc_mutex_lock( &p_playlist->object_lock );
687   p_item = playlist_ItemGetByPos( p_playlist, i_pos );
688   vlc_mutex_unlock( &p_playlist->object_lock );
689   if( !p_item )
690       return;
691
692   vlc_mutex_lock( &p_item->input.lock );
693
694   p_author =
695     CDDAFormatStr( p_access, p_cdda,
696                    config_GetPsz( p_access, MODULE_STRING "-author-format" ),
697                    psz_mrl, i_track );
698
699   playlist_ItemAddInfo( p_item ,  _("General"),_("Author"), p_author);
700
701 #ifdef HAVE_LIBCDDB
702   if (p_cdda->i_cddb_enabled) {
703     const char *psz_general_cat = _("General");
704
705     playlist_ItemAddInfo( p_item, psz_general_cat, _("Album"),
706                       "%s", p_cdda->cddb.disc->title);
707     playlist_ItemAddInfo( p_item, psz_general_cat, _("Disc Artist(s)"),
708                       "%s", p_cdda->cddb.disc->artist);
709     playlist_ItemAddInfo( p_item, psz_general_cat,
710                         _("CDDB Disc Category"),
711                       "%s", CDDB_CATEGORY[p_cdda->cddb.disc->category]);
712     playlist_ItemAddInfo( p_item, psz_general_cat, _("Genre"),
713                       "%s", p_cdda->cddb.disc->genre);
714     if ( p_cdda->cddb.disc->discid ) {
715       playlist_ItemAddInfo( p_item, psz_general_cat, _("CDDB Disc ID"),
716                         "%x", p_cdda->cddb.disc->discid );
717     }
718     if (p_cdda->cddb.disc->year != 0) {
719       playlist_ItemAddInfo( p_item, psz_general_cat,
720                         _("Year"), "%5d", p_cdda->cddb.disc->year );
721     }
722
723     if (p_cdda->i_cddb_enabled) {
724       cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
725                                           i_track-1);
726       if (t != NULL && t->artist != NULL) {
727         playlist_ItemAddInfo( p_item, psz_general_cat,
728                           _("Track Artist"), "%s", t->artist );
729         playlist_ItemAddInfo( p_item , psz_general_cat,
730                           _("Track Title"), "%s",  t->title );
731       }
732     }
733
734   }
735 #endif /*HAVE_LIBCDDB*/
736
737   vlc_mutex_unlock( &p_item->input.lock );
738 }
739
740 static int
741 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda, 
742                    const char *psz_source, vlc_bool_t b_single_track )
743 {
744   int i;
745   playlist_t * p_playlist;
746   char       * psz_mrl;
747   unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
748     strlen("@T") + strlen("100") + 1;
749
750 #ifdef HAVE_LIBCDDB
751   p_cdda->i_cddb_enabled =
752     config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
753   if( b_single_track && !p_cdda->i_cddb_enabled ) return 0;
754 #else
755   if( b_single_track ) return VLC_SUCCESS;
756 #endif
757
758   psz_mrl = malloc( psz_mrl_max );
759
760   if( psz_mrl == NULL )
761     {
762       msg_Warn( p_access, "out of memory" );
763       return VLC_ENOMEM;
764     }
765
766   p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
767                                                FIND_ANYWHERE );
768   if( !p_playlist )
769     {
770       msg_Warn( p_access, "can't find playlist" );
771       free(psz_mrl);
772       return VLC_EGENERIC;
773     }
774
775   CDDAMetaInfo(p_access);
776
777   if (b_single_track) {
778     /* May fill out more information when the playlist user interface becomes
779        more mature.
780      */
781     CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, p_cdda->i_track,
782                            psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
783                            p_playlist->i_index);
784   } else {
785
786     for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
787       {
788         input_title_t *t = p_cdda->p_title[i-1] = vlc_input_title_New();
789         
790         asprintf( &t->psz_name, _("Track %i"), i );
791         t->i_size = ( p_cdda->p_lsns[i] - p_cdda->p_lsns[i-1] ) *
792           (int64_t)CDIO_CD_FRAMESIZE_RAW;
793         
794         t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
795         CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i, psz_mrl,
796                                psz_mrl_max, psz_source, PLAYLIST_APPEND,
797                                PLAYLIST_END);
798       }
799   }
800
801   return VLC_SUCCESS;
802 }
803
804 /****************************************************************************
805  * Public functions
806  ****************************************************************************/
807 int
808 E_(CDDADebugCB)   ( vlc_object_t *p_this, const char *psz_name,
809                     vlc_value_t oldval, vlc_value_t val, void *p_data )
810 {
811   cdda_data_t *p_cdda;
812
813   if (NULL == p_cdda_input) return VLC_EGENERIC;
814
815   p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
816
817   if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
818     msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
819              p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
820   }
821   p_cdda->i_debug = val.i_int;
822   return VLC_SUCCESS;
823 }
824
825 int
826 E_(CDDBEnabledCB)   ( vlc_object_t *p_this, const char *psz_name,
827                       vlc_value_t oldval, vlc_value_t val, void *p_data )
828 {
829   cdda_data_t *p_cdda;
830
831   if (NULL == p_cdda_input) return VLC_EGENERIC;
832
833   p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
834
835 #ifdef HAVE_LIBCDDB
836   if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
837     msg_Dbg( p_cdda_input, "Old CDDB Enabled (x%0x) %d, new (x%0x) %d",
838              p_cdda->i_cddb_enabled, p_cdda->i_cddb_enabled,
839              val.i_int, val.i_int);
840   }
841   p_cdda->i_cddb_enabled = val.i_int;
842 #endif
843   return VLC_SUCCESS;
844 }
845
846 /*****************************************************************************
847  * Open: open cdda device or image file and initialize structures 
848  * for subsequent operations.
849  *****************************************************************************/
850 int
851 E_(CDDAOpen)( vlc_object_t *p_this )
852 {
853     access_t    *p_access = (access_t*)p_this;
854     char *      psz_source = NULL;
855     cdda_data_t *p_cdda;
856     CdIo        *p_cdio;
857     track_t     i_track = 1;
858     vlc_bool_t  b_single_track = false;
859     int         i_rc = VLC_EGENERIC;
860
861     /* Set where to log errors messages from libcdio. */
862     p_cdda_input = p_access;
863
864     /* parse the options passed in command line : */
865
866     if( p_access->psz_path && *p_access->psz_path )
867     {
868       char *psz_parser = psz_source = strdup( p_access->psz_path );
869
870       while( *psz_parser && *psz_parser != '@' )
871         {
872           psz_parser++;
873         }
874       
875       if( *psz_parser == '@' )
876         {
877           /* Found options */
878           *psz_parser = '\0';
879           ++psz_parser;
880           
881           if ('T' == *psz_parser || 't' == *psz_parser )
882             ++psz_parser;
883           
884           i_track = (int)strtol( psz_parser, NULL, 10 );
885           i_track = i_track ? i_track : 1;
886           b_single_track = true;
887         }
888     } else {
889
890         /* No device/track given. Continue only when this plugin was 
891            selected */
892         if( !p_this->b_force ) return VLC_EGENERIC;
893
894         psz_source = var_CreateGetString( p_this, "cd-audio" );
895
896         if( !psz_source || !*psz_source ) {
897         /* Scan for a CD-ROM drive with a CD-DA in it. */
898         char **cd_drives =
899           cdio_get_devices_with_cap(NULL,  CDIO_FS_AUDIO, false);
900
901         if (NULL == cd_drives || NULL == cd_drives[0] ) {
902           msg_Err( p_access, 
903                    _("libcdio couldn't find something with a CD-DA in it") );
904           if (cd_drives) cdio_free_device_list(cd_drives);
905           return VLC_EGENERIC;
906         }
907         
908         psz_source = strdup(cd_drives[0]);
909         cdio_free_device_list(cd_drives);
910       }
911     }
912
913     cdio_log_set_handler ( cdio_log_handler );
914
915     /* Open CDDA */
916     if( !(p_cdio = cdio_open( psz_source, DRIVER_UNKNOWN )) )
917     {
918         msg_Warn( p_access, "could not open %s", psz_source );
919         goto error2;
920     }
921
922     p_cdda = malloc( sizeof(cdda_data_t) );
923     if( p_cdda == NULL )
924     {
925         msg_Err( p_access, "out of memory" );
926         free( psz_source );
927         return VLC_ENOMEM;
928     }
929     memset( p_cdda, 0, sizeof(cdda_data_t) );
930
931 #ifdef HAVE_LIBCDDB
932     cddb_log_set_handler ( cddb_log_handler );
933     p_cdda->cddb.disc = NULL;
934     p_cdda->i_cddb_enabled =
935       config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
936 #endif
937
938     p_cdda->b_header = VLC_FALSE;
939     p_cdda->p_cdio   = p_cdio;
940     p_cdda->i_track  = i_track;
941     p_cdda->i_debug  = config_GetInt( p_this, MODULE_STRING "-debug" );
942
943     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
944
945     /* Set up p_access */
946     p_access->pf_read    = NULL;
947     p_access->pf_block   = CDDABlock;
948     p_access->pf_control = CDDAControl;
949     p_access->pf_seek    = CDDASeek;
950
951     p_access->info.i_update    = 0;
952     p_access->info.i_size      = 0;
953     p_access->info.i_pos       = 0;
954     p_access->info.b_eof       = VLC_FALSE;
955     p_access->info.i_title     = 0;
956     p_access->info.i_seekpoint = 0;
957
958     p_access->p_sys     = (access_sys_t *) p_cdda;
959
960     /* We read the Table Of Content information */
961     i_rc = GetCDInfo( p_access, p_cdda );
962     if ( VLC_SUCCESS != i_rc ) goto error;
963
964     CDDAFixupPlaylist( p_access, p_cdda, psz_source, b_single_track );
965     
966     /* Build a WAV header to put in front of the output data. 
967        This gets sent back in the Block (read) routine.
968      */
969     memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
970     SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
971     SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
972     p_cdda->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
973     p_cdda->waveheader.Length = 0;                     /* we just don't know */
974     p_cdda->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
975     p_cdda->waveheader.SubChunkID  = VLC_FOURCC('f', 'm', 't', ' ');
976     SetDWLE( &p_cdda->waveheader.SubChunkLength, 16);
977     SetWLE( &p_cdda->waveheader.Modus, 2);
978     SetDWLE( &p_cdda->waveheader.SampleFreq, CDDA_FREQUENCY_SAMPLE);
979     SetWLE( &p_cdda->waveheader.BytesPerSample,
980             2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
981     SetDWLE( &p_cdda->waveheader.BytesPerSec,
982              2*16/8 /*BytesPerSample*/ * CDDA_FREQUENCY_SAMPLE );
983     p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
984     p_cdda->waveheader.DataLength  = 0;    /* we just don't know */
985
986     /* PTS delay */
987     var_Create( p_access, MODULE_STRING "-caching", 
988                 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
989     return VLC_SUCCESS;
990
991  error:
992     cdio_destroy( p_cdda->p_cdio );
993     free( p_cdda );
994  error2:
995     free( psz_source );
996     return i_rc;
997
998 }
999
1000 /*****************************************************************************
1001  * CDDAClose: closes cdda and frees any resources associded with it.
1002  *****************************************************************************/
1003 void
1004 E_(CDDAClose)( vlc_object_t *p_this )
1005 {
1006     access_t    *p_access = (access_t *) p_this;
1007     cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
1008     track_t      i;
1009
1010     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
1011
1012     /* Remove playlist titles */
1013     for( i = 0; i < p_cdda->i_tracks; i++ )
1014     {
1015         vlc_input_title_Delete( p_cdda->p_title[i] );
1016     }
1017
1018     cdio_destroy( p_cdda->p_cdio );
1019
1020     cdio_log_set_handler (uninit_log_handler);
1021
1022 #ifdef HAVE_LIBCDDB
1023     cddb_log_set_handler (uninit_log_handler);
1024     if (p_cdda->i_cddb_enabled)
1025       cddb_disc_destroy(p_cdda->cddb.disc);
1026 #endif
1027
1028     free( p_cdda->p_lsns );
1029     if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
1030     free( p_cdda );
1031     p_cdda_input = NULL;
1032 }
1033
1034 /*****************************************************************************
1035  * Control: The front-end or vlc engine calls here to ether get
1036  * information such as meta information or plugin capabilities or to
1037  * issue miscellaneous "set" requests.
1038  *****************************************************************************/
1039 static int CDDAControl( access_t *p_access, int i_query, va_list args )
1040 {
1041     cdda_data_t  *p_cdda = (cdda_data_t *) p_access->p_sys;
1042     int          *pi_int;
1043     int i;
1044
1045     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
1046                "query %d", i_query );
1047
1048     switch( i_query )
1049     {
1050         /* Pass back a copy of meta information that was gathered when we
1051            during the Open/Initialize call.
1052          */
1053         case ACCESS_GET_META:
1054           { 
1055             vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
1056             if ( p_cdda->p_meta ) {
1057               *pp_meta = vlc_meta_Duplicate( p_cdda->p_meta );
1058               dbg_print( INPUT_DBG_META, "%s", _("Meta copied") );
1059             } else 
1060               msg_Warn( p_access, _("Tried to copy NULL meta info") );
1061             
1062             return VLC_SUCCESS;
1063           }
1064           return VLC_EGENERIC;
1065
1066         case ACCESS_CAN_SEEK:
1067         case ACCESS_CAN_FASTSEEK:
1068         case ACCESS_CAN_PAUSE:
1069         case ACCESS_CAN_CONTROL_PACE: 
1070           {
1071             vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
1072             *pb_bool = VLC_TRUE;
1073             break;
1074           }
1075
1076         /* */
1077         case ACCESS_GET_MTU:
1078             pi_int = (int*)va_arg( args, int * );
1079             *pi_int = CDDA_DATA_ONCE;
1080             break;
1081
1082         case ACCESS_GET_PTS_DELAY:
1083           { 
1084             int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
1085             *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
1086               * MILLISECONDS_PER_SEC;
1087             break;
1088           }
1089
1090         /* */
1091         case ACCESS_SET_PAUSE_STATE:
1092             break;
1093
1094         case ACCESS_GET_TITLE_INFO:
1095           { input_title_t ***ppp_title;
1096             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
1097             pi_int    = (int*)va_arg( args, int* );
1098             *((int*)va_arg( args, int* )) = 1; /* Title offset */
1099
1100             /* Duplicate track info */
1101             *pi_int = p_cdda->i_tracks;
1102             *ppp_title = malloc(sizeof( input_title_t **) * p_cdda->i_tracks );
1103
1104             if (!*ppp_title) return VLC_ENOMEM;
1105
1106             for( i = 0; i < p_cdda->i_tracks; i++ )
1107             {
1108               if ( p_cdda->p_title[i] )
1109                 (*ppp_title)[i] = 
1110                   vlc_input_title_Duplicate( p_cdda->p_title[i] );
1111             }
1112           }
1113           break;
1114
1115         case ACCESS_SET_TITLE:
1116             i = (int)va_arg( args, int );
1117             if( i != p_access->info.i_title )
1118             {
1119                 /* Update info */
1120                 p_access->info.i_update |=
1121                     INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1122                 p_access->info.i_title = i;
1123                 p_access->info.i_size = p_cdda->p_title[i]->i_size;
1124                 p_access->info.i_pos = 0;
1125
1126                 /* Next sector to read */
1127                 p_cdda->i_lsn = p_cdda->p_lsns[i];
1128             }
1129             break;
1130
1131         case ACCESS_SET_SEEKPOINT:
1132         case ACCESS_SET_PRIVATE_ID_STATE:
1133             return VLC_EGENERIC;
1134         default:
1135           msg_Warn( p_access, _("unimplemented query in control") );
1136             return VLC_EGENERIC;
1137
1138     }
1139     return VLC_SUCCESS;
1140 }
1141
1142 /*****************************************************************************
1143   GetCDInfo: 
1144
1145  Initialize information pertaining to the CD: the number of tracks,
1146  first track number, LSNs for each track and the leadout. The leadout
1147  information is stored after the last track. The LSN array is
1148  0-origin, same as p_access->info.  Add first_track to get what track
1149  number this is on the CD. Note: libcdio uses the real track number.
1150
1151  We return the VLC-type status, e.g. VLC_SUCCESS, VLC_ENOMEM, etc.
1152  *****************************************************************************/
1153 static int
1154 GetCDInfo( access_t *p_access, cdda_data_t *p_cdda ) 
1155 {
1156     track_t i;
1157     discmode_t  discmode = CDIO_DISC_MODE_NO_INFO;
1158
1159     p_cdda->i_tracks       = cdio_get_num_tracks(p_cdda->p_cdio);
1160     p_cdda->i_first_track  = cdio_get_first_track_num(p_cdda->p_cdio);
1161
1162     discmode = cdio_get_discmode(p_cdda->p_cdio);
1163     switch(discmode) {
1164     case CDIO_DISC_MODE_CD_DA:
1165     case CDIO_DISC_MODE_CD_MIXED:
1166       /* These are possible for CD-DA */
1167       break;
1168     default:
1169       /* These are not possible for CD-DA */
1170       msg_Err( p_access, 
1171                _("Disc seems not to be CD-DA. libcdio reports it is %s"),
1172                discmode2str[discmode]
1173                );
1174       return VLC_EGENERIC;
1175     }
1176     
1177     p_cdda->p_lsns = malloc( (p_cdda->i_tracks + 1) * sizeof(lsn_t) );
1178
1179     if( p_cdda->p_lsns == NULL )
1180       {
1181         msg_Err( p_access, "out of memory" );
1182         return VLC_ENOMEM;
1183       }
1184
1185     
1186
1187     /* Fill the p_lsns structure with the track/sector matches.
1188        Note cdio_get_track_lsn when given num_tracks + 1 will return
1189        the leadout LSN.
1190      */
1191     for( i = 0 ; i <= p_cdda->i_tracks ; i++ )
1192       {
1193         (p_cdda->p_lsns)[ i ] = 
1194           cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_first_track+i);
1195       }
1196     
1197     return VLC_SUCCESS;
1198 }