1 /*******************************************************************************
2 * Copyright 2009-2016 Jörg Müller
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 ******************************************************************************/
16
17 #include "JackDevice.h"
18 #include "JackLibrary.h"
19 #include "devices/DeviceManager.h"
20 #include "devices/IDeviceFactory.h"
21 #include "Exception.h"
22 #include "IReader.h"
23
24 #include <cstring>
25 #include <algorithm>
26
27 AUD_NAMESPACE_BEGIN
28
updateRingBuffers()29 void JackDevice::updateRingBuffers()
30 {
31 size_t size, temp;
32 unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
33 unsigned int i, j;
34 unsigned int channels = m_specs.channels;
35 sample_t* buffer = m_buffer.getBuffer();
36 float* deinterleave = m_deinterleavebuf.getBuffer();
37 jack_transport_state_t state;
38 jack_position_t position;
39
40 std::unique_lock<std::mutex> lock(m_mixingLock);
41
42 while(m_valid)
43 {
44 if(m_sync > 1)
45 {
46 if(m_syncFunc)
47 {
48 state = AUD_jack_transport_query(m_client, &position);
49 m_syncFunc(m_syncFuncData, state != JackTransportStopped, position.frame / (float) m_specs.rate);
50 }
51
52 for(i = 0; i < channels; i++)
53 AUD_jack_ringbuffer_reset(m_ringbuffers[i]);
54 }
55
56 size = AUD_jack_ringbuffer_write_space(m_ringbuffers[0]);
57 for(i = 1; i < channels; i++)
58 if((temp = AUD_jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
59 size = temp;
60
61 while(size > samplesize)
62 {
63 size /= samplesize;
64 mix((data_t*)buffer, size);
65 for(i = 0; i < channels; i++)
66 {
67 for(j = 0; j < size; j++)
68 deinterleave[i * size + j] = buffer[i + j * channels];
69 AUD_jack_ringbuffer_write(m_ringbuffers[i], (char*)(deinterleave + i * size), size * sizeof(float));
70 }
71
72 size = AUD_jack_ringbuffer_write_space(m_ringbuffers[0]);
73 for(i = 1; i < channels; i++)
74 if((temp = AUD_jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
75 size = temp;
76 }
77
78 if(m_sync > 1)
79 {
80 m_sync = 3;
81 }
82
83 m_mixingCondition.wait(lock);
84 }
85 }
86
jack_mix(jack_nframes_t length,void * data)87 int JackDevice::jack_mix(jack_nframes_t length, void* data)
88 {
89 JackDevice* device = (JackDevice*)data;
90 unsigned int i;
91 int count = device->m_specs.channels;
92 char* buffer;
93
94 if(device->m_sync)
95 {
96 // play silence while syncing
97 for(unsigned int i = 0; i < count; i++)
98 std::memset(AUD_jack_port_get_buffer(device->m_ports[i], length), 0, length * sizeof(float));
99 }
100 else
101 {
102 size_t temp;
103 size_t readsamples = AUD_jack_ringbuffer_read_space(device->m_ringbuffers[0]);
104 for(i = 1; i < count; i++)
105 if((temp = AUD_jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples)
106 readsamples = temp;
107
108 readsamples = std::min(readsamples / sizeof(float), size_t(length));
109
110 for(unsigned int i = 0; i < count; i++)
111 {
112 buffer = (char*)AUD_jack_port_get_buffer(device->m_ports[i], length);
113 AUD_jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float));
114 if(readsamples < length)
115 std::memset(buffer + readsamples * sizeof(float), 0, (length - readsamples) * sizeof(float));
116 }
117
118 if(device->m_mixingLock.try_lock())
119 {
120 device->m_mixingCondition.notify_all();
121 device->m_mixingLock.unlock();
122 }
123 }
124
125 return 0;
126 }
127
jack_sync(jack_transport_state_t state,jack_position_t * pos,void * data)128 int JackDevice::jack_sync(jack_transport_state_t state, jack_position_t* pos, void* data)
129 {
130 JackDevice* device = (JackDevice*)data;
131
132 if(state == JackTransportStopped)
133 return 1;
134
135 if(device->m_mixingLock.try_lock())
136 {
137 if(device->m_sync > 2)
138 {
139 if(device->m_sync == 3)
140 {
141 device->m_sync = 0;
142 device->m_mixingLock.unlock();
143 return 1;
144 }
145 }
146 else
147 {
148 device->m_sync = 2;
149 device->m_mixingCondition.notify_all();
150 }
151 device->m_mixingLock.unlock();
152 }
153 else if(!device->m_sync)
154 device->m_sync = 1;
155
156 return 0;
157 }
158
jack_shutdown(void * data)159 void JackDevice::jack_shutdown(void* data)
160 {
161 JackDevice* device = (JackDevice*)data;
162 device->m_valid = false;
163 }
164
JackDevice(std::string name,DeviceSpecs specs,int buffersize)165 JackDevice::JackDevice(std::string name, DeviceSpecs specs, int buffersize) :
166 m_synchronizer(this)
167 {
168 if(specs.channels == CHANNELS_INVALID)
169 specs.channels = CHANNELS_STEREO;
170
171 // jack uses floats
172 m_specs = specs;
173 m_specs.format = FORMAT_FLOAT32;
174
175 jack_options_t options = JackNullOption;
176 jack_status_t status;
177
178 // open client
179 m_client = AUD_jack_client_open(name.c_str(), options, &status);
180 if(m_client == nullptr)
181 AUD_THROW(DeviceException, "Connecting to the JACK server failed.");
182
183 // set callbacks
184 AUD_jack_set_process_callback(m_client, JackDevice::jack_mix, this);
185 AUD_jack_on_shutdown(m_client, JackDevice::jack_shutdown, this);
186 AUD_jack_set_sync_callback(m_client, JackDevice::jack_sync, this);
187
188 // register our output channels which are called ports in jack
189 m_ports = new jack_port_t*[m_specs.channels];
190
191 try
192 {
193 char portname[64];
194 for(int i = 0; i < m_specs.channels; i++)
195 {
196 sprintf(portname, "out %d", i+1);
197 m_ports[i] = AUD_jack_port_register(m_client, portname, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
198 if(m_ports[i] == nullptr)
199 AUD_THROW(DeviceException, "Registering output port with JACK failed.");
200 }
201 }
202 catch(Exception&)
203 {
204 AUD_jack_client_close(m_client);
205 delete[] m_ports;
206 throw;
207 }
208
209 m_specs.rate = (SampleRate)AUD_jack_get_sample_rate(m_client);
210
211 buffersize *= sizeof(sample_t);
212 m_ringbuffers = new jack_ringbuffer_t*[specs.channels];
213 for(unsigned int i = 0; i < specs.channels; i++)
214 m_ringbuffers[i] = AUD_jack_ringbuffer_create(buffersize);
215 buffersize *= specs.channels;
216 m_deinterleavebuf.resize(buffersize);
217 m_buffer.resize(buffersize);
218
219 create();
220
221 m_valid = true;
222 m_sync = 0;
223 m_syncFunc = nullptr;
224 m_nextState = m_state = AUD_jack_transport_query(m_client, nullptr);
225
226 // activate the client
227 if(AUD_jack_activate(m_client))
228 {
229 AUD_jack_client_close(m_client);
230 delete[] m_ports;
231 for(unsigned int i = 0; i < specs.channels; i++)
232 AUD_jack_ringbuffer_free(m_ringbuffers[i]);
233 delete[] m_ringbuffers;
234 destroy();
235
236 AUD_THROW(DeviceException, "Client activation with JACK failed.");
237 }
238
239 const char** ports = AUD_jack_get_ports(m_client, nullptr, nullptr,
240 JackPortIsPhysical | JackPortIsInput);
241 if(ports != nullptr)
242 {
243 for(int i = 0; i < m_specs.channels && ports[i]; i++)
244 AUD_jack_connect(m_client, AUD_jack_port_name(m_ports[i]), ports[i]);
245
246 AUD_jack_free(ports);
247 }
248
249 m_mixingThread = std::thread(&JackDevice::updateRingBuffers, this);
250 }
251
~JackDevice()252 JackDevice::~JackDevice()
253 {
254 if(m_valid)
255 AUD_jack_client_close(m_client);
256 m_valid = false;
257
258 delete[] m_ports;
259
260 m_mixingLock.lock();
261 m_mixingCondition.notify_all();
262 m_mixingLock.unlock();
263
264 m_mixingThread.join();
265
266 for(unsigned int i = 0; i < m_specs.channels; i++)
267 AUD_jack_ringbuffer_free(m_ringbuffers[i]);
268 delete[] m_ringbuffers;
269
270 destroy();
271 }
272
getSynchronizer()273 ISynchronizer* JackDevice::getSynchronizer()
274 {
275 return &m_synchronizer;
276 }
277
playing(bool playing)278 void JackDevice::playing(bool playing)
279 {
280 // Do nothing.
281 }
282
startPlayback()283 void JackDevice::startPlayback()
284 {
285 AUD_jack_transport_start(m_client);
286 m_nextState = JackTransportRolling;
287 }
288
stopPlayback()289 void JackDevice::stopPlayback()
290 {
291 AUD_jack_transport_stop(m_client);
292 m_nextState = JackTransportStopped;
293 }
294
seekPlayback(double time)295 void JackDevice::seekPlayback(double time)
296 {
297 if(time >= 0.0f)
298 AUD_jack_transport_locate(m_client, time * m_specs.rate);
299 }
300
setSyncCallback(ISynchronizer::syncFunction sync,void * data)301 void JackDevice::setSyncCallback(ISynchronizer::syncFunction sync, void* data)
302 {
303 m_syncFunc = sync;
304 m_syncFuncData = data;
305 }
306
getPlaybackPosition()307 double JackDevice::getPlaybackPosition()
308 {
309 jack_position_t position;
310 AUD_jack_transport_query(m_client, &position);
311 return position.frame / (double) m_specs.rate;
312 }
313
doesPlayback()314 bool JackDevice::doesPlayback()
315 {
316 jack_transport_state_t state = AUD_jack_transport_query(m_client, nullptr);
317
318 if(state != m_state)
319 m_nextState = m_state = state;
320
321 return m_nextState != JackTransportStopped;
322 }
323
324 class JackDeviceFactory : public IDeviceFactory
325 {
326 private:
327 DeviceSpecs m_specs;
328 int m_buffersize;
329 std::string m_name;
330
331 public:
JackDeviceFactory()332 JackDeviceFactory() :
333 m_buffersize(AUD_DEFAULT_BUFFER_SIZE),
334 m_name("Audaspace")
335 {
336 m_specs.format = FORMAT_FLOAT32;
337 m_specs.channels = CHANNELS_STEREO;
338 m_specs.rate = RATE_48000;
339 }
340
openDevice()341 virtual std::shared_ptr<IDevice> openDevice()
342 {
343 return std::shared_ptr<IDevice>(new JackDevice(m_name, m_specs, m_buffersize));
344 }
345
getPriority()346 virtual int getPriority()
347 {
348 return 0;
349 }
350
setSpecs(DeviceSpecs specs)351 virtual void setSpecs(DeviceSpecs specs)
352 {
353 m_specs = specs;
354 }
355
setBufferSize(int buffersize)356 virtual void setBufferSize(int buffersize)
357 {
358 m_buffersize = buffersize;
359 }
360
setName(std::string name)361 virtual void setName(std::string name)
362 {
363 m_name = name;
364 }
365 };
366
registerPlugin()367 void JackDevice::registerPlugin()
368 {
369 if(loadJACK())
370 DeviceManager::registerDevice("JACK", std::shared_ptr<IDeviceFactory>(new JackDeviceFactory));
371 }
372
373 #ifdef JACK_PLUGIN
registerPlugin()374 extern "C" AUD_PLUGIN_API void registerPlugin()
375 {
376 JackDevice::registerPlugin();
377 }
378
getName()379 extern "C" AUD_PLUGIN_API const char* getName()
380 {
381 return "JACK";
382 }
383 #endif
384
385 AUD_NAMESPACE_END
386