Jack2 1.9.8
|
00001 /* 00002 Copyright (C) 2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 00018 */ 00019 00020 #include "JackPortAudioAdapter.h" 00021 #include "JackError.h" 00022 00023 namespace Jack 00024 { 00025 00026 int JackPortAudioAdapter::Render(const void* inputBuffer, 00027 void* outputBuffer, 00028 unsigned long framesPerBuffer, 00029 const PaStreamCallbackTimeInfo* timeInfo, 00030 PaStreamCallbackFlags statusFlags, 00031 void* userData) 00032 { 00033 JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(userData); 00034 adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, framesPerBuffer); 00035 return paContinue; 00036 } 00037 00038 JackPortAudioAdapter::JackPortAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) 00039 : JackAudioAdapterInterface(buffer_size, sample_rate) 00040 { 00041 jack_log("JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate); 00042 00043 const JSList* node; 00044 const jack_driver_param_t* param; 00045 int in_max = 0; 00046 int out_max = 0; 00047 00048 fInputDevice = Pa_GetDefaultInputDevice(); 00049 fOutputDevice = Pa_GetDefaultOutputDevice(); 00050 00051 for (node = params; node; node = jack_slist_next(node)) { 00052 param = (const jack_driver_param_t*) node->data; 00053 00054 switch (param->character) 00055 { 00056 case 'i' : 00057 fCaptureChannels = param->value.ui; 00058 break; 00059 case 'o' : 00060 fPlaybackChannels = param->value.ui; 00061 break; 00062 case 'C' : 00063 if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0) { 00064 jack_error("Can't use %s, taking default input device", param->value.str); 00065 fInputDevice = Pa_GetDefaultInputDevice(); 00066 } 00067 break; 00068 case 'P' : 00069 if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0) { 00070 jack_error("Can't use %s, taking default output device", param->value.str); 00071 fOutputDevice = Pa_GetDefaultOutputDevice(); 00072 } 00073 break; 00074 case 'r' : 00075 SetAdaptedSampleRate(param->value.ui); 00076 break; 00077 case 'p' : 00078 SetAdaptedBufferSize(param->value.ui); 00079 break; 00080 case 'd' : 00081 if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0) 00082 jack_error("Can't use %s, taking default input device", param->value.str); 00083 if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0) 00084 jack_error("Can't use %s, taking default output device", param->value.str); 00085 break; 00086 case 'l' : 00087 fPaDevices.DisplayDevicesNames(); 00088 break; 00089 case 'q': 00090 fQuality = param->value.ui; 00091 break; 00092 case 'g': 00093 fRingbufferCurSize = param->value.ui; 00094 fAdaptative = false; 00095 break; 00096 } 00097 } 00098 00099 //max channels 00100 if (in_max == 0 && fInputDevice != paNoDevice) 00101 in_max = fPaDevices.GetDeviceInfo(fInputDevice)->maxInputChannels; 00102 if (out_max == 0 && fOutputDevice != paNoDevice) 00103 out_max = fPaDevices.GetDeviceInfo(fOutputDevice)->maxOutputChannels; 00104 00105 //effective channels 00106 if ((fCaptureChannels == 0) || (fCaptureChannels > in_max)) 00107 fCaptureChannels = in_max; 00108 if ((fPlaybackChannels == 0) || (fPlaybackChannels > out_max)) 00109 fPlaybackChannels = out_max; 00110 00111 //set adapter interface channels 00112 SetInputs(fCaptureChannels); 00113 SetOutputs(fPlaybackChannels); 00114 } 00115 00116 int JackPortAudioAdapter::Open() 00117 { 00118 PaError err; 00119 PaStreamParameters inputParameters; 00120 PaStreamParameters outputParameters; 00121 00122 if (fInputDevice == paNoDevice && fOutputDevice == paNoDevice) { 00123 jack_error("No input and output device!!"); 00124 return -1; 00125 } 00126 00127 jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str()); 00128 jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str()); 00129 jack_log("JackPortAudioAdapter::Open fAdaptedBufferSize = %u fAdaptedSampleRate %u", fAdaptedBufferSize, fAdaptedSampleRate); 00130 00131 inputParameters.device = fInputDevice; 00132 inputParameters.channelCount = fCaptureChannels; 00133 inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output 00134 inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO 00135 ? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency 00136 : 0; 00137 inputParameters.hostApiSpecificStreamInfo = NULL; 00138 00139 outputParameters.device = fOutputDevice; 00140 outputParameters.channelCount = fPlaybackChannels; 00141 outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output 00142 outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO 00143 ? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency 00144 : 0; 00145 outputParameters.hostApiSpecificStreamInfo = NULL; 00146 00147 err = Pa_OpenStream( &fStream, 00148 (fInputDevice == paNoDevice) ? 0 : &inputParameters, 00149 (fOutputDevice == paNoDevice) ? 0 : &outputParameters, 00150 fAdaptedSampleRate, 00151 fAdaptedBufferSize, 00152 paNoFlag, // Clipping is on... 00153 Render, 00154 this); 00155 00156 if (err != paNoError) { 00157 jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err)); 00158 return -1; 00159 } 00160 00161 err = Pa_StartStream(fStream); 00162 00163 if (err != paNoError) { 00164 jack_error("Pa_StartStream error = %s", Pa_GetErrorText(err)); 00165 return -1; 00166 } 00167 00168 jack_log("JackPortAudioAdapter::Open OK"); 00169 return 0; 00170 } 00171 00172 int JackPortAudioAdapter::Close() 00173 { 00174 #ifdef JACK_MONITOR 00175 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); 00176 #endif 00177 jack_log("JackPortAudioAdapter::Close"); 00178 Pa_StopStream(fStream); 00179 jack_log("JackPortAudioAdapter:: Pa_StopStream"); 00180 Pa_CloseStream(fStream); 00181 jack_log("JackPortAudioAdapter:: Pa_CloseStream"); 00182 return 0; 00183 } 00184 00185 int JackPortAudioAdapter::SetSampleRate(jack_nframes_t sample_rate) 00186 { 00187 JackAudioAdapterInterface::SetHostSampleRate(sample_rate); 00188 Close(); 00189 return Open(); 00190 } 00191 00192 int JackPortAudioAdapter::SetBufferSize(jack_nframes_t buffer_size) 00193 { 00194 JackAudioAdapterInterface::SetHostBufferSize(buffer_size); 00195 Close(); 00196 return Open(); 00197 } 00198 00199 } // namespace 00200 00201 #ifdef __cplusplus 00202 extern "C" 00203 { 00204 #endif 00205 00206 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() 00207 { 00208 jack_driver_desc_t * desc; 00209 jack_driver_desc_filler_t filler; 00210 jack_driver_param_value_t value; 00211 00212 desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler); 00213 00214 value.ui = 0; 00215 jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", NULL); 00216 jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", NULL); 00217 00218 strcpy(value.str, "default input device"); 00219 jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set PortAudio device name", NULL); 00220 00221 strcpy(value.str, "default output device"); 00222 jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set PortAudio device name", NULL); 00223 00224 value.ui = 44100U; 00225 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); 00226 00227 value.ui = 512U; 00228 jack_driver_descriptor_add_parameter(desc, &filler, "periodsize", 'p', JackDriverParamUInt, &value, NULL, "Period size", NULL); 00229 00230 strcpy(value.str, "default device"); 00231 jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "PortAudio device name", NULL); 00232 00233 value.i = true; 00234 jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available PortAudio devices", NULL); 00235 00236 value.ui = 0; 00237 jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL); 00238 00239 value.ui = 32768; 00240 jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)"); 00241 00242 return desc; 00243 } 00244 00245 #ifdef __cplusplus 00246 } 00247 #endif 00248