Commit 7ed16e3e authored by Hanspeter Portner's avatar Hanspeter Portner

implement forge:autopop() for-iterator.

parent 35625550
......@@ -4,6 +4,8 @@
* api: CanvasResponder
* gui: clipboard support
* gui: external editor
* api: remove inline-display/cairo once ardour supports routing atoms
=== High priority
* doc: Parameter
* api: make vector a real container forge object
......@@ -1810,6 +1810,10 @@ moony_open(moony_t *moony, lua_State *L)
lua_pushcclosure(L, _latom_seq_foreach, 1);
lua_rawseti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_SEQUENCE_FOREACH);
lua_pushlightuserdata(L, moony);
lua_pushcclosure(L, _lforge_autopop_itr, 1);
lua_rawseti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_FORGE_AUTOPOP_ITR);
lua_newtable(L);
lua_rawseti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_COUNT + MOONY_UPCLOSURE_TUPLE_FOREACH);
lua_newtable(L);
......@@ -1821,13 +1825,6 @@ moony_open(moony_t *moony, lua_State *L)
lua_newtable(L);
lua_rawseti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_COUNT + MOONY_UPCLOSURE_SEQUENCE_MULTIPLEX);
lua_newtable(L);
lua_rawseti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_COUNT + MOONY_UPCLOSURE_TUPLE_PACK);
lua_newtable(L);
lua_rawseti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_COUNT + MOONY_UPCLOSURE_OBJECT_PACK);
lua_newtable(L);
lua_rawseti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_COUNT + MOONY_UPCLOSURE_SEQUENCE_PACK);
#undef SET_MAP
}
......
......@@ -23,39 +23,6 @@
#include <osc.lv2/forge.h>
static const lua_CFunction upclosures [MOONY_UPCLOSURE_COUNT] = {
[MOONY_UPCLOSURE_TUPLE_PACK] = _lforge_tuple_itr,
[MOONY_UPCLOSURE_OBJECT_PACK] = _lforge_object_itr,
[MOONY_UPCLOSURE_SEQUENCE_PACK] = _lforge_sequence_itr
};
__realtime static inline void
_pushupclosure(lua_State *L, moony_t *moony, moony_upclosure_t type, bool cache)
{
assert( (type >= MOONY_UPCLOSURE_TUPLE_FOREACH) && (type < MOONY_UPCLOSURE_COUNT) );
int *upc = &moony->upc[type];
lua_rawgeti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_COUNT + type); // ref
if(lua_rawgeti(L, -1, *upc) == LUA_TNIL) // no cached udata, create one!
{
#if 0
if(moony->log)
lv2_log_trace(&moony->logger, "_pushupclosure:\n");
#endif
lua_pop(L, 1); // nil
lua_pushlightuserdata(L, moony);
moony_newuserdata(L, moony, MOONY_UDATA_FORGE, cache);
lua_pushcclosure(L, upclosures[type], 2);
lua_pushvalue(L, -1);
lua_rawseti(L, -3, *upc); // store in cache
}
lua_remove(L, -2); // ref
*upc += 1;
}
__realtime static void
_lforge_pop_inlined(lua_State *L, lforge_t *lforge)
{
......@@ -798,46 +765,6 @@ _lforge_tuple(lua_State *L)
return 1; // derived forge
}
__realtime int
_lforge_tuple_itr(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lframe = lua_touserdata(L, lua_upvalueindex(2));
lforge_t *lforge = lua_touserdata(L, 1);
if(lua_isnil(L, 2)) // 1st invocation
{
lframe->depth = 1;
lframe->last.frames = lforge->last.frames;
lframe->forge = lforge->forge;
if(!lv2_atom_forge_tuple(lforge->forge, &lframe->frame[0]))
luaL_error(L, forge_buffer_overflow);
lua_pushvalue(L, lua_upvalueindex(2)); // push cached lforge
}
else // 2nd invocation
{
_lforge_pop_inlined(L, lframe);
lua_pushnil(L); // terminate iterator
}
return 1; // derived forge || nil
}
__realtime static int
_lforge_tuple_pack(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lforge = lua_touserdata(L, 1);
_pushupclosure(L, moony, MOONY_UPCLOSURE_TUPLE_PACK, lforge->lheader.cache);
lua_pushvalue(L, 1);
return 2;
}
__realtime static int
_lforge_object(lua_State *L)
{
......@@ -858,49 +785,6 @@ _lforge_object(lua_State *L)
return 1; // derived forge
}
__realtime int
_lforge_object_itr(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lframe = lua_touserdata(L, lua_upvalueindex(2));
lforge_t *lforge = lua_touserdata(L, 1);
if(lua_isnil(L, 2)) // 1st invocation
{
lframe->depth = 1;
lframe->last.frames = lforge->last.frames;
lframe->forge = lforge->forge;
if(!lv2_atom_forge_object(lforge->forge, &lframe->frame[0], lforge->pack.id, lforge->pack.otype))
luaL_error(L, forge_buffer_overflow);
lua_pushvalue(L, lua_upvalueindex(2)); // push cached lforge
}
else // 2nd invocation
{
_lforge_pop_inlined(L, lframe);
lua_pushnil(L); // terminate iterator
}
return 1; // derived forge || nil
}
__realtime static int
_lforge_object_pack(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lforge = lua_touserdata(L, 1);
lforge->pack.otype = luaL_optinteger(L, 2, 0);
lforge->pack.id = luaL_optinteger(L, 3, 0);
_pushupclosure(L, moony, MOONY_UPCLOSURE_OBJECT_PACK, lforge->lheader.cache);
lua_pushvalue(L, 1);
return 2;
}
__realtime static int
_lforge_key(lua_State *L)
{
......@@ -1050,47 +934,6 @@ _lforge_sequence(lua_State *L)
return 1; // derived forge
}
__realtime int
_lforge_sequence_itr(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lframe = lua_touserdata(L, lua_upvalueindex(2));
lforge_t *lforge = lua_touserdata(L, 1);
if(lua_isnil(L, 2)) // 1st invocation
{
lframe->depth = 1;
lframe->last.frames = lforge->last.frames;
lframe->forge = lforge->forge;
if(!lv2_atom_forge_sequence_head(lforge->forge, &lframe->frame[0], lforge->pack.unit))
luaL_error(L, forge_buffer_overflow);
lua_pushvalue(L, lua_upvalueindex(2)); // push cached lforge
}
else // 2nd invocation
{
_lforge_pop_inlined(L, lframe);
lua_pushnil(L); // terminate iterator
}
return 1; // derived forge || nil
}
__realtime static int
_lforge_sequence_pack(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lforge = lua_touserdata(L, 1);
lforge->pack.unit = luaL_optinteger(L, 2, 0);;
_pushupclosure(L, moony, MOONY_UPCLOSURE_SEQUENCE_PACK, lforge->lheader.cache);
lua_pushvalue(L, 1);
return 2;
}
__realtime static int
_lforge_typed(lua_State *L)
{
......@@ -1811,6 +1654,33 @@ _lforge_pop(lua_State *L)
return 1;
}
__realtime int
_lforge_autopop_itr(lua_State *L)
{
if(lua_isnil(L, 2)) // 1st invocation
{
lua_settop(L, 1); // return lforge
}
else // 2nd invocation
{
lforge_t *lforge = lua_touserdata(L, 1);
_lforge_pop_inlined(L, lforge);
lua_pushnil(L); // terminate iterator
}
return 1; // derived forge || nil
}
__realtime static int
_lforge_autopop(lua_State *L)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_COUNT + MOONY_CCLOSURE_FORGE_AUTOPOP_ITR); // _lforge_autopop_itr
lua_pushvalue(L, 1); // lforge
return 2;
}
__realtime static int
_lforge_read(lua_State *L)
{
......@@ -1872,16 +1742,13 @@ const luaL_Reg lforge_mt [] = {
{"atom", _lforge_atom},
{"tuple", _lforge_tuple},
{"tuplePack", _lforge_tuple_pack},
{"object", _lforge_object},
{"objectPack", _lforge_object_pack},
{"key", _lforge_key},
{"vector", _lforge_vector},
{"sequence", _lforge_sequence},
{"sequencePack", _lforge_sequence_pack},
{"frameTime", _lforge_frame_time},
{"beatTime", _lforge_beat_time},
{"time", _lforge_time},
......@@ -1932,6 +1799,7 @@ const luaL_Reg lforge_mt [] = {
{"fillText", _lforge_canvas_fill_text},
{"pop", _lforge_pop},
{"autopop", _lforge_autopop},
// stash
{"read", _lforge_read},
......
......@@ -45,11 +45,7 @@ LV2_Atom_Forge_Ref
_lforge_basic(lua_State *L, int pos, LV2_Atom_Forge *forge, LV2_URID range);
int
_lforge_tuple_itr(lua_State *L);
int
_lforge_object_itr(lua_State *L);
int
_lforge_sequence_itr(lua_State *L);
_lforge_autopop_itr(lua_State *L);
extern const char *forge_buffer_overflow;
......
......@@ -156,6 +156,8 @@ typedef enum _moony_cclosure_t {
MOONY_CCLOSURE_OBJECT_FOREACH,
MOONY_CCLOSURE_SEQUENCE_FOREACH,
MOONY_CCLOSURE_FORGE_AUTOPOP_ITR,
MOONY_CCLOSURE_CLONE,
MOONY_CCLOSURE_WRITE,
MOONY_CCLOSURE_READ,
......@@ -170,10 +172,6 @@ typedef enum _moony_upclosure_t {
MOONY_UPCLOSURE_SEQUENCE_FOREACH,
MOONY_UPCLOSURE_SEQUENCE_MULTIPLEX,
MOONY_UPCLOSURE_TUPLE_PACK,
MOONY_UPCLOSURE_OBJECT_PACK,
MOONY_UPCLOSURE_SEQUENCE_PACK,
MOONY_UPCLOSURE_COUNT
} moony_upclosure_t;
......
......@@ -240,6 +240,7 @@ span.brace {
<li><a href="#forge-tuple">Tuple</a></li>
<li><a href="#forge-vector">Vector</a></li>
<li><a href="#forge-pop">Pop</a></li>
<li><a href="#forge-autopop">Autopop</a></li>
</ul>
</li>
<li><a href="#forge-osc">OSC</a>
......@@ -1323,14 +1324,6 @@ end</code></pre>
<dd>derived container forge object, needs to be finalized with <a href="#forge-pop">Pop</a></dd>
</dl>
<dl>
<dt class="func">forge:sequencePack(unit=0)</dt>
<dt>unit (integer)</dt>
<dd>event time unit as integer URID, defaults to 0, can either be Atom.frameTime or Atom.beatTime</dd>
<dt class="ret">(function)</dt>
<dd>iterator for derived container forge object which is automatically finalized</dd>
</dl>
<pre><code data-ref="forge-sequence">-- Forge Sequence
function stash_tuple(forge)
......@@ -1344,7 +1337,7 @@ function stash_tuple(forge)
seq:frameTime(1):int(13)
seq:pop() -- finalize container
for seq in forge:sequencePack(Atom.beatTime) do -- create iterator for derived container forge object
for seq in forge:sequence(Atom.beatTime):autopop() do -- create iterator for derived container forge object
seq:time(0.0):int(12)
seq:beatTime(1.0):int(13)
end -- finalize container
......@@ -1409,16 +1402,6 @@ end</code></pre>
<dd>derived container forge object, needs to be finalized with <a href="#forge-pop">Pop</a></dd>
</dl>
<dl>
<dt class="func">forge:objectPack(otype=0, id=0)</dt>
<dt>otype (integer)</dt>
<dd>object type as integer URID, defaults to 0</dd>
<dt>id (integer)</dt>
<dd>object ID as integer URID, defaults to 0</dd>
<dt class="ret">(function)</dt>
<dd>iterator for derived container forge object which is automatically finalized</dd>
</dl>
<pre><code data-ref="forge-object">-- Forge Object
local urn = HashMap('urn:moony:xyz')
......@@ -1428,7 +1411,7 @@ function stash_tuple(forge)
obj:key(urn.bar, urn.ctx):long(13) -- with context
obj:pop() -- finalize container
for obj in forge:objectPack(urn.FooBar) do -- create iterator for derived container forge object
for obj in forge:object(urn.FooBar):autopop() do -- create iterator for derived container forge object
obj:key(urn.foo):int(12) -- without context
obj:key(urn.bar, urn.ctx):long(13) -- with context
end -- finalize container
......@@ -1462,12 +1445,6 @@ end</code></pre>
<dd>derived container forge object, needs to be finalized with <a href="#forge-pop">Pop</a></dd>
</dl>
<dl>
<dt class="func">forge:tuplePack()</dt>
<dt class="ret">(function)</dt>
<dd>iterator for derived container forge object which is automatically finalized</dd>
</dl>
<pre><code data-ref="forge-key">-- Forge Tuple
function stash_tuple(forge)
......@@ -1480,7 +1457,7 @@ function stash_tuple(forge)
tup:bool(true)
tup:pop() -- finalize container
for tup in forge:tuplePack() do -- create iterator for derived container forge object
for tup in forge:tuple():autopop() do -- create iterator for derived container forge object
tup:int(12)
tup:long(13)
tup:float(13.5)
......@@ -1534,6 +1511,44 @@ end</code></pre>
<dt class="ret">(userdata)</dt>
<dd>parent container forge object</dd>
</dl>
<pre><code data-ref="forge-pop">-- Pop
function stash(forge)
local tup = forge:tuple()
tup:int(1)
tup:int(2)
tup:pop()
end
function apply(atom)
assert(#atom == 2)
end</code></pre>
</div>
<!-- Forge AutoPop -->
<div class="api-section">
<h3 id="forge-autopop">Autopop</h3>
<p>Finalize any derived container forge object automatically via a for-iterator-construction.</p>
<dl>
<dt class="func">forge:autopop()</dt>
<dt class="ret">(function, userdata)</dt>
<dd>iterator function, parent container forge object</dd>
</dl>
<pre><code data-ref="forge-autopop">-- Autopop
function stash(forge)
for tup in forge:tuple():autopop() do
tup:int(1)
tup:int(2)
end
end
function apply(atom)
assert(#atom == 2)
end</code></pre>
</div>
<!-- Forge OSC -->
......@@ -1666,9 +1681,9 @@ end</code></pre>
<pre><code data-ref="forge-timetag">-- Forge custom OSC arguments
function stash(forge)
for obj in forge:objectPack(OSC.Message) do
for obj in forge:object(OSC.Message):autopop() do
obj:key(OSC.messagePath):string('/custom')
for tup in obj:key(OSC.messageArguments):tuplePack() do
for tup in obj:key(OSC.messageArguments):tuple():autopop() do
-- forge 'i', 'f', 's', 'b' OSC arguments
tup:int(12) -- 'i'nteger
tup:float(1.5) -- 'f'loat
......
......@@ -523,8 +523,8 @@ do
assert(tup ~= forge)
tup:int(1):float(2.0):long(3):double(4.0):pop()
-- produce tuplePack
for tup in forge:frameTime(1):tuplePack() do
-- test autopop
for tup in forge:frameTime(1):tuple():autopop() do
tup:bool(true)
end
end
......@@ -573,7 +573,7 @@ do
assert(#{atom:unpack()} == #{atom:unpack(-100, 100)})
assert(#{atom:unpack(1, 2)} == #{atom:unpack(3, 4)})
-- consume tuplePack
-- consume autopop
atom = seq[2]
assert(atom.type == Atom.Tuple)
assert(#atom == 1)
......@@ -609,8 +609,8 @@ do
assert(obj:pop() == forge)
-- produce objectPack
for obj in forge:frameTime(0):objectPack(otype, id) do
-- test autopop
for obj in forge:frameTime(0):object(otype, id):autopop() do
obj:key(key1):int(14)
end
end
......@@ -637,7 +637,7 @@ do
end
end
-- consume objectPack
-- consume autopop
atom = seq[2]
assert(atom.type == Atom.Object)
assert(atom.id == id)
......@@ -708,9 +708,9 @@ do
forge:message('/color', 'r', 0xff00007f)
-- create OSC message from scratch
for obj in forge:frameTime(6):objectPack(OSC.Message) do
for obj in forge:frameTime(6):object(OSC.Message):autopop() do
obj:key(OSC.messagePath):string('/custom')
for tup in obj:key(OSC.messageArguments):tuplePack() do
for tup in obj:key(OSC.messageArguments):tuple():autopop() do
tup:raw(0) -- nil
tup:impulse()
tup:char(string.byte('c'))
......@@ -1114,8 +1114,8 @@ do
assert(subseq:pop() == forge)
-- produce sequencePack
for seq in forge:frameTime(1):sequencePack() do
-- test autopop
for seq in forge:frameTime(1):sequence():autopop() do
seq:time(10):bool(true)
end
end
......@@ -1133,7 +1133,7 @@ do
assert(atom.body == 1)
end
-- consume sequencePack
-- consume autopop
subseq = seq[2]
assert(subseq.type == Atom.Sequence)
assert(subseq.unit == 0)
......
......@@ -74,7 +74,7 @@ local field_func = token(l.OPERATOR, S('.:')) * token(l.FUNCTION, word_match{
'frameTime', 'beatTime', 'time', 'atom', 'int', 'long', 'float', 'double', 'bool', 'urid', 'string', 'literal', 'uri', 'path',
'chunk', 'midi', 'raw', 'bundle', 'message', 'impulse', 'char', 'rgba', 'timetag', 'tuple', 'tuplePack',
'object', 'objectPack', 'key', 'property', 'vector', 'sequence', 'sequencePack',
'typed', 'get', 'set', 'put', 'patch', 'remove', 'add', 'ack', 'error', 'pop',
'typed', 'get', 'set', 'put', 'patch', 'remove', 'add', 'ack', 'error', 'pop', 'autopop',
'graph', 'beginPath', 'closePath', 'arc', 'curveTo', 'lineTo', 'moveTo', 'rectangle', 'style', 'lineWidth', 'lineDash', 'lineCap', 'lineJoin', 'miterLimig', 'stroke', 'fill', 'clip', 'save', 'restore', 'translate', 'scale', 'rotate', 'reset', 'fontSize', 'fillText',
-- moony common
'foreach', 'unpack', 'clone', 'stash', 'apply', 'register',
......
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