mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
jack: Add UMP to MIDI conversions
Add 2 new port format extensions, one for OSC and another for UMP. Make sure we convert the events from UMP/OSC/MIDI to jack events depending on the port type. Try to produce UMP by default.
This commit is contained in:
parent
7b03a41e3d
commit
648ba982d4
2 changed files with 180 additions and 46 deletions
|
|
@ -25,6 +25,13 @@ int jack_get_video_image_size(jack_client_t *client, jack_image_size_t *size);
|
||||||
|
|
||||||
int jack_set_sample_rate (jack_client_t *client, jack_nframes_t nframes);
|
int jack_set_sample_rate (jack_client_t *client, jack_nframes_t nframes);
|
||||||
|
|
||||||
|
/* raw OSC message */
|
||||||
|
#define JACK_DEFAULT_OSC_TYPE "8 bit raw OSC"
|
||||||
|
|
||||||
|
/* MIDI 2.0 UMP type. This contains raw UMP data, which can have MIDI 1.0 or
|
||||||
|
* MIDI 2.0 packets. The data is an array of 32 bit ints. */
|
||||||
|
#define JACK_DEFAULT_UMP_TYPE "32 bit raw UMP"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include <spa/utils/result.h>
|
#include <spa/utils/result.h>
|
||||||
#include <spa/utils/string.h>
|
#include <spa/utils/string.h>
|
||||||
#include <spa/utils/ringbuffer.h>
|
#include <spa/utils/ringbuffer.h>
|
||||||
|
#include <spa/control/ump-utils.h>
|
||||||
|
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
#include <pipewire/private.h>
|
#include <pipewire/private.h>
|
||||||
|
|
@ -39,8 +40,6 @@
|
||||||
#include "pipewire/extensions/metadata.h"
|
#include "pipewire/extensions/metadata.h"
|
||||||
#include "pipewire-jack-extensions.h"
|
#include "pipewire-jack-extensions.h"
|
||||||
|
|
||||||
#define JACK_DEFAULT_VIDEO_TYPE "32 bit float RGBA video"
|
|
||||||
|
|
||||||
/* use 512KB stack per thread - the default is way too high to be feasible
|
/* use 512KB stack per thread - the default is way too high to be feasible
|
||||||
* with mlockall() on many systems */
|
* with mlockall() on many systems */
|
||||||
#define THREAD_STACK 524288
|
#define THREAD_STACK 524288
|
||||||
|
|
@ -65,9 +64,16 @@ PW_LOG_TOPIC_STATIC(jack_log_topic, "jack");
|
||||||
#define PW_LOG_TOPIC_DEFAULT jack_log_topic
|
#define PW_LOG_TOPIC_DEFAULT jack_log_topic
|
||||||
|
|
||||||
#define TYPE_ID_AUDIO 0
|
#define TYPE_ID_AUDIO 0
|
||||||
#define TYPE_ID_MIDI 1
|
#define TYPE_ID_VIDEO 1
|
||||||
#define TYPE_ID_VIDEO 2
|
#define TYPE_ID_MIDI 2
|
||||||
#define TYPE_ID_OTHER 3
|
#define TYPE_ID_OSC 3
|
||||||
|
#define TYPE_ID_UMP 4
|
||||||
|
#define TYPE_ID_OTHER 5
|
||||||
|
|
||||||
|
#define TYPE_ID_IS_EVENT(t) ((t) >= TYPE_ID_MIDI && (t) <= TYPE_ID_UMP)
|
||||||
|
#define TYPE_ID_CAN_OSC(t) ((t) == TYPE_ID_MIDI || (t) == TYPE_ID_OSC)
|
||||||
|
#define TYPE_ID_IS_HIDDEN(t) ((t) >= TYPE_ID_OTHER)
|
||||||
|
#define TYPE_ID_IS_COMPATIBLE(a,b)(((a) == (b)) || (TYPE_ID_IS_EVENT(a) && TYPE_ID_IS_EVENT(b)))
|
||||||
|
|
||||||
#define SELF_CONNECT_ALLOW 0
|
#define SELF_CONNECT_ALLOW 0
|
||||||
#define SELF_CONNECT_FAIL_EXT -1
|
#define SELF_CONNECT_FAIL_EXT -1
|
||||||
|
|
@ -638,7 +644,7 @@ static struct mix *find_port_peer(struct port *port, uint32_t peer_id)
|
||||||
{
|
{
|
||||||
struct mix *mix;
|
struct mix *mix;
|
||||||
spa_list_for_each(mix, &port->mix, port_link) {
|
spa_list_for_each(mix, &port->mix, port_link) {
|
||||||
pw_log_info("%p %d %d", port, mix->peer_id, peer_id);
|
pw_log_trace("%p %d %d", port, mix->peer_id, peer_id);
|
||||||
if (mix->peer_id == peer_id)
|
if (mix->peer_id == peer_id)
|
||||||
return mix;
|
return mix;
|
||||||
}
|
}
|
||||||
|
|
@ -1381,12 +1387,25 @@ static inline bool is_osc(jack_midi_event_t *ev)
|
||||||
return ev->size >= 1 && (ev->buffer[0] == '#' || ev->buffer[0] == '/');
|
return ev->size >= 1 && (ev->buffer[0] == '#' || ev->buffer[0] == '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t convert_from_midi(void *midi, void *buffer, size_t size)
|
static size_t convert_from_event(void *midi, void *buffer, size_t size, uint32_t type)
|
||||||
{
|
{
|
||||||
struct spa_pod_builder b = { 0, };
|
struct spa_pod_builder b = { 0, };
|
||||||
uint32_t i, count;
|
uint32_t i, count;
|
||||||
struct spa_pod_frame f;
|
struct spa_pod_frame f;
|
||||||
|
uint32_t event_type;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
/* we handle MIDI as OSC, check below */
|
||||||
|
event_type = SPA_CONTROL_OSC;
|
||||||
|
break;
|
||||||
|
case TYPE_ID_UMP:
|
||||||
|
event_type = SPA_CONTROL_UMP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
count = jack_midi_get_event_count(midi);
|
count = jack_midi_get_event_count(midi);
|
||||||
|
|
||||||
spa_pod_builder_init(&b, buffer, size);
|
spa_pod_builder_init(&b, buffer, size);
|
||||||
|
|
@ -1395,14 +1414,43 @@ static size_t convert_from_midi(void *midi, void *buffer, size_t size)
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
jack_midi_event_t ev;
|
jack_midi_event_t ev;
|
||||||
jack_midi_event_get(&ev, midi, i);
|
jack_midi_event_get(&ev, midi, i);
|
||||||
spa_pod_builder_control(&b, ev.time,
|
|
||||||
is_osc(&ev) ? SPA_CONTROL_OSC : SPA_CONTROL_Midi);
|
if (type != TYPE_ID_MIDI || is_osc(&ev)) {
|
||||||
spa_pod_builder_bytes(&b, ev.buffer, ev.size);
|
/* no midi port or it's OSC */
|
||||||
|
spa_pod_builder_control(&b, ev.time, event_type);
|
||||||
|
spa_pod_builder_bytes(&b, ev.buffer, ev.size);
|
||||||
|
} else {
|
||||||
|
/* midi port and it's not OSC, convert to UMP */
|
||||||
|
uint8_t *data = ev.buffer;
|
||||||
|
size_t size = ev.size;
|
||||||
|
uint64_t state = 0;
|
||||||
|
|
||||||
|
while (size > 0) {
|
||||||
|
uint32_t ump[4];
|
||||||
|
int ump_size = spa_ump_from_midi(&data, &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);
|
||||||
return b.state.offset;
|
return b.state.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int event_compare(uint8_t s1, uint8_t s2)
|
||||||
|
{
|
||||||
|
/* 11 (controller) > 12 (program change) >
|
||||||
|
* 8 (note off) > 9 (note on) > 10 (aftertouch) >
|
||||||
|
* 13 (channel pressure) > 14 (pitch bend) */
|
||||||
|
static int priotab[] = { 5,4,3,7,6,2,1,0 };
|
||||||
|
if ((s1 & 0xf) != (s2 & 0xf))
|
||||||
|
return 0;
|
||||||
|
return priotab[(s2>>4) & 7] - priotab[(s1>>4) & 7];
|
||||||
|
}
|
||||||
|
|
||||||
static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *b)
|
static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *b)
|
||||||
{
|
{
|
||||||
if (a->offset < b->offset)
|
if (a->offset < b->offset)
|
||||||
|
|
@ -1414,21 +1462,20 @@ static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *
|
||||||
switch(a->type) {
|
switch(a->type) {
|
||||||
case SPA_CONTROL_Midi:
|
case SPA_CONTROL_Midi:
|
||||||
{
|
{
|
||||||
/* 11 (controller) > 12 (program change) >
|
uint8_t *sa = SPA_POD_BODY(&a->value), *sb = SPA_POD_BODY(&b->value);
|
||||||
* 8 (note off) > 9 (note on) > 10 (aftertouch) >
|
if (SPA_POD_BODY_SIZE(&a->value) < 1 || SPA_POD_BODY_SIZE(&b->value) < 1)
|
||||||
* 13 (channel pressure) > 14 (pitch bend) */
|
|
||||||
static int priotab[] = { 5,4,3,7,6,2,1,0 };
|
|
||||||
uint8_t *da, *db;
|
|
||||||
|
|
||||||
if (SPA_POD_BODY_SIZE(&a->value) < 1 ||
|
|
||||||
SPA_POD_BODY_SIZE(&b->value) < 1)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
return event_compare(sa[0], sb[0]);
|
||||||
da = SPA_POD_BODY(&a->value);
|
}
|
||||||
db = SPA_POD_BODY(&b->value);
|
case SPA_CONTROL_UMP:
|
||||||
if ((da[0] & 0xf) != (db[0] & 0xf))
|
{
|
||||||
|
uint32_t *sa = SPA_POD_BODY(&a->value), *sb = SPA_POD_BODY(&b->value);
|
||||||
|
if (SPA_POD_BODY_SIZE(&a->value) < 4 || SPA_POD_BODY_SIZE(&b->value) < 4)
|
||||||
return 0;
|
return 0;
|
||||||
return priotab[(db[0]>>4) & 7] - priotab[(da[0]>>4) & 7];
|
if ((sa[0] >> 28) != 2 || (sa[0] >> 28) != 4 ||
|
||||||
|
(sb[0] >> 28) != 2 || (sb[0] >> 28) != 4)
|
||||||
|
return 0;
|
||||||
|
return event_compare(sa[0] >> 16, sb[0] >> 16);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1487,11 +1534,12 @@ static inline int midi_event_write(void *port_buffer,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void *midi, bool fix)
|
static void convert_to_event(struct spa_pod_sequence **seq, uint32_t n_seq, void *midi, bool fix, uint32_t type)
|
||||||
{
|
{
|
||||||
struct spa_pod_control *c[n_seq];
|
struct spa_pod_control *c[n_seq];
|
||||||
|
uint64_t state = 0;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int res;
|
int res = 0;
|
||||||
|
|
||||||
for (i = 0; i < n_seq; i++)
|
for (i = 0; i < n_seq; i++)
|
||||||
c[i] = spa_pod_control_first(&seq[i]->body);
|
c[i] = spa_pod_control_first(&seq[i]->body);
|
||||||
|
|
@ -1515,16 +1563,51 @@ static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void
|
||||||
|
|
||||||
switch(next->type) {
|
switch(next->type) {
|
||||||
case SPA_CONTROL_OSC:
|
case SPA_CONTROL_OSC:
|
||||||
|
if (!TYPE_ID_CAN_OSC(type))
|
||||||
|
break;
|
||||||
|
SPA_FALLTHROUGH;
|
||||||
case SPA_CONTROL_Midi:
|
case SPA_CONTROL_Midi:
|
||||||
{
|
{
|
||||||
uint8_t *data = SPA_POD_BODY(&next->value);
|
uint8_t *data = SPA_POD_BODY(&next->value);
|
||||||
size_t size = SPA_POD_BODY_SIZE(&next->value);
|
size_t size = SPA_POD_BODY_SIZE(&next->value);
|
||||||
|
|
||||||
if ((res = midi_event_write(midi, next->offset, data, size, fix)) < 0)
|
if (type == TYPE_ID_UMP) {
|
||||||
|
while (size > 0) {
|
||||||
|
uint32_t ump[4];
|
||||||
|
int ump_size = spa_ump_from_midi(&data, &size, ump, sizeof(ump), 0, &state);
|
||||||
|
if (ump_size <= 0)
|
||||||
|
break;
|
||||||
|
if ((res = midi_event_write(midi, next->offset,
|
||||||
|
(uint8_t*)ump, ump_size, false)) < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = midi_event_write(midi, next->offset, data, size, fix);
|
||||||
|
}
|
||||||
|
if (res < 0)
|
||||||
pw_log_warn("midi %p: can't write event: %s", midi,
|
pw_log_warn("midi %p: can't write event: %s", midi,
|
||||||
spa_strerror(res));
|
spa_strerror(res));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SPA_CONTROL_UMP:
|
||||||
|
{
|
||||||
|
void *data = SPA_POD_BODY(&next->value);
|
||||||
|
size_t size = SPA_POD_BODY_SIZE(&next->value);
|
||||||
|
uint8_t ev[32];
|
||||||
|
|
||||||
|
if (type == TYPE_ID_MIDI) {
|
||||||
|
int ev_size = spa_ump_to_midi(data, size, ev, sizeof(ev));
|
||||||
|
if (ev_size <= 0)
|
||||||
|
break;
|
||||||
|
size = ev_size;
|
||||||
|
data = ev;
|
||||||
|
} else if (type != TYPE_ID_UMP)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((res = midi_event_write(midi, next->offset, data, size, fix)) < 0)
|
||||||
|
pw_log_warn("midi %p: can't write event: %s", midi,
|
||||||
|
spa_strerror(res));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c[next_index] = spa_pod_control_next(c[next_index]);
|
c[next_index] = spa_pod_control_next(c[next_index]);
|
||||||
}
|
}
|
||||||
|
|
@ -1591,19 +1674,22 @@ static inline void process_empty(struct port *p, uint32_t frames)
|
||||||
struct client *c = p->client;
|
struct client *c = p->client;
|
||||||
void *ptr, *src = p->emptyptr;
|
void *ptr, *src = p->emptyptr;
|
||||||
struct port *tied = p->tied;
|
struct port *tied = p->tied;
|
||||||
|
uint32_t type = p->object->port.type_id;
|
||||||
|
|
||||||
if (SPA_UNLIKELY(tied != NULL)) {
|
if (SPA_UNLIKELY(tied != NULL)) {
|
||||||
if ((src = tied->get_buffer(tied, frames)) == NULL)
|
if ((src = tied->get_buffer(tied, frames)) == NULL)
|
||||||
src = p->emptyptr;
|
src = p->emptyptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (p->object->port.type_id) {
|
switch (type) {
|
||||||
case TYPE_ID_AUDIO:
|
case TYPE_ID_AUDIO:
|
||||||
ptr = get_buffer_output(p, frames, sizeof(float), NULL);
|
ptr = get_buffer_output(p, frames, sizeof(float), NULL);
|
||||||
if (SPA_LIKELY(ptr != NULL))
|
if (SPA_LIKELY(ptr != NULL))
|
||||||
memcpy(ptr, src, frames * sizeof(float));
|
memcpy(ptr, src, frames * sizeof(float));
|
||||||
break;
|
break;
|
||||||
case TYPE_ID_MIDI:
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
case TYPE_ID_UMP:
|
||||||
{
|
{
|
||||||
struct buffer *b;
|
struct buffer *b;
|
||||||
ptr = get_buffer_output(p, c->max_frames, 1, &b);
|
ptr = get_buffer_output(p, c->max_frames, 1, &b);
|
||||||
|
|
@ -1611,8 +1697,8 @@ static inline void process_empty(struct port *p, uint32_t frames)
|
||||||
/* first build the complete pod in scratch memory, then copy it
|
/* first build the complete pod in scratch memory, then copy it
|
||||||
* to the target buffer. This makes it possible for multiple threads
|
* to the target buffer. This makes it possible for multiple threads
|
||||||
* to do this concurrently */
|
* to do this concurrently */
|
||||||
b->datas[0].chunk->size = convert_from_midi(src,
|
b->datas[0].chunk->size = convert_from_event(src, midi_scratch,
|
||||||
midi_scratch, MIDI_SCRATCH_FRAMES * sizeof(float));
|
MIDI_SCRATCH_FRAMES * sizeof(float), type);
|
||||||
memcpy(ptr, midi_scratch, b->datas[0].chunk->size);
|
memcpy(ptr, midi_scratch, b->datas[0].chunk->size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -2393,6 +2479,8 @@ static int param_enum_format(struct client *c, struct port *p,
|
||||||
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp),
|
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp),
|
||||||
SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32));
|
SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32));
|
||||||
break;
|
break;
|
||||||
|
case TYPE_ID_UMP:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
case TYPE_ID_MIDI:
|
case TYPE_ID_MIDI:
|
||||||
*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,
|
||||||
|
|
@ -2424,6 +2512,8 @@ static int param_format(struct client *c, struct port *p,
|
||||||
SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32));
|
SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_DSP_F32));
|
||||||
break;
|
break;
|
||||||
case TYPE_ID_MIDI:
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
case TYPE_ID_UMP:
|
||||||
*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),
|
||||||
|
|
@ -2448,6 +2538,8 @@ static int param_buffers(struct client *c, struct port *p,
|
||||||
switch (p->object->port.type_id) {
|
switch (p->object->port.type_id) {
|
||||||
case TYPE_ID_AUDIO:
|
case TYPE_ID_AUDIO:
|
||||||
case TYPE_ID_MIDI:
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
case TYPE_ID_UMP:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
|
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
|
||||||
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS),
|
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS),
|
||||||
|
|
@ -2781,7 +2873,7 @@ static inline void *init_buffer(struct port *p, uint32_t nframes)
|
||||||
if (p->zeroed)
|
if (p->zeroed)
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
if (p->object->port.type_id == TYPE_ID_MIDI) {
|
if (TYPE_ID_IS_EVENT(p->object->port.type_id)) {
|
||||||
struct midi_buffer *mb = data;
|
struct midi_buffer *mb = data;
|
||||||
midi_init_buffer(data, c->max_frames, nframes);
|
midi_init_buffer(data, c->max_frames, nframes);
|
||||||
pw_log_debug("port %p: init midi buffer size:%d frames:%d", p,
|
pw_log_debug("port %p: init midi buffer size:%d frames:%d", p,
|
||||||
|
|
@ -3266,10 +3358,14 @@ static jack_port_type_id_t string_to_type(const char *port_type)
|
||||||
{
|
{
|
||||||
if (spa_streq(JACK_DEFAULT_AUDIO_TYPE, port_type))
|
if (spa_streq(JACK_DEFAULT_AUDIO_TYPE, port_type))
|
||||||
return TYPE_ID_AUDIO;
|
return TYPE_ID_AUDIO;
|
||||||
else if (spa_streq(JACK_DEFAULT_MIDI_TYPE, port_type))
|
|
||||||
return TYPE_ID_MIDI;
|
|
||||||
else if (spa_streq(JACK_DEFAULT_VIDEO_TYPE, port_type))
|
else if (spa_streq(JACK_DEFAULT_VIDEO_TYPE, port_type))
|
||||||
return TYPE_ID_VIDEO;
|
return TYPE_ID_VIDEO;
|
||||||
|
else if (spa_streq(JACK_DEFAULT_MIDI_TYPE, port_type))
|
||||||
|
return TYPE_ID_MIDI;
|
||||||
|
else if (spa_streq(JACK_DEFAULT_OSC_TYPE, port_type))
|
||||||
|
return TYPE_ID_OSC;
|
||||||
|
else if (spa_streq(JACK_DEFAULT_UMP_TYPE, port_type))
|
||||||
|
return TYPE_ID_UMP;
|
||||||
else if (spa_streq("other", port_type))
|
else if (spa_streq("other", port_type))
|
||||||
return TYPE_ID_OTHER;
|
return TYPE_ID_OTHER;
|
||||||
else
|
else
|
||||||
|
|
@ -3281,22 +3377,46 @@ static const char* type_to_string(jack_port_type_id_t type_id)
|
||||||
switch(type_id) {
|
switch(type_id) {
|
||||||
case TYPE_ID_AUDIO:
|
case TYPE_ID_AUDIO:
|
||||||
return JACK_DEFAULT_AUDIO_TYPE;
|
return JACK_DEFAULT_AUDIO_TYPE;
|
||||||
case TYPE_ID_MIDI:
|
|
||||||
return JACK_DEFAULT_MIDI_TYPE;
|
|
||||||
case TYPE_ID_VIDEO:
|
case TYPE_ID_VIDEO:
|
||||||
return JACK_DEFAULT_VIDEO_TYPE;
|
return JACK_DEFAULT_VIDEO_TYPE;
|
||||||
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
case TYPE_ID_UMP:
|
||||||
|
/* all returned as MIDI */
|
||||||
|
return JACK_DEFAULT_MIDI_TYPE;
|
||||||
case TYPE_ID_OTHER:
|
case TYPE_ID_OTHER:
|
||||||
return "other";
|
return "other";
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* type_to_format_dsp(jack_port_type_id_t type_id)
|
||||||
|
{
|
||||||
|
switch(type_id) {
|
||||||
|
case TYPE_ID_AUDIO:
|
||||||
|
return JACK_DEFAULT_AUDIO_TYPE;
|
||||||
|
case TYPE_ID_VIDEO:
|
||||||
|
return JACK_DEFAULT_VIDEO_TYPE;
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
return JACK_DEFAULT_OSC_TYPE;
|
||||||
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_UMP:
|
||||||
|
/* all exposed to PipeWire as UMP */
|
||||||
|
return JACK_DEFAULT_UMP_TYPE;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool type_is_dsp(jack_port_type_id_t type_id)
|
static bool type_is_dsp(jack_port_type_id_t type_id)
|
||||||
{
|
{
|
||||||
switch(type_id) {
|
switch(type_id) {
|
||||||
case TYPE_ID_AUDIO:
|
case TYPE_ID_AUDIO:
|
||||||
case TYPE_ID_MIDI:
|
case TYPE_ID_MIDI:
|
||||||
case TYPE_ID_VIDEO:
|
case TYPE_ID_VIDEO:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
case TYPE_ID_UMP:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -3686,7 +3806,7 @@ static void registry_event_global(void *data, uint32_t id,
|
||||||
}
|
}
|
||||||
if (is_monitor && !c->show_monitor)
|
if (is_monitor && !c->show_monitor)
|
||||||
goto exit;
|
goto exit;
|
||||||
if (type_id == TYPE_ID_MIDI && !c->show_midi)
|
if (TYPE_ID_IS_EVENT(type_id) && !c->show_midi)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
o = NULL;
|
o = NULL;
|
||||||
|
|
@ -3747,6 +3867,8 @@ static void registry_event_global(void *data, uint32_t id,
|
||||||
(int)(sizeof(tmp)-11), tmp, serial);
|
(int)(sizeof(tmp)-11), tmp, serial);
|
||||||
else
|
else
|
||||||
snprintf(o->port.name, sizeof(o->port.name), "%s", tmp);
|
snprintf(o->port.name, sizeof(o->port.name), "%s", tmp);
|
||||||
|
|
||||||
|
o->port.type_id = type_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->fill_aliases) {
|
if (c->fill_aliases) {
|
||||||
|
|
@ -3766,7 +3888,6 @@ static void registry_event_global(void *data, uint32_t id,
|
||||||
}
|
}
|
||||||
|
|
||||||
o->port.flags = flags;
|
o->port.flags = flags;
|
||||||
o->port.type_id = type_id;
|
|
||||||
o->port.node_id = node_id;
|
o->port.node_id = node_id;
|
||||||
o->port.is_monitor = is_monitor;
|
o->port.is_monitor = is_monitor;
|
||||||
|
|
||||||
|
|
@ -5094,7 +5215,7 @@ jack_nframes_t jack_get_sample_rate (jack_client_t *client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c->sample_rate = res;
|
c->sample_rate = res;
|
||||||
pw_log_debug("sample_rate: %u", res);
|
pw_log_trace_fp("sample_rate: %u", res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5225,6 +5346,8 @@ jack_port_t * jack_port_register (jack_client_t *client,
|
||||||
p->get_buffer = get_buffer_input_float;
|
p->get_buffer = get_buffer_input_float;
|
||||||
break;
|
break;
|
||||||
case TYPE_ID_MIDI:
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
case TYPE_ID_UMP:
|
||||||
p->get_buffer = get_buffer_input_midi;
|
p->get_buffer = get_buffer_input_midi;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -5238,6 +5361,8 @@ jack_port_t * jack_port_register (jack_client_t *client,
|
||||||
p->get_buffer = get_buffer_output_float;
|
p->get_buffer = get_buffer_output_float;
|
||||||
break;
|
break;
|
||||||
case TYPE_ID_MIDI:
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
case TYPE_ID_UMP:
|
||||||
p->get_buffer = get_buffer_output_midi;
|
p->get_buffer = get_buffer_output_midi;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -5250,7 +5375,7 @@ jack_port_t * jack_port_register (jack_client_t *client,
|
||||||
|
|
||||||
spa_list_init(&p->mix);
|
spa_list_init(&p->mix);
|
||||||
|
|
||||||
pw_properties_set(p->props, PW_KEY_FORMAT_DSP, port_type);
|
pw_properties_set(p->props, PW_KEY_FORMAT_DSP, type_to_format_dsp(type_id));
|
||||||
pw_properties_set(p->props, PW_KEY_PORT_NAME, port_name);
|
pw_properties_set(p->props, PW_KEY_PORT_NAME, port_name);
|
||||||
if (flags > 0x1f) {
|
if (flags > 0x1f) {
|
||||||
pw_properties_setf(p->props, PW_KEY_PORT_EXTRA,
|
pw_properties_setf(p->props, PW_KEY_PORT_EXTRA,
|
||||||
|
|
@ -5493,15 +5618,13 @@ static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames)
|
||||||
/* first convert to a thread local scratch buffer, then memcpy into
|
/* first convert to a thread local scratch buffer, then memcpy into
|
||||||
* the per port buffer. This makes it possible to call this function concurrently
|
* the per port buffer. This makes it possible to call this function concurrently
|
||||||
* but also have different pointers per port */
|
* but also have different pointers per port */
|
||||||
convert_to_midi(seq, n_seq, mb, p->client->fix_midi_events);
|
convert_to_event(seq, n_seq, mb, p->client->fix_midi_events, p->object->port.type_id);
|
||||||
memcpy(ptr, mb, sizeof(struct midi_buffer) + (mb->event_count
|
memcpy(ptr, mb, sizeof(struct midi_buffer) + (mb->event_count
|
||||||
* sizeof(struct midi_event)));
|
* sizeof(struct midi_event)));
|
||||||
if (mb->write_pos) {
|
if (mb->write_pos) {
|
||||||
size_t offs = mb->buffer_size - 1 - mb->write_pos;
|
size_t offs = mb->buffer_size - 1 - mb->write_pos;
|
||||||
memcpy(SPA_PTROFF(ptr, offs, void), SPA_PTROFF(mb, offs, void), mb->write_pos);
|
memcpy(SPA_PTROFF(ptr, offs, void), SPA_PTROFF(mb, offs, void), mb->write_pos);
|
||||||
}
|
}
|
||||||
if (mb->event_count > 0)
|
|
||||||
spa_debug_mem(0, ptr, 64);
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5561,7 +5684,7 @@ void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t frames)
|
||||||
if ((b = get_mix_buffer(c, mix, frames)) == NULL)
|
if ((b = get_mix_buffer(c, mix, frames)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (o->port.type_id == TYPE_ID_MIDI) {
|
if (TYPE_ID_IS_EVENT(o->port.type_id)) {
|
||||||
struct spa_pod_sequence *seq[1];
|
struct spa_pod_sequence *seq[1];
|
||||||
struct spa_data *d;
|
struct spa_data *d;
|
||||||
void *pod;
|
void *pod;
|
||||||
|
|
@ -5576,7 +5699,7 @@ void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t frames)
|
||||||
if (!spa_pod_is_sequence(pod))
|
if (!spa_pod_is_sequence(pod))
|
||||||
goto done;
|
goto done;
|
||||||
seq[0] = pod;
|
seq[0] = pod;
|
||||||
convert_to_midi(seq, 1, ptr, c->fix_midi_events);
|
convert_to_event(seq, 1, ptr, c->fix_midi_events, o->port.type_id);
|
||||||
} else {
|
} else {
|
||||||
ptr = get_buffer_data(b, frames);
|
ptr = get_buffer_data(b, frames);
|
||||||
}
|
}
|
||||||
|
|
@ -5584,7 +5707,7 @@ void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t frames)
|
||||||
ptr = p->get_buffer(p, frames);
|
ptr = p->get_buffer(p, frames);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
pw_log_warn("%p: port:%p buffer:%p frames:%d", c, p, ptr, frames);
|
pw_log_trace_fp("%p: port:%p buffer:%p frames:%d", c, p, ptr, frames);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6140,7 +6263,7 @@ int jack_connect (jack_client_t *client,
|
||||||
if (src == NULL || dst == NULL ||
|
if (src == NULL || dst == NULL ||
|
||||||
!(src->port.flags & JackPortIsOutput) ||
|
!(src->port.flags & JackPortIsOutput) ||
|
||||||
!(dst->port.flags & JackPortIsInput) ||
|
!(dst->port.flags & JackPortIsInput) ||
|
||||||
src->port.type_id != dst->port.type_id) {
|
!TYPE_ID_IS_COMPATIBLE(src->port.type_id, dst->port.type_id)) {
|
||||||
res = -EINVAL;
|
res = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
@ -6297,6 +6420,10 @@ size_t jack_port_type_get_buffer_size (jack_client_t *client, const char *port_t
|
||||||
return jack_get_buffer_size(client) * sizeof(float);
|
return jack_get_buffer_size(client) * sizeof(float);
|
||||||
else if (spa_streq(JACK_DEFAULT_MIDI_TYPE, port_type))
|
else if (spa_streq(JACK_DEFAULT_MIDI_TYPE, port_type))
|
||||||
return c->max_frames * sizeof(float);
|
return c->max_frames * sizeof(float);
|
||||||
|
else if (spa_streq(JACK_DEFAULT_OSC_TYPE, port_type))
|
||||||
|
return c->max_frames * sizeof(float);
|
||||||
|
else if (spa_streq(JACK_DEFAULT_UMP_TYPE, port_type))
|
||||||
|
return c->max_frames * sizeof(float);
|
||||||
else if (spa_streq(JACK_DEFAULT_VIDEO_TYPE, port_type))
|
else if (spa_streq(JACK_DEFAULT_VIDEO_TYPE, port_type))
|
||||||
return 320 * 240 * 4 * sizeof(float);
|
return 320 * 240 * 4 * sizeof(float);
|
||||||
else
|
else
|
||||||
|
|
@ -6559,7 +6686,7 @@ const char ** jack_get_ports (jack_client_t *client,
|
||||||
continue;
|
continue;
|
||||||
pw_log_debug("%p: check port type:%d flags:%08lx name:\"%s\"", c,
|
pw_log_debug("%p: check port type:%d flags:%08lx name:\"%s\"", c,
|
||||||
o->port.type_id, o->port.flags, o->port.name);
|
o->port.type_id, o->port.flags, o->port.name);
|
||||||
if (o->port.type_id > TYPE_ID_VIDEO)
|
if (TYPE_ID_IS_HIDDEN(o->port.type_id))
|
||||||
continue;
|
continue;
|
||||||
if (!SPA_FLAG_IS_SET(o->port.flags, flags))
|
if (!SPA_FLAG_IS_SET(o->port.flags, flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue