aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2019-07-28 23:40:40 +0200
committercbdev <cb@cbcdn.com>2019-07-28 23:40:40 +0200
commit4e604b493e0dc855b6ea6978e5cf8e2de5d2b8d5 (patch)
treee8e68bca670c2f093891587ff496b63825e976c5
parentaef72140273b3d98a4d86a42f0f3bcce6d5899ca (diff)
downloadmidimonster-4e604b493e0dc855b6ea6978e5cf8e2de5d2b8d5.tar.gz
midimonster-4e604b493e0dc855b6ea6978e5cf8e2de5d2b8d5.tar.bz2
midimonster-4e604b493e0dc855b6ea6978e5cf8e2de5d2b8d5.zip
Fix evdev relative axes, add detect option
-rw-r--r--TODO1
-rw-r--r--backends/evdev.c57
-rw-r--r--backends/evdev.h8
-rw-r--r--backends/evdev.md18
-rw-r--r--monster.cfg4
5 files changed, 75 insertions, 13 deletions
diff --git a/TODO b/TODO
index 2a97c30..5f4ce91 100644
--- a/TODO
+++ b/TODO
@@ -3,5 +3,4 @@ Note source in channel value struct
Optimize core channel search (store backend offset)
Printing backend / Verbose mode
-evdev relative axis size
mm_managed_fd.impl is not freed currently
diff --git a/backends/evdev.c b/backends/evdev.c
index ca8469a..565eb17 100644
--- a/backends/evdev.c
+++ b/backends/evdev.c
@@ -27,6 +27,12 @@ typedef union {
uint64_t label;
} evdev_channel_ident;
+static struct {
+ uint8_t detect;
+} evdev_config = {
+ .detect = 0
+};
+
int init(){
backend evdev = {
.name = BACKEND_NAME,
@@ -49,7 +55,15 @@ int init(){
}
static int evdev_configure(char* option, char* value) {
- fprintf(stderr, "The evdev backend does not take any global configuration\n");
+ if(!strcmp(option, "detect")){
+ evdev_config.detect = 1;
+ if(!strcmp(value, "off")){
+ evdev_config.detect = 0;
+ }
+ return 0;
+ }
+
+ fprintf(stderr, "Unknown configuration option %s for evdev backend\n", option);
return 1;
}
@@ -185,6 +199,22 @@ static int evdev_configure_instance(instance* inst, char* option, char* value) {
data->exclusive = 1;
return 0;
}
+ else if(!strncmp(option, "relaxis.", 8)){
+ data->relative_axis = realloc(data->relative_axis, (data->relative_axes + 1) * sizeof(evdev_relaxis_config));
+ if(!data->relative_axis){
+ fprintf(stderr, "Failed to allocate memory\n");
+ return 1;
+ }
+ data->relative_axis[data->relative_axes].code = libevdev_event_code_from_name(EV_REL, option + 8);
+ data->relative_axis[data->relative_axes].max = strtoul(value, &next_token, 0);
+ data->relative_axis[data->relative_axes].current = strtoul(next_token, NULL, 0);
+ if(data->relative_axis[data->relative_axes].code < 0){
+ fprintf(stderr, "Failed to configure relative axis extents for %s.%s\n", inst->name, option + 8);
+ return 1;
+ }
+ data->relative_axes++;
+ return 0;
+ }
#ifndef EVDEV_NO_UINPUT
else if(!strcmp(option, "output")){
data->output_enabled = 1;
@@ -214,7 +244,7 @@ static int evdev_configure_instance(instance* inst, char* option, char* value) {
return 0;
}
#endif
- fprintf(stderr, "Unknown configuration parameter %s for evdev backend\n", option);
+ fprintf(stderr, "Unknown instance configuration parameter %s for evdev instance %s\n", option, inst->name);
return 1;
}
@@ -275,21 +305,32 @@ static int evdev_push_event(instance* inst, evdev_instance_data* data, struct in
.fields.code = event.code
};
channel* chan = mm_channel(inst, ident.label, 0);
+ size_t axis;
if(chan){
val.raw.u64 = event.value;
switch(event.type){
case EV_REL:
- val.normalised = 0.5 + ((event.value < 0) ? 0.5 : -0.5);
+ for(axis = 0; axis < data->relative_axes; axis++){
+ if(data->relative_axis[axis].code == event.code){
+ data->relative_axis[axis].current = clamp(data->relative_axis[axis].current + event.value, data->relative_axis[axis].max, 0);
+ val.normalised = (double) data->relative_axis[axis].current / (double) data->relative_axis[axis].max;
+ break;
+ }
+ }
+ if(axis == data->relative_axes){
+ val.normalised = 0.5 + ((event.value < 0) ? 0.5 : -0.5);
+ break;
+ }
break;
case EV_ABS:
range = libevdev_get_abs_maximum(data->input_ev, event.code) - libevdev_get_abs_minimum(data->input_ev, event.code);
- val.normalised = (event.value - libevdev_get_abs_minimum(data->input_ev, event.code)) / (double) range;
+ val.normalised = clamp((event.value - libevdev_get_abs_minimum(data->input_ev, event.code)) / (double) range, 1.0, 0.0);
break;
case EV_KEY:
case EV_SW:
default:
- val.normalised = 1.0 * event.value;
+ val.normalised = clamp(1.0 * event.value, 1.0, 0.0);
break;
}
@@ -299,6 +340,10 @@ static int evdev_push_event(instance* inst, evdev_instance_data* data, struct in
}
}
+ if(evdev_config.detect){
+ fprintf(stderr, "Incoming evdev data for channel %s.%s.%s\n", inst->name, libevdev_event_type_get_name(event.type), libevdev_event_code_get_name(event.type, event.code));
+ }
+
return 0;
}
@@ -470,6 +515,8 @@ static int evdev_shutdown(){
libevdev_free(data->output_proto);
#endif
+ data->relative_axes = 0;
+ free(data->relative_axis);
free(data);
}
diff --git a/backends/evdev.h b/backends/evdev.h
index c6e3a25..d719631 100644
--- a/backends/evdev.h
+++ b/backends/evdev.h
@@ -24,10 +24,18 @@ static int evdev_shutdown();
#define UINPUT_MAX_NAME_SIZE 512
#endif
+typedef struct /*_evdev_relative_axis_config*/ {
+ int code;
+ int64_t max;
+ int64_t current;
+} evdev_relaxis_config;
+
typedef struct /*_evdev_instance_model*/ {
int input_fd;
struct libevdev* input_ev;
int exclusive;
+ size_t relative_axes;
+ evdev_relaxis_config* relative_axis;
int output_enabled;
#ifndef EVDEV_NO_UINPUT
diff --git a/backends/evdev.md b/backends/evdev.md
index d750f1e..995b44c 100644
--- a/backends/evdev.md
+++ b/backends/evdev.md
@@ -7,7 +7,9 @@ This functionality may require elevated privileges (such as special group member
#### Global configuration
-This backend does not take any global configuration.
+| Option | Example value | Default value | Description |
+|---------------|-----------------------|-----------------------|-----------------------|
+| `detect` | `on` | `off` | Output the channel specification for all events coming in on configured instances to help with configuration. |
#### Instance configuration
@@ -18,7 +20,8 @@ This backend does not take any global configuration.
| `output` | `My Input Device` | none | Output device presentation name. Setting this option enables the instance for output |
| `exclusive` | `1` | `0` | Prevent other processes from using the device |
| `id` | `0x1 0x2 0x3` | none | Set output device bus identification (Vendor, Product and Version), optional |
-| `axis.AXISNAME`| `34300 0 65536 255 4095` | none | Specify absolute axis details (see below) for output. This is required for any absolute axis to be output.
+| `axis.AXISNAME`| `34300 0 65536 255 4095` | none | Specify absolute axis details (see below) for output. This is required for any absolute axis to be output. |
+| `relaxis.AXISNAME`| `65534 32767` | none | Specify relative axis details (extent and optional initial value) for output and input (see below). |
The absolute axis details configuration (e.g. `axis.ABS_X`) is required for any absolute axis on output-enabled
instances. The configuration value contains, space-separated, the following values:
@@ -34,6 +37,13 @@ If an axis is not used for output, this configuration can be omitted.
For real devices, all of these parameters for every axis can be found by running `evtest` on the device.
+To use the input from relative axes in absolute-value based protocols, the backend needs a reference frame to
+convert the relative movements to absolute values.
+
+If relative axes are used without specifying their extents, the channel will generate normalized values
+of `0`, `0.5` and `1` for any input less than, equal to and greater than `0`, respectively. As for output, only
+the values `-1`, `0` and `1` are generated for the same interval.
+
#### Channel specification
A channel is specified by its event type and event code, separated by `.`. For a complete list of event types and codes
@@ -64,10 +74,6 @@ Input devices may synchronize logically connected event types (for example, X an
events. The MIDIMonster also generates these events after processing channel events, but may not keep the original
event grouping.
-Relative axes (`EV_REL`-type events), such as generated by mouses, are currently handled in a very basic fashion,
-generating only the normalized channel values of `0`, `0.5` and `1` for any input less than, equal to and greater
-than `0`, respectively. As for output, only the values `-1`, `0` and `1` are generated for the same interval.
-
`EV_KEY` key-down events are sent for normalized channel values over `0.9`.
Extended event type values such as `EV_LED`, `EV_SND`, etc are recognized in the MIDIMonster configuration file
diff --git a/monster.cfg b/monster.cfg
index 7db3ec3..2e6f76f 100644
--- a/monster.cfg
+++ b/monster.cfg
@@ -1,6 +1,8 @@
[backend artnet]
bind = 0.0.0.0
+[backend evdev]
+
[artnet art]
universe = 0
dest = 255.255.255.255
@@ -11,6 +13,6 @@ input = TPPS
[loopback loop]
[map]
+mouse.EV_REL.REL_X > loop.chan0
art.{3..4}{4..3} > loop.chan{4..3}{3..4}
art.{1..10} > loop.data{1..10}
-art.{500..599} > loop.test{500..599}