- 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
pull/1/head
John Tsiombikas 2008-04-07 08:37:52 +00:00
commit 8f5d0cf7c4
6 zmienionych plików z 439 dodań i 0 usunięć

1
.gitattributes vendored 100644
Wyświetl plik

@ -0,0 +1 @@
*.png filter=lfs diff=lfs merge=lfs -text

25
Makefile 100644
Wyświetl plik

@ -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)

134
back.c 100644
Wyświetl plik

@ -0,0 +1,134 @@
/*
spnavcfg - an interactive GUI configurator for the spacenavd daemon.
Copyright (C) 2007 John Tsiombikas <nuclear@siggraph.org>
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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#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);
}

28
cmd.h 100644
Wyświetl plik

@ -0,0 +1,28 @@
/*
spnavcfg - an interactive GUI configurator for the spacenavd daemon.
Copyright (C) 2007 John Tsiombikas <nuclear@siggraph.org>
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 <http://www.gnu.org/licenses/>.
*/
#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_ */

195
front.c 100644
Wyświetl plik

@ -0,0 +1,195 @@
/*
spnavcfg - an interactive GUI configurator for the spacenavd daemon.
Copyright (C) 2007 John Tsiombikas <nuclear@siggraph.org>
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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <gtk/gtk.h>
#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;
}

56
spnavcfg.c 100644
Wyświetl plik

@ -0,0 +1,56 @@
/*
spnavcfg - an interactive GUI configurator for the spacenavd daemon.
Copyright (C) 2007 John Tsiombikas <nuclear@siggraph.org>
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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
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);
}
}