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