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