Skip to content

Commit e9e0281

Browse files
committed
ALSA: seq: Automatic conversion of UMP events
This patch enables the automatic conversion of UMP events from/to the legacy ALSA sequencer MIDI events. Also, as UMP itself has two different modes (MIDI 1.0 and MIDI 2.0), yet another converters between them are needed, too. Namely, we have conversions between the legacy and UMP like: - seq legacy event -> seq UMP MIDI 1.0 event - seq legacy event -> seq UMP MIDI 2.0 event - seq UMP MIDI 1.0 event -> seq legacy event - seq UMP MIDI 2.0 event -> seq legacy event and the conversions between UMP MIDI 1.0 and 2.0 clients like: - seq UMP MIDI 1.0 event -> seq UMP MIDI 2.0 event - seq UMP MIDI 2.0 event -> seq UMP MIDI 1.0 event The translation is per best-effort; some MIDI 2.0 specific events are ignored when translated to MIDI 1.0. Reviewed-by: Jaroslav Kysela <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent a3ca3b3 commit e9e0281

7 files changed

+1279
-14
lines changed

sound/core/seq/Kconfig

+2
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,7 @@ config SND_SEQ_UMP
6666
Say Y here to enable the support for handling UMP (Universal MIDI
6767
Packet) events via ALSA sequencer infrastructure, which is an
6868
essential feature for enabling MIDI 2.0 support.
69+
It includes the automatic conversion of ALSA sequencer events
70+
among legacy and UMP clients.
6971

7072
endif # SND_SEQUENCER

sound/core/seq/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
88
seq_fifo.o seq_prioq.o seq_timer.o \
99
seq_system.o seq_ports.o
1010
snd-seq-$(CONFIG_SND_PROC_FS) += seq_info.o
11+
snd-seq-$(CONFIG_SND_SEQ_UMP) += seq_ump_convert.o
1112
snd-seq-midi-objs := seq_midi.o
1213
snd-seq-midi-emul-objs := seq_midi_emul.o
1314
snd-seq-midi-event-objs := seq_midi_event.o

sound/core/seq/seq_clientmgr.c

+34-14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "seq_timer.h"
2121
#include "seq_info.h"
2222
#include "seq_system.h"
23+
#include "seq_ump_convert.h"
2324
#include <sound/seq_device.h>
2425
#ifdef CONFIG_COMPAT
2526
#include <linux/compat.h>
@@ -612,6 +613,27 @@ static int update_timestamp_of_queue(struct snd_seq_event *event,
612613
return 1;
613614
}
614615

616+
/* deliver a single event; called from below and UMP converter */
617+
int __snd_seq_deliver_single_event(struct snd_seq_client *dest,
618+
struct snd_seq_client_port *dest_port,
619+
struct snd_seq_event *event,
620+
int atomic, int hop)
621+
{
622+
switch (dest->type) {
623+
case USER_CLIENT:
624+
if (!dest->data.user.fifo)
625+
return 0;
626+
return snd_seq_fifo_event_in(dest->data.user.fifo, event);
627+
case KERNEL_CLIENT:
628+
if (!dest_port->event_input)
629+
return 0;
630+
return dest_port->event_input(event,
631+
snd_seq_ev_is_direct(event),
632+
dest_port->private_data,
633+
atomic, hop);
634+
}
635+
return 0;
636+
}
615637

616638
/*
617639
* deliver an event to the specified destination.
@@ -648,22 +670,20 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client,
648670
update_timestamp_of_queue(event, dest_port->time_queue,
649671
dest_port->time_real);
650672

651-
switch (dest->type) {
652-
case USER_CLIENT:
653-
if (dest->data.user.fifo)
654-
result = snd_seq_fifo_event_in(dest->data.user.fifo, event);
655-
break;
673+
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
674+
if (snd_seq_ev_is_ump(event)) {
675+
result = snd_seq_deliver_from_ump(client, dest, dest_port,
676+
event, atomic, hop);
677+
goto __skip;
678+
} else if (snd_seq_client_is_ump(dest)) {
679+
result = snd_seq_deliver_to_ump(client, dest, dest_port,
680+
event, atomic, hop);
681+
goto __skip;
682+
}
683+
#endif /* CONFIG_SND_SEQ_UMP */
656684

657-
case KERNEL_CLIENT:
658-
if (dest_port->event_input == NULL)
659-
break;
660-
result = dest_port->event_input(event, direct,
661-
dest_port->private_data,
685+
result = __snd_seq_deliver_single_event(dest, dest_port, event,
662686
atomic, hop);
663-
break;
664-
default:
665-
break;
666-
}
667687

668688
__skip:
669689
if (dest_port)

sound/core/seq/seq_clientmgr.h

+15
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table
8585
int snd_seq_client_notify_subscription(int client, int port,
8686
struct snd_seq_port_subscribe *info, int evtype);
8787

88+
int __snd_seq_deliver_single_event(struct snd_seq_client *dest,
89+
struct snd_seq_client_port *dest_port,
90+
struct snd_seq_event *event,
91+
int atomic, int hop);
92+
8893
/* only for OSS sequencer */
8994
bool snd_seq_client_ioctl_lock(int clientid);
9095
void snd_seq_client_ioctl_unlock(int clientid);
@@ -95,4 +100,14 @@ extern int seq_client_load[15];
95100
struct snd_seq_client *snd_seq_kernel_client_get(int client);
96101
void snd_seq_kernel_client_put(struct snd_seq_client *cptr);
97102

103+
static inline bool snd_seq_client_is_ump(struct snd_seq_client *c)
104+
{
105+
return c->midi_version != SNDRV_SEQ_CLIENT_LEGACY_MIDI;
106+
}
107+
108+
static inline bool snd_seq_client_is_midi2(struct snd_seq_client *c)
109+
{
110+
return c->midi_version == SNDRV_SEQ_CLIENT_UMP_MIDI_2_0;
111+
}
112+
98113
#endif

sound/core/seq/seq_ports.h

+15
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ struct snd_seq_port_subs_info {
4242
int (*close)(void *private_data, struct snd_seq_port_subscribe *info);
4343
};
4444

45+
/* context for converting from legacy control event to UMP packet */
46+
struct snd_seq_ump_midi2_bank {
47+
bool rpn_set;
48+
bool nrpn_set;
49+
bool bank_set;
50+
unsigned char cc_rpn_msb, cc_rpn_lsb;
51+
unsigned char cc_nrpn_msb, cc_nrpn_lsb;
52+
unsigned char cc_data_msb, cc_data_lsb;
53+
unsigned char cc_bank_msb, cc_bank_lsb;
54+
};
55+
4556
struct snd_seq_client_port {
4657

4758
struct snd_seq_addr addr; /* client/port number */
@@ -75,6 +86,10 @@ struct snd_seq_client_port {
7586
/* UMP direction and group */
7687
unsigned char direction;
7788
unsigned char ump_group;
89+
90+
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
91+
struct snd_seq_ump_midi2_bank midi2_bank[16]; /* per channel */
92+
#endif
7893
};
7994

8095
struct snd_seq_client;

0 commit comments

Comments
 (0)