2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24
#include <glib/gi18n.h>
25
#include <glib/gprintf.h>
31
#include "applet-struct.h"
32
#include "applet-notifications.h"
33
#include "applet-rame.h"
34
#include "cairo-dock.h"
37
#define RAME_DATA_PIPE "/proc/meminfo"
38
#define CD_RAME_PROC_FS "/proc"
40
#define goto_next_line \
41
str = strchr (str, '\n'); \
43
myData.bAcquisitionOK = FALSE; \
47
#define get_value(iValue) \
48
str = strchr (str, ':'); \
50
myData.bAcquisitionOK = FALSE; \
58
void cd_rame_read_data (CairoDockModuleInstance *myApplet)
60
gchar *cContent = NULL;
62
GError *erreur = NULL;
63
g_file_get_contents (RAME_DATA_PIPE, &cContent, &length, &erreur);
66
cd_warning("ram : %s", erreur->message);
69
myData.bAcquisitionOK = FALSE;
74
gchar *str = cContent;
76
get_value (myData.ramTotal) // MemTotal
77
cd_debug ("ramTotal : %lld", myData.ramTotal);
80
get_value (myData.ramFree) // MemFree
81
cd_debug ("ramFree : %lld", myData.ramFree);
83
myData.ramUsed = myData.ramTotal - myData.ramFree;
85
get_value (myData.ramBuffers) // Buffers.
88
get_value (myData.ramCached) // Cached.
89
cd_debug ("ramCached : %lld", myData.ramCached);
91
goto_next_line // SwapCached:
92
goto_next_line // Active:
93
goto_next_line // Inactive:
94
goto_next_line // HighTotal:
95
goto_next_line // HighFree:
96
goto_next_line // LowTotal:
97
goto_next_line // LowFree:
99
while (strncmp (str, "SwapTotal", 9) != 0)
103
get_value (myData.swapTotal) // SwapTotal.
104
cd_debug ("swapTotal : %lld", myData.swapTotal);
106
get_value (myData.swapFree) // SwapFree.
107
cd_debug ("swapFree : %lld", myData.swapFree);
109
myData.swapUsed = myData.swapTotal - myData.swapFree;
112
myData.bAcquisitionOK = TRUE;
113
if (! myData.bInitialized)
114
myData.bInitialized = TRUE;
118
gboolean cd_rame_update_from_data (CairoDockModuleInstance *myApplet)
120
if ( ! myData.bAcquisitionOK)
122
if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_LABEL)
123
CD_APPLET_SET_NAME_FOR_MY_ICON (myConfig.defaultTitle);
124
else if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_ICON)
125
CD_APPLET_SET_QUICK_INFO_ON_MY_ICON ("N/A");
128
CD_APPLET_RENDER_GAUGE (myData.pGauge, 0.);
132
CD_APPLET_RENDER_GRAPH (myData.pGraph);
137
if (! myData.bInitialized)
139
if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_ICON)
140
CD_APPLET_SET_QUICK_INFO_ON_MY_ICON (myDock ? "..." : D_("Loading"));
143
CD_APPLET_RENDER_GAUGE (myData.pGauge, 0.);
147
CD_APPLET_RENDER_GRAPH (myData.pGraph);
152
//double fRamPercent = 100. * (myData.ramUsed - myData.ramCached) / myData.ramTotal;
153
//double fSwapPercent = 100. * myData.swapUsed / myData.swapTotal;
154
double fRamPercent = 100. * (myConfig.bShowFreeMemory ? myData.ramFree + myData.ramCached + myData.ramBuffers : myData.ramUsed - myData.ramCached - myData.ramBuffers) / myData.ramTotal;
155
double fSwapPercent = (myData.swapTotal ? 100. * (myConfig.bShowFreeMemory ? myData.swapFree : myData.swapUsed) / myData.swapTotal : 0.);
156
cd_debug ("fRamPercent : %.2f %% ; fSwapPercent : %.2f %%", fRamPercent, fSwapPercent);
157
gboolean bRamNeedsUpdate = (fabs (myData.fPrevRamPercent - fRamPercent) > .1);
158
gboolean bSwapNeedsUpdate = (myConfig.bShowSwap && fabs (myData.fPrevSwapPercent - fSwapPercent) > .1);
159
if (myConfig.iInfoDisplay != CAIRO_DOCK_INFO_NONE && (bRamNeedsUpdate || bSwapNeedsUpdate))
161
GString *sInfo = g_string_new ("");
162
if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_LABEL || myDesklet)
163
g_string_assign (sInfo, "RAM : ");
165
g_string_append_printf (sInfo, (fRamPercent < 10 ? "%.1f%%" : "%.0f%%"), fRamPercent);
166
if (myConfig.bShowSwap)
168
g_string_append_c (sInfo, '\n');
169
if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_LABEL || myDesklet)
170
g_string_append_printf (sInfo, "SWAP: ");
171
g_string_append_printf (sInfo, (fSwapPercent < 10 ? "%.1f%%" : "%.0f%%"), fSwapPercent);
174
if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_ICON)
176
CD_APPLET_SET_QUICK_INFO_ON_MY_ICON (sInfo->str);
180
CD_APPLET_SET_NAME_FOR_MY_ICON (sInfo->str);
182
g_string_free (sInfo, TRUE);
185
if (! myConfig.bShowSwap)
187
if (myData.pGauge && bRamNeedsUpdate)
189
CD_APPLET_RENDER_GAUGE (myData.pGauge, fRamPercent / 100);
191
else if (myData.pGraph)
193
CD_APPLET_RENDER_GRAPH_NEW_VALUE (myData.pGraph, fRamPercent / 100);
198
if (myData.pGauge && (bRamNeedsUpdate || bSwapNeedsUpdate))
200
GList *pList = NULL; /// un tableau ca serait plus sympa ...
201
double *pValue = g_new (double, 1);
202
*pValue = (double) fRamPercent / 100;
203
pList = g_list_append (pList, pValue);
204
pValue = g_new (double, 1);
205
*pValue = (double) fSwapPercent / 100;
206
pList = g_list_append (pList, pValue);
207
CD_APPLET_RENDER_GAUGE_MULTI_VALUE (myData.pGauge, pList);
208
g_list_foreach (pList, (GFunc) g_free, NULL);
211
else if (myData.pGraph)
213
CD_APPLET_RENDER_GRAPH_NEW_VALUES (myData.pGraph, fRamPercent / 100, fSwapPercent / 100);
218
myData.fPrevRamPercent = fRamPercent;
219
if (bSwapNeedsUpdate)
220
myData.fPrevSwapPercent = fSwapPercent;
223
return myData.bAcquisitionOK;
228
#define jump_to_next_value(tmp) \
229
while (*tmp != ' ' && *tmp != '\0') \
231
if (*tmp == '\0') { \
232
cd_warning ("problem when reading pipe"); \
235
while (*tmp == ' ') \
238
void cd_rame_free_process (CDProcess *pProcess)
240
if (pProcess == NULL)
242
g_free (pProcess->cName);
247
void cd_rame_get_process_memory (void)
249
static gchar cFilePathBuffer[20+1]; // /proc/12345/stat
250
static gchar cContent[512+1];
253
GError *erreur = NULL;
254
GDir *dir = g_dir_open (CD_RAME_PROC_FS, 0, &erreur);
257
cd_warning ("Attention : %s", erreur->message);
258
g_error_free (erreur);
262
if (myData.pTopList == NULL)
264
myData.pTopList = g_new0 (CDProcess *, myConfig.iNbDisplayedProcesses);
265
myData.iNbDisplayedProcesses = myConfig.iNbDisplayedProcesses;
267
if (myData.pPreviousTopList == NULL)
268
myData.pPreviousTopList = g_new0 (CDProcess *, myConfig.iNbDisplayedProcesses);
269
if (myData.iMemPageSize == 0)
270
myData.iMemPageSize = sysconf(_SC_PAGESIZE);
273
for (i = 0; i < myConfig.iNbDisplayedProcesses; i ++)
274
cd_rame_free_process (myData.pPreviousTopList[i]);
275
memcpy (myData.pPreviousTopList, myData.pTopList, myConfig.iNbDisplayedProcesses * sizeof (CDProcess *));
276
memset (myData.pTopList, 0, myConfig.iNbDisplayedProcesses * sizeof (CDProcess *));
281
unsigned long long iVmSize, iVmRSS, iTotalMemory; // Quantité de mémoire totale utilisée / (Virtual Memory Resident Stack Size) Taille de la pile en mémoire.
283
while ((cPid = g_dir_read_name (dir)) != NULL)
285
if (! g_ascii_isdigit (*cPid))
288
snprintf (cFilePathBuffer, 20, "/proc/%s/stat", cPid);
289
int pipe = open (cFilePathBuffer, O_RDONLY);
290
int iPid = atoi (cPid);
291
if (pipe <= 0) // pas de pot le process s'est termine depuis qu'on a ouvert le repertoire.
296
if (read (pipe, cContent, sizeof (cContent)) <= 0)
298
cd_warning ("can't read %s", cFilePathBuffer);
304
pProcess = g_new0 (CDProcess, 1);
305
pProcess->iPid = iPid;
308
jump_to_next_value (tmp); // on saute le pid.
310
cName = tmp + 1; // on saute la '('.
312
while (*str != ')' && *str != '\0')
315
jump_to_next_value (tmp); // on saute le nom.
316
jump_to_next_value (tmp); // on saute l'etat.
317
jump_to_next_value (tmp);
318
jump_to_next_value (tmp);
319
jump_to_next_value (tmp);
320
jump_to_next_value (tmp);
321
jump_to_next_value (tmp);
322
jump_to_next_value (tmp);
323
jump_to_next_value (tmp);
324
jump_to_next_value (tmp);
325
jump_to_next_value (tmp);
326
jump_to_next_value (tmp);
327
jump_to_next_value (tmp); // on saute le temps user.
328
jump_to_next_value (tmp); // on saute le temps system.
329
jump_to_next_value (tmp);
330
jump_to_next_value (tmp);
331
jump_to_next_value (tmp);
332
jump_to_next_value (tmp); // on saute le nice.
333
jump_to_next_value (tmp);
334
jump_to_next_value (tmp);
335
jump_to_next_value (tmp);
336
iVmSize = atoll (tmp);
337
jump_to_next_value (tmp);
338
iVmRSS = atoll (tmp);
340
iTotalMemory = iVmRSS * myData.iMemPageSize;
341
if (iTotalMemory > 0)
343
i = myConfig.iNbDisplayedProcesses - 1;
344
while (i >= 0 && (myData.pTopList[i] == NULL || iTotalMemory > myData.pTopList[i]->iMemAmount))
346
if (i != myConfig.iNbDisplayedProcesses - 1)
349
for (j = myConfig.iNbDisplayedProcesses - 2; j >= i; j --)
350
myData.pTopList[j+1] = myData.pTopList[j];
352
pProcess = g_new0 (CDProcess, 1);
353
pProcess->iPid = iPid;
354
pProcess->cName = g_strndup (cName, str - cName);
355
pProcess->iMemAmount = iTotalMemory;
356
myData.pTopList[i] = pProcess;
364
void cd_rame_clean_all_processes (void)
367
for (i = 0; i < myData.iNbDisplayedProcesses; i ++)
369
cd_rame_free_process (myData.pTopList[i]);
370
cd_rame_free_process (myData.pPreviousTopList[i]);
372
memset (myData.pTopList, 0, myData.iNbDisplayedProcesses * sizeof (CDProcess *));
373
memset (myData.pPreviousTopList, 0, myData.iNbDisplayedProcesses * sizeof (CDProcess *));