aboutsummaryrefslogtreecommitdiffhomepage
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
parentc0bb55ff08faf2f89af947090d1c9bc412927d9f (diff)
downloadmidimonster-4f467a30f88a628e0e49858986d9278e12a92ce5.tar.gz
midimonster-4f467a30f88a628e0e49858986d9278e12a92ce5.tar.bz2
midimonster-4f467a30f88a628e0e49858986d9278e12a92ce5.zip
Implement wininput skeleton and mouse output
-rw-r--r--backends/Makefile2
-rw-r--r--backends/wininput.c224
-rw-r--r--backends/wininput.h44
-rw-r--r--midimonster.h2
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 */