xref: /freebsd/share/examples/sound/midi.c (revision 6747b1a8218f229c7593cdb02e4b41e2b1186e26)
1*6747b1a8SChristos Margiolis /*
2*6747b1a8SChristos Margiolis  * SPDX-License-Identifier: BSD-2-Clause
3*6747b1a8SChristos Margiolis  *
4*6747b1a8SChristos Margiolis  * Copyright (c) 2022 Goran Mekić
5*6747b1a8SChristos Margiolis  * Copyright (c) 2024 The FreeBSD Foundation
6*6747b1a8SChristos Margiolis  *
7*6747b1a8SChristos Margiolis  * Portions of this software were developed by Christos Margiolis
8*6747b1a8SChristos Margiolis  * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
9*6747b1a8SChristos Margiolis  *
10*6747b1a8SChristos Margiolis  * Redistribution and use in source and binary forms, with or without
11*6747b1a8SChristos Margiolis  * modification, are permitted provided that the following conditions
12*6747b1a8SChristos Margiolis  * are met:
13*6747b1a8SChristos Margiolis  * 1. Redistributions of source code must retain the above copyright
14*6747b1a8SChristos Margiolis  *    notice, this list of conditions and the following disclaimer.
15*6747b1a8SChristos Margiolis  * 2. Redistributions in binary form must reproduce the above copyright
16*6747b1a8SChristos Margiolis  *    notice, this list of conditions and the following disclaimer in the
17*6747b1a8SChristos Margiolis  *    documentation and/or other materials provided with the distribution.
18*6747b1a8SChristos Margiolis  *
19*6747b1a8SChristos Margiolis  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20*6747b1a8SChristos Margiolis  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*6747b1a8SChristos Margiolis  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*6747b1a8SChristos Margiolis  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23*6747b1a8SChristos Margiolis  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*6747b1a8SChristos Margiolis  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*6747b1a8SChristos Margiolis  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*6747b1a8SChristos Margiolis  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*6747b1a8SChristos Margiolis  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*6747b1a8SChristos Margiolis  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*6747b1a8SChristos Margiolis  * SUCH DAMAGE.
30*6747b1a8SChristos Margiolis  */
31*6747b1a8SChristos Margiolis 
32*6747b1a8SChristos Margiolis #include <err.h>
33*6747b1a8SChristos Margiolis #include <fcntl.h>
34*6747b1a8SChristos Margiolis #include <stdio.h>
35*6747b1a8SChristos Margiolis #include <stdlib.h>
36*6747b1a8SChristos Margiolis #include <unistd.h>
37*6747b1a8SChristos Margiolis 
38*6747b1a8SChristos Margiolis #define CMD_MASK	0xF0
39*6747b1a8SChristos Margiolis #define CHANNEL_MASK	0x0F
40*6747b1a8SChristos Margiolis #define NOTE_ON		0x90
41*6747b1a8SChristos Margiolis #define NOTE_OFF	0x80
42*6747b1a8SChristos Margiolis #define CTL_CHANGE	0xB0
43*6747b1a8SChristos Margiolis 
44*6747b1a8SChristos Margiolis int
main(int argc,char * argv[])45*6747b1a8SChristos Margiolis main(int argc, char *argv[])
46*6747b1a8SChristos Margiolis {
47*6747b1a8SChristos Margiolis 	int fd;
48*6747b1a8SChristos Margiolis 	unsigned char raw, type, channel, b1, b2;
49*6747b1a8SChristos Margiolis 
50*6747b1a8SChristos Margiolis 	if ((fd = open("/dev/umidi0.0", O_RDWR)) < 0)
51*6747b1a8SChristos Margiolis 		err(1, "Error opening MIDI device");
52*6747b1a8SChristos Margiolis 
53*6747b1a8SChristos Margiolis 	for (;;) {
54*6747b1a8SChristos Margiolis 		if (read(fd, &raw, sizeof(raw)) < sizeof(raw))
55*6747b1a8SChristos Margiolis 			err(1, "Error reading command byte");
56*6747b1a8SChristos Margiolis 		if (!(raw & 0x80))
57*6747b1a8SChristos Margiolis 			continue;
58*6747b1a8SChristos Margiolis 
59*6747b1a8SChristos Margiolis 		type = raw & CMD_MASK;
60*6747b1a8SChristos Margiolis 		channel = raw & CHANNEL_MASK;
61*6747b1a8SChristos Margiolis 
62*6747b1a8SChristos Margiolis 		if (read(fd, &b1, sizeof(b1)) < sizeof(b1))
63*6747b1a8SChristos Margiolis 			err(1, "Error reading byte 1");
64*6747b1a8SChristos Margiolis 		if (read(fd, &b2, sizeof(b2)) < sizeof(b2))
65*6747b1a8SChristos Margiolis 			err(1, "Error reading byte 2");
66*6747b1a8SChristos Margiolis 
67*6747b1a8SChristos Margiolis 		switch (type) {
68*6747b1a8SChristos Margiolis 		case NOTE_ON:
69*6747b1a8SChristos Margiolis 			printf("Channel %d, note on %d, velocity %d\n",
70*6747b1a8SChristos Margiolis 			    channel, b1, b2);
71*6747b1a8SChristos Margiolis 			break;
72*6747b1a8SChristos Margiolis 		case NOTE_OFF:
73*6747b1a8SChristos Margiolis 			printf("Channel %d, note off %d, velocity %d\n",
74*6747b1a8SChristos Margiolis 			    channel, b1, b2);
75*6747b1a8SChristos Margiolis 			break;
76*6747b1a8SChristos Margiolis 		case CTL_CHANGE:
77*6747b1a8SChristos Margiolis 			printf("Channel %d, controller change %d, value %d\n",
78*6747b1a8SChristos Margiolis 			    channel, b1, b2);
79*6747b1a8SChristos Margiolis 			break;
80*6747b1a8SChristos Margiolis 		default:
81*6747b1a8SChristos Margiolis 			printf("Unknown event type %d\n", type);
82*6747b1a8SChristos Margiolis 			break;
83*6747b1a8SChristos Margiolis 		}
84*6747b1a8SChristos Margiolis 	}
85*6747b1a8SChristos Margiolis 
86*6747b1a8SChristos Margiolis 	close(fd);
87*6747b1a8SChristos Margiolis 
88*6747b1a8SChristos Margiolis 	return (0);
89*6747b1a8SChristos Margiolis }
90