Commit b29c6cd9 authored by Hanspeter Portner's avatar Hanspeter Portner

implement lock stash for incoming events.

parent 64d809b8
......@@ -15,6 +15,7 @@ include_directories(${PROJECT_SOURCE_DIR}/cJSON)
include_directories(${PROJECT_SOURCE_DIR}/api)
include_directories(${PROJECT_SOURCE_DIR}/ui)
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${PROJECT_SOURCE_DIR}/plugin)
include_directories(${PROJECT_BINARY_DIR})
# check for visibility support in compiler on Unices
......
......@@ -445,9 +445,9 @@ _state_save(LV2_Handle instance, LV2_State_Store_Function store,
LV2_State_Status status = LV2_STATE_SUCCESS;
char *chunk = NULL;
_spin_lock(&moony->lock.chunk);
_spin_lock(&moony->lock.state);
chunk = strdup(moony->chunk);
_unlock(&moony->lock.chunk);
_unlock(&moony->lock.state);
if(chunk)
{
......@@ -547,9 +547,7 @@ _state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_St
if(chunk && size && type)
{
//_spin_lock(&moony->lock.chunk);
strncpy(moony->chunk, chunk, size);
//_unlock(&moony->lock.chunk);
if(luaL_dostring(L, moony->chunk))
moony_error(moony);
......@@ -886,8 +884,6 @@ moony_init(moony_t *moony, const char *subject, double sample_rate,
moony->dirty_out = 1; // trigger update of UI
moony->props_out = 1; // trigger update of UI
atomic_flag_clear_explicit(&moony->lock.chunk, memory_order_relaxed);
atomic_flag_clear_explicit(&moony->lock.error, memory_order_relaxed);
atomic_flag_clear_explicit(&moony->lock.state, memory_order_relaxed);
moony_freeuserdata(moony);
......@@ -1434,16 +1430,20 @@ moony_newuserdata(lua_State *L, moony_t *moony, moony_udata_t type, bool cache)
}
void
moony_in(moony_t *moony, const LV2_Atom_Sequence *control, LV2_Atom_Sequence *notify)
moony_pre(moony_t *moony, LV2_Atom_Sequence *notify)
{
lua_State *L = moony->vm.L;
LV2_Atom_Forge *forge = &moony->notify_forge;
LV2_Atom_Forge_Ref ref;
// initialize notify forge
const uint32_t capacity = notify->atom.size;
lv2_atom_forge_set_buffer(&moony->notify_forge, (uint8_t *)notify, capacity);
ref = lv2_atom_forge_sequence_head(&moony->notify_forge, &moony->notify_frame, 0);
moony->notify_ref = lv2_atom_forge_sequence_head(&moony->notify_forge, &moony->notify_frame, 0);
}
void
moony_in(moony_t *moony, const LV2_Atom_Sequence *control, LV2_Atom_Sequence *notify)
{
lua_State *L = moony->vm.L;
LV2_Atom_Forge *forge = &moony->notify_forge;
LV2_Atom_Forge_Ref ref = moony->notify_ref;
// read control sequence
LV2_ATOM_SEQUENCE_FOREACH(control, ev)
......@@ -1512,76 +1512,60 @@ moony_in(moony_t *moony, const LV2_Atom_Sequence *control, LV2_Atom_Sequence *no
{
if(property->body == moony->uris.moony_code)
{
if(_try_lock(&moony->lock.state))
// stash
lua_rawgeti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_STASH);
if(lua_pcall(L, 0, 0, 0))
moony_error(moony);
lua_gc(L, LUA_GCSTEP, 0);
// load chunk
const char *str = LV2_ATOM_BODY_CONST(value);
if(luaL_dostring(L, str)) // failed loading chunk
{
// stash
lua_rawgeti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_STASH);
if(lua_pcall(L, 0, 0, 0))
moony_error(moony);
lua_gc(L, LUA_GCSTEP, 0);
// load chunk
const char *str = LV2_ATOM_BODY_CONST(value);
if(luaL_dostring(L, str)) // failed loading chunk
{
moony_error(moony);
}
else // succeeded loading chunk
{
if(_try_lock(&moony->lock.chunk))
{
strncpy(moony->chunk, str, value->size);
_unlock(&moony->lock.chunk);
} //FIXME else
moony->error[0] = 0x0; // reset error flag
if(moony->state_atom)
{
// restore Lua defined properties
lua_rawgeti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_RESTORE);
if(lua_pcall(L, 0, 0, 0))
moony_error(moony);
lua_gc(L, LUA_GCSTEP, 0);
}
}
moony_error(moony);
}
else // succeeded loading chunk
{
strncpy(moony->chunk, str, value->size);
moony->error[0] = 0x0; // reset error flag
// apply stash
if(moony->stash_atom) // something has been stashed previously
if(moony->state_atom)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_APPLY);
// restore Lua defined properties
lua_rawgeti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_RESTORE);
if(lua_pcall(L, 0, 0, 0))
moony_error(moony);
lua_gc(L, LUA_GCSTEP, 0);
moony_free(moony, moony->stash_atom, moony->stash_size);
moony->stash_atom = NULL;
moony->stash_size = 0;
}
}
// apply stash
if(moony->stash_atom) // something has been stashed previously
{
lua_rawgeti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_APPLY);
if(lua_pcall(L, 0, 0, 0))
moony_error(moony);
lua_gc(L, LUA_GCSTEP, 0);
_unlock(&moony->lock.state);
} //FIXME else
moony_free(moony, moony->stash_atom, moony->stash_size);
moony->stash_atom = NULL;
moony->stash_size = 0;
}
}
else if(property->body == moony->uris.moony_selection)
{
// we do not do any stash, apply and restore for selections
if(_try_lock(&moony->lock.state))
// load chunk
const char *str = LV2_ATOM_BODY_CONST(value);
if(luaL_dostring(L, str)) // failed loading chunk
{
// load chunk
const char *str = LV2_ATOM_BODY_CONST(value);
if(luaL_dostring(L, str)) // failed loading chunk
{
moony_error(moony);
}
else // succeeded loading chunk
{
moony->error[0] = 0x0; // reset error flag
}
_unlock(&moony->lock.state);
} //FIXME else
moony_error(moony);
}
else // succeeded loading chunk
{
moony->error[0] = 0x0; // reset error flag
}
}
}
}
......@@ -1593,51 +1577,46 @@ moony_in(moony_t *moony, const LV2_Atom_Sequence *control, LV2_Atom_Sequence *no
// clear all properties in UI
LV2_Atom_Forge_Frame obj_frame, add_frame, rem_frame;
if(ref)
ref = lv2_atom_forge_frame_time(&moony->notify_forge, 0);
ref = lv2_atom_forge_frame_time(forge, 0);
if(ref)
ref = lv2_atom_forge_object(&moony->notify_forge, &obj_frame, 0, moony->uris.patch.patch);
ref = lv2_atom_forge_object(forge, &obj_frame, 0, moony->uris.patch.patch);
if(ref)
ref = lv2_atom_forge_key(&moony->notify_forge, moony->uris.patch.subject);
ref = lv2_atom_forge_key(forge, moony->uris.patch.subject);
if(ref)
ref = lv2_atom_forge_urid(&moony->notify_forge, moony->uris.patch.self);
ref = lv2_atom_forge_urid(forge, moony->uris.patch.self);
if(ref)
ref = lv2_atom_forge_key(&moony->notify_forge, moony->uris.patch.remove);
ref = lv2_atom_forge_key(forge, moony->uris.patch.remove);
if(ref)
ref = lv2_atom_forge_object(&moony->notify_forge, &rem_frame, 0, 0);
ref = lv2_atom_forge_object(forge, &rem_frame, 0, 0);
if(ref)
ref = lv2_atom_forge_key(&moony->notify_forge, moony->uris.patch.writable);
ref = lv2_atom_forge_key(forge, moony->uris.patch.writable);
if(ref)
ref = lv2_atom_forge_urid(&moony->notify_forge, moony->uris.patch.wildcard);
ref = lv2_atom_forge_urid(forge, moony->uris.patch.wildcard);
if(ref)
ref = lv2_atom_forge_key(&moony->notify_forge, moony->uris.patch.readable);
ref = lv2_atom_forge_key(forge, moony->uris.patch.readable);
if(ref)
ref = lv2_atom_forge_urid(&moony->notify_forge, moony->uris.patch.wildcard);
ref = lv2_atom_forge_urid(forge, moony->uris.patch.wildcard);
if(ref)
lv2_atom_forge_pop(&moony->notify_forge, &rem_frame);
lv2_atom_forge_pop(forge, &rem_frame);
if(ref)
ref = lv2_atom_forge_key(&moony->notify_forge, moony->uris.patch.add);
ref = lv2_atom_forge_key(forge, moony->uris.patch.add);
if(ref)
lv2_atom_forge_object(&moony->notify_forge, &add_frame, 0, 0);
lv2_atom_forge_object(forge, &add_frame, 0, 0);
if(ref)
lv2_atom_forge_pop(&moony->notify_forge, &add_frame);
lv2_atom_forge_pop(forge, &add_frame);
if(ref)
lv2_atom_forge_pop(&moony->notify_forge, &obj_frame);
lv2_atom_forge_pop(forge, &obj_frame);
moony->props_out = 0;
}
if(moony->dirty_out)
{
if(_try_lock(&moony->lock.chunk))
{
uint32_t len = strlen(moony->chunk);
if(ref)
ref = lv2_atom_forge_frame_time(forge, 0);
if(ref)
ref = _moony_patch(&moony->uris.patch, forge, moony->uris.moony_code, moony->chunk, len);
_unlock(&moony->lock.chunk);
} //FIXME else
uint32_t len = strlen(moony->chunk);
if(ref)
ref = lv2_atom_forge_frame_time(forge, 0);
if(ref)
ref = _moony_patch(&moony->uris.patch, forge, moony->uris.moony_code, moony->chunk, len);
moony->dirty_out = 0; // reset flag
}
......
......@@ -266,8 +266,6 @@ struct _moony_t {
int upc [MOONY_UPCLOSURE_COUNT];
struct {
atomic_flag chunk;
atomic_flag error;
atomic_flag state;
} lock;
......@@ -285,6 +283,7 @@ int moony_init(moony_t *moony, const char *subject, double sample_rate,
const LV2_Feature *const *features);
void moony_deinit(moony_t *moony);
void moony_open(moony_t *moony, lua_State *L, bool use_assert);
void moony_pre(moony_t *moony, LV2_Atom_Sequence *notify);
void moony_in(moony_t *moony, const LV2_Atom_Sequence *control, LV2_Atom_Sequence *notify);
void moony_out(moony_t *moony, LV2_Atom_Sequence *notify, uint32_t frames);
const void* extension_data(const char* uri);
......
......@@ -18,6 +18,7 @@
#include <moony.h>
#include <api_atom.h>
#include <api_forge.h>
#include <lock_stash.h>
#include <lauxlib.h>
......@@ -36,6 +37,10 @@ struct _Handle {
LV2_Atom_Sequence *notify;
LV2_Atom_Forge forge [4];
lock_stash_t stash [5];
bool stashed;
uint32_t stash_nsamples;
};
static LV2_Handle
......@@ -65,6 +70,12 @@ instantiate(const LV2_Descriptor* descriptor, double rate, const char *bundle_pa
for(unsigned i=0; i<handle->max_val; i++)
lv2_atom_forge_init(&handle->forge[i], handle->moony.map);
for(unsigned i=0; i<handle->max_val + 1; i++)
{
_stash_init(&handle->stash[i], handle->moony.map);
_stash_reset(&handle->stash[i]);
}
return handle;
}
......@@ -83,20 +94,19 @@ connect_port(LV2_Handle instance, uint32_t port, void *data)
handle->notify = (LV2_Atom_Sequence *)data;
}
static int
_run(lua_State *L)
static inline void
_run_period(lua_State *L, Handle *handle, uint32_t nsamples,
const LV2_Atom_Sequence **event_in, const LV2_Atom_Sequence *control)
{
Handle *handle = lua_touserdata(L, lua_upvalueindex(1));
if(lua_getglobal(L, "run") != LUA_TNIL)
{
lua_pushinteger(L, handle->sample_count);
lua_pushinteger(L, nsamples);
// push sequence / forge pair(s)
for(unsigned i=0; i<handle->max_val; i++)
{
latom_t *latom = moony_newuserdata(L, &handle->moony, MOONY_UDATA_ATOM, true);
latom->atom = (const LV2_Atom *)handle->event_in[i];
latom->atom = (const LV2_Atom *)event_in[i];
latom->body.raw = LV2_ATOM_BODY_CONST(latom->atom);
lforge_t *lforge = moony_newuserdata(L, &handle->moony, MOONY_UDATA_FORGE, true);
......@@ -108,7 +118,7 @@ _run(lua_State *L)
// push control / notify pair
{
latom_t *latom = moony_newuserdata(L, &handle->moony, MOONY_UDATA_ATOM, true);
latom->atom = (const LV2_Atom *)handle->control;
latom->atom = (const LV2_Atom *)control;
latom->body.raw = LV2_ATOM_BODY_CONST(latom->atom);
lforge_t *lforge = moony_newuserdata(L, &handle->moony, MOONY_UDATA_FORGE, true);
......@@ -119,6 +129,36 @@ _run(lua_State *L)
lua_call(L, 1 + 2*handle->max_val + 2, 0);
}
}
static int
_run(lua_State *L)
{
Handle *handle = lua_touserdata(L, lua_upvalueindex(1));
// apply stash, if any
if(handle->stashed)
{
const LV2_Atom_Sequence *event_in [4] = {
[0] = &handle->stash[0].seq,
[1] = &handle->stash[1].seq,
[2] = &handle->stash[2].seq,
[3] = &handle->stash[3].seq
};
const LV2_Atom_Sequence *control = &handle->stash[handle->max_val].seq;
_run_period(L, handle, handle->stash_nsamples, event_in, control);
for(unsigned i=0; i<handle->max_val; i++)
{
LV2_ATOM_SEQUENCE_FOREACH(handle->event_out[i], ev)
ev->time.frames = 0; // overwrite time stamps
}
LV2_ATOM_SEQUENCE_FOREACH(handle->notify, ev)
ev->time.frames = 0; // overwrite time stamps
}
_run_period(L, handle, handle->sample_count, handle->event_in, handle->control);
return 0;
}
......@@ -131,9 +171,6 @@ run(LV2_Handle instance, uint32_t nsamples)
handle->sample_count = nsamples;
// handle UI comm
moony_in(&handle->moony, handle->control, handle->notify);
// prepare event_out sequence
LV2_Atom_Forge_Frame frame [4];
......@@ -144,25 +181,83 @@ run(LV2_Handle instance, uint32_t nsamples)
lv2_atom_forge_sequence_head(&handle->forge[i], &frame[i], 0);
}
// run
if(!moony_bypass(&handle->moony) && _try_lock(&handle->moony.lock.state))
moony_pre(&handle->moony, handle->notify);
if(_try_lock(&handle->moony.lock.state))
{
if(lua_gettop(L) != 1)
// apply stash, if any
if(handle->stashed)
{
lock_stash_t *stash = &handle->stash[handle->max_val];
moony_in(&handle->moony, &stash->seq, handle->notify);
LV2_ATOM_SEQUENCE_FOREACH(handle->notify, ev)
ev->time.frames = 0; // overwrite time stamps
}
// handle UI comm
moony_in(&handle->moony, handle->control, handle->notify);
// run
if(!moony_bypass(&handle->moony))
{
// cache for reuse
lua_settop(L, 0);
lua_pushlightuserdata(L, handle);
lua_pushcclosure(L, _run, 1);
if(lua_gettop(L) != 1)
{
// cache for reuse
lua_settop(L, 0);
lua_pushlightuserdata(L, handle);
lua_pushcclosure(L, _run, 1);
}
lua_pushvalue(L, 1); // _run with upvalue
if(lua_pcall(L, 0, 0, 0))
moony_error(&handle->moony);
moony_freeuserdata(&handle->moony);
lua_gc(L, LUA_GCSTEP, 0);
}
lua_pushvalue(L, 1); // _run with upvalue
if(lua_pcall(L, 0, 0, 0))
moony_error(&handle->moony);
moony_freeuserdata(&handle->moony);
lua_gc(L, LUA_GCSTEP, 0);
if(handle->stashed)
{
for(unsigned i=0; i<handle->max_val + 1; i++)
_stash_reset(&handle->stash[i]);
handle->stash_nsamples = 0;
handle->stashed = false;
}
_unlock(&handle->moony.lock.state);
} //FIXME else
}
else
{
lock_stash_t *stash;
// stash incoming events to later apply
for(unsigned i=1; i<handle->max_val; i++)
{
stash = &handle->stash[i];
LV2_ATOM_SEQUENCE_FOREACH(handle->event_in[i], ev)
{
if(stash->ref)
stash->ref = lv2_atom_forge_frame_time(&stash->forge, handle->stash_nsamples + ev->time.frames);
if(stash->ref)
stash->ref = lv2_atom_forge_write(&stash->forge, &ev->body, lv2_atom_total_size(&ev->body));
}
}
stash = &handle->stash[handle->max_val];
LV2_ATOM_SEQUENCE_FOREACH(handle->control, ev)
{
if(stash->ref)
stash->ref = lv2_atom_forge_frame_time(&stash->forge, handle->stash_nsamples + ev->time.frames);
if(stash->ref)
stash->ref = lv2_atom_forge_write(&stash->forge, &ev->body, lv2_atom_total_size(&ev->body));
}
handle->stash_nsamples += nsamples;
handle->stashed = true;
}
for(unsigned i=0; i<handle->max_val; i++)
if(&frame[i] != handle->forge[i].stack) // intercept assert
......
......@@ -18,6 +18,7 @@
#include <moony.h>
#include <api_atom.h>
#include <api_forge.h>
#include <lock_stash.h>
#include <lauxlib.h>
......@@ -38,6 +39,10 @@ struct _Handle {
LV2_Atom_Sequence *notify;
LV2_Atom_Forge forge;
lock_stash_t stash [2];
bool stashed;
uint32_t stash_nsamples;
};
static LV2_Handle
......@@ -65,6 +70,12 @@ instantiate(const LV2_Descriptor* descriptor, double rate, const char *bundle_pa
handle->max_val = 1;
lv2_atom_forge_init(&handle->forge, handle->moony.map);
for(unsigned i=0; i<2; i++)
{
_stash_init(&handle->stash[i], handle->moony.map);
_stash_reset(&handle->stash[i]);
}
return handle;
}
......@@ -88,20 +99,19 @@ connect_port(LV2_Handle instance, uint32_t port, void *data)
handle->notify = (LV2_Atom_Sequence *)data;
}
static int
_run(lua_State *L)
static inline void
_run_period(lua_State *L, Handle *handle, uint32_t nsamples,
const LV2_Atom_Sequence *event_in, const LV2_Atom_Sequence *control)
{
Handle *handle = lua_touserdata(L, lua_upvalueindex(1));
int top = lua_gettop(L);
if(lua_getglobal(L, "run") != LUA_TNIL)
{
lua_pushinteger(L, handle->sample_count);
lua_pushinteger(L, nsamples);
// push sequence / forge pair
{
latom_t *latom = moony_newuserdata(L, &handle->moony, MOONY_UDATA_ATOM, true);
latom->atom = (const LV2_Atom *)handle->event_in;
latom->atom = (const LV2_Atom *)event_in;
latom->body.raw = LV2_ATOM_BODY_CONST(latom->atom);
lforge_t *lforge = moony_newuserdata(L, &handle->moony, MOONY_UDATA_FORGE, true);
......@@ -117,7 +127,7 @@ _run(lua_State *L)
// push control / notify pair
{
latom_t *latom = moony_newuserdata(L, &handle->moony, MOONY_UDATA_ATOM, true);
latom->atom = (const LV2_Atom *)handle->control;
latom->atom = (const LV2_Atom *)control;
latom->body.raw = LV2_ATOM_BODY_CONST(latom->atom);
lforge_t *lforge = moony_newuserdata(L, &handle->moony, MOONY_UDATA_FORGE, true);
......@@ -135,6 +145,28 @@ _run(lua_State *L)
for(unsigned i=ret; i<handle->max_val; i++) // fill in missing returns with 0.f
*handle->val_out[i] = 0.f;
}
}
static int
_run(lua_State *L)
{
Handle *handle = lua_touserdata(L, lua_upvalueindex(1));
// apply stash, if any
if(handle->stashed)
{
const LV2_Atom_Sequence *event_in = &handle->stash[0].seq;
const LV2_Atom_Sequence *control = &handle->stash[1].seq;
_run_period(L, handle, handle->stash_nsamples, event_in, control);
LV2_ATOM_SEQUENCE_FOREACH(handle->event_out, ev)
ev->time.frames = 0; // overwrite time stamps
LV2_ATOM_SEQUENCE_FOREACH(handle->notify, ev)
ev->time.frames = 0; // overwrite time stamps
}
_run_period(L, handle, handle->sample_count, handle->event_in, handle->control);
return 0;
}
......@@ -147,34 +179,83 @@ run(LV2_Handle instance, uint32_t nsamples)
handle->sample_count = nsamples;
// handle UI comm
moony_in(&handle->moony, handle->control, handle->notify);
// prepare event_out sequence
LV2_Atom_Forge_Frame frame;
uint32_t capacity = handle->event_out->atom.size;
lv2_atom_forge_set_buffer(&handle->forge, (uint8_t *)handle->event_out, capacity);
lv2_atom_forge_sequence_head(&handle->forge, &frame, 0);
// run
if(!moony_bypass(&handle->moony) && _try_lock(&handle->moony.lock.state))
moony_pre(&handle->moony, handle->notify);
if(_try_lock(&handle->moony.lock.state))
{
if(lua_gettop(L) != 1)
// apply stash, if any
if(handle->stashed)
{
lock_stash_t *stash = &handle->stash[1];
moony_in(&handle->moony, &stash->seq, handle->notify);
LV2_ATOM_SEQUENCE_FOREACH(handle->notify, ev)
ev->time.frames = 0; // overwrite time stamps
}
// handle UI comm
moony_in(&handle->moony, handle->control, handle->notify);
// run
if(!moony_bypass(&handle->moony))
{
// cache for reuse
lua_settop(L, 0);
lua_pushlightuserdata(L, handle);
lua_pushcclosure(L, _run, 1);
if(lua_gettop(L) != 1)
{
// cache for reuse
lua_settop(L, 0);
lua_pushlightuserdata(L, handle);
lua_pushcclosure(L, _run, 1);
}
lua_pushvalue(L, 1); // _run with upvalue
if(lua_pcall(L, 0, 0, 0))
moony_error(&handle->moony);
moony_freeuserdata(&handle->moony);
lua_gc(L, LUA_GCSTEP, 0);
}
lua_pushvalue(L, 1); // _run with upvalue
if(lua_pcall(L, 0, 0, 0))
moony_error(&handle->moony);
moony_freeuserdata(&handle->moony);
lua_gc(L, LUA_GCSTEP, 0);
if(handle->stashed)
{
for(unsigned i=0; i<2; i++)
_stash_reset(&handle->stash[i]);
handle->stash_nsamples = 0;
handle->stashed = false;
}
_unlock(&handle->moony.lock.state);
} //FIXME else
}
else
{
// stash incoming events to later apply
lock_stash_t *stash = &handle->stash[0];
LV2_ATOM_SEQUENCE_FOREACH(handle->event_in, ev)
{
if(stash->ref)
stash->ref = lv2_atom_forge_frame_time(&stash->forge, handle->stash_nsamples + ev->time.frames);
if(stash->ref)
stash->ref = lv2_atom_forge_write(&stash->forge, &ev->body, lv2_atom_total_size(&ev->body));
}
stash = &handle->stash[1];
LV2_ATOM_SEQUENCE_FOREACH(handle->control, ev)
{
if(stash->ref)
stash->ref = lv2_atom_forge_frame_time(&stash->forge, handle->stash_nsamples + ev->time.frames);
if(stash->ref)
stash->ref = lv2_atom_forge_write(&stash->forge, &ev->body, lv2_atom_total_size(&ev->body));
}
handle->stash_nsamples += nsamples;
handle->stashed = true;
}
if(&frame != handle->forge.stack) // intercept assert
moony_err(&handle->moony, "forge frame mismatch");
......
......@@ -18,6 +18,7 @@
#include <moony.h>
#include <api_atom.h>
#include <api_forge.h>
#include <lock_stash.h>
#include <lauxlib.h>
......@@ -34,6 +35,10 @@ struct _Handle {
const LV2_Atom_Sequence *control;
LV2_Atom_Sequence *notify;
lock_stash_t stash;
bool stashed;
uint32_t stash_nsamples;
};
static LV2_Handle
......@@ -60,6 +65,9 @@ instantiate(const LV2_Descriptor* descriptor, double rate, const char *bundle_pa
else
handle->max_val = 1;
_stash_init(&handle->stash, handle->moony.map);
_stash_reset(&handle->stash);
return handle;
}
......@@ -78,15 +86,14 @@ connect_port(LV2_Handle instance, uint32_t port, void *data)
handle->notify = (LV2_Atom_Sequence *)data;
}
static int
_run(lua_State *L)
static inline void
_run_period(lua_State *L, Handle *handle, uint32_t nsamples,
const LV2_Atom_Sequence *control)
{
Handle *handle = lua_touserdata(L, lua_upvalueindex(1));
int top = lua_gettop(L);
if(lua_getglobal(L, "run") != LUA_TNIL)
{
lua_pushinteger(L, handle->sample_count);
lua_pushinteger(L, nsamples);
for(unsigned i=0; i<handle->max_val; i++)
lua_pushnumber(L, *handle->val_in[i]);
......@@ -94,7 +101,7 @@ _run(lua_State *L)
// push control / notify pair
{
latom_t *latom = moony_newuserdata(L, &handle->moony, MOONY_UDATA_ATOM, true);
latom->atom = (const LV2_Atom *)handle->control;
latom->atom = (const LV2_Atom *)control;
latom->body.raw = LV2_ATOM_BODY_CONST(latom->atom);
lforge_t *lforge = moony_newuserdata(L, &handle->moony, MOONY_UDATA_FORGE, true);
......@@ -112,6 +119,25 @@ _run(lua_State *L)
for(unsigned i=ret; i<handle->max_val; i++) // fill in missing returns with 0.f