00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "AudioSource.h"
00036
00037
00038 #ifdef SUPPORT_ALSA_DSP
00039
00040 #ifdef HAVE_CONFIG_H
00041 #include "config.h"
00042 #endif
00043
00044 #include "Util.h"
00045 #include "Exception.h"
00046 #include "AlsaDspSource.h"
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 static const char fileid[] = "$Id: AlsaDspSource.cpp,v 1.4 2005/04/04 08:36:16 darkeye Exp $";
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 bool
00069 AlsaDspSource :: isBigEndian ( void ) const throw ()
00070 {
00071 return SND_PCM_FORMAT_S16 == SND_PCM_FORMAT_S16_BE;
00072 }
00073
00074
00075
00076
00077
00078 void
00079 AlsaDspSource :: init ( const char * name ) throw ( Exception )
00080 {
00081 pcmName = Util::strDup( name);
00082 captureHandle = 0;
00083 bufferTime = 1000000;
00084 running = false;
00085 }
00086
00087
00088
00089
00090
00091 void
00092 AlsaDspSource :: strip ( void ) throw ( Exception )
00093 {
00094 if ( isOpen() ) {
00095 close();
00096 }
00097
00098 delete[] pcmName;
00099 }
00100
00101
00102
00103
00104
00105 bool
00106 AlsaDspSource :: open ( void ) throw ( Exception )
00107 {
00108 unsigned int u;
00109 snd_pcm_format_t format;
00110 snd_pcm_hw_params_t *hwParams;
00111
00112 if ( isOpen() ) {
00113 return false;
00114 }
00115
00116 switch ( getBitsPerSample() ) {
00117 case 8:
00118 format = SND_PCM_FORMAT_S8;
00119 break;
00120
00121 case 16:
00122 format = SND_PCM_FORMAT_S16;
00123 break;
00124
00125 default:
00126 return false;
00127 }
00128
00129 if (snd_pcm_open(&captureHandle, pcmName, SND_PCM_STREAM_CAPTURE, 0) < 0) {
00130 captureHandle = 0;
00131 return false;
00132 }
00133
00134 if (snd_pcm_hw_params_malloc(&hwParams) < 0) {
00135 close();
00136 throw Exception( __FILE__, __LINE__, "can't alloc hardware "\
00137 "parameter structure");
00138 }
00139
00140 if (snd_pcm_hw_params_any(captureHandle, hwParams) < 0) {
00141 snd_pcm_hw_params_free(hwParams);
00142 close();
00143 throw Exception( __FILE__, __LINE__, "can't initialize hardware "\
00144 "parameter structure");
00145 }
00146
00147 if (snd_pcm_hw_params_set_access(captureHandle, hwParams,
00148 SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
00149 snd_pcm_hw_params_free(hwParams);
00150 close();
00151 throw Exception( __FILE__, __LINE__, "can't set access type");
00152 }
00153
00154 if (snd_pcm_hw_params_set_format(captureHandle, hwParams, format) < 0) {
00155 snd_pcm_hw_params_free(hwParams);
00156 close();
00157 throw Exception( __FILE__, __LINE__, "can't set sample format");
00158 }
00159
00160 u = getSampleRate();
00161 if (snd_pcm_hw_params_set_rate_near(captureHandle, hwParams, &u, 0) < 0) {
00162 snd_pcm_hw_params_free(hwParams);
00163 close();
00164 throw Exception( __FILE__, __LINE__, "can't set sample rate", u);
00165 }
00166
00167 u = getChannel();
00168 if (snd_pcm_hw_params_set_channels(captureHandle, hwParams, u) < 0) {
00169 snd_pcm_hw_params_free(hwParams);
00170 close();
00171 throw Exception( __FILE__, __LINE__, "can't set channels", u);
00172 }
00173
00174 u = getBufferTime() / 4;
00175 if (snd_pcm_hw_params_set_period_time_near(captureHandle, hwParams, &u, 0)
00176 < 0) {
00177 snd_pcm_hw_params_free(hwParams);
00178 close();
00179 throw Exception( __FILE__, __LINE__, "can't set interrupt frequency");
00180 }
00181
00182 u = getBufferTime();
00183 if (snd_pcm_hw_params_set_buffer_time_near(captureHandle, hwParams, &u, 0)
00184 < 0) {
00185 snd_pcm_hw_params_free(hwParams);
00186 close();
00187 throw Exception( __FILE__, __LINE__, "can't set buffer size");
00188 }
00189
00190 if (snd_pcm_hw_params(captureHandle, hwParams) < 0) {
00191 snd_pcm_hw_params_free(hwParams);
00192 close();
00193 throw Exception( __FILE__, __LINE__, "can't set hardware parameters");
00194 }
00195
00196 snd_pcm_hw_params_free(hwParams);
00197
00198 if (snd_pcm_prepare(captureHandle) < 0) {
00199 close();
00200 throw Exception( __FILE__, __LINE__, "can't prepare audio interface "\
00201 "for use");
00202 }
00203
00204 bytesPerFrame = getChannel() * getBitsPerSample() / 8;
00205
00206 return true;
00207 }
00208
00209
00210
00211
00212
00213 bool
00214 AlsaDspSource :: canRead ( unsigned int sec,
00215 unsigned int usec ) throw ( Exception )
00216 {
00217 if ( !isOpen() ) {
00218 return false;
00219 }
00220
00221 if ( !running ) {
00222 snd_pcm_start(captureHandle);
00223 running = true;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 return true;
00235 }
00236
00237
00238
00239
00240
00241 unsigned int
00242 AlsaDspSource :: read ( void * buf,
00243 unsigned int len ) throw ( Exception )
00244 {
00245 snd_pcm_sframes_t ret;
00246
00247 if ( !isOpen() ) {
00248 return 0;
00249 }
00250
00251 do {
00252 ret = snd_pcm_readi(captureHandle, buf, len/bytesPerFrame);
00253
00254
00255 if (ret == -EPIPE) {
00256 reportEvent(1, "Buffer overrun!");
00257 snd_pcm_prepare(captureHandle);
00258 ret = -EAGAIN;
00259 }
00260 } while (ret == -EAGAIN);
00261
00262 if ( ret < 0 ) {
00263 throw Exception(__FILE__, __LINE__, snd_strerror(ret));
00264 }
00265
00266 running = true;
00267 return ret * bytesPerFrame;
00268 }
00269
00270
00271
00272
00273
00274 void
00275 AlsaDspSource :: close ( void ) throw ( Exception )
00276 {
00277 if ( !isOpen() ) {
00278 return;
00279 }
00280
00281 snd_pcm_close(captureHandle);
00282
00283 captureHandle = 0;
00284 running = false;
00285 }
00286
00287 #endif // HAVE_ALSA_LIB
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310