]> gitweb.michael.orlitzky.com - xfce4-hdaps.git/blob - panel-plugin/xfce4-hdaps.c
8dbc74d1765dcbd997f7f999f7736faa962ba283
[xfce4-hdaps.git] / panel-plugin / xfce4-hdaps.c
1 /*
2 * xfce4-hdaps, an XFCE4 panel plugin for the HDAPS system.
3 *
4 * Copyright Michael Orlitzky
5 *
6 * http://michael.orlitzky.com/
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it 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 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * http://www.fsf.org/licensing/licenses/gpl.html
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include "xfce4-hdaps.h"
26 #include "xfce4-hdaps-dialogs.h"
27
28 /* We need a default device. Since we require kernels
29 newer than 2.6.28, it's probably sdX, and I'm guessing
30 that sda is most likely. */
31 #define DEFAULT_DEVICE_NAME "sda"
32
33 /* How often do we poll, in milliseconds?
34 This should be configured, but we set the default here. */
35 #define DEFAULT_POLL_FREQUENCY 500
36
37
38 /* Prototype, needed to register below. */
39 static void hdaps_construct(XfcePanelPlugin *plugin);
40
41 /* Register the plugin with the panel. */
42 XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL(hdaps_construct);
43
44
45 void hdaps_save(XfcePanelPlugin *plugin, HdapsPlugin *hdaps) {
46
47 XfceRc *rc;
48 gchar *file;
49
50 /* Get the config file location. XFCE should know this. */
51 file = xfce_panel_plugin_save_location(plugin, TRUE);
52
53 if (G_UNLIKELY(file == NULL)) {
54 DBG("Failed to find the configuration file. Bailing.");
55 return;
56 }
57
58 /* Open the config file read/write. */
59 rc = xfce_rc_simple_open(file, FALSE);
60
61 /* And we can free the file path now that we've
62 opened the file. */
63 g_free(file);
64
65 if (G_UNLIKELY(rc == NULL)) {
66 DBG("Failed to open the configuration file. Bailing.");
67 return;
68 }
69
70
71 /* Write any user-configured values to the resource file. */
72 if (hdaps->device_name) {
73 xfce_rc_write_entry(rc, "device_name", hdaps->device_name);
74 }
75
76 xfce_rc_write_int_entry(rc, "poll_frequency", hdaps->poll_frequency);
77
78 /* close the rc file */
79 xfce_rc_close(rc);
80 }
81
82
83
84 void hdaps_set_icon(HdapsPlugin *hdaps, int status) {
85 GdkPixbuf *icon;
86 gint size;
87
88 /* Panel info magic. */
89 size = xfce_panel_plugin_get_size(hdaps->plugin) - 6;
90
91 /* Try to load an icon from the current icon theme. */
92 if (status == HDAPS_ERROR) {
93 /* Error */
94 icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
95 "emblem-noread",
96 size, 0, NULL);
97 }
98 else if (status == HDAPS_OFF) {
99 icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
100 "drive-harddisk",
101 size, 0, NULL);
102 }
103 else {
104 /* status > HDAPS_OFF means it's on. */
105 icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
106 "emblem-nowrite",
107 size, 0, NULL);
108 }
109
110 /* Get rid of the previous icon. */
111 if (hdaps->icon) {
112 gtk_widget_destroy(hdaps->icon);
113 }
114
115 if (icon) {
116 hdaps->icon = gtk_image_new_from_pixbuf(icon);
117 g_object_unref(G_OBJECT(icon));
118 }
119 else {
120 hdaps->icon = gtk_image_new_from_icon_name("dialog-warning", GTK_ICON_SIZE_BUTTON);
121 }
122
123 gtk_box_pack_start(GTK_BOX(hdaps->hvbox), GTK_WIDGET(hdaps->icon), FALSE, FALSE, 0);
124 gtk_widget_show(hdaps->icon);
125
126 return;
127 }
128
129
130
131 void hdaps_set_tooltip(HdapsPlugin *hdaps, int status) {
132
133 if (status == HDAPS_ERROR) {
134 gtk_tooltips_set_tip(hdaps->tooltip, hdaps->eventbox, "HDAPS Error", NULL);
135 }
136 else if (status == HDAPS_OFF) {
137 gtk_tooltips_set_tip(hdaps->tooltip, hdaps->eventbox, "HDAPS Off", NULL);
138 }
139 else {
140 gtk_tooltips_set_tip(hdaps->tooltip, hdaps->eventbox, "HDAPS On", NULL);
141 }
142 }
143
144
145 static void hdaps_set_defaults(HdapsPlugin *hdaps) {
146 DBG("Configuring all settings to defaults.");
147 hdaps->device_name = g_strdup(DEFAULT_DEVICE_NAME);
148 snprintf(hdaps->sysfs_file, FILENAME_MAX, UNLOAD_HEADS_FMT, hdaps->device_name);
149 hdaps->poll_frequency = DEFAULT_POLL_FREQUENCY;
150 }
151
152
153 static void hdaps_read(HdapsPlugin *hdaps) {
154
155 XfceRc *rc;
156 gchar *file;
157 const gchar *saved_device_name;
158
159 /* Get the plugin config file location. XFCE should know this. */
160 file = xfce_panel_plugin_save_location(hdaps->plugin, TRUE);
161
162 if (G_UNLIKELY(file == NULL)) {
163 DBG("Something went wrong getting the configuration file location.");
164 DBG("Retaining default settings.");
165 return;
166 }
167
168 /* Open the config file read-only. */
169 rc = xfce_rc_simple_open(file, TRUE);
170
171 /* Don't need this anymore if we've got a file handle. */
172 g_free(file);
173
174 if (G_UNLIKELY(rc == NULL)) {
175 DBG("There was an error opening the configuration file.");
176 DBG("Retaining default settings.");
177 return;
178 }
179
180 /* Read the settings, one at a time. */
181
182 /* We use saved_device_name here because we need
183 to dupe the string after we read it in from the
184 config file. */
185 saved_device_name = xfce_rc_read_entry(rc,
186 "device_name",
187 DEFAULT_DEVICE_NAME);
188 hdaps->device_name = g_strdup(saved_device_name);
189 snprintf(hdaps->sysfs_file, FILENAME_MAX, UNLOAD_HEADS_FMT, hdaps->device_name);
190
191 /* Integers are easier. */
192 hdaps->poll_frequency = xfce_rc_read_int_entry(rc,
193 "poll_frequency",
194 DEFAULT_POLL_FREQUENCY);
195
196 /* And close the config file. */
197 xfce_rc_close(rc);
198 }
199
200
201
202
203 static HdapsPlugin *hdaps_new(XfcePanelPlugin *plugin) {
204 HdapsPlugin *hdaps;
205 GtkOrientation orientation;
206
207 /* Allocate memory for the plugin struct, and zero it. */
208 hdaps = panel_slice_new0(HdapsPlugin);
209
210 /* The HdapsPlugin gets a copy of the XfcePanelPlugin. */
211 hdaps->plugin = plugin;
212
213 /* Set default values right before reading in the user's settings.
214 This way, hdaps_read() doesn't have to set defaults on error
215 conditions. */
216 hdaps_set_defaults(hdaps);
217
218 /* Read any user settings into the HdapsPlugin. */
219 hdaps_read(hdaps);
220
221 /* Get the current orientation. Magic. */
222 orientation = xfce_panel_plugin_get_orientation(plugin);
223
224 /* This creates the event box and shows it. This
225 is necessary to,
226
227 a) See the widget
228 b) Interact with it via right-click, etc.
229 */
230 hdaps->eventbox = gtk_event_box_new();
231 gtk_widget_show(hdaps->eventbox);
232
233 /* Set up the hvbox for the widget, which supports
234 both horizontal and vertical (hv) orientations. */
235 hdaps->hvbox = xfce_hvbox_new(orientation, FALSE, 2);
236 gtk_widget_show(hdaps->hvbox);
237 gtk_container_add(GTK_CONTAINER(hdaps->eventbox), hdaps->hvbox);
238
239 /* We only change the icon when the status has changed,
240 so it's important that they start out n*sync. */
241 hdaps->previous_status = HDAPS_OFF;
242 hdaps_set_icon(hdaps, HDAPS_OFF);
243
244 /* Create the tooltip widget, and set its initial value.
245 * The first couple of lines are stolen from the battery
246 * status plugin. I make no claim as to their correctness.
247 */
248 hdaps->tooltip = gtk_tooltips_new();
249 g_object_ref(G_OBJECT(hdaps->tooltip));
250 gtk_object_sink(GTK_OBJECT(hdaps->tooltip));
251 hdaps_set_tooltip(hdaps, HDAPS_OFF);
252
253 return hdaps;
254 }
255
256
257
258 static void hdaps_free(XfcePanelPlugin *plugin,
259 HdapsPlugin *hdaps) {
260
261 GtkWidget *dialog;
262
263 /* Destroy the dialog if it's still open. */
264 dialog = g_object_get_data(G_OBJECT(plugin), "dialog");
265
266 if (G_UNLIKELY(dialog != NULL)) {
267 gtk_widget_destroy(dialog);
268 }
269
270 /* Destroy the panel widgets. When dumb comments like these
271 are left over, they're from the sample panel applet,
272 I swear. */
273 gtk_widget_destroy(hdaps->hvbox);
274
275 /* Remove the timeout that was set during creation. */
276 if (hdaps->timeout) {
277 g_source_remove(hdaps->timeout);
278 }
279
280 /* And free the string (if any) containing
281 the device name. */
282 if (G_LIKELY(hdaps->device_name != NULL)) {
283 g_free(hdaps->device_name);
284 }
285
286 /* Goodbye, tooltips. */
287 gtk_tooltips_set_tip(hdaps->tooltip, hdaps->eventbox, NULL, NULL);
288 g_object_unref(G_OBJECT(hdaps->tooltip));
289
290 /* ...and finally free the plugin structure. */
291 panel_slice_free(HdapsPlugin, hdaps);
292 }
293
294
295
296 static void hdaps_orientation_changed(XfcePanelPlugin *plugin,
297 GtkOrientation orientation,
298 HdapsPlugin *hdaps) {
299
300 /* Change the plugin's orientation. Basically magic to me. */
301 xfce_hvbox_set_orientation(XFCE_HVBOX(hdaps->hvbox), orientation);
302 }
303
304
305
306 static gboolean hdaps_size_changed(XfcePanelPlugin *plugin,
307 gint size,
308 HdapsPlugin *hdaps) {
309
310 GtkOrientation orientation;
311
312 /* Get the current orientation of the plugin. */
313 orientation = xfce_panel_plugin_get_orientation(plugin);
314
315 /* We want to make the widget "bigger" in the direction
316 of its orientation. Or is it the other way around? */
317 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
318 gtk_widget_set_size_request(GTK_WIDGET(plugin), -1, size);
319 }
320 else {
321 gtk_widget_set_size_request(GTK_WIDGET(plugin), size, -1);
322 }
323
324 /* We handled the change, so we're supposed to return TRUE. */
325 return TRUE;
326 }
327
328
329
330 static gboolean hdaps_update_status(HdapsPlugin *hdaps) {
331 /* This checks the status of HDAPS and updates the
332 widget accordingly. */
333
334 /* This just gets the status. */
335 int status = parse_int_from_file(hdaps->sysfs_file);
336
337 /* The value in the sysfs_file represents the number of milliseconds
338 * that the drive heads will be parked. Of course, this will
339 * generally count down, and appear different each time we poll.
340 *
341 * So, to determine whether or not HDAPS has gone from "on"
342 * to "off," we treat all values greater than zero the same.
343 */
344 if (status > 0) {
345 status = HDAPS_ON;
346 }
347
348 if (status != hdaps->previous_status) {
349 /* And we only update the icon if we need to. */
350 hdaps_set_icon(hdaps, status);
351 hdaps_set_tooltip(hdaps, status);
352 hdaps->previous_status = status;
353 }
354
355 return TRUE;
356 }
357
358
359
360 void hdaps_reset_timeout(HdapsPlugin *hdaps) {
361 /* Remove, and then re-set the timeout function. Useful
362 for changing the poll frequency. */
363 if (hdaps->timeout) {
364 g_source_remove(hdaps->timeout);
365 }
366
367 hdaps->timeout = g_timeout_add(hdaps->poll_frequency, (GSourceFunc)hdaps_update_status, hdaps);
368 }
369
370
371
372 static void hdaps_construct(XfcePanelPlugin *plugin) {
373 HdapsPlugin *hdaps;
374
375 /* Set the "translation domain". I don't know what that does. */
376 xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
377
378 /* First, create the plugin. */
379 hdaps = hdaps_new(plugin);
380
381 /* Add the plugin's eventbox to the panel. */
382 gtk_container_add(GTK_CONTAINER(plugin), hdaps->eventbox);
383
384 /* This configures the right-click menu to appear
385 on the plugin's eventbox. */
386 xfce_panel_plugin_add_action_widget(plugin, hdaps->eventbox);
387
388 /* Connect the common event handlers. */
389 g_signal_connect(G_OBJECT(plugin), "free-data",
390 G_CALLBACK(hdaps_free), hdaps);
391
392 g_signal_connect (G_OBJECT(plugin), "save",
393 G_CALLBACK(hdaps_save), hdaps);
394
395 g_signal_connect (G_OBJECT(plugin), "size-changed",
396 G_CALLBACK(hdaps_size_changed), hdaps);
397
398 g_signal_connect (G_OBJECT(plugin), "orientation-changed",
399 G_CALLBACK(hdaps_orientation_changed), hdaps);
400
401 /* Show the "configure" right-click menu item, and
402 connect its event handler. */
403 xfce_panel_plugin_menu_show_configure(plugin);
404 g_signal_connect(G_OBJECT(plugin), "configure-plugin",
405 G_CALLBACK(hdaps_configure), hdaps);
406
407 /* Show the "about" right-click menu item, and
408 connect its event handler. */
409 xfce_panel_plugin_menu_show_about(plugin);
410 g_signal_connect(G_OBJECT(plugin), "about",
411 G_CALLBACK(hdaps_about), hdaps);
412
413 /* Set the timeout for the function which checks the
414 HDAPS status. */
415 hdaps_reset_timeout(hdaps);
416
417 return;
418 }