@@ -21,6 +21,7 @@ endif | |||||
# ---------------------------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------------------------- | ||||
BUILD_C_FLAGS += -I$(CWD) -I$(CWD)/includes | |||||
BUILD_CXX_FLAGS += -I$(CWD) -I$(CWD)/backend -I$(CWD)/includes -I$(CWD)/modules -I$(CWD)/utils | BUILD_CXX_FLAGS += -I$(CWD) -I$(CWD)/backend -I$(CWD)/includes -I$(CWD)/modules -I$(CWD)/utils | ||||
LINK_FLAGS += $(MODULEDIR)/juce_core.a | LINK_FLAGS += $(MODULEDIR)/juce_core.a | ||||
LINK_FLAGS += $(JUCE_CORE_LIBS) | LINK_FLAGS += $(JUCE_CORE_LIBS) | ||||
@@ -44,8 +45,10 @@ OBJS = \ | |||||
$(OBJDIR)/libjack_ports.cpp.o \ | $(OBJDIR)/libjack_ports.cpp.o \ | ||||
$(OBJDIR)/libjack_port-searching.cpp.o \ | $(OBJDIR)/libjack_port-searching.cpp.o \ | ||||
$(OBJDIR)/libjack_server-control.cpp.o \ | $(OBJDIR)/libjack_server-control.cpp.o \ | ||||
$(OBJDIR)/libjack_stats.cpp.o \ | |||||
$(OBJDIR)/libjack_time.cpp.o \ | $(OBJDIR)/libjack_time.cpp.o \ | ||||
$(OBJDIR)/libjack_transport.cpp.o | |||||
$(OBJDIR)/libjack_transport.cpp.o \ | |||||
$(OBJDIR)/ringbuffer.c.o | |||||
TARGET = $(BINDIR)/jack/libjack.so.0 | TARGET = $(BINDIR)/jack/libjack.so.0 | ||||
endif | endif | ||||
@@ -70,6 +73,11 @@ $(TARGET): $(OBJS) | |||||
# ---------------------------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------------------------- | ||||
$(OBJDIR)/%.c.o: %.c | |||||
-@mkdir -p $(OBJDIR) | |||||
@echo "Compiling $<" | |||||
@$(CC) $< $(BUILD_C_FLAGS) -c -o $@ | |||||
$(OBJDIR)/%.cpp.o: %.cpp | $(OBJDIR)/%.cpp.o: %.cpp | ||||
-@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
@echo "Compiling $<" | @echo "Compiling $<" | ||||
@@ -551,88 +551,88 @@ void CarlaJackAppClient::run() | |||||
if (cmtl.wasLocked()) | if (cmtl.wasLocked()) | ||||
{ | { | ||||
// tranport for all clients | |||||
const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); | |||||
fServer.playing = bridgeTimeInfo.playing; | |||||
fServer.position.frame = bridgeTimeInfo.frame; | |||||
fServer.position.usecs = bridgeTimeInfo.usecs; | |||||
if (bridgeTimeInfo.valid & 0x1 /* kValidBBT */) | |||||
{ | |||||
fServer.position.valid = JackPositionBBT; | |||||
fServer.position.bar = bridgeTimeInfo.bar; | |||||
fServer.position.beat = bridgeTimeInfo.beat; | |||||
fServer.position.tick = bridgeTimeInfo.tick; | |||||
fServer.position.beats_per_bar = bridgeTimeInfo.beatsPerBar; | |||||
fServer.position.beat_type = bridgeTimeInfo.beatType; | |||||
fServer.position.ticks_per_beat = bridgeTimeInfo.ticksPerBeat; | |||||
fServer.position.beats_per_minute = bridgeTimeInfo.beatsPerMinute; | |||||
fServer.position.bar_start_tick = bridgeTimeInfo.barStartTick; | |||||
} | |||||
else | |||||
{ | |||||
fServer.position.valid = static_cast<jack_position_bits_t>(0); | |||||
} | |||||
float* fdata = fShmAudioPool.data; | float* fdata = fShmAudioPool.data; | ||||
if (JackClientState* const jclient = fClients.getFirst(nullptr)) | |||||
//for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next()) | |||||
if (! fClients.isEmpty()) | |||||
{ | { | ||||
//JackClientState* const jclient(it.getValue(nullptr)); | |||||
//CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr); | |||||
// tranport for all clients | |||||
const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); | |||||
const CarlaMutexTryLocker cmtl2(jclient->mutex); | |||||
fServer.playing = bridgeTimeInfo.playing; | |||||
fServer.position.frame = bridgeTimeInfo.frame; | |||||
fServer.position.usecs = bridgeTimeInfo.usecs; | |||||
if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated) | |||||
if (bridgeTimeInfo.valid & 0x1 /* kValidBBT */) | |||||
{ | { | ||||
if (fAudioIns > 0) | |||||
fdata += fServer.bufferSize*fAudioIns; | |||||
fServer.position.valid = JackPositionBBT; | |||||
if (fAudioOuts > 0) | |||||
carla_zeroFloats(fdata, fServer.bufferSize*fAudioOuts); | |||||
fServer.position.bar = bridgeTimeInfo.bar; | |||||
fServer.position.beat = bridgeTimeInfo.beat; | |||||
fServer.position.tick = bridgeTimeInfo.tick; | |||||
if (jclient->deactivated) | |||||
{ | |||||
fShmRtClientControl.data->procFlags = 1; | |||||
} | |||||
fServer.position.beats_per_bar = bridgeTimeInfo.beatsPerBar; | |||||
fServer.position.beat_type = bridgeTimeInfo.beatType; | |||||
fServer.position.ticks_per_beat = bridgeTimeInfo.ticksPerBeat; | |||||
fServer.position.beats_per_minute = bridgeTimeInfo.beatsPerMinute; | |||||
fServer.position.bar_start_tick = bridgeTimeInfo.barStartTick; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
uint32_t i; | |||||
fServer.position.valid = static_cast<jack_position_bits_t>(0); | |||||
} | |||||
i = 0; | |||||
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next()) | |||||
{ | |||||
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioIns); | |||||
if (JackPortState* const jport = it.getValue(nullptr)) | |||||
jport->buffer = fdata; | |||||
fdata += fServer.bufferSize; | |||||
} | |||||
for (; i++ < fAudioIns;) | |||||
fdata += fServer.bufferSize; | |||||
for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next()) | |||||
{ | |||||
JackClientState* const jclient(it.getValue(nullptr)); | |||||
CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr); | |||||
const CarlaMutexTryLocker cmtl2(jclient->mutex); | |||||
i = 0; | |||||
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next()) | |||||
if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated) | |||||
{ | { | ||||
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioOuts); | |||||
if (JackPortState* const jport = it.getValue(nullptr)) | |||||
jport->buffer = fdata; | |||||
fdata += fServer.bufferSize; | |||||
if (fAudioIns > 0) | |||||
fdata += fServer.bufferSize*fAudioIns; | |||||
if (fAudioOuts > 0) | |||||
carla_zeroFloats(fdata, fServer.bufferSize*fAudioOuts); | |||||
if (jclient->deactivated) | |||||
{ | |||||
fShmRtClientControl.data->procFlags = 1; | |||||
} | |||||
} | } | ||||
for (; i++ < fAudioOuts;) | |||||
else | |||||
{ | { | ||||
//carla_stderr("clearing buffer %i", i); | |||||
carla_zeroFloats(fdata, fServer.bufferSize); | |||||
fdata += fServer.bufferSize; | |||||
uint32_t i; | |||||
i = 0; | |||||
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next()) | |||||
{ | |||||
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioIns); | |||||
if (JackPortState* const jport = it.getValue(nullptr)) | |||||
jport->buffer = fdata; | |||||
fdata += fServer.bufferSize; | |||||
} | |||||
for (; i++ < fAudioIns;) | |||||
fdata += fServer.bufferSize; | |||||
i = 0; | |||||
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next()) | |||||
{ | |||||
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioOuts); | |||||
if (JackPortState* const jport = it.getValue(nullptr)) | |||||
jport->buffer = fdata; | |||||
fdata += fServer.bufferSize; | |||||
} | |||||
for (; i++ < fAudioOuts;) | |||||
{ | |||||
carla_zeroFloats(fdata, fServer.bufferSize); | |||||
fdata += fServer.bufferSize; | |||||
} | |||||
jclient->processCb(fServer.bufferSize, jclient->processCbPtr); | |||||
} | } | ||||
jclient->processCb(fServer.bufferSize, jclient->processCbPtr); | |||||
} | } | ||||
} | } | ||||
else | else | ||||
@@ -679,7 +679,11 @@ void CarlaJackAppClient::run() | |||||
{ | { | ||||
const CarlaMutexLocker cms(fRealtimeThreadMutex); | const CarlaMutexLocker cms(fRealtimeThreadMutex); | ||||
if (JackClientState* const jclient = fClients.getLast(nullptr)) | |||||
if (fClients.isEmpty()) | |||||
{ | |||||
activated = false; | |||||
} | |||||
else if (JackClientState* const jclient = fClients.getLast(nullptr)) | |||||
{ | { | ||||
const CarlaMutexLocker cms(jclient->mutex); | const CarlaMutexLocker cms(jclient->mutex); | ||||
activated = jclient->activated; | activated = jclient->activated; | ||||
@@ -120,6 +120,9 @@ struct JackClientState { | |||||
JackProcessCallback processCb; | JackProcessCallback processCb; | ||||
void* processCbPtr; | void* processCbPtr; | ||||
JackFreewheelCallback freewheelCb; | |||||
void* freewheelCbPtr; | |||||
JackBufferSizeCallback bufferSizeCb; | JackBufferSizeCallback bufferSizeCb; | ||||
void* bufferSizeCbPtr; | void* bufferSizeCbPtr; | ||||
@@ -144,6 +147,8 @@ struct JackClientState { | |||||
infoShutdownCbPtr(nullptr), | infoShutdownCbPtr(nullptr), | ||||
processCb(nullptr), | processCb(nullptr), | ||||
processCbPtr(nullptr), | processCbPtr(nullptr), | ||||
freewheelCb(nullptr), | |||||
freewheelCbPtr(nullptr), | |||||
bufferSizeCb(nullptr), | bufferSizeCb(nullptr), | ||||
bufferSizeCbPtr(nullptr), | bufferSizeCbPtr(nullptr), | ||||
sampleRateCb(nullptr), | sampleRateCb(nullptr), | ||||
@@ -15,7 +15,6 @@ | |||||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
*/ | */ | ||||
// need to include this first | |||||
#include "libjack.hpp" | #include "libjack.hpp" | ||||
CARLA_BACKEND_USE_NAMESPACE | CARLA_BACKEND_USE_NAMESPACE | ||||
@@ -66,8 +65,15 @@ int jack_set_process_callback(jack_client_t* client, JackProcessCallback callbac | |||||
} | } | ||||
CARLA_EXPORT | CARLA_EXPORT | ||||
int jack_set_freewheel_callback(jack_client_t*, JackFreewheelCallback, void*) | |||||
int jack_set_freewheel_callback(jack_client_t* client, JackFreewheelCallback callback, void* arg) | |||||
{ | { | ||||
JackClientState* const jclient = (JackClientState*)client; | |||||
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1); | |||||
const CarlaMutexLocker cms(jclient->mutex); | |||||
jclient->freewheelCb = callback; | |||||
jclient->freewheelCbPtr = arg; | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -15,9 +15,12 @@ | |||||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
*/ | */ | ||||
// need to include this first | |||||
#include "libjack.hpp" | #include "libjack.hpp" | ||||
#define JACK_UUID_SIZE 36 | |||||
#define JACK_UUID_STRING_SIZE (JACK_UUID_SIZE+1) /* includes trailing null */ | |||||
#define JACK_UUID_EMPTY_INITIALIZER 0 | |||||
CARLA_BACKEND_USE_NAMESPACE | CARLA_BACKEND_USE_NAMESPACE | ||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
@@ -26,45 +29,132 @@ CARLA_EXPORT | |||||
const char* JACK_METADATA_PRETTY_NAME; | const char* JACK_METADATA_PRETTY_NAME; | ||||
const char* JACK_METADATA_PRETTY_NAME = "http://jackaudio.org/metadata/pretty-name"; | const char* JACK_METADATA_PRETTY_NAME = "http://jackaudio.org/metadata/pretty-name"; | ||||
// extern const char* JACK_METADATA_HARDWARE; | |||||
// extern const char* JACK_METADATA_CONNECTED; | |||||
// extern const char* JACK_METADATA_PORT_GROUP; | |||||
// extern const char* JACK_METADATA_ICON_SMALL; | |||||
// extern const char* JACK_METADATA_ICON_LARGE; | |||||
CARLA_EXPORT | |||||
const char* JACK_METADATA_HARDWARE; | |||||
const char* JACK_METADATA_HARDWARE = "http://jackaudio.org/metadata/hardware"; | |||||
CARLA_EXPORT | |||||
const char* JACK_METADATA_CONNECTED; | |||||
const char* JACK_METADATA_CONNECTED = "http://jackaudio.org/metadata/connected"; | |||||
CARLA_EXPORT | |||||
const char* JACK_METADATA_PORT_GROUP; | |||||
const char* JACK_METADATA_PORT_GROUP = "http://jackaudio.org/metadata/port-group"; | |||||
CARLA_EXPORT | |||||
const char* JACK_METADATA_ICON_SMALL; | |||||
const char* JACK_METADATA_ICON_SMALL = "http://jackaudio.org/metadata/icon-small"; | |||||
CARLA_EXPORT | |||||
const char* JACK_METADATA_ICON_LARGE; | |||||
const char* JACK_METADATA_ICON_LARGE = "http://jackaudio.org/metadata/icon-large"; | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// int | |||||
// jack_set_property(jack_client_t*, | |||||
// jack_uuid_t subject, | |||||
// const char* key, | |||||
// const char* value, | |||||
// const char* type); | |||||
CARLA_EXPORT | |||||
int jack_set_property(jack_client_t*, jack_uuid_t, const char*, const char*, const char*) | |||||
{ | |||||
return -1; | |||||
} | |||||
// int | |||||
// jack_get_property(jack_uuid_t subject, | |||||
// const char* key, | |||||
// char** value, | |||||
// char** type); | |||||
CARLA_EXPORT | |||||
int jack_get_property(jack_uuid_t, const char*, char**, char**) | |||||
{ | |||||
return -1; | |||||
} | |||||
// void | |||||
// jack_free_description (jack_description_t* desc, int free_description_itself); | |||||
CARLA_EXPORT | |||||
void jack_free_description(jack_description_t*, int) | |||||
{ | |||||
} | |||||
CARLA_EXPORT | |||||
int jack_get_properties(jack_uuid_t, jack_description_t*) | |||||
{ | |||||
return -1; | |||||
} | |||||
// int | |||||
// jack_get_properties (jack_uuid_t subject, | |||||
// jack_description_t* desc); | |||||
CARLA_EXPORT | |||||
int jack_get_all_properties(jack_description_t**) | |||||
{ | |||||
return -1; | |||||
} | |||||
// int | |||||
// jack_get_all_properties (jack_description_t** descs); | |||||
CARLA_EXPORT | |||||
int jack_remove_property(jack_client_t*, jack_uuid_t, const char*) | |||||
{ | |||||
return -1; | |||||
} | |||||
// int jack_remove_property (jack_client_t* client, jack_uuid_t subject, const char* key); | |||||
CARLA_EXPORT | |||||
int jack_remove_properties(jack_client_t*, jack_uuid_t) | |||||
{ | |||||
return -1; | |||||
} | |||||
// int jack_remove_properties (jack_client_t* client, jack_uuid_t subject); | |||||
CARLA_EXPORT | |||||
int jack_remove_all_properties(jack_client_t*) | |||||
{ | |||||
return -1; | |||||
} | |||||
// int jack_remove_all_properties (jack_client_t* client); | |||||
CARLA_EXPORT | |||||
int jack_set_property_change_callback(jack_client_t*, JackPropertyChangeCallback, void*) | |||||
{ | |||||
return -1; | |||||
} | |||||
// int jack_set_property_change_callback (jack_client_t* client, | |||||
// JackPropertyChangeCallback callback, | |||||
// void* arg); | |||||
// -------------------------------------------------------------------------------------------------------------------- | |||||
CARLA_EXPORT | |||||
jack_uuid_t jack_client_uuid_generate() | |||||
{ | |||||
return 0; | |||||
} | |||||
CARLA_EXPORT | |||||
jack_uuid_t jack_port_uuid_generate(uint32_t) | |||||
{ | |||||
return 0; | |||||
} | |||||
CARLA_EXPORT | |||||
uint32_t jack_uuid_to_index(jack_uuid_t) | |||||
{ | |||||
return 0; | |||||
} | |||||
CARLA_EXPORT | |||||
int jack_uuid_compare(jack_uuid_t, jack_uuid_t) | |||||
{ | |||||
return 0; | |||||
} | |||||
CARLA_EXPORT | |||||
void jack_uuid_copy(jack_uuid_t*, jack_uuid_t) | |||||
{ | |||||
} | |||||
CARLA_EXPORT | |||||
void jack_uuid_clear(jack_uuid_t*) | |||||
{ | |||||
} | |||||
CARLA_EXPORT | |||||
int jack_uuid_parse(const char*, jack_uuid_t*) | |||||
{ | |||||
return 0; | |||||
} | |||||
CARLA_EXPORT | |||||
void jack_uuid_unparse(jack_uuid_t, char buf[JACK_UUID_STRING_SIZE]) | |||||
{ | |||||
} | |||||
CARLA_EXPORT | |||||
int jack_uuid_empty(jack_uuid_t) | |||||
{ | |||||
return 0; | |||||
} | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- |
@@ -98,7 +98,7 @@ jack_port_t* jack_port_by_name(jack_client_t* /*client*/, const char* name) | |||||
{ | { | ||||
name += 8; | name += 8; | ||||
const int index = std::atoi(name); | |||||
const int index = std::atoi(name)-1; | |||||
CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < 2, nullptr); | CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < 2, nullptr); | ||||
return (jack_port_t*)&capturePorts[index]; | return (jack_port_t*)&capturePorts[index]; | ||||
@@ -107,7 +107,7 @@ jack_port_t* jack_port_by_name(jack_client_t* /*client*/, const char* name) | |||||
{ | { | ||||
name += 9; | name += 9; | ||||
const int index = std::atoi(name); | |||||
const int index = std::atoi(name)-1; | |||||
CARLA_SAFE_ASSERT_RETURN(index >= 0, nullptr); | CARLA_SAFE_ASSERT_RETURN(index >= 0, nullptr); | ||||
return (jack_port_t*)&playbackPorts[index]; | return (jack_port_t*)&playbackPorts[index]; | ||||
@@ -175,10 +175,17 @@ int jack_port_connected(const jack_port_t*) | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
// const char ** jack_port_get_connections (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; | |||||
CARLA_EXPORT | |||||
const char** jack_port_get_connections (const jack_port_t*) | |||||
{ | |||||
return nullptr; | |||||
} | |||||
// const char ** jack_port_get_all_connections (const jack_client_t *client, | |||||
// const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; | |||||
CARLA_EXPORT | |||||
const char** jack_port_get_all_connections(const jack_client_t*, const jack_port_t*) | |||||
{ | |||||
return nullptr; | |||||
} | |||||
// -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
@@ -0,0 +1,41 @@ | |||||
/* | |||||
* Carla JACK API for external applications | |||||
* Copyright (C) 2016-2017 Filipe Coelho <falktx@falktx.com> | |||||
* | |||||
* This program 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 any later version. | |||||
* | |||||
* This program 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. | |||||
* | |||||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||||
*/ | |||||
#include "libjack.hpp" | |||||
CARLA_BACKEND_USE_NAMESPACE | |||||
// -------------------------------------------------------------------------------------------------------------------- | |||||
CARLA_EXPORT | |||||
float jack_get_max_delayed_usecs(jack_client_t*) | |||||
{ | |||||
return 0.0f; | |||||
} | |||||
CARLA_EXPORT | |||||
float jack_get_xrun_delayed_usecs(jack_client_t*) | |||||
{ | |||||
return 0.0f; | |||||
} | |||||
CARLA_EXPORT | |||||
void jack_reset_max_delayed_usecs(jack_client_t*) | |||||
{ | |||||
} | |||||
// -------------------------------------------------------------------------------------------------------------------- |
@@ -0,0 +1,405 @@ | |||||
/* | |||||
Copyright (C) 2000 Paul Davis | |||||
Copyright (C) 2003 Rohan Drape | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code. | |||||
This is safe for the case of one read thread and one write thread. | |||||
*/ | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#ifdef USE_MLOCK | |||||
#include <sys/mman.h> | |||||
#endif /* USE_MLOCK */ | |||||
#include "CarlaDefines.h" | |||||
typedef struct { | |||||
char *buf; | |||||
size_t len; | |||||
} | |||||
jack_ringbuffer_data_t ; | |||||
typedef struct { | |||||
char *buf; | |||||
volatile size_t write_ptr; | |||||
volatile size_t read_ptr; | |||||
size_t size; | |||||
size_t size_mask; | |||||
int mlocked; | |||||
} | |||||
jack_ringbuffer_t ; | |||||
CARLA_EXPORT jack_ringbuffer_t *jack_ringbuffer_create(size_t sz); | |||||
CARLA_EXPORT void jack_ringbuffer_free(jack_ringbuffer_t *rb); | |||||
CARLA_EXPORT void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb, | |||||
jack_ringbuffer_data_t *vec); | |||||
CARLA_EXPORT void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb, | |||||
jack_ringbuffer_data_t *vec); | |||||
CARLA_EXPORT size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt); | |||||
CARLA_EXPORT size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt); | |||||
CARLA_EXPORT void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt); | |||||
CARLA_EXPORT size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb); | |||||
CARLA_EXPORT int jack_ringbuffer_mlock(jack_ringbuffer_t *rb); | |||||
CARLA_EXPORT void jack_ringbuffer_reset(jack_ringbuffer_t *rb); | |||||
CARLA_EXPORT void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz); | |||||
CARLA_EXPORT size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src, | |||||
size_t cnt); | |||||
void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt); | |||||
size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb); | |||||
/* Create a new ringbuffer to hold at least `sz' bytes of data. The | |||||
actual buffer size is rounded up to the next power of two. */ | |||||
CARLA_EXPORT jack_ringbuffer_t * | |||||
jack_ringbuffer_create (size_t sz) | |||||
{ | |||||
int power_of_two; | |||||
jack_ringbuffer_t *rb; | |||||
if ((rb = (jack_ringbuffer_t *) malloc (sizeof (jack_ringbuffer_t))) == NULL) { | |||||
return NULL; | |||||
} | |||||
for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++); | |||||
rb->size = 1 << power_of_two; | |||||
rb->size_mask = rb->size; | |||||
rb->size_mask -= 1; | |||||
rb->write_ptr = 0; | |||||
rb->read_ptr = 0; | |||||
if ((rb->buf = (char *) malloc (rb->size)) == NULL) { | |||||
free (rb); | |||||
return NULL; | |||||
} | |||||
rb->mlocked = 0; | |||||
return rb; | |||||
} | |||||
/* Free all data associated with the ringbuffer `rb'. */ | |||||
CARLA_EXPORT void | |||||
jack_ringbuffer_free (jack_ringbuffer_t * rb) | |||||
{ | |||||
#ifdef USE_MLOCK | |||||
if (rb->mlocked) { | |||||
munlock (rb->buf, rb->size); | |||||
} | |||||
#endif /* USE_MLOCK */ | |||||
free (rb->buf); | |||||
free (rb); | |||||
} | |||||
/* Lock the data block of `rb' using the system call 'mlock'. */ | |||||
CARLA_EXPORT int | |||||
jack_ringbuffer_mlock (jack_ringbuffer_t * rb) | |||||
{ | |||||
#ifdef USE_MLOCK | |||||
if (mlock (rb->buf, rb->size)) { | |||||
return -1; | |||||
} | |||||
#endif /* USE_MLOCK */ | |||||
rb->mlocked = 1; | |||||
return 0; | |||||
} | |||||
/* Reset the read and write pointers to zero. This is not thread | |||||
safe. */ | |||||
CARLA_EXPORT void | |||||
jack_ringbuffer_reset (jack_ringbuffer_t * rb) | |||||
{ | |||||
rb->read_ptr = 0; | |||||
rb->write_ptr = 0; | |||||
memset(rb->buf, 0, rb->size); | |||||
} | |||||
/* Reset the read and write pointers to zero. This is not thread | |||||
safe. */ | |||||
CARLA_EXPORT void | |||||
jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz) | |||||
{ | |||||
rb->size = sz; | |||||
rb->size_mask = rb->size; | |||||
rb->size_mask -= 1; | |||||
rb->read_ptr = 0; | |||||
rb->write_ptr = 0; | |||||
} | |||||
/* Return the number of bytes available for reading. This is the | |||||
number of bytes in front of the read pointer and behind the write | |||||
pointer. */ | |||||
CARLA_EXPORT size_t | |||||
jack_ringbuffer_read_space (const jack_ringbuffer_t * rb) | |||||
{ | |||||
size_t w, r; | |||||
w = rb->write_ptr; | |||||
r = rb->read_ptr; | |||||
if (w > r) { | |||||
return w - r; | |||||
} else { | |||||
return (w - r + rb->size) & rb->size_mask; | |||||
} | |||||
} | |||||
/* Return the number of bytes available for writing. This is the | |||||
number of bytes in front of the write pointer and behind the read | |||||
pointer. */ | |||||
CARLA_EXPORT size_t | |||||
jack_ringbuffer_write_space (const jack_ringbuffer_t * rb) | |||||
{ | |||||
size_t w, r; | |||||
w = rb->write_ptr; | |||||
r = rb->read_ptr; | |||||
if (w > r) { | |||||
return ((r - w + rb->size) & rb->size_mask) - 1; | |||||
} else if (w < r) { | |||||
return (r - w) - 1; | |||||
} else { | |||||
return rb->size - 1; | |||||
} | |||||
} | |||||
/* The copying data reader. Copy at most `cnt' bytes from `rb' to | |||||
`dest'. Returns the actual number of bytes copied. */ | |||||
CARLA_EXPORT size_t | |||||
jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt) | |||||
{ | |||||
size_t free_cnt; | |||||
size_t cnt2; | |||||
size_t to_read; | |||||
size_t n1, n2; | |||||
if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) { | |||||
return 0; | |||||
} | |||||
to_read = cnt > free_cnt ? free_cnt : cnt; | |||||
cnt2 = rb->read_ptr + to_read; | |||||
if (cnt2 > rb->size) { | |||||
n1 = rb->size - rb->read_ptr; | |||||
n2 = cnt2 & rb->size_mask; | |||||
} else { | |||||
n1 = to_read; | |||||
n2 = 0; | |||||
} | |||||
memcpy (dest, &(rb->buf[rb->read_ptr]), n1); | |||||
rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask; | |||||
if (n2) { | |||||
memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2); | |||||
rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask; | |||||
} | |||||
return to_read; | |||||
} | |||||
/* The copying data reader w/o read pointer advance. Copy at most | |||||
`cnt' bytes from `rb' to `dest'. Returns the actual number of bytes | |||||
copied. */ | |||||
CARLA_EXPORT size_t | |||||
jack_ringbuffer_peek (jack_ringbuffer_t * rb, char *dest, size_t cnt) | |||||
{ | |||||
size_t free_cnt; | |||||
size_t cnt2; | |||||
size_t to_read; | |||||
size_t n1, n2; | |||||
size_t tmp_read_ptr; | |||||
tmp_read_ptr = rb->read_ptr; | |||||
if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) { | |||||
return 0; | |||||
} | |||||
to_read = cnt > free_cnt ? free_cnt : cnt; | |||||
cnt2 = tmp_read_ptr + to_read; | |||||
if (cnt2 > rb->size) { | |||||
n1 = rb->size - tmp_read_ptr; | |||||
n2 = cnt2 & rb->size_mask; | |||||
} else { | |||||
n1 = to_read; | |||||
n2 = 0; | |||||
} | |||||
memcpy (dest, &(rb->buf[tmp_read_ptr]), n1); | |||||
tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask; | |||||
if (n2) { | |||||
memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2); | |||||
} | |||||
return to_read; | |||||
} | |||||
/* The copying data writer. Copy at most `cnt' bytes to `rb' from | |||||
`src'. Returns the actual number of bytes copied. */ | |||||
CARLA_EXPORT size_t | |||||
jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt) | |||||
{ | |||||
size_t free_cnt; | |||||
size_t cnt2; | |||||
size_t to_write; | |||||
size_t n1, n2; | |||||
if ((free_cnt = jack_ringbuffer_write_space (rb)) == 0) { | |||||
return 0; | |||||
} | |||||
to_write = cnt > free_cnt ? free_cnt : cnt; | |||||
cnt2 = rb->write_ptr + to_write; | |||||
if (cnt2 > rb->size) { | |||||
n1 = rb->size - rb->write_ptr; | |||||
n2 = cnt2 & rb->size_mask; | |||||
} else { | |||||
n1 = to_write; | |||||
n2 = 0; | |||||
} | |||||
memcpy (&(rb->buf[rb->write_ptr]), src, n1); | |||||
rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask; | |||||
if (n2) { | |||||
memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2); | |||||
rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask; | |||||
} | |||||
return to_write; | |||||
} | |||||
/* Advance the read pointer `cnt' places. */ | |||||
CARLA_EXPORT void | |||||
jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt) | |||||
{ | |||||
size_t tmp = (rb->read_ptr + cnt) & rb->size_mask; | |||||
rb->read_ptr = tmp; | |||||
} | |||||
/* Advance the write pointer `cnt' places. */ | |||||
CARLA_EXPORT void | |||||
jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt) | |||||
{ | |||||
size_t tmp = (rb->write_ptr + cnt) & rb->size_mask; | |||||
rb->write_ptr = tmp; | |||||
} | |||||
/* The non-copying data reader. `vec' is an array of two places. Set | |||||
the values at `vec' to hold the current readable data at `rb'. If | |||||
the readable data is in one segment the second segment has zero | |||||
length. */ | |||||
CARLA_EXPORT void | |||||
jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb, | |||||
jack_ringbuffer_data_t * vec) | |||||
{ | |||||
size_t free_cnt; | |||||
size_t cnt2; | |||||
size_t w, r; | |||||
w = rb->write_ptr; | |||||
r = rb->read_ptr; | |||||
if (w > r) { | |||||
free_cnt = w - r; | |||||
} else { | |||||
free_cnt = (w - r + rb->size) & rb->size_mask; | |||||
} | |||||
cnt2 = r + free_cnt; | |||||
if (cnt2 > rb->size) { | |||||
/* Two part vector: the rest of the buffer after the current write | |||||
ptr, plus some from the start of the buffer. */ | |||||
vec[0].buf = &(rb->buf[r]); | |||||
vec[0].len = rb->size - r; | |||||
vec[1].buf = rb->buf; | |||||
vec[1].len = cnt2 & rb->size_mask; | |||||
} else { | |||||
/* Single part vector: just the rest of the buffer */ | |||||
vec[0].buf = &(rb->buf[r]); | |||||
vec[0].len = free_cnt; | |||||
vec[1].len = 0; | |||||
} | |||||
} | |||||
/* The non-copying data writer. `vec' is an array of two places. Set | |||||
the values at `vec' to hold the current writeable data at `rb'. If | |||||
the writeable data is in one segment the second segment has zero | |||||
length. */ | |||||
CARLA_EXPORT void | |||||
jack_ringbuffer_get_write_vector (const jack_ringbuffer_t * rb, | |||||
jack_ringbuffer_data_t * vec) | |||||
{ | |||||
size_t free_cnt; | |||||
size_t cnt2; | |||||
size_t w, r; | |||||
w = rb->write_ptr; | |||||
r = rb->read_ptr; | |||||
if (w > r) { | |||||
free_cnt = ((r - w + rb->size) & rb->size_mask) - 1; | |||||
} else if (w < r) { | |||||
free_cnt = (r - w) - 1; | |||||
} else { | |||||
free_cnt = rb->size - 1; | |||||
} | |||||
cnt2 = w + free_cnt; | |||||
if (cnt2 > rb->size) { | |||||
/* Two part vector: the rest of the buffer after the current write | |||||
ptr, plus some from the start of the buffer. */ | |||||
vec[0].buf = &(rb->buf[w]); | |||||
vec[0].len = rb->size - w; | |||||
vec[1].buf = rb->buf; | |||||
vec[1].len = cnt2 & rb->size_mask; | |||||
} else { | |||||
vec[0].buf = &(rb->buf[w]); | |||||
vec[0].len = free_cnt; | |||||
vec[1].len = 0; | |||||
} | |||||
} | |||||
@@ -24,17 +24,25 @@ def signalHandler(sig, frame): | |||||
# -------------------------------------------------------------------------------------------------------- | # -------------------------------------------------------------------------------------------------------- | ||||
binaryDir = "/home/falktx/Personal/FOSS/GIT/falkTX/Carla/bin" | |||||
host = CarlaHostDLL("/home/falktx/FOSS/GIT-mine/falkTX/Carla/bin/libcarla_standalone2.so", True) | |||||
binaryDir = "/home/falktx/Personal/GIT-mine/falkTX/Carla/bin" | |||||
host = CarlaHostDLL("/home/falktx/Personal/GIT-mine/falkTX/Carla/bin/libcarla_standalone2.so", True) | |||||
host.set_engine_option(ENGINE_OPTION_PATH_BINARIES, 0, binaryDir) | host.set_engine_option(ENGINE_OPTION_PATH_BINARIES, 0, binaryDir) | ||||
host.set_engine_option(ENGINE_OPTION_PROCESS_MODE, 2, "") | |||||
host.set_engine_option(ENGINE_OPTION_TRANSPORT_MODE, 0, "") | |||||
if not host.engine_init("JACK", "Carla-Plugin-JACK"): | |||||
if not host.engine_init("PulseAudio", "Carla-Plugin-JACK"): | |||||
print("Engine failed to initialize, possible reasons:\n%s" % host.get_last_error()) | print("Engine failed to initialize, possible reasons:\n%s" % host.get_last_error()) | ||||
exit(1) | exit(1) | ||||
fname = "/usr/bin/pulseaudio" | fname = "/usr/bin/pulseaudio" | ||||
label = "--high-priority --realtime --exit-idle-time=-1 --file=/usr/share/cadence/pulse2jack/play.pa -n" | label = "--high-priority --realtime --exit-idle-time=-1 --file=/usr/share/cadence/pulse2jack/play.pa -n" | ||||
fname = "/usr/bin/patchage" | |||||
label = "" | |||||
fname = "/usr/bin/carla" | |||||
label = "" | |||||
if not host.add_plugin(BINARY_NATIVE, PLUGIN_JACK, fname, "", label, 0, None, 0): | if not host.add_plugin(BINARY_NATIVE, PLUGIN_JACK, fname, "", label, 0, None, 0): | ||||
print("Failed to load plugin, possible reasons:\n%s" % host.get_last_error()) | print("Failed to load plugin, possible reasons:\n%s" % host.get_last_error()) | ||||
host.engine_close() | host.engine_close() | ||||