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