add missing files after merging
[blender.git] / intern / audaspace / jack / AUD_JackDevice.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * Copyright 2009-2011 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * Audaspace is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Audaspace; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file audaspace/jack/AUD_JackDevice.cpp
28  *  \ingroup audjack
29  */
30
31 #include "AUD_JackDevice.h"
32 #include "AUD_IReader.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36
37 void* AUD_JackDevice::runMixingThread(void* device)
38 {
39         ((AUD_JackDevice*)device)->updateRingBuffers();
40         return NULL;
41 }
42
43 void AUD_JackDevice::updateRingBuffers()
44 {
45         size_t size, temp;
46         unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
47         unsigned int i, j;
48         unsigned int channels = m_specs.channels;
49         sample_t* buffer = m_buffer.getBuffer();
50         float* deinterleave = m_deinterleavebuf.getBuffer();
51         jack_transport_state_t state;
52         jack_position_t position;
53
54         pthread_mutex_lock(&m_mixingLock);
55         while(m_valid)
56         {
57                 if(m_sync > 1)
58                 {
59                         if(m_syncFunc)
60                         {
61                                 state = jack_transport_query(m_client, &position);
62                                 m_syncFunc(m_syncFuncData, state != JackTransportStopped, position.frame / (float) m_specs.rate);
63                         }
64
65                         for(i = 0; i < channels; i++)
66                                 jack_ringbuffer_reset(m_ringbuffers[i]);
67                 }
68
69                 size = jack_ringbuffer_write_space(m_ringbuffers[0]);
70                 for(i = 1; i < channels; i++)
71                         if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
72                                 size = temp;
73
74                 while(size > samplesize)
75                 {
76                         size /= samplesize;
77                         mix((data_t*)buffer, size);
78                         for(i = 0; i < channels; i++)
79                         {
80                                 for(j = 0; j < size; j++)
81                                         deinterleave[i * size + j] = buffer[i + j * channels];
82                                 jack_ringbuffer_write(m_ringbuffers[i], (char*)(deinterleave + i * size), size * sizeof(float));
83                         }
84
85                         size = jack_ringbuffer_write_space(m_ringbuffers[0]);
86                         for(i = 1; i < channels; i++)
87                                 if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
88                                         size = temp;
89                 }
90
91                 if(m_sync > 1)
92                 {
93                         m_sync = 3;
94                 }
95
96                 pthread_cond_wait(&m_mixingCondition, &m_mixingLock);
97         }
98         pthread_mutex_unlock(&m_mixingLock);
99 }
100
101 int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data)
102 {
103         AUD_JackDevice* device = (AUD_JackDevice*)data;
104         unsigned int i;
105         int count = device->m_specs.channels;
106         char* buffer;
107
108         if(device->m_sync)
109         {
110                 // play silence while syncing
111                 for(unsigned int i = 0; i < count; i++)
112                         memset(jack_port_get_buffer(device->m_ports[i], length), 0, length * sizeof(float));
113         }
114         else
115         {
116                 size_t temp;
117                 size_t readsamples = jack_ringbuffer_read_space(device->m_ringbuffers[0]);
118                 for(i = 1; i < count; i++)
119                         if((temp = jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples)
120                                 readsamples = temp;
121
122                 readsamples = AUD_MIN(readsamples / sizeof(float), length);
123
124                 for(unsigned int i = 0; i < count; i++)
125                 {
126                         buffer = (char*)jack_port_get_buffer(device->m_ports[i], length);
127                         jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float));
128                         if(readsamples < length)
129                                 memset(buffer + readsamples * sizeof(float), 0, (length - readsamples) * sizeof(float));
130                 }
131
132                 if(pthread_mutex_trylock(&(device->m_mixingLock)) == 0)
133                 {
134                         pthread_cond_signal(&(device->m_mixingCondition));
135                         pthread_mutex_unlock(&(device->m_mixingLock));
136                 }
137         }
138
139         return 0;
140 }
141
142 int AUD_JackDevice::jack_sync(jack_transport_state_t state, jack_position_t* pos, void* data)
143 {
144         AUD_JackDevice* device = (AUD_JackDevice*)data;
145
146         if(state == JackTransportStopped)
147                 return 1;
148
149         if(pthread_mutex_trylock(&(device->m_mixingLock)) == 0)
150         {
151                 if(device->m_sync > 2)
152                 {
153                         if(device->m_sync == 3)
154                         {
155                                 device->m_sync = 0;
156                                 pthread_mutex_unlock(&(device->m_mixingLock));
157                                 return 1;
158                         }
159                 }
160                 else
161                 {
162                         device->m_sync = 2;
163                         pthread_cond_signal(&(device->m_mixingCondition));
164                 }
165                 pthread_mutex_unlock(&(device->m_mixingLock));
166         }
167         else if(!device->m_sync)
168                 device->m_sync = 1;
169
170         return 0;
171 }
172
173 void AUD_JackDevice::jack_shutdown(void *data)
174 {
175         AUD_JackDevice* device = (AUD_JackDevice*)data;
176         device->m_valid = false;
177 }
178
179 static const char* clientopen_error = "AUD_JackDevice: Couldn't connect to "
180                                                                           "jack server.";
181 static const char* port_error = "AUD_JackDevice: Couldn't create output port.";
182 static const char* activate_error = "AUD_JackDevice: Couldn't activate the "
183                                                                         "client.";
184
185 AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buffersize)
186 {
187         if(specs.channels == AUD_CHANNELS_INVALID)
188                 specs.channels = AUD_CHANNELS_STEREO;
189
190         // jack uses floats
191         m_specs = specs;
192         m_specs.format = AUD_FORMAT_FLOAT32;
193
194         jack_options_t options = JackNullOption;
195         jack_status_t status;
196
197         // open client
198         m_client = jack_client_open(name.c_str(), options, &status);
199         if(m_client == NULL)
200                 AUD_THROW(AUD_ERROR_JACK, clientopen_error);
201
202         // set callbacks
203         jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this);
204         jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this);
205         jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this);
206
207         // register our output channels which are called ports in jack
208         m_ports = new jack_port_t*[m_specs.channels];
209
210         try
211         {
212                 char portname[64];
213                 for(int i = 0; i < m_specs.channels; i++)
214                 {
215                         sprintf(portname, "out %d", i+1);
216                         m_ports[i] = jack_port_register(m_client, portname,
217                                                                                         JACK_DEFAULT_AUDIO_TYPE,
218                                                                                         JackPortIsOutput, 0);
219                         if(m_ports[i] == NULL)
220                                 AUD_THROW(AUD_ERROR_JACK, port_error);
221                 }
222         }
223         catch(AUD_Exception&)
224         {
225                 jack_client_close(m_client);
226                 delete[] m_ports;
227                 throw;
228         }
229
230         m_specs.rate = (AUD_SampleRate)jack_get_sample_rate(m_client);
231
232         buffersize *= sizeof(sample_t);
233         m_ringbuffers = new jack_ringbuffer_t*[specs.channels];
234         for(unsigned int i = 0; i < specs.channels; i++)
235                 m_ringbuffers[i] = jack_ringbuffer_create(buffersize);
236         buffersize *= specs.channels;
237         m_deinterleavebuf.resize(buffersize);
238         m_buffer.resize(buffersize);
239
240         create();
241
242         m_valid = true;
243         m_sync = 0;
244         m_syncFunc = NULL;
245         m_nextState = m_state = jack_transport_query(m_client, NULL);
246
247         pthread_mutex_init(&m_mixingLock, NULL);
248         pthread_cond_init(&m_mixingCondition, NULL);
249
250         // activate the client
251         if(jack_activate(m_client))
252         {
253                 jack_client_close(m_client);
254                 delete[] m_ports;
255                 for(unsigned int i = 0; i < specs.channels; i++)
256                         jack_ringbuffer_free(m_ringbuffers[i]);
257                 delete[] m_ringbuffers;
258                 pthread_mutex_destroy(&m_mixingLock);
259                 pthread_cond_destroy(&m_mixingCondition);
260                 destroy();
261
262                 AUD_THROW(AUD_ERROR_JACK, activate_error);
263         }
264
265         const char** ports = jack_get_ports(m_client, NULL, NULL,
266                                                                                 JackPortIsPhysical | JackPortIsInput);
267         if(ports != NULL)
268         {
269                 for(int i = 0; i < m_specs.channels && ports[i]; i++)
270                         jack_connect(m_client, jack_port_name(m_ports[i]), ports[i]);
271
272                 free(ports);
273         }
274
275         pthread_attr_t attr;
276         pthread_attr_init(&attr);
277         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
278
279         pthread_create(&m_mixingThread, &attr, runMixingThread, this);
280
281         pthread_attr_destroy(&attr);
282 }
283
284 AUD_JackDevice::~AUD_JackDevice()
285 {
286         if(m_valid)
287                 jack_client_close(m_client);
288         m_valid = false;
289
290         delete[] m_ports;
291
292         pthread_mutex_lock(&m_mixingLock);
293         pthread_cond_signal(&m_mixingCondition);
294         pthread_mutex_unlock(&m_mixingLock);
295         pthread_join(m_mixingThread, NULL);
296
297         pthread_cond_destroy(&m_mixingCondition);
298         pthread_mutex_destroy(&m_mixingLock);
299         for(unsigned int i = 0; i < m_specs.channels; i++)
300                 jack_ringbuffer_free(m_ringbuffers[i]);
301         delete[] m_ringbuffers;
302
303         destroy();
304 }
305
306 void AUD_JackDevice::playing(bool playing)
307 {
308         // Do nothing.
309 }
310
311 void AUD_JackDevice::startPlayback()
312 {
313         jack_transport_start(m_client);
314         m_nextState = JackTransportRolling;
315 }
316
317 void AUD_JackDevice::stopPlayback()
318 {
319         jack_transport_stop(m_client);
320         m_nextState = JackTransportStopped;
321 }
322
323 void AUD_JackDevice::seekPlayback(float time)
324 {
325         if(time >= 0.0f)
326                 jack_transport_locate(m_client, time * m_specs.rate);
327 }
328
329 void AUD_JackDevice::setSyncCallback(AUD_syncFunction sync, void* data)
330 {
331         m_syncFunc = sync;
332         m_syncFuncData = data;
333 }
334
335 float AUD_JackDevice::getPlaybackPosition()
336 {
337         jack_position_t position;
338         jack_transport_query(m_client, &position);
339         return position.frame / (float) m_specs.rate;
340 }
341
342 bool AUD_JackDevice::doesPlayback()
343 {
344         jack_transport_state_t state = jack_transport_query(m_client, NULL);
345
346         if(state != m_state)
347                 m_nextState = m_state = state;
348
349         return m_nextState != JackTransportStopped;
350 }