1 /* $Id$ */
2 /* Copyright (c) 2011-2015 Pierre Pronchery <khorben@defora.org> */
3 /* This file is part of DeforaOS Desktop Phone */
4 /* This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, version 3 of the License.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>. */
15 /* FIXME:
16  * - check if it resets the modem on "OK" (and if so, avoid it) */
17 
18 
19 
20 #include <stdlib.h>
21 #include <string.h>
22 #include <gtk/gtk.h>
23 #include <System.h>
24 #ifdef PROGNAME
25 # include <Desktop.h>
26 #endif
27 #include "Phone.h"
28 #include "../../config.h"
29 
30 #ifndef PREFIX
31 # define PREFIX		"/usr/local"
32 #endif
33 #ifndef SYSCONFDIR
34 # define SYSCONFDIR	PREFIX "/etc"
35 #endif
36 
37 
38 /* GPRS */
39 /* private */
40 /* types */
41 typedef struct _PhonePlugin
42 {
43 	PhonePluginHelper * helper;
44 	guint source;
45 	gboolean roaming;
46 	gboolean connected;
47 	size_t in;
48 	size_t out;
49 	size_t glin;
50 	size_t glout;
51 	char * _operator;
52 
53 	gboolean active;
54 	GtkWidget * window;
55 	GtkWidget * notebook;
56 	GtkWidget * attach;
57 	GtkWidget * apn;
58 	GtkWidget * username;
59 	GtkWidget * password;
60 #ifndef PROGNAME
61 	GtkWidget * defaults;
62 #endif
63 	GtkWidget * connect;
64 	GtkWidget * st_image;
65 	GtkWidget * st_label;
66 	GtkWidget * st_in;
67 	GtkWidget * st_out;
68 	GtkWidget * st_glin;
69 	GtkWidget * st_glout;
70 #if GTK_CHECK_VERSION(2, 10, 0)
71 	GtkWidget * systray;
72 	GtkStatusIcon * icon;
73 #endif
74 } GPRS;
75 
76 
77 /* prototypes */
78 /* plug-in */
79 static GPRS * _gprs_init(PhonePluginHelper * helper);
80 static void _gprs_destroy(GPRS * gprs);
81 static int _gprs_event(GPRS * gprs, PhoneEvent * event);
82 static void _gprs_settings(GPRS * gprs);
83 
84 /* accessors */
85 static void _gprs_set_connected(GPRS * gprs, gboolean connected,
86 		char const * message, size_t in, size_t out);
87 
88 /* useful */
89 static int _gprs_access_point(GPRS * gprs);
90 static int _gprs_connect(GPRS * gprs);
91 
92 static void _gprs_counters_load(GPRS * gprs);
93 static void _gprs_counters_save(GPRS * gprs);
94 
95 static int _gprs_disconnect(GPRS * gprs);
96 
97 static int _gprs_load_defaults(GPRS * gprs);
98 static int _gprs_load_operator(GPRS * gprs, char const * _operator);
99 
100 /* callbacks */
101 static void _gprs_on_activate(gpointer data);
102 static void _gprs_on_load_defaults(gpointer data);
103 static void _gprs_on_popup_menu(GtkStatusIcon * icon, guint button,
104 		guint time, gpointer data);
105 static gboolean _gprs_on_timeout(gpointer data);
106 
107 
108 /* public */
109 /* variables */
110 PhonePluginDefinition plugin =
111 {
112 	"Dial-up networking",
113 	"phone-gprs",
114 	NULL,
115 	_gprs_init,
116 	_gprs_destroy,
117 	_gprs_event,
118 	_gprs_settings
119 };
120 
121 
122 /* private */
123 /* functions */
124 /* plug-in */
125 /* gprs_init */
_gprs_init(PhonePluginHelper * helper)126 static GPRS * _gprs_init(PhonePluginHelper * helper)
127 {
128 	GPRS * gprs;
129 #if GTK_CHECK_VERSION(2, 10, 0)
130 	char const * p;
131 	gboolean active;
132 #endif
133 
134 	if((gprs = object_new(sizeof(*gprs))) == NULL)
135 		return NULL;
136 	gprs->helper = helper;
137 	gprs->source = 0;
138 	gprs->roaming = FALSE;
139 	gprs->connected = FALSE;
140 	gprs->in = 0;
141 	gprs->out = 0;
142 	gprs->glin = 0;
143 	gprs->glout = 0;
144 	gprs->_operator = NULL;
145 	gprs->active = FALSE;
146 	gprs->window = NULL;
147 #if GTK_CHECK_VERSION(2, 10, 0)
148 	gprs->icon = gtk_status_icon_new_from_icon_name("phone-gprs");
149 # if GTK_CHECK_VERSION(2, 16, 0)
150 	gtk_status_icon_set_tooltip_text(gprs->icon, "Not connected");
151 # endif
152 # if GTK_CHECK_VERSION(2, 18, 0)
153 	gtk_status_icon_set_title(gprs->icon, "Dial-up networking");
154 #  if GTK_CHECK_VERSION(2, 20, 0)
155 	gtk_status_icon_set_name(gprs->icon, "phone-gprs");
156 #  endif
157 # endif
158 	g_signal_connect_swapped(gprs->icon, "activate", G_CALLBACK(
159 				_gprs_on_activate), gprs);
160 	g_signal_connect(gprs->icon, "popup-menu", G_CALLBACK(
161 				_gprs_on_popup_menu), gprs);
162 	active = ((p = helper->config_get(helper->phone, "gprs", "systray"))
163 			!= NULL && strtoul(p, NULL, 10) != 0) ? TRUE : FALSE;
164 	gtk_status_icon_set_visible(gprs->icon, active);
165 #endif
166 	_gprs_counters_load(gprs);
167 	return gprs;
168 }
169 
170 
171 /* gprs_destroy */
_gprs_destroy(GPRS * gprs)172 static void _gprs_destroy(GPRS * gprs)
173 {
174 	free(gprs->_operator);
175 	_gprs_counters_save(gprs);
176 #if GTK_CHECK_VERSION(2, 10, 0)
177 	g_object_unref(gprs->icon);
178 #endif
179 	if(gprs->source != 0)
180 		g_source_remove(gprs->source);
181 	if(gprs->window != NULL)
182 		gtk_widget_destroy(gprs->window);
183 	object_delete(gprs);
184 }
185 
186 
187 /* gprs_event */
188 static int _gprs_event_modem(GPRS * gprs, ModemEvent * event);
189 static void _gprs_event_modem_operator(GPRS * gprs, char const * _operator);
190 
_gprs_event(GPRS * gprs,PhoneEvent * event)191 static int _gprs_event(GPRS * gprs, PhoneEvent * event)
192 {
193 	switch(event->type)
194 	{
195 		case PHONE_EVENT_TYPE_MODEM_EVENT:
196 			return _gprs_event_modem(gprs,
197 					event->modem_event.event);
198 		case PHONE_EVENT_TYPE_OFFLINE:
199 		case PHONE_EVENT_TYPE_UNAVAILABLE:
200 			gprs->roaming = FALSE;
201 			return 0;
202 		default: /* not relevant */
203 			return 0;
204 	}
205 }
206 
_gprs_event_modem(GPRS * gprs,ModemEvent * event)207 static int _gprs_event_modem(GPRS * gprs, ModemEvent * event)
208 {
209 	gboolean connected;
210 
211 	switch(event->type)
212 	{
213 		case MODEM_EVENT_TYPE_CONNECTION:
214 			connected = event->connection.connected;
215 			_gprs_set_connected(gprs, connected, NULL,
216 					event->connection.in,
217 					event->connection.out);
218 			break;
219 		case MODEM_EVENT_TYPE_REGISTRATION:
220 			/* operator */
221 			_gprs_event_modem_operator(gprs,
222 					event->registration._operator);
223 			/* roaming */
224 			gprs->roaming = event->registration.roaming;
225 			/* status */
226 			if(gprs->active != FALSE)
227 				break;
228 			if(event->registration.status
229 					!= MODEM_REGISTRATION_STATUS_REGISTERED)
230 				break;
231 			gprs->active = TRUE;
232 			/* FIXME optionally force GPRS registration */
233 			break;
234 		default:
235 			break;
236 	}
237 	return 0;
238 }
239 
_gprs_event_modem_operator(GPRS * gprs,char const * _operator)240 static void _gprs_event_modem_operator(GPRS * gprs, char const * _operator)
241 {
242 	PhonePluginHelper * helper = gprs->helper;
243 	char const * p;
244 
245 	free(gprs->_operator);
246 	gprs->_operator = (_operator != NULL) ? strdup(_operator) : NULL;
247 	if(gprs->window == NULL)
248 		return;
249 #ifndef PROGNAME
250 	gtk_widget_set_sensitive(gprs->defaults, (gprs->_operator != NULL)
251 			? TRUE : FALSE);
252 #endif
253 	/* FIXME also load the defaults when creating the window if relevant */
254 	if(((p = gtk_entry_get_text(GTK_ENTRY(gprs->apn))) == NULL
255 				|| strlen(p) == 0)
256 			&& ((p = gtk_entry_get_text(GTK_ENTRY(gprs->username)))
257 				== NULL || strlen(p) == 0)
258 			&& ((p = gtk_entry_get_text(GTK_ENTRY(gprs->password)))
259 				== NULL || strlen(p) == 0)
260 			&& helper->config_get(helper->phone, "gprs", "apn")
261 			== NULL
262 			&& helper->config_get(helper->phone, "gprs", "username")
263 			== NULL
264 			&& helper->config_get(helper->phone, "gprs", "password")
265 			== NULL)
266 		_gprs_load_defaults(gprs);
267 }
268 
269 
270 /* gprs_settings */
271 static GtkWidget * _settings_preferences(GPRS * gprs);
272 static GtkWidget * _settings_status(GPRS * gprs);
273 /* callbacks */
274 static void _settings_on_apply(gpointer data);
275 static void _settings_on_cancel(gpointer data);
276 static gboolean _settings_on_closex(gpointer data);
277 static void _settings_on_connect(gpointer data);
278 #ifdef PROGNAME
279 static void _settings_on_help(gpointer data);
280 #endif
281 static void _settings_on_ok(gpointer data);
282 static void _settings_on_reset(gpointer data);
283 
_gprs_settings(GPRS * gprs)284 static void _gprs_settings(GPRS * gprs)
285 {
286 	GtkWidget * vbox;
287 	GtkWidget * bbox;
288 	GtkWidget * widget;
289 
290 	if(gprs->window != NULL)
291 	{
292 		gtk_notebook_set_current_page(GTK_NOTEBOOK(gprs->notebook), 0);
293 		gtk_window_present(GTK_WINDOW(gprs->window));
294 		return;
295 	}
296 	gprs->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
297 	gtk_container_set_border_width(GTK_CONTAINER(gprs->window), 4);
298 	gtk_window_set_default_size(GTK_WINDOW(gprs->window), 200, 300);
299 #if GTK_CHECK_VERSION(2, 6, 0)
300 	gtk_window_set_icon_name(GTK_WINDOW(gprs->window), "phone-gprs");
301 #endif
302 	gtk_window_set_title(GTK_WINDOW(gprs->window), "Dial-up networking");
303 	g_signal_connect_swapped(gprs->window, "delete-event", G_CALLBACK(
304 				_settings_on_closex), gprs);
305 #if GTK_CHECK_VERSION(3, 0, 0)
306 	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
307 #else
308 	vbox = gtk_vbox_new(FALSE, 4);
309 #endif
310 	gprs->notebook = gtk_notebook_new();
311 	/* preferences */
312 	widget = _settings_preferences(gprs);
313 	gtk_notebook_append_page(GTK_NOTEBOOK(gprs->notebook), widget,
314 			gtk_label_new("Preferences"));
315 	/* status */
316 	widget = _settings_status(gprs);
317 	gtk_notebook_append_page(GTK_NOTEBOOK(gprs->notebook), widget,
318 			gtk_label_new("Status"));
319 	gtk_box_pack_start(GTK_BOX(vbox), gprs->notebook, TRUE, TRUE, 0);
320 	/* button box */
321 #if GTK_CHECK_VERSION(3, 0, 0)
322 	bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
323 #else
324 	bbox = gtk_hbutton_box_new();
325 #endif
326 	gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
327 	gtk_box_set_spacing(GTK_BOX(bbox), 4);
328 #ifdef PROGNAME
329 	widget = gtk_button_new_from_stock(GTK_STOCK_HELP);
330 	g_signal_connect_swapped(widget, "clicked", G_CALLBACK(
331 				_settings_on_help), gprs);
332 	gtk_container_add(GTK_CONTAINER(bbox), widget);
333 #endif
334 	widget = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
335 	g_signal_connect_swapped(widget, "clicked", G_CALLBACK(
336 				_settings_on_cancel), gprs);
337 	gtk_container_add(GTK_CONTAINER(bbox), widget);
338 	widget = gtk_button_new_from_stock(GTK_STOCK_OK);
339 	g_signal_connect_swapped(widget, "clicked", G_CALLBACK(_settings_on_ok),
340 			gprs);
341 	gtk_container_add(GTK_CONTAINER(bbox), widget);
342 	gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
343 	gtk_container_add(GTK_CONTAINER(gprs->window), vbox);
344 	_settings_on_cancel(gprs);
345 	_gprs_on_timeout(gprs);
346 	gtk_widget_show_all(gprs->window);
347 }
348 
_settings_preferences(GPRS * gprs)349 static GtkWidget * _settings_preferences(GPRS * gprs)
350 {
351 	GtkSizeGroup * group;
352 	GtkWidget * vbox;
353 	GtkWidget * hbox;
354 	GtkWidget * frame;
355 	GtkWidget * vbox2;
356 	GtkWidget * widget;
357 
358 #if GTK_CHECK_VERSION(3, 0, 0)
359 	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
360 #else
361 	vbox = gtk_vbox_new(FALSE, 4);
362 #endif
363 	/* attachment */
364 	gprs->attach = gtk_check_button_new_with_label(
365 			"Force GPRS registration");
366 	gtk_box_pack_start(GTK_BOX(vbox), gprs->attach, FALSE, TRUE, 0);
367 	/* systray */
368 	gprs->systray = gtk_check_button_new_with_label("Show in system tray");
369 	gtk_box_pack_start(GTK_BOX(vbox), gprs->systray, FALSE, TRUE, 0);
370 	/* credentials */
371 	frame = gtk_frame_new("Credentials");
372 #if GTK_CHECK_VERSION(3, 0, 0)
373 	vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
374 #else
375 	vbox2 = gtk_vbox_new(FALSE, 4);
376 #endif
377 	gtk_container_set_border_width(GTK_CONTAINER(vbox2), 4);
378 	group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
379 	/* access point */
380 #if GTK_CHECK_VERSION(3, 0, 0)
381 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
382 #else
383 	hbox = gtk_hbox_new(FALSE, 4);
384 #endif
385 	widget = gtk_label_new("Access point:");
386 #if GTK_CHECK_VERSION(3, 0, 0)
387 	g_object_set(widget, "halign", GTK_ALIGN_START, NULL);
388 #else
389 	gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.5);
390 #endif
391 	gtk_size_group_add_widget(group, widget);
392 	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
393 	gprs->apn = gtk_entry_new();
394 	gtk_box_pack_start(GTK_BOX(hbox), gprs->apn, TRUE, TRUE, 0);
395 	gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);
396 	/* username */
397 #if GTK_CHECK_VERSION(3, 0, 0)
398 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
399 #else
400 	hbox = gtk_hbox_new(FALSE, 4);
401 #endif
402 	widget = gtk_label_new("Username:");
403 #if GTK_CHECK_VERSION(3, 0, 0)
404 	g_object_set(widget, "halign", GTK_ALIGN_START, NULL);
405 #else
406 	gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.5);
407 #endif
408 	gtk_size_group_add_widget(group, widget);
409 	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
410 	gprs->username = gtk_entry_new();
411 	gtk_box_pack_start(GTK_BOX(hbox), gprs->username, TRUE, TRUE, 0);
412 	gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);
413 	/* password */
414 #if GTK_CHECK_VERSION(3, 0, 0)
415 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
416 #else
417 	hbox = gtk_hbox_new(FALSE, 4);
418 #endif
419 	widget = gtk_label_new("Password:");
420 #if GTK_CHECK_VERSION(3, 0, 0)
421 	g_object_set(widget, "halign", GTK_ALIGN_START, NULL);
422 #else
423 	gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.5);
424 #endif
425 	gtk_size_group_add_widget(group, widget);
426 	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
427 	gprs->password = gtk_entry_new();
428 	gtk_entry_set_visibility(GTK_ENTRY(gprs->password), FALSE);
429 	gtk_box_pack_start(GTK_BOX(hbox), gprs->password, TRUE, TRUE, 0);
430 	gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);
431 #ifndef PROGNAME
432 	/* defaults */
433 # if GTK_CHECK_VERSION(3, 0, 0)
434 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
435 # else
436 	hbox = gtk_hbox_new(FALSE, 4);
437 # endif
438 	gprs->defaults = gtk_button_new_with_label("Load defaults");
439 	gtk_widget_set_sensitive(gprs->defaults, (gprs->_operator != NULL)
440 			? TRUE : FALSE);
441 	g_signal_connect_swapped(gprs->defaults, "clicked", G_CALLBACK(
442 				_gprs_on_load_defaults), gprs);
443 	gtk_box_pack_end(GTK_BOX(hbox), gprs->defaults, FALSE, TRUE, 0);
444 	gtk_box_pack_end(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);
445 #endif
446 	gtk_container_add(GTK_CONTAINER(frame), vbox2);
447 	gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
448 	return vbox;
449 }
450 
_settings_status(GPRS * gprs)451 static GtkWidget * _settings_status(GPRS * gprs)
452 {
453 	GtkWidget * vbox;
454 	GtkWidget * hbox;
455 	GtkWidget * widget;
456 	GtkWidget * bbox;
457 
458 #if GTK_CHECK_VERSION(3, 0, 0)
459 	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
460 #else
461 	vbox = gtk_vbox_new(FALSE, 4);
462 #endif
463 	/* details */
464 	widget = gtk_frame_new("Details");
465 #if GTK_CHECK_VERSION(3, 0, 0)
466 	bbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
467 #else
468 	bbox = gtk_vbox_new(FALSE, 4);
469 #endif
470 	gtk_container_set_border_width(GTK_CONTAINER(bbox), 4);
471 #if GTK_CHECK_VERSION(3, 0, 0)
472 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
473 #else
474 	hbox = gtk_hbox_new(FALSE, 4);
475 #endif
476 	gprs->st_image = gtk_image_new_from_icon_name(GTK_STOCK_DISCONNECT,
477 			GTK_ICON_SIZE_BUTTON);
478 	gtk_box_pack_start(GTK_BOX(hbox), gprs->st_image, FALSE, TRUE, 0);
479 	gprs->st_label = gtk_label_new("Not connected");
480 #if GTK_CHECK_VERSION(3, 0, 0)
481 	g_object_set(gprs->st_label, "halign", GTK_ALIGN_START, NULL);
482 #else
483 	gtk_misc_set_alignment(GTK_MISC(gprs->st_label), 0.0, 0.5);
484 #endif
485 	gtk_box_pack_start(GTK_BOX(hbox), gprs->st_label, TRUE, TRUE, 0);
486 	gtk_box_pack_start(GTK_BOX(bbox), hbox, FALSE, TRUE, 0);
487 	gprs->st_in = gtk_label_new(NULL);
488 #if GTK_CHECK_VERSION(3, 0, 0)
489 	g_object_set(gprs->st_in, "halign", GTK_ALIGN_START, NULL);
490 #else
491 	gtk_misc_set_alignment(GTK_MISC(gprs->st_in), 0.0, 0.5);
492 #endif
493 	gtk_widget_set_no_show_all(gprs->st_in, TRUE);
494 	gtk_box_pack_start(GTK_BOX(bbox), gprs->st_in, FALSE, TRUE, 0);
495 	gprs->st_out = gtk_label_new(NULL);
496 #if GTK_CHECK_VERSION(3, 0, 0)
497 	g_object_set(gprs->st_out, "halign", GTK_ALIGN_START, NULL);
498 #else
499 	gtk_misc_set_alignment(GTK_MISC(gprs->st_out), 0.0, 0.5);
500 #endif
501 	gtk_widget_set_no_show_all(gprs->st_out, TRUE);
502 	gtk_box_pack_start(GTK_BOX(bbox), gprs->st_out, FALSE, TRUE, 0);
503 	gtk_container_add(GTK_CONTAINER(widget), bbox);
504 	gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, TRUE, 0);
505 	/* connect */
506 	gprs->connect = gtk_button_new_from_stock(GTK_STOCK_CONNECT);
507 	g_signal_connect_swapped(gprs->connect, "clicked", G_CALLBACK(
508 				_settings_on_connect), gprs);
509 	gtk_box_pack_start(GTK_BOX(vbox), gprs->connect, FALSE, TRUE, 0);
510 	/* counters */
511 	widget = gtk_frame_new("Counters");
512 #if GTK_CHECK_VERSION(3, 0, 0)
513 	hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
514 #else
515 	hbox = gtk_vbox_new(FALSE, 4);
516 #endif
517 	gtk_container_set_border_width(GTK_CONTAINER(hbox), 4);
518 	gprs->st_glin = gtk_label_new(NULL);
519 #if GTK_CHECK_VERSION(3, 0, 0)
520 	g_object_set(gprs->st_glin, "halign", GTK_ALIGN_START, NULL);
521 #else
522 	gtk_misc_set_alignment(GTK_MISC(gprs->st_glin), 0.0, 0.5);
523 #endif
524 	gtk_box_pack_start(GTK_BOX(hbox), gprs->st_glin, FALSE, TRUE, 0);
525 	gprs->st_glout = gtk_label_new(NULL);
526 #if GTK_CHECK_VERSION(3, 0, 0)
527 	g_object_set(gprs->st_glout, "halign", GTK_ALIGN_START, NULL);
528 #else
529 	gtk_misc_set_alignment(GTK_MISC(gprs->st_glout), 0.0, 0.5);
530 #endif
531 	gtk_box_pack_start(GTK_BOX(hbox), gprs->st_glout, FALSE, TRUE, 0);
532 	bbox = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
533 	g_signal_connect_swapped(bbox, "clicked", G_CALLBACK(
534 				_settings_on_reset), gprs);
535 	gtk_box_pack_start(GTK_BOX(hbox), bbox, FALSE, TRUE, 0);
536 	gtk_container_add(GTK_CONTAINER(widget), hbox);
537 	gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, TRUE, 0);
538 	return vbox;
539 }
540 
_settings_on_apply(gpointer data)541 static void _settings_on_apply(gpointer data)
542 {
543 	GPRS * gprs = data;
544 	PhonePluginHelper * helper = gprs->helper;
545 	gboolean active;
546 	char const * p;
547 
548 	active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gprs->attach));
549 	helper->config_set(helper->phone, "gprs", "attach", active ? "1" : "0");
550 	p = gtk_entry_get_text(GTK_ENTRY(gprs->apn));
551 	helper->config_set(helper->phone, "gprs", "apn", p);
552 	p = gtk_entry_get_text(GTK_ENTRY(gprs->username));
553 	helper->config_set(helper->phone, "gprs", "username", p);
554 	p = gtk_entry_get_text(GTK_ENTRY(gprs->password));
555 	helper->config_set(helper->phone, "gprs", "password", p);
556 #if GTK_CHECK_VERSION(2, 10, 0)
557 	active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gprs->systray));
558 	helper->config_set(helper->phone, "gprs", "systray", active
559 			? "1" : "0");
560 	gtk_status_icon_set_visible(gprs->icon, active);
561 #endif
562 	_gprs_access_point(gprs);
563 	_gprs_counters_save(gprs);
564 	gprs->active = FALSE;
565 }
566 
_settings_on_cancel(gpointer data)567 static void _settings_on_cancel(gpointer data)
568 {
569 	GPRS * gprs = data;
570 	PhonePluginHelper * helper = gprs->helper;
571 	char const * p;
572 	gboolean active;
573 
574 	gtk_widget_hide(gprs->window);
575 	active = ((p = helper->config_get(helper->phone, "gprs", "attach"))
576 			!= NULL && strtoul(p, NULL, 10) != 0) ? TRUE : FALSE;
577 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gprs->attach), active);
578 	if((p = helper->config_get(helper->phone, "gprs", "apn")) == NULL)
579 		p = "";
580 	gtk_entry_set_text(GTK_ENTRY(gprs->apn), p);
581 	if((p = helper->config_get(helper->phone, "gprs", "username")) == NULL)
582 		p = "";
583 	gtk_entry_set_text(GTK_ENTRY(gprs->username), p);
584 	if((p = helper->config_get(helper->phone, "gprs", "password")) == NULL)
585 		p = "";
586 	gtk_entry_set_text(GTK_ENTRY(gprs->password), p);
587 #if GTK_CHECK_VERSION(2, 10, 0)
588 	active = ((p = helper->config_get(helper->phone, "gprs", "systray"))
589 			!= NULL && strtoul(p, NULL, 10) != 0) ? TRUE : FALSE;
590 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gprs->systray), active);
591 #endif
592 	_gprs_set_connected(gprs, gprs->connected, NULL, gprs->in, gprs->out);
593 }
594 
_settings_on_closex(gpointer data)595 static gboolean _settings_on_closex(gpointer data)
596 {
597 	GPRS * gprs = data;
598 
599 	_settings_on_cancel(gprs);
600 	return TRUE;
601 }
602 
_settings_on_connect(gpointer data)603 static void _settings_on_connect(gpointer data)
604 {
605 	GPRS * gprs = data;
606 	int res;
607 
608 	_settings_on_apply(gprs);
609 	res = gprs->connected ? _gprs_disconnect(gprs) : _gprs_connect(gprs);
610 	if(res != 0)
611 		gprs->helper->error(gprs->helper->phone, error_get(NULL), 1);
612 }
613 
614 #ifdef PROGNAME
_settings_on_help(gpointer data)615 static void _settings_on_help(gpointer data)
616 {
617 	desktop_help_contents(PACKAGE, PROGNAME);
618 }
619 #endif
620 
_settings_on_ok(gpointer data)621 static void _settings_on_ok(gpointer data)
622 {
623 	GPRS * gprs = data;
624 
625 	gtk_widget_hide(gprs->window);
626 	_settings_on_apply(gprs);
627 }
628 
_settings_on_reset(gpointer data)629 static void _settings_on_reset(gpointer data)
630 {
631 	GPRS * gprs = data;
632 
633 	gprs->glin = 0;
634 	gprs->glout = 0;
635 	/* refresh the dialog box */
636 	_gprs_set_connected(gprs, gprs->connected, NULL, gprs->in, gprs->out);
637 	/* save in the configuration */
638 	_gprs_counters_save(gprs);
639 }
640 
641 
642 /* accessors */
643 /* gprs_set_connected */
_gprs_set_connected(GPRS * gprs,gboolean connected,char const * message,size_t in,size_t out)644 static void _gprs_set_connected(GPRS * gprs, gboolean connected,
645 		char const * message, size_t in, size_t out)
646 {
647 	char buf[64];
648 
649 	gprs->connected = connected;
650 	if(message == NULL)
651 		message = connected ? "Connected" : "Not connected";
652 	if(gprs->window == NULL)
653 		return;
654 	gtk_image_set_from_icon_name(GTK_IMAGE(gprs->st_image), connected
655 			? GTK_STOCK_CONNECT : GTK_STOCK_DISCONNECT,
656 			GTK_ICON_SIZE_BUTTON);
657 	gtk_label_set_text(GTK_LABEL(gprs->st_label), message);
658 	gtk_button_set_label(GTK_BUTTON(gprs->connect), connected
659 			? GTK_STOCK_DISCONNECT : GTK_STOCK_CONNECT);
660 	if(connected)
661 	{
662 		snprintf(buf, sizeof(buf), "Received: %lu kB (%lu kB/s)",
663 				(unsigned long)in / 1024,
664 				(unsigned long)(in - gprs->in) / 1024);
665 		gtk_label_set_text(GTK_LABEL(gprs->st_in), buf);
666 		snprintf(buf, sizeof(buf), "Sent: %lu kB (%lu kB/s)",
667 				(unsigned long)out / 1024,
668 				(unsigned long)(out - gprs->out) / 1024);
669 		gtk_label_set_text(GTK_LABEL(gprs->st_out), buf);
670 		gtk_widget_show(gprs->st_in);
671 		gtk_widget_show(gprs->st_out);
672 #if GTK_CHECK_VERSION(2, 16, 0)
673 		snprintf(buf, sizeof(buf), "%s\nReceived: %lu kB\nSent: %lu kB",
674 				message, (unsigned long)in / 1024,
675 				(unsigned long)out / 1024);
676 		gtk_status_icon_set_tooltip_text(gprs->icon, buf);
677 #endif
678 		gprs->in = in;
679 		gprs->out = out;
680 		if(gprs->source == 0)
681 			gprs->source = g_timeout_add(1000, _gprs_on_timeout,
682 					gprs);
683 	}
684 	else
685 	{
686 		if(gprs->source != 0)
687 			g_source_remove(gprs->source);
688 		gprs->source = 0;
689 		gtk_widget_hide(gprs->st_in);
690 		gtk_widget_hide(gprs->st_out);
691 #if GTK_CHECK_VERSION(2, 16, 0)
692 		gtk_status_icon_set_tooltip_text(gprs->icon, message);
693 #endif
694 		/* add the last known data to the global counters */
695 		gprs->glin += gprs->in;
696 		gprs->glout += gprs->out;
697 		/* save in the configuration */
698 		_gprs_counters_save(gprs);
699 		/* reset the known data */
700 		gprs->in = 0;
701 		gprs->out = 0;
702 	}
703 	/* counters */
704 	snprintf(buf, sizeof(buf), "Received: %lu kB", (gprs->glin + in)
705 			/ 1024);
706 	gtk_label_set_text(GTK_LABEL(gprs->st_glin), buf);
707 	snprintf(buf, sizeof(buf), "Sent: %lu kB", (gprs->glout + out) / 1024);
708 	gtk_label_set_text(GTK_LABEL(gprs->st_glout), buf);
709 }
710 
711 
712 /* useful */
713 /* gprs_access_point */
_gprs_access_point(GPRS * gprs)714 static int _gprs_access_point(GPRS * gprs)
715 {
716 	int ret = 0;
717 	PhonePluginHelper * helper = gprs->helper;
718 	char const * p;
719 	ModemRequest request;
720 
721 	if((p = helper->config_get(helper->phone, "gprs", "apn")) == NULL)
722 		return 0;
723 	memset(&request, 0, sizeof(request));
724 	request.type = MODEM_REQUEST_AUTHENTICATE;
725 	/* set the access point */
726 	request.authenticate.name = "APN";
727 	request.authenticate.username = "IP";
728 	request.authenticate.password = p;
729 	ret |= helper->request(helper->phone, &request);
730 	/* set the credentials */
731 	request.authenticate.name = "GPRS";
732 	p = helper->config_get(helper->phone, "gprs", "username");
733 	request.authenticate.username = p;
734 	p = helper->config_get(helper->phone, "gprs", "password");
735 	request.authenticate.password = p;
736 	ret |= helper->request(helper->phone, &request);
737 	return ret;
738 }
739 
740 
741 /* gprs_connect */
_gprs_connect(GPRS * gprs)742 static int _gprs_connect(GPRS * gprs)
743 {
744 	GtkDialogFlags flags = GTK_DIALOG_MODAL
745 		| GTK_DIALOG_DESTROY_WITH_PARENT;
746 	char const message[] = "You are currently roaming, and additional"
747 		" charges are therefore likely to apply.\n"
748 		"Do you really want to connect?";
749 	GtkWidget * widget;
750 	int res;
751 	ModemRequest request;
752 
753 	if(_gprs_access_point(gprs) != 0)
754 		return -1;
755 	if(gprs->roaming)
756 	{
757 		widget = gtk_message_dialog_new(GTK_WINDOW(gprs->window), flags,
758 				GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO,
759 #if GTK_CHECK_VERSION(2, 6, 0)
760 				"%s", "Warning");
761 		gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(
762 					widget),
763 #endif
764 				"%s", message);
765 		gtk_window_set_title(GTK_WINDOW(widget), "Warning");
766 		res = gtk_dialog_run(GTK_DIALOG(widget));
767 		gtk_widget_destroy(widget);
768 		if(res != GTK_RESPONSE_YES)
769 			return 0;
770 	}
771 	_gprs_set_connected(gprs, TRUE, "Connecting...", 0, 0);
772 	memset(&request, 0, sizeof(request));
773 	request.type = MODEM_REQUEST_CALL;
774 	request.call.call_type = MODEM_CALL_TYPE_DATA;
775 	request.call.number = "*99***1#"; /* XXX specific to GSM/GPRS */
776 	if(gprs->helper->request(gprs->helper->phone, &request) != 0)
777 		return -gprs->helper->error(gprs->helper->phone,
778 				error_get(NULL), 1);
779 	return 0;
780 }
781 
782 
783 /* gprs_counters_load */
_gprs_counters_load(GPRS * gprs)784 static void _gprs_counters_load(GPRS * gprs)
785 {
786 	PhonePluginHelper * helper = gprs->helper;
787 	char const * p;
788 
789 	gprs->glin = 0;
790 	if((p = helper->config_get(helper->phone, "gprs", "in")) != NULL)
791 		gprs->glin = strtol(p, NULL, 10);
792 	gprs->glout = 0;
793 	if((p = helper->config_get(helper->phone, "gprs", "out")) != NULL)
794 		gprs->glout = strtol(p, NULL, 10);
795 }
796 
797 
798 /* gprs_counters_save */
_gprs_counters_save(GPRS * gprs)799 static void _gprs_counters_save(GPRS * gprs)
800 {
801 	PhonePluginHelper * helper = gprs->helper;
802 	char buf[16];
803 
804 	snprintf(buf, sizeof(buf), "%lu", gprs->glin);
805 	helper->config_set(helper->phone, "gprs", "in", buf);
806 	snprintf(buf, sizeof(buf), "%lu", gprs->glout);
807 	helper->config_set(helper->phone, "gprs", "out", buf);
808 }
809 
810 
811 /* gprs_disconnect */
_gprs_disconnect(GPRS * gprs)812 static int _gprs_disconnect(GPRS * gprs)
813 {
814 	ModemRequest request;
815 
816 	if(_gprs_access_point(gprs) != 0)
817 		return -1;
818 	_gprs_set_connected(gprs, TRUE, "Disconnecting...", 0, 0);
819 	memset(&request, 0, sizeof(request));
820 	request.type = MODEM_REQUEST_CALL_HANGUP;
821 	return gprs->helper->request(gprs->helper->phone, &request);
822 }
823 
824 
825 /* gprs_load_defaults */
_gprs_load_defaults(GPRS * gprs)826 static int _gprs_load_defaults(GPRS * gprs)
827 {
828 	return _gprs_load_operator(gprs, gprs->_operator);
829 }
830 
831 
832 /* gprs_load_operator */
_gprs_load_operator(GPRS * gprs,char const * _operator)833 static int _gprs_load_operator(GPRS * gprs, char const * _operator)
834 {
835 	Config * config;
836 	String const * p;
837 
838 	if((config = config_new()) == NULL)
839 		return -1;
840 	if(config_load(config, SYSCONFDIR "/" PACKAGE "/gprs.conf") != 0
841 			|| (p = config_get(config, _operator, "apn")) == NULL)
842 	{
843 		config_delete(config);
844 		return -1;
845 	}
846 	gtk_entry_set_text(GTK_ENTRY(gprs->apn), p);
847 	if((p = config_get(config, _operator, "username")) == NULL)
848 		p = "";
849 	gtk_entry_set_text(GTK_ENTRY(gprs->username), p);
850 	if((p = config_get(config, _operator, "password")) == NULL)
851 		p = "";
852 	gtk_entry_set_text(GTK_ENTRY(gprs->password), p);
853 	config_delete(config);
854 	return 0;
855 }
856 
857 
858 /* callbacks */
859 /* gprs_on_activate */
_gprs_on_activate(gpointer data)860 static void _gprs_on_activate(gpointer data)
861 {
862 	GPRS * gprs = data;
863 
864 	_gprs_settings(gprs);
865 	gtk_notebook_set_current_page(GTK_NOTEBOOK(gprs->notebook), 1);
866 	gtk_window_present(GTK_WINDOW(gprs->window));
867 }
868 
869 
870 /* gprs_on_load_defaults */
_gprs_on_load_defaults(gpointer data)871 static void _gprs_on_load_defaults(gpointer data)
872 {
873 	GPRS * gprs = data;
874 	GtkWidget * widget;
875 	const GtkDialogFlags flags = GTK_DIALOG_MODAL
876 		| GTK_DIALOG_DESTROY_WITH_PARENT;
877 
878 	if(_gprs_load_defaults(gprs) == 0)
879 		return;
880 	widget = gtk_message_dialog_new(GTK_WINDOW(gprs->window),
881 			flags, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
882 #if GTK_CHECK_VERSION(2, 6, 0)
883 			"%s", "Error");
884 		gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(
885 					widget),
886 #endif
887 			"%s", "No defaults known for the current operator");
888 	gtk_dialog_run(GTK_DIALOG(widget));
889 	gtk_widget_destroy(widget);
890 }
891 
892 
893 /* gprs_on_popup_menu */
_gprs_on_popup_menu(GtkStatusIcon * icon,guint button,guint time,gpointer data)894 static void _gprs_on_popup_menu(GtkStatusIcon * icon, guint button,
895 		guint time, gpointer data)
896 {
897 	GPRS * gprs = data;
898 	GtkWidget * menu;
899 	GtkWidget * menuitem;
900 	GtkWidget * image;
901 
902 	menu = gtk_menu_new();
903 	/* status */
904 	menuitem = gtk_image_menu_item_new_with_mnemonic("_Status");
905 	g_signal_connect_swapped(menuitem, "activate", G_CALLBACK(
906 				_gprs_on_activate), gprs);
907 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
908 	menuitem = gtk_separator_menu_item_new();
909 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
910 	/* connection */
911 	menuitem = gtk_image_menu_item_new_with_mnemonic(gprs->connected
912 			? "_Disconnect" : "_Connect");
913 	image = gtk_image_new_from_stock(gprs->connected ? GTK_STOCK_DISCONNECT
914 			: GTK_STOCK_CONNECT, GTK_ICON_SIZE_MENU);
915 	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
916 	g_signal_connect_swapped(menuitem, "activate", G_CALLBACK(
917 				gprs->connected ? _gprs_disconnect
918 				: _gprs_connect), gprs);
919 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
920 	menuitem = gtk_separator_menu_item_new();
921 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
922 	/* preferences */
923 	menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES,
924 			NULL);
925 	g_signal_connect_swapped(menuitem, "activate", G_CALLBACK(
926 				_gprs_settings), gprs);
927 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
928 #ifdef PROGNAME
929 	menuitem = gtk_separator_menu_item_new();
930 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
931 	/* quit */
932 	menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
933 	g_signal_connect(menuitem, "activate", G_CALLBACK(gtk_main_quit), NULL);
934 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
935 #endif
936 	gtk_widget_show_all(menu);
937 	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, time);
938 }
939 
940 
941 /* gprs_on_timeout */
_gprs_on_timeout(gpointer data)942 static gboolean _gprs_on_timeout(gpointer data)
943 {
944 	GPRS * gprs = data;
945 
946 	gprs->helper->trigger(gprs->helper->phone, MODEM_EVENT_TYPE_CONNECTION);
947 	return TRUE;
948 }
949