#include "config.h"
#include <locale.h>
#include <libintl.h>
#define _(x) gettext(x)
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include <string.h>
#include "rtapi.h"
#include "hal.h"
#include "../hal_priv.h"
#include <rtapi_mutex.h>
#include <gtk/gtk.h>
#include "miscgtk.h"
#include <gdk/gdkkeysyms.h>
#define PROBE_NAME_LEN 63
typedef struct {
int listnum;
char *pickname;
hal_pin_t *pin;
hal_sig_t *sig;
hal_param_t *param;
GtkWidget *window;
GtkWidget *notebook;
GtkWidget *lists[3];
char probe_name[PROBE_NAME_LEN + 1];
} probe_t;
typedef struct {
probe_t *probe;
GtkWidget *value_label;
GtkWidget *name_label;
GtkWidget *button_select;
} meter_t;
int comp_id;
GtkWidget *main_window;
int small;
static meter_t *meter_new(void);
static probe_t *probe_new(char *probe_name);
static void popup_probe_window(GtkWidget * widget, gpointer data);
static void quit(int sig);
static void exit_from_hal(void);
static int refresh_value(gpointer data);
static char *data_value(int type, void *valptr);
static void create_probe_window(probe_t * probe);
static void apply_selection(GtkWidget * widget, gpointer data);
static void close_selection(GtkWidget * widget, gpointer data);
static gboolean key_press(GtkWidget * clist, GdkEventKey *event, gpointer user_data);
static void selection_made(GtkWidget * clist, gint row, gint column,
GdkEventButton * event, gpointer data);
static void page_switched(GtkNotebook *notebook, GtkNotebookPage *page,
guint page_num, gpointer user_data);
int main(int argc, gchar * argv[])
{
GtkWidget *vbox, *hbox;
GtkWidget *button_select, *button_exit;
char buf[30];
int initial_type = 0, n, i, height, geometryflag = 0, xposition = 0, yposition = 0, width = 270;
char *initial_name = NULL , *win_name;
meter_t *meter;
bindtextdomain("linuxcnc", EMC2_PO_DIR);
setlocale(LC_MESSAGES,"");
setlocale(LC_CTYPE,"");
textdomain("linuxcnc");
gtk_init(&argc, &argv);
small = 0;
n = 1;
while ( argc > n ) {
if ( strcmp (argv[n], "-g") == 0 ) {
geometryflag = 1;
n++;
xposition = atoi(argv[n]);
n++;
yposition = atoi(argv[n]);
n++;
if ( argc > n ){
strcpy(buf,argv[n]);
for (i=0; i< strlen(argv[n]); i++) {
if (isdigit(buf[i]) == 0) { break; }
}
if (strlen(argv[n]) == i){
width = atoi(argv[n]);
n++;
}
}
}
if ((argc > n) && ( strcmp (argv[n], "-s") == 0 )) {
small = 1;
n++;
}
if (argc > n) {
if (strncmp(argv[n], "pin", 3) == 0) {
initial_type = 0;
} else if (strncmp(argv[n], "sig", 3) == 0) {
initial_type = 1;
} else if (strncmp(argv[n], "par", 3) == 0) {
initial_type = 2;
} else {
printf(_("ERROR: '%s' is not a valid probe type\n"), argv[n]);
return -1;
}
n++;
if ( argc > n ) {
initial_name = argv[n];
n++;
} else {
printf(_("ERROR: no pin/signal/parameter name\n"));
return -1;
}
}
}
if ((initial_name == NULL) && (small == 1)) {
printf(_("ERROR: -s option requires a probe type and a pin/signal/parameter name\n"));
return -1;
}
snprintf(buf, 29, "halmeter-%d", getpid());
comp_id = hal_init(buf);
if (comp_id < 0) {
return -1;
}
hal_ready(comp_id);
atexit(exit_from_hal);
signal(SIGINT, quit);
signal(SIGTERM, quit);
main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
if ( small ) {
height = 22;
win_name = initial_name;
} else {
height = 80;
win_name = _("Hal Meter");
}
gtk_widget_set_usize(GTK_WIDGET(main_window), width, height);
gtk_window_set_policy(GTK_WINDOW(main_window), FALSE, FALSE, FALSE);
gtk_window_set_keep_above(GTK_WINDOW(main_window),TRUE);
gtk_window_set_title(GTK_WINDOW(main_window), win_name);
gtk_signal_connect(GTK_OBJECT(main_window), "destroy",
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
vbox = gtk_vbox_new(FALSE, 3);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
gtk_container_add(GTK_CONTAINER(main_window), vbox);
gtk_widget_show(vbox);
meter = meter_new();
if (meter == NULL) {
printf("null meter\n");
exit(-1);
}
if (initial_name != NULL) {
meter->probe->pickname = initial_name;
meter->probe->listnum = initial_type;
apply_selection(NULL, meter->probe);
}
gtk_box_pack_start(GTK_BOX(vbox), meter->value_label, TRUE, TRUE, 0);
gtk_widget_show(meter->value_label);
if ( !small ) {
gtk_box_pack_start(GTK_BOX(vbox), meter->name_label, TRUE, TRUE, 0);
gtk_widget_show(meter->name_label);
}
gtk_timeout_add(100, refresh_value, meter);
if ( !small ) {
hbox = gtk_hbox_new_in_box(FALSE, 0, 0, vbox, FALSE, TRUE, 0);
button_select = gtk_button_new_with_label(_("_Select"));
button_exit = gtk_button_new_with_label(_("E_xit"));
gtk_button_set_use_underline((GtkButton *)button_select, TRUE);
gtk_button_set_use_underline((GtkButton *)button_exit, TRUE);
gtk_box_pack_start(GTK_BOX(hbox), button_select, TRUE, TRUE, 4);
gtk_box_pack_start(GTK_BOX(hbox), button_exit, TRUE, TRUE, 4);
gtk_signal_connect(GTK_OBJECT(button_exit), "clicked",
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
gtk_signal_connect(GTK_OBJECT(button_select), "clicked",
GTK_SIGNAL_FUNC(popup_probe_window), meter->probe);
meter->button_select = button_select;
gtk_widget_show(button_select);
gtk_widget_show(button_exit);
}
gtk_widget_show(main_window);
if (geometryflag == 1) {
gtk_window_move(GTK_WINDOW(main_window),xposition,yposition);
}
gtk_main();
return (0);
}
static meter_t *meter_new(void)
{
meter_t *new;
new = malloc(sizeof(meter_t));
if (new == NULL) {
return NULL;
}
new->probe = probe_new(_("Select Item to Probe"));
if (new->probe == NULL) {
free(new);
return NULL;
}
new->value_label = gtk_label_new("----");
gtk_label_set_justify(GTK_LABEL(new->value_label), GTK_JUSTIFY_CENTER);
gtk_label_set_line_wrap(GTK_LABEL(new->value_label), FALSE);
if ( !small ) {
new->name_label = gtk_label_new("------");
gtk_label_set_justify(GTK_LABEL(new->name_label),
GTK_JUSTIFY_CENTER);
gtk_label_set_line_wrap(GTK_LABEL(new->name_label), FALSE);
}
return new;
}
probe_t *probe_new(char *probe_name)
{
probe_t *new;
if (probe_name == NULL) {
probe_name = _("Select Item to Probe");
}
new = malloc(sizeof(probe_t));
if (new == NULL) {
return NULL;
}
new->pickname = NULL;
new->listnum = -1;
new->pin = NULL;
new->sig = NULL;
new->param = NULL;
strncpy(new->probe_name, probe_name, HAL_NAME_LEN);
new->probe_name[HAL_NAME_LEN] = '\0';
new->window = NULL;
return new;
}
void popup_probe_window(GtkWidget * widget, gpointer data)
{
probe_t *probe;
int next, row, match;
hal_pin_t *pin;
hal_sig_t *sig;
hal_param_t *param;
gchar *name;
probe = (probe_t *) data;
if (probe->window == NULL) {
create_probe_window(probe);
}else{
gtk_window_present(GTK_WINDOW(probe->window));
}
gtk_clist_clear(GTK_CLIST(probe->lists[0]));
gtk_clist_clear(GTK_CLIST(probe->lists[1]));
gtk_clist_clear(GTK_CLIST(probe->lists[2]));
rtapi_mutex_get(&(hal_data->mutex));
next = hal_data->pin_list_ptr;
row = 0; match = 0;
gtk_clist_freeze(GTK_CLIST(probe->lists[0]));
while (next != 0) {
pin = SHMPTR(next);
name = pin->name;
gtk_clist_append(GTK_CLIST(probe->lists[0]), &name);
if ((probe->listnum == 0) && (probe->pin == pin)) {
gtk_clist_select_row(GTK_CLIST(probe->lists[0]), row, 0);
gtk_clist_get_text(GTK_CLIST(probe->lists[0]), row, 0,
&(probe->pickname));
match = 1;
}
next = pin->next_ptr;
row++;
}
gtk_clist_thaw(GTK_CLIST(probe->lists[0]));
if (!match)
gtk_clist_unselect_row(GTK_CLIST(probe->lists[0]), 0, 0);
next = hal_data->sig_list_ptr;
row = 0; match = 0;
gtk_clist_freeze(GTK_CLIST(probe->lists[1]));
while (next != 0) {
sig = SHMPTR(next);
name = sig->name;
gtk_clist_append(GTK_CLIST(probe->lists[1]), &name);
if ((probe->listnum == 1) && (probe->sig == sig)) {
gtk_clist_select_row(GTK_CLIST(probe->lists[1]), row, 0);
gtk_clist_get_text(GTK_CLIST(probe->lists[1]), row, 0,
&(probe->pickname));
match = 1;
}
next = sig->next_ptr;
row++;
}
gtk_clist_thaw(GTK_CLIST(probe->lists[1]));
if (!match)
gtk_clist_unselect_row(GTK_CLIST(probe->lists[1]), 0, 0);
next = hal_data->param_list_ptr;
row = 0; match = 0;
gtk_clist_freeze(GTK_CLIST(probe->lists[2]));
while (next != 0) {
param = SHMPTR(next);
name = param->name;
gtk_clist_append(GTK_CLIST(probe->lists[2]), &name);
if ((probe->listnum == 2) && (probe->param == param)) {
gtk_clist_select_row(GTK_CLIST(probe->lists[2]), row, 0);
gtk_clist_get_text(GTK_CLIST(probe->lists[2]), row, 0,
&(probe->pickname));
match = 1;
}
next = param->next_ptr;
row++;
}
gtk_clist_thaw(GTK_CLIST(probe->lists[2]));
if (!match)
gtk_clist_unselect_row(GTK_CLIST(probe->lists[2]), 0, 0);
if (probe->listnum >= 0) {
gtk_notebook_set_page(GTK_NOTEBOOK(probe->notebook), probe->listnum);
} else { gtk_notebook_set_page(GTK_NOTEBOOK(probe->notebook), 0);
}
rtapi_mutex_give(&(hal_data->mutex));
gtk_widget_show_all(probe->window);
}
static void quit(int sig)
{
gtk_main_quit();
}
static void exit_from_hal(void)
{
hal_exit(comp_id);
}
static int refresh_value(gpointer data)
{
meter_t *meter;
probe_t *probe;
char *value_str, *name_str;
hal_sig_t *sig;
static int first = 1;
meter = (meter_t *) data;
probe = meter->probe;
if ( first ) {
first = 0;
if ( probe->pickname == NULL ) {
g_signal_emit_by_name(meter->button_select, "clicked");
}
}
rtapi_mutex_get(&(hal_data->mutex));
if (probe->pin != NULL) {
if (probe->pin->name[0] == '\0') {
probe->pin = NULL;
rtapi_mutex_give(&(hal_data->mutex));
return 1;
}
name_str = probe->pin->name;
if (probe->pin->signal == 0) {
value_str = data_value(probe->pin->type, &(probe->pin->dummysig));
} else {
sig = SHMPTR(probe->pin->signal);
value_str = data_value(probe->pin->type, SHMPTR(sig->data_ptr));
}
} else if (probe->sig != NULL) {
if (probe->sig->name[0] == '\0') {
probe->sig = NULL;
rtapi_mutex_give(&(hal_data->mutex));
return 1;
}
name_str = probe->sig->name;
value_str =
data_value(probe->sig->type, SHMPTR(probe->sig->data_ptr));
} else if (probe->param != NULL) {
if (probe->param->name[0] == '\0') {
probe->param = NULL;
rtapi_mutex_give(&(hal_data->mutex));
return 1;
}
name_str = probe->param->name;
value_str =
data_value(probe->param->type, SHMPTR(probe->param->data_ptr));
} else {
name_str = "-----";
value_str = "---";
}
rtapi_mutex_give(&(hal_data->mutex));
gtk_label_set_text(GTK_LABEL(meter->value_label), value_str);
if (!small) {
gtk_label_set_text(GTK_LABEL(meter->name_label), name_str);
}
return 1;
}
static char *data_value(int type, void *valptr)
{
char *value_str;
static char buf[25];
switch (type) {
case HAL_BIT:
if (*((char *) valptr) == 0)
value_str = "FALSE";
else
value_str = "TRUE";
break;
case HAL_FLOAT:
snprintf(buf, 14, "%.7g", (double)*((hal_float_t *) valptr));
value_str = buf;
break;
case HAL_S32:
snprintf(buf, 24, "%10ld", (long)*((hal_s32_t *) valptr));
value_str = buf;
break;
case HAL_U32:
snprintf(buf, 24, "%10lu (0x%08lX)", (unsigned long)*((hal_u32_t *) valptr),
*((unsigned long *) valptr));
value_str = buf;
break;
default:
value_str = "";
}
return value_str;
}
static void create_probe_window(probe_t * probe)
{
GtkWidget *vbox, *hbox, *notebk;
GtkWidget *button_close;
GtkWidget *scrolled_window;
gchar *tab_label_text[3];
gint n;
probe->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize(GTK_WIDGET(probe->window), -2, 400);
gtk_window_set_policy(GTK_WINDOW(probe->window), FALSE, TRUE, FALSE);
gtk_window_set_title(GTK_WINDOW(probe->window), probe->probe_name);
vbox = gtk_vbox_new(FALSE, 3);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
gtk_container_add(GTK_CONTAINER(probe->window), vbox);
gtk_widget_show(vbox);
notebk = gtk_notebook_new();
probe->notebook = notebk;
gtk_box_pack_start(GTK_BOX(vbox), notebk, TRUE, TRUE, 0);
gtk_notebook_set_homogeneous_tabs(GTK_NOTEBOOK(notebk), TRUE);
tab_label_text[0] = _(" _Pins ");
tab_label_text[1] = _(" _Signals ");
tab_label_text[2] = _(" Para_meters ");
for (n = 0; n < 3; n++) {
scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
gtk_widget_show(scrolled_window);
probe->lists[n] = gtk_clist_new(1);
gtk_signal_connect(GTK_OBJECT(probe->lists[n]), "select_row",
GTK_SIGNAL_FUNC(selection_made), probe);
gtk_signal_connect(GTK_OBJECT(probe->lists[n]), "key_press_event",
GTK_SIGNAL_FUNC(key_press), probe );
gtk_clist_set_shadow_type(GTK_CLIST(probe->lists[n]), GTK_SHADOW_OUT);
gtk_clist_set_selection_mode(GTK_CLIST(probe->lists[n]),
GTK_SELECTION_BROWSE);
gtk_container_add(GTK_CONTAINER(scrolled_window), probe->lists[n]);
gtk_widget_show(probe->lists[n]);
hbox = gtk_hbox_new(TRUE, 0);
gtk_label_new_in_box(tab_label_text[n], hbox, TRUE, TRUE, 0);
gtk_widget_show(hbox);
gtk_notebook_append_page(GTK_NOTEBOOK(notebk), scrolled_window, hbox);
gtk_signal_connect(GTK_OBJECT(notebk), "switch-page",
GTK_SIGNAL_FUNC(page_switched), probe);
gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(notebk), hbox,
TRUE, TRUE, GTK_PACK_START);
}
gtk_widget_show(notebk);
probe->listnum=0;
hbox = gtk_hbox_new_in_box(TRUE, 0, 0, vbox, FALSE, TRUE, 0);
button_close = gtk_button_new_with_label(_("_Close"));
gtk_button_set_use_underline((GtkButton *)button_close, TRUE);
gtk_box_pack_start(GTK_BOX(hbox), button_close, TRUE, TRUE, 4);
gtk_signal_connect(GTK_OBJECT(button_close), "clicked",
GTK_SIGNAL_FUNC(close_selection), probe);
gtk_widget_show(button_close);
gtk_signal_connect(GTK_OBJECT(probe->window), "destroy",
GTK_SIGNAL_FUNC(gtk_widget_destroyed), &(probe->window));
}
static void apply_selection(GtkWidget * widget, gpointer data)
{
probe_t *probe;
probe = (probe_t *) data;
probe->pin = NULL;
probe->sig = NULL;
probe->param = NULL;
if (probe->pickname == NULL) {
return;
}
if (probe->listnum == 0) {
probe->pin = halpr_find_pin_by_name(probe->pickname);
} else if (probe->listnum == 1) {
probe->sig = halpr_find_sig_by_name(probe->pickname);
} else if (probe->listnum == 2) {
probe->param = halpr_find_param_by_name(probe->pickname);
}
}
static void close_selection(GtkWidget * widget, gpointer data)
{
probe_t *probe;
probe = (probe_t *) data;
gtk_widget_destroy(probe->window);
}
static gboolean key_press(GtkWidget *clist, GdkEventKey *event, gpointer user_data)
{
gchar *name, *key;
int row, data_good;
probe_t *probe;
probe = (probe_t *) user_data;
if (event->keyval) {
row = 0; data_good = 1;
while (data_good != 0) {
key = (gdk_keyval_name (event->keyval));
data_good = gtk_clist_get_text(GTK_CLIST(clist), row, 0, &name );
printf("check: %s %c\n",key,name[0]);
if (*key == name[0]) {
gtk_clist_moveto(GTK_CLIST(probe->lists[probe->listnum]), row, 0,.5,0);
return 0;
}
row++;
}
}
return 0;
}
static void selection_made(GtkWidget * clist, gint row, gint column,
GdkEventButton * event, gpointer data)
{
probe_t *probe;
probe = (probe_t *) data;
if (clist == NULL) {
return;
}
if (event) {
gtk_clist_get_text(GTK_CLIST(clist), row, 0, &(probe->pickname));
apply_selection(GTK_WIDGET(probe->window), probe);
if (event->type == GDK_2BUTTON_PRESS) {
close_selection(GTK_WIDGET(probe->window), probe);
}
return;
}
}
static void page_switched(GtkNotebook *notebook, GtkNotebookPage *page,
guint page_num, gpointer user_data)
{
((probe_t *)user_data)->listnum=page_num;
}