cuticle/hi/relay.c
2024-06-30 14:43:13 +03:00

143 lines
3.7 KiB
C

#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() {
CHiPubNode *n = calloc(1, sizeof(*n));
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;
}
static void keyhook_destroy(CHiPubNode *pubn) {
CHiKeyhookNode *n = (void*) pubn;
XRecordDisableContext(dpy, n->rc);
XRecordFreeContext(dpy, n->rc);
free(n);
}
CUTIVIS CHiPubNode *CHi_Keyhook() {
CHiKeyhookNode *n = calloc(1, sizeof(*n));
n->pub.type = CUTIHI_T('CKey','hook');
n->pub.Start = n->pub.Stop = NULL;
n->pub.Perform = keyhook_perform;
n->pub.Destroy = keyhook_destroy;
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;
}