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