Jack2 1.9.10
|
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 static_cast<JackPortAudioAdapter*>(userData)->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, framesPerBuffer); 00034 return paContinue; 00035 } 00036 00037 JackPortAudioAdapter::JackPortAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) 00038 : JackAudioAdapterInterface(buffer_size, sample_rate) 00039 { 00040 jack_log("JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate); 00041 00042 const JSList* node; 00043 const jack_driver_param_t* param; 00044 int in_max = 0; 00045 int out_max = 0; 00046 00047 fInputDevice = Pa_GetDefaultInputDevice(); 00048 fOutputDevice = Pa_GetDefaultOutputDevice(); 00049 00050 for (node = params; node; node = jack_slist_next(node)) { 00051 param = (const jack_driver_param_t*) node->data; 00052 00053 switch (param->character) 00054 { 00055 case 'i' : 00056 fCaptureChannels = param->value.ui; 00057 break; 00058 case 'o' : 00059 fPlaybackChannels = param->value.ui; 00060 break; 00061 case 'C' : 00062 if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0) { 00063 jack_error("Can't use %s, taking default input device", param->value.str); 00064 fInputDevice = Pa_GetDefaultInputDevice(); 00065 } 00066 break; 00067 case 'P' : 00068 if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0) { 00069 jack_error("Can't use %s, taking default output device", param->value.str); 00070 fOutputDevice = Pa_GetDefaultOutputDevice(); 00071 } 00072 break; 00073 case 'r' : 00074 SetAdaptedSampleRate(param->value.ui); 00075 break; 00076 case 'p' : 00077 SetAdaptedBufferSize(param->value.ui); 00078 break; 00079 case 'd' : 00080 if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0) 00081 jack_error("Can't use %s, taking default input device", param->value.str); 00082 if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0) 00083 jack_error("Can't use %s, taking default output device", param->value.str); 00084 break; 00085 case 'l' : 00086 fPaDevices.DisplayDevicesNames(); 00087 break; 00088 case 'q': 00089 fQuality = param->value.ui; 00090 break; 00091 case 'g': 00092 fRingbufferCurSize = param->value.ui; 00093 fAdaptative = false; 00094 break; 00095 } 00096 } 00097 00098 //max channels 00099 if (in_max == 0 && fInputDevice != paNoDevice) 00100 in_max = fPaDevices.GetDeviceInfo(fInputDevice)->maxInputChannels; 00101 if (out_max == 0 && fOutputDevice != paNoDevice) 00102 out_max = fPaDevices.GetDeviceInfo(fOutputDevice)->maxOutputChannels; 00103 00104 //effective channels 00105 if ((fCaptureChannels == 0) || (fCaptureChannels > in_max)) 00106 fCaptureChannels = in_max; 00107 if ((fPlaybackChannels == 0) || (fPlaybackChannels > out_max)) 00108 fPlaybackChannels = out_max; 00109 00110 //set adapter interface channels 00111 SetInputs(fCaptureChannels); 00112 SetOutputs(fPlaybackChannels); 00113 } 00114 00115 int JackPortAudioAdapter::Open() 00116 { 00117 PaError err; 00118 PaStreamParameters inputParameters; 00119 PaStreamParameters outputParameters; 00120 00121 if (fInputDevice == paNoDevice && fOutputDevice == paNoDevice) { 00122 jack_error("No input and output device!!"); 00123 return -1; 00124 } 00125 00126 jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str()); 00127 jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str()); 00128 jack_log("JackPortAudioAdapter::Open fAdaptedBufferSize = %u fAdaptedSampleRate %u", fAdaptedBufferSize, fAdaptedSampleRate); 00129 00130 inputParameters.device = fInputDevice; 00131 inputParameters.channelCount = fCaptureChannels; 00132 inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output 00133 inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO 00134 ? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency 00135 : 0; 00136 inputParameters.hostApiSpecificStreamInfo = NULL; 00137 00138 outputParameters.device = fOutputDevice; 00139 outputParameters.channelCount = fPlaybackChannels; 00140 outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output 00141 outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO 00142 ? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency 00143 : 0; 00144 outputParameters.hostApiSpecificStreamInfo = NULL; 00145 00146 err = Pa_OpenStream( &fStream, 00147 (fInputDevice == paNoDevice) ? 0 : &inputParameters, 00148 (fOutputDevice == paNoDevice) ? 0 : &outputParameters, 00149 fAdaptedSampleRate, 00150 fAdaptedBufferSize, 00151 paNoFlag, // Clipping is on... 00152 Render, 00153 this); 00154 00155 if (err != paNoError) { 00156 jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err)); 00157 return -1; 00158 } 00159 00160 err = Pa_StartStream(fStream); 00161 00162 if (err != paNoError) { 00163 jack_error("Pa_StartStream error = %s", Pa_GetErrorText(err)); 00164 return -1; 00165 } 00166 00167 jack_log("JackPortAudioAdapter::Open OK"); 00168 return 0; 00169 } 00170 00171 int JackPortAudioAdapter::Close() 00172 { 00173 #ifdef JACK_MONITOR 00174 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); 00175 #endif 00176 jack_log("JackPortAudioAdapter::Close"); 00177 Pa_StopStream(fStream); 00178 jack_log("JackPortAudioAdapter:: Pa_StopStream"); 00179 Pa_CloseStream(fStream); 00180 jack_log("JackPortAudioAdapter:: Pa_CloseStream"); 00181 return 0; 00182 } 00183 00184 int JackPortAudioAdapter::SetSampleRate(jack_nframes_t sample_rate) 00185 { 00186 JackAudioAdapterInterface::SetHostSampleRate(sample_rate); 00187 Close(); 00188 return Open(); 00189 } 00190 00191 int JackPortAudioAdapter::SetBufferSize(jack_nframes_t buffer_size) 00192 { 00193 JackAudioAdapterInterface::SetHostBufferSize(buffer_size); 00194 Close(); 00195 return Open(); 00196 } 00197 00198 } // namespace 00199 00200 #ifdef __cplusplus 00201 extern "C" 00202 { 00203 #endif 00204 00205 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() 00206 { 00207 jack_driver_desc_t * desc; 00208 jack_driver_desc_filler_t filler; 00209 jack_driver_param_value_t value; 00210 00211 desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler); 00212 00213 value.ui = 0; 00214 jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", NULL); 00215 jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", NULL); 00216 00217 jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set PortAudio device name", NULL); 00218 00219 jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set PortAudio device name", NULL); 00220 00221 value.ui = 44100U; 00222 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL); 00223 00224 value.ui = 512U; 00225 jack_driver_descriptor_add_parameter(desc, &filler, "periodsize", 'p', JackDriverParamUInt, &value, NULL, "Period size", NULL); 00226 00227 jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "PortAudio device name", NULL); 00228 00229 value.i = true; 00230 jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available PortAudio devices", NULL); 00231 00232 value.ui = 0; 00233 jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL); 00234 00235 value.ui = 32768; 00236 jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)"); 00237 00238 return desc; 00239 } 00240 00241 #ifdef __cplusplus 00242 } 00243 #endif 00244