xref: /third_party/alsa-lib/test/rawmidi.c (revision d5ac70f0)
1#include <stdio.h>
2#include <stdlib.h>
3#include <ctype.h>
4#include "../include/asoundlib.h"
5#include <signal.h>
6
7static void usage(void)
8{
9	fprintf(stderr, "usage: rawmidi [options]\n");
10	fprintf(stderr, "  options:\n");
11	fprintf(stderr, "    -v: verbose mode\n");
12	fprintf(stderr, "    -i device-id : test ALSA input device\n");
13	fprintf(stderr, "    -o device-id : test ALSA output device\n");
14	fprintf(stderr, "    -I node      : test input node\n");
15	fprintf(stderr, "    -O node      : test output node\n");
16	fprintf(stderr, "    -c clock     : kernel clock type (0=none, 1=realtime, 2=monotonic, 3=monotonic raw)\n");
17	fprintf(stderr, "    -t: test midi thru\n");
18	fprintf(stderr, "  example:\n");
19	fprintf(stderr, "    rawmidi -i hw:0,0 -O /dev/midi1\n");
20	fprintf(stderr, "    tests input for card 0, device 0, using snd_rawmidi API\n");
21	fprintf(stderr, "    and /dev/midi1 using file descriptors\n");
22}
23
24int stop=0;
25
26void sighandler(int dum)
27{
28	stop=1;
29}
30
31int main(int argc,char** argv)
32{
33	int i;
34	int err;
35	int thru=0;
36	int verbose = 0;
37	char *device_in = NULL;
38	char *device_out = NULL;
39	char *node_in = NULL;
40	char *node_out = NULL;
41	int clock_type = -1;
42
43	int fd_in = -1,fd_out = -1;
44	snd_rawmidi_t *handle_in = 0,*handle_out = 0;
45
46	if (argc==1) {
47		usage();
48		exit(0);
49	}
50
51	for (i = 1 ; i<argc ; i++) {
52		if (argv[i][0]=='-') {
53			switch (argv[i][1]) {
54				case 'h':
55					usage();
56					break;
57				case 'v':
58					verbose = 1;
59					break;
60				case 't':
61					thru = 1;
62					break;
63				case 'c':
64					if (i + 1 < argc)
65						clock_type = atoi(argv[++i]);
66					break;
67				case 'i':
68					if (i + 1 < argc)
69						device_in = argv[++i];
70					break;
71				case 'I':
72					if (i + 1 < argc)
73						node_in = argv[++i];
74					break;
75				case 'o':
76					if (i + 1 < argc)
77						device_out = argv[++i];
78					break;
79				case 'O':
80					if (i + 1 < argc)
81						node_out = argv[++i];
82					break;
83			}
84		}
85	}
86
87	if (verbose) {
88		fprintf(stderr,"Using: \n");
89		fprintf(stderr,"Input: ");
90		if (device_in) {
91			fprintf(stderr,"device %s\n",device_in);
92		}else if (node_in){
93			fprintf(stderr,"%s\n",node_in);
94		}else{
95			fprintf(stderr,"NONE\n");
96		}
97		fprintf(stderr,"Output: ");
98		if (device_out) {
99			fprintf(stderr,"device %s\n",device_out);
100		}else if (node_out){
101			fprintf(stderr,"%s\n",node_out);
102		}else{
103			fprintf(stderr,"NONE\n");
104		}
105	}
106
107	if (device_in) {
108		err = snd_rawmidi_open(&handle_in,NULL,device_in,0);
109		if (err) {
110			fprintf(stderr,"snd_rawmidi_open %s failed: %d\n",device_in,err);
111		}
112	}
113	if (node_in && (!node_out || strcmp(node_out,node_in))) {
114		fd_in = open(node_in,O_RDONLY);
115		if (fd_in<0) {
116			fprintf(stderr,"open %s for input failed\n",node_in);
117		}
118	}
119
120	signal(SIGINT,sighandler);
121
122	if (device_out) {
123		err = snd_rawmidi_open(NULL,&handle_out,device_out,0);
124		if (err) {
125			fprintf(stderr,"snd_rawmidi_open %s failed: %d\n",device_out,err);
126		}
127	}
128	if (node_out && (!node_in || strcmp(node_out,node_in))) {
129		fd_out = open(node_out,O_WRONLY);
130		if (fd_out<0) {
131			fprintf(stderr,"open %s for output failed\n",node_out);
132		}
133	}
134
135	if (node_in && node_out && strcmp(node_out,node_in)==0) {
136		fd_in = fd_out = open(node_out,O_RDWR);
137		if (fd_out<0) {
138			fprintf(stderr,"open %s for input and output failed\n",node_out);
139		}
140	}
141
142	if (!thru) {
143		if (handle_in || fd_in!=-1) {
144			if (clock_type != -1) {
145				snd_rawmidi_params_t *params;
146				snd_rawmidi_params_malloc(&params);
147				if (!handle_in) {
148					fprintf(stderr, "-c only usable with -i");
149					clock_type = -1;
150				}
151				if (clock_type != -1) {
152					fprintf(stderr, "Enable kernel clock type %d\n", clock_type);
153					snd_rawmidi_params_current(handle_in, params);
154					err = snd_rawmidi_params_set_read_mode(handle_in, params, SND_RAWMIDI_READ_TSTAMP);
155					if (err) {
156						fprintf(stderr,"snd_rawmidi_params_set_read_mode failed: %d\n", err);
157						clock_type = -1;
158					}
159				}
160				if (clock_type != -1) {
161					err = snd_rawmidi_params_set_clock_type(handle_in, params, clock_type);
162					if (err) {
163						fprintf(stderr, "snd_rawmidi_params_set_clock_type failed: %d\n", err);
164						clock_type = -1;
165					}
166				}
167				if (clock_type != -1) {
168					err = snd_rawmidi_params(handle_in, params);
169					if (err) {
170						fprintf(stderr, "snd_rawmidi_params failed: %d\n", err);
171						clock_type = -1;
172					}
173				}
174				snd_rawmidi_params_free(params);
175			}
176
177			fprintf(stderr,"Read midi in\n");
178			fprintf(stderr,"Press ctrl-c to stop\n");
179		}
180
181		if (handle_in) {
182			unsigned char buf[1024];
183			ssize_t ret;
184			while (!stop) {
185				if (clock_type != -1) {
186					struct timespec tstamp;
187					ret = snd_rawmidi_tread(handle_in, &tstamp, buf, sizeof(buf));
188					if (ret < 0)
189						fprintf(stderr, "read timestamp error: %d - %s\n", (int)ret, snd_strerror(ret));
190					if (ret > 0 && verbose) {
191						fprintf(stderr, "read [%lld:%09lld]", (long long)tstamp.tv_sec, (long long)tstamp.tv_nsec);
192						for (i = 0; i < ret; i++)
193							fprintf(stderr, " %02x", buf[i]);
194						fprintf(stderr, "\n");
195					}
196				} else {
197					ret = snd_rawmidi_read(handle_in, buf, sizeof(buf));
198					if (ret < 0)
199						fprintf(stderr, "read error: %d - %s\n", (int)ret, snd_strerror(ret));
200					if (ret > 0 && verbose)
201						for (i = 0; i < ret; i++)
202							fprintf(stderr,"read %02x\n",buf[i]);
203				}
204			}
205		}
206		if (fd_in!=-1) {
207			unsigned char ch;
208			while (!stop) {
209				read(fd_in,&ch,1);
210				if (verbose) {
211					fprintf(stderr,"read %02x\n",ch);
212				}
213			}
214		}
215
216		if (handle_out || fd_out!=-1) {
217			fprintf(stderr,"Writing note on / note off\n");
218		}
219
220		if (handle_out) {
221			unsigned char ch;
222			ch=0x90; snd_rawmidi_write(handle_out,&ch,1);
223			ch=60;   snd_rawmidi_write(handle_out,&ch,1);
224			ch=100;  snd_rawmidi_write(handle_out,&ch,1);
225			snd_rawmidi_drain(handle_out);
226			sleep(1);
227			ch=0x90; snd_rawmidi_write(handle_out,&ch,1);
228			ch=60;   snd_rawmidi_write(handle_out,&ch,1);
229			ch=0;    snd_rawmidi_write(handle_out,&ch,1);
230			snd_rawmidi_drain(handle_out);
231		}
232		if (fd_out!=-1) {
233			unsigned char ch;
234			ch=0x90; write(fd_out,&ch,1);
235			ch=60;   write(fd_out,&ch,1);
236			ch=100;  write(fd_out,&ch,1);
237			sleep(1);
238			ch=0x90; write(fd_out,&ch,1);
239			ch=60;   write(fd_out,&ch,1);
240			ch=0;    write(fd_out,&ch,1);
241		}
242	} else {
243		if ((handle_in || fd_in!=-1) && (handle_out || fd_out!=-1)) {
244			if (verbose) {
245				fprintf(stderr,"Testing midi thru in\n");
246			}
247			while (!stop) {
248				unsigned char ch;
249
250				if (handle_in) {
251					snd_rawmidi_read(handle_in,&ch,1);
252				}
253				if (fd_in!=-1) {
254					read(fd_in,&ch,1);
255				}
256				if (verbose) {
257					fprintf(stderr,"thru: %02x\n",ch);
258				}
259
260				if (handle_out) {
261					snd_rawmidi_write(handle_out,&ch,1);
262					snd_rawmidi_drain(handle_out);
263				}
264				if (fd_out!=-1) {
265					write(fd_out,&ch,1);
266				}
267			}
268		}else{
269				fprintf(stderr,"Testing midi thru needs both input and output\n");
270				exit(-1);
271		}
272	}
273
274	if (verbose) {
275		fprintf(stderr,"Closing\n");
276	}
277
278	if (handle_in) {
279		snd_rawmidi_drain(handle_in);
280		snd_rawmidi_close(handle_in);
281	}
282	if (handle_out) {
283		snd_rawmidi_drain(handle_out);
284		snd_rawmidi_close(handle_out);
285	}
286	if (fd_in!=-1) {
287		close(fd_in);
288	}
289	if (fd_out!=-1) {
290		close(fd_out);
291	}
292
293	return 0;
294}
295