macro: add first implementation

The doctext needs fixes and the API might not be final.
This however works and allow to read the macro.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
This commit is contained in:
Benjamin Tissoires
2015-09-08 12:44:55 -04:00
parent a7a1f1a2a4
commit ce10bb1e84
7 changed files with 257 additions and 16 deletions

View File

@@ -598,15 +598,20 @@ etekcity_read_button(struct ratbag_button *button)
button->index, button->profile->index,
rc < 0 ? strerror(-rc) : "not read enough", rc);
} else {
log_info(device->ratbag,
"macro on button %d of profile %d is named '%s', and contains %d events:\n",
button->index, button->profile->index,
macro->name, macro->length);
ratbag_button_set_macro(button);
log_raw(device->ratbag,
"macro on button %d of profile %d is named '%s', and contains %d events:\n",
button->index, button->profile->index,
macro->name, macro->length);
for (j = 0; j < macro->length; j++) {
log_info(device->ratbag,
" - %s %s\n",
libevdev_event_code_get_name(EV_KEY, macro_mapping[macro->keys[j].keycode]),
macro->keys[j].flag & 0x80 ? "released" : "pressed");
ratbag_button_set_macro_event(button,
j,
macro->keys[j].flag & 0x80 ? RATBAG_MACRO_EVENT_KEY_RELEASED : RATBAG_MACRO_EVENT_KEY_PRESSED,
macro_mapping[macro->keys[j].keycode]);
log_raw(device->ratbag,
" - %s %s\n",
libevdev_event_code_get_name(EV_KEY, macro_mapping[macro->keys[j].keycode]),
macro->keys[j].flag & 0x80 ? "released" : "pressed");
}
}
msleep(10);

View File

@@ -247,6 +247,21 @@ struct ratbag_profile {
{ .type = RATBAG_BUTTON_ACTION_TYPE_MACRO, \
/* FIXME: add the macro keys */ }
struct ratbag_macro_event {
enum ratbag_macro_event_type type;
union ratbag_macro_evnt {
unsigned int key;
unsigned int timeout;
} event;
};
#define MAX_MACRO_EVENTS 64
struct ratbag_macro {
const char *name;
const char *group;
struct ratbag_macro_event events[MAX_MACRO_EVENTS];
};
struct ratbag_button_action {
enum ratbag_button_action_type type;
union ratbag_btn_action {
@@ -256,8 +271,8 @@ struct ratbag_button_action {
unsigned int key; /* action_type == key */
/* FIXME: modifiers */
} key;
/* FIXME: MACRO */
} action;
struct ratbag_macro *macro; /* dynamically allocated, so kept aside */
};
struct ratbag_button {
@@ -338,7 +353,7 @@ ratbag_button_action_match(const struct ratbag_button_action *action,
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL:
return match->action.special == action->action.special;
case RATBAG_BUTTON_ACTION_TYPE_MACRO:
/* FIXME: currently, do nothing */
return 1;
default:
break;
}

View File

@@ -1204,6 +1204,8 @@ static void
ratbag_button_destroy(struct ratbag_button *button)
{
list_remove(&button->link);
if (button->action.macro)
free(button->action.macro);
free(button);
}
@@ -1284,3 +1286,97 @@ ratbag_resolution_get_user_data(const struct ratbag_resolution *ratbag_resolutio
{
return ratbag_resolution->userdata;
}
LIBRATBAG_EXPORT int
ratbag_button_set_macro(struct ratbag_button *button)
{
struct ratbag_macro *macro;
if (!button->action.macro)
button->action.macro = zalloc(sizeof(*macro));
else
memset(button->action.macro, 0, sizeof(*macro));
button->action.type = RATBAG_BUTTON_ACTION_TYPE_MACRO;
return 0;
}
LIBRATBAG_EXPORT int
ratbag_button_set_macro_event(struct ratbag_button *button,
unsigned int index,
enum ratbag_macro_event_type type,
unsigned int data)
{
struct ratbag_macro *macro;
if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO ||
index >= MAX_MACRO_EVENTS)
return -EINVAL;
macro = button->action.macro;
switch (type) {
case RATBAG_MACRO_EVENT_KEY_PRESSED:
case RATBAG_MACRO_EVENT_KEY_RELEASED:
macro->events[index].type = type;
macro->events[index].event.key = data;
break;
case RATBAG_MACRO_EVENT_WAIT:
macro->events[index].type = type;
macro->events[index].event.timeout = data;
break;
case RATBAG_MACRO_EVENT_NONE:
macro->events[index].type = type;
break;
default:
return -EINVAL;
}
return 0;
}
LIBRATBAG_EXPORT enum ratbag_macro_event_type
ratbag_button_get_macro_event_type(struct ratbag_button *button, unsigned int index)
{
if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO ||
index >= MAX_MACRO_EVENTS)
return RATBAG_MACRO_EVENT_INVALID;
return button->action.macro->events[index].type;
}
LIBRATBAG_EXPORT int
ratbag_button_get_macro_event_key(struct ratbag_button *button, unsigned int index)
{
struct ratbag_macro *macro;
if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO ||
index >= MAX_MACRO_EVENTS)
return -EINVAL;
macro = button->action.macro;
if (macro->events[index].type != RATBAG_MACRO_EVENT_KEY_PRESSED &&
macro->events[index].type != RATBAG_MACRO_EVENT_KEY_RELEASED)
return -EINVAL;
return macro->events[index].event.key;
}
LIBRATBAG_EXPORT int
ratbag_button_get_macro_event_timeout(struct ratbag_button *button, unsigned int index)
{
struct ratbag_macro *macro;
if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO ||
index >= MAX_MACRO_EVENTS)
return -EINVAL;
macro = button->action.macro;
if (macro->events[index].type != RATBAG_MACRO_EVENT_WAIT)
return -EINVAL;
return macro->events[index].event.timeout;
}

View File

@@ -1259,19 +1259,95 @@ ratbag_button_disable(struct ratbag_button *button);
/**
* @ingroup button
*
* FIXME: no idea at this point
* Macro event types describing the event.
*/
unsigned int
ratbag_button_get_macro(struct ratbag_button *button);
enum ratbag_macro_event_type {
RATBAG_MACRO_EVENT_INVALID = -1,
RATBAG_MACRO_EVENT_NONE = 0,
RATBAG_MACRO_EVENT_KEY_PRESSED,
RATBAG_MACRO_EVENT_KEY_RELEASED,
RATBAG_MACRO_EVENT_WAIT,
};
/**
* @ingroup button
*
* FIXME: no idea at this point
* If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* this function returns the macro event type configured for the event at the
* given index.
*
* If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* this function returns @ref RATBAG_MACRO_EVENT_INVALID.
*
* @param button A previously initialized ratbag button
* @param index An index of the event within the macro we are interested in.
*
* @return The type of the event at the given index
*/
unsigned int
enum ratbag_macro_event_type
ratbag_button_get_macro_event_type(struct ratbag_button *button, unsigned int index);
/**
* @ingroup button
*
* If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, and if the
* event stored at the given index is @ref RATBAG_MACRO_EVENT_KEY_PRESSED or
* @ref RATBAG_MACRO_EVENT_KEY_RELEASED, this function returns the key code
* configured for the event at the given index.
*
* If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* or if the event stored at the given index is not
* @ref RATBAG_MACRO_EVENT_KEY_PRESSED or @ref RATBAG_MACRO_EVENT_KEY_RELEASED,
* this function returns -EINVAL.
*
* @param button A previously initialized ratbag button
* @param index An index of the event within the macro we are interested in.
*
* @return The key of the event at the given index
*/
int
ratbag_button_get_macro_event_key(struct ratbag_button *button, unsigned int index);
/**
* @ingroup button
*
* If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, and if the
* event stored at the given index is @ref RATBAG_MACRO_EVENT_WAIT, this
* function returns the timeout configured for the event at the given index.
*
* If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* or if the event stored at the given index is not
* @ref RATBAG_MACRO_EVENT_WAIT, this function returns -EINVAL.
*
* @param button A previously initialized ratbag button
* @param index An index of the event within the macro we are interested in.
*
* @return The tiemout of the event at the given index
*/
int
ratbag_button_get_macro_event_timeout(struct ratbag_button *button, unsigned int index);
/**
* @ingroup button
*
* Sets the button's action to @ref RATBAG_BUTTON_ACTION_TYPE_MACRO and
* allocates the required memory to store the macro.
*/
int
ratbag_button_set_macro(struct ratbag_button *button);
/**
* @ingroup button
*
* Sets the macro's event at the given index to the given type with the
* key code or timeout given.
*/
int
ratbag_button_set_macro_event(struct ratbag_button *button,
unsigned int index,
enum ratbag_macro_event_type type,
unsigned int data);
/**
* @ingroup button
*

View File

@@ -8,12 +8,17 @@ global:
ratbag_button_get_type;
ratbag_button_get_button;
ratbag_button_get_key;
ratbag_button_get_macro_event_type;
ratbag_button_get_macro_event_key;
ratbag_button_get_macro_event_timeout;
ratbag_button_get_special;
ratbag_button_get_user_data;
ratbag_button_has_action_type;
ratbag_button_ref;
ratbag_button_set_button;
ratbag_button_set_key;
ratbag_button_set_macro;
ratbag_button_set_macro_event;
ratbag_button_set_special;
ratbag_button_set_user_data;
ratbag_button_unref;

View File

@@ -145,6 +145,48 @@ button_action_key_to_str(struct ratbag_button *button)
return strdup(str);
}
static const char *strip_ev_key(int key)
{
const char *str = libevdev_event_code_get_name(EV_KEY, key);
if (!strncmp(str, "KEY_", 4))
return str + 4;
return str;
};
char *
button_action_macro_to_str(struct ratbag_button *button)
{
char str[4096] = {0};
int offset;
unsigned int i;
offset = snprintf(str, sizeof(str), "macro:");
for (i = 0; i < MAX_MACRO_EVENTS; i++) {
enum ratbag_macro_event_type type = ratbag_button_get_macro_event_type(button, i);
int key = ratbag_button_get_macro_event_key(button, i);
int timeout = ratbag_button_get_macro_event_timeout(button, i);
if (type == RATBAG_MACRO_EVENT_NONE)
break;
switch (type) {
case RATBAG_MACRO_EVENT_KEY_PRESSED:
offset += snprintf(str + offset, sizeof(str) - offset, " %s↓", strip_ev_key(key));
break;
case RATBAG_MACRO_EVENT_KEY_RELEASED:
offset += snprintf(str + offset, sizeof(str) - offset, " %s↑", strip_ev_key(key));
break;
case RATBAG_MACRO_EVENT_WAIT:
offset += snprintf(str + offset, sizeof(str) - offset, " %d.%d⏱", timeout / 1000, timeout % 1000);
default:
offset += snprintf(str + offset, sizeof(str) - offset, " ###");
}
}
return strdup(str);
}
char *
button_action_to_str(struct ratbag_button *button)
{
@@ -157,7 +199,7 @@ button_action_to_str(struct ratbag_button *button)
case RATBAG_BUTTON_ACTION_TYPE_BUTTON: str = button_action_button_to_str(button); break;
case RATBAG_BUTTON_ACTION_TYPE_KEY: str = button_action_key_to_str(button); break;
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL: str = strdup(button_action_special_to_str(button)); break;
case RATBAG_BUTTON_ACTION_TYPE_MACRO: str = strdup("macro"); break;
case RATBAG_BUTTON_ACTION_TYPE_MACRO: str = button_action_macro_to_str(button); break;
case RATBAG_BUTTON_ACTION_TYPE_NONE: str = strdup("none"); break;
default:
error("type %d unknown\n", type);

View File

@@ -37,6 +37,8 @@
#include <libratbag-util.h>
#include <libevdev/libevdev.h>
#define MAX_MACRO_EVENTS 64
LIBRATBAG_ATTRIBUTE_PRINTF(1, 2)
static inline void
error(const char *format, ...)