static osc_data_t *
oscmidi_serialize(osc_data_t *buf, osc_data_t *end, OSC_MIDI_Format format, uint8_t channel, uint8_t status, uint8_t dat1, uint8_t dat2)
{
	osc_data_t *buf_ptr = buf;
	osc_data_t *itm = NULL;
	uint_fast8_t multi = config.oscmidi.multi;

	if(!multi)
	{
		buf_ptr = osc_start_bundle_item(buf_ptr, end, &itm);
		buf_ptr = osc_set_path(buf_ptr, end, config.oscmidi.path);
		buf_ptr = osc_set_fmt(buf_ptr, end, oscmidi_fmt_1[format]);
	}

	switch(format)
	{
		case OSC_MIDI_FORMAT_MIDI:
		{
			uint8_t *M;
			buf_ptr = osc_set_midi_inline(buf_ptr, end, &M);
			if(buf_ptr)
			{
				M[0] = 0;
				M[1] = channel | status;
				M[2] = dat1;
				M[3] = dat2;
			}
			break;
		}
		case OSC_MIDI_FORMAT_INT32:
		{
			int32_t i = (dat2 << 16) | (dat1 << 8) | ( (channel | status) << 0);
			buf_ptr = osc_set_int32(buf_ptr, end, i);
			break;
		}
		case OSC_MIDI_FORMAT_BLOB:
		{
			uint8_t *B;
			buf_ptr = osc_set_blob_inline(buf_ptr, end, 3, (void **)&B);
			if(buf_ptr)
			{
				B[0] = channel | status;
				B[1] = dat1;
				B[2] = dat2;
			}
			break;
		}
	}

	if(!multi)
		buf_ptr = osc_end_bundle_item(buf_ptr, end, itm);

	return buf_ptr;
}
Пример #2
0
// rt
static void
_message_cb(const char *path, const char *fmt, const LV2_Atom_Tuple *body,
	void *data)
{
	prog_t *handle = data;

	osc_data_t *ptr = handle->osc_ptr;
	const osc_data_t *end = handle->osc_end;

	osc_data_t *itm = NULL;
	if(handle->bndl_cnt)
		ptr = osc_start_bundle_item(ptr, end, &itm);

	ptr = osc_set_path(ptr, end, path);
	ptr = osc_set_fmt(ptr, end, fmt);

	const LV2_Atom *itr = lv2_atom_tuple_begin(body);
	for(const char *type = fmt;
		*type && !lv2_atom_tuple_is_end(LV2_ATOM_BODY(body), body->atom.size, itr);
		type++, itr = lv2_atom_tuple_next(itr))
	{
		switch(*type)
		{
			case 'i':
			{
				ptr = osc_set_int32(ptr, end, ((const LV2_Atom_Int *)itr)->body);
				break;
			}
			case 'f':
			{
				ptr = osc_set_float(ptr, end, ((const LV2_Atom_Float *)itr)->body);
				break;
			}
			case 's':
			case 'S':
			{
				ptr = osc_set_string(ptr, end, LV2_ATOM_BODY_CONST(itr));
				break;
			}
			case 'b':
			{
				ptr = osc_set_blob(ptr, end, itr->size, LV2_ATOM_BODY(itr));
				break;
			}

			case 'h':
			{
				ptr = osc_set_int64(ptr, end, ((const LV2_Atom_Long *)itr)->body);
				break;
			}
			case 'd':
			{
				ptr = osc_set_double(ptr, end, ((const LV2_Atom_Double *)itr)->body);
				break;
			}
			case 't':
			{
				ptr = osc_set_timetag(ptr, end, ((const LV2_Atom_Long *)itr)->body);
				break;
			}

			case 'T':
			case 'F':
			case 'N':
			case 'I':
			{
				break;
			}

			case 'c':
			{
				ptr = osc_set_char(ptr, end, ((const LV2_Atom_Int *)itr)->body);
				break;
			}
			case 'm':
			{
				const uint8_t *src = LV2_ATOM_BODY_CONST(itr);
				const uint8_t dst [4] = {
					0x00, // port byte
					itr->size >= 1 ? src[0] : 0x00,
					itr->size >= 2 ? src[1] : 0x00,
					itr->size >= 3 ? src[2] : 0x00
				};
				ptr = osc_set_midi(ptr, end, dst);
				break;
			}
		}
	}
	
	if(handle->bndl_cnt)
		ptr = osc_end_bundle_item(ptr, end, itm);

	handle->osc_ptr = ptr;
}
osc_data_t *
rpn_run(osc_data_t *buf, osc_data_t *end, Custom_Item *itm, RPN_Stack *stack)
{
	osc_data_t *buf_ptr = buf;
	RPN_VM *vm = &itm->vm;

	stack->ptr = stack->arr; // reset stack

	RPN_Instruction *inst;
	for(inst = vm->inst; *inst != RPN_TERMINATOR; inst++)
		switch(*inst)
		{
			case RPN_PUSH_VALUE:
			{
				push(stack, vm->val[inst - vm->inst]);
				break;
			}
			case RPN_POP_INT32:
			{
				volatile int32_t i = pop(stack);
				buf_ptr = osc_set_int32(buf_ptr, end, i);
				break;
			}
			case RPN_POP_FLOAT:
			{
				float f = pop(stack);
				buf_ptr = osc_set_float(buf_ptr, end, f);
				break;
			}
			case RPN_POP_MIDI:
			{
				uint8_t *m;
				buf_ptr = osc_set_midi_inline(buf_ptr, end, &m);
				if(buf_ptr)
				{
					m[3] = pop(stack);
					m[2] = pop(stack);
					m[1] = pop(stack);
					m[0] = pop(stack);
				}
				break;
			}

			case RPN_PUSH_FID:
			{
				push(stack, stack->fid);
				break;
			}
			case RPN_PUSH_SID:
			{
				push(stack, stack->sid);
				break;
			}
			case RPN_PUSH_GID:
			{
				push(stack, stack->gid);
				break;
			}
			case RPN_PUSH_PID:
			{
				push(stack, stack->pid);
				break;
			}
			case RPN_PUSH_X:
			{
				push(stack, stack->x);
				break;
			}
			case RPN_PUSH_Z:
			{
				push(stack, stack->z);
				break;
			}
			case RPN_PUSH_VX:
			{
				push(stack, stack->vx);
				break;
			}
			case RPN_PUSH_VZ:
			{
				push(stack, stack->vz);
				break;
			}
			case RPN_PUSH_N:
			{
				push(stack, SENSOR_N);
				break;
			}

			case RPN_PUSH_REG:
			{
				int32_t pos = pop(stack);
				float c = pop(stack);
				if(pos < RPN_REG_HEIGHT)
					stack->reg[pos] = c;
				else
				{
					; //TODO warn
				}
				break;
			}
			case RPN_POP_REG:
			{
				int32_t pos = pop(stack);
				if(pos < RPN_REG_HEIGHT)
					push(stack, stack->reg[pos]);
				else // TODO warn
					push(stack, NAN);
				break;
			}

			// standard operators
			case RPN_ADD:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a + b;
				push(stack, c);
				break;
			}
			case RPN_SUB:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a - b;
				push(stack, c);
				break;
			}
			case RPN_MUL:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a * b;
				push(stack, c);
				break;
			}
			case RPN_DIV:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a / b;
				push(stack, c);
				break;
			}
			case RPN_MOD:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = fmod(a, b);
				push(stack, c);
				break;
			}
			case RPN_POW:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = pow(a, b);
				push(stack, c);
				break;
			}
			case RPN_NEG:
			{
				float c = pop(stack);
				push(stack, -c);
				break;
			}
			case RPN_XCHANGE:
			{
				xchange(stack);
				break;
			}
			case RPN_DUPL_AT:
			{
				int32_t pos = pop(stack);
				if(pos > RPN_STACK_HEIGHT)
					pos = RPN_STACK_HEIGHT;
				else if(pos < 1)
					pos = 1;
				duplicate(stack, pos);
				break;
			}
			case RPN_DUPL_TOP:
			{
				duplicate(stack, 1);
				break;
			}
			case RPN_LSHIFT:
			{
				int32_t b = pop(stack);
				int32_t a = pop(stack);
				int32_t c = a << b;
				push(stack, c);
				break;
			}
			case RPN_RSHIFT:
			{
				int32_t b = pop(stack);
				int32_t a = pop(stack);
				int32_t c = a >> b;
				push(stack, c);
				break;
			}
			case RPN_LOGICAL_AND:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a && b;
				push(stack, c);
				break;
			}
			case RPN_BITWISE_AND:
			{
				int32_t b = pop(stack);
				int32_t a = pop(stack);
				int32_t c = a & b;
				push(stack, c);
				break;
			}
			case RPN_LOGICAL_OR:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a || b;
				push(stack, c);
				break;
			}
			case RPN_BITWISE_OR:
			{
				int32_t b = pop(stack);
				int32_t a = pop(stack);
				int32_t c = a | b;
				push(stack, c);
				break;
			}

			// conditionals
			case RPN_NOT:
			{
				float c = pop(stack);
				push(stack, !c);
				break;
			}
			case RPN_NOTEQ:
			{
				float a = pop(stack);
				float b = pop(stack);
				float c = a != b;
				push(stack, c);
				break;
			}
			case RPN_COND:
			{
				float c = pop(stack);
				if(!c)
					xchange(stack);
				pop(stack);
				break;
			}
			case RPN_LT:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a < b;
				push(stack, c);
				break;
			}
			case RPN_LEQ:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a <= b;
				push(stack, c);
				break;
			}
			case RPN_GT:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a > b;
				push(stack, c);
				break;
			}
			case RPN_GEQ:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a >= b;
				push(stack, c);
				break;
			}
			case RPN_EQ:
			{
				float b = pop(stack);
				float a = pop(stack);
				float c = a == b;
				push(stack, c);
				break;
			}
			case RPN_TERMINATOR:
				// never reached
				break;
		}
	
	return buf_ptr;
}