Jack2 1.9.8

JackAudioAdapter.cpp

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 "JackAudioAdapter.h"
00021 #include "JackError.h"
00022 #include "JackCompilerDeps.h"
00023 #include "JackTools.h"
00024 #include "JackTime.h"
00025 #include "jslist.h"
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <assert.h>
00029 
00030 using namespace std;
00031 
00032 namespace Jack
00033 {
00034 
00035 int JackAudioAdapter::Process(jack_nframes_t frames, void* arg)
00036 {
00037     JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
00038     jack_default_audio_sample_t* inputBuffer[adapter->fAudioAdapter->GetInputs()];
00039     jack_default_audio_sample_t* outputBuffer[adapter->fAudioAdapter->GetOutputs()];
00040 
00041     // Always clear output
00042     for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
00043         inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fCapturePortList[i], frames);
00044         memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t));
00045     }
00046 
00047     for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
00048         outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames);
00049     }
00050 
00051     adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames);
00052     return 0;
00053 }
00054 
00055 int JackAudioAdapter::BufferSize(jack_nframes_t buffer_size, void* arg)
00056 {
00057     JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
00058     adapter->Reset();
00059     adapter->fAudioAdapter->SetHostBufferSize(buffer_size);
00060     return 0;
00061 }
00062 
00063 int JackAudioAdapter::SampleRate(jack_nframes_t sample_rate, void* arg)
00064 {
00065     JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
00066     adapter->Reset();
00067     adapter->fAudioAdapter->SetHostSampleRate(sample_rate);
00068     return 0;
00069 }
00070 
00071 void JackAudioAdapter::Latency(jack_latency_callback_mode_t mode, void* arg)
00072 {
00073     JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
00074 
00075     if (mode == JackCaptureLatency) {
00076         for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
00077             jack_latency_range_t range;
00078             range.min = range.max = adapter->fAudioAdapter->GetInputLatency(i);
00079             jack_port_set_latency_range(adapter->fCapturePortList[i], JackCaptureLatency, &range);
00080         }
00081 
00082     } else {
00083         for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
00084             jack_latency_range_t range;
00085             range.min = range.max = adapter->fAudioAdapter->GetOutputLatency(i);
00086             jack_port_set_latency_range(adapter->fPlaybackPortList[i], JackPlaybackLatency, &range);
00087         }
00088     }
00089 }
00090 
00091 JackAudioAdapter::JackAudioAdapter(jack_client_t* client, JackAudioAdapterInterface* audio_io, const JSList* params)
00092     :fClient(client), fAudioAdapter(audio_io)
00093 {
00094     const JSList* node;
00095     const jack_driver_param_t* param;
00096     fAutoConnect = false;
00097 
00098     for (node = params; node; node = jack_slist_next(node)) {
00099         param = (const jack_driver_param_t*)node->data;
00100         switch (param->character) {
00101             case 'c':
00102                 fAutoConnect = true;
00103                 break;
00104         }
00105     }
00106 }
00107 
00108 JackAudioAdapter::~JackAudioAdapter()
00109 {
00110     // When called, Close has already been used for the client, thus ports are already unregistered.
00111     delete fAudioAdapter;
00112 }
00113 
00114 void JackAudioAdapter::FreePorts()
00115 {
00116     for (int i = 0; i < fAudioAdapter->GetInputs(); i++) {
00117         if (fCapturePortList[i]) {
00118             jack_port_unregister(fClient, fCapturePortList[i]);
00119         }
00120     }
00121     for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) {
00122         if (fPlaybackPortList[i]) {
00123             jack_port_unregister(fClient, fPlaybackPortList[i]);
00124         }
00125     }
00126 
00127     delete[] fCapturePortList;
00128     delete[] fPlaybackPortList;
00129 }
00130 
00131 void JackAudioAdapter::ConnectPorts()
00132 {
00133     const char** ports;
00134 
00135     ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
00136     if (ports != NULL) {
00137         for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) {
00138             jack_connect(fClient, jack_port_name(fCapturePortList[i]), ports[i]);
00139         }
00140         jack_free(ports);
00141     }
00142 
00143     ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
00144     if (ports != NULL) {
00145         for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) {
00146             jack_connect(fClient, ports[i], jack_port_name(fPlaybackPortList[i]));
00147         }
00148         jack_free(ports);
00149     }
00150 }
00151 
00152 void JackAudioAdapter::Reset()
00153 {
00154     fAudioAdapter->Reset();
00155 }
00156 
00157 int JackAudioAdapter::Open()
00158 {
00159     char name[32];
00160     jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs());
00161     fAudioAdapter->Create();
00162 
00163     //jack ports
00164     fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()];
00165     fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()];
00166 
00167     for (int i = 0; i < fAudioAdapter->GetInputs(); i++) {
00168         snprintf(name, sizeof(name), "capture_%d", i + 1);
00169         if ((fCapturePortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, 0)) == NULL) {
00170             goto fail;
00171         }
00172     }
00173 
00174     for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) {
00175         snprintf(name, sizeof(name), "playback_%d", i + 1);
00176         if ((fPlaybackPortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, 0)) == NULL) {
00177             goto fail;
00178         }
00179     }
00180 
00181     //callbacks and activation
00182     if (jack_set_process_callback(fClient, Process, this) < 0) {
00183         goto fail;
00184     }
00185     if (jack_set_buffer_size_callback(fClient, BufferSize, this) < 0) {
00186         goto fail;
00187     }
00188     if (jack_set_sample_rate_callback(fClient, SampleRate, this) < 0) {
00189         goto fail;
00190     }
00191     if (jack_set_latency_callback(fClient, Latency, this) < 0) {
00192         goto fail;
00193     }
00194     if (jack_activate(fClient) < 0) {
00195         goto fail;
00196     }
00197 
00198     if (fAutoConnect) {
00199         ConnectPorts();
00200     }
00201 
00202     // Ring buffers are now allocated...
00203     return fAudioAdapter->Open();
00204     return 0;
00205 
00206 fail:
00207     FreePorts();
00208     fAudioAdapter->Destroy();
00209     return -1;
00210 }
00211 
00212 int JackAudioAdapter::Close()
00213 {
00214     fAudioAdapter->Close();
00215     fAudioAdapter->Destroy();
00216     return 0;
00217 }
00218 
00219 } //namespace