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/>.
25
#include <sys/types.h>
26
#include <sys/socket.h>
29
#include <net/if_types.h>
30
#include <net/if_dl.h>
33
#include "applet-struct.h"
34
#include "applet-notifications.h"
35
#include "applet-netspeed.h"
36
#include "cairo-dock.h"
38
#define NETSPEED_DATA_PIPE "/proc/net/dev"
41
// Prend un debit en octet par seconde et le transforme en une chaine de la forme : xxx yB/s
42
static void cd_netspeed_formatRate (unsigned long long rate, gchar* debit, int iBufferSize, gboolean bLong)
48
snprintf (debit, iBufferSize, "0 %s/s", D_("B"));
50
snprintf (debit, iBufferSize, "0");
56
snprintf (debit, iBufferSize, "%i %s/s", smallRate, D_("B"));
58
snprintf (debit, iBufferSize, "%iB", smallRate);
60
else if (rate < (1<<20))
62
smallRate = rate >> 10;
64
snprintf (debit, iBufferSize, "%i %s/s", smallRate, D_("KB"));
66
snprintf (debit, iBufferSize, "%iK", smallRate);
68
else if (rate < (1<<30))
70
smallRate = rate >> 20;
72
snprintf (debit, iBufferSize, "%i %s/s", smallRate, D_("MB"));
74
snprintf (debit, iBufferSize, "%iM", smallRate);
76
else if (rate < ((unsigned long long)1<<40))
78
smallRate = rate >> 30;
80
snprintf (debit, iBufferSize, "%i %s/s", smallRate, D_("GB"));
82
snprintf (debit, iBufferSize, "%iG", smallRate);
84
else // c'est vraiment pour dire qu'on est exhaustif :-)
86
smallRate = rate >> 40;
88
snprintf (debit, iBufferSize, "%i %s/s", smallRate, D_("TB"));
90
snprintf (debit, iBufferSize, "%iT", smallRate);
95
void cd_netspeed_format_value (CairoDataRenderer *pRenderer, int iNumValue, gchar *cFormatBuffer, int iBufferLength, GldiModuleInstance *myApplet)
97
static gchar s_upRateFormatted[11];
98
cd_netspeed_formatRate (iNumValue == 0 ? myData.iDownloadSpeed : myData.iUploadSpeed, s_upRateFormatted, 11, FALSE);
99
snprintf (cFormatBuffer, iBufferLength,
101
cairo_data_renderer_can_write_values (pRenderer) ? (iNumValue == 0 ?"↓" : "↑") : "",
106
void cd_netspeed_get_data (GldiModuleInstance *myApplet)
108
g_timer_stop (myData.pClock);
109
double fTimeElapsed = g_timer_elapsed (myData.pClock, NULL);
110
g_timer_start (myData.pClock);
111
g_return_if_fail (fTimeElapsed > 0.1 || !myData.bInitialized);
112
myData.bAcquisitionOK = FALSE;
114
#ifdef __FreeBSD__ // thanks to Max Power for the BSD port
115
struct ifaddrs *ifap, *ifa;
116
if (getifaddrs(&ifap) != 0)
118
cd_warning ("NetSpeed : getifaddrs");
121
long long int iReceivedBytes = 0, iTransmittedBytes = 0;
122
for (ifa = ifap; ifa; ifa = ifa->ifa_next) // for all interfaces
124
// check the interface
125
struct sockaddr_dl *sdl = (struct sockaddr_dl *) ifa->ifa_addr;
126
if (sdl->sdl_type != IFT_ETHER)
127
continue; // skip all non ethernet interfaces such as loopback, usb, etc...
128
if (myConfig.cInterface != NULL && strcmp (ifa->ifa_name, myConfig.cInterface) != 0) // we monitor a given interface
131
myData.bAcquisitionOK = TRUE;
132
struct if_data *data = (struct if_data*) ifa->ifa_data; // get data
135
iReceivedBytes += (long long int)data->ifi_ibytes;
136
iTransmittedBytes += (long long int)data->ifi_obytes;
140
gchar *cContent = NULL;
142
GError *erreur = NULL;
143
g_file_get_contents (NETSPEED_DATA_PIPE, &cContent, &length, &erreur);
146
cd_warning("NetSpeed : %s", erreur->message);
147
g_error_free(erreur);
151
gchar *tmp = cContent, *if_data;
152
long long int iReceivedBytes = 0, iTransmittedBytes = 0;
155
if (iNumLine > 2) // first 2 lines are the names of the fields (next lines are the various interfaces, in any order, the loopback is not always the first one).
157
while (*tmp == ' ') // drop spaces
160
// "interface : data"
161
if_data = strchr (tmp, ':');
162
if (!if_data) // shouldn't occur
166
if ((myConfig.cInterface == NULL && strcmp (tmp, "lo") != 0) // we monitor all interfaces except 'lo'
167
|| (myConfig.cInterface != NULL && strcmp (tmp, myConfig.cInterface) == 0)) // we monitor a given interface
169
myData.bAcquisitionOK = TRUE;
170
tmp = if_data + 1; // drop ':'
171
while (*tmp == ' ') // drop spaces
173
iReceivedBytes += atoll (tmp);
176
for (i = 0; i < 8; i ++) // drop 8 next values
178
while (*tmp != ' ') // drop numbers
180
while (*tmp == ' ') // drop spaces
183
iTransmittedBytes += atoll (tmp);
185
if (myConfig.cInterface != NULL) // only one interface
188
else // skip this interface
190
tmp = if_data + 1; // drop ':'
193
tmp = strchr (tmp, '\n');
194
if (tmp == NULL || *(++tmp) == '\0') // EOF
201
if (myData.bInitialized) // we already have some previous values => we can compute the speed
203
myData.iDownloadSpeed = (iReceivedBytes - myData.iReceivedBytes) / fTimeElapsed;
204
myData.iUploadSpeed = (iTransmittedBytes - myData.iTransmittedBytes) / fTimeElapsed;
206
myData.iReceivedBytes = iReceivedBytes;
207
myData.iTransmittedBytes = iTransmittedBytes;
209
if (! myData.bInitialized)
210
myData.bInitialized = TRUE;
213
gboolean cd_netspeed_update_from_data (GldiModuleInstance *myApplet)
215
static double s_fValues[CD_NETSPEED_NB_MAX_VALUES];
216
static gchar s_upRateFormatted[11];
217
static gchar s_downRateFormatted[11];
219
if ( ! myData.bAcquisitionOK)
221
if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_LABEL)
223
if (myConfig.defaultTitle) // has another default name
224
CD_APPLET_SET_NAME_FOR_MY_ICON (myConfig.defaultTitle);
226
CD_APPLET_SET_NAME_FOR_MY_ICON (myApplet->pModule->pVisitCard->cTitle);
228
else if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_ICON)
229
CD_APPLET_SET_QUICK_INFO_ON_MY_ICON ("N/A");
231
memset (s_fValues, 0, sizeof (s_fValues));
232
CD_APPLET_RENDER_NEW_DATA_ON_MY_ICON (s_fValues);
234
gldi_task_downgrade_frequency (myData.pPeriodicTask);
238
gldi_task_set_normal_frequency (myData.pPeriodicTask);
240
if (! myData.bInitialized)
242
if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_ICON)
243
CD_APPLET_SET_QUICK_INFO_ON_MY_ICON (myDock ? "..." : D_("Loading"));
244
memset (s_fValues, 0, sizeof (s_fValues));
245
CD_APPLET_RENDER_NEW_DATA_ON_MY_ICON (s_fValues);
249
if (myConfig.iInfoDisplay == CAIRO_DOCK_INFO_ON_LABEL)
251
cd_netspeed_formatRate (myData.iUploadSpeed, s_upRateFormatted, 11, myDesklet != NULL);
252
cd_netspeed_formatRate (myData.iDownloadSpeed, s_downRateFormatted, 11, myDesklet != NULL);
253
CD_APPLET_SET_NAME_FOR_MY_ICON_PRINTF ("↓%s - ↑%s", s_downRateFormatted, s_upRateFormatted);
256
if(myData.iUploadSpeed > myData.iMaxUpRate) {
257
myData.iMaxUpRate = myData.iUploadSpeed;
259
if(myData.iDownloadSpeed > myData.iMaxDownRate) {
260
myData.iMaxDownRate = myData.iDownloadSpeed;
263
double fUpValue, fDownValue;
264
if (myData.iMaxUpRate != 0)
265
fUpValue = (double) myData.iUploadSpeed / myData.iMaxUpRate;
268
if (myData.iMaxDownRate != 0)
269
fDownValue = (double) myData.iDownloadSpeed / myData.iMaxDownRate;
273
s_fValues[0] = fDownValue;
274
s_fValues[1] = fUpValue;
275
CD_APPLET_RENDER_NEW_DATA_ON_MY_ICON (s_fValues);
278
CD_APPLET_LEAVE (TRUE);