/* * xfce4-hdaps, an XFCE4 panel plugin for the HDAPS system. * * Copyright Michael Orlitzky * * http://michael.orlitzky.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * http://www.fsf.org/licensing/licenses/gpl.html */ #ifdef HAVE_CONFIG_H #include #endif #include "xfce4-hdaps.h" #include "xfce4-hdaps-dialogs.h" /* We need a default device. Since we require kernels newer than 2.6.28, it's probably sdX, and I'm guessing that sda is most likely. */ #define DEFAULT_DEVICE_NAME "sda" /* How often do we poll, in milliseconds? This should be configured, but we set the default here. */ #define DEFAULT_POLL_FREQUENCY 500 /* Prototype, needed to register below. */ static void hdaps_construct(XfcePanelPlugin *plugin); /* Register the plugin with the panel. */ XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL(hdaps_construct); void hdaps_save(XfcePanelPlugin *plugin, HdapsPlugin *hdaps) { XfceRc *rc; gchar *file; /* Get the config file location. XFCE should know this. */ file = xfce_panel_plugin_save_location(plugin, TRUE); if (G_UNLIKELY(file == NULL)) { DBG("Failed to find the configuration file. Bailing."); return; } /* Open the config file read/write. */ rc = xfce_rc_simple_open(file, FALSE); /* And we can free the file path now that we've opened the file. */ g_free(file); if (G_UNLIKELY(rc == NULL)) { DBG("Failed to open the configuration file. Bailing."); return; } /* Write any user-configured values to the resource file. */ if (hdaps->device_name) { xfce_rc_write_entry(rc, "device_name", hdaps->device_name); } xfce_rc_write_int_entry(rc, "poll_frequency", hdaps->poll_frequency); /* close the rc file */ xfce_rc_close(rc); } void hdaps_set_icon(HdapsPlugin *hdaps, int status) { GdkPixbuf *icon; gint size; /* Panel info magic. */ size = xfce_panel_plugin_get_size(hdaps->plugin) - 6; /* Try to load an icon from the current icon theme. */ if (status == HDAPS_ERROR) { /* Error */ icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "emblem-noread", size, 0, NULL); } else if (status == HDAPS_OFF) { icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "drive-harddisk", size, 0, NULL); } else { /* status > HDAPS_OFF means it's on. */ icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "emblem-nowrite", size, 0, NULL); } /* Get rid of the previous icon. */ if (hdaps->icon) { gtk_widget_destroy(hdaps->icon); } if (icon) { hdaps->icon = gtk_image_new_from_pixbuf(icon); g_object_unref(G_OBJECT(icon)); } else { hdaps->icon = gtk_image_new_from_icon_name("dialog-warning", GTK_ICON_SIZE_BUTTON); } gtk_box_pack_start(GTK_BOX(hdaps->hvbox), GTK_WIDGET(hdaps->icon), FALSE, FALSE, 0); gtk_widget_show(hdaps->icon); return; } void hdaps_set_tooltip(HdapsPlugin *hdaps, int status) { if (status == HDAPS_ERROR) { gtk_tooltips_set_tip(hdaps->tooltip, hdaps->eventbox, "HDAPS Error", NULL); } else if (status == HDAPS_OFF) { gtk_tooltips_set_tip(hdaps->tooltip, hdaps->eventbox, "HDAPS Off", NULL); } else { gtk_tooltips_set_tip(hdaps->tooltip, hdaps->eventbox, "HDAPS On", NULL); } } static void hdaps_set_defaults(HdapsPlugin *hdaps) { DBG("Configuring all settings to defaults."); hdaps->device_name = g_strdup(DEFAULT_DEVICE_NAME); snprintf(hdaps->sysfs_file, FILENAME_MAX, UNLOAD_HEADS_FMT, hdaps->device_name); hdaps->poll_frequency = DEFAULT_POLL_FREQUENCY; } static void hdaps_read(HdapsPlugin *hdaps) { XfceRc *rc; gchar *file; const gchar *saved_device_name; /* Get the plugin config file location. XFCE should know this. */ file = xfce_panel_plugin_save_location(hdaps->plugin, TRUE); if (G_UNLIKELY(file == NULL)) { DBG("Something went wrong getting the configuration file location."); DBG("Retaining default settings."); return; } /* Open the config file read-only. */ rc = xfce_rc_simple_open(file, TRUE); /* Don't need this anymore if we've got a file handle. */ g_free(file); if (G_UNLIKELY(rc == NULL)) { DBG("There was an error opening the configuration file."); DBG("Retaining default settings."); return; } /* Read the settings, one at a time. */ /* We use saved_device_name here because we need to dupe the string after we read it in from the config file. */ saved_device_name = xfce_rc_read_entry(rc, "device_name", DEFAULT_DEVICE_NAME); hdaps->device_name = g_strdup(saved_device_name); snprintf(hdaps->sysfs_file, FILENAME_MAX, UNLOAD_HEADS_FMT, hdaps->device_name); /* Integers are easier. */ hdaps->poll_frequency = xfce_rc_read_int_entry(rc, "poll_frequency", DEFAULT_POLL_FREQUENCY); /* And close the config file. */ xfce_rc_close(rc); } static HdapsPlugin *hdaps_new(XfcePanelPlugin *plugin) { HdapsPlugin *hdaps; GtkOrientation orientation; /* Allocate memory for the plugin struct, and zero it. */ hdaps = panel_slice_new0(HdapsPlugin); /* The HdapsPlugin gets a copy of the XfcePanelPlugin. */ hdaps->plugin = plugin; /* Set default values right before reading in the user's settings. This way, hdaps_read() doesn't have to set defaults on error conditions. */ hdaps_set_defaults(hdaps); /* Read any user settings into the HdapsPlugin. */ hdaps_read(hdaps); /* Get the current orientation. Magic. */ orientation = xfce_panel_plugin_get_orientation(plugin); /* This creates the event box and shows it. This is necessary to, a) See the widget b) Interact with it via right-click, etc. */ hdaps->eventbox = gtk_event_box_new(); gtk_widget_show(hdaps->eventbox); /* Set up the hvbox for the widget, which supports both horizontal and vertical (hv) orientations. */ hdaps->hvbox = xfce_hvbox_new(orientation, FALSE, 2); gtk_widget_show(hdaps->hvbox); gtk_container_add(GTK_CONTAINER(hdaps->eventbox), hdaps->hvbox); /* We only change the icon when the status has changed, so it's important that they start out n*sync. */ hdaps->previous_status = HDAPS_OFF; hdaps_set_icon(hdaps, HDAPS_OFF); /* Create the tooltip widget, and set its initial value. * The first couple of lines are stolen from the battery * status plugin. I make no claim as to their correctness. */ hdaps->tooltip = gtk_tooltips_new(); g_object_ref(G_OBJECT(hdaps->tooltip)); gtk_object_sink(GTK_OBJECT(hdaps->tooltip)); hdaps_set_tooltip(hdaps, HDAPS_OFF); return hdaps; } static void hdaps_free(XfcePanelPlugin *plugin, HdapsPlugin *hdaps) { GtkWidget *dialog; /* Destroy the dialog if it's still open. */ dialog = g_object_get_data(G_OBJECT(plugin), "dialog"); if (G_UNLIKELY(dialog != NULL)) { gtk_widget_destroy(dialog); } /* Destroy the panel widgets. When dumb comments like these are left over, they're from the sample panel applet, I swear. */ gtk_widget_destroy(hdaps->hvbox); /* Remove the timeout that was set during creation. */ if (hdaps->timeout) { g_source_remove(hdaps->timeout); } /* And free the string (if any) containing the device name. */ if (G_LIKELY(hdaps->device_name != NULL)) { g_free(hdaps->device_name); } /* Goodbye, tooltips. */ gtk_tooltips_set_tip(hdaps->tooltip, hdaps->eventbox, NULL, NULL); g_object_unref(G_OBJECT(hdaps->tooltip)); /* ...and finally free the plugin structure. */ panel_slice_free(HdapsPlugin, hdaps); } static void hdaps_orientation_changed(XfcePanelPlugin *plugin, GtkOrientation orientation, HdapsPlugin *hdaps) { /* Change the plugin's orientation. Basically magic to me. */ xfce_hvbox_set_orientation(XFCE_HVBOX(hdaps->hvbox), orientation); } static gboolean hdaps_size_changed(XfcePanelPlugin *plugin, gint size, HdapsPlugin *hdaps) { GtkOrientation orientation; /* Get the current orientation of the plugin. */ orientation = xfce_panel_plugin_get_orientation(plugin); /* We want to make the widget "bigger" in the direction of its orientation. Or is it the other way around? */ if (orientation == GTK_ORIENTATION_HORIZONTAL) { gtk_widget_set_size_request(GTK_WIDGET(plugin), -1, size); } else { gtk_widget_set_size_request(GTK_WIDGET(plugin), size, -1); } /* We handled the change, so we're supposed to return TRUE. */ return TRUE; } static gboolean hdaps_update_status(HdapsPlugin *hdaps) { /* This checks the status of HDAPS and updates the widget accordingly. */ /* This just gets the status. */ int status = parse_int_from_file(hdaps->sysfs_file); /* The value in the sysfs_file represents the number of milliseconds * that the drive heads will be parked. Of course, this will * generally count down, and appear different each time we poll. * * So, to determine whether or not HDAPS has gone from "on" * to "off," we treat all values greater than zero the same. */ if (status > 0) { status = HDAPS_ON; } if (status != hdaps->previous_status) { /* And we only update the icon if we need to. */ hdaps_set_icon(hdaps, status); hdaps_set_tooltip(hdaps, status); hdaps->previous_status = status; } return TRUE; } void hdaps_reset_timeout(HdapsPlugin *hdaps) { /* Remove, and then re-set the timeout function. Useful for changing the poll frequency. */ if (hdaps->timeout) { g_source_remove(hdaps->timeout); } hdaps->timeout = g_timeout_add(hdaps->poll_frequency, (GSourceFunc)hdaps_update_status, hdaps); } static void hdaps_construct(XfcePanelPlugin *plugin) { HdapsPlugin *hdaps; /* Set the "translation domain". I don't know what that does. */ xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8"); /* First, create the plugin. */ hdaps = hdaps_new(plugin); /* Add the plugin's eventbox to the panel. */ gtk_container_add(GTK_CONTAINER(plugin), hdaps->eventbox); /* This configures the right-click menu to appear on the plugin's eventbox. */ xfce_panel_plugin_add_action_widget(plugin, hdaps->eventbox); /* Connect the common event handlers. */ g_signal_connect(G_OBJECT(plugin), "free-data", G_CALLBACK(hdaps_free), hdaps); g_signal_connect (G_OBJECT(plugin), "save", G_CALLBACK(hdaps_save), hdaps); g_signal_connect (G_OBJECT(plugin), "size-changed", G_CALLBACK(hdaps_size_changed), hdaps); g_signal_connect (G_OBJECT(plugin), "orientation-changed", G_CALLBACK(hdaps_orientation_changed), hdaps); /* Show the "configure" right-click menu item, and connect its event handler. */ xfce_panel_plugin_menu_show_configure(plugin); g_signal_connect(G_OBJECT(plugin), "configure-plugin", G_CALLBACK(hdaps_configure), hdaps); /* Show the "about" right-click menu item, and connect its event handler. */ xfce_panel_plugin_menu_show_about(plugin); g_signal_connect(G_OBJECT(plugin), "about", G_CALLBACK(hdaps_about), hdaps); /* Set the timeout for the function which checks the HDAPS status. */ hdaps_reset_timeout(hdaps); return; }