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