summaryrefslogtreecommitdiff
path: root/cpufreq/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpufreq/src')
-rw-r--r--cpufreq/src/Makefile.am40
-rw-r--r--cpufreq/src/cpufreq-applet.c1032
-rw-r--r--cpufreq/src/cpufreq-applet.h61
-rw-r--r--cpufreq/src/cpufreq-monitor-cpuinfo.c134
-rw-r--r--cpufreq/src/cpufreq-monitor-cpuinfo.h50
-rw-r--r--cpufreq/src/cpufreq-monitor-factory.c69
-rw-r--r--cpufreq/src/cpufreq-monitor-factory.h33
-rw-r--r--cpufreq/src/cpufreq-monitor-libcpufreq.c199
-rw-r--r--cpufreq/src/cpufreq-monitor-libcpufreq.h56
-rw-r--r--cpufreq/src/cpufreq-monitor-procfs.c221
-rw-r--r--cpufreq/src/cpufreq-monitor-procfs.h54
-rw-r--r--cpufreq/src/cpufreq-monitor-sysfs.c345
-rw-r--r--cpufreq/src/cpufreq-monitor-sysfs.h54
-rw-r--r--cpufreq/src/cpufreq-monitor.c411
-rw-r--r--cpufreq/src/cpufreq-monitor.h72
-rw-r--r--cpufreq/src/cpufreq-popup.c509
-rw-r--r--cpufreq/src/cpufreq-popup.h66
-rw-r--r--cpufreq/src/cpufreq-prefs.c705
-rw-r--r--cpufreq/src/cpufreq-prefs.h66
-rw-r--r--cpufreq/src/cpufreq-selector.c289
-rw-r--r--cpufreq/src/cpufreq-selector.h51
-rw-r--r--cpufreq/src/cpufreq-selector/Makefile.am89
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-factory.c47
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-factory.h31
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.c197
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.h61
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.c243
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.h54
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-service.c487
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-service.h71
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-service.xml23
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.c430
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.h58
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector.c173
-rw-r--r--cpufreq/src/cpufreq-selector/cpufreq-selector.h74
-rw-r--r--cpufreq/src/cpufreq-selector/main.c233
-rw-r--r--cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.conf20
-rw-r--r--cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.service.in4
-rw-r--r--cpufreq/src/cpufreq-selector/org.mate.cpufreqselector.policy.in22
-rw-r--r--cpufreq/src/cpufreq-utils.c311
-rw-r--r--cpufreq/src/cpufreq-utils.h44
41 files changed, 7189 insertions, 0 deletions
diff --git a/cpufreq/src/Makefile.am b/cpufreq/src/Makefile.am
new file mode 100644
index 00000000..db5679d0
--- /dev/null
+++ b/cpufreq/src/Makefile.am
@@ -0,0 +1,40 @@
+if BUILD_CPUFREQ_SELECTOR
+selector_SUBDIR = cpufreq-selector
+endif
+
+SUBDIRS = $(selector_SUBDIR)
+
+INCLUDES = \
+ -DCPUFREQ_MENU_UI_DIR=\""$(datadir)/mate-2.0/ui"\" \
+ $(MATE_APPLETS3_CFLAGS) \
+ $(LIBGLADE_CFLAGS) \
+ $(DBUS_CFLAGS)
+
+libexec_PROGRAMS = cpufreq-applet
+
+if HAVE_LIBCPUFREQ
+cpufreq_files=cpufreq-monitor-libcpufreq.c cpufreq-monitor-libcpufreq.h
+endif
+
+cpufreq_applet_SOURCES = \
+ cpufreq-applet.c cpufreq-applet.h \
+ cpufreq-utils.c cpufreq-utils.h \
+ cpufreq-prefs.c cpufreq-prefs.h \
+ cpufreq-selector.c cpufreq-selector.h \
+ cpufreq-popup.c cpufreq-popup.h \
+ cpufreq-monitor.c cpufreq-monitor.h \
+ cpufreq-monitor-factory.c cpufreq-monitor-factory.h \
+ cpufreq-monitor-procfs.c cpufreq-monitor-procfs.h \
+ cpufreq-monitor-sysfs.c cpufreq-monitor-sysfs.h \
+ $(cpufreq_files) \
+ cpufreq-monitor-cpuinfo.c cpufreq-monitor-cpuinfo.h
+
+cpufreq_applet_LDADD = \
+ $(MATE_APPLETS3_LIBS) \
+ $(LIBGLADE_LIBS) \
+ $(LIBCPUFREQ_LIBS) \
+ $(DBUS_LIBS)
+
+
+
+-include $(top_srcdir)/git.mk
diff --git a/cpufreq/src/cpufreq-applet.c b/cpufreq/src/cpufreq-applet.c
new file mode 100644
index 00000000..07a80339
--- /dev/null
+++ b/cpufreq/src/cpufreq-applet.c
@@ -0,0 +1,1032 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <mate-panel-applet.h>
+#include <mate-panel-applet-mateconf.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cpufreq-applet.h"
+#include "cpufreq-prefs.h"
+#include "cpufreq-popup.h"
+#include "cpufreq-monitor.h"
+#include "cpufreq-monitor-factory.h"
+#include "cpufreq-utils.h"
+
+struct _CPUFreqApplet {
+ MatePanelApplet base;
+
+ /* Visibility */
+ CPUFreqShowMode show_mode;
+ CPUFreqShowTextMode show_text_mode;
+ gboolean show_freq;
+ gboolean show_perc;
+ gboolean show_unit;
+ gboolean show_icon;
+
+ CPUFreqMonitor *monitor;
+
+ MatePanelAppletOrient orient;
+ gint size;
+
+ GtkWidget *label;
+ GtkWidget *unit_label;
+ GtkWidget *icon;
+ GtkWidget *box;
+ GtkWidget *labels_box;
+ GtkWidget *container;
+ GdkPixbuf *pixbufs[5];
+
+ gint max_label_width;
+ gint max_perc_width;
+ gint max_unit_width;
+
+ gboolean need_refresh;
+
+ CPUFreqPrefs *prefs;
+ CPUFreqPopup *popup;
+};
+
+struct _CPUFreqAppletClass {
+ MatePanelAppletClass parent_class;
+};
+
+static void cpufreq_applet_init (CPUFreqApplet *applet);
+static void cpufreq_applet_class_init (CPUFreqAppletClass *klass);
+
+static void cpufreq_applet_preferences_cb (GtkAction *action,
+ CPUFreqApplet *applet);
+static void cpufreq_applet_help_cb (GtkAction *action,
+ CPUFreqApplet *applet);
+static void cpufreq_applet_about_cb (GtkAction *action,
+ CPUFreqApplet *applet);
+
+static void cpufreq_applet_pixmap_set_image (CPUFreqApplet *applet,
+ gint perc);
+
+static void cpufreq_applet_setup (CPUFreqApplet *applet);
+static void cpufreq_applet_update (CPUFreqApplet *applet,
+ CPUFreqMonitor *monitor);
+static void cpufreq_applet_refresh (CPUFreqApplet *applet);
+
+static void cpufreq_applet_destroy (GtkObject *widget);
+static gboolean cpufreq_applet_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean cpufreq_applet_key_press (GtkWidget *widget,
+ GdkEventKey *event);
+static void cpufreq_applet_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void cpufreq_applet_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void cpufreq_applet_change_orient (MatePanelApplet *pa,
+ MatePanelAppletOrient orient);
+static gboolean cpufreq_applet_factory (CPUFreqApplet *applet,
+ const gchar *iid,
+ gpointer gdata);
+
+static const gchar *const cpufreq_icons[] = {
+ MATE_PIXMAPSDIR"/cpufreq-applet/cpufreq-25.png",
+ MATE_PIXMAPSDIR"/cpufreq-applet/cpufreq-50.png",
+ MATE_PIXMAPSDIR"/cpufreq-applet/cpufreq-75.png",
+ MATE_PIXMAPSDIR"/cpufreq-applet/cpufreq-100.png",
+ MATE_PIXMAPSDIR"/cpufreq-applet/cpufreq-na.png",
+ NULL
+};
+
+static const GtkActionEntry cpufreq_applet_menu_actions[] = {
+ { "CPUFreqAppletPreferences", GTK_STOCK_PROPERTIES, N_("_Preferences"),
+ NULL, NULL,
+ G_CALLBACK (cpufreq_applet_preferences_cb) },
+ { "CPUFreqAppletHelp", GTK_STOCK_HELP, N_("_Help"),
+ NULL, NULL,
+ G_CALLBACK (cpufreq_applet_help_cb) },
+ { "CPUFreqAppletAbout", GTK_STOCK_ABOUT, N_("_About"),
+ NULL, NULL,
+ G_CALLBACK (cpufreq_applet_about_cb) }
+};
+
+G_DEFINE_TYPE (CPUFreqApplet, cpufreq_applet, PANEL_TYPE_APPLET)
+
+/* Enum Types */
+GType
+cpufreq_applet_show_mode_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ { CPUFREQ_MODE_GRAPHIC, "CPUFREQ_MODE_GRAPHIC", "mode-graphic" },
+ { CPUFREQ_MODE_TEXT, "CPUFREQ_MODE_TEXT", "mode-text" },
+ { CPUFREQ_MODE_BOTH, "CPUFREQ_MODE_BOTH", "mode-both" },
+ { 0, NULL, NULL }
+ };
+
+ etype = g_enum_register_static ("CPUFreqShowMode", values);
+ }
+
+ return etype;
+}
+
+GType
+cpufreq_applet_show_text_mode_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ { CPUFREQ_MODE_TEXT_FREQUENCY, "CPUFREQ_MODE_TEXT_FREQUENCY", "mode-text-frequency" },
+ { CPUFREQ_MODE_TEXT_FREQUENCY_UNIT, "CPUFREQ_MODE_TEXT_FREQUENCY_UNIT", "mode-text-frequency-unit" },
+ { CPUFREQ_MODE_TEXT_PERCENTAGE, "CPUFREQ_MODE_TEXT_PERCENTAGE", "mode-text-percentage" },
+ { 0, NULL, NULL }
+ };
+
+ etype = g_enum_register_static ("CPUFreqShowTextMode", values);
+ }
+
+ return etype;
+}
+
+static void
+cpufreq_applet_init (CPUFreqApplet *applet)
+{
+ applet->prefs = NULL;
+ applet->popup = NULL;
+ applet->monitor = NULL;
+
+ applet->label = gtk_label_new (NULL);
+ applet->unit_label = gtk_label_new (NULL);
+ applet->icon = gtk_image_new ();
+ applet->box = NULL;
+
+ applet->show_mode = CPUFREQ_MODE_BOTH;
+ applet->show_text_mode = CPUFREQ_MODE_TEXT_FREQUENCY_UNIT;
+
+ applet->need_refresh = TRUE;
+
+ mate_panel_applet_set_flags (MATE_PANEL_APPLET (applet), MATE_PANEL_APPLET_EXPAND_MINOR);
+ mate_panel_applet_set_background_widget (MATE_PANEL_APPLET (applet), GTK_WIDGET (applet));
+
+ applet->size = mate_panel_applet_get_size (MATE_PANEL_APPLET (applet));
+ applet->orient = mate_panel_applet_get_orient (MATE_PANEL_APPLET (applet));
+
+ switch (applet->orient) {
+ case MATE_PANEL_APPLET_ORIENT_LEFT:
+ case MATE_PANEL_APPLET_ORIENT_RIGHT:
+ applet->container = gtk_alignment_new (0.5, 0.5, 0, 0);
+ break;
+ case MATE_PANEL_APPLET_ORIENT_UP:
+ case MATE_PANEL_APPLET_ORIENT_DOWN:
+ applet->container = gtk_alignment_new (0, 0.5, 0, 0);
+ break;
+ }
+
+ gtk_container_add (GTK_CONTAINER (applet), applet->container);
+ gtk_widget_show (applet->container);
+}
+
+static void
+cpufreq_applet_class_init (CPUFreqAppletClass *klass)
+{
+ MatePanelAppletClass *applet_class = MATE_PANEL_APPLET_CLASS (klass);
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtkobject_class->destroy = cpufreq_applet_destroy;
+
+ widget_class->size_allocate = cpufreq_applet_size_allocate;
+ widget_class->size_request = cpufreq_applet_size_request;
+ widget_class->button_press_event = cpufreq_applet_button_press;
+ widget_class->key_press_event = cpufreq_applet_key_press;
+
+ applet_class->change_orient = cpufreq_applet_change_orient;
+}
+
+static void
+cpufreq_applet_destroy (GtkObject *widget)
+{
+ CPUFreqApplet *applet;
+ gint i;
+
+ applet = CPUFREQ_APPLET (widget);
+
+ if (applet->monitor) {
+ g_object_unref (G_OBJECT (applet->monitor));
+ applet->monitor = NULL;
+ }
+
+ for (i = 0; i <= 3; i++) {
+ if (applet->pixbufs[i]) {
+ g_object_unref (G_OBJECT (applet->pixbufs[i]));
+ applet->pixbufs[i] = NULL;
+ }
+ }
+
+ if (applet->prefs) {
+ g_object_unref (applet->prefs);
+ applet->prefs = NULL;
+ }
+
+ if (applet->popup) {
+ g_object_unref (applet->popup);
+ applet->popup = NULL;
+ }
+
+ GTK_OBJECT_CLASS (cpufreq_applet_parent_class)->destroy (widget);
+}
+
+static void
+cpufreq_applet_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+ CPUFreqApplet *applet;
+ gint size = 0;
+
+ applet = CPUFREQ_APPLET (widget);
+
+ GTK_WIDGET_CLASS (cpufreq_applet_parent_class)->size_allocate (widget, allocation);
+
+ switch (applet->orient) {
+ case MATE_PANEL_APPLET_ORIENT_LEFT:
+ case MATE_PANEL_APPLET_ORIENT_RIGHT:
+ size = allocation->width;
+ break;
+ case MATE_PANEL_APPLET_ORIENT_UP:
+ case MATE_PANEL_APPLET_ORIENT_DOWN:
+ size = allocation->height;
+ break;
+ }
+
+ if (size != applet->size) {
+ applet->size = size;
+ cpufreq_applet_refresh (applet);
+ }
+}
+
+static gint
+cpufreq_applet_get_max_label_width (CPUFreqApplet *applet)
+{
+ GList *available_freqs;
+ gint width = 0;
+
+ if (applet->max_label_width > 0)
+ return applet->max_label_width;
+
+ if (!CPUFREQ_IS_MONITOR (applet->monitor))
+ return 0;
+
+ available_freqs = cpufreq_monitor_get_available_frequencies (applet->monitor);
+ while (available_freqs) {
+ GtkWidget *label;
+ GtkRequisition req;
+ const gchar *text;
+ gchar *freq_text;
+ gint freq;
+
+ text = (const gchar *) available_freqs->data;
+ freq = atoi (text);
+
+ freq_text = cpufreq_utils_get_frequency_label (freq);
+ label = gtk_label_new (freq_text);
+ gtk_widget_size_request (label, &req);
+
+ width = MAX (width, req.width);
+
+ g_free (freq_text);
+ gtk_widget_destroy (label);
+
+ available_freqs = g_list_next (available_freqs);
+ }
+
+ applet->max_label_width = width;
+
+ return width;
+}
+
+static gint
+cpufreq_applet_get_max_perc_width (CPUFreqApplet *applet)
+{
+ GtkWidget *label;
+ GtkRequisition req;
+
+ if (applet->max_perc_width > 0)
+ return applet->max_perc_width;
+
+ label = gtk_label_new ("100%");
+ gtk_widget_size_request (label, &req);
+ applet->max_perc_width = req.width;
+ gtk_widget_destroy (label);
+
+ return applet->max_perc_width;
+}
+
+static gint
+cpufreq_applet_get_max_unit_width (CPUFreqApplet *applet)
+{
+ GtkWidget *label;
+ GtkRequisition req;
+ gint w1, w2;
+
+ if (applet->max_unit_width > 0)
+ return applet->max_unit_width;
+
+ label = gtk_label_new ("GHz");
+ gtk_widget_size_request (label, &req);
+ w1 = req.width;
+
+ gtk_label_set_text (GTK_LABEL (label), "MHz");
+ gtk_widget_size_request (label, &req);
+ w2 = req.width;
+
+ gtk_widget_destroy (label);
+
+ applet->max_unit_width = MAX (w1, w2);
+
+ return applet->max_unit_width;
+}
+
+static void
+cpufreq_applet_size_request (GtkWidget *widget, GtkRequisition *requisition)
+{
+ CPUFreqApplet *applet;
+ gint labels_width = 0;
+ gint width;
+
+ applet = CPUFREQ_APPLET (widget);
+
+ GTK_WIDGET_CLASS (cpufreq_applet_parent_class)->size_request (widget, requisition);
+
+ if (applet->orient == MATE_PANEL_APPLET_ORIENT_LEFT ||
+ applet->orient == MATE_PANEL_APPLET_ORIENT_RIGHT)
+ return;
+
+ if (applet->show_freq) {
+ labels_width += cpufreq_applet_get_max_label_width (applet) + 2;
+ }
+
+ if (applet->show_perc) {
+ labels_width += cpufreq_applet_get_max_perc_width (applet);
+ }
+
+ if (applet->show_unit) {
+ labels_width += cpufreq_applet_get_max_unit_width (applet);
+ }
+
+ if (applet->show_icon) {
+ GtkRequisition req;
+
+ gtk_widget_size_request (applet->icon, &req);
+ width = GTK_IS_HBOX (applet->box) ?
+ labels_width + req.width + 2 :
+ MAX (labels_width, req.width + 2);
+ } else {
+ width = labels_width;
+ }
+
+ requisition->width = width;
+}
+
+static void
+cpufreq_applet_popup_position_menu (GtkMenu *menu,
+ int *x,
+ int *y,
+ gboolean *push_in,
+ gpointer gdata)
+{
+ GtkWidget *widget;
+ GtkRequisition requisition;
+ GtkAllocation allocation;
+ gint menu_xpos;
+ gint menu_ypos;
+
+ widget = GTK_WIDGET (gdata);
+
+ gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
+
+ gdk_window_get_origin (gtk_widget_get_window (widget), &menu_xpos, &menu_ypos);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ menu_xpos += allocation.x;
+ menu_ypos += allocation.y;
+
+ switch (mate_panel_applet_get_orient (MATE_PANEL_APPLET (widget))) {
+ case MATE_PANEL_APPLET_ORIENT_DOWN:
+ case MATE_PANEL_APPLET_ORIENT_UP:
+ if (menu_ypos > gdk_screen_get_height (gtk_widget_get_screen (widget)) / 2)
+ menu_ypos -= requisition.height;
+ else
+ menu_ypos += allocation.height;
+ break;
+ case MATE_PANEL_APPLET_ORIENT_RIGHT:
+ case MATE_PANEL_APPLET_ORIENT_LEFT:
+ if (menu_xpos > gdk_screen_get_width (gtk_widget_get_screen (widget)) / 2)
+ menu_xpos -= requisition.width;
+ else
+ menu_xpos += allocation.width;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ *x = menu_xpos;
+ *y = menu_ypos;
+ *push_in = TRUE;
+}
+
+static void
+cpufreq_applet_menu_popup (CPUFreqApplet *applet,
+ guint32 time)
+{
+ GtkWidget *menu;
+
+ if (!cpufreq_utils_selector_is_available ())
+ return;
+
+ if (!applet->popup) {
+ applet->popup = cpufreq_popup_new ();
+ cpufreq_popup_set_monitor (applet->popup, applet->monitor);
+ cpufreq_popup_set_parent (applet->popup, GTK_WIDGET (applet));
+ }
+
+ menu = cpufreq_popup_get_menu (applet->popup);
+
+ if (!menu)
+ return;
+
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+ cpufreq_applet_popup_position_menu,
+ (gpointer) applet,
+ 1, time);
+}
+
+static gboolean
+cpufreq_applet_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ CPUFreqApplet *applet;
+
+ applet = CPUFREQ_APPLET (widget);
+
+ if (event->button == 2)
+ return FALSE;
+
+ if (event->button == 1 &&
+ event->type != GDK_2BUTTON_PRESS &&
+ event->type != GDK_3BUTTON_PRESS) {
+ cpufreq_applet_menu_popup (applet, event->time);
+
+ return TRUE;
+ }
+
+ return GTK_WIDGET_CLASS (cpufreq_applet_parent_class)->button_press_event (widget, event);
+}
+
+static gboolean
+cpufreq_applet_key_press (GtkWidget *widget, GdkEventKey *event)
+{
+ CPUFreqApplet *applet;
+
+ applet = CPUFREQ_APPLET (widget);
+
+ switch (event->keyval) {
+ case GDK_KP_Enter:
+ case GDK_ISO_Enter:
+ case GDK_3270_Enter:
+ case GDK_Return:
+ case GDK_space:
+ case GDK_KP_Space:
+ cpufreq_applet_menu_popup (applet, event->time);
+
+ return TRUE;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+cpufreq_applet_change_orient (MatePanelApplet *pa, MatePanelAppletOrient orient)
+{
+ CPUFreqApplet *applet;
+ GtkAllocation allocation;
+ gint size;
+
+ applet = CPUFREQ_APPLET (pa);
+
+ applet->orient = orient;
+
+ gtk_widget_get_allocation (GTK_WIDGET (applet), &allocation);
+
+ if ((orient == MATE_PANEL_APPLET_ORIENT_LEFT) ||
+ (orient == MATE_PANEL_APPLET_ORIENT_RIGHT)) {
+ size = allocation.width;
+ gtk_alignment_set (GTK_ALIGNMENT (applet->container),
+ 0.5, 0.5, 0, 0);
+ } else {
+ size = allocation.height;
+ gtk_alignment_set (GTK_ALIGNMENT (applet->container),
+ 0, 0.5, 0, 0);
+ }
+
+ if (size != applet->size) {
+ applet->size = size;
+ cpufreq_applet_refresh (applet);
+ }
+}
+
+static void
+cpufreq_applet_preferences_cb (GtkAction *action,
+ CPUFreqApplet *applet)
+{
+ cpufreq_preferences_dialog_run (applet->prefs,
+ gtk_widget_get_screen (GTK_WIDGET (applet)));
+}
+
+static void
+cpufreq_applet_help_cb (GtkAction *action,
+ CPUFreqApplet *applet)
+{
+ GError *error = NULL;
+
+ gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (applet)),
+ "ghelp:cpufreq-applet",
+ gtk_get_current_event_time (),
+ &error);
+
+ if (error) {
+ cpufreq_utils_display_error (_("Could not open help document"),
+ error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+cpufreq_applet_about_cb (GtkAction *action,
+ CPUFreqApplet *applet)
+{
+ static const gchar *const authors[] = {
+ "Carlos Garcia Campos <[email protected]>",
+ NULL
+ };
+ static const gchar *const documenters[] = {
+ "Carlos Garcia Campos <[email protected]>",
+ "Davyd Madeley <[email protected]>",
+ NULL
+ };
+ static const gchar *const artists[] = {
+ "Pablo Arroyo Loma <[email protected]>",
+ NULL
+ };
+
+ gtk_show_about_dialog (NULL,
+ "version", VERSION,
+ "copyright", "\xC2\xA9 2004 Carlos Garcia Campos",
+ "comments", _("This utility shows the current CPU "
+ "Frequency Scaling."),
+ "authors", authors,
+ "documenters", documenters,
+ "artists", artists,
+ "translator-credits", _("translator-credits"),
+ "logo-icon-name", "mate-cpu-frequency-applet",
+ NULL);
+}
+
+static void
+cpufreq_applet_pixmap_set_image (CPUFreqApplet *applet, gint perc)
+{
+ gint image;
+
+ /* 0-29 -> 25%
+ * 30-69 -> 50%
+ * 70-89 -> 75%
+ * 90-100 -> 100%
+ */
+ if (perc < 30)
+ image = 0;
+ else if ((perc >= 30) && (perc < 70))
+ image = 1;
+ else if ((perc >= 70) && (perc < 90))
+ image = 2;
+ else if ((perc >= 90) && (perc <= 100))
+ image = 3;
+ else
+ image = 4;
+
+ if (applet->pixbufs[image] == NULL) {
+ applet->pixbufs[image] = gdk_pixbuf_new_from_file_at_size (cpufreq_icons[image],
+ 24, 24, NULL);
+ }
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (applet->icon), applet->pixbufs[image]);
+}
+
+static gboolean
+refresh_cb (CPUFreqApplet *applet)
+{
+ cpufreq_applet_refresh (applet);
+
+ return FALSE;
+}
+
+static void
+cpufreq_applet_update_visibility (CPUFreqApplet *applet)
+{
+ CPUFreqShowMode show_mode;
+ CPUFreqShowTextMode show_text_mode;
+ gboolean show_freq = FALSE;
+ gboolean show_perc = FALSE;
+ gboolean show_unit = FALSE;
+ gboolean show_icon = FALSE;
+ gboolean changed = FALSE;
+ gboolean need_update = FALSE;
+
+ show_mode = cpufreq_prefs_get_show_mode (applet->prefs);
+ show_text_mode = cpufreq_prefs_get_show_text_mode (applet->prefs);
+
+ if (show_mode != CPUFREQ_MODE_GRAPHIC) {
+ show_icon = (show_mode == CPUFREQ_MODE_BOTH);
+
+ switch (show_text_mode) {
+ case CPUFREQ_MODE_TEXT_FREQUENCY:
+ show_freq = TRUE;
+ break;
+ case CPUFREQ_MODE_TEXT_PERCENTAGE:
+ show_perc = TRUE;
+ break;
+ case CPUFREQ_MODE_TEXT_FREQUENCY_UNIT:
+ show_freq = TRUE;
+ show_unit = TRUE;
+ break;
+ }
+ } else {
+ show_icon = TRUE;
+ }
+
+ if (applet->show_mode != show_mode) {
+ applet->show_mode = show_mode;
+ need_update = TRUE;
+ }
+
+ if (applet->show_text_mode != show_text_mode) {
+ applet->show_text_mode = show_text_mode;
+ need_update = TRUE;
+ }
+
+ if (show_freq != applet->show_freq) {
+ applet->show_freq = show_freq;
+ changed = TRUE;
+ }
+
+ if (show_perc != applet->show_perc) {
+ applet->show_perc = show_perc;
+ changed = TRUE;
+ }
+
+ if (changed) {
+ g_object_set (G_OBJECT (applet->label),
+ "visible",
+ applet->show_freq || applet->show_perc,
+ NULL);
+ }
+
+ if (show_unit != applet->show_unit) {
+ applet->show_unit = show_unit;
+ changed = TRUE;
+
+ g_object_set (G_OBJECT (applet->unit_label),
+ "visible", applet->show_unit,
+ NULL);
+ }
+
+ if (show_icon != applet->show_icon) {
+ applet->show_icon = show_icon;
+ changed = TRUE;
+
+ g_object_set (G_OBJECT (applet->icon),
+ "visible", applet->show_icon,
+ NULL);
+ }
+
+ if (changed)
+ g_idle_add ((GSourceFunc)refresh_cb, applet);
+
+ if (need_update)
+ cpufreq_applet_update (applet, applet->monitor);
+}
+
+static void
+cpufreq_applet_update (CPUFreqApplet *applet, CPUFreqMonitor *monitor)
+{
+ gchar *text_mode = NULL;
+ gchar *freq_label, *unit_label;
+ gint freq;
+ gint perc;
+ guint cpu;
+ const gchar *governor;
+
+ cpu = cpufreq_monitor_get_cpu (monitor);
+ freq = cpufreq_monitor_get_frequency (monitor);
+ perc = cpufreq_monitor_get_percentage (monitor);
+ governor = cpufreq_monitor_get_governor (monitor);
+
+ freq_label = cpufreq_utils_get_frequency_label (freq);
+ unit_label = cpufreq_utils_get_frequency_unit (freq);
+
+ if (applet->show_freq) {
+ gtk_label_set_text (GTK_LABEL (applet->label), freq_label);
+ }
+
+ if (applet->show_perc) {
+ gchar *text_perc;
+
+ text_perc = g_strdup_printf ("%d%%", perc);
+ gtk_label_set_text (GTK_LABEL (applet->label), text_perc);
+ g_free (text_perc);
+ }
+
+ if (applet->show_unit) {
+ gtk_label_set_text (GTK_LABEL (applet->unit_label), unit_label);
+ }
+
+ if (applet->show_icon) {
+ cpufreq_applet_pixmap_set_image (applet, perc);
+ }
+
+ if (governor) {
+ gchar *gov_text;
+
+ gov_text = g_strdup (governor);
+ gov_text[0] = g_ascii_toupper (gov_text[0]);
+ text_mode = g_strdup_printf ("%s\n%s %s (%d%%)",
+ gov_text, freq_label,
+ unit_label, perc);
+ g_free (gov_text);
+ }
+
+ g_free (freq_label);
+ g_free (unit_label);
+
+ if (text_mode) {
+ gchar *text_tip;
+
+ text_tip = cpufreq_utils_get_n_cpus () == 1 ?
+ g_strdup_printf ("%s", text_mode) :
+ g_strdup_printf ("CPU %u - %s", cpu, text_mode);
+ g_free (text_mode);
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (applet), text_tip);
+ g_free (text_tip);
+ }
+
+ /* Call refresh only the first time */
+ if (applet->need_refresh) {
+ cpufreq_applet_refresh (applet);
+ applet->need_refresh = FALSE;
+ }
+}
+
+static gint
+cpufreq_applet_get_widget_size (CPUFreqApplet *applet,
+ GtkWidget *widget)
+{
+ GtkRequisition req;
+ gint size;
+
+ if (!gtk_widget_get_visible (widget))
+ return 0;
+
+ gtk_widget_size_request (widget, &req);
+
+ switch (applet->orient) {
+ case MATE_PANEL_APPLET_ORIENT_LEFT:
+ case MATE_PANEL_APPLET_ORIENT_RIGHT:
+ size = req.width;
+ break;
+ case MATE_PANEL_APPLET_ORIENT_UP:
+ case MATE_PANEL_APPLET_ORIENT_DOWN:
+ size = req.height;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return size;
+}
+
+static void
+cpufreq_applet_refresh (CPUFreqApplet *applet)
+{
+ gint total_size = 0;
+ gint panel_size, label_size;
+ gint unit_label_size, pixmap_size;
+ gint size_step = 12;
+ gboolean horizontal;
+ gboolean do_unref = FALSE;
+
+ panel_size = applet->size - 1; /* 1 pixel margin */
+
+ horizontal = (applet->orient == MATE_PANEL_APPLET_ORIENT_UP ||
+ applet->orient == MATE_PANEL_APPLET_ORIENT_DOWN);
+
+ /* We want a fixed label size, the biggest */
+ if (horizontal)
+ label_size = cpufreq_applet_get_widget_size (applet, applet->label);
+ else
+ label_size = cpufreq_applet_get_max_label_width (applet);
+ total_size += label_size;
+
+ if (horizontal)
+ unit_label_size = cpufreq_applet_get_widget_size (applet, applet->unit_label);
+ else
+ unit_label_size = cpufreq_applet_get_max_unit_width (applet);
+ total_size += unit_label_size;
+
+ pixmap_size = cpufreq_applet_get_widget_size (applet, applet->icon);
+ total_size += pixmap_size;
+
+ if (applet->box) {
+ do_unref = TRUE;
+ g_object_ref (applet->icon);
+ gtk_container_remove (GTK_CONTAINER (applet->box), applet->icon);
+ if (applet->labels_box) {
+ g_object_ref (applet->label);
+ gtk_container_remove (GTK_CONTAINER (applet->labels_box), applet->label);
+ g_object_ref (applet->unit_label);
+ gtk_container_remove (GTK_CONTAINER (applet->labels_box), applet->unit_label);
+ }
+ gtk_widget_destroy (applet->box);
+ }
+
+ if (horizontal) {
+ applet->labels_box = gtk_hbox_new (FALSE, 2);
+ if ((label_size + pixmap_size) <= panel_size)
+ applet->box = gtk_vbox_new (FALSE, 2);
+ else
+ applet->box = gtk_hbox_new (FALSE, 2);
+ } else {
+ if (total_size <= panel_size) {
+ applet->box = gtk_hbox_new (FALSE, 2);
+ applet->labels_box = gtk_hbox_new (FALSE, 2);
+ } else if ((label_size + unit_label_size) <= (panel_size - size_step)) {
+ applet->box = gtk_vbox_new (FALSE, 2);
+ applet->labels_box = gtk_hbox_new (FALSE, 2);
+ } else {
+ applet->box = gtk_vbox_new (FALSE, 2);
+ applet->labels_box = gtk_vbox_new (FALSE, 2);
+ }
+ }
+
+ gtk_box_pack_start (GTK_BOX (applet->labels_box), applet->label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (applet->labels_box), applet->unit_label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (applet->box), applet->icon, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (applet->box), applet->labels_box, FALSE, FALSE, 0);
+ gtk_widget_show (applet->labels_box);
+
+ gtk_container_add (GTK_CONTAINER (applet->container), applet->box);
+ gtk_widget_show (applet->box);
+
+ if (do_unref) {
+ g_object_unref (applet->label);
+ g_object_unref (applet->unit_label);
+ g_object_unref (applet->icon);
+ }
+}
+
+/* Preferences callbacks */
+static void
+cpufreq_applet_prefs_cpu_changed (CPUFreqPrefs *prefs,
+ GParamSpec *arg1,
+ CPUFreqApplet *applet)
+{
+ cpufreq_monitor_set_cpu (applet->monitor,
+ cpufreq_prefs_get_cpu (applet->prefs));
+}
+
+static void
+cpufreq_applet_prefs_show_mode_changed (CPUFreqPrefs *prefs,
+ GParamSpec *arg1,
+ CPUFreqApplet *applet)
+{
+ cpufreq_applet_update_visibility (applet);
+}
+
+static void
+cpufreq_applet_setup (CPUFreqApplet *applet)
+{
+ GtkActionGroup *action_group;
+ gchar *ui_path;
+ AtkObject *atk_obj;
+ gchar *prefs_key;
+
+ g_set_application_name (_("CPU Frequency Scaling Monitor"));
+
+ gtk_window_set_default_icon_name ("mate-cpu-frequency-applet");
+
+ mate_panel_applet_add_preferences (MATE_PANEL_APPLET (applet),
+ "/schemas/apps/cpufreq-applet/prefs", NULL);
+
+ /* Preferences */
+ if (applet->prefs)
+ g_object_unref (applet->prefs);
+
+ prefs_key = mate_panel_applet_get_preferences_key (MATE_PANEL_APPLET (applet));
+ applet->prefs = cpufreq_prefs_new (prefs_key);
+ g_free (prefs_key);
+
+ g_signal_connect (G_OBJECT (applet->prefs),
+ "notify::cpu",
+ G_CALLBACK (cpufreq_applet_prefs_cpu_changed),
+ (gpointer) applet);
+ g_signal_connect (G_OBJECT (applet->prefs),
+ "notify::show-mode",
+ G_CALLBACK (cpufreq_applet_prefs_show_mode_changed),
+ (gpointer) applet);
+ g_signal_connect (G_OBJECT (applet->prefs),
+ "notify::show-text-mode",
+ G_CALLBACK (cpufreq_applet_prefs_show_mode_changed),
+ (gpointer) applet);
+
+ /* Monitor */
+ applet->monitor = cpufreq_monitor_factory_create_monitor (
+ cpufreq_prefs_get_cpu (applet->prefs));
+ cpufreq_monitor_run (applet->monitor);
+ g_signal_connect_swapped (G_OBJECT (applet->monitor), "changed",
+ G_CALLBACK (cpufreq_applet_update),
+ (gpointer) applet);
+
+ /* Setup the menus */
+ action_group = gtk_action_group_new ("CPUFreq Applet Actions");
+ gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (action_group,
+ cpufreq_applet_menu_actions,
+ G_N_ELEMENTS (cpufreq_applet_menu_actions),
+ applet);
+ ui_path = g_build_filename (CPUFREQ_MENU_UI_DIR, "cpufreq-applet-menu.xml", NULL);
+ mate_panel_applet_setup_menu_from_file (MATE_PANEL_APPLET (applet),
+ ui_path, action_group);
+ g_free (ui_path);
+
+ if (mate_panel_applet_get_locked_down (MATE_PANEL_APPLET (applet))) {
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (action_group, "CPUFreqPreferences");
+ gtk_action_set_visible (action, FALSE);
+ }
+ g_object_unref (action_group);
+
+ atk_obj = gtk_widget_get_accessible (GTK_WIDGET (applet));
+
+ if (GTK_IS_ACCESSIBLE (atk_obj)) {
+ atk_object_set_name (atk_obj, _("CPU Frequency Scaling Monitor"));
+ atk_object_set_description (atk_obj, _("This utility shows the current CPU Frequency"));
+ }
+
+ cpufreq_applet_update_visibility (applet);
+
+ gtk_widget_show (GTK_WIDGET (applet));
+}
+
+static gboolean
+cpufreq_applet_factory (CPUFreqApplet *applet, const gchar *iid, gpointer gdata)
+{
+ gboolean retval = FALSE;
+
+ if (!strcmp (iid, "CPUFreqApplet")) {
+ cpufreq_applet_setup (applet);
+
+ retval = TRUE;
+ }
+
+ return retval;
+}
+
+MATE_PANEL_APPLET_OUT_PROCESS_FACTORY ("CPUFreqAppletFactory",
+ CPUFREQ_TYPE_APPLET,
+ "cpufreq-applet",
+ (MatePanelAppletFactoryCallback) cpufreq_applet_factory,
+ NULL)
diff --git a/cpufreq/src/cpufreq-applet.h b/cpufreq/src/cpufreq-applet.h
new file mode 100644
index 00000000..11d400a1
--- /dev/null
+++ b/cpufreq/src/cpufreq-applet.h
@@ -0,0 +1,61 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef CPUFREQ_APPLET_H
+#define CPUFREQ_APPLET_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_APPLET (cpufreq_applet_get_type ())
+#define CPUFREQ_APPLET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_APPLET, CPUFreqApplet))
+#define CPUFREQ_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_APPLET, CPUFreqAppletClass))
+#define CPUFREQ_IS_APPLET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_APPLET))
+#define CPUFREQ_IS_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_APPLET))
+#define CPUFREQ_APPLET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_APPLET, CPUFreqAppletClass))
+
+#define CPUFREQ_TYPE_SHOW_MODE (cpufreq_applet_show_mode_get_type ())
+#define CPUFREQ_TYPE_SHOW_TEXT_MODE (cpufreq_applet_show_text_mode_get_type ())
+
+typedef struct _CPUFreqApplet CPUFreqApplet;
+typedef struct _CPUFreqAppletClass CPUFreqAppletClass;
+
+typedef enum {
+ CPUFREQ_MODE_GRAPHIC,
+ CPUFREQ_MODE_TEXT,
+ CPUFREQ_MODE_BOTH
+} CPUFreqShowMode;
+
+typedef enum {
+ CPUFREQ_MODE_TEXT_FREQUENCY,
+ CPUFREQ_MODE_TEXT_FREQUENCY_UNIT,
+ CPUFREQ_MODE_TEXT_PERCENTAGE
+} CPUFreqShowTextMode;
+
+GType cpufreq_applet_get_type (void) G_GNUC_CONST;
+
+GType cpufreq_applet_show_mode_get_type (void) G_GNUC_CONST;
+GType cpufreq_applet_show_text_mode_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* CPUFREQ_APPLET_H */
diff --git a/cpufreq/src/cpufreq-monitor-cpuinfo.c b/cpufreq/src/cpufreq-monitor-cpuinfo.c
new file mode 100644
index 00000000..59585d8a
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-cpuinfo.c
@@ -0,0 +1,134 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include "cpufreq-monitor-cpuinfo.h"
+#include "cpufreq-utils.h"
+
+static void cpufreq_monitor_cpuinfo_class_init (CPUFreqMonitorCPUInfoClass *klass);
+
+static gboolean cpufreq_monitor_cpuinfo_run (CPUFreqMonitor *monitor);
+
+G_DEFINE_TYPE (CPUFreqMonitorCPUInfo, cpufreq_monitor_cpuinfo, CPUFREQ_TYPE_MONITOR)
+
+static void
+cpufreq_monitor_cpuinfo_init (CPUFreqMonitorCPUInfo *monitor)
+{
+}
+
+static void
+cpufreq_monitor_cpuinfo_class_init (CPUFreqMonitorCPUInfoClass *klass)
+{
+ CPUFreqMonitorClass *monitor_class = CPUFREQ_MONITOR_CLASS (klass);
+
+ monitor_class->run = cpufreq_monitor_cpuinfo_run;
+}
+
+CPUFreqMonitor *
+cpufreq_monitor_cpuinfo_new (guint cpu)
+{
+ CPUFreqMonitorCPUInfo *monitor;
+
+ monitor = g_object_new (CPUFREQ_TYPE_MONITOR_CPUINFO, "cpu", cpu, NULL);
+
+ return CPUFREQ_MONITOR (monitor);
+}
+
+static gboolean
+cpufreq_monitor_cpuinfo_run (CPUFreqMonitor *monitor)
+{
+ gchar *file;
+ gchar **lines;
+ gchar *buffer = NULL;
+ gchar *p;
+ gint cpu, i;
+ gint cur_freq, max_freq;
+ gchar *governor;
+ GError *error = NULL;
+
+ file = g_strdup ("/proc/cpuinfo");
+ if (!cpufreq_file_get_contents (file, &buffer, NULL, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ g_free (file);
+
+ return FALSE;
+ }
+ g_free (file);
+
+ /* TODO: SMP support */
+ lines = g_strsplit (buffer, "\n", -1);
+ for (i = 0; lines[i]; i++) {
+ if (g_ascii_strncasecmp ("cpu MHz", lines[i], strlen ("cpu MHz")) == 0) {
+ p = g_strrstr (lines[i], ":");
+
+ if (p == NULL) {
+ g_strfreev (lines);
+ g_free (buffer);
+
+ return FALSE;
+ }
+
+ if (strlen (lines[i]) < (size_t)(p - lines[i])) {
+ g_strfreev (lines);
+ g_free (buffer);
+
+ return FALSE;
+ }
+
+ if ((sscanf (p + 1, "%d.", &cpu)) != 1) {
+ g_strfreev (lines);
+ g_free (buffer);
+
+ return FALSE;
+ }
+
+ break;
+ }
+ }
+
+ g_strfreev (lines);
+ g_free (buffer);
+
+ governor = g_strdup (_("Frequency Scaling Unsupported"));
+ cur_freq = cpu * 1000;
+ max_freq = cur_freq;
+
+ g_object_set (G_OBJECT (monitor),
+ "governor", governor,
+ "frequency", cur_freq,
+ "max-frequency", max_freq,
+ NULL);
+
+ g_free (governor);
+
+ return TRUE;
+}
+
+
+
+
diff --git a/cpufreq/src/cpufreq-monitor-cpuinfo.h b/cpufreq/src/cpufreq-monitor-cpuinfo.h
new file mode 100644
index 00000000..ec58b405
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-cpuinfo.h
@@ -0,0 +1,50 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_MONITOR_CPUINFO_H__
+#define __CPUFREQ_MONITOR_CPUINFO_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-monitor.h"
+
+#define CPUFREQ_TYPE_MONITOR_CPUINFO (cpufreq_monitor_cpuinfo_get_type ())
+#define CPUFREQ_MONITOR_CPUINFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_MONITOR_CPUINFO, CPUFreqMonitorCPUInfo))
+#define CPUFREQ_MONITOR_CPUINFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_MONITOR_CPUINFO, CPUFreqMonitorCPUInfoClass))
+#define CPUFREQ_IS_MONITOR_CPUINFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_MONITOR_CPUINFO))
+#define CPUFREQ_IS_MONITOR_CPUINFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_MONITOR_CPUINFO))
+#define CPUFREQ_MONITOR_CPUINFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_MONITOR_CPUINFO, CPUFreqMonitorCPUInfoClass))
+
+typedef struct _CPUFreqMonitorCPUInfo CPUFreqMonitorCPUInfo;
+typedef struct _CPUFreqMonitorCPUInfoClass CPUFreqMonitorCPUInfoClass;
+
+struct _CPUFreqMonitorCPUInfo {
+ CPUFreqMonitor parent;
+};
+
+struct _CPUFreqMonitorCPUInfoClass {
+ CPUFreqMonitorClass parent_class;
+};
+
+GType cpufreq_monitor_cpuinfo_get_type (void) G_GNUC_CONST;
+CPUFreqMonitor *cpufreq_monitor_cpuinfo_new (guint cpu);
+
+#endif /* __CPUFREQ_MONITOR_CPUINFO_H__ */
diff --git a/cpufreq/src/cpufreq-monitor-factory.c b/cpufreq/src/cpufreq-monitor-factory.c
new file mode 100644
index 00000000..8b68082c
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-factory.c
@@ -0,0 +1,69 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "cpufreq-applet.h"
+#include "cpufreq-utils.h"
+#include "cpufreq-monitor-sysfs.h"
+#include "cpufreq-monitor-procfs.h"
+#include "cpufreq-monitor-cpuinfo.h"
+#ifdef HAVE_LIBCPUFREQ
+#include "cpufreq-monitor-libcpufreq.h"
+#endif
+#include "cpufreq-monitor-factory.h"
+
+CPUFreqMonitor *
+cpufreq_monitor_factory_create_monitor (guint cpu)
+{
+ CPUFreqMonitor *monitor = NULL;
+
+#ifdef HAVE_LIBCPUFREQ
+ monitor = cpufreq_monitor_libcpufreq_new (cpu);
+ return monitor;
+#endif
+
+ if (g_file_test ("/sys/devices/system/cpu/cpu0/cpufreq", G_FILE_TEST_EXISTS)) { /* 2.6 kernel */
+ monitor = cpufreq_monitor_sysfs_new (cpu);
+ } else if (g_file_test ("/proc/cpufreq", G_FILE_TEST_EXISTS)) { /* 2.4 kernel (Deprecated)*/
+ monitor = cpufreq_monitor_procfs_new (cpu);
+ } else if (g_file_test ("/proc/cpuinfo", G_FILE_TEST_EXISTS)) {
+ /* If there is no cpufreq support it shows only the cpu frequency,
+ * I think is better than do nothing. I have to notify it to the user, because
+ * he could think that cpufreq is supported but it doesn't work succesfully
+ */
+
+ cpufreq_utils_display_error (_("CPU frequency scaling unsupported"),
+ _("You will not be able to modify the frequency of your machine. "
+ "Your machine may be misconfigured or not have hardware support "
+ "for CPU frequency scaling."));
+
+ monitor = cpufreq_monitor_cpuinfo_new (cpu);
+ }
+
+ return monitor;
+}
+
diff --git a/cpufreq/src/cpufreq-monitor-factory.h b/cpufreq/src/cpufreq-monitor-factory.h
new file mode 100644
index 00000000..6a14b5f1
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-factory.h
@@ -0,0 +1,33 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef CPUFREQ_MONITOR_FACTORY_H
+#define CPUFREQ_MONITOR_FACTORY_H
+
+#include "cpufreq-monitor.h"
+
+G_BEGIN_DECLS
+
+CPUFreqMonitor *cpufreq_monitor_factory_create_monitor (guint cpu);
+
+G_END_DECLS
+
+#endif /* CPUFREQ_MONITOR_FACTORY_H */
diff --git a/cpufreq/src/cpufreq-monitor-libcpufreq.c b/cpufreq/src/cpufreq-monitor-libcpufreq.c
new file mode 100644
index 00000000..494d9a66
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-libcpufreq.c
@@ -0,0 +1,199 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <stdlib.h>
+#include <cpufreq.h>
+
+#include "cpufreq-monitor-libcpufreq.h"
+#include "cpufreq-utils.h"
+
+static void cpufreq_monitor_libcpufreq_class_init (CPUFreqMonitorLibcpufreqClass *klass);
+
+static gboolean cpufreq_monitor_libcpufreq_run (CPUFreqMonitor *monitor);
+static GList *cpufreq_monitor_libcpufreq_get_available_frequencies (CPUFreqMonitor *monitor);
+static GList *cpufreq_monitor_libcpufreq_get_available_governors (CPUFreqMonitor *monitor);
+
+G_DEFINE_TYPE (CPUFreqMonitorLibcpufreq, cpufreq_monitor_libcpufreq, CPUFREQ_TYPE_MONITOR)
+
+typedef struct cpufreq_policy CPUFreqPolicy;
+typedef struct cpufreq_available_frequencies CPUFreqFrequencyList;
+typedef struct cpufreq_available_governors CPUFreqGovernorList;
+
+static void
+cpufreq_monitor_libcpufreq_init (CPUFreqMonitorLibcpufreq *monitor)
+{
+}
+
+static GObject *
+cpufreq_monitor_libcpufreq_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ gulong max_freq, min_freq;
+ guint cpu;
+
+ object = G_OBJECT_CLASS (
+ cpufreq_monitor_libcpufreq_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_params);
+ g_object_get (G_OBJECT (object),
+ "cpu", &cpu,
+ NULL);
+
+ if (cpufreq_get_hardware_limits (cpu, &min_freq, &max_freq) != 0) {
+ g_warning ("Error getting CPUINFO_MAX\n");
+ max_freq = -1;
+ }
+
+ g_object_set (G_OBJECT (object),
+ "max-frequency", max_freq,
+ NULL);
+
+ return object;
+}
+
+static void
+cpufreq_monitor_libcpufreq_class_init (CPUFreqMonitorLibcpufreqClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CPUFreqMonitorClass *monitor_class = CPUFREQ_MONITOR_CLASS (klass);
+
+ object_class->constructor = cpufreq_monitor_libcpufreq_constructor;
+
+ monitor_class->run = cpufreq_monitor_libcpufreq_run;
+ monitor_class->get_available_frequencies = cpufreq_monitor_libcpufreq_get_available_frequencies;
+ monitor_class->get_available_governors = cpufreq_monitor_libcpufreq_get_available_governors;
+}
+
+CPUFreqMonitor *
+cpufreq_monitor_libcpufreq_new (guint cpu)
+{
+ CPUFreqMonitorLibcpufreq *monitor;
+
+ monitor = g_object_new (CPUFREQ_TYPE_MONITOR_LIBCPUFREQ,
+ "cpu", cpu, NULL);
+
+ return CPUFREQ_MONITOR (monitor);
+}
+
+static gboolean
+cpufreq_monitor_libcpufreq_run (CPUFreqMonitor *monitor)
+{
+ guint cpu;
+ CPUFreqPolicy *policy;
+
+ g_object_get (G_OBJECT (monitor), "cpu", &cpu, NULL);
+
+ policy = cpufreq_get_policy (cpu);
+ if (!policy) {
+ /* Check whether it failed because
+ * cpu is not online.
+ */
+ if (!cpufreq_cpu_exists (cpu)) {
+ g_object_set (G_OBJECT (monitor), "online", FALSE, NULL);
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ g_object_set (G_OBJECT (monitor),
+ "online", TRUE,
+ "governor", policy->governor,
+ "frequency", cpufreq_get_freq_kernel (cpu),
+ NULL);
+
+ cpufreq_put_policy (policy);
+
+ return TRUE;
+}
+
+static gint
+compare (gconstpointer a, gconstpointer b)
+{
+ gint aa, bb;
+
+ aa = atoi ((gchar *) a);
+ bb = atoi ((gchar *) b);
+
+ if (aa == bb)
+ return 0;
+ else if (aa > bb)
+ return -1;
+ else
+ return 1;
+}
+
+static GList *
+cpufreq_monitor_libcpufreq_get_available_frequencies (CPUFreqMonitor *monitor)
+{
+ GList *list = NULL;
+ guint cpu;
+ CPUFreqFrequencyList *freqs, *freq;
+
+ g_object_get (G_OBJECT (monitor),
+ "cpu", &cpu, NULL);
+
+ freqs = cpufreq_get_available_frequencies (cpu);
+ if (!freqs)
+ return NULL;
+
+ for (freq = freqs; freq; freq = freq->next) {
+ gchar *frequency;
+
+ frequency = g_strdup_printf ("%lu", freq->frequency);
+
+ if (!g_list_find_custom (list, frequency, compare))
+ list = g_list_prepend (list, frequency);
+ else
+ g_free (frequency);
+ }
+
+ cpufreq_put_available_frequencies (freqs);
+
+ return g_list_sort (list, compare);
+}
+
+static GList *
+cpufreq_monitor_libcpufreq_get_available_governors (CPUFreqMonitor *monitor)
+{
+ guint cpu;
+ GList *list = NULL;
+ CPUFreqGovernorList *govs, *gov;
+
+ g_object_get (G_OBJECT (monitor),
+ "cpu", &cpu, NULL);
+
+ govs = cpufreq_get_available_governors (cpu);
+ if (!govs)
+ return NULL;
+
+ for (gov = govs; gov; gov = gov->next) {
+ list = g_list_prepend (list, g_strdup (gov->governor));
+ }
+
+ cpufreq_put_available_governors (govs);
+
+ return list;
+}
diff --git a/cpufreq/src/cpufreq-monitor-libcpufreq.h b/cpufreq/src/cpufreq-monitor-libcpufreq.h
new file mode 100644
index 00000000..7b41ea6b
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-libcpufreq.h
@@ -0,0 +1,56 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_MONITOR_LIBCPUFREQ_H__
+#define __CPUFREQ_MONITOR_LIBCPUFREQ_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-monitor.h"
+
+#define CPUFREQ_TYPE_MONITOR_LIBCPUFREQ \
+ (cpufreq_monitor_libcpufreq_get_type ())
+#define CPUFREQ_MONITOR_LIBCPUFREQ(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_MONITOR_LIBCPUFREQ, CPUFreqMonitorLibcpufreq))
+#define CPUFREQ_MONITOR_LIBCPUFREQ_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_MONITOR_LIBCPUFREQ, CPUFreqMonitorLibcpufreqClass))
+#define CPUFREQ_IS_MONITOR_LIBCPUFREQ(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_MONITOR_LIBCPUFREQ))
+#define CPUFREQ_IS_MONITOR_LIBCPUFREQ_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_MONITOR_LIBCPUFREQ))
+#define CPUFREQ_MONITOR_LIBCPUFREQ_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_MONITOR_LIBCPUFREQ, CPUFreqMonitorLibcpufreqClass))
+
+typedef struct _CPUFreqMonitorLibcpufreq CPUFreqMonitorLibcpufreq;
+typedef struct _CPUFreqMonitorLibcpufreqClass CPUFreqMonitorLibcpufreqClass;
+
+struct _CPUFreqMonitorLibcpufreq {
+ CPUFreqMonitor parent;
+};
+
+struct _CPUFreqMonitorLibcpufreqClass {
+ CPUFreqMonitorClass parent_class;
+};
+
+GType cpufreq_monitor_libcpufreq_get_type (void) G_GNUC_CONST;
+CPUFreqMonitor *cpufreq_monitor_libcpufreq_new (guint cpu);
+
+#endif /* __CPUFREQ_MONITOR_LIBCPUFREQ_H__ */
diff --git a/cpufreq/src/cpufreq-monitor-procfs.c b/cpufreq/src/cpufreq-monitor-procfs.c
new file mode 100644
index 00000000..97c635ba
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-procfs.c
@@ -0,0 +1,221 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cpufreq-monitor-procfs.h"
+#include "cpufreq-utils.h"
+
+static void cpufreq_monitor_procfs_class_init (CPUFreqMonitorProcfsClass *klass);
+
+static gboolean cpufreq_monitor_procfs_run (CPUFreqMonitor *monitor);
+static GList *cpufreq_monitor_procfs_get_available_frequencies (CPUFreqMonitor *monitor);
+
+G_DEFINE_TYPE (CPUFreqMonitorProcfs, cpufreq_monitor_procfs, CPUFREQ_TYPE_MONITOR)
+
+static void
+cpufreq_monitor_procfs_init (CPUFreqMonitorProcfs *monitor)
+{
+}
+
+static void
+cpufreq_monitor_procfs_class_init (CPUFreqMonitorProcfsClass *klass)
+{
+ CPUFreqMonitorClass *monitor_class = CPUFREQ_MONITOR_CLASS (klass);
+
+ monitor_class->run = cpufreq_monitor_procfs_run;
+ monitor_class->get_available_frequencies = cpufreq_monitor_procfs_get_available_frequencies;
+}
+
+CPUFreqMonitor *
+cpufreq_monitor_procfs_new (guint cpu)
+{
+ CPUFreqMonitorProcfs *monitor;
+
+ monitor = g_object_new (TYPE_CPUFREQ_MONITOR_PROCFS, "cpu", cpu, NULL);
+
+ return CPUFREQ_MONITOR (monitor);
+}
+
+static gint
+cpufreq_monitor_procfs_get_freq_from_userspace (guint cpu)
+{
+ gchar *buffer = NULL;
+ gchar *path;
+ gchar *p;
+ gchar *frequency;
+ gint freq;
+ gint len;
+ GError *error = NULL;
+
+ path = g_strdup_printf ("/proc/sys/cpu/%u/speed", cpu);
+
+ if (!cpufreq_file_get_contents (path, &buffer, NULL, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ g_free (path);
+
+ return -1;
+ }
+
+ g_free (path);
+
+ /* Try to remove the '\n' */
+ p = g_strrstr (buffer, "\n");
+ len = strlen (buffer);
+ if (p)
+ len -= strlen (p);
+
+ frequency = g_strndup (buffer, len);
+ g_free (buffer);
+
+ freq = atoi (frequency);
+ g_free (frequency);
+
+ return freq;
+}
+
+static gboolean
+cpufreq_monitor_procfs_parse (CPUFreqMonitorProcfs *monitor,
+ gint *cpu,
+ gint *fmax,
+ gint *pmin,
+ gint *pmax,
+ gint *fmin,
+ gchar *mode)
+{
+ gchar **lines;
+ gchar *buffer = NULL;
+ gint i, count;
+ guint mon_cpu;
+ GError *error = NULL;
+
+ if (!cpufreq_file_get_contents ("/proc/cpufreq", &buffer, NULL, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ g_object_get (G_OBJECT (monitor),
+ "cpu", &mon_cpu, NULL);
+
+ count = 0;
+ lines = g_strsplit (buffer, "\n", -1);
+ for (i = 0; lines[i]; i++) {
+ if (g_ascii_strncasecmp (lines[i], "CPU", 3) == 0) {
+ /* CPU 0 650000 kHz ( 81 %) - 800000 kHz (100 %) - powersave */
+ count = sscanf (lines[i], "CPU %d %d kHz (%d %%) - %d kHz (%d %%) - %20s",
+ cpu, fmin, pmin, fmax, pmax, mode);
+
+ if ((guint)(*cpu) == mon_cpu)
+ break;
+ }
+ }
+
+ g_strfreev (lines);
+ g_free (buffer);
+
+ return (count == 6);
+}
+
+static gboolean
+cpufreq_procfs_cpu_is_online (void)
+{
+ return g_file_test ("/proc/cpufreq",
+ G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR);
+}
+
+static gboolean
+cpufreq_monitor_procfs_run (CPUFreqMonitor *monitor)
+{
+ gint fmax, fmin, cpu;
+ gint pmin, pmax;
+ gchar mode[21];
+ gint cur_freq, max_freq;
+ gchar *governor;
+
+ if (!cpufreq_monitor_procfs_parse (CPUFREQ_MONITOR_PROCFS (monitor),
+ &cpu, &fmax, &pmin, &pmax, &fmin, mode)) {
+ /* Check whether it failed because
+ * cpu is not online.
+ */
+ if (!cpufreq_procfs_cpu_is_online ()) {
+ g_object_set (G_OBJECT (monitor), "online", FALSE, NULL);
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ governor = mode;
+ max_freq = fmax;
+
+ if (g_ascii_strcasecmp (governor, "powersave") == 0) {
+ cur_freq = fmin;
+ } else if (g_ascii_strcasecmp (governor, "performance") == 0) {
+ cur_freq = fmax;
+ } else if (g_ascii_strcasecmp (governor, "userspace") == 0) {
+ cur_freq = cpufreq_monitor_procfs_get_freq_from_userspace (cpu);
+ } else {
+ cur_freq = fmax;
+ }
+
+ g_object_set (G_OBJECT (monitor),
+ "online", TRUE,
+ "governor", governor,
+ "frequency", cur_freq,
+ "max-frequency", max_freq,
+ NULL);
+
+ return TRUE;
+}
+
+static GList *
+cpufreq_monitor_procfs_get_available_frequencies (CPUFreqMonitor *monitor)
+{
+ gint fmax, fmin, cpu, freq;
+ gint pmin, pmax;
+ gchar mode[21];
+ GList *list = NULL;
+
+ if (!cpufreq_monitor_procfs_parse (CPUFREQ_MONITOR_PROCFS (monitor), &cpu,
+ &fmax, &pmin, &pmax, &fmin, mode)) {
+ return NULL;
+ }
+
+ if ((pmax > 0) && (pmax != 100)) {
+ freq = (fmax * 100) / pmax;
+ list = g_list_prepend (list, g_strdup_printf ("%d", freq));
+ }
+
+ list = g_list_prepend (list, g_strdup_printf ("%d", fmax));
+ if (fmax != fmin)
+ list = g_list_prepend (list, g_strdup_printf ("%d", fmin));
+
+ return g_list_reverse (list);
+}
+
diff --git a/cpufreq/src/cpufreq-monitor-procfs.h b/cpufreq/src/cpufreq-monitor-procfs.h
new file mode 100644
index 00000000..62649152
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-procfs.h
@@ -0,0 +1,54 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_MONITOR_PROCFS_H__
+#define __CPUFREQ_MONITOR_PROCFS_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-monitor.h"
+
+G_BEGIN_DECLS
+
+#define TYPE_CPUFREQ_MONITOR_PROCFS (cpufreq_monitor_procfs_get_type ())
+#define CPUFREQ_MONITOR_PROCFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CPUFREQ_MONITOR_PROCFS, CPUFreqMonitorProcfs))
+#define CPUFREQ_MONITOR_PROCFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_CPUFREQ_MONITOR_PROCFS, CPUFreqMonitorProcfsClass))
+#define IS_CPUFREQ_MONITOR_PROCFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CPUFREQ_MONITOR_PROCFS))
+#define IS_CPUFREQ_MONITOR_PROCFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CPUFREQ_MONITOR_PROCFS))
+#define CPUFREQ_MONITOR_PROCFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CPUFREQ_MONITOR_PROCFS, CPUFreqMonitorProcfsClass))
+
+typedef struct _CPUFreqMonitorProcfs CPUFreqMonitorProcfs;
+typedef struct _CPUFreqMonitorProcfsClass CPUFreqMonitorProcfsClass;
+
+struct _CPUFreqMonitorProcfs {
+ CPUFreqMonitor parent;
+};
+
+struct _CPUFreqMonitorProcfsClass {
+ CPUFreqMonitorClass parent_class;
+};
+
+GType cpufreq_monitor_procfs_get_type (void) G_GNUC_CONST;
+CPUFreqMonitor *cpufreq_monitor_procfs_new (guint cpu);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_MONITOR_PROCFS_H__ */
diff --git a/cpufreq/src/cpufreq-monitor-sysfs.c b/cpufreq/src/cpufreq-monitor-sysfs.c
new file mode 100644
index 00000000..a123a36f
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-sysfs.c
@@ -0,0 +1,345 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "cpufreq-monitor-sysfs.h"
+#include "cpufreq-utils.h"
+
+enum {
+ SCALING_MAX,
+ SCALING_MIN,
+ GOVERNOR,
+ CPUINFO_MAX,
+ SCALING_SETSPEED,
+ SCALING_CUR_FREQ,
+ N_FILES
+};
+
+static void cpufreq_monitor_sysfs_class_init (CPUFreqMonitorSysfsClass *klass);
+
+static gboolean cpufreq_monitor_sysfs_run (CPUFreqMonitor *monitor);
+static GList *cpufreq_monitor_sysfs_get_available_frequencies (CPUFreqMonitor *monitor);
+static GList *cpufreq_monitor_sysfs_get_available_governors (CPUFreqMonitor *monitor);
+
+static gchar *cpufreq_sysfs_read (const gchar *path,
+ GError **error);
+
+/* /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_max_freq
+ * /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_min_freq
+ * /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_governor
+ * /sys/devices/system/cpu/cpu[0]/cpufreq/cpuinfo_max_freq
+ * /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_setspeed (userspace)
+ * /sys/devices/system/cpu/cpu[0]/cpufreq/scaling_cur_freq (new governors)
+ */
+const gchar *monitor_sysfs_files[] = {
+ "scaling_max_freq",
+ "scaling_min_freq",
+ "scaling_governor",
+ "cpuinfo_max_freq",
+ "scaling_setspeed",
+ "scaling_cur_freq",
+ NULL
+};
+
+#define CPUFREQ_SYSFS_BASE_PATH "/sys/devices/system/cpu/cpu%u/cpufreq/%s"
+
+G_DEFINE_TYPE (CPUFreqMonitorSysfs, cpufreq_monitor_sysfs, CPUFREQ_TYPE_MONITOR)
+
+static void
+cpufreq_monitor_sysfs_init (CPUFreqMonitorSysfs *monitor)
+{
+}
+
+static GObject *
+cpufreq_monitor_sysfs_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ gchar *path;
+ gchar *frequency;
+ gint max_freq;
+ guint cpu;
+ GError *error = NULL;
+
+ object = G_OBJECT_CLASS (
+ cpufreq_monitor_sysfs_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_params);
+ g_object_get (G_OBJECT (object),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
+ cpu, monitor_sysfs_files[CPUINFO_MAX]);
+
+ frequency = cpufreq_sysfs_read (path, &error);
+ if (!frequency) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ max_freq = -1;
+ } else {
+ max_freq = atoi (frequency);
+ }
+
+ g_free (path);
+ g_free (frequency);
+
+ g_object_set (G_OBJECT (object),
+ "max-frequency", max_freq,
+ NULL);
+
+ return object;
+}
+
+static void
+cpufreq_monitor_sysfs_class_init (CPUFreqMonitorSysfsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CPUFreqMonitorClass *monitor_class = CPUFREQ_MONITOR_CLASS (klass);
+
+ object_class->constructor = cpufreq_monitor_sysfs_constructor;
+
+ monitor_class->run = cpufreq_monitor_sysfs_run;
+ monitor_class->get_available_frequencies = cpufreq_monitor_sysfs_get_available_frequencies;
+ monitor_class->get_available_governors = cpufreq_monitor_sysfs_get_available_governors;
+}
+
+CPUFreqMonitor *
+cpufreq_monitor_sysfs_new (guint cpu)
+{
+ CPUFreqMonitorSysfs *monitor;
+
+ monitor = g_object_new (CPUFREQ_TYPE_MONITOR_SYSFS,
+ "cpu", cpu, NULL);
+
+ return CPUFREQ_MONITOR (monitor);
+}
+
+static gchar *
+cpufreq_sysfs_read (const gchar *path,
+ GError **error)
+{
+ gchar *buffer = NULL;
+
+ if (!cpufreq_file_get_contents (path, &buffer, NULL, error)) {
+ return NULL;
+ }
+
+ return g_strchomp (buffer);
+}
+
+static gboolean
+cpufreq_sysfs_cpu_is_online (guint cpu)
+{
+ gchar *path;
+ gboolean retval;
+
+ path = g_strdup_printf ("/sys/devices/system/cpu/cpu%u/", cpu);
+ retval = g_file_test (path, G_FILE_TEST_IS_DIR);
+ g_free (path);
+
+ return retval;
+}
+
+static gboolean
+cpufreq_monitor_sysfs_run (CPUFreqMonitor *monitor)
+{
+ guint cpu;
+ gchar *frequency;
+ gchar *governor;
+ gchar *path;
+ GError *error = NULL;
+
+ g_object_get (G_OBJECT (monitor),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
+ cpu, monitor_sysfs_files[GOVERNOR]);
+ governor = cpufreq_sysfs_read (path, &error);
+ if (!governor) {
+ gboolean retval = FALSE;
+
+ /* Check whether it failed because
+ * cpu is not online.
+ */
+ if (!cpufreq_sysfs_cpu_is_online (cpu)) {
+ g_object_set (G_OBJECT (monitor), "online", FALSE, NULL);
+ retval = TRUE;
+ } else {
+ g_warning ("%s", error->message);
+ }
+
+ g_error_free (error);
+ g_free (path);
+
+ return retval;
+ }
+
+ g_free (path);
+
+ if (g_ascii_strcasecmp (governor, "userspace") == 0) {
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
+ cpu, monitor_sysfs_files[SCALING_SETSPEED]);
+ } else if (g_ascii_strcasecmp (governor, "powersave") == 0) {
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
+ cpu, monitor_sysfs_files[SCALING_MIN]);
+ } else if (g_ascii_strcasecmp (governor, "performance") == 0) {
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
+ cpu, monitor_sysfs_files[SCALING_MAX]);
+ } else { /* Ondemand, Conservative, ... */
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH,
+ cpu, monitor_sysfs_files[SCALING_CUR_FREQ]);
+ }
+
+ frequency = cpufreq_sysfs_read (path, &error);
+ if (!frequency) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ g_free (path);
+ g_free (governor);
+
+ return FALSE;
+ }
+
+ g_free (path);
+
+ g_object_set (G_OBJECT (monitor),
+ "online", TRUE,
+ "governor", governor,
+ "frequency", atoi (frequency),
+ NULL);
+
+ g_free (governor);
+ g_free (frequency);
+
+ return TRUE;
+}
+
+static gint
+compare (gconstpointer a, gconstpointer b)
+{
+ gint aa, bb;
+
+ aa = atoi ((gchar *) a);
+ bb = atoi ((gchar *) b);
+
+ if (aa == bb)
+ return 0;
+ else if (aa > bb)
+ return -1;
+ else
+ return 1;
+}
+
+static GList *
+cpufreq_monitor_sysfs_get_available_frequencies (CPUFreqMonitor *monitor)
+{
+ gchar *path;
+ GList *list = NULL;
+ gchar **frequencies = NULL;
+ gint i;
+ guint cpu;
+ gchar *buffer = NULL;
+ GError *error = NULL;
+
+ g_object_get (G_OBJECT (monitor),
+ "cpu", &cpu, NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_available_frequencies");
+
+ if (!cpufreq_file_get_contents (path, &buffer, NULL, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ g_free (path);
+
+ return NULL;
+ }
+
+ g_free (path);
+
+ buffer = g_strchomp (buffer);
+ frequencies = g_strsplit (buffer, " ", -1);
+
+ i = 0;
+ while (frequencies[i]) {
+ if (!g_list_find_custom (list, frequencies[i], compare))
+ list = g_list_prepend (list, g_strdup (frequencies[i]));
+ i++;
+ }
+
+ g_strfreev (frequencies);
+ g_free (buffer);
+
+ return g_list_sort (list, compare);
+}
+
+static GList *
+cpufreq_monitor_sysfs_get_available_governors (CPUFreqMonitor *monitor)
+{
+ gchar *path;
+ GList *list = NULL;
+ gchar **governors = NULL;
+ gint i;
+ guint cpu;
+ gchar *buffer = NULL;
+ GError *error = NULL;
+
+ g_object_get (G_OBJECT (monitor),
+ "cpu", &cpu, NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_available_governors");
+
+ if (!cpufreq_file_get_contents (path, &buffer, NULL, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ g_free (path);
+
+ return NULL;
+ }
+
+ g_free (path);
+
+ buffer = g_strchomp (buffer);
+
+ governors = g_strsplit (buffer, " ", -1);
+
+ i = 0;
+ while (governors[i] != NULL) {
+ list = g_list_prepend (list, g_strdup (governors[i]));
+ i++;
+ }
+
+ g_strfreev (governors);
+ g_free (buffer);
+
+ return list;
+}
diff --git a/cpufreq/src/cpufreq-monitor-sysfs.h b/cpufreq/src/cpufreq-monitor-sysfs.h
new file mode 100644
index 00000000..ee75dd9b
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor-sysfs.h
@@ -0,0 +1,54 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_MONITOR_SYSFS_H__
+#define __CPUFREQ_MONITOR_SYSFS_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-monitor.h"
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_MONITOR_SYSFS (cpufreq_monitor_sysfs_get_type ())
+#define CPUFREQ_MONITOR_SYSFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_MONITOR_SYSFS, CPUFreqMonitorSysfs))
+#define CPUFREQ_MONITOR_SYSFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_MONITOR_SYSFS, CPUFreqMonitorSysfsClass))
+#define CPUFREQ_IS_MONITOR_SYSFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_MONITOR_SYSFS))
+#define CPUFREQ_IS_MONITOR_SYSFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_MONITOR_SYSFS))
+#define CPUFREQ_MONITOR_SYSFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_MONITOR_SYSFS, CPUFreqMonitorSysfsClass))
+
+typedef struct _CPUFreqMonitorSysfs CPUFreqMonitorSysfs;
+typedef struct _CPUFreqMonitorSysfsClass CPUFreqMonitorSysfsClass;
+
+struct _CPUFreqMonitorSysfs {
+ CPUFreqMonitor parent;
+};
+
+struct _CPUFreqMonitorSysfsClass {
+ CPUFreqMonitorClass parent_class;
+};
+
+GType cpufreq_monitor_sysfs_get_type (void) G_GNUC_CONST;
+CPUFreqMonitor *cpufreq_monitor_sysfs_new (guint cpu);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_MONITOR_SYSFS_H__ */
diff --git a/cpufreq/src/cpufreq-monitor.c b/cpufreq/src/cpufreq-monitor.c
new file mode 100644
index 00000000..662c94a9
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor.c
@@ -0,0 +1,411 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include "cpufreq-monitor.h"
+
+#define CPUFREQ_MONITOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), CPUFREQ_TYPE_MONITOR, CPUFreqMonitorPrivate))
+
+#define CPUFREQ_MONITOR_INTERVAL 1
+
+/* Properties */
+enum {
+ PROP_0,
+ PROP_CPU,
+ PROP_ONLINE,
+ PROP_FREQUENCY,
+ PROP_MAX_FREQUENCY,
+ PROP_GOVERNOR
+};
+
+/* Signals */
+enum {
+ SIGNAL_CHANGED,
+ N_SIGNALS
+};
+
+struct _CPUFreqMonitorPrivate {
+ guint cpu;
+ gboolean online;
+ gint cur_freq;
+ gint max_freq;
+ gchar *governor;
+ GList *available_freqs;
+ GList *available_govs;
+ guint timeout_handler;
+
+ gboolean changed;
+};
+
+static void cpufreq_monitor_init (CPUFreqMonitor *monitor);
+static void cpufreq_monitor_class_init (CPUFreqMonitorClass *klass);
+static void cpufreq_monitor_finalize (GObject *object);
+
+static void cpufreq_monitor_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *spec);
+static void cpufreq_monitor_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *spec);
+
+static guint signals[N_SIGNALS];
+
+G_DEFINE_ABSTRACT_TYPE (CPUFreqMonitor, cpufreq_monitor, G_TYPE_OBJECT)
+
+static void
+cpufreq_monitor_init (CPUFreqMonitor *monitor)
+{
+ monitor->priv = CPUFREQ_MONITOR_GET_PRIVATE (monitor);
+
+ monitor->priv->governor = NULL;
+ monitor->priv->available_freqs = NULL;
+ monitor->priv->available_govs = NULL;
+ monitor->priv->timeout_handler = 0;
+
+ monitor->priv->changed = FALSE;
+}
+
+static void
+cpufreq_monitor_class_init (CPUFreqMonitorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = cpufreq_monitor_set_property;
+ object_class->get_property = cpufreq_monitor_get_property;
+
+ /* Public virtual methods */
+ klass->run = NULL;
+ klass->get_available_frequencies = NULL;
+ klass->get_available_governors = NULL;
+
+ g_type_class_add_private (klass, sizeof (CPUFreqMonitorPrivate));
+
+ /* Porperties */
+ g_object_class_install_property (object_class,
+ PROP_CPU,
+ g_param_spec_uint ("cpu",
+ "CPU",
+ "The cpu to monitor",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT |
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_ONLINE,
+ g_param_spec_boolean ("online",
+ "Online",
+ "Whether cpu is online",
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_FREQUENCY,
+ g_param_spec_int ("frequency",
+ "Frequency",
+ "The current cpu frequency",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_MAX_FREQUENCY,
+ g_param_spec_int ("max-frequency",
+ "MaxFrequency",
+ "The max cpu frequency",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_GOVERNOR,
+ g_param_spec_string ("governor",
+ "Governor",
+ "The current cpufreq governor",
+ NULL,
+ G_PARAM_READWRITE));
+
+ /* Signals */
+ signals[SIGNAL_CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CPUFreqMonitorClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ object_class->finalize = cpufreq_monitor_finalize;
+}
+
+static void
+cpufreq_monitor_finalize (GObject *object)
+{
+ CPUFreqMonitor *monitor = CPUFREQ_MONITOR (object);
+
+ monitor->priv->online = FALSE;
+
+ if (monitor->priv->timeout_handler > 0) {
+ g_source_remove (monitor->priv->timeout_handler);
+ monitor->priv->timeout_handler = 0;
+ }
+
+ if (monitor->priv->governor) {
+ g_free (monitor->priv->governor);
+ monitor->priv->governor = NULL;
+ }
+
+ if (monitor->priv->available_freqs) {
+ g_list_foreach (monitor->priv->available_freqs,
+ (GFunc) g_free,
+ NULL);
+ g_list_free (monitor->priv->available_freqs);
+ monitor->priv->available_freqs = NULL;
+ }
+
+ if (monitor->priv->available_govs) {
+ g_list_foreach (monitor->priv->available_govs,
+ (GFunc) g_free,
+ NULL);
+ g_list_free (monitor->priv->available_govs);
+ monitor->priv->available_govs = NULL;
+ }
+
+ G_OBJECT_CLASS (cpufreq_monitor_parent_class)->finalize (object);
+}
+
+static void
+cpufreq_monitor_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *spec)
+{
+ CPUFreqMonitor *monitor;
+
+ monitor = CPUFREQ_MONITOR (object);
+
+ switch (prop_id) {
+ case PROP_CPU: {
+ guint cpu = g_value_get_uint (value);
+
+ if (cpu != monitor->priv->cpu) {
+ monitor->priv->cpu = cpu;
+ monitor->priv->changed = TRUE;
+ }
+ }
+ break;
+ case PROP_ONLINE:
+ monitor->priv->online = g_value_get_boolean (value);
+
+ break;
+ case PROP_FREQUENCY: {
+ gint freq = g_value_get_int (value);
+
+ if (freq != monitor->priv->cur_freq) {
+ monitor->priv->cur_freq = freq;
+ monitor->priv->changed = TRUE;
+ }
+ }
+ break;
+ case PROP_MAX_FREQUENCY: {
+ gint freq = g_value_get_int (value);
+
+ if (freq != monitor->priv->max_freq) {
+ monitor->priv->max_freq = freq;
+ monitor->priv->changed = TRUE;
+ }
+ }
+ break;
+ case PROP_GOVERNOR: {
+ const gchar *gov = g_value_get_string (value);
+
+ if (monitor->priv->governor) {
+ if (g_ascii_strcasecmp (gov, monitor->priv->governor) != 0) {
+ g_free (monitor->priv->governor);
+ monitor->priv->governor = gov ? g_strdup (gov) : NULL;
+ monitor->priv->changed = TRUE;
+ }
+ } else {
+ monitor->priv->governor = gov ? g_strdup (gov) : NULL;
+ monitor->priv->changed = TRUE;
+ }
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
+ break;
+ }
+}
+
+static void
+cpufreq_monitor_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *spec)
+{
+ CPUFreqMonitor *monitor;
+
+ monitor = CPUFREQ_MONITOR (object);
+
+ switch (prop_id) {
+ case PROP_CPU:
+ g_value_set_uint (value, monitor->priv->cpu);
+ break;
+ case PROP_ONLINE:
+ g_value_set_boolean (value, monitor->priv->online);
+ break;
+ case PROP_FREQUENCY:
+ g_value_set_int (value, monitor->priv->cur_freq);
+ break;
+ case PROP_MAX_FREQUENCY:
+ g_value_set_int (value, monitor->priv->max_freq);
+ break;
+ case PROP_GOVERNOR:
+ g_value_set_string (value, monitor->priv->governor);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
+ break;
+ }
+}
+
+static gboolean
+cpufreq_monitor_run_cb (CPUFreqMonitor *monitor)
+{
+ CPUFreqMonitorClass *class;
+ gboolean retval = FALSE;
+
+ class = CPUFREQ_MONITOR_GET_CLASS (monitor);
+
+ if (class->run)
+ retval = class->run (monitor);
+
+ if (monitor->priv->changed) {
+ g_signal_emit (monitor, signals[SIGNAL_CHANGED], 0);
+ monitor->priv->changed = FALSE;
+ }
+
+ return retval;
+}
+
+void
+cpufreq_monitor_run (CPUFreqMonitor *monitor)
+{
+ g_return_if_fail (CPUFREQ_IS_MONITOR (monitor));
+
+ if (monitor->priv->timeout_handler > 0)
+ return;
+
+ monitor->priv->timeout_handler =
+ g_timeout_add_seconds (CPUFREQ_MONITOR_INTERVAL,
+ (GSourceFunc) cpufreq_monitor_run_cb,
+ (gpointer) monitor);
+}
+
+GList *
+cpufreq_monitor_get_available_frequencies (CPUFreqMonitor *monitor)
+{
+ CPUFreqMonitorClass *class;
+
+ g_return_val_if_fail (CPUFREQ_IS_MONITOR (monitor), NULL);
+
+ if (!monitor->priv->online)
+ return NULL;
+
+ if (monitor->priv->available_freqs)
+ return monitor->priv->available_freqs;
+
+ class = CPUFREQ_MONITOR_GET_CLASS (monitor);
+
+ if (class->get_available_frequencies) {
+ monitor->priv->available_freqs = class->get_available_frequencies (monitor);
+ }
+
+ return monitor->priv->available_freqs;
+}
+
+GList *
+cpufreq_monitor_get_available_governors (CPUFreqMonitor *monitor)
+{
+ CPUFreqMonitorClass *class;
+
+ g_return_val_if_fail (CPUFREQ_IS_MONITOR (monitor), NULL);
+
+ if (!monitor->priv->online)
+ return NULL;
+
+ if (monitor->priv->available_govs)
+ return monitor->priv->available_govs;
+
+ class = CPUFREQ_MONITOR_GET_CLASS (monitor);
+
+ if (class->get_available_governors) {
+ monitor->priv->available_govs = class->get_available_governors (monitor);
+ }
+
+ return monitor->priv->available_govs;
+}
+
+guint
+cpufreq_monitor_get_cpu (CPUFreqMonitor *monitor)
+{
+ g_return_val_if_fail (CPUFREQ_IS_MONITOR (monitor), 0);
+
+ return monitor->priv->cpu;
+}
+
+void
+cpufreq_monitor_set_cpu (CPUFreqMonitor *monitor, guint cpu)
+{
+ g_return_if_fail (CPUFREQ_IS_MONITOR (monitor));
+
+ g_object_set (G_OBJECT (monitor),
+ "cpu", cpu, NULL);
+}
+
+gint
+cpufreq_monitor_get_frequency (CPUFreqMonitor *monitor)
+{
+ g_return_val_if_fail (CPUFREQ_IS_MONITOR (monitor), -1);
+
+ return monitor->priv->cur_freq;
+}
+
+const gchar *
+cpufreq_monitor_get_governor (CPUFreqMonitor *monitor)
+{
+ g_return_val_if_fail (CPUFREQ_IS_MONITOR (monitor), NULL);
+
+ return monitor->priv->governor;
+}
+
+gint
+cpufreq_monitor_get_percentage (CPUFreqMonitor *monitor)
+{
+ g_return_val_if_fail (CPUFREQ_IS_MONITOR (monitor), -1);
+
+ if (monitor->priv->max_freq > 0) {
+ return ((monitor->priv->cur_freq * 100) / monitor->priv->max_freq);
+ }
+
+ return -1;
+}
diff --git a/cpufreq/src/cpufreq-monitor.h b/cpufreq/src/cpufreq-monitor.h
new file mode 100644
index 00000000..0b9ac508
--- /dev/null
+++ b/cpufreq/src/cpufreq-monitor.h
@@ -0,0 +1,72 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_MONITOR_H__
+#define __CPUFREQ_MONITOR_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_MONITOR (cpufreq_monitor_get_type ())
+#define CPUFREQ_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_MONITOR, CPUFreqMonitor))
+#define CPUFREQ_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_MONITOR, CPUFreqMonitorClass))
+#define CPUFREQ_IS_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_MONITOR))
+#define CPUFREQ_IS_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_MONITOR))
+#define CPUFREQ_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_MONITOR, CPUFreqMonitorClass))
+
+typedef struct _CPUFreqMonitor CPUFreqMonitor;
+typedef struct _CPUFreqMonitorClass CPUFreqMonitorClass;
+typedef struct _CPUFreqMonitorPrivate CPUFreqMonitorPrivate;
+
+struct _CPUFreqMonitor {
+ GObject parent;
+
+ CPUFreqMonitorPrivate *priv;
+};
+
+struct _CPUFreqMonitorClass {
+ GObjectClass parent_class;
+
+ gboolean (* run) (CPUFreqMonitor *monitor);
+ GList *(* get_available_frequencies) (CPUFreqMonitor *monitor);
+ GList *(* get_available_governors) (CPUFreqMonitor *monitor);
+
+ /*< signals >*/
+ void (* changed) (CPUFreqMonitor *monitor);
+};
+
+GType cpufreq_monitor_get_type (void) G_GNUC_CONST;
+
+void cpufreq_monitor_run (CPUFreqMonitor *monitor);
+GList *cpufreq_monitor_get_available_frequencies (CPUFreqMonitor *monitor);
+GList *cpufreq_monitor_get_available_governors (CPUFreqMonitor *monitor);
+
+guint cpufreq_monitor_get_cpu (CPUFreqMonitor *monitor);
+void cpufreq_monitor_set_cpu (CPUFreqMonitor *monitor,
+ guint cpu);
+const gchar *cpufreq_monitor_get_governor (CPUFreqMonitor *monitor);
+gint cpufreq_monitor_get_frequency (CPUFreqMonitor *monitor);
+gint cpufreq_monitor_get_percentage (CPUFreqMonitor *monitor);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_MONITOR_H__ */
diff --git a/cpufreq/src/cpufreq-popup.c b/cpufreq/src/cpufreq-popup.c
new file mode 100644
index 00000000..8486c2b3
--- /dev/null
+++ b/cpufreq/src/cpufreq-popup.c
@@ -0,0 +1,509 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib/gi18n.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cpufreq-popup.h"
+#include "cpufreq-selector.h"
+#include "cpufreq-utils.h"
+
+struct _CPUFreqPopupPrivate {
+ GtkUIManager *ui_manager;
+ GSList *radio_group;
+
+ GtkActionGroup *freqs_group;
+ GSList *freqs_actions;
+
+ GtkActionGroup *govs_group;
+ GSList *govs_actions;
+
+ guint merge_id;
+ gboolean need_build;
+ gboolean show_freqs;
+
+ CPUFreqMonitor *monitor;
+ GtkWidget *parent;
+};
+
+#define CPUFREQ_POPUP_GET_PRIVATE(object) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((object), CPUFREQ_TYPE_POPUP, CPUFreqPopupPrivate))
+
+static void cpufreq_popup_init (CPUFreqPopup *popup);
+static void cpufreq_popup_class_init (CPUFreqPopupClass *klass);
+static void cpufreq_popup_finalize (GObject *object);
+
+G_DEFINE_TYPE (CPUFreqPopup, cpufreq_popup, G_TYPE_OBJECT)
+
+static const gchar *ui_popup =
+"<ui>"
+" <popup name=\"CPUFreqSelectorPopup\" action=\"PopupAction\">"
+" <placeholder name=\"FreqsItemsGroup\">"
+" </placeholder>"
+" <separator />"
+" <placeholder name=\"GovsItemsGroup\">"
+" </placeholder>"
+" </popup>"
+"</ui>";
+
+#define FREQS_PLACEHOLDER_PATH "/CPUFreqSelectorPopup/FreqsItemsGroup"
+#define GOVS_PLACEHOLDER_PATH "/CPUFreqSelectorPopup/GovsItemsGroup"
+
+static void
+cpufreq_popup_init (CPUFreqPopup *popup)
+{
+ popup->priv = CPUFREQ_POPUP_GET_PRIVATE (popup);
+
+ popup->priv->ui_manager = gtk_ui_manager_new ();
+ popup->priv->radio_group = NULL;
+
+ popup->priv->freqs_group = NULL;
+ popup->priv->freqs_actions = NULL;
+
+ popup->priv->govs_group = NULL;
+ popup->priv->govs_actions = NULL;
+
+ popup->priv->merge_id = 0;
+ popup->priv->need_build = TRUE;
+ popup->priv->show_freqs = FALSE;
+
+ gtk_ui_manager_add_ui_from_string (popup->priv->ui_manager,
+ ui_popup, -1, NULL);
+
+ popup->priv->monitor = NULL;
+}
+
+static void
+cpufreq_popup_class_init (CPUFreqPopupClass *klass)
+{
+ GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (g_object_class, sizeof (CPUFreqPopupPrivate));
+
+ g_object_class->finalize = cpufreq_popup_finalize;
+}
+
+static void
+cpufreq_popup_finalize (GObject *object)
+{
+ CPUFreqPopup *popup = CPUFREQ_POPUP (object);
+
+ if (popup->priv->ui_manager) {
+ g_object_unref (popup->priv->ui_manager);
+ popup->priv->ui_manager = NULL;
+ }
+
+ if (popup->priv->freqs_group) {
+ g_object_unref (popup->priv->freqs_group);
+ popup->priv->freqs_group = NULL;
+ }
+
+ if (popup->priv->freqs_actions) {
+ g_slist_free (popup->priv->freqs_actions);
+ popup->priv->freqs_actions = NULL;
+ }
+
+ if (popup->priv->govs_group) {
+ g_object_unref (popup->priv->govs_group);
+ popup->priv->govs_group = NULL;
+ }
+
+ if (popup->priv->govs_actions) {
+ g_slist_free (popup->priv->govs_actions);
+ popup->priv->govs_actions = NULL;
+ }
+
+ if (popup->priv->monitor) {
+ g_object_unref (popup->priv->monitor);
+ popup->priv->monitor = NULL;
+ }
+
+ G_OBJECT_CLASS (cpufreq_popup_parent_class)->finalize (object);
+}
+
+CPUFreqPopup *
+cpufreq_popup_new (void)
+{
+ CPUFreqPopup *popup;
+
+ popup = CPUFREQ_POPUP (g_object_new (CPUFREQ_TYPE_POPUP,
+ NULL));
+
+ return popup;
+}
+
+/* Public methods */
+void
+cpufreq_popup_set_monitor (CPUFreqPopup *popup,
+ CPUFreqMonitor *monitor)
+{
+ g_return_if_fail (CPUFREQ_IS_POPUP (popup));
+ g_return_if_fail (CPUFREQ_IS_MONITOR (monitor));
+
+ if (popup->priv->monitor == monitor)
+ return;
+
+ if (popup->priv->monitor)
+ g_object_unref (popup->priv->monitor);
+ popup->priv->monitor = g_object_ref (monitor);
+}
+
+void
+cpufreq_popup_set_parent (CPUFreqPopup *popup,
+ GtkWidget *parent)
+{
+ g_return_if_fail (CPUFREQ_IS_POPUP (popup));
+ g_return_if_fail (GTK_IS_WIDGET (parent));
+
+ popup->priv->parent = parent;
+}
+
+static void
+cpufreq_popup_frequencies_menu_activate (GtkAction *action,
+ CPUFreqPopup *popup)
+{
+ CPUFreqSelector *selector;
+ const gchar *name;
+ guint cpu;
+ guint freq;
+ guint32 parent;
+
+ if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
+ return;
+
+ selector = cpufreq_selector_get_default ();
+
+ cpu = cpufreq_monitor_get_cpu (popup->priv->monitor);
+ name = gtk_action_get_name (action);
+ freq = (guint) atoi (name + strlen ("Frequency"));
+ parent = GDK_WINDOW_XID (gtk_widget_get_window (popup->priv->parent));
+
+
+ cpufreq_selector_set_frequency_async (selector, cpu, freq, parent);
+}
+
+static void
+cpufreq_popup_governors_menu_activate (GtkAction *action,
+ CPUFreqPopup *popup)
+{
+ CPUFreqSelector *selector;
+ const gchar *name;
+ guint cpu;
+ const gchar *governor;
+ guint32 parent;
+
+ if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
+ return;
+
+ selector = cpufreq_selector_get_default ();
+
+ cpu = cpufreq_monitor_get_cpu (popup->priv->monitor);
+ name = gtk_action_get_name (action);
+ governor = name + strlen ("Governor");
+ parent = GDK_WINDOW_XID (gtk_widget_get_window (popup->priv->parent));
+
+ cpufreq_selector_set_governor_async (selector, cpu, governor, parent);
+}
+
+static void
+cpufreq_popup_menu_add_action (CPUFreqPopup *popup,
+ const gchar *menu,
+ GtkActionGroup *action_group,
+ const gchar *action_name,
+ const gchar *label,
+ gboolean sensitive)
+{
+ GtkToggleAction *action;
+ gchar *name;
+
+ name = g_strdup_printf ("%s%s", menu, action_name);
+
+ action = g_object_new (GTK_TYPE_RADIO_ACTION,
+ "name", name,
+ "label", label,
+ NULL);
+
+ gtk_action_set_sensitive (GTK_ACTION (action), sensitive);
+
+ gtk_radio_action_set_group (GTK_RADIO_ACTION (action), popup->priv->radio_group);
+ popup->priv->radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
+
+ if (g_ascii_strcasecmp (menu, "Frequency") == 0) {
+ popup->priv->freqs_actions = g_slist_prepend (popup->priv->freqs_actions,
+ (gpointer) action);
+
+ g_signal_connect (action, "activate",
+ G_CALLBACK (cpufreq_popup_frequencies_menu_activate),
+ (gpointer) popup);
+ } else if (g_ascii_strcasecmp (menu, "Governor") == 0) {
+ popup->priv->govs_actions = g_slist_prepend (popup->priv->govs_actions,
+ (gpointer) action);
+
+ g_signal_connect (action, "activate",
+ G_CALLBACK (cpufreq_popup_governors_menu_activate),
+ (gpointer) popup);
+ }
+
+ gtk_action_group_add_action (action_group, GTK_ACTION (action));
+ g_object_unref (action);
+
+ g_free (name);
+}
+
+static void
+frequencies_menu_create_actions (CPUFreqPopup *popup)
+{
+ GList *available_freqs;
+
+ available_freqs = cpufreq_monitor_get_available_frequencies (popup->priv->monitor);
+
+ while (available_freqs) {
+ const gchar *text;
+ gchar *freq_text;
+ gchar *label;
+ gchar *unit;
+ gint freq;
+
+ text = (const gchar *) available_freqs->data;
+ freq = atoi (text);
+
+ freq_text = cpufreq_utils_get_frequency_label (freq);
+ unit = cpufreq_utils_get_frequency_unit (freq);
+
+ label = g_strdup_printf ("%s %s", freq_text, unit);
+ g_free (freq_text);
+ g_free (unit);
+
+ cpufreq_popup_menu_add_action (popup,
+ "Frequency",
+ popup->priv->freqs_group,
+ text, label, TRUE);
+ g_free (label);
+
+ available_freqs = g_list_next (available_freqs);
+ }
+}
+
+static void
+governors_menu_create_actions (CPUFreqPopup *popup)
+{
+ GList *available_govs;
+
+ available_govs = cpufreq_monitor_get_available_governors (popup->priv->monitor);
+ available_govs = g_list_sort (available_govs, (GCompareFunc)g_ascii_strcasecmp);
+
+ while (available_govs) {
+ const gchar *governor;
+ gchar *label;
+
+ governor = (const gchar *) available_govs->data;
+ if (g_ascii_strcasecmp (governor, "userspace") == 0) {
+ popup->priv->show_freqs = TRUE;
+ available_govs = g_list_next (available_govs);
+ continue;
+ }
+
+ label = g_strdup (governor);
+ label[0] = g_ascii_toupper (label[0]);
+
+ cpufreq_popup_menu_add_action (popup,
+ "Governor",
+ popup->priv->govs_group,
+ governor, label, TRUE);
+ g_free (label);
+
+ available_govs = g_list_next (available_govs);
+ }
+}
+
+static void
+cpufreq_popup_build_ui (CPUFreqPopup *popup,
+ GSList *actions,
+ const gchar *menu_path)
+{
+ GSList *l = NULL;
+
+ for (l = actions; l && l->data; l = g_slist_next (l)) {
+ GtkAction *action;
+ gchar *name = NULL;
+ gchar *label = NULL;
+
+ action = (GtkAction *) l->data;
+
+ g_object_get (G_OBJECT (action),
+ "name", &name,
+ "label", &label,
+ NULL);
+
+ gtk_ui_manager_add_ui (popup->priv->ui_manager,
+ popup->priv->merge_id,
+ menu_path,
+ label, name,
+ GTK_UI_MANAGER_MENUITEM,
+ FALSE);
+
+ g_free (name);
+ g_free (label);
+ }
+}
+
+static void
+cpufreq_popup_build_frequencies_menu (CPUFreqPopup *popup,
+ const gchar *path)
+{
+ if (!popup->priv->freqs_group) {
+ GtkActionGroup *action_group;
+
+ action_group = gtk_action_group_new ("FreqsActions");
+ popup->priv->freqs_group = action_group;
+ gtk_action_group_set_translation_domain (action_group, NULL);
+
+ frequencies_menu_create_actions (popup);
+ popup->priv->freqs_actions = g_slist_reverse (popup->priv->freqs_actions);
+ gtk_ui_manager_insert_action_group (popup->priv->ui_manager,
+ action_group, 0);
+ }
+
+ cpufreq_popup_build_ui (popup,
+ popup->priv->freqs_actions,
+ path);
+}
+
+static void
+cpufreq_popup_build_governors_menu (CPUFreqPopup *popup,
+ const gchar *path)
+{
+ if (!popup->priv->govs_group) {
+ GtkActionGroup *action_group;
+
+ action_group = gtk_action_group_new ("GovsActions");
+ popup->priv->govs_group = action_group;
+ gtk_action_group_set_translation_domain (action_group, NULL);
+
+ governors_menu_create_actions (popup);
+ popup->priv->govs_actions = g_slist_reverse (popup->priv->govs_actions);
+ gtk_ui_manager_insert_action_group (popup->priv->ui_manager,
+ action_group, 1);
+ }
+
+ cpufreq_popup_build_ui (popup,
+ popup->priv->govs_actions,
+ path);
+}
+
+static void
+cpufreq_popup_build_menu (CPUFreqPopup *popup)
+{
+ if (popup->priv->merge_id > 0) {
+ gtk_ui_manager_remove_ui (popup->priv->ui_manager,
+ popup->priv->merge_id);
+ gtk_ui_manager_ensure_update (popup->priv->ui_manager);
+ }
+
+ popup->priv->merge_id = gtk_ui_manager_new_merge_id (popup->priv->ui_manager);
+
+ cpufreq_popup_build_frequencies_menu (popup, FREQS_PLACEHOLDER_PATH);
+ cpufreq_popup_build_governors_menu (popup, GOVS_PLACEHOLDER_PATH);
+
+ gtk_action_group_set_visible (popup->priv->freqs_group,
+ popup->priv->show_freqs);
+}
+
+static void
+cpufreq_popup_menu_set_active_action (CPUFreqPopup *popup,
+ GtkActionGroup *action_group,
+ const gchar *prefix,
+ const gchar *item)
+{
+ gchar name[128];
+ GtkAction *action;
+
+ g_snprintf (name, sizeof (name), "%s%s", prefix, item);
+ action = gtk_action_group_get_action (action_group, name);
+
+ g_signal_handlers_block_by_func (action,
+ cpufreq_popup_frequencies_menu_activate,
+ popup);
+ g_signal_handlers_block_by_func (action,
+ cpufreq_popup_governors_menu_activate,
+ popup);
+
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+
+ g_signal_handlers_unblock_by_func (action,
+ cpufreq_popup_frequencies_menu_activate,
+ popup);
+ g_signal_handlers_unblock_by_func (action,
+ cpufreq_popup_governors_menu_activate,
+ popup);
+}
+
+static void
+cpufreq_popup_menu_set_active (CPUFreqPopup *popup)
+{
+ const gchar *governor;
+
+ governor = cpufreq_monitor_get_governor (popup->priv->monitor);
+
+ if (g_ascii_strcasecmp (governor, "userspace") == 0) {
+ gchar *active;
+ guint freq;
+
+ freq = cpufreq_monitor_get_frequency (popup->priv->monitor);
+ active = g_strdup_printf ("%d", freq);
+ cpufreq_popup_menu_set_active_action (popup,
+ popup->priv->freqs_group,
+ "Frequency", active);
+ g_free (active);
+ } else {
+ cpufreq_popup_menu_set_active_action (popup,
+ popup->priv->govs_group,
+ "Governor", governor);
+ }
+}
+
+GtkWidget *
+cpufreq_popup_get_menu (CPUFreqPopup *popup)
+{
+ GtkWidget *menu;
+
+ g_return_val_if_fail (CPUFREQ_IS_POPUP (popup), NULL);
+ g_return_val_if_fail (CPUFREQ_IS_MONITOR (popup->priv->monitor), NULL);
+
+ if (!cpufreq_utils_selector_is_available ())
+ return NULL;
+
+ if (popup->priv->need_build) {
+ cpufreq_popup_build_menu (popup);
+ popup->priv->need_build = FALSE;
+ }
+
+ cpufreq_popup_menu_set_active (popup);
+
+ menu = gtk_ui_manager_get_widget (popup->priv->ui_manager,
+ "/CPUFreqSelectorPopup");
+
+ return menu;
+}
diff --git a/cpufreq/src/cpufreq-popup.h b/cpufreq/src/cpufreq-popup.h
new file mode 100644
index 00000000..3a252d16
--- /dev/null
+++ b/cpufreq/src/cpufreq-popup.h
@@ -0,0 +1,66 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef CPUFREQ_POPUP_H
+#define CPUFREQ_POPUP_H
+
+#include <glib-object.h>
+
+#include "cpufreq-monitor.h"
+#include "cpufreq-prefs.h"
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_POPUP (cpufreq_popup_get_type ())
+#define CPUFREQ_POPUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_POPUP, CPUFreqPopup))
+#define CPUFREQ_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_POPUP, CPUFreqPopupClass))
+#define CPUFREQ_IS_POPUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_POPUP))
+#define CPUFREQ_IS_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_POPUP))
+#define CPUFREQ_POPUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_POPUP, CPUFreqPopupClass))
+
+typedef struct _CPUFreqPopup CPUFreqPopup;
+typedef struct _CPUFreqPopupClass CPUFreqPopupClass;
+typedef struct _CPUFreqPopupPrivate CPUFreqPopupPrivate;
+
+struct _CPUFreqPopup {
+ GObject base;
+
+ CPUFreqPopupPrivate *priv;
+};
+
+struct _CPUFreqPopupClass {
+ GObjectClass parent_class;
+};
+
+GType cpufreq_popup_get_type (void) G_GNUC_CONST;
+CPUFreqPopup *cpufreq_popup_new (void);
+
+void cpufreq_popup_set_preferences (CPUFreqPopup *popup,
+ CPUFreqPrefs *prefs);
+void cpufreq_popup_set_monitor (CPUFreqPopup *popup,
+ CPUFreqMonitor *monitor);
+void cpufreq_popup_set_parent (CPUFreqPopup *popup,
+ GtkWidget *parent);
+GtkWidget *cpufreq_popup_get_menu (CPUFreqPopup *popup);
+
+G_END_DECLS
+
+#endif /* CPUFREQ_POPUP_H */
diff --git a/cpufreq/src/cpufreq-prefs.c b/cpufreq/src/cpufreq-prefs.c
new file mode 100644
index 00000000..a57d02d9
--- /dev/null
+++ b/cpufreq/src/cpufreq-prefs.c
@@ -0,0 +1,705 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <mateconf/mateconf-client.h>
+
+#include "cpufreq-prefs.h"
+#include "cpufreq-utils.h"
+
+enum {
+ PROP_0,
+ PROP_MATECONF_KEY,
+ PROP_CPU,
+ PROP_SHOW_MODE,
+ PROP_SHOW_TEXT_MODE,
+};
+
+struct _CPUFreqPrefsPrivate {
+ MateConfClient *mateconf_client;
+ gchar *mateconf_key;
+
+ guint cpu;
+ CPUFreqShowMode show_mode;
+ CPUFreqShowTextMode show_text_mode;
+
+ /* Preferences dialog */
+ GtkWidget *dialog;
+ GtkWidget *show_freq;
+ GtkWidget *show_unit;
+ GtkWidget *show_perc;
+ GtkWidget *cpu_combo;
+ GtkWidget *monitor_settings_box;
+ GtkWidget *show_mode_combo;
+};
+
+#define CPUFREQ_PREFS_GET_PRIVATE(object) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((object), CPUFREQ_TYPE_PREFS, CPUFreqPrefsPrivate))
+
+static void cpufreq_prefs_init (CPUFreqPrefs *prefs);
+static void cpufreq_prefs_class_init (CPUFreqPrefsClass *klass);
+static void cpufreq_prefs_finalize (GObject *object);
+
+static void cpufreq_prefs_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void cpufreq_prefs_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void cpufreq_prefs_dialog_update_sensitivity (CPUFreqPrefs *prefs);
+
+
+G_DEFINE_TYPE (CPUFreqPrefs, cpufreq_prefs, G_TYPE_OBJECT)
+
+static void
+cpufreq_prefs_init (CPUFreqPrefs *prefs)
+{
+ prefs->priv = CPUFREQ_PREFS_GET_PRIVATE (prefs);
+
+ prefs->priv->mateconf_client = mateconf_client_get_default ();
+ prefs->priv->mateconf_key = NULL;
+
+ prefs->priv->cpu = 0;
+}
+
+static void
+cpufreq_prefs_class_init (CPUFreqPrefsClass *klass)
+{
+ GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
+
+ g_object_class->set_property = cpufreq_prefs_set_property;
+ g_object_class->get_property = cpufreq_prefs_get_property;
+
+ g_type_class_add_private (g_object_class, sizeof (CPUFreqPrefsPrivate));
+
+ /* Properties */
+ g_object_class_install_property (g_object_class,
+ PROP_MATECONF_KEY,
+ g_param_spec_string ("mateconf-key",
+ "MateConfKey",
+ "The applet mateconf key",
+ NULL,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (g_object_class,
+ PROP_CPU,
+ g_param_spec_uint ("cpu",
+ "CPU",
+ "The monitored cpu",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (g_object_class,
+ PROP_SHOW_MODE,
+ g_param_spec_enum ("show-mode",
+ "ShowMode",
+ "The applet show mode",
+ CPUFREQ_TYPE_SHOW_MODE,
+ CPUFREQ_MODE_BOTH,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (g_object_class,
+ PROP_SHOW_TEXT_MODE,
+ g_param_spec_enum ("show-text-mode",
+ "ShowTextMode",
+ "The applet show text mode",
+ CPUFREQ_TYPE_SHOW_TEXT_MODE,
+ CPUFREQ_MODE_TEXT_FREQUENCY_UNIT,
+ G_PARAM_READWRITE));
+
+ g_object_class->finalize = cpufreq_prefs_finalize;
+}
+
+static void
+cpufreq_prefs_finalize (GObject *object)
+{
+ CPUFreqPrefs *prefs = CPUFREQ_PREFS (object);
+
+ if (prefs->priv->mateconf_client) {
+ g_object_unref (prefs->priv->mateconf_client);
+ prefs->priv->mateconf_client = NULL;
+ }
+
+ if (prefs->priv->mateconf_key) {
+ g_free (prefs->priv->mateconf_key);
+ prefs->priv->mateconf_key = NULL;
+ }
+
+ if (prefs->priv->dialog) {
+ gtk_widget_destroy (prefs->priv->dialog);
+ prefs->priv->dialog = NULL;
+ }
+
+ G_OBJECT_CLASS (cpufreq_prefs_parent_class)->finalize (object);
+}
+
+static void
+cpufreq_prefs_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CPUFreqPrefs *prefs = CPUFREQ_PREFS (object);
+ gboolean update_sensitivity = FALSE;
+
+ switch (prop_id) {
+ case PROP_MATECONF_KEY:
+ prefs->priv->mateconf_key = g_value_dup_string (value);
+ break;
+ case PROP_CPU: {
+ guint cpu;
+
+ cpu = g_value_get_uint (value);
+ if (prefs->priv->cpu != cpu) {
+ gchar *key;
+
+ prefs->priv->cpu = cpu;
+ key = g_strjoin ("/",
+ prefs->priv->mateconf_key,
+ "cpu",
+ NULL);
+ mateconf_client_set_int (prefs->priv->mateconf_client,
+ key, prefs->priv->cpu,
+ NULL);
+ g_free (key);
+ }
+ }
+ break;
+ case PROP_SHOW_MODE: {
+ CPUFreqShowMode mode;
+
+ mode = g_value_get_enum (value);
+ if (prefs->priv->show_mode != mode) {
+ gchar *key;
+
+ update_sensitivity = TRUE;
+ prefs->priv->show_mode = mode;
+ key = g_strjoin ("/",
+ prefs->priv->mateconf_key,
+ "show_mode",
+ NULL);
+ mateconf_client_set_int (prefs->priv->mateconf_client,
+ key, prefs->priv->show_mode,
+ NULL);
+ g_free (key);
+ }
+ }
+ break;
+ case PROP_SHOW_TEXT_MODE: {
+ CPUFreqShowTextMode mode;
+
+ mode = g_value_get_enum (value);
+ if (prefs->priv->show_text_mode != mode) {
+ gchar *key;
+
+ update_sensitivity = TRUE;
+ prefs->priv->show_text_mode = mode;
+ key = g_strjoin ("/",
+ prefs->priv->mateconf_key,
+ "show_text_mode",
+ NULL);
+ mateconf_client_set_int (prefs->priv->mateconf_client,
+ key, prefs->priv->show_text_mode,
+ NULL);
+ g_free (key);
+ }
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+
+ if (prefs->priv->dialog && update_sensitivity)
+ cpufreq_prefs_dialog_update_sensitivity (prefs);
+}
+
+static void
+cpufreq_prefs_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CPUFreqPrefs *prefs = CPUFREQ_PREFS (object);
+
+ switch (prop_id) {
+ case PROP_MATECONF_KEY:
+ /* Is not readable */
+ break;
+ case PROP_CPU:
+ g_value_set_uint (value, prefs->priv->cpu);
+ break;
+ case PROP_SHOW_MODE:
+ g_value_set_enum (value, prefs->priv->show_mode);
+ break;
+ case PROP_SHOW_TEXT_MODE:
+ g_value_set_enum (value, prefs->priv->show_text_mode);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+cpufreq_prefs_setup (CPUFreqPrefs *prefs)
+{
+ guint cpu;
+ CPUFreqShowMode show_mode;
+ CPUFreqShowTextMode show_text_mode;
+ gchar *key;
+ GError *error = NULL;
+
+ g_assert (MATECONF_IS_CLIENT (prefs->priv->mateconf_client));
+ g_assert (prefs->priv->mateconf_key != NULL);
+
+ key = g_strjoin ("/", prefs->priv->mateconf_key, "cpu", NULL);
+ cpu = mateconf_client_get_int (prefs->priv->mateconf_client,
+ key, &error);
+ g_free (key);
+ /* In case anything went wrong with mateconf, get back to the default */
+ if (error) {
+ g_warning ("%s", error->message);
+ cpu = 0;
+ g_error_free (error);
+ error = NULL;
+ }
+ prefs->priv->cpu = cpu;
+
+ key = g_strjoin ("/", prefs->priv->mateconf_key, "show_mode", NULL);
+ show_mode = mateconf_client_get_int (prefs->priv->mateconf_client,
+ key, &error);
+ g_free (key);
+ /* In case anything went wrong with mateconf, get back to the default */
+ if (error ||
+ show_mode < CPUFREQ_MODE_GRAPHIC ||
+ show_mode > CPUFREQ_MODE_BOTH) {
+ show_mode = CPUFREQ_MODE_BOTH;
+ if (error) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ }
+ prefs->priv->show_mode = show_mode;
+
+ key = g_strjoin ("/", prefs->priv->mateconf_key, "show_text_mode", NULL);
+ show_text_mode = mateconf_client_get_int (prefs->priv->mateconf_client,
+ key, &error);
+ g_free (key);
+ /* In case anything went wrong with mateconf, get back to the default */
+ if (error ||
+ show_text_mode < CPUFREQ_MODE_TEXT_FREQUENCY ||
+ show_text_mode > CPUFREQ_MODE_TEXT_PERCENTAGE) {
+ show_text_mode = CPUFREQ_MODE_TEXT_FREQUENCY_UNIT;
+ if (error) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ }
+ prefs->priv->show_text_mode = show_text_mode;
+}
+
+CPUFreqPrefs *
+cpufreq_prefs_new (const gchar *mateconf_key)
+{
+ CPUFreqPrefs *prefs;
+
+ g_return_val_if_fail (mateconf_key != NULL, NULL);
+
+ prefs = CPUFREQ_PREFS (g_object_new (CPUFREQ_TYPE_PREFS,
+ "mateconf-key", mateconf_key,
+ NULL));
+
+ cpufreq_prefs_setup (prefs);
+
+ return prefs;
+}
+
+/* Public Methods */
+guint
+cpufreq_prefs_get_cpu (CPUFreqPrefs *prefs)
+{
+ g_return_val_if_fail (CPUFREQ_IS_PREFS (prefs), 0);
+
+ return MIN (prefs->priv->cpu, cpufreq_utils_get_n_cpus () - 1);
+}
+
+CPUFreqShowMode
+cpufreq_prefs_get_show_mode (CPUFreqPrefs *prefs)
+{
+ g_return_val_if_fail (CPUFREQ_IS_PREFS (prefs),
+ CPUFREQ_MODE_BOTH);
+
+ return prefs->priv->show_mode;
+}
+
+CPUFreqShowTextMode
+cpufreq_prefs_get_show_text_mode (CPUFreqPrefs *prefs)
+{
+ g_return_val_if_fail (CPUFREQ_IS_PREFS (prefs),
+ CPUFREQ_MODE_TEXT_FREQUENCY_UNIT);
+
+ return prefs->priv->show_text_mode;
+}
+
+/* Preferences Dialog */
+static gboolean
+cpufreq_prefs_key_is_writable (CPUFreqPrefs *prefs, const gchar *key)
+{
+ gboolean writable;
+ gchar *fullkey;
+
+ g_assert (prefs->priv->mateconf_client != NULL);
+
+ fullkey = g_strjoin ("/", prefs->priv->mateconf_key, key, NULL);
+ writable = mateconf_client_key_is_writable (prefs->priv->mateconf_client,
+ fullkey, NULL);
+ g_free (fullkey);
+
+ return writable;
+}
+
+static void
+cpufreq_prefs_dialog_show_freq_toggled (GtkWidget *show_freq, CPUFreqPrefs *prefs)
+{
+ CPUFreqShowTextMode show_text_mode;
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_freq))) {
+ GtkWidget *show_unit = prefs->priv->show_unit;
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_unit)))
+ show_text_mode = CPUFREQ_MODE_TEXT_FREQUENCY_UNIT;
+ else
+ show_text_mode = CPUFREQ_MODE_TEXT_FREQUENCY;
+
+ g_object_set (G_OBJECT (prefs),
+ "show-text-mode", show_text_mode,
+ NULL);
+ }
+}
+
+static void
+cpufreq_prefs_dialog_show_unit_toggled (GtkWidget *show_unit, CPUFreqPrefs *prefs)
+{
+ CPUFreqShowTextMode show_text_mode;
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_unit))) {
+ show_text_mode = CPUFREQ_MODE_TEXT_FREQUENCY_UNIT;
+ } else {
+ show_text_mode = CPUFREQ_MODE_TEXT_FREQUENCY;
+ }
+
+ g_object_set (G_OBJECT (prefs),
+ "show-text-mode", show_text_mode,
+ NULL);
+}
+
+static void
+cpufreq_prefs_dialog_show_perc_toggled (GtkWidget *show_perc, CPUFreqPrefs *prefs)
+{
+
+ CPUFreqShowTextMode show_text_mode;
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_perc))) {
+ /* Show cpu usage in percentage */
+ show_text_mode = CPUFREQ_MODE_TEXT_PERCENTAGE;
+
+ g_object_set (G_OBJECT (prefs),
+ "show-text-mode", show_text_mode,
+ NULL);
+ }
+}
+
+static void
+cpufreq_prefs_dialog_cpu_number_changed (GtkWidget *cpu_combo, CPUFreqPrefs *prefs)
+{
+ gint cpu;
+
+ cpu = gtk_combo_box_get_active (GTK_COMBO_BOX (prefs->priv->cpu_combo));
+
+ if (cpu >= 0) {
+ g_object_set (G_OBJECT (prefs),
+ "cpu", cpu,
+ NULL);
+ }
+}
+
+static void
+cpufreq_prefs_dialog_show_mode_changed (GtkWidget *show_mode_combo, CPUFreqPrefs *prefs)
+{
+ CPUFreqShowMode show_mode;
+
+ show_mode = gtk_combo_box_get_active (GTK_COMBO_BOX (show_mode_combo));
+ g_object_set (G_OBJECT (prefs),
+ "show-mode", show_mode,
+ NULL);
+}
+
+static void
+cpufreq_prefs_dialog_response_cb (CPUFreqPrefs *prefs,
+ gint response,
+ GtkDialog *dialog)
+{
+ GError *error = NULL;
+
+ if (response == GTK_RESPONSE_HELP) {
+ gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (prefs->priv->dialog)),
+ "ghelp:cpufreq-applet?cpufreq-applet-prefs",
+ gtk_get_current_event_time (),
+ &error);
+
+ if (error) {
+ cpufreq_utils_display_error (_("Could not open help document"),
+ error->message);
+ g_error_free (error);
+ }
+ } else {
+ gtk_widget_destroy (prefs->priv->dialog);
+ prefs->priv->dialog = NULL;
+ }
+}
+
+static void
+cpufreq_prefs_dialog_update_visibility (CPUFreqPrefs *prefs)
+{
+ if (cpufreq_utils_get_n_cpus () > 1)
+ gtk_widget_show (prefs->priv->monitor_settings_box);
+ else
+ gtk_widget_hide (prefs->priv->monitor_settings_box);
+}
+
+static void
+cpufreq_prefs_dialog_update_sensitivity (CPUFreqPrefs *prefs)
+{
+ gtk_widget_set_sensitive (prefs->priv->show_mode_combo,
+ cpufreq_prefs_key_is_writable (prefs, "show_mode"));
+
+ if (prefs->priv->show_mode != CPUFREQ_MODE_GRAPHIC) {
+ gboolean key_writable;
+
+ key_writable = cpufreq_prefs_key_is_writable (prefs, "show_text_mode");
+
+ gtk_widget_set_sensitive (prefs->priv->show_freq,
+ (TRUE && key_writable));
+ gtk_widget_set_sensitive (prefs->priv->show_perc,
+ (TRUE && key_writable));
+
+ if (prefs->priv->show_text_mode == CPUFREQ_MODE_TEXT_PERCENTAGE)
+ gtk_widget_set_sensitive (prefs->priv->show_unit,
+ FALSE);
+ else
+ gtk_widget_set_sensitive (prefs->priv->show_unit,
+ (TRUE && key_writable));
+ } else {
+ gtk_widget_set_sensitive (prefs->priv->show_freq, FALSE);
+ gtk_widget_set_sensitive (prefs->priv->show_unit, FALSE);
+ gtk_widget_set_sensitive (prefs->priv->show_perc, FALSE);
+ }
+}
+
+static void
+cpufreq_prefs_dialog_update (CPUFreqPrefs *prefs)
+{
+ if (cpufreq_utils_get_n_cpus () > 1) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (prefs->priv->cpu_combo),
+ MIN (prefs->priv->cpu, cpufreq_utils_get_n_cpus () - 1));
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (prefs->priv->show_mode_combo),
+ prefs->priv->show_mode);
+
+ switch (prefs->priv->show_text_mode) {
+ case CPUFREQ_MODE_TEXT_FREQUENCY:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->priv->show_freq),
+ TRUE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->priv->show_unit),
+ FALSE);
+
+ break;
+ case CPUFREQ_MODE_TEXT_FREQUENCY_UNIT:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->priv->show_freq),
+ TRUE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->priv->show_unit),
+ TRUE);
+
+ break;
+ case CPUFREQ_MODE_TEXT_PERCENTAGE:
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->priv->show_perc),
+ TRUE);
+
+ break;
+ }
+}
+
+static void
+cpufreq_prefs_dialog_cpu_combo_setup (CPUFreqPrefs *prefs)
+{
+ GtkListStore *model;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+ guint i;
+ guint n_cpus;
+
+ model = gtk_list_store_new (1, G_TYPE_STRING);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (prefs->priv->cpu_combo),
+ GTK_TREE_MODEL (model));
+
+ n_cpus = cpufreq_utils_get_n_cpus ();
+
+ for (i = 0; i < n_cpus; i++) {
+ gchar *text_label;
+
+ text_label = g_strdup_printf ("CPU %u", i);
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ 0, text_label,
+ -1);
+
+ g_free (text_label);
+ }
+
+ g_object_unref (model);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_clear (GTK_CELL_LAYOUT (prefs->priv->cpu_combo));
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (prefs->priv->cpu_combo),
+ renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (prefs->priv->cpu_combo),
+ renderer,
+ "text", 0,
+ NULL);
+}
+
+static void
+cpufreq_prefs_dialog_show_mode_combo_setup (CPUFreqPrefs *prefs)
+{
+ GtkListStore *model;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+
+ model = gtk_list_store_new (1, G_TYPE_STRING);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (prefs->priv->show_mode_combo),
+ GTK_TREE_MODEL (model));
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ 0, _("Graphic"),
+ -1);
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ 0, _("Text"),
+ -1);
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ 0, _("Graphic and Text"),
+ -1);
+
+ g_object_unref (model);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_clear (GTK_CELL_LAYOUT (prefs->priv->show_mode_combo));
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (prefs->priv->show_mode_combo),
+ renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (prefs->priv->show_mode_combo),
+ renderer,
+ "text", 0,
+ NULL);
+}
+
+static void
+cpufreq_prefs_dialog_create (CPUFreqPrefs *prefs)
+{
+ GtkBuilder *builder;
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_file (builder, GTK_BUILDERDIR "/cpufreq-preferences.ui", NULL);
+
+ prefs->priv->dialog = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_dialog"));
+
+ prefs->priv->cpu_combo = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_cpu_number"));
+
+ prefs->priv->show_mode_combo = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_show_mode"));
+
+ prefs->priv->show_freq = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_show_freq"));
+ prefs->priv->show_unit = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_show_unit"));
+ prefs->priv->show_perc = GTK_WIDGET (gtk_builder_get_object (builder, "prefs_show_perc"));
+
+ prefs->priv->monitor_settings_box = GTK_WIDGET (gtk_builder_get_object (builder, "monitor_settings_box"));
+
+ g_object_unref (builder);
+
+ cpufreq_prefs_dialog_show_mode_combo_setup (prefs);
+
+ if (cpufreq_utils_get_n_cpus () > 1)
+ cpufreq_prefs_dialog_cpu_combo_setup (prefs);
+
+ g_signal_connect_swapped (G_OBJECT (prefs->priv->dialog), "response",
+ G_CALLBACK (cpufreq_prefs_dialog_response_cb),
+ (gpointer) prefs);
+
+ g_signal_connect (G_OBJECT (prefs->priv->show_freq), "toggled",
+ G_CALLBACK (cpufreq_prefs_dialog_show_freq_toggled),
+ (gpointer) prefs);
+ g_signal_connect (G_OBJECT (prefs->priv->show_unit), "toggled",
+ G_CALLBACK (cpufreq_prefs_dialog_show_unit_toggled),
+ (gpointer) prefs);
+ g_signal_connect (G_OBJECT (prefs->priv->show_perc), "toggled",
+ G_CALLBACK (cpufreq_prefs_dialog_show_perc_toggled),
+ (gpointer) prefs);
+ g_signal_connect (G_OBJECT (prefs->priv->cpu_combo), "changed",
+ G_CALLBACK (cpufreq_prefs_dialog_cpu_number_changed),
+ (gpointer) prefs);
+ g_signal_connect (G_OBJECT (prefs->priv->show_mode_combo), "changed",
+ G_CALLBACK (cpufreq_prefs_dialog_show_mode_changed),
+ (gpointer) prefs);
+}
+
+void
+cpufreq_preferences_dialog_run (CPUFreqPrefs *prefs, GdkScreen *screen)
+{
+ g_return_if_fail (CPUFREQ_IS_PREFS (prefs));
+
+ if (prefs->priv->dialog) {
+ /* Dialog already exist, only show it */
+ gtk_window_present (GTK_WINDOW (prefs->priv->dialog));
+ return;
+ }
+
+ cpufreq_prefs_dialog_create (prefs);
+ gtk_window_set_screen (GTK_WINDOW (prefs->priv->dialog), screen);
+
+ cpufreq_prefs_dialog_update_sensitivity (prefs);
+ cpufreq_prefs_dialog_update_visibility (prefs);
+ cpufreq_prefs_dialog_update (prefs);
+
+ gtk_widget_show (prefs->priv->dialog);
+}
diff --git a/cpufreq/src/cpufreq-prefs.h b/cpufreq/src/cpufreq-prefs.h
new file mode 100644
index 00000000..8be9abe8
--- /dev/null
+++ b/cpufreq/src/cpufreq-prefs.h
@@ -0,0 +1,66 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef CPUFREQ_PREFS_H
+#define CPUFREQ_PREFS_H
+
+#include <gdk/gdk.h>
+#include <glib-object.h>
+#include "cpufreq-applet.h"
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_PREFS (cpufreq_prefs_get_type ())
+#define CPUFREQ_PREFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_PREFS, CPUFreqPrefs))
+#define CPUFREQ_PREFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_PREFS, CPUFreqPrefsClass))
+#define CPUFREQ_IS_PREFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_PREFS))
+#define CPUFREQ_IS_PREFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_PREFS))
+#define CPUFREQ_PREFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_PREFS, CPUFreqPrefsClass))
+
+typedef struct _CPUFreqPrefs CPUFreqPrefs;
+typedef struct _CPUFreqPrefsClass CPUFreqPrefsClass;
+typedef struct _CPUFreqPrefsPrivate CPUFreqPrefsPrivate;
+
+struct _CPUFreqPrefs {
+ GObject base;
+
+ CPUFreqPrefsPrivate *priv;
+};
+
+struct _CPUFreqPrefsClass {
+ GObjectClass parent_class;
+};
+
+GType cpufreq_prefs_get_type (void) G_GNUC_CONST;
+
+CPUFreqPrefs *cpufreq_prefs_new (const gchar *mateconf_key);
+
+guint cpufreq_prefs_get_cpu (CPUFreqPrefs *prefs);
+CPUFreqShowMode cpufreq_prefs_get_show_mode (CPUFreqPrefs *prefs);
+CPUFreqShowTextMode cpufreq_prefs_get_show_text_mode (CPUFreqPrefs *prefs);
+
+/* Properties dialog */
+void cpufreq_preferences_dialog_run (CPUFreqPrefs *prefs,
+ GdkScreen *screen);
+
+G_END_DECLS
+
+#endif /* CPUFREQ_PREFS_H */
diff --git a/cpufreq/src/cpufreq-selector.c b/cpufreq/src/cpufreq-selector.c
new file mode 100644
index 00000000..d5a37e15
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector.c
@@ -0,0 +1,289 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_POLKIT
+#include <dbus/dbus-glib.h>
+#endif /* HAVE_POLKIT */
+
+#include "cpufreq-selector.h"
+
+struct _CPUFreqSelector {
+ GObject parent;
+
+#ifdef HAVE_POLKIT
+ DBusGConnection *system_bus;
+#endif /* HAVE_POLKIT */
+};
+
+struct _CPUFreqSelectorClass {
+ GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (CPUFreqSelector, cpufreq_selector, G_TYPE_OBJECT)
+
+static void
+cpufreq_selector_finalize (GObject *object)
+{
+ CPUFreqSelector *selector = CPUFREQ_SELECTOR (object);
+
+#ifdef HAVE_POLKIT
+ selector->system_bus = NULL;
+#endif /* HAVE_POLKIT */
+
+ G_OBJECT_CLASS (cpufreq_selector_parent_class)->finalize (object);
+}
+
+static void
+cpufreq_selector_class_init (CPUFreqSelectorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cpufreq_selector_finalize;
+}
+
+static void
+cpufreq_selector_init (CPUFreqSelector *selector)
+{
+}
+
+CPUFreqSelector *
+cpufreq_selector_get_default (void)
+{
+ static CPUFreqSelector *selector = NULL;
+
+ if (!selector)
+ selector = CPUFREQ_SELECTOR (g_object_new (CPUFREQ_TYPE_SELECTOR, NULL));
+
+ return selector;
+}
+
+#ifdef HAVE_POLKIT
+typedef enum {
+ FREQUENCY,
+ GOVERNOR
+} CPUFreqSelectorCall;
+
+typedef struct {
+ CPUFreqSelector *selector;
+
+ CPUFreqSelectorCall call;
+
+ guint cpu;
+ guint frequency;
+ gchar *governor;
+
+ guint32 parent_xid;
+} SelectorAsyncData;
+
+static void selector_set_frequency_async (SelectorAsyncData *data);
+static void selector_set_governor_async (SelectorAsyncData *data);
+
+static void
+selector_async_data_free (SelectorAsyncData *data)
+{
+ if (!data)
+ return;
+
+ g_free (data->governor);
+ g_free (data);
+}
+
+static gboolean
+cpufreq_selector_connect_to_system_bus (CPUFreqSelector *selector,
+ GError **error)
+{
+ if (selector->system_bus)
+ return TRUE;
+
+ selector->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, error);
+
+ return (selector->system_bus != NULL);
+}
+
+static void
+dbus_set_call_notify_cb (DBusGProxy *proxy,
+ DBusGProxyCall *call,
+ gpointer user_data)
+{
+ SelectorAsyncData *data;
+ GError *error = NULL;
+
+ data = (SelectorAsyncData *)user_data;
+
+ if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) {
+ selector_async_data_free (data);
+ return;
+ }
+
+ selector_async_data_free (data);
+ g_warning ("%s", error->message);
+ g_error_free (error);
+}
+
+static void
+selector_set_frequency_async (SelectorAsyncData *data)
+{
+ DBusGProxy *proxy;
+ GError *error = NULL;
+
+ if (!cpufreq_selector_connect_to_system_bus (data->selector, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ selector_async_data_free (data);
+
+ return;
+ }
+
+ proxy = dbus_g_proxy_new_for_name (data->selector->system_bus,
+ "org.mate.CPUFreqSelector",
+ "/org/mate/cpufreq_selector/selector",
+ "org.mate.CPUFreqSelector");
+
+ dbus_g_proxy_begin_call_with_timeout (proxy, "SetFrequency",
+ dbus_set_call_notify_cb,
+ data, NULL,
+ INT_MAX,
+ G_TYPE_UINT, data->cpu,
+ G_TYPE_UINT, data->frequency,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+}
+
+void
+cpufreq_selector_set_frequency_async (CPUFreqSelector *selector,
+ guint cpu,
+ guint frequency,
+ guint32 parent)
+{
+ SelectorAsyncData *data;
+
+ data = g_new0 (SelectorAsyncData, 1);
+
+ data->selector = selector;
+ data->call = FREQUENCY;
+ data->cpu = cpu;
+ data->frequency = frequency;
+ data->parent_xid = parent;
+
+ selector_set_frequency_async (data);
+}
+
+static void
+selector_set_governor_async (SelectorAsyncData *data)
+{
+ DBusGProxy *proxy;
+ GError *error = NULL;
+
+ if (!cpufreq_selector_connect_to_system_bus (data->selector, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ selector_async_data_free (data);
+
+ return;
+ }
+
+ proxy = dbus_g_proxy_new_for_name (data->selector->system_bus,
+ "org.mate.CPUFreqSelector",
+ "/org/mate/cpufreq_selector/selector",
+ "org.mate.CPUFreqSelector");
+
+ dbus_g_proxy_begin_call_with_timeout (proxy, "SetGovernor",
+ dbus_set_call_notify_cb,
+ data, NULL,
+ INT_MAX,
+ G_TYPE_UINT, data->cpu,
+ G_TYPE_STRING, data->governor,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+}
+
+void
+cpufreq_selector_set_governor_async (CPUFreqSelector *selector,
+ guint cpu,
+ const gchar *governor,
+ guint32 parent)
+{
+ SelectorAsyncData *data;
+
+ data = g_new0 (SelectorAsyncData, 1);
+
+ data->selector = selector;
+ data->call = GOVERNOR;
+ data->cpu = cpu;
+ data->governor = g_strdup (governor);
+ data->parent_xid = parent;
+
+ selector_set_governor_async (data);
+}
+#else /* !HAVE_POLKIT */
+static void
+cpufreq_selector_run_command (CPUFreqSelector *selector,
+ const gchar *args)
+{
+ gchar *command;
+ gchar *path;
+ GError *error = NULL;
+
+ path = g_find_program_in_path ("cpufreq-selector");
+
+ if (!path)
+ return;
+
+ command = g_strdup_printf ("%s %s", path, args);
+ g_free (path);
+
+ g_spawn_command_line_async (command, &error);
+ g_free (command);
+
+ if (error) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+}
+
+void
+cpufreq_selector_set_frequency_async (CPUFreqSelector *selector,
+ guint cpu,
+ guint frequency,
+ guint32 parent)
+{
+ gchar *args;
+
+ args = g_strdup_printf ("-c %u -f %u", cpu, frequency);
+ cpufreq_selector_run_command (selector, args);
+ g_free (args);
+}
+
+void
+cpufreq_selector_set_governor_async (CPUFreqSelector *selector,
+ guint cpu,
+ const gchar *governor,
+ guint32 parent)
+{
+ gchar *args;
+
+ args = g_strdup_printf ("-c %u -g %s", cpu, governor);
+ cpufreq_selector_run_command (selector, args);
+ g_free (args);
+}
+#endif /* HAVE_POLKIT */
diff --git a/cpufreq/src/cpufreq-selector.h b/cpufreq/src/cpufreq-selector.h
new file mode 100644
index 00000000..5941d416
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector.h
@@ -0,0 +1,51 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CPUFREQ_SELECTOR_H__
+#define __CPUFREQ_SELECTOR_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_SELECTOR (cpufreq_selector_get_type ())
+#define CPUFREQ_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR, CPUFreqSelector))
+#define CPUFREQ_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR, CPUFreqSelectorClass))
+#define CPUFREQ_IS_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR))
+#define CPUFREQ_IS_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR))
+#define CPUFREQ_SELECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR, CPUFreqSelectorClass))
+
+typedef struct _CPUFreqSelector CPUFreqSelector;
+typedef struct _CPUFreqSelectorClass CPUFreqSelectorClass;
+
+GType cpufreq_selector_get_type (void) G_GNUC_CONST;
+
+CPUFreqSelector *cpufreq_selector_get_default (void);
+void cpufreq_selector_set_frequency_async (CPUFreqSelector *selector,
+ guint cpu,
+ guint frequency,
+ guint32 parent);
+void cpufreq_selector_set_governor_async (CPUFreqSelector *selector,
+ guint cpu,
+ const gchar *governor,
+ guint32 parent);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_SELECTOR_H__ */
diff --git a/cpufreq/src/cpufreq-selector/Makefile.am b/cpufreq/src/cpufreq-selector/Makefile.am
new file mode 100644
index 00000000..b2db7a97
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/Makefile.am
@@ -0,0 +1,89 @@
+cpufreqselectordir = $(bindir)
+
+INCLUDES = $(CPUFREQ_SELECTOR_CFLAGS)
+
+if HAVE_POLKIT
+INCLUDES += \
+ $(DBUS_CFLAGS) \
+ $(POLKIT_CFLAGS)
+endif
+
+bin_PROGRAMS = cpufreq-selector
+
+install-exec-hook:
+if CPUFREQ_SELECTOR_SUID
+ chmod 4755 $(DESTDIR)$(bindir)/cpufreq-selector
+endif
+
+
+if HAVE_LIBCPUFREQ
+cpufreq_files=cpufreq-selector-libcpufreq.c cpufreq-selector-libcpufreq.h
+endif
+
+if HAVE_POLKIT
+service_files=cpufreq-selector-service.c cpufreq-selector-service.h
+endif
+
+cpufreq_selector_SOURCES = \
+ cpufreq-selector.c cpufreq-selector.h \
+ cpufreq-selector-sysfs.c cpufreq-selector-sysfs.h \
+ cpufreq-selector-procfs.c cpufreq-selector-procfs.h \
+ $(cpufreq_files) \
+ $(service_files) \
+ cpufreq-selector-factory.c cpufreq-selector-factory.h \
+ $(BUILT_SOURCES) \
+ main.c
+
+cpufreq_selector_LDADD = \
+ $(CPUFREQ_SELECTOR_LIBS) \
+ $(LIBCPUFREQ_LIBS)
+
+if HAVE_POLKIT
+cpufreq_selector_LDADD += \
+ $(DBUS_LIBS) \
+ $(POLKIT_LIBS)
+endif
+
+cpufreq_selector_LDFLAGS = $(LDFLAGS) -Wl,-z,now
+
+dbus_services_in_files = org.mate.CPUFreqSelector.service.in
+polkit_in_files = org.mate.cpufreqselector.policy.in
+
+dbus_servicesdir = $(datadir)/dbus-1/system-services
+dbus_confdir = $(sysconfdir)/dbus-1/system.d
+polkitdir = $(datadir)/polkit-1/actions
+
+if HAVE_POLKIT
+BUILT_SOURCES = cpufreq-selector-service-glue.h
+
+cpufreq-selector-service-glue.h: $(srcdir)/cpufreq-selector-service.xml
+ dbus-binding-tool --prefix=cpufreq_selector_service --mode=glib-server \
+ --output=cpufreq-selector-service-glue.h \
+ $(srcdir)/cpufreq-selector-service.xml
+
+dbus_services_DATA = $(dbus_services_in_files:.service.in=.service)
+$(dbus_services_DATA): $(dbus_services_in_files)
+ sed -e "s|\@BINDIR\@|$(DESTDIR)$(bindir)|" $< > $@
+dbus_conf_DATA = org.mate.CPUFreqSelector.conf
+
+@INTLTOOL_POLICY_RULE@
+polkit_DATA = $(polkit_in_files:.policy.in=.policy)
+
+else
+dbus_services_DATA=
+dbus_conf_DATA=
+polkit_DATA=
+endif
+
+EXTRA_DIST = \
+ cpufreq-selector-service.xml \
+ $(dbus_services_in_files) \
+ org.mate.CPUFreqSelector.conf \
+ $(polkit_in_files)
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(dbus_services_DATA) \
+ $(polkit_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.c
new file mode 100644
index 00000000..024b5cb7
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.c
@@ -0,0 +1,47 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cpufreq-selector-factory.h"
+#include "cpufreq-selector-sysfs.h"
+#include "cpufreq-selector-procfs.h"
+#ifdef HAVE_LIBCPUFREQ
+#include "cpufreq-selector-libcpufreq.h"
+#endif
+
+CPUFreqSelector *
+cpufreq_selector_factory_create_selector (guint cpu)
+{
+ CPUFreqSelector *selector = NULL;
+
+#ifdef HAVE_LIBCPUFREQ
+ selector = cpufreq_selector_libcpufreq_new (cpu);
+#else
+ if (g_file_test ("/sys/devices/system/cpu/cpu0/cpufreq", G_FILE_TEST_EXISTS)) { /* 2.6 kernel */
+ selector = cpufreq_selector_sysfs_new (cpu);
+ } else if (g_file_test ("/proc/cpufreq", G_FILE_TEST_EXISTS)) { /* 2.4 kernel */
+ selector = cpufreq_selector_procfs_new (cpu);
+ }
+#endif /* HAVE_LIBCPUFREQ */
+
+ return selector;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.h
new file mode 100644
index 00000000..fba0a8dc
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-factory.h
@@ -0,0 +1,31 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef CPUFREQ_SELECTOR_FACTORY
+#define CPUFREQ_SELECTOR_FACTORY
+
+#include "cpufreq-selector.h"
+
+G_BEGIN_DECLS
+
+CPUFreqSelector *cpufreq_selector_factory_create_selector (guint cpu);
+
+G_END_DECLS
+
+#endif /* CPUFREQ_SELECTOR_FACTORY */
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.c
new file mode 100644
index 00000000..4b9573b3
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.c
@@ -0,0 +1,197 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <cpufreq.h>
+#include <stdlib.h>
+
+#include "cpufreq-selector-libcpufreq.h"
+
+static void cpufreq_selector_libcpufreq_init (CPUFreqSelectorLibcpufreq *selector);
+static void cpufreq_selector_libcpufreq_class_init (CPUFreqSelectorLibcpufreqClass *klass);
+
+static gboolean cpufreq_selector_libcpufreq_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+static gboolean cpufreq_selector_libcpufreq_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+
+G_DEFINE_TYPE (CPUFreqSelectorLibcpufreq, cpufreq_selector_libcpufreq, CPUFREQ_TYPE_SELECTOR)
+
+typedef struct cpufreq_policy CPUFreqPolicy;
+typedef struct cpufreq_available_frequencies CPUFreqFrequencyList;
+typedef struct cpufreq_available_governors CPUFreqGovernorList;
+
+static void
+cpufreq_selector_libcpufreq_init (CPUFreqSelectorLibcpufreq *selector)
+{
+}
+
+static void
+cpufreq_selector_libcpufreq_class_init (CPUFreqSelectorLibcpufreqClass *klass)
+{
+ CPUFreqSelectorClass *selector_class = CPUFREQ_SELECTOR_CLASS (klass);
+
+ selector_class->set_frequency = cpufreq_selector_libcpufreq_set_frequency;
+ selector_class->set_governor = cpufreq_selector_libcpufreq_set_governor;
+}
+
+CPUFreqSelector *
+cpufreq_selector_libcpufreq_new (guint cpu)
+{
+ CPUFreqSelector *selector;
+
+ selector = CPUFREQ_SELECTOR (g_object_new (CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ,
+ "cpu", cpu,
+ NULL));
+
+ return selector;
+}
+
+static guint
+cpufreq_selector_libcpufreq_get_valid_frequency (CPUFreqSelectorLibcpufreq *selector,
+ guint frequency)
+{
+ guint cpu;
+ gint dist = G_MAXINT;
+ guint retval = 0;
+ CPUFreqFrequencyList *freqs, *freq;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ freqs = cpufreq_get_available_frequencies (cpu);
+ if (!freqs)
+ return 0;
+
+ for (freq = freqs; freq; freq = freq->next) {
+ guint current_dist;
+
+ if (freq->frequency == frequency) {
+ cpufreq_put_available_frequencies (freqs);
+
+ return frequency;
+ }
+
+ current_dist = abs (freq->frequency - frequency);
+ if (current_dist < dist) {
+ dist = current_dist;
+ retval = freq->frequency;
+ }
+ }
+
+ return retval;
+}
+
+static gboolean
+cpufreq_selector_libcpufreq_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error)
+{
+ guint freq;
+ guint cpu;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ freq = cpufreq_selector_libcpufreq_get_valid_frequency (CPUFREQ_SELECTOR_LIBCPUFREQ (selector),
+ frequency);
+ if (cpufreq_set_frequency (cpu, freq) != 0) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_SET_FREQUENCY,
+ "Cannot set frequency '%d'",
+ frequency);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+cpufreq_selector_libcpufreq_validate_governor (CPUFreqSelectorLibcpufreq *selector,
+ const gchar *governor)
+{
+ guint cpu;
+ CPUFreqGovernorList *govs, *gov;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ govs = cpufreq_get_available_governors (cpu);
+ if (!govs)
+ return FALSE;
+
+ for (gov = govs; gov; gov = gov->next) {
+ if (g_ascii_strcasecmp (gov->governor, governor) == 0) {
+ cpufreq_put_available_governors (govs);
+
+ return TRUE;
+ }
+ }
+
+ cpufreq_put_available_governors (govs);
+
+ return FALSE;
+}
+
+static gboolean
+cpufreq_selector_libcpufreq_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error)
+{
+ CPUFreqSelectorLibcpufreq *selector_libcpufreq;
+ guint cpu;
+
+ selector_libcpufreq = CPUFREQ_SELECTOR_LIBCPUFREQ (selector);
+
+ if (!cpufreq_selector_libcpufreq_validate_governor (selector_libcpufreq, governor)) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_INVALID_GOVERNOR,
+ "Invalid governor '%s'",
+ governor);
+
+ return FALSE;
+ }
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ if (cpufreq_modify_policy_governor (cpu, (gchar *)governor) != 0) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_INVALID_GOVERNOR,
+ "Invalid governor '%s'",
+ governor);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.h
new file mode 100644
index 00000000..37dcda63
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-libcpufreq.h
@@ -0,0 +1,61 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_SELECTOR_LIBCPUFREQ_H__
+#define __CPUFREQ_SELECTOR_LIBCPUFREQ_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-selector.h"
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ \
+ (cpufreq_selector_libcpufreq_get_type ())
+#define CPUFREQ_SELECTOR_LIBCPUFREQ(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ, CPUFreqSelectorLibcpufreq))
+#define CPUFREQ_SELECTOR_LIBCPUFREQ_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ, CPUFreqSelectorLibcpufreqClass))
+#define CPUFREQ_IS_SELECTOR_LIBCPUFREQ(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ))
+#define CPUFREQ_IS_SELECTOR_LIBCPUFREQ_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ))
+#define CPUFREQ_SELECTOR_LIBCPUFREQ_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR_LIBCPUFREQ, CPUFreqSelectorLibcpufreqClass))
+
+typedef struct _CPUFreqSelectorLibcpufreq CPUFreqSelectorLibcpufreq;
+typedef struct _CPUFreqSelectorLibcpufreqClass CPUFreqSelectorLibcpufreqClass;
+
+struct _CPUFreqSelectorLibcpufreq {
+ CPUFreqSelector parent;
+};
+
+struct _CPUFreqSelectorLibcpufreqClass {
+ CPUFreqSelectorClass parent_class;
+};
+
+
+GType cpufreq_selector_libcpufreq_get_type (void) G_GNUC_CONST;
+CPUFreqSelector *cpufreq_selector_libcpufreq_new (guint cpu);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_SELECTOR_SYSFS_H__ */
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.c
new file mode 100644
index 00000000..f08d681d
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.c
@@ -0,0 +1,243 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "cpufreq-selector-procfs.h"
+
+static void cpufreq_selector_procfs_init (CPUFreqSelectorProcfs *selector);
+static void cpufreq_selector_procfs_class_init (CPUFreqSelectorProcfsClass *klass);
+
+static gboolean cpufreq_selector_procfs_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+static gboolean cpufreq_selector_procfs_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+
+G_DEFINE_TYPE (CPUFreqSelectorProcfs, cpufreq_selector_procfs, CPUFREQ_TYPE_SELECTOR)
+
+static void
+cpufreq_selector_procfs_init (CPUFreqSelectorProcfs *selector)
+{
+}
+
+static void
+cpufreq_selector_procfs_class_init (CPUFreqSelectorProcfsClass *klass)
+{
+ CPUFreqSelectorClass *selector_class = CPUFREQ_SELECTOR_CLASS (klass);
+
+ selector_class->set_frequency = cpufreq_selector_procfs_set_frequency;
+ selector_class->set_governor = cpufreq_selector_procfs_set_governor;
+}
+
+CPUFreqSelector *
+cpufreq_selector_procfs_new (guint cpu)
+{
+ CPUFreqSelector *selector;
+
+ selector = CPUFREQ_SELECTOR (g_object_new (CPUFREQ_TYPE_SELECTOR_PROCFS,
+ "cpu", cpu,
+ NULL));
+
+ return selector;
+}
+
+static gboolean
+cpufreq_procfs_read (guint selector_cpu,
+ guint *fmax,
+ guint *pmin,
+ guint *pmax,
+ guint *fmin,
+ gchar *mode,
+ GError **error)
+{
+ gchar **lines;
+ gchar *buffer = NULL;
+ gint i;
+ guint cpu;
+ gboolean found = FALSE;
+
+ if (!g_file_get_contents ("/proc/cpufreq", &buffer, NULL, error)) {
+ return FALSE;
+ }
+
+ lines = g_strsplit (buffer, "\n", -1);
+ for (i = 0; lines[i]; i++) {
+ if (g_ascii_strncasecmp (lines[i], "CPU", 3) == 0) {
+ /* CPU 0 650000 kHz ( 81 %) - 800000 kHz (100 %) - powersave */
+ sscanf (lines[i], "CPU %u %u kHz (%u %%) - %u kHz (%u %%) - %20s",
+ &cpu, fmin, pmin, fmax, pmax, mode);
+
+ if (cpu == selector_cpu) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ g_strfreev (lines);
+ g_free (buffer);
+
+ if (!found) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_INVALID_CPU,
+ "Invalid CPU number '%d'",
+ selector_cpu);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+cpufreq_procfs_write (const gchar *path,
+ const gchar *setting,
+ GError **error)
+{
+ FILE *fd;
+
+ fd = g_fopen (path, "w");
+
+ if (!fd) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Failed to open '%s' for writing: "
+ "g_fopen() failed: %s",
+ path,
+ g_strerror (errno));
+
+ return FALSE;
+ }
+
+ if (g_fprintf (fd, "%s", setting) < 0) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Failed to write '%s': "
+ "g_fprintf() failed: %s",
+ path,
+ g_strerror (errno));
+
+ fclose (fd);
+
+ return FALSE;
+ }
+
+ fclose (fd);
+
+ return TRUE;
+}
+
+static gboolean
+cpufreq_selector_procfs_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error)
+{
+ gchar *str;
+ gchar *path;
+ guint freq;
+ guint cpu;
+ guint pmin, pmax;
+ guint sc_max, sc_min;
+ gchar mode[21];
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ if (!cpufreq_procfs_read (cpu, &sc_max, &pmin, &pmax, &sc_min, mode, error)) {
+ return FALSE;
+ }
+
+ if (g_ascii_strcasecmp (mode, "userspace") != 0) {
+ if (!cpufreq_selector_procfs_set_governor (selector,
+ "userspace",
+ error)) {
+ return FALSE;
+ }
+ }
+
+ if (frequency != sc_max && frequency != sc_min) {
+ if (abs (sc_max - frequency) < abs (frequency - sc_min))
+ freq = sc_max;
+ else
+ freq = sc_min;
+ } else {
+ freq = frequency;
+ }
+
+ path = g_strdup_printf ("/proc/sys/cpu/%u/speed", cpu);
+ str = g_strdup_printf ("%u", freq);
+ if (!cpufreq_procfs_write (path, str, error)) {
+ g_free (path);
+ g_free (str);
+
+ return FALSE;
+ }
+
+ g_free (path);
+ g_free (str);
+
+ return TRUE;
+}
+
+static gboolean
+cpufreq_selector_procfs_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error)
+{
+ gchar *str;
+ guint cpu;
+ guint pmin, pmax;
+ guint sc_max, sc_min;
+ gchar mode[21];
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ if (!cpufreq_procfs_read (cpu, &sc_max, &pmin, &pmax, &sc_min, mode, error)) {
+ return FALSE;
+ }
+
+ if (g_ascii_strcasecmp (governor, mode) == 0)
+ return TRUE;
+
+ str = g_strdup_printf ("%u:%u:%u:%s", cpu, sc_min, sc_max, governor);
+
+ if (!cpufreq_procfs_write ("/proc/cpufreq", str, error)) {
+ g_free (str);
+
+ return FALSE;
+ }
+
+ g_free (str);
+
+ return TRUE;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.h
new file mode 100644
index 00000000..55193731
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-procfs.h
@@ -0,0 +1,54 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_SELECTOR_PROCFS_H__
+#define __CPUFREQ_SELECTOR_PROCFS_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-selector.h"
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_SELECTOR_PROCFS (cpufreq_selector_procfs_get_type ())
+#define CPUFREQ_SELECTOR_PROCFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR_PROCFS, CPUFreqSelectorProcfs))
+#define CPUFREQ_SELECTOR_PROCFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR_PROCFS, CPUFreqSelectorProcfsClass))
+#define CPUFREQ_IS_SELECTOR_PROCFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR_PROCFS))
+#define CPUFREQ_IS_SELECTOR_PROCFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR_PROCFS))
+#define CPUFREQ_SELECTOR_PROCFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR_PROCFS, CPUFreqSelectorProcfsClass))
+
+typedef struct _CPUFreqSelectorProcfs CPUFreqSelectorProcfs;
+typedef struct _CPUFreqSelectorProcfsClass CPUFreqSelectorProcfsClass;
+
+struct _CPUFreqSelectorProcfs {
+ CPUFreqSelector parent;
+};
+
+struct _CPUFreqSelectorProcfsClass {
+ CPUFreqSelectorClass parent_class;
+};
+
+GType cpufreq_selector_procfs_get_type (void) G_GNUC_CONST;
+CPUFreqSelector *cpufreq_selector_procfs_new (guint cpu);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_SELECTOR_PROCFS_H__ */
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-service.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.c
new file mode 100644
index 00000000..696ff220
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.c
@@ -0,0 +1,487 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <polkit/polkit.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "cpufreq-selector.h"
+#include "cpufreq-selector-factory.h"
+#include "cpufreq-selector-service.h"
+
+#include "cpufreq-selector-service-glue.h"
+
+#define MAX_CPUS 255
+
+struct _CPUFreqSelectorService {
+ GObject parent;
+
+ CPUFreqSelector *selectors[MAX_CPUS];
+ gint selectors_max;
+
+ DBusGConnection *system_bus;
+
+ /* PolicyKit */
+ PolkitAuthority *authority;
+};
+
+struct _CPUFreqSelectorServiceClass {
+ GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (CPUFreqSelectorService, cpufreq_selector_service, G_TYPE_OBJECT)
+
+#define BUS_NAME "org.mate.CPUFreqSelector"
+
+GType
+cpufreq_selector_service_error_get_type (void)
+{
+ static GType etype = 0;
+
+ if (G_UNLIKELY (etype == 0)) {
+ static const GEnumValue values[] = {
+ { SERVICE_ERROR_GENERAL, "SERVICE_ERROR_GENERAL", "GeneralError" },
+ { SERVICE_ERROR_DBUS, "SERVICE_ERROR_DBUS", "DBUSError" },
+ { SERVICE_ERROR_ALREADY_REGISTERED, "SERVICE_ERROR_ALREADY_REGISTERED", "AlreadyRegistered" },
+ { SERVICE_ERROR_NOT_AUTHORIZED, "SERVICE_ERROR_NOT_AUTHORIZED", "NotAuthorized"},
+ { 0, NULL, NULL}
+ };
+
+ etype = g_enum_register_static ("CPUFreqSelectorServiceError", values);
+ }
+
+ return etype;
+}
+
+GQuark
+cpufreq_selector_service_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (G_UNLIKELY (error_quark == 0))
+ error_quark =
+ g_quark_from_static_string ("cpufreq-selector-service-error-quark");
+
+ return error_quark;
+}
+
+static void
+cpufreq_selector_service_finalize (GObject *object)
+{
+ CPUFreqSelectorService *service = CPUFREQ_SELECTOR_SERVICE (object);
+ gint i;
+
+ service->system_bus = NULL;
+
+ if (service->selectors_max >= 0) {
+ for (i = 0; i < service->selectors_max; i++) {
+ if (service->selectors[i]) {
+ g_object_unref (service->selectors[i]);
+ service->selectors[i] = NULL;
+ }
+ }
+
+ service->selectors_max = -1;
+ }
+
+ if (service->authority) {
+ g_object_unref (service->authority);
+ service->authority = NULL;
+ }
+
+ G_OBJECT_CLASS (cpufreq_selector_service_parent_class)->finalize (object);
+}
+
+static void
+cpufreq_selector_service_class_init (CPUFreqSelectorServiceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cpufreq_selector_service_finalize;
+}
+
+static void
+cpufreq_selector_service_init (CPUFreqSelectorService *service)
+{
+ service->selectors_max = -1;
+}
+
+CPUFreqSelectorService *
+cpufreq_selector_service_get_instance (void)
+{
+ static CPUFreqSelectorService *service = NULL;
+
+ if (!service)
+ service = CPUFREQ_SELECTOR_SERVICE (g_object_new (CPUFREQ_TYPE_SELECTOR_SERVICE, NULL));
+
+ return service;
+}
+
+static gboolean
+service_shutdown (gpointer user_data)
+{
+ g_object_unref (SELECTOR_SERVICE);
+
+ return FALSE;
+}
+
+static void
+reset_killtimer (void)
+{
+ static guint timer_id = 0;
+
+ if (timer_id > 0)
+ g_source_remove (timer_id);
+
+ timer_id = g_timeout_add_seconds (30,
+ (GSourceFunc) service_shutdown,
+ NULL);
+}
+
+gboolean
+cpufreq_selector_service_register (CPUFreqSelectorService *service,
+ GError **error)
+{
+ DBusGConnection *connection;
+ DBusGProxy *bus_proxy;
+ gboolean res;
+ guint result;
+ GError *err = NULL;
+
+ if (service->system_bus) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_ALREADY_REGISTERED,
+ "Service %s already registered", BUS_NAME);
+ return FALSE;
+ }
+
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+ if (!connection) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Couldn't connect to system bus: %s",
+ err->message);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ bus_proxy = dbus_g_proxy_new_for_name (connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ if (!bus_proxy) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Could not construct bus_proxy object");
+ return FALSE;
+ }
+
+ res = dbus_g_proxy_call (bus_proxy,
+ "RequestName",
+ &err,
+ G_TYPE_STRING, BUS_NAME,
+ G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &result,
+ G_TYPE_INVALID);
+ g_object_unref (bus_proxy);
+
+ if (!res) {
+ if (err) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Failed to acquire %s: %s",
+ BUS_NAME, err->message);
+ g_error_free (err);
+ } else {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Failed to acquire %s", BUS_NAME);
+ }
+
+ return FALSE;
+ }
+
+ if (result == DBUS_REQUEST_NAME_REPLY_EXISTS) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_ALREADY_REGISTERED,
+ "Service %s already registered", BUS_NAME);
+ return FALSE;
+ }
+
+ service->authority = polkit_authority_get ();
+
+ service->system_bus = connection;
+
+ dbus_g_object_type_install_info (CPUFREQ_TYPE_SELECTOR_SERVICE,
+ &dbus_glib_cpufreq_selector_service_object_info);
+ dbus_g_connection_register_g_object (connection,
+ "/org/mate/cpufreq_selector/selector",
+ G_OBJECT (service));
+ dbus_g_error_domain_register (CPUFREQ_SELECTOR_SERVICE_ERROR, NULL,
+ CPUFREQ_TYPE_SELECTOR_SERVICE_ERROR);
+
+ reset_killtimer ();
+
+ return TRUE;
+}
+
+static CPUFreqSelector *
+get_selector_for_cpu (CPUFreqSelectorService *service,
+ guint cpu)
+{
+ if (!service->selectors[cpu]) {
+ service->selectors[cpu] = cpufreq_selector_factory_create_selector (cpu);
+ if (!service->selectors[cpu])
+ return NULL;
+
+ if (service->selectors_max < cpu)
+ service->selectors_max = cpu;
+ }
+
+ return service->selectors[cpu];
+}
+
+/* PolicyKit */
+static gboolean
+cpufreq_selector_service_check_policy (CPUFreqSelectorService *service,
+ DBusGMethodInvocation *context,
+ GError **error)
+{
+ PolkitSubject *subject;
+ PolkitAuthorizationResult *result;
+ gchar *sender;
+ gboolean ret;
+
+ sender = dbus_g_method_get_sender (context);
+ subject = polkit_system_bus_name_new (sender);
+ g_free (sender);
+
+ result = polkit_authority_check_authorization_sync (service->authority,
+ subject,
+ "org.mate.cpufreqselector",
+ NULL,
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+ NULL, error);
+ g_object_unref (subject);
+
+ if (*error) {
+ g_warning ("Check policy: %s", (*error)->message);
+ g_object_unref (result);
+
+ return FALSE;
+ }
+
+ ret = polkit_authorization_result_get_is_authorized (result);
+ if (!ret) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_NOT_AUTHORIZED,
+ "Caller is not authorized");
+ }
+
+ g_object_unref (result);
+
+ return ret;
+}
+
+/* D-BUS interface */
+gboolean
+cpufreq_selector_service_set_frequency (CPUFreqSelectorService *service,
+ guint cpu,
+ guint frequency,
+ DBusGMethodInvocation *context)
+{
+ CPUFreqSelector *selector;
+ GError *error = NULL;
+
+ reset_killtimer ();
+
+ if (!cpufreq_selector_service_check_policy (service, context, &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (cpu > MAX_CPUS) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting frequency on cpu %d: Invalid cpu",
+ cpu);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ selector = get_selector_for_cpu (service, cpu);
+ if (!selector) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting frequency on cpu %d: No cpufreq support",
+ cpu);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ cpufreq_selector_set_frequency (selector, frequency, &error);
+ if (error) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting frequency %d on cpu %d: %s",
+ frequency, cpu, error->message);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ dbus_g_method_return (context);
+
+ return TRUE;
+}
+
+gboolean
+cpufreq_selector_service_set_governor (CPUFreqSelectorService *service,
+ guint cpu,
+ const gchar *governor,
+ DBusGMethodInvocation *context)
+{
+ CPUFreqSelector *selector;
+ GError *error = NULL;
+
+ reset_killtimer ();
+
+ if (!cpufreq_selector_service_check_policy (service, context, &error)) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (cpu > MAX_CPUS) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting governor on cpu %d: Invalid cpu",
+ cpu);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ selector = get_selector_for_cpu (service, cpu);
+ if (!selector) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting governor on cpu %d: No cpufreq support",
+ cpu);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+
+ return FALSE;
+ }
+
+ cpufreq_selector_set_governor (selector, governor, &error);
+ if (error) {
+ GError *err;
+
+ err = g_error_new (CPUFREQ_SELECTOR_SERVICE_ERROR,
+ SERVICE_ERROR_DBUS,
+ "Error setting governor %s on cpu %d: %s",
+ governor, cpu, error->message);
+ dbus_g_method_return_error (context, err);
+ g_error_free (err);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ dbus_g_method_return (context);
+
+ return TRUE;
+}
+
+
+gboolean
+cpufreq_selector_service_can_set (CPUFreqSelectorService *service,
+ DBusGMethodInvocation *context)
+{
+ PolkitSubject *subject;
+ PolkitAuthorizationResult *result;
+ gchar *sender;
+ gboolean ret;
+ GError *error = NULL;
+
+ reset_killtimer ();
+
+ sender = dbus_g_method_get_sender (context);
+ subject = polkit_system_bus_name_new (sender);
+ g_free (sender);
+
+ result = polkit_authority_check_authorization_sync (service->authority,
+ subject,
+ "org.mate.cpufreqselector",
+ NULL,
+ 0,
+ NULL,
+ &error);
+ g_object_unref (subject);
+
+ if (error) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (polkit_authorization_result_get_is_authorized (result)) {
+ ret = TRUE;
+ } else if (polkit_authorization_result_get_is_challenge (result)) {
+ ret = TRUE;
+ } else {
+ ret = FALSE;
+ }
+
+ g_object_unref (result);
+
+ dbus_g_method_return (context, ret);
+
+ return TRUE;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-service.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.h
new file mode 100644
index 00000000..a6bcc77b
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.h
@@ -0,0 +1,71 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2008 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CPUFREQ_SELECTOR_SERVICE_H__
+#define __CPUFREQ_SELECTOR_SERVICE_H__
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_SELECTOR_SERVICE (cpufreq_selector_service_get_type ())
+#define CPUFREQ_SELECTOR_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR_SERVICE, CPUFreqSelectorService))
+#define CPUFREQ_SELECTOR_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR_SERVICE, CPUFreqSelectorServiceClass))
+#define CPUFREQ_IS_SELECTOR_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR_SERVICE))
+#define CPUFREQ_IS_SELECTOR_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR_SERVICE))
+#define CPUFREQ_SELECTOR_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR_SERVICE, CPUFreqSelectorServiceClass))
+
+#define SELECTOR_SERVICE (cpufreq_selector_service_get_instance ())
+
+#define CPUFREQ_SELECTOR_SERVICE_ERROR (cpufreq_selector_service_error_quark ())
+#define CPUFREQ_TYPE_SELECTOR_SERVICE_ERROR (cpufreq_selector_service_error_get_type ())
+
+enum {
+ SERVICE_ERROR_GENERAL,
+ SERVICE_ERROR_DBUS,
+ SERVICE_ERROR_ALREADY_REGISTERED,
+ SERVICE_ERROR_NOT_AUTHORIZED
+};
+
+typedef struct _CPUFreqSelectorService CPUFreqSelectorService;
+typedef struct _CPUFreqSelectorServiceClass CPUFreqSelectorServiceClass;
+
+GType cpufreq_selector_service_get_type (void) G_GNUC_CONST;
+GType cpufreq_selector_service_error_get_type (void) G_GNUC_CONST;
+GQuark cpufreq_selector_service_error_quark (void) G_GNUC_CONST;
+CPUFreqSelectorService *cpufreq_selector_service_get_instance (void);
+gboolean cpufreq_selector_service_register (CPUFreqSelectorService *service,
+ GError **error);
+
+gboolean cpufreq_selector_service_set_frequency (CPUFreqSelectorService *service,
+ guint cpu,
+ guint frequency,
+ DBusGMethodInvocation *context);
+gboolean cpufreq_selector_service_set_governor (CPUFreqSelectorService *service,
+ guint cpu,
+ const gchar *governor,
+ DBusGMethodInvocation *context);
+gboolean cpufreq_selector_service_can_set (CPUFreqSelectorService *service,
+ DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_SELECTOR_SERVICE_H__ */
+
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-service.xml b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.xml
new file mode 100644
index 00000000..798dd5b2
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-service.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<node name="/org/mate/CPUFreqSelector">
+ <interface name="org.mate.CPUFreqSelector">
+ <method name="SetFrequency">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cpu" direction="in" type="u"/>
+ <arg name="frequency" direction="in" type="u"/>
+ </method>
+
+ <method name="SetGovernor">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cpu" direction="in" type="u"/>
+ <arg name="governor" direction="in" type="s"/>
+ </method>
+
+ <method name="CanSet">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="result" direction="out" type="b"/>
+ </method>
+
+ </interface>
+</node>
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.c b/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.c
new file mode 100644
index 00000000..ae790caf
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.c
@@ -0,0 +1,430 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "cpufreq-selector-sysfs.h"
+
+#define CPUFREQ_SELECTOR_SYSFS_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), CPUFREQ_TYPE_SELECTOR_SYSFS, CPUFreqSelectorSysfsPrivate))
+
+struct _CPUFreqSelectorSysfsPrivate {
+ GList *available_freqs;
+ GList *available_govs;
+};
+
+static void cpufreq_selector_sysfs_init (CPUFreqSelectorSysfs *selector);
+static void cpufreq_selector_sysfs_class_init (CPUFreqSelectorSysfsClass *klass);
+static void cpufreq_selector_sysfs_finalize (GObject *object);
+
+static gboolean cpufreq_selector_sysfs_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+static gboolean cpufreq_selector_sysfs_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+
+#define CPUFREQ_SYSFS_BASE_PATH "/sys/devices/system/cpu/cpu%u/cpufreq/%s"
+
+G_DEFINE_TYPE (CPUFreqSelectorSysfs, cpufreq_selector_sysfs, CPUFREQ_TYPE_SELECTOR)
+
+static void
+cpufreq_selector_sysfs_init (CPUFreqSelectorSysfs *selector)
+{
+ selector->priv = CPUFREQ_SELECTOR_SYSFS_GET_PRIVATE (selector);
+
+ selector->priv->available_freqs = NULL;
+ selector->priv->available_govs = NULL;
+}
+
+static void
+cpufreq_selector_sysfs_class_init (CPUFreqSelectorSysfsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CPUFreqSelectorClass *selector_class = CPUFREQ_SELECTOR_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (CPUFreqSelectorSysfsPrivate));
+
+ selector_class->set_frequency = cpufreq_selector_sysfs_set_frequency;
+ selector_class->set_governor = cpufreq_selector_sysfs_set_governor;
+
+ object_class->finalize = cpufreq_selector_sysfs_finalize;
+}
+
+static void
+cpufreq_selector_sysfs_finalize (GObject *object)
+{
+ CPUFreqSelectorSysfs *selector = CPUFREQ_SELECTOR_SYSFS (object);
+
+ if (selector->priv->available_freqs) {
+ g_list_foreach (selector->priv->available_freqs,
+ (GFunc) g_free,
+ NULL);
+ g_list_free (selector->priv->available_freqs);
+ selector->priv->available_freqs = NULL;
+ }
+
+ if (selector->priv->available_govs) {
+ g_list_foreach (selector->priv->available_govs,
+ (GFunc) g_free,
+ NULL);
+ g_list_free (selector->priv->available_govs);
+ selector->priv->available_govs = NULL;
+ }
+
+ G_OBJECT_CLASS (cpufreq_selector_sysfs_parent_class)->finalize (object);
+}
+
+CPUFreqSelector *
+cpufreq_selector_sysfs_new (guint cpu)
+{
+ CPUFreqSelector *selector;
+
+ selector = CPUFREQ_SELECTOR (g_object_new (CPUFREQ_TYPE_SELECTOR_SYSFS,
+ "cpu", cpu,
+ NULL));
+
+ return selector;
+}
+
+static gchar *
+cpufreq_sysfs_read (const gchar *path,
+ GError **error)
+{
+ gchar *buffer = NULL;
+
+ if (!g_file_get_contents (path, &buffer, NULL, error)) {
+ return NULL;
+ }
+
+ return g_strchomp (buffer);
+}
+
+static gboolean
+cpufreq_sysfs_write (const gchar *path,
+ const gchar *setting,
+ GError **error)
+{
+ FILE *fd;
+
+ fd = g_fopen (path, "w");
+
+ if (!fd) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Failed to open '%s' for writing: "
+ "g_fopen() failed: %s",
+ path,
+ g_strerror (errno));
+
+ return FALSE;
+ }
+
+ if (g_fprintf (fd, "%s", setting) < 0) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Failed to write '%s': "
+ "g_fprintf() failed: %s",
+ path,
+ g_strerror (errno));
+
+ fclose (fd);
+
+ return FALSE;
+ }
+
+ fclose (fd);
+
+ return TRUE;
+}
+
+static gint
+compare (gconstpointer a, gconstpointer b)
+{
+ gint aa, bb;
+
+ aa = atoi ((gchar *) a);
+ bb = atoi ((gchar *) b);
+
+ if (aa == bb)
+ return 0;
+ else if (aa > bb)
+ return -1;
+ else
+ return 1;
+}
+
+static GList *
+cpufreq_selector_sysfs_get_freqs (CPUFreqSelectorSysfs *selector)
+{
+ gchar *buffer;
+ GList *list = NULL;
+ gchar **frequencies = NULL;
+ gint i;
+ gchar *path;
+ guint cpu;
+ GError *error = NULL;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_available_frequencies");
+
+ buffer = cpufreq_sysfs_read (path, &error);
+ if (!buffer) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ g_free (path);
+
+ return NULL;
+ }
+
+ g_free (path);
+
+ frequencies = g_strsplit (buffer, " ", -1);
+
+ i = 0;
+ while (frequencies[i]) {
+ if (!g_list_find_custom (list, frequencies[i], compare))
+ list = g_list_prepend (list, g_strdup (frequencies[i]));
+ i++;
+ }
+
+ g_strfreev (frequencies);
+ g_free (buffer);
+
+ return g_list_sort (list, compare);
+}
+
+static const gchar *
+cpufreq_selector_sysfs_get_valid_frequency (CPUFreqSelectorSysfs *selector,
+ guint frequency)
+{
+ GList *list = NULL;
+ GList *l;
+ gint dist = G_MAXINT;
+ const gchar *retval = NULL;
+
+ if (!selector->priv->available_freqs) {
+ list = cpufreq_selector_sysfs_get_freqs (selector);
+ selector->priv->available_freqs = list;
+ } else {
+ list = selector->priv->available_freqs;
+ }
+
+ if (!list)
+ return NULL;
+
+ for (l = list; l && l->data; l = g_list_next (l)) {
+ const gchar *freq;
+ guint f;
+ guint current_dist;
+
+ freq = (const gchar *) l->data;
+ f = atoi (freq);
+
+ if (f == frequency)
+ return freq;
+
+ current_dist = abs (frequency - f);
+ if (current_dist < dist) {
+ dist = current_dist;
+ retval = freq;
+ }
+ }
+
+ return retval;
+}
+
+static gboolean
+cpufreq_selector_sysfs_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error)
+{
+ gchar *governor;
+ gchar *path;
+ const gchar *frequency_text;
+ guint cpu;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_governor");
+
+ governor = cpufreq_sysfs_read (path, error);
+ g_free (path);
+
+ if (!governor)
+ return FALSE;
+
+ if (g_ascii_strcasecmp (governor, "userspace") != 0) {
+ if (!cpufreq_selector_sysfs_set_governor (selector,
+ "userspace",
+ error)) {
+ g_free (governor);
+
+ return FALSE;
+ }
+ }
+
+ g_free (governor);
+
+ frequency_text =
+ cpufreq_selector_sysfs_get_valid_frequency (CPUFREQ_SELECTOR_SYSFS (selector),
+ frequency);
+ if (!frequency_text) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_SET_FREQUENCY,
+ "Cannot set frequency '%d'",
+ frequency);
+
+ return FALSE;
+ }
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_setspeed");
+ if (!cpufreq_sysfs_write (path, frequency_text, error)) {
+ g_free (path);
+
+ return FALSE;
+ }
+
+ g_free (path);
+
+ return TRUE;
+}
+
+static GList *
+cpufreq_selector_sysfs_get_govs (CPUFreqSelectorSysfs *selector)
+{
+ gchar *buffer;
+ GList *list = NULL;
+ gchar **governors = NULL;
+ gint i;
+ gchar *path;
+ guint cpu;
+ GError *error = NULL;
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_available_governors");
+
+ buffer = cpufreq_sysfs_read (path, &error);
+ if (!buffer) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ g_free (path);
+
+ return NULL;
+ }
+
+ g_free (path);
+
+ governors = g_strsplit (buffer, " ", -1);
+
+ i = 0;
+ while (governors[i]) {
+ list = g_list_prepend (list, g_strdup (governors[i]));
+ i++;
+ }
+
+ g_strfreev (governors);
+ g_free (buffer);
+
+ return list;
+}
+
+static gboolean
+cpufreq_selector_sysfs_validate_governor (CPUFreqSelectorSysfs *selector,
+ const gchar *governor)
+{
+ GList *list = NULL;
+
+ if (!selector->priv->available_govs) {
+ list = cpufreq_selector_sysfs_get_govs (selector);
+ selector->priv->available_govs = list;
+ } else {
+ list = selector->priv->available_govs;
+ }
+
+ if (!list)
+ return FALSE;
+
+ list = g_list_find_custom (selector->priv->available_govs,
+ governor,
+ (GCompareFunc) g_ascii_strcasecmp);
+
+ return (list != NULL);
+}
+
+static gboolean
+cpufreq_selector_sysfs_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error)
+{
+ CPUFreqSelectorSysfs *selector_sysfs;
+ gchar *path;
+ guint cpu;
+
+ selector_sysfs = CPUFREQ_SELECTOR_SYSFS (selector);
+
+ if (!cpufreq_selector_sysfs_validate_governor (selector_sysfs, governor)) {
+ g_set_error (error,
+ CPUFREQ_SELECTOR_ERROR,
+ SELECTOR_ERROR_INVALID_GOVERNOR,
+ "Invalid governor '%s'",
+ governor);
+
+ return FALSE;
+ }
+
+ g_object_get (G_OBJECT (selector),
+ "cpu", &cpu,
+ NULL);
+
+ path = g_strdup_printf (CPUFREQ_SYSFS_BASE_PATH, cpu,
+ "scaling_governor");
+
+ if (!cpufreq_sysfs_write (path, governor, error)) {
+ g_free (path);
+
+ return FALSE;
+ }
+
+ g_free (path);
+
+ return TRUE;
+}
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.h b/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.h
new file mode 100644
index 00000000..a2608bbc
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector-sysfs.h
@@ -0,0 +1,58 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_SELECTOR_SYSFS_H__
+#define __CPUFREQ_SELECTOR_SYSFS_H__
+
+#include <glib-object.h>
+
+#include "cpufreq-selector.h"
+
+G_BEGIN_DECLS
+
+#define CPUFREQ_TYPE_SELECTOR_SYSFS (cpufreq_selector_sysfs_get_type ())
+#define CPUFREQ_SELECTOR_SYSFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR_SYSFS, CPUFreqSelectorSysfs))
+#define CPUFREQ_SELECTOR_SYSFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR_SYSFS, CPUFreqSelectorSysfsClass))
+#define CPUFREQ_IS_SELECTOR_SYSFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR_SYSFS))
+#define CPUFREQ_IS_SELECTOR_SYSFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR_SYSFS))
+#define CPUFREQ_SELECTOR_SYSFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR_SYSFS, CPUFreqSelectorSysfsClass))
+
+typedef struct _CPUFreqSelectorSysfs CPUFreqSelectorSysfs;
+typedef struct _CPUFreqSelectorSysfsClass CPUFreqSelectorSysfsClass;
+typedef struct _CPUFreqSelectorSysfsPrivate CPUFreqSelectorSysfsPrivate;
+
+struct _CPUFreqSelectorSysfs {
+ CPUFreqSelector parent;
+
+ CPUFreqSelectorSysfsPrivate *priv;
+};
+
+struct _CPUFreqSelectorSysfsClass {
+ CPUFreqSelectorClass parent_class;
+};
+
+
+GType cpufreq_selector_sysfs_get_type (void) G_GNUC_CONST;
+CPUFreqSelector *cpufreq_selector_sysfs_new (guint cpu);
+
+G_END_DECLS
+
+#endif /* __CPUFREQ_SELECTOR_SYSFS_H__ */
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector.c b/cpufreq/src/cpufreq-selector/cpufreq-selector.c
new file mode 100644
index 00000000..f019fec3
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector.c
@@ -0,0 +1,173 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib.h>
+#include "cpufreq-selector.h"
+
+#define CPUFREQ_SELECTOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), CPUFREQ_TYPE_SELECTOR, CPUFreqSelectorPrivate))
+
+enum {
+ PROP_0,
+ PROP_CPU
+};
+
+struct _CPUFreqSelectorPrivate {
+ guint cpu;
+};
+
+static void cpufreq_selector_init (CPUFreqSelector *selector);
+static void cpufreq_selector_class_init (CPUFreqSelectorClass *klass);
+
+static void cpufreq_selector_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *spec);
+static void cpufreq_selector_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *spec);
+
+G_DEFINE_ABSTRACT_TYPE (CPUFreqSelector, cpufreq_selector, G_TYPE_OBJECT)
+
+GQuark
+cpufreq_selector_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (error_quark == 0)
+ error_quark =
+ g_quark_from_static_string ("cpufreq-selector-error-quark");
+
+ return error_quark;
+}
+
+static void
+cpufreq_selector_init (CPUFreqSelector *selector)
+{
+
+ selector->priv = CPUFREQ_SELECTOR_GET_PRIVATE (selector);
+
+ selector->priv->cpu = 0;
+}
+
+static void
+cpufreq_selector_class_init (CPUFreqSelectorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (CPUFreqSelectorPrivate));
+
+ object_class->set_property = cpufreq_selector_set_property;
+ object_class->get_property = cpufreq_selector_get_property;
+
+ /* Public virtual methods */
+ klass->set_frequency = NULL;
+ klass->set_governor = NULL;
+
+ /* Porperties */
+ g_object_class_install_property (object_class,
+ PROP_CPU,
+ g_param_spec_uint ("cpu",
+ NULL,
+ NULL,
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE));
+}
+
+static void
+cpufreq_selector_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *spec)
+{
+ CPUFreqSelector *selector = CPUFREQ_SELECTOR (object);
+
+ switch (prop_id) {
+ case PROP_CPU:
+ selector->priv->cpu = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
+ break;
+ }
+}
+
+static void
+cpufreq_selector_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *spec)
+{
+ CPUFreqSelector *selector = CPUFREQ_SELECTOR (object);
+
+ switch (prop_id) {
+ case PROP_CPU:
+ g_value_set_uint (value, selector->priv->cpu);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
+ break;
+ }
+}
+
+gboolean
+cpufreq_selector_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error)
+{
+ CPUFreqSelectorClass *class;
+
+ g_return_val_if_fail (CPUFREQ_IS_SELECTOR (selector), FALSE);
+ g_return_val_if_fail (frequency > 0, FALSE);
+
+ class = CPUFREQ_SELECTOR_GET_CLASS (selector);
+
+ if (class->set_frequency) {
+ return class->set_frequency (selector, frequency, error);
+ }
+
+ return FALSE;
+}
+
+gboolean
+cpufreq_selector_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error)
+{
+ CPUFreqSelectorClass *class;
+
+ g_return_val_if_fail (CPUFREQ_IS_SELECTOR (selector), FALSE);
+ g_return_val_if_fail (governor != NULL, FALSE);
+
+ class = CPUFREQ_SELECTOR_GET_CLASS (selector);
+
+ if (class->set_governor) {
+ return class->set_governor (selector, governor, error);
+ }
+
+ return FALSE;
+}
+
+
diff --git a/cpufreq/src/cpufreq-selector/cpufreq-selector.h b/cpufreq/src/cpufreq-selector/cpufreq-selector.h
new file mode 100644
index 00000000..73e41054
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/cpufreq-selector.h
@@ -0,0 +1,74 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef __CPUFREQ_SELECTOR_H__
+#define __CPUFREQ_SELECTOR_H__
+
+#include <glib-object.h>
+
+#define CPUFREQ_TYPE_SELECTOR (cpufreq_selector_get_type ())
+#define CPUFREQ_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CPUFREQ_TYPE_SELECTOR, CPUFreqSelector))
+#define CPUFREQ_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), CPUFREQ_TYPE_SELECTOR, CPUFreqSelectorClass))
+#define CPUFREQ_IS_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CPUFREQ_TYPE_SELECTOR))
+#define CPUFREQ_IS_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CPUFREQ_TYPE_SELECTOR))
+#define CPUFREQ_SELECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CPUFREQ_TYPE_SELECTOR, CPUFreqSelectorClass))
+
+#define CPUFREQ_SELECTOR_ERROR (cpufreq_selector_error_quark ())
+
+enum {
+ SELECTOR_ERROR_INVALID_CPU,
+ SELECTOR_ERROR_INVALID_GOVERNOR,
+ SELECTOR_ERROR_SET_FREQUENCY
+};
+
+typedef struct _CPUFreqSelector CPUFreqSelector;
+typedef struct _CPUFreqSelectorClass CPUFreqSelectorClass;
+typedef struct _CPUFreqSelectorPrivate CPUFreqSelectorPrivate;
+
+struct _CPUFreqSelector {
+ GObject parent;
+
+ CPUFreqSelectorPrivate *priv;
+};
+
+struct _CPUFreqSelectorClass {
+ GObjectClass parent_class;
+
+ gboolean (* set_frequency) (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+ gboolean (* set_governor) (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+};
+
+
+GType cpufreq_selector_get_type (void) G_GNUC_CONST;
+GQuark cpufreq_selector_error_quark (void) G_GNUC_CONST;
+
+gboolean cpufreq_selector_set_frequency (CPUFreqSelector *selector,
+ guint frequency,
+ GError **error);
+gboolean cpufreq_selector_set_governor (CPUFreqSelector *selector,
+ const gchar *governor,
+ GError **error);
+
+#endif /* __CPUFREQ_SELECTOR_H__ */
diff --git a/cpufreq/src/cpufreq-selector/main.c b/cpufreq/src/cpufreq-selector/main.c
new file mode 100644
index 00000000..f0fbb7b1
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/main.c
@@ -0,0 +1,233 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef HAVE_POLKIT
+#include "cpufreq-selector-service.h"
+#endif
+#include "cpufreq-selector-factory.h"
+
+
+static gint cpu = 0;
+static gchar *governor = NULL;
+static gulong frequency = 0;
+
+static const GOptionEntry options[] = {
+ { "cpu", 'c', 0, G_OPTION_ARG_INT, &cpu, "CPU Number", NULL },
+ { "governor", 'g', 0, G_OPTION_ARG_STRING, &governor, "Governor", NULL },
+ { "frequency", 'f', 0, G_OPTION_ARG_INT, &frequency, "Frequency in KHz", NULL },
+ { NULL }
+};
+
+#ifdef HAVE_POLKIT
+static void
+do_exit (GMainLoop *loop,
+ GObject *object)
+{
+ if (g_main_loop_is_running (loop))
+ g_main_loop_quit (loop);
+}
+
+static void
+cpufreq_selector_set_values_dbus (void)
+{
+ DBusGConnection *connection;
+ DBusGProxy *proxy;
+ gboolean res;
+ GError *error = NULL;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (!connection) {
+ g_printerr ("Couldn't connect to system bus: %s\n",
+ error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.mate.CPUFreqSelector",
+ "/org/mate/cpufreq_selector/selector",
+ "org.mate.CPUFreqSelector");
+ if (!proxy) {
+ g_printerr ("Could not construct proxy object\n");
+
+ return;
+ }
+
+ if (governor) {
+ res = dbus_g_proxy_call (proxy, "SetGovernor", &error,
+ G_TYPE_UINT, cpu,
+ G_TYPE_STRING, governor,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res) {
+ if (error) {
+ g_printerr ("Error calling SetGovernor: %s\n", error->message);
+ g_error_free (error);
+ } else {
+ g_printerr ("Error calling SetGovernor\n");
+ }
+
+ g_object_unref (proxy);
+
+ return;
+ }
+ }
+
+ if (frequency != 0) {
+ res = dbus_g_proxy_call (proxy, "SetFrequency", &error,
+ G_TYPE_UINT, cpu,
+ G_TYPE_UINT, frequency,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res) {
+ if (error) {
+ g_printerr ("Error calling SetFrequency: %s\n", error->message);
+ g_error_free (error);
+ } else {
+ g_printerr ("Error calling SetFrequency\n");
+ }
+
+ g_object_unref (proxy);
+
+ return;
+ }
+ }
+
+ g_object_unref (proxy);
+}
+#endif /* HAVE_POLKIT */
+
+static void
+cpufreq_selector_set_values (void)
+{
+ CPUFreqSelector *selector;
+ GError *error = NULL;
+
+ selector = cpufreq_selector_factory_create_selector (cpu);
+ if (!selector) {
+ g_printerr ("No cpufreq support\n");
+
+ return;
+ }
+
+ if (governor) {
+ cpufreq_selector_set_governor (selector, governor, &error);
+
+ if (error) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ }
+
+ if (frequency != 0) {
+ cpufreq_selector_set_frequency (selector, frequency, &error);
+
+ if (error) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ }
+
+ g_object_unref (selector);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+#ifdef HAVE_POLKIT
+ GMainLoop *loop;
+#endif
+ GOptionContext *context;
+ GError *error = NULL;
+
+#ifndef HAVE_POLKIT
+ if (geteuid () != 0) {
+ g_printerr ("You must be root\n");
+
+ return 1;
+ }
+
+ if (argc < 2) {
+ g_printerr ("Missing operand after `cpufreq-selector'\n");
+ g_printerr ("Try `cpufreq-selector --help' for more information.\n");
+
+ return 1;
+ }
+#endif
+
+ g_type_init ();
+
+ context = g_option_context_new ("- CPUFreq Selector");
+ g_option_context_add_main_entries (context, options, NULL);
+
+ if (!g_option_context_parse (context, &argc, &argv, &error)) {
+ if (error) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ }
+
+ g_option_context_free (context);
+
+ return 1;
+ }
+
+ g_option_context_free (context);
+
+#ifdef HAVE_POLKIT
+ if (!cpufreq_selector_service_register (SELECTOR_SERVICE, &error)) {
+ if (governor || frequency != 0) {
+ cpufreq_selector_set_values_dbus ();
+
+ return 0;
+ }
+
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+
+ return 1;
+ }
+
+ cpufreq_selector_set_values ();
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_object_weak_ref (G_OBJECT (SELECTOR_SERVICE),
+ (GWeakNotify) do_exit,
+ loop);
+
+ g_main_loop_run (loop);
+
+ g_main_loop_unref (loop);
+#else /* !HAVE_POLKIT */
+ cpufreq_selector_set_values ();
+#endif /* HAVE_POLKIT */
+
+ return 0;
+}
diff --git a/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.conf b/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.conf
new file mode 100644
index 00000000..c4b27a23
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.conf
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<busconfig>
+
+ <!-- Only root can own the service -->
+ <policy user="root">
+ <allow own="org.mate.CPUFreqSelector"/>
+ <allow send_interface="org.mate.CPUFreqSelector"/>
+ </policy>
+
+ <policy context="default">
+ <allow send_interface="org.mate.CPUFreqSelector"/>
+ </policy>
+
+</busconfig>
+
diff --git a/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.service.in b/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.service.in
new file mode 100644
index 00000000..e402df2e
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/org.mate.CPUFreqSelector.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.mate.CPUFreqSelector
+Exec=@BINDIR@/cpufreq-selector
+User=root
diff --git a/cpufreq/src/cpufreq-selector/org.mate.cpufreqselector.policy.in b/cpufreq/src/cpufreq-selector/org.mate.cpufreqselector.policy.in
new file mode 100644
index 00000000..f1249cd2
--- /dev/null
+++ b/cpufreq/src/cpufreq-selector/org.mate.cpufreqselector.policy.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<policyconfig>
+
+ <vendor>The MATE Project</vendor>
+ <vendor_url>http://www.mate.org/</vendor_url>
+ <icon_name>mate-cpu-frequency-applet</icon_name>
+
+ <action id="org.mate.cpufreqselector">
+ <_description>Change CPU Frequency scaling</_description>
+ <_message>Privileges are required to change the CPU Frequency scaling.</_message>
+ <defaults>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+</policyconfig>
diff --git a/cpufreq/src/cpufreq-utils.c b/cpufreq/src/cpufreq-utils.c
new file mode 100644
index 00000000..47b80c1f
--- /dev/null
+++ b/cpufreq/src/cpufreq-utils.c
@@ -0,0 +1,311 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2006 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "cpufreq-utils.h"
+
+#ifdef HAVE_POLKIT
+#include <dbus/dbus-glib.h>
+#endif /* HAVE_POLKIT */
+
+guint
+cpufreq_utils_get_n_cpus (void)
+{
+ gint mcpu = -1;
+ gchar *file = NULL;
+ static guint n_cpus = 0;
+
+ if (n_cpus > 0)
+ return n_cpus;
+
+ do {
+ if (file)
+ g_free (file);
+ mcpu ++;
+ file = g_strdup_printf ("/sys/devices/system/cpu/cpu%d", mcpu);
+ } while (g_file_test (file, G_FILE_TEST_EXISTS));
+ g_free (file);
+
+ if (mcpu >= 0) {
+ n_cpus = (guint)mcpu;
+ return mcpu;
+ }
+
+ mcpu = -1;
+ file = NULL;
+ do {
+ if (file)
+ g_free (file);
+ mcpu ++;
+ file = g_strdup_printf ("/proc/sys/cpu/%d", mcpu);
+ } while (g_file_test (file, G_FILE_TEST_EXISTS));
+ g_free (file);
+
+ if (mcpu >= 0) {
+ n_cpus = (guint)mcpu;
+ return mcpu;
+ }
+
+ n_cpus = 1;
+
+ return 1;
+}
+
+void
+cpufreq_utils_display_error (const gchar *message,
+ const gchar *secondary)
+{
+ GtkWidget *dialog;
+
+ g_return_if_fail (message != NULL);
+
+ dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s", message);
+ if (secondary) {
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", secondary);
+ }
+
+ gtk_window_set_title (GTK_WINDOW (dialog), ""); /* as per HIG */
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
+ g_signal_connect (G_OBJECT (dialog),
+ "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_widget_show (dialog);
+}
+
+#ifdef HAVE_POLKIT
+#define CACHE_VALIDITY_SEC 2
+
+static gboolean
+selector_is_available (void)
+{
+ DBusGProxy *proxy;
+ static DBusGConnection *system_bus = NULL;
+ GError *error = NULL;
+ gboolean result;
+
+ if (!system_bus) {
+ system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (!system_bus) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ return FALSE;
+ }
+ }
+
+ proxy = dbus_g_proxy_new_for_name (system_bus,
+ "org.mate.CPUFreqSelector",
+ "/org/mate/cpufreq_selector/selector",
+ "org.mate.CPUFreqSelector");
+
+ if (!dbus_g_proxy_call (proxy, "CanSet", &error,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &result,
+ G_TYPE_INVALID)) {
+ g_warning ("Error calling org.mate.CPUFreqSelector.CanSet: %s", error->message);
+ g_error_free (error);
+ result = FALSE;
+ }
+
+ g_object_unref (proxy);
+
+ return result;
+}
+
+gboolean
+cpufreq_utils_selector_is_available (void)
+{
+ static gboolean cache = FALSE;
+ static time_t last_refreshed = 0;
+ time_t now;
+
+ time (&now);
+ if (ABS (now - last_refreshed) > CACHE_VALIDITY_SEC) {
+ cache = selector_is_available ();
+ last_refreshed = now;
+ }
+
+ return cache;
+}
+#else /* !HAVE_POLKIT */
+gboolean
+cpufreq_utils_selector_is_available (void)
+{
+ struct stat *info;
+ gchar *path = NULL;
+
+ path = g_find_program_in_path ("cpufreq-selector");
+ if (!path)
+ return FALSE;
+
+ if (geteuid () == 0) {
+ g_free (path);
+ return TRUE;
+ }
+
+ info = (struct stat *) g_malloc (sizeof (struct stat));
+
+ if ((lstat (path, info)) != -1) {
+ if ((info->st_mode & S_ISUID) && (info->st_uid == 0)) {
+ g_free (info);
+ g_free (path);
+
+ return TRUE;
+ }
+ }
+
+ g_free (info);
+ g_free (path);
+
+ return FALSE;
+}
+#endif /* HAVE_POLKIT_MATE */
+
+gchar *
+cpufreq_utils_get_frequency_label (guint freq)
+{
+ gint divisor;
+
+ if (freq > 999999) /* freq (kHz) */
+ divisor = (1000 * 1000);
+ else
+ divisor = 1000;
+
+ if (((freq % divisor) == 0) || divisor == 1000) /* integer */
+ return g_strdup_printf ("%d", freq / divisor);
+ else /* float */
+ return g_strdup_printf ("%3.2f", ((gfloat)freq / divisor));
+}
+
+gchar *
+cpufreq_utils_get_frequency_unit (guint freq)
+{
+ if (freq > 999999) /* freq (kHz) */
+ return g_strdup ("GHz");
+ else
+ return g_strdup ("MHz");
+}
+
+gboolean
+cpufreq_utils_governor_is_automatic (const gchar *governor)
+{
+ g_return_val_if_fail (governor != NULL, FALSE);
+
+ if (g_ascii_strcasecmp (governor, "userspace") == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+cpufreq_file_get_contents (const gchar *filename,
+ gchar **contents,
+ gsize *length,
+ GError **error)
+{
+ gint fd;
+ GString *buffer = NULL;
+ gchar *display_filename;
+
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (contents != NULL, FALSE);
+
+ display_filename = g_filename_display_name (filename);
+
+ *contents = NULL;
+ if (length)
+ *length = 0;
+
+ fd = open (filename, O_RDONLY);
+ if (fd < 0) {
+ gint save_errno = errno;
+
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (save_errno),
+ "Failed to open file '%s': %s",
+ display_filename,
+ g_strerror (save_errno));
+ g_free (display_filename);
+
+ return FALSE;
+ }
+
+ while (TRUE) {
+ ssize_t bytes_read;
+ gchar buf[1024];
+
+ bytes_read = read (fd, buf, sizeof (buf));
+ if (bytes_read < 0) { /* Error */
+ if (errno != EINTR) {
+ gint save_errno = errno;
+
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (save_errno),
+ "Failed to read from file '%s': %s",
+ display_filename,
+ g_strerror (save_errno));
+
+ if (buffer)
+ g_string_free (buffer, TRUE);
+
+ g_free (display_filename);
+ close (fd);
+
+ return FALSE;
+ }
+ } else if (bytes_read == 0) { /* EOF */
+ break;
+ } else {
+ if (!buffer)
+ buffer = g_string_sized_new (bytes_read);
+ buffer = g_string_append_len (buffer, buf, bytes_read);
+ }
+ }
+
+ g_free (display_filename);
+
+ if (buffer)
+ *contents = g_string_free (buffer, FALSE);
+
+ if (length)
+ *length = strlen (*contents);
+
+ close (fd);
+
+ return TRUE;
+}
diff --git a/cpufreq/src/cpufreq-utils.h b/cpufreq/src/cpufreq-utils.h
new file mode 100644
index 00000000..9420c651
--- /dev/null
+++ b/cpufreq/src/cpufreq-utils.h
@@ -0,0 +1,44 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2006 Carlos Garcia Campos <[email protected]>
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#ifndef CPUFREQ_UTILS_H
+#define CPUFREQ_UTILS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/* Useful global methods */
+guint cpufreq_utils_get_n_cpus (void);
+void cpufreq_utils_display_error (const gchar *message,
+ const gchar *secondary);
+gboolean cpufreq_utils_selector_is_available (void);
+gchar *cpufreq_utils_get_frequency_label (guint freq);
+gchar *cpufreq_utils_get_frequency_unit (guint freq);
+gboolean cpufreq_utils_governor_is_automatic (const gchar *governor);
+gboolean cpufreq_file_get_contents (const gchar *filename,
+ gchar **contents,
+ gsize *length,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* CPUFREQ_UTILS_H */