#include <string.h>
#include <gtk/gtkmain.h>
#include <libgnomeui/gnome-app-util.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkcheckbutton.h>
#include "network.h"
#include "packet.h"
+#include "static-startup.h"
/* Config: */
#define DAEMON_CHECK_INTERVAL_MS 100
+#define EXTERNAL_STARTUP_CHECK_INTERVAL_MS 1000
#define PORT_RANGE_BEGIN 2048
#define PORT_RANGE_END 10240
+#define UI_GNOME_PROBE_TIMEOUT_SEC 10
static GnomeApp *App;
static GnomeAppBar *AppBar;
static GtkEntry *PortEntry;
static GtkEntry *HostIPEntry;
+static GtkLabel *AutostartLabel;
+static GtkCheckButton *AutostartCheckButton;
static void state_start_stop(void)
static gboolean daemon_check_timeout_func(gpointer data /* unused */)
{
+ if (!App) /* Quitting? */
+ return FALSE; /* stop running */
+
state_start_stop();
return TRUE; /* continue running */
}
+static gboolean external_startup_check_timeout_func(gpointer data /* unused */)
+{
+gboolean state_startup_is_on;
+
+ if (!App) /* Quitting? */
+ return FALSE; /* stop running */
+
+ if (static_startup_query(&state_startup_is_on))
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(AutostartCheckButton),state_startup_is_on);
+ return TRUE; /* continue running */
+}
+
+static void buttonstart(void)
+{
+ if (!optarg_port_set_string(gtk_entry_get_text(PortEntry)))
+ return;
+ network_start(optarg_port);
+}
+
void on_PortButtonRandom_clicked(GtkButton *button,gpointer user_data)
{
g_return_if_fail(GTK_IS_BUTTON(button));
return;
gtk_entry_set_text(PortEntry,
udpgate_printf_alloca("%d",(int)g_random_int_range(PORT_RANGE_BEGIN,PORT_RANGE_END)));
+ buttonstart();
}
void on_AutostartCheckButton_toggled(GtkToggleButton *togglebutton,gpointer user_data)
{
+static gint inside=0;
+
g_return_if_fail(GTK_IS_TOGGLE_BUTTON(togglebutton));
+
+ /* Avoid reentrancy to prevent segfault during failed registration.
+ * FIXME: Who knows why? Some forbidden GTK recursion occurs.
+ */
+ g_assert(inside>=0);
+ if (inside)
+ return;
+ inside++;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(AutostartCheckButton)))
+ static_startup_on();
+ else
+ static_startup_off();
+ external_startup_check_timeout_func(NULL); /* data; unused */
+
+ g_assert(inside==1);
+ inside--;
}
void on_ButtonStart_clicked(GtkButton *button,gpointer user_data)
{
-const gchar *port_string;
-char *endp;
-long port_long;
-
g_return_if_fail(GTK_IS_BUTTON(button));
- port_string=gtk_entry_get_text(PortEntry);
- port_long=strtol(port_string,&endp,0);
- if (endp && *endp) {
- g_warning(_("Invalid port specification, offending string: %s"),endp);
- return;
- }
- if (port_long<1 || port_long>=G_MAXINT || (endp && *endp)) {
- g_warning(_("Invalid port integer number specification (%ld)"),port_long);
- return;
- }
- network_start(port_long);
+ buttonstart();
}
void on_ButtonStop_clicked(GtkButton *button,gpointer user_data)
void on_ButtonHide_clicked(GtkButton *button,gpointer user_data)
{
+GnomeApp *App_local;
+
g_return_if_fail(GTK_IS_BUTTON(button));
+ /* update config file */
+ optarg_port_set_string(gtk_entry_get_text(PortEntry));
+
/* Do not: gtk_main_quit();
* as 'App' widget will quit our gtk_main() automatically.
*/
- gtk_widget_destroy(GTK_WIDGET(App));
+ /* Do not: gtk_widget_destroy(App); App=NULL;
+ * as it would race with g_timeout_add()ed function which check
+ * 'if (!App)' first and expect there fully valid tree afterwards.
+ */
+ App_local=App;
+ App=NULL;
+ gtk_widget_destroy(GTK_WIDGET(App_local));
}
static void ui_gnome_network_notify_hostip(guint32 hostip_guint32)
{
+ if (!App) /* Quitting? */
+ return;
+
if (!hostip_guint32) {
- if (is_daemon_running()==(pid_t)-1)
+pid_t daemon_pid;
+
+ daemon_pid=is_daemon_running();
+ if ((pid_t)-1==daemon_pid)
gtk_entry_set_text(HostIPEntry,_("(unknown; Start the daemon)"));
- else
+ else if (getpid()==daemon_pid)
gtk_entry_set_text(HostIPEntry,_("(unknown; detecting...)"));
+ else
+ gtk_entry_set_text(HostIPEntry,_("(unknown; Kill the daemon and start your own)"));
}
else {
gtk_entry_set_text(HostIPEntry,HOSTIP_GUINT32_TO_STRING(hostip_guint32));
}
}
+static guint ui_gnome_g_log_handler_handler_id;
static void ui_gnome_g_log_handler(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,gpointer user_data)
{
GtkWidget *dialog;
+ if (!App) /* Quitting? */
+ return;
+
/**/ if (log_level & G_LOG_LEVEL_ERROR)
dialog=gnome_app_error(App,message);
else if (log_level & (G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING))
else
dialog=gnome_app_message(App,message);
+ /* Do not set it modal as ... who knows. At least in the fully static
+ * build during on_AutostartCheckButton_toggled() we get reported
+ * the messages twice and application immediately gtk_main_quit()
+ * even the second (toplevel) gtk_main().
+ */
+#if 0
gtk_window_set_modal(GTK_WINDOW(dialog),TRUE);
g_signal_connect((gpointer)dialog,"close",G_CALLBACK(gtk_main_quit),NULL);
gtk_main();
/* 'dialog' gets destroyed automatically */
+#endif
+}
+
+static void ui_gnome_interactive(void)
+{
+ probe_timeout_sec_max=UI_GNOME_PROBE_TIMEOUT_SEC;
+ gtk_main();
+ network_notify_hostip=NULL;
+ g_log_remove_handler(
+ G_LOG_DOMAIN, /* log_domain; "Captive" */
+ ui_gnome_g_log_handler_handler_id); /* handler_id */
+ network_detach();
}
/* of "ui-gnome-interface.h": */
AppBar=GNOME_APPBAR(lookup_widget(GTK_WIDGET(App),"AppBar"));
PortEntry=GTK_ENTRY(lookup_widget(GTK_WIDGET(App),"PortEntry"));
HostIPEntry=GTK_ENTRY(lookup_widget(GTK_WIDGET(App),"HostIPEntry"));
+ AutostartLabel=GTK_LABEL(lookup_widget(GTK_WIDGET(App),"AutostartLabel"));
+ AutostartCheckButton=GTK_CHECK_BUTTON(lookup_widget(GTK_WIDGET(App),"AutostartCheckButton"));
/* ui_gnome_g_log_handler() needs 'App'. */
- g_log_set_handler(
+ ui_gnome_g_log_handler_handler_id=g_log_set_handler(
G_LOG_DOMAIN, /* log_domain; "Captive" */
(G_LOG_LEVEL_MASK|G_LOG_FLAG_FATAL)&~(0
|G_LOG_LEVEL_MESSAGE
NULL); /* user_data */
ui_gnome_network_notify_hostip(0);
+ gtk_entry_set_text(PortEntry,udpgate_printf_alloca("%d",(int)optarg_port));
+ if (!static_startup_supported()) {
+ gtk_widget_set_sensitive(GTK_WIDGET(AutostartLabel),FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(AutostartCheckButton),FALSE);
+ }
+ if (!static_startup_query(NULL))
+ gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(AutostartCheckButton),TRUE);
+ daemon_check_timeout_func(NULL); /* data; unused */
+ external_startup_check_timeout_func(NULL); /* data; unused */
gtk_widget_show_all(GTK_WIDGET(App));
g_timeout_add(
DAEMON_CHECK_INTERVAL_MS, /* interval */
daemon_check_timeout_func, /* function */
NULL); /* data; unused */
+ g_timeout_add(
+ EXTERNAL_STARTUP_CHECK_INTERVAL_MS, /* interval */
+ external_startup_check_timeout_func, /* function */
+ NULL); /* data; unused */
network_notify_hostip=ui_gnome_network_notify_hostip;
- return TRUE;
-}
+ ui_interactive=ui_gnome_interactive;
-void ui_gnome_interactive(void)
-{
- gtk_main();
+ return TRUE;
}