Merging upstream version 0.8.0 (Closes: #639729, #761971).
[debian/lxpanel.git] / plugins / cpufreq / cpufreq.c
CommitLineData
bfba7517
DB
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>
24d886e1 25#include <glib.h>
bfba7517
DB
26#include <glib/gi18n.h>
27
28#include <string.h>
29
bfba7517 30#include "plugin.h"
89173f95 31#include "misc.h"
bfba7517
DB
32
33#include "dbg.h"
34
89173f95 35#define PROC_ICON "cpufreq-icon"
24d886e1 36#define SYSFS_CPU_DIRECTORY "/sys/devices/system/cpu"
bfba7517
DB
37#define SCALING_GOV "scaling_governor"
38#define SCALING_AGOV "scaling_available_governors"
39#define SCALING_AFREQ "scaling_available_frequencies"
24d886e1 40#define SCALING_CUR_FREQ "scaling_cur_freq"
bfba7517
DB
41#define SCALING_SETFREQ "scaling_setspeed"
42#define SCALING_MAX "scaling_max_freq"
43#define SCALING_MIN "scaling_min_freq"
44
45
46typedef struct {
47 GtkWidget *main;
00916e98 48 config_setting_t *settings;
bfba7517
DB
49 GList *governors;
50 GList *cpus;
51 int has_cpufreq;
52 char* cur_governor;
53 int cur_freq;
54 unsigned int timer;
00916e98 55 //gboolean remember;
bfba7517
DB
56} cpufreq;
57
58typedef struct {
00916e98 59 char *data;
bfba7517
DB
60 cpufreq *cf;
61} Param;
62
00916e98
AG
63static void cpufreq_destructor(gpointer user_data);
64
bfba7517
DB
65static void
66get_cur_governor(cpufreq *cf){
67 FILE *fp;
68 char buf[ 100 ], sstmp [ 256 ];
69
00916e98 70 snprintf(sstmp, sizeof(sstmp), "%s/%s", (char*)cf->cpus->data, SCALING_GOV);
bfba7517 71 if ((fp = fopen( sstmp, "r")) != NULL) {
bfba7517
DB
72 if(cf->cur_governor)
73 {
74 g_free(cf->cur_governor);
75 cf->cur_governor = NULL;
76 }
00916e98
AG
77 if (fgets(buf, 100, fp))
78 {
79 buf[strlen(buf)-1] = '\0';
80 cf->cur_governor = strdup(buf);
81 }
bfba7517
DB
82 fclose(fp);
83 }
84}
85
86static void
87get_cur_freq(cpufreq *cf){
88 FILE *fp;
89 char buf[ 100 ], sstmp [ 256 ];
90
00916e98 91 snprintf(sstmp, sizeof(sstmp), "%s/%s", (char*)cf->cpus->data, SCALING_CUR_FREQ);
bfba7517 92 if ((fp = fopen( sstmp, "r")) != NULL) {
00916e98
AG
93 if (fgets(buf, 100, fp))
94 {
95 buf[strlen(buf)-1] = '\0';
96 cf->cur_freq = atoi(buf);
97 }
bfba7517
DB
98 fclose(fp);
99 }
100}
101
00916e98 102/*static void
bfba7517
DB
103get_governors(cpufreq *cf){
104 FILE *fp;
105 GList *l;
106 char buf[ 100 ], sstmp [ 256 ], c, bufl = 0;
107
108 g_list_free(cf->governors);
109 cf->governors = NULL;
110
111 get_cur_governor(cf);
112
113 if(cf->cpus == NULL){
114 cf->governors = NULL;
115 return;
116 }
24d886e1 117 sprintf(sstmp,"%s/%s",cf->cpus->data, SCALING_AGOV);
bfba7517
DB
118
119 if (!(fp = fopen( sstmp, "r"))) {
120 printf("cpufreq: cannot open %s\n",sstmp);
121 return;
122 }
123
124 while((c = fgetc(fp)) != EOF){
125 if(c == ' '){
126 if(bufl > 1){
127 buf[bufl] = '\0';
128 cf->governors = g_list_append(cf->governors, strdup(buf));
129 }
130 bufl = 0;
131 buf[0] = '\0';
132 }else{
133 buf[bufl++] = c;
134 }
135 }
136
137 fclose(fp);
138}
139
140static void
141cpufreq_set_freq(GtkWidget *widget, Param* p){
142 FILE *fp;
143 char buf[ 100 ], sstmp [ 256 ];
144
145 if(strcmp(p->cf->cur_governor, "userspace")) return;
146
24d886e1 147 sprintf(sstmp,"%s/%s",p->cf->cpus->data, SCALING_SETFREQ);
bfba7517
DB
148 if ((fp = fopen( sstmp, "w")) != NULL) {
149 fprintf(fp,"%s",p->data);
150 fclose(fp);
151 }
152}
153
154static GtkWidget *
155frequency_menu(cpufreq *cf){
156 FILE *fp;
157 Param* param;
158 char buf[ 100 ], sstmp [ 256 ], c, bufl = 0;
159
24d886e1 160 sprintf(sstmp,"%s/%s",cf->cpus->data, SCALING_AFREQ);
bfba7517
DB
161
162 if (!(fp = fopen( sstmp, "r"))) {
163 printf("cpufreq: cannot open %s\n",sstmp);
170c1e2e 164 return 0;
bfba7517
DB
165 }
166
167 GtkMenu* menu = GTK_MENU(gtk_menu_new());
168 GtkWidget* menuitem;
169
170 while((c = fgetc(fp)) != EOF){
171 if(c == ' '){
172 if(bufl > 1){
173 buf[bufl] = '\0';
f8c25730 174 menuitem = gtk_menu_item_new_with_label(strdup(buf));
bfba7517
DB
175 gtk_menu_append (GTK_MENU_SHELL (menu), menuitem);
176 gtk_widget_show (menuitem);
177 param = g_new0(Param, 1);
178 param->data = strdup(buf);
179 param->cf = cf;
180 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(cpufreq_set_freq), param);
f8c25730 181 g_object_weak_ref(G_OBJECT(menuitem), (GWeakNotify)g_free, param);
bfba7517
DB
182 }
183 bufl = 0;
184 buf[0] = '\0';
185 }else{
186 buf[bufl++] = c;
187 }
188 }
189
190 fclose(fp);
f8c25730 191 return GTK_WIDGET(menu);
00916e98 192}*/
bfba7517
DB
193
194static void
24d886e1
DB
195get_cpus(cpufreq *cf)
196{
197
bfba7517
DB
198 const char *cpu;
199 char cpu_path[100];
200
24d886e1
DB
201 GDir * cpuDirectory = g_dir_open(SYSFS_CPU_DIRECTORY, 0, NULL);
202 if (cpuDirectory == NULL)
bfba7517
DB
203 {
204 cf->cpus = NULL;
205 printf("cpufreq: no cpu found\n");
206 return;
207 }
208
24d886e1
DB
209 while ((cpu = g_dir_read_name(cpuDirectory)))
210 {
211 /* Look for directories of the form "cpu<n>", where "<n>" is a decimal integer. */
212 if ((strncmp(cpu, "cpu", 3) == 0) && (cpu[3] >= '0') && (cpu[3] <= '9'))
213 {
00916e98 214 snprintf(cpu_path, sizeof(cpu_path), "%s/%s/cpufreq", SYSFS_CPU_DIRECTORY, cpu);
bfba7517 215
24d886e1 216 GDir * cpufreqDir = g_dir_open(SYSFS_CPU_DIRECTORY, 0, NULL);
00916e98 217 if (cpufreqDir == NULL)
bfba7517
DB
218 {
219 cf->cpus = NULL;
220 cf->has_cpufreq = 0;
24d886e1 221 break;
bfba7517 222 }
24d886e1
DB
223
224 cf->has_cpufreq = 1;
225 cf->cpus = g_list_append(cf->cpus, strdup(cpu_path));
bfba7517
DB
226 }
227 }
228 g_dir_close(cpuDirectory);
229}
230
00916e98 231/*static void
bfba7517
DB
232cpufreq_set_governor(GtkWidget *widget, Param* p){
233 FILE *fp;
234 char buf[ 100 ], sstmp [ 256 ];
235
24d886e1 236 sprintf(sstmp, "%s/%s", p->cf->cpus->data, SCALING_GOV);
bfba7517
DB
237 if ((fp = fopen( sstmp, "w")) != NULL) {
238 fprintf(fp,"%s",p->data);
239 fclose(fp);
240 }
241}
242
243static GtkWidget *
244cpufreq_menu(cpufreq *cf){
245 GList *l;
246 GSList *group;
247 char buff[100];
248 GtkMenuItem* menuitem;
249 Param* param;
250
251 GtkMenu* menu = GTK_MENU(gtk_menu_new());
f8c25730 252 g_signal_connect(menu, "selection-done", G_CALLBACK(gtk_widget_destroy), NULL);
bfba7517
DB
253
254 get_governors(cf);
255 group = NULL;
256
24d886e1 257 if((cf->governors == NULL) || (!cf->has_cpufreq) || (cf->cur_governor == NULL)){
bfba7517 258 menuitem = GTK_MENU_ITEM(gtk_menu_item_new_with_label("CPUFreq not supported"));
f8c25730
DB
259 gtk_menu_append (GTK_MENU_SHELL (menu), GTK_WIDGET (menuitem));
260 gtk_widget_show (GTK_WIDGET (menuitem));
261 return GTK_WIDGET(menu);
bfba7517
DB
262 }
263
264 if(strcmp(cf->cur_governor, "userspace") == 0){
265 menuitem = GTK_MENU_ITEM(gtk_menu_item_new_with_label(" Frequency"));
f8c25730
DB
266 gtk_menu_append (GTK_MENU_SHELL (menu), GTK_WIDGET (menuitem));
267 gtk_widget_show (GTK_WIDGET (menuitem));
bfba7517
DB
268 gtk_menu_item_set_submenu(menuitem, frequency_menu(cf));
269 menuitem = GTK_MENU_ITEM(gtk_separator_menu_item_new());
f8c25730 270 gtk_menu_append (GTK_MENU_SHELL (menu), GTK_WIDGET (menuitem));
bfba7517
DB
271 gtk_widget_show (GTK_WIDGET(menuitem));
272 }
273
274 for( l = cf->governors; l; l = l->next )
275 {
276 if(strcmp((char*)l->data, cf->cur_governor) == 0){
277 sprintf(buff,"> %s", l->data);
278 menuitem = GTK_MENU_ITEM(gtk_menu_item_new_with_label(strdup(buff)));
279 }else{
280 sprintf(buff," %s", l->data);
281 menuitem = GTK_MENU_ITEM(gtk_menu_item_new_with_label(strdup(buff)));
282 }
283
f8c25730
DB
284 gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (menuitem));
285 gtk_widget_show (GTK_WIDGET (menuitem));
bfba7517
DB
286 param = g_new0(Param, 1);
287 param->data = l->data;
288 param->cf = cf;
289 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(cpufreq_set_governor), param);
f8c25730 290 g_object_weak_ref(G_OBJECT(menuitem), (GWeakNotify) g_free, param);
bfba7517
DB
291 }
292
f8c25730 293 return GTK_WIDGET (menu);
00916e98 294}*/
bfba7517
DB
295
296
297
298static gboolean
00916e98 299clicked(GtkWidget *widget, GdkEventButton *evt, LXPanel *panel)
bfba7517 300{
00916e98
AG
301 ENTER;
302
303 /* Standard right-click handling. */
bfba7517
DB
304 if( evt->button == 1 )
305 {
24d886e1 306// Setting governor can't work without root privilege
00916e98 307// gtk_menu_popup( cpufreq_menu((cpufreq*)plugin->priv), NULL, NULL, NULL, NULL,
24d886e1 308// evt->button, evt->time );
bfba7517 309 return TRUE;
bfba7517
DB
310 }
311
00916e98 312 RET(FALSE);
bfba7517
DB
313}
314
00916e98
AG
315static gboolean
316_update_tooltip(cpufreq *cf)
bfba7517
DB
317{
318 char *tooltip;
319
320 get_cur_freq(cf);
321 get_cur_governor(cf);
322
323 ENTER;
324
00916e98 325 tooltip = g_strdup_printf(_("Frequency: %d MHz\nGovernor: %s"),
bfba7517 326 cf->cur_freq / 1000, cf->cur_governor);
00916e98 327 gtk_widget_set_tooltip_text(cf->main, tooltip);
bfba7517
DB
328 g_free(tooltip);
329 RET(TRUE);
330}
331
00916e98
AG
332static gboolean update_tooltip(gpointer user_data)
333{
334 if (g_source_is_destroyed(g_main_current_source()))
335 return FALSE;
336 return _update_tooltip(user_data);
337}
338
339static GtkWidget *cpufreq_constructor(LXPanel *panel, config_setting_t *settings)
bfba7517
DB
340{
341 cpufreq *cf;
00916e98 342 //GtkWidget *button;
bfba7517
DB
343
344 ENTER;
345 cf = g_new0(cpufreq, 1);
00916e98 346 g_return_val_if_fail(cf != NULL, NULL);
bfba7517
DB
347 cf->governors = NULL;
348 cf->cpus = NULL;
00916e98 349 cf->settings = settings;
bfba7517 350
89173f95 351 cf->main = lxpanel_button_new_for_icon(panel, PROC_ICON, NULL, NULL);
00916e98 352 lxpanel_plugin_set_data(cf->main, cf, cpufreq_destructor);
bfba7517
DB
353
354 cf->has_cpufreq = 0;
355
356 get_cpus(cf);
357
00916e98
AG
358 //if (config_setting_lookup_int(settings, "Remember", &tmp_int)) cf->remember = tmp_int != 0;
359 //if (config_setting_lookup_int(settings, "Governor", &tmp_str)) cf->cur_governor = g_strdup(tmp_str);
360 //config_setting_lookup_int(settings, "Frequency", &cf->cur_freq);
bfba7517 361
00916e98
AG
362 _update_tooltip(cf);
363 cf->timer = g_timeout_add_seconds(2, update_tooltip, (gpointer)cf);
bfba7517 364
00916e98 365 RET(cf->main);
bfba7517
DB
366}
367
00916e98
AG
368/*
369static gboolean applyConfig(gpointer user_data)
370{
371 cpufreq *cf = lxpanel_plugin_get_data(user_data);
bfba7517 372
00916e98
AG
373 config_group_set_int(cf->settings, "Remember", cf->remember);
374 return FALSE;
375}
bfba7517 376
00916e98
AG
377static GtkWidget *config(LXPanel *panel, GtkWidget *p, GtkWindow *parent)
378{
379 cpufreq *cf = lxpanel_plugin_get_data(p);
380 return lxpanel_generic_config_dlg(_("CPUFreq frontend"), panel, applyConfig, p,
bfba7517
DB
381 _("Remember governor and frequency"), &cf->remember, CONF_TYPE_BOOL,
382 NULL);
bfba7517 383}
00916e98 384*/
bfba7517
DB
385
386static void
00916e98 387cpufreq_destructor(gpointer user_data)
bfba7517 388{
00916e98 389 cpufreq *cf = (cpufreq *)user_data;
bfba7517
DB
390 g_list_free ( cf->cpus );
391 g_list_free ( cf->governors );
392 g_source_remove(cf->timer);
393 g_free(cf);
394}
395
bfba7517 396
00916e98 397FM_DEFINE_MODULE(lxpanel_gtk, cpufreq)
bfba7517 398
00916e98
AG
399/* Plugin descriptor. */
400LXPanelPluginInit fm_module_init_lxpanel_gtk = {
401 .name = N_("CPUFreq frontend"),
402 .description = N_("Display CPU frequency and allow to change governors and frequency"),
bfba7517 403
00916e98
AG
404 .new_instance = cpufreq_constructor,
405 //.config = config,
406 .button_press_event = clicked
bfba7517 407};