. nouveaux plugins - ne fonctionnent pas encore tous
[vlc.git] / plugins / dsp / aout_dsp.c
1 /*****************************************************************************
2  * aout_dsp.c : dsp functions library
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /* TODO:
24  *
25  * - an aout_sysGetFormats() function
26  * - dsp inline/static
27  * - make this library portable (see mpg123)
28  * - macroify aout_sysPlaySamples &/| aout_sysGetBufInfo ?
29  *
30  */
31
32 /*****************************************************************************
33  * Preamble
34  *****************************************************************************/
35 #include "defs.h"
36
37 #include <errno.h>                                                 /* ENOMEM */
38 #include <fcntl.h>                                       /* open(), O_WRONLY */
39 #include <sys/ioctl.h>                                            /* ioctl() */
40 #include <string.h>                                            /* strerror() */
41 #include <unistd.h>                                      /* write(), close() */
42 #include <stdio.h>                                           /* "intf_msg.h" */
43 #include <stdlib.h>                            /* calloc(), malloc(), free() */
44
45 #ifdef SYS_BSD
46 #include <machine/soundcard.h>       /* SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT,
47                    SNDCTL_DSP_STEREO, SNDCTL_DSP_SPEED, SNDCTL_DSP_GETOSPACE */
48 #else
49 #include <sys/soundcard.h>           /* SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT,
50                    SNDCTL_DSP_STEREO, SNDCTL_DSP_SPEED, SNDCTL_DSP_GETOSPACE */
51 #endif
52
53 #include "config.h"
54 #include "common.h"                                     /* boolean_t, byte_t */
55 #include "threads.h"
56 #include "mtime.h"
57 #include "plugins.h"
58
59 #include "audio_output.h"                                   /* aout_thread_t */
60
61 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
62 #include "main.h"
63
64 /*****************************************************************************
65  * vout_dsp_t: dsp audio output method descriptor
66  *****************************************************************************
67  * This structure is part of the audio output thread descriptor.
68  * It describes the dsp specific properties of an audio device.
69  *****************************************************************************/
70 typedef struct aout_sys_s
71 {
72     audio_buf_info        audio_buf;
73
74 } aout_sys_t;
75
76 /*****************************************************************************
77  * aout_SysOpen: opens the audio device (the digital sound processor)
78  *****************************************************************************
79  * - This function opens the dsp as an usual non-blocking write-only file, and
80  *   modifies the p_aout->p_sys->i_fd with the file's descriptor.
81  *****************************************************************************/
82 int aout_SysOpen( aout_thread_t *p_aout )
83 {
84     /* Allocate structure */
85     p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
86     if( p_aout->p_sys == NULL )
87     {
88         intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
89         return( 1 );
90     }
91
92     /* Initialize some variables */
93     p_aout->i_format = AOUT_DEFAULT_FORMAT;
94     p_aout->psz_device = main_GetPszVariable( AOUT_DSP_VAR, AOUT_DSP_DEFAULT );
95     p_aout->i_channels = 1 + main_GetIntVariable( AOUT_STEREO_VAR, AOUT_STEREO_DEFAULT );
96     p_aout->l_rate     = main_GetIntVariable( AOUT_RATE_VAR, AOUT_RATE_DEFAULT );
97
98     /* Open the sound device */
99     if ( (p_aout->i_fd = open( p_aout->psz_device, O_WRONLY )) < 0 )
100     {
101         intf_ErrMsg( "aout error: can't open audio device (%s)\n", p_aout->psz_device );
102         return( -1 );
103     }
104
105     return( 0 );
106 }
107
108 /*****************************************************************************
109  * aout_SysReset: resets the dsp
110  *****************************************************************************/
111 int aout_SysReset( aout_thread_t *p_aout )
112 {
113     if ( ioctl( p_aout->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )
114     {
115         intf_ErrMsg( "aout error: can't reset audio device (%s)\n", p_aout->psz_device );
116     return( -1 );
117     }
118
119     return( 0 );
120 }
121
122 /*****************************************************************************
123  * aout_SysSetFormat: sets the dsp output format
124  *****************************************************************************
125  * This functions tries to initialize the dsp output format with the value
126  * contained in the dsp structure, and if this value could not be set, the
127  * default value returned by ioctl is set.
128  *****************************************************************************/
129 int aout_SysSetFormat( aout_thread_t *p_aout )
130 {
131     int i_format;
132
133     i_format = p_aout->i_format;
134     if ( ioctl( p_aout->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )
135     {
136         intf_ErrMsg( "aout error: can't set audio output format (%i)\n", p_aout->i_format );
137         return( -1 );
138     }
139
140     if ( i_format != p_aout->i_format )
141     {
142         intf_DbgMsg( "aout debug: audio output format not supported (%i)\n", p_aout->i_format );
143         p_aout->i_format = i_format;
144     }
145
146     return( 0 );
147 }
148
149 /*****************************************************************************
150  * aout_SysSetChannels: sets the dsp's stereo or mono mode
151  *****************************************************************************
152  * This function acts just like the previous one...
153  *****************************************************************************/
154 int aout_SysSetChannels( aout_thread_t *p_aout )
155 {
156     boolean_t b_stereo = p_aout->b_stereo;
157
158     if ( ioctl( p_aout->i_fd, SNDCTL_DSP_STEREO, &b_stereo ) < 0 )
159     {
160         intf_ErrMsg( "aout error: can't set number of audio channels (%i)\n", p_aout->i_channels );
161         return( -1 );
162     }
163
164     if ( b_stereo != p_aout->b_stereo )
165     {
166         intf_DbgMsg( "aout debug: number of audio channels not supported (%i)\n", p_aout->i_channels );
167         p_aout->b_stereo = b_stereo;
168         p_aout->i_channels = 1 + b_stereo;
169     }
170
171     return( 0 );
172 }
173
174 /*****************************************************************************
175  * aout_SysSetRate: sets the dsp's audio output rate
176  *****************************************************************************
177  * This function tries to initialize the dsp with the rate contained in the
178  * dsp structure, but if the dsp doesn't support this value, the function uses
179  * the value returned by ioctl...
180  *****************************************************************************/
181 int aout_SysSetRate( aout_thread_t *p_aout )
182 {
183     long l_rate;
184
185     l_rate = p_aout->l_rate;
186     if ( ioctl( p_aout->i_fd, SNDCTL_DSP_SPEED, &l_rate ) < 0 )
187     {
188         intf_ErrMsg( "aout error: can't set audio output rate (%li)\n", p_aout->l_rate );
189         return( -1 );
190     }
191
192     if ( l_rate != p_aout->l_rate )
193     {
194         intf_DbgMsg( "aout debug: audio output rate not supported (%li)\n", p_aout->l_rate );
195         p_aout->l_rate = l_rate;
196     }
197
198     return( 0 );
199 }
200
201 /*****************************************************************************
202  * aout_SysGetBufInfo: buffer status query
203  *****************************************************************************
204  * This function fills in the audio_buf_info structure :
205  * - int fragments : number of available fragments (partially usend ones not
206  *   counted)
207  * - int fragstotal : total number of fragments allocated
208  * - int fragsize : size of a fragment in bytes
209  * - int bytes : available space in bytes (includes partially used fragments)
210  * Note! 'bytes' could be more than fragments*fragsize
211  *****************************************************************************/
212 long aout_SysGetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
213 {
214     ioctl( p_aout->i_fd, SNDCTL_DSP_GETOSPACE, &p_aout->p_sys->audio_buf );
215
216     /* returns the allocated space in bytes */
217     return ( (p_aout->p_sys->audio_buf.fragstotal
218                  * p_aout->p_sys->audio_buf.fragsize)
219             - p_aout->p_sys->audio_buf.bytes );
220 }
221
222 /*****************************************************************************
223  * aout_SysPlaySamples: plays a sound samples buffer
224  *****************************************************************************
225  * This function writes a buffer of i_length bytes in the dsp
226  *****************************************************************************/
227 void aout_SysPlaySamples( aout_thread_t *p_aout, byte_t *buffer, int i_size )
228 {
229     if( p_aout->b_active )
230     {
231         write( p_aout->i_fd, buffer, i_size );
232     }
233 }
234
235 /*****************************************************************************
236  * aout_SysClose: closes the dsp audio device
237  *****************************************************************************/
238 void aout_SysClose( aout_thread_t *p_aout )
239 {
240     close( p_aout->i_fd );
241 }
242