1 /* $Id$ */
2 /* Copyright (c) 2010-2015 Pierre Pronchery <khorben@defora.org> */
3 /* This file is part of DeforaOS Desktop Panel */
4 /* This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, version 3 of the License.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>. */
15 
16 
17 
18 #include <sys/time.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22 #include <errno.h>
23 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
24 # include <sys/param.h>
25 # include <sys/sched.h>
26 # include <sys/sysctl.h>
27 #endif
28 #include <libintl.h>
29 #include <System.h>
30 #include "Panel/applet.h"
31 #define _(string) gettext(string)
32 
33 
34 /* Cpufreq */
35 /* private */
36 /* types */
37 typedef struct _PanelApplet
38 {
39 	PanelAppletHelper * helper;
40 	GtkWidget * hbox;
41 	GtkWidget * label;
42 	guint timeout;
43 	int min;
44 	int max;
45 	int step;
46 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
47 	char const * name;
48 #endif
49 } Cpufreq;
50 
51 
52 /* prototypes */
53 static Cpufreq * _cpufreq_init(PanelAppletHelper * helper, GtkWidget ** widget);
54 static void _cpufreq_destroy(Cpufreq * cpufreq);
55 
56 /* callbacks */
57 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
58 static gboolean _cpufreq_on_timeout(gpointer data);
59 #endif
60 
61 
62 /* public */
63 /* variables */
64 PanelAppletDefinition applet =
65 {
66 	"CPU frequency",
67 	"gnome-monitor",
68 	NULL,
69 	_cpufreq_init,
70 	_cpufreq_destroy,
71 	NULL,
72 	FALSE,
73 	TRUE
74 };
75 
76 
77 /* private */
78 /* functions */
79 /* cpufreq_init */
_cpufreq_init(PanelAppletHelper * helper,GtkWidget ** widget)80 static Cpufreq * _cpufreq_init(PanelAppletHelper * helper, GtkWidget ** widget)
81 {
82 	const int timeout = 1000;
83 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
84 	Cpufreq * cpufreq;
85 	PangoFontDescription * desc;
86 	GtkWidget * image;
87 	GtkWidget * label;
88 	char freq[256];
89 	size_t freqsize = sizeof(freq);
90 	char const * p;
91 
92 	/* detect the correct sysctl */
93 	if(sysctlbyname("hw.clockrate", &freq, &freqsize, NULL, 0) == 0)
94 		p = "hw.clockrate";
95 	else if(sysctlbyname("machdep.est.frequency.available", &freq,
96 				&freqsize, NULL, 0) == 0)
97 		p = "machdep.est.frequency.current";
98 	else if(sysctlbyname("machdep.powernow.frequency.available", &freq,
99 				&freqsize, NULL, 0) == 0)
100 		p = "machdep.powernow.frequency.current";
101 	else if(sysctlbyname("machdep.frequency.available", &freq, &freqsize,
102 				NULL, 0) == 0)
103 		p = "machdep.frequency.current";
104 	else
105 	{
106 		error_set("%s: %s", applet.name, _("No support detected"));
107 		return NULL;
108 	}
109 	if((cpufreq = malloc(sizeof(*cpufreq))) == NULL)
110 	{
111 		error_set("%s: %s", applet.name, strerror(errno));
112 		return NULL;
113 	}
114 	cpufreq->helper = helper;
115 	desc = pango_font_description_new();
116 	pango_font_description_set_family(desc, "Monospace");
117 	pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
118 #if GTK_CHECK_VERSION(3, 0, 0)
119 	cpufreq->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
120 #else
121 	cpufreq->hbox = gtk_hbox_new(FALSE, 4);
122 #endif
123 	image = gtk_image_new_from_icon_name("gnome-monitor",
124 			panel_window_get_icon_size(helper->window));
125 	gtk_box_pack_start(GTK_BOX(cpufreq->hbox), image, FALSE, TRUE, 0);
126 	cpufreq->min = 0;
127 	cpufreq->max = 0;
128 	cpufreq->step = 1;
129 	cpufreq->name = p;
130 	cpufreq->max = atoi(freq);
131 	cpufreq->min = (p = strrchr(freq, ' ')) != NULL ? atoi(p)
132 		: cpufreq->max;
133 	cpufreq->label = gtk_label_new(" ");
134 #if GTK_CHECK_VERSION(3, 0, 0)
135 	gtk_widget_override_font(cpufreq->label, desc);
136 #else
137 	gtk_widget_modify_font(cpufreq->label, desc);
138 #endif
139 	gtk_box_pack_start(GTK_BOX(cpufreq->hbox), cpufreq->label, FALSE, TRUE,
140 			0);
141 	label = gtk_label_new(_("MHz"));
142 	gtk_box_pack_start(GTK_BOX(cpufreq->hbox), label, FALSE, TRUE, 0);
143 	if(_cpufreq_on_timeout(cpufreq) == TRUE)
144 		cpufreq->timeout = g_timeout_add(timeout, _cpufreq_on_timeout,
145 				cpufreq);
146 	pango_font_description_free(desc);
147 	gtk_widget_show_all(cpufreq->hbox);
148 	*widget = cpufreq->hbox;
149 	return cpufreq;
150 #else
151 	error_set("%s: %s", applet.name, _("Unsupported platform"));
152 	return NULL;
153 #endif
154 }
155 
156 
157 /* cpufreq_destroy */
_cpufreq_destroy(Cpufreq * cpufreq)158 static void _cpufreq_destroy(Cpufreq * cpufreq)
159 {
160 	g_source_remove(cpufreq->timeout);
161 	gtk_widget_destroy(cpufreq->hbox);
162 	free(cpufreq);
163 }
164 
165 
166 /* callbacks */
167 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
168 /* cpufreq_on_timeout */
_cpufreq_on_timeout(gpointer data)169 static gboolean _cpufreq_on_timeout(gpointer data)
170 {
171 	Cpufreq * cpufreq = data;
172 	PanelAppletHelper * helper = cpufreq->helper;
173 	uint64_t freq;
174 	size_t freqsize = sizeof(freq);
175 	char buf[256];
176 
177 	if(sysctlbyname(cpufreq->name, &freq, &freqsize, NULL, 0) < 0)
178 	{
179 		error_set("%s: %s: %s", applet.name, cpufreq->name,
180 				strerror(errno));
181 		helper->error(NULL, error_get(NULL), 1);
182 		return TRUE;
183 	}
184 	snprintf(buf, sizeof(buf), "%4u", (unsigned int)freq);
185 	gtk_label_set_text(GTK_LABEL(cpufreq->label), buf);
186 # if GTK_CHECK_VERSION(2, 12, 0)
187 	snprintf(buf, sizeof(buf), "%s%u %s", _("CPU frequency: "),
188 			(unsigned int)freq, _("MHz"));
189 	gtk_widget_set_tooltip_text(cpufreq->hbox, buf);
190 # endif
191 	return TRUE;
192 }
193 #endif
194