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