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