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; }
// 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; }