]> gitweb.michael.orlitzky.com - xfce4-hdaps.git/blob - panel-plugin/xfce4-hdaps.c
e54532602c4eb1a8ded2ec4e540e23bfd18e7e32
[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
148 /* Here we determine the default device name. There are essentially
149 two "defaults," one soft, and the other hard. The soft default
150 is to choose the first supported HDAPS device in the system. This
151 would benefit users who, for example, only have one supported drive
152 named hda. If we can't find any supported HDAPS devices, we use the
153 hard default of DEFAULT_DEVICE_NAME. */
154 char hdaps_devices[MAX_HDAPS_DEVICES][FILENAME_MAX];
155 int found_devices = get_hdaps_device_list(hdaps_devices);
156
157 if (found_devices > 0) {
158 hdaps->device_name = g_strdup(hdaps_devices[0]);
159 }
160 else {
161 hdaps->device_name = g_strdup(DEFAULT_DEVICE_NAME);
162 }
163
164 snprintf(hdaps->sysfs_file, FILENAME_MAX, UNLOAD_HEADS_FMT, hdaps->device_name);
165
166 /* The other default is easier. */
167 hdaps->poll_frequency = DEFAULT_POLL_FREQUENCY;
168 }
169
170
171 static void hdaps_read(HdapsPlugin *hdaps) {
172
173 XfceRc *rc;
174 gchar *file;
175 const gchar *saved_device_name;
176
177 /* Get the plugin config file location. XFCE should know this. */
178 file = xfce_panel_plugin_save_location(hdaps->plugin, TRUE);
179
180 if (G_UNLIKELY(file == NULL)) {
181 DBG("Something went wrong getting the configuration file location.");
182 DBG("Retaining default settings.");
183 return;
184 }
185
186 /* Open the config file read-only. */
187 rc = xfce_rc_simple_open(file, TRUE);
188
189 /* Don't need this anymore if we've got a file handle. */
190 g_free(file);
191
192 if (G_UNLIKELY(rc == NULL)) {
193 DBG("There was an error opening the configuration file.");
194 DBG("Retaining default settings.");
195 return;
196 }
197
198 /* Read the settings, one at a time. */
199
200 /* We use saved_device_name here because we need
201 to dupe the string after we read it in from the
202 config file. */
203 saved_device_name = xfce_rc_read_entry(rc,
204 "device_name",
205 DEFAULT_DEVICE_NAME);
206 hdaps->device_name = g_strdup(saved_device_name);
207 snprintf(hdaps->sysfs_file, FILENAME_MAX, UNLOAD_HEADS_FMT, hdaps->device_name);
208
209 /* Integers are easier. */
210 hdaps->poll_frequency = xfce_rc_read_int_entry(rc,
211 "poll_frequency",
212 DEFAULT_POLL_FREQUENCY);
213
214 /* And close the config file. */
215 xfce_rc_close(rc);
216 }
217
218
219
220
221 static HdapsPlugin *hdaps_new(XfcePanelPlugin *plugin) {
222 HdapsPlugin *hdaps;
223 GtkOrientation orientation;
224
225 /* Allocate memory for the plugin struct, and zero it. */
226 hdaps = panel_slice_new0(HdapsPlugin);
227
228 /* The HdapsPlugin gets a copy of the XfcePanelPlugin. */
229 hdaps->plugin = plugin;
230
231 /* Set default values right before reading in the user's settings.
232 This way, hdaps_read() doesn't have to set defaults on error
233 conditions. */
234 hdaps_set_defaults(hdaps);
235
236 /* Read any user settings into the HdapsPlugin. */
237 hdaps_read(hdaps);
238
239 /* Get the current orientation. Magic. */
240 orientation = xfce_panel_plugin_get_orientation(plugin);
241
242 /* This creates the event box and shows it. This
243 is necessary to,
244
245 a) See the widget
246 b) Interact with it via right-click, etc.
247 */
248 hdaps->eventbox = gtk_event_box_new();
249 gtk_widget_show(hdaps->eventbox);
250
251 /* Set up the hvbox for the widget, which supports
252 both horizontal and vertical (hv) orientations. */
253 hdaps->hvbox = xfce_hvbox_new(orientation, FALSE, 2);
254 gtk_widget_show(hdaps->hvbox);
255 gtk_container_add(GTK_CONTAINER(hdaps->eventbox), hdaps->hvbox);
256
257 /* We only change the icon when the status has changed,
258 so it's important that they start out n*sync. */
259 hdaps->previous_status = HDAPS_OFF;
260 hdaps_set_icon(hdaps, HDAPS_OFF);
261
262 /* Create the tooltip widget, and set its initial value.
263 * The first couple of lines are stolen from the battery
264 * status plugin. I make no claim as to their correctness.
265 */
266 hdaps->tooltip = gtk_tooltips_new();
267 g_object_ref(G_OBJECT(hdaps->tooltip));
268 gtk_object_sink(GTK_OBJECT(hdaps->tooltip));
269 hdaps_set_tooltip(hdaps, HDAPS_OFF);
270
271 return hdaps;
272 }
273
274
275
276 static void hdaps_free(XfcePanelPlugin *plugin,
277 HdapsPlugin *hdaps) {
278
279 GtkWidget *dialog;
280
281 /* Destroy the dialog if it's still open. */
282 dialog = g_object_get_data(G_OBJECT(plugin), "dialog");
283
284 if (G_UNLIKELY(dialog != NULL)) {
285 gtk_widget_destroy(dialog);
286 }
287
288 /* Destroy the panel widgets. When dumb comments like these
289 are left over, they're from the sample panel applet,
290 I swear. */
291 gtk_widget_destroy(hdaps->hvbox);
292
293 /* Remove the timeout that was set during creation. */
294 if (hdaps->timeout) {
295 g_source_remove(hdaps->timeout);
296 }
297
298 /* And free the string (if any) containing
299 the device name. */
300 if (G_LIKELY(hdaps->device_name != NULL)) {
301 g_free(hdaps->device_name);
302 }
303
304 /* Goodbye, tooltips. */
305 gtk_tooltips_set_tip(hdaps->tooltip, hdaps->eventbox, NULL, NULL);
306 g_object_unref(G_OBJECT(hdaps->tooltip));
307
308 /* ...and finally free the plugin structure. */
309 panel_slice_free(HdapsPlugin, hdaps);
310 }
311
312
313
314 static void hdaps_orientation_changed(XfcePanelPlugin *plugin,
315 GtkOrientation orientation,
316 HdapsPlugin *hdaps) {
317
318 /* Change the plugin's orientation. Basically magic to me. */
319 xfce_hvbox_set_orientation(XFCE_HVBOX(hdaps->hvbox), orientation);
320 }
321
322
323
324 static gboolean hdaps_size_changed(XfcePanelPlugin *plugin,
325 gint size,
326 HdapsPlugin *hdaps) {
327
328 GtkOrientation orientation;
329
330 /* Get the current orientation of the plugin. */
331 orientation = xfce_panel_plugin_get_orientation(plugin);
332
333 /* We want to make the widget "bigger" in the direction
334 of its orientation. Or is it the other way around? */
335 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
336 gtk_widget_set_size_request(GTK_WIDGET(plugin), -1, size);
337 }
338 else {
339 gtk_widget_set_size_request(GTK_WIDGET(plugin), size, -1);
340 }
341
342 /* We handled the change, so we're supposed to return TRUE. */
343 return TRUE;
344 }
345
346
347
348 static gboolean hdaps_update_status(HdapsPlugin *hdaps) {
349 /* This checks the status of HDAPS and updates the
350 widget accordingly. */
351
352 /* This just gets the status. */
353 int status = parse_int_from_file(hdaps->sysfs_file);
354
355 /* The value in the sysfs_file represents the number of milliseconds
356 * that the drive heads will be parked. Of course, this will
357 * generally count down, and appear different each time we poll.
358 *
359 * So, to determine whether or not HDAPS has gone from "on"
360 * to "off," we treat all values greater than zero the same.
361 */
362 if (status > 0) {
363 status = HDAPS_ON;
364 }
365
366 if (status != hdaps->previous_status) {
367 /* And we only update the icon if we need to. */
368 hdaps_set_icon(hdaps, status);
369 hdaps_set_tooltip(hdaps, status);
370 hdaps->previous_status = status;
371 }
372
373 return TRUE;
374 }
375
376
377
378 void hdaps_reset_timeout(HdapsPlugin *hdaps) {
379 /* Remove, and then re-set the timeout function. Useful
380 for changing the poll frequency. */
381 if (hdaps->timeout) {
382 g_source_remove(hdaps->timeout);
383 }
384
385 hdaps->timeout = g_timeout_add(hdaps->poll_frequency, (GSourceFunc)hdaps_update_status, hdaps);
386 }
387
388
389
390 static void hdaps_construct(XfcePanelPlugin *plugin) {
391 HdapsPlugin *hdaps;
392
393 /* Set the "translation domain". I don't know what that does. */
394 xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
395
396 /* First, create the plugin. */
397 hdaps = hdaps_new(plugin);
398
399 /* Add the plugin's eventbox to the panel. */
400 gtk_container_add(GTK_CONTAINER(plugin), hdaps->eventbox);
401
402 /* This configures the right-click menu to appear
403 on the plugin's eventbox. */
404 xfce_panel_plugin_add_action_widget(plugin, hdaps->eventbox);
405
406 /* Connect the common event handlers. */
407 g_signal_connect(G_OBJECT(plugin), "free-data",
408 G_CALLBACK(hdaps_free), hdaps);
409
410 g_signal_connect (G_OBJECT(plugin), "save",
411 G_CALLBACK(hdaps_save), hdaps);
412
413 g_signal_connect (G_OBJECT(plugin), "size-changed",
414 G_CALLBACK(hdaps_size_changed), hdaps);
415
416 g_signal_connect (G_OBJECT(plugin), "orientation-changed",
417 G_CALLBACK(hdaps_orientation_changed), hdaps);
418
419 /* Show the "configure" right-click menu item, and
420 connect its event handler. */
421 xfce_panel_plugin_menu_show_configure(plugin);
422 g_signal_connect(G_OBJECT(plugin), "configure-plugin",
423 G_CALLBACK(hdaps_configure), hdaps);
424
425 /* Show the "about" right-click menu item, and
426 connect its event handler. */
427 xfce_panel_plugin_menu_show_about(plugin);
428 g_signal_connect(G_OBJECT(plugin), "about",
429 G_CALLBACK(hdaps_about), hdaps);
430
431 /* Set the timeout for the function which checks the
432 HDAPS status. */
433 hdaps_reset_timeout(hdaps);
434
435 return;
436 }