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