1 /*
2  * acpi_notifier -- for Claws Mail
3  *
4  * Copyright (C) 2005 Colin Leroy <colin@colino.net>
5  *
6  * Sylpheed is a GTK+ based, lightweight, and fast e-mail client
7  * Copyright (C) 1999-2005 Hiroyuki Yamamoto and the Claws Mail Team
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #include "claws-features.h"
27 #endif
28 
29 #include <glib.h>
30 #include <glib/gi18n.h>
31 
32 #include <string.h>
33 
34 #include <glib.h>
35 #include <gtk/gtk.h>
36 
37 #include "defs.h"
38 #include "claws.h"
39 #include "version.h"
40 #include "prefs.h"
41 #include "prefs_gtk.h"
42 #include "main.h"
43 #include "menu.h"
44 #include "hooks.h"
45 #include "plugin.h"
46 #include "alertpanel.h"
47 #include "utils.h"
48 #include "folder_item_prefs.h"
49 #include "gtkcmoptionmenu.h"
50 #include "file-utils.h"
51 
52 #define PREFS_BLOCK_NAME "AcpiNotifier"
53 #define PLUGIN_NAME _("Acpi Notifier")
54 
55 typedef struct _PredefinedAcpis {
56 	gchar *name;
57 	gchar *on_param;
58 	gchar *off_param;
59 	gchar *file_path;
60 	gboolean is_program;
61 	gchar *help;
62 } PredefinedAcpis;
63 
64 /**
65  * Add your implementation here (and send me the patch!)
66  */
67 char *acpi_help[] = {
68 	"",
69 	N_("Make sure that the kernel module 'acerhk' is loaded.\n"
70 	    "You can get it from http://www.cakey.de/acerhk/"),
71 	N_("Make sure that the kernel module 'acer_acpi' is loaded.\n"
72 	    "You can get it from http://code.google.com/p/aceracpi/"),
73 	N_("Make sure that the kernel module 'asus_laptop' is loaded."),
74 	N_("Make sure that the kernel module 'asus_acpi' is loaded."),
75 	N_("Make sure that the kernel module 'ibm_acpi' is loaded."),
76 	N_("Make sure that you have apanelc installed.\n"
77 	    "You can get it from http://apanel.sourceforge.net/"),
78 	NULL
79 };
80 PredefinedAcpis known_implementations[] = {
81 	{"Other file", "", "", "", FALSE, NULL},
82 
83 	{"ACER (acerhk)", "1", "0", "/proc/driver/acerhk/led", FALSE, NULL},
84 
85 	{"ACER (acer_acpi)", "1", "0", "/proc/acpi/acer/mailled", FALSE, NULL},
86 
87 	{"ASUS (asus_laptop)", "1", "0", "/sys/class/leds/asus:mail/brightness", FALSE, NULL},
88 
89 	{"ASUS (asus_acpi)", "1", "0", "/proc/acpi/asus/mled", FALSE, NULL},
90 
91 	{"IBM (ibm_acpi)", "7 on", "7 off", "/proc/acpi/ibm/led", FALSE, NULL},
92 
93 	{"Lenovo (tp_smapi)", "on", "off", "/proc/acpi/ibm/light", FALSE, NULL},
94 
95 	{"Fujitsu (apanel)", "led on", "led off", "apanelc", TRUE, NULL},
96 
97 	{NULL, NULL, NULL, NULL, FALSE, NULL}
98 };
99 
100 static gulong folder_hook_id = HOOK_NONE;
101 static gulong alertpanel_hook_id = HOOK_NONE;
102 
103 struct AcpiNotifierPage
104 {
105 	PrefsPage page;
106 
107 	GtkWidget *no_mail_off_btn;
108 	GtkWidget *no_mail_blink_btn;
109 	GtkWidget *no_mail_on_btn;
110 	GtkWidget *unread_mail_off_btn;
111 	GtkWidget *unread_mail_blink_btn;
112 	GtkWidget *unread_mail_on_btn;
113 	GtkWidget *new_mail_off_btn;
114 	GtkWidget *new_mail_blink_btn;
115 	GtkWidget *new_mail_on_btn;
116 	GtkWidget *default_implementations_optmenu;
117 	GtkWidget *on_value_entry;
118 	GtkWidget *off_value_entry;
119 	GtkWidget *file_entry;
120 	GtkWidget *hbox_acpi_file;
121 	GtkWidget *hbox_acpi_values;
122 	GtkWidget *warning_label;
123 	GtkWidget *warning_box;
124 	GtkWidget *blink_on_err_chkbtn;
125 };
126 
127 typedef struct _AcpiNotifierPrefs AcpiNotifierPrefs;
128 
129 struct _AcpiNotifierPrefs
130 {
131 	gint		 no_mail_action;
132 	gint		 unread_mail_action;
133 	gint		 new_mail_action;
134 	gboolean	 blink_on_err;
135 	gchar 		*on_param;
136 	gchar 		*off_param;
137 	gchar 		*file_path;
138 };
139 
140 AcpiNotifierPrefs acpiprefs;
141 
142 static struct AcpiNotifierPage acpi_prefs_page;
143 
144 enum {
145 	OFF = 0,
146 	BLINK,
147 	ON
148 } BlinkType;
149 
150 static PrefParam param[] = {
151 	{"no_mail_action", "0", &acpiprefs.no_mail_action, P_INT,
152 	 NULL, NULL, NULL},
153 	{"unread_mail_action", "0", &acpiprefs.unread_mail_action, P_INT,
154 	 NULL, NULL, NULL},
155 	{"new_mail_action", "1", &acpiprefs.new_mail_action, P_INT,
156 	 NULL, NULL, NULL},
157 	{"blink_on_err", "TRUE", &acpiprefs.blink_on_err, P_BOOL,
158 	 NULL, NULL, NULL},
159 	{"on_param", NULL, &acpiprefs.on_param, P_STRING,
160 	 NULL, NULL, NULL},
161 	{"off_param", NULL, &acpiprefs.off_param, P_STRING,
162 	 NULL, NULL, NULL},
163 	{"file_path", NULL, &acpiprefs.file_path, P_STRING,
164 	 NULL, NULL, NULL},
165 	{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
166 };
167 
check_impl(const gchar * filepath)168 static gboolean check_impl (const gchar *filepath)
169 {
170 	int i;
171 	for (i = 0; known_implementations[i].name != NULL; i++) {
172 		if (strcmp(known_implementations[i].file_path, filepath))
173 			continue;
174 		if (!known_implementations[i].is_program)
175 			return is_file_exist(filepath);
176 		else {
177 			gchar *cmd = g_strdup_printf("which %s", filepath);
178 			int found = system(cmd);
179 			g_free(cmd);
180 			return (found == 0);
181 		}
182 	}
183 	return is_file_exist(filepath);
184 }
185 
is_program(const gchar * filepath)186 static gboolean is_program (const gchar *filepath)
187 {
188 	int i;
189 	for (i = 0; known_implementations[i].name != NULL; i++) {
190 		if (strcmp(known_implementations[i].file_path, filepath))
191 			continue;
192 		return known_implementations[i].is_program;
193 	}
194 	return FALSE;
195 }
196 
show_error(struct AcpiNotifierPage * page,const gchar * filepath)197 static void show_error (struct AcpiNotifierPage *page, const gchar *filepath)
198 {
199 	int i;
200 	if (!filepath) {
201 		gtk_widget_hide(page->warning_box);
202 		return;
203 	}
204 	for (i = 0; known_implementations[i].name != NULL; i++) {
205 		if (strcmp(known_implementations[i].file_path, filepath))
206 			continue;
207 		if (known_implementations[i].help) {
208 			gchar *tmp = g_strdup_printf("%s\n%s",
209 					_("Control file doesn't exist."),
210 					known_implementations[i].help);
211 			gtk_label_set_text(GTK_LABEL(page->warning_label), tmp);
212 			g_free(tmp);
213 		} else {
214 			gtk_label_set_text(GTK_LABEL(page->warning_label),
215 				_("Control file doesn't exist."));
216 		}
217 		gtk_widget_show_all(page->warning_box);
218 		return;
219 	}
220 }
221 
type_activated(GtkMenuItem * menuitem,gpointer data)222 static void type_activated(GtkMenuItem *menuitem, gpointer data)
223 {
224 	GtkWidget *menu, *item;
225 	struct AcpiNotifierPage *page = (struct AcpiNotifierPage *)data;
226 	gint selected;
227 
228 	if (page->file_entry == NULL)
229 		return;
230 
231 	menu = gtk_cmoption_menu_get_menu(
232 		GTK_CMOPTION_MENU(page->default_implementations_optmenu));
233 	item = gtk_menu_get_active(GTK_MENU(menu));
234 	selected = GPOINTER_TO_INT
235 		(g_object_get_data(G_OBJECT(item), MENU_VAL_ID));
236 
237 	if (selected != 0) {
238 		gtk_widget_hide(page->hbox_acpi_file);
239 		gtk_widget_hide(page->hbox_acpi_values);
240 		gtk_entry_set_text(GTK_ENTRY(page->file_entry),
241 			known_implementations[selected].file_path);
242 		gtk_entry_set_text(GTK_ENTRY(page->on_value_entry),
243 			known_implementations[selected].on_param);
244 		gtk_entry_set_text(GTK_ENTRY(page->off_value_entry),
245 			known_implementations[selected].off_param);
246 		if (!check_impl(known_implementations[selected].file_path))
247 			show_error(page, known_implementations[selected].file_path);
248 		else
249 			show_error(page, NULL);
250 	} else {
251 		gtk_widget_show_all(page->hbox_acpi_file);
252 		gtk_widget_show_all(page->hbox_acpi_values);
253 	}
254 }
file_entry_changed(GtkWidget * entry,gpointer data)255 static void file_entry_changed (GtkWidget *entry, gpointer data)
256 {
257 	struct AcpiNotifierPage *page = (struct AcpiNotifierPage *)data;
258 	if (!page->warning_box)
259 		return;
260 
261 	if (!check_impl(gtk_entry_get_text(GTK_ENTRY(entry))))
262 		show_error(page, gtk_entry_get_text(GTK_ENTRY(entry)));
263 	else
264 		show_error(page, NULL);
265 }
266 
acpi_prefs_create_widget_func(PrefsPage * _page,GtkWindow * window,gpointer data)267 static void acpi_prefs_create_widget_func(PrefsPage * _page,
268 					   GtkWindow * window,
269 					   gpointer data)
270 {
271 	struct AcpiNotifierPage *page = (struct AcpiNotifierPage *) _page;
272 
273 	GtkWidget *vbox;
274 	GtkWidget *hbox;
275 	GtkWidget *hbox_acpi_file;
276 	GtkWidget *hbox_acpi_values;
277 	GtkWidget *start_label;
278 	GtkWidget *no_mail_label;
279 	GtkWidget *no_mail_off_btn;
280 	GtkWidget *no_mail_blink_btn;
281 	GtkWidget *no_mail_on_btn;
282 	GtkWidget *unread_mail_label;
283 	GtkWidget *unread_mail_off_btn;
284 	GtkWidget *unread_mail_blink_btn;
285 	GtkWidget *unread_mail_on_btn;
286 	GtkWidget *new_mail_label;
287 	GtkWidget *new_mail_off_btn;
288 	GtkWidget *new_mail_blink_btn;
289 	GtkWidget *new_mail_on_btn;
290 	GtkWidget *default_implementations_optmenu;
291 	GtkWidget *default_implementations_menu;
292 	GtkWidget *on_value_entry;
293 	GtkWidget *off_value_entry;
294 	GtkWidget *file_entry;
295 	GtkWidget *menuitem;
296 	GtkWidget *warning_label;
297 	GtkWidget *warning_box;
298 	GtkWidget *image;
299 	GtkWidget *blink_on_err_chkbtn;
300 
301 	int i;
302 	int found = 0;
303 
304 	vbox = gtk_vbox_new(FALSE, 6);
305 	gtk_container_set_border_width (GTK_CONTAINER (vbox), VBOX_BORDER);
306 
307 	no_mail_label = gtk_label_new(_(" : no new or unread mail"));
308 	unread_mail_label = gtk_label_new(_(" : unread mail"));
309 	new_mail_label = gtk_label_new(_(" : new mail"));
310 
311 	no_mail_off_btn = gtk_radio_button_new_with_label(NULL, _("off"));
312 	no_mail_blink_btn = gtk_radio_button_new_with_label_from_widget(
313 		GTK_RADIO_BUTTON(no_mail_off_btn), _("blinking"));
314 	no_mail_on_btn = gtk_radio_button_new_with_label_from_widget(
315 		GTK_RADIO_BUTTON(no_mail_off_btn), _("on"));
316 
317 	unread_mail_off_btn = gtk_radio_button_new_with_label(NULL, _("off"));
318 	unread_mail_blink_btn = gtk_radio_button_new_with_label_from_widget(
319 		GTK_RADIO_BUTTON(unread_mail_off_btn), _("blinking"));
320 	unread_mail_on_btn = gtk_radio_button_new_with_label_from_widget(
321 		GTK_RADIO_BUTTON(unread_mail_off_btn), _("on"));
322 
323 	new_mail_off_btn = gtk_radio_button_new_with_label(NULL, _("off"));
324 	new_mail_blink_btn = gtk_radio_button_new_with_label_from_widget(
325 		GTK_RADIO_BUTTON(new_mail_off_btn), _("blinking"));
326 	new_mail_on_btn = gtk_radio_button_new_with_label_from_widget(
327 		GTK_RADIO_BUTTON(new_mail_off_btn), _("on"));
328 
329 	on_value_entry = gtk_entry_new();
330 	off_value_entry = gtk_entry_new();
331 	file_entry = gtk_entry_new();
332 	gtk_widget_set_size_request(on_value_entry, 40, -1);
333 	gtk_widget_set_size_request(off_value_entry, 40, -1);
334 
335 	default_implementations_optmenu = gtk_cmoption_menu_new ();
336 	default_implementations_menu = gtk_menu_new();
337         gtk_cmoption_menu_set_menu (
338 			GTK_CMOPTION_MENU(default_implementations_optmenu),
339 			default_implementations_menu);
340 	for (i = 0; known_implementations[i].name != NULL; i++) {
341 		MENUITEM_ADD (default_implementations_menu,
342 				menuitem, known_implementations[i].name, i);
343                 g_signal_connect(G_OBJECT(menuitem), "activate",
344                                  G_CALLBACK(type_activated),
345                                  page);
346 	}
347 
348 	hbox = gtk_hbox_new(FALSE, 6);
349 	start_label = gtk_label_new(_("LED "));
350 	gtk_box_pack_start(GTK_BOX(hbox), start_label, FALSE, FALSE, 0);
351 	gtk_box_pack_start(GTK_BOX(hbox), no_mail_off_btn, FALSE, FALSE, 0);
352 	gtk_box_pack_start(GTK_BOX(hbox), no_mail_blink_btn, FALSE, FALSE, 0);
353 	gtk_box_pack_start(GTK_BOX(hbox), no_mail_on_btn, FALSE, FALSE, 0);
354 	gtk_box_pack_start(GTK_BOX(hbox), no_mail_label, FALSE, FALSE, 0);
355 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
356 
357 	hbox = gtk_hbox_new(FALSE, 6);
358 	start_label = gtk_label_new(_("LED "));
359 	gtk_box_pack_start(GTK_BOX(hbox),
360 			start_label, FALSE, FALSE, 0);
361 	gtk_box_pack_start(GTK_BOX(hbox),
362 			unread_mail_off_btn, FALSE, FALSE, 0);
363 	gtk_box_pack_start(GTK_BOX(hbox),
364 			unread_mail_blink_btn, FALSE, FALSE, 0);
365 	gtk_box_pack_start(GTK_BOX(hbox),
366 			unread_mail_on_btn, FALSE, FALSE, 0);
367 	gtk_box_pack_start(GTK_BOX(hbox),
368 			unread_mail_label, FALSE, FALSE, 0);
369 	gtk_box_pack_start(GTK_BOX(vbox),
370 			hbox, FALSE, FALSE, 0);
371 
372 	hbox = gtk_hbox_new(FALSE, 6);
373 	start_label = gtk_label_new(_("LED "));
374 	gtk_box_pack_start(GTK_BOX(hbox),
375 			start_label, FALSE, FALSE, 0);
376 	gtk_box_pack_start(GTK_BOX(hbox),
377 			new_mail_off_btn, FALSE, FALSE, 0);
378 	gtk_box_pack_start(GTK_BOX(hbox),
379 			new_mail_blink_btn, FALSE, FALSE, 0);
380 	gtk_box_pack_start(GTK_BOX(hbox),
381 			new_mail_on_btn, FALSE, FALSE, 0);
382 	gtk_box_pack_start(GTK_BOX(hbox),
383 			new_mail_label, FALSE, FALSE, 0);
384 	gtk_box_pack_start(GTK_BOX(vbox),
385 			hbox, FALSE, FALSE, 0);
386 
387 	hbox = gtk_hbox_new(FALSE, 6);
388 	start_label = gtk_label_new(_("ACPI type: "));
389 	gtk_box_pack_start(GTK_BOX(hbox),
390 			start_label, FALSE, FALSE, 0);
391 	gtk_box_pack_start(GTK_BOX(hbox),
392 			default_implementations_optmenu, FALSE, FALSE, 0);
393 	gtk_box_pack_start(GTK_BOX(vbox),
394 			hbox, FALSE, FALSE, 0);
395 
396 	hbox_acpi_file = gtk_hbox_new(FALSE, 6);
397 	start_label = gtk_label_new(_("ACPI file: "));
398 	gtk_box_pack_start(GTK_BOX(hbox_acpi_file),
399 			start_label, FALSE, FALSE, 0);
400 	gtk_box_pack_start(GTK_BOX(hbox_acpi_file),
401 			file_entry, FALSE, FALSE, 0);
402 	gtk_box_pack_start(GTK_BOX(vbox),
403 			hbox_acpi_file, FALSE, FALSE, 0);
404         g_signal_connect(G_OBJECT(file_entry), "changed",
405                          G_CALLBACK(file_entry_changed), page);
406 
407 	hbox_acpi_values = gtk_hbox_new(FALSE, 6);
408 	start_label = gtk_label_new(_("values - On: "));
409 	gtk_box_pack_start(GTK_BOX(hbox_acpi_values),
410 			start_label, FALSE, FALSE, 0);
411 	gtk_box_pack_start(GTK_BOX(hbox_acpi_values),
412 			on_value_entry, FALSE, FALSE, 0);
413 	start_label = gtk_label_new(_(" - Off: "));
414 	gtk_box_pack_start(GTK_BOX(hbox_acpi_values),
415 			start_label, FALSE, FALSE, 0);
416 	gtk_box_pack_start(GTK_BOX(hbox_acpi_values),
417 			off_value_entry, FALSE, FALSE, 0);
418 	gtk_box_pack_start(GTK_BOX(vbox),
419 			hbox_acpi_values, FALSE, FALSE, 0);
420 
421 	warning_box = gtk_hbox_new(FALSE, 6);
422 
423 	image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING,
424 			GTK_ICON_SIZE_SMALL_TOOLBAR);
425 	gtk_box_pack_start(GTK_BOX(warning_box), image, FALSE, FALSE, 0);
426 	warning_label = gtk_label_new(
427 			_("Control file doesn't exist."));
428 	gtk_box_pack_start(GTK_BOX(warning_box), warning_label, FALSE, FALSE, 0);
429 	gtk_box_pack_start(GTK_BOX(vbox), warning_box, FALSE, FALSE, 0);
430 
431 	gtk_widget_show_all(vbox);
432 	gtk_widget_hide(warning_box);
433 
434 	blink_on_err_chkbtn = gtk_check_button_new_with_label(
435 		_("Blink when user interaction is required"));
436 	gtk_box_pack_start(GTK_BOX(vbox), blink_on_err_chkbtn, FALSE, FALSE, 0);
437 	gtk_toggle_button_set_active(
438 			GTK_TOGGLE_BUTTON(blink_on_err_chkbtn),
439 			acpiprefs.blink_on_err);
440 	gtk_widget_show(blink_on_err_chkbtn);
441 
442 	switch (acpiprefs.no_mail_action) {
443 	case OFF:
444 		gtk_toggle_button_set_active(
445 			GTK_TOGGLE_BUTTON(no_mail_off_btn), TRUE);
446 		break;
447 	case BLINK:
448 		gtk_toggle_button_set_active(
449 			GTK_TOGGLE_BUTTON(no_mail_blink_btn), TRUE);
450 		break;
451 	case ON:
452 		gtk_toggle_button_set_active(
453 			GTK_TOGGLE_BUTTON(no_mail_on_btn), TRUE);
454 		break;
455 	}
456 
457 	switch (acpiprefs.unread_mail_action) {
458 	case OFF:
459 		gtk_toggle_button_set_active(
460 			GTK_TOGGLE_BUTTON(unread_mail_off_btn), TRUE);
461 		break;
462 	case BLINK:
463 		gtk_toggle_button_set_active(
464 			GTK_TOGGLE_BUTTON(unread_mail_blink_btn), TRUE);
465 		break;
466 	case ON:
467 		gtk_toggle_button_set_active(
468 			GTK_TOGGLE_BUTTON(unread_mail_on_btn), TRUE);
469 		break;
470 	}
471 
472 	switch (acpiprefs.new_mail_action) {
473 	case OFF:
474 		gtk_toggle_button_set_active(
475 			GTK_TOGGLE_BUTTON(new_mail_off_btn), TRUE);
476 		break;
477 	case BLINK:
478 		gtk_toggle_button_set_active(
479 			GTK_TOGGLE_BUTTON(new_mail_blink_btn), TRUE);
480 		break;
481 	case ON:
482 		gtk_toggle_button_set_active(
483 			GTK_TOGGLE_BUTTON(new_mail_on_btn), TRUE);
484 		break;
485 	}
486 
487 	if (acpiprefs.file_path != NULL) {
488 		for (i = 0; known_implementations[i].name != NULL; i++) {
489 			if (!strcmp(acpiprefs.file_path,
490 				    known_implementations[i].file_path)) {
491 				gtk_cmoption_menu_set_history(
492 					GTK_CMOPTION_MENU(
493 					default_implementations_optmenu), i);
494 				found = i;
495 			}
496 		}
497 	}
498 	if (found == 0) {
499 		for (i = 0; known_implementations[i].name != NULL; i++) {
500 			if (check_impl(known_implementations[i].file_path)) {
501 				gtk_cmoption_menu_set_history(
502 					GTK_CMOPTION_MENU(
503 					default_implementations_optmenu), i);
504 				found = i;
505 			}
506 		}
507 	}
508 	page->page.widget = vbox;
509 
510 	page->no_mail_off_btn = no_mail_off_btn;
511 	page->no_mail_blink_btn = no_mail_blink_btn;
512 	page->no_mail_on_btn = no_mail_on_btn;
513 	page->unread_mail_off_btn = unread_mail_off_btn;
514 	page->unread_mail_blink_btn = unread_mail_blink_btn;
515 	page->unread_mail_on_btn = unread_mail_on_btn;
516 	page->new_mail_off_btn = new_mail_off_btn;
517 	page->new_mail_blink_btn = new_mail_blink_btn;
518 	page->new_mail_on_btn = new_mail_on_btn;
519 	page->default_implementations_optmenu = default_implementations_optmenu;
520 	page->on_value_entry = on_value_entry;
521 	page->off_value_entry = off_value_entry;
522 	page->file_entry = file_entry;
523 	page->hbox_acpi_file = hbox_acpi_file;
524 	page->hbox_acpi_values = hbox_acpi_values;
525 	page->warning_box = warning_box;
526 	page->warning_label = warning_label;
527 	page->blink_on_err_chkbtn = blink_on_err_chkbtn;
528 
529 	if (found != 0) {
530 		gtk_widget_hide(hbox_acpi_file);
531 		gtk_widget_hide(hbox_acpi_values);
532 		gtk_entry_set_text(GTK_ENTRY(file_entry),
533 			known_implementations[found].file_path);
534 		gtk_entry_set_text(GTK_ENTRY(on_value_entry),
535 			known_implementations[found].on_param);
536 		gtk_entry_set_text(GTK_ENTRY(off_value_entry),
537 			known_implementations[found].off_param);
538 
539 		if (!check_impl(known_implementations[found].file_path))
540 			show_error(page, known_implementations[found].file_path);
541 	} else {
542 		gtk_cmoption_menu_set_history(
543 			GTK_CMOPTION_MENU(default_implementations_optmenu), 0);
544 		gtk_widget_show_all(hbox_acpi_file);
545 		gtk_widget_show_all(hbox_acpi_values);
546 		if (acpiprefs.file_path != NULL)
547 			gtk_entry_set_text(GTK_ENTRY(file_entry),
548 					acpiprefs.file_path);
549 		if (acpiprefs.on_param != NULL)
550 			gtk_entry_set_text(GTK_ENTRY(on_value_entry),
551 					acpiprefs.on_param);
552 		if (acpiprefs.off_param != NULL)
553 			gtk_entry_set_text(GTK_ENTRY(off_value_entry),
554 					acpiprefs.off_param);
555 		if (!acpiprefs.file_path || !check_impl(acpiprefs.file_path))
556 			show_error(page, acpiprefs.file_path);
557 	}
558 }
559 
acpi_prefs_destroy_widget_func(PrefsPage * _page)560 static void acpi_prefs_destroy_widget_func(PrefsPage *_page)
561 {
562 }
563 
acpi_prefs_save_func(PrefsPage * _page)564 static void acpi_prefs_save_func(PrefsPage * _page)
565 {
566 	struct AcpiNotifierPage *page = (struct AcpiNotifierPage *) _page;
567 	PrefFile *pfile;
568 	gchar *rcpath;
569 	GtkWidget *menu;
570 	GtkWidget *menuitem;
571 	gint selected = 0;
572 
573 	g_free(acpiprefs.file_path);
574 	acpiprefs.file_path = gtk_editable_get_chars(
575 			GTK_EDITABLE(page->file_entry), 0, -1);
576 	g_free(acpiprefs.on_param);
577 	acpiprefs.on_param = gtk_editable_get_chars(
578 			GTK_EDITABLE(page->on_value_entry), 0, -1);
579 	g_free(acpiprefs.off_param);
580 	acpiprefs.off_param = gtk_editable_get_chars(
581 			GTK_EDITABLE(page->off_value_entry), 0, -1);
582 
583 	if (gtk_toggle_button_get_active(
584 		GTK_TOGGLE_BUTTON(page->no_mail_off_btn)))
585 		acpiprefs.no_mail_action = OFF;
586 	else if (gtk_toggle_button_get_active(
587 		GTK_TOGGLE_BUTTON(page->no_mail_blink_btn)))
588 		acpiprefs.no_mail_action = BLINK;
589 	else if (gtk_toggle_button_get_active(
590 		GTK_TOGGLE_BUTTON(page->no_mail_on_btn)))
591 		acpiprefs.no_mail_action = ON;
592 
593 	if (gtk_toggle_button_get_active(
594 		GTK_TOGGLE_BUTTON(page->unread_mail_off_btn)))
595 		acpiprefs.unread_mail_action = OFF;
596 	else if (gtk_toggle_button_get_active(
597 		GTK_TOGGLE_BUTTON(page->unread_mail_blink_btn)))
598 		acpiprefs.unread_mail_action = BLINK;
599 	else if (gtk_toggle_button_get_active(
600 		GTK_TOGGLE_BUTTON(page->unread_mail_on_btn)))
601 		acpiprefs.unread_mail_action = ON;
602 
603 	if (gtk_toggle_button_get_active(
604 		GTK_TOGGLE_BUTTON(page->new_mail_off_btn)))
605 		acpiprefs.new_mail_action = OFF;
606 	else if (gtk_toggle_button_get_active(
607 		GTK_TOGGLE_BUTTON(page->new_mail_blink_btn)))
608 		acpiprefs.new_mail_action = BLINK;
609 	else if (gtk_toggle_button_get_active(
610 		GTK_TOGGLE_BUTTON(page->new_mail_on_btn)))
611 		acpiprefs.new_mail_action = ON;
612 
613 	acpiprefs.blink_on_err = gtk_toggle_button_get_active(
614 		GTK_TOGGLE_BUTTON(page->blink_on_err_chkbtn));
615 
616 	menu = gtk_cmoption_menu_get_menu(
617 		GTK_CMOPTION_MENU(page->default_implementations_optmenu));
618 	menuitem = gtk_menu_get_active(GTK_MENU(menu));
619 	selected = GPOINTER_TO_INT
620 		(g_object_get_data(G_OBJECT(menuitem), MENU_VAL_ID));
621 
622 	if (selected != 0) {
623 		g_free(acpiprefs.file_path);
624 		acpiprefs.file_path = g_strdup(
625 				known_implementations[selected].file_path);
626 		g_free(acpiprefs.on_param);
627 		acpiprefs.on_param = g_strdup(
628 				known_implementations[selected].on_param);
629 		g_free(acpiprefs.off_param);
630 		acpiprefs.off_param = g_strdup(
631 				known_implementations[selected].off_param);
632 	}
633 
634 	rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
635 	pfile = prefs_write_open(rcpath);
636 	g_free(rcpath);
637 	if (!pfile || (prefs_set_block_label(pfile, PREFS_BLOCK_NAME) < 0))
638 		return;
639 
640 	if (prefs_write_param(param, pfile->fp) < 0) {
641 		g_warning("failed to write " PREFS_BLOCK_NAME
642 			  " configuration to file\n");
643 		prefs_file_close_revert(pfile);
644 		return;
645 	}
646         if (fprintf(pfile->fp, "\n") < 0) {
647 		FILE_OP_ERROR(rcpath, "fprintf");
648 		prefs_file_close_revert(pfile);
649 	} else
650 	        prefs_file_close(pfile);
651 }
652 
acpi_set(gboolean on)653 static void acpi_set(gboolean on)
654 {
655 	FILE *fp = NULL;
656 
657 	if (!acpiprefs.file_path) {
658 		debug_print("acpiprefs.file_path NULL\n");
659 		return;
660 	}
661 	if (!check_impl(acpiprefs.file_path)) {
662 		debug_print("acpiprefs.file_path not implemented\n");
663 		return;
664 	}
665 	if (!acpiprefs.on_param || !acpiprefs.off_param) {
666 		debug_print("no param\n");
667 		return;
668 	}
669 
670 	if (!is_program(acpiprefs.file_path)) {
671 		fp = claws_fopen(acpiprefs.file_path, "wb");
672 		if (fp == NULL)
673 			return;
674 
675 		if (on) {
676 			claws_fwrite(acpiprefs.on_param, 1, strlen(acpiprefs.on_param), fp);
677 		} else {
678 			claws_fwrite(acpiprefs.off_param, 1, strlen(acpiprefs.off_param), fp);
679 		}
680 		claws_safe_fclose(fp);
681 	} else {
682 		gchar *cmd = g_strdup_printf("%s %s",
683 				acpiprefs.file_path,
684 				on ? acpiprefs.on_param:acpiprefs.off_param);
685 		execute_command_line(cmd, TRUE, NULL);
686 		g_free(cmd);
687 	}
688 }
689 
690 static guint should_quit = FALSE;
691 static int last_blink = 0;
692 
acpi_blink(gpointer data)693 static gint acpi_blink(gpointer data)
694 {
695 	if (!should_quit) {
696 		acpi_set(last_blink);
697 		last_blink = !last_blink;
698 		return TRUE;
699 	} else {
700 		acpi_set(FALSE);
701 		return FALSE;
702 	}
703 }
704 
705 static int blink_timeout_id = 0;
706 static int alertpanel_blink_timeout_id = 0;
707 static gint my_new = -1, my_unread = -1;
708 static int my_action = -1;
709 
acpi_update_hook(gpointer source,gpointer data)710 static gboolean acpi_update_hook(gpointer source, gpointer data)
711 {
712 	int action = 0;
713 	guint new, unread, unreadmarked, marked, total;
714 	guint replied, forwarded, locked, ignored, watched;
715 
716 	if (alertpanel_blink_timeout_id)
717 		return FALSE;
718 
719 	folder_count_total_msgs(&new, &unread, &unreadmarked, &marked, &total,
720 				&replied, &forwarded, &locked, &ignored, &watched);
721 
722 	if (my_new != new || my_unread != unread) {
723 		my_new = new;
724 		my_unread = unread;
725 		if (my_new > 0) {
726 			action = acpiprefs.new_mail_action;
727 		} else if (my_unread > 0) {
728 			action = acpiprefs.unread_mail_action;
729 		} else {
730 			action = acpiprefs.no_mail_action;
731 		}
732 
733 		if (action != my_action) {
734 			my_action = action;
735 
736 			if (action != BLINK && blink_timeout_id != 0) {
737 				g_source_remove(blink_timeout_id);
738 				blink_timeout_id = 0;
739 			}
740 
741 			switch (action) {
742 			case ON:
743 				acpi_set(TRUE);
744 				break;
745 			case BLINK:
746 				acpi_set(TRUE);
747 				last_blink = FALSE;
748 				blink_timeout_id = g_timeout_add(1000, acpi_blink, NULL);
749 				break;
750 			case OFF:
751 				acpi_set(FALSE);
752 				break;
753 			}
754 		}
755 	}
756 
757 	return FALSE;
758 }
759 
acpi_alertpanel_hook(gpointer source,gpointer data)760 static gboolean acpi_alertpanel_hook(gpointer source, gpointer data)
761 {
762 	gboolean *opened = (gboolean *)source;
763 
764 	if (*opened == TRUE) {
765 		if (blink_timeout_id)
766 			g_source_remove(blink_timeout_id);
767 		blink_timeout_id = 0;
768 
769 		if (alertpanel_blink_timeout_id)
770 			return FALSE;
771 
772 		acpi_set(TRUE);
773 		last_blink = FALSE;
774 		alertpanel_blink_timeout_id = g_timeout_add(250, acpi_blink, NULL);
775 	} else {
776 		if (alertpanel_blink_timeout_id)
777 			g_source_remove(alertpanel_blink_timeout_id);
778 		alertpanel_blink_timeout_id = 0;
779 		my_new = -1;
780 		my_unread = -1;
781 		my_action = -1;
782 		acpi_update_hook(NULL, NULL);
783 	}
784 	return FALSE;
785 }
786 
acpi_prefs_init(void)787 void acpi_prefs_init(void)
788 {
789 	static gchar *path[3];
790 	gchar *rcpath;
791 
792 	path[0] = _("Plugins");
793 	path[1] = PLUGIN_NAME;
794 	path[2] = NULL;
795 
796 	prefs_set_default(param);
797 	rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
798 	prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL);
799 	g_free(rcpath);
800 
801 	acpi_prefs_page.page.path = path;
802 	acpi_prefs_page.page.create_widget = acpi_prefs_create_widget_func;
803 	acpi_prefs_page.page.destroy_widget = acpi_prefs_destroy_widget_func;
804 	acpi_prefs_page.page.save_page = acpi_prefs_save_func;
805 	acpi_prefs_page.page.weight = 40.0;
806 
807 	prefs_gtk_register_page((PrefsPage *) &acpi_prefs_page);
808 	folder_hook_id = hooks_register_hook (FOLDER_ITEM_UPDATE_HOOKLIST,
809 			acpi_update_hook, NULL);
810 	alertpanel_hook_id = hooks_register_hook (ALERTPANEL_OPENED_HOOKLIST,
811 			acpi_alertpanel_hook, NULL);
812 	should_quit = FALSE;
813 }
814 
acpi_prefs_done(void)815 void acpi_prefs_done(void)
816 {
817 	should_quit = TRUE;
818 	acpi_set(FALSE);
819 	if (claws_is_exiting())
820 		return;
821 	prefs_gtk_unregister_page((PrefsPage *) &acpi_prefs_page);
822 	hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, folder_hook_id);
823 	hooks_unregister_hook(ALERTPANEL_OPENED_HOOKLIST, alertpanel_hook_id);
824 }
825 
826 
acpi_init(void)827 void acpi_init(void)
828 {
829 	gint i;
830 	for (i = 0; acpi_help[i] != NULL; i++)
831 		known_implementations[i].help =
832 			*acpi_help[i] ? _(acpi_help[i]) : "";
833 	acpi_prefs_init();
834 }
835 
acpi_done(void)836 void acpi_done(void)
837 {
838 	acpi_prefs_done();
839 }
840 
plugin_init(gchar ** error)841 gint plugin_init(gchar **error)
842 {
843 	if( !check_plugin_version(MAKE_NUMERIC_VERSION(3,8,1,46),
844 				VERSION_NUMERIC, PLUGIN_NAME, error) )
845 		return -1;
846 
847 	acpi_init();
848 	return 0;
849 }
850 
plugin_done(void)851 gboolean plugin_done(void)
852 {
853 	if (blink_timeout_id)
854 		g_source_remove(blink_timeout_id);
855 	if (alertpanel_blink_timeout_id)
856 		g_source_remove(alertpanel_blink_timeout_id);
857 
858 	acpi_done();
859 	return TRUE;
860 }
861 
plugin_name(void)862 const gchar *plugin_name(void)
863 {
864 	return PLUGIN_NAME;
865 }
866 
plugin_desc(void)867 const gchar *plugin_desc(void)
868 {
869 	return _("This plugin handles various ACPI mail LEDs.");
870 }
871 
plugin_type(void)872 const gchar *plugin_type(void)
873 {
874 	return "GTK2";
875 }
876 
plugin_licence(void)877 const gchar *plugin_licence(void)
878 {
879 	return "GPL3+";
880 }
881 
plugin_version(void)882 const gchar *plugin_version(void)
883 {
884 	return VERSION;
885 }
886 
plugin_provides(void)887 struct PluginFeature *plugin_provides(void)
888 {
889 	static struct PluginFeature features[] =
890 		{ {PLUGIN_NOTIFIER, N_("Laptop LED")},
891 		  {PLUGIN_NOTHING, NULL}};
892 	return features;
893 }
894