modules: accept and produce UMP only

This commit is contained in:
Wim Taymans 2024-07-26 15:20:14 +02:00
parent 40cd8535eb
commit d9e7a10b0d
11 changed files with 199 additions and 126 deletions

View file

@ -23,6 +23,7 @@
#include <spa/utils/ringbuffer.h> #include <spa/utils/ringbuffer.h>
#include <spa/monitor/device.h> #include <spa/monitor/device.h>
#include <spa/control/control.h> #include <spa/control/control.h>
#include <spa/control/ump-utils.h>
#include <spa/node/node.h> #include <spa/node/node.h>
#include <spa/node/utils.h> #include <spa/node/utils.h>
@ -449,7 +450,7 @@ static void midi_event_recv(void *user_data, uint16_t timestamp, uint8_t *data,
struct impl *this = user_data; struct impl *this = user_data;
struct port *port = &this->ports[PORT_OUT]; struct port *port = &this->ports[PORT_OUT];
struct time_sync *sync = &port->sync; struct time_sync *sync = &port->sync;
uint64_t time; uint64_t time, state = 0;
int res; int res;
spa_assert(size > 0); spa_assert(size > 0);
@ -459,11 +460,19 @@ static void midi_event_recv(void *user_data, uint16_t timestamp, uint8_t *data,
spa_log_trace(this->log, "%p: event:0x%x size:%d timestamp:%d time:%"PRIu64"", spa_log_trace(this->log, "%p: event:0x%x size:%d timestamp:%d time:%"PRIu64"",
this, (int)data[0], (int)size, (int)timestamp, (uint64_t)time); this, (int)data[0], (int)size, (int)timestamp, (uint64_t)time);
res = midi_event_ringbuffer_push(&this->event_rbuf, time, data, size); while (size > 0) {
if (res < 0) { uint32_t ump[4];
midi_event_ringbuffer_init(&this->event_rbuf); int ump_size = spa_ump_from_midi(&data, &size,
spa_log_warn(this->log, "%p: MIDI receive buffer overflow: %s", ump, sizeof(ump), 0, &state);
this, spa_strerror(res)); if (ump_size <= 0)
break;
res = midi_event_ringbuffer_push(&this->event_rbuf, time, (uint8_t*)ump, ump_size);
if (res < 0) {
midi_event_ringbuffer_init(&this->event_rbuf);
spa_log_warn(this->log, "%p: MIDI receive buffer overflow: %s",
this, spa_strerror(res));
}
} }
} }
@ -704,7 +713,7 @@ static int process_output(struct impl *this)
offset = time * this->rate / SPA_NSEC_PER_SEC; offset = time * this->rate / SPA_NSEC_PER_SEC;
offset = SPA_CLAMP(offset, 0u, this->duration - 1); offset = SPA_CLAMP(offset, 0u, this->duration - 1);
spa_pod_builder_control(&port->builder, offset, SPA_CONTROL_Midi); spa_pod_builder_control(&port->builder, offset, SPA_CONTROL_UMP);
buf = spa_pod_builder_reserve_bytes(&port->builder, size); buf = spa_pod_builder_reserve_bytes(&port->builder, size);
if (buf) { if (buf) {
midi_event_ringbuffer_pop(&this->event_rbuf, buf, size); midi_event_ringbuffer_pop(&this->event_rbuf, buf, size);
@ -773,15 +782,18 @@ static int write_data(struct impl *this, struct spa_data *d)
time = 0; time = 0;
SPA_POD_SEQUENCE_FOREACH(pod, c) { SPA_POD_SEQUENCE_FOREACH(pod, c) {
uint8_t *event; int size;
size_t size; uint8_t event[32];
if (c->type != SPA_CONTROL_Midi) if (c->type != SPA_CONTROL_UMP)
continue; continue;
time = SPA_MAX(time, this->current_time + c->offset * SPA_NSEC_PER_SEC / this->rate); time = SPA_MAX(time, this->current_time + c->offset * SPA_NSEC_PER_SEC / this->rate);
event = SPA_POD_BODY(&c->value);
size = SPA_POD_BODY_SIZE(&c->value); size = spa_ump_to_midi(SPA_POD_BODY(&c->value),
SPA_POD_BODY_SIZE(&c->value), event, sizeof(event));
if (size <= 0)
continue;
spa_log_trace(this->log, "%p: output event:0x%x time:%"PRIu64, this, spa_log_trace(this->log, "%p: output event:0x%x time:%"PRIu64, this,
(size > 0) ? event[0] : 0, time); (size > 0) ? event[0] : 0, time);
@ -1555,7 +1567,8 @@ next:
param = spa_pod_builder_add_object(&b, param = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application), SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control)); SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control),
SPA_FORMAT_CONTROL_types, SPA_POD_CHOICE_FLAGS_Int(1u<<SPA_CONTROL_UMP));
break; break;
case SPA_PARAM_Format: case SPA_PARAM_Format:
@ -1567,7 +1580,8 @@ next:
param = spa_pod_builder_add_object(&b, param = spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Format, SPA_PARAM_Format, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application), SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control)); SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control),
SPA_FORMAT_CONTROL_types, SPA_POD_Int(1u<<SPA_CONTROL_UMP));
break; break;
case SPA_PARAM_Buffers: case SPA_PARAM_Buffers:
@ -2008,13 +2022,13 @@ impl_init(const struct spa_handle_factory *factory,
for (i = 0; i < N_PORTS; ++i) { for (i = 0; i < N_PORTS; ++i) {
struct port *port = &this->ports[i]; struct port *port = &this->ports[i];
static const struct spa_dict_item in_port_items[] = { static const struct spa_dict_item in_port_items[] = {
SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "8 bit raw midi"), SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "32 bit raw UMP"),
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, "in"), SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, "in"),
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_ALIAS, "in"), SPA_DICT_ITEM_INIT(SPA_KEY_PORT_ALIAS, "in"),
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_GROUP, "group.0"), SPA_DICT_ITEM_INIT(SPA_KEY_PORT_GROUP, "group.0"),
}; };
static const struct spa_dict_item out_port_items[] = { static const struct spa_dict_item out_port_items[] = {
SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "8 bit raw midi"), SPA_DICT_ITEM_INIT(SPA_KEY_FORMAT_DSP, "32 bit raw UMP"),
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, "out"), SPA_DICT_ITEM_INIT(SPA_KEY_PORT_NAME, "out"),
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_ALIAS, "out"), SPA_DICT_ITEM_INIT(SPA_KEY_PORT_ALIAS, "out"),
SPA_DICT_ITEM_INIT(SPA_KEY_PORT_GROUP, "group.0"), SPA_DICT_ITEM_INIT(SPA_KEY_PORT_GROUP, "group.0"),

View file

@ -103,7 +103,7 @@ static void on_process(void *userdata, struct spa_io_position *position)
while (sample_offset < position->clock.duration) { while (sample_offset < position->clock.duration) {
if (cycle % 2 == 0) { if (cycle % 2 == 0) {
/* MIDI note on, channel 0, middle C, max velocity */ /* MIDI note on, channel 0, middle C, max velocity */
uint8_t buf[] = { 0x90, 0x3c, 0x7f }; uint32_t event = 0x20903c7f;
/* The time position of the message in the graph cycle /* The time position of the message in the graph cycle
* is given as offset from the cycle start, in * is given as offset from the cycle start, in
@ -111,18 +111,18 @@ static void on_process(void *userdata, struct spa_io_position *position)
* samples, and the sample offset should satisfy * samples, and the sample offset should satisfy
* 0 <= sample_offset < position->clock.duration. * 0 <= sample_offset < position->clock.duration.
*/ */
spa_pod_builder_control(&builder, sample_offset, SPA_CONTROL_Midi); spa_pod_builder_control(&builder, sample_offset, SPA_CONTROL_UMP);
/* Raw MIDI data for the message */ /* Raw MIDI data for the message */
spa_pod_builder_bytes(&builder, buf, sizeof(buf)); spa_pod_builder_bytes(&builder, &event, sizeof(event));
pw_log_info("note on at %"PRIu64, sample_position + sample_offset); pw_log_info("note on at %"PRIu64, sample_position + sample_offset);
} else { } else {
/* MIDI note off, channel 0, middle C, max velocity */ /* MIDI note off, channel 0, middle C, max velocity */
uint8_t buf[] = { 0x80, 0x3c, 0x7f }; uint32_t event = 0x20803c7f;
spa_pod_builder_control(&builder, sample_offset, SPA_CONTROL_Midi); spa_pod_builder_control(&builder, sample_offset, SPA_CONTROL_UMP);
spa_pod_builder_bytes(&builder, buf, sizeof(buf)); spa_pod_builder_bytes(&builder, &event, sizeof(event));
pw_log_info("note off at %"PRIu64, sample_position + sample_offset); pw_log_info("note off at %"PRIu64, sample_position + sample_offset);
} }
@ -213,7 +213,7 @@ int main(int argc, char *argv[])
PW_FILTER_PORT_FLAG_MAP_BUFFERS, PW_FILTER_PORT_FLAG_MAP_BUFFERS,
sizeof(struct port), sizeof(struct port),
pw_properties_new( pw_properties_new(
PW_KEY_FORMAT_DSP, "8 bit raw midi", PW_KEY_FORMAT_DSP, "32 bit raw UMP",
PW_KEY_PORT_NAME, "output", PW_KEY_PORT_NAME, "output",
NULL), NULL),
NULL, 0); NULL, 0);

View file

@ -24,6 +24,7 @@
#include <spa/param/audio/format-utils.h> #include <spa/param/audio/format-utils.h>
#include <spa/param/latency-utils.h> #include <spa/param/latency-utils.h>
#include <spa/param/audio/raw.h> #include <spa/param/audio/raw.h>
#include <spa/control/ump-utils.h>
#include <pipewire/impl.h> #include <pipewire/impl.h>
#include <pipewire/i18n.h> #include <pipewire/i18n.h>
@ -333,30 +334,30 @@ static void midi_to_ffado(struct port *p, float *src, uint32_t n_samples)
p->event_pos = 0; p->event_pos = 0;
SPA_POD_SEQUENCE_FOREACH(seq, c) { SPA_POD_SEQUENCE_FOREACH(seq, c) {
switch(c->type) { uint8_t data[16];
case SPA_CONTROL_Midi: int j, size;
{
uint8_t *data = SPA_POD_BODY(&c->value);
size_t size = SPA_POD_BODY_SIZE(&c->value);
if (index < c->offset) if (c->type != SPA_CONTROL_UMP)
index = SPA_ROUND_UP_N(c->offset, 8); continue;
for (i = 0; i < size; i++) {
if (index >= n_samples) { size = spa_ump_to_midi(SPA_POD_BODY(&c->value),
/* keep events that don't fit for the next cycle */ SPA_POD_BODY_SIZE(&c->value), data, sizeof(data));
if (p->event_pos < sizeof(p->event_buffer)) if (size <= 0)
p->event_buffer[p->event_pos++] = data[i]; continue;
else
unhandled++; if (index < c->offset)
} index = SPA_ROUND_UP_N(c->offset, 8);
for (j = 0; j < size; j++) {
if (index >= n_samples) {
/* keep events that don't fit for the next cycle */
if (p->event_pos < sizeof(p->event_buffer))
p->event_buffer[p->event_pos++] = data[j];
else else
dst[index] = 0x01000000 | (uint32_t) data[i]; unhandled++;
index += 8;
} }
break; else
} dst[index] = 0x01000000 | (uint32_t) data[j];
default: index += 8;
break;
} }
} }
if (unhandled > 0) if (unhandled > 0)
@ -481,8 +482,16 @@ static void ffado_to_midi(struct port *p, float *dst, uint32_t *src, uint32_t si
continue; continue;
if (process_byte(p, i, data & 0xff, &frame, &bytes, &size)) { if (process_byte(p, i, data & 0xff, &frame, &bytes, &size)) {
spa_pod_builder_control(&b, frame, SPA_CONTROL_Midi); uint64_t state = 0;
spa_pod_builder_bytes(&b, bytes, size); while (size > 0) {
uint32_t ev[4];
int ev_size = spa_ump_from_midi(&bytes, &size, ev, sizeof(ev), 0, &state);
if (ev_size <= 0)
break;
spa_pod_builder_control(&b, frame, SPA_CONTROL_UMP);
spa_pod_builder_bytes(&b, ev, ev_size);
}
} }
} }
spa_pod_builder_pop(&b, &f); spa_pod_builder_pop(&b, &f);
@ -733,7 +742,7 @@ static int make_stream_ports(struct stream *s)
break; break;
case ffado_stream_type_midi: case ffado_stream_type_midi:
props = pw_properties_new( props = pw_properties_new(
PW_KEY_FORMAT_DSP, "8 bit raw midi", PW_KEY_FORMAT_DSP, "32 bit raw UMP",
PW_KEY_PORT_NAME, port->name, PW_KEY_PORT_NAME, port->name,
PW_KEY_PORT_PHYSICAL, "true", PW_KEY_PORT_PHYSICAL, "true",
PW_KEY_PORT_TERMINAL, "true", PW_KEY_PORT_TERMINAL, "true",

View file

@ -24,6 +24,7 @@
#include <spa/param/audio/format-utils.h> #include <spa/param/audio/format-utils.h>
#include <spa/param/latency-utils.h> #include <spa/param/latency-utils.h>
#include <spa/param/audio/raw.h> #include <spa/param/audio/raw.h>
#include <spa/control/ump-utils.h>
#include <pipewire/impl.h> #include <pipewire/impl.h>
#include <pipewire/i18n.h> #include <pipewire/i18n.h>
@ -254,23 +255,23 @@ static void midi_to_jack(struct impl *impl, float *dst, float *src, uint32_t n_s
seq = (struct spa_pod_sequence*)pod; seq = (struct spa_pod_sequence*)pod;
SPA_POD_SEQUENCE_FOREACH(seq, c) { SPA_POD_SEQUENCE_FOREACH(seq, c) {
switch(c->type) { uint8_t data[16];
case SPA_CONTROL_Midi: int size;
{
uint8_t *data = SPA_POD_BODY(&c->value);
size_t size = SPA_POD_BODY_SIZE(&c->value);
if (impl->fix_midi) if (c->type != SPA_CONTROL_UMP)
fix_midi_event(data, size); continue;
if ((res = jack.midi_event_write(dst, c->offset, data, size)) < 0) size = spa_ump_to_midi(SPA_POD_BODY(&c->value),
pw_log_warn("midi %p: can't write event: %s", dst, SPA_POD_BODY_SIZE(&c->value), data, sizeof(data));
spa_strerror(res)); if (size <= 0)
break; continue;
}
default: if (impl->fix_midi)
break; fix_midi_event(data, size);
}
if ((res = jack.midi_event_write(dst, c->offset, data, size)) < 0)
pw_log_warn("midi %p: can't write event: %s", dst,
spa_strerror(res));
} }
} }
@ -286,9 +287,19 @@ static void jack_to_midi(float *dst, float *src, uint32_t size)
spa_pod_builder_push_sequence(&b, &f, 0); spa_pod_builder_push_sequence(&b, &f, 0);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
jack_midi_event_t ev; jack_midi_event_t ev;
uint64_t state = 0;
jack.midi_event_get(&ev, src, i); jack.midi_event_get(&ev, src, i);
spa_pod_builder_control(&b, ev.time, SPA_CONTROL_Midi);
spa_pod_builder_bytes(&b, ev.buffer, ev.size); while (ev.size > 0) {
uint32_t ump[4];
int ump_size = spa_ump_from_midi(&ev.buffer, &ev.size, ump, sizeof(ump), 0, &state);
if (ump_size <= 0)
break;
spa_pod_builder_control(&b, ev.time, SPA_CONTROL_UMP);
spa_pod_builder_bytes(&b, ump, ump_size);
}
} }
spa_pod_builder_pop(&b, &f); spa_pod_builder_pop(&b, &f);
} }
@ -487,7 +498,7 @@ static void make_stream_ports(struct stream *s)
} else { } else {
snprintf(name, sizeof(name), "%s_%d", prefix, i - s->info.channels); snprintf(name, sizeof(name), "%s_%d", prefix, i - s->info.channels);
props = pw_properties_new( props = pw_properties_new(
PW_KEY_FORMAT_DSP, "8 bit raw midi", PW_KEY_FORMAT_DSP, "32 bit raw UMP",
PW_KEY_PORT_NAME, name, PW_KEY_PORT_NAME, name,
PW_KEY_PORT_PHYSICAL, "true", PW_KEY_PORT_PHYSICAL, "true",
NULL); NULL);

View file

@ -422,7 +422,7 @@ static void make_stream_ports(struct stream *s)
} else { } else {
snprintf(name, sizeof(name), "midi%d", i - s->info.channels); snprintf(name, sizeof(name), "midi%d", i - s->info.channels);
props = pw_properties_new( props = pw_properties_new(
PW_KEY_FORMAT_DSP, "8 bit raw midi", PW_KEY_FORMAT_DSP, "32 bit raw UMP",
PW_KEY_AUDIO_CHANNEL, name, PW_KEY_AUDIO_CHANNEL, name,
PW_KEY_PORT_PHYSICAL, "true", PW_KEY_PORT_PHYSICAL, "true",
NULL); NULL);

View file

@ -543,7 +543,7 @@ static void make_stream_ports(struct stream *s)
} else { } else {
snprintf(name, sizeof(name), "midi%d", i - s->info.channels); snprintf(name, sizeof(name), "midi%d", i - s->info.channels);
props = pw_properties_new( props = pw_properties_new(
PW_KEY_FORMAT_DSP, "8 bit raw midi", PW_KEY_FORMAT_DSP, "32 bit raw UMP",
PW_KEY_PORT_PHYSICAL, "true", PW_KEY_PORT_PHYSICAL, "true",
PW_KEY_AUDIO_CHANNEL, name, PW_KEY_AUDIO_CHANNEL, name,
NULL); NULL);

View file

@ -1,5 +1,6 @@
#include <spa/utils/endian.h> #include <spa/utils/endian.h>
#include <spa/control/ump-utils.h>
#ifdef HAVE_OPUS_CUSTOM #ifdef HAVE_OPUS_CUSTOM
#include <opus/opus.h> #include <opus/opus.h>
@ -248,7 +249,7 @@ static void midi_to_netjack2(struct netjack2_peer *peer,
struct spa_pod_sequence *seq; struct spa_pod_sequence *seq;
struct spa_pod_control *c; struct spa_pod_control *c;
struct nj2_midi_event *ev; struct nj2_midi_event *ev;
uint32_t free_size; int free_size;
buf->magic = MIDI_BUFFER_MAGIC; buf->magic = MIDI_BUFFER_MAGIC;
buf->buffer_size = peer->quantum_limit * sizeof(float); buf->buffer_size = peer->quantum_limit * sizeof(float);
@ -271,40 +272,41 @@ static void midi_to_netjack2(struct netjack2_peer *peer,
free_size = buf->buffer_size - sizeof(*buf); free_size = buf->buffer_size - sizeof(*buf);
SPA_POD_SEQUENCE_FOREACH(seq, c) { SPA_POD_SEQUENCE_FOREACH(seq, c) {
switch(c->type) { int size;
case SPA_CONTROL_Midi: uint8_t data[16];
{ void *ptr;
uint8_t *data = SPA_POD_BODY(&c->value);
size_t size = SPA_POD_BODY_SIZE(&c->value);
void *ptr;
if (c->offset >= n_samples || if (c->type != SPA_CONTROL_UMP)
size >= free_size) { continue;
buf->lost_events++;
continue;
}
if (peer->fix_midi)
fix_midi_event(data, size);
ev = &buf->event[buf->event_count]; size = spa_ump_to_midi(SPA_POD_BODY(&c->value),
ev->time = c->offset; SPA_POD_BODY_SIZE(&c->value), data, sizeof(data));
ev->size = size; if (size <= 0)
if (size <= MIDI_INLINE_MAX) { continue;
ptr = ev->buffer;
} else { if (c->offset >= n_samples ||
buf->write_pos += size; size >= free_size) {
ev->offset = buf->buffer_size - 1 - buf->write_pos; buf->lost_events++;
free_size -= size; continue;
ptr = SPA_PTROFF(buf, ev->offset, void);
}
memcpy(ptr, data, size);
buf->event_count++;
free_size -= sizeof(*ev);
break;
} }
default:
break; if (peer->fix_midi)
fix_midi_event(data, size);
ev = &buf->event[buf->event_count];
ev->time = c->offset;
ev->size = size;
if (size <= MIDI_INLINE_MAX) {
ptr = ev->buffer;
} else {
buf->write_pos += size;
ev->offset = buf->buffer_size - 1 - buf->write_pos;
free_size -= size;
ptr = SPA_PTROFF(buf, ev->offset, void);
} }
memcpy(ptr, data, size);
buf->event_count++;
free_size -= sizeof(*ev);
} }
if (buf->write_pos > 0) if (buf->write_pos > 0)
memmove(SPA_PTROFF(buf, sizeof(*buf) + buf->event_count * sizeof(struct nj2_midi_event), void), memmove(SPA_PTROFF(buf, sizeof(*buf) + buf->event_count * sizeof(struct nj2_midi_event), void),
@ -322,7 +324,9 @@ static inline void netjack2_to_midi(float *dst, uint32_t size, struct nj2_midi_b
spa_pod_builder_push_sequence(&b, &f, 0); spa_pod_builder_push_sequence(&b, &f, 0);
for (i = 0; buf != NULL && i < buf->event_count; i++) { for (i = 0; buf != NULL && i < buf->event_count; i++) {
struct nj2_midi_event *ev = &buf->event[i]; struct nj2_midi_event *ev = &buf->event[i];
void *data; uint8_t *data;
size_t s;
uint64_t state = 0;
if (ev->size <= MIDI_INLINE_MAX) if (ev->size <= MIDI_INLINE_MAX)
data = ev->buffer; data = ev->buffer;
@ -331,8 +335,16 @@ static inline void netjack2_to_midi(float *dst, uint32_t size, struct nj2_midi_b
else else
continue; continue;
spa_pod_builder_control(&b, ev->time, SPA_CONTROL_Midi); s = ev->size;
spa_pod_builder_bytes(&b, data, ev->size); while (s > 0) {
uint32_t ump[4];
int ump_size = spa_ump_from_midi(&data, &s, ump, sizeof(ump), 0, &state);
if (ump_size <= 0)
break;
spa_pod_builder_control(&b, ev->time, SPA_CONTROL_UMP);
spa_pod_builder_bytes(&b, ump, ump_size);
}
} }
spa_pod_builder_pop(&b, &f); spa_pod_builder_pop(&b, &f);
} }

View file

@ -66,7 +66,7 @@ static void rtp_midi_process_playback(void *data)
} else { } else {
timestamp = target; timestamp = target;
} }
spa_pod_builder_control(&b, target - timestamp, SPA_CONTROL_Midi); spa_pod_builder_control(&b, target - timestamp, c->type);
spa_pod_builder_bytes(&b, spa_pod_builder_bytes(&b,
SPA_POD_BODY(&c->value), SPA_POD_BODY(&c->value),
SPA_POD_BODY_SIZE(&c->value)); SPA_POD_BODY_SIZE(&c->value));
@ -242,25 +242,34 @@ static int rtp_midi_receive_midi(struct impl *impl, uint8_t *packet, uint32_t ti
while (offs < end) { while (offs < end) {
uint32_t delta; uint32_t delta;
int size; int size;
uint64_t state = 0;
uint8_t *d;
size_t s;
if (first && !hdr->z) if (first && !hdr->z)
delta = 0; delta = 0;
else else
offs += parse_varlen(&packet[offs], end - offs, &delta); offs += parse_varlen(&packet[offs], end - offs, &delta);
timestamp += (uint32_t)(delta * impl->corr); timestamp += (uint32_t)(delta * impl->corr);
spa_pod_builder_control(&b, timestamp, SPA_CONTROL_Midi);
size = get_midi_size(&packet[offs], end - offs); size = get_midi_size(&packet[offs], end - offs);
if (size <= 0 || offs + size > end) { if (size <= 0 || offs + size > end) {
pw_log_warn("invalid size (%08x) %d (%u %u)", pw_log_warn("invalid size (%08x) %d (%u %u)",
packet[offs], size, offs, end); packet[offs], size, offs, end);
break; break;
} }
spa_pod_builder_bytes(&b, &packet[offs], size); d = &packet[offs];
s = size;
while (s > 0) {
uint32_t ump[4];
int ump_size = spa_ump_from_midi(&d, &s, ump, sizeof(ump), 0, &state);
if (ump_size <= 0)
break;
spa_pod_builder_control(&b, timestamp, SPA_CONTROL_UMP);
spa_pod_builder_bytes(&b, ump, ump_size);
}
offs += size; offs += size;
first = false; first = false;
} }
@ -373,14 +382,17 @@ static void rtp_midi_flush_packets(struct impl *impl,
prev_offset = len = base = 0; prev_offset = len = base = 0;
SPA_POD_SEQUENCE_FOREACH(sequence, c) { SPA_POD_SEQUENCE_FOREACH(sequence, c) {
void *ev; uint32_t delta, offset;
uint32_t size, delta, offset; uint8_t event[16];
size_t size;
if (c->type != SPA_CONTROL_Midi) if (c->type != SPA_CONTROL_UMP)
continue; continue;
ev = SPA_POD_BODY(&c->value), size = spa_ump_to_midi(SPA_POD_BODY(&c->value),
size = SPA_POD_BODY_SIZE(&c->value); SPA_POD_BODY_SIZE(&c->value), event, sizeof(event));
if (size <= 0)
continue;
offset = c->offset * impl->rate / rate; offset = c->offset * impl->rate / rate;
@ -414,12 +426,12 @@ static void rtp_midi_flush_packets(struct impl *impl,
header.sequence_number = htons(impl->seq); header.sequence_number = htons(impl->seq);
header.timestamp = htonl(impl->ts_offset + timestamp + base); header.timestamp = htonl(impl->ts_offset + timestamp + base);
memcpy(&impl->buffer[len], ev, size); memcpy(&impl->buffer[len], event, size);
len += size; len += size;
} else { } else {
delta = offset - prev_offset; delta = offset - prev_offset;
prev_offset = offset; prev_offset = offset;
len += write_event(&impl->buffer[len], delta, ev, size); len += write_event(&impl->buffer[len], delta, event, size);
} }
} }
if (len > 0) { if (len > 0) {

View file

@ -11,6 +11,7 @@
#include <spa/utils/dll.h> #include <spa/utils/dll.h>
#include <spa/param/audio/format-utils.h> #include <spa/param/audio/format-utils.h>
#include <spa/control/control.h> #include <spa/control/control.h>
#include <spa/control/ump-utils.h>
#include <spa/debug/types.h> #include <spa/debug/types.h>
#include <spa/debug/mem.h> #include <spa/debug/mem.h>
#include <spa/debug/log.h> #include <spa/debug/log.h>
@ -385,7 +386,7 @@ struct rtp_stream *rtp_stream_new(struct pw_core *core,
res = -EINVAL; res = -EINVAL;
goto out; goto out;
} }
pw_properties_set(props, PW_KEY_FORMAT_DSP, "8 bit raw midi"); pw_properties_set(props, PW_KEY_FORMAT_DSP, "32 bit raw UMP");
impl->stride = impl->format_info->size; impl->stride = impl->format_info->size;
impl->rate = pw_properties_get_uint32(props, "midi.rate", 10000); impl->rate = pw_properties_get_uint32(props, "midi.rate", 10000);
if (impl->rate == 0) if (impl->rate == 0)

View file

@ -67,7 +67,7 @@ static void vban_midi_process_playback(void *data)
} else { } else {
timestamp = target; timestamp = target;
} }
spa_pod_builder_control(&b, target - timestamp, SPA_CONTROL_Midi); spa_pod_builder_control(&b, target - timestamp, c->type);
spa_pod_builder_bytes(&b, spa_pod_builder_bytes(&b,
SPA_POD_BODY(&c->value), SPA_POD_BODY(&c->value),
SPA_POD_BODY_SIZE(&c->value)); SPA_POD_BODY_SIZE(&c->value));
@ -162,19 +162,29 @@ static int vban_midi_receive_midi(struct impl *impl, uint8_t *packet,
while (offs < plen) { while (offs < plen) {
int size; int size;
uint8_t *midi_data;
spa_pod_builder_control(&b, timestamp, SPA_CONTROL_Midi); size_t midi_size;
uint64_t midi_state = 0;
size = get_midi_size(&packet[offs], plen - offs); size = get_midi_size(&packet[offs], plen - offs);
if (size <= 0 || offs + size > plen) { if (size <= 0 || offs + size > plen) {
pw_log_warn("invalid size (%08x) %d (%u %u)", pw_log_warn("invalid size (%08x) %d (%u %u)",
packet[offs], size, offs, plen); packet[offs], size, offs, plen);
break; break;
} }
spa_pod_builder_bytes(&b, &packet[offs], size); midi_data = &packet[offs];
midi_size = size;
while (midi_size > 0) {
uint32_t ump[4];
int ump_size = spa_ump_from_midi(&midi_data, &midi_size,
ump, sizeof(ump), 0, &midi_state);
if (ump_size <= 0)
break;
spa_pod_builder_control(&b, timestamp, SPA_CONTROL_UMP);
spa_pod_builder_bytes(&b, ump, ump_size);
}
offs += size; offs += size;
} }
spa_pod_builder_pop(&b, &f[0]); spa_pod_builder_pop(&b, &f[0]);
@ -239,14 +249,17 @@ static void vban_midi_flush_packets(struct impl *impl,
len = 0; len = 0;
SPA_POD_SEQUENCE_FOREACH(sequence, c) { SPA_POD_SEQUENCE_FOREACH(sequence, c) {
void *ev; int size;
uint32_t size; uint8_t event[16];
if (c->type != SPA_CONTROL_Midi) if (c->type != SPA_CONTROL_UMP)
continue;
size = spa_ump_to_midi(SPA_POD_BODY(&c->value),
SPA_POD_BODY_SIZE(&c->value), event, sizeof(event));
if (size <= 0)
continue; continue;
ev = SPA_POD_BODY(&c->value),
size = SPA_POD_BODY_SIZE(&c->value);
if (len == 0) { if (len == 0) {
/* start new packet */ /* start new packet */
header.n_frames++; header.n_frames++;
@ -258,7 +271,7 @@ static void vban_midi_flush_packets(struct impl *impl,
vban_stream_emit_send_packet(impl, iov, 2); vban_stream_emit_send_packet(impl, iov, 2);
len = 0; len = 0;
} }
memcpy(&impl->buffer[len], ev, size); memcpy(&impl->buffer[len], event, size);
len += size; len += size;
} }
if (len > 0) { if (len > 0) {

View file

@ -11,6 +11,7 @@
#include <spa/utils/dll.h> #include <spa/utils/dll.h>
#include <spa/param/audio/format-utils.h> #include <spa/param/audio/format-utils.h>
#include <spa/control/control.h> #include <spa/control/control.h>
#include <spa/control/ump-utils.h>
#include <spa/debug/types.h> #include <spa/debug/types.h>
#include <spa/debug/mem.h> #include <spa/debug/mem.h>
#include <spa/debug/log.h> #include <spa/debug/log.h>
@ -325,7 +326,7 @@ struct vban_stream *vban_stream_new(struct pw_core *core,
res = -EINVAL; res = -EINVAL;
goto out; goto out;
} }
pw_properties_set(props, PW_KEY_FORMAT_DSP, "8 bit raw midi"); pw_properties_set(props, PW_KEY_FORMAT_DSP, "32 bit raw UMP");
impl->stride = impl->format_info->size; impl->stride = impl->format_info->size;
impl->rate = pw_properties_get_uint32(props, "midi.rate", 10000); impl->rate = pw_properties_get_uint32(props, "midi.rate", 10000);
if (impl->rate == 0) if (impl->rate == 0)