aboutsummaryrefslogtreecommitdiffhomepage
path: root/backends/wininput.c
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2020-05-01 16:49:49 +0200
committercbdev <cb@cbcdn.com>2020-05-01 16:49:49 +0200
commit4f467a30f88a628e0e49858986d9278e12a92ce5 (patch)
treef2a94dad142d6b4be7a5a116d6daec172b2c64b8 /backends/wininput.c
parentc0bb55ff08faf2f89af947090d1c9bc412927d9f (diff)
downloadmidimonster-4f467a30f88a628e0e49858986d9278e12a92ce5.tar.gz
midimonster-4f467a30f88a628e0e49858986d9278e12a92ce5.tar.bz2
midimonster-4f467a30f88a628e0e49858986d9278e12a92ce5.zip
Implement wininput skeleton and mouse output
Diffstat (limited to 'backends/wininput.c')
-rw-r--r--backends/wininput.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/backends/wininput.c b/backends/wininput.c
new file mode 100644
index 0000000..352be66
--- /dev/null
+++ b/backends/wininput.c
@@ -0,0 +1,224 @@
+#define BACKEND_NAME "wininput"
+#define DEBUG
+
+#include <string.h>
+#include "wininput.h"
+
+MM_PLUGIN_API int init(){
+ backend wininput = {
+ .name = BACKEND_NAME,
+ .conf = wininput_configure,
+ .create = wininput_instance,
+ .conf_instance = wininput_configure_instance,
+ .channel = wininput_channel,
+ .handle = wininput_set,
+ .process = wininput_handle,
+ .start = wininput_start,
+ .shutdown = wininput_shutdown
+ };
+
+ if(sizeof(wininput_channel_ident) != sizeof(uint64_t)){
+ LOG("Channel identification union out of bounds");
+ return 1;
+ }
+
+ //register backend
+ if(mm_backend_register(wininput)){
+ LOG("Failed to register backend");
+ return 1;
+ }
+ return 0;
+}
+
+static int wininput_configure(char* option, char* value){
+ LOG("The backend does not take any global configuration");
+ return 1;
+}
+
+static int wininput_configure_instance(instance* inst, char* option, char* value){
+ LOG("The backend does not take any instance configuration");
+ return 0;
+}
+
+static int wininput_instance(instance* inst){
+ wininput_instance_data* data = calloc(1, sizeof(wininput_instance_data));
+ if(!data){
+ LOG("Failed to allocate memory");
+ return 1;
+ }
+
+ inst->impl = data;
+ return 0;
+}
+
+static channel* wininput_channel(instance* inst, char* spec, uint8_t flags){
+ char* token = spec;
+ wininput_channel_ident ident = {
+ .label = 0
+ };
+
+ if(!strncmp(spec, "mouse.", 6)){
+ //TODO wheel
+ token += 6;
+ ident.fields.type = mouse;
+ if(!strcmp(token, "x")){
+ ident.fields.channel = position;
+ }
+ else if(!strcmp(token, "y")){
+ ident.fields.channel = position;
+ ident.fields.control = 1;
+ }
+ else if(!strcmp(token, "lmb")){
+ ident.fields.channel = button;
+ }
+ else if(!strcmp(token, "rmb")){
+ ident.fields.channel = button;
+ ident.fields.control = 1;
+ }
+ else if(!strcmp(token, "mmb")){
+ ident.fields.channel = button;
+ ident.fields.control = 2;
+ }
+ else if(!strcmp(token, "xmb1")){
+ ident.fields.channel = button;
+ ident.fields.control = 3;
+ }
+ else if(!strcmp(token, "xmb2")){
+ ident.fields.channel = button;
+ ident.fields.control = 4;
+ }
+ else{
+ LOGPF("Unknown control %s", token);
+ return NULL;
+ }
+ }
+ else if(!strncmp(spec, "keyboard.", 9)){
+ token += 9;
+ //TODO
+ }
+ else{
+ LOGPF("Unknown channel spec %s", spec);
+ }
+
+ if(ident.label){
+ return mm_channel(inst, ident.label, 1);
+ }
+ return NULL;
+}
+
+static INPUT wininput_event_mouse(wininput_instance_data* data, uint8_t channel, uint8_t control, double value){
+ DWORD flags_down = 0, flags_up = 0;
+ INPUT ev = {
+ .type = INPUT_MOUSE
+ };
+
+ if(channel == position){
+ if(control){
+ data->mouse.y = value * 0xFFFF;
+ }
+ else{
+ data->mouse.x = value * 0xFFFF;
+ }
+
+ ev.mi.dwFlags |= MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
+ ev.mi.dx = data->mouse.x;
+ ev.mi.dy = data->mouse.y;
+ }
+ if(channel == button){
+ switch(control){
+ case 0:
+ flags_up |= MOUSEEVENTF_LEFTUP;
+ flags_down |= MOUSEEVENTF_LEFTDOWN;
+ break;
+ case 1:
+ flags_up |= MOUSEEVENTF_RIGHTUP;
+ flags_down |= MOUSEEVENTF_RIGHTDOWN;
+ break;
+ case 2:
+ flags_up |= MOUSEEVENTF_MIDDLEUP;
+ flags_down |= MOUSEEVENTF_MIDDLEDOWN;
+ break;
+ case 3:
+ case 4:
+ ev.mi.mouseData = (control == 3) ? XBUTTON1 : XBUTTON2;
+ flags_up |= MOUSEEVENTF_XUP;
+ flags_down |= MOUSEEVENTF_XDOWN;
+ break;
+ }
+
+ if(value > 0.9){
+ ev.mi.dwFlags |= flags_down;
+ }
+ else{
+ ev.mi.dwFlags |= flags_up;
+ }
+ }
+
+ return ev;
+}
+
+static INPUT wininput_event_keyboard(wininput_instance_data* data, uint8_t channel, uint8_t control, double value){
+ INPUT ev = {
+ .type = INPUT_KEYBOARD
+ };
+
+ return ev;
+}
+
+static int wininput_set(instance* inst, size_t num, channel** c, channel_value* v){
+ wininput_channel_ident ident = {
+ .label = 0
+ };
+ wininput_instance_data* data = (wininput_instance_data*) inst->impl;
+ size_t n = 0, offset = 0;
+ INPUT events[500];
+
+ //FIXME might want to coalesce mouse events
+ if(num > sizeof(events) / sizeof(events[0])){
+ LOGPF("Truncating output on %s to the last %" PRIsize_t " events, please notify the developers", inst->name, sizeof(events) / sizeof(events[0]));
+ offset = num - sizeof(events) / sizeof(events[0]);
+ }
+
+ for(n = 0; n + offset < num; n++){
+ ident.label = c[n + offset]->ident;
+ if(ident.fields.type == mouse){
+ events[n] = wininput_event_mouse(data, ident.fields.channel, ident.fields.control, v[n + offset].normalised);
+ }
+ else if(ident.fields.type == keyboard){
+ events[n] = wininput_event_keyboard(data, ident.fields.channel, ident.fields.control, v[n + offset].normalised);
+ }
+ else{
+ n--;
+ offset++;
+ }
+ }
+
+ if(n){
+ offset = SendInput(n, events, sizeof(INPUT));
+ if(offset != n){
+ LOGPF("Output %" PRIsize_t " of %" PRIsize_t " events on %s", offset, n, inst->name);
+ }
+ }
+ return 0;
+}
+
+static int wininput_handle(size_t num, managed_fd* fds){
+ //TODO
+ return 0;
+}
+
+static int wininput_start(size_t n, instance** inst){
+ //TODO
+ return 0;
+}
+
+static int wininput_shutdown(size_t n, instance** inst){
+ size_t u;
+
+ for(u = 0; u < n; u++){
+ free(inst[u]->impl);
+ }
+
+ LOG("Backend shut down");
+ return 0;
+}