-
Notifications
You must be signed in to change notification settings - Fork 0
/
nonblocking.c
117 lines (107 loc) · 4.33 KB
/
nonblocking.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//
// Programmer: Craig Stuart Sapp <[email protected]>
// Creation Date: Sat May 9 22:03:40 PDT 2009
// Last Modified: Sat May 9 22:03:46 PDT 2009
// Filename: nonblockinginput.c
// Syntax: C; ALSA 1.0
// $Smake: gcc -o %b %f -lasound
//
// Description: Receive MIDI data from a synthesizer using the ALSA rawmidi
// interface in non-blocking mode.
//
// First double-check that you have the ALSA system installed on your computer
// by running this command-line command:
// cat /proc/asound/version
// Which should return something like:
// Advanced Linux Sound Architecture Driver Version 1.0.17.
// This example program should work if the version number (1.0.17 in this
// case) is "1".
//
// Online documentation notes:
//
// http://www.alsa-project.org/alsa-doc/alsa-lib/rawmidi.html
//
// Using SND_RAWMIDI_NONBLOCK flag for snd_rawmidi_open() or
// snd_rawmidi_open_lconf() instruct device driver to return the -EBUSY
// error when device is already occupied with another application. This
// flag also changes behaviour of snd_rawmidi_write() and snd_rawmidi_read()
// returning -EAGAIN when no more bytes can be processed.
//
// http://www.alsa-project.org/alsa-doc/alsa-lib/group___raw_midi.html
//
// int snd_rawmidi_open(snd_rawmidi_t** input, snd_rawmidi_t output,
// const char* name, int mode)
// intput == returned input handle (NULL if not wanted)
// output == returned output handle (NULL if not wanted)
// name == ASCII identifier of the rawmidi handle, such as "hw:1,0,0"
// mode == open mode (see mode descriptions above):
// SND_RAWMIDI_NONBLOCK, SND_RAWMIDI_APPEND, SND_RAWMIDI_SYNC
//
// int snd_rawmidi_close(snd_rawmidi_t* rawmidi)
// Close a deviced opended by snd_rawmidi_open(). Returns an negative
// error code if there was an error closing the device.
//
// int snd_rawmidi_write(snd_rawmidi_t* output, char* data, int datasize)
// output == midi output pointer setup with snd_rawmidi_open().
// data == array of bytes to send.
// datasize == number of bytes in the data array to write to MIDI output.
//
// const char* snd_strerror(int errornum)
// errornum == error number returned by an ALSA snd__* function.
// Returns a string explaining the error number.
//
#include <alsa/asoundlib.h> /* Interface to the ALSA system */
// function declarations:
void errormessage(const char *format, ...);
///////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
int status;
int mode = SND_RAWMIDI_NONBLOCK;
snd_rawmidi_t* midiin = NULL;
const char* portname = "hw:1,0,0"; // see alsarawportlist.c example program
if ((argc > 1) && (strncmp("hw:", argv[1], 3) == 0)) {
portname = argv[1];
}
if ((status = snd_rawmidi_open(&midiin, NULL, portname, mode)) < 0) {
errormessage("Problem opening MIDI input: %s", snd_strerror(status));
exit(1);
}
int maxcount = 1000; // Exit after this many bytes have been received.
int count = 0; // Current count of bytes received.
char buffer[1]; // Storage for input buffer received
while (count < maxcount) {
status = 0;
while (status != -EAGAIN) {
status = snd_rawmidi_read(midiin, buffer, 1);
if ((status < 0) && (status != -EBUSY) && (status != -EAGAIN)) {
errormessage("Problem reading MIDI input: %s",snd_strerror(status));
} else if (status >= 0) {
count++;
if ((unsigned char)buffer[0] >= 0x80) { // print command in hex
printf("0x%x ", (unsigned char)buffer[0]);
} else {
printf("%d ", (unsigned char)buffer[0]);
}
fflush(stdout);
if (count % 20 == 0) {
printf("\n");
}
}
}
}
snd_rawmidi_close(midiin);
midiin = NULL; // snd_rawmidi_close() does not clear invalid pointer,
return 0; // so might be a good idea to erase it after closing.
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// error -- print error message
//
void errormessage(const char *format, ...) {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
putc('\n', stderr);
}