static void
_rtmidic_cb(double timestamp, size_t size, uint8_t* message, void **cb)
{
	Data *dat = (Data *)((uint8_t *)cb - offsetof(Data, cb));
	Tjost_Module *module = (Tjost_Module *)((uint8_t *)dat - offsetof(Tjost_Module, dat));

	// TODO assert(size <= 4)
	uint8_t m [4] = {0x0};
	m[1] = message[0];
	m[2] = message[1];
	m[3] = message[2];

	const size_t len = 16;
	osc_data_t buf [len];
	osc_data_t *ptr = buf;
	osc_data_t *end = ptr + len;

	ptr = osc_set_path(ptr, end, "/midi");
	ptr = osc_set_fmt(ptr, end, "m");
	ptr = osc_set_midi(ptr, end, m);

	if(ptr && osc_check_message(buf, len))
	{
		if(tjost_pipe_produce(&dat->pipe, module, 0, len, buf))
			fprintf(stderr, MOD_NAME": tjost_pipe_produce error\n");
	}
	else
		fprintf(stderr, MOD_NAME": rx OSC message invalid\n");
}
static osc_data_t * 
oscmidi_engine_off_cb(osc_data_t *buf, osc_data_t *end, CMC_Blob_Event *bev)
{
	osc_data_t *buf_ptr = buf;
	osc_data_t *itm = NULL;
	OSC_MIDI_Format format = config.oscmidi.format;
	uint_fast8_t multi = config.oscmidi.multi;
	uint_fast8_t use_mpe = config.oscmidi.mpe;

	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]);
	}

	uint8_t key;
	uint8_t ch;
	midi_rem_key(oscmidi_hash, bev->sid, &key, &ch);
	if(use_mpe)
		mpe_release(&mpe, bev->gid, ch);

	// serialize
	buf_ptr = oscmidi_serialize(buf_ptr, end, format, ch, MIDI_STATUS_NOTE_OFF, key, 0x7f);

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

	return buf_ptr;
}
static osc_data_t *
oscmidi_engine_on_cb(osc_data_t *buf, osc_data_t *end, CMC_Blob_Event *bev)
{
	osc_data_t *buf_ptr = buf;
	osc_data_t *itm = NULL;
	OSC_MIDI_Format format = config.oscmidi.format;
	uint_fast8_t multi = config.oscmidi.multi;
	uint_fast8_t use_mpe = config.oscmidi.mpe;
	OSC_MIDI_Group *group = &oscmidi_groups[bev->gid];
	OSC_MIDI_Mapping mapping = group->mapping;

	if(multi)
	{
		buf_ptr = osc_start_bundle_item(buf_ptr, end, &itm);
		buf_ptr = osc_set_path(buf_ptr, end, config.oscmidi.path);
		if( (mapping == OSC_MIDI_MAPPING_CONTROL_CHANGE) && (group->control <= 0xd) )
			buf_ptr = osc_set_fmt(buf_ptr, end, oscmidi_fmt_4[format]);
		else
			buf_ptr = osc_set_fmt(buf_ptr, end, oscmidi_fmt_3[format]);
	}

	uint8_t ch;
	if(use_mpe)
		ch = mpe_acquire(&mpe, bev->gid);
	else
		ch = bev->gid;
	float X = group->offset + bev->x*group->range;
	uint8_t key = floor(X);
	midi_add_key(oscmidi_hash, bev->sid, key, ch);

	uint16_t bend =(X - key)*mul[bev->gid] + 0x1fff;
	uint16_t eff = bev->y * 0x3fff;

	// serialize
	buf_ptr = oscmidi_serialize(buf_ptr, end, format, ch, MIDI_STATUS_NOTE_ON, key, 0x7f);
	buf_ptr = oscmidi_serialize(buf_ptr, end, format, ch, MIDI_STATUS_PITCH_BEND, bend & 0x7f, bend >> 7);
	switch(mapping)
	{
		case OSC_MIDI_MAPPING_NOTE_PRESSURE:
			buf_ptr = oscmidi_serialize(buf_ptr, end, format, ch, MIDI_STATUS_NOTE_PRESSURE, key, eff >> 7);
			break;
		case OSC_MIDI_MAPPING_CHANNEL_PRESSURE:
			buf_ptr = oscmidi_serialize(buf_ptr, end, format, ch, MIDI_STATUS_CHANNEL_PRESSURE, eff >> 7, 0x0);
			break;
		case OSC_MIDI_MAPPING_CONTROL_CHANGE:
			if(group->control <= 0xd)
				buf_ptr = oscmidi_serialize(buf_ptr, end, format, ch, MIDI_STATUS_CONTROL_CHANGE, group->control | MIDI_LSV, eff & 0x7f);
			buf_ptr = oscmidi_serialize(buf_ptr, end, format, ch, MIDI_STATUS_CONTROL_CHANGE, group->control | MIDI_MSV, eff >> 7);
			break;
	}
	
	if(multi)
		buf_ptr = osc_end_bundle_item(buf_ptr, end, itm);

	return buf_ptr;
}
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;
}
static osc_data_t *
oscmidi_engine_frame_cb(osc_data_t *buf, osc_data_t *end, CMC_Frame_Event *fev)
{
	osc_data_t *buf_ptr = buf;

	if(cmc_engines_active + config.dump.enabled > 1)
		buf_ptr = osc_start_bundle_item(buf_ptr, end, &pack);
	buf_ptr = osc_start_bundle(buf_ptr, end, fev->offset, &bndl);

	if(update_zones)
	{
		OSC_MIDI_Format format = config.oscmidi.format;
		uint_fast8_t multi = config.oscmidi.multi;
		osc_data_t *itm = NULL;

		for(uint8_t z=0; z<cmc_groups_n; z++)
		{
			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, "mmmmmm");
			}

			const zone_t *zone = &mpe.zones[z];

			// define zone span
			buf_ptr = oscmidi_serialize(buf_ptr, end, format, zone->base, MIDI_STATUS_CONTROL_CHANGE, MIDI_CONTROLLER_RPN_LSB, 0x6);
			buf_ptr = oscmidi_serialize(buf_ptr, end, format, zone->base, MIDI_STATUS_CONTROL_CHANGE, MIDI_CONTROLLER_RPN_MSB, 0x0);
			buf_ptr = oscmidi_serialize(buf_ptr, end, format, zone->base, MIDI_STATUS_CONTROL_CHANGE, MIDI_CONTROLLER_DATA_ENTRY, zone->span);

			// define zone bend range
			buf_ptr = oscmidi_serialize(buf_ptr, end, format, zone->base+1, MIDI_STATUS_CONTROL_CHANGE, MIDI_CONTROLLER_RPN_LSB, 0x0);
			buf_ptr = oscmidi_serialize(buf_ptr, end, format, zone->base+1, MIDI_STATUS_CONTROL_CHANGE, MIDI_CONTROLLER_RPN_MSB, 0x0);
			const uint8_t semitone_range = ceil(oscmidi_groups[z].range);
			buf_ptr = oscmidi_serialize(buf_ptr, end, format, zone->base+1, MIDI_STATUS_CONTROL_CHANGE, MIDI_CONTROLLER_DATA_ENTRY, semitone_range);

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

		update_zones = 0;
	}

	return buf_ptr;
}
示例#6
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;
}