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