ref: 35c587c39e8b863e0112234ebea1a1dc1ae98202
author: qwx <qwx@sciops.net>
date: Mon May 27 19:53:55 EDT 2019
initial import
--- /dev/null
+++ b/mkey.c
@@ -1,0 +1,190 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+
+enum{
+ Nrate = 44100,
+ Ndelay = Nrate / 50,
+};
+char *notetab[] = {
+ "c0","c♯0","d0","d♯0","e0","f0","f♯0","g0","g♯0","a0","a♯0","b0",
+ "c1","c♯1","d1","d♯1","e1","f1","f♯1","g1","g♯1","a1","a♯1","b1",
+ "c2","c♯2","d2","d♯2","e2","f2","f♯2","g2","g♯2","a2","a♯2","b2",
+ "c3","c♯3","d3","d♯3","e3","f3","f♯3","g3","g♯3","a3","a♯3","b3",
+ "c4","c♯4","d4","d♯4","e4","f4","f♯4","g4","g♯4","a4","a♯4","b4",
+ "c5","c♯5","d5","d♯5","e5","f5","f♯5","g5","g♯5","a5","a♯5","b5",
+ "c6","c♯6","d6","d♯6","e6","f6","f♯6","g6","g♯6","a6","a♯6","b6",
+ "c7","c♯7","d7","d♯7","e7","f7","f♯7","g7","g♯7","a7","a♯7","b7",
+ "c8","c♯8","d8","d♯8","e8","f8","f♯8","g8","g♯8","a8","a♯8","b8",
+ "c9","c♯9","d9","d♯9","e9","f9","f♯9","g9","g♯9","a9","a♯9","b9",
+ "c10","c♯10","d10","d♯10","e10","f10","f♯10","g10"
+};
+int oct0 = 3*12, vol = 63, freq[nelem(notetab)], fon[nelem(notetab)];
+int soft;
+
+Rune keytab[] = {
+ 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', Kshift, '\n',
+ 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\\',
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '='
+};
+
+void
+athread(void *)
+{
+ int i, fd;
+ short s;
+ uvlong T;
+ uchar out[4*Ndelay], *p;
+
+ if((fd = open("/dev/audio", OWRITE)) < 0)
+ sysfatal("open: %r");
+ for(T=0;;){
+ for(p=out; p<out+nelem(out); T++, p+=4){
+ for(i=0, s=0; i<nelem(freq); i++)
+ if(fon[i] && T % freq[i] >= freq[i] / 2)
+ s += 64;
+ s *= vol;
+ p[0] = p[2] = s;
+ p[1] = p[3] = s >> 8;
+ }
+ if(write(fd, out, sizeof out) != sizeof out)
+ break;
+ yield();
+ }
+ close(fd);
+}
+
+void
+kproc(void *)
+{
+ int n, fh, fd, kon;
+ char buf[128], buf2[128], *s, *s2;
+ uchar u[4];
+ Rune r, *k;
+
+ if((fd = open("/dev/kbd", OREAD)) < 0)
+ sysfatal("open: %r");
+ memset(buf, 0, sizeof buf);
+ memset(buf2, 0, sizeof buf2);
+ fh = font->height * (nelem(keytab) / 12 - 1);
+ for(;;){
+ if(buf[0] != 0){
+ n = strlen(buf)+1;
+ memmove(buf, buf+n, sizeof(buf)-n);
+ }
+ if(buf[0] == 0){
+ if((n = read(fd, buf, sizeof(buf)-1)) < 0)
+ sysfatal("read: %r");
+ buf[n-1] = 0;
+ buf[n] = 0;
+ }
+ if(buf[0] == 'c'){
+ if(utfrune(buf+1, Kdel))
+ goto end;
+ if(utfrune(buf+1, KF|1) && oct0 >= 12)
+ oct0 -= 12;
+ if(utfrune(buf+1, KF|2) && oct0 < 12*7)
+ oct0 += 12;
+ if(utfrune(buf+1, KF|3) && vol > 0)
+ vol -= 7;
+ if(utfrune(buf+1, KF|4) && vol < 126)
+ vol += 7;
+ }
+ kon = buf[0] == 'k';
+ if(kon){
+ s = buf+1;
+ s2 = buf2+1;
+ }else if(buf[0] == 'K'){
+ s = buf2+1;
+ s2 = buf+1;
+ }else
+ continue;
+ lockdisplay(display);
+ while(*s != 0){
+ s += chartorune(&r, s);
+ if(r == Kdel)
+ goto end;
+ if(utfrune(s2, r) != nil)
+ continue;
+ for(k=keytab; k<keytab+nelem(keytab); k++){
+ if(r != *k)
+ continue;
+ n = k - keytab;
+ if(n+oct0 >= nelem(notetab))
+ break;
+ string(screen, addpt(screen->r.min, Pt(n%12*4*font->width, fh-n/12*font->height)),
+ kon ? display->white : display->black,
+ ZP, font, notetab[n+oct0]);
+ if(soft)
+ fon[n+oct0] = kon;
+ else{
+ u[0] = 0;
+ u[1] = kon ? 0x90 : 0x80;
+ u[2] = n+oct0;
+ u[3] = kon ? vol : 0;
+ write(1, u, sizeof u);
+ }
+ }
+ }
+ flushimage(display, 1);
+ unlockdisplay(display);
+ strcpy(buf2, buf);
+ }
+end:
+ close(fd);
+ threadexitsall(nil);
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [-s]\n", argv0);
+ threadexits("usage");
+}
+
+void
+threadmain(int argc, char **argv)
+{
+ int i;
+ Mousectl *mctl;
+
+ ARGBEGIN{
+ case 's': soft = 1; break;
+ default: usage();
+ }ARGEND
+ if(initdraw(nil, nil, "mkey") < 0)
+ sysfatal("initdraw: %r");
+ string(screen, divpt(screen->r.max, 2), display->black, ZP, font, "a"); /* so font->width != 0... */
+ draw(screen, screen->r, display->black, nil, ZP);
+ flushimage(display, 1);
+ display->locking = 1;
+ unlockdisplay(display);
+ if((mctl = initmouse(nil, screen)) == nil)
+ sysfatal("initmouse: %r");
+ if(soft){
+ for(i=0; i<nelem(freq); i++)
+ freq[i] = Nrate / (440 * pow(1.05946, i - 69));
+ if(threadcreate(athread, nil, mainstacksize) < 0)
+ sysfatal("threadcreate: %r");
+ }
+ if(proccreate(kproc, nil, mainstacksize) < 0)
+ sysfatal("proccreate: %r");
+ Alt a[] = {
+ {mctl->resizec, nil, CHANRCV},
+ {mctl->c, nil, CHANRCV},
+ {nil, nil, CHANEND}
+ };
+ for(;;)
+ if(alt(a) == 0){
+ lockdisplay(display);
+ if(getwindow(display, Refnone) < 0)
+ sysfatal("resize failed: %r");
+ draw(screen, screen->r, display->black, nil, ZP);
+ flushimage(display, 1);
+ unlockdisplay(display);
+ }
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,6 @@
+</$objtype/mkfile
+BIN=$home/bin/$objtype
+TARG=mkey
+OFILES=mkey.$O
+HFILES=
+</sys/src/cmd/mkone