aboutsummaryrefslogtreecommitdiff
path: root/midi.c
diff options
context:
space:
mode:
Diffstat (limited to 'midi.c')
-rw-r--r--midi.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/midi.c b/midi.c
new file mode 100644
index 0000000..3d21f79
--- /dev/null
+++ b/midi.c
@@ -0,0 +1,109 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <alloca.h>
4#include <unistd.h>
5#include <alsa/asoundlib.h>
6
7#include "midi.h"
8
9static snd_seq_t *seq_handle;
10static snd_seq_addr_t *ports;
11
12void *midi(void *arg) {
13 MidiArgs* args = (MidiArgs*)arg;
14
15 while (1) {
16 if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
17 fprintf(stderr, "Error opening ALSA sequencer.\n");
18 exit(1);
19 }
20
21 if (snd_seq_set_client_name(seq_handle, CLIENT_NAME) < 0) {
22 fprintf(stderr, "Could not set up client name.\n");
23 exit(1);
24 }
25
26 if (snd_seq_create_simple_port(seq_handle, CLIENT_NAME,
27 SND_SEQ_PORT_CAP_WRITE |
28 SND_SEQ_PORT_CAP_SUBS_WRITE,
29 SND_SEQ_PORT_TYPE_MIDI_GENERIC |
30 SND_SEQ_PORT_TYPE_APPLICATION) < 0) {
31 fprintf(stderr, "Error creating sequencer port.\n");
32 exit(1);
33 }
34
35 // Connecting ports.
36 ports = realloc(ports, MAX_MIDI_PORTS * sizeof(snd_seq_addr_t));
37 if (snd_seq_parse_address(seq_handle, &ports[0], args->port_name) < 0) {
38 fprintf(stderr, "Invalid port %s.\n", args->port_name);
39 exit(1);
40 }
41
42 // Listing assigned ports.
43 fprintf(stdout, "Ports:\n");
44 for (int j = 0; j < MAX_MIDI_PORTS; j++) {
45 fprintf(stdout, " client: %d, port: %d\n", ports[j].client, ports[j].port);
46 }
47
48 // Connecting ports.
49 for (int i = 0; i < MAX_MIDI_PORTS; ++i) {
50 int err = snd_seq_connect_from(seq_handle, 0, ports[i].client, ports[i].port);
51 if (err < 0) {
52 fprintf(stderr, "Cannot connect from port %d:%d - %s", ports[i].client, ports[i].port, snd_strerror(err));
53 exit(1);
54 }
55 }
56
57 if (snd_seq_nonblock(seq_handle, 1) < 0) {
58 fprintf(stderr, "Set nonblock mode failed.");
59 exit(1);
60 }
61
62
63 // Reading MIDI device.
64 struct pollfd *pfds;
65 size_t npfds;
66
67 npfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
68 pfds = alloca(sizeof(*pfds) * npfds);
69
70 for (;;) {
71 snd_seq_poll_descriptors(seq_handle, pfds, npfds, POLLIN);
72 if (poll(pfds, npfds, -1) < 0) {
73 break;
74 }
75
76 for (;;) {
77 snd_seq_event_t *ev;
78
79 if (snd_seq_event_input(seq_handle, &ev) < 0) {
80 break;
81 }
82
83 if (ev) {
84 switch (ev->type) {
85 case SND_SEQ_EVENT_NOTEON:
86 printf("%3d:%-3dNote on %2d, note %d, velocity: %3d\n",
87 ev->source.client, ev->source.port,
88 ev->data.note.channel,
89 ev->data.note.note,
90 ev->data.note.velocity);
91 break;
92
93 case SND_SEQ_EVENT_NOTEOFF:
94 printf("%3d:%-3dNote off\t%2d, note %d\n",
95 ev->source.client, ev->source.port,
96 ev->data.note.channel,
97 ev->data.note.note);
98 break;
99
100
101 }
102 }
103 }
104
105 fflush(stdout);
106 }
107 }
108}
109