Thu Apr 28 2011 17:14:00

Asterisk developer's documentation


pbx_gtkconsole.c File Reference

GTK Console monitor -- very kludgy right now. More...

#include "asterisk.h"
#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"
Include dependency graph for pbx_gtkconsole.c:

Go to the source code of this file.

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void __verboser (const char *_stuff)
static int add_mod (const char *module, const char *description, int usecount, const char *like)
static void add_module (void)
static int cleanup (void *useless)
static int cli_activate (void)
static void cliinput (void *data, int source, GdkInputCondition ic)
static void * consolethread (void *data)
static void exit_completely (GtkWidget *widget, gpointer data)
static void exit_nicely (GtkWidget *widget, gpointer data)
static void exit_now (GtkWidget *widget, gpointer data)
static void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
static int load_module (void)
static int mod_update (void)
static int reload (void)
static void remove_module (void)
static int show_console (void)
static int unload_module (void)
static void update_statusbar (char *msg)
static void verboser (const char *stuff)

Variables

static struct ast_module_info
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "GTK Console" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static struct ast_module_infoast_module_info = &__mod_info
static int cleanupid = -1
static GtkWidget * cli
static int clipipe [2]
static GtkWidget * closew
static pthread_t console_thread
static int inuse = 0
static struct timeval last
static GtkWidget * modules
static GtkWidget * quit
static GtkWidget * statusbar
static GtkWidget * verb
static ast_mutex_t verb_lock = AST_MUTEX_INIT_VALUE
static GtkWidget * window

Detailed Description

GTK Console monitor -- very kludgy right now.

Definition in file pbx_gtkconsole.c.


Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 510 of file pbx_gtkconsole.c.

static void __unreg_module ( void  ) [static]

Definition at line 510 of file pbx_gtkconsole.c.

static void __verboser ( const char *  _stuff) [static]

Definition at line 100 of file pbx_gtkconsole.c.

References ast_strdupa, ast_tvdiff_ms(), ast_tvzero(), cleanup(), last, and term_strip().

Referenced by cliinput(), and verboser().

{
   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 int add_mod ( const char *  module,
const char *  description,
int  usecount,
const char *  like 
) [static]

Definition at line 277 of file pbx_gtkconsole.c.

References description, and pass.

Referenced by mod_update().

{
   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 void add_module ( void  ) [static]

Definition at line 263 of file pbx_gtkconsole.c.

References ast_config_AST_MODULE_DIR, and file_ok_sel().

Referenced by show_console().

{
   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 cleanup ( void *  useless) [static]

Definition at line 88 of file pbx_gtkconsole.c.

Referenced by __verboser(), _sip_tcp_helper_thread(), build_user(), and handle_uri().

{
   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 int cli_activate ( void  ) [static]

Definition at line 347 of file pbx_gtkconsole.c.

References ast_cli_command, buf, and TRUE.

Referenced by show_console().

{
   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 void cliinput ( void *  data,
int  source,
GdkInputCondition  ic 
) [static]

Definition at line 145 of file pbx_gtkconsole.c.

References __verboser(), and buf.

Referenced by show_console().

{
   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* consolethread ( void *  data) [static]

Definition at line 338 of file pbx_gtkconsole.c.

Referenced by show_console().

{
   gtk_widget_show(window);
   gdk_threads_enter();
   gtk_main();
   gdk_threads_leave();
   return NULL;
}
static void exit_completely ( GtkWidget *  widget,
gpointer  data 
) [static]

Definition at line 322 of file pbx_gtkconsole.c.

References ast_cli_command.

Referenced by show_console().

{
#if 0
   /* Clever... */
   ast_cli_command(clipipe[1], "quit");
#else
   kill(getpid(), SIGTERM);
#endif
}
static void exit_nicely ( GtkWidget *  widget,
gpointer  data 
) [static]

Definition at line 332 of file pbx_gtkconsole.c.

Referenced by show_console().

{
   fflush(stdout);
   gtk_widget_destroy(window);
}
static void exit_now ( GtkWidget *  widget,
gpointer  data 
) [static]

Definition at line 308 of file pbx_gtkconsole.c.

References ast_loader_unregister(), ast_unload_resource(), ast_unregister_verbose(), ast_update_use_count(), ast_verb, mod_update(), and verboser().

Referenced by show_console().

{
   int res;

   ast_loader_unregister(mod_update);
   gtk_main_quit();
   inuse--;
   ast_update_use_count();
   res = 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 file_ok_sel ( GtkWidget *  w,
GtkFileSelection *  fs 
) [static]

Definition at line 243 of file pbx_gtkconsole.c.

References ast_config_AST_MODULE_DIR, ast_load_resource(), buf, and update_statusbar().

Referenced by add_module().

{
   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 int load_module ( void  ) [static]

Definition at line 483 of file pbx_gtkconsole.c.

References ast_log(), AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_update_use_count(), ast_verb, LOG_DEBUG, LOG_WARNING, option_debug, and show_console().

{
   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;
}
static int mod_update ( void  ) [static]

Definition at line 292 of file pbx_gtkconsole.c.

References add_mod(), and ast_update_module_list().

Referenced by exit_now(), and show_console().

{
   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 int reload ( void  ) [static]

Definition at line 203 of file pbx_gtkconsole.c.

References ast_load_resource(), AST_MODULE_LOAD_SUCCESS, ast_unload_resource(), buf, free, strdup, and update_statusbar().

{
   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 remove_module ( void  ) [static]

Definition at line 183 of file pbx_gtkconsole.c.

References ast_unload_resource(), buf, and update_statusbar().

Referenced by show_console().

{
   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 show_console ( void  ) [static]

Definition at line 358 of file pbx_gtkconsole.c.

References add_module(), ast_loader_register(), ast_pthread_create, ast_register_verbose(), cli_activate(), cliinput(), consolethread(), exit_completely(), exit_nicely(), exit_now(), FALSE, mod_update(), reload, remove_module(), TRUE, update_statusbar(), and verboser().

Referenced by load_module().

{
   GtkWidget *hbox;
   GtkWidget *wbox;
   GtkWidget *notebook;
   GtkWidget *sw;
   GtkWidget *bbox, *hbbox, *add, *removew, *reloadw;
   char *modtitles[3] = { "Module", "Description", "Use Count" };
   int res;

   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);
   res = 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 unload_module ( void  ) [static]

Definition at line 74 of file pbx_gtkconsole.c.

{
   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 void update_statusbar ( char *  msg) [static]

Definition at line 68 of file pbx_gtkconsole.c.

Referenced by file_ok_sel(), reload(), remove_module(), and show_console().

{
   gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 1);
   gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, msg);
}
static void verboser ( const char *  stuff) [static]

Definition at line 133 of file pbx_gtkconsole.c.

References __verboser(), ast_mutex_lock(), ast_mutex_unlock(), and verb_lock.

Referenced by exit_now(), and show_console().

{
   if (*stuff == 127) {
      stuff++;
   }

   ast_mutex_lock(&verb_lock);
   /* Lock appropriately if we're really being called in verbose mode */
   __verboser(stuff);
   ast_mutex_unlock(&verb_lock);
}

Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "GTK Console" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 510 of file pbx_gtkconsole.c.

Definition at line 510 of file pbx_gtkconsole.c.

int cleanupid = -1 [static]

Definition at line 56 of file pbx_gtkconsole.c.

GtkWidget* cli [static]

Definition at line 64 of file pbx_gtkconsole.c.

int clipipe[2] [static]

Definition at line 55 of file pbx_gtkconsole.c.

GtkWidget* closew [static]

Definition at line 60 of file pbx_gtkconsole.c.

pthread_t console_thread [static]

Definition at line 52 of file pbx_gtkconsole.c.

int inuse = 0 [static]
struct timeval last [static]

Definition at line 66 of file pbx_gtkconsole.c.

GtkWidget* modules [static]

Definition at line 62 of file pbx_gtkconsole.c.

GtkWidget* quit [static]

Definition at line 59 of file pbx_gtkconsole.c.

Referenced by launch_asyncagi(), mwi_send_process_buffer(), mwi_thread(), and ss_thread().

GtkWidget* statusbar [static]

Definition at line 63 of file pbx_gtkconsole.c.

GtkWidget* verb [static]

Definition at line 61 of file pbx_gtkconsole.c.

Referenced by ast_register_verbose().

ast_mutex_t verb_lock = AST_MUTEX_INIT_VALUE [static]

Definition at line 50 of file pbx_gtkconsole.c.

Referenced by verboser().

GtkWidget* window [static]

Definition at line 58 of file pbx_gtkconsole.c.