xref: /third_party/alsa-lib/test/midiloop.c (revision d5ac70f0)
1#include <stdlib.h>
2#include <stdio.h>
3#include <ctype.h>
4#include <sys/time.h>
5#include "../include/asoundlib.h"
6#include <string.h>
7#include <signal.h>
8
9static void usage(void)
10{
11	fprintf(stderr, "Usage: midiloop [options]\n");
12	fprintf(stderr, "  options:\n");
13	fprintf(stderr, "    -v: verbose mode\n");
14	fprintf(stderr, "    -i <rawmidi device> : test input device\n");
15	fprintf(stderr, "    -o <rawmidi device> : test output device\n");
16}
17
18int stop = 0;
19
20void sighandler(int dummy ATTRIBUTE_UNUSED)
21{
22	stop=1;
23}
24
25long long timediff(struct timeval t1, struct timeval t2)
26{
27	signed long l;
28
29	t1.tv_sec -= t2.tv_sec;
30	l = (signed long) t1.tv_usec - (signed long) t2.tv_usec;
31	if (l < 0) {
32		t1.tv_sec--;
33		l = -l;
34		l %= 1000000;
35	}
36	return ((long long)t1.tv_sec * (long long)1000000) + (long long)l;
37}
38
39int writepattern(snd_rawmidi_t *handle_out, unsigned char *obuf)
40{
41	int patsize, i;
42
43	patsize = 0;
44	for (i = 0; i < 15; i++) {
45		obuf[patsize++] = 0x90 + i;
46		obuf[patsize++] = 0x40;
47		obuf[patsize++] = 0x3f;
48		obuf[patsize++] = 0xb0 + i;
49		obuf[patsize++] = 0x2e;
50		obuf[patsize++] = 0x7a;
51		obuf[patsize++] = 0x80 + i;
52		obuf[patsize++] = 0x23;
53		obuf[patsize++] = 0x24;
54		obuf[patsize++] = 0xf0;
55		obuf[patsize++] = i;
56		obuf[patsize++] = 0xf7;
57	}
58	i = snd_rawmidi_write(handle_out, obuf, patsize);
59	if (i != patsize) {
60		printf("Written only %i bytes from %i bytes\n", i, patsize);
61		exit(EXIT_FAILURE);
62	}
63	return patsize;
64}
65
66int main(int argc, char** argv)
67{
68	int i, j, k, opos, ipos, patsize;
69	int err;
70	int verbose = 0;
71	snd_rawmidi_t *handle_in = NULL, *handle_out = NULL;
72	unsigned char ibuf[512], obuf[512];
73	char *iname = "hw:0,0", *oname = "hw:0,0";
74	struct timeval start, end;
75	long long diff;
76	snd_rawmidi_status_t *istat, *ostat;
77
78	for (i = 1 ; i<argc ; i++) {
79		if (argv[i][0]=='-') {
80			if (!strcmp(argv[i], "--help")) {
81				usage();
82				return 0;
83			}
84			switch (argv[i][1]) {
85				case 'h':
86					usage();
87					return 0;
88				case 'v':
89					verbose = 1;
90					break;
91				case 'i':
92					if (i + 1 < argc)
93						iname = argv[++i];
94					break;
95				case 'o':
96					if (i + 1 < argc)
97						oname = argv[++i];
98					break;
99			}
100		}
101	}
102
103	if (iname == NULL)
104		iname = oname;
105	if (oname == NULL)
106		oname = iname;
107
108	if (verbose) {
109		fprintf(stderr, "Using: \n");
110		fprintf(stderr, "  Input: %s  Output: %s\n", iname, oname);
111	}
112
113	err = snd_rawmidi_open(&handle_in, NULL, iname, SND_RAWMIDI_NONBLOCK);
114	if (err) {
115		fprintf(stderr,"snd_rawmidi_open %s failed: %d\n",iname,err);
116		exit(EXIT_FAILURE);
117	}
118
119	err = snd_rawmidi_open(NULL, &handle_out, oname, 0);
120	if (err) {
121		fprintf(stderr,"snd_rawmidi_open %s failed: %d\n",oname,err);
122		exit(EXIT_FAILURE);
123	}
124
125	signal(SIGINT, sighandler);
126
127	i = snd_rawmidi_read(handle_in, ibuf, sizeof(ibuf));
128	if (i > 0) {
129		printf("Read ahead: %i\n", i);
130		for (j = 0; j < i; j++)
131			printf("%02x:", ibuf[j]);
132		printf("\n");
133		exit(EXIT_FAILURE);
134	}
135
136	snd_rawmidi_nonblock(handle_in, 0);
137
138	patsize = writepattern(handle_out, obuf);
139	gettimeofday(&start, NULL);
140	patsize = writepattern(handle_out, obuf);
141
142	k = ipos = opos = err = 0;
143	while (!stop) {
144		i = snd_rawmidi_read(handle_in, ibuf, sizeof(ibuf));
145		for (j = 0; j < i; j++, ipos++)
146			if (obuf[k] != ibuf[j]) {
147				printf("ipos = %i, i[0x%x] != o[0x%x]\n", ipos, ibuf[j], obuf[k]);
148				if (opos > 0)
149					stop = 1;
150			} else {
151				printf("match success: ipos = %i, opos = %i [%i:0x%x]\n", ipos, opos, k, obuf[k]);
152				k++; opos++;
153				if (k >= patsize) {
154					patsize = writepattern(handle_out, obuf);
155					k = 0;
156				}
157			}
158	}
159
160	gettimeofday(&end, NULL);
161
162	printf("End...\n");
163
164	snd_rawmidi_status_alloca(&istat);
165	snd_rawmidi_status_alloca(&ostat);
166	err = snd_rawmidi_status(handle_in, istat);
167	if (err < 0)
168		fprintf(stderr, "input stream status error: %d\n", err);
169	err = snd_rawmidi_status(handle_out, ostat);
170	if (err < 0)
171		fprintf(stderr, "output stream status error: %d\n", err);
172	printf("input.status.avail = %zi\n", snd_rawmidi_status_get_avail(istat));
173	printf("input.status.xruns = %zi\n", snd_rawmidi_status_get_xruns(istat));
174	printf("output.status.avail = %zi\n", snd_rawmidi_status_get_avail(ostat));
175	printf("output.status.xruns = %zi\n", snd_rawmidi_status_get_xruns(ostat));
176
177	diff = timediff(end, start);
178	printf("Time diff: %lliusec (%lli bytes/sec)\n", diff, ((long long)opos * 1000000) / diff);
179
180	if (verbose) {
181		fprintf(stderr,"Closing\n");
182	}
183
184	snd_rawmidi_drain(handle_in);
185	snd_rawmidi_close(handle_in);
186	snd_rawmidi_drain(handle_out);
187	snd_rawmidi_close(handle_out);
188
189	return 0;
190}
191