1 /* GKrellM
2 | Copyright (C) 1999-2019 Bill Wilson
3 |
4 | Author: Bill Wilson billw@gkrellm.net
5 | Latest versions might be found at: http://gkrellm.net
6 |
7 |
8 | GKrellM is free software: you can redistribute it and/or modify it
9 | under the terms of the GNU General Public License as published by
10 | the Free Software Foundation, either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | GKrellM is distributed in the hope that it will be useful, but WITHOUT
14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 | License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with this program. If not, see http://www.gnu.org/licenses/
20 |
21 |
22 | Additional permission under GNU GPL version 3 section 7
23 |
24 | If you modify this program, or any covered work, by linking or
25 | combining it with the OpenSSL project's OpenSSL library (or a
26 | modified version of that library), containing parts covered by
27 | the terms of the OpenSSL or SSLeay licenses, you are granted
28 | additional permission to convey the resulting work.
29 | Corresponding Source for a non-source form of such a combination
30 | shall include the source code for the parts of OpenSSL used as well
31 | as that of the covered work.
32 */
33
34 #include "gkrellm.h"
35 #include "gkrellm-private.h"
36
37 #include <math.h>
38
39 static GList *gkrellm_alert_list,
40 *alert_plugin_list;
41
42
43 static void
run_command(GkrellmAlert * alert,gchar * command)44 run_command(GkrellmAlert *alert, gchar *command)
45 {
46 gchar cmd[1024];
47
48 if (!command || !*command)
49 return;
50 if (alert->cb_command_process)
51 (*alert->cb_command_process)(alert, command, cmd, sizeof(cmd),
52 alert->cb_command_process_data);
53 else
54 snprintf(cmd, sizeof(cmd), "%s", command);
55 g_spawn_command_line_async(cmd, NULL);
56 }
57
58 void
gkrellm_render_default_alert_decal(GkrellmAlert * alert)59 gkrellm_render_default_alert_decal(GkrellmAlert *alert)
60 {
61 GkrellmPiximage *im;
62 GkrellmAlertdecal *ad;
63
64 if (!alert)
65 return;
66 ad = &alert->ad;
67 if (ad->w <= 0 || ad->h <= 0)
68 return;
69 if (alert->high.alarm_on || alert->low.alarm_on)
70 gkrellm_get_decal_alarm_piximage(&im, &ad->nframes);
71 else if (alert->high.warn_on || alert->low.warn_on)
72 gkrellm_get_decal_warn_piximage(&im, &ad->nframes);
73 else
74 return;
75 gkrellm_scale_piximage_to_pixmap(im, &ad->pixmap, &ad->mask, ad->w,
76 ad->h * ad->nframes);
77 }
78
79 gboolean
gkrellm_alert_decal_visible(GkrellmAlert * alert)80 gkrellm_alert_decal_visible(GkrellmAlert *alert)
81 {
82 if (alert && alert->ad.decal)
83 return TRUE;
84 return FALSE;
85 }
86
87 static gboolean
create_alert_objects(GkrellmAlert * alert)88 create_alert_objects(GkrellmAlert *alert)
89 {
90 GkrellmAlertdecal *ad;
91 // GkrellmKrell *k;
92
93 /* Whichever monitor created the alert that is being triggered:
94 | 1) has set a panel pointer in the create and is done, so I will make
95 | here a default panel sized alert decal for him, or
96 | 2) has not set a panel ptr, but will do so in the callback and then
97 | let me make the default alert, or
98 | 3) has done one of the 2 above panel possibilities, and will also
99 | render a custom size/position for the alert decal and set the pixmap.
100 | For this case, the alert decal may be a render of the default decal
101 | image or may be a custom image from the monitor. The work needed is
102 | setting ad x,y,w,h and nframes and rendering to ad->pixmap.
103 */
104 if (alert->cb_trigger)
105 (*alert->cb_trigger)(alert, alert->cb_trigger_data);
106 if (!alert->panel)
107 return FALSE; /* Monitor may need trigger deferred */
108 ad = &alert->ad;
109 if (!alert->ad.pixmap /* && style is decal alert */)
110 {
111 ad->x = 0;
112 ad->y = 0;
113 ad->w = alert->panel->w;
114 ad->h = alert->panel->h;
115 gkrellm_render_default_alert_decal(alert);
116 }
117 /* Don't let create_decal append the decal, I want to insert it first so
118 | it will appear under all other panel decals.
119 */
120 ad->decal = gkrellm_create_decal_pixmap(NULL, ad->pixmap, ad->mask,
121 ad->nframes, NULL, ad->x, ad->y);
122 gkrellm_insert_decal(alert->panel, ad->decal, FALSE /* prepend */);
123
124 #if 0
125 k = gkrellm_create_krell(NULL,
126 gkrellm_krell_mini_piximage(), gkrellm_krell_mini_style());
127 k->y0 = 5;
128 k->full_scale = 100;
129
130 alert->ak.krell = k;
131 gkrellm_insert_krell(alert->panel, k, TRUE);
132 #endif
133 return TRUE;
134 }
135
136 static void
destroy_alert_objects(GkrellmAlert * alert)137 destroy_alert_objects(GkrellmAlert *alert)
138 {
139 gkrellm_destroy_decal(alert->ad.decal);
140 if (alert->ad.pixmap)
141 g_object_unref(G_OBJECT(alert->ad.pixmap));
142 alert->ad.pixmap = NULL;
143 alert->ad.mask = NULL;
144 alert->ad.decal = NULL;
145 gkrellm_destroy_krell(alert->ak.krell);
146 alert->ak.krell = NULL;
147 }
148
149 static void
plugin_warn(GkrellmAlert * alert,gboolean state)150 plugin_warn(GkrellmAlert *alert, gboolean state)
151 {
152 GList *list;
153 GkrellmAlertPlugin *gap;
154 GkrellmAlertPluginLink *apl;
155
156 for (list = alert->plugin_list; list; list = list->next)
157 {
158 apl = (GkrellmAlertPluginLink *) list->data;
159 gap = apl->alert_plugin;
160 if (MONITOR_ENABLED(gap->mon) && gap->warn_func)
161 (*gap->warn_func)(alert, apl->data, state);
162 }
163 }
164
165 static void
plugin_alarm(GkrellmAlert * alert,gboolean state)166 plugin_alarm(GkrellmAlert *alert, gboolean state)
167 {
168 GList *list;
169 GkrellmAlertPlugin *gap;
170 GkrellmAlertPluginLink *apl;
171
172 for (list = alert->plugin_list; list; list = list->next)
173 {
174 apl = (GkrellmAlertPluginLink *) list->data;
175 gap = apl->alert_plugin;
176 if (MONITOR_ENABLED(gap->mon) && gap->alarm_func)
177 (*gap->alarm_func)(alert, apl->data, state);
178 }
179 }
180
181 static void
trigger_warn(GkrellmAlert * alert,GkrellmTrigger * trigger)182 trigger_warn(GkrellmAlert *alert, GkrellmTrigger *trigger)
183 {
184 if (!trigger->warn_on)
185 {
186 trigger->warn_on = TRUE;
187 create_alert_objects(alert);
188 gkrellm_alert_list = g_list_append(gkrellm_alert_list, alert);
189 if (!alert->suppress_command)
190 {
191 run_command(alert, alert->warn_command);
192 plugin_warn(alert, ON);
193 }
194 alert->suppress_command = FALSE;
195 alert->warn_repeat = alert->warn_repeat_set;
196 }
197 }
198
199 static void
stop_warn(GkrellmAlert * alert,GkrellmTrigger * trigger)200 stop_warn(GkrellmAlert *alert, GkrellmTrigger *trigger)
201 {
202 if (trigger->warn_on)
203 {
204 plugin_warn(alert, OFF);
205 trigger->warn_on = FALSE;
206 destroy_alert_objects(alert);
207 gkrellm_alert_list = g_list_remove(gkrellm_alert_list, alert);
208 alert->warn_repeat = 0;
209 alert->suppress_command = FALSE;
210 }
211 }
212
213 static void
trigger_alarm(GkrellmAlert * alert,GkrellmTrigger * trigger)214 trigger_alarm(GkrellmAlert *alert, GkrellmTrigger *trigger)
215 {
216 if (!trigger->alarm_on)
217 {
218 trigger->alarm_on = TRUE;
219 trigger->warn_delay = 0;
220 create_alert_objects(alert);
221 gkrellm_alert_list = g_list_append(gkrellm_alert_list, alert);
222 if (!alert->suppress_command)
223 {
224 run_command(alert, alert->alarm_command);
225 plugin_alarm(alert, ON);
226 }
227 alert->suppress_command = FALSE;
228 alert->alarm_repeat = alert->alarm_repeat_set;
229 }
230 }
231
232 static void
stop_alarm(GkrellmAlert * alert,GkrellmTrigger * trigger)233 stop_alarm(GkrellmAlert *alert, GkrellmTrigger *trigger)
234 {
235 if (trigger->alarm_on)
236 {
237 plugin_alarm(alert, OFF);
238 trigger->alarm_on = FALSE;
239 destroy_alert_objects(alert);
240 gkrellm_alert_list = g_list_remove(gkrellm_alert_list, alert);
241 alert->alarm_repeat = 0;;
242 alert->suppress_command = FALSE;
243 }
244 }
245
246 void
gkrellm_freeze_alert(GkrellmAlert * alert)247 gkrellm_freeze_alert(GkrellmAlert *alert)
248 {
249 if (alert)
250 alert->freeze = TRUE;
251 }
252
253 void
gkrellm_thaw_alert(GkrellmAlert * alert)254 gkrellm_thaw_alert(GkrellmAlert *alert)
255 {
256 if (alert)
257 alert->freeze = FALSE;
258 }
259
260 static gboolean
check_high_alarm_limit(GkrellmAlert * alert,gfloat value)261 check_high_alarm_limit(GkrellmAlert *alert, gfloat value)
262 {
263 GkrellmTrigger *trigger = &alert->high;
264
265 if (value < trigger->alarm_limit)
266 {
267 trigger->alarm_delay = alert->delay;
268 return FALSE;
269 }
270 if (trigger->alarm_delay == 0)
271 {
272 if (trigger->warn_delay > 0)
273 trigger->warn_delay -= 1;
274 return TRUE;
275 }
276 trigger->alarm_delay -= 1;
277 return FALSE;
278 }
279
280 static gboolean
check_high_warn_limit(GkrellmAlert * alert,gfloat value)281 check_high_warn_limit(GkrellmAlert *alert, gfloat value)
282 {
283 GkrellmTrigger *trigger = &alert->high;
284
285 if (value < trigger->warn_limit)
286 {
287 trigger->warn_delay = alert->delay;
288 return FALSE;
289 }
290 if (trigger->warn_delay == 0)
291 return TRUE;
292 trigger->warn_delay -= 1;
293 return FALSE;
294 }
295
296 static gboolean
check_low_warn_limit(GkrellmAlert * alert,gfloat value)297 check_low_warn_limit(GkrellmAlert *alert, gfloat value)
298 {
299 GkrellmTrigger *trigger = &alert->low;
300
301 if (value > trigger->warn_limit)
302 {
303 trigger->warn_delay = alert->delay;
304 return FALSE;
305 }
306 if (trigger->warn_delay == 0)
307 return TRUE;
308 trigger->warn_delay -= 1;
309 return FALSE;
310 }
311
312 static gboolean
check_low_alarm_limit(GkrellmAlert * alert,gfloat value)313 check_low_alarm_limit(GkrellmAlert *alert, gfloat value)
314 {
315 GkrellmTrigger *trigger = &alert->low;
316
317 if (value > trigger->alarm_limit)
318 {
319 trigger->alarm_delay = alert->delay;
320 return FALSE;
321 }
322 if (trigger->alarm_delay == 0)
323 {
324 if (trigger->warn_delay > 0)
325 trigger->warn_delay -= 1;
326 return TRUE;
327 }
328 trigger->alarm_delay -= 1;
329 return FALSE;
330 }
331
332 void
gkrellm_check_alert(GkrellmAlert * alert,gfloat value)333 gkrellm_check_alert(GkrellmAlert *alert, gfloat value)
334 {
335 GList *plist;
336 GkrellmAlertPlugin *gap;
337 GkrellmAlertPluginLink *apl;
338
339 if (!alert || !alert->activated || alert->freeze || !_GK.initialized)
340 return;
341
342 if (alert->delay == 0 || GK.second_tick)
343 {
344 if (alert->check_low)
345 {
346 if (check_low_alarm_limit(alert, value))
347 {
348 stop_alarm(alert, &alert->high);
349 stop_warn(alert, &alert->high);
350 stop_warn(alert, &alert->low);
351 trigger_alarm(alert, &alert->low);
352 }
353 else
354 {
355 stop_alarm(alert, &alert->low);
356 if (check_low_warn_limit(alert, value))
357 {
358 stop_alarm(alert, &alert->high);
359 stop_warn(alert, &alert->high);
360 trigger_warn(alert, &alert->low);
361 }
362 else
363 stop_warn(alert, &alert->low);
364 }
365 }
366 if (alert->check_high)
367 {
368 if (check_high_alarm_limit(alert, value))
369 {
370 stop_warn(alert, &alert->high);
371 stop_warn(alert, &alert->low);
372 stop_alarm(alert, &alert->low);
373 trigger_alarm(alert, &alert->high);
374 }
375 else
376 {
377 stop_alarm(alert, &alert->high);
378 if (check_high_warn_limit(alert, value))
379 {
380 stop_warn(alert, &alert->low);
381 stop_alarm(alert, &alert->low);
382 trigger_warn(alert, &alert->high);
383 }
384 else
385 stop_warn(alert, &alert->high);
386 }
387 }
388 }
389
390 for (plist = alert->plugin_list; plist; plist = plist->next)
391 {
392 apl = (GkrellmAlertPluginLink *) plist->data;
393 gap = apl->alert_plugin;
394 if (MONITOR_ENABLED(gap->mon) && gap->check_func)
395 (*gap->check_func)(alert, apl->data, value);
396 }
397 }
398
399 void
gkrellm_alert_trigger_connect(GkrellmAlert * alert,void (* func)(),gpointer data)400 gkrellm_alert_trigger_connect(GkrellmAlert *alert, void (*func)(),
401 gpointer data)
402 {
403 if (!alert)
404 return;
405 alert->cb_trigger = func;
406 alert->cb_trigger_data = data;
407 }
408
409 void
gkrellm_alert_stop_connect(GkrellmAlert * alert,void (* func)(),gpointer data)410 gkrellm_alert_stop_connect(GkrellmAlert *alert, void (*func)(), gpointer data)
411 {
412 if (!alert)
413 return;
414 alert->cb_stop = func;
415 alert->cb_stop_data = data;
416 }
417
418 static void
destroy_alert(GkrellmAlert * alert)419 destroy_alert(GkrellmAlert *alert)
420 {
421 GList *plist, *list;
422 GkrellmAlertPlugin *gap;
423 GkrellmAlertPluginLink *apl;
424 gpointer data;
425
426 if (!alert)
427 return;
428 if (g_list_find(gkrellm_alert_list, alert))
429 {
430 gkrellm_alert_list = g_list_remove(gkrellm_alert_list, alert);
431 destroy_alert_objects(alert);
432 }
433
434 for (plist = alert_plugin_list; plist; plist = plist->next)
435 {
436 data = NULL;
437 gap = (GkrellmAlertPlugin *) plist->data;
438 for (list = alert->plugin_list; list; list = list->next)
439 {
440 apl = (GkrellmAlertPluginLink *) list->data;
441 if (apl->alert_plugin == gap)
442 {
443 data = apl->data;
444 break;
445 }
446 }
447 if (MONITOR_ENABLED(gap->mon) && gap->destroy_func)
448 (*gap->destroy_func)(alert, data);
449 }
450 gkrellm_free_glist_and_data(&alert->plugin_list); /* should all be detached */
451 g_free(alert->name);
452 g_free(alert->unit_string);
453 g_free(alert->alarm_command);
454 g_free(alert->warn_command);
455 g_free(alert->id_string);
456 g_free(alert);
457 }
458
459 void
gkrellm_alert_destroy(GkrellmAlert ** ap)460 gkrellm_alert_destroy(GkrellmAlert **ap)
461 {
462 if (!ap || !*ap)
463 return;
464 gkrellm_alert_window_destroy(ap);
465 destroy_alert(*ap);
466 *ap = NULL;
467 }
468
469 GkrellmAlert *
gkrellm_alert_create(GkrellmPanel * p,gchar * name,gchar * unit_string,gboolean check_high,gboolean check_low,gboolean do_updates,gfloat max_high,gfloat min_low,gfloat step0,gfloat step1,gint digits)470 gkrellm_alert_create(GkrellmPanel *p, gchar *name, gchar *unit_string,
471 gboolean check_high, gboolean check_low, gboolean do_updates,
472 gfloat max_high, gfloat min_low,
473 gfloat step0, gfloat step1, gint digits)
474 {
475 GkrellmAlert *alert;
476
477 alert = g_new0(GkrellmAlert, 1);
478 alert->panel = p;
479 alert->name = g_strdup(name);
480 alert->unit_string = g_strdup(unit_string);
481 alert->check_high = check_high;
482 alert->check_low = check_low;
483 alert->do_panel_updates = do_updates;
484 alert->max_high = max_high;
485 alert->min_low = min_low;
486 alert->step0 = step0;
487 alert->step1 = step1;
488 alert->digits = digits;
489
490 alert->alarm_command = g_strdup("");
491 alert->warn_command = g_strdup("");
492 alert->do_alarm_command = alert->do_warn_command = TRUE;
493
494 gkrellm_alert_set_triggers(alert, min_low, min_low, min_low, min_low);
495 alert->activated = FALSE;
496 alert->check_hardwired = FALSE;
497
498 return alert;
499 }
500
501 /* Set alarm trigger values for hardwired alarms which have no config
502 */
503 void
gkrellm_alert_set_triggers(GkrellmAlert * alert,gfloat high_alarm,gfloat high_warn,gfloat low_warn,gfloat low_alarm)504 gkrellm_alert_set_triggers(GkrellmAlert *alert,
505 gfloat high_alarm, gfloat high_warn,
506 gfloat low_warn, gfloat low_alarm)
507 {
508 if (alert->check_high)
509 {
510 alert->high.alarm_limit = high_alarm;
511 alert->high.warn_limit = high_warn;
512 }
513 if (alert->check_low)
514 {
515 alert->low.warn_limit = low_warn;
516 alert->low.alarm_limit = low_alarm;
517 }
518 alert->activated = TRUE;
519 alert->check_hardwired = TRUE;
520 }
521
522
523 void
gkrellm_alert_commands_config(GkrellmAlert * alert,gboolean alarm,gboolean warn)524 gkrellm_alert_commands_config(GkrellmAlert *alert,
525 gboolean alarm, gboolean warn)
526 {
527 alert->do_alarm_command = alarm;
528 alert->do_warn_command = warn;
529 }
530
531 void
gkrellm_alert_set_delay(GkrellmAlert * alert,gint delay)532 gkrellm_alert_set_delay(GkrellmAlert *alert, gint delay)
533 {
534 if (!alert)
535 return;
536 alert->delay = delay;
537 alert->low.warn_delay = alert->low.alarm_delay = delay;
538 alert->high.warn_delay = alert->high.alarm_delay = delay;
539 }
540
541 void
gkrellm_alert_delay_config(GkrellmAlert * alert,gint step,gint high,gint low)542 gkrellm_alert_delay_config(GkrellmAlert *alert, gint step,
543 gint high, gint low)
544 {
545 if (!alert || step < 1 || high < step)
546 return;
547 low = (low / step) * step;
548 high = (high / step) * step;
549
550 alert->delay_high = (gfloat) high;
551 alert->delay_low = (gfloat) low;
552 alert->delay_step = (gfloat) step;
553 gkrellm_alert_set_delay(alert, low);
554 }
555
556 void
gkrellm_alert_dup(GkrellmAlert ** a_dst,GkrellmAlert * a_src)557 gkrellm_alert_dup(GkrellmAlert **a_dst, GkrellmAlert *a_src)
558 {
559 GkrellmAlert *alert;
560
561 if (!a_dst || !a_src)
562 return;
563 if (*a_dst)
564 (*a_dst)->plugin_list = NULL; /* XXX fixme */
565 gkrellm_alert_destroy(a_dst);
566 alert = gkrellm_alert_create(a_src->panel, a_src->name,
567 a_src->unit_string, a_src->check_high, a_src->check_low,
568 a_src->do_panel_updates, a_src->max_high, a_src->min_low,
569 a_src->step0, a_src->step1, a_src->digits);
570 gkrellm_dup_string(&alert->alarm_command, a_src->alarm_command);
571 gkrellm_dup_string(&alert->warn_command, a_src->warn_command);
572 alert->warn_repeat_set = a_src->warn_repeat_set;
573 alert->alarm_repeat_set = a_src->alarm_repeat_set;
574 alert->low = a_src->low;
575 alert->high = a_src->high;
576 gkrellm_alert_set_delay(alert, a_src->delay);
577 alert->plugin_list = a_src->plugin_list; /* XXX fixme */
578
579 alert->activated = a_src->activated;
580 *a_dst = alert;
581 }
582
583 static void
reset_alert(GkrellmAlert * alert,gboolean suppress)584 reset_alert(GkrellmAlert *alert, gboolean suppress)
585 {
586 GkrellmTrigger *th = &alert->high,
587 *tl = &alert->low;
588
589 if ( suppress
590 && ( ((th->alarm_on || tl->alarm_on) && alert->alarm_repeat_set == 0)
591 || ((th->warn_on || tl->warn_on) && alert->warn_repeat_set == 0)
592 )
593 )
594 alert->suppress_command = TRUE;
595 th->alarm_on = FALSE;
596 th->warn_on = FALSE;
597 tl->alarm_on = FALSE;
598 tl->warn_on = FALSE;
599 alert->alarm_repeat = 0;
600 alert->warn_repeat = 0;
601 destroy_alert_objects(alert);
602 }
603
604 void
gkrellm_reset_alert(GkrellmAlert * alert)605 gkrellm_reset_alert(GkrellmAlert *alert)
606 {
607 if (!alert)
608 return;
609 if (g_list_find(gkrellm_alert_list, alert))
610 {
611 reset_alert(alert, FALSE);
612 gkrellm_alert_list = g_list_remove(gkrellm_alert_list, alert);
613 }
614 }
615
616 void
gkrellm_reset_alert_soft(GkrellmAlert * alert)617 gkrellm_reset_alert_soft(GkrellmAlert *alert)
618 {
619 if (!alert)
620 return;
621 if (g_list_find(gkrellm_alert_list, alert))
622 {
623 reset_alert(alert, TRUE);
624 gkrellm_alert_list = g_list_remove(gkrellm_alert_list, alert);
625 }
626 }
627
628 void
gkrellm_reset_panel_alerts(GkrellmPanel * p)629 gkrellm_reset_panel_alerts(GkrellmPanel *p)
630 {
631 GList *list;
632 GkrellmAlert *alert;
633 gboolean done = FALSE;
634
635 if (!p)
636 return;
637 while (!done)
638 {
639 done = TRUE; /* Assume won't find any */
640 for (list = gkrellm_alert_list; list; list = list->next)
641 {
642 alert = (GkrellmAlert *) list->data;
643 if (alert->panel != p)
644 continue;
645 done = FALSE;
646 reset_alert(alert, FALSE);
647 gkrellm_alert_list = g_list_remove(gkrellm_alert_list, alert);
648 alert->panel = NULL;
649 alert->cb_trigger = NULL;
650 alert->cb_trigger_data = NULL;
651 alert->cb_stop = NULL;
652 alert->cb_stop_data = NULL;
653 break;
654 }
655 }
656 }
657
658 /* At theme changes, turn all alerts off so there won't be any alert decals
659 | in monitor lists when they are destroyed. The alerts should just get
660 | retriggered. Surely an alert going off is a good time to change themes.
661 */
662 void
gkrellm_alert_reset_all(void)663 gkrellm_alert_reset_all(void)
664 {
665 GList *list;
666
667 for (list = gkrellm_alert_list; list; list = list->next)
668 reset_alert((GkrellmAlert *) list->data, TRUE);
669 g_list_free(gkrellm_alert_list);
670 gkrellm_alert_list = NULL;
671 }
672
673 void
gkrellm_alert_update(void)674 gkrellm_alert_update(void)
675 {
676 GList *list, *plist;
677 GkrellmAlert *alert;
678 GkrellmAlertdecal *ad;
679 GkrellmAlertkrell *ak;
680 GkrellmAlertPlugin *gap;
681 GkrellmAlertPluginLink *apl;
682
683 for (list = gkrellm_alert_list; list; list = list->next)
684 {
685 alert = (GkrellmAlert *) list->data;
686 ad = &alert->ad;
687 ak = &alert->ak;
688 if (ak->krell)
689 {
690 ak->krell_position = (ak->krell_position + 2) % 100;
691 gkrellm_update_krell(alert->panel, ak->krell, ak->krell_position);
692 }
693 if (ad->decal)
694 {
695 if (ad->frame <= 0)
696 ad->dir = 1;
697 else if (ad->frame >= ad->nframes - 1)
698 ad->dir = 0;
699 ad->frame += (ad->dir) ? 1 : -1;
700 gkrellm_draw_decal_pixmap(alert->panel, ad->decal, ad->frame);
701 }
702 if (alert->do_panel_updates)
703 gkrellm_draw_panel_layers(alert->panel);
704 if (GK.second_tick)
705 {
706 if (alert->alarm_repeat > 0 && --alert->alarm_repeat == 0)
707 {
708 run_command(alert, alert->alarm_command);
709 alert->alarm_repeat = alert->alarm_repeat_set;
710 }
711 if (alert->warn_repeat > 0 && --alert->warn_repeat == 0)
712 {
713 run_command(alert, alert->warn_command);
714 alert->warn_repeat = alert->warn_repeat_set;
715 }
716 for (plist = alert->plugin_list; plist; plist = plist->next)
717 {
718 apl = (GkrellmAlertPluginLink *) plist->data;
719 gap = apl->alert_plugin;
720 if (MONITOR_ENABLED(gap->mon) && gap->update_func)
721 (*gap->update_func)(alert, apl->data);
722 }
723 }
724 }
725 }
726
727 gboolean
gkrellm_alert_is_activated(GkrellmAlert * alert)728 gkrellm_alert_is_activated(GkrellmAlert *alert)
729 {
730 if (alert)
731 return alert->activated;
732 return FALSE;
733 }
734
735 void
gkrellm_alert_get_alert_state(GkrellmAlert * alert,gboolean * alarm_state,gboolean * warn_state)736 gkrellm_alert_get_alert_state(GkrellmAlert *alert, gboolean *alarm_state,
737 gboolean *warn_state)
738 {
739 if (!alert)
740 return;
741 if (warn_state)
742 *warn_state = (alert->high.warn_on || alert->low.warn_on);
743 if (alarm_state)
744 *alarm_state = (alert->high.alarm_on || alert->low.alarm_on);
745 }
746
747
748 /* ------------------------------------------------------------ */
749 /* Plugin interface to alerts. */
750
751 GkrellmAlertPlugin *
gkrellm_alert_plugin_add(GkrellmMonitor * mon,gchar * name)752 gkrellm_alert_plugin_add(GkrellmMonitor *mon, gchar *name)
753 {
754 GkrellmAlertPlugin *gap;
755
756 if (!mon || !name || !*name)
757 return NULL;
758 gap = g_new0(GkrellmAlertPlugin, 1);
759 gap->mon = mon;
760 gap->name = g_strdup(name);
761 alert_plugin_list = g_list_append(alert_plugin_list, gap);
762 return gap;
763 }
764
765 void
gkrellm_alert_plugin_alert_connect(GkrellmAlertPlugin * gap,void (* alarm_func)(),void (* warn_func)(),void (* update_func)(),void (* check_func)(),void (* destroy_func)())766 gkrellm_alert_plugin_alert_connect(GkrellmAlertPlugin *gap,
767 void (*alarm_func)(), void (*warn_func)(),
768 void (*update_func)(), void (*check_func)(),
769 void (*destroy_func)())
770 {
771 gap->alarm_func = alarm_func;
772 gap->warn_func = warn_func;
773 gap->update_func = update_func;
774 gap->check_func = check_func;
775 gap->destroy_func = destroy_func;
776 }
777
778 void
gkrellm_alert_plugin_config_connect(GkrellmAlertPlugin * gap,gchar * tab_name,void (* config_create_func)(),void (* config_apply_func),void (* config_save_func)(),void (* config_load_func)())779 gkrellm_alert_plugin_config_connect(GkrellmAlertPlugin *gap, gchar *tab_name,
780 void (*config_create_func)(), void (*config_apply_func),
781 void (*config_save_func)(), void (*config_load_func)())
782 {
783 if (!gap)
784 return;
785 g_free(gap->tab_name);
786 gap->tab_name = g_strdup(tab_name);
787 gap->config_create_func = config_create_func;
788 gap->config_apply_func = config_apply_func;
789 gap->config_save_func = config_save_func;
790 gap->config_load_func = config_load_func;
791 }
792
793 /* The id_string is so a plugin can get a unique config name for an alert.
794 */
795 gchar *
gkrellm_alert_plugin_config_get_id_string(GkrellmAlert * alert)796 gkrellm_alert_plugin_config_get_id_string(GkrellmAlert *alert)
797 {
798 if (alert)
799 return alert->id_string;
800 return NULL;
801 }
802
803 void
gkrellm_alert_plugin_alert_attach(GkrellmAlertPlugin * gap,GkrellmAlert * alert,gpointer data)804 gkrellm_alert_plugin_alert_attach(GkrellmAlertPlugin *gap,
805 GkrellmAlert *alert, gpointer data)
806 {
807 GkrellmAlertPluginLink *apl;
808
809 if (!gap || !alert)
810 return;
811 apl = g_new0(GkrellmAlertPluginLink, 1);
812 apl->alert_plugin = gap;
813 apl->data = data;
814 alert->plugin_list = g_list_append(alert->plugin_list, apl);
815 }
816
817 void
gkrellm_alert_plugin_alert_detach(GkrellmAlertPlugin * gap,GkrellmAlert * alert)818 gkrellm_alert_plugin_alert_detach(GkrellmAlertPlugin *gap, GkrellmAlert *alert)
819 {
820 GList *list;
821 GkrellmAlertPluginLink *apl;
822
823 if (!gap || !alert)
824 return;
825 for (list = alert->plugin_list; list; list = list->next)
826 {
827 apl = (GkrellmAlertPluginLink *) list->data;
828 if (apl->alert_plugin == gap)
829 {
830 alert->plugin_list = g_list_remove(alert->plugin_list, apl);
831 g_free(apl);
832 break;
833 }
834 }
835 }
836
837 gpointer
gkrellm_alert_plugin_get_data(GkrellmAlertPlugin * gap,GkrellmAlert * alert)838 gkrellm_alert_plugin_get_data(GkrellmAlertPlugin *gap,GkrellmAlert *alert)
839 {
840 GList *list;
841 GkrellmAlertPluginLink *apl;
842
843 if (!gap || !alert)
844 return NULL;
845 for (list = alert->plugin_list; list; list = list->next)
846 {
847 apl = (GkrellmAlertPluginLink *) list->data;
848 if (apl->alert_plugin == gap)
849 return apl->data;
850 }
851 return NULL;
852 }
853
854 void
gkrellm_alert_plugin_command_process(GkrellmAlert * alert,gchar * src,gchar * dst,gint dst_size)855 gkrellm_alert_plugin_command_process(GkrellmAlert *alert, gchar *src,
856 gchar *dst, gint dst_size)
857 {
858 if (alert && alert->cb_command_process)
859 (*alert->cb_command_process)(alert, src, dst, dst_size,
860 alert->cb_command_process_data);
861 else
862 snprintf(dst, dst_size, "%s", src);
863 }
864
865
866 /* ------------------------------------------------------------ */
867 void
gkrellm_alert_command_process_connect(GkrellmAlert * alert,void (* func)(),gpointer data)868 gkrellm_alert_command_process_connect(GkrellmAlert *alert, void (*func)(),
869 gpointer data)
870 {
871 if (!alert)
872 return;
873 alert->cb_command_process = func;
874 alert->cb_command_process_data = data;
875 }
876
877 void
gkrellm_alert_config_connect(GkrellmAlert * alert,void (* func)(),gpointer data)878 gkrellm_alert_config_connect(GkrellmAlert *alert, void (*func)(),gpointer data)
879 {
880 if (!alert)
881 return;
882 alert->cb_config = func;
883 alert->cb_config_data = data;
884 }
885
886 void
gkrellm_alert_config_create_connect(GkrellmAlert * alert,void (* func)(),gpointer data)887 gkrellm_alert_config_create_connect(GkrellmAlert *alert,
888 void (*func)(), gpointer data)
889 {
890 if (!alert)
891 return;
892 alert->cb_config_create = func;
893 alert->cb_config_create_data = data;
894 }
895
896 static void
alert_delete(GtkWidget * widget,GkrellmAlert ** ap)897 alert_delete(GtkWidget *widget, GkrellmAlert **ap)
898 {
899 GkrellmAlert *alert;
900
901 if (!ap)
902 return;
903 alert = *ap;
904 alert->activated = FALSE;
905 alert->config_closing = TRUE;
906 if (alert->cb_config)
907 (*alert->cb_config)(alert, alert->cb_config_data);
908 if (alert->config_window)
909 gtk_widget_destroy(alert->config_window);
910 destroy_alert(alert);
911 *ap = NULL;
912 }
913
914 static void
alert_close(GtkWidget * widget,GkrellmAlert ** ap)915 alert_close(GtkWidget *widget, GkrellmAlert **ap)
916 {
917 GkrellmAlert *alert;
918
919 if (!ap)
920 return;
921 alert = *ap;
922 if (!alert->activated)
923 alert_delete(NULL, ap);
924 else if (alert->config_window)
925 {
926 gtk_widget_destroy(alert->config_window);
927 alert->config_window = NULL;
928 alert->delete_button = NULL;
929 }
930 }
931
932 void
gkrellm_alert_window_destroy(GkrellmAlert ** ap)933 gkrellm_alert_window_destroy(GkrellmAlert **ap)
934 {
935 alert_close(NULL, ap);
936 }
937
938 static gint
alert_config_window_delete_event(GtkWidget * widget,GdkEvent * ev,GkrellmAlert ** ap)939 alert_config_window_delete_event(GtkWidget *widget, GdkEvent *ev,
940 GkrellmAlert **ap)
941 {
942 alert_close(widget, ap);
943 return FALSE;
944 }
945
946 static void
alert_apply(GtkWidget * widget,GkrellmAlert ** ap)947 alert_apply(GtkWidget *widget, GkrellmAlert **ap)
948 {
949 GList *plist, *list;
950 GkrellmAlert *alert;
951 GkrellmAlertPlugin *gap;
952 GkrellmAlertPluginLink *apl;
953 gpointer data;
954 gchar *s;
955 GtkSpinButton *spin;
956 gint n;
957
958 alert = *ap;
959 if (!alert->activated && !alert->config_modified)
960 return;
961 if (alert->high.alarm_limit_spin_button)
962 {
963 spin = GTK_SPIN_BUTTON(alert->high.alarm_limit_spin_button);
964 alert->high.alarm_limit = gtk_spin_button_get_value(spin);
965 spin = GTK_SPIN_BUTTON(alert->high.warn_limit_spin_button);
966 alert->high.warn_limit = gtk_spin_button_get_value(spin);
967 }
968
969 if (alert->low.alarm_limit_spin_button)
970 {
971 spin = GTK_SPIN_BUTTON(alert->low.alarm_limit_spin_button);
972 alert->low.alarm_limit = gtk_spin_button_get_value(spin);
973 spin = GTK_SPIN_BUTTON(alert->low.warn_limit_spin_button);
974 alert->low.warn_limit = gtk_spin_button_get_value(spin);
975 }
976
977 if (alert->high.alarm_limit == 0.0 && alert->low.alarm_limit == 0.0)
978 return;
979 if (alert->alarm_command_entry)
980 {
981 spin = GTK_SPIN_BUTTON(alert->alarm_repeat_spin_button);
982 alert->alarm_repeat_set = gtk_spin_button_get_value_as_int(spin);
983
984 s = gkrellm_gtk_entry_get_text(&alert->alarm_command_entry);
985 gkrellm_dup_string(&alert->alarm_command, s);
986 if (!*s)
987 alert->alarm_repeat_set = 0;
988 if (alert->high.alarm_on || alert->low.alarm_on)
989 alert->alarm_repeat = alert->alarm_repeat_set;
990 }
991 if (alert->warn_command_entry)
992 {
993 spin = GTK_SPIN_BUTTON(alert->warn_repeat_spin_button);
994 alert->warn_repeat_set = gtk_spin_button_get_value_as_int(spin);
995
996 s = gkrellm_gtk_entry_get_text(&alert->warn_command_entry);
997 gkrellm_dup_string(&alert->warn_command, s);
998 if (!*s)
999 alert->warn_repeat_set = 0;
1000 if (alert->high.warn_on || alert->low.warn_on)
1001 alert->warn_repeat = alert->warn_repeat_set;
1002 }
1003 if (alert->delay_spin_button)
1004 {
1005 spin = GTK_SPIN_BUTTON(alert->delay_spin_button);
1006 n = gtk_spin_button_get_value_as_int(spin);
1007 gkrellm_alert_set_delay(alert, n / alert->delay_step);
1008 }
1009 alert->activated = TRUE;
1010
1011 for (plist = alert_plugin_list; plist; plist = plist->next)
1012 {
1013 data = NULL;
1014 gap = (GkrellmAlertPlugin *) plist->data;
1015 for (list = alert->plugin_list; list; list = list->next)
1016 {
1017 apl = (GkrellmAlertPluginLink *) list->data;
1018 if (apl->alert_plugin == gap)
1019 {
1020 data = apl->data;
1021 break;
1022 }
1023 }
1024 if (MONITOR_ENABLED(gap->mon) && gap->config_apply_func)
1025 (*gap->config_apply_func)(alert, data, alert->config_closing);
1026 }
1027
1028 gtk_widget_set_sensitive(alert->delete_button, alert->activated);
1029 gtk_widget_set_sensitive(alert->icon_box, alert->activated);
1030 if (alert->cb_config)
1031 (*alert->cb_config)(alert, alert->cb_config_data);
1032 gkrellm_config_modified();
1033 }
1034
1035 static void
alert_ok(GtkWidget * widget,GkrellmAlert ** ap)1036 alert_ok(GtkWidget *widget, GkrellmAlert **ap)
1037 {
1038 (*ap)->config_closing = TRUE;
1039 alert_apply(NULL, ap);
1040 alert_close(NULL, ap);
1041 }
1042
1043 static void
cb_delay_spin_changed(GtkAdjustment * adjustment,GkrellmAlert * alert)1044 cb_delay_spin_changed(GtkAdjustment *adjustment, GkrellmAlert *alert)
1045 {
1046 GtkSpinButton *spin;
1047 gint delay;
1048
1049 spin = GTK_SPIN_BUTTON(alert->delay_spin_button);
1050 delay = gtk_spin_button_get_value_as_int(spin);
1051 if ((delay % alert->delay_step) != 0)
1052 {
1053 delay = delay / alert->delay_step * alert->delay_step;
1054 gtk_spin_button_set_value(spin, delay);
1055 }
1056 alert->config_modified = TRUE;
1057 gtk_widget_set_sensitive(alert->icon_box, TRUE);
1058 }
1059
1060 static void
cb_high_alarm_spin_changed(GtkAdjustment * adjustment,GkrellmAlert * alert)1061 cb_high_alarm_spin_changed(GtkAdjustment *adjustment, GkrellmAlert *alert)
1062 {
1063 GtkSpinButton *spin;
1064 gfloat alarm, warn;
1065
1066 spin = GTK_SPIN_BUTTON(alert->high.alarm_limit_spin_button);
1067 alarm = gtk_spin_button_get_value(spin);
1068 spin = GTK_SPIN_BUTTON(alert->high.warn_limit_spin_button);
1069 warn = gtk_spin_button_get_value(spin);
1070 if (alarm < warn)
1071 gtk_spin_button_set_value(spin, alarm);
1072 alert->config_modified = TRUE;
1073 gtk_widget_set_sensitive(alert->icon_box, TRUE);
1074 }
1075
1076 static void
cb_high_warn_spin_changed(GtkWidget * adjustment,GkrellmAlert * alert)1077 cb_high_warn_spin_changed(GtkWidget *adjustment, GkrellmAlert *alert)
1078 {
1079 GtkSpinButton *spin;
1080 gfloat alarm, warn, low_warn;
1081
1082 spin = GTK_SPIN_BUTTON(alert->high.warn_limit_spin_button);
1083 warn = gtk_spin_button_get_value(spin);
1084 spin = GTK_SPIN_BUTTON(alert->high.alarm_limit_spin_button);
1085 alarm = gtk_spin_button_get_value(spin);
1086 if (alarm < warn)
1087 gtk_spin_button_set_value(spin, warn);
1088 if (alert->check_low)
1089 {
1090 spin = GTK_SPIN_BUTTON(alert->low.warn_limit_spin_button);
1091 low_warn = gtk_spin_button_get_value(spin);
1092 if (low_warn > warn)
1093 gtk_spin_button_set_value(spin, warn);
1094 }
1095 alert->config_modified = TRUE;
1096 gtk_widget_set_sensitive(alert->icon_box, TRUE);
1097 }
1098
1099 static void
cb_low_warn_spin_changed(GtkWidget * adjustment,GkrellmAlert * alert)1100 cb_low_warn_spin_changed(GtkWidget *adjustment, GkrellmAlert *alert)
1101 {
1102 GtkSpinButton *spin;
1103 gfloat alarm, warn, high_warn;
1104
1105 spin = GTK_SPIN_BUTTON(alert->low.warn_limit_spin_button);
1106 warn = gtk_spin_button_get_value(spin);
1107 spin = GTK_SPIN_BUTTON(alert->low.alarm_limit_spin_button);
1108 alarm = gtk_spin_button_get_value(spin);
1109 if (alarm > warn)
1110 gtk_spin_button_set_value(spin, warn);
1111 if (alert->check_high)
1112 {
1113 spin = GTK_SPIN_BUTTON(alert->high.warn_limit_spin_button);
1114 high_warn = gtk_spin_button_get_value(spin);
1115 if (high_warn < warn)
1116 gtk_spin_button_set_value(spin, warn);
1117 }
1118 alert->config_modified = TRUE;
1119 gtk_widget_set_sensitive(alert->icon_box, TRUE);
1120 }
1121
1122 static void
cb_low_alarm_spin_changed(GtkWidget * adjustment,GkrellmAlert * alert)1123 cb_low_alarm_spin_changed(GtkWidget *adjustment, GkrellmAlert *alert)
1124 {
1125 GtkSpinButton *spin;
1126 gfloat alarm, warn;
1127
1128 spin = GTK_SPIN_BUTTON(alert->low.alarm_limit_spin_button);
1129 alarm = gtk_spin_button_get_value(spin);
1130 spin = GTK_SPIN_BUTTON(alert->low.warn_limit_spin_button);
1131 warn = gtk_spin_button_get_value(spin);
1132 if (alarm > warn)
1133 gtk_spin_button_set_value(spin, alarm);
1134 alert->config_modified = TRUE;
1135 gtk_widget_set_sensitive(alert->icon_box, TRUE);
1136 }
1137
1138 void
gkrellm_alert_config_window(GkrellmAlert ** ap)1139 gkrellm_alert_config_window(GkrellmAlert **ap)
1140 {
1141 GtkWidget *tabs;
1142 GtkWidget *main_vbox, *tab_vbox, *vbox, *vbox1 = NULL;
1143 GtkWidget *hbox, *hbox1, *image;
1144 GtkWidget *table = NULL;
1145 GtkWidget *button;
1146 GtkWidget *label;
1147 GtkWidget *separator;
1148 GList *plist, *list;
1149 GkrellmAlert *alert;
1150 GkrellmAlertPlugin *gap;
1151 GkrellmAlertPluginLink *apl;
1152 gpointer data;
1153 gchar *title;
1154 gint w, n_tabs = 1;
1155
1156 if (!ap || !*ap)
1157 return;
1158 alert = *ap;
1159 if (!alert->config_window)
1160 {
1161 alert->config_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1162 g_signal_connect(G_OBJECT(alert->config_window), "delete_event",
1163 G_CALLBACK(alert_config_window_delete_event), ap);
1164 gtk_window_set_title(GTK_WINDOW(alert->config_window),
1165 _("GKrellM Set Alerts"));
1166 gtk_window_set_wmclass(GTK_WINDOW(alert->config_window),
1167 "Gkrellm_conf", "Gkrellm");
1168
1169 gtk_container_set_border_width(GTK_CONTAINER(alert->config_window), 4);
1170 main_vbox = gtk_vbox_new(FALSE, 0);
1171 gtk_container_add(GTK_CONTAINER(alert->config_window), main_vbox);
1172
1173 tabs = gtk_notebook_new();
1174 gtk_box_pack_start(GTK_BOX(main_vbox), tabs, TRUE, TRUE, 0);
1175 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
1176
1177 tab_vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Alerts"));
1178
1179 if (alert->name && alert->unit_string)
1180 title = g_strdup_printf("%s - %s",
1181 alert->name, alert->unit_string);
1182 else if (alert->name)
1183 title = g_strdup_printf("%s", alert->name);
1184 else
1185 title = g_strdup_printf("%s", alert->unit_string);
1186
1187 vbox = gkrellm_gtk_framed_vbox(tab_vbox, title, 4, FALSE, 4, 3);
1188 g_free(title);
1189
1190 hbox = gtk_hbox_new(FALSE, 0);
1191 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1192 w = 70;
1193 if (alert->max_high > 100000)
1194 w += log(alert->max_high / 100000) * 5;
1195
1196 alert->high.alarm_limit_spin_button = NULL;
1197 alert->high.warn_limit_spin_button = NULL;
1198 if (alert->check_high && !alert->check_hardwired)
1199 {
1200 vbox1 = gkrellm_gtk_framed_vbox(hbox, _("High Limits"),
1201 2, FALSE, 2,2);
1202 gkrellm_gtk_spin_button(vbox1,
1203 &alert->high.alarm_limit_spin_button,
1204 alert->high.alarm_limit, alert->min_low, alert->max_high,
1205 alert->step0, alert->step1,
1206 alert->digits, w, cb_high_alarm_spin_changed, alert, FALSE,
1207 _("High alarm limit"));
1208
1209 gkrellm_gtk_spin_button(vbox1, &alert->high.warn_limit_spin_button,
1210 alert->high.warn_limit, alert->min_low, alert->max_high,
1211 alert->step0, alert->step1,
1212 alert->digits, w, cb_high_warn_spin_changed, alert, FALSE,
1213 _("High warn limit"));
1214 }
1215
1216 alert->low.alarm_limit_spin_button = NULL;
1217 alert->low.warn_limit_spin_button = NULL;
1218 if (alert->check_low && !alert->check_hardwired)
1219 {
1220 vbox1 = gkrellm_gtk_framed_vbox_end(hbox, _("Low Limits"),
1221 2, FALSE, 2, 2);
1222 gkrellm_gtk_spin_button(vbox1, &alert->low.warn_limit_spin_button,
1223 alert->low.warn_limit, alert->min_low, alert->max_high,
1224 alert->step0, alert->step1,
1225 alert->digits, w, cb_low_warn_spin_changed, alert, FALSE,
1226 _("Low warn limit"));
1227 gkrellm_gtk_spin_button(vbox1, &alert->low.alarm_limit_spin_button,
1228 alert->low.alarm_limit, alert->min_low, alert->max_high,
1229 alert->step0, alert->step1,
1230 alert->digits, w, cb_low_alarm_spin_changed, alert, FALSE,
1231 _("Low alarm limit"));
1232 }
1233 if (alert->delay_step > 0)
1234 {
1235 vbox1 = gkrellm_gtk_framed_vbox(vbox, NULL, 2, FALSE, 2, 2);
1236 gkrellm_gtk_spin_button(vbox1, &alert->delay_spin_button,
1237 alert->delay * alert->delay_step,
1238 alert->delay_low, alert->delay_high,
1239 alert->delay_step, alert->delay_step,
1240 0, 70, cb_delay_spin_changed, alert, FALSE,
1241 _("Seconds limit conditions must exist to have an alert"));
1242 }
1243 if (alert->cb_config_create)
1244 {
1245 vbox1 = gkrellm_gtk_framed_vbox(vbox, NULL, 2, FALSE, 2, 2);
1246 (*alert->cb_config_create)(alert, vbox1,
1247 alert->cb_config_create_data);
1248 }
1249
1250 if (alert->do_alarm_command || alert->do_warn_command)
1251 {
1252 vbox1 = gkrellm_gtk_framed_vbox(vbox,
1253 _("Commands - with repeat intervals in seconds"),
1254 2, FALSE, 2, 2);
1255 table = gtk_table_new(3 /* across */, 3 /* down */, FALSE);
1256 gtk_table_set_col_spacings(GTK_TABLE(table), 4);
1257 gtk_box_pack_start(GTK_BOX(vbox1), table, FALSE, FALSE, 0);
1258 }
1259
1260 alert->alarm_command_entry = alert->alarm_repeat_spin_button = NULL;
1261 if (alert->do_alarm_command)
1262 {
1263 label = gtk_label_new(_("Alarm command:"));
1264 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
1265 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
1266 alert->alarm_command_entry = gtk_entry_new();
1267 gtk_entry_set_max_length(GTK_ENTRY(alert->alarm_command_entry),
1268 255);
1269 gtk_table_attach_defaults(GTK_TABLE(table),
1270 alert->alarm_command_entry, 1, 2, 0, 1);
1271 gtk_entry_set_text(GTK_ENTRY(alert->alarm_command_entry),
1272 alert->alarm_command);
1273 gkrellm_gtk_spin_button(NULL, &alert->alarm_repeat_spin_button,
1274 alert->alarm_repeat_set, 0, 1000,
1275 1, 10, 0, 60, NULL, NULL, FALSE, NULL);
1276 gtk_table_attach_defaults(GTK_TABLE(table),
1277 alert->alarm_repeat_spin_button, 2, 3, 0, 1);
1278 }
1279
1280 alert->warn_command_entry = alert->warn_repeat_spin_button = NULL;
1281 if (alert->do_warn_command)
1282 {
1283 label = gtk_label_new(_("Warn command:"));
1284 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
1285 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
1286 alert->warn_command_entry = gtk_entry_new();
1287 gtk_entry_set_max_length(GTK_ENTRY(alert->warn_command_entry),
1288 255);
1289 gtk_table_attach_defaults(GTK_TABLE(table),
1290 alert->warn_command_entry, 1, 2, 1, 2);
1291 gtk_entry_set_text(GTK_ENTRY(alert->warn_command_entry),
1292 alert->warn_command);
1293 gtk_widget_set_size_request(alert->warn_command_entry, 300, -1);
1294 gkrellm_gtk_spin_button(NULL, &alert->warn_repeat_spin_button,
1295 alert->warn_repeat_set, 0, 1000,
1296 1, 10, 0, 60, NULL, NULL, FALSE, NULL);
1297 gtk_table_attach_defaults(GTK_TABLE(table),
1298 alert->warn_repeat_spin_button, 2, 3, 1, 2);
1299 }
1300
1301 if (alert->do_alarm_command || alert->do_warn_command)
1302 {
1303 separator = gtk_hseparator_new();
1304 gtk_box_pack_start(GTK_BOX(vbox1), separator, FALSE, FALSE, 4);
1305
1306 label = gtk_label_new(
1307 _("A repeat of zero seconds executes the command once per alert."));
1308 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1309 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
1310 gtk_box_pack_start(GTK_BOX(vbox1), label, FALSE, FALSE, 0);
1311 }
1312
1313 for (plist = alert_plugin_list; plist; plist = plist->next)
1314 {
1315 data = NULL;
1316 gap = (GkrellmAlertPlugin *) plist->data;
1317 for (list = alert->plugin_list; list; list = list->next)
1318 {
1319 apl = (GkrellmAlertPluginLink *) list->data;
1320 if (apl->alert_plugin == gap)
1321 {
1322 data = apl->data;
1323 break;
1324 }
1325 }
1326 if (MONITOR_ENABLED(gap->mon) && gap->config_create_func)
1327 {
1328 tab_vbox = gkrellm_gtk_framed_notebook_page(tabs,
1329 gap->tab_name);
1330 (*gap->config_create_func)(tab_vbox, alert, data);
1331 ++n_tabs;
1332 }
1333 }
1334
1335 if (n_tabs == 1)
1336 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(tabs), FALSE);
1337
1338 alert->icon_box = gtk_event_box_new();
1339 hbox1 = gtk_hbox_new(FALSE, 0);
1340 gtk_box_pack_start(GTK_BOX(main_vbox), hbox1, FALSE, FALSE, 0);
1341 gtk_box_pack_start(GTK_BOX(hbox1), alert->icon_box, TRUE, FALSE, 0);
1342 image = gtk_image_new_from_pixbuf(gkrellm_alert_pixbuf());
1343 gtk_container_add(GTK_CONTAINER(alert->icon_box), image);
1344 gtk_widget_set_sensitive(alert->icon_box, alert->activated);
1345
1346 hbox = gtk_hbutton_box_new();
1347 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
1348 gtk_box_set_spacing(GTK_BOX(hbox), 5);
1349 gtk_box_pack_end(GTK_BOX(hbox1), hbox, FALSE, FALSE, 0);
1350
1351 alert->delete_button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1352 GTK_WIDGET_SET_FLAGS(alert->delete_button, GTK_CAN_DEFAULT);
1353 g_signal_connect(G_OBJECT(alert->delete_button), "clicked",
1354 G_CALLBACK(alert_delete), ap);
1355 gtk_box_pack_start(GTK_BOX(hbox), alert->delete_button, TRUE, TRUE, 0);
1356 gtk_widget_set_sensitive(alert->delete_button, alert->activated);
1357
1358 button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
1359 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1360 g_signal_connect(G_OBJECT(button), "clicked",
1361 G_CALLBACK(alert_apply), ap);
1362 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
1363
1364 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
1365 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1366 g_signal_connect(G_OBJECT(button), "clicked",
1367 G_CALLBACK(alert_close), ap);
1368 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
1369
1370 button = gtk_button_new_from_stock(GTK_STOCK_OK);
1371 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1372 g_signal_connect(G_OBJECT(button), "clicked",
1373 G_CALLBACK(alert_ok), ap);
1374 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
1375 gtk_widget_grab_default(button);
1376
1377 gtk_widget_show_all(alert->config_window);
1378 }
1379 else
1380 gtk_window_present(GTK_WINDOW(alert->config_window));
1381 alert->config_closing = FALSE;
1382 }
1383
1384 void
gkrellm_save_alertconfig(FILE * f,GkrellmAlert * alert,gchar * mon_keyword,gchar * name)1385 gkrellm_save_alertconfig(FILE *f, GkrellmAlert *alert,
1386 gchar *mon_keyword, gchar *name)
1387 {
1388 GList *list;
1389 GkrellmAlertPlugin *gap;
1390 GkrellmAlertPluginLink *apl;
1391 gchar *s, *p;
1392
1393 if (!f || !alert || !mon_keyword)
1394 return;
1395 if (name)
1396 s = g_strdup_printf("%s %s %s ", mon_keyword,
1397 GKRELLM_ALERTCONFIG_KEYWORD, name);
1398 else
1399 s = g_strdup_printf("%s %s ", mon_keyword,GKRELLM_ALERTCONFIG_KEYWORD);
1400
1401 if (alert->alarm_command && *alert->alarm_command)
1402 fprintf(f, "%s alarm_command %s\n", s, alert->alarm_command);
1403 if (alert->warn_command && *alert->warn_command)
1404 fprintf(f, "%s warn_command %s\n", s, alert->warn_command);
1405 fprintf(f, "%s values %d %d %d %d\n", s, alert->do_panel_updates,
1406 alert->check_high, alert->check_low, alert->check_hardwired);
1407 fprintf(f, "%s repeat %d %d\n", s, alert->alarm_repeat_set,
1408 alert->warn_repeat_set);
1409
1410 /* 2.1.15: scale saved float values to avoid decimal points in the config
1411 | because of locale breakage if decimal point changes '.' <-> ',"
1412 */
1413 fprintf(f, "%s limits %.0f %.0f %.0f %.0f\n", s,
1414 alert->high.alarm_limit * GKRELLM_FLOAT_FACTOR,
1415 alert->high.warn_limit * GKRELLM_FLOAT_FACTOR,
1416 alert->low.warn_limit * GKRELLM_FLOAT_FACTOR,
1417 alert->low.alarm_limit * GKRELLM_FLOAT_FACTOR);
1418 if (alert->delay_step > 0)
1419 fprintf(f, "%s delay %d %d %d %d\n", s, alert->delay,
1420 alert->delay_high, alert->delay_low, alert->delay_step);
1421
1422 /* name can be quoted, but the id_string should not have embedded quotes.
1423 | id_string is so a plugin can get a unique config name for an alert
1424 */
1425 g_free(alert->id_string);
1426 p = name;
1427 if (p && *p == '"')
1428 ++p;
1429 alert->id_string = g_strconcat(mon_keyword, p ? "-" : NULL, p, NULL);
1430 if ((p = strrchr(alert->id_string, '"')) != NULL)
1431 *p = '\0';
1432 for (p = alert->id_string; *p; ++p)
1433 if (*p == '/' || *p == ' ')
1434 *p = '-';
1435 fprintf(f, "%s id_string %s\n", s, alert->id_string);
1436
1437 for (list = alert->plugin_list; list; list = list->next)
1438 {
1439 apl = (GkrellmAlertPluginLink *) list->data;
1440 gap = apl->alert_plugin;
1441 if (MONITOR_ENABLED(gap->mon) && gap->config_save_func)
1442 {
1443 p = g_strconcat(s, "plugin ", gap->name, NULL);
1444 (*gap->config_save_func)(alert, apl->data, f, p, alert->id_string);
1445 g_free(p);
1446 }
1447 }
1448 g_free(s);
1449 }
1450
1451 void
gkrellm_load_alertconfig(GkrellmAlert ** ap,gchar * config_line)1452 gkrellm_load_alertconfig(GkrellmAlert **ap, gchar *config_line)
1453 {
1454 GList *list;
1455 GkrellmAlert *alert;
1456 GkrellmAlertPlugin *gap;
1457 gchar config[32], item[CFG_BUFSIZE];
1458 gchar name[64], item1[CFG_BUFSIZE];
1459 gint n;
1460
1461 if (!ap || !config_line)
1462 return;
1463 if (!*ap)
1464 *ap = g_new0(GkrellmAlert, 1);
1465 alert = *ap;
1466
1467 n = sscanf(config_line, "%31s %[^\n]", config, item);
1468 if (n != 2)
1469 return;
1470
1471 if (!strcmp(config, "alarm_command"))
1472 gkrellm_dup_string(&alert->alarm_command, item);
1473 else if (!strcmp(config, "warn_command"))
1474 gkrellm_dup_string(&alert->warn_command, item);
1475 else if (!strcmp(config, "values"))
1476 sscanf(item, "%d %d %d %d", &alert->do_panel_updates,
1477 &alert->check_high, &alert->check_low, &alert->check_hardwired);
1478 else if (!strcmp(config, "delay"))
1479 {
1480 sscanf(item, "%d %d %d %d", &n,
1481 &alert->delay_high, &alert->delay_low, &alert->delay_step);
1482 gkrellm_alert_set_delay(alert, n);
1483 }
1484 else if (!strcmp(config, "repeat"))
1485 sscanf(item, "%d %d", &alert->alarm_repeat_set,
1486 &alert->warn_repeat_set);
1487 else if (!strcmp(config, "limits"))
1488 {
1489 sscanf(item, "%f %f %f %f",
1490 &alert->high.alarm_limit, &alert->high.warn_limit,
1491 &alert->low.warn_limit, &alert->low.alarm_limit);
1492
1493 alert->high.alarm_limit /= _GK.float_factor;
1494 alert->high.warn_limit /= _GK.float_factor;
1495 alert->low.warn_limit /= _GK.float_factor;
1496 alert->low.alarm_limit /= _GK.float_factor;
1497 }
1498 else if (!strcmp(config, "id_string"))
1499 {
1500 gkrellm_dup_string(&alert->id_string, item);
1501 for (list = alert_plugin_list; list; list = list->next)
1502 {
1503 gap = (GkrellmAlertPlugin *) list->data;
1504 if (MONITOR_ENABLED(gap->mon) && gap->config_load_func)
1505 (*gap->config_load_func)(alert, "id_string", alert->id_string);
1506 }
1507 }
1508 else if (!strcmp(config, "plugin"))
1509 {
1510 if (sscanf(item, "%63s %[^\n]", name, item1) == 2)
1511 {
1512 for (list = alert_plugin_list; list; list = list->next)
1513 {
1514 gap = (GkrellmAlertPlugin *) list->data;
1515 if (!strcmp(name, gap->name))
1516 {
1517 if (MONITOR_ENABLED(gap->mon) && gap->config_load_func)
1518 (*gap->config_load_func)(alert,
1519 item1, alert->id_string);
1520 break;
1521 }
1522 }
1523 }
1524 }
1525 alert->activated = TRUE;
1526 }
1527
1528
1529 /* ------------------------------------------------------------------- */
1530 /* gdk-pixbuf-csource --static --raw alert_inline.png */
1531
1532 /* GdkPixbuf RGBA C-Source image dump 1-byte-run-length-encoded */
1533
1534 /*
1535 | pixdata = new GdkPixbuf.Pixdata({
1536 | magic
1537 | length
1538 | pixdata_type
1539 | rowstride
1540 | width
1541 | height
1542 | pixel_data
1543 */
1544
1545 /* GdkPixbuf RGBA C-Source image dump */
1546
1547 static const guint8 alert_inline[] =
1548 { ""
1549 /* Pixbuf magic (0x47646b50) */
1550 "GdkP"
1551 /* length: header (24) + pixel_data (1296) */
1552 "\0\0\5("
1553 /* pixdata_type (0x1010002) */
1554 "\1\1\0\2"
1555 /* rowstride (72) */
1556 "\0\0\0H"
1557 /* width (18) */
1558 "\0\0\0\22"
1559 /* height (18) */
1560 "\0\0\0\22"
1561 /* pixel_data: */
1562 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1563 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1564 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\204}{\377B89\377\20"
1565 "\24\20\377\10\2\10\377\0\2\0\377\30\24\20\3779<9\377\214\212\204\377"
1566 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1567 "\0\0e`T\37732*\377\202]@\377\251eF\377\267g\77\377\265cF\377\243eG\377"
1568 "\202VG\37773$\377io`\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1569 "\0\0\0\0\0\0PVG\377a<*\377\257^\77\377\310\211q\377\333\262\241\377\222"
1570 "\202t\377\311\254\234\377\333\262\233\377\310\211q\377\257^\77\377Z="
1571 "+\377\\bM\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0cfS\377Z=+\377\257"
1572 "^\77\377\320\234\203\377\333\270\241\377\252\217}\377\31\25\23\3772*"
1573 "%\377\342\274\251\377\333\270\241\377\320\234\203\377\257^\77\377Z=+"
1574 "\377|~k\377\0\0\0\0\0\0\0\0\0\0\0\0\204\206{\37773$\377\251_\77\377\301"
1575 "\202b\377\325\253\222\377\341\255\233\377aNE\377\222tb\377\0\0\0\377"
1576 "\310\232\211\377\333\257\233\377\325\253\222\377\302{h\377\251Z\77\377"
1577 "73$\377\0\0\0\0\0\0\0\0\0\0\0\0JAB\377xQ1\377\257[\77\377\320\234\203"
1578 "\377\325\234\203\377\333\236\205\3770#\35\377\333\236\205\377\30\21\17"
1579 "\377aF;\377\325\234\203\377\325\234\203\377\310\222u\377\257[\77\377"
1580 "tJ1\377kik\377\0\0\0\0\0\0\0\0\20\24\20\377\235[G\377\257[\77\377\317"
1581 "\212p\377\325\215u\377vOA\377vOA\377\325\215u\377vM>\377\0\0\0\377\325"
1582 "\213q\377\317\212p\377\317\213v\377\260T8\377\235[G\377)$)\377\0\0\0"
1583 "\0\0\0\0\0\0\2\0\377\251Z\77\377\267X\77\377\310q\\\377\310{c\377.\32"
1584 "\25\377\270lW\377\316z\\\377sA6\377\0\0\0\377sA6\377\317vb\377\301mV"
1585 "\377\257Q\77\377\245R8\377\10\2\10\377\0\0\0\0\0\0\0\0\0\2\0\377\251"
1586 "S\77\377\260T8\377\277N9\377\226M9\377,\25\21\377\205@4\377\205@4\377"
1587 "\200B4\377,\25\21\377+\26\20\377\277N9\377\270K9\377\252M8\377\237N8"
1588 "\377\10\2\10\377\0\0\0\0\0\0\0\0\30\24\30\377\230Y@\377\252S8\377\267"
1589 "R\77\377T)\34\377\200>.\377\300]F\377\307[F\377\300]F\377\200<.\377\0"
1590 "\0\0\377\221J<\377\260L8\377\245J8\377\230VG\377!(!\377\0\0\0\0\0\0\0"
1591 "\0""9<1\377xO@\377\245J8\377\227D1\377\0\0\0\377\266S8\377\302Q\77\377"
1592 "\274S\77\377\274S\77\377\274S\77\377\0\0\0\377N\37\31\377\252F8\377\236"
1593 "F2\377~N@\377cic\377\0\0\0\0\0\0\0\0\234\216\224\37773$\377\237G8\377"
1594 "\22\10\6\377\0\0\0\377N\40\26\377\242\77""1\377\257I2\377\266G8\377N"
1595 "\40\26\377\0\0\0\377\0\0\0\377F\37\26\377\231D9\37773$\377\0\0\0\0\0"
1596 "\0\0\0\0\0\0\0\0\0\0\0ii`\377T3#\377\231E2\377\237G8\377\252F8\377\251"
1597 "B2\377\251B2\377\251B2\377\252F8\377\236@2\377\231@2\377\231E2\377N6"
1598 "#\377{\204q\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0baY\377T3#\377"
1599 "\223D2\377\231E2\377\236@2\377\236@2\377\237<6\377\231E2\377\231@2\377"
1600 "\223@2\377T3#\377ii`\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1601 "\0\0\0\0\0\0t}j\377-4#\377~N@\377\216K9\377\223@2\377\223@2\377\222K"
1602 "@\377xO@\37773$\377{\204q\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1603 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0kik\377!(!\377\10\2\10\377\0"
1604 "\2\0\377)$)\377kik\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1605 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1606 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
1607 "\0\0\0\0\0"};
1608
1609
1610 static GdkPixbuf *alert_pixbuf;
1611
1612 GdkPixbuf *
gkrellm_alert_pixbuf(void)1613 gkrellm_alert_pixbuf(void)
1614 {
1615 guint8 *data = (guint8 *) alert_inline;
1616 guint width, height, stride;
1617 gpointer pixels;
1618
1619 if (!alert_pixbuf)
1620 {
1621 // alert_pixbuf = gdk_pixbuf_new_from_inline(-1, alert_inline,
1622 // FALSE, NULL);
1623 stride = big_endian_uint(data + 12);
1624 width = big_endian_uint(data + 16);
1625 height = big_endian_uint(data + 20);
1626
1627 pixels = g_memdup((gconstpointer)(data + 24), height * stride);
1628
1629 alert_pixbuf = gdk_pixbuf_new_from_data(pixels,
1630 GDK_COLORSPACE_RGB, TRUE, 8, width, height, stride,
1631 (GdkPixbufDestroyNotify) g_free, pixels);
1632 }
1633 return alert_pixbuf;
1634 }
1635