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