* maybe use network-idle -> network-transmit ->
* network-receive -> network-transmit-receive */
-#include <arpa/inet.h>
-
+#include <locale.h>
#include <stdlib.h>
#include <string.h>
-#include <dbus/dbus-glib.h>
-#include <gtk/gtk.h>
#include <libnotify/notify.h>
-#include "config.h"
+#include "dhcpcd-gtk.h"
#include "menu.h"
-/* Work out if we have a private address or not
- * 10/8
- * 172.16/12
- * 192.168/16
- */
-#ifndef IN_PRIVATE
-# define IN_PRIVATE(addr) (((addr & IN_CLASSA_NET) == 0x0a000000) || \
- ((addr & 0xfff00000) == 0xac100000) || \
- ((addr & IN_CLASSB_NET) == 0xc0a80000))
-#endif
-#ifndef IN_LINKLOCAL
-# define IN_LINKLOCAL(addr) ((addr & IN_CLASSB_NET) == 0xa9fe0000)
-#endif
-
-struct if_msg {
- char *name;
- char *reason;
- struct in_addr ip;
- unsigned char cidr;
- gboolean wireless;
- char *ssid;
-};
+DBusGProxy *dbus = NULL;
+GList *interfaces = NULL;
-static DBusGProxy *bus_proxy;
static GtkStatusIcon *status_icon;
-static GList *interfaces;
+static gint ani_timer;
+static int ani_counter;
static gboolean online;
static gboolean carrier;
-static NotifyNotification *nn;
-
static char **interface_order;
+static NotifyNotification *nn;
const char *const up_reasons[] = {
"BOUND",
NULL
};
-/* Should be in a header */
-void notify_close(void);
-
static gboolean
ignore_if_msg(const struct if_msg *ifm)
{
return FALSE;
}
+static struct if_msg *
+find_if_msg(const char *iface)
+{
+ GList *gl;
+ struct if_msg *ifm;
+
+ for (gl = interfaces; gl; gl = gl->next) {
+ ifm = (struct if_msg *)gl->data;
+ if (g_strcmp0(ifm->ifname, iface) == 0)
+ return ifm;
+ }
+ return NULL;
+}
+
+static void
+free_if_ap(struct if_ap *ifa)
+{
+ g_free(ifa->ifname);
+ g_free(ifa->bssid);
+ g_free(ifa->flags);
+ g_free(ifa->ssid);
+ g_free(ifa);
+}
+
static void
free_if_msg(struct if_msg *ifm)
{
- g_free(ifm->name);
+ GSList *gl;
+
+ g_free(ifm->ifname);
g_free(ifm->reason);
g_free(ifm->ssid);
+ for (gl = ifm->scan_results; gl; gl = gl->next)
+ free_if_ap((struct if_ap *)gl->data);
+ g_slist_free(ifm->scan_results);
g_free(ifm);
}
exit(EXIT_FAILURE);
}
+static GSList *
+get_scan_results(struct if_msg *ifm)
+{
+ GType otype;
+ GError *error;
+ GPtrArray *array;
+ GHashTable *config;
+ GSList *list = NULL;
+ struct if_ap *ifa;
+ guint i;
+ GValue *val;
+
+ otype = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
+ otype = dbus_g_type_get_collection("GPtrArray", otype);
+
+ if (!dbus_g_proxy_call(dbus, "ScanResults", &error,
+ G_TYPE_STRING, ifm->ifname, G_TYPE_INVALID,
+ otype, &array, G_TYPE_INVALID))
+ error_exit(_("ScanResults"), error);
+
+ for (i = 0; i < array->len; i++) {
+ config = g_ptr_array_index(array, i);
+ val = g_hash_table_lookup(config, "BSSID");
+ if (val == NULL)
+ continue;
+ ifa = g_malloc0(sizeof(*ifa));
+ ifa->ifname = g_strdup(ifm->ifname);
+ ifa->bssid = g_strdup(g_value_get_string(val));
+ val = g_hash_table_lookup(config, "Frequency");
+ if (val)
+ ifa->frequency = g_value_get_int(val);
+ val = g_hash_table_lookup(config, "Quality");
+ if (val)
+ ifa->quality = g_value_get_int(val);
+ val = g_hash_table_lookup(config, "Noise");
+ if (val)
+ ifa->noise = g_value_get_int(val);
+ val = g_hash_table_lookup(config, "Level");
+ if (val)
+ ifa->level = g_value_get_int(val);
+ val = g_hash_table_lookup(config, "Flags");
+ if (val)
+ ifa->flags = g_strdup(g_value_get_string(val));
+ val = g_hash_table_lookup(config, "SSID");
+ if (val)
+ ifa->ssid = g_strdup(g_value_get_string(val));
+ list = g_slist_append(list, ifa);
+ }
+ return list;
+}
+
static struct if_msg *
make_if_msg(GHashTable *config)
{
if (val == NULL)
return NULL;
ifm = g_malloc0(sizeof(*ifm));
- ifm->name = g_strdup(g_value_get_string(val));
+ ifm->ifname = g_strdup(g_value_get_string(val));
val = g_hash_table_lookup(config, "Reason");
if (val)
ifm->reason = g_strdup(g_value_get_string(val));
showip = TRUE;
showssid = FALSE;
if (if_up(ifm))
- reason = "Acquired address";
+ reason = N_("Acquired address");
else {
if (g_strcmp0(ifm->reason, "EXPIRE") == 0)
- reason = "Failed to renew";
+ reason = N_("Failed to renew");
else if (g_strcmp0(ifm->reason, "CARRIER") == 0) {
if (ifm->wireless) {
- reason = "Asssociated with";
+ reason = N_("Asssociated with");
if (ifm->ssid != NULL)
showssid = TRUE;
} else
- reason = "Cable plugged in";
+ reason = N_("Cable plugged in");
showip = FALSE;
} else if (g_strcmp0(ifm->reason, "NOCARRIER") == 0) {
if (ifm->wireless) {
if (ifm->ssid != NULL || ifm->ip.s_addr != 0) {
- reason = "Lost association with";
+ reason = N_("Disassociated from");
showssid = TRUE;
} else
- reason = "Not associated";
+ reason = N_("Not associated");
} else
- reason = "Cable unplugged";
+ reason = N_("Cable unplugged");
showip = FALSE;
}
}
if (reason == NULL)
reason = ifm->reason;
- len = strlen(ifm->name) + 3;
+ len = strlen(ifm->ifname) + 3;
len += strlen(reason) + 1;
if (ifm->ip.s_addr != 0) {
len += 16; /* 000. * 4 */
if (showssid)
len += strlen(ifm->ssid) + 1;
msg = p = g_malloc(len);
- p += g_snprintf(msg, len, "%s: %s", ifm->name, reason);
+ p += g_snprintf(msg, len, "%s: %s", ifm->ifname, reason);
if (showssid)
p += g_snprintf(p, len - (p - msg), " %s", ifm->ssid);
if (ifm->ip.s_addr != 0 && showip) {
ifa = (const struct if_msg *)a;
ifb = (const struct if_msg *)b;
for (order = (const char *const *)interface_order; *order; order++) {
- if (g_strcmp0(*order, ifa->name) == 0)
+ if (g_strcmp0(*order, ifa->ifname) == 0)
return -1;
- if (g_strcmp0(*order, ifb->name) == 0)
+ if (g_strcmp0(*order, ifb->ifname) == 0)
return 1;
}
return 0;
}
+static gboolean
+animate_carrier(_unused gpointer data)
+{
+ if (ani_timer == 0)
+ return FALSE;
+
+ switch(ani_counter++) {
+ case 0:
+ gtk_status_icon_set_from_icon_name(status_icon, "network-transmit");
+ break;
+ case 1:
+ gtk_status_icon_set_from_icon_name(status_icon, "network-receive");
+ break;
+ default:
+ gtk_status_icon_set_from_icon_name(status_icon, "network-idle");
+ ani_counter = 0;
+ break;
+ }
+ return TRUE;
+}
+
+static gboolean
+animate_online(_unused gpointer data)
+{
+ if (ani_timer == 0)
+ return FALSE;
+
+ if (ani_counter++ > 6) {
+ ani_timer = 0;
+ ani_counter = 0;
+ return FALSE;
+ }
+
+ if (ani_counter % 2 == 0)
+ gtk_status_icon_set_from_icon_name(status_icon, "network-idle");
+ else
+ gtk_status_icon_set_from_icon_name(status_icon, "network-transmit-receive");
+ return TRUE;
+}
+
static void
update_online(char **buffer)
{
gboolean ison, iscarrier;
char *msg, *msgs, *tmp;
- const char *icon;
const GList *gl;
const struct if_msg *ifm;
if (online != ison || carrier != iscarrier) {
online = ison;
- if (ison)
- icon = "network-transmit-receive";
- else if (iscarrier)
- icon = "network-transmit";
- else
- icon = "network-offline";
- gtk_status_icon_set_from_icon_name(status_icon, icon);
+ if (ani_timer != 0) {
+ g_source_remove(ani_timer);
+ ani_timer = 0;
+ ani_counter = 0;
+ }
+ if (ison) {
+ animate_online(NULL);
+ ani_timer = g_timeout_add(300, animate_online, NULL);
+ } else if (iscarrier) {
+ animate_carrier(NULL);
+ ani_timer = g_timeout_add(500, animate_carrier, NULL);
+ } else {
+ gtk_status_icon_set_from_icon_name(status_icon,
+ "network-offline");
+ }
}
gtk_status_icon_set_tooltip(status_icon, msgs);
if (buffer)
ifp = NULL;
for (gl = interfaces; gl; gl = gl->next) {
ifp = (struct if_msg *)gl->data;
- if (g_strcmp0(ifp->name, ifm->name) == 0) {
+ if (g_strcmp0(ifp->ifname, ifm->ifname) == 0) {
+ ifm->scan_results = ifp->scan_results;
+ ifp->scan_results = NULL;
free_if_msg(ifp);
if (rem)
interfaces = g_list_delete_link(interfaces, gl);
msg = print_if_msg(ifm);
title = NULL;
if (if_up(ifm))
- act = "Connected to ";
+ act = N_("Connected to ");
else
act = NULL;
for (r = down_reasons; *r; r++) {
if (g_strcmp0(*r, ifm->reason) == 0) {
- act = "Disconnected from ";
+ act = N_("Disconnected from ");
break;
}
}
if (act && ifm->ip.s_addr) {
ipn = htonl(ifm->ip.s_addr);
if (IN_LINKLOCAL(ipn))
- net = "private network";
+ net = N_("private network");
else if (IN_PRIVATE(ipn))
- net = "LAN";
+ net = N_("LAN");
else
- net = "internet";
+ net = N_("internet");
title = g_strconcat(act, net, NULL);
}
notify(title, msg, GTK_STOCK_NETWORK);
g_free(title);
} else
- notify("Interface event", msg, GTK_STOCK_NETWORK);
+ notify(N_("Interface event"), msg, GTK_STOCK_NETWORK);
g_free(msg);
}
GError *error = NULL;
GType otype;
char *msg;
+ GList *gl;
+ GSList *gsl;
+ GPtrArray *array;
+ struct if_msg *ifm;
otype = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
otype = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, otype);
- if (!dbus_g_proxy_call(bus_proxy, "GetInterfaces", &error,
+ if (!dbus_g_proxy_call(dbus, "GetInterfaces", &error,
G_TYPE_INVALID,
otype, &ifs, G_TYPE_INVALID))
error_exit("GetInterfaces", error);
* that interface was configured, so get the real order now. */
g_strfreev(interface_order);
interface_order = NULL;
- if (!dbus_g_proxy_call(bus_proxy, "ListInterfaces", &error,
+ if (!dbus_g_proxy_call(dbus, "ListInterfaces", &error,
G_TYPE_INVALID,
G_TYPE_STRV, &interface_order, G_TYPE_INVALID))
error_exit("ListInterfaces", error);
interfaces = g_list_sort(interfaces, if_msg_comparer);
+
+ otype = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
+ otype = dbus_g_type_get_collection("GPtrArray", otype);
+ for (gl = interfaces; gl; gl = gl->next) {
+ ifm = (struct if_msg *)gl->data;
+ if (!ifm->wireless)
+ continue;
+ if (!dbus_g_proxy_call(dbus, "ScanResults", &error,
+ G_TYPE_STRING, ifm->ifname, G_TYPE_INVALID,
+ otype, &array, G_TYPE_INVALID))
+ {
+ g_message("ScanResults: %s", error->message);
+ g_clear_error(&error);
+ continue;
+ }
+ for (gsl = ifm->scan_results; gsl; gsl = gsl->next)
+ g_free(gsl->data);
+ g_slist_free(ifm->scan_results);
+ ifm->scan_results = get_scan_results(ifm);
+ }
+
msg = NULL;
update_online(&msg);
// GTK+ 2.16 msg = gtk_status_icon_get_tooltip_text(status_icon);
if (msg != NULL) {
- notify("Interface status", msg, GTK_STOCK_NETWORK);
+ notify(N_("Interface status"), msg, GTK_STOCK_NETWORK);
g_free(msg);
}
}
gboolean refresh;
GError *error = NULL;
- g_message("status changed to %s", status);
+ g_message("Status changed to %s", status);
if (g_strcmp0(status, "down") == 0) {
for (gl = interfaces; gl; gl = gl->next)
free_if_msg((struct if_msg *)gl->data);
g_list_free(interfaces);
interfaces = NULL;
update_online(NULL);
- msg = last? "Connection to dhcpcd lost" : "dhcpcd not running";
+ msg = N_(last? "Connection to dhcpcd lost" : "dhcpcd not running");
gtk_status_icon_set_tooltip(status_icon, msg);
- notify("No network", msg, GTK_STOCK_NETWORK);
+ notify(_("No network"), msg, GTK_STOCK_NETWORK);
}
refresh = FALSE;
if (!refresh)
return;
- if (!dbus_g_proxy_call(bus_proxy, "GetDhcpcdVersion", &error,
+ if (!dbus_g_proxy_call(dbus, "GetDhcpcdVersion", &error,
G_TYPE_INVALID,
G_TYPE_STRING, &version, G_TYPE_INVALID))
- error_exit("GetDhcpcdVersion", error);
- g_message("Connected to dhcpcd-%s", version);
+ error_exit(_("GetDhcpcdVersion"), error);
+ g_message(_("Connected to %s-%s"), "dhcpcd", version);
g_free(version);
dhcpcd_get_interfaces();
}
check_status(status);
}
+static void
+dhcpcd_scan_results(_unused DBusGProxy *proxy, const char *iface, _unused void *data)
+{
+ struct if_msg *ifm;
+ struct if_ap *ifa, *ifa2;
+ GSList *gl, *aps, *l;
+ char *txt, *ntxt;
+
+ ifm = find_if_msg(iface);
+ if (ifm == NULL)
+ return;
+ g_message(_("%s: Received scan results"), ifm->ifname);
+ aps = get_scan_results(ifm);
+ txt = NULL;
+ for (gl = aps; gl; gl = gl->next) {
+ ifa = (struct if_ap *)gl->data;
+ for (l = ifm->scan_results; l; l = l->next) {
+ ifa2 = (struct if_ap *)l->data;
+ if (g_strcmp0(ifa->ssid, ifa2->ssid) == 0)
+ break;
+ }
+ if (l == NULL) {
+ if (txt == NULL)
+ txt = g_strdup(ifa->ssid);
+ else {
+ ntxt = g_strconcat(txt, "\n", ifa->ssid, NULL);
+ g_free(txt);
+ txt = ntxt;
+ }
+ }
+ }
+ for (gl = ifm->scan_results; gl; gl = gl->next)
+ free_if_ap((struct if_ap *)gl->data);
+ g_slist_free(ifm->scan_results);
+ ifm->scan_results = aps;
+ if (txt != NULL) {
+ notify(N_("Found new AP"), txt, GTK_STOCK_NETWORK);
+ g_free(txt);
+ }
+}
+
int
main(int argc, char *argv[])
{
char *version = NULL;
GType otype;
int tries = 5;
-
+
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, NULL);
+ bind_textdomain_codeset(PACKAGE, "UTF-8");
+ textdomain(PACKAGE);
+
gtk_init(&argc, &argv);
g_set_application_name("dhcpcd Monitor");
status_icon = gtk_status_icon_new_from_icon_name("network-offline");
if (status_icon == NULL)
status_icon = gtk_status_icon_new_from_stock(GTK_STOCK_DISCONNECT);
+ //network_offline = gtk_status_icon_get_pixbuf(status_icon);
- gtk_status_icon_set_tooltip(status_icon, "Connecting to dhcpcd ...");
+ gtk_status_icon_set_tooltip(status_icon, _("Connecting to dhcpcd ..."));
gtk_status_icon_set_visible(status_icon, TRUE);
notify_init(PACKAGE);
- g_message("connecting to dbus ...");
+ g_message(_("Connecting to dbus ..."));
bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
if (bus == NULL || error != NULL)
- error_exit("could not connect to system bus", error);
- bus_proxy = dbus_g_proxy_new_for_name(bus,
+ error_exit(_("Could not connect to system bus"), error);
+ dbus = dbus_g_proxy_new_for_name(bus,
DHCPCD_SERVICE,
DHCPCD_PATH,
DHCPCD_SERVICE);
- g_message("connecting to dhcpcd-dbus ...");
+ g_message(_("Connecting to dhcpcd-dbus ..."));
while (--tries > 0) {
- if (dbus_g_proxy_call_with_timeout(bus_proxy,
+ g_clear_error(&error);
+ if (dbus_g_proxy_call_with_timeout(dbus,
"GetVersion",
500,
&error,
break;
}
if (tries == 0)
- error_exit("GetVersion", error);
- g_message("Connected to dhcpcd-dbus-%s", version);
+ error_exit(_("GetVersion"), error);
+ g_message(_("Connected to %s-%s"), "dhcpcd-dbus", version);
g_free(version);
- gtk_status_icon_set_tooltip(status_icon, "Triggering dhcpcd ...");
+ gtk_status_icon_set_tooltip(status_icon, _("Triggering dhcpcd ..."));
online = FALSE;
menu_init(status_icon);
- if (!dbus_g_proxy_call(bus_proxy, "GetStatus", &error,
+ if (!dbus_g_proxy_call(dbus, "GetStatus", &error,
G_TYPE_INVALID,
G_TYPE_STRING, &version, G_TYPE_INVALID))
- error_exit("GetStatus", error);
+ error_exit(_("GetStatus"), error);
check_status(version);
g_free(version);
otype = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
- dbus_g_proxy_add_signal(bus_proxy, "Event",
+ dbus_g_proxy_add_signal(dbus, "Event",
otype, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(bus_proxy, "Event",
+ dbus_g_proxy_connect_signal(dbus, "Event",
G_CALLBACK(dhcpcd_event),
- NULL, NULL);
- dbus_g_proxy_add_signal(bus_proxy, "StatusChanged",
+ bus, NULL);
+ dbus_g_proxy_add_signal(dbus, "StatusChanged",
G_TYPE_STRING, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(bus_proxy, "StatusChanged",
+ dbus_g_proxy_connect_signal(dbus, "StatusChanged",
G_CALLBACK(dhcpcd_status),
- NULL, NULL);
+ bus, NULL);
+ dbus_g_proxy_add_signal(dbus, "ScanResults",
+ G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(dbus, "ScanResults",
+ G_CALLBACK(dhcpcd_scan_results),
+ bus, NULL);
gtk_main();
return 0;