2 * Asterisk -- A telephony toolkit for Linux.
4 * GTK Console monitor -- very kludgy right now
6 * Copyright (C) 1999, Mark Spencer
8 * Mark Spencer <markster@linux-support.net>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
15 * I know this might seem somewhat pointless in its current phase, but one
16 * of the most important parts of this module is demonstrate that modules
17 * can require other external libraries and still be loaded (in this
18 * case, a host of libraries involving gtk), so long as they are properly
19 * linked (see the Makefile)
23 #include <asterisk/pbx.h>
24 #include <asterisk/config.h>
25 #include <asterisk/module.h>
26 #include <asterisk/logger.h>
27 #include <asterisk/options.h>
37 /* For where to put dynamic tables */
38 #include "../asterisk.h"
40 static pthread_mutex_t verb_lock = PTHREAD_MUTEX_INITIALIZER;
42 static pthread_t console_thread;
45 static char *dtext = "Asterisk PBX Console (GTK Version)";
47 static GtkWidget *window;
48 static GtkWidget *quit;
49 static GtkWidget *closew;
50 static GtkWidget *verb;
51 static GtkWidget *modules;
52 static GtkWidget *statusbar;
54 static void update_statusbar(char *msg)
56 gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 1);
57 gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, msg);
60 int unload_module(void)
63 /* Kill off the main thread */
64 pthread_cancel(console_thread);
66 gtk_widget_destroy(window);
73 static void verboser(char *stuff, int opos, int replacelast, int complete)
76 pthread_mutex_lock(&verb_lock);
81 gtk_clist_remove(GTK_CLIST(verb), GTK_CLIST(verb)->rows - 1);
82 gtk_clist_append(GTK_CLIST(verb), s2);
83 gtk_clist_moveto(GTK_CLIST(verb), GTK_CLIST(verb)->rows - 1, 0, 0, 0);
85 pthread_mutex_unlock(&verb_lock);
88 static void remove_module()
93 if (GTK_CLIST(modules)->selection) {
94 module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (int) GTK_CLIST(modules)->selection->data);
96 res = ast_unload_resource(module, 0);
99 snprintf(buf, sizeof(buf), "Module '%s' is in use", module);
100 update_statusbar(buf);
102 snprintf(buf, sizeof(buf), "Module '%s' removed", module);
103 update_statusbar(buf);
107 static void reload_module()
112 if (GTK_CLIST(modules)->selection) {
113 module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (int) GTK_CLIST(modules)->selection->data);
114 module = strdup(module);
117 res = ast_unload_resource(module, 0);
120 snprintf(buf, sizeof(buf), "Module '%s' is in use", module);
121 update_statusbar(buf);
124 res = ast_load_resource(module);
127 snprintf(buf, sizeof(buf), "Error reloading module '%s'", module);
129 snprintf(buf, sizeof(buf), "Module '%s' reloaded", module);
131 for (x=0; x < GTK_CLIST(modules)->rows; x++) {
132 if (!strcmp((char *)gtk_clist_get_row_data(GTK_CLIST(modules), x), module)) {
133 gtk_clist_select_row(GTK_CLIST(modules), x, -1);
137 update_statusbar(buf);
145 static void file_ok_sel(GtkWidget *w, GtkFileSelection *fs)
147 char *module = gtk_file_selection_get_filename(fs);
149 if (!strncmp(module, AST_MODULE_DIR "/", strlen(AST_MODULE_DIR "/")))
150 module += strlen(AST_MODULE_DIR "/");
152 if (ast_load_resource(module)) {
153 snprintf(buf, sizeof(buf), "Error loading module '%s'.", module);
154 update_statusbar(buf);
156 snprintf(buf, sizeof(buf), "Module '%s' loaded", module);
157 update_statusbar(buf);
160 gtk_widget_destroy(GTK_WIDGET(fs));
163 static void add_module()
166 filew = gtk_file_selection_new("Load Module");
167 gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION(filew)->ok_button),
168 "clicked", GTK_SIGNAL_FUNC(file_ok_sel), filew);
169 gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION(filew)->cancel_button),
170 "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(filew));
171 gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), AST_MODULE_DIR "/*.so");
172 gtk_widget_show(filew);
175 static int add_mod(char *module, char *description, int usecount)
180 snprintf(use, sizeof(use), "%d", usecount);
182 pass[1] = description;
185 row = gtk_clist_append(GTK_CLIST(modules), pass);
186 gtk_clist_set_row_data(GTK_CLIST(modules), row, module);
190 static int mod_update(void)
193 /* Update the mod stuff */
194 if (GTK_CLIST(modules)->selection) {
195 module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (int) GTK_CLIST(modules)->selection->data);
198 gtk_clist_freeze(GTK_CLIST(modules));
199 gtk_clist_clear(GTK_CLIST(modules));
200 ast_update_module_list(add_mod);
202 gtk_clist_select_row(GTK_CLIST(modules), gtk_clist_find_row_from_data(GTK_CLIST(modules), module), -1);
203 gtk_clist_thaw(GTK_CLIST(modules));
208 static void exit_now(GtkWidget *widget, gpointer data)
210 ast_loader_unregister(mod_update);
213 ast_update_use_count();
214 ast_unregister_verbose(verboser);
215 ast_unload_resource("pbx_gtkconsole", 0);
216 if (option_verbose > 1)
217 ast_verbose(VERBOSE_PREFIX_2 "GTK Console Monitor Exiting\n");
221 static void exit_completely(GtkWidget *widget, gpointer data)
223 /* This is the wrong way to do this. We need an ast_clean_exit() routine */
227 static void exit_nicely(GtkWidget *widget, gpointer data)
230 gtk_widget_destroy(window);
233 static void *consolethread(void *data)
235 gtk_widget_show(window);
242 static int show_console()
248 GtkWidget *bbox, *hbbox, *add, *removew, *reloadw;
249 char *modtitles[3] = { "Module", "Description", "Use Count" };
250 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
252 statusbar = gtk_statusbar_new();
253 gtk_widget_show(statusbar);
255 gtk_signal_connect(GTK_OBJECT(window), "delete_event",
256 GTK_SIGNAL_FUNC (exit_nicely), window);
257 gtk_signal_connect(GTK_OBJECT(window), "destroy",
258 GTK_SIGNAL_FUNC (exit_now), window);
259 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
261 quit = gtk_button_new_with_label("Quit Asterisk");
262 gtk_signal_connect(GTK_OBJECT(quit), "clicked",
263 GTK_SIGNAL_FUNC (exit_completely), window);
264 gtk_widget_show(quit);
266 closew = gtk_button_new_with_label("Close Window");
267 gtk_signal_connect(GTK_OBJECT(closew), "clicked",
268 GTK_SIGNAL_FUNC (exit_nicely), window);
269 gtk_widget_show(closew);
271 notebook = gtk_notebook_new();
272 verb = gtk_clist_new(1);
273 gtk_clist_columns_autosize(GTK_CLIST(verb));
274 sw = gtk_scrolled_window_new(NULL, NULL);
275 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
276 gtk_container_add(GTK_CONTAINER(sw), verb);
277 gtk_widget_show(verb);
279 gtk_widget_set_usize(verb, 600, 400);
280 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, gtk_label_new("Verbose Status"));
283 modules = gtk_clist_new_with_titles(3, modtitles);
284 gtk_clist_columns_autosize(GTK_CLIST(modules));
285 gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 0, TRUE);
286 gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 1, TRUE);
287 gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 2, TRUE);
288 gtk_clist_set_sort_column(GTK_CLIST(modules), 0);
289 gtk_clist_set_auto_sort(GTK_CLIST(modules), TRUE);
290 gtk_clist_column_titles_passive(GTK_CLIST(modules));
291 sw = gtk_scrolled_window_new(NULL, NULL);
292 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
293 gtk_container_add(GTK_CONTAINER(sw), modules);
294 gtk_clist_set_selection_mode(GTK_CLIST(modules), GTK_SELECTION_BROWSE);
295 gtk_widget_show(modules);
298 add = gtk_button_new_with_label("Load...");
299 gtk_widget_show(add);
300 removew = gtk_button_new_with_label("Unload");
301 gtk_widget_show(removew);
302 reloadw = gtk_button_new_with_label("Reload");
303 gtk_widget_show(reloadw);
304 gtk_signal_connect(GTK_OBJECT(removew), "clicked",
305 GTK_SIGNAL_FUNC (remove_module), window);
306 gtk_signal_connect(GTK_OBJECT(add), "clicked",
307 GTK_SIGNAL_FUNC (add_module), window);
308 gtk_signal_connect(GTK_OBJECT(reloadw), "clicked",
309 GTK_SIGNAL_FUNC (reload_module), window);
311 bbox = gtk_vbox_new(FALSE, 5);
312 gtk_widget_show(bbox);
314 gtk_widget_set_usize(bbox, 100, -1);
315 gtk_box_pack_start(GTK_BOX(bbox), add, FALSE, FALSE, 5);
316 gtk_box_pack_start(GTK_BOX(bbox), removew, FALSE, FALSE, 5);
317 gtk_box_pack_start(GTK_BOX(bbox), reloadw, FALSE, FALSE, 5);
319 hbbox = gtk_hbox_new(FALSE, 5);
320 gtk_widget_show(hbbox);
322 gtk_box_pack_start(GTK_BOX(hbbox), sw, TRUE, TRUE, 5);
323 gtk_box_pack_start(GTK_BOX(hbbox), bbox, FALSE, FALSE, 5);
325 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), hbbox, gtk_label_new("Module Information"));
327 gtk_widget_show(notebook);
329 wbox = gtk_hbox_new(FALSE, 5);
330 gtk_widget_show(wbox);
331 gtk_box_pack_end(GTK_BOX(wbox), quit, FALSE, FALSE, 5);
332 gtk_box_pack_end(GTK_BOX(wbox), closew, FALSE, FALSE, 5);
334 hbox = gtk_vbox_new(FALSE, 0);
335 gtk_widget_show(hbox);
337 gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 5);
338 gtk_box_pack_start(GTK_BOX(hbox), wbox, FALSE, FALSE, 5);
339 gtk_box_pack_start(GTK_BOX(hbox), statusbar, FALSE, FALSE, 0);
342 gtk_container_add(GTK_CONTAINER(window), hbox);
343 gtk_window_set_title(GTK_WINDOW(window), "Asterisk Console");
344 pthread_create(&console_thread, NULL, consolethread, NULL);
345 /* XXX Okay, seriously fix me! XXX */
347 ast_register_verbose(verboser);
348 gtk_clist_freeze(GTK_CLIST(verb));
349 ast_loader_register(mod_update);
350 gtk_clist_thaw(GTK_CLIST(verb));
352 update_statusbar("Asterisk Console Ready");
357 int load_module(void)
360 if (gtk_init_check(NULL, NULL)) {
361 /* XXX Do we need to call this twice? XXX */
362 gtk_init(NULL, NULL);
363 if (!show_console()) {
365 ast_update_use_count();
366 if (option_verbose > 1)
367 ast_verbose( VERBOSE_PREFIX_2 "Launched GTK Console monitor\n");
369 ast_log(LOG_WARNING, "Unable to start GTK console\n");
372 ast_log(LOG_DEBUG, "Unable to start GTK console monitor -- ignoring\n");
373 else if (option_verbose > 1)
374 ast_verbose( VERBOSE_PREFIX_2 "GTK is not available -- skipping monitor\n");
384 char *description(void)