📄 vcp_main.c
字号:
/** This file, 'vcp_main.c', is a GUI program allows a user to generate a "Virtual Control Panel" with on-screen GUI widgets that can control or display the state of HAL pins. It is a user space component and uses GTK 1.2 or 2.0 for the GUI code.*//** Copyright (C) 2005 John Kasunich <jmkasunich AT users DOT sourceforge DOT net>*//** This program is free software; you can redistribute it and/or modify it under the terms of version 2.1 of the GNU General Public License as published by the Free Software Foundation. This library 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR ANY HARM OR LOSS RESULTING FROM ITS USE. IT IS _EXTREMELY_ UNWISE TO RELY ON SOFTWARE ALONE FOR SAFETY. Any machinery capable of harming persons must have provisions for completely removing power from all motors, etc, before persons enter any danger area. All machinery must be designed to comply with local and national safety codes, and the authors of this software can not, and do not, take any responsibility for such compliance. In particular, controls on a Virtual Control Panel MUST NOT be relied on for safety. Real controls that physically interrupt the flow of power to the machine must be used to render the machine safe. This code was written as part of the EMC HAL project. For more information, go to www.linuxcnc.org.*/#ifndef ULAPI#error This is a user mode component only!#endif#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" /* RTAPI realtime OS API */#include "hal.h" /* HAL public API decls */#include "tokenizer.h"#include "vcp.h"/************************************************************************ GLOBAL VARIABLES *************************************************************************/char errbuf[ERRBUFLEN];int comp_id; /* HAL component ID *//************************************************************************ LOCAL VARIABLES *************************************************************************/static vcp_widget_t *root; /* root of widget tree *//************************************************************************ LOCAL FUNCTION PROTOTYPES *************************************************************************//* init functions */static int init_widget ( vcp_widget_t *wp );/* callback functions */static void exit_from_hal(void);static void free_tree(void);static void quit(int sig);static int heartbeat(gpointer data);static void run_poll_functs(vcp_widget_t *wp);/* parser functions */static vcp_widget_t *get_vcp_tree(char *filename);static vcp_widget_t *get_child_widget(vcp_widget_t *parent, char *name, token_file_t *tf);static void free_widget(vcp_widget_t *widget);static int get_attrib(vcp_widget_t *widget, char *name, token_file_t *tf);static int convert_attrib(vcp_attrib_def_t *adef, char *value, void *base_addr);/************************************************************************ MAIN() FUNCTION *************************************************************************/int main(int argc, gchar * argv[]){ vcp_widget_t *wp, *main_win; /* process and remove any GTK specific command line args */ gtk_init(&argc, &argv); printf ( "NOTICE: VCP is still under construction\n" ); printf ( "It may be broken at any time, and should not be used yet!\n" ); sleep(2); /* process halvcp command line args (if any) here */ if ( argc != 2 ) { printf ( "usage: halvcp <file>\n" ); return -1; } /* open and parse the .vcp file */ root = get_vcp_tree(argv[1]); if ( root == NULL ) { rtapi_print_msg(RTAPI_MSG_ERR, "VCP: ERROR: error in input file\n"); return -1; } /* register an exit function to free the tree */ g_atexit(free_tree); printf ( "Got a good tree\n" ); /* connect to the HAL */ comp_id = hal_init("halvcp"); if (comp_id < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VCP: ERROR: hal_init() failed\n"); return -1; } /* register an exit function to cleanup and disconnect from the HAL */ g_atexit(exit_from_hal); printf ( "connected to HAL\n" ); /* look for main window in widget tree */ if ( root->child == NULL ) { rtapi_print_msg(RTAPI_MSG_ERR, "VCP: ERROR: nothing inside vcp{} block\n"); return -1; } wp = root->child; main_win = NULL; while ( wp != NULL ) { if ( strcmp(wp->type->name, "main-window") == 0 ) { main_win = wp; } else { printf ( "unexpected top level widget '%s'\n", wp->type->name ); } wp = wp->sibling; } if ( main_win == NULL ) { rtapi_print_msg(RTAPI_MSG_ERR, "VCP: ERROR: 'main-window' missing\n"); return -1; } /* init all widgets inside (and including) main window */ if ( init_widget(main_win) != 0 ) { return -1; } /* register signal handlers for ctrl-C and SIGTERM */ signal(SIGINT, quit); signal(SIGTERM, quit); /* The interface is now completely set up */ /* show the window */ gtk_widget_show(main_win->gtk_widget); /* arrange for periodic call of heartbeat() (every 100mS) */ gtk_timeout_add(100, heartbeat, NULL); /* enter the main loop */ gtk_main(); return (0);}/************************************************************************ LOCAL INIT FUNCTION CODE *************************************************************************/static int init_widget ( vcp_widget_t *wp ){ if ( wp->type->init_funct != NULL ) { /* call the init function */ if ( wp->type->init_funct(wp) != 0 ) { rtapi_print_msg(RTAPI_MSG_ERR, "VCP: ERROR: error initing widget '%s'\n", wp->type->name); return -1; } } /* init children and siblings */ if ( wp->child != NULL ) { if ( init_widget(wp->child) != 0 ) { return -1; } } if ( wp->sibling != NULL ) { if ( init_widget(wp->sibling) != 0 ) { return -1; } } return 0;}/************************************************************************ LOCAL CALLBACK FUNCTION CODE *************************************************************************/static void exit_from_hal(void){ hal_exit(comp_id); printf ( "exited from HAL\n" );}static void free_tree(void){ free_widget(root); printf ( "freed widget tree\n" );}static void quit(int sig){ gtk_main_quit();}/* This function is called approximately 10 times per second. It is responsible for updating anything that is supposed to be "live", such as the display widgets.*/static int heartbeat(gpointer data){ run_poll_functs(root); return 0;}static void run_poll_functs(vcp_widget_t *wp){ /* run poll function of this widget (if any) */ if ( wp->poll_funct != NULL ) { /* call the poll function */ wp->poll_funct(wp); } /* run poll functions of children and siblings */ if ( wp->child != NULL ) { run_poll_functs(wp->child); } if ( wp->sibling != NULL ) { run_poll_functs(wp->sibling); }}/************************************************************************ LOCAL PARSER FUNCTION CODE *************************************************************************/static vcp_widget_t *get_vcp_tree(char *filename){ token_file_t *tf; vcp_widget_t *wp; char *name, *tmp; tf = tf_open(filename, 100, "{}=", '\\', '#', '"' ); if ( tf == NULL ) { return NULL; } name = tf_get_token(tf); tmp = tf_get_token(tf); if ( name == NULL ) { printf ( "nothing in file '%s'\n", filename ); tf_close(tf); return NULL; } if (( strcmp(name, "vcp") != 0 ) || (tmp == NULL ) || ( tmp[0] != '{' )) { printf ( "VCP file '%s' must start with 'vcp {'\n", filename ); tf_close(tf); return NULL; } wp = get_child_widget(NULL, name, tf ); if ( wp == NULL ) { printf ( "error in VCP file '%s'\n", filename ); tf_close(tf); return NULL; } tf_close(tf); return wp;}static vcp_widget_t *get_child_widget(vcp_widget_t *parent, char *name, token_file_t *tf){ vcp_widget_def_t *wdef; vcp_attrib_def_t *adef; vcp_widget_t *widget, *wp; char *item_name, *delim, *cp; int n;printf ( "get_child('%s')\n", name ); n = 0; wdef = widget_defs[n]; while ( wdef != NULL ) { if ( strcmp(wdef->name, name) == 0 ) { break; } wdef = widget_defs[n++]; } if ( wdef == NULL ) { printf ( "line %d: invalid widget type '%s'\n", tf->tokenline, name ); return NULL; }printf ( " matched\n" ); /* found a match for name, check if it is a legal child of parent */ if ( parent != NULL ) { if ( ( wdef->w_class & parent->type->w_class_mask ) == 0 ) { printf ( "line %d: '%s' not permitted as child of '%s'\n", tf->tokenline, wdef->name, parent->type->name ); return NULL; } }printf ( " legal\n" ); /* allocate the widget structure */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -