Blender V2.61 - r43446
|
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 }