Merge branch 'collectd-5.7'
[collectd.git] / src / notify_desktop.c
1 /**
2  * collectd - src/notify_desktop.c
3  * Copyright (C) 2008       Sebastian Harl
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Sebastian Harl <sh at tokkee.org>
25  **/
26
27 /*
28  * This plugin sends desktop notifications to a notification daemon.
29  */
30
31 #include "collectd.h"
32
33 #include "common.h"
34 #include "plugin.h"
35
36 #include <glib.h>
37 #include <libnotify/notify.h>
38
39 #ifndef NOTIFY_CHECK_VERSION
40 #define NOTIFY_CHECK_VERSION(x, y, z) 0
41 #endif
42
43 #define log_info(...) INFO("notify_desktop: " __VA_ARGS__)
44 #define log_warn(...) WARNING("notify_desktop: " __VA_ARGS__)
45 #define log_err(...) ERROR("notify_desktop: " __VA_ARGS__)
46
47 #define DEFAULT_TIMEOUT 5000
48
49 static int okay_timeout = DEFAULT_TIMEOUT;
50 static int warn_timeout = DEFAULT_TIMEOUT;
51 static int fail_timeout = DEFAULT_TIMEOUT;
52
53 static int set_timeout(oconfig_item_t *ci, int *timeout) {
54   if ((0 != ci->children_num) || (1 != ci->values_num) ||
55       (OCONFIG_TYPE_NUMBER != ci->values[0].type)) {
56     log_err("%s expects a single number argument.", ci->key);
57     return 1;
58   }
59
60   *timeout = (int)ci->values[0].value.number;
61   if (0 > *timeout)
62     *timeout = DEFAULT_TIMEOUT;
63   return 0;
64 } /* set_timeout */
65
66 static int c_notify_config(oconfig_item_t *ci) {
67   for (int i = 0; i < ci->children_num; ++i) {
68     oconfig_item_t *c = ci->children + i;
69
70     if (0 == strcasecmp(c->key, "OkayTimeout"))
71       set_timeout(c, &okay_timeout);
72     else if (0 == strcasecmp(c->key, "WarningTimeout"))
73       set_timeout(c, &warn_timeout);
74     else if (0 == strcasecmp(c->key, "FailureTimeout"))
75       set_timeout(c, &fail_timeout);
76   }
77   return 0;
78 } /* c_notify_config */
79
80 static int c_notify(const notification_t *n,
81                     user_data_t __attribute__((unused)) * user_data) {
82   NotifyNotification *notification = NULL;
83   NotifyUrgency urgency = NOTIFY_URGENCY_LOW;
84   int timeout = okay_timeout;
85
86   char summary[1024];
87
88   if (NOTIF_WARNING == n->severity) {
89     urgency = NOTIFY_URGENCY_NORMAL;
90     timeout = warn_timeout;
91   } else if (NOTIF_FAILURE == n->severity) {
92     urgency = NOTIFY_URGENCY_CRITICAL;
93     timeout = fail_timeout;
94   }
95
96   ssnprintf(summary, sizeof(summary), "collectd %s notification",
97             (NOTIF_FAILURE == n->severity)
98                 ? "FAILURE"
99                 : (NOTIF_WARNING == n->severity)
100                       ? "WARNING"
101                       : (NOTIF_OKAY == n->severity) ? "OKAY" : "UNKNOWN");
102
103   notification = notify_notification_new(summary, n->message, NULL
104 #if NOTIFY_CHECK_VERSION(0, 7, 0)
105                                          );
106 #else
107                                          ,
108                                          NULL);
109 #endif
110   if (NULL == notification) {
111     log_err("Failed to create a new notification.");
112     return -1;
113   }
114
115   notify_notification_set_urgency(notification, urgency);
116   notify_notification_set_timeout(notification, timeout);
117
118   if (!notify_notification_show(notification, NULL))
119     log_err("Failed to display notification.");
120
121   g_object_unref(G_OBJECT(notification));
122   return 0;
123 } /* c_notify */
124
125 static int c_notify_shutdown(void) {
126   plugin_unregister_init("notify_desktop");
127   plugin_unregister_notification("notify_desktop");
128   plugin_unregister_shutdown("notify_desktop");
129
130   if (notify_is_initted())
131     notify_uninit();
132   return 0;
133 } /* c_notify_shutdown */
134
135 static int c_notify_init(void) {
136   char *name = NULL;
137   char *vendor = NULL;
138   char *version = NULL;
139   char *spec_version = NULL;
140
141   if (!notify_init(PACKAGE_STRING)) {
142     log_err("Failed to initialize libnotify.");
143     return -1;
144   }
145
146   if (!notify_get_server_info(&name, &vendor, &version, &spec_version))
147     log_warn("Failed to get the notification server info. "
148              "Check if you have a notification daemon running.");
149   else {
150     log_info("Found notification daemon: %s (%s) %s (spec version %s)", name,
151              vendor, version, spec_version);
152     free(name);
153     free(vendor);
154     free(version);
155     free(spec_version);
156   }
157
158   plugin_register_notification("notify_desktop", c_notify,
159                                /* user_data = */ NULL);
160   plugin_register_shutdown("notify_desktop", c_notify_shutdown);
161   return 0;
162 } /* c_notify_init */
163
164 void module_register(void) {
165   plugin_register_complex_config("notify_desktop", c_notify_config);
166   plugin_register_init("notify_desktop", c_notify_init);
167   return;
168 } /* module_register */