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