Commit 5418dbd7 authored by Hanspeter Portner's avatar Hanspeter Portner

support iteration over Options interface.

parent b0e506bf
......@@ -7,4 +7,3 @@
* doc: Parameter
* api: simplify forge:vector
* api: simplify forge:set
* api: Options iterator
......@@ -295,18 +295,79 @@ _lnote__index(lua_State *L)
return 1;
}
static const luaL_Reg lnote_mt [] = {
{"__index", _lnote__index},
{"__call", _lnote__index},
{NULL, NULL}
};
__realtime static int
_lnote__call(lua_State *L)
_lopts__index(lua_State *L)
{
lua_settop(L, 2);
lua_gettable(L, -2); // self[uri]
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
const LV2_URID key = luaL_checkinteger(L, 2);
if(moony->opts)
{
for(LV2_Options_Option *opt = moony->opts;
(opt->key != 0) && (opt->value != NULL);
opt++)
{
if(opt->key == key)
{
const LV2_Atom *atom = (const LV2_Atom *)&opt->size;
_latom_body_new(L, atom, opt->value, false);
return 1;
}
}
}
lua_pushnil(L); // not found
return 1;
}
static const luaL_Reg lnote_mt [] = {
{"__index", _lnote__index},
{"__call", _lnote__index},
__realtime static int
_lopts_itr(lua_State *L)
{
LV2_Options_Option **opt_ptr = lua_touserdata(L, lua_upvalueindex(1));
LV2_Options_Option *opt = *opt_ptr;
if( (opt->key != 0) && (opt->value != NULL) )
{
const LV2_Atom *atom = (const LV2_Atom *)&opt->size;
lua_pushinteger(L, opt->key);
_latom_body_new(L, atom, opt->value, false);
*opt_ptr = opt + 1;
return 2;
}
lua_pushnil(L);
return 1;
}
__realtime static int
_lopts__pairs(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
if(moony->opts)
{
LV2_Options_Option **opt_ptr = lua_newuserdata(L, sizeof(LV2_Options_Option **));
*opt_ptr = moony->opts;
lua_pushcclosure(L, _lopts_itr, 1);
return 1;
}
lua_pushnil(L);
return 1;
}
static const luaL_Reg lopts_mt [] = {
{"__index", _lopts__index},
{"__call", _lopts__index},
{"__pairs", _lopts__pairs},
{NULL, NULL}
};
......@@ -407,31 +468,6 @@ _log(lua_State *L)
return 0;
}
__realtime static int
_options(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
const LV2_URID key = luaL_checkinteger(L, 1);
if(moony->opts)
{
for(LV2_Options_Option *opt = moony->opts;
(opt->key != 0) && (opt->value != NULL);
opt++)
{
if(opt->key == key)
{
const LV2_Atom *atom = (const LV2_Atom *)&opt->size;
_latom_body_new(L, atom, opt->value, false);
return 1;
}
}
}
lua_pushnil(L); // not found
return 1;
}
__realtime LV2_Atom_Forge_Ref
_sink_rt(LV2_Atom_Forge_Sink_Handle handle, const void *buf, uint32_t size)
{
......@@ -1404,6 +1440,30 @@ moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L)
lua_setmetatable(L, -2);
lua_setglobal(L, "Unmap");
// Note
lua_newtable(L);
lua_newtable(L);
lua_pushlightuserdata(L, moony); // @ upvalueindex 1
luaL_setfuncs(L, lnote_mt, 1);
_protect_metatable(L, -1);
lua_setmetatable(L, -2);
lua_setglobal(L, "Note");
// lv2.opts
lua_newtable(L);
lua_newtable(L);
lua_pushlightuserdata(L, moony); // @ upvalueindex 1
luaL_setfuncs(L, lopts_mt, 1);
_protect_metatable(L, -1);
lua_setmetatable(L, -2);
lua_setglobal(L, "Options");
// overwrite print function with LV2 log
lua_pushlightuserdata(L, moony); // @ upvalueindex 1
lua_pushlightuserdata(L, vm); // @ upvalueindex 2
lua_pushcclosure(L, _log, 2);
lua_setglobal(L, "print");
// lv2.hash
lua_pushlightuserdata(L, moony); // @ upvalueindex 1
lua_pushcclosure(L, _lhash_map, 1);
......@@ -1432,12 +1492,6 @@ moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L)
urid; \
})
lua_newtable(L);
{
SET_MAP(L, LV2_CORE__, ControlPort);
}
lua_setglobal(L, "State");
lua_newtable(L);
{
//SET_MAP(L, LV2_ATOM__, Blank); // is depracated
......@@ -1480,15 +1534,6 @@ moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L)
}
lua_setglobal(L, "MIDI");
// Note
lua_newtable(L);
lua_newtable(L);
lua_pushlightuserdata(L, moony); // @ upvalueindex 1
luaL_setfuncs(L, lnote_mt, 1);
_protect_metatable(L, -1);
lua_setmetatable(L, -2);
lua_setglobal(L, "Note");
lua_newtable(L);
{
SET_MAP(L, LV2_TIME__, Position);
......@@ -1704,17 +1749,6 @@ moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L)
lua_newtable(L);
lua_rawseti(L, LUA_REGISTRYINDEX, UDATA_OFFSET + MOONY_UDATA_STASH);
// overwrite print function with LV2 log
lua_pushlightuserdata(L, moony); // @ upvalueindex 1
lua_pushlightuserdata(L, vm); // @ upvalueindex 2
lua_pushcclosure(L, _log, 2);
lua_setglobal(L, "print");
// Options
lua_pushlightuserdata(L, moony); // @ upvalueindex 1
lua_pushcclosure(L, _options, 1);
lua_setglobal(L, "Options");
// MIDIResponder metatable
luaL_newmetatable(L, "lmidiresponder");
lua_pushlightuserdata(L, moony); // @ upvalueindex 1
......
......@@ -748,7 +748,7 @@ end</code></pre>
function.</p>
<dl>
<dt class="func">function Map(URI)</dt>
<dt class="func">Map:__call(URI) | Map(URI) | Map:__index(URI) | Map[URI]</dt>
<dt>URI (string)</dt>
<dd>URI to be mapped</dd>
<dt class="ret">(integer)</dt>
......@@ -770,11 +770,11 @@ local bar_urid = Map[prefix .. 'bar']</code></pre>
function.</p>
<dl>
<dt class="func">function Unmap(URID)</dt>
<dt class="func">Unmap:__call(URID) | Unmap(URID) | Unmap:__index(URID) | Unmap[URID]</dt>
<dt>URID (integer)</dt>
<dd>URID to be unmapped</dd>
<dt class="ret">(string)</dt>
<dd>unmapped URi</dd>
<dd>unmapped URI</dd>
</dl>
<pre><code data-ref="urid-unmap">-- Unmap can be indexed or called as function
......@@ -803,7 +803,7 @@ assert(prefix .. 'bar' == bar_uri)</code></pre>
<a href="#responder-state">StateResponder</a>.</p>
<dl>
<dt class="func">function HashMap(prefix)</dt>
<dt class="func">HashMap(prefix)</dt>
<dt>prefix (string)</dt>
<dd>prefix string to be appended to</dd>
<dt class="ret">(table)</dt>
......@@ -828,7 +828,7 @@ assert(hashmap.bar == bar_urid)</code></pre>
and time.</p>
<dl>
<dt class="func">function VoiceMap()</dt>
<dt class="func">VoiceMap()</dt>
<dt class="ret">(integer)</dt>
<dd>unique integer ID</dd>
</dl>
......@@ -3009,24 +3009,34 @@ assert(io.body == 13)</code></pre>
If the host exports those values, they may be queried via the options table.</p>
<dl>
<dt class="func">Options:__call(key)</dt>
<dt>key (integer)</dt>
<dt class="func">Options:__call(URID) | Options(URID) | Options:__index(URID) | Options[URID]</dt>
<dt>URID (integer)</dt>
<dd>key to index options table with as integer URID, e.g. valid keys are:
Param.sampleRate, Buf_Size.sequenceSize, Buf_Size.minBlockLength, Buf_Size.maxBlockLength, Ui.updateRate</dd>
<dt class="ret">(userdata)</dt>
<dd>value of indexed key as atom object</dd>
</dl>
<dl>
<dt class="func">Options:__pairs()</dt>
<dt class="ret">(integer | userdata)</dt>
<dd>iterates over all options, returning option key and atom userdata.</dd>
</dl>
<pre><code data-ref="options">-- Options
-- sample rate is always available
local sampleRate = Options(Param.sampleRate)
assert(sampleRate.body == 48000)
-- only available if exported by host
local sequenceSize = Options(Buf_Size.sequenceSize)
local minBlockLength = Options(Buf_Size.minBlockLength)
local maxBlockLength = Options(Buf_Size.maxBlockLength)</code></pre>
local sampleRate = Options[Param.sampleRate]
assert(sampleRate.body == 48000)
local sequenceSize = Options[Buf_Size.sequenceSize]
local minBlockLength = Options[Buf_Size.minBlockLength]
local maxBlockLength = Options[Buf_Size.maxBlockLength]
local updateRate = Options(Ui.updateRate)
for urid, atom in pairs(Options) do
print(Unmap[urid], atom)
end</code></pre>
</div>
<!-- Responder -->
......
......@@ -678,7 +678,7 @@ local chord = {0, 3, 7, 11} -- table with chord note offsets
local offset = 0.1 -- time offset between notes in seconds
local schedule = {} -- table to store Note events
local dur = math.floor(offset * Options(Param.sampleRate).body) -- time offset in frames
local dur = math.floor(offset * Options[Param.sampleRate].body) -- time offset in frames
-- compare function to sort scheduled messages according to frame time
local function cmp(a, b)
......
......@@ -1261,10 +1261,15 @@ end
-- Options
print('[test] Options')
do
assert(Options(Param.sampleRate).body == 48000)
assert(Options(Buf_Size.minBlockLength) == nil)
assert(Options(Buf_Size.maxBlockLength) == nil)
assert(Options[Param.sampleRate].body == 48000)
assert(Options[Buf_Size.minBlockLength] == nil)
assert(Options[Buf_Size.maxBlockLength] == nil)
assert(Options(Buf_Size.sequenceSize) == nil)
for k, v in pairs(Options) do
assert(k == Param.sampleRate)
assert(v.body == 48000)
end
end
-- Patch
......
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