mirror of
https://github.com/robotn/gohook.git
synced 2025-05-20 15:24:25 +08:00
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:
parent
e5d15765a1
commit
11eee3201f
1430
chan/eb_chan.h
Normal file
1430
chan/eb_chan.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
|
||||
|
32
extern.go
32
extern.go
@ -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
101
hook.go
@ -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);
|
||||
}
|
||||
|
32
test/main.go
32
test/main.go
@ -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...")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user