mirror of
https://github.com/workinghard/jslisten.git
synced 2025-12-13 19:02:09 +00:00
Merge branch 'master' of https://github.com/workinghard/jslisten
Conflicts: bin/jslisten
This commit is contained in:
34
README.md
34
README.md
@@ -3,9 +3,10 @@
|
||||
## Index
|
||||
1. [Overview](#overview)
|
||||
2. [Usage](#usage)
|
||||
3. [Installation](##installation)
|
||||
4. [Configuration](##configuration)
|
||||
5. [Known limitations](##known_limitations)
|
||||
3. [Installation](#installation)
|
||||
4. [Configuration](#configuration)
|
||||
5. [Known limitations](#known-limitations)
|
||||
6. [Multiple key combinations](#multiple-key-combinations)
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -30,8 +31,12 @@ After searching the internet, I found nothing really interesting. Kodi addon wil
|
||||
Following example for Raspbian. Should work for many other distributions almost the same way.
|
||||
* Use the precompiled binary in bin/ or run "# make" to create the binary
|
||||
* Place the binary to "/opt/bin" (if you change the folder, please update your init script)
|
||||
* Copy the init script "utils/jslisten-init" to "/etc/init.d/jslisten"
|
||||
* Execute "# update-rc.d jslisten defaults" to make the daemon run on startup
|
||||
* Copy the configuration script to /etc/jslisten.cfg
|
||||
* Modify the configuration script to your needs
|
||||
* Copy the service script "utils/jslisten.service" to "/etc/systemd/system"
|
||||
* Update the systemd daemon: "# systemctl daemon-reload"
|
||||
* Start the daemon "# systemctl start jslisten.service"
|
||||
* Make it start at boot "# systemctl enable jslisten"
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -57,4 +62,23 @@ button4=
|
||||
* If you have many different /dev/inputs, you might need to adjust this program to search for special one.
|
||||
* Kodi and X11 are blocking /dev/input/* events. For X11 you can add an exception in /usr/share/X11/xorg.conf.d/10-quirks.conf but Kodi is ... nasty ... As long as they don't implement a nice
|
||||
unified unput support, my workaround is to revoke the kodi group rights to the input devices. :(
|
||||
* If you experience any issues, feel free to use '--debug' option
|
||||
|
||||
## Multiple key combinations
|
||||
You can have different key sets to run different programs:
|
||||
```
|
||||
[Generic]
|
||||
program="/opt/bin/modeSwitcher.sh"
|
||||
button1=10
|
||||
button2=11
|
||||
button3=0
|
||||
button4=
|
||||
|
||||
[Fun]
|
||||
program="/opt/bin/haveFun.sh"
|
||||
button1=0
|
||||
button2=3
|
||||
button3=
|
||||
button4=
|
||||
```
|
||||
|
||||
|
||||
BIN
bin/jslisten
BIN
bin/jslisten
Binary file not shown.
13
etc/jslisten.cfg
Normal file
13
etc/jslisten.cfg
Normal file
@@ -0,0 +1,13 @@
|
||||
[Generic]
|
||||
program="/opt/bin/test.sh"
|
||||
button1=10
|
||||
button2=11
|
||||
button3=0
|
||||
button4=
|
||||
|
||||
[Add1]
|
||||
program="/opt/bin/test2.sh"
|
||||
button1=0
|
||||
button2=3
|
||||
button3=
|
||||
button4=
|
||||
270
src/jslisten.c
270
src/jslisten.c
@@ -54,23 +54,37 @@
|
||||
#define MYPROGNAME "jslisten"
|
||||
#define myConfFile "/.jslisten"
|
||||
#define myGlConfFile "/etc/jslisten.cfg"
|
||||
#define MY_LOG_LEVEL LOG_NOTICE //LOG_DEBUG //LOG_NOTICE
|
||||
//#define MY_LOG_LEVEL LOG_NOTICE //LOG_DEBUG //LOG_NOTICE
|
||||
|
||||
#define INI_BUFFERSIZE 512
|
||||
#define MAX_HOTKEYS 99
|
||||
|
||||
|
||||
//---------------------------------
|
||||
// Global definitions
|
||||
//---------------------------------
|
||||
char iniFile[512];
|
||||
char iniFile[INI_BUFFERSIZE];
|
||||
int joyFD;
|
||||
long button1 = BUTTON_DEFINED_RANGE; // Default unassigned
|
||||
long button2 = BUTTON_DEFINED_RANGE; // Default unassigned
|
||||
long button3 = BUTTON_DEFINED_RANGE; // Default unassigned
|
||||
long button4 = BUTTON_DEFINED_RANGE; // Default unassigned
|
||||
int buttonActive = 0;
|
||||
char swFilename[100];
|
||||
struct KeySet{
|
||||
// Set Default unassigned
|
||||
long button1;
|
||||
int button1Active;
|
||||
long button2;
|
||||
int button2Active;
|
||||
long button3;
|
||||
int button3Active;
|
||||
long button4;
|
||||
int button4Active;
|
||||
int activeButtons;
|
||||
int isTriggered;
|
||||
char swFilename[100];
|
||||
};
|
||||
|
||||
struct KeySet myKeys[MAX_HOTKEYS];
|
||||
|
||||
int numHotkeys = 0;
|
||||
//int buttonActive = 0;
|
||||
int logLevel = LOG_NOTICE;
|
||||
|
||||
//---------------------------------
|
||||
// Check if the button was assigned
|
||||
@@ -133,46 +147,49 @@ void readConfig(void) {
|
||||
|
||||
/* section/key enumeration */
|
||||
for (s = 0; ini_getsection(s, section, sizearray(section), iniFile) > 0; s++) {
|
||||
for (k = 0; ini_getkey(section, k, str, sizearray(str), iniFile) > 0; k++) {
|
||||
if ( strncmp("program", str, 7) == 0 ) { // Key found
|
||||
n = ini_gets(section, str, "dummy", swFilename, sizearray(swFilename), iniFile);
|
||||
if ( n > 5 && strncmp("dummy", swFilename, 5) != 0 ) { // Value is not empty
|
||||
syslog(LOG_INFO, "Filename: %s\n", swFilename);
|
||||
}
|
||||
}
|
||||
if ( strncmp("button1", str, 7) == 0 ) { // Key found
|
||||
l = ini_getl(section, str, BUTTON_DEFINED_RANGE, iniFile);
|
||||
if ( buttonDefined(l) == true ) { // Value is not empty
|
||||
syslog(LOG_INFO, "button1: %ld\n", l);
|
||||
button1 = l;
|
||||
buttonActive++;
|
||||
}
|
||||
}
|
||||
if ( strncmp("button2", str, 7) == 0 ) { // Key found
|
||||
l = ini_getl(section, str, BUTTON_DEFINED_RANGE, iniFile);
|
||||
if ( buttonDefined(l) == true ) { // Value is not empty
|
||||
syslog(LOG_INFO, "button2: %ld\n", l);
|
||||
button2 = l;
|
||||
buttonActive++;
|
||||
}
|
||||
}
|
||||
if ( strncmp("button3", str, 7) == 0 ) { // Key found
|
||||
l = ini_getl(section, str, BUTTON_DEFINED_RANGE, iniFile);
|
||||
if ( buttonDefined(l) == true ) { // Value is not empty
|
||||
syslog(LOG_INFO, "button3: %ld\n", l);
|
||||
button3 = l;
|
||||
buttonActive++;
|
||||
}
|
||||
}
|
||||
if ( strncmp("button4", str, 7) == 0 ) { // Key found
|
||||
l = ini_getl(section, str, BUTTON_DEFINED_RANGE, iniFile);
|
||||
if ( buttonDefined(l) == true ){ // Value is not empty
|
||||
syslog(LOG_INFO, "button4: %ld\n", l);
|
||||
button4 = l;
|
||||
buttonActive++;
|
||||
}
|
||||
}
|
||||
} /* for */
|
||||
if ( numHotkeys < MAX_HOTKEYS ) {
|
||||
for (k = 0; ini_getkey(section, k, str, sizearray(str), iniFile) > 0; k++) {
|
||||
if ( strncmp("program", str, 7) == 0 ) { // Key found
|
||||
n = ini_gets(section, str, "dummy", myKeys[numHotkeys].swFilename, sizearray(myKeys[numHotkeys].swFilename), iniFile);
|
||||
if ( n > 5 && strncmp("dummy", myKeys[numHotkeys].swFilename, 5) != 0 ) { // Value is not empty
|
||||
syslog(LOG_INFO, "Filename: %s\n", myKeys[numHotkeys].swFilename);
|
||||
}
|
||||
}
|
||||
if ( strncmp("button1", str, 7) == 0 ) { // Key found
|
||||
l = ini_getl(section, str, BUTTON_DEFINED_RANGE, iniFile);
|
||||
if ( buttonDefined(l) == true ) { // Value is not empty
|
||||
syslog(LOG_INFO, "button1: %ld\n", l);
|
||||
myKeys[numHotkeys].button1 = l;
|
||||
myKeys[numHotkeys].activeButtons++;
|
||||
}
|
||||
}
|
||||
if ( strncmp("button2", str, 7) == 0 ) { // Key found
|
||||
l = ini_getl(section, str, BUTTON_DEFINED_RANGE, iniFile);
|
||||
if ( buttonDefined(l) == true ) { // Value is not empty
|
||||
syslog(LOG_INFO, "button2: %ld\n", l);
|
||||
myKeys[numHotkeys].button2 = l;
|
||||
myKeys[numHotkeys].activeButtons++;
|
||||
}
|
||||
}
|
||||
if ( strncmp("button3", str, 7) == 0 ) { // Key found
|
||||
l = ini_getl(section, str, BUTTON_DEFINED_RANGE, iniFile);
|
||||
if ( buttonDefined(l) == true ) { // Value is not empty
|
||||
syslog(LOG_INFO, "button3: %ld\n", l);
|
||||
myKeys[numHotkeys].button3 = l;
|
||||
myKeys[numHotkeys].activeButtons++;
|
||||
}
|
||||
}
|
||||
if ( strncmp("button4", str, 7) == 0 ) { // Key found
|
||||
l = ini_getl(section, str, BUTTON_DEFINED_RANGE, iniFile);
|
||||
if ( buttonDefined(l) == true ){ // Value is not empty
|
||||
syslog(LOG_INFO, "button4: %ld\n", l);
|
||||
myKeys[numHotkeys].button4 = l;
|
||||
myKeys[numHotkeys].activeButtons++;
|
||||
}
|
||||
}
|
||||
} /* for */
|
||||
}
|
||||
numHotkeys++; // Remember how many sections we have
|
||||
} /* for */
|
||||
}
|
||||
|
||||
@@ -181,19 +198,84 @@ void readConfig(void) {
|
||||
//---------------------------------------------
|
||||
int checkConfig(void) {
|
||||
int rc=0;
|
||||
if ( sizearray(swFilename) < 3 ) { // no program make no sense
|
||||
syslog(LOG_ERR, "err: no valid filename provided. Please check ini file\n");
|
||||
rc = 1;
|
||||
}
|
||||
if ( buttonDefined(button1) == false ) { // we need at least one button for tracking
|
||||
syslog(LOG_ERR, "err: button assignment missing. Please set at least button1 in the ini file!\n");
|
||||
rc = 1;
|
||||
}
|
||||
syslog(LOG_INFO, "Active assigned buttons: %d\n", buttonActive);
|
||||
int i;
|
||||
for (i=0;i<numHotkeys;i++){
|
||||
if ( sizearray(myKeys[i].swFilename) < 3 ) { // no program make no sense
|
||||
syslog(LOG_ERR, "err: no valid filename provided in section %d. Please check ini file\n", i);
|
||||
rc = 1;
|
||||
}
|
||||
if ( buttonDefined(myKeys[i].button1) == false ) { // we need at least one button for tracking
|
||||
syslog(LOG_ERR, "err: button assignment missing in section %d. Please set at least button1 in the ini file!\n", i);
|
||||
rc = 1;
|
||||
}
|
||||
syslog(LOG_INFO, "Active assigned buttons in section %d: ", i);
|
||||
syslog(LOG_INFO, "%d\n", myKeys[i].activeButtons);
|
||||
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
// Check button pressed
|
||||
//---------------------------------------------
|
||||
int checkButtonPressed(struct js_event js) {
|
||||
int section = -1;
|
||||
int i;
|
||||
// Update the button press in all key combinations
|
||||
for (i=0;i<numHotkeys;i++){
|
||||
if ( js.number == myKeys[i].button1 ) {
|
||||
myKeys[i].button1Active = js.value;
|
||||
}
|
||||
if ( js.number == myKeys[i].button2 ) {
|
||||
myKeys[i].button2Active = js.value;
|
||||
}
|
||||
if ( js.number == myKeys[i].button3 ) {
|
||||
myKeys[i].button3Active = js.value;
|
||||
}
|
||||
if ( js.number == myKeys[i].button4 ) {
|
||||
myKeys[i].button4Active = js.value;
|
||||
}
|
||||
}
|
||||
// Analyse combinations
|
||||
for (i=0; i<numHotkeys;i++){
|
||||
switch (myKeys[i].activeButtons) {
|
||||
case 1:
|
||||
if ( myKeys[i].button1Active == 1 ) { myKeys[i].isTriggered = 1; section = i; }
|
||||
break;
|
||||
case 2:
|
||||
if ( myKeys[i].button1Active == 1 && myKeys[i].button2Active == 1 ) {
|
||||
myKeys[i].isTriggered = 1; section = i;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if ( myKeys[i].button1Active == 1 && myKeys[i].button2Active == 1 && myKeys[i].button3Active == 1 ) {
|
||||
myKeys[i].isTriggered = 1; section = i;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if ( myKeys[i].button1Active == 1 && myKeys[i].button2Active == 1 && myKeys[i].button3Active == 1 && myKeys[i].button4Active == 1) {
|
||||
myKeys[i].isTriggered = 1; section = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
// Reset the keys
|
||||
//---------------------------------------------
|
||||
void resetHotkeys(){
|
||||
int i;
|
||||
for (i=0;i<numHotkeys;i++){
|
||||
myKeys[i].button1Active = 0;
|
||||
myKeys[i].button2Active = 0;
|
||||
myKeys[i].button3Active = 0;
|
||||
myKeys[i].button4Active = 0;
|
||||
myKeys[i].isTriggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------
|
||||
// Get the input device
|
||||
//---------------------------------------------
|
||||
@@ -373,11 +455,6 @@ int bindJoy(void) {
|
||||
int btnmapok = 1;
|
||||
int i;
|
||||
|
||||
int button1State=0;
|
||||
int button2State=0;
|
||||
int button3State=0;
|
||||
int button4State=0;
|
||||
|
||||
ioctl(joyFD, JSIOCGVERSION, &version);
|
||||
ioctl(joyFD, JSIOCGAXES, &axes);
|
||||
ioctl(joyFD, JSIOCGBUTTONS, &buttons);
|
||||
@@ -424,48 +501,18 @@ int bindJoy(void) {
|
||||
while (read(joyFD, &js, sizeof(struct js_event)) == sizeof(struct js_event)) {
|
||||
syslog(LOG_DEBUG, "Event: type %d, time %d, number %d, value %d\n",
|
||||
js.type, js.time, js.number, js.value);
|
||||
if ( js.number == button1 ) {
|
||||
button1State = js.value;
|
||||
}
|
||||
if ( js.number == button2 ) {
|
||||
button2State = js.value;
|
||||
}
|
||||
if ( js.number == button3 ) {
|
||||
button3State = js.value;
|
||||
}
|
||||
if ( js.number == button4 ) {
|
||||
button4State = js.value;
|
||||
}
|
||||
needTrigger = 0;
|
||||
switch (buttonActive) {
|
||||
case 1:
|
||||
if ( button1State == 1 ) { needTrigger = 1; }
|
||||
break;
|
||||
case 2:
|
||||
if ( button1State == 1 && button2State == 1 ) { needTrigger = 1; }
|
||||
break;
|
||||
case 3:
|
||||
if ( button1State == 1 && button2State == 1 && button3State == 1 ) { needTrigger = 1; }
|
||||
break;
|
||||
case 4:
|
||||
if ( button1State == 1 && button2State == 1 && button3State == 1 && button4State == 1) {
|
||||
needTrigger = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( needTrigger == 1 ) {
|
||||
needTrigger = checkButtonPressed(js);
|
||||
if ( needTrigger > -1 ) { // We have found one key section
|
||||
syslog(LOG_INFO, "Swtching mode. ...\n");
|
||||
// reset state, so we call only once
|
||||
button1State = 0;
|
||||
button2State = 0;
|
||||
button3State = 0;
|
||||
button4State = 0;
|
||||
int rc = system(swFilename);
|
||||
// call external program
|
||||
int rc = system(myKeys[needTrigger].swFilename);
|
||||
if ( rc == 0 ) {
|
||||
syslog(LOG_INFO, "Call succesfull\n");
|
||||
}else{
|
||||
syslog(LOG_INFO, "Call failed\n");
|
||||
}
|
||||
// reset state, so we call only once
|
||||
resetHotkeys();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,7 +543,7 @@ void signal_callback_handler(int signum) {
|
||||
//---------------------------------------------
|
||||
// main function
|
||||
//---------------------------------------------
|
||||
int main(void) {
|
||||
int main(int argc, char* argv[]) {
|
||||
int rc;
|
||||
// Register signal and signal handler
|
||||
signal(SIGINT, signal_callback_handler);
|
||||
@@ -504,8 +551,31 @@ int main(void) {
|
||||
signal(SIGTERM, signal_callback_handler);
|
||||
signal(SIGHUP, signal_callback_handler);
|
||||
|
||||
|
||||
// Init Defaults
|
||||
int i;
|
||||
for (i=0;i<MAX_HOTKEYS;i++) {
|
||||
myKeys[i].button1 = BUTTON_DEFINED_RANGE;
|
||||
myKeys[i].button1Active = 0;
|
||||
myKeys[i].button2 = BUTTON_DEFINED_RANGE;
|
||||
myKeys[i].button2Active = 0;
|
||||
myKeys[i].button3 = BUTTON_DEFINED_RANGE;
|
||||
myKeys[i].button3Active = 0;
|
||||
myKeys[i].button4 = BUTTON_DEFINED_RANGE;
|
||||
myKeys[i].button4Active = 0;
|
||||
myKeys[i].activeButtons = 0;
|
||||
myKeys[i].isTriggered = false;
|
||||
}
|
||||
|
||||
// Parse parameters to set debug level
|
||||
if ( argc > 1 ) {
|
||||
if (strncmp(argv[1], "--debug", 7) == 0) {
|
||||
logLevel = LOG_DEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
// Open Syslog
|
||||
setlogmask (LOG_UPTO (MY_LOG_LEVEL));
|
||||
setlogmask (LOG_UPTO (logLevel));
|
||||
openlog (MYPROGNAME, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
|
||||
syslog(LOG_NOTICE, "Listen to joystick inputs ...\n");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user