]> git.sesse.net Git - vlc/blob - modules/access/cddax.c
New spanish translation, by Antonio Javier Varela.
[vlc] / modules / access / cddax.c
1 /*****************************************************************************
2  * cddax.c : CD digital audio input module for vlc using libcdio
3  *****************************************************************************
4  * Copyright (C) 2000 VideoLAN
5  * $Id: cddax.c,v 1.3 2003/10/05 14:51:47 rocky Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Gildas Bazin <gbazin@netcourrier.com>
9  *          Rocky Bernstein <rocky@panix.com> 
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/input.h>
34 #include <sys/types.h>
35 #include <cdio/cdio.h>
36 #include <cdio/cd_types.h>
37
38 #include "codecs.h"
39
40 #ifdef HAVE_UNISTD_H
41 #   include <unistd.h>
42 #endif
43
44 #include <string.h>
45
46 #include "vcdx/cdrom.h"
47
48 /* how many blocks CDDAOpen will read in each loop */
49 #define CDDA_BLOCKS_ONCE 1
50 #define CDDA_DATA_ONCE   (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW)
51
52 /*****************************************************************************
53  * cdda_data_t: CD audio information
54  *****************************************************************************/
55 typedef struct cdda_data_s
56 {
57     cddev_t     *p_cddev;                           /* CD device descriptor */
58     int         i_nb_tracks;                        /* Nb of tracks (titles) */
59     int         i_track;                                    /* Current track */
60     lsn_t       i_sector;                                  /* Current Sector */
61     lsn_t *     p_sectors;                                  /* Track sectors */
62     vlc_bool_t  b_end_of_track;           /* If the end of track was reached */
63     int         i_debug;                  /* Debugging mask */
64
65 } cdda_data_t;
66
67 struct demux_sys_t
68 {
69     es_descriptor_t *p_es;
70     mtime_t         i_pts;
71 };
72
73 /*****************************************************************************
74  * Debugging 
75  *****************************************************************************/
76 #define INPUT_DBG_MRL         1 
77 #define INPUT_DBG_EXT         2 /* Calls from external routines */
78 #define INPUT_DBG_CALL        4 /* all calls */
79 #define INPUT_DBG_LSN         8 /* LSN changes */
80 #define INPUT_DBG_CDIO       16 /* Debugging from CDIO */
81 #define INPUT_DBG_SEEK       32 /* Seeks to set location */
82
83 #define DEBUG_TEXT N_("set debug mask for additional debugging.")
84 #define DEBUG_LONGTEXT N_( \
85     "This integer when viewed in binary is a debugging mask\n" \
86     "MRL             1\n" \
87     "external call   2\n" \
88     "all calls       4\n" \
89     "LSN             8\n" \
90     "libcdio  (10)  16\n" \
91     "seeks    (20)  32\n" )
92
93 #define INPUT_DEBUG 1
94 #if INPUT_DEBUG
95 #define dbg_print(mask, s, args...) \
96    if (p_cdda->i_debug & mask) \
97      msg_Dbg(p_input, "%s: "s, __func__ , ##args)
98 #else
99 #define dbg_print(mask, s, args...) 
100 #endif
101
102 /*****************************************************************************
103  * Local prototypes
104  *****************************************************************************/
105 static int  CDDAOpen         ( vlc_object_t * );
106 static void CDDAClose        ( vlc_object_t * );
107 static int  CDDARead         ( input_thread_t *, byte_t *, size_t );
108 static void CDDASeek         ( input_thread_t *, off_t );
109 static int  CDDASetArea      ( input_thread_t *, input_area_t * );
110 static int  CDDASetProgram   ( input_thread_t *, pgrm_descriptor_t * );
111
112 static int  CDDAOpenDemux    ( vlc_object_t * );
113 static void CDDACloseDemux   ( vlc_object_t * );
114 static int  CDDADemux        ( input_thread_t * p_input );
115
116 /*****************************************************************************
117  * Local prototypes
118  *****************************************************************************/
119
120 /* FIXME: This variable is a hack. Would be nice to eliminate. */
121 static input_thread_t *p_cdda_input = NULL;
122
123 static int debug_callback   ( vlc_object_t *p_this, const char *psz_name,
124                               vlc_value_t oldval, vlc_value_t val, 
125                               void *p_data );
126
127 /*****************************************************************************
128  * Module descriptor
129  *****************************************************************************/
130 #define CACHING_TEXT N_("Caching value in ms")
131 #define CACHING_LONGTEXT N_( \
132     "Allows you to modify the default caching value for cdda streams. This " \
133     "value should be set in miliseconds units." )
134
135 vlc_module_begin();
136     set_description( _("CD Audio input") );
137     set_capability( "access", 75 /* slightly higher than cdda */ );
138     add_integer( "cddax-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
139     set_callbacks( CDDAOpen, CDDAClose );
140     add_shortcut( "cdda" );
141
142     /* Configuration options */
143     add_category_hint( N_("CDX"), NULL, VLC_TRUE );
144     add_integer ( MODULE_STRING "-debug", 0, debug_callback, DEBUG_TEXT, 
145                   DEBUG_LONGTEXT, VLC_TRUE );
146
147     add_submodule();
148         set_description( _("CD Audio demux") );
149         set_capability( "demux", 0 );
150         set_callbacks( CDDAOpenDemux, CDDACloseDemux );
151         add_shortcut( "cdda" );
152 vlc_module_end();
153
154 /****************************************************************************
155  * Private functions
156  ****************************************************************************/
157
158 static int
159 debug_callback   ( vlc_object_t *p_this, const char *psz_name,
160                    vlc_value_t oldval, vlc_value_t val, void *p_data )
161 {
162   cdda_data_t *p_cdda;
163
164   if (NULL == p_cdda_input) return VLC_EGENERIC;
165   
166   p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
167
168   if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
169     msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d", 
170              p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
171   }
172   p_cdda->i_debug = val.i_int;
173   return VLC_SUCCESS;
174 }
175
176 /* process messages that originate from libcdio. */
177 static void
178 cdio_log_handler (cdio_log_level_t level, const char message[])
179 {
180   cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
181   switch (level) {
182   case CDIO_LOG_DEBUG:
183   case CDIO_LOG_INFO:
184     if (p_cdda->i_debug & INPUT_DBG_CDIO) 
185       msg_Dbg( p_cdda_input, message);
186     break;
187   case CDIO_LOG_WARN:
188     msg_Warn( p_cdda_input, message);
189     break;
190   case CDIO_LOG_ERROR:
191   case CDIO_LOG_ASSERT:
192     msg_Err( p_cdda_input, message);
193     break;
194   default:
195     msg_Warn( p_cdda_input, message,
196             _("The above message had unknown vcdimager log level"), 
197             level);
198   }
199   return;
200 }
201
202
203 /*****************************************************************************
204  * CDDAOpen: open cdda
205  *****************************************************************************/
206 static int CDDAOpen( vlc_object_t *p_this )
207 {
208     input_thread_t *        p_input = (input_thread_t *)p_this;
209     char *                  psz_orig;
210     char *                  psz_parser;
211     char *                  psz_source;
212     cdda_data_t *           p_cdda;
213     int                     i;
214     input_area_t *          p_area;
215     int                     i_title = 1;
216     cddev_t                 *p_cddev;
217
218     /* Set where to log errors messages from libcdio. */
219     p_cdda_input = (input_thread_t *)p_this;
220
221     /* parse the options passed in command line : */
222     psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
223
224     if( !psz_orig )
225     {
226         return( -1 );
227     }
228
229     while( *psz_parser && *psz_parser != '@' )
230     {
231         psz_parser++;
232     }
233
234     if( *psz_parser == '@' )
235     {
236         /* Found options */
237         *psz_parser = '\0';
238         ++psz_parser;
239
240         if ('T' == *psz_parser || 't' == *psz_parser ) 
241             ++psz_parser;
242           
243         i_title = (int)strtol( psz_parser, NULL, 10 );
244         i_title = i_title ? i_title : 1;
245     }
246
247     if( !*psz_source ) {
248       /* No source specified, so figure it out. */
249       if( !p_input->psz_access ) {
250         free( psz_orig );
251         return -1;
252       }
253       psz_source = config_GetPsz( p_input, MODULE_STRING "-device" );
254       
255       if( !psz_source ) {
256         /* Scan for a CD with a CD-DA in it. */
257         char **cd_drives = 
258           cdio_get_devices_with_cap(NULL,  CDIO_FS_AUDIO, false);
259         if (NULL == cd_drives) return -1;
260         if (cd_drives[0] == NULL) {
261           cdio_free_device_list(cd_drives);
262           return -1;
263         }
264         psz_source = strdup(cd_drives[0]);
265         cdio_free_device_list(cd_drives);
266       }
267     }
268
269     /* Open CDDA */
270     if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
271     {
272         msg_Warn( p_input, "could not open %s", psz_source );
273         free( psz_source );
274         return -1;
275     }
276     free( psz_source );
277
278     p_cdda = malloc( sizeof(cdda_data_t) );
279     if( p_cdda == NULL )
280     {
281         msg_Err( p_input, "out of memory" );
282         free( psz_source );
283         return -1;
284     }
285
286     p_cdda->p_cddev        = p_cddev;
287     p_cdda->i_debug        = config_GetInt( p_this, MODULE_STRING "-debug" );
288     p_input->p_access_data = (void *)p_cdda;
289
290     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
291
292     p_input->i_mtu = CDDA_DATA_ONCE;
293
294     /* We read the Table Of Content information */
295     p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
296                               p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
297     if( p_cdda->i_nb_tracks < 0 )
298         msg_Err( p_input, "unable to count tracks" );
299     else if( p_cdda->i_nb_tracks <= 0 )
300         msg_Err( p_input, "no audio tracks found" );
301
302     if( p_cdda->i_nb_tracks <= 1)
303     {
304         ioctl_Close( p_cdda->p_cddev );
305         free( p_cdda );
306         return -1;
307     }
308
309     if( i_title >= p_cdda->i_nb_tracks || i_title < 1 )
310         i_title = 1;
311
312     /* Set stream and area data */
313     vlc_mutex_lock( &p_input->stream.stream_lock );
314
315     /* Initialize ES structures */
316     input_InitStream( p_input, 0 );
317
318     /* cdda input method */
319     p_input->stream.i_method = INPUT_METHOD_CDDA;
320
321     p_input->stream.b_pace_control = 1;
322     p_input->stream.b_seekable = 1;
323     p_input->stream.i_mux_rate = 44100 * 4 / 50;
324
325 #define area p_input->stream.pp_areas
326     for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
327     {
328         input_AddArea( p_input, i, 1 );
329
330         /* Absolute start offset and size */
331         area[i]->i_start =
332             (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
333         area[i]->i_size =
334             (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
335             * (off_t)CDIO_CD_FRAMESIZE_RAW;
336     }
337 #undef area
338
339     p_area = p_input->stream.pp_areas[i_title];
340
341     CDDASetArea( p_input, p_area );
342
343     vlc_mutex_unlock( &p_input->stream.stream_lock );
344
345     if( !p_input->psz_demux || !*p_input->psz_demux )
346     {
347         p_input->psz_demux = "cdda";
348     }
349
350     p_input->pf_read = CDDARead;
351     p_input->pf_seek = CDDASeek;
352     p_input->pf_set_area = CDDASetArea;
353     p_input->pf_set_program = CDDASetProgram;
354
355     /* Update default_pts to a suitable value for cdda access */
356     p_input->i_pts_delay = config_GetInt( p_input, 
357                                           MODULE_STRING "-caching" ) * 1000;
358
359     return 0;
360 }
361
362 /*****************************************************************************
363  * CDDAClose: closes cdda
364  *****************************************************************************/
365 static void CDDAClose( vlc_object_t *p_this )
366 {
367     input_thread_t *   p_input = (input_thread_t *)p_this;
368     cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
369
370     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
371     ioctl_Close( p_cdda->p_cddev );
372     free( p_cdda );
373     p_cdda_input = NULL;
374 }
375
376 /*****************************************************************************
377  * CDDARead: reads from the CDDA into PES packets.
378  *****************************************************************************
379  * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
380  * bytes.
381  *****************************************************************************/
382 static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
383                      size_t i_len )
384 {
385     cdda_data_t *           p_cdda;
386     int                     i_blocks;
387     int                     i_index;
388     int                     i_read;
389
390     p_cdda = (cdda_data_t *)p_input->p_access_data;
391
392     i_read = 0;
393
394     /* Compute the number of blocks we have to read */
395
396     i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
397
398     for ( i_index = 0; i_index < i_blocks; i_index++ )
399     {
400
401       if (cdio_read_audio_sector(p_cdda->p_cddev->cdio, p_buffer, 
402                                  p_cdda->i_sector) != 0)
403         {
404           msg_Err( p_input, "could not read sector %d", p_cdda->i_sector );
405           return -1;
406         }
407
408         p_cdda->i_sector ++;
409         if ( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
410         {
411             input_area_t *p_area;
412
413             dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL), 
414                        "end of track, cur: %u", p_cdda->i_sector );
415
416             if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )
417                 return 0; /* EOF */
418
419             vlc_mutex_lock( &p_input->stream.stream_lock );
420             p_area = p_input->stream.pp_areas[
421                     p_input->stream.p_selected_area->i_id + 1 ];
422
423             p_area->i_part = 1;
424             CDDASetArea( p_input, p_area );
425             vlc_mutex_unlock( &p_input->stream.stream_lock );
426         }
427         i_read += CDIO_CD_FRAMESIZE_RAW;
428     }
429
430     if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
431     {
432         msg_Err( p_input, "must read full sectors" );
433     }
434
435     return i_read;
436 }
437
438 /*****************************************************************************
439  * CDDASetProgram: Does nothing since a CDDA is mono_program
440  *****************************************************************************/
441 static int CDDASetProgram( input_thread_t * p_input,
442                            pgrm_descriptor_t * p_program)
443 {
444     cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
445     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
446     return 0;
447 }
448
449 /*****************************************************************************
450  * CDDASetArea: initialize input data for title x.
451  * It should be called for each user navigation request.
452  ****************************************************************************/
453 static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
454 {
455     cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
456     vlc_value_t val;
457
458     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
459
460     /* we can't use the interface slider until initilization is complete */
461     p_input->stream.b_seekable = 0;
462
463     if( p_area != p_input->stream.p_selected_area )
464     {
465         /* Change the default area */
466         p_input->stream.p_selected_area = p_area;
467
468         /* Change the current track */
469         p_cdda->i_track = p_area->i_id - 1;
470         p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
471
472         /* Update the navigation variables without triggering a callback */
473         val.i_int = p_area->i_id;
474         var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
475     }
476
477     p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
478
479     p_input->stream.p_selected_area->i_tell =
480         (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
481          - p_input->stream.p_selected_area->i_start;
482
483     /* warn interface that something has changed */
484     p_input->stream.b_seekable = 1;
485     p_input->stream.b_changed = 1;
486
487     return 0;
488 }
489
490 /****************************************************************************
491  * CDDASeek
492  ****************************************************************************/
493 static void CDDASeek( input_thread_t * p_input, off_t i_off )
494 {
495     cdda_data_t * p_cdda;
496
497     p_cdda = (cdda_data_t *) p_input->p_access_data;
498
499     p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
500                        + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
501
502     vlc_mutex_lock( &p_input->stream.stream_lock );
503     p_input->stream.p_selected_area->i_tell =
504         (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
505          - p_input->stream.p_selected_area->i_start;
506
507     vlc_mutex_unlock( &p_input->stream.stream_lock );
508
509     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
510     "sector %ud, offset: %lld, i_tell: %lld",  p_cdda->i_sector, i_off, 
511                p_input->stream.p_selected_area->i_tell );
512
513 }
514
515 /****************************************************************************
516  * Demux Part
517  ****************************************************************************/
518 static int  CDDAOpenDemux    ( vlc_object_t * p_this)
519 {
520     input_thread_t *p_input = (input_thread_t *)p_this;
521     demux_sys_t    *p_demux;
522     WAVEFORMATEX   *p_wf;
523
524     if( p_input->stream.i_method != INPUT_METHOD_CDDA )
525     {
526         return VLC_EGENERIC;
527     }
528
529     p_demux = malloc( sizeof( es_descriptor_t ) );
530     p_demux->i_pts = 0;
531     p_demux->p_es = NULL;
532
533     p_input->pf_demux  = CDDADemux;
534     p_input->pf_demux_control = demux_vaControlDefault;
535     p_input->pf_rewind = NULL;
536     p_input->p_demux_data = p_demux;
537
538     vlc_mutex_lock( &p_input->stream.stream_lock );
539     if( input_AddProgram( p_input, 0, 0) == NULL )
540     {
541         msg_Err( p_input, "cannot add program" );
542         free( p_input->p_demux_data );
543         return( -1 );
544     }
545     p_input->stream.pp_programs[0]->b_is_ok = 0;
546     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
547
548     /* create our ES */ 
549     p_demux->p_es = input_AddES( p_input, 
550                                  p_input->stream.p_selected_program, 
551                                  1 /* id */, AUDIO_ES, NULL, 0 );
552     if( !p_demux->p_es )
553     {
554         vlc_mutex_unlock( &p_input->stream.stream_lock );
555         msg_Err( p_input, "out of memory" );
556         free( p_input->p_demux_data );
557         return( -1 );
558     }
559     p_demux->p_es->i_stream_id = 1;
560     p_demux->p_es->i_fourcc = VLC_FOURCC('a','r','a','w');
561
562     p_demux->p_es->p_waveformatex = p_wf = malloc( sizeof( WAVEFORMATEX ) );
563     p_wf->wFormatTag = WAVE_FORMAT_PCM;
564     p_wf->nChannels = 2;
565     p_wf->nSamplesPerSec = 44100;
566     p_wf->nAvgBytesPerSec = 2 * 44100 * 2;
567     p_wf->nBlockAlign = 4;
568     p_wf->wBitsPerSample = 16;
569     p_wf->cbSize = 0;
570
571     input_SelectES( p_input, p_demux->p_es );
572
573     p_input->stream.p_selected_program->b_is_ok = 1;
574     vlc_mutex_unlock( &p_input->stream.stream_lock );
575
576     return VLC_SUCCESS;
577 }
578
579 static void CDDACloseDemux( vlc_object_t * p_this)
580 {
581     input_thread_t *p_input = (input_thread_t*)p_this;
582     demux_sys_t    *p_demux = (demux_sys_t*)p_input->p_demux_data;
583
584     free( p_demux );
585     p_input->p_demux_data = NULL;
586     return;
587 }
588
589 static int  CDDADemux( input_thread_t * p_input )
590 {
591     demux_sys_t    *p_demux = (demux_sys_t*)p_input->p_demux_data;
592     ssize_t         i_read;
593     data_packet_t * p_data;
594     pes_packet_t *  p_pes;
595
596     input_ClockManageRef( p_input,
597                           p_input->stream.p_selected_program,
598                           p_demux->i_pts );
599
600     i_read = input_SplitBuffer( p_input, &p_data, CDIO_CD_FRAMESIZE_RAW );
601     if( i_read <= 0 )
602     {
603         return 0; // EOF
604     }
605
606     p_pes = input_NewPES( p_input->p_method_data );
607
608     if( p_pes == NULL )
609     {
610         msg_Err( p_input, "out of memory" );
611         input_DeletePacket( p_input->p_method_data, p_data );
612         return -1;
613     }
614
615     p_pes->i_rate = p_input->stream.control.i_rate;
616     p_pes->p_first = p_pes->p_last = p_data;
617     p_pes->i_nb_data = 1;
618     p_pes->i_pes_size = i_read;
619
620     p_pes->i_dts =
621         p_pes->i_pts = input_ClockGetTS( p_input,
622                                          p_input->stream.p_selected_program,
623                                          p_demux->i_pts );
624
625     if( p_demux->p_es->p_decoder_fifo )
626     {
627         input_DecodePES( p_demux->p_es->p_decoder_fifo, p_pes );
628     }
629     else
630     {
631         input_DeletePES( p_input->p_method_data, p_pes );
632     }
633
634     p_demux->i_pts += ((mtime_t)90000) * i_read
635                       / (mtime_t)44100 / 4 /* stereo 16 bits */;
636     return 1;
637 }