From 8f5d0cf7c4fde1f8a288e8d59ae5c1e3b705b4ba Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 7 Apr 2008 08:37:52 +0000 Subject: [PATCH] - added new interactive GUI config program for spacenavd git-svn-id: svn+ssh://svn.code.sf.net/p/spacenav/code/spnavcfg@22 ef983eb1-d774-4af8-acfd-baaf7b16a646 --- .gitattributes | 1 + Makefile | 25 +++++++ back.c | 134 +++++++++++++++++++++++++++++++++ cmd.h | 28 +++++++ front.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++++ spnavcfg.c | 56 ++++++++++++++ 6 files changed, 439 insertions(+) create mode 100644 .gitattributes create mode 100644 Makefile create mode 100644 back.c create mode 100644 cmd.h create mode 100644 front.c create mode 100644 spnavcfg.c diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..24a8e87 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.png filter=lfs diff=lfs merge=lfs -text diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..df25ff7 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +PREFIX = /usr/local + +obj = spnavcfg.o front.o back.o ../spacenavd/cfgfile.o +bin = spnavcfg + +CC = gcc +INSTALL = install +CFLAGS = -pedantic -Wall -g -I../spacenavd `pkg-config --cflags gtk+-2.0` +LDFLAGS = `pkg-config --libs gtk+-2.0` + +$(bin): $(obj) + $(CC) -o $@ $(obj) $(LDFLAGS) + +.PHONY: clean +clean: + rm -f $(obj) $(bin) + +.PHONY: install +install: + $(INSTALL) -d $(PREFIX)/bin + $(INSTALL) -m 4775 $(bin) $(PREFIX)/bin/$(bin) + +.PHONY: uninstall +uninstall: + rm -f $(PREFIX)/bin/$(bin) diff --git a/back.c b/back.c new file mode 100644 index 0000000..0da52d4 --- /dev/null +++ b/back.c @@ -0,0 +1,134 @@ +/* +spnavcfg - an interactive GUI configurator for the spacenavd daemon. +Copyright (C) 2007 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include +#include +#include +#include +#include +#include +#include +#include "cfgfile.h" +#include "cmd.h" + +#define CFGFILE "/etc/spnavrc" + +int get_daemon_pid(void); +static int update_cfg(void); +static void sig(int s); + +static struct cfg cfg; +static int dpid = -1; + +int backend(int pfd) +{ + signal(SIGTERM, sig); + + for(;;) { + ssize_t res; + int cmd; + + /* get command */ + if(read(pfd, &cmd, 1) == -1 && errno != EINTR) { + perror("pipe read blew up in my face! wtf"); + return -1; + } + + switch(cmd) { + case CMD_PING: + kill(getppid(), ((dpid = get_daemon_pid()) == -1) ? SIGUSR2 : SIGUSR1); + break; + + case CMD_CFG: + { + char *buf = (char*)&cfg; + int sz = sizeof cfg; + + while(sz && (res = read(pfd, buf, sz)) > 0) { + buf += res; + sz -= res; + } + update_cfg(); + } + break; + + case CMD_STARTX: + case CMD_STOPX: + if(dpid == -1) { + if((dpid = get_daemon_pid()) == -1) { + return -1; + } + } + if(kill(dpid, cmd == CMD_STARTX ? SIGUSR1 : SIGUSR2) == -1) { + if(errno != EPERM) { + dpid = -1; + kill(getppid(), SIGUSR2); + } + } + break; + + default: + break; + } + } + + return 0; +} + +int get_daemon_pid(void) +{ + FILE *fp; + char buf[64]; + + if(!(fp = fopen("/tmp/.spnavd.pid", "r"))) { + fprintf(stderr, "no spacenav pid file, can't find daemon\n"); + return -1; + } + fgets(buf, sizeof buf, fp); + fclose(fp); + + if(!isdigit(buf[0])) { + fprintf(stderr, "fucked up pidfile, can't find daemon\n"); + return -1; + } + return atoi(buf); +} + +static int update_cfg(void) +{ + if(write_cfg(CFGFILE, &cfg) == -1) { + return -1; + } + + if(dpid == -1) { + if((dpid = get_daemon_pid()) == -1) { + return -1; + } + } + + if(kill(dpid, SIGHUP) == -1 && errno != EPERM) { + dpid = -1; /* invalidate pid, will be searched again next time */ + return -1; + } + + return 0; +} + +static void sig(int s) +{ + _exit(0); +} diff --git a/cmd.h b/cmd.h new file mode 100644 index 0000000..d10e1fe --- /dev/null +++ b/cmd.h @@ -0,0 +1,28 @@ +/* +spnavcfg - an interactive GUI configurator for the spacenavd daemon. +Copyright (C) 2007 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef CMD_H_ +#define CMD_H_ + +enum { + CMD_PING, /* check daemon status */ + CMD_CFG, /* update configuration (and HUP daemon) */ + CMD_STARTX, /* signal daemon to enable X protocol */ + CMD_STOPX /* yada yada stop X protocol */ +}; + +#endif /* CMD_H_ */ diff --git a/front.c b/front.c new file mode 100644 index 0000000..2108585 --- /dev/null +++ b/front.c @@ -0,0 +1,195 @@ +/* +spnavcfg - an interactive GUI configurator for the spacenavd daemon. +Copyright (C) 2007 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include +#include +#include +#include +#include +#include "cfgfile.h" +#include "cmd.h" + +#define CFGFILE "/etc/spnavrc" + +static void update_cfg(void); +static void layout(void); +static void sig(int s); +static void chk_handler(GtkToggleButton *bn, void *data); +static void slider_handler(GtkRange *rng, void *data); + +static void add_child(GtkWidget *parent, GtkWidget *child); +static GtkWidget *create_vbox(GtkWidget *parent); +static GtkWidget *create_hbox(GtkWidget *parent); + +static GtkWidget *win; + +static struct cfg cfg; +static int pipe_fd; + +void frontend(int pfd) +{ + int argc = 0; + int ruid = getuid(); +#ifdef __linux__ + int setresuid(uid_t ruid, uid_t euid, uid_t suid); + setresuid(ruid, ruid, ruid); +#else + seteuid(ruid); +#endif + + pipe_fd = pfd; + + signal(SIGUSR1, sig); + signal(SIGUSR2, sig); + + gtk_init(&argc, 0); + + read_cfg(CFGFILE, &cfg); + + win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(win), "spacenavd configuration"); + g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(gtk_main_quit), 0); + gtk_container_set_border_width(GTK_CONTAINER(win), 4); + + layout(); + + gtk_widget_show_all(win); + + gtk_main(); +} + +static void update_cfg(void) +{ + int cmd = CMD_CFG; + write(pipe_fd, &cmd, 1); + write(pipe_fd, &cfg, sizeof cfg); +} + +static void layout(void) +{ + int i; + GtkWidget *w; + GtkWidget *vbox, *hbox, *bbox, *tbl, *frm; + + vbox = create_vbox(win); + + frm = gtk_frame_new("invert axis"); + add_child(vbox, frm); + + tbl = gtk_table_new(3, 4, FALSE); + add_child(frm, tbl); + + gtk_table_attach_defaults(GTK_TABLE(tbl), gtk_label_new("X"), 1, 2, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(tbl), gtk_label_new("Y"), 2, 3, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(tbl), gtk_label_new("Z"), 3, 4, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(tbl), gtk_label_new("translation"), 0, 1, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(tbl), gtk_label_new("rotation"), 0, 1, 2, 3); + + for(i=0; i<6; i++) { + int x = i % 3 + 1; + int y = i / 3 + 1; + w = gtk_check_button_new(); + gtk_table_attach_defaults(GTK_TABLE(tbl), w, x, x + 1, y, y + 1); + g_signal_connect(G_OBJECT(w), "toggled", G_CALLBACK(chk_handler), (void*)i); + } + + /*hbox = create_hbox(vbox);*/ + frm = gtk_frame_new("sensitivity"); + add_child(vbox, frm); + + w = gtk_hscale_new_with_range(0.0, 4.0, 0.1); + gtk_range_set_update_policy(GTK_RANGE(w), GTK_UPDATE_DELAYED); + gtk_range_set_value(GTK_RANGE(w), cfg.sensitivity); + gtk_scale_set_value_pos(GTK_SCALE(w), GTK_POS_RIGHT); + g_signal_connect(G_OBJECT(w), "value_changed", G_CALLBACK(slider_handler), 0); + add_child(frm, w); + + bbox = gtk_hbutton_box_new(); + add_child(vbox, bbox); + + /*w = gtk_button_new_from_stock(GTK_STOCK_APPLY); + g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(bn_handler), 0); + add_child(bbox, w);*/ + + w = gtk_button_new_from_stock(GTK_STOCK_CLOSE); + g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(gtk_main_quit), 0); + add_child(bbox, w); +} + +static void sig(int s) +{ + GtkWidget *dlg; + + switch(s) { + case SIGUSR1: /* daemon alive */ + dlg = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "The spacenavd driver is running fine."); + g_signal_connect_swapped(dlg, "response", G_CALLBACK(gtk_widget_destroy), dlg); + break; + + case SIGUSR2: /* daemon dead */ + dlg = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "The driver isn't running at the moment.\n" + "You can still modify the configuration through this panel though."); + g_signal_connect_swapped(dlg, "response", G_CALLBACK(gtk_widget_destroy), dlg); + break; + + default: + break; + } +} + +static void chk_handler(GtkToggleButton *bn, void *data) +{ + int which = (int)data; + int state = gtk_toggle_button_get_active(bn); + + cfg.invert[which] = state; + update_cfg(); +} + +static void slider_handler(GtkRange *rng, void *data) +{ + cfg.sensitivity = gtk_range_get_value(rng); + update_cfg(); +} + + +static void add_child(GtkWidget *parent, GtkWidget *child) +{ + if(GTK_IS_BOX(parent)) { + gtk_box_pack_start(GTK_BOX(parent), child, TRUE, TRUE, 3); + } else if(GTK_CONTAINER(parent)) { + gtk_container_add(GTK_CONTAINER(parent), child); + } else { + fprintf(stderr, "failed to add child\n"); + } +} + +static GtkWidget *create_vbox(GtkWidget *parent) +{ + GtkWidget *box = gtk_vbox_new(FALSE, 5); + add_child(parent, box); + return box; +} + +static GtkWidget *create_hbox(GtkWidget *parent) +{ + GtkWidget *box = gtk_hbox_new(FALSE, 5); + add_child(parent, box); + return box; +} diff --git a/spnavcfg.c b/spnavcfg.c new file mode 100644 index 0000000..2959c9a --- /dev/null +++ b/spnavcfg.c @@ -0,0 +1,56 @@ +/* +spnavcfg - an interactive GUI configurator for the spacenavd daemon. +Copyright (C) 2007 John Tsiombikas + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include +#include +#include +#include +#include + +void frontend(int pfd); +void backend(int pfd); + +static void sig(int s); + +int main(int argc, char **argv) +{ + int cpid; + int pipefd[2]; + + signal(SIGCHLD, sig); + + pipe(pipefd); + if((cpid = fork()) == 0) { + /* child should be the setuid-root backend, write cfg and kill */ + close(pipefd[1]); + backend(pipefd[0]); + _exit(0); + } else { + /* parent, GUI frontend */ + close(pipefd[0]); + frontend(pipefd[1]); + kill(cpid, SIGTERM); + } + return 0; +} + +static void sig(int s) +{ + if(s == SIGCHLD) { + wait(0); + } +}