Jack2 1.9.10

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