20 #include "JackDriverLoader.h"    21 #include "driver_interface.h"    22 #include "JackPortAudioDriver.h"    23 #include "JackEngineControl.h"    24 #include "JackGraphManager.h"    25 #include "JackError.h"    27 #include "JackTools.h"    28 #include "JackCompilerDeps.h"    37 int JackPortAudioDriver::Render(
const void* inputBuffer, 
void* outputBuffer,
    38                                 unsigned long framesPerBuffer,
    43     return static_cast<JackPortAudioDriver*
>(userData)->Render(inputBuffer, outputBuffer, statusFlags);
    46 int JackPortAudioDriver::Render(
const void* inputBuffer, 
void* outputBuffer, 
PaStreamCallbackFlags statusFlags)
    48     fInputBuffer = (jack_default_audio_sample_t**)inputBuffer;
    49     fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer;
    53             jack_error(
"JackPortAudioDriver::Render paOutputUnderflow");
    55             jack_error(
"JackPortAudioDriver::Render paInputUnderflow");
    57             jack_error(
"JackPortAudioDriver::Render paOutputOverflow");
    59             jack_error(
"JackPortAudioDriver::Render paInputOverflow");
    61             jack_error(
"JackPortAudioDriver::Render paOutputUnderflow");
    63         if (statusFlags != paPrimingOutput) {
    64             jack_time_t cur_time = GetMicroSeconds();
    65             NotifyXRun(cur_time, 
float(cur_time - fBeginDateUst));   
    70     set_threaded_log_function();
    72     return (Process() == 0) ? paContinue : paAbort;
    75 int JackPortAudioDriver::Read()
    77     for (
int i = 0; i < fCaptureChannels; i++) {
    78         memcpy(GetInputBuffer(i), fInputBuffer[i], 
sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
    83 int JackPortAudioDriver::Write()
    85     for (
int i = 0; i < fPlaybackChannels; i++) {
    86         memcpy(fOutputBuffer[i], GetOutputBuffer(i), 
sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
    91 PaError JackPortAudioDriver::OpenStream(jack_nframes_t buffer_size)
    96     jack_log(
"JackPortAudioDriver::OpenStream buffer_size = %d", buffer_size);
    99     inputParameters.
device = fInputDevice;
   103                                        ? ((fPaDevices->GetHostFromDevice(fInputDevice) == 
"ASIO") ? 0 : 
Pa_GetDeviceInfo(inputParameters.
device)->defaultLowInputLatency)
   107     outputParameters.
device = fOutputDevice;
   111                                         ? ((fPaDevices->GetHostFromDevice(fOutputDevice) == 
"ASIO") ? 0 : 
Pa_GetDeviceInfo(outputParameters.
device)->defaultLowOutputLatency)
   116                         (fInputDevice == 
paNoDevice) ? 0 : &inputParameters,
   117                         (fOutputDevice == 
paNoDevice) ? 0 : &outputParameters,
   118                         fEngineControl->fSampleRate,
   125 void JackPortAudioDriver::UpdateLatencies()
   134     for (
int i = 0; i < fCaptureChannels; i++) {
   135         input_range.
max = input_range.
min = fEngineControl->fBufferSize + (info->
inputLatency * fEngineControl->fSampleRate) + fCaptureLatency;
   136         fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
   139     for (
int i = 0; i < fPlaybackChannels; i++) {
   140         output_range.
max = output_range.
min = (info->
outputLatency * fEngineControl->fSampleRate) + fPlaybackLatency;
   141         if (fEngineControl->fSyncMode) {
   142             output_range.
max = output_range.
min += fEngineControl->fBufferSize;
   144             output_range.
max = output_range.
min += fEngineControl->fBufferSize * 2;
   146         fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
   147         if (fWithMonitorPorts) {
   148             monitor_range.
min = monitor_range.
max = fEngineControl->fBufferSize;
   149             fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
   154 int JackPortAudioDriver::Open(jack_nframes_t buffer_size,
   155                               jack_nframes_t samplerate,
   161                               const char* capture_driver_uid,
   162                               const char* playback_driver_uid,
   163                               jack_nframes_t capture_latency,
   164                               jack_nframes_t playback_latency)
   174     fCaptureLatency = capture_latency;
   175     fPlaybackLatency = playback_latency;
   177     jack_log(
"JackPortAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s samplerate = %ld",
   178              buffer_size, inchannels, outchannels, capture_driver_uid, playback_driver_uid, samplerate);
   182         if (fPaDevices->GetInputDeviceFromName(capture_driver_uid, fInputDevice, in_max) < 0) {
   187         if (fPaDevices->GetOutputDeviceFromName(playback_driver_uid, fOutputDevice, out_max) < 0) {
   193     if (buffer_size == 0) {
   194         buffer_size = fPaDevices->GetPreferredBufferSize(fInputDevice);
   195         jack_log(
"JackPortAudioDriver::Open preferred buffer_size = %d", buffer_size);
   199     char capture_driver_name[JACK_CLIENT_NAME_SIZE];
   200     char playback_driver_name[JACK_CLIENT_NAME_SIZE];
   201     snprintf(capture_driver_name, 
sizeof(capture_driver_name), 
"%s", capture_driver_uid);
   202     snprintf(playback_driver_name, 
sizeof(playback_driver_name), 
"%s", playback_driver_uid);
   203     if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor,
   204         capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) {
   208     jack_log(
"JackPortAudioDriver::Open fInputDevice = %d, fOutputDevice %d", fInputDevice, fOutputDevice);
   211     if (inchannels == 0) {
   212         jack_log(
"JackPortAudioDriver::Open setup max in channels = %ld", in_max);
   215     if (outchannels == 0) {
   216         jack_log(
"JackPortAudioDriver::Open setup max out channels = %ld", out_max);
   217         outchannels = out_max;
   221     if (inchannels > in_max) {
   222         jack_error(
"This device has only %d available input channels.", in_max);
   225     if (outchannels > out_max) {
   226         jack_error(
"This device has only %d available output channels.", out_max);
   227         outchannels = out_max;
   231     fCaptureChannels = inchannels;
   232     fPlaybackChannels = outchannels;
   234     err = OpenStream(buffer_size);
   235     if (err != paNoError) {
   241     fEngineControl->fPeriod = fEngineControl->fPeriodUsecs * 1000;
   242     fEngineControl->fComputation = JackTools::ComputationMicroSec(fEngineControl->fBufferSize) * 1000;
   243     fEngineControl->fConstraint = fEngineControl->fPeriodUsecs * 1000;
   249     JackAudioDriver::Close();
   250     jack_error(
"Can't open default PortAudio device");
   254 int JackPortAudioDriver::Close()
   257     jack_log(
"JackPortAudioDriver::Close");
   258     JackAudioDriver::Close();
   260     if (err != paNoError) {
   265     return (err != paNoError) ? -1 : 0;
   268 int JackPortAudioDriver::Attach()
   270     if (JackAudioDriver::Attach() == 0) {
   274 #if defined(HAVE_ASIO)   275         if (fInputDevice != 
paNoDevice && fPaDevices->GetHostFromDevice(fInputDevice) == 
"ASIO") {
   276             for (
int i = 0; i < fCaptureChannels; i++) {
   278                     JackPort* port = fGraphManager->GetPort(fCapturePortList[i]);
   279                     port->SetAlias(alias);
   284         if (fOutputDevice != 
paNoDevice && fPaDevices->GetHostFromDevice(fOutputDevice) == 
"ASIO") {
   285             for (
int i = 0; i < fPlaybackChannels; i++) {
   287                     JackPort* port = fGraphManager->GetPort(fPlaybackPortList[i]);
   288                     port->SetAlias(alias);
   300 int JackPortAudioDriver::Start()
   302     jack_log(
"JackPortAudioDriver::Start");
   303     if (JackAudioDriver::Start() == 0) {
   309         JackAudioDriver::Stop();
   314 int JackPortAudioDriver::Stop()
   316     jack_log(
"JackPortAudioDriver::Stop");
   321     if (JackAudioDriver::Stop() < 0) {
   324         return (err == paNoError) ? 0 : -1;
   328 int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
   341     err = OpenStream(buffer_size);
   342     if (err != paNoError) {
   346         JackAudioDriver::SetBufferSize(buffer_size); 
   362 #include "JackCompilerDeps.h"   370         desc = jack_driver_descriptor_construct(
"portaudio", JackDriverMaster, 
"PortAudio API based audio backend", &filler);
   373         jack_driver_descriptor_add_parameter(desc, &filler, 
"channels", 
'c', JackDriverParamUInt, &value, NULL, 
"Maximum number of channels", NULL);
   374         jack_driver_descriptor_add_parameter(desc, &filler, 
"inchannels", 
'i', JackDriverParamUInt, &value, NULL, 
"Maximum number of input channels", NULL);
   375         jack_driver_descriptor_add_parameter(desc, &filler, 
"outchannels", 
'o', JackDriverParamUInt, &value, NULL, 
"Maximum number of output channels", NULL);
   377         jack_driver_descriptor_add_parameter(desc, &filler, 
"capture", 
'C', JackDriverParamString, &value, NULL, 
"Provide capture ports. Optionally set PortAudio device name", NULL);
   379         jack_driver_descriptor_add_parameter(desc, &filler, 
"playback", 
'P', JackDriverParamString, &value, NULL, 
"Provide playback ports. Optionally set PortAudio device name", NULL);
   382         jack_driver_descriptor_add_parameter(desc, &filler, 
"monitor", 
'm', JackDriverParamBool, &value, NULL, 
"Provide monitor ports for the output", NULL);
   385         jack_driver_descriptor_add_parameter(desc, &filler, 
"duplex", 
'D', JackDriverParamBool, &value, NULL, 
"Provide both capture and playback ports", NULL);
   388         jack_driver_descriptor_add_parameter(desc, &filler, 
"rate", 
'r', JackDriverParamUInt, &value, NULL, 
"Sample rate", NULL);
   391         jack_driver_descriptor_add_parameter(desc, &filler, 
"period", 
'p', JackDriverParamUInt, &value, NULL, 
"Frames per period", 
"Frames per period. If 0 and ASIO driver, will take preferred value");
   393         jack_driver_descriptor_add_parameter(desc, &filler, 
"device", 
'd', JackDriverParamString, &value, NULL, 
"PortAudio device name", NULL);
   396         jack_driver_descriptor_add_parameter(desc, &filler, 
"input-latency", 
'I', JackDriverParamUInt, &value, NULL, 
"Extra input latency", NULL);
   397         jack_driver_descriptor_add_parameter(desc, &filler, 
"output-latency", 
'O', JackDriverParamUInt, &value, NULL, 
"Extra output latency", NULL);
   400         jack_driver_descriptor_add_parameter(desc, &filler, 
"list-devices", 
'l', JackDriverParamBool, &value, NULL, 
"Display available PortAudio devices", NULL);
   407         jack_nframes_t srate = 44100;
   408         jack_nframes_t frames_per_interrupt = 512;
   409         const char* capture_pcm_name = 
"";
   410         const char* playback_pcm_name = 
"";
   411         bool capture = 
false;
   412         bool playback = 
false;
   415         bool monitor = 
false;
   418         jack_nframes_t systemic_input_latency = 0;
   419         jack_nframes_t systemic_output_latency = 0;
   422         for (node = params; node; node = jack_slist_next(node))
   426             switch (param->character) {
   429                 capture_pcm_name = param->value.str;
   430                 playback_pcm_name = param->value.str;
   439                 chan_in = chan_out = (int)param->value.ui;
   443                 chan_in = (
int)param->value.ui;
   447                 chan_out = (int)param->value.ui;
   452                 if (strcmp(param->value.str, 
"none") != 0) {
   453                     capture_pcm_name = param->value.str;
   459                 if (strcmp(param->value.str, 
"none") != 0) {
   460                     playback_pcm_name = param->value.str;
   465                 monitor = param->value.i;
   469                 srate = param->value.ui;
   473                 frames_per_interrupt = (
unsigned int)param->value.ui;
   477                 systemic_input_latency = param->value.ui;
   481                 systemic_output_latency = param->value.ui;
   485                 pa_devices->DisplayDevicesNames();
   492         if (!capture && !playback) {
   498         if (driver->Open(frames_per_interrupt, srate, capture, playback,
   499             chan_in, chan_out, monitor, capture_pcm_name,
   500             playback_pcm_name, systemic_input_latency,
   501             systemic_output_latency) == 0) {
 
Locked Engine, access to methods is serialized using a mutex. 
PaError Pa_StopStream(PaStream *stream)
#define paOutputUnderflow
Inter process synchronization using POSIX semaphore. 
const PaStreamInfo * Pa_GetStreamInfo(PaStream *stream)
SERVER_EXPORT void jack_error(const char *fmt,...)
PaError Pa_OpenStream(PaStream **stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData)
PaError PaAsio_GetOutputChannelName(PaDeviceIndex device, int channelIndex, const char **channelName)
PaError Pa_StartStream(PaStream *stream)
void * hostApiSpecificStreamInfo
PaError PaAsio_GetInputChannelName(PaDeviceIndex device, int channelIndex, const char **channelName)
PaSampleFormat sampleFormat
unsigned long PaStreamCallbackFlags
The base interface for drivers clients. 
const PaDeviceInfo * Pa_GetDeviceInfo(PaDeviceIndex device)
const char * Pa_GetErrorText(PaError errorCode)
SERVER_EXPORT void jack_log(const char *fmt,...)
PaError Pa_CloseStream(PaStream *stream)
A PortAudio Devices manager.