Command-line version implemented.
[udpgate.git] / src / ui-gnome.c
1 /* $Id$
2  * Gnome user interface
3  * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "ui-gnome.h"   /* self */
23 #include <glib/gmessages.h>
24 #include "main.h"
25 #include <libgnomeui/gnome-app.h>
26 #include <sys/types.h>
27 #include <signal.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <libgnomeui/gnome-appbar.h>
31 #include <gtk/gtkbutton.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <gtk/gtkentry.h>
35 #include <gtk/gtktogglebutton.h>
36 #include <string.h>
37 #include <gtk/gtkmain.h>
38 #include <libgnomeui/gnome-app-util.h>
39
40 #include "network.h"
41 #include "packet.h"
42
43
44 /* Config: */
45 #define DAEMON_CHECK_INTERVAL_MS 100
46 #define PORT_RANGE_BEGIN 2048
47 #define PORT_RANGE_END 10240
48
49
50 static GnomeApp *App;
51 static GtkButton *ButtonStart;
52 static GtkButton *ButtonStop;
53 static GtkHBox *PortHBox;
54 static GnomeAppBar *AppBar;
55 static GtkEntry *PortEntry;
56 static GtkEntry *HostIPEntry;
57
58
59 static void state_start_stop(void)
60 {
61 pid_t daemon_pid;
62 gboolean daemon_running;
63 static gboolean last_daemon_running,last_daemon_running_set=FALSE;
64
65         daemon_pid=is_daemon_running();
66         daemon_running=((pid_t)-1!=daemon_pid);
67
68         /* Cache the result; maybe not needed. */
69         if (last_daemon_running_set && last_daemon_running==daemon_running)
70                 return;
71         last_daemon_running=daemon_running;
72         last_daemon_running_set=TRUE;
73
74         gtk_widget_set_sensitive(GTK_WIDGET(ButtonStart),!daemon_running);
75         gtk_widget_set_sensitive(GTK_WIDGET(ButtonStop) , daemon_running);
76         gtk_widget_set_sensitive(GTK_WIDGET(PortHBox)   ,!daemon_running);
77         if (daemon_running)
78                 gnome_appbar_set_status(AppBar,
79                                 udpgate_printf_alloca(_("udpgate daemon running as PID %d."),(int)daemon_pid));
80         else
81                 gnome_appbar_set_status(AppBar,_("No udpgate daemon currently running."));
82 }
83
84 static gboolean daemon_check_timeout_func(gpointer data /* unused */)
85 {
86         state_start_stop();
87         return TRUE;    /* continue running */
88 }
89
90 void on_PortButtonRandom_clicked(GtkButton *button,gpointer user_data)
91 {
92         g_return_if_fail(GTK_IS_BUTTON(button));
93
94         state_start_stop();
95         if ((pid_t)-1!=is_daemon_running())
96                 return;
97         gtk_entry_set_text(PortEntry,
98                         udpgate_printf_alloca("%d",(int)g_random_int_range(PORT_RANGE_BEGIN,PORT_RANGE_END)));
99 }
100
101 void on_AutostartCheckButton_toggled(GtkToggleButton *togglebutton,gpointer user_data)
102 {
103         g_return_if_fail(GTK_IS_TOGGLE_BUTTON(togglebutton));
104 }
105
106 void on_ButtonStart_clicked(GtkButton *button,gpointer user_data)
107 {
108 const gchar *port_string;
109 char *endp;
110 long port_long;
111
112         g_return_if_fail(GTK_IS_BUTTON(button));
113
114         port_string=gtk_entry_get_text(PortEntry);
115         port_long=strtol(port_string,&endp,0);
116         if (endp && *endp) {
117                 g_warning(_("Invalid port specification, offending string: %s"),endp);
118                 return;
119                 }
120         if (port_long<1 || port_long>=G_MAXINT || (endp && *endp)) {
121                 g_warning(_("Invalid port integer number specification (%ld)"),port_long);
122                 return;
123                 }
124         network_start(port_long);
125 }
126
127 void on_ButtonStop_clicked(GtkButton *button,gpointer user_data)
128 {
129         g_return_if_fail(GTK_IS_BUTTON(button));
130
131         network_stop();
132 }
133
134 void on_ButtonHide_clicked(GtkButton *button,gpointer user_data)
135 {
136         g_return_if_fail(GTK_IS_BUTTON(button));
137
138         /* Do not: gtk_main_quit();
139          * as 'App' widget will quit our gtk_main() automatically.
140          */
141         gtk_widget_destroy(GTK_WIDGET(App));
142 }
143
144 static void ui_gnome_network_notify_hostip(guint32 hostip_guint32)
145 {
146         if (!hostip_guint32) {
147                 if (is_daemon_running()==(pid_t)-1)
148                         gtk_entry_set_text(HostIPEntry,_("(unknown; Start the daemon)"));
149                 else
150                         gtk_entry_set_text(HostIPEntry,_("(unknown; detecting...)"));
151                 }
152         else {
153                 gtk_entry_set_text(HostIPEntry,HOSTIP_GUINT32_TO_STRING(hostip_guint32));
154                 }
155 }
156
157 static guint ui_gnome_g_log_handler_handler_id;
158 static void ui_gnome_g_log_handler(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,gpointer user_data)
159 {
160 GtkWidget *dialog;
161
162         /**/ if (log_level & G_LOG_LEVEL_ERROR)
163                 dialog=gnome_app_error(App,message);
164         else if (log_level & (G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING))
165                 dialog=gnome_app_warning(App,message);
166         else
167                 dialog=gnome_app_message(App,message);
168
169         gtk_window_set_modal(GTK_WINDOW(dialog),TRUE);
170         g_signal_connect((gpointer)dialog,"close",G_CALLBACK(gtk_main_quit),NULL);
171         gtk_main();
172         /* 'dialog' gets destroyed automatically */
173 }
174
175 static void ui_gnome_interactive(void)
176 {
177         gtk_main();
178         network_notify_hostip=NULL;
179         g_log_remove_handler(
180                         G_LOG_DOMAIN,   /* log_domain; "Captive" */
181                         ui_gnome_g_log_handler_handler_id);     /* handler_id */
182         network_detach();
183 }
184
185 /* of "ui-gnome-interface.h": */
186 GtkWidget *create_App(void);
187 /* of "ui-gnome-support.h": */
188 GtkWidget *lookup_widget(GtkWidget *widget,const gchar *widget_name);
189
190 gboolean ui_gnome_init(void)
191 {
192         App=GNOME_APP(create_App());
193
194         ButtonStart=GTK_BUTTON(lookup_widget(GTK_WIDGET(App),"ButtonStart"));
195         ButtonStop=GTK_BUTTON(lookup_widget(GTK_WIDGET(App),"ButtonStop"));
196         PortHBox=GTK_HBOX(lookup_widget(GTK_WIDGET(App),"PortHBox"));
197         AppBar=GNOME_APPBAR(lookup_widget(GTK_WIDGET(App),"AppBar"));
198         PortEntry=GTK_ENTRY(lookup_widget(GTK_WIDGET(App),"PortEntry"));
199         HostIPEntry=GTK_ENTRY(lookup_widget(GTK_WIDGET(App),"HostIPEntry"));
200
201         /* ui_gnome_g_log_handler() needs 'App'. */
202         ui_gnome_g_log_handler_handler_id=g_log_set_handler(
203                         G_LOG_DOMAIN,   /* log_domain; "Captive" */
204                         (G_LOG_LEVEL_MASK|G_LOG_FLAG_FATAL)&~(0
205                                         |G_LOG_LEVEL_MESSAGE
206                                         |G_LOG_LEVEL_INFO
207                                         |G_LOG_LEVEL_DEBUG),    /* log_levels */
208                         ui_gnome_g_log_handler, /* log_func */
209                         NULL);  /* user_data */
210
211         ui_gnome_network_notify_hostip(0);
212         gtk_entry_set_text(PortEntry,udpgate_printf_alloca("%d",(int)optarg_port));
213
214         gtk_widget_show_all(GTK_WIDGET(App));
215         g_timeout_add(
216                         DAEMON_CHECK_INTERVAL_MS,       /* interval */
217                         daemon_check_timeout_func,      /* function */
218                         NULL);  /* data; unused */
219
220         network_notify_hostip=ui_gnome_network_notify_hostip;
221
222         ui_interactive=ui_gnome_interactive;
223
224         return TRUE;
225 }