diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-01-19 00:19:29 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-01-19 00:19:29 +0000 |
commit | f8247040e6231c4b3b5099ea3a526348b7941566 (patch) | |
tree | 0cc92ad6ebf6ae49a62f6e7ef8ec819121d63630 /trunk/pbx/pbx_gtkconsole.c | |
parent | d88e56c61ce2042544c1a8a71c93b69ab2e6ffba (diff) |
Creating tag for the release of asterisk-1.6.0-beta1v1.6.0-beta1
git-svn-id: http://svn.digium.com/svn/asterisk/tags/1.6.0-beta1@99163 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'trunk/pbx/pbx_gtkconsole.c')
-rw-r--r-- | trunk/pbx/pbx_gtkconsole.c | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/trunk/pbx/pbx_gtkconsole.c b/trunk/pbx/pbx_gtkconsole.c new file mode 100644 index 000000000..5e47ac668 --- /dev/null +++ b/trunk/pbx/pbx_gtkconsole.c @@ -0,0 +1,502 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief GTK Console monitor -- very kludgy right now + * + */ + +/*** MODULEINFO + <depend>gtk</depend> + <defaultenabled>no</defaultenabled> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <fcntl.h> +#include <signal.h> +#include <sys/time.h> + +#include <gtk/gtk.h> +#include <glib.h> + +#include "asterisk/pbx.h" +#include "asterisk/config.h" +#include "asterisk/module.h" +#include "asterisk/logger.h" +#include "asterisk/cli.h" +#include "asterisk/utils.h" +#include "asterisk/paths.h" +#include "asterisk/term.h" + +AST_MUTEX_DEFINE_STATIC(verb_lock); + +static pthread_t console_thread; + +static int inuse=0; +static int clipipe[2]; +static int cleanupid = -1; + +static GtkWidget *window; +static GtkWidget *quit; +static GtkWidget *closew; +static GtkWidget *verb; +static GtkWidget *modules; +static GtkWidget *statusbar; +static GtkWidget *cli; + +static struct timeval last; + +static void update_statusbar(char *msg) +{ + gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 1); + gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, msg); +} + +static int unload_module(void) +{ + if (inuse) { + /* Kill off the main thread */ + pthread_cancel(console_thread); + gdk_threads_enter(); + gtk_widget_destroy(window); + gdk_threads_leave(); + close(clipipe[0]); + close(clipipe[1]); + } + return 0; +} + +static int cleanup(void *useless) +{ + gdk_threads_enter(); + gtk_clist_thaw(GTK_CLIST(verb)); + gtk_widget_queue_resize(verb->parent); + gtk_clist_moveto(GTK_CLIST(verb), GTK_CLIST(verb)->rows - 1, 0, 0, 0); + cleanupid = -1; + gdk_threads_leave(); + return 0; +} + + +static void __verboser(const char *_stuff) +{ + char *s2[2]; + struct timeval tv; + int ms; + char *stuff; + + stuff = ast_strdupa(_stuff); + term_strip(stuff, stuff, strlen(stuff) + 1); + + s2[0] = (char *)stuff; + s2[1] = NULL; + gtk_clist_freeze(GTK_CLIST(verb)); + gtk_clist_append(GTK_CLIST(verb), s2); + if (!ast_tvzero(last)) { + gdk_threads_leave(); + gettimeofday(&tv, NULL); + if (cleanupid > -1) + gtk_timeout_remove(cleanupid); + ms = ast_tvdiff_ms(tv, last); + if (ms < 100) { + /* We just got a message within 100ms, so just schedule an update + in the near future */ + cleanupid = gtk_timeout_add(200, cleanup, NULL); + } else { + cleanup(&cleanupid); + } + last = tv; + } else { + gettimeofday(&last, NULL); + } +} + +static void verboser(const char *stuff) +{ + ast_mutex_lock(&verb_lock); + /* Lock appropriately if we're really being called in verbose mode */ + __verboser(stuff); + ast_mutex_unlock(&verb_lock); +} + +static void cliinput(void *data, int source, GdkInputCondition ic) +{ + static char buf[256]; + static int offset = 0; + int res; + char *c; + char *l; + char n; + /* Read as much stuff is there */ + res = read(source, buf + offset, sizeof(buf) - 1 - offset); + if (res > -1) + buf[res + offset] = '\0'; + /* make sure we've null terminated whatever we have so far */ + c = buf; + l = buf; + while(*c) { + if (*c == '\n') { + /* Keep the trailing \n */ + c++; + n = *c; + *c = '\0'; + __verboser(l); + *(c - 1) = '\0'; + *c = n; + l = c; + } else + c++; + } + if (strlen(l)) { + /* We have some left over */ + memmove(buf, l, strlen(l) + 1); + offset = strlen(buf); + } else { + offset = 0; + } + +} + +static void remove_module(void) +{ + int res; + char *module; + char buf[256]; + if (GTK_CLIST(modules)->selection) { + module = (char *) gtk_clist_get_row_data(GTK_CLIST(modules), (long) GTK_CLIST(modules)->selection->data); + gdk_threads_leave(); + res = ast_unload_resource(module, 0); + gdk_threads_enter(); + if (res) { + snprintf(buf, sizeof(buf), "Module '%s' is in use", module); + update_statusbar(buf); + } else { + snprintf(buf, sizeof(buf), "Module '%s' removed", module); + update_statusbar(buf); + } + } +} + +static int reload(void) +{ + int res, x; + char *module; + char buf[256]; + if (GTK_CLIST(modules)->selection) { + module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (long) GTK_CLIST(modules)->selection->data); + module = strdup(module); + if (module) { + gdk_threads_leave(); + res = ast_unload_resource(module, 0); + gdk_threads_enter(); + if (res) { + snprintf(buf, sizeof(buf), "Module '%s' is in use", module); + update_statusbar(buf); + } else { + gdk_threads_leave(); + res = ast_load_resource(module); + gdk_threads_enter(); + if (res) { + snprintf(buf, sizeof(buf), "Error reloading module '%s'", module); + } else { + snprintf(buf, sizeof(buf), "Module '%s' reloaded", module); + } + for (x=0; x < GTK_CLIST(modules)->rows; x++) { + if (!strcmp((char *)gtk_clist_get_row_data(GTK_CLIST(modules), x), module)) { + gtk_clist_select_row(GTK_CLIST(modules), x, -1); + break; + } + } + update_statusbar(buf); + + } + free(module); + } + } + + return AST_MODULE_LOAD_SUCCESS; +} + +static void file_ok_sel(GtkWidget *w, GtkFileSelection *fs) +{ + char tmp[PATH_MAX]; + char *module = gtk_file_selection_get_filename(fs); + char buf[256]; + snprintf(tmp, sizeof(tmp), "%s/", ast_config_AST_MODULE_DIR); + if (!strncmp(module, (char *)tmp, strlen(tmp))) + module += strlen(tmp); + gdk_threads_leave(); + if (ast_load_resource(module)) { + snprintf(buf, sizeof(buf), "Error loading module '%s'.", module); + update_statusbar(buf); + } else { + snprintf(buf, sizeof(buf), "Module '%s' loaded", module); + update_statusbar(buf); + } + gdk_threads_enter(); + gtk_widget_destroy(GTK_WIDGET(fs)); +} + +static void add_module(void) +{ + char tmp[PATH_MAX]; + GtkWidget *filew; + snprintf(tmp, sizeof(tmp), "%s/*.so", ast_config_AST_MODULE_DIR); + filew = gtk_file_selection_new("Load Module"); + gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION(filew)->ok_button), + "clicked", GTK_SIGNAL_FUNC(file_ok_sel), filew); + gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION(filew)->cancel_button), + "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(filew)); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), (char *)tmp); + gtk_widget_show(filew); +} + +static int add_mod(const char *module, const char *description, int usecount, const char *like) +{ + char use[10]; + const char *pass[4]; + int row; + snprintf(use, sizeof(use), "%d", usecount); + pass[0] = module; + pass[1] = description; + pass[2] = use; + pass[3] = NULL; + row = gtk_clist_append(GTK_CLIST(modules), (char **) pass); + gtk_clist_set_row_data(GTK_CLIST(modules), row, (char *) module); + return 0; +} + +static int mod_update(void) +{ + char *module= NULL; + /* Update the mod stuff */ + if (GTK_CLIST(modules)->selection) { + module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (long) GTK_CLIST(modules)->selection->data); + } + gtk_clist_freeze(GTK_CLIST(modules)); + gtk_clist_clear(GTK_CLIST(modules)); + ast_update_module_list(add_mod, NULL); + if (module) + gtk_clist_select_row(GTK_CLIST(modules), gtk_clist_find_row_from_data(GTK_CLIST(modules), module), -1); + gtk_clist_thaw(GTK_CLIST(modules)); + return 1; +} + +static void exit_now(GtkWidget *widget, gpointer data) +{ + ast_loader_unregister(mod_update); + gtk_main_quit(); + inuse--; + ast_update_use_count(); + ast_unregister_verbose(verboser); + ast_unload_resource("pbx_gtkconsole", 0); + ast_verb(2, "GTK Console Monitor Exiting\n"); + /* XXX Trying to quit after calling this makes asterisk segfault XXX */ +} + +static void exit_completely(GtkWidget *widget, gpointer data) +{ +#if 0 + /* Clever... */ + ast_cli_command(clipipe[1], "quit"); +#else + kill(getpid(), SIGTERM); +#endif +} + +static void exit_nicely(GtkWidget *widget, gpointer data) +{ + fflush(stdout); + gtk_widget_destroy(window); +} + +static void *consolethread(void *data) +{ + gtk_widget_show(window); + gdk_threads_enter(); + gtk_main(); + gdk_threads_leave(); + return NULL; +} + +static int cli_activate(void) +{ + char buf[256] = ""; + strncpy(buf, gtk_entry_get_text(GTK_ENTRY(cli)), sizeof(buf) - 1); + gtk_entry_set_text(GTK_ENTRY(cli), ""); + if (strlen(buf)) { + ast_cli_command(clipipe[1], buf); + } + return TRUE; +} + +static int show_console(void) +{ + GtkWidget *hbox; + GtkWidget *wbox; + GtkWidget *notebook; + GtkWidget *sw; + GtkWidget *bbox, *hbbox, *add, *removew, *reloadw; + char *modtitles[3] = { "Module", "Description", "Use Count" }; + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + statusbar = gtk_statusbar_new(); + gtk_widget_show(statusbar); + + gtk_signal_connect(GTK_OBJECT(window), "delete_event", + GTK_SIGNAL_FUNC (exit_nicely), window); + gtk_signal_connect(GTK_OBJECT(window), "destroy", + GTK_SIGNAL_FUNC (exit_now), window); + gtk_container_set_border_width(GTK_CONTAINER(window), 10); + + quit = gtk_button_new_with_label("Quit Asterisk"); + gtk_signal_connect(GTK_OBJECT(quit), "clicked", + GTK_SIGNAL_FUNC (exit_completely), window); + gtk_widget_show(quit); + + closew = gtk_button_new_with_label("Close Window"); + gtk_signal_connect(GTK_OBJECT(closew), "clicked", + GTK_SIGNAL_FUNC (exit_nicely), window); + gtk_widget_show(closew); + + notebook = gtk_notebook_new(); + verb = gtk_clist_new(1); + gtk_clist_columns_autosize(GTK_CLIST(verb)); + sw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_container_add(GTK_CONTAINER(sw), verb); + gtk_widget_show(verb); + gtk_widget_show(sw); + gtk_widget_set_usize(verb, 640, 400); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, gtk_label_new("Verbose Status")); + + + modules = gtk_clist_new_with_titles(3, modtitles); + gtk_clist_columns_autosize(GTK_CLIST(modules)); + gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 0, TRUE); + gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 1, TRUE); + gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 2, TRUE); + gtk_clist_set_sort_column(GTK_CLIST(modules), 0); + gtk_clist_set_auto_sort(GTK_CLIST(modules), TRUE); + gtk_clist_column_titles_passive(GTK_CLIST(modules)); + sw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_container_add(GTK_CONTAINER(sw), modules); + gtk_clist_set_selection_mode(GTK_CLIST(modules), GTK_SELECTION_BROWSE); + gtk_widget_show(modules); + gtk_widget_show(sw); + + add = gtk_button_new_with_label("Load..."); + gtk_widget_show(add); + removew = gtk_button_new_with_label("Unload"); + gtk_widget_show(removew); + reloadw = gtk_button_new_with_label("Reload"); + gtk_widget_show(reloadw); + gtk_signal_connect(GTK_OBJECT(removew), "clicked", + GTK_SIGNAL_FUNC (remove_module), window); + gtk_signal_connect(GTK_OBJECT(add), "clicked", + GTK_SIGNAL_FUNC (add_module), window); + gtk_signal_connect(GTK_OBJECT(reloadw), "clicked", + GTK_SIGNAL_FUNC (reload), window); + + bbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(bbox); + + gtk_widget_set_usize(bbox, 100, -1); + gtk_box_pack_start(GTK_BOX(bbox), add, FALSE, FALSE, 5); + gtk_box_pack_start(GTK_BOX(bbox), removew, FALSE, FALSE, 5); + gtk_box_pack_start(GTK_BOX(bbox), reloadw, FALSE, FALSE, 5); + + hbbox = gtk_hbox_new(FALSE, 5); + gtk_widget_show(hbbox); + + gtk_box_pack_start(GTK_BOX(hbbox), sw, TRUE, TRUE, 5); + gtk_box_pack_start(GTK_BOX(hbbox), bbox, FALSE, FALSE, 5); + + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), hbbox, gtk_label_new("Module Information")); + + gtk_widget_show(notebook); + + wbox = gtk_hbox_new(FALSE, 5); + gtk_widget_show(wbox); + gtk_box_pack_end(GTK_BOX(wbox), quit, FALSE, FALSE, 5); + gtk_box_pack_end(GTK_BOX(wbox), closew, FALSE, FALSE, 5); + + hbox = gtk_vbox_new(FALSE, 0); + gtk_widget_show(hbox); + + /* Command line */ + cli = gtk_entry_new(); + gtk_widget_show(cli); + + gtk_signal_connect(GTK_OBJECT(cli), "activate", + GTK_SIGNAL_FUNC (cli_activate), NULL); + + gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 5); + gtk_box_pack_start(GTK_BOX(hbox), wbox, FALSE, FALSE, 5); + gtk_box_pack_start(GTK_BOX(hbox), cli, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), statusbar, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(window), hbox); + gtk_window_set_title(GTK_WINDOW(window), "Asterisk Console"); + gtk_widget_grab_focus(cli); + ast_pthread_create(&console_thread, NULL, consolethread, NULL); + /* XXX Okay, seriously fix me! XXX */ + usleep(100000); + ast_register_verbose(verboser); + gtk_clist_freeze(GTK_CLIST(verb)); + ast_loader_register(mod_update); + gtk_clist_thaw(GTK_CLIST(verb)); + gdk_input_add(clipipe[0], GDK_INPUT_READ, cliinput, NULL); + mod_update(); + update_statusbar("Asterisk Console Ready"); + return 0; +} + + +static int load_module(void) +{ + if (pipe(clipipe)) { + ast_log(LOG_WARNING, "Unable to create CLI pipe\n"); + return AST_MODULE_LOAD_FAILURE; + } + g_thread_init(NULL); + if (gtk_init_check(NULL, NULL)) { + if (!show_console()) { + inuse++; + ast_update_use_count(); + ast_verb(2, "Launched GTK Console monitor\n"); + } else + ast_log(LOG_WARNING, "Unable to start GTK console\n"); + } else { + if (option_debug) + ast_log(LOG_DEBUG, "Unable to start GTK console monitor -- ignoring\n"); + else + ast_verb(2, "GTK is not available -- skipping monitor\n"); + } + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "GTK Console", + .load = load_module, + .unload = unload_module, + .reload = reload, + ); |