]> git.sesse.net Git - vlc/blob - modules/access/cdda.c
* all: removed decoder_fifo_t.
[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.7 2003/11/24 00:39:01 fenrir 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     set_capability( "access", 70 );
94     add_integer( "cdda-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
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_demux_control = demux_vaControlDefault;
405     p_input->pf_rewind = NULL;
406     p_input->p_demux_data = p_demux;
407
408     vlc_mutex_lock( &p_input->stream.stream_lock );
409     if( input_AddProgram( p_input, 0, 0) == NULL )
410     {
411         msg_Err( p_input, "cannot add program" );
412         free( p_input->p_demux_data );
413         return( -1 );
414     }
415     p_input->stream.pp_programs[0]->b_is_ok = 0;
416     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
417
418     /* create our ES */ 
419     p_demux->p_es = input_AddES( p_input, 
420                                  p_input->stream.p_selected_program,
421                                  1 /* id */, AUDIO_ES, NULL, 0 );
422     if( !p_demux->p_es )
423     {
424         vlc_mutex_unlock( &p_input->stream.stream_lock );
425         msg_Err( p_input, "out of memory" );
426         free( p_input->p_demux_data );
427         return( -1 );
428     }
429     p_demux->p_es->i_stream_id = 1;
430     p_demux->p_es->i_fourcc = VLC_FOURCC('a','r','a','w');
431
432     p_demux->p_es->p_waveformatex = p_wf = malloc( sizeof( WAVEFORMATEX ) );
433     p_wf->wFormatTag = WAVE_FORMAT_PCM;
434     p_wf->nChannels = 2;
435     p_wf->nSamplesPerSec = 44100;
436     p_wf->nAvgBytesPerSec = 2 * 44100 * 2;
437     p_wf->nBlockAlign = 4;
438     p_wf->wBitsPerSample = 16;
439     p_wf->cbSize = 0;
440
441     input_SelectES( p_input, p_demux->p_es );
442
443     p_input->stream.p_selected_program->b_is_ok = 1;
444     vlc_mutex_unlock( &p_input->stream.stream_lock );
445
446     return VLC_SUCCESS;
447 }
448
449 static void CDDACloseDemux( vlc_object_t * p_this)
450 {
451     input_thread_t *p_input = (input_thread_t*)p_this;
452     demux_sys_t    *p_demux = (demux_sys_t*)p_input->p_demux_data;
453
454     free( p_demux );
455     p_input->p_demux_data = NULL;
456     return;
457 }
458
459 static int  CDDADemux( input_thread_t * p_input )
460 {
461     demux_sys_t    *p_demux = (demux_sys_t*)p_input->p_demux_data;
462     ssize_t         i_read;
463     data_packet_t * p_data;
464     pes_packet_t *  p_pes;
465
466     input_ClockManageRef( p_input,
467                           p_input->stream.p_selected_program,
468                           p_demux->i_pts );
469
470     if( ( i_read = input_SplitBuffer( p_input, &p_data, CDDA_DATA_SIZE ) )
471         <= 0 )
472     {
473         return 0; // EOF
474     }
475
476     p_pes = input_NewPES( p_input->p_method_data );
477
478     if( p_pes == NULL )
479     {
480         msg_Err( p_input, "out of memory" );
481         input_DeletePacket( p_input->p_method_data, p_data );
482         return -1;
483     }
484
485     p_pes->i_rate = p_input->stream.control.i_rate;
486     p_pes->p_first = p_pes->p_last = p_data;
487     p_pes->i_nb_data = 1;
488     p_pes->i_pes_size = i_read;
489
490     p_pes->i_dts =
491         p_pes->i_pts = input_ClockGetTS( p_input,
492                                          p_input->stream.p_selected_program,
493                                          p_demux->i_pts );
494
495     if( p_demux->p_es->p_dec )
496     {
497         input_DecodePES( p_demux->p_es->p_dec, p_pes );
498     }
499     else
500     {
501         input_DeletePES( p_input->p_method_data, p_pes );
502     }
503
504     p_demux->i_pts += ((mtime_t)90000) * i_read
505                       / (mtime_t)44100 / 4 /* stereo 16 bits */;
506     return 1;
507 }