Blender V2.61 - r43446

AUD_JackDevice.cpp

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