diff options
-rw-r--r-- | backends/Makefile | 2 | ||||
-rw-r--r-- | backends/wininput.c | 224 | ||||
-rw-r--r-- | backends/wininput.h | 44 | ||||
-rw-r--r-- | midimonster.h | 2 |
4 files changed, 270 insertions, 2 deletions
diff --git a/backends/Makefile b/backends/Makefile index 700c9b3..9b66728 100644 --- a/backends/Makefile +++ b/backends/Makefile @@ -1,6 +1,6 @@ .PHONY: all clean full LINUX_BACKENDS = midi.so evdev.so -WINDOWS_BACKENDS = artnet.dll osc.dll loopback.dll sacn.dll maweb.dll winmidi.dll openpixelcontrol.dll rtpmidi.dll +WINDOWS_BACKENDS = artnet.dll osc.dll loopback.dll sacn.dll maweb.dll winmidi.dll openpixelcontrol.dll rtpmidi.dll wininput.dll BACKENDS = artnet.so osc.so loopback.so sacn.so lua.so maweb.so jack.so openpixelcontrol.so python.so rtpmidi.so OPTIONAL_BACKENDS = ola.so BACKEND_LIB = libmmbackend.o 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; +} diff --git a/backends/wininput.h b/backends/wininput.h new file mode 100644 index 0000000..240f1a6 --- /dev/null +++ b/backends/wininput.h @@ -0,0 +1,44 @@ +#include "midimonster.h" + +MM_PLUGIN_API int init(); +static int wininput_configure(char* option, char* value); +static int wininput_configure_instance(instance* inst, char* option, char* value); +static int wininput_instance(instance* inst); +static channel* wininput_channel(instance* inst, char* spec, uint8_t flags); +static int wininput_set(instance* inst, size_t num, channel** c, channel_value* v); +static int wininput_handle(size_t num, managed_fd* fds); +static int wininput_start(size_t n, instance** inst); +static int wininput_shutdown(size_t n, instance** inst); + +enum /*wininput_channel_type*/ { + none = 0, + mouse, + keyboard, + joystick +}; + +enum /*wininput_control_channel*/ { + position, + //wheel, /*relative*/ + button, + + keypress, + key_unicode +}; + +typedef union { + struct { + uint8_t pad[4]; + uint8_t type; + uint8_t channel; + uint16_t control; + } fields; + uint64_t label; +} wininput_channel_ident; + +typedef struct { + struct { + uint16_t x; + uint16_t y; + } mouse; +} wininput_instance_data; diff --git a/midimonster.h b/midimonster.h index 75eb30a..a5de60e 100644 --- a/midimonster.h +++ b/midimonster.h @@ -7,7 +7,7 @@ /* Core version unless set by the build process */ #ifndef MIDIMONSTER_VERSION - #define MIDIMONSTER_VERSION "v0.5-dist" + #define MIDIMONSTER_VERSION "v0.6-dist" #endif /* Set backend name if unset */ |