Merge branch 'master' into develop
[jack2.git] / common / JackAudioAdapter.cpp
blob3eda1167c928897cc48b301bea572236699c40dc
1 /*
2 Copyright (C) 2008 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "JackAudioAdapter.h"
21 #include "JackError.h"
22 #include "JackCompilerDeps.h"
23 #include "JackTools.h"
24 #include "JackTime.h"
25 #include "jslist.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <assert.h>
30 using namespace std;
32 namespace Jack
35 int JackAudioAdapter::Process(jack_nframes_t frames, void* arg)
37 JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
38 return adapter->ProcessAux(frames);
41 int JackAudioAdapter::ProcessAux(jack_nframes_t frames)
43 // Always clear output
44 for (int i = 0; i < fAudioAdapter->GetInputs(); i++) {
45 fInputBufferList[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(fCapturePortList[i], frames);
46 memset(fInputBufferList[i], 0, frames * sizeof(jack_default_audio_sample_t));
49 for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) {
50 fOutputBufferList[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(fPlaybackPortList[i], frames);
53 fAudioAdapter->PullAndPush(fInputBufferList, fOutputBufferList, frames);
54 return 0;
57 int JackAudioAdapter::BufferSize(jack_nframes_t buffer_size, void* arg)
59 JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
60 adapter->Reset();
61 adapter->fAudioAdapter->SetHostBufferSize(buffer_size);
62 return 0;
65 int JackAudioAdapter::SampleRate(jack_nframes_t sample_rate, void* arg)
67 JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
68 adapter->Reset();
69 adapter->fAudioAdapter->SetHostSampleRate(sample_rate);
70 return 0;
73 void JackAudioAdapter::Latency(jack_latency_callback_mode_t mode, void* arg)
75 JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
77 if (mode == JackCaptureLatency) {
78 for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
79 jack_latency_range_t range;
80 range.min = range.max = adapter->fAudioAdapter->GetInputLatency(i);
81 jack_port_set_latency_range(adapter->fCapturePortList[i], JackCaptureLatency, &range);
84 } else {
85 for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
86 jack_latency_range_t range;
87 range.min = range.max = adapter->fAudioAdapter->GetOutputLatency(i);
88 jack_port_set_latency_range(adapter->fPlaybackPortList[i], JackPlaybackLatency, &range);
93 JackAudioAdapter::JackAudioAdapter(jack_client_t* client, JackAudioAdapterInterface* audio_io, const JSList* params)
94 :fClient(client), fAudioAdapter(audio_io)
96 const JSList* node;
97 const jack_driver_param_t* param;
98 fAutoConnect = false;
100 for (node = params; node; node = jack_slist_next(node)) {
101 param = (const jack_driver_param_t*)node->data;
102 switch (param->character) {
103 case 'c':
104 fAutoConnect = true;
105 break;
110 JackAudioAdapter::~JackAudioAdapter()
112 // When called, Close has already been used for the client, thus ports are already unregistered.
113 delete fAudioAdapter;
116 void JackAudioAdapter::FreePorts()
118 for (int i = 0; i < fAudioAdapter->GetInputs(); i++) {
119 if (fCapturePortList[i]) {
120 jack_port_unregister(fClient, fCapturePortList[i]);
123 for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) {
124 if (fPlaybackPortList[i]) {
125 jack_port_unregister(fClient, fPlaybackPortList[i]);
129 delete[] fCapturePortList;
130 delete[] fPlaybackPortList;
132 delete[] fInputBufferList;
133 delete[] fOutputBufferList;
136 void JackAudioAdapter::ConnectPorts()
138 const char** ports;
140 ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
141 if (ports != NULL) {
142 for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) {
143 jack_connect(fClient, jack_port_name(fCapturePortList[i]), ports[i]);
145 jack_free(ports);
148 ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
149 if (ports != NULL) {
150 for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) {
151 jack_connect(fClient, ports[i], jack_port_name(fPlaybackPortList[i]));
153 jack_free(ports);
157 void JackAudioAdapter::Reset()
159 fAudioAdapter->Reset();
162 int JackAudioAdapter::Open()
164 char name[32];
165 jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs());
166 fAudioAdapter->Create();
168 //jack ports
169 fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()];
170 fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()];
172 fInputBufferList = new jack_default_audio_sample_t*[fAudioAdapter->GetInputs()];
173 fOutputBufferList = new jack_default_audio_sample_t*[fAudioAdapter->GetOutputs()];
175 for (int i = 0; i < fAudioAdapter->GetInputs(); i++) {
176 snprintf(name, sizeof(name), "capture_%d", i + 1);
177 if ((fCapturePortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, 0)) == NULL) {
178 goto fail;
182 for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) {
183 snprintf(name, sizeof(name), "playback_%d", i + 1);
184 if ((fPlaybackPortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, 0)) == NULL) {
185 goto fail;
189 //callbacks and activation
190 if (jack_set_process_callback(fClient, Process, this) < 0) {
191 goto fail;
193 if (jack_set_buffer_size_callback(fClient, BufferSize, this) < 0) {
194 goto fail;
196 if (jack_set_sample_rate_callback(fClient, SampleRate, this) < 0) {
197 goto fail;
199 if (jack_set_latency_callback(fClient, Latency, this) < 0) {
200 goto fail;
202 if (jack_activate(fClient) < 0) {
203 goto fail;
206 if (fAutoConnect) {
207 ConnectPorts();
210 // Ring buffers are now allocated...
211 return fAudioAdapter->Open();
212 return 0;
214 fail:
215 FreePorts();
216 fAudioAdapter->Destroy();
217 return -1;
220 int JackAudioAdapter::Close()
222 fAudioAdapter->Close();
223 fAudioAdapter->Destroy();
224 return 0;
227 } //namespace