Commit 7131c9f8 authored by Hanspeter Portner's avatar Hanspeter Portner

api: add support for patch:Insert/Copy/Move/Insert.

* forge:insert/copy/move/insert
* Patch:Insert/accept/context
parent 8662dee3
Pipeline #8047788 passed with stages
in 14 minutes and 48 seconds
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
* api: CanvasResponder * api: CanvasResponder
=== High priority === High priority
* api: simplify forge:set * properly catch forge errors in 'notify'
...@@ -44,6 +44,18 @@ ...@@ -44,6 +44,18 @@
# define LV2_PATCH__Copy LV2_PATCH_PREFIX "Copy" # define LV2_PATCH__Copy LV2_PATCH_PREFIX "Copy"
#endif #endif
#ifndef LV2_PATCH__Insert
# define LV2_PATCH__Insert LV2_PATCH_PREFIX "Insert"
#endif
#ifndef LV2_PATCH__accept
# define LV2_PATCH__accept LV2_PATCH_PREFIX "accept"
#endif
#ifndef LV2_PATCH__context
# define LV2_PATCH__context LV2_PATCH_PREFIX "context"
#endif
#ifndef LV2_UNITS__midiController #ifndef LV2_UNITS__midiController
# define LV2_UNITS__midiController LV2_UNITS_PREFIX "midiController" # define LV2_UNITS__midiController LV2_UNITS_PREFIX "midiController"
#endif #endif
...@@ -1264,6 +1276,10 @@ moony_init(moony_t *moony, const char *subject, double sample_rate, ...@@ -1264,6 +1276,10 @@ moony_init(moony_t *moony, const char *subject, double sample_rate,
moony->uris.patch.sequence = moony->map->map(moony->map->handle, LV2_PATCH__sequenceNumber); moony->uris.patch.sequence = moony->map->map(moony->map->handle, LV2_PATCH__sequenceNumber);
moony->uris.patch.error = moony->map->map(moony->map->handle, LV2_PATCH__Error); moony->uris.patch.error = moony->map->map(moony->map->handle, LV2_PATCH__Error);
moony->uris.patch.ack = moony->map->map(moony->map->handle, LV2_PATCH__Ack); moony->uris.patch.ack = moony->map->map(moony->map->handle, LV2_PATCH__Ack);
moony->uris.patch.delete = moony->map->map(moony->map->handle, LV2_PATCH__Delete);
moony->uris.patch.copy = moony->map->map(moony->map->handle, LV2_PATCH__Copy);
moony->uris.patch.move = moony->map->map(moony->map->handle, LV2_PATCH__Move);
moony->uris.patch.insert = moony->map->map(moony->map->handle, LV2_PATCH__Insert);
moony->uris.rdfs_label = moony->map->map(moony->map->handle, RDFS__label); moony->uris.rdfs_label = moony->map->map(moony->map->handle, RDFS__label);
moony->uris.rdfs_range = moony->map->map(moony->map->handle, RDFS__range); moony->uris.rdfs_range = moony->map->map(moony->map->handle, RDFS__range);
...@@ -1599,14 +1615,17 @@ moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L) ...@@ -1599,14 +1615,17 @@ moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L)
SET_MAP(L, LV2_PATCH__, Get); SET_MAP(L, LV2_PATCH__, Get);
SET_MAP(L, LV2_PATCH__, Message); SET_MAP(L, LV2_PATCH__, Message);
SET_MAP(L, LV2_PATCH__, Move); SET_MAP(L, LV2_PATCH__, Move);
SET_MAP(L, LV2_PATCH__, Insert);
SET_MAP(L, LV2_PATCH__, Patch); SET_MAP(L, LV2_PATCH__, Patch);
SET_MAP(L, LV2_PATCH__, Post); SET_MAP(L, LV2_PATCH__, Post);
SET_MAP(L, LV2_PATCH__, Put); SET_MAP(L, LV2_PATCH__, Put);
SET_MAP(L, LV2_PATCH__, Request); SET_MAP(L, LV2_PATCH__, Request);
SET_MAP(L, LV2_PATCH__, Response); SET_MAP(L, LV2_PATCH__, Response);
SET_MAP(L, LV2_PATCH__, Set); SET_MAP(L, LV2_PATCH__, Set);
SET_MAP(L, LV2_PATCH__, accept);
SET_MAP(L, LV2_PATCH__, add); SET_MAP(L, LV2_PATCH__, add);
SET_MAP(L, LV2_PATCH__, body); SET_MAP(L, LV2_PATCH__, body);
SET_MAP(L, LV2_PATCH__, context);
SET_MAP(L, LV2_PATCH__, destination); SET_MAP(L, LV2_PATCH__, destination);
SET_MAP(L, LV2_PATCH__, property); SET_MAP(L, LV2_PATCH__, property);
SET_MAP(L, LV2_PATCH__, readable); SET_MAP(L, LV2_PATCH__, readable);
......
...@@ -1306,6 +1306,144 @@ _lforge_error(lua_State *L) ...@@ -1306,6 +1306,144 @@ _lforge_error(lua_State *L)
return 1; return 1;
} }
__realtime static int
_lforge_delete(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lforge = lua_touserdata(L, 1);
const LV2_URID subject = luaL_checkinteger(L, 2);
const int32_t sequence_num = luaL_optinteger(L, 3, 0);
LV2_Atom_Forge_Frame frame;
if(!lv2_atom_forge_object(lforge->forge, &frame, 0, moony->uris.patch.delete))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.subject))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_urid(lforge->forge, subject))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.sequence))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_int(lforge->forge, sequence_num))
luaL_error(L, forge_buffer_overflow);
lv2_atom_forge_pop(lforge->forge, &frame);
lua_settop(L, 1);
return 1;
}
__realtime static int
_lforge_copy(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lforge = lua_touserdata(L, 1);
const LV2_URID subject = luaL_checkinteger(L, 2);
const LV2_URID destination = luaL_checkinteger(L, 3);
const int32_t sequence_num = luaL_optinteger(L, 4, 0);
LV2_Atom_Forge_Frame frame;
if(!lv2_atom_forge_object(lforge->forge, &frame, 0, moony->uris.patch.copy))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.subject))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_urid(lforge->forge, subject))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.destination))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_urid(lforge->forge, destination))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.sequence))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_int(lforge->forge, sequence_num))
luaL_error(L, forge_buffer_overflow);
lv2_atom_forge_pop(lforge->forge, &frame);
lua_settop(L, 1);
return 1;
}
__realtime static int
_lforge_move(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lforge = lua_touserdata(L, 1);
const LV2_URID subject = luaL_checkinteger(L, 2);
const LV2_URID destination = luaL_checkinteger(L, 3);
const int32_t sequence_num = luaL_optinteger(L, 4, 0);
LV2_Atom_Forge_Frame frame;
if(!lv2_atom_forge_object(lforge->forge, &frame, 0, moony->uris.patch.move))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.subject))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_urid(lforge->forge, subject))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.destination))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_urid(lforge->forge, destination))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.sequence))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_int(lforge->forge, sequence_num))
luaL_error(L, forge_buffer_overflow);
lv2_atom_forge_pop(lforge->forge, &frame);
lua_settop(L, 1);
return 1;
}
__realtime static int
_lforge_insert(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lforge = lua_touserdata(L, 1);
const LV2_URID subject = luaL_optinteger(L, 2, 0);
const LV2_URID sequence_num = luaL_optinteger(L, 3, 0);
lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
lframe->depth = 2;
lframe->last.frames = lforge->last.frames;
lframe->forge = lforge->forge;
lua_pushvalue(L, 1); // lforge
lua_setuservalue(L, -2); // store parent as uservalue
if(!lv2_atom_forge_object(lforge->forge, &lframe->frame[0], 0, moony->uris.patch.insert))
luaL_error(L, forge_buffer_overflow);
if(subject) // is optional
{
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.subject))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_urid(lforge->forge, subject))
luaL_error(L, forge_buffer_overflow);
}
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.sequence))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_int(lforge->forge, sequence_num))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.body))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_object(lforge->forge, &lframe->frame[1], 0, 0))
luaL_error(L, forge_buffer_overflow);
return 1; // derived forge
}
__realtime static int __realtime static int
_lforge_canvas_graph(lua_State *L) _lforge_canvas_graph(lua_State *L)
{ {
...@@ -1824,6 +1962,10 @@ const luaL_Reg lforge_mt [] = { ...@@ -1824,6 +1962,10 @@ const luaL_Reg lforge_mt [] = {
{"add", _lforge_add}, {"add", _lforge_add},
{"ack", _lforge_ack}, {"ack", _lforge_ack},
{"error", _lforge_error}, {"error", _lforge_error},
{"delete", _lforge_delete},
{"copy", _lforge_copy},
{"move", _lforge_move},
{"insert", _lforge_insert},
// canvas // canvas
{"graph", _lforge_canvas_graph}, {"graph", _lforge_canvas_graph},
......
...@@ -211,6 +211,10 @@ struct _patch_t { ...@@ -211,6 +211,10 @@ struct _patch_t {
LV2_URID sequence; LV2_URID sequence;
LV2_URID error; LV2_URID error;
LV2_URID ack; LV2_URID ack;
LV2_URID delete;
LV2_URID copy;
LV2_URID move;
LV2_URID insert;
}; };
struct _moony_t { struct _moony_t {
......
...@@ -213,6 +213,10 @@ pre { ...@@ -213,6 +213,10 @@ pre {
<li><a href="#forge-put">Put</a></li> <li><a href="#forge-put">Put</a></li>
<li><a href="#forge-ack">Ack</a></li> <li><a href="#forge-ack">Ack</a></li>
<li><a href="#forge-error">Error</a></li> <li><a href="#forge-error">Error</a></li>
<li><a href="#forge-delete">Delete</a></li>
<li><a href="#forge-copy">Copy</a></li>
<li><a href="#forge-move">Move</a></li>
<li><a href="#forge-insert">Insert</a></li>
</ul> </ul>
</li> </li>
<li><a href="#forge-canvas">Canvas</a> <li><a href="#forge-canvas">Canvas</a>
...@@ -1922,6 +1926,114 @@ function stash(forge) ...@@ -1922,6 +1926,114 @@ function stash(forge)
end</code></pre> end</code></pre>
</div> </div>
<!-- Forge Delete -->
<div class="api-section">
<h3 id="forge-delete">Delete</h3>
<p>Forge a delete patch atom, e.g. an atom object of type Patch.Delete.</p>
<dl>
<dt class="func">forge:delete(subject, sequenceNumber=0)</dt>
<dt>subject (integer)</dt>
<dd>patch subject as integer URID</dd>
<dt>sequenceNumber (integer)</dt>
<dd>patch sequence number as integer, defaults to 0</dd>
<dt class="ret">(userdata)</dt>
<dd>self forge object</dd>
</dl>
<pre><code data-ref="forge-delete">-- Forge Delete
local urn = HashMap('urn:moony:xzy')
function stash(forge)
forge:delete(urn.subj, 1002) -- with sequence number
end</code></pre>
</div>
<!-- Forge Copy -->
<div class="api-section">
<h3 id="forge-copy">Copy</h3>
<p>Forge a copy patch atom, e.g. an atom object of type Patch.Copy.</p>
<dl>
<dt class="func">forge:copy(subject, destination, sequenceNumber=0)</dt>
<dt>subject (integer)</dt>
<dd>patch subject as integer URID</dd>
<dt>destination (integer)</dt>
<dd>patch destination as integer URID</dd>
<dt>sequenceNumber (integer)</dt>
<dd>patch sequence number as integer, defaults to 0</dd>
<dt class="ret">(userdata)</dt>
<dd>self forge object</dd>
</dl>
<pre><code data-ref="forge-copy">-- Forge Copy
local urn = HashMap('urn:moony:xzy')
function stash(forge)
forge:copy(urn.subj, urn.dest, 1002) -- with sequence number
end</code></pre>
</div>
<!-- Forge Move -->
<div class="api-section">
<h3 id="forge-move">Move</h3>
<p>Forge a move patch atom, e.g. an atom object of type Patch.Move.</p>
<dl>
<dt class="func">forge:move(subject, destination, sequenceNumber=0)</dt>
<dt>subject (integer)</dt>
<dd>patch subject as integer URID</dd>
<dt>destination (integer)</dt>
<dd>patch destination as integer URID</dd>
<dt>sequenceNumber (integer)</dt>
<dd>patch sequence number as integer, defaults to 0</dd>
<dt class="ret">(userdata)</dt>
<dd>self forge object</dd>
</dl>
<pre><code data-ref="forge-move">-- Forge Move
local urn = HashMap('urn:moony:xzy')
function stash(forge)
forge:move(urn.subj, urn.dest, 1002) -- with sequence number
end</code></pre>
</div>
<!-- Forge Insert -->
<div class="api-section">
<h3 id="forge-insert">Insert</h3>
<p>Forge a patch insert atom, e.g. an atom object of type Patch.Insert.</p>
<dl>
<dt class="func">forge:insert(subject=0, sequenceNumber=0)</dt>
<dt>subject (integer)</dt>
<dd>patch subject as integer URID, defaults to 0</dd>
<dt>sequenceNumber (integer)</dt>
<dd>patch sequence number as integer, defaults to 0</dd>
<dt class="ret">(userdata)</dt>
<dd>derived container forge object, needs to be finalized with <a href="#forge-pop">Pop</a></dd>
</dl>
<pre><code data-ref="forge-insert">-- Forge Insert
local urn = HashMap('urn:moony:xzy')
function stash_tuple(forge)
local insert = forge:insert() -- without subject and sequence number
insert:key(urn.foo):int(12)
insert:key(urn.bar):float(12.5)
insert:pop()
insert= forge:insert(urn.subj, 1002) -- with subject and sequence number
insert:key(urn.foo):int(12)
insert:key(urn.bar):float(12.5)
insert:pop()
end</code></pre>
</div>
<!-- Forge Canvas --> <!-- Forge Canvas -->
<div class="api-section"> <div class="api-section">
<h2 id="forge-canvas">Canvas</h2> <h2 id="forge-canvas">Canvas</h2>
...@@ -4553,6 +4665,7 @@ assert(Patch.Error == ctx.patch.Error) ...@@ -4553,6 +4665,7 @@ assert(Patch.Error == ctx.patch.Error)
assert(Patch.Get == ctx.patch.Get) assert(Patch.Get == ctx.patch.Get)
assert(Patch.Message == ctx.patch.Message) assert(Patch.Message == ctx.patch.Message)
assert(Patch.Move == ctx.patch.Move) assert(Patch.Move == ctx.patch.Move)
assert(Patch.Insert == ctx.patch.Insert)
assert(Patch.Patch == ctx.patch.Patch) assert(Patch.Patch == ctx.patch.Patch)
assert(Patch.Post == ctx.patch.Post) assert(Patch.Post == ctx.patch.Post)
assert(Patch.Put == ctx.patch.Put) assert(Patch.Put == ctx.patch.Put)
...@@ -4560,7 +4673,9 @@ assert(Patch.Request == ctx.patch.Request) ...@@ -4560,7 +4673,9 @@ assert(Patch.Request == ctx.patch.Request)
assert(Patch.Response == ctx.patch.Response) assert(Patch.Response == ctx.patch.Response)
assert(Patch.Set == ctx.patch.Set) assert(Patch.Set == ctx.patch.Set)
assert(Patch.add == ctx.patch.add) assert(Patch.add == ctx.patch.add)
assert(Patch.accept == ctx.patch.accept)
assert(Patch.body == ctx.patch.body) assert(Patch.body == ctx.patch.body)
assert(Patch.context == ctx.patch.context)
assert(Patch.destination == ctx.patch.destination) assert(Patch.destination == ctx.patch.destination)
assert(Patch.property == ctx.patch.property) assert(Patch.property == ctx.patch.property)
assert(Patch.readable == ctx.patch.readable) assert(Patch.readable == ctx.patch.readable)
......
...@@ -505,6 +505,7 @@ local patch_lib = lib_const('Patch', { ...@@ -505,6 +505,7 @@ local patch_lib = lib_const('Patch', {
'Get', 'Get',
'Message', 'Message',
'Move', 'Move',
'Insert',
'Patch', 'Patch',
'Post', 'Post',
'Put', 'Put',
...@@ -512,7 +513,9 @@ local patch_lib = lib_const('Patch', { ...@@ -512,7 +513,9 @@ local patch_lib = lib_const('Patch', {
'Response', 'Response',
'Set', 'Set',
'add', 'add',
'accept',
'body', 'body',
'context',
'destination', 'destination',
'property', 'property',
'readable', 'readable',
...@@ -680,6 +683,10 @@ local field_func = token(T.OPERATOR, S('.:')) * token(T.FUNCTION, word_match(ord ...@@ -680,6 +683,10 @@ local field_func = token(T.OPERATOR, S('.:')) * token(T.FUNCTION, word_match(ord
'add', 'add',
'ack', 'ack',
'error', 'error',
'copy',
'move',
'insert',
'delete',
-- moony forge pop -- moony forge pop
'pop', 'pop',
'autopop', 'autopop',
......
...@@ -1294,6 +1294,7 @@ end ...@@ -1294,6 +1294,7 @@ end
print('[test] Patch') print('[test] Patch')
do do
local subject = Map['http://open-music-kontrollers.ch/lv2/moony#subject'] local subject = Map['http://open-music-kontrollers.ch/lv2/moony#subject']
local destination = Map['http://open-music-kontrollers.ch/lv2/moony#destination']
local property = Map['http://open-music-kontrollers.ch/lv2/moony#property'] local property = Map['http://open-music-kontrollers.ch/lv2/moony#property']
local access = Patch.writable local access = Patch.writable
local rtid = Blank() & 0x7fffffff local rtid = Blank() & 0x7fffffff
...@@ -1336,10 +1337,20 @@ do ...@@ -1336,10 +1337,20 @@ do
forge:time(7):ack(subject, rtid) forge:time(7):ack(subject, rtid)
forge:time(8):error(subject, rtid) forge:time(8):error(subject, rtid)
forge:time(9):delete(subject, rtid)
forge:time(10):copy(subject, destination, rtid)
forge:time(11):move(subject, destination, rtid)
local insert = forge:time(12):insert(subject, rtid)
insert:key(property):string('insertion')
insert:pop()
end end
local function consumer(seq) local function consumer(seq)
assert(#seq == 9) assert(#seq == 13)
local get = seq[1] local get = seq[1]
assert(get.type == Atom.Object) assert(get.type == Atom.Object)
...@@ -1423,6 +1434,40 @@ do ...@@ -1423,6 +1434,40 @@ do
assert(#err == 2) assert(#err == 2)
assert(err[Patch.subject].body == subject) assert(err[Patch.subject].body == subject)
assert(err[Patch.sequenceNumber].body == rtid) assert(err[Patch.sequenceNumber].body == rtid)
local err = seq[10]
assert(err.type == Atom.Object)
assert(err.otype == Patch.Delete)
assert(#err == 2)
assert(err[Patch.subject].body == subject)
assert(err[Patch.sequenceNumber].body == rtid)
local err = seq[11]
assert(err.type == Atom.Object)
assert(err.otype == Patch.Copy)
assert(#err == 3)
assert(err[Patch.subject].body == subject)
assert(err[Patch.destination].body == destination)
assert(err[Patch.sequenceNumber].body == rtid)
local err = seq[12]
assert(err.type == Atom.Object)
assert(err.otype == Patch.Move)
assert(#err == 3)
assert(err[Patch.subject].body == subject)
assert(err[Patch.destination].body == destination)
assert(err[Patch.sequenceNumber].body == rtid)
local put = seq[13]
assert(put.type == Atom.Object)
assert(put.otype == Patch.Insert)
assert(#put == 3)
assert(put[Patch.subject].body == subject)
assert(put[Patch.sequenceNumber].body == rtid)
local body = put[Patch.body]
assert(body)
assert(#body == 1)
assert(body[property].body == 'insertion')
end end
test(producer, consumer) test(producer, consumer)
......
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