Part 2 of making the lib async

- New event struct mimiking C structs
 - changed c channel library to eb_chan
 - changed API to something more palatable
This commit is contained in:
htmk 2019-02-08 20:26:02 -02:00
parent e5d15765a1
commit 11eee3201f
5 changed files with 1602 additions and 81 deletions

1430
chan/eb_chan.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,22 +15,66 @@
#include <stdlib.h>
#include "pub.h"
#include "../chan/src/chan.h"
//#include "../chan/src/chan.h"
#include "../chan/eb_chan.h"
//chan_t * events = NULL;
eb_chan events;
chan_t * events = NULL;
void go_send(char*);
void go_sleep(void);
bool sending = false;
void startev(){
// events = chan_init(1024);
events = eb_chan_create(1024);
eb_chan_retain(events);
sending = true;
add_event("q");
}
//bool done = false;
void pollEv(){
if(events == NULL) return;
for(;eb_chan_buf_len(events)!=0;){
char* tmp;
if(eb_chan_try_recv(events,(const void**) &tmp) == eb_chan_res_ok){
go_send(tmp);
free(tmp);
}else{
//
}
}
}
void endPoll(){
sending = false;
pollEv();//remove last things from channel
eb_chan_release(events);
}
void dispatch_proc(iohook_event * const event) {
char buffer[256] = { 0 };
size_t length = snprintf(buffer, sizeof(buffer),
"{id:%i,when:%" PRIu64 ",mask=0x%X",
event->type, event->time, event->mask);
if(!sending) return;
//leaking memory? hope not
char* buffer = calloc(200,sizeof(char));
// char buffer[256] = { 0 };
// size_t length = snprintf(buffer, sizeof(buffer),
// "{id:%i,when:%" PRIu64 ",mask=0x%X",
// event->type, event->time, event->mask);
switch (event->type) {
case EVENT_HOOK_ENABLED:
case EVENT_HOOK_DISABLED:
sprintf(buffer,"{\"id\":%i,\"time\":%" PRIu64 ",\"mask\":%hu,\"reserved\":%hu}",
event->type, event->time, event->mask,event->reserved);
// fprintf(stdout,"hook enabled");
break;//send it?
case EVENT_KEY_PRESSED:
case EVENT_KEY_RELEASED:
case EVENT_KEY_TYPED:
length = snprintf(buffer + length, sizeof(buffer) - length,
",keycode:%hu,rawcode:%hu,keychar:%hu}",
sprintf(buffer,
"{\"id\":%i,\"time\":%" PRIu64 ",\"mask\":%hu,\"reserved\":%hu,\"keycode\":%hu,\"rawcode\":%hu,\"keychar\":%hu}",
event->type, event->time, event->mask,event->reserved,
event->data.keyboard.keycode,
event->data.keyboard.rawcode,
event->data.keyboard.keychar);
@ -40,16 +84,18 @@ void dispatch_proc(iohook_event * const event) {
case EVENT_MOUSE_CLICKED:
case EVENT_MOUSE_MOVED:
case EVENT_MOUSE_DRAGGED:
snprintf(buffer + length, sizeof(buffer) - length,
",x:%u,y:%u,button:%u,clicks:%u}",
sprintf(buffer,
"{\"id\":%i,\"time\":%" PRIu64 ",\"mask\":%hu,\"reserved\":%hu,\"x\":%hd,\"y\":%hd,\"button\":%u,\"clicks\":%u}",
event->type, event->time, event->mask,event->reserved,
event->data.mouse.x,
event->data.mouse.y,
event->data.mouse.button,
event->data.mouse.clicks);
break;
case EVENT_MOUSE_WHEEL:
snprintf(buffer + length, sizeof(buffer) - length,
",clicks:%hu,x:%hd,y:%hd,type:%hu,ammount:%hu,rotation:%hd,direction:%hu}",
sprintf(buffer,
"{\"id\":%i,\"time\":%" PRIu64 ",\"mask\":%hu,\"reserved\":%hu,\"clicks\":%hu,\"x\":%hd,\"y\":%hd,\"type\":%hu,\"ammount\":%hu,\"rotation\":%hd,\"direction\":%hu}",
event->type, event->time, event->mask, event->reserved,
event->data.wheel.clicks,
event->data.wheel.x,
event->data.wheel.y,
@ -59,21 +105,29 @@ void dispatch_proc(iohook_event * const event) {
event->data.wheel.direction);
break;
default:
fprintf(stderr,"\nError on file: %s, unusual event->type\n",__FILE__);
fprintf(stderr,"\nError on file: %s, unusual event->type: %i\n",__FILE__,event->type);
return;
}
//to-do remove this for
for(int i = 0; i < 5; i++){
switch(chan_select(NULL,0,NULL,&events,1,(void**) &buffer)){
case 0:
fprintf(stdout,"\nitem sent: %s",buffer);
switch(eb_chan_try_send(events,buffer)){
// switch(chan_select(NULL,0,NULL,&events,1,(void**) &buffer)){
case eb_chan_res_ok:
// case 0:
// fprintf(stdout,"\nlen:%i,item sent: %s",chan_size(events),buffer);
// fprintf(stdout,"\nlen:%i,item sent: %s",eb_chan_buf_len(events),buffer);
i=5;
break;
default:
chan_dispose(events);
fprintf(stdout,"\n%i",i);
if (i == 4) {//let's not leak memory
free(buffer);
}
// chan_dispose(events);
// fprintf(stdout,"%i",i);
continue;
}
}
// fprintf(stdout, "----%s\n", buffer);
}

View File

@ -6,16 +6,32 @@ package hook
// #include "event/hook_async.h"
*/
import "C"
import "time"
import (
"encoding/json"
"fmt"
"log"
"time"
)
//export go_send
func go_send(s *C.char) {
str := C.GoString(s)
ev <- str
str := []byte(C.GoString(s))
fmt.Println(string(str))
out := Event{}
err := json.Unmarshal(str, &out)
if err != nil{
log.Fatal(err)
}
out.When = time.Now() //at least it's consistent
if err != nil {
log.Fatal(err)
}
//todo: maybe make non-bloking
ev <- out
}
//export go_sleep
func go_sleep(){
//todo: find smallest time that does not destroy the cpu utilization
time.Sleep(time.Millisecond*50)
}
////export go_sleep
//func go_sleep(){
//
// time.Sleep(time.Millisecond*50)
//}

101
hook.go
View File

@ -20,64 +20,79 @@ package hook
//#cgo windows LDFLAGS: -lgdi32 -luser32
// #include "event/hook_async.h"
#include "chan/src/chan.h"
#include "event/goEvent.h"
void go_send(char*);
void go_sleep(void);
extern chan_t* events;
void startev(){
events = chan_init(1024);
add_event("q");
}
bool done = false;
void pollEv(){
while(!done){
for(int i=chan_size(events); i >0;i--){
char* tmp;
chan_recv(events,(void**) &tmp);
go_send(tmp);
}
//go_sleep();
}
}
void endPoll(){
done = true;
}
*/
import "C"
import (
// "fmt"
"unsafe"
"time"
)
var ev chan string = make(chan string,128)
//todo: add enums
const (
HOOK_ENABLED = 1 //iota
HOOK_DISABLED = 2
KEY_TYPED = 3
KEY_PRESSED = 4
KEY_RELEASED = 5
MOUSE_CLICKED = 6
MOUSE_PRESSED = 7
MOUSE_RELEASED = 8
MOUSE_MOVED = 9
MOUSE_DRAGGED = 10
MOUSE_WHEEL = 11
)
// AddEvent add event listener
func AddEvent(key string) int {
cs := C.CString(key)
defer C.free(unsafe.Pointer(cs))
eve := C.add_event(cs)
geve := int(eve)
return geve
type Event struct {
Kind uint8 `json:"id"`
When time.Time
Mask uint16 `json:"mask"`
Reserved uint16 `json:"reserved"`
Keycode uint16 `json:"keycode"`
Rawcode uint16 `json:"rawcode"`
Keychar uint16 `json:"keychar"`
Button uint16 `json:"button"`
Clicks uint16 `json:"clicks"`
X int16 `json:"x"`
Y int16 `json:"y"`
Ammount uint16 `json:"ammount"`
Rotation int16 `json:"rotation"`
Direction uint8 `json:"direction"`
}
func StartEvent() chan string{
C.startev()
go C.pollEv()
var (
ev chan Event = make(chan Event, 1024)
asyncon bool = false
)
func Start() chan Event {
//fmt.Print("Here1")
asyncon = true
go C.startev()
go func() {
for {
C.pollEv()
time.Sleep(time.Millisecond * 50)
//todo: find smallest time that does not destroy the cpu utilization
//fmt.Println("_here_")
if ! asyncon {
return
}
}
//fmt.Print("WOOOOOOOOOT")
}()
//fmt.Print("Here2")
return ev
}
// StopEvent stop event listener
func StopEvent() {
func End() {
C.endPoll()
C.stop_event()
C.chan_close(C.events);
for len(ev) != 0 {
<-ev
}
asyncon = false
//C.chan_close(C.events);
}

View File

@ -2,22 +2,28 @@ package main
import (
"fmt"
"time"
"github.com/robotn/gohook"
"github.com/cauefcr/gohook"
)
func main() {
s := hook.StartEvent()
s := hook.Start()
tout := time.After(time.Second * 10)
done := false
for !done {
select {
case i := <-s:
if i.Keychar == uint16('q') {
tout = time.After(1 * time.Millisecond)
}
fmt.Printf("%+v\n", i)
case <-tout:
fmt.Print("Done.")
done = true
break;
}
}
hook.End()
go func() {
fmt.Print("woo!")
for i:=range s {
fmt.Println(i)
}
}()
// hook.AsyncHook()
veve := hook.AddEvent("v")
if veve == 0 {
fmt.Println("v...")
}
}