]> git.sesse.net Git - vlc/blob - modules/access/cdda.c
* INSTALL.win32: added a small note about running vlc under the msvc debugger.
[vlc] / modules / access / cdda.c
1 /*****************************************************************************
2  * cdda.c : CD digital audio input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2000 VideoLAN
5  * $Id: cdda.c,v 1.4 2003/05/22 12:00:56 gbazin Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Gildas Bazin <gbazin@netcourrier.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33 #include <sys/types.h>
34
35 #include "codecs.h"
36
37 #ifdef HAVE_UNISTD_H
38 #   include <unistd.h>
39 #endif
40
41 #include <string.h>
42
43 #include "vcd/cdrom.h"
44
45 /* how many blocks VCDRead will read in each loop */
46 #define CDDA_BLOCKS_ONCE 20
47 #define CDDA_DATA_ONCE   (CDDA_BLOCKS_ONCE * CDDA_DATA_SIZE)
48
49 /*****************************************************************************
50  * cdda_data_t: CD audio information
51  *****************************************************************************/
52 typedef struct cdda_data_s
53 {
54     vcddev_t    *vcddev;                            /* vcd device descriptor */
55     int         i_nb_tracks;                        /* Nb of tracks (titles) */
56     int         i_track;                                    /* Current track */
57     int         i_sector;                                  /* Current Sector */
58     int *       p_sectors;                                  /* Track sectors */
59     vlc_bool_t  b_end_of_track;           /* If the end of track was reached */
60
61 } cdda_data_t;
62
63 struct demux_sys_t
64 {
65     es_descriptor_t *p_es;
66     mtime_t         i_pts;
67 };
68
69 /*****************************************************************************
70  * Local prototypes
71  *****************************************************************************/
72 static int  CDDAOpen         ( vlc_object_t * );
73 static void CDDAClose        ( vlc_object_t * );
74 static int  CDDARead         ( input_thread_t *, byte_t *, size_t );
75 static void CDDASeek         ( input_thread_t *, off_t );
76 static int  CDDASetArea      ( input_thread_t *, input_area_t * );
77 static int  CDDASetProgram   ( input_thread_t *, pgrm_descriptor_t * );
78
79 static int  CDDAOpenDemux    ( vlc_object_t * );
80 static void CDDACloseDemux   ( vlc_object_t * );
81 static int  CDDADemux        ( input_thread_t * p_input );
82
83 /*****************************************************************************
84  * Module descriptior
85  *****************************************************************************/
86 #define CACHING_TEXT N_("Caching value in ms")
87 #define CACHING_LONGTEXT N_( \
88     "Allows you to modify the default caching value for cdda streams. This " \
89     "value should be set in miliseconds units." )
90
91 vlc_module_begin();
92     set_description( _("CD Audio input") );
93     add_integer( "cdda-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
94     set_capability( "access", 70 );
95     set_callbacks( CDDAOpen, CDDAClose );
96     add_shortcut( "cdda" );
97
98     add_submodule();
99         set_description( _("CD Audio demux") );
100         set_capability( "demux", 0 );
101         set_callbacks( CDDAOpenDemux, CDDACloseDemux );
102         add_shortcut( "cdda" );
103 vlc_module_end();
104
105 /*****************************************************************************
106  * CDDAOpen: open cdda
107  *****************************************************************************/
108 static int CDDAOpen( vlc_object_t *p_this )
109 {
110     input_thread_t *        p_input = (input_thread_t *)p_this;
111     char *                  psz_orig;
112     char *                  psz_parser;
113     char *                  psz_source;
114     cdda_data_t *           p_cdda;
115     int                     i;
116     input_area_t *          p_area;
117     int                     i_title = 1;
118     vcddev_t                *vcddev;
119
120     /* parse the options passed in command line : */
121     psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
122
123     if( !psz_orig )
124     {
125         return( -1 );
126     }
127
128     while( *psz_parser && *psz_parser != '@' )
129     {
130         psz_parser++;
131     }
132
133     if( *psz_parser == '@' )
134     {
135         /* Found options */
136         *psz_parser = '\0';
137         ++psz_parser;
138
139         i_title = (int)strtol( psz_parser, NULL, 10 );
140         i_title = i_title ? i_title : 1;
141     }
142
143     if( !*psz_source )
144     {
145         if( !p_input->psz_access )
146         {
147             free( psz_orig );
148             return -1;
149         }
150         psz_source = config_GetPsz( p_input, "vcd" );
151         if( !psz_source ) return -1;
152     }
153
154     /* Open CDDA */
155     if( !(vcddev = ioctl_Open( p_this, psz_source )) )
156     {
157         msg_Warn( p_input, "could not open %s", psz_source );
158         free( psz_source );
159         return -1;
160     }
161     free( psz_source );
162
163     p_cdda = malloc( sizeof(cdda_data_t) );
164     if( p_cdda == NULL )
165     {
166         msg_Err( p_input, "out of memory" );
167         free( psz_source );
168         return -1;
169     }
170
171     p_cdda->vcddev = vcddev;
172     p_input->p_access_data = (void *)p_cdda;
173
174     p_input->i_mtu = CDDA_DATA_ONCE;
175
176     /* We read the Table Of Content information */
177     p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
178                               p_cdda->vcddev, &p_cdda->p_sectors );
179     if( p_cdda->i_nb_tracks < 0 )
180         msg_Err( p_input, "unable to count tracks" );
181     else if( p_cdda->i_nb_tracks <= 0 )
182         msg_Err( p_input, "no audio tracks found" );
183
184     if( p_cdda->i_nb_tracks <= 1)
185     {
186         ioctl_Close( p_this, p_cdda->vcddev );
187         free( p_cdda );
188         return -1;
189     }
190
191     if( i_title >= p_cdda->i_nb_tracks || i_title < 1 )
192         i_title = 1;
193
194     /* Set stream and area data */
195     vlc_mutex_lock( &p_input->stream.stream_lock );
196
197     /* Initialize ES structures */
198     input_InitStream( p_input, 0 );
199
200     /* cdda input method */
201     p_input->stream.i_method = INPUT_METHOD_CDDA;
202
203     p_input->stream.b_pace_control = 1;
204     p_input->stream.b_seekable = 1;
205     p_input->stream.i_mux_rate = 44100 * 4 / 50;
206
207 #define area p_input->stream.pp_areas
208     for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
209     {
210         input_AddArea( p_input, i, 1 );
211
212         /* Absolute start offset and size */
213         area[i]->i_start =
214             (off_t)p_cdda->p_sectors[i-1] * (off_t)CDDA_DATA_SIZE;
215         area[i]->i_size =
216             (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
217             * (off_t)CDDA_DATA_SIZE;
218     }
219 #undef area
220
221     p_area = p_input->stream.pp_areas[i_title];
222
223     CDDASetArea( p_input, p_area );
224
225     vlc_mutex_unlock( &p_input->stream.stream_lock );
226
227     if( !p_input->psz_demux || !*p_input->psz_demux )
228     {
229         p_input->psz_demux = "cdda";
230     }
231
232     p_input->pf_read = CDDARead;
233     p_input->pf_seek = CDDASeek;
234     p_input->pf_set_area = CDDASetArea;
235     p_input->pf_set_program = CDDASetProgram;
236
237     /* Update default_pts to a suitable value for cdda access */
238     p_input->i_pts_delay = config_GetInt( p_input, "cdda-caching" ) * 1000;
239
240     return 0;
241 }
242
243 /*****************************************************************************
244  * CDDAClose: closes cdda
245  *****************************************************************************/
246 static void CDDAClose( vlc_object_t *p_this )
247 {
248     input_thread_t *   p_input = (input_thread_t *)p_this;
249     cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
250
251     ioctl_Close( p_this, p_cdda->vcddev );
252     free( p_cdda );
253 }
254
255 /*****************************************************************************
256  * CDDARead: reads from the CDDA into PES packets.
257  *****************************************************************************
258  * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
259  * bytes.
260  *****************************************************************************/
261 static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
262                      size_t i_len )
263 {
264     cdda_data_t *           p_cdda;
265     int                     i_blocks;
266     int                     i_index;
267     int                     i_read;
268
269     p_cdda = (cdda_data_t *)p_input->p_access_data;
270
271     i_read = 0;
272
273     /* Compute the number of blocks we have to read */
274
275     i_blocks = i_len / CDDA_DATA_SIZE;
276
277     if ( ioctl_ReadSectors( VLC_OBJECT(p_input), p_cdda->vcddev,
278              p_cdda->i_sector, p_buffer, i_blocks, CDDA_TYPE ) < 0 )
279     {
280         msg_Err( p_input, "could not read sector %d", p_cdda->i_sector );
281         return -1;
282     }
283
284     for ( i_index = 0; i_index < i_blocks; i_index++ )
285     {
286         p_cdda->i_sector ++;
287         if ( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
288         {
289             input_area_t *p_area;
290
291             if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )
292                 return 0; /* EOF */
293
294             vlc_mutex_lock( &p_input->stream.stream_lock );
295             p_area = p_input->stream.pp_areas[
296                     p_input->stream.p_selected_area->i_id + 1 ];
297
298             msg_Dbg( p_input, "new title" );
299
300             p_area->i_part = 1;
301             CDDASetArea( p_input, p_area );
302             vlc_mutex_unlock( &p_input->stream.stream_lock );
303         }
304         i_read += CDDA_DATA_SIZE;
305     }
306
307     if ( i_len % CDDA_DATA_SIZE ) /* this should not happen */
308     {
309         msg_Err( p_input, "must read full sectors" );
310     }
311
312     return i_read;
313 }
314
315
316 /*****************************************************************************
317  * CDDASetProgram: Does nothing since a CDDA is mono_program
318  *****************************************************************************/
319 static int CDDASetProgram( input_thread_t * p_input,
320                            pgrm_descriptor_t * p_program)
321 {
322     return 0;
323 }
324
325
326 /*****************************************************************************
327  * CDDASetArea: initialize input data for title x.
328  * It should be called for each user navigation request.
329  ****************************************************************************/
330 static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
331 {
332     cdda_data_t *p_cdda = (cdda_data_t*)p_input->p_access_data;
333     vlc_value_t val;
334
335     /* we can't use the interface slider until initilization is complete */
336     p_input->stream.b_seekable = 0;
337
338     if( p_area != p_input->stream.p_selected_area )
339     {
340         /* Change the default area */
341         p_input->stream.p_selected_area = p_area;
342
343         /* Change the current track */
344         p_cdda->i_track = p_area->i_id - 1;
345         p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
346
347         /* Update the navigation variables without triggering a callback */
348         val.i_int = p_area->i_id;
349         var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
350     }
351
352     p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
353
354     p_input->stream.p_selected_area->i_tell =
355         (off_t)p_cdda->i_sector * (off_t)CDDA_DATA_SIZE
356          - p_input->stream.p_selected_area->i_start;
357
358     /* warn interface that something has changed */
359     p_input->stream.b_seekable = 1;
360     p_input->stream.b_changed = 1;
361
362     return 0;
363 }
364
365
366 /****************************************************************************
367  * CDDASeek
368  ****************************************************************************/
369 static void CDDASeek( input_thread_t * p_input, off_t i_off )
370 {
371     cdda_data_t * p_cdda;
372
373     p_cdda = (cdda_data_t *) p_input->p_access_data;
374
375     p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
376                        + i_off / (off_t)CDDA_DATA_SIZE;
377
378     vlc_mutex_lock( &p_input->stream.stream_lock );
379     p_input->stream.p_selected_area->i_tell =
380         (off_t)p_cdda->i_sector * (off_t)CDDA_DATA_SIZE
381          - p_input->stream.p_selected_area->i_start;
382     vlc_mutex_unlock( &p_input->stream.stream_lock );
383 }
384
385 /****************************************************************************
386  * Demux Part
387  ****************************************************************************/
388 static int  CDDAOpenDemux    ( vlc_object_t * p_this)
389 {
390     input_thread_t *p_input = (input_thread_t *)p_this;
391     demux_sys_t    *p_demux;
392     WAVEFORMATEX   *p_wf;
393
394     if( p_input->stream.i_method != INPUT_METHOD_CDDA )
395     {
396         return VLC_EGENERIC;
397     }
398
399     p_demux = malloc( sizeof( es_descriptor_t ) );
400     p_demux->i_pts = 0;
401     p_demux->p_es = NULL;
402
403     p_input->pf_demux  = CDDADemux;
404     p_input->pf_rewind = NULL;
405     p_input->p_demux_data = p_demux;
406
407     vlc_mutex_lock( &p_input->stream.stream_lock );
408     if( input_AddProgram( p_input, 0, 0) == NULL )
409     {
410         msg_Err( p_input, "cannot add program" );
411         free( p_input->p_demux_data );
412         return( -1 );
413     }
414     p_input->stream.pp_programs[0]->b_is_ok = 0;
415     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
416
417     /* create our ES */ 
418     p_demux->p_es = input_AddES( p_input, 
419                                  p_input->stream.p_selected_program,
420                                  1 /* id */, AUDIO_ES, NULL, 0 );
421     if( !p_demux->p_es )
422     {
423         vlc_mutex_unlock( &p_input->stream.stream_lock );
424         msg_Err( p_input, "out of memory" );
425         free( p_input->p_demux_data );
426         return( -1 );
427     }
428     p_demux->p_es->i_stream_id = 1;
429     p_demux->p_es->i_fourcc = VLC_FOURCC('a','r','a','w');
430
431     p_demux->p_es->p_waveformatex = p_wf = malloc( sizeof( WAVEFORMATEX ) );
432     p_wf->wFormatTag = WAVE_FORMAT_PCM;
433     p_wf->nChannels = 2;
434     p_wf->nSamplesPerSec = 44100;
435     p_wf->nAvgBytesPerSec = 2 * 44100 * 2;
436     p_wf->nBlockAlign = 4;
437     p_wf->wBitsPerSample = 16;
438     p_wf->cbSize = 0;
439
440     input_SelectES( p_input, p_demux->p_es );
441
442     p_input->stream.p_selected_program->b_is_ok = 1;
443     vlc_mutex_unlock( &p_input->stream.stream_lock );
444
445     return VLC_SUCCESS;
446 }
447
448 static void CDDACloseDemux( vlc_object_t * p_this)
449 {
450     input_thread_t *p_input = (input_thread_t*)p_this;
451     demux_sys_t    *p_demux = (demux_sys_t*)p_input->p_demux_data;
452
453     free( p_demux );
454     p_input->p_demux_data = NULL;
455     return;
456 }
457
458 static int  CDDADemux( input_thread_t * p_input )
459 {
460     demux_sys_t    *p_demux = (demux_sys_t*)p_input->p_demux_data;
461     ssize_t         i_read;
462     data_packet_t * p_data;
463     pes_packet_t *  p_pes;
464
465     input_ClockManageRef( p_input,
466                           p_input->stream.p_selected_program,
467                           p_demux->i_pts );
468
469     if( ( i_read = input_SplitBuffer( p_input, &p_data, CDDA_DATA_SIZE ) )
470         <= 0 )
471     {
472         return 0; // EOF
473     }
474
475     p_pes = input_NewPES( p_input->p_method_data );
476
477     if( p_pes == NULL )
478     {
479         msg_Err( p_input, "out of memory" );
480         input_DeletePacket( p_input->p_method_data, p_data );
481         return -1;
482     }
483
484     p_pes->i_rate = p_input->stream.control.i_rate;
485     p_pes->p_first = p_pes->p_last = p_data;
486     p_pes->i_nb_data = 1;
487     p_pes->i_pes_size = i_read;
488
489     p_pes->i_dts =
490         p_pes->i_pts = input_ClockGetTS( p_input,
491                                          p_input->stream.p_selected_program,
492                                          p_demux->i_pts );
493
494     if( p_demux->p_es->p_decoder_fifo )
495     {
496         input_DecodePES( p_demux->p_es->p_decoder_fifo, p_pes );
497     }
498     else
499     {
500         input_DeletePES( p_input->p_method_data, p_pes );
501     }
502
503     p_demux->i_pts += ((mtime_t)90000) * i_read
504                       / (mtime_t)44100 / 4 /* stereo 16 bits */;
505     return 1;
506 }