]> git.sesse.net Git - vlc/blob - plugins/dsp/aout_dsp.c
This is the first part of the new configuration architecture for vlc.
[vlc] / plugins / dsp / aout_dsp.c
1 /*****************************************************************************
2  * aout_dsp.c : dsp functions library
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: aout_dsp.c,v 1.22 2002/02/24 20:51:09 gbazin Exp $
6  *
7  * Authors: Michel Kaempf <maxx@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
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 /* TODO:
26  *
27  * - an aout_GetFormats() function
28  * - dsp inline/static
29  * - make this library portable (see mpg123)
30  *
31  */
32
33 /*****************************************************************************
34  * Preamble
35  *****************************************************************************/
36 #include <errno.h>                                                 /* ENOMEM */
37 #include <fcntl.h>                                       /* open(), O_WRONLY */
38 #include <sys/ioctl.h>                                            /* ioctl() */
39 #include <string.h>                                            /* strerror() */
40 #include <unistd.h>                                      /* write(), close() */
41 #include <stdio.h>                                           /* "intf_msg.h" */
42 #include <stdlib.h>                            /* calloc(), malloc(), free() */
43
44 #include <videolan/vlc.h>
45
46 #ifdef SYS_BSD
47 #include <machine/soundcard.h>       /* SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT,
48                    SNDCTL_DSP_STEREO, SNDCTL_DSP_SPEED, SNDCTL_DSP_GETOSPACE */
49 #else
50 #include <sys/soundcard.h>           /* SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT,
51                    SNDCTL_DSP_STEREO, SNDCTL_DSP_SPEED, SNDCTL_DSP_GETOSPACE */
52 #endif
53
54 #include "audio_output.h"                                   /* aout_thread_t */
55
56 #define DSP_DEV_VAR "dsp_dev"
57 /*****************************************************************************
58  * aout_sys_t: dsp audio output method descriptor
59  *****************************************************************************
60  * This structure is part of the audio output thread descriptor.
61  * It describes the dsp specific properties of an audio device.
62  *****************************************************************************/
63 typedef struct aout_sys_s
64 {
65     audio_buf_info        audio_buf;
66
67     /* Path to the audio output device */
68     char *                psz_device;
69     int                   i_fd;
70
71 } aout_sys_t;
72
73 /*****************************************************************************
74  * Local prototypes.
75  *****************************************************************************/
76 static int     aout_Open        ( aout_thread_t *p_aout );
77 static int     aout_SetFormat   ( aout_thread_t *p_aout );
78 static long    aout_GetBufInfo  ( aout_thread_t *p_aout, long l_buffer_info );
79 static void    aout_Play        ( aout_thread_t *p_aout,
80                                   byte_t *buffer, int i_size );
81 static void    aout_Close       ( aout_thread_t *p_aout );
82
83 /*****************************************************************************
84  * Functions exported as capabilities. They are declared as static so that
85  * we don't pollute the namespace too much.
86  *****************************************************************************/
87 void _M( aout_getfunctions )( function_list_t * p_function_list )
88 {
89     p_function_list->functions.aout.pf_open = aout_Open;
90     p_function_list->functions.aout.pf_setformat = aout_SetFormat;
91     p_function_list->functions.aout.pf_getbufinfo = aout_GetBufInfo;
92     p_function_list->functions.aout.pf_play = aout_Play;
93     p_function_list->functions.aout.pf_close = aout_Close;
94 }
95
96 /*****************************************************************************
97  * aout_Open: opens the audio device (the digital sound processor)
98  *****************************************************************************
99  * This function opens the dsp as a usual non-blocking write-only file, and
100  * modifies the p_aout->p_sys->i_fd with the file's descriptor.
101  *****************************************************************************/
102 static int aout_Open( aout_thread_t *p_aout )
103 {
104     /* Allocate structure */
105     p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
106     if( p_aout->p_sys == NULL )
107     {
108         intf_ErrMsg("aout error: %s", strerror(ENOMEM) );
109         return( 1 );
110     }
111
112     /* Initialize some variables */
113     if( !(p_aout->p_sys->psz_device = config_GetPszVariable( DSP_DEV_VAR )) )
114     {
115         intf_ErrMsg( "aout error: don't know which audio device to open" );
116         free( p_aout->p_sys );
117         return( -1 );
118     }
119
120     /* Open the sound device */
121     if( (p_aout->p_sys->i_fd = open( p_aout->p_sys->psz_device, O_WRONLY ))
122         < 0 )
123     {
124         intf_ErrMsg( "aout error: can't open audio device (%s)",
125                      p_aout->p_sys->psz_device );
126         free( p_aout->p_sys->psz_device );
127         free( p_aout->p_sys );
128         return( -1 );
129     }
130
131     return( 0 );
132 }
133
134 /*****************************************************************************
135  * aout_SetFormat: resets the dsp and sets its format
136  *****************************************************************************
137  * This functions resets the DSP device, tries to initialize the output
138  * format with the value contained in the dsp structure, and if this value
139  * could not be set, the default value returned by ioctl is set. It then
140  * does the same for the stereo mode, and for the output rate.
141  *****************************************************************************/
142 static int aout_SetFormat( aout_thread_t *p_aout )
143 {
144     int i_format;
145     long l_rate;
146     boolean_t b_stereo = p_aout->b_stereo;
147
148     /* Reset the DSP device */
149     if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )
150     {
151         intf_ErrMsg( "aout error: can't reset audio device (%s)",
152                      p_aout->p_sys->psz_device );
153         return( -1 );
154     }
155
156     /* Set the output format */
157     i_format = p_aout->i_format;
158     if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )
159     {
160         intf_ErrMsg( "aout error: can't set audio output format (%i)",
161                      p_aout->i_format );
162         return( -1 );
163     }
164
165     if( i_format != p_aout->i_format )
166     {
167         intf_WarnMsg( 2, "aout warning: audio output format not supported (%i)"
168                       ,p_aout->i_format );
169         p_aout->i_format = i_format;
170     }
171
172     /* Set the number of channels */
173     if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_STEREO, &b_stereo ) < 0 )
174     {
175         intf_ErrMsg( "aout error: can't set number of audio channels (%i)",
176                      p_aout->i_channels );
177         return( -1 );
178     }
179
180     if( b_stereo != p_aout->b_stereo )
181     {
182         intf_WarnMsg( 2, "aout warning: number of audio channels not supported"
183                       " (%i)", p_aout->i_channels );
184         p_aout->b_stereo = b_stereo;
185         p_aout->i_channels = 1 + b_stereo;
186     }
187
188     /* Set the output rate */
189     l_rate = p_aout->l_rate;
190     if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_SPEED, &l_rate ) < 0 )
191     {
192         intf_ErrMsg( "aout error: can't set audio output rate (%li)",
193                      p_aout->l_rate );
194         return( -1 );
195     }
196
197     if( l_rate != p_aout->l_rate )
198     {
199         intf_WarnMsg( 1, "aout warning: audio output rate not supported (%li)",
200                       p_aout->l_rate );
201         p_aout->l_rate = l_rate;
202     }
203
204     return( 0 );
205 }
206
207 /*****************************************************************************
208  * aout_GetBufInfo: buffer status query
209  *****************************************************************************
210  * This function fills in the audio_buf_info structure :
211  * - int fragments : number of available fragments (partially usend ones not
212  *   counted)
213  * - int fragstotal : total number of fragments allocated
214  * - int fragsize : size of a fragment in bytes
215  * - int bytes : available space in bytes (includes partially used fragments)
216  * Note! 'bytes' could be more than fragments*fragsize
217  *****************************************************************************/
218 static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
219 {
220     ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_GETOSPACE,
221            &p_aout->p_sys->audio_buf );
222
223     /* returns the allocated space in bytes */
224     return ( (p_aout->p_sys->audio_buf.fragstotal
225                  * p_aout->p_sys->audio_buf.fragsize)
226             - p_aout->p_sys->audio_buf.bytes );
227 }
228
229 /*****************************************************************************
230  * aout_Play: plays a sound samples buffer
231  *****************************************************************************
232  * This function writes a buffer of i_length bytes in the dsp
233  *****************************************************************************/
234 static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
235 {
236     if( p_aout->b_active )
237     {
238         write( p_aout->p_sys->i_fd, buffer, i_size );
239     }
240 }
241
242 /*****************************************************************************
243  * aout_Close: closes the dsp audio device
244  *****************************************************************************/
245 static void aout_Close( aout_thread_t *p_aout )
246 {
247     close( p_aout->p_sys->i_fd );
248     free( p_aout->p_sys->psz_device );
249 }