From a552c190ebf3fb531691122c0fb8dcca10153ef8 Mon Sep 17 00:00:00 2001 From: falkTX Date: Tue, 16 Jul 2013 05:11:38 +0100 Subject: [PATCH] Import and use jackbridge from Carla in C++ code --- c++/Makefile.mk | 2 - c++/jack_utils.hpp | 16 +- c++/jackbridge/CarlaDefines.hpp | 150 ++++ c++/jackbridge/CarlaLibUtils.hpp | 100 +++ c++/jackbridge/CarlaUtils.hpp | 418 +++++++++++ c++/jackbridge/JackBridge.cpp | 1092 +++++++++++++++++++++++++++++ c++/jackbridge/JackBridge.hpp | 343 +++++++++ c++/jackbridge/Makefile | 67 ++ c++/jackmeter/Makefile | 2 +- c++/jackmeter/jackmeter.cpp | 54 +- c++/xycontroller/Makefile | 2 +- c++/xycontroller/xycontroller.cpp | 34 +- data/windows/build-win32.sh | 7 - data/windows/build-win64.sh | 7 - data/windows/jack.pc | 10 - 15 files changed, 2221 insertions(+), 83 deletions(-) create mode 100644 c++/jackbridge/CarlaDefines.hpp create mode 100644 c++/jackbridge/CarlaLibUtils.hpp create mode 100644 c++/jackbridge/CarlaUtils.hpp create mode 100644 c++/jackbridge/JackBridge.cpp create mode 100644 c++/jackbridge/JackBridge.hpp create mode 100644 c++/jackbridge/Makefile delete mode 100644 data/windows/jack.pc diff --git a/c++/Makefile.mk b/c++/Makefile.mk index 4d7def9..cc733ff 100644 --- a/c++/Makefile.mk +++ b/c++/Makefile.mk @@ -36,7 +36,5 @@ endif # -------------------------------------------------------------- -HAVE_QT5 = $(shell pkg-config --atleast-version 5 QtCore && echo true) - # Currently broken # HAVE_JACKSESSION = $(shell pkg-config --atleast-version=0.121.0 jack && echo true) diff --git a/c++/jack_utils.hpp b/c++/jack_utils.hpp index 10aae16..63b97c8 100644 --- a/c++/jack_utils.hpp +++ b/c++/jack_utils.hpp @@ -18,37 +18,31 @@ #ifndef __JACK_UTILS_HPP__ #define __JACK_UTILS_HPP__ -#include -#include -#include - -#ifdef HAVE_JACKSESSION -# include -#endif +#include "jackbridge/JackBridge.cpp" #include #include #include static inline -std::vector jack_port_get_all_connections_as_vector(jack_client_t* const client, jack_port_t* const port) +std::vector jackbridge_port_get_all_connections_as_vector(jack_client_t* const client, jack_port_t* const port) { std::vector connectionsVector; - const char** connections = jack_port_get_all_connections(client, port); + const char** connections = jackbridge_port_get_all_connections(client, port); if (connections) { for (int i=0; connections[i]; i++) connectionsVector.push_back(strdup(connections[i])); - jack_free(connections); + jackbridge_free(connections); } return connectionsVector; } static inline -std::string jack_status_get_error_string(const jack_status_t& status) +std::string jackbridge_status_get_error_string(const jack_status_t& status) { std::string errorString; diff --git a/c++/jackbridge/CarlaDefines.hpp b/c++/jackbridge/CarlaDefines.hpp new file mode 100644 index 0000000..9043535 --- /dev/null +++ b/c++/jackbridge/CarlaDefines.hpp @@ -0,0 +1,150 @@ +/* + * Carla common defines + * Copyright (C) 2011-2013 Filipe Coelho + * + * 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 COPYING file + */ + +#ifndef __CARLA_DEFINES_HPP__ +#define __CARLA_DEFINES_HPP__ + +// Check OS +#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +# define CARLA_OS_WIN64 +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# define CARLA_OS_WIN32 +#elif defined(__APPLE__) +# define CARLA_OS_MAC +#elif defined(__HAIKU__) +# define CARLA_OS_HAIKU +#elif defined(__linux__) || defined(__linux) +# define CARLA_OS_LINUX +#else +# warning Unsupported platform! +#endif + +#if defined(CARLA_OS_WIN32) || defined(CARLA_OS_WIN64) +# define CARLA_OS_WIN +#elif ! defined(CARLA_OS_HAIKU) +# define CARLA_OS_UNIX +#endif + +// Check for C++11 support +#if defined(HAVE_CPP11_SUPPORT) +# define CARLA_PROPER_CPP11_SUPPORT +#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 +# define CARLA_PROPER_CPP11_SUPPORT +# if (__GNUC__ * 100 + __GNUC_MINOR__) < 407 +# define override // gcc4.7+ only +# endif +# endif +#endif + +#ifndef CARLA_PROPER_CPP11_SUPPORT +# define override +# define noexcept +# define nullptr (0) +#endif + +// Common includes +#ifdef CARLA_OS_WIN +# include +# include +#else +# include +# ifndef __cdecl +# define __cdecl +# endif +#endif + +// Define various string format types +#if defined(CARLA_OS_WIN64) +# define P_INT64 "%I64i" +# define P_INTPTR "%I64i" +# define P_UINTPTR "%I64x" +# define P_SIZE "%I64u" +#elif defined(CARLA_OS_WIN32) +# define P_INT64 "%I64i" +# define P_INTPTR "%i" +# define P_UINTPTR "%x" +# define P_SIZE "%u" +#elif __WORDSIZE == 64 +# define P_INT64 "%li" +# define P_INTPTR "%li" +# define P_UINTPTR "%lx" +# define P_SIZE "%lu" +#else +# define P_INT64 "%lli" +# define P_INTPTR "%i" +# define P_UINTPTR "%x" +# define P_SIZE "%u" +#endif + +// Define BINARY_NATIVE +#if defined(CARLA_OS_HAIKU) || defined(CARLA_OS_UNIX) +# if defined (__LP64__) || defined (_LP64) +# define BINARY_NATIVE BINARY_POSIX64 +# else +# define BINARY_NATIVE BINARY_POSIX32 +# endif +#elif defined(CARLA_OS_WIN) +# ifdef CARLA_OS_WIN64 +# define BINARY_NATIVE BINARY_WIN64 +# else +# define BINARY_NATIVE BINARY_WIN32 +# endif +#else +# warning Unknown binary native +# define BINARY_NATIVE BINARY_OTHER +#endif + +// Define CARLA_SAFE_ASSERT* +#define CARLA_SAFE_ASSERT(cond) ((!(cond)) ? carla_assert(#cond, __FILE__, __LINE__) : pass()) +#define CARLA_SAFE_ASSERT_INT(cond, value) ((!(cond)) ? carla_assert_int(#cond, __FILE__, __LINE__, value) : pass()) +#define CARLA_SAFE_ASSERT_INT2(cond, v1, v2) ((!(cond)) ? carla_assert_int2(#cond, __FILE__, __LINE__, v1, v2) : pass()) + +// Define CARLA_ASSERT* +#if defined(CARLA_NO_ASSERTS) +# define CARLA_ASSERT(cond) +# define CARLA_ASSERT_INT(cond, value) +# define CARLA_ASSERT_INT2(cond, v1, v2) +#elif defined(NDEBUG) +# define CARLA_ASSERT CARLA_SAFE_ASSERT +# define CARLA_ASSERT_INT CARLA_SAFE_ASSERT_INT +# define CARLA_ASSERT_INT2 CARLA_SAFE_ASSERT_INT2 +#else +# define CARLA_ASSERT(cond) assert(cond) +# define CARLA_ASSERT_INT(cond, value) assert(cond) +# define CARLA_ASSERT_INT2(cond, v1, v2) assert(cond) +#endif + +// Define CARLA_EXPORT +#ifdef BUILD_BRIDGE +# define CARLA_EXPORT extern "C" +#else +# if defined(CARLA_OS_WIN) && ! defined(__WINE__) +# define CARLA_EXPORT extern "C" __declspec (dllexport) +# else +# define CARLA_EXPORT extern "C" __attribute__ ((visibility("default"))) +# endif +#endif + +// Define OS_SEP +#ifdef CARLA_OS_WIN +# define OS_SEP '\\' +#else +# define OS_SEP '/' +#endif + +#endif // __CARLA_DEFINES_HPP__ diff --git a/c++/jackbridge/CarlaLibUtils.hpp b/c++/jackbridge/CarlaLibUtils.hpp new file mode 100644 index 0000000..68e3fae --- /dev/null +++ b/c++/jackbridge/CarlaLibUtils.hpp @@ -0,0 +1,100 @@ +/* + * Carla library utils + * Copyright (C) 2011-2013 Filipe Coelho + * + * 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 COPYING file + */ + +#ifndef __CARLA_LIB_UTILS_HPP__ +#define __CARLA_LIB_UTILS_HPP__ + +#include "CarlaUtils.hpp" + +#ifndef CARLA_OS_WIN +# include +#endif + +// ------------------------------------------------- +// library related calls + +static inline +void* lib_open(const char* const filename) +{ + CARLA_ASSERT(filename != nullptr); + +#ifdef CARLA_OS_WIN + return (void*)LoadLibraryA(filename); +#else + return dlopen(filename, RTLD_NOW|RTLD_LOCAL); +#endif +} + +static inline +bool lib_close(void* const lib) +{ + CARLA_ASSERT(lib != nullptr); + + if (lib == nullptr) + return false; + +#ifdef CARLA_OS_WIN + return FreeLibrary((HMODULE)lib); +#else + return (dlclose(lib) == 0); +#endif +} + +static inline +void* lib_symbol(void* const lib, const char* const symbol) +{ + CARLA_ASSERT(lib != nullptr); + CARLA_ASSERT(symbol != nullptr); + + if (lib == nullptr && symbol == nullptr) + return nullptr; + +#ifdef CARLA_OS_WIN + return (void*)GetProcAddress((HMODULE)lib, symbol); +#else + return dlsym(lib, symbol); +#endif +} + +static inline +const char* lib_error(const char* const filename) +{ + CARLA_ASSERT(filename != nullptr); + +#ifdef CARLA_OS_WIN + static char libError[2048]; + //carla_fill(libError, 2048, '\0'); + + LPVOID winErrorString; + DWORD winErrorCode = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, winErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&winErrorString, 0, nullptr); + + std::snprintf(libError, 2048, "%s: error code %li: %s", filename, winErrorCode, (const char*)winErrorString); + LocalFree(winErrorString); + + return libError; +#else + return dlerror(); + + // unused + (void)filename; +#endif +} + +// ------------------------------------------------- + +#endif // __CARLA_LIB_UTILS_HPP__ diff --git a/c++/jackbridge/CarlaUtils.hpp b/c++/jackbridge/CarlaUtils.hpp new file mode 100644 index 0000000..29e406f --- /dev/null +++ b/c++/jackbridge/CarlaUtils.hpp @@ -0,0 +1,418 @@ +/* + * Carla common utils + * Copyright (C) 2011-2013 Filipe Coelho + * + * 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 COPYING file + */ + +#ifndef __CARLA_UTILS_HPP__ +#define __CARLA_UTILS_HPP__ + +#include "CarlaDefines.hpp" + +#include +#include +#include +#include +#include + +#ifdef CARLA_PROPER_CPP11_SUPPORT +# include +#else +# include +#endif + +#if defined(CARLA_OS_HAIKU) +# include +#elif defined(CARLA_OS_LINUX) +# include +# include +#endif + +// ------------------------------------------------- +// misc functions + +static inline +const char* bool2str(const bool yesNo) +{ + return yesNo ? "true" : "false"; +} + +static inline +void pass() {} + +// ------------------------------------------------- +// string print functions + +#ifndef DEBUG +# define carla_debug(...) +#else +static inline +void carla_debug(const char* const fmt, ...) +{ + va_list args; + va_start(args, fmt); +# ifndef CARLA_OS_WIN + std::fprintf(stdout, "\x1b[30;1m"); +# endif + std::vfprintf(stdout, fmt, args); +# ifndef CARLA_OS_WIN + std::fprintf(stdout, "\x1b[0m\n"); +# else + std::fprintf(stdout, "\n"); +# endif + va_end(args); +} +#endif + +static inline +void carla_stdout(const char* const fmt, ...) +{ + va_list args; + va_start(args, fmt); + std::vfprintf(stdout, fmt, args); + std::fprintf(stdout, "\n"); + va_end(args); +} + +static inline +void carla_stderr(const char* const fmt, ...) +{ + va_list args; + va_start(args, fmt); + std::vfprintf(stderr, fmt, args); + std::fprintf(stderr, "\n"); + va_end(args); +} + +static inline +void carla_stderr2(const char* const fmt, ...) +{ + va_list args; + va_start(args, fmt); +#ifndef CARLA_OS_WIN + std::fprintf(stderr, "\x1b[31m"); +#endif + std::vfprintf(stderr, fmt, args); +#ifndef CARLA_OS_WIN + std::fprintf(stderr, "\x1b[0m\n"); +#else + std::fprintf(stderr, "\n"); +#endif + va_end(args); +} + +// ------------------------------------------------- +// carla_assert* + +static inline +void carla_assert(const char* const assertion, const char* const file, const int line) +{ + carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i", assertion, file, line); +} + +static inline +void carla_assert_int(const char* const assertion, const char* const file, const int line, const int value) +{ + carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value); +} + +static inline +void carla_assert_int2(const char* const assertion, const char* const file, const int line, const int v1, const int v2) +{ + carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2); +} + +// ------------------------------------------------- +// carla_*sleep + +static inline +void carla_sleep(const unsigned int secs) +{ + CARLA_ASSERT(secs > 0); + +#ifdef CARLA_OS_WIN + Sleep(secs * 1000); +#else + sleep(secs); +#endif +} + +static inline +void carla_msleep(const unsigned int msecs) +{ + CARLA_ASSERT(msecs > 0); + +#ifdef CARLA_OS_WIN + Sleep(msecs); +#else + usleep(msecs * 1000); +#endif +} + +// ------------------------------------------------- +// carla_setenv + +static inline +void carla_setenv(const char* const key, const char* const value) +{ + CARLA_ASSERT(key != nullptr); + CARLA_ASSERT(value != nullptr); + +#ifdef CARLA_OS_WIN + SetEnvironmentVariableA(key, value); +#else + setenv(key, value, 1); +#endif +} + +// ------------------------------------------------- +// carla_setprocname (not available on all platforms) + +static inline +void carla_setprocname(const char* const name) +{ + CARLA_ASSERT(name != nullptr); + +#if defined(CARLA_OS_HAIKU) + if ((thread_id this_thread = find_thread(nullptr)) != B_NAME_NOT_FOUND) + rename_thread(this_thread, name); +#elif defined(CARLA_OS_LINUX) + prctl(PR_SET_NAME, name); +#else + carla_stderr("carla_setprocname(\"%s\") - unsupported on this platform", name); +#endif +} + +// ------------------------------------------------- +// carla_strdup + +static inline +const char* carla_strdup(const char* const strBuf) +{ + CARLA_ASSERT(strBuf != nullptr); + + const size_t bufferLen = (strBuf != nullptr) ? std::strlen(strBuf) : 0; + char* const buffer = new char[bufferLen+1]; + + if (strBuf != nullptr && bufferLen > 0) + std::strcpy(buffer, strBuf); + + buffer[bufferLen] = '\0'; + + return buffer; +} + +static inline +const char* carla_strdup_free(char* const strBuf) +{ + const char* const buffer = carla_strdup(strBuf); + std::free(strBuf); + return buffer; +} + +// ------------------------------------------------- +// math functions + +template +static inline +const T& carla_min(const T& v1, const T& v2, const T& min) +{ + return ((v1 < min || v2 < min) ? min : (v1 < v2 ? v1 : v2)); +} + +template +static inline +const T& carla_max(const T& v1, const T& v2, const T& max) +{ + return ((v1 > max || v2 > max) ? max : (v1 > v2 ? v1 : v2)); +} + +template +static inline +const T& carla_fixValue(const T& min, const T& max, const T& value) +{ + if (value < min) + return min; + if (value > max) + return max; + return value; +} + +template +static inline +void carla_add(T* dataDst, T* dataSrc, const size_t size) +{ + CARLA_ASSERT(dataDst != nullptr); + CARLA_ASSERT(dataSrc != nullptr); + CARLA_ASSERT(size != 0); + + if (dataDst == nullptr || dataSrc == nullptr || size == 0) + return; + + for (size_t i=0; i < size; ++i) + *dataDst++ += *dataSrc++; +} + +template +static inline +void carla_add(T* dataDst, const T* dataSrc, const size_t size) +{ + CARLA_ASSERT(dataDst != nullptr); + CARLA_ASSERT(dataSrc != nullptr); + CARLA_ASSERT(size != 0); + + if (dataDst == nullptr || dataSrc == nullptr || size == 0) + return; + + for (size_t i=0; i < size; ++i) + *dataDst++ += *dataSrc++; +} + +template +static inline +void carla_copy(T* dataDst, T* dataSrc, const size_t size) +{ + CARLA_ASSERT(dataDst != nullptr); + CARLA_ASSERT(dataSrc != nullptr); + CARLA_ASSERT(size != 0); + + if (dataDst == nullptr || dataSrc == nullptr || size == 0) + return; + + for (size_t i=0; i < size; ++i) + *dataDst++ = *dataSrc++; +} + +template +static inline +void carla_copy(T* dataDst, const T* dataSrc, const size_t size) +{ + CARLA_ASSERT(dataDst != nullptr); + CARLA_ASSERT(dataSrc != nullptr); + CARLA_ASSERT(size != 0); + + if (dataDst == nullptr || dataSrc == nullptr || size == 0) + return; + + for (size_t i=0; i < size; ++i) + *dataDst++ = *dataSrc++; +} + +template +static inline +void carla_fill(T* data, const size_t size, const T v) +{ + CARLA_ASSERT(data != nullptr); + CARLA_ASSERT(size != 0); + + if (data == nullptr || size == 0) + return; + + for (size_t i=0; i < size; ++i) + *data++ = v; +} + +static inline +void carla_addDouble(double* const dataDst, double* const dataSrc, const size_t size) +{ + carla_add(dataDst, dataSrc, size); +} + +static inline +void carla_addFloat(float* const dataDst, float* const dataSrc, const size_t size) +{ + carla_add(dataDst, dataSrc, size); +} + +static inline +void carla_copyDouble(double* const dataDst, double* const dataSrc, const size_t size) +{ + CARLA_ASSERT(dataDst != nullptr); + CARLA_ASSERT(dataSrc != nullptr); + CARLA_ASSERT(size > 0); + + std::memcpy(dataDst, dataSrc, size*sizeof(double)); +} + +static inline +void carla_copyFloat(float* const dataDst, float* const dataSrc, const size_t size) +{ + CARLA_ASSERT(dataDst != nullptr); + CARLA_ASSERT(dataSrc != nullptr); + CARLA_ASSERT(size > 0); + + std::memcpy(dataDst, dataSrc, size*sizeof(float)); +} + +static inline +void carla_zeroDouble(double* const data, const size_t size) +{ + carla_fill(data, size, 0.0); +} + +static inline +void carla_zeroFloat(float* const data, const size_t size) +{ + carla_fill(data, size, 0.0f); +} + +#if defined(CARLA_OS_MAC) && ! defined(DISTRHO_OS_MAC) +namespace std { +inline float + fmin(float __x, float __y) + { return __builtin_fminf(__x, __y); } +inline float + fmax(float __x, float __y) + { return __builtin_fmaxf(__x, __y); } +inline float + rint(float __x) + { return __builtin_rintf(__x); } +} +#endif + +// ------------------------------------------------- +// memory functions + +static inline +void carla_zeroMem(void* const memory, const size_t numBytes) +{ + CARLA_ASSERT(memory != nullptr); + CARLA_ASSERT(numBytes != 0); + + if (memory == nullptr || numBytes == 0) + return; + + std::memset(memory, 0, numBytes); +} + +template +static inline +void carla_zeroStruct(T& structure) +{ + std::memset(&structure, 0, sizeof(T)); +} + +template +static inline +void carla_zeroStruct(T* const structure, const size_t count) +{ + CARLA_ASSERT(structure != nullptr); + CARLA_ASSERT(count >= 1); + + std::memset(structure, 0, sizeof(T)*count); +} + +// ------------------------------------------------- + +#endif // __CARLA_UTILS_HPP__ diff --git a/c++/jackbridge/JackBridge.cpp b/c++/jackbridge/JackBridge.cpp new file mode 100644 index 0000000..8f51631 --- /dev/null +++ b/c++/jackbridge/JackBridge.cpp @@ -0,0 +1,1092 @@ +/* + * JackBridge (Part 1, JACK functions) + * Copyright (C) 2013 Filipe Coelho + * + * 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 COPYING file + */ + +#include "JackBridge.hpp" + +#if ! (defined(JACKBRIDGE_DIRECT) || defined(JACKBRIDGE_DUMMY)) + +#include "CarlaLibUtils.hpp" + +// ----------------------------------------------------------------------------- + +typedef const char* (*jacksym_get_version_string)(); +typedef jack_client_t* (*jacksym_client_open)(const char*, jack_options_t, jack_status_t*, ...); +typedef const char* (*jacksym_client_rename)(jack_client_t* client, const char* new_name); + +typedef int (*jacksym_client_close)(jack_client_t*); +typedef int (*jacksym_client_name_size)(); +typedef char* (*jacksym_get_client_name)(jack_client_t*); + +typedef int (*jacksym_activate)(jack_client_t*); +typedef int (*jacksym_deactivate)(jack_client_t*); +typedef void (*jacksym_on_shutdown)(jack_client_t*, JackShutdownCallback, void*); +typedef int (*jacksym_set_process_callback)(jack_client_t*, JackProcessCallback, void*); +typedef int (*jacksym_set_freewheel_callback)(jack_client_t*, JackFreewheelCallback, void*); +typedef int (*jacksym_set_buffer_size_callback)(jack_client_t*, JackBufferSizeCallback, void*); +typedef int (*jacksym_set_sample_rate_callback)(jack_client_t*, JackSampleRateCallback, void*); +typedef int (*jacksym_set_client_registration_callback)(jack_client_t*, JackClientRegistrationCallback, void*); +typedef int (*jacksym_set_port_registration_callback)(jack_client_t*, JackPortRegistrationCallback, void*); +typedef int (*jacksym_set_port_connect_callback)(jack_client_t*, JackPortConnectCallback, void*); +typedef int (*jacksym_set_port_rename_callback)(jack_client_t*, JackPortRenameCallback, void*); +typedef int (*jacksym_set_latency_callback)(jack_client_t*, JackLatencyCallback, void*); +typedef int (*jacksym_set_xrun_callback)(jack_client_t*, JackXRunCallback, void*); + +typedef jack_nframes_t (*jacksym_get_sample_rate)(jack_client_t*); +typedef jack_nframes_t (*jacksym_get_buffer_size)(jack_client_t*); +typedef jack_port_t* (*jacksym_port_register)(jack_client_t*, const char*, const char*, unsigned long, unsigned long); + +typedef int (*jacksym_port_unregister)(jack_client_t*, jack_port_t*); +typedef void* (*jacksym_port_get_buffer)(jack_port_t*, jack_nframes_t); + +typedef const char* (*jacksym_port_name)(const jack_port_t*); +typedef const char* (*jacksym_port_short_name)(const jack_port_t*); +typedef int (*jacksym_port_flags)(const jack_port_t*); +typedef const char* (*jacksym_port_type)(const jack_port_t*); +typedef int (*jacksym_port_is_mine)(const jack_client_t*, const jack_port_t*); +typedef int (*jacksym_port_connected)(const jack_port_t*); +typedef int (*jacksym_port_connected_to)(const jack_port_t*, const char*); +typedef const char** (*jacksym_port_get_connections)(const jack_port_t*); +typedef const char** (*jacksym_port_get_all_connections)(const jack_client_t*, const jack_port_t*); + +typedef int (*jacksym_port_set_name)(jack_port_t*, const char*); +typedef int (*jacksym_connect)(jack_client_t*, const char*, const char*); +typedef int (*jacksym_disconnect)(jack_client_t*, const char*, const char*); +typedef int (*jacksym_port_name_size)(); +typedef void (*jacksym_port_get_latency_range)(jack_port_t*, jack_latency_callback_mode_t, jack_latency_range_t*); +typedef void (*jacksym_port_set_latency_range)(jack_port_t*, jack_latency_callback_mode_t, jack_latency_range_t*); +typedef int (*jacksym_recompute_total_latencies)(jack_client_t*); + +typedef const char** (*jacksym_get_ports)(jack_client_t*, const char*, const char*, unsigned long); +typedef jack_port_t* (*jacksym_port_by_name)(jack_client_t*, const char*); +typedef jack_port_t* (*jacksym_port_by_id)(jack_client_t*, jack_port_id_t); + +typedef void (*jacksym_free)(void*); + +typedef uint32_t (*jacksym_midi_get_event_count)(void*); +typedef int (*jacksym_midi_event_get)(jack_midi_event_t*, void*, uint32_t); +typedef void (*jacksym_midi_clear_buffer)(void*); +typedef int (*jacksym_midi_event_write)(void*, jack_nframes_t, const jack_midi_data_t*, size_t); +typedef jack_midi_data_t* (*jacksym_midi_event_reserve)(void*, jack_nframes_t, size_t); + +typedef int (*jacksym_transport_locate)(jack_client_t*, jack_nframes_t); +typedef void (*jacksym_transport_start)(jack_client_t*); +typedef void (*jacksym_transport_stop)(jack_client_t*); +typedef jack_transport_state_t (*jacksym_transport_query)(const jack_client_t*, jack_position_t*); + +typedef int (*jacksym_custom_publish_data)(jack_client_t* client, const char* key, const void* data, size_t size); +typedef int (*jacksym_custom_get_data)(jack_client_t* client, const char* client_name, const char* key, void** data, size_t* size); +typedef int (*jacksym_custom_unpublish_data)(jack_client_t* client, const char* key); +typedef int (*jacksym_custom_set_data_appearance_callback)(jack_client_t* client, JackCustomDataAppearanceCallback callback, void* arg); +typedef const char** (*jacksym_custom_get_keys)(jack_client_t* client, const char* client_name); + +// ----------------------------------------------------------------------------- + +struct JackBridge { + void* lib; + + jacksym_get_version_string get_version_string_ptr; + jacksym_client_open client_open_ptr; + jacksym_client_rename client_rename_ptr; + jacksym_client_close client_close_ptr; + jacksym_client_name_size client_name_size_ptr; + jacksym_get_client_name get_client_name_ptr; + jacksym_activate activate_ptr; + jacksym_deactivate deactivate_ptr; + jacksym_on_shutdown on_shutdown_ptr; + jacksym_set_process_callback set_process_callback_ptr; + jacksym_set_freewheel_callback set_freewheel_callback_ptr; + jacksym_set_buffer_size_callback set_buffer_size_callback_ptr; + jacksym_set_sample_rate_callback set_sample_rate_callback_ptr; + jacksym_set_client_registration_callback set_client_registration_callback_ptr; + jacksym_set_port_registration_callback set_port_registration_callback_ptr; + jacksym_set_port_connect_callback set_port_connect_callback_ptr; + jacksym_set_port_rename_callback set_port_rename_callback_ptr; + jacksym_set_latency_callback set_latency_callback_ptr; + jacksym_set_xrun_callback set_xrun_callback_ptr; + jacksym_get_sample_rate get_sample_rate_ptr; + jacksym_get_buffer_size get_buffer_size_ptr; + jacksym_port_register port_register_ptr; + jacksym_port_unregister port_unregister_ptr; + jacksym_port_get_buffer port_get_buffer_ptr; + jacksym_port_name port_name_ptr; + jacksym_port_short_name port_short_name_ptr; + jacksym_port_flags port_flags_ptr; + jacksym_port_type port_type_ptr; + jacksym_port_is_mine port_is_mine_ptr; + jacksym_port_connected port_connected_ptr; + jacksym_port_connected_to port_connected_to_ptr; + jacksym_port_get_connections port_get_connections_ptr; + jacksym_port_get_all_connections port_get_all_connections_ptr; + jacksym_port_set_name port_set_name_ptr; + jacksym_connect connect_ptr; + jacksym_disconnect disconnect_ptr; + jacksym_port_name_size port_name_size_ptr; + jacksym_port_get_latency_range port_get_latency_range_ptr; + jacksym_port_set_latency_range port_set_latency_range_ptr; + jacksym_recompute_total_latencies recompute_total_latencies_ptr; + jacksym_get_ports get_ports_ptr; + jacksym_port_by_name port_by_name_ptr; + jacksym_port_by_id port_by_id_ptr; + jacksym_free free_ptr; + + jacksym_midi_get_event_count midi_get_event_count_ptr; + jacksym_midi_event_get midi_event_get_ptr; + jacksym_midi_clear_buffer midi_clear_buffer_ptr; + jacksym_midi_event_write midi_event_write_ptr; + jacksym_midi_event_reserve midi_event_reserve_ptr; + + jacksym_transport_locate transport_locate_ptr; + jacksym_transport_start transport_start_ptr; + jacksym_transport_stop transport_stop_ptr; + jacksym_transport_query transport_query_ptr; + + jacksym_custom_publish_data custom_publish_data_ptr; + jacksym_custom_get_data custom_get_data_ptr; + jacksym_custom_unpublish_data custom_unpublish_data_ptr; + jacksym_custom_set_data_appearance_callback custom_set_data_appearance_callback_ptr; + jacksym_custom_get_keys custom_get_keys_ptr; + + JackBridge() + : lib(nullptr), + get_version_string_ptr(nullptr), + client_open_ptr(nullptr), + client_rename_ptr(nullptr), + client_close_ptr(nullptr), + client_name_size_ptr(nullptr), + get_client_name_ptr(nullptr), + activate_ptr(nullptr), + deactivate_ptr(nullptr), + on_shutdown_ptr(nullptr), + set_process_callback_ptr(nullptr), + set_freewheel_callback_ptr(nullptr), + set_buffer_size_callback_ptr(nullptr), + set_sample_rate_callback_ptr(nullptr), + set_client_registration_callback_ptr(nullptr), + set_port_registration_callback_ptr(nullptr), + set_port_connect_callback_ptr(nullptr), + set_port_rename_callback_ptr(nullptr), + set_latency_callback_ptr(nullptr), + set_xrun_callback_ptr(nullptr), + get_sample_rate_ptr(nullptr), + get_buffer_size_ptr(nullptr), + port_register_ptr(nullptr), + port_unregister_ptr(nullptr), + port_get_buffer_ptr(nullptr), + port_name_ptr(nullptr), + port_short_name_ptr(nullptr), + port_flags_ptr(nullptr), + port_type_ptr(nullptr), + port_is_mine_ptr(nullptr), + port_connected_ptr(nullptr), + port_connected_to_ptr(nullptr), + port_get_connections_ptr(nullptr), + port_get_all_connections_ptr(nullptr), + port_set_name_ptr(nullptr), + connect_ptr(nullptr), + disconnect_ptr(nullptr), + port_name_size_ptr(nullptr), + port_get_latency_range_ptr(nullptr), + port_set_latency_range_ptr(nullptr), + recompute_total_latencies_ptr(nullptr), + get_ports_ptr(nullptr), + port_by_name_ptr(nullptr), + port_by_id_ptr(nullptr), + free_ptr(nullptr), + midi_get_event_count_ptr(nullptr), + midi_event_get_ptr(nullptr), + midi_clear_buffer_ptr(nullptr), + midi_event_write_ptr(nullptr), + midi_event_reserve_ptr(nullptr), + transport_locate_ptr(nullptr), + transport_start_ptr(nullptr), + transport_stop_ptr(nullptr), + transport_query_ptr(nullptr), + custom_publish_data_ptr(nullptr), + custom_get_data_ptr(nullptr), + custom_unpublish_data_ptr(nullptr), + custom_set_data_appearance_callback_ptr(nullptr), + custom_get_keys_ptr(nullptr) + { +# if defined(CARLA_OS_MAC) + const char* const filename("libjack.dylib"); +# elif defined(CARLA_OS_WIN) + const char* const filename("libjack.dll"); +# else + const char* const filename("libjack.so.0"); +# endif + + lib = lib_open(filename); + + if (lib == nullptr) + { + fprintf(stderr, "Failed to load JACK DLL, reason:\n%s\n", lib_error(filename)); + return; + } + else + { + fprintf(stdout, "%s loaded sucessfully!\n", filename); + } + + #define JOIN(a, b) a ## b + #define LIB_SYMBOL(NAME) JOIN(NAME, _ptr) = (jacksym_##NAME)lib_symbol(lib, "jack_" #NAME); + + LIB_SYMBOL(get_version_string) + LIB_SYMBOL(client_open) + LIB_SYMBOL(client_rename) + LIB_SYMBOL(client_close) + LIB_SYMBOL(client_name_size) + LIB_SYMBOL(get_client_name) + LIB_SYMBOL(activate) + LIB_SYMBOL(deactivate) + LIB_SYMBOL(on_shutdown) + LIB_SYMBOL(set_process_callback) + LIB_SYMBOL(set_freewheel_callback) + LIB_SYMBOL(set_buffer_size_callback) + LIB_SYMBOL(set_sample_rate_callback) + LIB_SYMBOL(set_client_registration_callback) + LIB_SYMBOL(set_port_registration_callback) + LIB_SYMBOL(set_port_connect_callback) + LIB_SYMBOL(set_port_rename_callback) + LIB_SYMBOL(set_latency_callback) + LIB_SYMBOL(set_xrun_callback) + LIB_SYMBOL(get_sample_rate) + LIB_SYMBOL(get_buffer_size) + LIB_SYMBOL(port_register) + LIB_SYMBOL(port_unregister) + LIB_SYMBOL(port_get_buffer) + LIB_SYMBOL(port_name) + LIB_SYMBOL(port_short_name) + LIB_SYMBOL(port_flags) + LIB_SYMBOL(port_type) + LIB_SYMBOL(port_is_mine) + LIB_SYMBOL(port_connected) + LIB_SYMBOL(port_connected_to) + LIB_SYMBOL(port_get_connections) + LIB_SYMBOL(port_get_all_connections) + LIB_SYMBOL(port_set_name) + LIB_SYMBOL(connect) + LIB_SYMBOL(disconnect) + LIB_SYMBOL(port_name_size) + LIB_SYMBOL(port_get_latency_range) + LIB_SYMBOL(port_set_latency_range) + LIB_SYMBOL(recompute_total_latencies) + LIB_SYMBOL(get_ports) + LIB_SYMBOL(port_by_name) + LIB_SYMBOL(port_by_id) + LIB_SYMBOL(free) + + LIB_SYMBOL(midi_get_event_count) + LIB_SYMBOL(midi_event_get) + LIB_SYMBOL(midi_clear_buffer) + LIB_SYMBOL(midi_event_write) + LIB_SYMBOL(midi_event_reserve) + + LIB_SYMBOL(transport_locate) + LIB_SYMBOL(transport_start) + LIB_SYMBOL(transport_stop) + LIB_SYMBOL(transport_query) + + LIB_SYMBOL(custom_publish_data) + LIB_SYMBOL(custom_get_data) + LIB_SYMBOL(custom_unpublish_data) + LIB_SYMBOL(custom_set_data_appearance_callback) + LIB_SYMBOL(custom_get_keys) + + #undef JOIN + #undef LIB_SYMBOL + } + + ~JackBridge() + { + if (lib != nullptr) + lib_close(lib); + } +}; + +static JackBridge bridge; + +#endif // ! JACKBRIDGE_DIRECT + +// ----------------------------------------------------------------------------- + +const char* jackbridge_get_version_string() +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_get_version_string(); +#else + if (bridge.get_version_string_ptr != nullptr) + return bridge.get_version_string_ptr(); + return nullptr; +#endif +} + +jack_client_t* jackbridge_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_client_open(client_name, options, status); +#else + if (bridge.client_open_ptr != nullptr) + return bridge.client_open_ptr(client_name, options, status); + return nullptr; +#endif +} + +const char* jackbridge_client_rename(jack_client_t* client, const char* new_name) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + //return jack_client_rename(client, new_name); + return nullptr; + + // unused, for now + (void)client; + (void)new_name; +#else + if (bridge.client_rename_ptr != nullptr) + return bridge.client_rename_ptr(client, new_name); + return nullptr; +#endif +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_client_close(jack_client_t* client) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_client_close(client) == 0); +#else + if (bridge.client_close_ptr != nullptr) + return (bridge.client_close_ptr(client) == 0); + return false; +#endif +} + +int jackbridge_client_name_size() +{ +#if JACKBRIDGE_DUMMY + return 0; +#elif JACKBRIDGE_DIRECT + return jack_client_name_size(); +#else + if (bridge.client_name_size_ptr != nullptr) + return bridge.client_name_size_ptr(); + return 0; +#endif +} + +char* jackbridge_get_client_name(jack_client_t* client) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_get_client_name(client); +#else + if (bridge.get_client_name_ptr != nullptr) + return bridge.get_client_name_ptr(client); + return nullptr; +#endif +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_activate(jack_client_t* client) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_activate(client) == 0); +#else + if (bridge.activate_ptr != nullptr) + return (bridge.activate_ptr(client) == 0); + return false; +#endif +} + +bool jackbridge_deactivate(jack_client_t* client) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_deactivate(client) == 0); +#else + if (bridge.deactivate_ptr != nullptr) + return (bridge.deactivate_ptr(client) == 0); + return false; +#endif +} + +void jackbridge_on_shutdown(jack_client_t* client, JackShutdownCallback shutdown_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY +#elif JACKBRIDGE_DIRECT + jack_on_shutdown(client, shutdown_callback, arg); +#else + if (bridge.on_shutdown_ptr != nullptr) + bridge.on_shutdown_ptr(client, shutdown_callback, arg); +#endif +} + +bool jackbridge_set_process_callback(jack_client_t* client, JackProcessCallback process_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_process_callback(client, process_callback, arg) == 0); +#else + if (bridge.set_process_callback_ptr != nullptr) + return (bridge.set_process_callback_ptr(client, process_callback, arg) == 0); + return false; +#endif +} + +bool jackbridge_set_freewheel_callback(jack_client_t* client, JackFreewheelCallback freewheel_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_freewheel_callback(client, freewheel_callback, arg) == 0); +#else + if (bridge.set_freewheel_callback_ptr != nullptr) + return (bridge.set_freewheel_callback_ptr(client, freewheel_callback, arg) == 0); + return false; +#endif +} + +bool jackbridge_set_buffer_size_callback(jack_client_t* client, JackBufferSizeCallback bufsize_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_buffer_size_callback(client, bufsize_callback, arg) == 0); +#else + if (bridge.set_buffer_size_callback_ptr != nullptr) + return (bridge.set_buffer_size_callback_ptr(client, bufsize_callback, arg) == 0); + return false; +#endif +} + +bool jackbridge_set_sample_rate_callback(jack_client_t* client, JackSampleRateCallback srate_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_sample_rate_callback(client, srate_callback, arg) == 0); +#else + if (bridge.set_sample_rate_callback_ptr != nullptr) + return (bridge.set_sample_rate_callback_ptr(client, srate_callback, arg) == 0); + return false; +#endif +} + +bool jackbridge_set_client_registration_callback(jack_client_t* client, JackClientRegistrationCallback registration_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_client_registration_callback(client, registration_callback, arg) == 0); +#else + if (bridge.set_client_registration_callback_ptr != nullptr) + return (bridge.set_client_registration_callback_ptr(client, registration_callback, arg) == 0); + return false; +#endif +} + +bool jackbridge_set_port_registration_callback(jack_client_t* client, JackPortRegistrationCallback registration_callback, void *arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_port_registration_callback(client, registration_callback, arg) == 0); +#else + if (bridge.set_port_registration_callback_ptr != nullptr) + return (bridge.set_port_registration_callback_ptr(client, registration_callback, arg) == 0); + return false; +#endif +} + +bool jackbridge_set_port_connect_callback(jack_client_t* client, JackPortConnectCallback connect_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_port_connect_callback(client, connect_callback, arg) == 0); +#else + if (bridge.set_port_connect_callback_ptr != nullptr) + return (bridge.set_port_connect_callback_ptr(client, connect_callback, arg) == 0); + return false; +#endif +} + +bool jackbridge_set_port_rename_callback(jack_client_t* client, JackPortRenameCallback rename_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_port_rename_callback(client, rename_callback, arg) == 0); +#else + if (bridge.set_port_rename_callback_ptr != nullptr) + return (bridge.set_port_rename_callback_ptr(client, rename_callback, arg) == 0); + return false; +#endif +} + +bool jackbridge_set_latency_callback(jack_client_t* client, JackLatencyCallback latency_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_latency_callback(client, latency_callback, arg) == 0); +#else + if (bridge.set_latency_callback_ptr != nullptr) + return (bridge.set_latency_callback_ptr(client, latency_callback, arg) == 0); + return false; +#endif +} + +bool jackbridge_set_xrun_callback(jack_client_t* client, JackXRunCallback xrun_callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_set_xrun_callback(client, xrun_callback, arg) == 0); +#else + if (bridge.set_xrun_callback_ptr != nullptr) + return (bridge.set_xrun_callback_ptr(client, xrun_callback, arg) == 0); + return false; +#endif +} + +// ----------------------------------------------------------------------------- + +jack_nframes_t jackbridge_get_sample_rate(jack_client_t* client) +{ +#if JACKBRIDGE_DUMMY + return 0; +#elif JACKBRIDGE_DIRECT + return jack_get_sample_rate(client); +#else + if (bridge.get_sample_rate_ptr != nullptr) + return bridge.get_sample_rate_ptr(client); + return 0; +#endif +} + +jack_nframes_t jackbridge_get_buffer_size(jack_client_t* client) +{ +#if JACKBRIDGE_DUMMY + return 0; +#elif JACKBRIDGE_DIRECT + return jack_get_buffer_size(client); +#else + if (bridge.get_buffer_size_ptr != nullptr) + return bridge.get_buffer_size_ptr(client); + return 0; +#endif +} + +jack_port_t* jackbridge_port_register(jack_client_t* client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_port_register(client, port_name, port_type, flags, buffer_size); +#else + if (bridge.port_register_ptr != nullptr) + return bridge.port_register_ptr(client, port_name, port_type, flags, buffer_size); + return nullptr; +#endif +} + +bool jackbridge_port_unregister(jack_client_t* client, jack_port_t* port) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_port_unregister(client, port) == 0); +#else + if (bridge.port_unregister_ptr != nullptr) + return (bridge.port_unregister_ptr(client, port) == 0); + return false; +#endif +} + +void* jackbridge_port_get_buffer(jack_port_t* port, jack_nframes_t nframes) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_port_get_buffer(port, nframes); +#else + if (bridge.port_get_buffer_ptr != nullptr) + return bridge.port_get_buffer_ptr(port, nframes); + return nullptr; +#endif +} + +// ----------------------------------------------------------------------------- + +const char* jackbridge_port_name(const jack_port_t* port) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_port_name(port); +#else + if (bridge.port_name_ptr != nullptr) + return bridge.port_name_ptr(port); + return nullptr; +#endif +} + +const char* jackbridge_port_short_name(const jack_port_t* port) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_port_short_name(port); +#else + if (bridge.port_short_name_ptr != nullptr) + return bridge.port_short_name_ptr(port); + return nullptr; +#endif +} + +int jackbridge_port_flags(const jack_port_t* port) +{ +#if JACKBRIDGE_DUMMY + return 0; +#elif JACKBRIDGE_DIRECT + return jack_port_flags(port); +#else + if (bridge.port_flags_ptr != nullptr) + return bridge.port_flags_ptr(port); + return 0; +#endif +} + +const char* jackbridge_port_type(const jack_port_t* port) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_port_type(port); +#else + if (bridge.port_type_ptr != nullptr) + return bridge.port_type_ptr(port); + return nullptr; +#endif +} + +bool jackbridge_port_is_mine(const jack_client_t* client, const jack_port_t* port) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return jack_port_is_mine(client, port); +#else + if (bridge.port_is_mine_ptr != nullptr) + return bridge.port_is_mine_ptr(client, port); + return false; +#endif +} + +bool jackbridge_port_connected(const jack_port_t* port) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return jack_port_connected(port); +#else + if (bridge.port_connected_ptr != nullptr) + return bridge.port_connected_ptr(port); + return false; +#endif +} + +bool jackbridge_port_connected_to(const jack_port_t* port, const char* port_name) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return jack_port_connected_to(port, port_name); +#else + if (bridge.port_connected_to_ptr != nullptr) + return bridge.port_connected_to_ptr(port, port_name); + return false; +#endif +} + +const char** jackbridge_port_get_connections(const jack_port_t* port) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_port_get_connections(port); +#else + if (bridge.port_get_connections_ptr != nullptr) + return bridge.port_get_connections_ptr(port); + return nullptr; +#endif +} + +const char** jackbridge_port_get_all_connections(const jack_client_t* client, const jack_port_t* port) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_port_get_all_connections(client, port); +#else + if (bridge.port_get_all_connections_ptr != nullptr) + return bridge.port_get_all_connections_ptr(client, port); + return nullptr; +#endif +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_port_set_name(jack_port_t* port, const char* port_name) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_port_set_name(port, port_name) == 0); +#else + if (bridge.port_set_name_ptr != nullptr) + return (bridge.port_set_name_ptr(port, port_name) == 0); + return false; +#endif +} + +bool jackbridge_connect(jack_client_t* client, const char* source_port, const char* destination_port) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_connect(client, source_port, destination_port) == 0); +#else + if (bridge.connect_ptr != nullptr) + return (bridge.connect_ptr(client, source_port, destination_port) == 0); + return false; +#endif +} + +bool jackbridge_disconnect(jack_client_t* client, const char* source_port, const char* destination_port) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_disconnect(client, source_port, destination_port) == 0); +#else + if (bridge.disconnect_ptr != nullptr) + return (bridge.disconnect_ptr(client, source_port, destination_port) == 0); + return false; +#endif +} + +int jackbridge_port_name_size() +{ +#if JACKBRIDGE_DUMMY + return 0; +#elif JACKBRIDGE_DIRECT + return jack_port_name_size(); +#else + if (bridge.port_name_size_ptr != nullptr) + return bridge.port_name_size_ptr(); + return 0; +#endif +} + +void jackbridge_port_get_latency_range(jack_port_t* port, jack_latency_callback_mode_t mode, jack_latency_range_t* range) +{ +#if JACKBRIDGE_DUMMY +#elif JACKBRIDGE_DIRECT + return jack_port_get_latency_range(port, mode, range); +#else + if (bridge.port_get_latency_range_ptr != nullptr) + bridge.port_get_latency_range_ptr(port, mode, range); +#endif +} + +void jackbridge_port_set_latency_range(jack_port_t* port, jack_latency_callback_mode_t mode, jack_latency_range_t* range) +{ +#if JACKBRIDGE_DUMMY +#elif JACKBRIDGE_DIRECT + return jack_port_set_latency_range(port, mode, range); +#else + if (bridge.port_set_latency_range_ptr != nullptr) + bridge.port_set_latency_range_ptr(port, mode, range); +#endif +} + +bool jackbridge_recompute_total_latencies(jack_client_t* client) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_recompute_total_latencies(client) == 0); +#else + if (bridge.recompute_total_latencies_ptr != nullptr) + return (bridge.recompute_total_latencies_ptr(client) == 0); + return false; +#endif +} + +const char** jackbridge_get_ports(jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_get_ports(client, port_name_pattern, type_name_pattern, flags); +#else + if (bridge.get_ports_ptr != nullptr) + return bridge.get_ports_ptr(client, port_name_pattern, type_name_pattern, flags); + return nullptr; +#endif +} + +jack_port_t* jackbridge_port_by_name(jack_client_t* client, const char* port_name) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_port_by_name(client, port_name); +#else + if (bridge.port_by_name_ptr != nullptr) + return bridge.port_by_name_ptr(client, port_name); + return nullptr; +#endif +} + +jack_port_t* jackbridge_port_by_id(jack_client_t* client, jack_port_id_t port_id) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_port_by_id(client, port_id); +#else + if (bridge.port_by_id_ptr != nullptr) + return bridge.port_by_id_ptr(client, port_id); + return nullptr; +#endif +} + +// ----------------------------------------------------------------------------- + +void jackbridge_free(void* ptr) +{ +#if JACKBRIDGE_DUMMY +#elif JACKBRIDGE_DIRECT + return jack_free(ptr); +#else + if (bridge.free_ptr != nullptr) + return bridge.free_ptr(ptr); + + // just in case + std::free(ptr); +#endif +} + +// ----------------------------------------------------------------------------- + +uint32_t jackbridge_midi_get_event_count(void* port_buffer) +{ +#if JACKBRIDGE_DUMMY + return 0; +#elif JACKBRIDGE_DIRECT + return jack_midi_get_event_count(port_buffer); +#else + if (bridge.midi_get_event_count_ptr != nullptr) + return bridge.midi_get_event_count_ptr(port_buffer); + return 0; +#endif +} + +bool jackbridge_midi_event_get(jack_midi_event_t* event, void* port_buffer, uint32_t event_index) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_midi_event_get(event, port_buffer, event_index) == 0); +#else + if (bridge.midi_event_get_ptr != nullptr) + return (bridge.midi_event_get_ptr(event, port_buffer, event_index) == 0); + return false; +#endif +} + +void jackbridge_midi_clear_buffer(void* port_buffer) +{ +#if JACKBRIDGE_DUMMY +#elif JACKBRIDGE_DIRECT + return jack_midi_clear_buffer(port_buffer); +#else + if (bridge.midi_clear_buffer_ptr != nullptr) + bridge.midi_clear_buffer_ptr(port_buffer); +#endif +} + +bool jackbridge_midi_event_write(void* port_buffer, jack_nframes_t time, const jack_midi_data_t* data, size_t data_size) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_midi_event_write(port_buffer, time, data, data_size) == 0); +#else + if (bridge.midi_event_write_ptr != nullptr) + return (bridge.midi_event_write_ptr(port_buffer, time, data, data_size) == 0); + return false; +#endif +} + +jack_midi_data_t* jackbridge_midi_event_reserve(void* port_buffer, jack_nframes_t time, size_t data_size) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_midi_event_reserve(port_buffer, time, data_size); +#else + if (bridge.midi_event_reserve_ptr != nullptr) + return bridge.midi_event_reserve_ptr(port_buffer, time, data_size); + return nullptr; +#endif +} + +// ----------------------------------------------------------------------------- + +int jackbridge_transport_locate(jack_client_t* client, jack_nframes_t frame) +{ +#if JACKBRIDGE_DUMMY + return 0; +#elif JACKBRIDGE_DIRECT + return (jack_transport_locate(client, frame) == 0); +#else + if (bridge.transport_locate_ptr != nullptr) + return (bridge.transport_locate_ptr(client, frame) == 0); + return 0; +#endif +} + +void jackbridge_transport_start(jack_client_t* client) +{ +#if JACKBRIDGE_DUMMY +#elif JACKBRIDGE_DIRECT + jack_transport_start(client); +#else + if (bridge.transport_start_ptr != nullptr) + bridge.transport_start_ptr(client); +#endif +} + +void jackbridge_transport_stop(jack_client_t* client) +{ +#if JACKBRIDGE_DUMMY +#elif JACKBRIDGE_DIRECT + jack_transport_stop(client); +#else + if (bridge.transport_stop_ptr != nullptr) + bridge.transport_stop_ptr(client); +#endif +} + +jack_transport_state_t jackbridge_transport_query(const jack_client_t* client, jack_position_t* pos) +{ +#if JACKBRIDGE_DUMMY + return JackTransportStopped; +#elif JACKBRIDGE_DIRECT + return jack_transport_query(client, pos); +#else + if (bridge.transport_query_ptr != nullptr) + return bridge.transport_query_ptr(client, pos); + return JackTransportStopped; +#endif +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_custom_publish_data(jack_client_t* client, const char* key, const void* data, size_t size) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_custom_publish_data(client, key, data, size) == 0); +#else + if (bridge.custom_publish_data_ptr != nullptr) + return (bridge.custom_publish_data_ptr(client, key, data, size) == 0); + return false; +#endif +} + +bool jackbridge_custom_get_data(jack_client_t* client, const char* client_name, const char* key, void** data, size_t* size) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_custom_get_data(client, client_name, key, data, size) == 0); +#else + if (bridge.custom_get_data_ptr != nullptr) + return (bridge.custom_get_data_ptr(client, client_name, key, data, size) == 0); + return false; +#endif +} + +bool jackbridge_custom_unpublish_data(jack_client_t* client, const char* key) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_custom_unpublish_data(client, key) == 0); +#else + if (bridge.custom_unpublish_data_ptr != nullptr) + return (bridge.custom_unpublish_data_ptr(client, key) == 0); + return false; +#endif +} + +bool jackbridge_custom_set_data_appearance_callback(jack_client_t* client, JackCustomDataAppearanceCallback callback, void* arg) +{ +#if JACKBRIDGE_DUMMY + return false; +#elif JACKBRIDGE_DIRECT + return (jack_custom_set_data_appearance_callback(client, callback, arg) == 0); +#else + if (bridge.custom_set_data_appearance_callback_ptr != nullptr) + return (bridge.custom_set_data_appearance_callback_ptr(client, callback, arg) == 0); + return false; +#endif +} + +const char** jackbridge_custom_get_keys(jack_client_t* client, const char* client_name) +{ +#if JACKBRIDGE_DUMMY + return nullptr; +#elif JACKBRIDGE_DIRECT + return jack_custom_get_keys(client, client_name); +#else + if (bridge.custom_get_keys_ptr != nullptr) + return bridge.custom_get_keys_ptr(client, client_name); + return nullptr; +#endif +} + +// ----------------------------------------------------------------------------- diff --git a/c++/jackbridge/JackBridge.hpp b/c++/jackbridge/JackBridge.hpp new file mode 100644 index 0000000..7c8660c --- /dev/null +++ b/c++/jackbridge/JackBridge.hpp @@ -0,0 +1,343 @@ +/* + * JackBridge + * Copyright (C) 2013 Filipe Coelho + * + * 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 COPYING file + */ + +#ifndef __JACKBRIDGE_HPP__ +#define __JACKBRIDGE_HPP__ + +#include "CarlaDefines.hpp" + +#ifndef JACKBRIDGE_EXPORT +# undef CARLA_EXPORT +# define CARLA_EXPORT +#endif + +#ifdef JACKBRIDGE_DIRECT +# include +# include +# include +# include +#else + +#include + +#ifdef CARLA_PROPER_CPP11_SUPPORT +# include +#else +# include +#endif + +#ifndef POST_PACKED_STRUCTURE +# ifdef __GNUC__ + /* POST_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the preceding structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. + */ + #define PRE_PACKED_STRUCTURE + #define POST_PACKED_STRUCTURE __attribute__((__packed__)) +# else + #ifdef _MSC_VER + #define PRE_PACKED_STRUCTURE1 __pragma(pack(push,1)) + #define PRE_PACKED_STRUCTURE PRE_PACKED_STRUCTURE1 + /* PRE_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the following structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. + */ + #define POST_PACKED_STRUCTURE ;__pragma(pack(pop)) + /* and POST_PACKED_STRUCTURE needs to be a macro which + restores the packing to its previous setting */ + #else + #define PRE_PACKED_STRUCTURE + #define POST_PACKED_STRUCTURE + #endif // _MSC_VER +# endif // __GNUC__ +#endif + +#define JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio" +#define JACK_DEFAULT_MIDI_TYPE "8 bit raw midi" + +#define JACK_HAS_CUSTOM_DATA_API 1 +#define JACK_HAS_PORT_IS_CONTROL_VOLTAGE_FLAG 1 + +#define JackOpenOptions (JackSessionID|JackServerName|JackNoStartServer|JackUseExactName) +#define JackLoadOptions (JackLoadInit|JackLoadName|JackUseExactName) +#define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode) +#define EXTENDED_TIME_INFO + +enum JackOptions { + JackNullOption = 0x00, + JackNoStartServer = 0x01, + JackUseExactName = 0x02, + JackServerName = 0x04, + JackLoadName = 0x08, + JackLoadInit = 0x10, + JackSessionID = 0x20 +}; + +enum JackStatus { + JackFailure = 0x01, + JackInvalidOption = 0x02, + JackNameNotUnique = 0x04, + JackServerStarted = 0x08, + JackServerFailed = 0x10, + JackServerError = 0x20, + JackNoSuchClient = 0x40, + JackLoadFailure = 0x80, + JackInitFailure = 0x100, + JackShmFailure = 0x200, + JackVersionError = 0x400, + JackBackendError = 0x800, + JackClientZombie = 0x1000 +}; + +enum JackLatencyCallbackMode { + JackCaptureLatency, + JackPlaybackLatency +}; + +enum JackPortFlags { + JackPortIsInput = 0x1, + JackPortIsOutput = 0x2, + JackPortIsPhysical = 0x4, + JackPortCanMonitor = 0x8, + JackPortIsTerminal = 0x10, + JackPortIsControlVoltage = 0x100 +}; + +enum JackTransportState { + JackTransportStopped = 0, + JackTransportRolling = 1, + JackTransportLooping = 2, + JackTransportStarting = 3, + JackTransportNetStarting = 4 +}; + +enum JackPositionBits { + JackPositionBBT = 0x010, + JackPositionTimecode = 0x020, + JackBBTFrameOffset = 0x040, + JackAudioVideoRatio = 0x080, + JackVideoFrameOffset = 0x100 +}; + +enum JackSessionEventType { + JackSessionSave = 1, + JackSessionSaveAndQuit = 2, + JackSessionSaveTemplate = 3 +}; + +enum JackSessionFlags { + JackSessionSaveError = 0x01, + JackSessionNeedTerminal = 0x02 +}; + +enum JackCustomChange { + JackCustomRemoved, + JackCustomAdded, + JackCustomReplaced +}; + +typedef uint32_t jack_nframes_t; +typedef uint32_t jack_port_id_t; +typedef uint64_t jack_time_t; +typedef uint64_t jack_unique_t; +typedef unsigned char jack_midi_data_t; +typedef float jack_default_audio_sample_t; + +typedef enum JackOptions jack_options_t; +typedef enum JackStatus jack_status_t; +typedef enum JackLatencyCallbackMode jack_latency_callback_mode_t; +typedef enum JackTransportState jack_transport_state_t; +typedef enum JackPositionBits jack_position_bits_t; +typedef enum JackSessionEventType jack_session_event_type_t; +typedef enum JackSessionFlags jack_session_flags_t; +typedef enum JackCustomChange jack_custom_change_t; + +struct _jack_midi_event { + jack_nframes_t time; + size_t size; + jack_midi_data_t* buffer; +}; + +PRE_PACKED_STRUCTURE +struct _jack_latency_range { + jack_nframes_t min; + jack_nframes_t max; +} POST_PACKED_STRUCTURE; + +PRE_PACKED_STRUCTURE +struct _jack_position { + jack_unique_t unique_1; + jack_time_t usecs; + jack_nframes_t frame_rate; + jack_nframes_t frame; + jack_position_bits_t valid; + int32_t bar; + int32_t beat; + int32_t tick; + double bar_start_tick; + float beats_per_bar; + float beat_type; + double ticks_per_beat; + double beats_per_minute; + double frame_time; + double next_time; + jack_nframes_t bbt_offset; + float audio_frames_per_video_frame; + jack_nframes_t video_offset; + int32_t padding[7]; + jack_unique_t unique_2; +} POST_PACKED_STRUCTURE; + +struct _jack_session_event { + jack_session_event_type_t type; + const char* session_dir; + const char* client_uuid; + char* command_line; + jack_session_flags_t flags; + uint32_t future; +}; + +struct _jack_session_command_t { + const char* uuid; + const char* client_name; + const char* command; + jack_session_flags_t flags; +}; + +typedef struct _jack_port jack_port_t; +typedef struct _jack_client jack_client_t; +typedef struct _jack_midi_event jack_midi_event_t; +typedef struct _jack_latency_range jack_latency_range_t; +typedef struct _jack_position jack_position_t; +typedef struct _jack_session_event jack_session_event_t; +typedef struct _jack_session_command_t jack_session_command_t; + +typedef void (*JackLatencyCallback)(jack_latency_callback_mode_t mode, void* arg); +typedef int (*JackProcessCallback)(jack_nframes_t nframes, void* arg); +typedef void (*JackThreadInitCallback)(void *arg); +typedef int (*JackGraphOrderCallback)(void *arg); +typedef int (*JackXRunCallback)(void* arg); +typedef int (*JackBufferSizeCallback)(jack_nframes_t nframes, void* arg); +typedef int (*JackSampleRateCallback)(jack_nframes_t nframes, void* arg); +typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int register_, void* arg); +typedef void (*JackClientRegistrationCallback)(const char* name, int register_, void* arg); +typedef int (*JackClientRenameCallback)(const char* old_name, const char* new_name, void* arg); +typedef void (*JackPortConnectCallback)(jack_port_id_t a, jack_port_id_t b, int connect, void* arg); +typedef int (*JackPortRenameCallback)(jack_port_id_t port, const char* old_name, const char* new_name, void* arg); +typedef void (*JackFreewheelCallback)(int starting, void* arg); +typedef void (*JackShutdownCallback)(void* arg); +typedef void (*JackInfoShutdownCallback)(jack_status_t code, const char* reason, void* arg); +typedef int (*JackSyncCallback)(jack_transport_state_t state, jack_position_t* pos, void* arg); +typedef void (*JackTimebaseCallback)(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg); +typedef void (*JackSessionCallback)(jack_session_event_t* event, void* arg); +typedef void (*JackCustomDataAppearanceCallback)(const char* client_name, const char* key, jack_custom_change_t change, void* arg); + +#endif // ! JACKBRIDGE_DIRECT + +CARLA_EXPORT const char* jackbridge_get_version_string(); +CARLA_EXPORT jack_client_t* jackbridge_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...); +CARLA_EXPORT const char* jackbridge_client_rename(jack_client_t* client, const char* new_name); + +CARLA_EXPORT bool jackbridge_client_close(jack_client_t* client); +CARLA_EXPORT int jackbridge_client_name_size(); +CARLA_EXPORT char* jackbridge_get_client_name(jack_client_t* client); + +CARLA_EXPORT bool jackbridge_activate(jack_client_t* client); +CARLA_EXPORT bool jackbridge_deactivate(jack_client_t* client); + +CARLA_EXPORT int jackbridge_get_client_pid(const char* name); +CARLA_EXPORT int jackbridge_is_realtime(jack_client_t* client); + +CARLA_EXPORT bool jackbridge_set_thread_init_callback(jack_client_t* client, JackThreadInitCallback thread_init_callback, void* arg); +CARLA_EXPORT void jackbridge_on_shutdown(jack_client_t* client, JackShutdownCallback shutdown_callback, void* arg); +CARLA_EXPORT void jackbridge_on_info_shutdown(jack_client_t* client, JackInfoShutdownCallback shutdown_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_process_callback(jack_client_t* client, JackProcessCallback process_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_freewheel_callback(jack_client_t* client, JackFreewheelCallback freewheel_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_buffer_size_callback(jack_client_t* client, JackBufferSizeCallback bufsize_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_sample_rate_callback(jack_client_t* client, JackSampleRateCallback srate_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_client_registration_callback(jack_client_t* client, JackClientRegistrationCallback registration_callback, void* arg); +#ifndef JACKBRIDGE_DIRECT +CARLA_EXPORT bool jackbridge_set_client_rename_callback(jack_client_t* client, JackClientRenameCallback registration_callback, void* arg); +#endif +CARLA_EXPORT bool jackbridge_set_port_registration_callback(jack_client_t* client, JackPortRegistrationCallback registration_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_port_connect_callback(jack_client_t* client, JackPortConnectCallback connect_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_port_rename_callback(jack_client_t* client, JackPortRenameCallback rename_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_graph_order_callback(jack_client_t* client, JackGraphOrderCallback graph_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_xrun_callback(jack_client_t* client, JackXRunCallback xrun_callback, void* arg); +CARLA_EXPORT bool jackbridge_set_latency_callback(jack_client_t* client, JackLatencyCallback latency_callback, void* arg); + +CARLA_EXPORT bool jackbridge_set_freewheel(jack_client_t* client, int onoff); +CARLA_EXPORT bool jackbridge_set_buffer_size(jack_client_t* client, jack_nframes_t nframes); +CARLA_EXPORT bool jackbridge_engine_takeover_timebase(jack_client_t* client); +CARLA_EXPORT float jackbridge_cpu_load(jack_client_t* client); + +CARLA_EXPORT jack_nframes_t jackbridge_get_sample_rate(jack_client_t* client); +CARLA_EXPORT jack_nframes_t jackbridge_get_buffer_size(jack_client_t* client); + +CARLA_EXPORT jack_port_t* jackbridge_port_register(jack_client_t* client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size); + +CARLA_EXPORT bool jackbridge_port_unregister(jack_client_t* client, jack_port_t* port); +CARLA_EXPORT void* jackbridge_port_get_buffer(jack_port_t* port, jack_nframes_t nframes); + +CARLA_EXPORT const char* jackbridge_port_name(const jack_port_t* port); +CARLA_EXPORT const char* jackbridge_port_short_name(const jack_port_t* port); +CARLA_EXPORT int jackbridge_port_flags(const jack_port_t* port); +CARLA_EXPORT const char* jackbridge_port_type(const jack_port_t* port); +CARLA_EXPORT bool jackbridge_port_is_mine(const jack_client_t* client, const jack_port_t* port); +CARLA_EXPORT bool jackbridge_port_connected(const jack_port_t* port); +CARLA_EXPORT bool jackbridge_port_connected_to(const jack_port_t* port, const char* port_name); +CARLA_EXPORT const char** jackbridge_port_get_connections(const jack_port_t* port); +CARLA_EXPORT const char** jackbridge_port_get_all_connections(const jack_client_t* client, const jack_port_t* port); + +CARLA_EXPORT bool jackbridge_port_set_name(jack_port_t* port, const char* port_name); +CARLA_EXPORT bool jackbridge_connect(jack_client_t* client, const char* source_port, const char* destination_port); +CARLA_EXPORT bool jackbridge_disconnect(jack_client_t* client, const char* source_port, const char* destination_port); +CARLA_EXPORT int jackbridge_port_name_size(); +CARLA_EXPORT void jackbridge_port_get_latency_range(jack_port_t* port, jack_latency_callback_mode_t mode, jack_latency_range_t* range); +CARLA_EXPORT void jackbridge_port_set_latency_range(jack_port_t* port, jack_latency_callback_mode_t mode, jack_latency_range_t* range); +CARLA_EXPORT bool jackbridge_recompute_total_latencies(jack_client_t* client); + +CARLA_EXPORT const char** jackbridge_get_ports(jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags); +CARLA_EXPORT jack_port_t* jackbridge_port_by_name(jack_client_t* client, const char* port_name); +CARLA_EXPORT jack_port_t* jackbridge_port_by_id(jack_client_t* client, jack_port_id_t port_id); + +CARLA_EXPORT void jackbridge_free(void* ptr); + +CARLA_EXPORT uint32_t jackbridge_midi_get_event_count(void* port_buffer); +CARLA_EXPORT bool jackbridge_midi_event_get(jack_midi_event_t* event, void* port_buffer, uint32_t event_index); +CARLA_EXPORT void jackbridge_midi_clear_buffer(void* port_buffer); +CARLA_EXPORT bool jackbridge_midi_event_write(void* port_buffer, jack_nframes_t time, const jack_midi_data_t* data, size_t data_size); +CARLA_EXPORT jack_midi_data_t* jackbridge_midi_event_reserve(void* port_buffer, jack_nframes_t time, size_t data_size); + +CARLA_EXPORT int jackbridge_transport_locate(jack_client_t* client, jack_nframes_t frame); +CARLA_EXPORT void jackbridge_transport_start(jack_client_t* client); +CARLA_EXPORT void jackbridge_transport_stop(jack_client_t* client); +CARLA_EXPORT jack_transport_state_t jackbridge_transport_query(const jack_client_t* client, jack_position_t* pos); + +CARLA_EXPORT bool jackbridge_custom_publish_data(jack_client_t* client, const char* key, const void* data, size_t size); +CARLA_EXPORT bool jackbridge_custom_get_data(jack_client_t* client, const char* client_name, const char* key, void** data, size_t* size); +CARLA_EXPORT bool jackbridge_custom_unpublish_data(jack_client_t* client, const char* key); +CARLA_EXPORT bool jackbridge_custom_set_data_appearance_callback(jack_client_t* client, JackCustomDataAppearanceCallback callback, void* arg); +CARLA_EXPORT const char** jackbridge_custom_get_keys(jack_client_t* client, const char* client_name); + +#endif // __JACKBRIDGE_HPP__ diff --git a/c++/jackbridge/Makefile b/c++/jackbridge/Makefile new file mode 100644 index 0000000..1210b80 --- /dev/null +++ b/c++/jackbridge/Makefile @@ -0,0 +1,67 @@ +#!/usr/bin/make -f +# Makefile for jackbridge # +# ------------------------------------- # +# Created by falkTX +# + +include ../../Makefile.mk + +# -------------------------------------------------------------- + +WINECXX ?= wineg++ + +BUILD_CXX_FLAGS += -DJACKBRIDGE_EXPORT +BUILD_CXX_FLAGS += -I. -I../../includes -I../../utils + +ifeq ($(MACOS),true) +LINK_FLAGS += -dynamiclib +else +LINK_FLAGS += -shared +endif + +WIN_BUILD_FLAGS = $(BUILD_CXX_FLAGS) -DJACKBRIDGE_DUMMY=1 -w +WIN_32BIT_FLAGS = $(32BIT_FLAGS) +WIN_64BIT_FLAGS = $(64BIT_FLAGS) +WIN_LINK_FLAGS = $(LINK_FLAGS) + +WINE_BUILD_FLAGS = $(BUILD_CXX_FLAGS) -fPIC +WINE_32BIT_FLAGS = $(32BIT_FLAGS) -L/usr/lib32/wine -L/usr/lib/i386-linux-gnu/wine +WINE_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine +WINE_LINK_FLAGS = $(LINK_FLAGS) -ldl -lrt -lpthread + +OBJS = JackBridge1.cpp JackBridge2.cpp +OBJSw32 = JackBridge1.w32.o JackBridge2.w32.o +OBJSw64 = JackBridge1.w64.o JackBridge2.w64.o + +# -------------------------------------------------------------- + +all: + +win32: ../jackbridge-win32.dll +win64: ../jackbridge-win64.dll +wine32: ../jackbridge-win32.dll.so +wine64: ../jackbridge-win64.dll.so + +# -------------------------------------------------------------- + +JackBridge%.w32.o: JackBridge%.cpp + $(CXX) $^ $(WINE_BUILD_FLAGS) $(WINE_32BIT_FLAGS) -c -o $@ + +JackBridge%.w64.o: JackBridge%.cpp + $(CXX) $^ $(WINE_BUILD_FLAGS) $(WINE_64BIT_FLAGS) -c -o $@ + +# -------------------------------------------------------------- + +../jackbridge-win32.dll: $(OBJS) + $(CXX) $^ $(WIN_BUILD_FLAGS) $(WIN_32BIT_FLAGS) $(WIN_LINK_FLAGS) -Wl,--output-def,$@.def,--out-implib,$@.a -o $@ $(CMD_STRIP) $@ + +../jackbridge-win64.dll: $(OBJS) + $(CXX) $^ $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) $(WIN_LINK_FLAGS) -Wl,--output-def,$@.def,--out-implib,$@.a -o $@ $(CMD_STRIP) $@ + +../jackbridge-win32.dll.so: $(OBJSw32) ../jackbridge-win32.dll.def + $(WINECXX) $^ $(WINE_32BIT_FLAGS) $(WINE_LINK_FLAGS) -o $@ $(CMD_STRIP) $@ + +../jackbridge-win64.dll.so: $(OBJS) ../jackbridge-win64.dll.def + $(WINECXX) $^ $(WINE_64BIT_FLAGS) $(WINE_LINK_FLAGS) -o $@ $(CMD_STRIP) $@ + +# -------------------------------------------------------------- diff --git a/c++/jackmeter/Makefile b/c++/jackmeter/Makefile index c52d3f5..51121f6 100644 --- a/c++/jackmeter/Makefile +++ b/c++/jackmeter/Makefile @@ -31,7 +31,7 @@ OBJS = \ all: cadence-jackmeter cadence-jackmeter: $(FILES) $(OBJS) - $(CXX) $(OBJS) $(LINK_FLAGS) -o $@ && $(STRIP) $@ + $(CXX) $(OBJS) $(LINK_FLAGS) -ldl -o $@ && $(STRIP) $@ cadence-jackmeter.exe: $(FILES) $(OBJS) icon.o $(CXX) $(OBJS) icon.o $(LINK_FLAGS) -limm32 -lole32 -luuid -lwinspool -lws2_32 -mwindows -o $@ && $(STRIP) $@ diff --git a/c++/jackmeter/jackmeter.cpp b/c++/jackmeter/jackmeter.cpp index e9d6ca9..e49725a 100644 --- a/c++/jackmeter/jackmeter.cpp +++ b/c++/jackmeter/jackmeter.cpp @@ -49,8 +49,8 @@ bool gIsOutput = true; int process_callback(const jack_nframes_t nframes, void*) { - float* const jOut1 = (float*)jack_port_get_buffer(jPort1, nframes); - float* const jOut2 = (float*)jack_port_get_buffer(jPort2, nframes); + float* const jOut1 = (float*)jackbridge_port_get_buffer(jPort1, nframes); + float* const jOut2 = (float*)jackbridge_port_get_buffer(jPort2, nframes); for (jack_nframes_t i = 0; i < nframes; i++) { @@ -81,12 +81,12 @@ void session_callback(jack_session_event_t* const event, void* const arg) event->command_line = strdup(filepath.toUtf8().constData()); - jack_session_reply(jClient, event); + jackbridge_session_reply(jClient, event); if (event->type == JackSessionSaveAndQuit) x_quitNow = true; - jack_session_event_free(event); + jackbridge_session_event_free(event); } #endif @@ -97,21 +97,21 @@ void reconnect_ports() { x_needReconnect = false; - jack_port_t* const jPlayPort1 = jack_port_by_name(jClient, gIsOutput ? "system:playback_1" : "system:capture_1"); - jack_port_t* const jPlayPort2 = jack_port_by_name(jClient, gIsOutput ? "system:playback_2" : "system:capture_2"); - std::vector jPortList1(jack_port_get_all_connections_as_vector(jClient, jPlayPort1)); - std::vector jPortList2(jack_port_get_all_connections_as_vector(jClient, jPlayPort2)); + jack_port_t* const jPlayPort1 = jackbridge_port_by_name(jClient, gIsOutput ? "system:playback_1" : "system:capture_1"); + jack_port_t* const jPlayPort2 = jackbridge_port_by_name(jClient, gIsOutput ? "system:playback_2" : "system:capture_2"); + std::vector jPortList1(jackbridge_port_get_all_connections_as_vector(jClient, jPlayPort1)); + std::vector jPortList2(jackbridge_port_get_all_connections_as_vector(jClient, jPlayPort2)); foreach (char* const& thisPortName, jPortList1) { - jack_port_t* const thisPort = jack_port_by_name(jClient, thisPortName); + jack_port_t* const thisPort = jackbridge_port_by_name(jClient, thisPortName); - if (! (jack_port_is_mine(jClient, thisPort) || jack_port_connected_to(jPort1, thisPortName))) + if (! (jackbridge_port_is_mine(jClient, thisPort) || jackbridge_port_connected_to(jPort1, thisPortName))) { if (gIsOutput) - jack_connect(jClient, thisPortName, "M:in1"); + jackbridge_connect(jClient, thisPortName, "M:in1"); else - jack_connect(jClient, "Mi:in1", thisPortName); + jackbridge_connect(jClient, "Mi:in1", thisPortName); } free(thisPortName); @@ -119,14 +119,14 @@ void reconnect_ports() foreach (char* const& thisPortName, jPortList2) { - jack_port_t* const thisPort = jack_port_by_name(jClient, thisPortName); + jack_port_t* const thisPort = jackbridge_port_by_name(jClient, thisPortName); - if (! (jack_port_is_mine(jClient, thisPort) || jack_port_connected_to(jPort2, thisPortName))) + if (! (jackbridge_port_is_mine(jClient, thisPort) || jackbridge_port_connected_to(jPort2, thisPortName))) { if (gIsOutput) - jack_connect(jClient, thisPortName, "M:in2"); + jackbridge_connect(jClient, thisPortName, "M:in2"); else - jack_connect(jClient, "Mi:in2", thisPortName); + jackbridge_connect(jClient, "Mi:in2", thisPortName); } free(thisPortName); @@ -159,7 +159,7 @@ public: displayMeter(1, 0.0f); displayMeter(2, 0.0f); - int refresh = float(jack_get_buffer_size(jClient)) / jack_get_sample_rate(jClient) * 1000; + int refresh = float(jackbridge_get_buffer_size(jClient)) / jackbridge_get_sample_rate(jClient) * 1000; m_peakTimerId = startTimer(refresh > 50 ? refresh : 50); } @@ -212,26 +212,26 @@ int main(int argc, char* argv[]) #else jack_options_t jOptions = static_cast(JackNoStartServer|JackUseExactName); #endif - jClient = jack_client_open(gIsOutput ? "M" : "Mi", jOptions, &jStatus); + jClient = jackbridge_client_open(gIsOutput ? "M" : "Mi", jOptions, &jStatus); if (! jClient) { - std::string errorString(jack_status_get_error_string(jStatus)); + std::string errorString(jackbridge_status_get_error_string(jStatus)); QMessageBox::critical(nullptr, app.translate("MeterW", "Error"), app.translate("MeterW", "Could not connect to JACK, possible reasons:\n" "%1").arg(QString::fromStdString(errorString))); return 1; } - jPort1 = jack_port_register(jClient, "in1", JACK_DEFAULT_AUDIO_TYPE, gIsOutput ? JackPortIsInput : JackPortIsOutput, 0); - jPort2 = jack_port_register(jClient, "in2", JACK_DEFAULT_AUDIO_TYPE, gIsOutput ? JackPortIsInput : JackPortIsOutput, 0); + jPort1 = jackbridge_port_register(jClient, "in1", JACK_DEFAULT_AUDIO_TYPE, gIsOutput ? JackPortIsInput : JackPortIsOutput, 0); + jPort2 = jackbridge_port_register(jClient, "in2", JACK_DEFAULT_AUDIO_TYPE, gIsOutput ? JackPortIsInput : JackPortIsOutput, 0); - jack_set_process_callback(jClient, process_callback, nullptr); - jack_set_port_connect_callback(jClient, port_callback, nullptr); + jackbridge_set_process_callback(jClient, process_callback, nullptr); + jackbridge_set_port_connect_callback(jClient, port_callback, nullptr); #ifdef HAVE_JACKSESSION - jack_set_session_callback(jClient, session_callback, argv[0]); + jackbridge_set_session_callback(jClient, session_callback, argv[0]); #endif - jack_activate(jClient); + jackbridge_activate(jClient); reconnect_ports(); @@ -244,8 +244,8 @@ int main(int argc, char* argv[]) // App-Loop int ret = app.exec(); - jack_deactivate(jClient); - jack_client_close(jClient); + jackbridge_deactivate(jClient); + jackbridge_client_close(jClient); return ret; } diff --git a/c++/xycontroller/Makefile b/c++/xycontroller/Makefile index 523c455..03e1399 100644 --- a/c++/xycontroller/Makefile +++ b/c++/xycontroller/Makefile @@ -35,7 +35,7 @@ OBJS = xycontroller.o \ all: cadence-xycontroller cadence-xycontroller: $(FILES) $(OBJS) - $(CXX) $(OBJS) $(LINK_FLAGS) -o $@ && $(STRIP) $@ + $(CXX) $(OBJS) $(LINK_FLAGS) -ldl -o $@ && $(STRIP) $@ cadence-xycontroller.exe: $(FILES) $(OBJS) icon.o $(CXX) $(OBJS) icon.o $(LINK_FLAGS) -limm32 -lole32 -luuid -lwinspool -lws2_32 -mwindows -o $@ && $(STRIP) $@ diff --git a/c++/xycontroller/xycontroller.cpp b/c++/xycontroller/xycontroller.cpp index 9aa1795..ddac3c6 100644 --- a/c++/xycontroller/xycontroller.cpp +++ b/c++/xycontroller/xycontroller.cpp @@ -868,21 +868,21 @@ private: int process_callback(const jack_nframes_t nframes, void*) { - void* const midiInBuffer = jack_port_get_buffer(jMidiInPort, nframes); - void* const midiOutBuffer = jack_port_get_buffer(jMidiOutPort, nframes); + void* const midiInBuffer = jackbridge_port_get_buffer(jMidiInPort, nframes); + void* const midiOutBuffer = jackbridge_port_get_buffer(jMidiOutPort, nframes); if (! (midiInBuffer && midiOutBuffer)) return 1; // MIDI In jack_midi_event_t midiEvent; - uint32_t midiEventCount = jack_midi_get_event_count(midiInBuffer); + uint32_t midiEventCount = jackbridge_midi_get_event_count(midiInBuffer); qMidiInData.lock(); for (uint32_t i=0; i < midiEventCount; i++) { - if (jack_midi_event_get(&midiEvent, midiInBuffer, i) != 0) + if (! jackbridge_midi_event_get(&midiEvent, midiInBuffer, i)) break; if (midiEvent.size == 1) @@ -898,7 +898,7 @@ int process_callback(const jack_nframes_t nframes, void*) qMidiInData.unlock(); // MIDI Out - jack_midi_clear_buffer(midiOutBuffer); + jackbridge_midi_clear_buffer(midiOutBuffer); qMidiOutData.lock(); if (! qMidiOutData.isEmpty()) @@ -910,7 +910,7 @@ int process_callback(const jack_nframes_t nframes, void*) data[0] = d1; data[1] = d2; data[2] = d3; - jack_midi_event_write(midiOutBuffer, 0, data, 3); + jackbridge_midi_event_write(midiOutBuffer, 0, data, 3); } } qMidiOutData.unlock(); @@ -930,12 +930,12 @@ void session_callback(jack_session_event_t* const event, void* const arg) event->command_line = strdup(filepath.toUtf8().constData()); - jack_session_reply(jClient, event); + jackbridge_session_reply(jClient, event); if (event->type == JackSessionSaveAndQuit) QApplication::instance()->quit(); - jack_session_event_free(event); + jackbridge_session_event_free(event); } #endif @@ -962,25 +962,25 @@ int main(int argc, char* argv[]) #else jack_options_t jOptions = static_cast(JackNoStartServer); #endif - jClient = jack_client_open("XY-Controller", jOptions, &jStatus); + jClient = jackbridge_client_open("XY-Controller", jOptions, &jStatus); if (! jClient) { - std::string errorString(jack_status_get_error_string(jStatus)); + std::string errorString(jackbridge_status_get_error_string(jStatus)); QMessageBox::critical(nullptr, app.translate("XY-Controller", "Error"), app.translate("XY-Controller", "Could not connect to JACK, possible reasons:\n" "%1").arg(QString::fromStdString(errorString))); return 1; } - jMidiInPort = jack_port_register(jClient, "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); - jMidiOutPort = jack_port_register(jClient, "midi_out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); + jMidiInPort = jackbridge_port_register(jClient, "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); + jMidiOutPort = jackbridge_port_register(jClient, "midi_out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); - jack_set_process_callback(jClient, process_callback, nullptr); + jackbridge_set_process_callback(jClient, process_callback, nullptr); #ifdef HAVE_JACKSESSION - jack_set_session_callback(jClient, session_callback, argv[0]); + jackbridge_set_session_callback(jClient, session_callback, argv[0]); #endif - jack_activate(jClient); + jackbridge_activate(jClient); // Show GUI XYControllerW gui; @@ -989,8 +989,8 @@ int main(int argc, char* argv[]) // App-Loop int ret = app.exec(); - jack_deactivate(jClient); - jack_client_close(jClient); + jackbridge_deactivate(jClient); + jackbridge_client_close(jClient); return ret; } diff --git a/data/windows/build-win32.sh b/data/windows/build-win32.sh index 82b7ba8..c7b2902 100755 --- a/data/windows/build-win32.sh +++ b/data/windows/build-win32.sh @@ -21,8 +21,6 @@ export UIC=$MINGW-uic export STRIP=$MINGW-strip export WINDRES=$MINGW-windres -export PKG_CONFIG_PATH="`pwd`/data/windows:$MINGW_PATH/lib/pkgconfig" - export WINEPREFIX=~/.winepy3 export PYTHON_EXE="C:\\\\Python33\\\\python.exe" @@ -34,11 +32,6 @@ export PYRCC="wine C:\\\\Python33\\\\Lib\\\\site-packages\\\\PyQt4\\\\pyrcc4.exe export CFLAGS="-DPTW32_STATIC_LIB -I$MINGW_PATH/include" export CXXFLAGS="-DPTW32_STATIC_LIB -DWIN32 -I$MINGW_PATH/include" -# win32 jack libs -cp -r "$WINEPREFIX/drive_c/Program Files (x86)/Jack/includes/" ./data/windows/ -cp -r "$WINEPREFIX/drive_c/Program Files (x86)/Jack/lib/" ./data/windows/ -cp "$WINEPREFIX/drive_c/windows/syswow64/libjack.dll" ./data/windows/lib/ - # Clean build make clean diff --git a/data/windows/build-win64.sh b/data/windows/build-win64.sh index ee267ef..2f32bcf 100755 --- a/data/windows/build-win64.sh +++ b/data/windows/build-win64.sh @@ -21,8 +21,6 @@ export UIC=$MINGW-uic export STRIP=$MINGW-strip export WINDRES=$MINGW-windres -export PKG_CONFIG_PATH="`pwd`/data/windows:$MINGW_PATH/lib/pkgconfig" - export WINEPREFIX=~/.winepy3_x64 export PYTHON_EXE="C:\\\\Python33\\\\python.exe" @@ -34,11 +32,6 @@ export PYRCC="wine C:\\\\Python33\\\\Lib\\\\site-packages\\\\PyQt4\\\\pyrcc4.exe export CFLAGS="-DPTW32_STATIC_LIB -I$MINGW_PATH/include" export CXXFLAGS="-DPTW32_STATIC_LIB -DWIN32 -I$MINGW_PATH/include" -# win32 jack libs -cp -r "$WINEPREFIX/drive_c/Program Files/Jack/includes/" ./data/windows/ -cp -r "$WINEPREFIX/drive_c/Program Files/Jack/lib/" ./data/windows/ -cp "$WINEPREFIX/drive_c/windows/syswow64/libjack.dll" ./data/windows/lib/ - # Clean build make clean diff --git a/data/windows/jack.pc b/data/windows/jack.pc deleted file mode 100644 index e77eb4e..0000000 --- a/data/windows/jack.pc +++ /dev/null @@ -1,10 +0,0 @@ -prefix=../../data/windows -exec_prefix=../../data/windows -libdir=../../data/windows/lib -includedir=../../data/windows/includes - -Name: jack -Description: the Jack Audio Connection Kit: a low-latency synchronous callback-based media server -Version: 1.9.9.5 -Libs: -L../../data/windows/lib -ljack -Cflags: -I../../data/windows/includes