1 /**
2 * CPUFreq plugin to lxpanel
3 *
4 * Copyright (C) 2009 by Daniel Kesler <kesler.daniel@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22 #include <sys/types.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #if defined(__DragonFly__) || defined(__FreeBSD__)
26 #include <sys/sysctl.h>
27 #endif
28 #include <glib.h>
29 #include <glib/gi18n.h>
30
31 #include <string.h>
32
33 #include "plugin.h"
34 #include "misc.h"
35
36 #include "dbg.h"
37
38 #define PROC_ICON "cpufreq-icon"
39 #if defined(__linux__)
40 #define SYSFS_CPU_DIRECTORY "/sys/devices/system/cpu"
41 #define SCALING_GOV "scaling_governor"
42 #define SCALING_AGOV "scaling_available_governors"
43 #define SCALING_AFREQ "scaling_available_frequencies"
44 #define SCALING_CUR_FREQ "scaling_cur_freq"
45 #define SCALING_SETFREQ "scaling_setspeed"
46 #define SCALING_MAX "scaling_max_freq"
47 #define SCALING_MIN "scaling_min_freq"
48 #endif
49
50 typedef struct {
51 GtkWidget *main;
52 config_setting_t *settings;
53 #if defined(__linux__)
54 GList *governors;
55 GList *cpus;
56 char* cur_governor;
57 #elif defined(__DragonFly__) || defined(__FreeBSD__)
58 int cpus;
59 #endif
60 int has_cpufreq;
61 int cur_freq;
62 unsigned int timer;
63 //gboolean remember;
64 } cpufreq;
65
66 typedef struct {
67 char *data;
68 cpufreq *cf;
69 } Param;
70
71 static void cpufreq_destructor(gpointer user_data);
72
73 #if defined(__linux__)
74 static void
get_cur_governor(cpufreq * cf)75 get_cur_governor(cpufreq *cf){
76 FILE *fp;
77 char buf[ 100 ], sstmp [ 256 ];
78
79 snprintf(sstmp, sizeof(sstmp), "%s/%s", (char*)cf->cpus->data, SCALING_GOV);
80 if ((fp = fopen( sstmp, "r")) != NULL) {
81 if(cf->cur_governor)
82 {
83 g_free(cf->cur_governor);
84 cf->cur_governor = NULL;
85 }
86 if (fgets(buf, 100, fp))
87 {
88 buf[strlen(buf)-1] = '\0';
89 cf->cur_governor = strdup(buf);
90 }
91 fclose(fp);
92 }
93 }
94
95 static void
get_cur_freq(cpufreq * cf)96 get_cur_freq(cpufreq *cf){
97 FILE *fp;
98 char buf[ 100 ], sstmp [ 256 ];
99
100 snprintf(sstmp, sizeof(sstmp), "%s/%s", (char*)cf->cpus->data, SCALING_CUR_FREQ);
101 if ((fp = fopen( sstmp, "r")) != NULL) {
102 if (fgets(buf, 100, fp))
103 {
104 buf[strlen(buf)-1] = '\0';
105 cf->cur_freq = atoi(buf);
106 }
107 fclose(fp);
108 }
109 }
110
111 static void
get_cpus(cpufreq * cf)112 get_cpus(cpufreq *cf)
113 {
114
115 const char *cpu;
116 char cpu_path[100];
117
118 GDir * cpuDirectory = g_dir_open(SYSFS_CPU_DIRECTORY, 0, NULL);
119 if (cpuDirectory == NULL)
120 {
121 cf->cpus = NULL;
122 printf("cpufreq: no cpu found\n");
123 return;
124 }
125
126 while ((cpu = g_dir_read_name(cpuDirectory)))
127 {
128 /* Look for directories of the form "cpu<n>", where "<n>" is a decimal integer. */
129 if ((strncmp(cpu, "cpu", 3) == 0) && (cpu[3] >= '0') && (cpu[3] <= '9'))
130 {
131 snprintf(cpu_path, sizeof(cpu_path), "%s/%s/cpufreq", SYSFS_CPU_DIRECTORY, cpu);
132
133 GDir * cpufreqDir = g_dir_open(SYSFS_CPU_DIRECTORY, 0, NULL);
134 if (cpufreqDir == NULL)
135 {
136 cf->cpus = NULL;
137 cf->has_cpufreq = 0;
138 break;
139 }
140
141 cf->has_cpufreq = 1;
142 cf->cpus = g_list_append(cf->cpus, strdup(cpu_path));
143 }
144 }
145 g_dir_close(cpuDirectory);
146 }
147 #elif defined(__DragonFly__) || defined(__FreeBSD__)
148 static void
get_cur_freq(cpufreq * cf)149 get_cur_freq(cpufreq *cf)
150 {
151 int buf;
152 size_t length_buf = sizeof(int);
153
154 if (sysctlbyname("dev.cpu.0.freq", &buf, &length_buf, NULL, 0) < 0)
155 cf->cur_freq = 0;
156 else
157 cf->cur_freq = buf;
158 }
159
160 int
detect_cpus_number(void)161 detect_cpus_number(void)
162 {
163 static int mib[] = {CTL_HW, HW_NCPU};
164 int buf;
165 size_t length_buf = sizeof(int);
166
167 if (sysctl(mib, 2, &buf, &length_buf, NULL, 0) < 0)
168 return 0;
169 else
170 return buf;
171 }
172
173 static void
get_cpus(cpufreq * cf)174 get_cpus(cpufreq *cf)
175 {
176 int ncpus, buf;
177 size_t lenght_buf = sizeof(int);
178
179 ncpus = detect_cpus_number();
180 cf->cpus = ncpus;
181 if (cf->cpus > 0)
182 cf->has_cpufreq = 1;
183 else
184 {
185 cf->has_cpufreq = 0;
186 printf("cpufreq: no cpu found\n");
187 }
188 }
189 #endif
190
191
192 static gboolean
clicked(GtkWidget * widget,GdkEventButton * evt,LXPanel * panel)193 clicked(GtkWidget *widget, GdkEventButton *evt, LXPanel *panel)
194 {
195 ENTER;
196
197 /* Standard right-click handling. */
198 if( evt->button == 1 )
199 {
200 // Setting governor can't work without root privilege
201 // gtk_menu_popup( cpufreq_menu((cpufreq*)plugin->priv), NULL, NULL, NULL, NULL,
202 // evt->button, evt->time );
203 return TRUE;
204 }
205
206 RET(FALSE);
207 }
208
209 static gboolean
_update_tooltip(cpufreq * cf)210 _update_tooltip(cpufreq *cf)
211 {
212 char *tooltip;
213
214 get_cur_freq(cf);
215 #if defined(__linux__)
216 get_cur_governor(cf);
217 #endif
218
219 ENTER;
220
221 #if defined(__linux__)
222 tooltip = g_strdup_printf(_("Frequency: %d MHz\nGovernor: %s"),
223 cf->cur_freq / 1000, cf->cur_governor);
224 #elif defined(__DragonFly__) || defined(__FreeBSD__)
225 tooltip = g_strdup_printf("Frequency: %d MHz", cf->cur_freq);
226 #endif
227 gtk_widget_set_tooltip_text(cf->main, tooltip);
228 g_free(tooltip);
229 RET(TRUE);
230 }
231
update_tooltip(gpointer user_data)232 static gboolean update_tooltip(gpointer user_data)
233 {
234 if (g_source_is_destroyed(g_main_current_source()))
235 return FALSE;
236 return _update_tooltip(user_data);
237 }
238
cpufreq_constructor(LXPanel * panel,config_setting_t * settings)239 static GtkWidget *cpufreq_constructor(LXPanel *panel, config_setting_t *settings)
240 {
241 cpufreq *cf;
242 //GtkWidget *button;
243
244 ENTER;
245 cf = g_new0(cpufreq, 1);
246 g_return_val_if_fail(cf != NULL, NULL);
247 #if defined(__linux__)
248 cf->governors = NULL;
249 cf->cpus = NULL;
250 #elif defined(__DragonFly__) || defined(__FreeBSD__)
251 cf->cpus = 0;
252 #endif
253 cf->settings = settings;
254
255 cf->main = lxpanel_button_new_for_icon(panel, PROC_ICON, NULL, NULL);
256 lxpanel_plugin_set_data(cf->main, cf, cpufreq_destructor);
257
258 cf->has_cpufreq = 0;
259
260 get_cpus(cf);
261
262 //if (config_setting_lookup_int(settings, "Remember", &tmp_int)) cf->remember = tmp_int != 0;
263 //if (config_setting_lookup_int(settings, "Governor", &tmp_str)) cf->cur_governor = g_strdup(tmp_str);
264 //config_setting_lookup_int(settings, "Frequency", &cf->cur_freq);
265
266 _update_tooltip(cf);
267 cf->timer = g_timeout_add_seconds(2, update_tooltip, (gpointer)cf);
268
269 RET(cf->main);
270 }
271
272 static void
cpufreq_destructor(gpointer user_data)273 cpufreq_destructor(gpointer user_data)
274 {
275 cpufreq *cf = (cpufreq *)user_data;
276 #if defined(__linux__)
277 g_list_free ( cf->cpus );
278 g_list_free ( cf->governors );
279 #endif
280 g_source_remove(cf->timer);
281 g_free(cf);
282 }
283
284
285 FM_DEFINE_MODULE(lxpanel_gtk, cpufreq)
286
287 /* Plugin descriptor. */
288 LXPanelPluginInit fm_module_init_lxpanel_gtk = {
289 .name = N_("CPUFreq frontend"),
290 #if defined(__linux__)
291 .description = N_("Display CPU frequency and allow to change governors and frequency"),
292 #elif defined(__DragonFly__) || defined(__FreeBSD__)
293 .description = "Display CPU frequency",
294 #endif
295
296 .new_instance = cpufreq_constructor,
297 //.config = config,
298 .button_press_event = clicked
299 };
300