00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <dev_sound.h>
00024 #include <jutils.h>
00025 #include <generic.h>
00026 #include <config.h>
00027
00028 #define PA_SAMPLE_TYPE paFloat32
00029 #define PA_SAMPLES_PER_FRAME 2
00030 #define PA_NUM_SECONDS 5
00031 #define FRAMES_PER_BUFFER (64)
00032 #define PA_PIPE_SIZE (IN_BUFFER*2)*4
00033
00034 #define INPUT_DEVICE Pa_GetDefaultInputDeviceID()
00035 #define OUTPUT_DEVICE Pa_GetDefaultOutputDeviceID()
00036
00037
00038 #ifdef HAVE_JACK
00039 int dev_jack_process(jack_nframes_t nframes, void *arg) {
00040 jack_nframes_t opframes;
00041 SoundDevice *dev = (SoundDevice*)arg;
00042 if(!dev->jack) return 0;
00043
00044
00045 dev->jack_out_buf = (jack_default_audio_sample_t*)
00046 jack_port_get_buffer(dev->jack_out_port,nframes);
00047 opframes = dev->jack_out_pipe->read
00048 (nframes * sizeof(float) * 2 , dev->jack_out_buf);
00049
00050
00051 dev->jack_in_buf = (jack_default_audio_sample_t*)
00052 jack_port_get_buffer(dev->jack_in_port,nframes);
00053 dev->jack_in_pipe->write
00054 (nframes * sizeof(float) * 2 , dev->jack_in_buf);
00055
00056 return 0;
00057 }
00058
00059 void dev_jack_shutdown(void *arg) {
00060 SoundDevice *dev = (SoundDevice*)arg;
00061
00062 dev->jack = false;
00063 jack_port_unregister(dev->jack_client, dev->jack_in_port);
00064 jack_port_unregister(dev->jack_client, dev->jack_out_port);
00065 jack_deactivate(dev->jack_client);
00066 delete dev->jack_in_pipe;
00067 delete dev->jack_out_pipe;
00068 }
00069 #endif
00070
00071
00072 SoundDevice::SoundDevice() {
00073 memset(&input_device,0,sizeof(input_device));
00074 memset(&output_device,0,sizeof(output_device));
00075 pa_dev.input = &input_device;
00076 pa_dev.output = &output_device;
00077 input_device.pipe = new Pipe(PA_PIPE_SIZE);
00078 input_device.pipe->set_block(false,true);
00079 output_device.pipe = new Pipe(PA_PIPE_SIZE);
00080 output_device.pipe->set_block(true,false);
00081 input_device.pipe->set_output_type("copy_float_to_int16");
00082 output_device.pipe->set_input_type("copy_int16_to_float");
00083 jack = false;
00084 jack_in = false;
00085 jack_out = false;
00086 }
00087
00088 SoundDevice::~SoundDevice() {
00089 close();
00090 }
00091
00092 static int pa_process( void *inputBuffer, void *outputBuffer,
00093 unsigned long framesPerBuffer,
00094 PaTimestamp outTime, void *userData )
00095 {
00096 int readBytes;
00097 PaDevices *dev = (PaDevices *)userData;
00098 long len = framesPerBuffer * (PA_SAMPLES_PER_FRAME*sizeof(PA_SAMPLE_TYPE));
00099 if(inputBuffer != NULL) {
00100 readBytes = dev->input->pipe->write(len,inputBuffer);
00101 }
00102 if(outputBuffer != NULL) {
00103 readBytes = dev->output->pipe->read(len,outputBuffer);
00104
00105
00106
00107
00108
00109 }
00110 return 0;
00111 }
00112
00113 bool SoundDevice::input(bool state) {
00114 bool res = false;
00115 if(jack) return true;
00116 if(!res) res = pa_open(state,PaInput);
00117 return res;
00118 }
00119
00120 PaError SoundDevice::pa_real_open(int mode) {
00121 return Pa_OpenStream( ((mode & PaInput) == PaInput)?&input_device.stream:&output_device.stream,
00122 ((mode & PaInput) == PaInput)?input_device.id:paNoDevice,
00123 ((mode & PaInput) == PaInput)?2:0,
00124 PA_SAMPLE_TYPE,
00125 NULL,
00126 ((mode & PaOutput) == PaOutput)?output_device.id:paNoDevice,
00127 ((mode & PaOutput) == PaOutput)?2:0,
00128 PA_SAMPLE_TYPE,
00129 NULL,
00130 SAMPLE_RATE,
00131 FRAMES_PER_BUFFER,
00132 0,
00133 0,
00134 pa_process,
00135 &pa_dev );
00136 }
00137
00138 bool SoundDevice::pa_open(bool state,int mode) {
00139 PaDevInfo *dev,*other;
00140 int creq,oreq;
00141 char dir[7];
00142 if(mode == PaInput) {
00143 dev = &input_device;
00144 other = &output_device;
00145 creq = PaInput;
00146 oreq = PaOutput;
00147 strcpy(dir,"input");
00148 dev->id = Pa_GetDefaultInputDeviceID();
00149 }
00150 else if(mode == PaOutput) {
00151 dev = &output_device;
00152 other = &input_device;
00153 creq = PaOutput;
00154 oreq = PaInput;
00155 strcpy(dir,"output");
00156 dev->id = Pa_GetDefaultOutputDeviceID();
00157 }
00158 if(state && ((pa_mode & creq) != creq)) {
00159 dev->info = (PaDeviceInfo*)Pa_GetDeviceInfo( dev->id );
00160 if(dev->info) func("%s device: %s",dir,dev->info->name);
00161 else {
00162 error("%s device not available",dir);
00163 return false;
00164 }
00165 if((pa_mode & oreq) == oreq) {
00166
00167 if(other->info) {
00168 if(strcmp(other->info->name,dev->info->name) == 0) {
00169 Pa_StopStream( other->stream );
00170 Pa_CloseStream( other->stream );
00171 err = pa_real_open(PaInput|PaOutput);
00172 if(err == paNoError ) output_device.stream = input_device.stream;
00173 }
00174 else {
00175 err = pa_real_open(mode);
00176 }
00177 }
00178 else {
00179 error("Full duplex has been requested but we don't have portaudio information");
00180 return false;
00181 }
00182 }
00183 else {
00184 err = pa_real_open(mode);
00185 }
00186 if( err != paNoError) {
00187 Pa_Terminate();
00188 error("error opening %s sound device: %s",dir,Pa_GetErrorText( err ) );
00189 return false;
00190 }
00191 else {
00192 err = Pa_StartStream(dev->stream);
00193 if(err != paNoError) {
00194 error("error starting %s audio stream: %s",dir,Pa_GetErrorText( err ) );
00195 return false;
00196 }
00197 pa_mode = pa_mode | creq;
00198 }
00199 } else if(!state && dev->stream) {
00200
00201 if((pa_mode & creq) == creq) {
00202 if((pa_mode & oreq) == oreq) {
00203 pa_mode = oreq;
00204 }
00205 else {
00206 Pa_StopStream(dev->stream);
00207 Pa_CloseStream(dev->stream);
00208 pa_mode = PaNull;
00209 }
00210 }
00211 dev->stream = NULL;
00212 dev->info = NULL;
00213 dev->pipe->flush();
00214
00215 }
00216 return true;
00217 }
00218
00219 bool SoundDevice::output(bool state) {
00220 bool res = false;
00221 if(jack) return true;
00222 if(!res) res = pa_open(state,PaOutput);
00223 return res;
00224 }
00225
00226 bool SoundDevice::open(bool read, bool write) {
00227
00228
00229
00230 #ifdef HAVE_JACK
00231
00232 jack_sample_size = sizeof(jack_default_audio_sample_t);
00233 if(!jack)
00234 if( (jack_client = jack_client_new("MuSE")) !=0 ) {
00235 notice("jack audio daemon detected");
00236 act("hooking in/out sound channels");
00237 warning("this feature is still experimental and won't work!");
00238 warning("you need to stop jack and free the audio card");
00239 jack = true;
00240 jack_samplerate = jack_get_sample_rate(jack_client);
00241 jack_set_process_callback(jack_client, dev_jack_process, this);
00242 jack_on_shutdown(jack_client,dev_jack_shutdown,this);
00243
00244 jack_in_pipe = new Pipe();
00245 jack_in_pipe->set_output_type("copy_float_to_int16");
00246 jack_in_pipe->set_block(false,true);
00247
00248 jack_out_pipe = new Pipe();
00249 jack_out_pipe->set_input_type("copy_int16_to_float");
00250 jack_in_pipe->set_block(true,false);
00251
00252
00253 jack_in_port = jack_port_register(jack_client, "capture",
00254 JACK_DEFAULT_AUDIO_TYPE,
00255 JackPortIsInput, 0);
00256
00257 jack_out_port = jack_port_register(jack_client, "playback",
00258 JACK_DEFAULT_AUDIO_TYPE,
00259 JackPortIsOutput, 0);
00260
00261 jack_activate(jack_client);
00262 return true;
00263 }
00264 #endif
00265 if( ! output(write) ) return false;
00266
00267
00268
00269 return true;
00270 }
00271
00272 void SoundDevice::close() {
00273 if((pa_mode&PaInput) == PaInput) {
00274 if((pa_mode&PaOutput) == PaOutput) {
00275 pa_mode = PaOutput;
00276 if(output_device.stream == input_device.stream)
00277 output_device.stream = NULL;
00278 }
00279 else pa_mode = PaNull;
00280 if(input_device.stream) {
00281 Pa_StopStream( input_device.stream);
00282 Pa_CloseStream( input_device.stream );
00283 input_device.stream = NULL;
00284 }
00285 input_device.pipe->flush();
00286
00287 }
00288
00289 if((pa_mode&PaOutput) == PaOutput) {
00290 if(output_device.stream) {
00291 Pa_StopStream( output_device.stream);
00292 Pa_CloseStream( output_device.stream );
00293 output_device.stream = NULL;
00294 }
00295 output_device.pipe->flush();
00296 if((pa_mode&PaInput) == PaInput)
00297 pa_mode = PaInput;
00298 else pa_mode = PaNull;
00299 }
00300
00301 }
00302
00303 int SoundDevice::read(void *buf, int len) {
00304
00305 int res = -1;
00306
00307 if(jack) {
00308
00309 res = jack_in_pipe->read(len*2,buf);
00310
00311 } else if(input_device.stream) {
00312
00313
00314 res = input_device.pipe->read(len*2,buf);
00315 }
00316 return res;
00317 }
00318
00319 int SoundDevice::write(void *buf, int len) {
00320
00321 int res = -1;
00322
00323 if(jack) {
00324
00325 res = jack_out_pipe->write(len*2,buf);
00326
00327 } else if(output_device.stream) {
00328 res = output_device.pipe->write(len,buf);
00329 }
00330 return res;
00331 }
00332
00333 void SoundDevice::flush_output() {
00334 output_device.pipe->flush();
00335 }
00336 void SoundDevice::flush_input() {
00337 input_device.pipe->flush();
00338 }