Jack2  1.9.9
JackAudioAdapter.cpp
1 /*
2 Copyright (C) 2008 Grame
3 
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.
8 
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.
13 
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.
17 
18 */
19 
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>
29 
30 using namespace std;
31 
32 namespace Jack
33 {
34 
35 int JackAudioAdapter::Process(jack_nframes_t frames, void* arg)
36 {
37  JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
38  return adapter->ProcessAux(frames);
39 }
40 
41 int JackAudioAdapter::ProcessAux(jack_nframes_t frames)
42 {
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));
47  }
48 
49  for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) {
50  fOutputBufferList[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(fPlaybackPortList[i], frames);
51  }
52 
53  fAudioAdapter->PullAndPush(fInputBufferList, fOutputBufferList, frames);
54  return 0;
55 }
56 
57 int JackAudioAdapter::BufferSize(jack_nframes_t buffer_size, void* arg)
58 {
59  JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
60  adapter->Reset();
61  adapter->fAudioAdapter->SetHostBufferSize(buffer_size);
62  return 0;
63 }
64 
65 int JackAudioAdapter::SampleRate(jack_nframes_t sample_rate, void* arg)
66 {
67  JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
68  adapter->Reset();
69  adapter->fAudioAdapter->SetHostSampleRate(sample_rate);
70  return 0;
71 }
72 
73 void JackAudioAdapter::Latency(jack_latency_callback_mode_t mode, void* arg)
74 {
75  JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
76 
77  if (mode == JackCaptureLatency) {
78  for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
80  range.min = range.max = adapter->fAudioAdapter->GetInputLatency(i);
81  jack_port_set_latency_range(adapter->fCapturePortList[i], JackCaptureLatency, &range);
82  }
83 
84  } else {
85  for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
87  range.min = range.max = adapter->fAudioAdapter->GetOutputLatency(i);
88  jack_port_set_latency_range(adapter->fPlaybackPortList[i], JackPlaybackLatency, &range);
89  }
90  }
91 }
92 
93 JackAudioAdapter::JackAudioAdapter(jack_client_t* client, JackAudioAdapterInterface* audio_io, const JSList* params)
94  :fClient(client), fAudioAdapter(audio_io)
95 {
96  const JSList* node;
97  const jack_driver_param_t* param;
98  fAutoConnect = false;
99 
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;
106  }
107  }
108 }
109 
110 JackAudioAdapter::~JackAudioAdapter()
111 {
112  // When called, Close has already been used for the client, thus ports are already unregistered.
113  delete fAudioAdapter;
114 }
115 
116 void JackAudioAdapter::FreePorts()
117 {
118  for (int i = 0; i < fAudioAdapter->GetInputs(); i++) {
119  if (fCapturePortList[i]) {
120  jack_port_unregister(fClient, fCapturePortList[i]);
121  }
122  }
123  for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) {
124  if (fPlaybackPortList[i]) {
125  jack_port_unregister(fClient, fPlaybackPortList[i]);
126  }
127  }
128 
129  delete[] fCapturePortList;
130  delete[] fPlaybackPortList;
131 
132  delete[] fInputBufferList;
133  delete[] fOutputBufferList;
134 }
135 
136 void JackAudioAdapter::ConnectPorts()
137 {
138  const char** ports;
139 
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]);
144  }
145  jack_free(ports);
146  }
147 
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]));
152  }
153  jack_free(ports);
154  }
155 }
156 
157 void JackAudioAdapter::Reset()
158 {
159  fAudioAdapter->Reset();
160 }
161 
162 int JackAudioAdapter::Open()
163 {
164  char name[32];
165  jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs());
166  fAudioAdapter->Create();
167 
168  //jack ports
169  fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()];
170  fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()];
171 
172  fInputBufferList = new jack_default_audio_sample_t*[fAudioAdapter->GetInputs()];
173  fOutputBufferList = new jack_default_audio_sample_t*[fAudioAdapter->GetOutputs()];
174 
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;
179  }
180  }
181 
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;
186  }
187  }
188 
189  //callbacks and activation
190  if (jack_set_process_callback(fClient, Process, this) < 0) {
191  goto fail;
192  }
193  if (jack_set_buffer_size_callback(fClient, BufferSize, this) < 0) {
194  goto fail;
195  }
196  if (jack_set_sample_rate_callback(fClient, SampleRate, this) < 0) {
197  goto fail;
198  }
199  if (jack_set_latency_callback(fClient, Latency, this) < 0) {
200  goto fail;
201  }
202  if (jack_activate(fClient) < 0) {
203  goto fail;
204  }
205 
206  if (fAutoConnect) {
207  ConnectPorts();
208  }
209 
210  // Ring buffers are now allocated...
211  return fAudioAdapter->Open();
212  return 0;
213 
214 fail:
215  FreePorts();
216  fAudioAdapter->Destroy();
217  return -1;
218 }
219 
220 int JackAudioAdapter::Close()
221 {
222  fAudioAdapter->Close();
223  fAudioAdapter->Destroy();
224  return 0;
225 }
226 
227 } //namespace
LIB_EXPORT int jack_port_unregister(jack_client_t *, jack_port_t *)
Definition: JackAPI.cpp:1061
LIB_EXPORT int jack_set_process_callback(jack_client_t *client, JackProcessCallback process_callback, void *arg)
Definition: JackAPI.cpp:781
LIB_EXPORT int jack_activate(jack_client_t *client)
Definition: JackAPI.cpp:1019
LIB_EXPORT void jack_port_set_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
Definition: JackAPI.cpp:551
LIB_EXPORT int jack_connect(jack_client_t *, const char *source_port, const char *destination_port)
Definition: JackAPI.cpp:1163
jack_nframes_t min
Definition: types.h:268
LIB_EXPORT jack_port_t * jack_port_register(jack_client_t *client, const char *port_name, const char *port_type, unsigned long flags, unsigned long buffer_size)
Definition: JackAPI.cpp:1045
jack_nframes_t max
Definition: types.h:272
LIB_EXPORT int jack_set_sample_rate_callback(jack_client_t *client, JackSampleRateCallback srate_callback, void *arg)
Definition: JackAPI.cpp:900
LIB_EXPORT void * jack_port_get_buffer(jack_port_t *, jack_nframes_t)
Definition: JackAPI.cpp:333
LIB_EXPORT int jack_set_buffer_size_callback(jack_client_t *client, JackBufferSizeCallback bufsize_callback, void *arg)
Definition: JackAPI.cpp:887
LIB_EXPORT const char * jack_port_name(const jack_port_t *port)
Definition: JackAPI.cpp:348
LIB_EXPORT const char ** jack_get_ports(jack_client_t *, const char *port_name_pattern, const char *type_name_pattern, unsigned long flags)
Definition: JackAPI.cpp:1241
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:107