diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/audaspace/CMakeLists.txt | 6 | ||||
-rw-r--r-- | intern/audaspace/SConscript | 2 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_C-API.cpp | 28 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_C-API.h | 9 | ||||
-rw-r--r-- | intern/audaspace/jack/AUD_JackDevice.cpp | 66 | ||||
-rw-r--r-- | intern/audaspace/jack/AUD_JackDevice.h | 7 | ||||
-rw-r--r-- | intern/audaspace/jack/AUD_JackLibrary.cpp | 116 | ||||
-rw-r--r-- | intern/audaspace/jack/AUD_JackLibrary.h | 104 |
8 files changed, 295 insertions, 43 deletions
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index ec66cffea3b..21a42553935 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -253,9 +253,15 @@ if(WITH_JACK) ) list(APPEND SRC jack/AUD_JackDevice.cpp + jack/AUD_JackLibrary.cpp jack/AUD_JackDevice.h + jack/AUD_JackLibrary.h ) + + if(WITH_JACK_DYNLOAD) + add_definitions(-DWITH_JACK_DYNLOAD) + endif() endif() if(WITH_CODEC_SNDFILE) diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript index ba549530e64..cc338629c85 100644 --- a/intern/audaspace/SConscript +++ b/intern/audaspace/SConscript @@ -46,6 +46,8 @@ if env['WITH_BF_JACK']: sources += env.Glob('jack/*.cpp') incs += ' jack ' + env['BF_JACK_INC'] defs.append('WITH_JACK') + if env['WITH_BF_JACK_DYNLOAD']: + defs.append('WITH_JACK_DYNLOAD') if env['WITH_BF_SNDFILE']: sources += env.Glob('sndfile/*.cpp') diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index e15964151c9..42fd87e3b8d 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -79,6 +79,7 @@ #ifdef WITH_JACK #include "AUD_JackDevice.h" +#include "AUD_JackLibrary.h" #endif @@ -110,6 +111,16 @@ void AUD_initOnce() #ifdef WITH_FFMPEG av_register_all(); #endif +#ifdef WITH_JACK + AUD_jack_init(); +#endif +} + +void AUD_exitOnce() +{ +#ifdef WITH_JACK + AUD_jack_exit(); +#endif } int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) @@ -144,14 +155,16 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) // No break, fall through to default, to return false } else - { #endif + if (!AUD_jack_supported()) { + printf("Warning: Jack cllient not installed\n"); + // No break, fall through to default, to return false + } + else { dev = boost::shared_ptr<AUD_IDevice>(new AUD_JackDevice("Blender", specs, buffersize)); break; -#ifdef __APPLE__ } #endif -#endif default: return false; } @@ -1262,3 +1275,12 @@ AUD_I3DDevice *AUD_get3DDevice() { return AUD_3ddevice; } + +int AUD_isJackSupported(void) +{ +#ifdef WITH_JACK + return AUD_jack_supported(); +#else + return 0; +#endif +} diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index 9c6611fe04a..64a3d06bd5f 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -61,11 +61,16 @@ typedef struct #endif /** - * Initializes FFMPEG if it is enabled. + * Initializes audio rutines (FFMPEG/Jack if it is enabled). */ extern void AUD_initOnce(void); /** + * Unitinitializes an audio routines. + */ +extern void AUD_exitOnce(void); + +/** * Initializes an audio device. * \param device The device type that should be used. * \param specs The audio specification to be used. @@ -752,6 +757,8 @@ extern void *AUD_getPythonFactory(AUD_Sound *sound); extern AUD_Sound *AUD_getPythonSound(void *sound); #endif +extern int AUD_isJackSupported(void); + #ifdef __cplusplus } diff --git a/intern/audaspace/jack/AUD_JackDevice.cpp b/intern/audaspace/jack/AUD_JackDevice.cpp index a83098ac496..cfbf80ac110 100644 --- a/intern/audaspace/jack/AUD_JackDevice.cpp +++ b/intern/audaspace/jack/AUD_JackDevice.cpp @@ -56,17 +56,17 @@ void AUD_JackDevice::updateRingBuffers() { if(m_syncFunc) { - state = jack_transport_query(m_client, &position); + state = AUD_jack_transport_query(m_client, &position); m_syncFunc(m_syncFuncData, state != JackTransportStopped, position.frame / (float) m_specs.rate); } for(i = 0; i < channels; i++) - jack_ringbuffer_reset(m_ringbuffers[i]); + AUD_jack_ringbuffer_reset(m_ringbuffers[i]); } - size = jack_ringbuffer_write_space(m_ringbuffers[0]); + size = AUD_jack_ringbuffer_write_space(m_ringbuffers[0]); for(i = 1; i < channels; i++) - if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size) + if((temp = AUD_jack_ringbuffer_write_space(m_ringbuffers[i])) < size) size = temp; while(size > samplesize) @@ -77,12 +77,12 @@ void AUD_JackDevice::updateRingBuffers() { for(j = 0; j < size; j++) deinterleave[i * size + j] = buffer[i + j * channels]; - jack_ringbuffer_write(m_ringbuffers[i], (char*)(deinterleave + i * size), size * sizeof(float)); + AUD_jack_ringbuffer_write(m_ringbuffers[i], (char*)(deinterleave + i * size), size * sizeof(float)); } - size = jack_ringbuffer_write_space(m_ringbuffers[0]); + size = AUD_jack_ringbuffer_write_space(m_ringbuffers[0]); for(i = 1; i < channels; i++) - if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size) + if((temp = AUD_jack_ringbuffer_write_space(m_ringbuffers[i])) < size) size = temp; } @@ -107,22 +107,22 @@ int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data) { // play silence while syncing for(unsigned int i = 0; i < count; i++) - memset(jack_port_get_buffer(device->m_ports[i], length), 0, length * sizeof(float)); + memset(AUD_jack_port_get_buffer(device->m_ports[i], length), 0, length * sizeof(float)); } else { size_t temp; - size_t readsamples = jack_ringbuffer_read_space(device->m_ringbuffers[0]); + size_t readsamples = AUD_jack_ringbuffer_read_space(device->m_ringbuffers[0]); for(i = 1; i < count; i++) - if((temp = jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples) + if((temp = AUD_jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples) readsamples = temp; readsamples = AUD_MIN(readsamples / sizeof(float), length); for(unsigned int i = 0; i < count; i++) { - buffer = (char*)jack_port_get_buffer(device->m_ports[i], length); - jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float)); + buffer = (char*)AUD_jack_port_get_buffer(device->m_ports[i], length); + AUD_jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float)); if(readsamples < length) memset(buffer + readsamples * sizeof(float), 0, (length - readsamples) * sizeof(float)); } @@ -193,14 +193,14 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff jack_status_t status; // open client - m_client = jack_client_open(name.c_str(), options, &status); + m_client = AUD_jack_client_open(name.c_str(), options, &status); if(m_client == NULL) AUD_THROW(AUD_ERROR_JACK, clientopen_error); // set callbacks - jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this); - jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this); - jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this); + AUD_jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this); + AUD_jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this); + AUD_jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this); // register our output channels which are called ports in jack m_ports = new jack_port_t*[m_specs.channels]; @@ -211,7 +211,7 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff for(int i = 0; i < m_specs.channels; i++) { sprintf(portname, "out %d", i+1); - m_ports[i] = jack_port_register(m_client, portname, + m_ports[i] = AUD_jack_port_register(m_client, portname, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if(m_ports[i] == NULL) @@ -220,17 +220,17 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff } catch(AUD_Exception&) { - jack_client_close(m_client); + AUD_jack_client_close(m_client); delete[] m_ports; throw; } - m_specs.rate = (AUD_SampleRate)jack_get_sample_rate(m_client); + m_specs.rate = (AUD_SampleRate)AUD_jack_get_sample_rate(m_client); buffersize *= sizeof(sample_t); m_ringbuffers = new jack_ringbuffer_t*[specs.channels]; for(unsigned int i = 0; i < specs.channels; i++) - m_ringbuffers[i] = jack_ringbuffer_create(buffersize); + m_ringbuffers[i] = AUD_jack_ringbuffer_create(buffersize); buffersize *= specs.channels; m_deinterleavebuf.resize(buffersize); m_buffer.resize(buffersize); @@ -240,18 +240,18 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff m_valid = true; m_sync = 0; m_syncFunc = NULL; - m_nextState = m_state = jack_transport_query(m_client, NULL); + m_nextState = m_state = AUD_jack_transport_query(m_client, NULL); pthread_mutex_init(&m_mixingLock, NULL); pthread_cond_init(&m_mixingCondition, NULL); // activate the client - if(jack_activate(m_client)) + if(AUD_jack_activate(m_client)) { - jack_client_close(m_client); + AUD_jack_client_close(m_client); delete[] m_ports; for(unsigned int i = 0; i < specs.channels; i++) - jack_ringbuffer_free(m_ringbuffers[i]); + AUD_jack_ringbuffer_free(m_ringbuffers[i]); delete[] m_ringbuffers; pthread_mutex_destroy(&m_mixingLock); pthread_cond_destroy(&m_mixingCondition); @@ -260,12 +260,12 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff AUD_THROW(AUD_ERROR_JACK, activate_error); } - const char** ports = jack_get_ports(m_client, NULL, NULL, + const char** ports = AUD_jack_get_ports(m_client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); if(ports != NULL) { for(int i = 0; i < m_specs.channels && ports[i]; i++) - jack_connect(m_client, jack_port_name(m_ports[i]), ports[i]); + AUD_jack_connect(m_client, AUD_jack_port_name(m_ports[i]), ports[i]); free(ports); } @@ -282,7 +282,7 @@ AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buff AUD_JackDevice::~AUD_JackDevice() { if(m_valid) - jack_client_close(m_client); + AUD_jack_client_close(m_client); m_valid = false; delete[] m_ports; @@ -295,7 +295,7 @@ AUD_JackDevice::~AUD_JackDevice() pthread_cond_destroy(&m_mixingCondition); pthread_mutex_destroy(&m_mixingLock); for(unsigned int i = 0; i < m_specs.channels; i++) - jack_ringbuffer_free(m_ringbuffers[i]); + AUD_jack_ringbuffer_free(m_ringbuffers[i]); delete[] m_ringbuffers; destroy(); @@ -308,20 +308,20 @@ void AUD_JackDevice::playing(bool playing) void AUD_JackDevice::startPlayback() { - jack_transport_start(m_client); + AUD_jack_transport_start(m_client); m_nextState = JackTransportRolling; } void AUD_JackDevice::stopPlayback() { - jack_transport_stop(m_client); + AUD_jack_transport_stop(m_client); m_nextState = JackTransportStopped; } void AUD_JackDevice::seekPlayback(float time) { if(time >= 0.0f) - jack_transport_locate(m_client, time * m_specs.rate); + AUD_jack_transport_locate(m_client, time * m_specs.rate); } void AUD_JackDevice::setSyncCallback(AUD_syncFunction sync, void* data) @@ -333,13 +333,13 @@ void AUD_JackDevice::setSyncCallback(AUD_syncFunction sync, void* data) float AUD_JackDevice::getPlaybackPosition() { jack_position_t position; - jack_transport_query(m_client, &position); + AUD_jack_transport_query(m_client, &position); return position.frame / (float) m_specs.rate; } bool AUD_JackDevice::doesPlayback() { - jack_transport_state_t state = jack_transport_query(m_client, NULL); + jack_transport_state_t state = AUD_jack_transport_query(m_client, NULL); if(state != m_state) m_nextState = m_state = state; diff --git a/intern/audaspace/jack/AUD_JackDevice.h b/intern/audaspace/jack/AUD_JackDevice.h index dc90c5249a2..a82a6bc5c38 100644 --- a/intern/audaspace/jack/AUD_JackDevice.h +++ b/intern/audaspace/jack/AUD_JackDevice.h @@ -36,12 +36,7 @@ #include <string> -#if defined(__APPLE__) // always first include for jack weaklinking ! -#include <weakjack.h> -#endif - -#include <jack.h> -#include <ringbuffer.h> +#include <AUD_JackLibrary.h> typedef void (*AUD_syncFunction)(void*, int, float); diff --git a/intern/audaspace/jack/AUD_JackLibrary.cpp b/intern/audaspace/jack/AUD_JackLibrary.cpp new file mode 100644 index 00000000000..150d22b324c --- /dev/null +++ b/intern/audaspace/jack/AUD_JackLibrary.cpp @@ -0,0 +1,116 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * Copyright 2013 Blender Foundation + * + * This file is part of AudaSpace. + * + * Audaspace is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * AudaSpace is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Audaspace; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file audaspace/jack/AUD_JacLibrary.cpp + * \ingroup audjack + */ + +#define AUD_JACK_LIBRARY_IMPL + +#include "AUD_JackLibrary.h" + +#ifdef WITH_JACK_DYNLOAD +# include <dlfcn.h> +# include <stdio.h> +#endif + +#ifdef WITH_JACK_DYNLOAD +static void *jack_handle = NULL; +#endif + +static bool jack_supported = false; + +void AUD_jack_init(void) +{ +#ifdef WITH_JACK_DYNLOAD + jack_handle = dlopen("libjack.so", RTLD_LAZY); + + if (!jack_handle) { + fprintf(stderr, "%s\n", dlerror()); + return; + } + +# define JACK_SYMBOL(sym) \ + { \ + char *error; \ + *(void **) (&(AUD_##sym)) = dlsym(jack_handle, #sym); \ + if ((error = dlerror()) != NULL) { \ + fprintf(stderr, "%s\n", error); \ + return; \ + } \ + } (void)0 + + dlerror(); /* Clear any existing error */ +#else // WITH_JACK_DYNLOAD +# define JACK_SYMBOL(sym) AUD_##sym = sym +#endif // WITH_JACK_DYNLOAD + + JACK_SYMBOL(jack_transport_query); + JACK_SYMBOL(jack_transport_locate); + + JACK_SYMBOL(jack_transport_start); + JACK_SYMBOL(jack_transport_stop); + + JACK_SYMBOL(jack_ringbuffer_reset); + JACK_SYMBOL(jack_ringbuffer_write); + JACK_SYMBOL(jack_ringbuffer_write_space); + JACK_SYMBOL(jack_ringbuffer_write_advance); + JACK_SYMBOL(jack_ringbuffer_read); + JACK_SYMBOL(jack_ringbuffer_create); + JACK_SYMBOL(jack_ringbuffer_free); + JACK_SYMBOL(jack_ringbuffer_read_space); + JACK_SYMBOL(jack_set_sync_callback); + + JACK_SYMBOL(jack_port_get_buffer); + + JACK_SYMBOL(jack_client_open); + JACK_SYMBOL(jack_set_process_callback); + JACK_SYMBOL(jack_on_shutdown); + JACK_SYMBOL(jack_port_register); + JACK_SYMBOL(jack_client_close); + JACK_SYMBOL(jack_get_sample_rate); + JACK_SYMBOL(jack_activate); + JACK_SYMBOL(jack_get_ports); + JACK_SYMBOL(jack_port_name); + JACK_SYMBOL(jack_connect); + + jack_supported = true; + +#undef JACK_SYMBOL +} + +void AUD_jack_exit(void) +{ +#ifdef WITH_JACK_DYNLOAD + if (jack_handle) { + dlclose(jack_handle); + } +#endif + jack_supported = false; +} + +bool AUD_jack_supported(void) +{ + return jack_supported; +} diff --git a/intern/audaspace/jack/AUD_JackLibrary.h b/intern/audaspace/jack/AUD_JackLibrary.h new file mode 100644 index 00000000000..c4f50796381 --- /dev/null +++ b/intern/audaspace/jack/AUD_JackLibrary.h @@ -0,0 +1,104 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * Copyright 2013 Blender Foundation + * + * This file is part of AudaSpace. + * + * Audaspace is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * AudaSpace is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Audaspace; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file audaspace/jack/AUD_JacLibrary.cpp + * \ingroup audjack + */ + +#ifndef __AUD_JACKLIBRARY__ +#define __AUD_JACKLIBRARY__ + +#if defined(__APPLE__) // always first include for jack weaklinking ! +#include <weakjack.h> +#endif + +#include <jack.h> +#include <ringbuffer.h> + +#ifdef AUD_JACK_LIBRARY_IMPL +# define JACK_SYM +#else +# define JACK_SYM extern +#endif + +/* All loadable Jack sumbols, prototypes from original jack.h */ + +JACK_SYM jack_transport_state_t (*AUD_jack_transport_query) ( + const jack_client_t *client, + jack_position_t *pos); + +JACK_SYM int (*AUD_jack_transport_locate) (jack_client_t *client, + jack_nframes_t frame); + +JACK_SYM void (*AUD_jack_transport_start) (jack_client_t *client); +JACK_SYM void (*AUD_jack_transport_stop) (jack_client_t *client); + +JACK_SYM void (*AUD_jack_ringbuffer_reset) (jack_ringbuffer_t *rb); +JACK_SYM size_t (*AUD_jack_ringbuffer_write) (jack_ringbuffer_t *rb, + const char *src, size_t cnt); +JACK_SYM size_t (*AUD_jack_ringbuffer_write_space) (const jack_ringbuffer_t *rb); +JACK_SYM void (*AUD_jack_ringbuffer_write_advance) (jack_ringbuffer_t *rb, + size_t cnt); +JACK_SYM size_t (*AUD_jack_ringbuffer_read) (jack_ringbuffer_t *rb, char *dest, + size_t cnt); +JACK_SYM jack_ringbuffer_t *(*AUD_jack_ringbuffer_create) (size_t sz); +JACK_SYM void (*AUD_jack_ringbuffer_free) (jack_ringbuffer_t *rb); +JACK_SYM size_t (*AUD_jack_ringbuffer_read_space) (const jack_ringbuffer_t *rb); +JACK_SYM int (*AUD_jack_set_sync_callback) (jack_client_t *client, + JackSyncCallback sync_callback, + void *arg); + +JACK_SYM void *(*AUD_jack_port_get_buffer) (jack_port_t *, jack_nframes_t); + +JACK_SYM jack_client_t *(*AUD_jack_client_open) (const char *client_name, + jack_options_t options, + jack_status_t *status, ...); +JACK_SYM int (*AUD_jack_set_process_callback) (jack_client_t *client, + JackProcessCallback process_callback, void *arg); +JACK_SYM void (*AUD_jack_on_shutdown) (jack_client_t *client, + JackShutdownCallback function, void *arg); +JACK_SYM jack_port_t *(*AUD_jack_port_register) (jack_client_t *client, + const char *port_name, + const char *port_type, + unsigned long flags, + unsigned long buffer_size); +JACK_SYM int (*AUD_jack_client_close) (jack_client_t *client); +JACK_SYM jack_nframes_t (*AUD_jack_get_sample_rate) (jack_client_t *); +JACK_SYM int (*AUD_jack_activate) (jack_client_t *client); +JACK_SYM const char **(*AUD_jack_get_ports) (jack_client_t *, + const char *port_name_pattern, + const char *type_name_pattern, + unsigned long flags); +JACK_SYM const char *(*AUD_jack_port_name) (const jack_port_t *port); +JACK_SYM int (*AUD_jack_connect) (jack_client_t *, + const char *source_port, + const char *destination_port); + +/* Public API */ + +void AUD_jack_init(void); +void AUD_jack_exit(void); +bool AUD_jack_supported(void); + +#endif // __AUD_JACKLIBRARY__ |