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