api_forge.c 55.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright (c) 2015 Hanspeter Portner (dev@open-music-kontrollers.ch)
 *
 * This is free software: you can redistribute it and/or modify
 * it under the terms of the Artistic License 2.0 as published by
 * The Perl Foundation.
 *
 * This source is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * Artistic License 2.0 for more details.
 *
 * You should have received a copy of the Artistic License 2.0
 * along the source as a COPYING file. If not, obtain it from
 * http://www.perlfoundation.org/artistic_license_2_0.
 */

18 19
#include <math.h>

20 21
#include <api_atom.h>
#include <api_forge.h>
Hanspeter Portner's avatar
Hanspeter Portner committed
22
#include <api_stash.h>
23

24 25
#include <osc.lv2/forge.h>

26
__realtime static void
27 28 29 30 31 32 33 34 35 36 37 38
_lforge_pop_inlined(lua_State *L, lforge_t *lforge)
{
	for(int i=lforge->depth; i>0; i--)
	{
		if(&lforge->frame[i-1] == lforge->forge->stack) // intercept assert
			lv2_atom_forge_pop(lforge->forge, &lforge->frame[i-1]);
		else
			luaL_error(L, "forge frame mismatch");
	}
	lforge->depth = 0; // reset depth
}

39
__realtime static inline int
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
_lforge_frame_time_inlined(lua_State *L, lforge_t *lforge, int64_t frames)
{
	if(frames >= lforge->last.frames)
	{
		if(!lv2_atom_forge_frame_time(lforge->forge, frames))
			luaL_error(L, forge_buffer_overflow);
		lforge->last.frames = frames;

		lua_settop(L, 1);
		return 1;
	}

	return luaL_error(L, "invalid frame time, must not decrease");
}

55
__realtime static int
56 57
_lforge_frame_time(lua_State *L)
{
58
	lforge_t *lforge = lua_touserdata(L, 1);
59 60 61 62 63
	int64_t frames = luaL_checkinteger(L, 2);

	return _lforge_frame_time_inlined(L, lforge, frames);
}

64
__realtime static inline int
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
_lforge_beat_time_inlined(lua_State *L, lforge_t *lforge, double beats)
{
	if(beats >= lforge->last.beats)
	{
		if(!lv2_atom_forge_beat_time(lforge->forge, beats))
			luaL_error(L, forge_buffer_overflow);
		lforge->last.beats = beats;

		lua_settop(L, 1);
		return 1;
	}

	return luaL_error(L, "invalid beat time, must not decrease");
}

80
__realtime static int
81 82
_lforge_beat_time(lua_State *L)
{
83
	lforge_t *lforge = lua_touserdata(L, 1);
84 85 86 87 88
	double beats = luaL_checknumber(L, 2);

	return _lforge_beat_time_inlined(L, lforge, beats);
}

89
__realtime static int
90 91
_lforge_time(lua_State *L)
{
92
	lforge_t *lforge = lua_touserdata(L, 1);
93 94 95 96 97 98 99 100 101

	if(lua_isinteger(L, 2))
	{
		int64_t frames = lua_tointeger(L, 2);

		return _lforge_frame_time_inlined(L, lforge, frames);
	}
	else if(lua_isnumber(L, 2))
	{
102
		double beats = lua_tonumber(L, 2);
103 104 105 106 107 108 109

		return _lforge_beat_time_inlined(L, lforge, beats);
	}

	return luaL_error(L, "integer or number expected");
}

110
__realtime static int
111 112
_lforge_atom(lua_State *L)
{
113
	lforge_t *lforge = lua_touserdata(L, 1);
114
	latom_t *latom = luaL_checkudata(L, 2, "latom");
115
	const uint32_t size = latom->atom->size;
116

117
	if(!lv2_atom_forge_atom(lforge->forge, size, latom->atom->type))
118
		luaL_error(L, forge_buffer_overflow);
119 120 121
	if(!lv2_atom_forge_raw(lforge->forge, latom->body.raw, size))
		luaL_error(L, forge_buffer_overflow);
	lv2_atom_forge_pad(lforge->forge, size);
122 123 124 125 126

	lua_settop(L, 1);
	return 1;
}

127
__realtime static inline LV2_Atom_Forge_Ref
128 129 130 131 132 133
_lforge_basic_int(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	int32_t val = luaL_checkinteger(L, pos);
	return lv2_atom_forge_int(forge, val);
}

134
__realtime static inline LV2_Atom_Forge_Ref
135 136 137 138 139 140
_lforge_basic_long(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	int64_t val = luaL_checkinteger(L, pos);
	return lv2_atom_forge_long(forge, val);
}

141
__realtime static inline LV2_Atom_Forge_Ref
142 143 144 145 146 147
_lforge_basic_float(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	float val = luaL_checknumber(L, pos);
	return lv2_atom_forge_float(forge, val);
}

148
__realtime static inline LV2_Atom_Forge_Ref
149 150 151 152 153 154
_lforge_basic_double(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	double val = luaL_checknumber(L, pos);
	return lv2_atom_forge_double(forge, val);
}

155
__realtime static inline LV2_Atom_Forge_Ref
156 157 158 159 160 161
_lforge_basic_bool(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	int32_t val = lua_toboolean(L, pos);
	return lv2_atom_forge_bool(forge, val);
}

162
__realtime static inline LV2_Atom_Forge_Ref
163 164 165 166 167 168
_lforge_basic_urid(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	LV2_URID val = luaL_checkinteger(L, pos);
	return lv2_atom_forge_urid(forge, val);
}

169
__realtime static inline LV2_Atom_Forge_Ref
170 171 172 173 174 175 176
_lforge_basic_string(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	size_t len;
	const char *val = luaL_checklstring(L, pos, &len);
	return lv2_atom_forge_string(forge, val, len);
}

177
__realtime static inline LV2_Atom_Forge_Ref
178 179 180 181 182 183 184
_lforge_basic_uri(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	size_t len;
	const char *val = luaL_checklstring(L, pos, &len);
	return lv2_atom_forge_uri(forge, val, len);
}

185
__realtime static inline LV2_Atom_Forge_Ref
186 187 188 189 190 191 192
_lforge_basic_path(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	size_t len;
	const char *val = luaL_checklstring(L, pos, &len);
	return lv2_atom_forge_path(forge, val, len);
}

193
__realtime static inline LV2_Atom_Forge_Ref
194 195 196 197 198 199 200
_lforge_basic_literal(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	size_t len;
	const char *val = luaL_checklstring(L, pos, &len);
	return lv2_atom_forge_literal(forge, val, len, 0, 0); //TODO context, lang
}

201
__realtime static int
202 203 204 205
_lforge_basic_bytes(lua_State *L, int pos, LV2_Atom_Forge *forge, LV2_URID type)
{
	int ltype = lua_type(L, pos);

206 207 208 209 210 211 212 213 214 215 216
	if(ltype == LUA_TSTRING)
	{
		size_t size;
		const char *str = lua_tolstring(L, pos, &size);
		if(!lv2_atom_forge_atom(forge, size, type))
			luaL_error(L, forge_buffer_overflow);
		if(!lv2_atom_forge_raw(forge, str, size))
			luaL_error(L, forge_buffer_overflow);
		lv2_atom_forge_pad(forge, size);
	}
	else if(ltype == LUA_TTABLE)
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
	{
		int size = lua_rawlen(L, pos);
		if(!lv2_atom_forge_atom(forge, size, type))
			luaL_error(L, forge_buffer_overflow);
		for(int i=1; i<=size; i++)
		{
			lua_rawgeti(L, pos, i);
			uint8_t byte = luaL_checkinteger(L, -1);
			lua_pop(L, 1);
			if(!lv2_atom_forge_raw(forge, &byte, 1))
				luaL_error(L, forge_buffer_overflow);
		}
		lv2_atom_forge_pad(forge, size);
	}
	else if(luaL_testudata(L, pos, "latom")) //to convert between chunk <-> midi
	{
		latom_t *latom = lua_touserdata(L, pos);
234
		const uint32_t size = latom->atom->size;
235 236 237 238 239 240
		if(!lv2_atom_forge_atom(forge, size, type))
			luaL_error(L, forge_buffer_overflow);
		if(!lv2_atom_forge_raw(forge, latom->body.raw, size))
			luaL_error(L, forge_buffer_overflow);
		lv2_atom_forge_pad(forge, size);
	}
241 242
	else // bytes as individual function arguments
	{
243
		const uint32_t size = lua_gettop(L) - (pos - 1);
244 245 246 247 248 249 250 251 252 253
		if(!lv2_atom_forge_atom(forge, size, type))
			luaL_error(L, forge_buffer_overflow);
		for(unsigned i=0; i<size; i++)
		{
			const uint8_t byte = luaL_checkinteger(L, pos + i);
			if(!lv2_atom_forge_raw(forge, &byte, 1))
				luaL_error(L, forge_buffer_overflow);
		}
		lv2_atom_forge_pad(forge, size);
	}
254 255 256 257

	return 1;
}

258
__realtime static inline LV2_Atom_Forge_Ref
259 260 261 262 263 264 265
_lforge_basic_chunk(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));

	return _lforge_basic_bytes(L, pos, forge, moony->forge.Chunk);
}

266
__realtime static inline LV2_Atom_Forge_Ref
267 268 269 270 271 272 273
_lforge_basic_midi(lua_State *L, int pos, LV2_Atom_Forge *forge)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));

	return _lforge_basic_bytes(L, pos, forge, moony->uris.midi_event);
}

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
__realtime static int
_lforge_basic_atom(lua_State *L, int pos, LV2_Atom_Forge *forge, LV2_URID range)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
	latom_t *latom = luaL_checkudata(L, pos, "latom");

	if(latom->atom->type != range)
	{
		luaL_error(L, "%s: atom type mismatch", __func__);
	}

	if(  !lv2_atom_forge_atom(forge, latom->atom->size, latom->atom->type)
		|| !lv2_atom_forge_write(forge, latom->body.raw, latom->atom->size) )
	{
		luaL_error(L, forge_buffer_overflow);
	}

	return 1;
}

294 295
__realtime static inline uint32_t
_lforge_basic_vector_child_size(LV2_Atom_Forge *forge, LV2_URID child_type)
296 297 298 299 300 301
{
	if(  (child_type == forge->Bool)
		|| (child_type == forge->Int)
		|| (child_type == forge->Float)
		|| (child_type == forge->URID) )
	{
302
		return 4;
303 304 305 306
	}
	else if( (child_type == forge->Long)
		|| (child_type == forge->Double) )
	{
307
		return 8;
308
	}
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349

	return 0; // failed
}

__realtime static inline LV2_Atom_Forge_Ref
_lforge_basic_vector_item(lua_State *L, int pos, LV2_Atom_Forge *forge,
	LV2_URID child_type)
{
	if(child_type == forge->Bool)
	{
		return lv2_atom_forge_bool(forge, lua_toboolean(L, pos));
	}
	else if(child_type == forge->Int)
	{
		return lv2_atom_forge_int(forge, luaL_checkinteger(L, pos));
	}
	else if(child_type == forge->Float)
	{
		return lv2_atom_forge_float(forge, luaL_checknumber(L, pos));
	}
	else if(child_type == forge->URID)
	{
		return lv2_atom_forge_urid(forge, luaL_checkinteger(L, pos));
	}
	else if(child_type == forge->Long)
	{
		return lv2_atom_forge_long(forge, luaL_checkinteger(L, pos));
	}
	else if(child_type == forge->Double)
	{
		return lv2_atom_forge_double(forge, luaL_checknumber(L, pos));
	}

	return 0; // failed
}

__realtime static inline LV2_Atom_Forge_Ref
_lforge_basic_vector(lua_State *L, int pos, LV2_Atom_Forge *forge,
	uint32_t child_size, LV2_URID child_type)
{
	luaL_checktype(L, pos, LUA_TTABLE);
350 351

	LV2_Atom_Forge_Frame frame;
352 353
	LV2_Atom_Forge_Ref ref = lv2_atom_forge_vector_head(forge, &frame,
		child_size, child_type);
354

355 356 357 358 359
	if(pos < 0)
		pos = pos - 1;

	lua_pushnil(L);
	while(lua_next(L, pos) && ref)
360
	{
361 362 363
		ref = _lforge_basic_vector_item(L, -1, forge, child_type);

		lua_pop(L, 1); // value
364 365 366 367 368 369 370 371
	}

	if(ref)
		lv2_atom_forge_pop(forge, &frame);

	return ref;
}

372
__realtime LV2_Atom_Forge_Ref
373 374
_lforge_basic(lua_State *L, int pos, LV2_Atom_Forge *forge,
	LV2_URID range, LV2_URID child_type)
375
{
376 377
	uint32_t child_size;

378
	//FIXME binary lookup?
379 380 381
	if(luaL_testudata(L, pos, "latom"))
		return _lforge_basic_atom(L, pos, forge, range);
	else if(range == forge->Int)
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
		return _lforge_basic_int(L, pos, forge);
	else if(range == forge->Long)
		return _lforge_basic_long(L, pos, forge);
	else if(range == forge->Float)
		return _lforge_basic_float(L, pos, forge);
	else if(range == forge->Double)
		return _lforge_basic_double(L, pos, forge);
	else if(range == forge->Bool)
		return _lforge_basic_bool(L, pos, forge);
	else if(range == forge->URID)
		return _lforge_basic_urid(L, pos, forge);
	else if(range == forge->String)
		return _lforge_basic_string(L, pos, forge);
	else if(range == forge->URI)
		return _lforge_basic_uri(L, pos, forge);
	else if(range == forge->Path)
		return _lforge_basic_path(L, pos, forge);
	else if(range == forge->Literal)
		return _lforge_basic_literal(L, pos, forge);
401 402
	else if(range == forge->Chunk)
		return _lforge_basic_chunk(L, pos, forge);
403 404
	else if( (range == forge->Vector) && (child_size = _lforge_basic_vector_child_size(forge, child_type) ))
		return _lforge_basic_vector(L, pos, forge, child_size, child_type);
405

406
	return lv2_atom_forge_atom(forge, 0, 0); // fall-back
407 408
}

409
__realtime static int
410 411
_lforge_int(lua_State *L)
{
412
	lforge_t *lforge = lua_touserdata(L, 1);
413 414 415 416 417 418 419 420

	if(!_lforge_basic_int(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

421
__realtime static int
422 423
_lforge_long(lua_State *L)
{
424
	lforge_t *lforge = lua_touserdata(L, 1);
425 426 427 428 429 430 431 432

	if(!_lforge_basic_long(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

433
__realtime static int
434 435
_lforge_float(lua_State *L)
{
436
	lforge_t *lforge = lua_touserdata(L, 1);
437 438 439 440 441 442 443 444

	if(!_lforge_basic_float(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

445
__realtime static int
446 447
_lforge_double(lua_State *L)
{
448
	lforge_t *lforge = lua_touserdata(L, 1);
449 450 451 452 453 454 455 456

	if(!_lforge_basic_double(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

457
__realtime static int
458 459
_lforge_bool(lua_State *L)
{
460
	lforge_t *lforge = lua_touserdata(L, 1);
461 462 463 464 465 466 467 468

	if(!_lforge_basic_bool(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

469
__realtime static int
470 471
_lforge_urid(lua_State *L)
{
472
	lforge_t *lforge = lua_touserdata(L, 1);
473 474 475 476 477 478 479 480

	if(!_lforge_basic_urid(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

481
__realtime static int
482 483
_lforge_string(lua_State *L)
{
484
	lforge_t *lforge = lua_touserdata(L, 1);
485 486 487 488 489 490 491 492

	if(!_lforge_basic_string(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

493
__realtime static int
494 495
_lforge_uri(lua_State *L)
{
496
	lforge_t *lforge = lua_touserdata(L, 1);
497 498 499 500 501 502 503 504

	if(!_lforge_basic_uri(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

505
__realtime static int
506 507
_lforge_path(lua_State *L)
{
508
	lforge_t *lforge = lua_touserdata(L, 1);
509 510 511 512 513 514 515 516

	if(!_lforge_basic_path(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

517
__realtime static int
518 519
_lforge_literal(lua_State *L)
{
520
	lforge_t *lforge = lua_touserdata(L, 1);
521 522
	size_t size;
	const char *val = luaL_checklstring(L, 2, &size);
523 524
	LV2_URID datatype = luaL_optinteger(L, 3, 0);
	LV2_URID lang = luaL_optinteger(L, 4, 0);
525 526 527 528 529 530 531 532

	if(!lv2_atom_forge_literal(lforge->forge, val, size, datatype, lang))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

533
__realtime static int
534
_lforge_chunk(lua_State *L)
535
{
536
	lforge_t *lforge = lua_touserdata(L, 1);
537

538 539
	if(!_lforge_basic_chunk(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);
540 541 542 543 544

	lua_settop(L, 1);
	return 1;
}

545
__realtime static int
546 547
_lforge_midi(lua_State *L)
{
548 549 550 551
	lforge_t *lforge = lua_touserdata(L, 1);

	if(!_lforge_basic_midi(L, 2, lforge->forge))
		luaL_error(L, forge_buffer_overflow);
552

553 554
	lua_settop(L, 1);
	return 1;
555 556
}

557
__realtime static int
Hanspeter Portner's avatar
Hanspeter Portner committed
558 559 560 561 562 563 564 565 566 567 568 569
_lforge_raw(lua_State *L)
{
	lforge_t *lforge = lua_touserdata(L, 1);
	const LV2_URID type = luaL_checkinteger(L, 2);

	if(!_lforge_basic_bytes(L, 3, lforge->forge, type))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

570
__realtime static uint64_t
571
_lforge_to_timetag(lua_State *L, moony_t *moony, lforge_t *lforge, int pos)
572
{
573
	uint64_t timetag= 1ULL; // immediate timetag
574 575
	if(lua_isinteger(L, pos))
	{
576 577
		// absolute timetag
		timetag = lua_tointeger(L, pos);
578 579 580
	}
	else if(lua_isnumber(L, pos) && moony->osc_sched)
	{
581 582
		// timetag of current frame
		timetag = moony->osc_sched->frames2osc(moony->osc_sched->handle,
583
			lforge->last.frames);
584 585
		volatile uint64_t sec = timetag >> 32;
		volatile uint64_t frac = timetag & 0xffffffff;
586

587 588 589 590 591
		// relative offset from current frame (in seconds)
		double offset_d = lua_tonumber(L, pos);
		double secs_d;
		double frac_d = modf(offset_d, &secs_d);

592
		// add relative offset to timetag
593 594 595 596 597 598 599
		sec += secs_d;
		frac += frac_d * 0x1p32;
		if(frac >= 0x100000000ULL) // overflow
		{
			sec += 1;
			frac -= 0x100000000ULL;
		}
600
		timetag = (sec << 32) | frac;
601 602 603 604

		/*
		// debug
		uint64_t t0 = moony->osc_sched->frames2osc(moony->osc_sched->handle, lforge->last.frames);
605
		uint64_t dt = timetag - t0;
606
		double dd = dt * 0x1p-32;
Hanspeter Portner's avatar
Hanspeter Portner committed
607
		printf("%"PRIu64" %lf\n", dt, dd);
608 609 610
		*/
	}

611
	return timetag ;
612 613
}

614
__realtime static int
615 616 617
_lforge_osc_bundle(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
618
	lforge_t *lforge = lua_touserdata(L, 1);
619

620
	LV2_OSC_URID *osc_urid = &moony->osc_urid;
621 622
	LV2_Atom_Forge *forge = lforge->forge;

Hanspeter Portner's avatar
Hanspeter Portner committed
623
	const uint64_t timetag = _lforge_to_timetag(L, moony, lforge, 2);
624

625
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
626 627 628 629
	lframe->depth = 2;
	lframe->last.frames = lforge->last.frames;
	lframe->forge = lforge->forge;

630 631 632
	lua_pushvalue(L, 1); // lforge
	lua_setuservalue(L, -2); // store parent as uservalue

633
	if(!lv2_osc_forge_bundle_head(forge, osc_urid, lframe->frame, LV2_OSC_TIMETAG_CREATE(timetag)))
634 635 636 637 638
		luaL_error(L, forge_buffer_overflow);

	return 1; // derived forge
}

639
__realtime static int
640 641 642
_lforge_osc_message(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
643
	lforge_t *lforge = lua_touserdata(L, 1);
644

645
	LV2_OSC_URID *osc_urid = &moony->osc_urid;
646 647 648 649 650 651 652
	LV2_Atom_Forge *forge = lforge->forge;

	const char *path = luaL_checkstring(L, 2);
	const char *fmt = luaL_optstring(L, 3, "");

	LV2_Atom_Forge_Frame frame [2];

653
	if(!lv2_osc_forge_message_head(forge, osc_urid, frame, path))
654 655 656 657 658
		luaL_error(L, forge_buffer_overflow);

	int pos = 4;
	for(const char *type = fmt; *type; type++)
	{
659
		switch( (LV2_OSC_Type)*type)
660
		{
661
			case LV2_OSC_INT32:
662
			{
663 664
				const int32_t i = luaL_checkinteger(L, pos++);
				if(!lv2_osc_forge_int(forge, osc_urid, i))
665 666 667
					luaL_error(L, forge_buffer_overflow);
				break;
			}
668
			case LV2_OSC_FLOAT:
669
			{
670 671
				const float f = luaL_checknumber(L, pos++);
				if(!lv2_osc_forge_float(forge, osc_urid, f))
672 673 674
					luaL_error(L, forge_buffer_overflow);
				break;
			}
675
			case LV2_OSC_STRING:
676
			{
677 678 679
				size_t n;
				const char *s = luaL_checklstring(L, pos++, &n);
				if(!lv2_osc_forge_string(forge, osc_urid, s, n))
680 681 682
					luaL_error(L, forge_buffer_overflow);
				break;
			}
683
			case LV2_OSC_BLOB:
684
			{
685 686 687 688 689 690 691
				size_t n;
				const char *b = luaL_checklstring(L, pos++, &n);
				if(!lv2_atom_forge_atom(forge, n, forge->Chunk))
					luaL_error(L, forge_buffer_overflow);
				if(!lv2_atom_forge_raw(forge, b, n))
					luaL_error(L, forge_buffer_overflow);
				lv2_atom_forge_pad(forge, n);
692 693 694
				break;
			}

695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
			case LV2_OSC_TRUE:
			{
				if(!lv2_osc_forge_true(forge, osc_urid))
					luaL_error(L, forge_buffer_overflow);
				break;
			}
			case LV2_OSC_FALSE:
			{
				if(!lv2_osc_forge_false(forge, osc_urid))
					luaL_error(L, forge_buffer_overflow);
				break;
			}
			case LV2_OSC_NIL:
			{
				if(!lv2_osc_forge_nil(forge, osc_urid))
					luaL_error(L, forge_buffer_overflow);
				break;
			}
			case LV2_OSC_IMPULSE:
714
			{
715 716
				if(!lv2_osc_forge_impulse(forge, osc_urid))
					luaL_error(L, forge_buffer_overflow);
717 718 719
				break;
			}

720
			case LV2_OSC_INT64:
721
			{
722 723
				const int64_t h = luaL_checkinteger(L, pos++);
				if(!lv2_osc_forge_long(forge, osc_urid, h))
724 725 726
					luaL_error(L, forge_buffer_overflow);
				break;
			}
727
			case LV2_OSC_DOUBLE:
728
			{
729 730
				const double d = luaL_checknumber(L, pos++);
				if(!lv2_osc_forge_double(forge, osc_urid, d))
731 732 733
					luaL_error(L, forge_buffer_overflow);
				break;
			}
734
			case LV2_OSC_TIMETAG:
735
			{
736 737
				const uint64_t t = _lforge_to_timetag(L, moony, lforge, pos++);
				if(!lv2_osc_forge_timetag(forge, osc_urid, LV2_OSC_TIMETAG_CREATE(t)))
738 739 740 741
					luaL_error(L, forge_buffer_overflow);
				break;
			}

742
			case LV2_OSC_SYMBOL:
743
			{
Hanspeter Portner's avatar
Hanspeter Portner committed
744 745
				const LV2_URID S = luaL_checkinteger(L, pos++);
				if(!lv2_osc_forge_symbol(forge, osc_urid, S))
746 747
					luaL_error(L, forge_buffer_overflow);
				break;
Hanspeter Portner's avatar
Hanspeter Portner committed
748
				break;
749
			}
750
			case LV2_OSC_MIDI:
751
			{
752 753 754 755 756 757 758
				size_t n;
				const char *m = luaL_checklstring(L, pos++, &n);
				if(!lv2_atom_forge_atom(forge, n, moony->osc_urid.MIDI_MidiEvent))
					luaL_error(L, forge_buffer_overflow);
				if(!lv2_atom_forge_raw(forge, m, n))
					luaL_error(L, forge_buffer_overflow);
				lv2_atom_forge_pad(forge, n);
759 760
				break;
			}
761 762 763 764 765 766 767
			case LV2_OSC_CHAR:
			{
				const char c = luaL_checkinteger(L, pos++);
				if(!lv2_osc_forge_char(forge, osc_urid, c))
					luaL_error(L, forge_buffer_overflow);
				break;
			}
768 769
			case LV2_OSC_RGBA:
			{
770 771 772 773 774 775 776
				const uint32_t rgba = luaL_checkinteger(L, pos++);
				if(!lv2_osc_forge_rgba(forge, osc_urid,
						(rgba >> 24) & 0xff,
						(rgba >> 16) & 0xff,
						(rgba >> 8) & 0xff,
						rgba & 0xff))
					luaL_error(L, forge_buffer_overflow);
777 778
				break;
			}
779 780 781
		}
	}

782
	lv2_osc_forge_pop(forge, frame);
783 784 785 786 787

	lua_settop(L, 1);
	return 1;
}

788
__realtime static int
789 790 791 792 793 794 795 796 797 798 799 800 801
_lforge_osc_impulse(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
	lforge_t *lforge = lua_touserdata(L, 1);
	LV2_OSC_URID *osc_urid = &moony->osc_urid;

	if(!lv2_osc_forge_impulse(lforge->forge, osc_urid))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

802
__realtime static int
803 804 805 806 807 808
_lforge_osc_char(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
	lforge_t *lforge = lua_touserdata(L, 1);
	LV2_OSC_URID *osc_urid = &moony->osc_urid;

809
	const char ch = luaL_checkinteger(L, 2);
810

811
	if(!lv2_osc_forge_char(lforge->forge, osc_urid, ch))
812 813 814 815 816 817
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

818
__realtime static int
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
_lforge_osc_rgba(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
	lforge_t *lforge = lua_touserdata(L, 1);
	LV2_OSC_URID *osc_urid = &moony->osc_urid;

	const uint32_t col = luaL_checkinteger(L, 2);
	const uint8_t r = (col >> 24) & 0xff;
	const uint8_t g = (col >> 16) & 0xff;
	const uint8_t b = (col >>  8) & 0xff;
	const uint8_t a = (col >>  0) & 0xff;

	if(!lv2_osc_forge_rgba(lforge->forge, osc_urid, r, g, b, a))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

838
__realtime static int
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
_lforge_osc_timetag(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
	lforge_t *lforge = lua_touserdata(L, 1);
	LV2_OSC_URID *osc_urid = &moony->osc_urid;

	const uint64_t tt = _lforge_to_timetag(L, moony, lforge, 2);

	if(!lv2_osc_forge_timetag(lforge->forge, osc_urid, LV2_OSC_TIMETAG_CREATE(tt)))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

854
__realtime static int
855 856 857
_lforge_tuple(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
858
	lforge_t *lforge = lua_touserdata(L, 1);
859
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
860 861 862 863
	lframe->depth = 1;
	lframe->last.frames = lforge->last.frames;
	lframe->forge = lforge->forge;

864 865 866
	lua_pushvalue(L, 1); // lforge
	lua_setuservalue(L, -2); // store parent as uservalue

867 868 869 870 871 872
	if(!lv2_atom_forge_tuple(lforge->forge, &lframe->frame[0]))
		luaL_error(L, forge_buffer_overflow);

	return 1; // derived forge
}

873
__realtime static int
874 875 876
_lforge_object(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
877
	lforge_t *lforge = lua_touserdata(L, 1);
878 879
	LV2_URID otype = luaL_optinteger(L, 2, 0);
	LV2_URID id = luaL_optinteger(L, 3, 0);
880
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
881 882 883 884
	lframe->depth = 1;
	lframe->last.frames = lforge->last.frames;
	lframe->forge = lforge->forge;

885 886 887
	lua_pushvalue(L, 1); // lforge
	lua_setuservalue(L, -2); // store parent as uservalue

888 889 890 891 892
	if(!lv2_atom_forge_object(lforge->forge, &lframe->frame[0], id, otype))
		luaL_error(L, forge_buffer_overflow);

	return 1; // derived forge
}
893
__realtime static int
894 895
_lforge_key(lua_State *L)
{
896
	lforge_t *lforge = lua_touserdata(L, 1);
897
	LV2_URID key = luaL_checkinteger(L, 2);
898
	LV2_URID context = luaL_optinteger(L, 3, 0);
899 900 901 902 903 904 905 906

	if(!lv2_atom_forge_property_head(lforge->forge, key, context))
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
__realtime static int
_lforge_vector_derive(moony_t *moony, lforge_t *lforge, lua_State *L,
	uint32_t child_size, uint32_t child_type)
{
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
	lframe->depth = 1;
	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_vector_head(lforge->forge, &lframe->frame[0], child_size, child_type))
		luaL_error(L, forge_buffer_overflow);

	return 1; // derived forge
}

__realtime static int
_lforge_vector_table(int idx, lforge_t *lforge, lua_State *L,
	uint32_t child_size, uint32_t child_type)
{
	if(!_lforge_basic_vector(L, idx, lforge->forge, child_size, child_type))
		luaL_error(L, forge_buffer_overflow);

	return 1; // self forge
}

__realtime static int
_lforge_vector_args(int from, int to, lforge_t *lforge, lua_State *L,
	uint32_t child_size, uint32_t child_type)
{
	LV2_Atom_Forge_Frame vec_frame;

	if(!lv2_atom_forge_vector_head(lforge->forge, &vec_frame, child_size, child_type))
		luaL_error(L, forge_buffer_overflow);

	for(int i = from; i <= to; i++)
	{
		if(!_lforge_basic_vector_item(L, i, lforge->forge, child_type))
			luaL_error(L, forge_buffer_overflow);
	}

	lv2_atom_forge_pop(lforge->forge, &vec_frame);

	return 1; // self forge
}

955
__realtime static int
956 957
_lforge_vector(lua_State *L)
{
958
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
959
	lforge_t *lforge = lua_touserdata(L, 1);
960
	const LV2_URID child_type = luaL_checkinteger(L, 2);
961
	uint32_t child_size;
962

963 964 965
	if(  (child_type == lforge->forge->Bool)
		|| (child_type == lforge->forge->Int)
		|| (child_type == lforge->forge->Float)
966 967
		|| (child_type == lforge->forge->URID) )
	{
968
		child_size = 4;
969
	}
970 971
	else if( (child_type == lforge->forge->Long)
		|| (child_type == lforge->forge->Double) )
972
	{
973
		child_size = 8;
974
	}
975
	else
976
	{
977
		luaL_error(L, "Atom vector only supports atom:Bool/Int/URID/Float/Long/Double");
978 979
	}

980
	const int top = lua_gettop(L);
981

982 983 984 985 986 987 988
	if(top >= 3)
	{
		if(lua_istable(L, 3))
			return _lforge_vector_table(3, lforge, L, child_size, child_type);
		else
			return _lforge_vector_args(3, top, lforge, L, child_size, child_type);
	}
989

990
	return _lforge_vector_derive(moony, lforge, L, child_size, child_type);
991 992
}

993
__realtime static int
994 995 996
_lforge_sequence(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
997
	lforge_t *lforge = lua_touserdata(L, 1);
998
	LV2_URID unit = luaL_optinteger(L, 2, 0);
999
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
1000 1001 1002
	lframe->depth = 1;
	lframe->last.frames = 0;
	lframe->forge = lforge->forge;
1003

1004 1005 1006
	lua_pushvalue(L, 1); // lforge
	lua_setuservalue(L, -2); // store parent as uservalue

1007 1008 1009 1010 1011 1012
	if(!lv2_atom_forge_sequence_head(lforge->forge, &lframe->frame[0], unit))
		luaL_error(L, forge_buffer_overflow);

	return 1; // derived forge
}

1013
__realtime static int
1014 1015 1016
_lforge_typed(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
1017
	lforge_t *lforge = lua_touserdata(L, 1);
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
	LV2_URID urid = luaL_checkinteger(L, 2);
	lua_remove(L, 2); // urid

	lua_CFunction hook = NULL;

	//TODO keep this list updated
	//TODO use binary tree sorted by URID
	if(urid == lforge->forge->Int)
		hook = _lforge_int;
	else if(urid == lforge->forge->Long)
		hook = _lforge_long;
	else if(urid == lforge->forge->Float)
		hook = _lforge_float;
	else if(urid == lforge->forge->Double)
		hook = _lforge_double;
	else if(urid == lforge->forge->Bool)
		hook = _lforge_bool;
	else if(urid == lforge->forge->URID)
		hook = _lforge_urid;
	else if(urid == lforge->forge->String)
		hook = _lforge_string;
	else if(urid == lforge->forge->Literal)
		hook = _lforge_literal;
	else if(urid == lforge->forge->URI)
		hook = _lforge_uri;
	else if(urid == lforge->forge->Path)
		hook = _lforge_path;

	else if(urid == lforge->forge->Chunk)
		hook = _lforge_chunk;
	else if(urid == moony->uris.midi_event)
		hook = _lforge_midi;
1050
	else if(urid == moony->osc_urid.OSC_Bundle)
1051
		hook = _lforge_osc_bundle;
1052
	else if(urid == moony->osc_urid.OSC_Message)
1053 1054 1055 1056 1057 1058
		hook = _lforge_osc_message;
	else if(urid == lforge->forge->Tuple)
		hook = _lforge_tuple;
	else if(urid == lforge->forge->Object)
		hook = _lforge_object;
	else if(urid == lforge->forge->Property)
1059
		hook = _lforge_key;
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
	else if(urid == lforge->forge->Vector)
		hook = _lforge_vector;
	else if(urid == lforge->forge->Sequence)
		hook = _lforge_sequence;

	if(!hook)
		return luaL_error(L, "unknown atom type");

	return hook(L);
}

1071
__realtime static int
1072 1073 1074
_lforge_get(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
1075
	lforge_t *lforge = lua_touserdata(L, 1);
Hanspeter Portner's avatar
Hanspeter Portner committed
1076
	const LV2_URID property = luaL_optinteger(L, 2, 0);
1077
	const LV2_URID subject = luaL_optinteger(L, 3, 0);
1078
	const int32_t sequence_num = luaL_optinteger(L, 4, 0);
1079 1080 1081

	LV2_Atom_Forge_Frame frame;

1082
	if(!lv2_atom_forge_object(lforge->forge, &frame, 0, moony->uris.patch.get))
1083 1084 1085 1086
		luaL_error(L, forge_buffer_overflow);

	if(subject) // is optional
	{
1087
		if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.subject))
1088 1089 1090 1091 1092
			luaL_error(L, forge_buffer_overflow);
		if(!lv2_atom_forge_urid(lforge->forge, subject))
			luaL_error(L, forge_buffer_overflow);
	}

Hanspeter Portner's avatar
Hanspeter Portner committed
1093 1094 1095 1096 1097 1098 1099 1100
	if(property)
	{
		if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.property))
			luaL_error(L, forge_buffer_overflow);
		if(!lv2_atom_forge_urid(lforge->forge, property))
			luaL_error(L, forge_buffer_overflow);
	}

1101 1102 1103 1104
	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);
1105

1106 1107 1108 1109 1110 1111
	lv2_atom_forge_pop(lforge->forge, &frame);

	lua_settop(L, 1);
	return 1;
}

1112
__realtime static int
1113 1114 1115
_lforge_set(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
1116
	lforge_t *lforge = lua_touserdata(L, 1);
1117 1118
	const LV2_URID property = luaL_checkinteger(L, 2);
	const LV2_URID subject = luaL_optinteger(L, 3, 0);
1119
	const int32_t sequence_num = luaL_optinteger(L, 4, 0);
1120
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
1121 1122 1123 1124
	lframe->depth = 1;
	lframe->last.frames = lforge->last.frames;
	lframe->forge = lforge->forge;

1125 1126 1127
	lua_pushvalue(L, 1); // lforge
	lua_setuservalue(L, -2); // store parent as uservalue

1128
	if(!lv2_atom_forge_object(lforge->forge, lframe->frame, 0, moony->uris.patch.set))
1129 1130 1131 1132
		luaL_error(L, forge_buffer_overflow);

	if(subject) // is optional
	{
1133
		if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.subject))
1134 1135 1136 1137 1138
			luaL_error(L, forge_buffer_overflow);
		if(!lv2_atom_forge_urid(lforge->forge, subject))
			luaL_error(L, forge_buffer_overflow);
	}

1139 1140 1141 1142
	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);
1143

1144
	if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.property))
1145 1146 1147 1148
		luaL_error(L, forge_buffer_overflow);
	if(!lv2_atom_forge_urid(lforge->forge, property))
		luaL_error(L, forge_buffer_overflow);

1149
	if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.value))
1150 1151 1152 1153 1154
		luaL_error(L, forge_buffer_overflow);

	return 1; // derived forge
}

1155
__realtime static int
1156 1157 1158
_lforge_put(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
1159
	lforge_t *lforge = lua_touserdata(L, 1);
1160 1161
	const LV2_URID subject = luaL_optinteger(L, 2, 0);
	const LV2_URID sequence_num = luaL_optinteger(L, 3, 0);
1162
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
1163 1164 1165 1166
	lframe->depth = 2;
	lframe->last.frames = lforge->last.frames;
	lframe->forge = lforge->forge;

1167 1168 1169
	lua_pushvalue(L, 1); // lforge
	lua_setuservalue(L, -2); // store parent as uservalue

1170
	if(!lv2_atom_forge_object(lforge->forge, &lframe->frame[0], 0, moony->uris.patch.put))
1171 1172 1173 1174
		luaL_error(L, forge_buffer_overflow);

	if(subject) // is optional
	{
1175
		if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.subject))
1176 1177 1178 1179 1180
			luaL_error(L, forge_buffer_overflow);
		if(!lv2_atom_forge_urid(lforge->forge, subject))
			luaL_error(L, forge_buffer_overflow);
	}

1181 1182 1183 1184
	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);
1185

1186
	if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.body))
1187 1188 1189 1190 1191 1192 1193
		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
}

1194
__realtime static int
1195 1196 1197
_lforge_patch(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
1198
	lforge_t *lforge = lua_touserdata(L, 1);
1199 1200
	const LV2_URID subject = luaL_optinteger(L, 2, 0);
	const int32_t sequence_num = luaL_optinteger(L, 3, 0);
1201
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
1202 1203 1204 1205
	lframe->depth = 1;
	lframe->last.frames = lforge->last.frames;
	lframe->forge = lforge->forge;

1206 1207 1208
	lua_pushvalue(L, 1); // lforge
	lua_setuservalue(L, -2); // store parent as uservalue

1209
	if(!lv2_atom_forge_object(lforge->forge, lframe->frame, 0, moony->uris.patch.patch))
1210 1211 1212 1213
		luaL_error(L, forge_buffer_overflow);

	if(subject) // is optional
	{
1214
		if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.subject))
1215 1216 1217 1218 1219
			luaL_error(L, forge_buffer_overflow);
		if(!lv2_atom_forge_urid(lforge->forge, subject))
			luaL_error(L, forge_buffer_overflow);
	}

1220 1221 1222 1223
	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);
1224

1225 1226 1227
	return 1; // derived forge
}

1228
__realtime static int
1229 1230 1231
_lforge_remove(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
1232
	lforge_t *lforge = lua_touserdata(L, 1);
1233
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
1234 1235 1236 1237
	lframe->depth = 1;
	lframe->last.frames = lforge->last.frames;
	lframe->forge = lforge->forge;

1238 1239 1240
	lua_pushvalue(L, 1); // lforge
	lua_setuservalue(L, -2); // store parent as uservalue

1241
	if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.remove))
1242 1243 1244 1245 1246 1247 1248
		luaL_error(L, forge_buffer_overflow);
	if(!lv2_atom_forge_object(lforge->forge, lframe->frame, 0, 0))
		luaL_error(L, forge_buffer_overflow);

	return 1; // derived forge
}

1249
__realtime static int
1250 1251 1252
_lforge_add(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
1253
	lforge_t *lforge = lua_touserdata(L, 1);
1254
	lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
1255 1256 1257 1258
	lframe->depth = 1;
	lframe->last.frames = lforge->last.frames;
	lframe->forge = lforge->forge;

1259 1260 1261
	lua_pushvalue(L, 1); // lforge
	lua_setuservalue(L, -2); // store parent as uservalue

1262
	if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.add))
1263 1264 1265 1266 1267 1268 1269
		luaL_error(L, forge_buffer_overflow);
	if(!lv2_atom_forge_object(lforge->forge, lframe->frame, 0, 0))
		luaL_error(L, forge_buffer_overflow);

	return 1; // derived forge
}

1270
__realtime static int
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
_lforge_ack(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 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.ack))
		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);

	lv2_atom_forge_pop(lforge->forge, &frame);

	lua_settop(L, 1);
	return 1;
}

1302
__realtime static int
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
_lforge_error(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 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.error))
		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);

	lv2_atom_forge_pop(lforge->forge, &frame);

	lua_settop(L, 1);
	return 1;
}

1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471
__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
}

1472
__realtime static int
1473 1474 1475 1476 1477
_lforge_canvas_begin_path(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
	lforge_t *lforge = lua_touserdata(L, 1);

1478
	if(!lv2_canvas_forge_beginPath(lforge->forge, &moony->canvas_urid) )
1479 1480 1481 1482 1483 1484
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

1485
__realtime static int
1486 1487 1488 1489 1490
_lforge_canvas_close_path(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
	lforge_t *lforge = lua_touserdata(L, 1);

1491
	if(!lv2_canvas_forge_closePath(lforge->forge, &moony->canvas_urid) )
1492 1493 1494 1495 1496 1497
		luaL_error(L, forge_buffer_overflow);

	lua_settop(L, 1);
	return 1;
}

1498
__realtime static int
1499 1500 1501 1502 1503
_lforge_canvas_arc(lua_State *L)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
	lforge_t *lforge = lua_touserdata(L, 1);

1504 1505 1506 1507 1508 1509
	if(!lv2_canvas_forge_arc(lforge->forge, &moony->canvas_urid,
			luaL_checknumber(L, 2),
			luaL_checknumber(L, 3),
			luaL_checknumber(L, 4),
			luaL_optnumber(L, 5, 0.f),
			luaL_optnumber(L, 6, M_PI*2)) )
1510 1511 1512