2 * xfce4-hdaps, an XFCE4 panel plugin for the HDAPS system.
4 * Copyright Michael Orlitzky
6 * http://michael.orlitzky.com/
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.
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.
18 * http://www.fsf.org/licensing/licenses/gpl.html
26 #include "xfce4-hdaps.h"
27 #include "xfce4-hdaps-dialogs.h"
29 /* We need a default device. Since we require kernels
30 newer than 2.6.28, it's probably sdX, and I'm guessing
31 that sda is most likely. */
32 #define DEFAULT_DEVICE_NAME "sda"
34 /* How often do we poll, in milliseconds?
35 This should be configured, but we set the default here. */
36 #define DEFAULT_POLL_FREQUENCY 500
39 /* Prototype, needed to register below. */
40 static void hdaps_construct(XfcePanelPlugin
*plugin
);
42 /* Register the plugin with the panel. */
43 XFCE_PANEL_PLUGIN_REGISTER(hdaps_construct
);
46 void hdaps_save(XfcePanelPlugin
*plugin
, HdapsPlugin
*hdaps
) {
51 /* Get the config file location. XFCE should know this. */
52 file
= xfce_panel_plugin_save_location(plugin
, TRUE
);
54 if (G_UNLIKELY(file
== NULL
)) {
55 DBG("Failed to find the configuration file. Bailing.");
59 /* Open the config file read/write. */
60 rc
= xfce_rc_simple_open(file
, FALSE
);
62 /* And we can free the file path now that we've
66 if (G_UNLIKELY(rc
== NULL
)) {
67 DBG("Failed to open the configuration file. Bailing.");
72 /* Write any user-configured values to the resource file. */
73 if (hdaps
->device_name
) {
74 xfce_rc_write_entry(rc
, "device_name", hdaps
->device_name
);
77 xfce_rc_write_int_entry(rc
, "poll_frequency", hdaps
->poll_frequency
);
79 /* close the rc file */
85 void hdaps_set_icon(HdapsPlugin
*hdaps
, int status
) {
89 /* Panel info magic. */
90 size
= xfce_panel_plugin_get_size(hdaps
->plugin
) - 6;
92 /* Try to load an icon from the current icon theme. */
93 if (status
== HDAPS_ERROR
) {
95 icon
= gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
99 else if (status
== HDAPS_OFF
) {
100 icon
= gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
105 /* status > HDAPS_OFF means it's on. */
106 icon
= gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
111 /* Get rid of the previous icon. */
113 gtk_widget_destroy(hdaps
->icon
);
117 hdaps
->icon
= gtk_image_new_from_pixbuf(icon
);
118 g_object_unref(G_OBJECT(icon
));
121 hdaps
->icon
= gtk_image_new_from_icon_name("dialog-warning", GTK_ICON_SIZE_BUTTON
);
124 gtk_box_pack_start(GTK_BOX(hdaps
->hvbox
), GTK_WIDGET(hdaps
->icon
), FALSE
, FALSE
, 0);
125 gtk_widget_show(hdaps
->icon
);
132 void hdaps_set_tooltip(HdapsPlugin
*hdaps
, int status
) {
134 if (status
== HDAPS_ERROR
) {
135 gtk_tooltips_set_tip(hdaps
->tooltip
, hdaps
->eventbox
, "HDAPS Error", NULL
);
137 else if (status
== HDAPS_OFF
) {
138 gtk_tooltips_set_tip(hdaps
->tooltip
, hdaps
->eventbox
, "HDAPS Off", NULL
);
141 gtk_tooltips_set_tip(hdaps
->tooltip
, hdaps
->eventbox
, "HDAPS On", NULL
);
146 static void hdaps_set_defaults(HdapsPlugin
*hdaps
) {
147 DBG("Configuring all settings to defaults.");
149 /* Here we determine the default device name. There are essentially
150 two "defaults," one soft, and the other hard. The soft default
151 is to choose the first supported HDAPS device in the system. This
152 would benefit users who, for example, only have one supported drive
153 named hda. If we can't find any supported HDAPS devices, we use the
154 hard default of DEFAULT_DEVICE_NAME. */
155 char hdaps_devices
[MAX_HDAPS_DEVICES
][FILENAME_MAX
];
156 int found_devices
= get_hdaps_device_list(hdaps_devices
);
158 if (found_devices
> 0) {
159 hdaps
->device_name
= g_strdup(hdaps_devices
[0]);
162 hdaps
->device_name
= g_strdup(DEFAULT_DEVICE_NAME
);
165 snprintf(hdaps
->sysfs_file
, FILENAME_MAX
, UNLOAD_HEADS_FMT
, hdaps
->device_name
);
167 /* The other default is easier. */
168 hdaps
->poll_frequency
= DEFAULT_POLL_FREQUENCY
;
172 static void hdaps_read(HdapsPlugin
*hdaps
) {
176 const gchar
*saved_device_name
;
178 /* Get the plugin config file location. XFCE should know this. */
179 file
= xfce_panel_plugin_save_location(hdaps
->plugin
, TRUE
);
181 if (G_UNLIKELY(file
== NULL
)) {
182 DBG("Something went wrong getting the configuration file location.");
183 DBG("Retaining default settings.");
187 /* Open the config file read-only. */
188 rc
= xfce_rc_simple_open(file
, TRUE
);
190 /* Don't need this anymore if we've got a file handle. */
193 if (G_UNLIKELY(rc
== NULL
)) {
194 DBG("There was an error opening the configuration file.");
195 DBG("Retaining default settings.");
199 /* Read the settings, one at a time. */
201 /* We use saved_device_name here because we need
202 to dupe the string after we read it in from the
204 saved_device_name
= xfce_rc_read_entry(rc
,
206 DEFAULT_DEVICE_NAME
);
207 hdaps
->device_name
= g_strdup(saved_device_name
);
208 snprintf(hdaps
->sysfs_file
, FILENAME_MAX
, UNLOAD_HEADS_FMT
, hdaps
->device_name
);
210 /* Integers are easier. */
211 hdaps
->poll_frequency
= xfce_rc_read_int_entry(rc
,
213 DEFAULT_POLL_FREQUENCY
);
215 /* And close the config file. */
222 static HdapsPlugin
*hdaps_new(XfcePanelPlugin
*plugin
) {
224 GtkOrientation orientation
;
226 /* Allocate memory for the plugin struct, and zero it. */
227 hdaps
= panel_slice_new0(HdapsPlugin
);
229 /* The HdapsPlugin gets a copy of the XfcePanelPlugin. */
230 hdaps
->plugin
= plugin
;
232 /* Set default values right before reading in the user's settings.
233 This way, hdaps_read() doesn't have to set defaults on error
235 hdaps_set_defaults(hdaps
);
237 /* Read any user settings into the HdapsPlugin. */
240 /* Get the current orientation. Magic. */
241 orientation
= xfce_panel_plugin_get_orientation(plugin
);
243 /* This creates the event box and shows it. This
247 b) Interact with it via right-click, etc.
249 hdaps
->eventbox
= gtk_event_box_new();
250 gtk_widget_show(hdaps
->eventbox
);
252 /* Make the event box transparent. In newer versions of xfce4-panel
253 users can make the panel transparent, so we don't want to stick a
254 big opaque box on it. */
255 gtk_event_box_set_visible_window(GTK_EVENT_BOX(hdaps
->eventbox
), FALSE
);
257 /* Set up the hvbox for the widget, which supports
258 both horizontal and vertical (hv) orientations. */
259 hdaps
->hvbox
= xfce_hvbox_new(orientation
, FALSE
, 2);
260 gtk_widget_show(hdaps
->hvbox
);
261 gtk_container_add(GTK_CONTAINER(hdaps
->eventbox
), hdaps
->hvbox
);
263 /* We only change the icon when the status has changed,
264 so it's important that they start out n*sync. */
265 hdaps
->previous_status
= HDAPS_OFF
;
266 hdaps_set_icon(hdaps
, HDAPS_OFF
);
268 /* Create the tooltip widget, and set its initial value.
269 * The first couple of lines are stolen from the battery
270 * status plugin. I make no claim as to their correctness.
272 hdaps
->tooltip
= gtk_tooltips_new();
273 g_object_ref(G_OBJECT(hdaps
->tooltip
));
274 gtk_object_sink(GTK_OBJECT(hdaps
->tooltip
));
275 hdaps_set_tooltip(hdaps
, HDAPS_OFF
);
282 static void hdaps_free(XfcePanelPlugin
*plugin
,
283 HdapsPlugin
*hdaps
) {
287 /* Destroy the dialog if it's still open. */
288 dialog
= g_object_get_data(G_OBJECT(plugin
), "dialog");
290 if (G_UNLIKELY(dialog
!= NULL
)) {
291 gtk_widget_destroy(dialog
);
294 /* Destroy the panel widgets. When dumb comments like these
295 are left over, they're from the sample panel applet,
297 gtk_widget_destroy(hdaps
->hvbox
);
299 /* Remove the timeout that was set during creation. */
300 if (hdaps
->timeout
) {
301 g_source_remove(hdaps
->timeout
);
304 /* And free the string (if any) containing
306 if (G_LIKELY(hdaps
->device_name
!= NULL
)) {
307 g_free(hdaps
->device_name
);
310 /* Goodbye, tooltips. */
311 gtk_tooltips_set_tip(hdaps
->tooltip
, hdaps
->eventbox
, NULL
, NULL
);
312 g_object_unref(G_OBJECT(hdaps
->tooltip
));
314 /* ...and finally free the plugin structure. */
315 panel_slice_free(HdapsPlugin
, hdaps
);
320 static void hdaps_orientation_changed(XfcePanelPlugin
*plugin
,
321 GtkOrientation orientation
,
322 HdapsPlugin
*hdaps
) {
324 /* Change the plugin's orientation. Basically magic to me. */
325 xfce_hvbox_set_orientation(XFCE_HVBOX(hdaps
->hvbox
), orientation
);
330 static gboolean
hdaps_size_changed(XfcePanelPlugin
*plugin
,
332 HdapsPlugin
*hdaps
) {
334 GtkOrientation orientation
;
336 /* Get the current orientation of the plugin. */
337 orientation
= xfce_panel_plugin_get_orientation(plugin
);
339 /* We want to make the widget "bigger" in the direction
340 of its orientation. Or is it the other way around? */
341 if (orientation
== GTK_ORIENTATION_HORIZONTAL
) {
342 gtk_widget_set_size_request(GTK_WIDGET(plugin
), -1, size
);
345 gtk_widget_set_size_request(GTK_WIDGET(plugin
), size
, -1);
348 /* This fixes an issue where the initial icon size is too small. */
349 hdaps_set_icon(hdaps
, hdaps
->previous_status
);
351 /* We handled the change, so we're supposed to return TRUE. */
357 static gboolean
hdaps_update_status(HdapsPlugin
*hdaps
) {
358 /* This checks the status of HDAPS and updates the
359 widget accordingly. */
361 /* This just gets the status. */
362 int status
= parse_int_from_file(hdaps
->sysfs_file
);
364 /* The value in the sysfs_file represents the number of milliseconds
365 * that the drive heads will be parked. Of course, this will
366 * generally count down, and appear different each time we poll.
368 * So, to determine whether or not HDAPS has gone from "on"
369 * to "off," we treat all values greater than zero the same.
375 if (status
!= hdaps
->previous_status
) {
376 /* And we only update the icon if we need to. */
377 hdaps_set_icon(hdaps
, status
);
378 hdaps_set_tooltip(hdaps
, status
);
379 hdaps
->previous_status
= status
;
387 void hdaps_reset_timeout(HdapsPlugin
*hdaps
) {
388 /* Remove, and then re-set the timeout function. Useful
389 for changing the poll frequency. */
390 if (hdaps
->timeout
) {
391 g_source_remove(hdaps
->timeout
);
394 hdaps
->timeout
= g_timeout_add(hdaps
->poll_frequency
, (GSourceFunc
)hdaps_update_status
, hdaps
);
399 static void hdaps_construct(XfcePanelPlugin
*plugin
) {
402 /* Set the "translation domain". I don't know what that does. */
403 xfce_textdomain(GETTEXT_PACKAGE
, PACKAGE_LOCALE_DIR
, "UTF-8");
405 /* First, create the plugin. */
406 hdaps
= hdaps_new(plugin
);
408 /* Add the plugin's eventbox to the panel. */
409 gtk_container_add(GTK_CONTAINER(plugin
), hdaps
->eventbox
);
411 /* This configures the right-click menu to appear
412 on the plugin's eventbox. */
413 xfce_panel_plugin_add_action_widget(plugin
, hdaps
->eventbox
);
415 /* Connect the common event handlers. */
416 g_signal_connect(G_OBJECT(plugin
), "free-data",
417 G_CALLBACK(hdaps_free
), hdaps
);
419 g_signal_connect (G_OBJECT(plugin
), "save",
420 G_CALLBACK(hdaps_save
), hdaps
);
422 g_signal_connect (G_OBJECT(plugin
), "size-changed",
423 G_CALLBACK(hdaps_size_changed
), hdaps
);
425 g_signal_connect (G_OBJECT(plugin
), "orientation-changed",
426 G_CALLBACK(hdaps_orientation_changed
), hdaps
);
428 /* Show the "configure" right-click menu item, and
429 connect its event handler. */
430 xfce_panel_plugin_menu_show_configure(plugin
);
431 g_signal_connect(G_OBJECT(plugin
), "configure-plugin",
432 G_CALLBACK(hdaps_configure
), hdaps
);
434 /* Show the "about" right-click menu item, and
435 connect its event handler. */
436 xfce_panel_plugin_menu_show_about(plugin
);
437 g_signal_connect(G_OBJECT(plugin
), "about",
438 G_CALLBACK(hdaps_about
), hdaps
);
440 /* Set the timeout for the function which checks the
442 hdaps_reset_timeout(hdaps
);