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