Commit 0766868f authored by Hanspeter Portner's avatar Hanspeter Portner

Squashed 'xpress.lv2/' changes from 5d103cdb..04c3ab5e

04c3ab5e fix gitlab CI recipe.
9ec38e6f fix pedantic warnings.
ddaed59b prototype global voice uuid in shared memory.

git-subtree-dir: xpress.lv2
git-subtree-split: 04c3ab5e0a2a77a9ee6c742c0febe6315127c150
parent cf9590c0
stages:
- build
- test
- deploy
.variables_template: &variables_definition
variables:
BASE_NAME: "xpress.lv2"
PKG_CONFIG_PATH: "/opt/lv2/lib/pkgconfig:/opt/${CI_BUILD_NAME}/lib/pkgconfig"
TOOLCHAIN_FILE: "${CI_PROJECT_DIR}/cmake/${CI_BUILD_NAME}.cmake"
TOOLCHAIN_FILE: "${CI_PROJECT_DIR}/meson/${CI_BUILD_NAME}"
.common_template: &common_definition
<<: *variables_definition
......@@ -20,12 +19,9 @@ stages:
.build_template: &build_definition
<<: *common_definition
script:
- mkdir build
- pushd build
- cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${CI_PROJECT_DIR} -DPLUGIN_DEST="${BASE_NAME}-$(cat ../VERSION)/${CI_BUILD_NAME}/${BASE_NAME}" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} ..
- cmake .. # needed for darwin
- make
- make install
- meson --prefix="/" --libdir="lib" --cross-file "${TOOLCHAIN_FILE}" build
- ninja -C build
- DESTDIR="${CI_PROJECT_DIR}/${BASE_NAME}-$(cat VERSION)/${CI_BUILD_NAME}" ninja -C build install
.universal_linux_template: &universal_linux_definition
image: ventosus/universal-linux-gnu
......
project('xpress.lv2', 'c', default_options : [
'buildtype=release',
'warning_level=1',
'werror=false',
'warning_level=3',
'werror=true',
'b_lto=true',
'c_std=c11'])
......@@ -13,8 +13,8 @@ cc = meson.get_compiler('c')
cp = find_program('cp')
clone = [cp, '@INPUT@', '@OUTPUT@']
m_dep = cc.find_library('m')
lv2_dep = dependency('lv2', version : '>=1.14.0')
deps = [lv2_dep]
inc_dir = []
......@@ -25,11 +25,16 @@ dsp_srcs = [join_paths('test', 'xpress.c')]
c_args = ['-fvisibility=hidden',
'-ffast-math']
if host_machine.system() == 'linux'
rt_dep = cc.find_library('rt')
deps += rt_dep
endif
mod = shared_module('xpress', dsp_srcs,
c_args : c_args,
include_directories : inc_dir,
name_prefix : '',
dependencies : [m_dep, lv2_dep],
dependencies : deps,
install : true,
install_dir : inst_dir)
......
......@@ -37,7 +37,7 @@ struct _targetI_t {
};
struct _targetO_t {
// empty
uint8_t dummy;
};
struct _plughandle_t {
......@@ -56,21 +56,6 @@ struct _plughandle_t {
targetO_t targetO [MAX_NVOICES];
};
static atomic_uint voice_uuid = ATOMIC_VAR_INIT(0);
static xpress_uuid_t
_voice_map_new_uuid(void *handle, uint32_t flag)
{
(void)flag;
atomic_uint *uuid = handle;
return atomic_fetch_add_explicit(uuid, 1, memory_order_relaxed);
}
static xpress_map_t voice_map_fallback = {
.handle = &voice_uuid,
.new_uuid = _voice_map_new_uuid
};
static void
_dump(plughandle_t *handle)
{
......@@ -155,8 +140,10 @@ static const xpress_iface_t ifaceO = {
};
static LV2_Handle
instantiate(const LV2_Descriptor* descriptor, double rate,
const char *bundle_path, const LV2_Feature *const *features)
instantiate(const LV2_Descriptor* descriptor,
double rate __attribute__((unused)),
const char *bundle_path __attribute__((unused)),
const LV2_Feature *const *features)
{
plughandle_t *handle = calloc(1, sizeof(plughandle_t));
if(!handle)
......@@ -188,8 +175,6 @@ instantiate(const LV2_Descriptor* descriptor, double rate,
free(handle);
return NULL;
}
if(!voice_map)
voice_map = &voice_map_fallback;
lv2_log_logger_init(&handle->logger, handle->map, handle->log);
......@@ -267,6 +252,8 @@ cleanup(LV2_Handle instance)
{
plughandle_t *handle = instance;
xpress_deinit(&handle->xpressI);
xpress_deinit(&handle->xpressO);
free(handle);
}
......
......@@ -24,7 +24,14 @@ extern "C" {
#include <stdlib.h>
#include <stdio.h>
#include <stdatomic.h>
#include <time.h>
#ifndef _WIN32
# include <sys/mman.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
#endif
#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
......@@ -35,6 +42,7 @@ extern "C" {
* API START
*****************************************************************************/
#define XPRESS_SHM_ID "/lv2_xpress_shm"
#define XPRESS_URI "http://open-music-kontrollers.ch/lv2/xpress"
#define XPRESS_PREFIX XPRESS_URI"#"
......@@ -60,11 +68,9 @@ extern "C" {
// types
typedef uint32_t xpress_uuid_t;
// enumerations
typedef enum _xpress_event_t xpress_event_t;
// structures
typedef struct _xpress_map_t xpress_map_t;
typedef struct _xpress_shm_t xpress_shm_t;
typedef struct _xpress_state_t xpress_state_t;
typedef struct _xpress_voice_t xpress_voice_t;
typedef struct _xpress_iface_t xpress_iface_t;
......@@ -81,11 +87,11 @@ typedef xpress_add_cb_t xpress_set_cb_t;
typedef void (*xpress_del_cb_t)(void *data, int64_t frames,
xpress_uuid_t uuid, void *target);
enum _xpress_event_t {
typedef enum _xpress_event_t {
XPRESS_EVENT_ADD = (1 << 0),
XPRESS_EVENT_DEL = (1 << 1),
XPRESS_EVENT_SET = (1 << 2)
};
} xpress_event_t;
#define XPRESS_EVENT_NONE (0)
#define XPRESS_EVENT_ALL (XPRESS_EVENT_ADD | XPRESS_EVENT_DEL | XPRESS_EVENT_SET)
......@@ -122,6 +128,10 @@ struct _xpress_map_t {
xpress_map_new_uuid_t new_uuid;
};
struct _xpress_shm_t {
atomic_uint voice_uuid;
};
struct _xpress_t {
struct {
LV2_URID xpress_Token;
......@@ -143,6 +153,8 @@ struct _xpress_t {
LV2_URID_Map *map;
xpress_map_t *voice_map;
xpress_shm_t *xpress_shm;
atomic_uint voice_uuid;
bool synced;
xpress_uuid_t source;
......@@ -152,7 +164,7 @@ struct _xpress_t {
unsigned max_nvoices;
unsigned nvoices;
xpress_voice_t voices [0];
xpress_voice_t voices [1];
};
#define XPRESS_CONCAT_IMPL(X, Y) X##Y
......@@ -160,7 +172,7 @@ struct _xpress_t {
#define XPRESS_T(XPRESS, MAX_NVOICES) \
xpress_t (XPRESS); \
xpress_voice_t XPRESS_CONCAT(_voices, __COUNTER__) [(MAX_NVOICES)];
xpress_voice_t XPRESS_CONCAT(_voices, __COUNTER__) [(MAX_NVOICES - 1)]
#define XPRESS_VOICE_FOREACH(XPRESS, VOICE) \
for(xpress_voice_t *(VOICE) = &(XPRESS)->voices[(int)(XPRESS)->nvoices - 1]; \
......@@ -178,6 +190,9 @@ xpress_init(xpress_t *xpress, const size_t max_nvoices, LV2_URID_Map *map,
xpress_map_t *voice_map, xpress_event_t event_mask, const xpress_iface_t *iface,
void *target, void *data);
static void
xpress_deinit(xpress_t *xpress);
// rt-safe
static inline void *
xpress_get(xpress_t *xpress, xpress_uuid_t uuid);
......@@ -245,8 +260,8 @@ _xpress_urn_uuid(LV2_URID_Map *map)
for(unsigned i=0x0; i<0x10; i++)
bytes[i] = rand() & 0xff;
bytes[6] = (bytes[6] & 0b00001111) | 0b01000000; // set four most significant bits of 7th byte to 0b0100
bytes[8] = (bytes[8] & 0b00111111) | 0b10000000; // set two most significant bits of 9th byte to 0b10
bytes[6] = (bytes[6] & 0x0f) | 0x40; // set four most significant bits of 7th byte to 0b0100
bytes[8] = (bytes[8] & 0x3f) | 0x80; // set two most significant bits of 9th byte to 0b10
char uuid [46];
snprintf(uuid, sizeof(uuid),
......@@ -347,6 +362,60 @@ _xpress_voice_free(xpress_t *xpress, xpress_voice_t *voice)
xpress->nvoices--;
}
xpress_shm_t *
_xpress_shm_init()
{
xpress_shm_t *xpress_shm = NULL;
#ifndef _WIN32
const size_t total_size = sizeof(xpress_shm_t);
bool is_first = true;
int fd = shm_open(XPRESS_SHM_ID, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if(fd == -1)
{
is_first = false;
fd = shm_open(XPRESS_SHM_ID, O_RDWR, S_IRUSR | S_IWUSR);
}
if(fd == -1)
{
return NULL;
}
if( (ftruncate(fd, total_size) == -1)
|| ((xpress_shm = mmap(NULL, total_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0)) == MAP_FAILED) )
{
shm_unlink(XPRESS_SHM_ID);
close(fd);
return NULL;
}
close(fd);
if(is_first)
{
atomic_init(&xpress_shm->voice_uuid, 1);
}
#endif
return xpress_shm;
}
void
_xpress_shm_deinit(xpress_shm_t *xpress_shm)
{
#ifndef _WIN32
const size_t total_size = sizeof(xpress_shm_t);
munmap(xpress_shm, total_size);
shm_unlink(XPRESS_SHM_ID);
#else
(void)xpress_shm;
#endif
}
static inline int
xpress_init(xpress_t *xpress, const size_t max_nvoices, LV2_URID_Map *map,
xpress_map_t *voice_map, xpress_event_t event_mask, const xpress_iface_t *iface,
......@@ -386,15 +455,37 @@ xpress_init(xpress_t *xpress, const size_t max_nvoices, LV2_URID_Map *map,
voice->uuid = 0;
voice->target = target && iface
? target + i*iface->size
? (uint8_t *)target + i*iface->size
: NULL;
}
xpress->source = _xpress_urn_uuid(map);
if(!xpress->voice_map)
{
// fall-back to shared memory
xpress->xpress_shm = _xpress_shm_init();
if(!xpress->xpress_shm)
{
// fall-back to local memory
const uint32_t pseudo_unique = (const uintptr_t)xpress;
atomic_init(&xpress->voice_uuid, pseudo_unique);
}
}
return 1;
}
static void
xpress_deinit(xpress_t *xpress)
{
if(xpress->xpress_shm)
{
_xpress_shm_deinit(xpress->xpress_shm);
}
}
static inline void *
xpress_get(xpress_t *xpress, xpress_uuid_t uuid)
{
......@@ -407,7 +498,7 @@ xpress_get(xpress_t *xpress, xpress_uuid_t uuid)
static inline int
xpress_advance(xpress_t *xpress, LV2_Atom_Forge *forge, uint32_t frames,
const LV2_Atom_Object *obj, LV2_Atom_Forge_Ref *ref)
const LV2_Atom_Object *obj, LV2_Atom_Forge_Ref *ref __attribute__((unused)))
{
if(!lv2_atom_forge_is_object_type(forge, obj->atom.type))
return 0;
......@@ -731,7 +822,21 @@ xpress_alive(xpress_t *xpress, LV2_Atom_Forge *forge, uint32_t frames)
static inline int32_t
xpress_map(xpress_t *xpress)
{
return xpress->voice_map->new_uuid(xpress->voice_map->handle, 0);
if(xpress->voice_map)
{
xpress_map_t *voice_map = xpress->voice_map;
return voice_map->new_uuid(voice_map->handle, 0);
}
else if(xpress->xpress_shm)
{
xpress_shm_t *xpress_shm = xpress->xpress_shm;
return atomic_fetch_add_explicit(&xpress_shm->voice_uuid, 1, memory_order_relaxed);
}
// fall-back
return atomic_fetch_add_explicit(&xpress->voice_uuid, 1, memory_order_relaxed);
}
#ifdef __cplusplus
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment