Skip to content

Commit

Permalink
add "mode" support
Browse files Browse the repository at this point in the history
  • Loading branch information
wertarbyte committed Nov 18, 2010
1 parent 51b9c09 commit fb18bd5
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 14 deletions.
2 changes: 2 additions & 0 deletions thd.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,8 @@ int main(int argc, char *argv[]) {
}
/* init keystate holder */
init_keystate_holder(&keystate);
/* set initial trigger mode */
change_trigger_mode("");
/* install signal handler */
struct sigaction handler;
handler.sa_handler = handle_signal;
Expand Down
22 changes: 21 additions & 1 deletion thd.pod
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,27 @@ Any number of event handlers can be placed in the configuration file:
KEY_VOLUMEUP 2 /usr/bin/amixer set Master 5%+
KEY_VOLUMEDOWN 1 /usr/bin/amixer set Master 5%-
KEY_VOLUMEDOWN 2 /usr/bin/amixer set Master 5%-


In more complex situations, triggerhappy can provide multiple modes that map a
single event to different keys; triggers are bound to a specific mode by appending
its name to the event name:

KEY_KPPLUS@media 1 /usr/bin/mpc next
KEY_KPMINUS@media 1 /usr/bin/mpc prev

These two lines will only cause mpc to be called if the triggerhappy daemon is in
"media" mode. Changing the mode can be achieved by placing a special trigger inside
the configuration:

KEY_F12@ 1 @media
KEY_F12@media 1 @

These two lines make the F12 key toggle between the (nameless) default mode and the
newly defined media mode.

Triggers with "@" appended are only executed if the specified mode is active; all other
triggers are enabled in every mode.

=head1 AUTHOR

Stefan Tomanek E<lt>[email protected]<gt>
Expand Down
80 changes: 67 additions & 13 deletions trigger.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
Expand All @@ -13,6 +14,20 @@ static trigger *trigger_list = NULL;

static int triggers_are_enabled = 1;

static char *trigger_mode = NULL;

char *get_trigger_mode() {
return trigger_mode;
}

void change_trigger_mode(const char *mode) {
if (trigger_mode != NULL) {
free(trigger_mode);
}
trigger_mode = strdup(mode);
fprintf(stderr, "Trigger mode changed to <%s>\n", trigger_mode);
}

void triggers_enabled( int status ) {
triggers_are_enabled = status;
}
Expand Down Expand Up @@ -48,9 +63,18 @@ trigger* parse_trigger(char* line) {
char *delim = " \t\n";

char *evdef = strtok_r(cp, delim, &sptr);
/* extract mode (if any) */
char *mode = NULL;
if (evdef) {
char *mode_delim = index(evdef, '@');
if (mode_delim) {
mode = strdup( &(mode_delim[1]) );
*mode_delim = '\0'; /* cut it off */
}
}
/* extract modifier */
char *sptr2 = NULL;
char *evname = ct( strtok_r(cp, "+", &sptr2) );
char *evname = ct( strtok_r(evdef, "+", &sptr2) );
/* build array of modifier keycodes */
trigger_modifier modifier;
int n = 0;
Expand All @@ -60,7 +84,16 @@ trigger* parse_trigger(char* line) {
n++;
}
int value = strint( strtok_r(NULL, delim, &sptr) );
char *cmd = ct( strtok_r(NULL, "\n", &sptr) );
char *cmdline = strtok_r(NULL, "\n", &sptr);
if (cmdline) {
/* remove whitespaces at the end */
char *end = cmdline + strlen(cmdline) - 1;
while (end >= cmdline && isspace(*end)) {
end--;
}
*(end+1) = '\0';
}
char *cmd = ct( cmdline );
free(cp);
cp = NULL;

Expand All @@ -71,6 +104,7 @@ trigger* parse_trigger(char* line) {
et->code = lookup_event_code( evname );
et->value = value;
et->cmdline = cmd;
et->mode = mode;
/* store modifier state */
memcpy(et->modifiers, modifier, sizeof(trigger_modifier));
et->next = NULL;
Expand All @@ -80,6 +114,7 @@ trigger* parse_trigger(char* line) {
} else {
free(evname);
free(cmd);
free(mode);
return NULL;
}
}
Expand Down Expand Up @@ -198,6 +233,11 @@ static int mods_equal( keystate_holder ksh, trigger_modifier tm ) {
return (n == 0);
}

static int correct_mode( const char *tmode ) {
/* not mode specified, valid in every mode */
return (tmode == NULL) || (strcmp( get_trigger_mode(), tmode ) == 0);
}

void run_triggers(int type, int code, int value, keystate_holder ksh) {
if (triggers_are_enabled == 0) {
return;
Expand All @@ -208,19 +248,29 @@ void run_triggers(int type, int code, int value, keystate_holder ksh) {
code == et->code &&
value == et->value &&
et->cmdline &&
correct_mode( et->mode ) &&
mods_equal(ksh, et->modifiers)) {
fprintf(stderr, "Executing trigger: %s\n", et->cmdline);
int pid = fork();
if (pid == 0 ) {
/* adjust environment */
setenv( "TH_KEYSTATE", get_keystate(ksh), 1 );
const char *en = lookup_event_name_i( et->type, et->code );
setenv( "TH_EVENT", en, 1 );
char ev[8];
sprintf( &(ev[0]), "%d", et->value );
setenv( "TH_VALUE", &(ev[0]), 1 );
system( et->cmdline );
exit(0);
/* switch trigger mode or execute program? */
if (et->cmdline[0] == '@') {
change_trigger_mode( &(et->cmdline)[1] );
/* we now stop checking for additional triggers
* to avoid changing back to the original mode
*/
break;
} else {
int pid = fork();
if (pid == 0 ) {
/* adjust environment */
setenv( "TH_KEYSTATE", get_keystate(ksh), 1 );
const char *en = lookup_event_name_i( et->type, et->code );
setenv( "TH_EVENT", en, 1 );
char ev[8];
sprintf( &(ev[0]), "%d", et->value );
setenv( "TH_VALUE", &(ev[0]), 1 );
system( et->cmdline );
exit(0);
}
}
}
et = et->next;
Expand All @@ -244,6 +294,10 @@ void clear_triggers() {
while ( *p != NULL ) {
trigger **n = &( (*p)->next );
free( (*p)->cmdline );
if ( (*p)->mode ) {
/* might be NULL */
free( (*p)->mode );
}
free( (*p) );
*p = NULL;
p = n;
Expand Down
1 change: 1 addition & 0 deletions trigger.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ typedef struct trigger {
int code;
int value;
trigger_modifier modifiers;
char *mode;
char *cmdline;
struct trigger *next;
} trigger;
Expand Down
6 changes: 6 additions & 0 deletions triggerhappy.conf.examples
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ KEY_VOLUMEUP 2 /usr/bin/amixer set Master 5%+ # even while holding
KEY_VOLUMEDOWN 1 /usr/bin/amixer set Master 5%-
KEY_VOLUMEDOWN+KEY_LEFTSHIFT 1 /usr/bin/amixer set Master 15%-
KEY_VOLUMEDOWN 2 /usr/bin/amixer set Master 5%-
# only trigger commands when in "media" mode
KEY_KPPLUS@media 1 /usr/bin/mpc next # next song
KEY_KPMINUS@media 1 /usr/bin/mpc prev # next song
# only used if in the nameless default mode
KEY_F12@ 1 @media # switch to media mode
KEY_F12@media 1 @ # switch back to nameless default mode

0 comments on commit fb18bd5

Please sign in to comment.