2024-06-26 20:47:26 +03:00
|
|
|
#include"relay.h"
|
|
|
|
|
|
|
|
#include"img.h"
|
|
|
|
#include<tmmintrin.h>
|
|
|
|
#include<X11/XKBlib.h>
|
|
|
|
#include<X11/extensions/record.h>
|
|
|
|
#include<stdio.h>
|
|
|
|
#include<pthread.h>
|
|
|
|
#include<stdatomic.h>
|
|
|
|
#include<math.h>
|
|
|
|
|
|
|
|
static int scale_perform(CHiPubNode *n) {
|
|
|
|
float *scales = CHi_Crawl(&n->sinks[0])->data.vec4;
|
|
|
|
CHiImage *img = CHi_Crawl(&n->sinks[1])->data.sample;
|
|
|
|
|
|
|
|
if(n->sources[0].data.sample) {
|
|
|
|
CHi_Image_Free(n->sources[0].data.sample);
|
|
|
|
}
|
|
|
|
CHiImage *ret = n->sources[0].data.sample = CHi_Image_New(img->bpc, img->channels, img->stride, img->width, img->height, NULL);
|
|
|
|
|
|
|
|
__m128i iscales = _mm_set_epi16(
|
|
|
|
scales[3] * 65535, scales[0] * 65535, scales[1] * 65535, scales[2] * 65535,
|
|
|
|
scales[3] * 65535, scales[0] * 65535, scales[1] * 65535, scales[2] * 65535
|
|
|
|
);
|
|
|
|
|
|
|
|
for(size_t y = 0; y < img->height; y++) {
|
|
|
|
for(size_t x = 0; x < img->width; x += 16) {
|
|
|
|
__m128i pixels8 = _mm_loadu_si128((__m128i*) ((uintptr_t) img->data16 + y * img->stride + x));
|
|
|
|
__m128i mulled = _mm_mulhi_epu16(pixels8, iscales);
|
|
|
|
_mm_storeu_si128((__m128i*) ((uintptr_t) ret->data16 + y * img->stride + x), mulled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
CUTIVIS CHiPubNode *CHi_ComponentScale() {
|
2024-06-30 14:43:13 +03:00
|
|
|
CHiPubNode *n = calloc(1, sizeof(*n));
|
2024-06-26 20:47:26 +03:00
|
|
|
n->type = CUTIHI_T('CCmp','nScl');
|
|
|
|
n->Start = n->Stop = NULL;
|
|
|
|
n->Perform = scale_perform;
|
|
|
|
n->clean = 0;
|
|
|
|
n->sinkCount = 2;
|
|
|
|
n->sinks = calloc(sizeof(*n->sinks), n->sinkCount);
|
|
|
|
n->sourceCount = 1;
|
|
|
|
n->sources = calloc(sizeof(*n->sources), n->sourceCount);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Display *dpy;
|
|
|
|
typedef struct {
|
|
|
|
CHiPubNode pub;
|
|
|
|
XRecordContext rc;
|
|
|
|
pthread_t thrd;
|
|
|
|
|
|
|
|
atomic_int key;
|
|
|
|
atomic_bool on;
|
|
|
|
} CHiKeyhookNode;
|
|
|
|
|
|
|
|
static void keyhook_handler(XPointer ud, XRecordInterceptData *recdata) {
|
|
|
|
if(recdata->category != XRecordFromServer) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int type = ((unsigned char*) recdata->data)[0] & 0x7F;
|
|
|
|
int key = ((unsigned char*) recdata->data)[1];
|
|
|
|
int repeat = recdata->data[2] & 1;
|
|
|
|
|
|
|
|
CHiKeyhookNode *n = (CHiKeyhookNode*) ud;
|
|
|
|
|
|
|
|
printf("%i\n", key);
|
|
|
|
if(!repeat && key == n->key) {
|
|
|
|
if(type == KeyPress) {
|
|
|
|
n->on = 1;
|
|
|
|
} else if(type == KeyRelease) {
|
|
|
|
n->on = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XRecordFreeData(recdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *keyhook_thread(void *ud) {
|
|
|
|
CHiKeyhookNode *n = ud;
|
|
|
|
|
|
|
|
XRecordRange *rr = XRecordAllocRange();
|
|
|
|
rr->device_events.first = KeyPress;
|
|
|
|
rr->device_events.last = ButtonRelease;
|
|
|
|
n->rc = XRecordCreateContext(dpy, 0, &(XRecordClientSpec) {XRecordAllClients}, 1, &rr, 1);
|
|
|
|
XRecordEnableContext(dpy, n->rc, keyhook_handler, (XPointer) n);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int keyhook_perform(CHiPubNode *n) {
|
|
|
|
((CHiKeyhookNode*) n)->key = CHi_Crawl(&n->sinks[0])->data.vec4[0];
|
|
|
|
|
|
|
|
n->sources[0].type = CUTIHI_VAL_VEC4;
|
|
|
|
|
|
|
|
if(n->ng->compilationStatus == CUTIHI_COMP_READY || n->sinks[1].data.vec4[0] == 0) {
|
|
|
|
n->sources[0].data.vec4[0] = ((CHiKeyhookNode*) n)->on;
|
|
|
|
} else if(((CHiKeyhookNode*) n)->on) {
|
|
|
|
n->sources[0].data.vec4[0] = fminf(1, n->sources[0].data.vec4[0] + CHi_Time_GetDelta(n->ng) * n->sinks[1].data.vec4[0]);
|
|
|
|
} else {
|
|
|
|
n->sources[0].data.vec4[0] = fmaxf(0, n->sources[0].data.vec4[0] - CHi_Time_GetDelta(n->ng) * n->sinks[1].data.vec4[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-06-30 14:43:13 +03:00
|
|
|
static void keyhook_destroy(CHiPubNode *pubn) {
|
|
|
|
CHiKeyhookNode *n = (void*) pubn;
|
|
|
|
|
|
|
|
XRecordDisableContext(dpy, n->rc);
|
|
|
|
XRecordFreeContext(dpy, n->rc);
|
|
|
|
|
|
|
|
free(n);
|
|
|
|
}
|
|
|
|
|
2024-06-26 20:47:26 +03:00
|
|
|
CUTIVIS CHiPubNode *CHi_Keyhook() {
|
2024-06-30 14:43:13 +03:00
|
|
|
CHiKeyhookNode *n = calloc(1, sizeof(*n));
|
2024-06-26 20:47:26 +03:00
|
|
|
n->pub.type = CUTIHI_T('CKey','hook');
|
|
|
|
n->pub.Start = n->pub.Stop = NULL;
|
|
|
|
n->pub.Perform = keyhook_perform;
|
2024-06-30 14:43:13 +03:00
|
|
|
n->pub.Destroy = keyhook_destroy;
|
2024-06-26 20:47:26 +03:00
|
|
|
n->pub.clean = 0;
|
|
|
|
n->pub.sinkCount = 2;
|
|
|
|
n->pub.sinks = calloc(sizeof(*n->pub.sinks), n->pub.sinkCount);
|
|
|
|
n->pub.sourceCount = 1;
|
|
|
|
n->pub.sources = calloc(sizeof(*n->pub.sources), n->pub.sourceCount);
|
|
|
|
|
|
|
|
n->on = 0;
|
|
|
|
n->key = 0;
|
|
|
|
|
|
|
|
if(!dpy) {
|
|
|
|
dpy = XOpenDisplay(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_create(&n->thrd, NULL, keyhook_thread, n);
|
|
|
|
|
|
|
|
return &n->pub;
|
|
|
|
}
|