Blender  V2.59
AUD_JackDevice.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: AUD_JackDevice.cpp 35141 2011-02-25 10:21:56Z jesterking $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * Copyright 2009-2011 Jörg Hermann Müller
00007  *
00008  * This file is part of AudaSpace.
00009  *
00010  * Audaspace is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * AudaSpace is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with Audaspace; if not, write to the Free Software Foundation,
00022  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 #include "AUD_Mixer.h"
00033 #include "AUD_JackDevice.h"
00034 #include "AUD_IReader.h"
00035 
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 
00039 void* AUD_JackDevice::runMixingThread(void* device)
00040 {
00041         ((AUD_JackDevice*)device)->updateRingBuffers();
00042         return NULL;
00043 }
00044 
00045 void AUD_JackDevice::updateRingBuffers()
00046 {
00047         size_t size, temp;
00048         unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
00049         unsigned int i, j;
00050         unsigned int channels = m_specs.channels;
00051         sample_t* buffer = m_buffer.getBuffer();
00052         float* deinterleave = m_deinterleavebuf.getBuffer();
00053         jack_transport_state_t state;
00054         jack_position_t position;
00055 
00056         pthread_mutex_lock(&m_mixingLock);
00057         while(m_valid)
00058         {
00059                 if(m_sync > 1)
00060                 {
00061                         if(m_syncFunc)
00062                         {
00063                                 state = jack_transport_query(m_client, &position);
00064                                 m_syncFunc(m_syncFuncData, state != JackTransportStopped, position.frame / (float) m_specs.rate);
00065                         }
00066 
00067                         for(i = 0; i < channels; i++)
00068                                 jack_ringbuffer_reset(m_ringbuffers[i]);
00069                 }
00070 
00071                 size = jack_ringbuffer_write_space(m_ringbuffers[0]);
00072                 for(i = 1; i < channels; i++)
00073                         if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
00074                                 size = temp;
00075 
00076                 while(size > samplesize)
00077                 {
00078                         size /= samplesize;
00079                         mix((data_t*)buffer, size);
00080                         for(i = 0; i < channels; i++)
00081                         {
00082                                 for(j = 0; j < size; j++)
00083                                         deinterleave[i * size + j] = buffer[i + j * channels];
00084                                 jack_ringbuffer_write(m_ringbuffers[i], (char*)(deinterleave + i * size), size * sizeof(float));
00085                         }
00086 
00087                         size = jack_ringbuffer_write_space(m_ringbuffers[0]);
00088                         for(i = 1; i < channels; i++)
00089                                 if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
00090                                         size = temp;
00091                 }
00092 
00093                 if(m_sync > 1)
00094                 {
00095                         m_sync = 3;
00096                 }
00097 
00098                 pthread_cond_wait(&m_mixingCondition, &m_mixingLock);
00099         }
00100         pthread_mutex_unlock(&m_mixingLock);
00101 }
00102 
00103 int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data)
00104 {
00105         AUD_JackDevice* device = (AUD_JackDevice*)data;
00106         unsigned int i;
00107         int count = device->m_specs.channels;
00108         char* buffer;
00109 
00110         if(device->m_sync)
00111         {
00112                 // play silence while syncing
00113                 for(unsigned int i = 0; i < count; i++)
00114                         memset(jack_port_get_buffer(device->m_ports[i], length), 0, length * sizeof(float));
00115         }
00116         else
00117         {
00118                 size_t temp;
00119                 size_t readsamples = jack_ringbuffer_read_space(device->m_ringbuffers[0]);
00120                 for(i = 1; i < count; i++)
00121                         if((temp = jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples)
00122                                 readsamples = temp;
00123 
00124                 readsamples = AUD_MIN(readsamples / sizeof(float), length);
00125 
00126                 for(unsigned int i = 0; i < count; i++)
00127                 {
00128                         buffer = (char*)jack_port_get_buffer(device->m_ports[i], length);
00129                         jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float));
00130                         if(readsamples < length)
00131                                 memset(buffer + readsamples * sizeof(float), 0, (length - readsamples) * sizeof(float));
00132                 }
00133 
00134                 if(pthread_mutex_trylock(&(device->m_mixingLock)) == 0)
00135                 {
00136                         pthread_cond_signal(&(device->m_mixingCondition));
00137                         pthread_mutex_unlock(&(device->m_mixingLock));
00138                 }
00139         }
00140 
00141         return 0;
00142 }
00143 
00144 int AUD_JackDevice::jack_sync(jack_transport_state_t state, jack_position_t* pos, void* data)
00145 {
00146         AUD_JackDevice* device = (AUD_JackDevice*)data;
00147 
00148         if(state == JackTransportStopped)
00149                 return 1;
00150 
00151         if(pthread_mutex_trylock(&(device->m_mixingLock)) == 0)
00152         {
00153                 if(device->m_sync > 2)
00154                 {
00155                         if(device->m_sync == 3)
00156                         {
00157                                 device->m_sync = 0;
00158                                 pthread_mutex_unlock(&(device->m_mixingLock));
00159                                 return 1;
00160                         }
00161                 }
00162                 else
00163                 {
00164                         device->m_sync = 2;
00165                         pthread_cond_signal(&(device->m_mixingCondition));
00166                 }
00167                 pthread_mutex_unlock(&(device->m_mixingLock));
00168         }
00169         else if(!device->m_sync)
00170                 device->m_sync = 1;
00171 
00172         return 0;
00173 }
00174 
00175 void AUD_JackDevice::jack_shutdown(void *data)
00176 {
00177         AUD_JackDevice* device = (AUD_JackDevice*)data;
00178         device->m_valid = false;
00179 }
00180 
00181 static const char* clientopen_error = "AUD_JackDevice: Couldn't connect to "
00182                                                                           "jack server.";
00183 static const char* port_error = "AUD_JackDevice: Couldn't create output port.";
00184 static const char* activate_error = "AUD_JackDevice: Couldn't activate the "
00185                                                                         "client.";
00186 
00187 AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buffersize)
00188 {
00189         if(specs.channels == AUD_CHANNELS_INVALID)
00190                 specs.channels = AUD_CHANNELS_STEREO;
00191 
00192         // jack uses floats
00193         m_specs = specs;
00194         m_specs.format = AUD_FORMAT_FLOAT32;
00195 
00196         jack_options_t options = JackNullOption;
00197         jack_status_t status;
00198 
00199         // open client
00200         m_client = jack_client_open(name.c_str(), options, &status);
00201         if(m_client == NULL)
00202                 AUD_THROW(AUD_ERROR_JACK, clientopen_error);
00203 
00204         // set callbacks
00205         jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this);
00206         jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this);
00207         jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this);
00208 
00209         // register our output channels which are called ports in jack
00210         m_ports = new jack_port_t*[m_specs.channels];
00211 
00212         try
00213         {
00214                 char portname[64];
00215                 for(int i = 0; i < m_specs.channels; i++)
00216                 {
00217                         sprintf(portname, "out %d", i+1);
00218                         m_ports[i] = jack_port_register(m_client, portname,
00219                                                                                         JACK_DEFAULT_AUDIO_TYPE,
00220                                                                                         JackPortIsOutput, 0);
00221                         if(m_ports[i] == NULL)
00222                                 AUD_THROW(AUD_ERROR_JACK, port_error);
00223                 }
00224         }
00225         catch(AUD_Exception&)
00226         {
00227                 jack_client_close(m_client);
00228                 delete[] m_ports;
00229                 throw;
00230         }
00231 
00232         m_specs.rate = (AUD_SampleRate)jack_get_sample_rate(m_client);
00233 
00234         buffersize *= sizeof(sample_t);
00235         m_ringbuffers = new jack_ringbuffer_t*[specs.channels];
00236         for(unsigned int i = 0; i < specs.channels; i++)
00237                 m_ringbuffers[i] = jack_ringbuffer_create(buffersize);
00238         buffersize *= specs.channels;
00239         m_deinterleavebuf.resize(buffersize);
00240         m_buffer.resize(buffersize);
00241 
00242         create();
00243 
00244         m_valid = true;
00245         m_sync = 0;
00246         m_syncFunc = NULL;
00247         m_nextState = m_state = jack_transport_query(m_client, NULL);
00248 
00249         pthread_mutex_init(&m_mixingLock, NULL);
00250         pthread_cond_init(&m_mixingCondition, NULL);
00251 
00252         // activate the client
00253         if(jack_activate(m_client))
00254         {
00255                 jack_client_close(m_client);
00256                 delete[] m_ports;
00257                 for(unsigned int i = 0; i < specs.channels; i++)
00258                         jack_ringbuffer_free(m_ringbuffers[i]);
00259                 delete[] m_ringbuffers;
00260                 pthread_mutex_destroy(&m_mixingLock);
00261                 pthread_cond_destroy(&m_mixingCondition);
00262                 destroy();
00263 
00264                 AUD_THROW(AUD_ERROR_JACK, activate_error);
00265         }
00266 
00267         const char** ports = jack_get_ports(m_client, NULL, NULL,
00268                                                                                 JackPortIsPhysical | JackPortIsInput);
00269         if(ports != NULL)
00270         {
00271                 for(int i = 0; i < m_specs.channels && ports[i]; i++)
00272                         jack_connect(m_client, jack_port_name(m_ports[i]), ports[i]);
00273 
00274                 free(ports);
00275         }
00276 
00277         pthread_attr_t attr;
00278         pthread_attr_init(&attr);
00279         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00280 
00281         pthread_create(&m_mixingThread, &attr, runMixingThread, this);
00282 
00283         pthread_attr_destroy(&attr);
00284 }
00285 
00286 AUD_JackDevice::~AUD_JackDevice()
00287 {
00288         if(m_valid)
00289                 jack_client_close(m_client);
00290         m_valid = false;
00291 
00292         delete[] m_ports;
00293 
00294         pthread_mutex_lock(&m_mixingLock);
00295         pthread_cond_signal(&m_mixingCondition);
00296         pthread_mutex_unlock(&m_mixingLock);
00297         pthread_join(m_mixingThread, NULL);
00298 
00299         pthread_cond_destroy(&m_mixingCondition);
00300         pthread_mutex_destroy(&m_mixingLock);
00301         for(unsigned int i = 0; i < m_specs.channels; i++)
00302                 jack_ringbuffer_free(m_ringbuffers[i]);
00303         delete[] m_ringbuffers;
00304 
00305         destroy();
00306 }
00307 
00308 void AUD_JackDevice::playing(bool playing)
00309 {
00310         // Do nothing.
00311 }
00312 
00313 void AUD_JackDevice::startPlayback()
00314 {
00315         jack_transport_start(m_client);
00316         m_nextState = JackTransportRolling;
00317 }
00318 
00319 void AUD_JackDevice::stopPlayback()
00320 {
00321         jack_transport_stop(m_client);
00322         m_nextState = JackTransportStopped;
00323 }
00324 
00325 void AUD_JackDevice::seekPlayback(float time)
00326 {
00327         if(time >= 0.0f)
00328                 jack_transport_locate(m_client, time * m_specs.rate);
00329 }
00330 
00331 void AUD_JackDevice::setSyncCallback(AUD_syncFunction sync, void* data)
00332 {
00333         m_syncFunc = sync;
00334         m_syncFuncData = data;
00335 }
00336 
00337 float AUD_JackDevice::getPlaybackPosition()
00338 {
00339         jack_position_t position;
00340         jack_transport_query(m_client, &position);
00341         return position.frame / (float) m_specs.rate;
00342 }
00343 
00344 bool AUD_JackDevice::doesPlayback()
00345 {
00346         jack_transport_state_t state = jack_transport_query(m_client, NULL);
00347 
00348         if(state != m_state)
00349                 m_nextState = m_state = state;
00350 
00351         return m_nextState != JackTransportStopped;
00352 }