NetworkManager r3491 - in trunk: . dispatcher-daemon include libnm-glib test



Author: dcbw
Date: Mon Mar 24 15:17:30 2008
New Revision: 3491
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3491&view=rev

Log:
2008-03-24  Dan Williams  <dcbw redhat com>

	Massive fixup of libnm-glib to:
	a) have all objects (with the exception of VPN) cache their properties and
		update them asynchronously on PropertiesChanged signals from NM
	b) return internal const data for most attributes/properties instead of
		allocated values that the caller must free
	c) cache wrapped objects such that a given D-Bus path will always map to the
		same GObject returned by libnm-glib
	d) remove a few signals and move them to GObject property notifications
	e) match recent NM D-Bus API changes for activation/deactivation
	f) remove some private functions from libnm-glib headers



Added:
   trunk/include/nm-dbus-glib-types.h
   trunk/libnm-glib/nm-active-connection.c
   trunk/libnm-glib/nm-active-connection.h
   trunk/libnm-glib/nm-object-cache.c
   trunk/libnm-glib/nm-object-cache.h
   trunk/libnm-glib/nm-object-private.h
   trunk/libnm-glib/nm-types-private.h
   trunk/libnm-glib/nm-types.c
   trunk/libnm-glib/nm-types.h
Modified:
   trunk/ChangeLog
   trunk/dispatcher-daemon/NetworkManagerDispatcher.c
   trunk/include/Makefile.am
   trunk/libnm-glib/Makefile.am
   trunk/libnm-glib/libnm-glib-test.c
   trunk/libnm-glib/nm-access-point.c
   trunk/libnm-glib/nm-access-point.h
   trunk/libnm-glib/nm-cdma-device.c
   trunk/libnm-glib/nm-cdma-device.h
   trunk/libnm-glib/nm-client.c
   trunk/libnm-glib/nm-client.h
   trunk/libnm-glib/nm-device-802-11-wireless.c
   trunk/libnm-glib/nm-device-802-11-wireless.h
   trunk/libnm-glib/nm-device-802-3-ethernet.c
   trunk/libnm-glib/nm-device-802-3-ethernet.h
   trunk/libnm-glib/nm-device.c
   trunk/libnm-glib/nm-device.h
   trunk/libnm-glib/nm-gsm-device.c
   trunk/libnm-glib/nm-ip4-config.c
   trunk/libnm-glib/nm-ip4-config.h
   trunk/libnm-glib/nm-object.c
   trunk/libnm-glib/nm-object.h
   trunk/libnm-glib/nm-settings.c
   trunk/libnm-glib/nm-vpn-connection.c
   trunk/libnm-glib/nm-vpn-manager.c
   trunk/libnm-glib/nm-vpn-plugin.c
   trunk/test/nm-tool.c

Modified: trunk/dispatcher-daemon/NetworkManagerDispatcher.c
==============================================================================
--- trunk/dispatcher-daemon/NetworkManagerDispatcher.c	(original)
+++ trunk/dispatcher-daemon/NetworkManagerDispatcher.c	Mon Mar 24 15:17:30 2008
@@ -20,6 +20,7 @@
  */
 
 #include <glib.h>
+#include <glib-object.h>
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib-lowlevel.h>
 #include <dbus/dbus-glib.h>
@@ -80,7 +81,7 @@
  *
  */
 static void
-nmd_execute_scripts (NMDeviceState state, char *iface_name)
+nmd_execute_scripts (NMDeviceState state, const char *iface_name)
 {
 	GDir *		dir;
 	const char *	file_name;
@@ -128,15 +129,13 @@
 }
 
 static void
-device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data)
+device_state_changed (NMDevice *device, GParamSpec *pspec, gpointer user_data)
 {
-	if (state == NM_DEVICE_STATE_ACTIVATED || state == NM_DEVICE_STATE_DISCONNECTED) {
-		char *iface;
+	NMDeviceState state;
 
-		iface = nm_device_get_iface (device);
-		nmd_execute_scripts (state, iface);
-		g_free (iface);
-	}
+	state = nm_device_get_state (device);
+	if (state == NM_DEVICE_STATE_ACTIVATED || state == NM_DEVICE_STATE_DISCONNECTED)
+		nmd_execute_scripts (state, nm_device_get_iface (device));
 }
 
 static void
@@ -145,7 +144,7 @@
 	guint id;
 
 	if (!g_hash_table_lookup (device_signals_hash, device)) {
-		id = g_signal_connect (device, "state-changed",
+		id = g_signal_connect (device, "notify::state",
 							   G_CALLBACK (device_state_changed),
 							   NULL);
 
@@ -168,14 +167,12 @@
 static void
 add_existing_device_listeners (NMClient *client)
 {
-	GSList *list, *iter;
-
-	list = nm_client_get_devices (client);
-	for (iter = list; iter; iter = iter->next)
-		device_add_listener (client, NM_DEVICE (iter->data), NULL);
+	const GPtrArray *devices;
+	int i;
 
-	g_slist_foreach (list, (GFunc) g_object_unref, NULL);
-	g_slist_free (list);
+	devices = nm_client_get_devices (client);
+	for (i = 0; devices && (i < devices->len); i++)
+		device_add_listener (client, g_ptr_array_index (devices, i), NULL);
 }
 
 static void

Modified: trunk/include/Makefile.am
==============================================================================
--- trunk/include/Makefile.am	(original)
+++ trunk/include/Makefile.am	Mon Mar 24 15:17:30 2008
@@ -1,11 +1,12 @@
 EXTRA_DIST = \
      NetworkManager.h \
      NetworkManagerVPN.h \
-     wireless-helper.h
+     wireless-helper.h \
+     nm-dbus-glib-types.h
 
 NetworkManagerincludedir=$(includedir)/NetworkManager
 
 NetworkManagerinclude_HEADERS = \
 	NetworkManager.h \
 	NetworkManagerVPN.h
-	
+

Added: trunk/include/nm-dbus-glib-types.h
==============================================================================
--- (empty file)
+++ trunk/include/nm-dbus-glib-types.h	Mon Mar 24 15:17:30 2008
@@ -0,0 +1,37 @@
+/* NetworkManager -- Network link manager
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef DBUS_GLIB_TYPES_H
+#define DBUS_GLIB_TYPES_H
+
+#include <dbus/dbus-glib.h>
+
+#define DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH   (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH))
+#define DBUS_TYPE_G_ARRAY_OF_STRING        (dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING))
+#define DBUS_TYPE_G_ARRAY_OF_UINT          (dbus_g_type_get_collection ("GArray", G_TYPE_UINT))
+#define DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_ARRAY_OF_UINT))
+#define DBUS_TYPE_G_MAP_OF_VARIANT         (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
+#define DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT  (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT))
+#define DBUS_TYPE_G_MAP_OF_STRING          (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
+#define DBUS_TYPE_G_LIST_OF_STRING         (dbus_g_type_get_collection ("GSList", G_TYPE_STRING))
+
+#endif /* DBUS_GLIB_TYPES_H */
+

Modified: trunk/libnm-glib/Makefile.am
==============================================================================
--- trunk/libnm-glib/Makefile.am	(original)
+++ trunk/libnm-glib/Makefile.am	Mon Mar 24 15:17:30 2008
@@ -12,7 +12,8 @@
 	nm-settings-glue.h \
 	nm-vpn-manager-bindings.h \
 	nm-vpn-connection-bindings.h \
-	nm-vpn-plugin-glue.h
+	nm-vpn-plugin-glue.h \
+	nm-active-connection-bindings.h
 
 lib_LTLIBRARIES = libnm_glib.la libnm_glib_vpn.la
 
@@ -39,11 +40,14 @@
 	nm-cdma-device.h \
 	nm-vpn-connection.h \
 	nm-vpn-manager.h \
-	nm-vpn-plugin.h
+	nm-vpn-plugin.h \
+	nm-types.h \
+	nm-active-connection.h
 
 libnm_glib_la_SOURCES = \
 	libnm_glib.c		\
 	nm-object.c		\
+	nm-object-private.h \
 	nm-client.c		\
 	nm-dbus-utils.c		\
 	nm-dbus-utils.h		\
@@ -58,7 +62,12 @@
 	nm-cdma-device.c	\
 	nm-vpn-connection.c	\
 	nm-vpn-manager.c	\
-	nm-marshal-main.c
+	nm-marshal-main.c \
+	nm-types.c \
+	nm-types-private.h \
+	nm-object-cache.c \
+	nm-object-cache.h \
+	nm-active-connection.c
 
 libnm_glib_la_LIBADD = \
 	$(top_builddir)/libnm-util/libnm-util.la	\
@@ -123,6 +132,9 @@
 nm-vpn-plugin-glue.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml
 	dbus-binding-tool --prefix=nm_vpn_plugin --mode=glib-server --output=nm-vpn-plugin-glue.h $(top_srcdir)/introspection/nm-vpn-plugin.xml
 
+nm-active-connection-bindings.h: $(top_srcdir)/introspection/nm-active-connection.xml
+	dbus-binding-tool --prefix=nm_active_connection --mode=glib-client --output=nm-active-connection-bindings.h $(top_srcdir)/introspection/nm-active-connection.xml
+
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libnm_glib.pc
 

Modified: trunk/libnm-glib/libnm-glib-test.c
==============================================================================
--- trunk/libnm-glib/libnm-glib-test.c	(original)
+++ trunk/libnm-glib/libnm-glib-test.c	Mon Mar 24 15:17:30 2008
@@ -1,4 +1,5 @@
 #include <stdlib.h>
+#include <signal.h>
 
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -11,8 +12,8 @@
 #include "nm-device-802-3-ethernet.h"
 #include "nm-device-802-11-wireless.h"
 #include "nm-utils.h"
+#include "nm-active-connection.h"
 
-#if 0
 static gboolean
 test_wireless_enabled (NMClient *client)
 {
@@ -21,16 +22,15 @@
 	wireless = nm_client_wireless_get_enabled (client);
 	g_print ("Wireless enabled? %s\n", wireless ? "yes" : "no");
 
-	nm_client_wireless_set_enabled (client, !wireless);
+//	nm_client_wireless_set_enabled (client, !wireless);
 
-	wireless = nm_client_wireless_get_enabled (client);
-	g_print ("Wireless enabled? %s\n", wireless ? "yes" : "no");
+	wireless = nm_client_wireless_hardware_get_enabled (client);
+	g_print ("Wireless HW enabled? %s\n", wireless ? "yes" : "no");
 
-	nm_client_wireless_set_enabled (client, !wireless);
+//	nm_client_wireless_set_enabled (client, !wireless);
 
 	return TRUE;
 }
-#endif
 
 static gboolean
 test_get_state (NMClient *client)
@@ -59,8 +59,8 @@
 dump_ip4_config (NMIP4Config *cfg)
 {
 	char *tmp;
-	GArray *array;
-	char **ptr_array;
+	const GArray *array;
+	const GPtrArray *ptr_array;
 	int i;
 
 	tmp = ip4_address_as_string (nm_ip4_config_get_address (cfg));
@@ -79,9 +79,7 @@
 	g_print ("IP4 broadcast: %s\n", tmp);
 	g_free (tmp);
 
-	tmp = nm_ip4_config_get_hostname (cfg);
-	g_print ("IP4 hostname: %s\n", tmp);
-	g_free (tmp);
+	g_print ("IP4 hostname: %s\n", nm_ip4_config_get_hostname (cfg));
 
 	array = nm_ip4_config_get_nameservers (cfg);
 	if (array) {
@@ -91,23 +89,16 @@
 			g_print ("\t%s\n", tmp);
 			g_free (tmp);
 		}
-
-		g_array_free (array, TRUE);
 	}
 
 	ptr_array = nm_ip4_config_get_domains (cfg);
 	if (ptr_array) {
 		g_print ("IP4 domains:\n");
-		for (i = 0; ptr_array[i]; i++) {
-			g_print ("\t%s\n", ptr_array[i]);
-		}
-
-		g_strfreev (ptr_array);
+		for (i = 0; i < ptr_array->len; i++)
+			g_print ("\t%s\n", (const char *) g_ptr_array_index (ptr_array, i));
 	}
 
-	tmp = nm_ip4_config_get_nis_domain (cfg);
-	g_print ("IP4 NIS domain: %s\n", tmp);
-	g_free (tmp);
+	g_print ("IP4 NIS domain: %s\n", nm_ip4_config_get_nis_domain (cfg));
 
 	array = nm_ip4_config_get_nis_servers (cfg);
 	if (array) {
@@ -117,8 +108,6 @@
 			g_print ("\t%s\n", tmp);
 			g_free (tmp);
 		}
-
-		g_array_free (array, TRUE);
 	}
 }
 
@@ -149,8 +138,8 @@
 dump_wireless (NMDevice80211Wireless *device)
 {
 	const char *str;
-	GSList *iter;
-	GSList *aps;
+	GPtrArray *aps;
+	int i;
 
 	g_print ("Mode: %d\n", nm_device_802_11_wireless_get_mode (device));
 	g_print ("Bitrate: %d\n", nm_device_802_11_wireless_get_bitrate (device));
@@ -160,13 +149,10 @@
 
 	g_print ("AccessPoints:\n");
 	aps = nm_device_802_11_wireless_get_access_points (device);
-	for (iter = aps; iter; iter = iter->next) {
-		dump_access_point (NM_ACCESS_POINT (iter->data));
+	for (i = 0; i < aps->len; i++) {
+		dump_access_point (NM_ACCESS_POINT (g_ptr_array_index (aps, i)));
 		g_print ("\n");
 	}
-
-	g_slist_foreach (aps, (GFunc) g_object_unref, NULL);
-	g_slist_free (aps);
 }
 
 static void
@@ -183,33 +169,29 @@
 static void
 dump_device (NMDevice *device)
 {
-	char *str;
-	guint32 u;
+	const char *str;
 	NMDeviceState state;
 
 	str = nm_device_get_iface (device);
 	g_print ("Interface: %s\n", str);
-	g_free (str);
 
 	str = nm_device_get_udi (device);
 	g_print ("Udi: %s\n", str);
-	g_free (str);
 
 	str = nm_device_get_driver (device);
 	g_print ("Driver: %s\n", str);
-	g_free (str);
 
-	u = nm_device_get_ip4_address (device);
-	g_print ("IP address: %d\n", u);
+	str = nm_device_get_vendor (device);
+	g_print ("Vendor: %s\n", str);
+
+	str = nm_device_get_product (device);
+	g_print ("Product: %s\n", str);
 
 	state = nm_device_get_state (device);
 	g_print ("State: %d\n", state);
 
-	if (state == NM_DEVICE_STATE_ACTIVATED) {
-		NMIP4Config *cfg = nm_device_get_ip4_config (device);
-		dump_ip4_config (cfg);
-		g_object_unref (cfg);
-	}
+	if (state == NM_DEVICE_STATE_ACTIVATED)
+		dump_ip4_config (nm_device_get_ip4_config (device));
 
 	if (NM_IS_DEVICE_802_3_ETHERNET (device))
 		dump_wired (NM_DEVICE_802_3_ETHERNET (device));
@@ -220,76 +202,132 @@
 static gboolean
 test_devices (NMClient *client)
 {
-	GSList *list, *iter;
+	GPtrArray *devices;
+	int i;
 
-	list = nm_client_get_devices (client);
+	devices = nm_client_get_devices (client);
 	g_print ("Got devices:\n");
-	for (iter = list; iter; iter = iter->next) {
-		NMDevice *device = NM_DEVICE (iter->data);
+	if (!devices) {
+		g_print ("  NONE\n");
+		return TRUE;
+	}
+
+	for (i = 0; i < devices->len; i++) {
+		NMDevice *device = g_ptr_array_index (devices, i);
 		dump_device (device);
 		g_print ("\n");
 	}
 
-	g_slist_free (list);
-
 	return TRUE;
 }
 
 static void
-device_added_cb (NMClient *client, NMDevice *device, gpointer user_data)
+active_connections_changed (NMClient *client, GParamSpec *pspec, gpointer user_data)
 {
-	g_print ("New device added\n");
-	dump_device (device);
+	const GPtrArray *connections;
+	int i, j;
+
+	g_print ("Active connections changed:\n");
+	connections = nm_client_get_active_connections (client);
+	for (i = 0; i < connections->len; i++) {
+		NMActiveConnection *connection;
+		const GPtrArray *devices;
+
+		connection = g_ptr_array_index (connections, i);
+		g_print ("    %s\n", nm_object_get_path (NM_OBJECT (connection)));
+		devices = nm_active_connection_get_devices (connection);
+		for (j = 0; j < devices->len; j++)
+			g_print ("           %s\n", nm_device_get_udi (g_ptr_array_index (devices, j)));
+	}
 }
 
 static void
-device_removed_cb (NMClient *client, NMDevice *device, gpointer user_data)
+show_active_connection_device (gpointer data, gpointer user_data)
 {
-	g_print ("Device removed\n");
-	dump_device (device);
+	NMDevice *device = NM_DEVICE (data);
+
+	g_print ("           %s\n", nm_device_get_udi (device));
 }
 
-#if 0
-static gboolean
-device_deactivate (gpointer user_data)
+static void
+test_get_active_connections (NMClient *client)
 {
-	NMDevice *device = NM_DEVICE (user_data);
-
-	nm_device_deactivate (device);
+	const GPtrArray *connections;
+	int i;
 
-	return FALSE;
+	g_print ("Active connections:\n");
+	connections = nm_client_get_active_connections (client);
+	for (i = 0; i < connections->len; i++) {
+		const GPtrArray *devices;
+
+		g_print ("    %s\n", nm_object_get_path (g_ptr_array_index (connections, i)));
+		devices = nm_active_connection_get_devices (g_ptr_array_index (connections, i));
+		g_ptr_array_foreach ((GPtrArray *) devices, show_active_connection_device, NULL);
+	}
 }
 
 static void
-device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data)
+device_state_changed (NMDevice *device, GParamSpec *pspec, gpointer user_data)
 {
-	char *str;
+	g_print ("Device state changed: %s %d\n",
+	         nm_device_get_iface (device),
+	         nm_device_get_state (device));
+}
 
-	str = nm_device_get_iface (device);
-	g_print ("Device state changed: %s %d\n", str, state);
-	g_free (str);
+static void
+device_added_cb (NMClient *client, NMDevice *device, gpointer user_data)
+{
+	g_print ("New device added\n");
+	dump_device (device);
+	g_signal_connect (G_OBJECT (device), "notify::state",
+	                  (GCallback) device_state_changed, NULL);
+}
 
-	if (state == NM_DEVICE_STATE_ACTIVATED) {
-		g_print ("Scheduling device deactivation\n");
-		g_timeout_add (5 * 1000,
-					   device_deactivate,
-					   device);
-	}
+static void
+device_removed_cb (NMClient *client, NMDevice *device, gpointer user_data)
+{
+	g_print ("Device removed\n");
+	dump_device (device);
 }
-#endif
 
 static void
-manager_running (NMClient *client, gboolean running, gpointer user_data)
+manager_running (NMClient *client, GParamSpec *pspec, gpointer user_data)
 {
-	if (running) {
+	if (nm_client_get_manager_running (client)) {
 		g_print ("NM appeared\n");
-		/* 	test_wireless_enabled (client); */
+		test_wireless_enabled (client);
 		test_get_state (client);
+		test_get_active_connections (client);
 		test_devices (client);
 	} else
 		g_print ("NM disappeared\n");
 }
 
+static GMainLoop *loop = NULL;
+
+static void
+signal_handler (int signo)
+{
+	if (signo == SIGINT || signo == SIGTERM) {
+		g_message ("Caught signal %d, shutting down...", signo);
+		g_main_loop_quit (loop);
+	}
+}
+
+static void
+setup_signals (void)
+{
+	struct sigaction action;
+	sigset_t mask;
+
+	sigemptyset (&mask);
+	action.sa_handler = signal_handler;
+	action.sa_mask = mask;
+	action.sa_flags = 0;
+	sigaction (SIGTERM,  &action, NULL);
+	sigaction (SIGINT,  &action, NULL);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -302,15 +340,20 @@
 		exit (1);
 	}
 
-	g_signal_connect (client, "manager-running", G_CALLBACK (manager_running), NULL);
-	manager_running (client, nm_client_manager_is_running (client), NULL);
+	g_signal_connect (client, "notify::" NM_CLIENT_MANAGER_RUNNING,
+	                  G_CALLBACK (manager_running), NULL);
+	g_signal_connect (client, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
+	                  G_CALLBACK (active_connections_changed), NULL);
+	manager_running (client, NULL, NULL);
 
 	g_signal_connect (client, "device-added",
 					  G_CALLBACK (device_added_cb), NULL);
 	g_signal_connect (client, "device-removed",
 					  G_CALLBACK (device_removed_cb), NULL);
 
-	g_main_loop_run (g_main_loop_new (NULL, FALSE));
+	loop = g_main_loop_new (NULL, FALSE);
+	setup_signals ();
+	g_main_loop_run (loop);
 
 	g_object_unref (client);
 

Modified: trunk/libnm-glib/nm-access-point.c
==============================================================================
--- trunk/libnm-glib/nm-access-point.c	(original)
+++ trunk/libnm-glib/nm-access-point.c	Mon Mar 24 15:17:30 2008
@@ -6,6 +6,8 @@
 
 #include "nm-access-point.h"
 #include "NetworkManager.h"
+#include "nm-types-private.h"
+#include "nm-object-private.h"
 
 #include "nm-access-point-bindings.h"
 
@@ -15,7 +17,8 @@
 
 typedef struct {
 	gboolean disposed;
-	DBusGProxy *ap_proxy;
+	DBusGProxy *proxy;
+
 	guint32 flags;
 	guint32 wpa_flags;
 	guint32 rsn_flags;
@@ -24,7 +27,7 @@
 	char *hw_address;
 	int mode;
 	guint32 max_bitrate;
-	gint8 strength;
+	guint8 strength;
 } NMAccessPointPrivate;
 
 enum {
@@ -52,22 +55,16 @@
 #define DBUS_PROP_MAX_BITRATE "MaxBitrate"
 #define DBUS_PROP_STRENGTH "Strength"
 
-NMAccessPoint *
+GObject *
 nm_access_point_new (DBusGConnection *connection, const char *path)
 {
-	return (NMAccessPoint *) g_object_new (NM_TYPE_ACCESS_POINT,
-								    NM_OBJECT_CONNECTION, connection,
-								    NM_OBJECT_PATH, path,
-								    NULL);
-}
-
-static void
-nm_access_point_set_flags (NMAccessPoint *ap, guint32 flags)
-{
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
 
-	priv->flags = flags;
-	g_object_notify (G_OBJECT (ap), NM_ACCESS_POINT_FLAGS);
+	return (GObject *) g_object_new (NM_TYPE_ACCESS_POINT,
+								    NM_OBJECT_DBUS_CONNECTION, connection,
+								    NM_OBJECT_DBUS_PATH, path,
+								    NULL);
 }
 
 guint32
@@ -87,15 +84,6 @@
 	return priv->flags;
 }
 
-static void
-nm_access_point_set_wpa_flags (NMAccessPoint *ap, guint32 flags)
-{
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-
-	priv->wpa_flags = flags;
-	g_object_notify (G_OBJECT (ap), NM_ACCESS_POINT_WPA_FLAGS);
-}
-
 guint32
 nm_access_point_get_wpa_flags (NMAccessPoint *ap)
 {
@@ -113,15 +101,6 @@
 	return priv->wpa_flags;
 }
 
-static void
-nm_access_point_set_rsn_flags (NMAccessPoint *ap, guint32 flags)
-{
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-
-	priv->rsn_flags = flags;
-	g_object_notify (G_OBJECT (ap), NM_ACCESS_POINT_RSN_FLAGS);
-}
-
 guint32
 nm_access_point_get_rsn_flags (NMAccessPoint *ap)
 {
@@ -139,25 +118,6 @@
 	return priv->rsn_flags;
 }
 
-static void
-nm_access_point_set_ssid (NMAccessPoint *ap, GArray *ssid)
-{
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-
-	if (priv->ssid) {
-		g_byte_array_free (priv->ssid, TRUE);
-		priv->ssid = NULL;
-	}
-
-	if (ssid && ssid->len > 0) {
-		priv->ssid = g_byte_array_sized_new (ssid->len);
-		priv->ssid->len = ssid->len;
-		memcpy (priv->ssid->data, ssid->data, ssid->len);
-	}
-
-	g_object_notify (G_OBJECT (ap), NM_ACCESS_POINT_SSID);
-}
-
 const GByteArray *
 nm_access_point_get_ssid (NMAccessPoint *ap)
 {
@@ -175,15 +135,6 @@
 	return priv->ssid;
 }
 
-static void
-nm_access_point_set_frequency (NMAccessPoint *ap, guint32 frequency)
-{
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-
-	priv->frequency = frequency;
-	g_object_notify (G_OBJECT (ap), NM_ACCESS_POINT_FREQUENCY);
-}
-
 guint32
 nm_access_point_get_frequency (NMAccessPoint *ap)
 {
@@ -201,16 +152,6 @@
 	return priv->frequency;
 }
 
-static void
-nm_access_point_set_hw_address (NMAccessPoint *ap, const char *address)
-{
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-
-	g_free (priv->hw_address);
-	priv->hw_address = address ? g_strdup (address) : NULL;
-	g_object_notify (G_OBJECT (ap), NM_ACCESS_POINT_HW_ADDRESS);
-}
-
 const char *
 nm_access_point_get_hw_address (NMAccessPoint *ap)
 {
@@ -228,15 +169,6 @@
 	return priv->hw_address;
 }
 
-static void
-nm_access_point_set_mode (NMAccessPoint *ap, int mode)
-{
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-
-	priv->mode = mode;
-	g_object_notify (G_OBJECT (ap), NM_ACCESS_POINT_MODE);
-}
-
 int
 nm_access_point_get_mode (NMAccessPoint *ap)
 {
@@ -254,15 +186,6 @@
 	return priv->mode;
 }
 
-static void
-nm_access_point_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate)
-{
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-
-	priv->max_bitrate = bitrate;
-	g_object_notify (G_OBJECT (ap), NM_ACCESS_POINT_MAX_BITRATE);
-}
-
 guint32
 nm_access_point_get_max_bitrate (NMAccessPoint *ap)
 {
@@ -280,16 +203,7 @@
 	return priv->max_bitrate;
 }
 
-static void
-nm_access_point_set_strength (NMAccessPoint *ap, gint8 strength)
-{
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
-
-	priv->strength = strength;
-	g_object_notify (G_OBJECT (ap), NM_ACCESS_POINT_STRENGTH);
-}
-
-gint8
+guint8
 nm_access_point_get_strength (NMAccessPoint *ap)
 {
 	NMAccessPointPrivate *priv;
@@ -325,7 +239,7 @@
 
 	priv->disposed = TRUE;
 
-	g_object_unref (priv->ap_proxy);
+	g_object_unref (priv->proxy);
 
 	G_OBJECT_CLASS (nm_access_point_parent_class)->dispose (object);
 }
@@ -345,38 +259,40 @@
 }
 
 static void
-set_property (GObject *object, guint prop_id,
-		    const GValue *value, GParamSpec *pspec)
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
 {
 	NMAccessPoint *ap = NM_ACCESS_POINT (object);
 
 	switch (prop_id) {
 	case PROP_FLAGS:
-		nm_access_point_set_flags (ap, g_value_get_uint (value));
+		g_value_set_uint (value, nm_access_point_get_flags (ap));
 		break;
 	case PROP_WPA_FLAGS:
-		nm_access_point_set_wpa_flags (ap, g_value_get_uint (value));
+		g_value_set_uint (value, nm_access_point_get_wpa_flags (ap));
 		break;
 	case PROP_RSN_FLAGS:
-		nm_access_point_set_rsn_flags (ap, g_value_get_uint (value));
+		g_value_set_uint (value, nm_access_point_get_rsn_flags (ap));
 		break;
 	case PROP_SSID:
-		nm_access_point_set_ssid (ap, (GArray *) g_value_get_boxed (value));
+		g_value_set_boxed (value, nm_access_point_get_ssid (ap));
 		break;
 	case PROP_FREQUENCY:
-		nm_access_point_set_frequency (ap, g_value_get_uint (value));
+		g_value_set_uint (value, nm_access_point_get_frequency (ap));
 		break;
 	case PROP_HW_ADDRESS:
-		nm_access_point_set_hw_address (ap, g_value_get_string (value));
+		g_value_set_string (value, nm_access_point_get_hw_address (ap));
 		break;
 	case PROP_MODE:
-		nm_access_point_set_mode (ap, g_value_get_int (value));
+		g_value_set_int (value, nm_access_point_get_mode (ap));
 		break;
 	case PROP_MAX_BITRATE:
-		nm_access_point_set_max_bitrate (ap, g_value_get_uint (value));
+		g_value_set_uint (value, nm_access_point_get_max_bitrate (ap));
 		break;
 	case PROP_STRENGTH:
-		nm_access_point_set_strength (ap, g_value_get_char (value));
+		g_value_set_uchar (value, nm_access_point_get_strength (ap));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -384,54 +300,36 @@
 	}
 }
 
-static void
-get_property (GObject *object,
-              guint prop_id,
-              GValue *value,
-              GParamSpec *pspec)
+static gboolean
+demarshal_ssid (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
 {
-	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (object);
-	GArray * ssid;
-	int len;
-	int i;
+	if (!nm_ssid_demarshal (value, (GByteArray **) field))
+		return FALSE;
 
-	switch (prop_id) {
-	case PROP_FLAGS:
-		g_value_set_uint (value, priv->flags);
-		break;
-	case PROP_WPA_FLAGS:
-		g_value_set_uint (value, priv->wpa_flags);
-		break;
-	case PROP_RSN_FLAGS:
-		g_value_set_uint (value, priv->rsn_flags);
-		break;
-	case PROP_SSID:
-		len = priv->ssid ? priv->ssid->len : 0;
-		ssid = g_array_sized_new (FALSE, TRUE, sizeof (unsigned char), len);
-		for (i = 0; i < len; i++)
-			g_array_append_val (ssid, priv->ssid->data[i]);
-		g_value_set_boxed (value, ssid);
-		g_array_free (ssid, TRUE);
-		break;
-	case PROP_FREQUENCY:
-		g_value_set_uint (value, priv->frequency);
-		break;
-	case PROP_HW_ADDRESS:
-		g_value_set_string (value, priv->hw_address);
-		break;
-	case PROP_MODE:
-		g_value_set_int (value, priv->mode);
-		break;
-	case PROP_MAX_BITRATE:
-		g_value_set_uint (value, priv->max_bitrate);
-		break;
-	case PROP_STRENGTH:
-		g_value_set_char (value, priv->strength);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
+	g_object_notify (G_OBJECT (object), NM_ACCESS_POINT_SSID);
+	return TRUE;
+}
+
+static void
+register_for_property_changed (NMAccessPoint *ap)
+{
+	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (ap);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_ACCESS_POINT_FLAGS,       nm_object_demarshal_generic, &priv->flags },
+		{ NM_ACCESS_POINT_WPA_FLAGS,   nm_object_demarshal_generic, &priv->wpa_flags },
+		{ NM_ACCESS_POINT_RSN_FLAGS,   nm_object_demarshal_generic, &priv->rsn_flags },
+		{ NM_ACCESS_POINT_SSID,        demarshal_ssid,              &priv->ssid },
+		{ NM_ACCESS_POINT_FREQUENCY,   nm_object_demarshal_generic, &priv->frequency },
+		{ NM_ACCESS_POINT_HW_ADDRESS,  nm_object_demarshal_generic, &priv->hw_address },
+		{ NM_ACCESS_POINT_MODE,        nm_object_demarshal_generic, &priv->mode },
+		{ NM_ACCESS_POINT_MAX_BITRATE, nm_object_demarshal_generic, &priv->max_bitrate },
+		{ NM_ACCESS_POINT_STRENGTH,    nm_object_demarshal_generic, &priv->strength },
+		{ NULL },
+	};
+
+	nm_object_handle_properties_changed (NM_OBJECT (ap),
+	                                     priv->proxy,
+	                                     property_changed_info);
 }
 
 static GObject*
@@ -450,12 +348,12 @@
 
 	priv = NM_ACCESS_POINT_GET_PRIVATE (object);
 
-	priv->ap_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
 									    NM_DBUS_SERVICE,
 									    nm_object_get_path (object),
 									    NM_DBUS_INTERFACE_ACCESS_POINT);
 
-	nm_object_handle_properties_changed (NM_OBJECT (object), priv->ap_proxy);
+	register_for_property_changed (NM_ACCESS_POINT (object));
 
 	return G_OBJECT (object);
 }
@@ -470,7 +368,6 @@
 
 	/* virtual methods */
 	object_class->constructor = constructor;
-	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
@@ -484,7 +381,7 @@
 		                    NM_802_11_AP_FLAGS_NONE,
 		                    NM_802_11_AP_FLAGS_PRIVACY,
 		                    NM_802_11_AP_FLAGS_NONE,
-		                    G_PARAM_READWRITE));
+		                    G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_WPA_FLAGS,
@@ -492,7 +389,7 @@
 		                    "WPA Flags",
 		                    "WPA Flags",
 		                    0, G_MAXUINT32, 0,
-		                    G_PARAM_READWRITE));
+		                    G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_RSN_FLAGS,
@@ -500,15 +397,15 @@
 		                    "RSN Flags",
 		                    "RSN Flags",
 		                    0, G_MAXUINT32, 0,
-		                    G_PARAM_READWRITE));
+		                    G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_SSID,
 		 g_param_spec_boxed (NM_ACCESS_POINT_SSID,
 						 "SSID",
 						 "SSID",
-						 DBUS_TYPE_G_UCHAR_ARRAY,
-						 G_PARAM_READWRITE));
+						 NM_TYPE_SSID,
+						 G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_FREQUENCY,
@@ -516,7 +413,7 @@
 						"Frequency",
 						"Frequency",
 						0, 10000, 0,
-						G_PARAM_READWRITE));
+						G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_HW_ADDRESS,
@@ -524,7 +421,7 @@
 						  "MAC Address",
 						  "Hardware MAC address",
 						  NULL,
-						  G_PARAM_READWRITE));
+						  G_PARAM_READABLE));
 	
 	g_object_class_install_property
 		(object_class, PROP_MODE,
@@ -532,7 +429,7 @@
 					    "Mode",
 					    "Mode",
 					    IW_MODE_ADHOC, IW_MODE_INFRA, IW_MODE_INFRA,
-					    G_PARAM_READWRITE));
+					    G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_MAX_BITRATE,
@@ -540,13 +437,13 @@
 						"Max Bitrate",
 						"Max Bitrate",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE));
+						G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_STRENGTH,
-		 g_param_spec_char (NM_ACCESS_POINT_STRENGTH,
+		 g_param_spec_uchar (NM_ACCESS_POINT_STRENGTH,
 						"Strength",
 						"Strength",
-						G_MININT8, G_MAXINT8, 0,
-						G_PARAM_READWRITE));
+						0, G_MAXUINT8, 0,
+						G_PARAM_READABLE));
 }

Modified: trunk/libnm-glib/nm-access-point.h
==============================================================================
--- trunk/libnm-glib/nm-access-point.h	(original)
+++ trunk/libnm-glib/nm-access-point.h	Mon Mar 24 15:17:30 2008
@@ -34,7 +34,7 @@
 
 GType nm_access_point_get_type (void);
 
-NMAccessPoint *nm_access_point_new (DBusGConnection *connection, const char *path);
+GObject *nm_access_point_new (DBusGConnection *connection, const char *path);
 
 guint32      nm_access_point_get_flags        (NMAccessPoint *ap);
 guint32      nm_access_point_get_wpa_flags    (NMAccessPoint *ap);
@@ -44,7 +44,7 @@
 const char * nm_access_point_get_hw_address   (NMAccessPoint *ap);
 int          nm_access_point_get_mode         (NMAccessPoint *ap);
 guint32      nm_access_point_get_max_bitrate  (NMAccessPoint *ap);
-gint8        nm_access_point_get_strength     (NMAccessPoint *ap);
+guint8       nm_access_point_get_strength     (NMAccessPoint *ap);
 
 G_END_DECLS
 

Added: trunk/libnm-glib/nm-active-connection.c
==============================================================================
--- (empty file)
+++ trunk/libnm-glib/nm-active-connection.c	Mon Mar 24 15:17:30 2008
@@ -0,0 +1,366 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#include <string.h>
+
+#include "NetworkManager.h"
+#include "nm-active-connection.h"
+#include "nm-object-private.h"
+#include "nm-types-private.h"
+#include "nm-device.h"
+
+#include "nm-active-connection-bindings.h"
+
+G_DEFINE_TYPE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT)
+
+#define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate))
+
+static gboolean demarshal_devices (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
+
+
+typedef struct {
+	gboolean disposed;
+	DBusGProxy *proxy;
+
+	char *service_name;
+	char *connection;
+	char *specific_object;
+	char *shared_service_name;
+	char *shared_connection;
+	GPtrArray *devices;
+} NMActiveConnectionPrivate;
+
+enum {
+	PROP_0,
+	PROP_SERVICE_NAME,
+	PROP_CONNECTION,
+	PROP_SPECIFIC_OBJECT,
+	PROP_SHARED_SERVICE_NAME,
+	PROP_SHARED_CONNECTION,
+	PROP_DEVICES,
+
+	LAST_PROP
+};
+
+#define DBUS_PROP_SERVICE_NAME "ServiceName"
+#define DBUS_PROP_CONNECTION "Connection"
+#define DBUS_PROP_SPECIFIC_OBJECT "SpecificObject"
+#define DBUS_PROP_SHARED_SERVICE_NAME "SharedServiceName"
+#define DBUS_PROP_SHARED_CONNECTION "SharedConnection"
+#define DBUS_PROP_DEVICES "Devices"
+
+GObject *
+nm_active_connection_new (DBusGConnection *connection, const char *path)
+{
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	return g_object_new (NM_TYPE_ACTIVE_CONNECTION,
+						 NM_OBJECT_DBUS_CONNECTION, connection,
+						 NM_OBJECT_DBUS_PATH, path,
+						 NULL);
+}
+
+const char *
+nm_active_connection_get_service_name (NMActiveConnection *connection)
+{
+	NMActiveConnectionPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
+	if (!priv->service_name) {
+		priv->service_name = nm_object_get_string_property (NM_OBJECT (connection),
+		                                                    NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+		                                                    DBUS_PROP_SERVICE_NAME);
+	}
+
+	return priv->service_name;
+}
+
+const char *
+nm_active_connection_get_connection (NMActiveConnection *connection)
+{
+	NMActiveConnectionPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
+	if (!priv->connection) {
+		priv->connection = nm_object_get_string_property (NM_OBJECT (connection),
+		                                                  NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+		                                                  DBUS_PROP_CONNECTION);
+	}
+
+	return priv->connection;
+}
+
+const char *
+nm_active_connection_get_specific_object (NMActiveConnection *connection)
+{
+	NMActiveConnectionPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
+	if (!priv->specific_object) {
+		priv->specific_object = nm_object_get_string_property (NM_OBJECT (connection),
+		                                                       NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+		                                                       DBUS_PROP_SPECIFIC_OBJECT);
+	}
+
+	return priv->specific_object;
+}
+
+const char *
+nm_active_connection_get_shared_service_name (NMActiveConnection *connection)
+{
+	NMActiveConnectionPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
+	if (!priv->shared_service_name) {
+		priv->shared_service_name = nm_object_get_string_property (NM_OBJECT (connection),
+		                                                           NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+		                                                           DBUS_PROP_SHARED_SERVICE_NAME);
+	}
+
+	return priv->shared_service_name;
+}
+
+const char *
+nm_active_connection_get_shared_connection (NMActiveConnection *connection)
+{
+	NMActiveConnectionPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
+	if (!priv->shared_connection) {
+		priv->shared_connection = nm_object_get_string_property (NM_OBJECT (connection),
+		                                                         NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+		                                                         DBUS_PROP_SHARED_CONNECTION);
+	}
+
+	return priv->shared_connection;
+}
+
+const GPtrArray *
+nm_active_connection_get_devices (NMActiveConnection *connection)
+{
+	NMActiveConnectionPrivate *priv;
+	GValue value = { 0, };
+
+	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL);
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
+	if (priv->devices)
+		return priv->devices;
+
+	if (!nm_object_get_property (NM_OBJECT (connection),
+	                             NM_DBUS_INTERFACE,
+	                             DBUS_PROP_DEVICES,
+	                             &value)) {
+		return NULL;
+	}
+
+	demarshal_devices (NM_OBJECT (connection), NULL, &value, &priv->devices);
+	g_value_unset (&value);
+
+	return priv->devices;
+}
+
+static void
+nm_active_connection_init (NMActiveConnection *ap)
+{
+}
+
+static void
+dispose (GObject *object)
+{
+	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	if (priv->devices) {
+		g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
+		g_ptr_array_free (priv->devices, TRUE);
+	}
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
+
+	g_free (priv->service_name);
+	g_free (priv->connection);
+	g_free (priv->specific_object);
+	g_free (priv->shared_service_name);
+	g_free (priv->shared_service_name);
+
+	G_OBJECT_CLASS (nm_active_connection_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMActiveConnection *self = NM_ACTIVE_CONNECTION (object);
+
+	switch (prop_id) {
+	case PROP_SERVICE_NAME:
+		g_value_set_string (value, nm_active_connection_get_service_name (self));
+		break;
+	case PROP_CONNECTION:
+		g_value_set_boxed (value, nm_active_connection_get_connection (self));
+		break;
+	case PROP_SPECIFIC_OBJECT:
+		g_value_set_boxed (value, nm_active_connection_get_specific_object (self));
+		break;
+	case PROP_SHARED_SERVICE_NAME:
+		g_value_set_string (value, nm_active_connection_get_shared_service_name (self));
+		break;
+	case PROP_SHARED_CONNECTION:
+		g_value_set_boxed (value, nm_active_connection_get_shared_connection (self));
+		break;
+	case PROP_DEVICES:
+		g_value_set_boxed (value, nm_active_connection_get_devices (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static gboolean
+demarshal_devices (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	DBusGConnection *connection;
+
+	connection = nm_object_get_connection (object);
+	if (!nm_object_array_demarshal (value, (GPtrArray **) field, connection, nm_device_new))
+		return FALSE;
+
+	g_object_notify (G_OBJECT (object), NM_ACTIVE_CONNECTION_DEVICES);
+	return TRUE;
+}
+
+static void
+register_for_property_changed (NMActiveConnection *connection)
+{
+	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_ACTIVE_CONNECTION_SERVICE_NAME,        nm_object_demarshal_generic, &priv->service_name },
+		{ NM_ACTIVE_CONNECTION_CONNECTION,          nm_object_demarshal_generic, &priv->connection },
+		{ NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,     nm_object_demarshal_generic, &priv->specific_object },
+		{ NM_ACTIVE_CONNECTION_SHARED_SERVICE_NAME, nm_object_demarshal_generic, &priv->shared_service_name },
+		{ NM_ACTIVE_CONNECTION_SHARED_CONNECTION,   nm_object_demarshal_generic, &priv->shared_connection },
+		{ NM_ACTIVE_CONNECTION_DEVICES,             demarshal_devices,           &priv->devices },
+		{ NULL },
+	};
+
+	nm_object_handle_properties_changed (NM_OBJECT (connection),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+			 guint n_construct_params,
+			 GObjectConstructParam *construct_params)
+{
+	NMObject *object;
+	NMActiveConnectionPrivate *priv;
+
+	object = (NMObject *) G_OBJECT_CLASS (nm_active_connection_parent_class)->constructor (type,
+																	  n_construct_params,
+																	  construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
+
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+									    NM_DBUS_SERVICE,
+									    nm_object_get_path (object),
+									    NM_DBUS_INTERFACE_ACTIVE_CONNECTION);
+
+	register_for_property_changed (NM_ACTIVE_CONNECTION (object));
+
+	return G_OBJECT (object);
+}
+
+
+static void
+nm_active_connection_class_init (NMActiveConnectionClass *ap_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (ap_class);
+
+	g_type_class_add_private (ap_class, sizeof (NMActiveConnectionPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+
+	/* properties */
+	g_object_class_install_property
+		(object_class, PROP_SERVICE_NAME,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_SERVICE_NAME,
+						  "Service Name",
+						  "Service Name",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_CONNECTION,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_CONNECTION,
+						      "Connection",
+						      "Connection",
+						      NULL,
+						      G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_SPECIFIC_OBJECT,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT,
+						      "Specific object",
+						      "Specific object",
+						      NULL,
+						      G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_SHARED_SERVICE_NAME,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_SHARED_SERVICE_NAME,
+						  "Shared Service Name",
+						  "Shared Service Name",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_SHARED_CONNECTION,
+		 g_param_spec_string (NM_ACTIVE_CONNECTION_SHARED_CONNECTION,
+						      "Shared Connection",
+						      "Shared Connection",
+						      NULL,
+						      G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_DEVICES,
+		 g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES,
+						       "Devices",
+						       "Devices",
+						       NM_TYPE_OBJECT_ARRAY,
+						       G_PARAM_READABLE));
+}

Added: trunk/libnm-glib/nm-active-connection.h
==============================================================================
--- (empty file)
+++ trunk/libnm-glib/nm-active-connection.h	Mon Mar 24 15:17:30 2008
@@ -0,0 +1,45 @@
+#ifndef NM_ACTIVE_CONNECTION_H
+#define NM_ACTIVE_CONNECTION_H
+
+#include <glib/gtypes.h>
+#include <glib-object.h>
+#include "nm-object.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_ACTIVE_CONNECTION            (nm_active_connection_get_type ())
+#define NM_ACTIVE_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnection))
+#define NM_ACTIVE_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionClass))
+#define NM_IS_ACTIVE_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_ACTIVE_CONNECTION))
+#define NM_IS_ACTIVE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_ACTIVE_CONNECTION))
+#define NM_ACTIVE_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionClass))
+
+#define NM_ACTIVE_CONNECTION_SERVICE_NAME        "service-name"
+#define NM_ACTIVE_CONNECTION_CONNECTION          "connection"
+#define NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT     "specific-object"
+#define NM_ACTIVE_CONNECTION_SHARED_SERVICE_NAME "shared-service-name"
+#define NM_ACTIVE_CONNECTION_SHARED_CONNECTION   "shared-connection"
+#define NM_ACTIVE_CONNECTION_DEVICES             "devices"
+
+typedef struct {
+	NMObject parent;
+} NMActiveConnection;
+
+typedef struct {
+	NMObjectClass parent;
+} NMActiveConnectionClass;
+
+GType nm_active_connection_get_type (void);
+
+GObject *nm_active_connection_new (DBusGConnection *connection, const char *path);
+
+const char * nm_active_connection_get_service_name        (NMActiveConnection *connection);
+const char * nm_active_connection_get_connection          (NMActiveConnection *connection);
+const char * nm_active_connection_get_specific_object     (NMActiveConnection *connection);
+const char * nm_active_connection_get_shared_service_name (NMActiveConnection *connection);
+const char * nm_active_connection_get_shared_connection   (NMActiveConnection *connection);
+const GPtrArray *nm_active_connection_get_devices         (NMActiveConnection *connection);
+
+G_END_DECLS
+
+#endif /* NM_ACTIVE_CONNECTION_H */

Modified: trunk/libnm-glib/nm-cdma-device.c
==============================================================================
--- trunk/libnm-glib/nm-cdma-device.c	(original)
+++ trunk/libnm-glib/nm-cdma-device.c	Mon Mar 24 15:17:30 2008
@@ -7,7 +7,7 @@
 #define NM_CDMA_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CDMA_DEVICE, NMCdmaDevicePrivate))
 
 typedef struct {
-	DBusGProxy *cdma_proxy;
+	DBusGProxy *proxy;
 
 	gboolean disposed;
 } NMCdmaDevicePrivate;
@@ -33,10 +33,10 @@
 
 	priv = NM_CDMA_DEVICE_GET_PRIVATE (object);
 
-	priv->cdma_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
-	                                              NM_DBUS_SERVICE,
-	                                              nm_object_get_path (NM_OBJECT (object)),
-	                                              NM_DBUS_INTERFACE_CDMA_DEVICE);
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
+	                                         NM_DBUS_SERVICE,
+	                                         nm_object_get_path (NM_OBJECT (object)),
+	                                         NM_DBUS_INTERFACE_CDMA_DEVICE);
 	return object;
 }
 
@@ -52,7 +52,7 @@
 
 	priv->disposed = TRUE;
 
-	g_object_unref (priv->cdma_proxy);
+	g_object_unref (priv->proxy);
 
 	G_OBJECT_CLASS (nm_cdma_device_parent_class)->dispose (object);
 }
@@ -69,14 +69,14 @@
 	object_class->dispose = dispose;
 }
 
-NMCdmaDevice *
+GObject *
 nm_cdma_device_new (DBusGConnection *connection, const char *path)
 {
 	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (path != NULL, NULL);
 
-	return (NMCdmaDevice *) g_object_new (NM_TYPE_CDMA_DEVICE,
-	                                      NM_OBJECT_CONNECTION, connection,
-	                                      NM_OBJECT_PATH, path,
-	                                      NULL);
+	return g_object_new (NM_TYPE_CDMA_DEVICE,
+	                     NM_OBJECT_DBUS_CONNECTION, connection,
+	                     NM_OBJECT_DBUS_PATH, path,
+	                     NULL);
 }

Modified: trunk/libnm-glib/nm-cdma-device.h
==============================================================================
--- trunk/libnm-glib/nm-cdma-device.h	(original)
+++ trunk/libnm-glib/nm-cdma-device.h	Mon Mar 24 15:17:30 2008
@@ -24,8 +24,7 @@
 
 GType        nm_cdma_device_get_type (void);
 
-NMCdmaDevice *nm_cdma_device_new (DBusGConnection *connection,
-                                  const char *path);
+GObject *nm_cdma_device_new (DBusGConnection *connection, const char *path);
 
 G_END_DECLS
 

Modified: trunk/libnm-glib/nm-client.c
==============================================================================
--- trunk/libnm-glib/nm-client.c	(original)
+++ trunk/libnm-glib/nm-client.c	Mon Mar 24 15:17:30 2008
@@ -2,6 +2,8 @@
 
 #include <dbus/dbus-glib.h>
 #include <string.h>
+#include <nm-utils.h>
+
 #include "nm-client.h"
 #include "nm-device-802-3-ethernet.h"
 #include "nm-device-802-11-wireless.h"
@@ -9,7 +11,11 @@
 #include "nm-cdma-device.h"
 #include "nm-device-private.h"
 #include "nm-marshal.h"
-#include <nm-utils.h>
+#include "nm-types-private.h"
+#include "nm-object-private.h"
+#include "nm-active-connection.h"
+#include "nm-object-cache.h"
+#include "nm-dbus-glib-types.h"
 
 #include "nm-client-bindings.h"
 
@@ -18,12 +24,14 @@
 #define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate))
 
 typedef struct {
+	gboolean disposed;
+
 	DBusGProxy *client_proxy;
 	DBusGProxy *bus_proxy;
 	gboolean manager_running;
 	NMState state;
-	gboolean have_device_list;
-	GHashTable *devices;
+	GPtrArray *devices;
+	GPtrArray *active_connections;
 
 	gboolean wireless_enabled;
 	gboolean wireless_hw_enabled;
@@ -31,17 +39,18 @@
 
 enum {
 	PROP_0,
+	PROP_STATE,
+	PROP_MANAGER_RUNNING,
 	PROP_WIRELESS_ENABLED,
 	PROP_WIRELESS_HARDWARE_ENABLED,
+	PROP_ACTIVE_CONNECTIONS,
 
 	LAST_PROP
 };
 
 enum {
-	MANAGER_RUNNING,
 	DEVICE_ADDED,
 	DEVICE_REMOVED,
-	STATE_CHANGED,
 
 	LAST_SIGNAL
 };
@@ -54,7 +63,6 @@
 									  const char *new_owner,
 									  gpointer user_data);
 
-static void client_state_changed_proxy (DBusGProxy *proxy, guint state, gpointer user_data);
 static void client_device_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data);
 static void client_device_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data);
 
@@ -64,24 +72,63 @@
 	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
 
 	priv->state = NM_STATE_UNKNOWN;
-	priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
-										   (GDestroyNotify) g_free,
-										   (GDestroyNotify) g_object_unref);
 }
 
 static void
-update_wireless_status (NMClient *client)
+update_wireless_status (NMClient *client, gboolean notify)
 {
 	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+	gboolean val;
+
+	val = nm_object_get_boolean_property (NM_OBJECT (client),
+										  NM_DBUS_INTERFACE,
+										  "WirelessHardwareEnabled");
+	if (val != priv->wireless_hw_enabled) {
+		priv->wireless_hw_enabled = val;
+		g_object_notify (G_OBJECT (client), NM_CLIENT_WIRELESS_HARDWARE_ENABLED);
+	}
+
+	val = priv->wireless_hw_enabled ? TRUE :
+				nm_object_get_boolean_property (NM_OBJECT (client),
+				                                NM_DBUS_INTERFACE,
+				                                "WirelessEnabled");
+	if (val != priv->wireless_enabled) {
+		priv->wireless_enabled = val;
+		g_object_notify (G_OBJECT (client), NM_CLIENT_WIRELESS_ENABLED);
+	}
+}
+
+static gboolean
+demarshal_active_connections (NMObject *object,
+                              GParamSpec *pspec,
+                              GValue *value,
+                              gpointer field)
+{
+	DBusGConnection *connection;
+
+	connection = nm_object_get_connection (object);
+	if (!nm_object_array_demarshal (value, (GPtrArray **) field, connection, nm_active_connection_new))
+		return FALSE;
 
-	priv->wireless_enabled = nm_object_get_boolean_property (NM_OBJECT (client),
-												  NM_DBUS_INTERFACE,
-												  "WirelessEnabled");
-
-	priv->wireless_hw_enabled = priv->wireless_enabled ?
-		TRUE : nm_object_get_boolean_property (NM_OBJECT (client),
-									    NM_DBUS_INTERFACE,
-									    "WirelessHardwareEnabled");
+	g_object_notify (G_OBJECT (object), NM_CLIENT_ACTIVE_CONNECTIONS);
+	return TRUE;
+}
+
+static void
+register_for_property_changed (NMClient *client)
+{
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_CLIENT_STATE,                     nm_object_demarshal_generic,  &priv->state },
+		{ NM_CLIENT_WIRELESS_ENABLED,          nm_object_demarshal_generic,  &priv->wireless_enabled },
+		{ NM_CLIENT_WIRELESS_HARDWARE_ENABLED, nm_object_demarshal_generic,  &priv->wireless_hw_enabled },
+		{ NM_CLIENT_ACTIVE_CONNECTIONS,        demarshal_active_connections, &priv->active_connections },
+		{ NULL },
+	};
+
+	nm_object_handle_properties_changed (NM_OBJECT (client),
+	                                     priv->client_proxy,
+	                                     property_changed_info);
 }
 
 static GObject*
@@ -108,12 +155,7 @@
 										   nm_object_get_path (object),
 										   NM_DBUS_INTERFACE);
 
-	dbus_g_proxy_add_signal (priv->client_proxy, "StateChanged", G_TYPE_UINT, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->client_proxy,
-						    "StateChanged",
-						    G_CALLBACK (client_state_changed_proxy),
-						    object,
-						    NULL);
+	register_for_property_changed (NM_CLIENT (object));
 
 	dbus_g_proxy_add_signal (priv->client_proxy, "DeviceAdded", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
 	dbus_g_proxy_connect_signal (priv->client_proxy,
@@ -129,9 +171,8 @@
 						    object,
 						    NULL);
 
-	nm_object_handle_properties_changed (NM_OBJECT (object), priv->client_proxy);
-
-	update_wireless_status (NM_CLIENT (object));
+	update_wireless_status (NM_CLIENT (object), FALSE);
+	nm_client_get_state (NM_CLIENT (object));
 
 	priv->bus_proxy = dbus_g_proxy_new_for_name (connection,
 										"org.freedesktop.DBus",
@@ -160,15 +201,34 @@
 }
 
 static void
-finalize (GObject *object)
+free_device_list (NMClient *client)
+{
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+
+	if (!priv->devices)
+		return;
+
+	g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
+	g_ptr_array_free (priv->devices, TRUE);
+	priv->devices = NULL;
+}
+
+static void
+dispose (GObject *object)
 {
 	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
 
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
+		return;
+	}
+
 	g_object_unref (priv->client_proxy);
 	g_object_unref (priv->bus_proxy);
-	g_hash_table_destroy (priv->devices);
 
-	G_OBJECT_CLASS (nm_client_parent_class)->finalize (object);
+	free_device_list (NM_CLIENT (object));
+
+	G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
 }
 
 static void
@@ -205,38 +265,31 @@
               GValue *value,
               GParamSpec *pspec)
 {
-	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
+	NMClient *self = NM_CLIENT (object);
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
 
 	switch (prop_id) {
+	case PROP_STATE:
+		g_value_set_uint (value, nm_client_get_state (self));
+		break;
+	case PROP_MANAGER_RUNNING:
+		g_value_set_boolean (value, priv->manager_running);
+		break;
 	case PROP_WIRELESS_ENABLED:
 		g_value_set_boolean (value, priv->wireless_enabled);
 		break;
 	case PROP_WIRELESS_HARDWARE_ENABLED:
 		g_value_set_boolean (value, priv->wireless_hw_enabled);
 		break;
+	case PROP_ACTIVE_CONNECTIONS:
+		g_value_set_boxed (value, nm_client_get_active_connections (self));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
 	}
 }
 
-
-static void
-manager_running (NMClient *client, gboolean running)
-{
-	if (!running) {
-		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
-
-		priv->state = NM_STATE_UNKNOWN;
-		g_hash_table_remove_all (priv->devices);
-		priv->have_device_list = FALSE;
-		priv->wireless_enabled = FALSE;
-		priv->wireless_hw_enabled = FALSE;
-	} else {
-		update_wireless_status (client);
-	}
-}
-
 static void
 nm_client_class_init (NMClientClass *client_class)
 {
@@ -248,16 +301,30 @@
 	object_class->constructor = constructor;
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
-	object_class->finalize = finalize;
-
-	client_class->manager_running = manager_running;
+	object_class->dispose = dispose;
 
 	/* properties */
 	g_object_class_install_property
+		(object_class, PROP_STATE,
+		 g_param_spec_uint (NM_CLIENT_STATE,
+						    "State",
+						    "NetworkManager state",
+						    NM_STATE_UNKNOWN, NM_STATE_DISCONNECTED, NM_STATE_UNKNOWN,
+						    G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_MANAGER_RUNNING,
+		 g_param_spec_boolean (NM_CLIENT_MANAGER_RUNNING,
+						       "ManagerRunning",
+						       "Whether NetworkManager is running",
+						       FALSE,
+						       G_PARAM_READABLE));
+
+	g_object_class_install_property
 		(object_class, PROP_WIRELESS_ENABLED,
 		 g_param_spec_boolean (NM_CLIENT_WIRELESS_ENABLED,
 						   "WirelessEnabled",
-						   "Is wirless enabled",
+						   "Is wireless enabled",
 						   TRUE,
 						   G_PARAM_READWRITE));
 
@@ -265,20 +332,19 @@
 		(object_class, PROP_WIRELESS_HARDWARE_ENABLED,
 		 g_param_spec_boolean (NM_CLIENT_WIRELESS_HARDWARE_ENABLED,
 						   "WirelessHardwareEnabled",
-						   "Is wirless hardware enabled",
+						   "Is wireless hardware enabled",
 						   TRUE,
-						   G_PARAM_READWRITE));
+						   G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_ACTIVE_CONNECTIONS,
+		 g_param_spec_boxed (NM_CLIENT_ACTIVE_CONNECTIONS,
+						   "Active connections",
+						   "Active connections",
+						   NM_TYPE_OBJECT_ARRAY,
+						   G_PARAM_READABLE));
 
 	/* signals */
-	signals[MANAGER_RUNNING] =
-		g_signal_new ("manager-running",
-					  G_OBJECT_CLASS_TYPE (object_class),
-					  G_SIGNAL_RUN_FIRST,
-					  G_STRUCT_OFFSET (NMClientClass, manager_running),
-					  NULL, NULL,
-					  g_cclosure_marshal_VOID__BOOLEAN,
-					  G_TYPE_NONE, 1,
-					  G_TYPE_BOOLEAN);
 	signals[DEVICE_ADDED] =
 		g_signal_new ("device-added",
 					  G_OBJECT_CLASS_TYPE (object_class),
@@ -298,16 +364,6 @@
 					  g_cclosure_marshal_VOID__OBJECT,
 					  G_TYPE_NONE, 1,
 					  G_TYPE_OBJECT);
-
-	signals[STATE_CHANGED] =
-		g_signal_new ("state-changed",
-					  G_OBJECT_CLASS_TYPE (object_class),
-					  G_SIGNAL_RUN_FIRST,
-					  G_STRUCT_OFFSET (NMClientClass, state_changed),
-					  NULL, NULL,
-					  g_cclosure_marshal_VOID__UINT,
-					  G_TYPE_NONE, 1,
-					  G_TYPE_UINT);
 }
 
 NMClient *
@@ -324,8 +380,8 @@
 	}
 
 	return (NMClient *) g_object_new (NM_TYPE_CLIENT,
-									  NM_OBJECT_CONNECTION, connection,
-									  NM_OBJECT_PATH, NM_DBUS_PATH,
+									  NM_OBJECT_DBUS_CONNECTION, connection,
+									  NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
 									  NULL);
 }
 
@@ -336,75 +392,34 @@
 						  const char *new_owner,
 						  gpointer user_data)
 {
-	if (name && !strcmp (name, NM_DBUS_SERVICE)) {
-		NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (user_data);
-		gboolean old_good = (old_owner && strlen (old_owner));
-		gboolean new_good = (new_owner && strlen (new_owner));
-		gboolean new_running = FALSE;
-
-		if (!old_good && new_good)
-			new_running = TRUE;
-		else if (old_good && !new_good)
-			new_running = FALSE;
-
-		if (new_running != priv->manager_running) {
-			priv->manager_running = new_running;
-			g_signal_emit (NM_CLIENT (user_data),
-			               signals[MANAGER_RUNNING],
-			               0,
-			               priv->manager_running);
-		}
-	}
-}
-
-static void
-client_state_changed_proxy (DBusGProxy *proxy, guint state, gpointer user_data)
-{
 	NMClient *client = NM_CLIENT (user_data);
 	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+	gboolean old_good = (old_owner && strlen (old_owner));
+	gboolean new_good = (new_owner && strlen (new_owner));
+	gboolean new_running = FALSE;
+
+	if (!name || strcmp (name, NM_DBUS_SERVICE))
+		return;
+
+	if (!old_good && new_good)
+		new_running = TRUE;
+	else if (old_good && !new_good)
+		new_running = FALSE;
 
-	if (priv->state != state) {
-		priv->state = state;
-		g_signal_emit (client, signals[STATE_CHANGED], 0, state);
-	}
-}
+	if (new_running == priv->manager_running)
+		return;
 
-static NMDevice *
-get_device (NMClient *client, const char *path, gboolean create_if_not_found)
-{
-	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
-	NMDevice *device;
-
-	device = g_hash_table_lookup (priv->devices, path);
-	if (!device && create_if_not_found) {
-		DBusGConnection *connection;
-		NMDeviceType type;
-
-		connection = nm_object_get_connection (NM_OBJECT (client));
-		type = nm_device_type_for_path (connection, path);
-
-		switch (type) {
-		case DEVICE_TYPE_802_3_ETHERNET:
-			device = NM_DEVICE (nm_device_802_3_ethernet_new (connection, path));
-			break;
-		case DEVICE_TYPE_802_11_WIRELESS:
-			device = NM_DEVICE (nm_device_802_11_wireless_new (connection, path));
-			break;
-		case DEVICE_TYPE_GSM:
-			device = NM_DEVICE (nm_gsm_device_new (connection, path));
-			break;
-		case DEVICE_TYPE_CDMA:
-			device = NM_DEVICE (nm_cdma_device_new (connection, path));
-			break;
-		default:
-			device = nm_device_new (connection, path);
-		}
-
-		if (device)
-			g_hash_table_insert (priv->devices, g_strdup (path), device);
+	priv->manager_running = new_running;
+	if (!priv->manager_running) {
+		priv->state = NM_STATE_UNKNOWN;
+		g_object_notify (G_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
+		free_device_list (client);
+		priv->wireless_enabled = FALSE;
+		priv->wireless_hw_enabled = FALSE;
+	} else {
+		g_object_notify (G_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
+		update_wireless_status (client, TRUE);
 	}
-
-	return device;
 }
 
 static void
@@ -413,7 +428,7 @@
 	NMClient *client = NM_CLIENT (user_data);
 	NMDevice *device;
 
-	device = get_device (client, path, TRUE);
+	device = nm_client_get_device_by_path (client, path);
 	if (device)
 		g_signal_emit (client, signals[DEVICE_ADDED], 0, device);
 }
@@ -422,90 +437,68 @@
 client_device_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
 {
 	NMClient *client = NM_CLIENT (user_data);
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
 	NMDevice *device;
 
-	device = get_device (client, path, FALSE);
+	device = nm_client_get_device_by_path (client, path);
 	if (device) {
 		g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
-		g_hash_table_remove (NM_CLIENT_GET_PRIVATE (client)->devices, path);
+		g_ptr_array_remove (priv->devices, device);
+		g_object_unref (device);
 	}
 }
 
-gboolean
-nm_client_manager_is_running (NMClient *client)
-{
-	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
-
-	return NM_CLIENT_GET_PRIVATE (client)->manager_running;
-}
-
-static void
-devices_to_slist (gpointer key, gpointer value, gpointer user_data)
-{
-	GSList **list = (GSList **) user_data;
-
-	*list = g_slist_prepend (*list, value);
-}
-
-GSList *
+GPtrArray *
 nm_client_get_devices (NMClient *client)
 {
 	NMClientPrivate *priv;
-	GSList *list = NULL;
-	GPtrArray *array = NULL;
-	GError *err = NULL;
+	DBusGConnection *connection;
+	GValue value = { 0, };
+	GError *error = NULL;
+	GPtrArray *temp;
 
 	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
 
 	priv = NM_CLIENT_GET_PRIVATE (client);
+	if (priv->devices)
+		return priv->devices;
 
-	if (priv->have_device_list) {
-		g_hash_table_foreach (priv->devices, devices_to_slist, &list);
-		return list;
+	if (!org_freedesktop_NetworkManager_get_devices (priv->client_proxy, &temp, &error)) {
+		g_warning ("%s: error getting devices: %s\n", __func__, error->message);
+		g_error_free (error);
+		return NULL;
 	}
 
-	if (!org_freedesktop_NetworkManager_get_devices (priv->client_proxy, &array, &err)) {
-		g_warning ("Error in get_devices: %s", err->message);
-		g_error_free (err);
-	} else {
-		int i;
-
-		for (i = 0; i < array->len; i++) {
-			NMDevice *device;
-			char *path = g_ptr_array_index (array, i);
-
-			device = get_device (client, (const char *) path, TRUE);
-			if (device)
-				list = g_slist_append (list, device);
-			g_free (path);
-		}
-
-		g_ptr_array_free (array, TRUE);
+	g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH);
+	g_value_take_boxed (&value, temp);
+	connection = nm_object_get_connection (NM_OBJECT (client));
+	nm_object_array_demarshal (&value, &priv->devices, connection, nm_device_new);
+	g_value_unset (&value);
 
-		priv->have_device_list = TRUE;
-	}
-
-	return list;
+	return priv->devices;
 }
 
 NMDevice *
 nm_client_get_device_by_path (NMClient *client, const char *object_path)
 {
-	GSList *devices;
-	GSList *iter;
+	GPtrArray *devices;
+	int i;
 	NMDevice *device = NULL;
 
 	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
 	g_return_val_if_fail (object_path, NULL);
 
 	devices = nm_client_get_devices (client);
-	for (iter = devices; iter; iter = iter->next) {
-		if (!strcmp (nm_object_get_path (NM_OBJECT (iter->data)), object_path)) {
-			device = NM_DEVICE (iter->data);
+	if (!devices)
+		return NULL;
+
+	for (i = 0; i < devices->len; i++) {
+		NMDevice *candidate = g_ptr_array_index (devices, i);
+		if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), object_path)) {
+			device = candidate;
 			break;
 		}
 	}
-	g_slist_free (devices);
 
 	return device;
 }
@@ -516,7 +509,10 @@
 } ActivateDeviceInfo;
 
 static void
-activate_cb (DBusGProxy *proxy, GError *err, gpointer user_data)
+activate_cb (DBusGProxy *proxy,
+             char *active_connection,
+             GError *err,
+             gpointer user_data)
 {
 	ActivateDeviceInfo *info = (ActivateDeviceInfo *) user_data;
 
@@ -567,132 +563,47 @@
 }
 
 void
-nm_client_free_active_connections_element (GHashTable *item)
+nm_client_deactivate_connection (NMClient *client, NMActiveConnection *active)
 {
-	GSList *devices, *iter;
+	NMClientPrivate *priv;
+	const char *path;
+	GError *error = NULL;
 
-	g_free (g_hash_table_lookup (item, NM_AC_KEY_SERVICE_NAME));
-	g_free (g_hash_table_lookup (item, NM_AC_KEY_CONNECTION));
-	g_free (g_hash_table_lookup (item, NM_AC_KEY_SPECIFIC_OBJECT));
-	g_free (g_hash_table_lookup (item, NM_AC_KEY_SHARED_TO_SERVICE_NAME));
-	g_free (g_hash_table_lookup (item, NM_AC_KEY_SHARED_TO_CONNECTION));
+	g_return_if_fail (NM_IS_CLIENT (client));
+	g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active));
 
-	devices = g_hash_table_lookup (item, NM_AC_KEY_DEVICES);
-	for (iter = devices; iter; iter = g_slist_next (iter))
-		g_object_unref (iter->data);
-	g_slist_free (devices);
+	// FIXME: return errors
+	priv = NM_CLIENT_GET_PRIVATE (client);
+	path = nm_object_get_path (NM_OBJECT (active));
+	if (!org_freedesktop_NetworkManager_deactivate_connection (priv->client_proxy, path, &error)) {
+		g_warning ("Could not deactivate connection '%s': %s", path, error->message);
+		g_error_free (error);
+	}
 }
 
-#define DBUS_TYPE_G_OBJECT_PATH_ARRAY (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH))
-
-GSList * 
+const GPtrArray * 
 nm_client_get_active_connections (NMClient *client)
 {
 	NMClientPrivate *priv;
-	GSList *connections = NULL;
-	GPtrArray *array = NULL;
-	GError *err = NULL;
-	int i, j;
+	GValue value = { 0, };
 
 	g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
 
 	priv = NM_CLIENT_GET_PRIVATE (client);
-	if (!org_freedesktop_NetworkManager_get_active_connections (priv->client_proxy, &array, &err)) {
-		g_warning ("Error in get_active_connections: %s", err->message);
-		g_error_free (err);
+	if (priv->active_connections)
+		return priv->active_connections;
+
+	if (!nm_object_get_property (NM_OBJECT (client),
+	                             "org.freedesktop.DBus.Properties",
+	                             "ActiveConnections",
+	                             &value)) {
 		return NULL;
 	}
 
-	for (i = 0; i < array->len; i++) {
-		GHashTable *reply;
-		GHashTable *active;
-		GValue *value, *value2;
-		GPtrArray *devices_array = NULL;
-		GSList *devices = NULL;
-		gboolean have_shared_service = TRUE;
-
-		active = g_hash_table_new (g_str_hash, g_str_equal);
-
-		reply = g_ptr_array_index (array, i);
-
-		/* Service name */
-		value = g_hash_table_lookup (reply, NM_AC_KEY_SERVICE_NAME);
-		if (!value || !G_VALUE_HOLDS_STRING (value)) {
-			g_warning ("%s: missing item " NM_AC_KEY_SERVICE_NAME, __func__);
-			nm_client_free_active_connections_element (active);
-			g_hash_table_destroy (reply);
-			continue;
-		}
-		g_hash_table_insert (active, NM_AC_KEY_SERVICE_NAME, g_value_dup_string (value));
+	demarshal_active_connections (NM_OBJECT (client), NULL, &value, &priv->active_connections);	
+	g_value_unset (&value);
 
-		/* Connection path */
-		value = g_hash_table_lookup (reply, NM_AC_KEY_CONNECTION);
-		if (!value || !G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) {
-			g_warning ("%s: missing item " NM_AC_KEY_CONNECTION, __func__);
-			nm_client_free_active_connections_element (active);
-			g_hash_table_destroy (reply);
-			continue;
-		}
-		g_hash_table_insert (active, NM_AC_KEY_CONNECTION, g_value_dup_boxed (value));
-
-		/* Specific object path */
-		value = g_hash_table_lookup (reply, NM_AC_KEY_SPECIFIC_OBJECT);
-		if (value && G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
-			g_hash_table_insert (active, NM_AC_KEY_SPECIFIC_OBJECT, g_value_dup_boxed (value));
-
-		/* Shared to service name */
-		value = g_hash_table_lookup (reply, NM_AC_KEY_SHARED_TO_SERVICE_NAME);
-		if (!value || !G_VALUE_HOLDS_STRING (value))
-			have_shared_service = FALSE;
-
-		value2 = g_hash_table_lookup (reply, NM_AC_KEY_SHARED_TO_CONNECTION);
-		if (have_shared_service && value2 && G_VALUE_HOLDS (value2, DBUS_TYPE_G_OBJECT_PATH)) {
-			g_hash_table_insert (active, NM_AC_KEY_SHARED_TO_SERVICE_NAME, g_value_dup_string (value));
-			g_hash_table_insert (active, NM_AC_KEY_SHARED_TO_CONNECTION, g_value_dup_boxed (value2));
-		} else {
-			/* Ignore missing shared-to-service _and_ missing shared-to-connection */
-			if (have_shared_service) {
-				g_warning ("%s: missing item " NM_AC_KEY_SHARED_TO_SERVICE_NAME, __func__);
-				nm_client_free_active_connections_element (active);
-				g_hash_table_destroy (reply);
-				continue;
-			}
-		}
-
-		/* Device array */
-		value = g_hash_table_lookup (reply, NM_AC_KEY_DEVICES);
-		if (!value || !G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH_ARRAY)) {
-			g_warning ("%s: missing item " NM_AC_KEY_DEVICES, __func__);
-			nm_client_free_active_connections_element (active);
-			g_hash_table_destroy (reply);
-			continue;
-		}
-
-		devices_array = g_value_get_boxed (value);
-		if (!devices_array || (devices_array->len == 0)) {
-			g_warning ("%s: no devices for this active connection.", __func__);
-			nm_client_free_active_connections_element (active);
-			g_hash_table_destroy (reply);
-			continue;
-		}
-
-		for (j = 0; j < devices_array->len; j++) {
-			NMDevice *device;
-			const char *path;
-
-			path = (const char *) g_ptr_array_index (devices_array, j);
-			device = get_device (client, path, TRUE);
-			devices = g_slist_append (devices, g_object_ref (device));
-		}
-
-		g_hash_table_insert (active, NM_AC_KEY_DEVICES, devices);
-
-		connections = g_slist_append (connections, active);
-		g_hash_table_destroy (reply);
-	}
-
-	g_ptr_array_free (array, TRUE);
-	return connections;
+	return priv->active_connections;
 }
 
 gboolean
@@ -736,6 +647,9 @@
 
 	priv = NM_CLIENT_GET_PRIVATE (client);
 
+	if (!priv->manager_running)
+		return NM_STATE_UNKNOWN;
+
 	if (priv->state == NM_STATE_UNKNOWN)
 		priv->state = nm_object_get_uint_property (NM_OBJECT (client), NM_DBUS_INTERFACE, "State");
 
@@ -754,3 +668,12 @@
 		g_error_free (err);
 	}
 }
+
+gboolean
+nm_client_get_manager_running (NMClient *client)
+{
+	g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
+
+	return NM_CLIENT_GET_PRIVATE (client)->manager_running;
+}
+

Modified: trunk/libnm-glib/nm-client.h
==============================================================================
--- trunk/libnm-glib/nm-client.h	(original)
+++ trunk/libnm-glib/nm-client.h	Mon Mar 24 15:17:30 2008
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
 
 #ifndef NM_CLIENT_H
-#define NM_CLIENT_H 1
+#define NM_CLIENT_H
 
 #include <glib/gtypes.h>
 #include <glib-object.h>
@@ -9,6 +9,7 @@
 #include <NetworkManager.h>
 #include "nm-object.h"
 #include "nm-device.h"
+#include "nm-active-connection.h"
 
 G_BEGIN_DECLS
 
@@ -19,8 +20,11 @@
 #define NM_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_CLIENT))
 #define NM_CLIENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CLIENT, NMClientClass))
 
-#define NM_CLIENT_WIRELESS_ENABLED "wireless_enabled"
-#define NM_CLIENT_WIRELESS_HARDWARE_ENABLED "wireless_hardware_enabled"
+#define NM_CLIENT_STATE "state"
+#define NM_CLIENT_MANAGER_RUNNING "manager-running"
+#define NM_CLIENT_WIRELESS_ENABLED "wireless-enabled"
+#define NM_CLIENT_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled"
+#define NM_CLIENT_ACTIVE_CONNECTIONS "active-connections"
 
 typedef struct {
 	NMObject parent;
@@ -30,23 +34,16 @@
 	NMObjectClass parent;
 
 	/* Signals */
-	void (*manager_running) (NMClient *client, gboolean running);
 	void (*device_added) (NMClient *client, NMDevice *device);
 	void (*device_removed) (NMClient *client, NMDevice *device);
-	void (*state_changed) (NMClient *client, NMState state);
 } NMClientClass;
 
 GType nm_client_get_type (void);
 
+NMClient *nm_client_new (void);
 
-NMClient *nm_client_new                  (void);
-
-gboolean  nm_client_manager_is_running    (NMClient *client);
-GSList   *nm_client_get_devices           (NMClient *client);
-NMDevice *nm_client_get_device_by_path    (NMClient *client,
-                                           const char *object_path);
-GSList *  nm_client_get_active_connections (NMClient *client);
-void      nm_client_free_active_connections_element (GHashTable *item);
+GPtrArray *nm_client_get_devices          (NMClient *client);
+NMDevice *nm_client_get_device_by_path    (NMClient *client, const char *object_path);
 
 typedef void (*NMClientActivateDeviceFn) (gpointer user_data, GError *error);
 
@@ -58,10 +55,14 @@
 						  NMClientActivateDeviceFn callback,
 						  gpointer user_data);
 
+void nm_client_deactivate_connection (NMClient *client, NMActiveConnection *active);
+
 gboolean  nm_client_wireless_get_enabled (NMClient *client);
 void      nm_client_wireless_set_enabled (NMClient *client, gboolean enabled);
 gboolean  nm_client_wireless_hardware_get_enabled (NMClient *client);
 NMState   nm_client_get_state            (NMClient *client);
+gboolean  nm_client_get_manager_running  (NMClient *client);
+const GPtrArray *nm_client_get_active_connections (NMClient *client);
 void      nm_client_sleep                (NMClient *client, gboolean sleep);
 
 G_END_DECLS

Modified: trunk/libnm-glib/nm-device-802-11-wireless.c
==============================================================================
--- trunk/libnm-glib/nm-device-802-11-wireless.c	(original)
+++ trunk/libnm-glib/nm-device-802-11-wireless.c	Mon Mar 24 15:17:30 2008
@@ -6,6 +6,10 @@
 
 #include "nm-device-802-11-wireless.h"
 #include "nm-device-private.h"
+#include "nm-object-private.h"
+#include "nm-object-cache.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-types-private.h"
 
 #include "nm-device-802-11-wireless-bindings.h"
 
@@ -13,18 +17,18 @@
 
 #define NM_DEVICE_802_11_WIRELESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_802_11_WIRELESS, NMDevice80211WirelessPrivate))
 
+static gboolean demarshal_active_ap (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
+
 typedef struct {
-	DBusGProxy *wireless_proxy;
-	gboolean have_ap_list;
-	GHashTable *aps;
+	gboolean disposed;
+	DBusGProxy *proxy;
 
-	char * hw_address;
+	char *hw_address;
 	int mode;
 	guint32 rate;
-	NMAccessPoint *current_ap;
+	NMAccessPoint *active_ap;
 	guint32 wireless_caps;
-
-	gboolean disposed;
+	GPtrArray *aps;
 } NMDevice80211WirelessPrivate;
 
 enum {
@@ -53,27 +57,16 @@
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
-NMDevice80211Wireless *
+GObject *
 nm_device_802_11_wireless_new (DBusGConnection *connection, const char *path)
 {
 	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (path != NULL, NULL);
 
-	return (NMDevice80211Wireless *) g_object_new (NM_TYPE_DEVICE_802_11_WIRELESS,
-										  NM_OBJECT_CONNECTION, connection,
-										  NM_OBJECT_PATH, path,
-										  NULL);
-}
-
-static void
-nm_device_802_11_wireless_set_hw_address (NMDevice80211Wireless *self,
-								  const char *address)
-{
-	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
-
-	g_free (priv->hw_address);
-	priv->hw_address = g_strdup (address);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_802_11_WIRELESS_HW_ADDRESS);
+	return g_object_new (NM_TYPE_DEVICE_802_11_WIRELESS,
+	                     NM_OBJECT_DBUS_CONNECTION, connection,
+	                     NM_OBJECT_DBUS_PATH, path,
+	                     NULL);
 }
 
 const char *
@@ -93,15 +86,6 @@
 	return priv->hw_address;
 }
 
-static void
-nm_device_802_11_wireless_set_mode (NMDevice80211Wireless *self, int mode)
-{
-	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
-
-	priv->mode = mode;
-	g_object_notify (G_OBJECT (self), NM_DEVICE_802_11_WIRELESS_MODE);
-}
-
 int
 nm_device_802_11_wireless_get_mode (NMDevice80211Wireless *device)
 {
@@ -119,17 +103,6 @@
 	return priv->mode;
 }
 
-static void
-nm_device_802_11_wireless_set_bitrate (NMDevice80211Wireless *self, guint32 bitrate)
-{
-	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
-
-	if (priv->rate != bitrate) {
-		priv->rate = bitrate;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_802_11_WIRELESS_BITRATE);
-	}
-}
-
 guint32
 nm_device_802_11_wireless_get_bitrate (NMDevice80211Wireless *device)
 {
@@ -161,15 +134,6 @@
 	return priv->rate;
 }
 
-static void
-nm_device_802_11_wireless_set_capabilities (NMDevice80211Wireless *self, guint caps)
-{
-	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
-
-	priv->wireless_caps = caps;
-	g_object_notify (G_OBJECT (self), NM_DEVICE_802_11_WIRELESS_CAPABILITIES);
-}
-
 guint32
 nm_device_802_11_wireless_get_capabilities (NMDevice80211Wireless *device)
 {
@@ -187,60 +151,17 @@
 	return priv->wireless_caps;
 }
 
-static NMAccessPoint *
-get_access_point (NMDevice80211Wireless *device, const char *path, gboolean create_if_not_found)
-{
-	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device);
-	NMAccessPoint *ap;
-
-	g_return_val_if_fail (path != NULL, NULL);
-
-	/* path of "/" means NULL */
-	if (!strcmp (path, "/"))
-		return NULL;
-
-	ap = g_hash_table_lookup (priv->aps, path);
-	if (!ap && create_if_not_found) {
-		ap = nm_access_point_new (nm_object_get_connection (NM_OBJECT (device)), path);
-		if (ap)
-			g_hash_table_insert (priv->aps, g_strdup (path), ap);
-	}
-
-	return ap;
-}
-
-static void
-nm_device_802_11_wireless_set_active_ap (NMDevice80211Wireless *self,
-								 const char *ap_path)
-{
-	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
-
-	if (!priv->current_ap && !ap_path)
-		return;
-
-	if (priv->current_ap) {
-		g_object_unref (priv->current_ap);
-		priv->current_ap = NULL;
-	}
-
-	if (ap_path) {
-		priv->current_ap = get_access_point (self, ap_path, TRUE);
-		if (priv->current_ap)
-			g_object_ref (priv->current_ap);
-	}
-
-	g_object_notify (G_OBJECT (self), NM_DEVICE_802_11_WIRELESS_ACTIVE_ACCESS_POINT);
-}
-
 NMAccessPoint *
-nm_device_802_11_wireless_get_active_access_point (NMDevice80211Wireless *device)
+nm_device_802_11_wireless_get_active_access_point (NMDevice80211Wireless *self)
 {
 	NMDevice80211WirelessPrivate *priv;
 	NMDeviceState state;
+	char *path;
+	GValue value = { 0, };
 
-	g_return_val_if_fail (NM_IS_DEVICE_802_11_WIRELESS (device), NULL);
+	g_return_val_if_fail (NM_IS_DEVICE_802_11_WIRELESS (self), NULL);
 
-	state = nm_device_get_state (NM_DEVICE (device));
+	state = nm_device_get_state (NM_DEVICE (self));
 	switch (state) {
 	case NM_DEVICE_STATE_PREPARE:
 	case NM_DEVICE_STATE_CONFIG:
@@ -253,105 +174,103 @@
 		break;
 	}
 
-	priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device);
-	if (!priv->current_ap) {
-		char *path;
-
-		path = nm_object_get_object_path_property (NM_OBJECT (device),
-		                                           NM_DBUS_INTERFACE_DEVICE_WIRELESS,
-		                                           DBUS_PROP_ACTIVE_ACCESS_POINT);
-		if (path) {
-			priv->current_ap = get_access_point (device, path, TRUE);
-			if (priv->current_ap)
-				g_object_ref (priv->current_ap);
-			g_free (path);
-		}
-	}
-
-	return priv->current_ap;
+	priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
+	if (priv->active_ap)
+		return priv->active_ap;
+
+	path = nm_object_get_object_path_property (NM_OBJECT (self),
+	                                           NM_DBUS_INTERFACE_DEVICE_WIRELESS,
+	                                           DBUS_PROP_ACTIVE_ACCESS_POINT);
+
+	g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH);
+	g_value_take_boxed (&value, path);
+	demarshal_active_ap (NM_OBJECT (self), NULL, &value, &priv->active_ap);
+	g_value_unset (&value);
+	return priv->active_ap;
 }
 
-NMAccessPoint *
-nm_device_802_11_wireless_get_access_point_by_path (NMDevice80211Wireless *device,
-											        const char *object_path)
+GPtrArray *
+nm_device_802_11_wireless_get_access_points (NMDevice80211Wireless *self)
 {
-	g_return_val_if_fail (NM_IS_DEVICE_802_11_WIRELESS (device), NULL);
-	g_return_val_if_fail (object_path != NULL, NULL);
-
-	return get_access_point (device, object_path, TRUE);
-}
+	NMDevice80211WirelessPrivate *priv;
+	DBusGConnection *connection;
+	GValue value = { 0, };
+	GError *error = NULL;
+	GPtrArray *temp;
+
+	g_return_val_if_fail (NM_IS_DEVICE_802_11_WIRELESS (self), NULL);
+
+	priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
+	if (priv->aps)
+		return priv->aps;
+
+	if (!org_freedesktop_NetworkManager_Device_Wireless_get_access_points (priv->proxy, &temp, &error)) {
+		g_warning ("%s: error getting access points: %s", __func__, error->message);
+		g_error_free (error);
+		return NULL;
+	}
 
-static void
-access_points_to_slist (gpointer key, gpointer value, gpointer user_data)
-{
-	GSList **list = (GSList **) user_data;
+	g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH);
+	g_value_take_boxed (&value, temp);
+	connection = nm_object_get_connection (NM_OBJECT (self));
+	nm_object_array_demarshal (&value, &priv->aps, connection, nm_access_point_new);
+	g_value_unset (&value);
 
-	*list = g_slist_prepend (*list, value);
+	return priv->aps;
 }
 
-GSList *
-nm_device_802_11_wireless_get_access_points (NMDevice80211Wireless *device)
+NMAccessPoint *
+nm_device_802_11_wireless_get_access_point_by_path (NMDevice80211Wireless *self,
+											        const char *path)
 {
-	NMDevice80211WirelessPrivate *priv;
-	GSList *list = NULL;
-	GPtrArray *array = NULL;
-	GError *err = NULL;
+	GPtrArray *aps;
+	int i;
+	NMAccessPoint *ap = NULL;
 
-	g_return_val_if_fail (NM_IS_DEVICE_802_11_WIRELESS (device), NULL);
+	g_return_val_if_fail (NM_IS_DEVICE_802_11_WIRELESS (self), NULL);
+	g_return_val_if_fail (path != NULL, NULL);
 
-	priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device);
+	aps = nm_device_802_11_wireless_get_access_points (self);
+	if (!aps)
+		return NULL;
 
-	if (priv->have_ap_list) {
-		g_hash_table_foreach (priv->aps, access_points_to_slist, &list);
-		return list;
-	}
-
-	if (!org_freedesktop_NetworkManager_Device_Wireless_get_access_points
-		(NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device)->wireless_proxy, &array, &err)) {
-
-		g_warning ("Error in get_access_points: %s", err->message);
-		g_error_free (err);
-	} else {
-		int i;
-
-		for (i = 0; i < array->len; i++) {
-			char *path = (char *) g_ptr_array_index (array, i);
-			NMAccessPoint *ap = get_access_point (device, (const char *) path, TRUE);
-			if (ap)
-				list = g_slist_prepend (list, ap);
-			g_free (path);
+	for (i = 0; i < aps->len; i++) {
+		NMAccessPoint *candidate = g_ptr_array_index (aps, i);
+		if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), path)) {
+			ap = candidate;
+			break;
 		}
-
-		g_ptr_array_free (array, TRUE);
-		list = g_slist_reverse (list);
-
-		priv->have_ap_list = TRUE;
 	}
 
-	return list;
+	return ap;
 }
 
 static void
 access_point_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
 {
-	NMDevice80211Wireless *device = NM_DEVICE_802_11_WIRELESS (user_data);
+	NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (user_data);
 	NMAccessPoint *ap;
 
-	ap = get_access_point (device, path, TRUE);
-	if (device && ap)
-		g_signal_emit (device, signals[ACCESS_POINT_ADDED], 0, ap);
+	g_return_if_fail (self != NULL);
+
+	ap = nm_device_802_11_wireless_get_access_point_by_path (self, path);
+	if (ap)
+		g_signal_emit (self, signals[ACCESS_POINT_ADDED], 0, ap);
 }
 
 static void
 access_point_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
 {
-	NMDevice80211Wireless *device = NM_DEVICE_802_11_WIRELESS (user_data);
+	NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (user_data);
+	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
 	NMAccessPoint *ap;
 
-	ap = get_access_point (device, path, FALSE);
-	if (device && ap) {
-		g_signal_emit (device, signals[ACCESS_POINT_REMOVED], 0, ap);
-		g_hash_table_remove (NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device)->aps, path);
+	g_return_if_fail (self != NULL);
+
+	ap = nm_device_802_11_wireless_get_access_point_by_path (self, path);
+	if (ap) {
+		g_signal_emit (self, signals[ACCESS_POINT_REMOVED], 0, ap);
+		g_ptr_array_remove (priv->aps, ap);
 	}
 }
 
@@ -363,37 +282,6 @@
 	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device);
 
 	priv->disposed = FALSE;
-	priv->aps = g_hash_table_new_full (g_str_hash, g_str_equal,
-	                                   (GDestroyNotify) g_free,
-	                                   (GDestroyNotify) g_object_unref);
-}
-
-static void
-set_property (GObject *object, guint prop_id,
-		    const GValue *value, GParamSpec *pspec)
-{
-	NMDevice80211Wireless *device = NM_DEVICE_802_11_WIRELESS (object);
-
-	switch (prop_id) {
-	case PROP_HW_ADDRESS:
-		nm_device_802_11_wireless_set_hw_address (device, g_value_get_string (value));
-		break;
-	case PROP_MODE:
-		nm_device_802_11_wireless_set_mode (device, g_value_get_int (value));
-		break;
-	case PROP_BITRATE:
-		nm_device_802_11_wireless_set_bitrate (device, g_value_get_uint (value));
-		break;
-	case PROP_ACTIVE_ACCESS_POINT:
-		nm_device_802_11_wireless_set_active_ap (device, (char *) g_value_get_boxed (value));
-		break;
-	case PROP_WIRELESS_CAPABILITIES:
-		nm_device_802_11_wireless_set_capabilities (device, g_value_get_uint (value));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
 }
 
 static void
@@ -402,23 +290,23 @@
               GValue *value,
               GParamSpec *pspec)
 {
-	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (object);
+	NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (object);
 
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
-		g_value_set_string (value, priv->hw_address);
+		g_value_set_string (value, nm_device_802_11_wireless_get_hw_address (self));
 		break;
 	case PROP_MODE:
-		g_value_set_int (value, priv->mode);
+		g_value_set_int (value, nm_device_802_11_wireless_get_mode (self));
 		break;
 	case PROP_BITRATE:
-		g_value_set_uint (value, priv->rate);
+		g_value_set_uint (value, nm_device_802_11_wireless_get_bitrate (self));
 		break;
 	case PROP_ACTIVE_ACCESS_POINT:
-		g_value_set_boxed (value, priv->current_ap ? nm_object_get_path (NM_OBJECT (priv->current_ap)) : "/");
+		g_value_set_object (value, nm_device_802_11_wireless_get_active_access_point (self));
 		break;
 	case PROP_WIRELESS_CAPABILITIES:
-		g_value_set_uint (value, priv->wireless_caps);
+		g_value_set_uint (value, nm_device_802_11_wireless_get_capabilities (self));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -427,11 +315,12 @@
 }
 
 static void
-state_changed_cb (NMDevice *device, NMDeviceState state, gpointer user_data)
+state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
 {
 	NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (device);
+	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
 
-	switch (state) {
+	switch (nm_device_get_state (device)) {
 	case NM_DEVICE_STATE_PREPARE:
 	case NM_DEVICE_STATE_CONFIG:
 	case NM_DEVICE_STATE_NEED_AUTH:
@@ -444,12 +333,69 @@
 	case NM_DEVICE_STATE_FAILED:
 	case NM_DEVICE_STATE_CANCELLED:
 	default:
-		nm_device_802_11_wireless_set_active_ap (self, NULL);
-		nm_device_802_11_wireless_set_bitrate (self, 0);
+		if (priv->active_ap) {
+			g_object_unref (priv->active_ap);
+			priv->active_ap = NULL;
+		}
+		g_object_notify (G_OBJECT (device), NM_DEVICE_802_11_WIRELESS_ACTIVE_ACCESS_POINT);
+		priv->rate = 0;
+		g_object_notify (G_OBJECT (device), NM_DEVICE_802_11_WIRELESS_BITRATE);
 		break;
 	}
 }
 
+static gboolean
+demarshal_active_ap (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (object);
+	const char *path;
+	NMAccessPoint *ap = NULL;
+	DBusGConnection *connection;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+		return FALSE;
+
+	path = g_value_get_boxed (value);
+	if (strcmp (path, "/")) {
+		ap = NM_ACCESS_POINT (nm_object_cache_get (path));
+		if (ap)
+			ap = g_object_ref (ap);
+		else {
+			connection = nm_object_get_connection (object);
+			ap = NM_ACCESS_POINT (nm_access_point_new (connection, path));
+		}
+	}
+
+	if (priv->active_ap) {
+		g_object_unref (priv->active_ap);
+		priv->active_ap = NULL;
+	}
+
+	if (ap)
+		priv->active_ap = ap;
+
+	g_object_notify (G_OBJECT (object), NM_DEVICE_802_11_WIRELESS_ACTIVE_ACCESS_POINT);
+	return TRUE;
+}
+
+static void
+register_for_property_changed (NMDevice80211Wireless *device)
+{
+	NMDevice80211WirelessPrivate *priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (device);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_DEVICE_802_11_WIRELESS_HW_ADDRESS,          nm_object_demarshal_generic, &priv->hw_address },
+		{ NM_DEVICE_802_11_WIRELESS_MODE,                nm_object_demarshal_generic, &priv->mode },
+		{ NM_DEVICE_802_11_WIRELESS_BITRATE,             nm_object_demarshal_generic, &priv->rate },
+		{ NM_DEVICE_802_11_WIRELESS_ACTIVE_ACCESS_POINT, demarshal_active_ap,         &priv->active_ap },
+		{ NM_DEVICE_802_11_WIRELESS_CAPABILITIES,        nm_object_demarshal_generic, &priv->wireless_caps },
+		{ NULL },
+	};
+
+	nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
 static GObject*
 constructor (GType type,
 		   guint n_construct_params,
@@ -466,29 +412,29 @@
 
 	priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (object);
 
-	priv->wireless_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
 											NM_DBUS_SERVICE,
 											nm_object_get_path (NM_OBJECT (object)),
 											NM_DBUS_INTERFACE_DEVICE_WIRELESS);
 
-	dbus_g_proxy_add_signal (priv->wireless_proxy, "AccessPointAdded",
+	dbus_g_proxy_add_signal (priv->proxy, "AccessPointAdded",
 	                         DBUS_TYPE_G_OBJECT_PATH,
 	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->wireless_proxy, "AccessPointAdded",
+	dbus_g_proxy_connect_signal (priv->proxy, "AccessPointAdded",
 						    G_CALLBACK (access_point_added_proxy),
 						    object, NULL);
 
-	dbus_g_proxy_add_signal (priv->wireless_proxy, "AccessPointRemoved",
+	dbus_g_proxy_add_signal (priv->proxy, "AccessPointRemoved",
 	                         DBUS_TYPE_G_OBJECT_PATH,
 	                         G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->wireless_proxy, "AccessPointRemoved",
+	dbus_g_proxy_connect_signal (priv->proxy, "AccessPointRemoved",
 						    G_CALLBACK (access_point_removed_proxy),
 						    object, NULL);
 
-	nm_object_handle_properties_changed (NM_OBJECT (object), priv->wireless_proxy);
+	register_for_property_changed (NM_DEVICE_802_11_WIRELESS (object));
 
 	g_signal_connect (NM_DEVICE (object),
-	                  "state-changed",
+	                  "notify::" NM_DEVICE_STATE,
 	                  G_CALLBACK (state_changed_cb),
 	                  NULL);
 
@@ -507,13 +453,16 @@
 
 	priv->disposed = TRUE;
 
-	g_object_unref (priv->wireless_proxy);
+	if (priv->active_ap)
+		g_object_unref (priv->active_ap);
 
-	g_hash_table_destroy (priv->aps);
-	priv->aps = NULL;
+	if (priv->aps) {
+		g_ptr_array_foreach (priv->aps, (GFunc) g_object_unref, NULL);
+		g_ptr_array_free (priv->aps, TRUE);
+		priv->aps = NULL;
+	}
 
-	if (priv->current_ap)
-		g_object_unref (priv->current_ap);
+	g_object_unref (priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_802_11_wireless_parent_class)->dispose (object);
 }
@@ -538,7 +487,6 @@
 
 	/* virtual methods */
 	object_class->constructor = constructor;
-	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
@@ -550,7 +498,7 @@
 						  "MAC Address",
 						  "Hardware MAC address",
 						  NULL,
-						  G_PARAM_READWRITE));
+						  G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_MODE,
@@ -558,7 +506,7 @@
 					    "Mode",
 					    "Mode",
 					    0, IW_MODE_INFRA, 0,
-					    G_PARAM_READWRITE));
+					    G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_BITRATE,
@@ -566,15 +514,15 @@
 					    "Bit Rate",
 					    "Bit Rate",
 					    0, G_MAXUINT32, 0,
-					    G_PARAM_READWRITE));
+					    G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_ACTIVE_ACCESS_POINT,
-		 g_param_spec_boxed (NM_DEVICE_802_11_WIRELESS_ACTIVE_ACCESS_POINT,
+		 g_param_spec_object (NM_DEVICE_802_11_WIRELESS_ACTIVE_ACCESS_POINT,
 						 "Active Access Point",
 						 "Active Access Point",
-						 DBUS_TYPE_G_OBJECT_PATH,
-						 G_PARAM_READWRITE));
+						 NM_TYPE_ACCESS_POINT,
+						 G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_WIRELESS_CAPABILITIES,
@@ -582,7 +530,7 @@
 		                    "Wireless Capabilities",
 		                    "Wireless Capabilities",
 		                    0, G_MAXUINT32, 0,
-		                    G_PARAM_READWRITE));
+		                    G_PARAM_READABLE));
 
 	/* signals */
 	signals[ACCESS_POINT_ADDED] =

Modified: trunk/libnm-glib/nm-device-802-11-wireless.h
==============================================================================
--- trunk/libnm-glib/nm-device-802-11-wireless.h	(original)
+++ trunk/libnm-glib/nm-device-802-11-wireless.h	Mon Mar 24 15:17:30 2008
@@ -33,8 +33,7 @@
 
 GType nm_device_802_11_wireless_get_type (void);
 
-NMDevice80211Wireless *nm_device_802_11_wireless_new         (DBusGConnection *connection,
-															  const char *path);
+GObject *nm_device_802_11_wireless_new (DBusGConnection *connection, const char *path);
 
 const char *    nm_device_802_11_wireless_get_hw_address           (NMDevice80211Wireless *device);
 int             nm_device_802_11_wireless_get_mode                 (NMDevice80211Wireless *device);
@@ -43,9 +42,9 @@
 NMAccessPoint * nm_device_802_11_wireless_get_active_access_point  (NMDevice80211Wireless *device);
 
 NMAccessPoint * nm_device_802_11_wireless_get_access_point_by_path (NMDevice80211Wireless *device,
-                                                                    const char *object_path);
+                                                                    const char *path);
 
-GSList *        nm_device_802_11_wireless_get_access_points        (NMDevice80211Wireless *device);
+GPtrArray *     nm_device_802_11_wireless_get_access_points        (NMDevice80211Wireless *device);
 
 G_END_DECLS
 

Modified: trunk/libnm-glib/nm-device-802-3-ethernet.c
==============================================================================
--- trunk/libnm-glib/nm-device-802-3-ethernet.c	(original)
+++ trunk/libnm-glib/nm-device-802-3-ethernet.c	Mon Mar 24 15:17:30 2008
@@ -1,5 +1,6 @@
 #include "nm-device-802-3-ethernet.h"
 #include "nm-device-private.h"
+#include "nm-object-private.h"
 
 #include "nm-device-802-3-ethernet-bindings.h"
 
@@ -8,7 +9,7 @@
 #define NM_DEVICE_802_3_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_802_3_ETHERNET, NMDevice8023EthernetPrivate))
 
 typedef struct {
-	DBusGProxy *wired_proxy;
+	DBusGProxy *proxy;
 
 	char * hw_address;
 	guint32 speed;
@@ -31,27 +32,16 @@
 #define DBUS_PROP_SPEED "Speed"
 #define DBUS_PROP_CARRIER "Carrier"
 
-NMDevice8023Ethernet *
+GObject *
 nm_device_802_3_ethernet_new (DBusGConnection *connection, const char *path)
 {
 	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (path != NULL, NULL);
 
-	return (NMDevice8023Ethernet *) g_object_new (NM_TYPE_DEVICE_802_3_ETHERNET,
-												  NM_OBJECT_CONNECTION, connection,
-												  NM_OBJECT_PATH, path,
-												  NULL);
-}
-
-static void
-nm_device_802_3_ethernet_set_hw_address (NMDevice8023Ethernet *self,
-                                         const char *address)
-{
-	NMDevice8023EthernetPrivate *priv = NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (self);
-
-	g_free (priv->hw_address);
-	priv->hw_address = g_strdup (address);
-	g_object_notify (G_OBJECT (self), NM_DEVICE_802_3_ETHERNET_HW_ADDRESS);
+	return g_object_new (NM_TYPE_DEVICE_802_3_ETHERNET,
+	                     NM_OBJECT_DBUS_CONNECTION, connection,
+	                     NM_OBJECT_DBUS_PATH, path,
+	                     NULL);
 }
 
 const char *
@@ -71,15 +61,6 @@
 	return priv->hw_address;
 }
 
-static void
-nm_device_802_3_ethernet_set_speed (NMDevice8023Ethernet *self, guint32 speed)
-{
-	NMDevice8023EthernetPrivate *priv = NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (self);
-
-	priv->speed = speed;
-	g_object_notify (G_OBJECT (self), NM_DEVICE_802_3_ETHERNET_SPEED);
-}
-
 guint32
 nm_device_802_3_ethernet_get_speed (NMDevice8023Ethernet *device)
 {
@@ -97,18 +78,6 @@
 	return priv->speed;
 }
 
-static void
-nm_device_802_3_ethernet_set_carrier (NMDevice8023Ethernet *self, gboolean carrier)
-{
-	NMDevice8023EthernetPrivate *priv = NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (self);
-
-	if (priv->carrier != carrier) {
-		priv->carrier_valid = TRUE;
-		priv->carrier = carrier;
-		g_object_notify (G_OBJECT (self), NM_DEVICE_802_3_ETHERNET_CARRIER);
-	}
-}
-
 gboolean
 nm_device_802_3_ethernet_get_carrier (NMDevice8023Ethernet *device)
 {
@@ -137,6 +106,22 @@
 	priv->carrier_valid = FALSE;
 }
 
+static void
+register_for_property_changed (NMDevice8023Ethernet *device)
+{
+	NMDevice8023EthernetPrivate *priv = NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (device);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_DEVICE_802_3_ETHERNET_HW_ADDRESS, nm_object_demarshal_generic, &priv->hw_address },
+		{ NM_DEVICE_802_3_ETHERNET_SPEED,      nm_object_demarshal_generic, &priv->speed },
+		{ NM_DEVICE_802_3_ETHERNET_CARRIER,    nm_object_demarshal_generic, &priv->carrier },
+		{ NULL },
+	};
+
+	nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
 static GObject*
 constructor (GType type,
 			 guint n_construct_params,
@@ -153,12 +138,12 @@
 
 	priv = NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (object);
 
-	priv->wired_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
-													  NM_DBUS_SERVICE,
-													  nm_object_get_path (NM_OBJECT (object)),
-													  NM_DBUS_INTERFACE_DEVICE_WIRED);
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
+	                                         NM_DBUS_SERVICE,
+	                                         nm_object_get_path (NM_OBJECT (object)),
+	                                         NM_DBUS_INTERFACE_DEVICE_WIRED);
 
-	nm_object_handle_properties_changed (NM_OBJECT (object), priv->wired_proxy);
+	register_for_property_changed (NM_DEVICE_802_3_ETHERNET (object));
 
 	return object;
 }
@@ -175,7 +160,7 @@
 
 	priv->disposed = TRUE;
 
-	g_object_unref (priv->wired_proxy);
+	g_object_unref (priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_802_3_ethernet_parent_class)->dispose (object);
 }
@@ -192,44 +177,22 @@
 }
 
 static void
-set_property (GObject *object, guint prop_id,
-		    const GValue *value, GParamSpec *pspec)
-{
-	NMDevice8023Ethernet *device = NM_DEVICE_802_3_ETHERNET (object);
-
-	switch (prop_id) {
-	case PROP_HW_ADDRESS:
-		nm_device_802_3_ethernet_set_hw_address (device, g_value_get_string (value));
-		break;
-	case PROP_SPEED:
-		nm_device_802_3_ethernet_set_speed (device, g_value_get_uint (value));
-		break;
-	case PROP_CARRIER:
-		nm_device_802_3_ethernet_set_carrier (device, g_value_get_boolean (value));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
 get_property (GObject *object,
               guint prop_id,
               GValue *value,
               GParamSpec *pspec)
 {
-	NMDevice8023EthernetPrivate *priv = NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (object);
+	NMDevice8023Ethernet *device = NM_DEVICE_802_3_ETHERNET (object);
 
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
-		g_value_set_string (value, priv->hw_address);
+		g_value_set_string (value, nm_device_802_3_ethernet_get_hw_address (device));
 		break;
 	case PROP_SPEED:
-		g_value_set_uint (value, priv->speed);
+		g_value_set_uint (value, nm_device_802_3_ethernet_get_speed (device));
 		break;
 	case PROP_CARRIER:
-		g_value_set_boolean (value, priv->carrier);
+		g_value_set_boolean (value, nm_device_802_3_ethernet_get_carrier (device));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -248,7 +211,6 @@
 	object_class->constructor = constructor;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
-	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 
 	/* properties */
@@ -258,7 +220,7 @@
 						  "MAC Address",
 						  "Hardware MAC address",
 						  NULL,
-						  G_PARAM_READWRITE));
+						  G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_SPEED,
@@ -266,14 +228,15 @@
 					    "Speed",
 					    "Speed",
 					    0, G_MAXUINT32, 0,
-					    G_PARAM_READWRITE));
+					    G_PARAM_READABLE));
 
 	g_object_class_install_property
 		(object_class, PROP_CARRIER,
 		 g_param_spec_boolean (NM_DEVICE_802_3_ETHERNET_CARRIER,
 					    "Carrier",
 					    "Carrier",
-					    FALSE, G_PARAM_READWRITE));
+					    FALSE,
+					    G_PARAM_READABLE));
 
 }
 

Modified: trunk/libnm-glib/nm-device-802-3-ethernet.h
==============================================================================
--- trunk/libnm-glib/nm-device-802-3-ethernet.h	(original)
+++ trunk/libnm-glib/nm-device-802-3-ethernet.h	Mon Mar 24 15:17:30 2008
@@ -26,8 +26,7 @@
 
 GType nm_device_802_3_ethernet_get_type (void);
 
-NMDevice8023Ethernet *nm_device_802_3_ethernet_new         (DBusGConnection *connection,
-															const char *path);
+GObject *nm_device_802_3_ethernet_new (DBusGConnection *connection, const char *path);
 
 const char * nm_device_802_3_ethernet_get_hw_address (NMDevice8023Ethernet *device);
 guint32      nm_device_802_3_ethernet_get_speed   (NMDevice8023Ethernet *device);

Modified: trunk/libnm-glib/nm-device.c
==============================================================================
--- trunk/libnm-glib/nm-device.c	(original)
+++ trunk/libnm-glib/nm-device.c	Mon Mar 24 15:17:30 2008
@@ -1,5 +1,14 @@
+#include <string.h>
+
+#include "NetworkManager.h"
+#include "nm-device-802-3-ethernet.h"
+#include "nm-device-802-11-wireless.h"
+#include "nm-gsm-device.h"
+#include "nm-cdma-device.h"
 #include "nm-device.h"
 #include "nm-device-private.h"
+#include "nm-object-private.h"
+#include "nm-object-cache.h"
 
 #include "nm-device-bindings.h"
 
@@ -8,35 +17,34 @@
 #define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
 
 typedef struct {
-	DBusGProxy *device_proxy;
-	NMDeviceState state;
+	gboolean disposed;
+	DBusGProxy *proxy;
 
+	char *iface;
+	char *udi;
+	char *driver;
+	guint32 capabilities;
+	NMIP4Config *ip4_config;
+	NMDeviceState state;
 	char *product;
 	char *vendor;
-
-	gboolean disposed;
 } NMDevicePrivate;
 
 enum {
-	STATE_CHANGED,
-
-	LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-
-enum {
 	PROP_0,
-	PROP_CONNECTION,
-	PROP_PATH,
+	PROP_INTERFACE,
+	PROP_UDI,
+	PROP_DRIVER,
+	PROP_CAPABILITIES,
+	PROP_IP4_CONFIG,
+	PROP_STATE,
+	PROP_PRODUCT,
+	PROP_VENDOR,
 
 	LAST_PROP
 };
 
 
-static void device_state_change_proxy (DBusGProxy *proxy, guint state, gpointer user_data);
-
 static void
 nm_device_init (NMDevice *device)
 {
@@ -44,8 +52,59 @@
 
 	priv->state = NM_DEVICE_STATE_UNKNOWN;
 	priv->disposed = FALSE;
-	priv->product = NULL;
-	priv->vendor = NULL;
+}
+
+static gboolean
+demarshal_ip4_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
+	const char *path;
+	NMIP4Config *config = NULL;
+	DBusGConnection *connection;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+		return FALSE;
+
+	path = g_value_get_boxed (value);
+	if (strcmp (path, "/")) {
+		config = NM_IP4_CONFIG (nm_object_cache_get (path));
+		if (config)
+			config = g_object_ref (config);
+		else {
+			connection = nm_object_get_connection (object);
+			config = NM_IP4_CONFIG (nm_ip4_config_new (connection, path));
+		}
+	}
+
+	if (priv->ip4_config) {
+		g_object_unref (priv->ip4_config);
+		priv->ip4_config = NULL;
+	}
+
+	if (config)
+		priv->ip4_config = config;
+
+	g_object_notify (G_OBJECT (object), NM_DEVICE_IP4_CONFIG);
+	return TRUE;
+}
+
+static void
+register_for_property_changed (NMDevice *device)
+{
+	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_DEVICE_UDI,          nm_object_demarshal_generic, &priv->udi },
+		{ NM_DEVICE_INTERFACE,    nm_object_demarshal_generic, &priv->iface },
+		{ NM_DEVICE_DRIVER,       nm_object_demarshal_generic, &priv->driver },
+		{ NM_DEVICE_CAPABILITIES, nm_object_demarshal_generic, &priv->capabilities },
+		{ NM_DEVICE_IP4_CONFIG,   demarshal_ip4_config,        &priv->ip4_config },
+		{ NM_DEVICE_STATE,        nm_object_demarshal_generic, &priv->state },
+		{ NULL },
+	};
+
+	nm_object_handle_properties_changed (NM_OBJECT (device),
+	                                     priv->proxy,
+	                                     property_changed_info);
 }
 
 static GObject*
@@ -64,15 +123,12 @@
 
 	priv = NM_DEVICE_GET_PRIVATE (object);
 
-	priv->device_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
-													NM_DBUS_SERVICE,
-													nm_object_get_path (object),
-													NM_DBUS_INTERFACE_DEVICE);
-
-	dbus_g_proxy_add_signal (priv->device_proxy, "StateChanged", G_TYPE_UINT, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal (priv->device_proxy, "StateChanged",
-								 G_CALLBACK (device_state_change_proxy),
-								 object, NULL);
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+											 NM_DBUS_SERVICE,
+											 nm_object_get_path (object),
+											 NM_DBUS_INTERFACE_DEVICE);
+
+	register_for_property_changed (NM_DEVICE (object));
 
 	return G_OBJECT (object);
 }
@@ -89,7 +145,9 @@
 
 	priv->disposed = TRUE;
 
-	g_object_unref (priv->device_proxy);
+	g_object_unref (priv->proxy);
+	if (priv->ip4_config)
+		g_object_unref (priv->ip4_config);
 
 	G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
 }
@@ -99,6 +157,9 @@
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
 
+	g_free (priv->iface);
+	g_free (priv->udi);
+	g_free (priv->driver);
 	g_free (priv->product);
 	g_free (priv->vendor);
 
@@ -106,6 +167,45 @@
 }
 
 static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDevice *device = NM_DEVICE (object);
+
+	switch (prop_id) {
+	case PROP_UDI:
+		g_value_set_string (value, nm_device_get_udi (device));
+		break;
+	case PROP_INTERFACE:
+		g_value_set_string (value, nm_device_get_iface (device));
+		break;
+	case PROP_DRIVER:
+		g_value_set_string (value, nm_device_get_driver (device));
+		break;
+	case PROP_CAPABILITIES:
+		g_value_set_uint (value, nm_device_get_capabilities (device));
+		break;
+	case PROP_IP4_CONFIG:
+		g_value_set_object (value, nm_device_get_ip4_config (device));
+		break;
+	case PROP_STATE:
+		g_value_set_uint (value, nm_device_get_state (device));
+		break;
+	case PROP_PRODUCT:
+		g_value_set_string (value, nm_device_get_product (device));
+		break;
+	case PROP_VENDOR:
+		g_value_set_string (value, nm_device_get_vendor (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
 nm_device_class_init (NMDeviceClass *device_class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (device_class);
@@ -114,98 +214,226 @@
 
 	/* virtual methods */
 	object_class->constructor = constructor;
+	object_class->get_property = get_property;
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
 
-	/* signals */
-	signals[STATE_CHANGED] =
-		g_signal_new ("state-changed",
-					  G_OBJECT_CLASS_TYPE (object_class),
-					  G_SIGNAL_RUN_FIRST,
-					  G_STRUCT_OFFSET (NMDeviceClass, state_changed),
-					  NULL, NULL,
-					  g_cclosure_marshal_VOID__UINT,
-					  G_TYPE_NONE, 1,
-					  G_TYPE_UINT);
+	/* properties */
+	g_object_class_install_property
+		(object_class, PROP_INTERFACE,
+		 g_param_spec_string (NM_DEVICE_INTERFACE,
+						  "Interface",
+						  "Interface name",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_UDI,
+		 g_param_spec_string (NM_DEVICE_UDI,
+						  "UDI",
+						  "HAL UDI",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_DRIVER,
+		 g_param_spec_string (NM_DEVICE_DRIVER,
+						  "Driver",
+						  "Driver",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_CAPABILITIES,
+		 g_param_spec_uint (NM_DEVICE_CAPABILITIES,
+						  "Capabilities",
+						  "Capabilities",
+						  0, G_MAXUINT32, 0,
+						  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_IP4_CONFIG,
+		 g_param_spec_object (NM_DEVICE_IP4_CONFIG,
+						  "IP4 Config",
+						  "IP4 Config",
+						  NM_TYPE_IP4_CONFIG,
+						  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_STATE,
+		 g_param_spec_uint (NM_DEVICE_STATE,
+						  "State",
+						  "State",
+						  0, G_MAXUINT32, 0,
+						  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_VENDOR,
+		 g_param_spec_string (NM_DEVICE_VENDOR,
+						  "Vendor",
+						  "Vendor string",
+						  NULL,
+						  G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_PRODUCT,
+		 g_param_spec_string (NM_DEVICE_PRODUCT,
+						  "Product",
+						  "Product string",
+						  NULL,
+						  G_PARAM_READABLE));
 }
 
-static void
-device_state_change_proxy (DBusGProxy *proxy, guint state, gpointer user_data)
+GObject *
+nm_device_new (DBusGConnection *connection, const char *path)
 {
-	NMDevice *device = NM_DEVICE (user_data);
-	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
+	DBusGProxy *proxy;
+	GError *err = NULL;
+	GValue value = {0,};
+	GType dtype = 0;
+	NMDevice *device = NULL;
+
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
 
-	if (priv->state != state) {
-		priv->state = state;
-		g_signal_emit (device, signals[STATE_CHANGED], 0, state);
+	proxy = dbus_g_proxy_new_for_name (connection,
+									   NM_DBUS_SERVICE,
+									   path,
+									   "org.freedesktop.DBus.Properties");
+	if (!proxy) {
+		g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
+		return NULL;
 	}
-}
 
-NMDevice *
-nm_device_new (DBusGConnection *connection, const char *path)
-{
-	return (NMDevice *) g_object_new (NM_TYPE_DEVICE,
-									  NM_OBJECT_CONNECTION, connection,
-									  NM_OBJECT_PATH, path,
-									  NULL);
+	if (!dbus_g_proxy_call (proxy,
+						    "Get", &err,
+						    G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
+						    G_TYPE_STRING, "DeviceType",
+						    G_TYPE_INVALID,
+						    G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
+		g_warning ("Error in get_property: %s\n", err->message);
+		g_error_free (err);
+		goto out;
+	}
+
+	switch (g_value_get_uint (&value)) {
+	case DEVICE_TYPE_802_3_ETHERNET:
+		dtype = NM_TYPE_DEVICE_802_3_ETHERNET;
+		break;
+	case DEVICE_TYPE_802_11_WIRELESS:
+		dtype = NM_TYPE_DEVICE_802_11_WIRELESS;
+		break;
+	case DEVICE_TYPE_GSM:
+		dtype = NM_TYPE_GSM_DEVICE;
+		break;
+	case DEVICE_TYPE_CDMA:
+		dtype = NM_TYPE_CDMA_DEVICE;
+		break;
+	default:
+		g_warning ("Unknown device type %d", g_value_get_uint (&value));
+		break;
+	}
+
+	if (dtype) {
+		device = (NMDevice *) g_object_new (dtype,
+											NM_OBJECT_DBUS_CONNECTION, connection,
+											NM_OBJECT_DBUS_PATH, path,
+											NULL);
+	}
+
+out:
+	g_object_unref (proxy);
+	return G_OBJECT (device);
 }
 
-char *
+const char *
 nm_device_get_iface (NMDevice *device)
 {
+	NMDevicePrivate *priv;
+
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	return nm_object_get_string_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Interface");
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (!priv->iface) {
+		priv->iface = nm_object_get_string_property (NM_OBJECT (device),
+		                                             NM_DBUS_INTERFACE_DEVICE,
+		                                             "Interface");
+	}
+
+	return priv->iface;
 }
 
-char *
+const char *
 nm_device_get_udi (NMDevice *device)
 {
+	NMDevicePrivate *priv;
+
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	return nm_object_get_string_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Udi");
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (!priv->udi) {
+		priv->udi = nm_object_get_string_property (NM_OBJECT (device),
+		                                           NM_DBUS_INTERFACE_DEVICE,
+		                                           "Udi");
+	}
+
+	return priv->udi;
 }
 
-char *
+const char *
 nm_device_get_driver (NMDevice *device)
 {
+	NMDevicePrivate *priv;
+
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	return nm_object_get_string_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Driver");
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (!priv->driver) {
+		priv->driver = nm_object_get_string_property (NM_OBJECT (device),
+		                                              NM_DBUS_INTERFACE_DEVICE,
+		                                              "Driver");
+	}
+
+	return priv->driver;
 }
 
 guint32
 nm_device_get_capabilities (NMDevice *device)
 {
-	g_return_val_if_fail (NM_IS_DEVICE (device), 0);
-
-	return nm_object_get_uint_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Capabilities");
-}
+	NMDevicePrivate *priv;
 
-guint32
-nm_device_get_ip4_address (NMDevice *device)
-{
 	g_return_val_if_fail (NM_IS_DEVICE (device), 0);
 
-	return nm_object_get_uint_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Ip4Address");
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (!priv->capabilities) {
+		priv->capabilities = nm_object_get_uint_property (NM_OBJECT (device),
+		                                                  NM_DBUS_INTERFACE_DEVICE,
+		                                                  "Capabilities");
+	}
+
+	return priv->capabilities;
 }
 
 NMIP4Config *
 nm_device_get_ip4_config (NMDevice *device)
 {
+	NMDevicePrivate *priv;
 	char *path;
-	NMIP4Config *config = NULL;
+	GValue value = { 0, };
 
 	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
 
-	path = nm_object_get_object_path_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Ip4Config");
+	priv = NM_DEVICE_GET_PRIVATE (device);
+	if (priv->ip4_config)
+		return priv->ip4_config;
 
-	if (path) {
-		config = nm_ip4_config_new (nm_object_get_connection (NM_OBJECT (device)), path);
-		g_free (path);
-	}
+	path = nm_object_get_object_path_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "Ip4Config");
 
-	return config;
+	g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH);
+	g_value_take_boxed (&value, path);
+	demarshal_ip4_config (NM_OBJECT (device), NULL, &value, &priv->ip4_config);
+	g_value_unset (&value);
+	return priv->ip4_config;
 }
 
 NMDeviceState
@@ -216,9 +444,11 @@
 	g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN);
 
 	priv = NM_DEVICE_GET_PRIVATE (device);
-
-	if (priv->state == NM_DEVICE_STATE_UNKNOWN)
-		priv->state = nm_object_get_uint_property (NM_OBJECT (device), NM_DBUS_INTERFACE_DEVICE, "State");
+	if (priv->state == NM_DEVICE_STATE_UNKNOWN) {
+		priv->state = nm_object_get_uint_property (NM_OBJECT (device), 
+		                                           NM_DBUS_INTERFACE_DEVICE,
+		                                           "State");
+	}
 
 	return priv->state;
 }
@@ -316,7 +546,7 @@
 {
 	NMDevicePrivate *priv;
 	DBusGConnection *connection;
-	char *udi;
+	const char *udi;
 	char *orig_dev_udi = NULL;
 	char *pd_parent_udi = NULL;
 
@@ -334,7 +564,6 @@
 	/* First, get the originating device info */
 	udi = nm_device_get_udi (device);
 	orig_dev_udi = get_product_and_vendor (connection, udi, TRUE, FALSE, &priv->product, &priv->vendor);
-	g_free (udi);
 
 	/* Ignore product and vendor for the Network Interface */
 	if (priv->product || priv->vendor) {
@@ -363,6 +592,9 @@
 		g_free (ignore);
 	}
 	g_free (pd_parent_udi);
+
+	g_object_notify (G_OBJECT (device), NM_DEVICE_VENDOR);
+	g_object_notify (G_OBJECT (device), NM_DEVICE_PRODUCT);
 }
 
 const char *
@@ -391,37 +623,3 @@
 	return priv->vendor;
 }
 
-NMDeviceType
-nm_device_type_for_path (DBusGConnection *connection,
-						 const char *path)
-{
-	DBusGProxy *proxy;
-	GError *err = NULL;
-	GValue value = {0,};
-	NMDeviceType type = DEVICE_TYPE_UNKNOWN;
-
-	g_return_val_if_fail (connection != NULL, type);
-	g_return_val_if_fail (path != NULL, type);
-
-	proxy = dbus_g_proxy_new_for_name (connection,
-									   NM_DBUS_SERVICE,
-									   path,
-									   "org.freedesktop.DBus.Properties");
-
-	if (dbus_g_proxy_call (proxy,
-						   "Get", &err,
-						   G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
-						   G_TYPE_STRING, "DeviceType",
-						   G_TYPE_INVALID,
-						   G_TYPE_VALUE, &value,
-						   G_TYPE_INVALID)) {
-		type = (NMDeviceType) g_value_get_uint (&value);
-	} else {
-		g_warning ("Error in get_property: %s\n", err->message);
-		g_error_free (err);
-	}
-
-	g_object_unref (proxy);
-
-	return type;
-}

Modified: trunk/libnm-glib/nm-device.h
==============================================================================
--- trunk/libnm-glib/nm-device.h	(original)
+++ trunk/libnm-glib/nm-device.h	Mon Mar 24 15:17:30 2008
@@ -18,34 +18,35 @@
 #define NM_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE))
 #define NM_DEVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE, NMDeviceClass))
 
+#define NM_DEVICE_UDI "udi"
+#define NM_DEVICE_INTERFACE "interface"
+#define NM_DEVICE_DRIVER "driver"
+#define NM_DEVICE_CAPABILITIES "capabilities"
+#define NM_DEVICE_IP4_CONFIG "ip4-config"
+#define NM_DEVICE_STATE "state"
+#define NM_DEVICE_VENDOR "vendor"
+#define NM_DEVICE_PRODUCT "product"
+
 typedef struct {
 	NMObject parent;
 } NMDevice;
 
 typedef struct {
 	NMObjectClass parent;
-
-	/* Signals */
-	void (*state_changed) (NMDevice *device, NMDeviceState state);
 } NMDeviceClass;
 
 GType nm_device_get_type (void);
 
-NMDevice    *nm_device_new               (DBusGConnection *connection,
-										  const char *path);
+GObject * nm_device_new (DBusGConnection *connection, const char *path);
 
-char         *nm_device_get_iface        (NMDevice *device);
-char         *nm_device_get_udi          (NMDevice *device);
-char         *nm_device_get_driver       (NMDevice *device);
+const char *  nm_device_get_iface        (NMDevice *device);
+const char *  nm_device_get_udi          (NMDevice *device);
+const char *  nm_device_get_driver       (NMDevice *device);
 guint32       nm_device_get_capabilities (NMDevice *device);
-guint32       nm_device_get_ip4_address  (NMDevice *device);
-NMIP4Config  *nm_device_get_ip4_config   (NMDevice *device);
+NMIP4Config * nm_device_get_ip4_config   (NMDevice *device);
 NMDeviceState nm_device_get_state        (NMDevice *device);
-const char   *nm_device_get_product      (NMDevice *device);
-const char   *nm_device_get_vendor       (NMDevice *device);
-
-NMDeviceType  nm_device_type_for_path    (DBusGConnection *connection,
-										  const char *path);
+const char *  nm_device_get_product      (NMDevice *device);
+const char *  nm_device_get_vendor       (NMDevice *device);
 
 G_END_DECLS
 

Modified: trunk/libnm-glib/nm-gsm-device.c
==============================================================================
--- trunk/libnm-glib/nm-gsm-device.c	(original)
+++ trunk/libnm-glib/nm-gsm-device.c	Mon Mar 24 15:17:30 2008
@@ -76,7 +76,7 @@
 	g_return_val_if_fail (path != NULL, NULL);
 
 	return (NMGsmDevice *) g_object_new (NM_TYPE_GSM_DEVICE,
-								  NM_OBJECT_CONNECTION, connection,
-								  NM_OBJECT_PATH, path,
+								  NM_OBJECT_DBUS_CONNECTION, connection,
+								  NM_OBJECT_DBUS_PATH, path,
 								  NULL);
 }

Modified: trunk/libnm-glib/nm-ip4-config.c
==============================================================================
--- trunk/libnm-glib/nm-ip4-config.c	(original)
+++ trunk/libnm-glib/nm-ip4-config.c	Mon Mar 24 15:17:30 2008
@@ -1,133 +1,461 @@
+#include <string.h>
+
 #include "nm-ip4-config.h"
 #include "NetworkManager.h"
-
-#define INTERFACE NM_DBUS_INTERFACE ".IP4Config"
+#include "nm-types-private.h"
+#include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_OBJECT)
 
+#define NM_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP4_CONFIG, NMIP4ConfigPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	guint32 address;
+	guint32 gateway;
+	guint32 netmask;
+	guint32 broadcast;
+	char *hostname;
+	GArray *nameservers;
+	GPtrArray *domains;
+	char *nis_domain;
+	GArray *nis_servers;
+} NMIP4ConfigPrivate;
+
+enum {
+	PROP_0,
+	PROP_ADDRESS,
+	PROP_GATEWAY,
+	PROP_NETMASK,
+	PROP_BROADCAST,
+	PROP_HOSTNAME,
+	PROP_NAMESERVERS,
+	PROP_DOMAINS,
+	PROP_NIS_DOMAIN,
+	PROP_NIS_SERVERS,
+
+	LAST_PROP
+};
+
 static void
 nm_ip4_config_init (NMIP4Config *config)
 {
 }
 
+static gboolean
+demarshal_ip4_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	if (!nm_uint_array_demarshal (value, (GArray **) field))
+		return FALSE;
+
+	if (!strcmp (pspec->name, NM_IP4_CONFIG_NAMESERVERS))
+		g_object_notify (G_OBJECT (object), NM_IP4_CONFIG_NAMESERVERS);
+	else if (!strcmp (pspec->name, NM_IP4_CONFIG_NIS_SERVERS))
+		g_object_notify (G_OBJECT (object), NM_IP4_CONFIG_NAMESERVERS);
+	return TRUE;
+}
+
+static gboolean
+demarshal_domains (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+	if (!nm_string_array_demarshal (value, (GPtrArray **) field))
+		return FALSE;
+
+	g_object_notify (G_OBJECT (object), NM_IP4_CONFIG_DOMAINS);
+	return TRUE;
+}
+
+static void
+register_for_property_changed (NMIP4Config *config)
+{
+	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	const NMPropertiesChangedInfo property_changed_info[] = {
+		{ NM_IP4_CONFIG_ADDRESS,     nm_object_demarshal_generic,  &priv->address },
+		{ NM_IP4_CONFIG_GATEWAY,     nm_object_demarshal_generic,  &priv->gateway },
+		{ NM_IP4_CONFIG_NETMASK,     nm_object_demarshal_generic,  &priv->netmask },
+		{ NM_IP4_CONFIG_BROADCAST,   nm_object_demarshal_generic,  &priv->broadcast },
+		{ NM_IP4_CONFIG_HOSTNAME,    nm_object_demarshal_generic,  &priv->hostname },
+		{ NM_IP4_CONFIG_NAMESERVERS, demarshal_ip4_array,          &priv->nameservers },
+		{ NM_IP4_CONFIG_DOMAINS,     demarshal_domains,            &priv->domains },
+		{ NM_IP4_CONFIG_NIS_DOMAIN,  nm_object_demarshal_generic,  &priv->nis_domain },
+		{ NM_IP4_CONFIG_NIS_SERVERS, demarshal_ip4_array,          &priv->nis_servers },
+		{ NULL },
+	};
+
+	nm_object_handle_properties_changed (NM_OBJECT (config),
+	                                     priv->proxy,
+	                                     property_changed_info);
+}
+
+static GObject*
+constructor (GType type,
+		   guint n_construct_params,
+		   GObjectConstructParam *construct_params)
+{
+	NMObject *object;
+	DBusGConnection *connection;
+	NMIP4ConfigPrivate *priv;
+
+	object = (NMObject *) G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructor (type,
+																 n_construct_params,
+																 construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+	connection = nm_object_get_connection (object);
+
+	priv->proxy = dbus_g_proxy_new_for_name (connection,
+										   NM_DBUS_SERVICE,
+										   nm_object_get_path (object),
+										   NM_DBUS_INTERFACE_IP4_CONFIG);
+
+	register_for_property_changed (NM_IP4_CONFIG (object));
+
+	return G_OBJECT (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+	int i;
+
+	g_free (priv->hostname);
+	g_free (priv->nis_domain);
+	if (priv->nameservers)
+		g_array_free (priv->nameservers, TRUE);
+	if (priv->nis_servers)
+		g_array_free (priv->nis_servers, TRUE);
+
+	if (priv->domains) {
+		for (i = 0; i < priv->domains->len; i++)
+			g_free (g_ptr_array_index (priv->domains, i));
+		g_ptr_array_free (priv->domains, TRUE);
+	}
+
+	G_OBJECT_CLASS (nm_ip4_config_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMIP4Config *self = NM_IP4_CONFIG (object);
+
+	switch (prop_id) {
+	case PROP_ADDRESS:
+		g_value_set_uint (value, nm_ip4_config_get_address (self));
+		break;
+	case PROP_GATEWAY:
+		g_value_set_uint (value, nm_ip4_config_get_gateway (self));
+		break;
+	case PROP_NETMASK:
+		g_value_set_uint (value, nm_ip4_config_get_netmask (self));
+		break;
+	case PROP_BROADCAST:
+		g_value_set_uint (value, nm_ip4_config_get_broadcast (self));
+		break;
+	case PROP_HOSTNAME:
+		g_value_set_string (value, nm_ip4_config_get_hostname (self));
+		break;
+	case PROP_NAMESERVERS:
+		g_value_set_boxed (value, nm_ip4_config_get_nameservers (self));
+		break;
+	case PROP_DOMAINS:
+		g_value_set_boxed (value, nm_ip4_config_get_domains (self));
+		break;
+	case PROP_NIS_DOMAIN:
+		g_value_set_string (value, nm_ip4_config_get_nis_domain (self));
+		break;
+	case PROP_NIS_SERVERS:
+		g_value_set_boxed (value, nm_ip4_config_get_nis_servers (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
 static void
 nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
 {
+	GObjectClass *object_class = G_OBJECT_CLASS (config_class);
+
+	g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate));
+
+	/* virtual methods */
+	object_class->constructor = constructor;
+	object_class->get_property = get_property;
+	object_class->finalize = finalize;
+
+	/* properties */
+	g_object_class_install_property
+		(object_class, PROP_ADDRESS,
+		 g_param_spec_uint (NM_IP4_CONFIG_ADDRESS,
+						    "Address",
+						    "Address",
+						    0, G_MAXUINT32, 0,
+						    G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_GATEWAY,
+		 g_param_spec_uint (NM_IP4_CONFIG_GATEWAY,
+						    "Gateway",
+						    "Gateway",
+						    0, G_MAXUINT32, 0,
+						    G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_NETMASK,
+		 g_param_spec_uint (NM_IP4_CONFIG_NETMASK,
+						    "Netmask",
+						    "Netmask",
+						    0, G_MAXUINT32, 0,
+						    G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_BROADCAST,
+		 g_param_spec_uint (NM_IP4_CONFIG_BROADCAST,
+						    "Broadcast",
+						    "Broadcast",
+						    0, G_MAXUINT32, 0,
+						    G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_HOSTNAME,
+		 g_param_spec_string (NM_IP4_CONFIG_HOSTNAME,
+						    "Hostname",
+						    "Hostname",
+						    NULL,
+						    G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_NAMESERVERS,
+		 g_param_spec_boxed (NM_IP4_CONFIG_NAMESERVERS,
+						    "Nameservers",
+						    "Nameservers",
+						    NM_TYPE_UINT_ARRAY,
+						    G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_DOMAINS,
+		 g_param_spec_boxed (NM_IP4_CONFIG_DOMAINS,
+						    "Domains",
+						    "Domains",
+						    NM_TYPE_STRING_ARRAY,
+						    G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_NIS_DOMAIN,
+		 g_param_spec_string (NM_IP4_CONFIG_NIS_DOMAIN,
+						    "NIS domain",
+						    "NIS domain",
+						    NULL,
+						    G_PARAM_READABLE));
+
+	g_object_class_install_property
+		(object_class, PROP_NIS_SERVERS,
+		 g_param_spec_boxed (NM_IP4_CONFIG_NIS_SERVERS,
+						    "NIS servers",
+						    "NIS servers",
+						    NM_TYPE_UINT_ARRAY,
+						    G_PARAM_READABLE));
 }
 
-NMIP4Config *
+GObject *
 nm_ip4_config_new (DBusGConnection *connection, const char *object_path)
 {
-	return (NMIP4Config *) g_object_new (NM_TYPE_IP4_CONFIG,
-										 NM_OBJECT_CONNECTION, connection,
-										 NM_OBJECT_PATH, object_path,
-										 NULL);
+	return (GObject *) g_object_new (NM_TYPE_IP4_CONFIG,
+									 NM_OBJECT_DBUS_CONNECTION, connection,
+									 NM_OBJECT_DBUS_PATH, object_path,
+									 NULL);
 }
 
 guint32
 nm_ip4_config_get_address (NMIP4Config *config)
 {
+	NMIP4ConfigPrivate *priv;
+
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
 
-	return nm_object_get_uint_property (NM_OBJECT (config), INTERFACE, "Address");
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	if (!priv->address) {
+		priv->address = nm_object_get_uint_property (NM_OBJECT (config),
+		                                             NM_DBUS_INTERFACE_IP4_CONFIG,
+		                                             "Address");
+	}
+
+	return priv->address;
 }
 
 guint32
 nm_ip4_config_get_gateway (NMIP4Config *config)
 {
+	NMIP4ConfigPrivate *priv;
+
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
 
-	return nm_object_get_uint_property (NM_OBJECT (config), INTERFACE, "Gateway");
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	if (!priv->gateway) {
+		priv->gateway = nm_object_get_uint_property (NM_OBJECT (config),
+		                                             NM_DBUS_INTERFACE_IP4_CONFIG,
+		                                             "Gateway");
+	}
+
+	return priv->gateway;
 }
 
 guint32
 nm_ip4_config_get_netmask (NMIP4Config *config)
 {
+	NMIP4ConfigPrivate *priv;
+
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
 
-	return nm_object_get_uint_property (NM_OBJECT (config), INTERFACE, "Netmask");
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	if (!priv->netmask) {
+		priv->netmask = nm_object_get_uint_property (NM_OBJECT (config),
+		                                             NM_DBUS_INTERFACE_IP4_CONFIG,
+		                                             "Netmask");
+	}
+
+	return priv->netmask;
 }
 
 guint32
 nm_ip4_config_get_broadcast (NMIP4Config *config)
 {
+	NMIP4ConfigPrivate *priv;
+
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), 0);
 
-	return nm_object_get_uint_property (NM_OBJECT (config), INTERFACE, "Broadcast");
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	if (!priv->broadcast) {
+		priv->broadcast = nm_object_get_uint_property (NM_OBJECT (config),
+		                                               NM_DBUS_INTERFACE_IP4_CONFIG,
+		                                               "Broadcast");
+	}
+
+	return priv->broadcast;
 }
 
-char *
+const char *
 nm_ip4_config_get_hostname (NMIP4Config *config)
 {
+	NMIP4ConfigPrivate *priv;
+
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	return nm_object_get_string_property (NM_OBJECT (config), INTERFACE, "Hostname");
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	if (!priv->hostname) {
+		priv->hostname = nm_object_get_string_property (NM_OBJECT (config),
+		                                                NM_DBUS_INTERFACE_IP4_CONFIG,
+		                                                "Hostname");
+	}
+
+	return priv->hostname;
 }
 
-GArray *
+const GArray *
 nm_ip4_config_get_nameservers (NMIP4Config *config)
 {
+	NMIP4ConfigPrivate *priv;
 	GArray *array = NULL;
 	GValue value = {0,};
 
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	if (nm_object_get_property (NM_OBJECT (config),
-								INTERFACE,
-								"Nameservers",
-								&value))
-		array = (GArray *) g_value_get_boxed (&value);
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	if (!priv->nameservers) {
+		if (nm_object_get_property (NM_OBJECT (config),
+		                            NM_DBUS_INTERFACE_IP4_CONFIG,
+		                            "Nameservers",
+		                            &value)) {
+			array = (GArray *) g_value_get_boxed (&value);
+			if (array && array->len) {
+				priv->nameservers = g_array_sized_new (FALSE, TRUE, sizeof (guint32), array->len);
+				g_array_append_vals (priv->nameservers, array->data, array->len);
+			}
+			g_value_unset (&value);
+		}
+	}
 
-	return array;
+	return priv->nameservers;
 }
 
-char **
+const GPtrArray *
 nm_ip4_config_get_domains (NMIP4Config *config)
 {
-	char **array = NULL;
+	NMIP4ConfigPrivate *priv;
 	GValue value = {0,};
 
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	if (nm_object_get_property (NM_OBJECT (config),
-								INTERFACE,
-								"Domains",
-								&value))
-		array = (char **) g_value_get_boxed (&value);
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	if (!priv->domains) {
+		if (nm_object_get_property (NM_OBJECT (config),
+									NM_DBUS_INTERFACE_IP4_CONFIG,
+									"Domains",
+									&value)) {
+			char **array = NULL, **p;
+
+			array = (char **) g_value_get_boxed (&value);
+			if (array && g_strv_length (array)) {
+				priv->domains = g_ptr_array_sized_new (g_strv_length (array));
+				for (p = array; *p; p++)
+					g_ptr_array_add (priv->domains, g_strdup (*p));
+			}
+			g_value_unset (&value);
+		}
+	}
 
-	return array;
+	return priv->domains;
 }
 
-char *
+const char *
 nm_ip4_config_get_nis_domain (NMIP4Config *config)
 {
-	char *address = NULL;
-	GValue value = {0,};
+	NMIP4ConfigPrivate *priv;
 
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	if (nm_object_get_property (NM_OBJECT (config),
-								INTERFACE,
-								"NisDomain",
-								&value))
-		address = g_strdup (g_value_get_string (&value));
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	if (!priv->nis_domain) {
+		priv->nis_domain = nm_object_get_string_property (NM_OBJECT (config),
+		                                                  NM_DBUS_INTERFACE_IP4_CONFIG,
+		                                                  "NisDomain");
+	}
 
-	return address;
+	return priv->nis_domain;
 }
 
 GArray *
 nm_ip4_config_get_nis_servers (NMIP4Config *config)
 {
+	NMIP4ConfigPrivate *priv;
 	GArray *array = NULL;
 	GValue value = {0,};
 
 	g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
 
-	if (nm_object_get_property (NM_OBJECT (config),
-								INTERFACE,
-								"NisServers",
-								&value))
-		array = (GArray *) g_value_get_boxed (&value);
+	priv = NM_IP4_CONFIG_GET_PRIVATE (config);
+	if (!priv->nis_servers) {
+		if (nm_object_get_property (NM_OBJECT (config),
+									NM_DBUS_INTERFACE_IP4_CONFIG,
+									"NisServers",
+									&value)) {
+			array = (GArray *) g_value_get_boxed (&value);
+			if (array && array->len) {
+				priv->nis_servers = g_array_sized_new (FALSE, TRUE, sizeof (guint32), array->len);
+				g_array_append_vals (priv->nis_servers, array->data, array->len);
+			}
+			g_value_unset (&value);
+		}
+	}
 
-	return array;
+	return priv->nis_servers;
 }

Modified: trunk/libnm-glib/nm-ip4-config.h
==============================================================================
--- trunk/libnm-glib/nm-ip4-config.h	(original)
+++ trunk/libnm-glib/nm-ip4-config.h	Mon Mar 24 15:17:30 2008
@@ -23,20 +23,29 @@
 	NMObjectClass parent;
 } NMIP4ConfigClass;
 
+#define NM_IP4_CONFIG_ADDRESS "address"
+#define NM_IP4_CONFIG_GATEWAY "gateway"
+#define NM_IP4_CONFIG_NETMASK "netmask"
+#define NM_IP4_CONFIG_BROADCAST "broadcast"
+#define NM_IP4_CONFIG_HOSTNAME "hostname"
+#define NM_IP4_CONFIG_NAMESERVERS "nameservers"
+#define NM_IP4_CONFIG_DOMAINS "domains"
+#define NM_IP4_CONFIG_NIS_DOMAIN "nis-domain"
+#define NM_IP4_CONFIG_NIS_SERVERS "nis-servers"
+
 GType nm_ip4_config_get_type (void);
 
-NMIP4Config *nm_ip4_config_new (DBusGConnection *connection,
-								const char *object_path);
+GObject *nm_ip4_config_new (DBusGConnection *connection, const char *object_path);
 
-guint32  nm_ip4_config_get_address     (NMIP4Config *config);
-guint32  nm_ip4_config_get_gateway     (NMIP4Config *config);
-guint32  nm_ip4_config_get_netmask     (NMIP4Config *config);
-guint32  nm_ip4_config_get_broadcast   (NMIP4Config *config);
-char    *nm_ip4_config_get_hostname    (NMIP4Config *config);
-GArray  *nm_ip4_config_get_nameservers (NMIP4Config *config);
-char   **nm_ip4_config_get_domains     (NMIP4Config *config);
-char    *nm_ip4_config_get_nis_domain  (NMIP4Config *config);
-GArray  *nm_ip4_config_get_nis_servers (NMIP4Config *config);
+guint32          nm_ip4_config_get_address     (NMIP4Config *config);
+guint32          nm_ip4_config_get_gateway     (NMIP4Config *config);
+guint32          nm_ip4_config_get_netmask     (NMIP4Config *config);
+guint32          nm_ip4_config_get_broadcast   (NMIP4Config *config);
+const char *     nm_ip4_config_get_hostname    (NMIP4Config *config);
+const GArray *   nm_ip4_config_get_nameservers (NMIP4Config *config);
+const GPtrArray *nm_ip4_config_get_domains     (NMIP4Config *config);
+const char *     nm_ip4_config_get_nis_domain  (NMIP4Config *config);
+GArray *         nm_ip4_config_get_nis_servers (NMIP4Config *config);
 
 G_END_DECLS
 

Added: trunk/libnm-glib/nm-object-cache.c
==============================================================================
--- (empty file)
+++ trunk/libnm-glib/nm-object-cache.c	Mon Mar 24 15:17:30 2008
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <glib.h>
+#include "nm-object-cache.h"
+#include "nm-object.h"
+
+static GStaticMutex cache_mutex = G_STATIC_MUTEX_INIT;
+static GHashTable *cache = NULL;
+
+static void
+_init_cache (void)
+{
+	if (G_UNLIKELY (cache == NULL))
+		cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+}
+
+void
+nm_object_cache_remove_by_path (const char *path)
+{
+	g_static_mutex_lock (&cache_mutex);
+	_init_cache ();
+	g_hash_table_remove (cache, path);
+	g_static_mutex_unlock (&cache_mutex);
+}
+
+void
+nm_object_cache_remove_by_object (NMObject *object)
+{
+	g_static_mutex_lock (&cache_mutex);
+	_init_cache ();
+	g_hash_table_remove (cache, nm_object_get_path (object));
+	g_static_mutex_unlock (&cache_mutex);
+}
+
+void
+nm_object_cache_add (NMObject *object)
+{
+	char *path;
+
+	g_static_mutex_lock (&cache_mutex);
+	_init_cache ();
+	path = g_strdup (nm_object_get_path (object));
+	g_hash_table_insert (cache, path, object);
+	g_object_set_data_full (G_OBJECT (object), "nm-object-cache-tag",
+	                        path, (GDestroyNotify) nm_object_cache_remove_by_path);
+	g_static_mutex_unlock (&cache_mutex);
+}
+
+NMObject *
+nm_object_cache_get (const char *path)
+{
+	NMObject *object;
+
+	g_static_mutex_lock (&cache_mutex);
+	_init_cache ();
+	object = g_hash_table_lookup (cache, path);
+	g_static_mutex_unlock (&cache_mutex);
+	return object;
+}
+

Added: trunk/libnm-glib/nm-object-cache.h
==============================================================================
--- (empty file)
+++ trunk/libnm-glib/nm-object-cache.h	Mon Mar 24 15:17:30 2008
@@ -0,0 +1,39 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_OBJECT_CACHE_H
+#define NM_OBJECT_CACHE_H
+
+#include <glib/gtypes.h>
+#include <glib-object.h>
+#include "nm-object.h"
+
+G_BEGIN_DECLS
+
+NMObject *nm_object_cache_get (const char *path);
+void nm_object_cache_add (NMObject *object);
+void nm_object_cache_remove_by_object (NMObject *object);
+void nm_object_cache_remove_by_path (const char *path);
+
+G_END_DECLS
+
+#endif /* NM_OBJECT_CACHE_H */

Added: trunk/libnm-glib/nm-object-private.h
==============================================================================
--- (empty file)
+++ trunk/libnm-glib/nm-object-private.h	Mon Mar 24 15:17:30 2008
@@ -0,0 +1,69 @@
+#ifndef NM_OBJECT_PRIVATE_H
+#define NM_OBJECT_PRIVATE_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "nm-object.h"
+
+typedef gboolean (*PropChangedMarshalFunc) (NMObject *, GParamSpec *, GValue *, gpointer);
+typedef GObject * (*NMObjectCreatorFunc) (DBusGConnection *, const char *);
+
+typedef struct {
+	const char *name;
+	PropChangedMarshalFunc func;
+	gpointer field;
+} NMPropertiesChangedInfo;
+
+
+void             nm_object_handle_properties_changed (NMObject *object,
+                                                      DBusGProxy *proxy,
+                                                      const NMPropertiesChangedInfo *info);
+
+gboolean nm_object_demarshal_generic (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
+
+
+/* DBus property accessors */
+
+gboolean nm_object_get_property (NMObject *object,
+								 const char *interface,
+								 const char *prop_name,
+								 GValue *value);
+
+void nm_object_set_property (NMObject *object,
+							 const char *interface,
+							 const char *prop_name,
+							 GValue *value);
+
+char *nm_object_get_string_property (NMObject *object,
+									 const char *interface,
+									 const char *prop_name);
+
+char *nm_object_get_object_path_property (NMObject *object,
+										  const char *interface,
+										  const char *prop_name);
+
+gint32 nm_object_get_int_property (NMObject *object,
+								   const char *interface,
+								   const char *prop_name);
+
+guint32 nm_object_get_uint_property (NMObject *object,
+									 const char *interface,
+									 const char *prop_name);
+
+gboolean nm_object_get_boolean_property (NMObject *object,
+										const char *interface,
+										const char *prop_name);
+
+gint8 nm_object_get_byte_property (NMObject *object,
+								   const char *interface,
+								   const char *prop_name);
+
+gdouble nm_object_get_double_property (NMObject *object,
+									   const char *interface,
+									   const char *prop_name);
+
+GByteArray *nm_object_get_byte_array_property (NMObject *object,
+											   const char *interface,
+											   const char *prop_name);
+
+#endif /* NM_OBJECT_PRIVATE_H */

Modified: trunk/libnm-glib/nm-object.c
==============================================================================
--- trunk/libnm-glib/nm-object.c	(original)
+++ trunk/libnm-glib/nm-object.c	Mon Mar 24 15:17:30 2008
@@ -1,17 +1,29 @@
 /* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
 
+#include <string.h>
 #include <nm-utils.h>
-#include "nm-object.h"
 #include "NetworkManager.h"
+#include "nm-object.h"
+#include "nm-object-cache.h"
+#include "nm-object-private.h"
+#include "nm-dbus-glib-types.h"
+
 
 G_DEFINE_ABSTRACT_TYPE (NMObject, nm_object, G_TYPE_OBJECT)
 
 #define NM_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OBJECT, NMObjectPrivate))
 
 typedef struct {
+	PropChangedMarshalFunc func;
+	gpointer field;
+} PropChangedInfo;
+
+typedef struct {
 	DBusGConnection *connection;
 	char *path;
 	DBusGProxy *properties_proxy;
+	GSList *pcs;
+	NMObject *parent;
 
 	gboolean disposed;
 } NMObjectPrivate;
@@ -43,6 +55,8 @@
 	if (!object)
 		return NULL;
 
+	nm_object_cache_add (NM_OBJECT (object));
+
 	priv = NM_OBJECT_GET_PRIVATE (object);
 
 	if (priv->connection == NULL || priv->path == NULL) {
@@ -82,6 +96,8 @@
 {
 	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
 
+	g_slist_foreach (priv->pcs, (GFunc) g_hash_table_destroy, NULL);
+	g_slist_free (priv->pcs);
 	g_free (priv->path);
 
 	G_OBJECT_CLASS (nm_object_parent_class)->finalize (object);
@@ -100,7 +116,7 @@
 		break;
 	case PROP_PATH:
 		/* Construct only */
-		priv->path = g_strdup (g_value_get_string (value));
+		priv->path = g_value_dup_string (value);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -144,7 +160,7 @@
 	/* porperties */
 	g_object_class_install_property
 		(object_class, PROP_CONNECTION,
-		 g_param_spec_boxed (NM_OBJECT_CONNECTION,
+		 g_param_spec_boxed (NM_OBJECT_DBUS_CONNECTION,
 							 "Connection",
 							 "Connection",
 							 DBUS_TYPE_G_CONNECTION,
@@ -152,7 +168,7 @@
 
 	g_object_class_install_property
 		(object_class, PROP_PATH,
-		 g_param_spec_string (NM_OBJECT_PATH,
+		 g_param_spec_string (NM_OBJECT_DBUS_PATH,
 							  "Object Path",
 							  "DBus Object Path",
 							  NULL,
@@ -177,7 +193,7 @@
 
 /* Stolen from dbus-glib */
 static char*
-wincaps_to_uscore (const char *caps)
+wincaps_to_dash (const char *caps)
 {
 	const char *p;
 	GString *str;
@@ -186,8 +202,8 @@
 	p = caps;
 	while (*p) {
 		if (g_ascii_isupper (*p)) {
-			if (str->len > 0 && (str->len < 2 || str->str[str->len-2] != '_'))
-				g_string_append_c (str, '_');
+			if (str->len > 0 && (str->len < 2 || str->str[str->len-2] != '-'))
+				g_string_append_c (str, '-');
 			g_string_append_c (str, g_ascii_tolower (*p));
 		} else
 			g_string_append_c (str, *p);
@@ -200,16 +216,38 @@
 static void
 handle_property_changed (gpointer key, gpointer data, gpointer user_data)
 {
-	GObject *object = G_OBJECT (user_data);
+	NMObject *self = NM_OBJECT (user_data);
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
 	char *prop_name;
-	GValue *value = (GValue *) data;
+	PropChangedInfo *pci;
+	GParamSpec *pspec;
+	gboolean success = FALSE, found = FALSE;
+	GSList *iter;
+
+	prop_name = wincaps_to_dash ((char *) key);
+	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (self)), prop_name);
+	if (!pspec) {
+		g_warning ("Property '%s' change detected but couldn't be found on the object.", prop_name);
+		goto out;
+	}
+
+	/* Iterate through the object and it's parents to find the property */
+	for (iter = priv->pcs; iter; iter = g_slist_next (iter)) {
+		pci = g_hash_table_lookup ((GHashTable *) iter->data, prop_name);
+		if (pci) {
+			found = TRUE;
+			success = (*(pci->func)) (self, pspec, (GValue *) data, pci->field);
+			if (success)
+				break;
+		}
+	}
 
-	prop_name = wincaps_to_uscore ((char *) key);
-	if (g_object_class_find_property (G_OBJECT_GET_CLASS (object), prop_name))
-		g_object_set_property (object, prop_name, value);
-	else
-		nm_warning ("Property '%s' change detected but can't be set", prop_name);
+	if (!found)
+		g_warning ("Property '%s' unhandled.", prop_name);
+	else if (!success)
+		g_warning ("Property '%s' could not be set due to errors.", prop_name);
 
+out:
 	g_free (prop_name);
 }
 
@@ -218,26 +256,109 @@
                           GHashTable *properties,
                           gpointer user_data)
 {
-	GObject *object = G_OBJECT (user_data);
-
-	g_object_freeze_notify (object);
-	g_hash_table_foreach (properties, handle_property_changed, object);
-	g_object_thaw_notify (object);
+	g_hash_table_foreach (properties, handle_property_changed, user_data);
 }
 
 void
-nm_object_handle_properties_changed (NMObject *object, DBusGProxy *proxy)
+nm_object_handle_properties_changed (NMObject *object,
+                                     DBusGProxy *proxy,
+                                     const NMPropertiesChangedInfo *info)
 {
-	dbus_g_proxy_add_signal (proxy, "PropertiesChanged",
-	                         dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
-	                         G_TYPE_INVALID);
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	NMPropertiesChangedInfo *tmp;
+	GHashTable *instance;
+
+	g_return_if_fail (NM_IS_OBJECT (object));
+	g_return_if_fail (proxy != NULL);
+	g_return_if_fail (info != NULL);
+
+	dbus_g_proxy_add_signal (proxy, "PropertiesChanged", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID);
 	dbus_g_proxy_connect_signal (proxy,
 						    "PropertiesChanged",
 						    G_CALLBACK (properties_changed_proxy),
 						    object,
 						    NULL);
+
+	instance = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+	priv->pcs = g_slist_prepend (priv->pcs, instance);
+
+	for (tmp = (NMPropertiesChangedInfo *) info; tmp->name; tmp++) {
+		PropChangedInfo *pci;
+
+		if (!tmp->name || !tmp->func || !tmp->field) {
+			g_warning ("%s: missing field in NMPropertiesChangedInfo", __func__);
+			continue;
+		}
+
+		pci = g_malloc0 (sizeof (PropChangedInfo));
+		if (!pci) {
+			g_warning ("%s: not enough memory for PropChangedInfo", __func__);
+			continue;
+		}
+		pci->func = tmp->func;
+		pci->field = tmp->field;
+		g_hash_table_insert (instance, g_strdup (tmp->name), pci);
+	}
 }
 
+#define HANDLE_TYPE(ucase, lcase) \
+	} else if (pspec->value_type == G_TYPE_##ucase) { \
+		if (G_VALUE_HOLDS_##ucase (value)) { \
+			g##lcase *param = (g##lcase *) field; \
+			*param = g_value_get_##lcase (value); \
+		} else { \
+			success = FALSE; \
+			goto done; \
+		}
+
+gboolean
+nm_object_demarshal_generic (NMObject *object,
+                             GParamSpec *pspec,
+                             GValue *value,
+                             gpointer field)
+{
+	gboolean success = TRUE;
+
+	if (pspec->value_type == G_TYPE_STRING) {
+		if (G_VALUE_HOLDS_STRING (value)) {
+			char **param = (char **) field;
+			g_free (*param);
+			*param = g_value_dup_string (value);
+		} else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) {
+			char **param = (char **) field;
+			g_free (*param);
+			*param = g_strdup (g_value_get_boxed (value));
+		} else {
+			success = FALSE;
+			goto done;
+		}
+	HANDLE_TYPE(BOOLEAN, boolean)
+	HANDLE_TYPE(CHAR, char)
+	HANDLE_TYPE(UCHAR, uchar)
+	HANDLE_TYPE(DOUBLE, double)
+	HANDLE_TYPE(INT, int)
+	HANDLE_TYPE(UINT, uint)
+	HANDLE_TYPE(INT64, int)
+	HANDLE_TYPE(UINT64, uint)
+	HANDLE_TYPE(LONG, long)
+	HANDLE_TYPE(ULONG, ulong)
+	} else {
+		g_warning ("%s: %s/%s unhandled type %s.",
+		           __func__, G_OBJECT_TYPE_NAME (object), pspec->name,
+		           g_type_name (pspec->value_type));
+		success = FALSE;
+	}
+
+done:
+	if (success) {
+		g_object_notify (G_OBJECT (object), pspec->name);
+	} else {
+		g_warning ("%s: %s/%s (type %s) couldn't be set with type %s.",
+		           __func__, G_OBJECT_TYPE_NAME (object), pspec->name,
+		           g_type_name (pspec->value_type), G_VALUE_TYPE_NAME (value));
+	}
+	return success;
+}
 
 gboolean
 nm_object_get_property (NMObject *object,
@@ -299,7 +420,10 @@
 	GValue value = {0,};
 
 	if (nm_object_get_property (object, interface, prop_name, &value)) {
-		str = g_strdup (g_value_get_string (&value));
+		if (G_VALUE_HOLDS_STRING (&value))
+			str = g_strdup (g_value_get_string (&value));
+		else if (G_VALUE_HOLDS (&value, DBUS_TYPE_G_OBJECT_PATH))
+			str = g_strdup (g_value_get_boxed (&value));
 		g_value_unset (&value);
 	}
 

Modified: trunk/libnm-glib/nm-object.h
==============================================================================
--- trunk/libnm-glib/nm-object.h	(original)
+++ trunk/libnm-glib/nm-object.h	Mon Mar 24 15:17:30 2008
@@ -14,8 +14,8 @@
 #define NM_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_OBJECT))
 #define NM_OBJECT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_OBJECT, NMObjectClass))
 
-#define NM_OBJECT_CONNECTION "connection"
-#define NM_OBJECT_PATH "path"
+#define NM_OBJECT_DBUS_CONNECTION "dbus-connection"
+#define NM_OBJECT_DBUS_PATH "dbus-path"
 
 typedef struct {
 	GObject parent;
@@ -30,54 +30,6 @@
 DBusGConnection *nm_object_get_connection (NMObject *object);
 const char      *nm_object_get_path       (NMObject *object);
 
-void             nm_object_handle_properties_changed (NMObject *object,
-						      DBusGProxy *proxy);
-
-/* DBus property accessors */
-
-gboolean nm_object_get_property (NMObject *object,
-								 const char *interface,
-								 const char *prop_name,
-								 GValue *value);
-
-void nm_object_set_property (NMObject *object,
-							 const char *interface,
-							 const char *prop_name,
-							 GValue *value);
-
-char *nm_object_get_string_property (NMObject *object,
-									 const char *interface,
-									 const char *prop_name);
-
-char *nm_object_get_object_path_property (NMObject *object,
-										  const char *interface,
-										  const char *prop_name);
-
-gint32 nm_object_get_int_property (NMObject *object,
-								   const char *interface,
-								   const char *prop_name);
-
-guint32 nm_object_get_uint_property (NMObject *object,
-									 const char *interface,
-									 const char *prop_name);
-
-gboolean nm_object_get_boolean_property (NMObject *object,
-										const char *interface,
-										const char *prop_name);
-
-gint8 nm_object_get_byte_property (NMObject *object,
-								   const char *interface,
-								   const char *prop_name);
-
-gdouble nm_object_get_double_property (NMObject *object,
-									   const char *interface,
-									   const char *prop_name);
-
-GByteArray *nm_object_get_byte_array_property (NMObject *object,
-											   const char *interface,
-											   const char *prop_name);
-
-
 G_END_DECLS
 
 #endif /* NM_OBJECT_H */

Modified: trunk/libnm-glib/nm-settings.c
==============================================================================
--- trunk/libnm-glib/nm-settings.c	(original)
+++ trunk/libnm-glib/nm-settings.c	Mon Mar 24 15:17:30 2008
@@ -2,6 +2,7 @@
 #include <nm-utils.h>
 #include <nm-setting-connection.h>
 #include "nm-settings.h"
+#include "nm-dbus-glib-types.h"
 
 
 GQuark
@@ -279,9 +280,6 @@
 	G_OBJECT_CLASS (nm_exported_connection_parent_class)->dispose (object);
 }
 
-#define DBUS_TYPE_G_STRING_VARIANT_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
-#define DBUS_TYPE_G_DICT_OF_DICTS (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, DBUS_TYPE_G_STRING_VARIANT_HASHTABLE))
-
 static void
 nm_exported_connection_class_init (NMExportedConnectionClass *exported_connection_class)
 {
@@ -316,7 +314,7 @@
 			      NULL, NULL,
 			      g_cclosure_marshal_VOID__POINTER,
 			      G_TYPE_NONE, 1,
-			      DBUS_TYPE_G_DICT_OF_DICTS);
+			      DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT);
 
 	connection_signals[EC_REMOVED] =
 		g_signal_new ("removed",

Added: trunk/libnm-glib/nm-types-private.h
==============================================================================
--- (empty file)
+++ trunk/libnm-glib/nm-types-private.h	Mon Mar 24 15:17:30 2008
@@ -0,0 +1,18 @@
+
+#ifndef NM_TYPES_PRIVATE_H
+#define NM_TYPES_PRIVATE_H
+
+#include <dbus/dbus-glib.h>
+#include "nm-types.h"
+#include "nm-object-private.h"
+
+gboolean nm_ssid_demarshal (GValue *value, GByteArray **dest);
+gboolean nm_uint_array_demarshal (GValue *value, GArray **dest);
+gboolean nm_string_array_demarshal (GValue *value, GPtrArray **dest);
+gboolean nm_object_array_demarshal (GValue *value,
+                                    GPtrArray **dest,
+                                    DBusGConnection *connection,
+                                    NMObjectCreatorFunc func);
+
+
+#endif /* NM_TYPES_PRIVATE_H */

Added: trunk/libnm-glib/nm-types.c
==============================================================================
--- (empty file)
+++ trunk/libnm-glib/nm-types.c	Mon Mar 24 15:17:30 2008
@@ -0,0 +1,255 @@
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <string.h>
+#include "nm-types.h"
+#include "nm-types-private.h"
+#include "nm-object-private.h"
+#include "nm-object-cache.h"
+#include "nm-dbus-glib-types.h"
+
+static gpointer
+nm_ssid_copy (GByteArray *src)
+{
+	GByteArray *dest;
+
+	dest = g_byte_array_sized_new (src->len);
+	g_byte_array_append (dest, src->data, src->len);
+	return dest;
+}
+
+static void
+nm_ssid_free (GByteArray *ssid)
+{
+	g_byte_array_free (ssid, TRUE);
+}
+
+GType
+nm_ssid_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-ssid"),
+		                                         (GBoxedCopyFunc) nm_ssid_copy,
+		                                         (GBoxedFreeFunc) nm_ssid_free);
+	return our_type;
+}
+
+gboolean
+nm_ssid_demarshal (GValue *value, GByteArray **dest)
+{
+	GByteArray *array;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY))
+		return FALSE;
+
+	if (*dest) {
+		g_boxed_free (NM_TYPE_SSID, *dest);
+		*dest = NULL;
+	}
+
+	array = (GByteArray *) g_value_get_boxed (value);
+	if (array && (array->len > 0)) {
+		*dest = g_byte_array_sized_new (array->len);
+		(*dest)->len = array->len;
+		memcpy ((*dest)->data, array->data, array->len);
+	}
+
+	return TRUE;
+}
+
+/*****************************/
+
+static gpointer
+nm_uint_array_copy (GArray *src)
+{
+	GArray *dest;
+
+	dest = g_array_sized_new (FALSE, TRUE, sizeof (guint32), src->len);
+	g_array_append_vals (dest, src->data, src->len);
+	return dest;
+}
+
+static void
+nm_uint_array_free (GArray *array)
+{
+	g_array_free (array, TRUE);
+}
+
+GType
+nm_uint_array_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-uint-array"),
+		                                         (GBoxedCopyFunc) nm_uint_array_copy,
+		                                         (GBoxedFreeFunc) nm_uint_array_free);
+	return our_type;
+}
+
+gboolean
+nm_uint_array_demarshal (GValue *value, GArray **dest)
+{
+	GArray *array;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_UINT_ARRAY))
+		return FALSE;
+
+	if (*dest) {
+		g_boxed_free (NM_TYPE_UINT_ARRAY, *dest);
+		*dest = NULL;
+	}
+
+	array = (GArray *) g_value_get_boxed (value);
+	if (array && (array->len > 0)) {
+		*dest = g_array_sized_new (FALSE, TRUE, sizeof (guint32), array->len);
+		g_array_append_vals (*dest, array->data, array->len);
+	}
+
+	return TRUE;
+}
+
+/*****************************/
+
+static gpointer
+nm_string_array_copy (GPtrArray *src)
+{
+	GPtrArray *dest;
+	int i;
+
+	dest = g_ptr_array_sized_new (src->len);
+	for (i = 0; i < src->len; i++)
+		g_ptr_array_add (dest, g_strdup (g_ptr_array_index (src, i)));
+	return dest;
+}
+
+static void
+nm_string_array_free (GPtrArray *array)
+{
+	int i;
+
+	for (i = 0; i < array->len; i++)
+		g_free (g_ptr_array_index (array, i));
+	g_ptr_array_free (array, TRUE);
+}
+
+GType
+nm_string_array_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-string-array"),
+		                                         (GBoxedCopyFunc) nm_string_array_copy,
+		                                         (GBoxedFreeFunc) nm_string_array_free);
+	return our_type;
+}
+
+gboolean
+nm_string_array_demarshal (GValue *value, GPtrArray **dest)
+{
+	GPtrArray *array;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_STRING))
+		return FALSE;
+
+	if (*dest) {
+		g_boxed_free (NM_TYPE_STRING_ARRAY, *dest);
+		*dest = NULL;
+	}
+
+	array = (GPtrArray *) g_value_get_boxed (value);
+	if (array && array->len) {
+		int i;
+
+		*dest = g_ptr_array_sized_new (array->len);
+		for (i = 0; i < array->len; i++)
+			g_ptr_array_add (*dest, g_strdup (g_ptr_array_index (array, i)));
+	}
+
+	return TRUE;
+}
+
+/*****************************/
+
+static gpointer
+nm_object_array_copy (GPtrArray *src)
+{
+	GPtrArray *dest;
+	int i;
+
+	dest = g_ptr_array_sized_new (src->len);
+	for (i = 0; i < src->len; i++)
+		g_ptr_array_add (dest, g_object_ref (g_ptr_array_index (src, i)));
+	return dest;
+}
+
+static void
+nm_object_array_free (GPtrArray *array)
+{
+	int i;
+
+	for (i = 0; i < array->len; i++)
+		g_object_unref (g_ptr_array_index (array, i));
+	g_ptr_array_free (array, TRUE);
+}
+
+GType
+nm_object_array_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+		our_type = g_boxed_type_register_static (g_intern_static_string ("nm-object-array"),
+		                                         (GBoxedCopyFunc) nm_object_array_copy,
+		                                         (GBoxedFreeFunc) nm_object_array_free);
+	return our_type;
+}
+
+gboolean
+nm_object_array_demarshal (GValue *value,
+                           GPtrArray **dest,
+                           DBusGConnection *connection,
+                           NMObjectCreatorFunc func)
+{
+	GPtrArray *temp = NULL;
+	GPtrArray *array;
+
+	if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH))
+		return FALSE;
+
+	array = (GPtrArray *) g_value_get_boxed (value);
+	if (array && array->len) {
+		int i;
+
+		temp = g_ptr_array_sized_new (array->len);
+		for (i = 0; i < array->len; i++) {
+			const char *path;
+			GObject *object;
+
+			path = g_ptr_array_index (array, i);
+			object = G_OBJECT (nm_object_cache_get (path));
+			if (object) {
+				g_ptr_array_add (temp, g_object_ref (object));
+			} else {
+				object = (*func) (connection, path);
+				if (object)
+					g_ptr_array_add (temp, object);
+				else
+					g_warning ("%s: couldn't create object for %s", __func__, path);
+			}
+		}
+	}
+
+	/* Deallocate after to ensure that an object that might already
+	 * be in the array doesn't get destroyed due to refcounting.
+	 */
+	if (*dest)
+		g_boxed_free (NM_TYPE_OBJECT_ARRAY, *dest);
+	*dest = temp;
+
+	return TRUE;
+}
+

Added: trunk/libnm-glib/nm-types.h
==============================================================================
--- (empty file)
+++ trunk/libnm-glib/nm-types.h	Mon Mar 24 15:17:30 2008
@@ -0,0 +1,19 @@
+#ifndef NM_TYPES_H
+#define NM_TYPES_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#define NM_TYPE_SSID  (nm_ssid_get_type ())
+GType     nm_ssid_get_type (void) G_GNUC_CONST;
+
+#define NM_TYPE_UINT_ARRAY  (nm_uint_array_get_type ())
+GType     nm_uint_array_get_type (void) G_GNUC_CONST;
+
+#define NM_TYPE_STRING_ARRAY  (nm_string_array_get_type ())
+GType     nm_string_array_get_type (void) G_GNUC_CONST;
+
+#define NM_TYPE_OBJECT_ARRAY  (nm_object_array_get_type ())
+GType     nm_object_array_get_type (void) G_GNUC_CONST;
+
+#endif /* NM_TYPES_H */

Modified: trunk/libnm-glib/nm-vpn-connection.c
==============================================================================
--- trunk/libnm-glib/nm-vpn-connection.c	(original)
+++ trunk/libnm-glib/nm-vpn-connection.c	Mon Mar 24 15:17:30 2008
@@ -17,7 +17,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
- * (C) Copyright 2004 Red Hat, Inc.
+ * (C) Copyright 2008 Red Hat, Inc.
  */
 
 #include <string.h>
@@ -26,6 +26,7 @@
 #include "nm-utils.h"
 #include "nm-vpn-connection-bindings.h"
 #include "nm-marshal.h"
+#include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMVPNConnection, nm_vpn_connection, NM_TYPE_OBJECT)
 
@@ -57,8 +58,8 @@
 	g_return_val_if_fail (path != NULL, NULL);
 
 	connection = (NMVPNConnection *) g_object_new (NM_TYPE_VPN_CONNECTION, 
-										  NM_OBJECT_CONNECTION, dbus_connection,
-										  NM_OBJECT_PATH, path,
+										  NM_OBJECT_DBUS_CONNECTION, dbus_connection,
+										  NM_OBJECT_DBUS_PATH, path,
 										  NULL);
 
 	nm_vpn_connection_get_name (connection);

Modified: trunk/libnm-glib/nm-vpn-manager.c
==============================================================================
--- trunk/libnm-glib/nm-vpn-manager.c	(original)
+++ trunk/libnm-glib/nm-vpn-manager.c	Mon Mar 24 15:17:30 2008
@@ -29,8 +29,8 @@
 	}
 
 	return (NMVPNManager *) g_object_new (NM_TYPE_VPN_MANAGER,
-								   NM_OBJECT_CONNECTION, connection,
-								   NM_OBJECT_PATH, NM_DBUS_PATH_VPN,
+								   NM_OBJECT_DBUS_CONNECTION, connection,
+								   NM_OBJECT_DBUS_PATH, NM_DBUS_PATH_VPN,
 								   NULL);
 
 }

Modified: trunk/libnm-glib/nm-vpn-plugin.c
==============================================================================
--- trunk/libnm-glib/nm-vpn-plugin.c	(original)
+++ trunk/libnm-glib/nm-vpn-plugin.c	Mon Mar 24 15:17:30 2008
@@ -4,6 +4,7 @@
 #include "nm-vpn-plugin.h"
 #include "nm-utils.h"
 #include "nm-connection.h"
+#include "nm-dbus-glib-types.h"
 
 static gboolean impl_vpn_plugin_connect    (NMVPNPlugin *plugin,
 								    GHashTable *connection,
@@ -704,7 +705,7 @@
 				    NULL, NULL,
 				    g_cclosure_marshal_VOID__BOXED,
 				    G_TYPE_NONE, 1,
-				    dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE));
+				    DBUS_TYPE_G_MAP_OF_VARIANT);
 
 	signals[LOGIN_BANNER] =
 		g_signal_new ("login-banner",

Modified: trunk/test/nm-tool.c
==============================================================================
--- trunk/test/nm-tool.c	(original)
+++ trunk/test/nm-tool.c	Mon Mar 24 15:17:30 2008
@@ -177,13 +177,12 @@
 	NMDeviceState state;
 	guint32 caps;
 	guint32 speed;
-	GArray *array;
+	const GArray *array;
 
 	state = nm_device_get_state (device);
 
-	tmp = nm_device_get_iface (device);
-	printf ("- Device: %s ----------------------------------------------------------------\n", tmp);
-	g_free (tmp);
+	printf ("- Device: %s ----------------------------------------------------------------\n",
+	        nm_device_get_iface (device));
 
 	/* General information */
 	if (NM_IS_DEVICE_802_3_ETHERNET (device))
@@ -191,12 +190,7 @@
 	else if (NM_IS_DEVICE_802_11_WIRELESS (device))
 		print_string ("Type", "802.11 Wireless");
 
-	tmp = nm_device_get_driver (device);
-	if (tmp) {
-		print_string ("Driver", tmp);
-		g_free (tmp);
-	} else
-		print_string ("Driver", "(unknown)");
+	print_string ("Driver", nm_device_get_driver (device) ? nm_device_get_driver (device) : "(unknown)");
 
 	if (state == NM_DEVICE_STATE_ACTIVATED)
 		print_string ("Active", "yes");
@@ -247,7 +241,7 @@
 		guint32 wcaps;
 		NMAccessPoint *active_ap = NULL;
 		const char *active_bssid = NULL;
-		GSList *aps;
+		GPtrArray *aps;
 
 		printf ("\n  Wireless Settings\n");
 
@@ -268,8 +262,7 @@
 		printf ("\n  Wireless Access Points%s\n", active_ap ? "(* = Current AP)" : "");
 
 		aps = nm_device_802_11_wireless_get_access_points (NM_DEVICE_802_11_WIRELESS (device));
-		g_slist_foreach (aps, detail_access_point, (gpointer) active_bssid);
-		g_slist_free (aps);
+		g_ptr_array_foreach (aps, detail_access_point, (gpointer) active_bssid);
 	} else if (NM_IS_DEVICE_802_3_ETHERNET (device)) {
 		printf ("\n  Wired Settings\n");
 		/* FIXME */
@@ -312,28 +305,13 @@
 				print_string ("  DNS", tmp);
 				g_free (tmp);
 			}
-
-			g_array_free (array, TRUE);
 		}
-
-		g_object_unref (cfg);
 	}
 
 	printf ("\n\n");
 }
 
 
-static void
-print_devices (NMClient *client)
-{
-	GSList *devices;
-
-	devices = nm_client_get_devices (client);
-	g_slist_foreach (devices, detail_device, NULL);
-	g_slist_free (devices);
-}
-
-
 int
 main (int argc, char *argv[])
 {
@@ -353,7 +331,7 @@
 		exit (1);
 	}
 
-	print_devices (client);
+	g_ptr_array_foreach (nm_client_get_devices (client), detail_device, NULL);
 
 	g_object_unref (client);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]