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(¶ms); 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