[gupnp] all: Port to new GLib type macros



commit 84d6605ed7075dc65de5936532dcef951b2f74bf
Author: Jens Georg <mail jensge org>
Date:   Fri Nov 2 17:35:39 2018 +0100

    all: Port to new GLib type macros

 libgupnp/gupnp-acl.c                    |  38 ++---
 libgupnp/gupnp-acl.h                    |  17 +--
 libgupnp/gupnp-connman-manager.c        |  62 +++++---
 libgupnp/gupnp-connman-manager.h        |  38 +----
 libgupnp/gupnp-context-manager.c        | 112 ++++++++------
 libgupnp/gupnp-context-manager.h        |  41 +-----
 libgupnp/gupnp-context.c                | 206 ++++++++++++++++----------
 libgupnp/gupnp-context.h                |  37 +----
 libgupnp/gupnp-control-point.c          | 158 ++++++++++++--------
 libgupnp/gupnp-control-point.h          |  41 +-----
 libgupnp/gupnp-device-info.c            | 243 ++++++++++++++++++++++---------
 libgupnp/gupnp-device-info.h            |  41 +-----
 libgupnp/gupnp-device-proxy.c           |   1 +
 libgupnp/gupnp-device-proxy.h           |  41 +-----
 libgupnp/gupnp-device.c                 |  47 +++---
 libgupnp/gupnp-device.h                 |  44 +-----
 libgupnp/gupnp-linux-context-manager.c  | 159 ++++++++++++--------
 libgupnp/gupnp-linux-context-manager.h  |  43 +-----
 libgupnp/gupnp-network-manager.c        | 101 +++++++------
 libgupnp/gupnp-network-manager.h        |  43 +-----
 libgupnp/gupnp-resource-factory.c       | 112 ++++++++------
 libgupnp/gupnp-resource-factory.h       |  42 +-----
 libgupnp/gupnp-root-device.c            | 129 +++++++++-------
 libgupnp/gupnp-root-device.h            |  42 +-----
 libgupnp/gupnp-service-info.c           | 168 +++++++++++++--------
 libgupnp/gupnp-service-info.h           |  41 +-----
 libgupnp/gupnp-service-introspection.c  | 106 +++++++++-----
 libgupnp/gupnp-service-introspection.h  |  49 +------
 libgupnp/gupnp-service-proxy.c          | 250 +++++++++++++++++++-------------
 libgupnp/gupnp-service-proxy.h          |  41 +-----
 libgupnp/gupnp-service.c                | 201 +++++++++++++++----------
 libgupnp/gupnp-service.h                |  43 +-----
 libgupnp/gupnp-simple-context-manager.c |  60 ++++----
 libgupnp/gupnp-simple-context-manager.h |  35 +----
 libgupnp/gupnp-unix-context-manager.c   |   4 +
 libgupnp/gupnp-unix-context-manager.h   |  43 +-----
 libgupnp/gupnp-white-list.c             |  76 ++++++----
 libgupnp/gupnp-white-list.h             |  41 +-----
 libgupnp/gupnp-xml-doc.c                |  17 +++
 libgupnp/gupnp-xml-doc.h                |  47 +-----
 meson.build                             |   7 +-
 41 files changed, 1520 insertions(+), 1547 deletions(-)
---
diff --git a/libgupnp/gupnp-acl.c b/libgupnp/gupnp-acl.c
index 387d003..d71b523 100644
--- a/libgupnp/gupnp-acl.c
+++ b/libgupnp/gupnp-acl.c
@@ -68,12 +68,12 @@ gupnp_acl_is_allowed (GUPnPAcl     *self,
 {
         g_return_val_if_fail (GUPNP_IS_ACL (self), FALSE);
 
-        return GUPNP_ACL_GET_INTERFACE (self)->is_allowed (self,
-                                                           device,
-                                                           service,
-                                                           path,
-                                                           address,
-                                                           agent);
+        return GUPNP_ACL_GET_IFACE (self)->is_allowed (self,
+                                                       device,
+                                                       service,
+                                                       path,
+                                                       address,
+                                                       agent);
 }
 
 /**
@@ -115,15 +115,15 @@ gupnp_acl_is_allowed_async (GUPnPAcl           *self,
 {
         g_return_if_fail (GUPNP_IS_ACL (self));
 
-        GUPNP_ACL_GET_INTERFACE (self)->is_allowed_async (self,
-                                                          device,
-                                                          service,
-                                                          path,
-                                                          address,
-                                                          agent,
-                                                          cancellable,
-                                                          callback,
-                                                          user_data);
+        GUPNP_ACL_GET_IFACE (self)->is_allowed_async (self,
+                                                      device,
+                                                      service,
+                                                      path,
+                                                      address,
+                                                      agent,
+                                                      cancellable,
+                                                      callback,
+                                                      user_data);
 }
 
 /**
@@ -143,9 +143,9 @@ gupnp_acl_is_allowed_finish (GUPnPAcl      *self,
 {
         g_return_val_if_fail (GUPNP_IS_ACL (self), FALSE);
 
-        return GUPNP_ACL_GET_INTERFACE (self)->is_allowed_finish (self,
-                                                                  res,
-                                                                  error);
+        return GUPNP_ACL_GET_IFACE (self)->is_allowed_finish (self,
+                                                              res,
+                                                              error);
 }
 
 /**
@@ -163,7 +163,7 @@ gupnp_acl_can_sync (GUPnPAcl *self)
 {
         g_return_val_if_fail (GUPNP_IS_ACL (self), FALSE);
 
-        return GUPNP_ACL_GET_INTERFACE (self)->can_sync (self);
+        return GUPNP_ACL_GET_IFACE (self)->can_sync (self);
 }
 
 /**
diff --git a/libgupnp/gupnp-acl.h b/libgupnp/gupnp-acl.h
index 329caf0..191b463 100644
--- a/libgupnp/gupnp-acl.h
+++ b/libgupnp/gupnp-acl.h
@@ -28,23 +28,8 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_acl_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_ACL (gupnp_acl_get_type())
-
-#define GUPNP_ACL(obj)                  \
-    (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-     GUPNP_TYPE_ACL,                    \
-     GUPnPAcl))
-
-#define GUPNP_IS_ACL(obj)               \
-    (G_TYPE_CHECK_INSTANCE_TYPE ((obj),  \
-     GUPNP_TYPE_ACL))
-
-#define GUPNP_ACL_GET_INTERFACE(obj)      \
-    (G_TYPE_INSTANCE_GET_INTERFACE ((obj), \
-     GUPNP_TYPE_ACL, GUPnPAclInterface))
+G_DECLARE_INTERFACE (GUPnPAcl, gupnp_acl, GUPNP, ACL, GObject)
 
 /**
  * GUPnPAcl:
diff --git a/libgupnp/gupnp-connman-manager.c b/libgupnp/gupnp-connman-manager.c
index 6a48beb..8880d1a 100644
--- a/libgupnp/gupnp-connman-manager.c
+++ b/libgupnp/gupnp-connman-manager.c
@@ -63,6 +63,12 @@ struct _GUPnPConnmanManagerPrivate {
         GCancellable *cancellable;
 };
 
+typedef struct _GUPnPConnmanManagerPrivate GUPnPConnmanManagerPrivate;
+
+struct _GUPnPConnmanManager {
+        GUPnPContextManager             parent;
+};
+
 #define CM_DBUS_CONNMAN_NAME      "net.connman"
 #define CM_DBUS_MANAGER_PATH      "/"
 #define CM_DBUS_MANAGER_INTERFACE "net.connman.Manager"
@@ -74,9 +80,9 @@ struct _GUPnPConnmanManagerPrivate {
 
 #define LOOPBACK_IFACE "lo"
 
-G_DEFINE_TYPE (GUPnPConnmanManager,
-               gupnp_connman_manager,
-               GUPNP_TYPE_CONTEXT_MANAGER);
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPConnmanManager,
+                            gupnp_connman_manager,
+                            GUPNP_TYPE_CONTEXT_MANAGER);
 
 static gboolean
 loopback_context_create (gpointer data)
@@ -85,9 +91,11 @@ loopback_context_create (gpointer data)
         GUPnPContext        *context;
         GError              *error = NULL;
         guint               port;
+        GUPnPConnmanManagerPrivate *priv;
 
         manager = GUPNP_CONNMAN_MANAGER (data);
-        manager->priv->idle_context_creation_src = NULL;
+        priv = gupnp_connman_manager_get_instance_private (manager);
+        priv->idle_context_creation_src = NULL;
 
         g_object_get (manager, "port", &port, NULL);
 
@@ -462,6 +470,7 @@ service_proxy_new_cb (GObject      *source_object,
                       gpointer     user_data)
 {
         GUPnPConnmanManager *manager;
+        GUPnPConnmanManagerPrivate *priv;
         GDBusProxy          *service_proxy;
         GError              *error = NULL;
         CMService           *cm_service;
@@ -478,8 +487,9 @@ service_proxy_new_cb (GObject      *source_object,
         }
 
         manager = GUPNP_CONNMAN_MANAGER (user_data);
+        priv = gupnp_connman_manager_get_instance_private (manager);
         path = g_dbus_proxy_get_object_path (service_proxy);
-        cm_service = g_hash_table_lookup (manager->priv->cm_services, path);
+        cm_service = g_hash_table_lookup (priv->cm_services, path);
 
         if (cm_service == NULL) {
                g_object_unref (service_proxy);
@@ -503,9 +513,11 @@ cm_service_add (GUPnPConnmanManager *manager,
         gchar          *iface;
         gchar          *name;
         gchar          *state;
+        GUPnPConnmanManagerPrivate *priv;
 
         iface   = NULL;
         name    = NULL;
+        priv = gupnp_connman_manager_get_instance_private (manager);
 
         g_variant_lookup (dict, "Name", "s", &name);
 
@@ -530,7 +542,7 @@ cm_service_add (GUPnPConnmanManager *manager,
         cm_service->port    = port;
         cm_service->current = new_state;
 
-        g_hash_table_insert (manager->priv->cm_services,
+        g_hash_table_insert (priv->cm_services,
                              g_strdup (path),
                              cm_service);
 
@@ -557,7 +569,9 @@ services_array_add (GUPnPConnmanManager *manager, GVariant *data)
         GVariantIter iter;
         GVariantIter dict_iter;
         guint        port;
+        GUPnPConnmanManagerPrivate *priv;
 
+        priv = gupnp_connman_manager_get_instance_private (manager);
         g_object_get (manager, "port", &port, NULL);
         g_variant_iter_init (&iter, data);
 
@@ -572,7 +586,7 @@ services_array_add (GUPnPConnmanManager *manager, GVariant *data)
                 if (g_variant_iter_init (&dict_iter, dict) == 0)
                         continue;
 
-                cm_service = g_hash_table_lookup (manager->priv->cm_services,
+                cm_service = g_hash_table_lookup (priv->cm_services,
                                                   path);
 
                 if (cm_service == NULL)
@@ -590,7 +604,7 @@ services_array_remove (GUPnPConnmanManager *manager, GVariant *data)
         char                       *path;
         GVariantIter               iter;
 
-        priv = manager->priv;
+        priv = gupnp_connman_manager_get_instance_private (manager);
         g_variant_iter_init (&iter, data);
 
         while (g_variant_iter_next (&iter, "&o", &path)) {
@@ -681,20 +695,23 @@ get_services_cb (GObject      *source_object,
 static void
 schedule_loopback_context_creation (GUPnPConnmanManager *manager)
 {
+        GUPnPConnmanManagerPrivate *priv;
+
         /* Create contexts in mainloop so that it happens after user has hooked
          * to the "context-available" signal.
          */
-        manager->priv->idle_context_creation_src = g_idle_source_new ();
+        priv = gupnp_connman_manager_get_instance_private (manager);
+        priv->idle_context_creation_src = g_idle_source_new ();
 
-        g_source_attach (manager->priv->idle_context_creation_src,
+        g_source_attach (priv->idle_context_creation_src,
                          g_main_context_get_thread_default ());
 
-        g_source_set_callback (manager->priv->idle_context_creation_src,
+        g_source_set_callback (priv->idle_context_creation_src,
                                loopback_context_create,
                                manager,
                                NULL);
 
-        g_source_unref (manager->priv->idle_context_creation_src);
+        g_source_unref (priv->idle_context_creation_src);
 }
 
 static void
@@ -704,7 +721,7 @@ init_connman_manager (GUPnPConnmanManager *manager)
         GError                     *error = NULL;
         GDBusConnection            *connection;
 
-        priv = manager->priv;
+        priv = gupnp_connman_manager_get_instance_private (manager);
 
         priv->manager_proxy = g_dbus_proxy_new_for_bus_sync (
                                 G_BUS_TYPE_SYSTEM,
@@ -765,7 +782,7 @@ gupnp_connman_manager_dispose (GObject *object)
         GDBusConnection            *cnx;
 
         manager = GUPNP_CONNMAN_MANAGER (object);
-        priv = manager->priv;
+        priv = gupnp_connman_manager_get_instance_private (manager);
         cnx = g_dbus_proxy_get_connection (priv->manager_proxy);
 
         if (priv->sig_change_id) {
@@ -806,11 +823,13 @@ gupnp_connman_manager_constructed (GObject *object)
 {
         GUPnPConnmanManager *manager;
         GObjectClass        *object_class;
+        GUPnPConnmanManagerPrivate *priv;
 
         manager = GUPNP_CONNMAN_MANAGER (object);
+        priv = gupnp_connman_manager_get_instance_private (manager);
 
-        manager->priv->cancellable = g_cancellable_new ();
-        manager->priv->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
+        priv->cancellable = g_cancellable_new ();
+        priv->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
                                                     NULL,
                                                     NULL);
 
@@ -829,12 +848,11 @@ gupnp_connman_manager_constructed (GObject *object)
 static void
 gupnp_connman_manager_init (GUPnPConnmanManager *manager)
 {
-        manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (
-                                                manager,
-                                                GUPNP_TYPE_CONNMAN_MANAGER,
-                                                GUPnPConnmanManagerPrivate);
+        GUPnPConnmanManagerPrivate *priv;
+
+        priv = gupnp_connman_manager_get_instance_private (manager);
 
-        manager->priv->cm_services = g_hash_table_new_full (
+        priv->cm_services = g_hash_table_new_full (
                                         g_str_hash,
                                         g_str_equal,
                                         (GDestroyNotify) g_free,
@@ -850,8 +868,6 @@ gupnp_connman_manager_class_init (GUPnPConnmanManagerClass *klass)
 
         object_class->constructed  = gupnp_connman_manager_constructed;
         object_class->dispose      = gupnp_connman_manager_dispose;
-
-        g_type_class_add_private (klass, sizeof (GUPnPConnmanManagerPrivate));
 }
 
 gboolean
diff --git a/libgupnp/gupnp-connman-manager.h b/libgupnp/gupnp-connman-manager.h
index 8ef017b..0e441a5 100644
--- a/libgupnp/gupnp-connman-manager.h
+++ b/libgupnp/gupnp-connman-manager.h
@@ -29,42 +29,14 @@
 
 G_BEGIN_DECLS
 
-G_GNUC_INTERNAL GType
-gupnp_connman_manager_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_CONNMAN_MANAGER \
                 (gupnp_connman_manager_get_type ())
-#define GUPNP_CONNMAN_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_CONNMAN_MANAGER, \
-                 GUPnPConnmanManager))
-#define GUPNP_CONNMAN_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_CONNMAN_MANAGER, \
-                 GUPnPConnmanManagerClass))
-#define GUPNP_IS_CONNMAN_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_CONNMAN_MANAGER))
-#define GUPNP_IS_CONNMAN_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_CONNMAN_MANAGER))
-#define GUPNP_CONNMAN_MANAGER_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_CONNMAN_MANAGER, \
-                 GUPnPConnmanManagerClass))
-
-typedef struct _GUPnPConnmanManagerPrivate GUPnPConnmanManagerPrivate;
-
-typedef struct {
-        GUPnPContextManager             parent;
-        GUPnPConnmanManagerPrivate      *priv;
-
-} GUPnPConnmanManager;
-
-typedef struct {
-        GUPnPContextManagerClass parent_class;
 
-} GUPnPConnmanManagerClass;
+G_DECLARE_FINAL_TYPE (GUPnPConnmanManager,
+                      gupnp_connman_manager,
+                      GUPNP,
+                      CONNMAN_MANAGER,
+                      GUPnPContextManager)
 
 G_GNUC_INTERNAL gboolean
 gupnp_connman_manager_is_available      (void);
diff --git a/libgupnp/gupnp-context-manager.c b/libgupnp/gupnp-context-manager.c
index 00f97a4..ffdb710 100644
--- a/libgupnp/gupnp-context-manager.c
+++ b/libgupnp/gupnp-context-manager.c
@@ -57,10 +57,6 @@
 #include "gupnp-connman-manager.h"
 #endif
 
-G_DEFINE_ABSTRACT_TYPE (GUPnPContextManager,
-                        gupnp_context_manager,
-                        G_TYPE_OBJECT);
-
 struct _GUPnPContextManagerPrivate {
         guint              port;
 
@@ -71,6 +67,11 @@ struct _GUPnPContextManagerPrivate {
 
         GUPnPWhiteList *white_list;
 };
+typedef struct _GUPnPContextManagerPrivate GUPnPContextManagerPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GUPnPContextManager,
+                                     gupnp_context_manager,
+                                     G_TYPE_OBJECT);
 
 enum {
         PROP_0,
@@ -92,8 +93,11 @@ on_context_available (GUPnPContextManager    *manager,
                       G_GNUC_UNUSED gpointer *user_data)
 {
         GUPnPWhiteList *white_list;
+        GUPnPContextManagerPrivate *priv;
+
+        priv = gupnp_context_manager_get_instance_private (manager);
 
-        white_list = manager->priv->white_list;
+        white_list = priv->white_list;
 
         /* Try to catch the notification, only if the white list
          * is enabled, not empty and the context doesn't match */
@@ -108,9 +112,8 @@ on_context_available (GUPnPContextManager    *manager,
                 g_object_set (context, "active", FALSE, NULL);
 
                 /* Save it in case we need to re-enable it */
-                manager->priv->blacklisted = g_list_prepend (
-                                                manager->priv->blacklisted,
-                                                g_object_ref (context));
+                priv->blacklisted = g_list_prepend (priv->blacklisted,
+                                                    g_object_ref (context));
         }
 }
 
@@ -121,12 +124,15 @@ on_context_unavailable (GUPnPContextManager    *manager,
 {
         GList *l;
         GList *black;
+        GUPnPContextManagerPrivate *priv;
+
+        priv = gupnp_context_manager_get_instance_private (manager);
 
         /* Make sure we don't send anything on now unavailable network */
         g_object_set (context, "active", FALSE, NULL);
 
         /* Unref all associated objects */
-        l = manager->priv->objects;
+        l = priv->objects;
 
         while (l) {
                 GUPnPContext *obj_context = NULL;
@@ -150,22 +156,22 @@ on_context_unavailable (GUPnPContextManager    *manager,
 
                         g_object_unref (l->data);
 
-                        manager->priv->objects =
-                                g_list_delete_link (manager->priv->objects, l);
+                        priv->objects = g_list_delete_link (priv->objects,
+                                                            l);
                         l = next;
                 } else {
                         l = l->next;
                 }
         }
 
-        black = g_list_find (manager->priv->blacklisted, context);
+        black = g_list_find (priv->blacklisted, context);
 
         if (black != NULL) {
                 g_signal_stop_emission_by_name (manager, "context-unavailable");
 
                 g_object_unref (black->data);
-                manager->priv->blacklisted =
-                        g_list_delete_link (manager->priv->blacklisted, black);
+                priv->blacklisted = g_list_delete_link (priv->blacklisted,
+                                                        black);
         }
 }
 
@@ -178,9 +184,12 @@ gupnp_context_manager_filter_context (GUPnPWhiteList *white_list,
         GList *obj;
         GList *blk;
         gboolean match;
+        GUPnPContextManagerPrivate *priv;
 
-        obj = manager->priv->objects;
-        blk = manager->priv->blacklisted;
+        priv = gupnp_context_manager_get_instance_private (manager);
+
+        obj = priv->objects;
+        blk = priv->blacklisted;
 
         while (obj != NULL) {
                 /* If the white list is empty, treat it as disabled */
@@ -235,9 +244,8 @@ gupnp_context_manager_filter_context (GUPnPWhiteList *white_list,
                 g_signal_emit_by_name (manager, "context-available", blk->data);
 
                 g_object_unref (blk->data);
-                manager->priv->blacklisted = g_list_delete_link (
-                                                manager->priv->blacklisted,
-                                                blk);
+                priv->blacklisted = g_list_delete_link (priv->blacklisted,
+                                                        blk);
                 blk = next;
         }
 }
@@ -281,17 +289,16 @@ on_white_list_enabled_cb (GUPnPWhiteList *white_list,
 static void
 gupnp_context_manager_init (GUPnPContextManager *manager)
 {
-        manager->priv =
-                G_TYPE_INSTANCE_GET_PRIVATE (manager,
-                                             GUPNP_TYPE_CONTEXT_MANAGER,
-                                             GUPnPContextManagerPrivate);
+        GUPnPContextManagerPrivate *priv;
+
+        priv = gupnp_context_manager_get_instance_private (manager);
 
-        manager->priv->white_list = gupnp_white_list_new ();
+        priv->white_list = gupnp_white_list_new ();
 
-        g_signal_connect_after (manager->priv->white_list, "notify::entries",
+        g_signal_connect_after (priv->white_list, "notify::entries",
                                 G_CALLBACK (on_white_list_change_cb), manager);
 
-        g_signal_connect_after (manager->priv->white_list, "notify::enabled",
+        g_signal_connect_after (priv->white_list, "notify::enabled",
                                 G_CALLBACK (on_white_list_enabled_cb), manager);
 }
 
@@ -305,7 +312,7 @@ gupnp_context_manager_set_property (GObject      *object,
         GUPnPContextManagerPrivate *priv;
 
         manager = GUPNP_CONTEXT_MANAGER (object);
-        priv = manager->priv;
+        priv = gupnp_context_manager_get_instance_private (manager);
 
         switch (property_id) {
         case PROP_PORT:
@@ -324,15 +331,17 @@ gupnp_context_manager_get_property (GObject    *object,
                                     GParamSpec *pspec)
 {
         GUPnPContextManager *manager;
+        GUPnPContextManagerPrivate *priv;
 
         manager = GUPNP_CONTEXT_MANAGER (object);
+        priv = gupnp_context_manager_get_instance_private (manager);
 
         switch (property_id) {
         case PROP_PORT:
-                g_value_set_uint (value, manager->priv->port);
+                g_value_set_uint (value, priv->port);
                 break;
         case PROP_WHITE_LIST:
-                g_value_set_object (value, manager->priv->white_list);
+                g_value_set_object (value, priv->white_list);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -346,9 +355,12 @@ gupnp_context_manager_dispose (GObject *object)
         GUPnPContextManager *manager;
         GUPnPWhiteList *wl;
         GObjectClass *object_class;
+        GUPnPContextManagerPrivate *priv;
 
         manager = GUPNP_CONTEXT_MANAGER (object);
-        wl = manager->priv->white_list;
+        priv = gupnp_context_manager_get_instance_private (manager);
+
+        wl = priv->white_list;
 
         g_signal_handlers_disconnect_by_func (wl,
                                               on_white_list_enabled_cb,
@@ -358,14 +370,14 @@ gupnp_context_manager_dispose (GObject *object)
                                               on_white_list_change_cb,
                                               NULL);
 
-        g_list_free_full (manager->priv->objects, g_object_unref);
-        manager->priv->objects = NULL;
-        g_list_free_full (manager->priv->blacklisted, g_object_unref);
-        manager->priv->blacklisted = NULL;
+        g_list_free_full (priv->objects, g_object_unref);
+        priv->objects = NULL;
+        g_list_free_full (priv->blacklisted, g_object_unref);
+        priv->blacklisted = NULL;
 
         if (wl) {
                 g_object_unref (wl);
-                manager->priv->white_list = NULL;
+                priv->white_list = NULL;
         }
 
         /* Call super */
@@ -384,8 +396,6 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
         object_class->get_property = gupnp_context_manager_get_property;
         object_class->dispose      = gupnp_context_manager_dispose;
 
-        g_type_class_add_private (klass, sizeof (GUPnPContextManagerPrivate));
-
         /**
          * GUPnPContextManager:port:
          *
@@ -547,10 +557,12 @@ void
 gupnp_context_manager_rescan_control_points (GUPnPContextManager *manager)
 {
         GList *l;
+        GUPnPContextManagerPrivate *priv;
 
         g_return_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager));
 
-        l = manager->priv->objects;
+        priv = gupnp_context_manager_get_instance_private (manager);
+        l = priv->objects;
 
         while (l) {
                 if (GUPNP_IS_CONTROL_POINT (l->data)) {
@@ -580,10 +592,13 @@ void
 gupnp_context_manager_manage_control_point (GUPnPContextManager *manager,
                                             GUPnPControlPoint   *control_point)
 {
+        GUPnPContextManagerPrivate *priv;
+
         g_return_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager));
         g_return_if_fail (GUPNP_IS_CONTROL_POINT (control_point));
 
-        manager->priv->objects = g_list_append (manager->priv->objects,
+        priv = gupnp_context_manager_get_instance_private (manager);
+        priv->objects = g_list_append (priv->objects,
                                                 g_object_ref (control_point));
 }
 
@@ -604,11 +619,14 @@ void
 gupnp_context_manager_manage_root_device (GUPnPContextManager *manager,
                                           GUPnPRootDevice     *root_device)
 {
+        GUPnPContextManagerPrivate *priv;
+
         g_return_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager));
         g_return_if_fail (GUPNP_IS_ROOT_DEVICE (root_device));
 
-        manager->priv->objects = g_list_append (manager->priv->objects,
-                                                g_object_ref (root_device));
+        priv = gupnp_context_manager_get_instance_private (manager);
+        priv->objects = g_list_append (priv->objects,
+                                       g_object_ref (root_device));
 }
 
 /**
@@ -623,9 +641,13 @@ gupnp_context_manager_manage_root_device (GUPnPContextManager *manager,
 guint
 gupnp_context_manager_get_port (GUPnPContextManager *manager)
 {
+        GUPnPContextManagerPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager), 0);
 
-        return manager->priv->port;
+        priv = gupnp_context_manager_get_instance_private (manager);
+
+        return priv->port;
 }
 
 /**
@@ -640,7 +662,11 @@ gupnp_context_manager_get_port (GUPnPContextManager *manager)
 GUPnPWhiteList *
 gupnp_context_manager_get_white_list (GUPnPContextManager *manager)
 {
+        GUPnPContextManagerPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager), NULL);
 
-        return manager->priv->white_list;
+        priv = gupnp_context_manager_get_instance_private (manager);
+
+        return priv->white_list;
 }
diff --git a/libgupnp/gupnp-context-manager.h b/libgupnp/gupnp-context-manager.h
index f470046..f2630c1 100644
--- a/libgupnp/gupnp-context-manager.h
+++ b/libgupnp/gupnp-context-manager.h
@@ -32,45 +32,14 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_context_manager_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_CONTEXT_MANAGER \
                 (gupnp_context_manager_get_type ())
-#define GUPNP_CONTEXT_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_CONTEXT_MANAGER, \
-                 GUPnPContextManager))
-#define GUPNP_CONTEXT_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_CONTEXT_MANAGER, \
-                 GUPnPContextManagerClass))
-#define GUPNP_IS_CONTEXT_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_CONTEXT_MANAGER))
-#define GUPNP_IS_CONTEXT_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_CONTEXT_MANAGER))
-#define GUPNP_CONTEXT_MANAGER_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_CONTEXT_MANAGER, \
-                 GUPnPContextManagerClass))
-
-typedef struct _GUPnPContextManagerPrivate GUPnPContextManagerPrivate;
-typedef struct _GUPnPContextManager GUPnPContextManager;
-typedef struct _GUPnPContextManagerClass GUPnPContextManagerClass;
-
-/**
- * GUPnPContextManager:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPContextManager {
-        GObject parent;
 
-        GUPnPContextManagerPrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPContextManager,
+                          gupnp_context_manager,
+                          GUPNP,
+                          CONTEXT_MANAGER,
+                          GObject)
 
 struct _GUPnPContextManagerClass {
         GObjectClass parent_class;
diff --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index 9d30f4b..1a947c5 100644
--- a/libgupnp/gupnp-context.c
+++ b/libgupnp/gupnp-context.c
@@ -74,15 +74,6 @@ static void
 gupnp_context_initable_iface_init (gpointer g_iface,
                                    gpointer iface_data);
 
-
-G_DEFINE_TYPE_EXTENDED (GUPnPContext,
-                        gupnp_context,
-                        GSSDP_TYPE_CLIENT,
-                        0,
-                        G_IMPLEMENT_INTERFACE
-                                (G_TYPE_INITABLE,
-                                 gupnp_context_initable_iface_init));
-
 struct _GUPnPContextPrivate {
         guint        port;
 
@@ -98,6 +89,16 @@ struct _GUPnPContextPrivate {
 
         GUPnPAcl    *acl;
 };
+typedef struct _GUPnPContextPrivate GUPnPContextPrivate;
+
+G_DEFINE_TYPE_EXTENDED (GUPnPContext,
+                        gupnp_context,
+                        GSSDP_TYPE_CLIENT,
+                        0,
+                        G_ADD_PRIVATE(GUPnPContext)
+                        G_IMPLEMENT_INTERFACE
+                                (G_TYPE_INITABLE,
+                                 gupnp_context_initable_iface_init));
 
 enum {
         PROP_0,
@@ -162,11 +163,6 @@ gupnp_context_init (GUPnPContext *context)
 {
         char *server_id;
 
-        context->priv =
-                G_TYPE_INSTANCE_GET_PRIVATE (context,
-                                             GUPNP_TYPE_CONTEXT,
-                                             GUPnPContextPrivate);
-
         server_id = make_server_id ();
         gssdp_client_set_server_id (GSSDP_CLIENT (context), server_id);
         g_free (server_id);
@@ -180,6 +176,7 @@ gupnp_context_initable_init (GInitable     *initable,
         char *user_agent;
         GError *inner_error = NULL;
         GUPnPContext *context;
+        GUPnPContextPrivate *priv;
 
         if (!initable_parent_iface->init(initable,
                                          cancellable,
@@ -190,12 +187,13 @@ gupnp_context_initable_init (GInitable     *initable,
         }
 
         context = GUPNP_CONTEXT (initable);
+        priv = gupnp_context_get_instance_private (context);
 
-        context->priv->session = soup_session_new ();
+        priv->session = soup_session_new ();
 
         user_agent = g_strdup_printf ("%s GUPnP/" VERSION " DLNADOC/1.50",
                                       g_get_prgname ()? : "");
-        g_object_set (context->priv->session,
+        g_object_set (priv->session,
                       SOUP_SESSION_USER_AGENT,
                       user_agent,
                       NULL);
@@ -204,23 +202,23 @@ gupnp_context_initable_init (GInitable     *initable,
         if (g_getenv ("GUPNP_DEBUG")) {
                 SoupLogger *logger;
                 logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1);
-                soup_session_add_feature (context->priv->session,
+                soup_session_add_feature (priv->session,
                                           SOUP_SESSION_FEATURE (logger));
         }
 
         /* Create the server already if the port is not null*/
-        if (context->priv->port != 0) {
+        if (priv->port != 0) {
                 gupnp_context_get_server (context);
 
-                if (context->priv->server == NULL) {
-                        g_object_unref (context->priv->session);
-                        context->priv->session = NULL;
+                if (priv->server == NULL) {
+                        g_object_unref (priv->session);
+                        priv->session = NULL;
 
                         g_set_error (error,
                                      GUPNP_SERVER_ERROR,
                                      GUPNP_SERVER_ERROR_OTHER,
                                      "Could not create HTTP server on port %d",
-                                     context->priv->port);
+                                     priv->port);
 
                         return FALSE;
                 }
@@ -245,15 +243,17 @@ gupnp_context_set_property (GObject      *object,
                             GParamSpec   *pspec)
 {
         GUPnPContext *context;
+        GUPnPContextPrivate *priv;
 
         context = GUPNP_CONTEXT (object);
+        priv = gupnp_context_get_instance_private (context);
 
         switch (property_id) {
         case PROP_PORT:
-                context->priv->port = g_value_get_uint (value);
+                priv->port = g_value_get_uint (value);
                 break;
         case PROP_SUBSCRIPTION_TIMEOUT:
-                context->priv->subscription_timeout = g_value_get_uint (value);
+                priv->subscription_timeout = g_value_get_uint (value);
                 break;
         case PROP_DEFAULT_LANGUAGE:
                 gupnp_context_set_default_language (context,
@@ -317,26 +317,28 @@ static void
 gupnp_context_dispose (GObject *object)
 {
         GUPnPContext *context;
+        GUPnPContextPrivate *priv;
         GObjectClass *object_class;
 
         context = GUPNP_CONTEXT (object);
+        priv = gupnp_context_get_instance_private (context);
 
-        if (context->priv->session) {
-                g_object_unref (context->priv->session);
-                context->priv->session = NULL;
+        if (priv->session) {
+                g_object_unref (priv->session);
+                priv->session = NULL;
         }
 
-        while (context->priv->host_path_datas) {
+        while (priv->host_path_datas) {
                 HostPathData *data;
 
-                data = (HostPathData *) context->priv->host_path_datas->data;
+                data = (HostPathData *) priv->host_path_datas->data;
 
                 gupnp_context_unhost_path (context, data->server_path);
         }
 
-        if (context->priv->server) {
-                g_object_unref (context->priv->server);
-                context->priv->server = NULL;
+        if (priv->server) {
+                g_object_unref (priv->server);
+                priv->server = NULL;
         }
 
         /* Call super */
@@ -348,14 +350,16 @@ static void
 gupnp_context_finalize (GObject *object)
 {
         GUPnPContext *context;
+        GUPnPContextPrivate *priv;
         GObjectClass *object_class;
 
         context = GUPNP_CONTEXT (object);
+        priv = gupnp_context_get_instance_private (context);
 
-        g_free (context->priv->default_language);
+        g_free (priv->default_language);
 
-        if (context->priv->server_uri)
-                soup_uri_free (context->priv->server_uri);
+        if (priv->server_uri)
+                soup_uri_free (priv->server_uri);
 
         /* Call super */
         object_class = G_OBJECT_CLASS (gupnp_context_parent_class);
@@ -413,8 +417,6 @@ gupnp_context_class_init (GUPnPContextClass *klass)
         object_class->finalize     = gupnp_context_finalize;
         object_class->constructor  = gupnp_context_constructor;
 
-        g_type_class_add_private (klass, sizeof (GUPnPContextPrivate));
-
         /**
          * GUPnPContext:port:
          *
@@ -543,9 +545,13 @@ gupnp_context_class_init (GUPnPContextClass *klass)
 SoupSession *
 gupnp_context_get_session (GUPnPContext *context)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
 
-        return context->priv->session;
+        priv = gupnp_context_get_instance_private (context);
+
+        return priv->session;
 }
 
 /*
@@ -573,27 +579,30 @@ default_server_handler (G_GNUC_UNUSED SoupServer        *server,
 SoupServer *
 gupnp_context_get_server (GUPnPContext *context)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
+        priv = gupnp_context_get_instance_private (context);
 
-        if (context->priv->server == NULL) {
+        if (priv->server == NULL) {
                 const char *ip = NULL;
                 guint port = 0;
                 GSocketAddress *addr = NULL;
                 GError *error = NULL;
 
-                context->priv->server = soup_server_new (NULL, NULL);
+                priv->server = soup_server_new (NULL, NULL);
 
-                soup_server_add_handler (context->priv->server,
+                soup_server_add_handler (priv->server,
                                          NULL,
                                          default_server_handler,
                                          context,
                                          NULL);
 
                 ip = gssdp_client_get_host_ip (GSSDP_CLIENT (context));
-                port = context->priv->port;
+                port = priv->port;
                 addr = g_inet_socket_address_new_from_string (ip, port);
 
-                if (! soup_server_listen (context->priv->server,
+                if (! soup_server_listen (priv->server,
                                           addr, (SoupServerListenOptions) 0, &error)) {
                         g_warning ("GUPnPContext: Unable to listen on %s:%u %s", ip, port, error->message);
                         g_error_free (error);
@@ -602,7 +611,7 @@ gupnp_context_get_server (GUPnPContext *context)
                 g_object_unref (addr);
         }
 
-        return context->priv->server;
+        return priv->server;
 }
 
 /*
@@ -625,11 +634,14 @@ make_server_uri (GUPnPContext *context)
 SoupURI *
 _gupnp_context_get_server_uri (GUPnPContext *context)
 {
-        if (context->priv->server_uri == NULL)
-                context->priv->server_uri = make_server_uri (context);
+        GUPnPContextPrivate *priv;
+
+        priv = gupnp_context_get_instance_private (context);
+        if (priv->server_uri == NULL)
+                priv->server_uri = make_server_uri (context);
 
-        if (context->priv->server_uri)
-                return soup_uri_copy (context->priv->server_uri);
+        if (priv->server_uri)
+                return soup_uri_copy (priv->server_uri);
 
         return NULL;
 }
@@ -670,12 +682,15 @@ gupnp_context_new (const char   *iface,
 guint
 gupnp_context_get_port (GUPnPContext *context)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), 0);
+        priv = gupnp_context_get_instance_private (context);
 
-        if (context->priv->server_uri == NULL)
-                context->priv->server_uri = make_server_uri (context);
+        if (priv->server_uri == NULL)
+                priv->server_uri = make_server_uri (context);
 
-        return soup_uri_get_port (context->priv->server_uri);
+        return soup_uri_get_port (priv->server_uri);
 }
 
 /**
@@ -691,9 +706,12 @@ void
 gupnp_context_set_subscription_timeout (GUPnPContext *context,
                                         guint         timeout)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
+        priv = gupnp_context_get_instance_private (context);
 
-        context->priv->subscription_timeout = timeout;
+        priv->subscription_timeout = timeout;
 
         g_object_notify (G_OBJECT (context), "subscription-timeout");
 }
@@ -710,9 +728,13 @@ gupnp_context_set_subscription_timeout (GUPnPContext *context,
 guint
 gupnp_context_get_subscription_timeout (GUPnPContext *context)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), 0);
 
-        return context->priv->subscription_timeout;
+        priv = gupnp_context_get_instance_private (context);
+
+        return priv->subscription_timeout;
 }
 
 static void
@@ -746,20 +768,22 @@ void
 gupnp_context_set_default_language (GUPnPContext *context,
                                     const char   *language)
 {
+        GUPnPContextPrivate *priv;
         char *old_language = NULL;
 
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
         g_return_if_fail (language != NULL);
+        priv = gupnp_context_get_instance_private (context);
 
 
-        old_language = context->priv->default_language;
+        old_language = priv->default_language;
 
         if ((old_language != NULL) && (!strcmp (language, old_language)))
                 return;
 
-        context->priv->default_language = g_strdup (language);
+        priv->default_language = g_strdup (language);
 
-        g_list_foreach (context->priv->host_path_datas,
+        g_list_foreach (priv->host_path_datas,
                         (GFunc) host_path_data_set_language,
                         (gpointer) language);
 
@@ -780,9 +804,13 @@ gupnp_context_set_default_language (GUPnPContext *context,
 const char *
 gupnp_context_get_default_language (GUPnPContext *context)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
 
-        return context->priv->default_language;
+        priv = gupnp_context_get_instance_private (context);
+
+        return priv->default_language;
 }
 
 /* Construct a local path from @requested path, removing the last slash
@@ -1218,16 +1246,19 @@ gupnp_context_host_path (GUPnPContext *context,
 {
         SoupServer *server;
         HostPathData *path_data;
+        GUPnPContextPrivate *priv;
 
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
         g_return_if_fail (local_path != NULL);
         g_return_if_fail (server_path != NULL);
 
+        priv = gupnp_context_get_instance_private (context);
+
         server = gupnp_context_get_server (context);
 
         path_data = host_path_data_new (local_path,
                                         server_path,
-                                        context->priv->default_language,
+                                        priv->default_language,
                                         context);
 
         soup_server_add_handler (server,
@@ -1236,8 +1267,8 @@ gupnp_context_host_path (GUPnPContext *context,
                                  path_data,
                                  NULL);
 
-        context->priv->host_path_datas =
-                g_list_append (context->priv->host_path_datas,
+        priv->host_path_datas =
+                g_list_append (priv->host_path_datas,
                                path_data);
 }
 
@@ -1269,6 +1300,7 @@ gupnp_context_host_path_for_agent (GUPnPContext *context,
                                    const char   *server_path,
                                    GRegex       *user_agent)
 {
+        GUPnPContextPrivate *priv;
         GList *node;
 
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), FALSE);
@@ -1276,7 +1308,8 @@ gupnp_context_host_path_for_agent (GUPnPContext *context,
         g_return_val_if_fail (server_path != NULL, FALSE);
         g_return_val_if_fail (user_agent != NULL, FALSE);
 
-        node = g_list_find_custom (context->priv->host_path_datas,
+        priv = gupnp_context_get_instance_private (context);
+        node = g_list_find_custom (priv->host_path_datas,
                                    server_path,
                                    (GCompareFunc) path_compare_func);
         if (node != NULL) {
@@ -1307,21 +1340,23 @@ gupnp_context_unhost_path (GUPnPContext *context,
 {
         SoupServer *server;
         HostPathData *path_data;
+        GUPnPContextPrivate *priv;
         GList *node;
 
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
         g_return_if_fail (server_path != NULL);
 
+        priv = gupnp_context_get_instance_private (context);
         server = gupnp_context_get_server (context);
 
-        node = g_list_find_custom (context->priv->host_path_datas,
+        node = g_list_find_custom (priv->host_path_datas,
                                    server_path,
                                    (GCompareFunc) path_compare_func);
         g_return_if_fail (node != NULL);
 
         path_data = (HostPathData *) node->data;
-        context->priv->host_path_datas = g_list_delete_link (
-                        context->priv->host_path_datas,
+        priv->host_path_datas = g_list_delete_link (
+                        priv->host_path_datas,
                         node);
 
         soup_server_remove_handler (server, server_path);
@@ -1340,9 +1375,12 @@ gupnp_context_unhost_path (GUPnPContext *context,
 GUPnPAcl *
 gupnp_context_get_acl (GUPnPContext *context)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
 
-        return context->priv->acl;
+        priv = gupnp_context_get_instance_private (context);
+        return priv->acl;
 }
 
 /**
@@ -1356,15 +1394,18 @@ gupnp_context_get_acl (GUPnPContext *context)
 void
 gupnp_context_set_acl (GUPnPContext *context, GUPnPAcl *acl)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
 
-        if (context->priv->acl != NULL) {
-                g_object_unref (context->priv->acl);
-                context->priv->acl = NULL;
+        priv = gupnp_context_get_instance_private (context);
+        if (priv->acl != NULL) {
+                g_object_unref (priv->acl);
+                priv->acl = NULL;
         }
 
         if (acl != NULL)
-                context->priv->acl = g_object_ref (acl);
+                priv->acl = g_object_ref (acl);
 
         g_object_notify (G_OBJECT (context), "acl");
 }
@@ -1404,7 +1445,9 @@ gupnp_acl_server_handler (SoupServer *server,
         const char *agent;
         const char *host;
         GUPnPDevice *device = NULL;
+        GUPnPContextPrivate *priv;
 
+        priv = gupnp_context_get_instance_private (handler->context);
         host = soup_client_context_get_host (client);
 
         if (handler->service) {
@@ -1425,9 +1468,9 @@ gupnp_acl_server_handler (SoupServer *server,
                                  host);
         }
 
-        if (handler->context->priv->acl != NULL) {
-                if (gupnp_acl_can_sync (handler->context->priv->acl)) {
-                        if (!gupnp_acl_is_allowed (handler->context->priv->acl,
+        if (priv->acl != NULL) {
+                if (gupnp_acl_can_sync (priv->acl)) {
+                        if (!gupnp_acl_is_allowed (priv->acl,
                                                    device,
                                                    handler->service,
                                                    path,
@@ -1443,7 +1486,7 @@ gupnp_acl_server_handler (SoupServer *server,
                         data = acl_async_handler_new (server, msg, path, query, client, handler);
 
                         soup_server_pause_message (server, msg);
-                        gupnp_acl_is_allowed_async (handler->context->priv->acl,
+                        gupnp_acl_is_allowed_async (priv->acl,
                                                     device,
                                                     handler->service,
                                                     path,
@@ -1483,18 +1526,21 @@ gupnp_context_add_server_handler (GUPnPContext *context,
                                   gpointer user_data,
                                   GDestroyNotify destroy)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
 
+        priv = gupnp_context_get_instance_private (context);
         if (use_acl) {
                 AclServerHandler *handler;
                 handler = acl_server_handler_new (NULL, context, callback, user_data, destroy);
-                soup_server_add_handler (context->priv->server,
+                soup_server_add_handler (priv->server,
                                          path,
                                          gupnp_acl_server_handler,
                                          handler,
                                          (GDestroyNotify) acl_server_handler_free);
         } else
-                soup_server_add_handler (context->priv->server,
+                soup_server_add_handler (priv->server,
                                          path,
                                          callback,
                                          user_data,
@@ -1506,9 +1552,12 @@ _gupnp_context_add_server_handler_with_data (GUPnPContext *context,
                                              const char *path,
                                              AclServerHandler *handler)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
 
-        soup_server_add_handler (context->priv->server,
+        priv = gupnp_context_get_instance_private (context);
+        soup_server_add_handler (priv->server,
                                  path,
                                  gupnp_acl_server_handler,
                                  handler,
@@ -1527,7 +1576,10 @@ _gupnp_context_add_server_handler_with_data (GUPnPContext *context,
 void
 gupnp_context_remove_server_handler (GUPnPContext *context, const char *path)
 {
+        GUPnPContextPrivate *priv;
+
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
 
-        soup_server_remove_handler (context->priv->server, path);
+        priv = gupnp_context_get_instance_private (context);
+        soup_server_remove_handler (priv->server, path);
 }
diff --git a/libgupnp/gupnp-context.h b/libgupnp/gupnp-context.h
index b5d7d24..ab56d62 100644
--- a/libgupnp/gupnp-context.h
+++ b/libgupnp/gupnp-context.h
@@ -30,45 +30,10 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_context_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_CONTEXT \
                 (gupnp_context_get_type ())
-#define GUPNP_CONTEXT(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_CONTEXT, \
-                 GUPnPContext))
-#define GUPNP_CONTEXT_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_CONTEXT, \
-                 GUPnPContextClass))
-#define GUPNP_IS_CONTEXT(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_CONTEXT))
-#define GUPNP_IS_CONTEXT_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_CONTEXT))
-#define GUPNP_CONTEXT_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_CONTEXT, \
-                 GUPnPContextClass))
-
-typedef struct _GUPnPContextPrivate GUPnPContextPrivate;
-typedef struct _GUPnPContext GUPnPContext;
-typedef struct _GUPnPContextClass GUPnPContextClass;
-
-/**
- * GUPnPContext:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPContext {
-        GSSDPClient parent;
 
-        GUPnPContextPrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPContext, gupnp_context, GUPNP, CONTEXT, GSSDPClient)
 
 struct _GUPnPContextClass {
         GSSDPClientClass parent_class;
diff --git a/libgupnp/gupnp-control-point.c b/libgupnp/gupnp-control-point.c
index ea40ad6..eb93c8c 100644
--- a/libgupnp/gupnp-control-point.c
+++ b/libgupnp/gupnp-control-point.c
@@ -42,10 +42,6 @@
 #define GUPNP_MAX_DESCRIPTION_DOWNLOAD_RETRIES 4
 #define GUPNP_INITIAL_DESCRIPTION_RETRY_TIMEOUT 5
 
-G_DEFINE_TYPE (GUPnPControlPoint,
-               gupnp_control_point,
-               GSSDP_TYPE_RESOURCE_BROWSER);
-
 struct _GUPnPControlPointPrivate {
         GUPnPResourceFactory *factory;
 
@@ -56,6 +52,11 @@ struct _GUPnPControlPointPrivate {
 
         GList *pending_gets;
 };
+typedef struct _GUPnPControlPointPrivate GUPnPControlPointPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPControlPoint,
+                            gupnp_control_point,
+                            GSSDP_TYPE_RESOURCE_BROWSER);
 
 enum {
         PROP_0,
@@ -85,12 +86,14 @@ typedef struct {
         int timeout;
 } GetDescriptionURLData;
 
+static void
+gupnp_control_point_remove_pending_get (GUPnPControlPoint     *control_point,
+                                        GetDescriptionURLData *data);
+
 static void
 get_description_url_data_free (GetDescriptionURLData *data)
 {
-        data->control_point->priv->pending_gets =
-                g_list_remove (data->control_point->priv->pending_gets, data);
-
+        gupnp_control_point_remove_pending_get (data->control_point, data);
         if (data->message) {
                 GUPnPContext *context;
                 SoupSession *session;
@@ -121,7 +124,11 @@ find_get_description_url_data (GUPnPControlPoint *control_point,
                                const char        *udn,
                                const char        *service_type)
 {
-        GList *l = control_point->priv->pending_gets;
+        GList *l;
+        GUPnPControlPointPrivate *priv;
+
+        priv = gupnp_control_point_get_instance_private (control_point);
+        l = priv->pending_gets;
 
         while (l) {
                 GetDescriptionURLData *data = l->data;
@@ -139,23 +146,20 @@ find_get_description_url_data (GUPnPControlPoint *control_point,
 static void
 gupnp_control_point_init (GUPnPControlPoint *control_point)
 {
-        control_point->priv =
-                G_TYPE_INSTANCE_GET_PRIVATE (control_point,
-                                             GUPNP_TYPE_CONTROL_POINT,
-                                             GUPnPControlPointPrivate);
-
-        control_point->priv->doc_cache =
-                g_hash_table_new_full (g_str_hash,
-                                       g_str_equal,
-                                       g_free,
-                                       NULL);
+        GUPnPControlPointPrivate *priv;
+
+        priv = gupnp_control_point_get_instance_private (control_point);
+        priv->doc_cache = g_hash_table_new_full (g_str_hash,
+                                                 g_str_equal,
+                                                 g_free,
+                                                 NULL);
 }
 
 /* Return TRUE if value == user_data */
 static gboolean
 find_doc (G_GNUC_UNUSED gpointer key,
           gpointer               value,
-          G_GNUC_UNUSED gpointer user_data)
+          gpointer               user_data)
 {
         return (value == user_data);
 }
@@ -166,10 +170,12 @@ doc_finalized (gpointer user_data,
                GObject *where_the_object_was)
 {
         GUPnPControlPoint *control_point;
+        GUPnPControlPointPrivate *priv;
 
         control_point = GUPNP_CONTROL_POINT (user_data);
+        priv = gupnp_control_point_get_instance_private (control_point);
 
-        g_hash_table_foreach_remove (control_point->priv->doc_cache,
+        g_hash_table_foreach_remove (priv->doc_cache,
                                      find_doc,
                                      where_the_object_was);
 }
@@ -189,27 +195,29 @@ gupnp_control_point_dispose (GObject *object)
         GUPnPControlPoint *control_point;
         GSSDPResourceBrowser *browser;
         GObjectClass *object_class;
+        GUPnPControlPointPrivate *priv;
 
         control_point = GUPNP_CONTROL_POINT (object);
+        priv = gupnp_control_point_get_instance_private (control_point);
         browser = GSSDP_RESOURCE_BROWSER (control_point);
 
         gssdp_resource_browser_set_active (browser, FALSE);
 
-        if (control_point->priv->factory) {
-                g_object_unref (control_point->priv->factory);
-                control_point->priv->factory = NULL;
+        if (priv->factory) {
+                g_object_unref (priv->factory);
+                priv->factory = NULL;
         }
 
         /* Cancel any pending description file GETs */
-        while (control_point->priv->pending_gets) {
+        while (priv->pending_gets) {
                 GetDescriptionURLData *data;
 
-                data = control_point->priv->pending_gets->data;
+                data = priv->pending_gets->data;
                 get_description_url_data_free (data);
         }
 
         /* Release weak references on remaining cached documents */
-        g_hash_table_foreach (control_point->priv->doc_cache,
+        g_hash_table_foreach (priv->doc_cache,
                               weak_unref_doc,
                               control_point);
 
@@ -223,10 +231,12 @@ gupnp_control_point_finalize (GObject *object)
 {
         GUPnPControlPoint *control_point;
         GObjectClass *object_class;
+        GUPnPControlPointPrivate *priv;
 
         control_point = GUPNP_CONTROL_POINT (object);
+        priv = gupnp_control_point_get_instance_private (control_point);
 
-        g_hash_table_destroy (control_point->priv->doc_cache);
+        g_hash_table_destroy (priv->doc_cache);
 
         /* Call super */
         object_class = G_OBJECT_CLASS (gupnp_control_point_parent_class);
@@ -239,8 +249,10 @@ find_service_node (GUPnPControlPoint *control_point,
                    const char        *service_type)
 {
         GList *l;
+        GUPnPControlPointPrivate *priv;
 
-        l = control_point->priv->services;
+        priv = gupnp_control_point_get_instance_private (control_point);
+        l = priv->services;
 
         while (l) {
                 GUPnPServiceInfo *info;
@@ -263,8 +275,10 @@ find_device_node (GUPnPControlPoint *control_point,
                   const char        *udn)
 {
         GList *l;
+        GUPnPControlPointPrivate *priv;
 
-        l = control_point->priv->devices;
+        priv = gupnp_control_point_get_instance_private (control_point);
+        l = priv->devices;
 
         while (l) {
                 GUPnPDeviceInfo *info;
@@ -292,11 +306,13 @@ create_and_report_service_proxy (GUPnPControlPoint  *control_point,
         GUPnPServiceProxy *proxy;
         GUPnPResourceFactory *factory;
         GUPnPContext *context;
+        GUPnPControlPointPrivate *priv;
 
         if (find_service_node (control_point, udn, service_type) != NULL)
                 /* We already have a proxy for this service */
                 return;
 
+        priv = gupnp_control_point_get_instance_private (control_point);
         factory = gupnp_control_point_get_resource_factory (control_point);
         context = gupnp_control_point_get_context (control_point);
 
@@ -310,9 +326,7 @@ create_and_report_service_proxy (GUPnPControlPoint  *control_point,
                                                              description_url,
                                                              url_base);
 
-        control_point->priv->services =
-                                g_list_prepend (control_point->priv->services,
-                                                proxy);
+        priv->services = g_list_prepend (priv->services, proxy);
 
         g_signal_emit (control_point,
                        signals[SERVICE_PROXY_AVAILABLE],
@@ -331,11 +345,13 @@ create_and_report_device_proxy (GUPnPControlPoint  *control_point,
         GUPnPDeviceProxy *proxy;
         GUPnPResourceFactory *factory;
         GUPnPContext *context;
+        GUPnPControlPointPrivate *priv;
 
         if (find_device_node (control_point, udn) != NULL)
                 /* We already have a proxy for this device */
                 return;
 
+        priv = gupnp_control_point_get_instance_private (control_point);
         factory = gupnp_control_point_get_resource_factory (control_point);
         context = gupnp_control_point_get_context (control_point);
 
@@ -347,9 +363,7 @@ create_and_report_device_proxy (GUPnPControlPoint  *control_point,
                                                             description_url,
                                                             url_base);
 
-        control_point->priv->devices = g_list_prepend
-                                                (control_point->priv->devices,
-                                                 proxy);
+        priv->devices = g_list_prepend (priv->devices, proxy);
 
         g_signal_emit (control_point,
                        signals[DEVICE_PROXY_AVAILABLE],
@@ -531,7 +545,8 @@ description_loaded (GUPnPControlPoint *control_point,
         SoupURI *url_base;
 
         /* Save the URL base, if any */
-        element = xml_util_get_element ((xmlNode *) doc->doc,
+        element = xml_util_get_element ((xmlNode *)
+                                        gupnp_xml_doc_get_doc (doc),
                                         "root",
                                         NULL);
         if (element == NULL) {
@@ -575,16 +590,17 @@ got_description_url (SoupSession           *session,
                      GetDescriptionURLData *data)
 {
         GUPnPXMLDoc *doc;
+        GUPnPControlPointPrivate *priv;
 
         if (msg->status_code == SOUP_STATUS_CANCELLED)
                 return;
 
         data->message = NULL;
+        priv = gupnp_control_point_get_instance_private (data->control_point);
 
         /* Now, make sure again this document is not already cached. If it is,
          * we re-use the cached one. */
-        doc = g_hash_table_lookup (data->control_point->priv->doc_cache,
-                                   data->description_url);
+        doc = g_hash_table_lookup (priv->doc_cache, data->description_url);
         if (doc) {
                 /* Doc was cached */
                 description_loaded (data->control_point,
@@ -615,10 +631,9 @@ got_description_url (SoupSession           *session,
                                             data->description_url);
 
                         /* Insert into document cache */
-                        g_hash_table_insert
-                                          (data->control_point->priv->doc_cache,
-                                           g_strdup (data->description_url),
-                                           doc);
+                        g_hash_table_insert (priv->doc_cache,
+                                             g_strdup (data->description_url),
+                                             doc);
 
                         /* Make sure the document is removed from the cache
                          * once finalized. */
@@ -677,8 +692,10 @@ load_description (GUPnPControlPoint *control_point,
                   guint              timeout)
 {
         GUPnPXMLDoc *doc;
+        GUPnPControlPointPrivate *priv;
 
-        doc = g_hash_table_lookup (control_point->priv->doc_cache,
+        priv = gupnp_control_point_get_instance_private (control_point);
+        doc = g_hash_table_lookup (priv->doc_cache,
                                    description_url);
         if (doc) {
                 /* Doc was cached */
@@ -721,9 +738,8 @@ load_description (GUPnPControlPoint *control_point,
                 data->description_url = g_strdup (description_url);
                 data->timeout_source  = NULL;
 
-                control_point->priv->pending_gets =
-                        g_list_prepend (control_point->priv->pending_gets,
-                                        data);
+                priv->pending_gets = g_list_prepend (priv->pending_gets,
+                                                     data);
 
                 soup_session_queue_message (session,
                                             data->message,
@@ -874,8 +890,10 @@ gupnp_control_point_resource_unavailable
         GUPnPControlPoint *control_point;
         char *udn, *service_type;
         GetDescriptionURLData *get_data;
+        GUPnPControlPointPrivate *priv;
 
         control_point = GUPNP_CONTROL_POINT (resource_browser);
+        priv = gupnp_control_point_get_instance_private (control_point);
 
         /* Parse USN */
         if (!parse_usn (usn, &udn, &service_type))
@@ -891,9 +909,8 @@ gupnp_control_point_resource_unavailable
                         /* Remove proxy */
                         proxy = GUPNP_SERVICE_PROXY (l->data);
 
-                        control_point->priv->services =
-                                g_list_delete_link
-                                        (control_point->priv->services, l);
+                        priv->services = g_list_delete_link (priv->services,
+                                                             l);
 
                         g_signal_emit (control_point,
                                        signals[SERVICE_PROXY_UNAVAILABLE],
@@ -911,9 +928,8 @@ gupnp_control_point_resource_unavailable
                         /* Remove proxy */
                         proxy = GUPNP_DEVICE_PROXY (l->data);
 
-                        control_point->priv->devices =
-                                 g_list_delete_link
-                                        (control_point->priv->devices, l);
+                        priv->devices = g_list_delete_link (priv->devices,
+                                                            l);
 
                         g_signal_emit (control_point,
                                        signals[DEVICE_PROXY_UNAVAILABLE],
@@ -945,12 +961,14 @@ gupnp_control_point_set_property (GObject      *object,
                                   GParamSpec   *pspec)
 {
         GUPnPControlPoint *control_point;
+        GUPnPControlPointPrivate *priv;
 
         control_point = GUPNP_CONTROL_POINT (object);
+        priv = gupnp_control_point_get_instance_private (control_point);
 
         switch (property_id) {
         case PROP_RESOURCE_FACTORY:
-                control_point->priv->factory = 
+                priv->factory =
                         GUPNP_RESOURCE_FACTORY (g_value_dup_object (value));
                 break;
         default:
@@ -980,6 +998,17 @@ gupnp_control_point_get_property (GObject    *object,
         }
 }
 
+static void
+gupnp_control_point_remove_pending_get (GUPnPControlPoint     *control_point,
+                                        GetDescriptionURLData *data)
+{
+        GUPnPControlPointPrivate *priv;
+
+        priv = gupnp_control_point_get_instance_private (control_point);
+        priv->pending_gets = g_list_remove (priv->pending_gets, data);
+}
+
+
 static void
 gupnp_control_point_class_init (GUPnPControlPointClass *klass)
 {
@@ -1000,8 +1029,6 @@ gupnp_control_point_class_init (GUPnPControlPointClass *klass)
         browser_class->resource_unavailable =
                 gupnp_control_point_resource_unavailable;
 
-        g_type_class_add_private (klass, sizeof (GUPnPControlPointPrivate));
-
         /**
          * GUPnPControlPoint:resource-factory:
          *
@@ -1197,9 +1224,13 @@ gupnp_control_point_get_context (GUPnPControlPoint *control_point)
 const GList *
 gupnp_control_point_list_device_proxies (GUPnPControlPoint *control_point)
 {
+        GUPnPControlPointPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTROL_POINT (control_point), NULL);
 
-        return (const GList *) control_point->priv->devices;
+        priv = gupnp_control_point_get_instance_private (control_point);
+
+        return (const GList *) priv->devices;
 }
 
 /**
@@ -1215,9 +1246,13 @@ gupnp_control_point_list_device_proxies (GUPnPControlPoint *control_point)
 const GList *
 gupnp_control_point_list_service_proxies (GUPnPControlPoint *control_point)
 {
+        GUPnPControlPointPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTROL_POINT (control_point), NULL);
 
-        return (const GList *) control_point->priv->services;
+        priv = gupnp_control_point_get_instance_private (control_point);
+
+        return (const GList *) priv->services;
 }
 
 /**
@@ -1231,10 +1266,15 @@ gupnp_control_point_list_service_proxies (GUPnPControlPoint *control_point)
 GUPnPResourceFactory *
 gupnp_control_point_get_resource_factory (GUPnPControlPoint *control_point)
 {
+        GUPnPControlPointPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_CONTROL_POINT (control_point), NULL);
 
-        if (control_point->priv->factory)
-                  return control_point->priv->factory;
+        priv = gupnp_control_point_get_instance_private (control_point);
+
+        if (priv->factory)
+                  return priv->factory;
 
         return gupnp_resource_factory_get_default ();
 }
+
diff --git a/libgupnp/gupnp-control-point.h b/libgupnp/gupnp-control-point.h
index 62918ae..4489127 100644
--- a/libgupnp/gupnp-control-point.h
+++ b/libgupnp/gupnp-control-point.h
@@ -31,45 +31,14 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_control_point_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_CONTROL_POINT \
                 (gupnp_control_point_get_type ())
-#define GUPNP_CONTROL_POINT(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_CONTROL_POINT, \
-                 GUPnPControlPoint))
-#define GUPNP_CONTROL_POINT_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_CONTROL_POINT, \
-                 GUPnPControlPointClass))
-#define GUPNP_IS_CONTROL_POINT(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_CONTROL_POINT))
-#define GUPNP_IS_CONTROL_POINT_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_CONTROL_POINT))
-#define GUPNP_CONTROL_POINT_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_CONTROL_POINT, \
-                 GUPnPControlPointClass))
-
-typedef struct _GUPnPControlPointPrivate GUPnPControlPointPrivate;
-typedef struct _GUPnPControlPoint GUPnPControlPoint;
-typedef struct _GUPnPControlPointClass GUPnPControlPointClass;
-
-/**
- * GUPnPControlPoint:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPControlPoint {
-        GSSDPResourceBrowser parent;
 
-        GUPnPControlPointPrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPControlPoint,
+                          gupnp_control_point,
+                          GUPNP,
+                          CONTROL_POINT,
+                          GSSDPResourceBrowser)
 
 struct _GUPnPControlPointClass {
         GSSDPResourceBrowserClass parent_class;
diff --git a/libgupnp/gupnp-device-info.c b/libgupnp/gupnp-device-info.c
index 754833d..a2b2cbd 100644
--- a/libgupnp/gupnp-device-info.c
+++ b/libgupnp/gupnp-device-info.c
@@ -34,10 +34,6 @@
 #include "gupnp-resource-factory-private.h"
 #include "xml-util.h"
 
-G_DEFINE_ABSTRACT_TYPE (GUPnPDeviceInfo,
-                        gupnp_device_info,
-                        G_TYPE_OBJECT);
-
 struct _GUPnPDeviceInfoPrivate {
         GUPnPResourceFactory *factory;
         GUPnPContext         *context;
@@ -52,6 +48,12 @@ struct _GUPnPDeviceInfoPrivate {
 
         xmlNode *element;
 };
+typedef struct _GUPnPDeviceInfoPrivate GUPnPDeviceInfoPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GUPnPDeviceInfo,
+                                     gupnp_device_info,
+                                     G_TYPE_OBJECT);
+
 
 enum {
         PROP_0,
@@ -68,9 +70,6 @@ enum {
 static void
 gupnp_device_info_init (GUPnPDeviceInfo *info)
 {
-        info->priv = G_TYPE_INSTANCE_GET_PRIVATE (info,
-                                                  GUPNP_TYPE_DEVICE_INFO,
-                                                  GUPnPDeviceInfoPrivate);
 }
 
 static void
@@ -80,34 +79,36 @@ gupnp_device_info_set_property (GObject      *object,
                                 GParamSpec   *pspec)
 {
         GUPnPDeviceInfo *info;
+        GUPnPDeviceInfoPrivate *priv;
 
         info = GUPNP_DEVICE_INFO (object);
+        priv = gupnp_device_info_get_instance_private (info);
 
         switch (property_id) {
         case PROP_RESOURCE_FACTORY:
-                info->priv->factory =
+                priv->factory =
                         GUPNP_RESOURCE_FACTORY (g_value_dup_object (value));
                 break;
         case PROP_CONTEXT:
-                info->priv->context = g_value_dup_object (value);
+                priv->context = g_value_dup_object (value);
                 break;
         case PROP_LOCATION:
-                info->priv->location = g_value_dup_string (value);
+                priv->location = g_value_dup_string (value);
                 break;
         case PROP_UDN:
-                info->priv->udn = g_value_dup_string (value);
+                priv->udn = g_value_dup_string (value);
                 break;
         case PROP_DEVICE_TYPE:
-                info->priv->device_type = g_value_dup_string (value);
+                priv->device_type = g_value_dup_string (value);
                 break;
         case PROP_URL_BASE:
-                info->priv->url_base = g_value_dup_boxed (value);
+                priv->url_base = g_value_dup_boxed (value);
                 break;
         case PROP_DOCUMENT:
-                info->priv->doc = g_value_dup_object (value);
+                priv->doc = g_value_dup_object (value);
                 break;
         case PROP_ELEMENT:
-                info->priv->element = g_value_get_pointer (value);
+                priv->element = g_value_get_pointer (value);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -122,21 +123,23 @@ gupnp_device_info_get_property (GObject    *object,
                                 GParamSpec *pspec)
 {
         GUPnPDeviceInfo *info;
+        GUPnPDeviceInfoPrivate *priv;
 
         info = GUPNP_DEVICE_INFO (object);
+        priv = gupnp_device_info_get_instance_private (info);
 
         switch (property_id) {
         case PROP_RESOURCE_FACTORY:
                 g_value_set_object (value,
-                                    info->priv->factory);
+                                    priv->factory);
                 break;
         case PROP_CONTEXT:
                 g_value_set_object (value,
-                                    info->priv->context);
+                                    priv->context);
                 break;
         case PROP_LOCATION:
                 g_value_set_string (value,
-                                    info->priv->location);
+                                    priv->location);
                 break;
         case PROP_UDN:
                 g_value_set_string (value,
@@ -147,7 +150,7 @@ gupnp_device_info_get_property (GObject    *object,
                                     gupnp_device_info_get_device_type (info));
                 break;
         case PROP_URL_BASE:
-                g_value_set_boxed (value, info->priv->url_base);
+                g_value_set_boxed (value, priv->url_base);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -159,22 +162,24 @@ static void
 gupnp_device_info_dispose (GObject *object)
 {
         GUPnPDeviceInfo *info;
+        GUPnPDeviceInfoPrivate *priv;
 
         info = GUPNP_DEVICE_INFO (object);
+        priv = gupnp_device_info_get_instance_private (info);
 
-        if (info->priv->factory) {
-                g_object_unref (info->priv->factory);
-                info->priv->factory = NULL;
+        if (priv->factory) {
+                g_object_unref (priv->factory);
+                priv->factory = NULL;
         }
 
-        if (info->priv->context) {
-                g_object_unref (info->priv->context);
-                info->priv->context = NULL;
+        if (priv->context) {
+                g_object_unref (priv->context);
+                priv->context = NULL;
         }
 
-        if (info->priv->doc) {
-                g_object_unref (info->priv->doc);
-                info->priv->doc = NULL;
+        if (priv->doc) {
+                g_object_unref (priv->doc);
+                priv->doc = NULL;
         }
 
         G_OBJECT_CLASS (gupnp_device_info_parent_class)->dispose (object);
@@ -184,14 +189,16 @@ static void
 gupnp_device_info_finalize (GObject *object)
 {
         GUPnPDeviceInfo *info;
+        GUPnPDeviceInfoPrivate *priv;
 
         info = GUPNP_DEVICE_INFO (object);
+        priv = gupnp_device_info_get_instance_private (info);
 
-        g_free (info->priv->location);
-        g_free (info->priv->udn);
-        g_free (info->priv->device_type);
+        g_free (priv->location);
+        g_free (priv->udn);
+        g_free (priv->device_type);
 
-        g_clear_pointer (&info->priv->url_base, soup_uri_free);
+        g_clear_pointer (&priv->url_base, soup_uri_free);
 
         G_OBJECT_CLASS (gupnp_device_info_parent_class)->finalize (object);
 }
@@ -208,8 +215,6 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
         object_class->dispose      = gupnp_device_info_dispose;
         object_class->finalize     = gupnp_device_info_finalize;
 
-        g_type_class_add_private (klass, sizeof (GUPnPDeviceInfoPrivate));
-
         /**
          * GUPnPDeviceInfo:resource-factory:
          *
@@ -372,9 +377,13 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
 GUPnPResourceFactory *
 gupnp_device_info_get_resource_factory (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return info->priv->factory;
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return priv->factory;
 }
 
 /**
@@ -388,9 +397,13 @@ gupnp_device_info_get_resource_factory (GUPnPDeviceInfo *info)
 GUPnPContext *
 gupnp_device_info_get_context (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return info->priv->context;
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return priv->context;
 }
 
 /**
@@ -404,9 +417,13 @@ gupnp_device_info_get_context (GUPnPDeviceInfo *info)
 const char *
 gupnp_device_info_get_location (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return info->priv->location;
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return priv->location;
 }
 
 /**
@@ -420,9 +437,13 @@ gupnp_device_info_get_location (GUPnPDeviceInfo *info)
 const SoupURI *
 gupnp_device_info_get_url_base (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return info->priv->url_base;
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return priv->url_base;
 }
 
 /**
@@ -436,15 +457,18 @@ gupnp_device_info_get_url_base (GUPnPDeviceInfo *info)
 const char *
 gupnp_device_info_get_udn (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        if (!info->priv->udn) {
-                info->priv->udn =
+        priv = gupnp_device_info_get_instance_private (info);
+        if (!priv->udn) {
+                priv->udn =
                         xml_util_get_child_element_content_glib
-                                (info->priv->element, "UDN");
+                                (priv->element, "UDN");
         }
 
-        return info->priv->udn;
+        return priv->udn;
 }
 
 /**
@@ -458,15 +482,18 @@ gupnp_device_info_get_udn (GUPnPDeviceInfo *info)
 const char *
 gupnp_device_info_get_device_type (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        if (!info->priv->device_type) {
-                info->priv->device_type =
+        priv = gupnp_device_info_get_instance_private (info);
+        if (!priv->device_type) {
+                priv->device_type =
                         xml_util_get_child_element_content_glib
-                                (info->priv->element, "deviceType");
+                                (priv->element, "deviceType");
         }
 
-        return info->priv->device_type;
+        return priv->device_type;
 }
 
 /**
@@ -480,9 +507,13 @@ gupnp_device_info_get_device_type (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_friendly_name (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_glib (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_glib (priv->element,
                                                         "friendlyName");
 }
 
@@ -497,9 +528,13 @@ gupnp_device_info_get_friendly_name (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_manufacturer (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_glib (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_glib (priv->element,
                                                         "manufacturer");
 }
 
@@ -514,11 +549,15 @@ gupnp_device_info_get_manufacturer (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_manufacturer_url (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_url (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_url (priv->element,
                                                        "manufacturerURL",
-                                                       info->priv->url_base);
+                                                       priv->url_base);
 }
 
 /**
@@ -532,9 +571,13 @@ gupnp_device_info_get_manufacturer_url (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_model_description (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_glib (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_glib (priv->element,
                                                         "modelDescription");
 }
 
@@ -549,9 +592,13 @@ gupnp_device_info_get_model_description (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_model_name (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_glib (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_glib (priv->element,
                                                         "modelName");
 }
 
@@ -566,9 +613,13 @@ gupnp_device_info_get_model_name (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_model_number (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_glib (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_glib (priv->element,
                                                         "modelNumber");
 }
 
@@ -583,11 +634,15 @@ gupnp_device_info_get_model_number (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_model_url (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_url (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_url (priv->element,
                                                        "modelURL",
-                                                       info->priv->url_base);
+                                                       priv->url_base);
 }
 
 /**
@@ -601,9 +656,13 @@ gupnp_device_info_get_model_url (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_serial_number (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_glib (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_glib (priv->element,
                                                         "serialNumber");
 }
 
@@ -618,9 +677,13 @@ gupnp_device_info_get_serial_number (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_upc (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_glib (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_glib (priv->element,
                                                         "UPC");
 }
 
@@ -636,11 +699,15 @@ gupnp_device_info_get_upc (GUPnPDeviceInfo *info)
 char *
 gupnp_device_info_get_presentation_url (GUPnPDeviceInfo *info)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_url (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_url (priv->element,
                                                        "presentationURL",
-                                                       info->priv->url_base);
+                                                       priv->url_base);
 }
 
 typedef struct {
@@ -732,13 +799,16 @@ gupnp_device_info_get_icon_url (GUPnPDeviceInfo *info,
         xmlNode *element;
         Icon *icon, *closest;
         char *ret;
+        GUPnPDeviceInfoPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
+        priv = gupnp_device_info_get_instance_private (info);
+
         /* List available icons */
         icons = NULL;
 
-        element = xml_util_get_element (info->priv->element,
+        element = xml_util_get_element (priv->element,
                                         "iconList",
                                         NULL);
         if (!element)
@@ -863,7 +933,7 @@ gupnp_device_info_get_icon_url (GUPnPDeviceInfo *info,
                 if (icon->url) {
                         SoupURI *uri;
 
-                        uri = soup_uri_new_with_base (info->priv->url_base,
+                        uri = soup_uri_new_with_base (priv->url_base,
                                                       (const char *) icon->url);
                         ret = soup_uri_to_string (uri, FALSE);
                         soup_uri_free (uri);
@@ -962,10 +1032,13 @@ gupnp_device_info_list_dlna_device_class_identifier (GUPnPDeviceInfo *info)
 {
         xmlNode *element;
         GList *list  = NULL;
+        GUPnPDeviceInfoPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        element = info->priv->element;
+        priv = gupnp_device_info_get_instance_private (info);
+
+        element = priv->element;
 
         for (element = element->children; element; element = element->next) {
                 /* No early exit since the node explicitly may appear multiple
@@ -1005,10 +1078,13 @@ GList *
 gupnp_device_info_list_dlna_capabilities (GUPnPDeviceInfo *info)
 {
         xmlChar *caps;
+        GUPnPDeviceInfoPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
-        caps = xml_util_get_child_element_content (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        caps = xml_util_get_child_element_content (priv->element,
                                                    "X_DLNACAP");
 
         if (caps) {
@@ -1061,10 +1137,14 @@ char *
 gupnp_device_info_get_description_value (GUPnPDeviceInfo *info,
                                          const char      *element)
 {
+        GUPnPDeviceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
         g_return_val_if_fail (element != NULL, NULL);
 
-        return xml_util_get_child_element_content_glib (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_glib (priv->element,
                                                         element);
 }
 
@@ -1090,6 +1170,7 @@ gupnp_device_info_list_devices (GUPnPDeviceInfo *info)
         GUPnPDeviceInfoClass *class;
         GList *devices;
         xmlNode *element;
+        GUPnPDeviceInfoPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
@@ -1099,7 +1180,9 @@ gupnp_device_info_list_devices (GUPnPDeviceInfo *info)
 
         devices = NULL;
 
-        element = xml_util_get_element (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        element = xml_util_get_element (priv->element,
                                         "deviceList",
                                         NULL);
         if (!element)
@@ -1132,12 +1215,15 @@ gupnp_device_info_list_device_types (GUPnPDeviceInfo *info)
 {
         GList *device_types;
         xmlNode *element;
+        GUPnPDeviceInfoPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
         device_types = NULL;
 
-        element = xml_util_get_element (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        element = xml_util_get_element (priv->element,
                                         "deviceList",
                                         NULL);
         if (!element)
@@ -1181,6 +1267,7 @@ gupnp_device_info_get_device (GUPnPDeviceInfo *info,
         GUPnPDeviceInfoClass *class;
         GUPnPDeviceInfo *device;
         xmlNode *element;
+        GUPnPDeviceInfoPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
         g_return_val_if_fail (type != NULL, NULL);
@@ -1190,8 +1277,9 @@ gupnp_device_info_get_device (GUPnPDeviceInfo *info,
         g_return_val_if_fail (class->get_device, NULL);
 
         device = NULL;
+        priv = gupnp_device_info_get_instance_private (info);
 
-        element = xml_util_get_element (info->priv->element,
+        element = xml_util_get_element (priv->element,
                                         "deviceList",
                                         NULL);
         if (!element)
@@ -1245,6 +1333,7 @@ gupnp_device_info_list_services (GUPnPDeviceInfo *info)
         GUPnPDeviceInfoClass *class;
         GList *services;
         xmlNode *element;
+        GUPnPDeviceInfoPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
@@ -1254,7 +1343,9 @@ gupnp_device_info_list_services (GUPnPDeviceInfo *info)
 
         services = NULL;
 
-        element = xml_util_get_element (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        element = xml_util_get_element (priv->element,
                                         "serviceList",
                                         NULL);
         if (!element)
@@ -1287,12 +1378,15 @@ gupnp_device_info_list_service_types (GUPnPDeviceInfo *info)
 {
         GList *service_types;
         xmlNode *element;
+        GUPnPDeviceInfoPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
 
         service_types = NULL;
 
-        element = xml_util_get_element (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        element = xml_util_get_element (priv->element,
                                         "serviceList",
                                         NULL);
         if (!element)
@@ -1336,6 +1430,7 @@ gupnp_device_info_get_service (GUPnPDeviceInfo *info,
         GUPnPDeviceInfoClass *class;
         GUPnPServiceInfo *service;
         xmlNode *element;
+        GUPnPDeviceInfoPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL);
         g_return_val_if_fail (type != NULL, NULL);
@@ -1346,7 +1441,9 @@ gupnp_device_info_get_service (GUPnPDeviceInfo *info,
 
         service = NULL;
 
-        element = xml_util_get_element (info->priv->element,
+        priv = gupnp_device_info_get_instance_private (info);
+
+        element = xml_util_get_element (priv->element,
                                         "serviceList",
                                         NULL);
         if (!element)
@@ -1384,5 +1481,9 @@ gupnp_device_info_get_service (GUPnPDeviceInfo *info,
 GUPnPXMLDoc *
 _gupnp_device_info_get_document (GUPnPDeviceInfo *info)
 {
-        return info->priv->doc;
+        GUPnPDeviceInfoPrivate *priv;
+
+        priv = gupnp_device_info_get_instance_private (info);
+
+        return priv->doc;
 }
diff --git a/libgupnp/gupnp-device-info.h b/libgupnp/gupnp-device-info.h
index ad99ff0..7a12354 100644
--- a/libgupnp/gupnp-device-info.h
+++ b/libgupnp/gupnp-device-info.h
@@ -32,45 +32,14 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_device_info_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_DEVICE_INFO \
                 (gupnp_device_info_get_type ())
-#define GUPNP_DEVICE_INFO(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_DEVICE_INFO, \
-                 GUPnPDeviceInfo))
-#define GUPNP_DEVICE_INFO_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_DEVICE_INFO, \
-                 GUPnPDeviceInfoClass))
-#define GUPNP_IS_DEVICE_INFO(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_DEVICE_INFO))
-#define GUPNP_IS_DEVICE_INFO_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_DEVICE_INFO))
-#define GUPNP_DEVICE_INFO_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_DEVICE_INFO, \
-                 GUPnPDeviceInfoClass))
-
-typedef struct _GUPnPDeviceInfoPrivate GUPnPDeviceInfoPrivate;
-typedef struct _GUPnPDeviceInfo GUPnPDeviceInfo;
-typedef struct _GUPnPDeviceInfoClass GUPnPDeviceInfoClass;
-
-/**
- * GUPnPDeviceInfo:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPDeviceInfo {
-        GObject parent;
 
-        GUPnPDeviceInfoPrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPDeviceInfo,
+                          gupnp_device_info,
+                          GUPNP,
+                          DEVICE_INFO,
+                          GObject)
 
 struct _GUPnPDeviceInfoClass {
         GObjectClass parent_class;
diff --git a/libgupnp/gupnp-device-proxy.c b/libgupnp/gupnp-device-proxy.c
index 14885c9..e67e8e8 100644
--- a/libgupnp/gupnp-device-proxy.c
+++ b/libgupnp/gupnp-device-proxy.c
@@ -38,6 +38,7 @@ G_DEFINE_TYPE (GUPnPDeviceProxy,
                gupnp_device_proxy,
                GUPNP_TYPE_DEVICE_INFO);
 
+
 static GUPnPDeviceInfo *
 gupnp_device_proxy_get_device (GUPnPDeviceInfo *info,
                                xmlNode         *element)
diff --git a/libgupnp/gupnp-device-proxy.h b/libgupnp/gupnp-device-proxy.h
index cada41e..9defa3e 100644
--- a/libgupnp/gupnp-device-proxy.h
+++ b/libgupnp/gupnp-device-proxy.h
@@ -26,45 +26,14 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_device_proxy_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_DEVICE_PROXY \
                 (gupnp_device_proxy_get_type ())
-#define GUPNP_DEVICE_PROXY(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_DEVICE_PROXY, \
-                 GUPnPDeviceProxy))
-#define GUPNP_DEVICE_PROXY_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_DEVICE_PROXY, \
-                 GUPnPDeviceProxyClass))
-#define GUPNP_IS_DEVICE_PROXY(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_DEVICE_PROXY))
-#define GUPNP_IS_DEVICE_PROXY_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_DEVICE_PROXY))
-#define GUPNP_DEVICE_PROXY_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_DEVICE_PROXY, \
-                 GUPnPDeviceProxyClass))
-
-typedef struct _GUPnPDeviceProxyPrivate GUPnPDeviceProxyPrivate;
-typedef struct _GUPnPDeviceProxy GUPnPDeviceProxy;
-typedef struct _GUPnPDeviceProxyClass GUPnPDeviceProxyClass;
-
-/**
- * GUPnPDeviceProxy:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPDeviceProxy {
-        GUPnPDeviceInfo parent;
 
-        GUPnPDeviceProxyPrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPDeviceProxy,
+                          gupnp_device_proxy,
+                          GUPNP,
+                          DEVICE_PROXY,
+                          GUPnPDeviceInfo)
 
 struct _GUPnPDeviceProxyClass {
         GUPnPDeviceInfoClass parent_class;
diff --git a/libgupnp/gupnp-device.c b/libgupnp/gupnp-device.c
index 2497029..d7a619a 100644
--- a/libgupnp/gupnp-device.c
+++ b/libgupnp/gupnp-device.c
@@ -36,13 +36,15 @@
 #include "gupnp-resource-factory-private.h"
 #include "xml-util.h"
 
-G_DEFINE_TYPE (GUPnPDevice,
-               gupnp_device,
-               GUPNP_TYPE_DEVICE_INFO);
-
 struct _GUPnPDevicePrivate {
         GUPnPRootDevice *root_device;
 };
+typedef struct _GUPnPDevicePrivate GUPnPDevicePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPDevice,
+                            gupnp_device,
+                            GUPNP_TYPE_DEVICE_INFO);
+
 
 enum {
         PROP_0,
@@ -54,6 +56,7 @@ gupnp_device_get_device (GUPnPDeviceInfo *info,
                          xmlNode         *element)
 {
         GUPnPDevice          *device;
+        GUPnPDevicePrivate   *priv;
         GUPnPResourceFactory *factory;
         GUPnPContext         *context;
         GUPnPDevice          *root_device;
@@ -61,9 +64,10 @@ gupnp_device_get_device (GUPnPDeviceInfo *info,
         const SoupURI        *url_base;
 
         device = GUPNP_DEVICE (info);
+        priv = gupnp_device_get_instance_private (device);
 
         root_device = GUPNP_IS_ROOT_DEVICE (device) ? device :
-                      GUPNP_DEVICE (device->priv->root_device);
+                      GUPNP_DEVICE (priv->root_device);
         if (root_device == NULL) {
                 g_warning ("Root device not found.");
 
@@ -91,6 +95,7 @@ gupnp_device_get_service (GUPnPDeviceInfo *info,
                           xmlNode         *element)
 {
         GUPnPDevice          *device;
+        GUPnPDevicePrivate   *priv;
         GUPnPService         *service;
         GUPnPResourceFactory *factory;
         GUPnPContext         *context;
@@ -99,9 +104,10 @@ gupnp_device_get_service (GUPnPDeviceInfo *info,
         const SoupURI        *url_base;
 
         device = GUPNP_DEVICE (info);
+        priv = gupnp_device_get_instance_private (device);
 
         root_device = GUPNP_IS_ROOT_DEVICE (device) ? device :
-                      GUPNP_DEVICE (device->priv->root_device);
+                      GUPNP_DEVICE (priv->root_device);
         if (root_device == NULL) {
                 g_warning ("Root device not found.");
 
@@ -132,19 +138,21 @@ gupnp_device_set_property (GObject      *object,
                            GParamSpec   *pspec)
 {
         GUPnPDevice *device;
+        GUPnPDevicePrivate   *priv;
 
         device = GUPNP_DEVICE (object);
+        priv = gupnp_device_get_instance_private (device);
 
         switch (property_id) {
         case PROP_ROOT_DEVICE:
-                device->priv->root_device = g_value_get_object (value);
+                priv->root_device = g_value_get_object (value);
 
                 /* This can be NULL in which case *this* is the root device */
-                if (device->priv->root_device) {
-                        GUPnPRootDevice **dev = &(device->priv->root_device);
+                if (priv->root_device) {
+                        GUPnPRootDevice **dev = &(priv->root_device);
 
                         g_object_add_weak_pointer
-                                (G_OBJECT (device->priv->root_device),
+                                (G_OBJECT (priv->root_device),
                                  (gpointer *) dev);
                 }
 
@@ -162,12 +170,14 @@ gupnp_device_get_property (GObject    *object,
                            GParamSpec *pspec)
 {
         GUPnPDevice *device;
+        GUPnPDevicePrivate   *priv;
 
         device = GUPNP_DEVICE (object);
+        priv = gupnp_device_get_instance_private (device);
 
         switch (property_id) {
         case PROP_ROOT_DEVICE:
-                g_value_set_object (value, device->priv->root_device);
+                g_value_set_object (value, priv->root_device);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -180,17 +190,19 @@ gupnp_device_dispose (GObject *object)
 {
         GUPnPDevice *device;
         GObjectClass *object_class;
+        GUPnPDevicePrivate   *priv;
 
         device = GUPNP_DEVICE (object);
+        priv = gupnp_device_get_instance_private (device);
 
-        if (device->priv->root_device) {
-                GUPnPRootDevice **dev = &(device->priv->root_device);
+        if (priv->root_device) {
+                GUPnPRootDevice **dev = &(priv->root_device);
 
                 g_object_remove_weak_pointer
-                        (G_OBJECT (device->priv->root_device),
+                        (G_OBJECT (priv->root_device),
                          (gpointer *) dev);
 
-                device->priv->root_device = NULL;
+                priv->root_device = NULL;
         }
 
         /* Call super */
@@ -201,9 +213,6 @@ gupnp_device_dispose (GObject *object)
 static void
 gupnp_device_init (GUPnPDevice *device)
 {
-        device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device,
-                                                    GUPNP_TYPE_DEVICE,
-                                                    GUPnPDevicePrivate);
 }
 
 static void
@@ -223,8 +232,6 @@ gupnp_device_class_init (GUPnPDeviceClass *klass)
         info_class->get_device  = gupnp_device_get_device;
         info_class->get_service = gupnp_device_get_service;
 
-        g_type_class_add_private (klass, sizeof (GUPnPDevicePrivate));
-
         /**
          * GUPnPDevice:root-device:
          *
diff --git a/libgupnp/gupnp-device.h b/libgupnp/gupnp-device.h
index 5900cfb..c0432bb 100644
--- a/libgupnp/gupnp-device.h
+++ b/libgupnp/gupnp-device.h
@@ -26,45 +26,13 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_device_get_type (void) G_GNUC_CONST;
+#define GUPNP_TYPE_DEVICE (gupnp_device_get_type ())
 
-#define GUPNP_TYPE_DEVICE \
-                (gupnp_device_get_type ())
-#define GUPNP_DEVICE(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_DEVICE, \
-                 GUPnPDevice))
-#define GUPNP_DEVICE_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_DEVICE, \
-                 GUPnPDeviceClass))
-#define GUPNP_IS_DEVICE(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_DEVICE))
-#define GUPNP_IS_DEVICE_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_DEVICE))
-#define GUPNP_DEVICE_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_DEVICE, \
-                 GUPnPDeviceClass))
-
-typedef struct _GUPnPDevicePrivate GUPnPDevicePrivate;
-typedef struct _GUPnPDevice GUPnPDevice;
-typedef struct _GUPnPDeviceClass GUPnPDeviceClass;
-
-/**
- * GUPnPDevice:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPDevice {
-        GUPnPDeviceInfo parent;
-
-        GUPnPDevicePrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPDevice,
+                          gupnp_device,
+                          GUPNP,
+                          DEVICE,
+                          GUPnPDeviceInfo)
 
 struct _GUPnPDeviceClass {
         GUPnPDeviceInfoClass parent_class;
diff --git a/libgupnp/gupnp-linux-context-manager.c b/libgupnp/gupnp-linux-context-manager.c
index 90fb56d..3e516cb 100644
--- a/libgupnp/gupnp-linux-context-manager.c
+++ b/libgupnp/gupnp-linux-context-manager.c
@@ -60,10 +60,6 @@
 #include "gupnp-linux-context-manager.h"
 #include "gupnp-context.h"
 
-G_DEFINE_TYPE (GUPnPLinuxContextManager,
-               gupnp_linux_context_manager,
-               GUPNP_TYPE_CONTEXT_MANAGER);
-
 struct _GUPnPLinuxContextManagerPrivate {
         /* Socket used for IOCTL calls */
         int fd;
@@ -86,6 +82,16 @@ struct _GUPnPLinuxContextManagerPrivate {
 
         gboolean dump_netlink_packets;
 };
+typedef struct _GUPnPLinuxContextManagerPrivate GUPnPLinuxContextManagerPrivate;
+
+
+struct _GUPnPLinuxContextManager {
+        GUPnPContextManager parent;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPLinuxContextManager,
+                            gupnp_linux_context_manager,
+                            GUPNP_TYPE_CONTEXT_MANAGER);
 
 typedef enum {
         /* Interface is up */
@@ -220,6 +226,16 @@ network_device_new (GUPnPLinuxContextManager *manager,
         return device;
 }
 
+static int
+get_ioctl_fd (GUPnPLinuxContextManager *self)
+{
+    GUPnPLinuxContextManagerPrivate *priv;
+
+    priv = gupnp_linux_context_manager_get_instance_private (self);
+
+    return priv->fd;
+}
+
 /* Try to update the ESSID of a network interface. */
 static void
 network_device_update_essid (NetworkInterface *device)
@@ -236,7 +252,7 @@ network_device_update_essid (NetworkInterface *device)
         strncpy (iwr.ifr_name, device->name, IFNAMSIZ - 1);
         iwr.u.essid.pointer = (caddr_t) essid;
         iwr.u.essid.length = IW_ESSID_MAX_SIZE;
-        ret = ioctl (device->manager->priv->fd, SIOCGIWESSID, &iwr);
+        ret = ioctl (get_ioctl_fd (device->manager), SIOCGIWESSID, &iwr);
 
         if ((ret == 0 && essid[0] != '\0') &&
             (!device->essid || strcmp (device->essid, essid)))
@@ -487,8 +503,10 @@ create_context (GUPnPLinuxContextManager *self,
                 struct ifaddrmsg         *ifa)
 {
         NetworkInterface *device;
+        GUPnPLinuxContextManagerPrivate *priv;
 
-        device = g_hash_table_lookup (self->priv->interfaces,
+        priv = gupnp_linux_context_manager_get_instance_private (self);
+        device = g_hash_table_lookup (priv->interfaces,
                                       GINT_TO_POINTER (ifa->ifa_index));
 
         if (!device) {
@@ -517,8 +535,10 @@ remove_context (GUPnPLinuxContextManager *self,
 {
         NetworkInterface *device;
         GUPnPContext *context;
+        GUPnPLinuxContextManagerPrivate *priv;
 
-        device = g_hash_table_lookup (self->priv->interfaces,
+        priv = gupnp_linux_context_manager_get_instance_private (self);
+        device = g_hash_table_lookup (priv->interfaces,
                                       GINT_TO_POINTER (ifa->ifa_index));
 
         if (!device) {
@@ -556,24 +576,27 @@ remove_context (GUPnPLinuxContextManager *self,
 static gboolean
 on_bootstrap (GUPnPLinuxContextManager *self)
 {
-        if (self->priv->nl_seq == 0) {
+        GUPnPLinuxContextManagerPrivate *priv;
+
+        priv = gupnp_linux_context_manager_get_instance_private (self);
+        if (priv->nl_seq == 0) {
                 query_all_network_interfaces (self);
 
                 return TRUE;
-        } else if (self->priv->nl_seq == 1) {
+        } else if (priv->nl_seq == 1) {
                 query_all_addresses (self);
 
                 return TRUE;
         } else {
-                self->priv->netlink_socket_source = g_socket_create_source
-                                                (self->priv->netlink_socket,
+                priv->netlink_socket_source = g_socket_create_source
+                                                (priv->netlink_socket,
                                                  G_IO_IN | G_IO_PRI,
                                                  NULL);
 
-                g_source_attach (self->priv->netlink_socket_source,
+                g_source_attach (priv->netlink_socket_source,
                                  g_main_context_get_thread_default ());
 
-                g_source_set_callback (self->priv->netlink_socket_source,
+                g_source_set_callback (priv->netlink_socket_source,
                                        (GSourceFunc)
                                        on_netlink_message_available,
                                        self,
@@ -598,6 +621,9 @@ send_netlink_request (GUPnPLinuxContextManager *self,
         struct msghdr msg;
         struct iovec io;
         int fd;
+        GUPnPLinuxContextManagerPrivate *priv;
+
+        priv = gupnp_linux_context_manager_get_instance_private (self);
 
         memset (&req, 0, sizeof (req));
         memset (&dest, 0, sizeof (dest));
@@ -605,7 +631,7 @@ send_netlink_request (GUPnPLinuxContextManager *self,
 
         dest.nl_family = AF_NETLINK;
         req.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtgenmsg));
-        req.hdr.nlmsg_seq = self->priv->nl_seq++;
+        req.hdr.nlmsg_seq = priv->nl_seq++;
         req.hdr.nlmsg_type = netlink_message;
         req.hdr.nlmsg_flags = NLM_F_REQUEST | flags;
         req.gen.rtgen_family = AF_INET;
@@ -618,7 +644,7 @@ send_netlink_request (GUPnPLinuxContextManager *self,
         msg.msg_name = &dest;
         msg.msg_namelen = sizeof (dest);
 
-        fd = g_socket_get_fd (self->priv->netlink_socket);
+        fd = g_socket_get_fd (priv->netlink_socket);
         if (sendmsg (fd, (struct msghdr *) &msg, 0) < 0)
                 g_warning ("Could not send netlink message: %s",
                            strerror (errno));
@@ -665,9 +691,12 @@ handle_device_status_change (GUPnPLinuxContextManager *self,
 {
         gpointer key;
         NetworkInterface *device;
+        GUPnPLinuxContextManagerPrivate *priv;
+
+        priv = gupnp_linux_context_manager_get_instance_private (self);
 
         key = GINT_TO_POINTER (ifi->ifi_index);
-        device = g_hash_table_lookup (self->priv->interfaces,
+        device = g_hash_table_lookup (priv->interfaces,
                                       key);
 
         if (device != NULL) {
@@ -686,7 +715,7 @@ handle_device_status_change (GUPnPLinuxContextManager *self,
                 if (ifi->ifi_flags & IFF_UP)
                         device->flags |= NETWORK_INTERFACE_UP;
 
-                g_hash_table_insert (self->priv->interfaces,
+                g_hash_table_insert (priv->interfaces,
                                      key,
                                      device);
         }
@@ -696,7 +725,11 @@ static void
 remove_device (GUPnPLinuxContextManager *self,
                struct ifinfomsg         *ifi)
 {
-        g_hash_table_remove (self->priv->interfaces,
+        GUPnPLinuxContextManagerPrivate *priv;
+
+        priv = gupnp_linux_context_manager_get_instance_private (self);
+
+        g_hash_table_remove (priv->interfaces,
                              GINT_TO_POINTER (ifi->ifi_index));
 }
 
@@ -715,8 +748,11 @@ receive_netlink_message (GUPnPLinuxContextManager *self, GError **error)
         struct nlmsghdr *header = (struct nlmsghdr *) buf;
         struct ifinfomsg *ifi;
         struct ifaddrmsg *ifa;
+        GUPnPLinuxContextManagerPrivate *priv;
+
+        priv = gupnp_linux_context_manager_get_instance_private (self);
 
-        len = g_socket_receive (self->priv->netlink_socket,
+        len = g_socket_receive (priv->netlink_socket,
                                 buf,
                                 sizeof (buf),
                                 NULL,
@@ -730,7 +766,7 @@ receive_netlink_message (GUPnPLinuxContextManager *self, GError **error)
                 return;
         }
 
-        if (self->priv->dump_netlink_packets) {
+        if (priv->dump_netlink_packets) {
                 GString *hexdump = NULL;
 
                 /* We should have at most len / 16 + 1 lines with 74 characters each */
@@ -760,7 +796,7 @@ receive_netlink_message (GUPnPLinuxContextManager *self, GError **error)
                                 g_debug ("Received RTM_NEWADDR");
                                 ifa = NLMSG_DATA (header);
                                 extract_info (header,
-                                              self->priv->dump_netlink_packets,
+                                              priv->dump_netlink_packets,
                                               ifa->ifa_prefixlen,
                                               &address,
                                               &label,
@@ -779,7 +815,7 @@ receive_netlink_message (GUPnPLinuxContextManager *self, GError **error)
                                 g_debug ("Received RTM_DELADDR");
                                 ifa = NLMSG_DATA (header);
                                 extract_info (header,
-                                              self->priv->dump_netlink_packets,
+                                              priv->dump_netlink_packets,
                                               ifa->ifa_prefixlen,
                                               &address,
                                               &label,
@@ -827,10 +863,14 @@ receive_netlink_message (GUPnPLinuxContextManager *self, GError **error)
 static gboolean
 create_ioctl_socket (GUPnPLinuxContextManager *self, GError **error)
 {
-        self->priv->fd = socket (AF_INET, SOCK_DGRAM, 0);
+        GUPnPLinuxContextManagerPrivate *priv;
 
-        if (self->priv->fd < 0) {
-                self->priv->fd = 0;
+        priv = gupnp_linux_context_manager_get_instance_private (self);
+
+        priv->fd = socket (AF_INET, SOCK_DGRAM, 0);
+
+        if (priv->fd < 0) {
+                priv->fd = 0;
 
                 g_set_error_literal (error,
                                      G_IO_ERROR,
@@ -851,6 +891,9 @@ create_netlink_socket (GUPnPLinuxContextManager *self, GError **error)
         int fd, status;
         GSocket *sock;
         GError *inner_error;
+        GUPnPLinuxContextManagerPrivate *priv;
+
+        priv = gupnp_linux_context_manager_get_instance_private (self);
 
         inner_error = NULL;
 
@@ -892,7 +935,7 @@ create_netlink_socket (GUPnPLinuxContextManager *self, GError **error)
 
         g_socket_set_blocking (sock, FALSE);
 
-        self->priv->netlink_socket = sock;
+        priv->netlink_socket = sock;
 
         return TRUE;
 }
@@ -919,14 +962,13 @@ gupnp_linux_context_manager_is_available (void)
 static void
 gupnp_linux_context_manager_init (GUPnPLinuxContextManager *self)
 {
-        self->priv =
-                G_TYPE_INSTANCE_GET_PRIVATE (self,
-                                             GUPNP_TYPE_LINUX_CONTEXT_MANAGER,
-                                             GUPnPLinuxContextManagerPrivate);
+        GUPnPLinuxContextManagerPrivate *priv;
 
-        self->priv->nl_seq = 0;
+        priv = gupnp_linux_context_manager_get_instance_private (self);
 
-        self->priv->interfaces =
+        priv->nl_seq = 0;
+
+        priv->interfaces =
                 g_hash_table_new_full (g_direct_hash,
                                        g_direct_equal,
                                        NULL,
@@ -941,11 +983,13 @@ gupnp_linux_context_manager_constructed (GObject *object)
         GUPnPLinuxContextManager *self;
         GError *error = NULL;
         const char *env_var = NULL;
+        GUPnPLinuxContextManagerPrivate *priv;
 
         self = GUPNP_LINUX_CONTEXT_MANAGER (object);
+        priv = gupnp_linux_context_manager_get_instance_private (self);
 
         env_var = g_getenv ("GUPNP_DEBUG_NETLINK");
-        self->priv->dump_netlink_packets = (env_var != NULL) &&
+        priv->dump_netlink_packets = (env_var != NULL) &&
                 strstr (env_var, "1") != NULL;
 
         if (!create_ioctl_socket (self, &error))
@@ -954,17 +998,17 @@ gupnp_linux_context_manager_constructed (GObject *object)
         if (!create_netlink_socket (self, &error))
                 goto cleanup;
 
-        self->priv->bootstrap_source = g_idle_source_new ();
-        g_source_attach (self->priv->bootstrap_source,
+        priv->bootstrap_source = g_idle_source_new ();
+        g_source_attach (priv->bootstrap_source,
                          g_main_context_get_thread_default ());
-        g_source_set_callback (self->priv->bootstrap_source,
+        g_source_set_callback (priv->bootstrap_source,
                                (GSourceFunc) on_bootstrap,
                                self,
                                NULL);
 cleanup:
         if (error) {
-                if (self->priv->fd > 0)
-                        close (self->priv->fd);
+                if (priv->fd > 0)
+                        close (priv->fd);
 
                 g_warning ("Failed to setup Linux context manager: %s",
                            error->message);
@@ -983,34 +1027,36 @@ gupnp_linux_context_manager_dispose (GObject *object)
 {
         GUPnPLinuxContextManager *self;
         GObjectClass *parent_class;
+        GUPnPLinuxContextManagerPrivate *priv;
 
         self = GUPNP_LINUX_CONTEXT_MANAGER (object);
+        priv = gupnp_linux_context_manager_get_instance_private (self);
 
-        if (self->priv->bootstrap_source != NULL) {
-                g_source_destroy (self->priv->bootstrap_source);
-                g_source_unref (self->priv->bootstrap_source);
-                self->priv->bootstrap_source = NULL;
+        if (priv->bootstrap_source != NULL) {
+                g_source_destroy (priv->bootstrap_source);
+                g_source_unref (priv->bootstrap_source);
+                priv->bootstrap_source = NULL;
         }
 
-        if (self->priv->netlink_socket_source != NULL) {
-               g_source_destroy (self->priv->netlink_socket_source);
-               g_source_unref (self->priv->netlink_socket_source);
-               self->priv->netlink_socket_source = NULL;
+        if (priv->netlink_socket_source != NULL) {
+               g_source_destroy (priv->netlink_socket_source);
+               g_source_unref (priv->netlink_socket_source);
+               priv->netlink_socket_source = NULL;
         }
 
-        if (self->priv->netlink_socket != NULL) {
-                g_object_unref (self->priv->netlink_socket);
-                self->priv->netlink_socket = NULL;
+        if (priv->netlink_socket != NULL) {
+                g_object_unref (priv->netlink_socket);
+                priv->netlink_socket = NULL;
         }
 
-        if (self->priv->fd != 0) {
-                close (self->priv->fd);
-                self->priv->fd = 0;
+        if (priv->fd != 0) {
+                close (priv->fd);
+                priv->fd = 0;
         }
 
-        if (self->priv->interfaces) {
-                g_hash_table_destroy (self->priv->interfaces);
-                self->priv->interfaces = NULL;
+        if (priv->interfaces) {
+                g_hash_table_destroy (priv->interfaces);
+                priv->interfaces = NULL;
         }
 
         /* Chain-up */
@@ -1027,7 +1073,4 @@ gupnp_linux_context_manager_class_init (GUPnPLinuxContextManagerClass *klass)
 
         object_class->constructed = gupnp_linux_context_manager_constructed;
         object_class->dispose     = gupnp_linux_context_manager_dispose;
-
-        g_type_class_add_private (klass,
-                                  sizeof (GUPnPLinuxContextManagerPrivate));
 }
diff --git a/libgupnp/gupnp-linux-context-manager.h b/libgupnp/gupnp-linux-context-manager.h
index fb8ada8..2764d4a 100644
--- a/libgupnp/gupnp-linux-context-manager.h
+++ b/libgupnp/gupnp-linux-context-manager.h
@@ -29,47 +29,14 @@
 
 G_BEGIN_DECLS
 
-G_GNUC_INTERNAL GType
-gupnp_linux_context_manager_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_LINUX_CONTEXT_MANAGER \
                 (gupnp_linux_context_manager_get_type ())
-#define GUPNP_LINUX_CONTEXT_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER, \
-                 GUPnPLinuxContextManager))
-#define GUPNP_LINUX_CONTEXT_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER, \
-                 GUPnPLinuxContextManagerClass))
-#define GUPNP_IS_LINUX_CONTEXT_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER))
-#define GUPNP_IS_LINUX_CONTEXT_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER))
-#define GUPNP_LINUX_CONTEXT_MANAGER_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_LINUX_CONTEXT_MANAGER, \
-                 GUPnPLinuxContextManagerClass))
-
-typedef struct _GUPnPLinuxContextManagerPrivate GUPnPLinuxContextManagerPrivate;
-
-typedef struct {
-        GUPnPContextManager parent;
-
-        GUPnPLinuxContextManagerPrivate *priv;
-} GUPnPLinuxContextManager;
-
-typedef struct {
-        GUPnPContextManagerClass parent_class;
 
-        /* future padding */
-        void (* _gupnp_reserved1) (void);
-        void (* _gupnp_reserved2) (void);
-        void (* _gupnp_reserved3) (void);
-        void (* _gupnp_reserved4) (void);
-} GUPnPLinuxContextManagerClass;
+G_DECLARE_FINAL_TYPE (GUPnPLinuxContextManager,
+                      gupnp_linux_context_manager,
+                      GUPNP,
+                      LINUX_CONTEXT_MANAGER,
+                      GUPnPContextManager)
 
 G_GNUC_INTERNAL gboolean gupnp_linux_context_manager_is_available (void);
 
diff --git a/libgupnp/gupnp-network-manager.c b/libgupnp/gupnp-network-manager.c
index b63d030..4ed976f 100644
--- a/libgupnp/gupnp-network-manager.c
+++ b/libgupnp/gupnp-network-manager.c
@@ -51,9 +51,26 @@
 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
 
-G_DEFINE_TYPE (GUPnPNetworkManager,
-               gupnp_network_manager,
-               GUPNP_TYPE_CONTEXT_MANAGER);
+struct _GUPnPNetworkManager {
+        GUPnPContextManager parent;
+};
+
+struct _GUPnPNetworkManagerPrivate {
+        GDBusProxy *manager_proxy;
+
+        GSource *idle_context_creation_src;
+
+        GList *nm_devices;
+
+        GCancellable *cancellable;
+
+        GDBusConnection *system_bus;
+};
+typedef struct _GUPnPNetworkManagerPrivate GUPnPNetworkManagerPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPNetworkManager,
+                            gupnp_network_manager,
+                            GUPNP_TYPE_CONTEXT_MANAGER);
 
 typedef enum
 {
@@ -107,18 +124,6 @@ typedef struct
         GDBusProxy *ap_proxy;
 } NMDevice;
 
-struct _GUPnPNetworkManagerPrivate {
-        GDBusProxy *manager_proxy;
-
-        GSource *idle_context_creation_src;
-
-        GList *nm_devices;
-
-        GCancellable *cancellable;
-
-        GDBusConnection *system_bus;
-};
-
 static NMDevice *
 nm_device_new (GUPnPNetworkManager *manager,
                GDBusProxy          *device_proxy)
@@ -174,8 +179,11 @@ create_loopback_context (gpointer data)
         GUPnPContext *context;
         guint port;
         GError *error = NULL;
+        GUPnPNetworkManagerPrivate *priv;
+
+        priv = gupnp_network_manager_get_instance_private (manager);
 
-        manager->priv->idle_context_creation_src = NULL;
+        priv->idle_context_creation_src = NULL;
 
         g_object_get (manager,
                       "port", &port,
@@ -295,6 +303,7 @@ on_wifi_device_activated (NMDevice *nm_device)
 {
         GVariant *value;
         const char *ap_path;
+        GUPnPNetworkManagerPrivate *priv;
 
         value = g_dbus_proxy_get_cached_property (nm_device->wifi_proxy,
                                                   "ActiveAccessPoint");
@@ -308,6 +317,7 @@ on_wifi_device_activated (NMDevice *nm_device)
                 return;
         }
 
+        priv = gupnp_network_manager_get_instance_private (nm_device->manager);
         ap_path = g_variant_get_string (value, NULL);
         if (G_UNLIKELY (ap_path == NULL))
                 create_context_for_device (nm_device);
@@ -318,7 +328,7 @@ on_wifi_device_activated (NMDevice *nm_device)
                                           DBUS_SERVICE_NM,
                                           ap_path,
                                           AP_INTERFACE,
-                                          nm_device->manager->priv->cancellable,
+                                          priv->cancellable,
                                           ap_proxy_new_cb,
                                           nm_device_ref (nm_device));
        }
@@ -376,9 +386,12 @@ use_new_device (GUPnPNetworkManager *manager,
 {
         NMDeviceState state;
         GVariant *value;
+        GUPnPNetworkManagerPrivate *priv;
 
-        manager->priv->nm_devices = g_list_append (manager->priv->nm_devices,
-                                                   nm_device_ref (nm_device));
+        priv = gupnp_network_manager_get_instance_private (manager);
+
+        priv->nm_devices = g_list_append (priv->nm_devices,
+                                          nm_device_ref (nm_device));
 
         g_signal_connect (nm_device->proxy,
                           "g-signal",
@@ -439,6 +452,7 @@ device_proxy_new_cb (GObject      *source_object,
         NMDeviceType type;
         GVariant *value;
         GError *error;
+        GUPnPNetworkManagerPrivate *priv;
 
         error = NULL;
 
@@ -467,6 +481,7 @@ device_proxy_new_cb (GObject      *source_object,
         type = g_variant_get_uint32 (value);
         g_variant_unref (value);
 
+        priv = gupnp_network_manager_get_instance_private (manager);
         nm_device = nm_device_new (manager, device_proxy);
 
         if (type == NM_DEVICE_TYPE_WIFI) {
@@ -479,7 +494,7 @@ device_proxy_new_cb (GObject      *source_object,
                                           DBUS_SERVICE_NM,
                                           path,
                                           WIFI_INTERFACE,
-                                          manager->priv->cancellable,
+                                          priv->cancellable,
                                           wifi_proxy_new_cb,
                                           nm_device_ref (nm_device));
         } else
@@ -510,8 +525,10 @@ on_manager_signal (GDBusProxy *proxy,
                    gpointer    user_data)
 {
         GUPnPNetworkManager *manager;
+        GUPnPNetworkManagerPrivate *priv;
 
         manager = GUPNP_NETWORK_MANAGER (user_data);
+        priv = gupnp_network_manager_get_instance_private (manager);
 
         if (g_strcmp0 (signal_name, "DeviceAdded") == 0) {
                 char *device_path = NULL;
@@ -527,7 +544,7 @@ on_manager_signal (GDBusProxy *proxy,
                                           DBUS_SERVICE_NM,
                                           device_path,
                                           DEVICE_INTERFACE,
-                                          manager->priv->cancellable,
+                                          priv->cancellable,
                                           device_proxy_new_cb,
                                           manager);
                 g_free (device_path);
@@ -541,12 +558,12 @@ on_manager_signal (GDBusProxy *proxy,
                 if (G_UNLIKELY (device_path == NULL))
                         return;
 
-                priv = manager->priv;
+                priv = gupnp_network_manager_get_instance_private (manager);
 
                 device_node = g_list_find_custom (
-                                priv->nm_devices,
-                                device_path,
-                                (GCompareFunc) compare_device_path);
+                                            priv->nm_devices,
+                                            device_path,
+                                            (GCompareFunc) compare_device_path);
                 if (G_UNLIKELY (device_node == NULL)) {
                         g_free (device_path);
 
@@ -571,6 +588,7 @@ get_devices_cb (GObject      *source_object,
         GVariantIter *device_iter;
         char* device_path;
         GError *error = NULL;
+        GUPnPNetworkManagerPrivate *priv;
 
         ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
                                         res,
@@ -585,6 +603,7 @@ get_devices_cb (GObject      *source_object,
         }
 
         manager = GUPNP_NETWORK_MANAGER (user_data);
+        priv = gupnp_network_manager_get_instance_private (manager);
 
         g_variant_get_child (ret, 0, "ao", &device_iter);
         while (g_variant_iter_loop (device_iter, "o", &device_path))
@@ -594,7 +613,7 @@ get_devices_cb (GObject      *source_object,
                                           DBUS_SERVICE_NM,
                                           device_path,
                                           DEVICE_INTERFACE,
-                                          manager->priv->cancellable,
+                                          priv->cancellable,
                                           device_proxy_new_cb,
                                           user_data);
         g_variant_iter_free (device_iter);
@@ -605,17 +624,21 @@ get_devices_cb (GObject      *source_object,
 static void
 schedule_loopback_context_creation (GUPnPNetworkManager *manager)
 {
+        GUPnPNetworkManagerPrivate *priv;
+
         /* Create contexts in mainloop so that is happens after user has hooked
          * to the "context-available" signal.
          */
-        manager->priv->idle_context_creation_src = g_idle_source_new ();
-        g_source_attach (manager->priv->idle_context_creation_src,
+        priv = gupnp_network_manager_get_instance_private (manager);
+
+        priv->idle_context_creation_src = g_idle_source_new ();
+        g_source_attach (priv->idle_context_creation_src,
                          g_main_context_get_thread_default ());
-        g_source_set_callback (manager->priv->idle_context_creation_src,
+        g_source_set_callback (priv->idle_context_creation_src,
                                create_loopback_context,
                                manager,
                                NULL);
-        g_source_unref (manager->priv->idle_context_creation_src);
+        g_source_unref (priv->idle_context_creation_src);
 }
 
 static void
@@ -624,7 +647,7 @@ init_network_manager (GUPnPNetworkManager *manager)
         GUPnPNetworkManagerPrivate *priv;
         GError *error;
 
-        priv = manager->priv;
+        priv = gupnp_network_manager_get_instance_private (manager);
 
         error = NULL;
         priv->manager_proxy = g_dbus_proxy_new_for_bus_sync (
@@ -663,10 +686,6 @@ init_network_manager (GUPnPNetworkManager *manager)
 static void
 gupnp_network_manager_init (GUPnPNetworkManager *manager)
 {
-        manager->priv =
-                G_TYPE_INSTANCE_GET_PRIVATE (manager,
-                                             GUPNP_TYPE_NETWORK_MANAGER,
-                                             GUPnPNetworkManagerPrivate);
 }
 
 static void
@@ -677,7 +696,7 @@ gupnp_network_manager_constructed (GObject *object)
         GObjectClass *object_class;
 
         manager = GUPNP_NETWORK_MANAGER (object);
-        priv = manager->priv;
+        priv = gupnp_network_manager_get_instance_private (manager);
 
         priv->cancellable = g_cancellable_new ();
         priv->nm_devices = NULL;
@@ -702,11 +721,11 @@ gupnp_network_manager_dispose (GObject *object)
         GObjectClass *object_class;
 
         manager = GUPNP_NETWORK_MANAGER (object);
-        priv = manager->priv;
+        priv = gupnp_network_manager_get_instance_private (manager);
 
-        if (manager->priv->idle_context_creation_src) {
-                g_source_destroy (manager->priv->idle_context_creation_src);
-                manager->priv->idle_context_creation_src = NULL;
+        if (priv->idle_context_creation_src) {
+                g_source_destroy (priv->idle_context_creation_src);
+                priv->idle_context_creation_src = NULL;
         }
 
         if (priv->manager_proxy != NULL) {
@@ -738,8 +757,6 @@ gupnp_network_manager_class_init (GUPnPNetworkManagerClass *klass)
 
         object_class->constructed  = gupnp_network_manager_constructed;
         object_class->dispose      = gupnp_network_manager_dispose;
-
-        g_type_class_add_private (klass, sizeof (GUPnPNetworkManagerPrivate));
 }
 
 gboolean
diff --git a/libgupnp/gupnp-network-manager.h b/libgupnp/gupnp-network-manager.h
index 9c9550d..76fd15c 100644
--- a/libgupnp/gupnp-network-manager.h
+++ b/libgupnp/gupnp-network-manager.h
@@ -27,47 +27,14 @@
 
 G_BEGIN_DECLS
 
-G_GNUC_INTERNAL GType
-gupnp_network_manager_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_NETWORK_MANAGER \
                 (gupnp_network_manager_get_type ())
-#define GUPNP_NETWORK_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_NETWORK_MANAGER, \
-                 GUPnPNetworkManager))
-#define GUPNP_NETWORK_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_NETWORK_MANAGER, \
-                 GUPnPNetworkManagerClass))
-#define GUPNP_IS_NETWORK_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_NETWORK_MANAGER))
-#define GUPNP_IS_NETWORK_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_NETWORK_MANAGER))
-#define GUPNP_NETWORK_MANAGER_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_NETWORK_MANAGER, \
-                 GUPnPNetworkManagerClass))
-
-typedef struct _GUPnPNetworkManagerPrivate GUPnPNetworkManagerPrivate;
-
-typedef struct {
-        GUPnPContextManager parent;
-
-        GUPnPNetworkManagerPrivate *priv;
-} GUPnPNetworkManager;
-
-typedef struct {
-        GUPnPContextManagerClass parent_class;
 
-        /* future padding */
-        void (* _gupnp_reserved1) (void);
-        void (* _gupnp_reserved2) (void);
-        void (* _gupnp_reserved3) (void);
-        void (* _gupnp_reserved4) (void);
-} GUPnPNetworkManagerClass;
+G_DECLARE_FINAL_TYPE (GUPnPNetworkManager,
+                      gupnp_network_manager,
+                      GUPNP,
+                      NETWORK_MANAGER,
+                      GUPnPContextManager)
 
 G_GNUC_INTERNAL gboolean
 gupnp_network_manager_is_available                      (void);
diff --git a/libgupnp/gupnp-resource-factory.c b/libgupnp/gupnp-resource-factory.c
index 3a65b4d..6a91e73 100644
--- a/libgupnp/gupnp-resource-factory.c
+++ b/libgupnp/gupnp-resource-factory.c
@@ -39,55 +39,55 @@
 #include "gupnp-resource-factory-private.h"
 #include "gupnp-root-device.h"
 
-G_DEFINE_TYPE (GUPnPResourceFactory,
-               gupnp_resource_factory,
-               G_TYPE_OBJECT);
-
 struct _GUPnPResourceFactoryPrivate {
         GHashTable *resource_type_hash;
         GHashTable *proxy_type_hash;
 };
+typedef struct _GUPnPResourceFactoryPrivate GUPnPResourceFactoryPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPResourceFactory,
+                            gupnp_resource_factory,
+                            G_TYPE_OBJECT);
+
 
 static void
 gupnp_resource_factory_init (GUPnPResourceFactory *factory)
 {
-        factory->priv =
-                G_TYPE_INSTANCE_GET_PRIVATE (factory,
-                                             GUPNP_TYPE_RESOURCE_FACTORY,
-                                             GUPnPResourceFactoryPrivate);
-
-        factory->priv->resource_type_hash =
-                        g_hash_table_new_full (g_str_hash,
-                                               g_str_equal,
-                                               g_free,
-                                               NULL);
-        factory->priv->proxy_type_hash =
-                        g_hash_table_new_full (g_str_hash,
-                                               g_str_equal,
-                                               g_free,
-                                               NULL);
+        GUPnPResourceFactoryPrivate *priv;
+
+        priv = gupnp_resource_factory_get_instance_private (factory);
+        priv->resource_type_hash = g_hash_table_new_full (g_str_hash,
+                                                          g_str_equal,
+                                                          g_free,
+                                                          NULL);
+        priv->proxy_type_hash = g_hash_table_new_full (g_str_hash,
+                                                       g_str_equal,
+                                                       g_free,
+                                                       NULL);
 }
 
-static void
+    static void
 gupnp_resource_factory_finalize (GObject *object)
 {
-        GUPnPResourceFactory *self;
-        GObjectClass *object_class;
+    GUPnPResourceFactory *self;
+    GObjectClass *object_class;
+    GUPnPResourceFactoryPrivate *priv;
 
-        self = GUPNP_RESOURCE_FACTORY (object);
+    self = GUPNP_RESOURCE_FACTORY (object);
+    priv = gupnp_resource_factory_get_instance_private (self);
 
-        if (self->priv->resource_type_hash) {
-                g_hash_table_destroy (self->priv->resource_type_hash);
-                self->priv->resource_type_hash = NULL;
-        }
+    if (priv->resource_type_hash) {
+        g_hash_table_destroy (priv->resource_type_hash);
+        priv->resource_type_hash = NULL;
+    }
 
-        if (self->priv->proxy_type_hash) {
-                g_hash_table_destroy (self->priv->proxy_type_hash);
-                self->priv->proxy_type_hash = NULL;
-        }
+    if (priv->proxy_type_hash) {
+        g_hash_table_destroy (priv->proxy_type_hash);
+        priv->proxy_type_hash = NULL;
+    }
 
-        object_class = G_OBJECT_CLASS (gupnp_resource_factory_parent_class);
-        object_class->finalize (object);
+    object_class = G_OBJECT_CLASS (gupnp_resource_factory_parent_class);
+    object_class->finalize (object);
 }
 
 static void
@@ -98,8 +98,6 @@ gupnp_resource_factory_class_init (GUPnPResourceFactoryClass *klass)
         object_class = G_OBJECT_CLASS (klass);
 
         object_class->finalize = gupnp_resource_factory_finalize;
-
-        g_type_class_add_private (klass, sizeof (GUPnPResourceFactoryPrivate));
 }
 
 /**
@@ -164,6 +162,7 @@ gupnp_resource_factory_create_device_proxy
         GUPnPDeviceProxy *proxy;
         char             *upnp_type;
         GType             proxy_type = GUPNP_TYPE_DEVICE_PROXY;
+        GUPnPResourceFactoryPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_RESOURCE_FACTORY (factory), NULL);
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
@@ -172,12 +171,14 @@ gupnp_resource_factory_create_device_proxy
         g_return_val_if_fail (location != NULL, NULL);
         g_return_val_if_fail (url_base != NULL, NULL);
 
+        priv = gupnp_resource_factory_get_instance_private (factory);
+
         upnp_type = xml_util_get_child_element_content_glib (element,
                                                              "deviceType");
         if (upnp_type) {
                 gpointer value;
 
-                value = g_hash_table_lookup (factory->priv->proxy_type_hash,
+                value = g_hash_table_lookup (priv->proxy_type_hash,
                                              upnp_type);
                 if (value)
                         proxy_type = GPOINTER_TO_SIZE (value);
@@ -229,6 +230,7 @@ gupnp_resource_factory_create_service_proxy
         char              *type_from_xml = NULL;
         GUPnPServiceProxy *proxy;
         GType              proxy_type = GUPNP_TYPE_SERVICE_PROXY;
+        GUPnPResourceFactoryPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_RESOURCE_FACTORY (factory), NULL);
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
@@ -237,6 +239,8 @@ gupnp_resource_factory_create_service_proxy
         g_return_val_if_fail (location != NULL, NULL);
         g_return_val_if_fail (url_base != NULL, NULL);
 
+        priv = gupnp_resource_factory_get_instance_private (factory);
+
         if (!service_type) {
                 type_from_xml =
                     xml_util_get_child_element_content_glib (element,
@@ -247,7 +251,7 @@ gupnp_resource_factory_create_service_proxy
         if (service_type) {
                 gpointer value;
 
-                value = g_hash_table_lookup (factory->priv->proxy_type_hash,
+                value = g_hash_table_lookup (priv->proxy_type_hash,
                                              service_type);
                 if (value)
                         proxy_type = GPOINTER_TO_SIZE (value);
@@ -296,6 +300,7 @@ gupnp_resource_factory_create_device
         GUPnPDevice *device;
         char        *upnp_type;
         GType        device_type = GUPNP_TYPE_DEVICE;
+        GUPnPResourceFactoryPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_RESOURCE_FACTORY (factory), NULL);
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
@@ -303,12 +308,14 @@ gupnp_resource_factory_create_device
         g_return_val_if_fail (element != NULL, NULL);
         g_return_val_if_fail (url_base != NULL, NULL);
 
+        priv = gupnp_resource_factory_get_instance_private (factory);
+
         upnp_type = xml_util_get_child_element_content_glib (element,
                                                              "deviceType");
         if (upnp_type) {
                 gpointer value;
 
-                value = g_hash_table_lookup (factory->priv->resource_type_hash,
+                value = g_hash_table_lookup (priv->resource_type_hash,
                                              upnp_type);
                 if (value)
                         device_type = GPOINTER_TO_SIZE (value);
@@ -357,6 +364,7 @@ gupnp_resource_factory_create_service
         GUPnPService *service;
         char         *upnp_type;
         GType         service_type = GUPNP_TYPE_SERVICE;
+        GUPnPResourceFactoryPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_RESOURCE_FACTORY (factory), NULL);
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
@@ -365,12 +373,14 @@ gupnp_resource_factory_create_service
         g_return_val_if_fail (location != NULL, NULL);
         g_return_val_if_fail (url_base != NULL, NULL);
 
+        priv = gupnp_resource_factory_get_instance_private (factory);
+
         upnp_type = xml_util_get_child_element_content_glib (element,
                                                              "serviceType");
         if (upnp_type) {
                 gpointer value;
 
-                value = g_hash_table_lookup (factory->priv->resource_type_hash,
+                value = g_hash_table_lookup (priv->resource_type_hash,
                                              upnp_type);
                 if (value)
                         service_type = GPOINTER_TO_SIZE (value);
@@ -408,7 +418,11 @@ gupnp_resource_factory_register_resource_type (GUPnPResourceFactory *factory,
                                                const char           *upnp_type,
                                                GType                 type)
 {
-        g_hash_table_insert (factory->priv->resource_type_hash,
+        GUPnPResourceFactoryPrivate *priv;
+
+        priv = gupnp_resource_factory_get_instance_private (factory);
+
+        g_hash_table_insert (priv->resource_type_hash,
                              g_strdup (upnp_type),
                              GSIZE_TO_POINTER (type));
 }
@@ -428,7 +442,11 @@ gupnp_resource_factory_unregister_resource_type
                                 (GUPnPResourceFactory *factory,
                                  const char           *upnp_type)
 {
-        return g_hash_table_remove (factory->priv->resource_type_hash,
+        GUPnPResourceFactoryPrivate *priv;
+
+        priv = gupnp_resource_factory_get_instance_private (factory);
+
+        return g_hash_table_remove (priv->resource_type_hash,
                                     upnp_type);
 }
 
@@ -451,7 +469,11 @@ gupnp_resource_factory_register_resource_proxy_type
                                  const char           *upnp_type,
                                  GType                 type)
 {
-        g_hash_table_insert (factory->priv->proxy_type_hash,
+        GUPnPResourceFactoryPrivate *priv;
+
+        priv = gupnp_resource_factory_get_instance_private (factory);
+
+        g_hash_table_insert (priv->proxy_type_hash,
                              g_strdup (upnp_type),
                              GSIZE_TO_POINTER (type));
 }
@@ -472,5 +494,9 @@ gupnp_resource_factory_unregister_resource_proxy_type
                                 (GUPnPResourceFactory *factory,
                                  const char           *upnp_type)
 {
-        return g_hash_table_remove (factory->priv->proxy_type_hash, upnp_type);
+        GUPnPResourceFactoryPrivate *priv;
+
+        priv = gupnp_resource_factory_get_instance_private (factory);
+
+        return g_hash_table_remove (priv->proxy_type_hash, upnp_type);
 }
diff --git a/libgupnp/gupnp-resource-factory.h b/libgupnp/gupnp-resource-factory.h
index a01447e..dcd34a8 100644
--- a/libgupnp/gupnp-resource-factory.h
+++ b/libgupnp/gupnp-resource-factory.h
@@ -28,45 +28,13 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_resource_factory_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_RESOURCE_FACTORY \
                 (gupnp_resource_factory_get_type ())
-#define GUPNP_RESOURCE_FACTORY(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_RESOURCE_FACTORY, \
-                 GUPnPResourceFactory))
-#define GUPNP_RESOURCE_FACTORY_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_RESOURCE_FACTORY, \
-                 GUPnPResourceFactoryClass))
-#define GUPNP_IS_RESOURCE_FACTORY(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_RESOURCE_FACTORY))
-#define GUPNP_IS_RESOURCE_FACTORY_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_RESOURCE_FACTORY))
-#define GUPNP_RESOURCE_FACTORY_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_RESOURCE_FACTORY, \
-                 GUPnPResourceFactoryClass))
-
-typedef struct _GUPnPResourceFactoryPrivate GUPnPResourceFactoryPrivate;
-typedef struct _GUPnPResourceFactory GUPnPResourceFactory;
-typedef struct _GUPnPResourceFactoryClass GUPnPResourceFactoryClass;
-
-/**
- * GUPnPResourceFactory:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPResourceFactory {
-        GObject parent;
-
-        GUPnPResourceFactoryPrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPResourceFactory,
+                          gupnp_resource_factory,
+                          GUPNP,
+                          RESOURCE_FACTORY,
+                          GObject)
 
 struct _GUPnPResourceFactoryClass {
         GObjectClass parent_class;
diff --git a/libgupnp/gupnp-root-device.c b/libgupnp/gupnp-root-device.c
index 4112e94..4637ed6 100644
--- a/libgupnp/gupnp-root-device.c
+++ b/libgupnp/gupnp-root-device.c
@@ -45,14 +45,6 @@ gupnp_root_device_initable_init (GInitable     *initable,
                                  GCancellable  *cancellable,
                                  GError       **error);
 
-G_DEFINE_TYPE_EXTENDED (GUPnPRootDevice,
-                        gupnp_root_device,
-                        GUPNP_TYPE_DEVICE,
-                        0,
-                        G_IMPLEMENT_INTERFACE
-                                (G_TYPE_INITABLE,
-                                 gupnp_root_device_initable_iface_init));
-
 struct _GUPnPRootDevicePrivate {
         GUPnPXMLDoc *description_doc;
 
@@ -62,6 +54,16 @@ struct _GUPnPRootDevicePrivate {
         char  *description_dir;
         char  *relative_location;
 };
+typedef struct _GUPnPRootDevicePrivate GUPnPRootDevicePrivate;
+
+G_DEFINE_TYPE_EXTENDED (GUPnPRootDevice,
+                        gupnp_root_device,
+                        GUPNP_TYPE_DEVICE,
+                        0,
+                        G_ADD_PRIVATE(GUPnPRootDevice)
+                        G_IMPLEMENT_INTERFACE
+                                (G_TYPE_INITABLE,
+                                 gupnp_root_device_initable_iface_init));
 
 enum {
         PROP_0,
@@ -75,14 +77,16 @@ static void
 gupnp_root_device_finalize (GObject *object)
 {
         GUPnPRootDevice *device;
+        GUPnPRootDevicePrivate *priv;
         GObjectClass *object_class;
 
         device = GUPNP_ROOT_DEVICE (object);
+        priv = gupnp_root_device_get_instance_private (device);
 
-        g_clear_object (&device->priv->description_doc);
-        g_free (device->priv->description_path);
-        g_free (device->priv->description_dir);
-        g_free (device->priv->relative_location);
+        g_clear_object (&priv->description_doc);
+        g_free (priv->description_path);
+        g_free (priv->description_dir);
+        g_free (priv->relative_location);
 
         /* Call super */
         object_class = G_OBJECT_CLASS (gupnp_root_device_parent_class);
@@ -93,13 +97,15 @@ static void
 gupnp_root_device_dispose (GObject *object)
 {
         GUPnPRootDevice *device;
+        GUPnPRootDevicePrivate *priv;
         GObjectClass *object_class;
 
         device = GUPNP_ROOT_DEVICE (object);
+        priv = gupnp_root_device_get_instance_private (device);
 
-        if (device->priv->group) {
-                g_object_unref (device->priv->group);
-                device->priv->group = NULL;
+        if (priv->group) {
+                g_object_unref (priv->group);
+                priv->group = NULL;
         }
 
         /* Call super */
@@ -110,9 +116,6 @@ gupnp_root_device_dispose (GObject *object)
 static void
 gupnp_root_device_init (GUPnPRootDevice *device)
 {
-        device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device,
-                                                    GUPNP_TYPE_ROOT_DEVICE,
-                                                    GUPnPRootDevicePrivate);
 }
 
 static void
@@ -130,18 +133,20 @@ gupnp_root_device_set_property (GObject      *object,
                                 GParamSpec   *pspec)
 {
         GUPnPRootDevice *device;
+        GUPnPRootDevicePrivate *priv;
 
         device = GUPNP_ROOT_DEVICE (object);
+        priv = gupnp_root_device_get_instance_private (device);
 
         switch (property_id) {
         case PROP_DESCRIPTION_DOC:
-                device->priv->description_doc = g_value_dup_object (value);
+                priv->description_doc = g_value_dup_object (value);
                 break;
         case PROP_DESCRIPTION_PATH:
-                device->priv->description_path = g_value_dup_string (value);
+                priv->description_path = g_value_dup_string (value);
                 break;
         case PROP_DESCRIPTION_DIR:
-                device->priv->description_dir = g_value_dup_string (value);
+                priv->description_dir = g_value_dup_string (value);
                 break;
         case PROP_AVAILABLE:
                 gupnp_root_device_set_available
@@ -160,17 +165,19 @@ gupnp_root_device_get_property (GObject    *object,
                                 GParamSpec *pspec)
 {
         GUPnPRootDevice *device;
+        GUPnPRootDevicePrivate *priv;
 
         device = GUPNP_ROOT_DEVICE (object);
+        priv = gupnp_root_device_get_instance_private (device);
 
         switch (property_id) {
         case PROP_DESCRIPTION_PATH:
                 g_value_set_string (value,
-                                    device->priv->description_path);
+                                    priv->description_path);
                 break;
         case PROP_DESCRIPTION_DIR:
                 g_value_set_string (value,
-                                    device->priv->description_dir);
+                                    priv->description_dir);
                 break;
         case PROP_AVAILABLE:
                 g_value_set_boolean (value,
@@ -297,8 +304,10 @@ gupnp_root_device_initable_init (GInitable     *initable,
         xmlNode *root_element, *element;
         SoupURI *url_base;
         gboolean result = FALSE;
+        GUPnPRootDevicePrivate *priv;
 
         device = GUPNP_ROOT_DEVICE (initable);
+        priv = gupnp_root_device_get_instance_private (device);
 
         location = NULL;
 
@@ -315,7 +324,7 @@ gupnp_root_device_initable_init (GInitable     *initable,
                 return FALSE;
         }
 
-        if (device->priv->description_path == NULL) {
+        if (priv->description_path == NULL) {
                 g_set_error_literal (error,
                                      GUPNP_ROOT_DEVICE_ERROR,
                                      GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_PATH,
@@ -324,7 +333,7 @@ gupnp_root_device_initable_init (GInitable     *initable,
                 return FALSE;
         }
 
-        if (device->priv->description_dir == NULL) {
+        if (priv->description_dir == NULL) {
                 g_set_error_literal (error,
                                      GUPNP_ROOT_DEVICE_ERROR,
                                      GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_FOLDER,
@@ -343,18 +352,18 @@ gupnp_root_device_initable_init (GInitable     *initable,
                 return FALSE;
         }
 
-        if (g_path_is_absolute (device->priv->description_path))
-                desc_path = g_strdup (device->priv->description_path);
+        if (g_path_is_absolute (priv->description_path))
+                desc_path = g_strdup (priv->description_path);
         else
-                desc_path = g_build_filename (device->priv->description_dir,
-                                              device->priv->description_path,
+                desc_path = g_build_filename (priv->description_dir,
+                                              priv->description_path,
                                               NULL);
 
         /* Check whether we have a parsed description document */
-        if (device->priv->description_doc == NULL) {
+        if (priv->description_doc == NULL) {
                 /* We don't, so load and parse it */
-                device->priv->description_doc = load_and_parse (desc_path);
-                if (device->priv->description_doc == NULL) {
+                priv->description_doc = load_and_parse (desc_path);
+                if (priv->description_doc == NULL) {
                         g_set_error_literal (error,
                                              GUPNP_XML_ERROR,
                                              GUPNP_XML_ERROR_PARSE,
@@ -365,7 +374,8 @@ gupnp_root_device_initable_init (GInitable     *initable,
         }
 
         /* Find correct element */
-        root_element = xml_util_get_element ((xmlNode *) device->priv->description_doc->doc,
+        root_element = xml_util_get_element ((xmlNode *)
+                                             gupnp_xml_doc_get_doc (priv->description_doc),
                                              "root",
                                              NULL);
         if (!root_element) {
@@ -396,18 +406,18 @@ gupnp_root_device_initable_init (GInitable     *initable,
         /* Generate location relative to HTTP root */
         udn = gupnp_device_info_get_udn (GUPNP_DEVICE_INFO (device));
         if (udn && strstr (udn, "uuid:") == udn)
-                device->priv->relative_location = g_strdup_printf ("%s.xml", udn + 5);
+                priv->relative_location = g_strdup_printf ("%s.xml", udn + 5);
         else
-                device->priv->relative_location = g_strdup_printf ("RootDevice%p.xml", device);
+                priv->relative_location = g_strdup_printf ("RootDevice%p.xml", device);
 
         relative_location = g_strjoin (NULL,
                                        "/",
-                                       device->priv->relative_location,
+                                       priv->relative_location,
                                        NULL);
 
         /* Host the description file and dir */
         gupnp_context_host_path (context, desc_path, relative_location);
-        gupnp_context_host_path (context, device->priv->description_dir, "");
+        gupnp_context_host_path (context, priv->description_dir, "");
 
         /* Generate full location */
         soup_uri_set_path (uri, relative_location);
@@ -431,17 +441,17 @@ gupnp_root_device_initable_init (GInitable     *initable,
         soup_uri_free (url_base);
 
         /* Create resource group */
-        device->priv->group = gssdp_resource_group_new (GSSDP_CLIENT (context));
+        priv->group = gssdp_resource_group_new (GSSDP_CLIENT (context));
 
         /* Add services and devices to resource group */
         usn = g_strdup_printf ("%s::upnp:rootdevice", (const char *) udn);
-        gssdp_resource_group_add_resource_simple (device->priv->group,
+        gssdp_resource_group_add_resource_simple (priv->group,
                                                   "upnp:rootdevice",
                                                   usn,
                                                   location);
         g_free (usn);
 
-        fill_resource_group (element, location, device->priv->group);
+        fill_resource_group (element, location, priv->group);
 
         result = TRUE;
 
@@ -468,8 +478,6 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
         object_class->dispose      = gupnp_root_device_dispose;
         object_class->finalize     = gupnp_root_device_finalize;
 
-        g_type_class_add_private (klass, sizeof (GUPnPRootDevicePrivate));
-
         /**
          * GUPnPRootDevice:description-doc:
          *
@@ -632,10 +640,13 @@ void
 gupnp_root_device_set_available (GUPnPRootDevice *root_device,
                                  gboolean         available)
 {
+        GUPnPRootDevicePrivate *priv;
+
         g_return_if_fail (GUPNP_IS_ROOT_DEVICE (root_device));
 
-        gssdp_resource_group_set_available (root_device->priv->group,
-                                            available);
+        priv = gupnp_root_device_get_instance_private (root_device);
+
+        gssdp_resource_group_set_available (priv->group, available);
 
         g_object_notify (G_OBJECT (root_device), "available");
 }
@@ -651,9 +662,13 @@ gupnp_root_device_set_available (GUPnPRootDevice *root_device,
 gboolean
 gupnp_root_device_get_available (GUPnPRootDevice *root_device)
 {
+        GUPnPRootDevicePrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_ROOT_DEVICE (root_device), FALSE);
 
-        return gssdp_resource_group_get_available (root_device->priv->group);
+        priv = gupnp_root_device_get_instance_private (root_device);
+
+        return gssdp_resource_group_get_available (priv->group);
 }
 
 /**
@@ -667,9 +682,13 @@ gupnp_root_device_get_available (GUPnPRootDevice *root_device)
 const char *
 gupnp_root_device_get_relative_location (GUPnPRootDevice *root_device)
 {
+        GUPnPRootDevicePrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_ROOT_DEVICE (root_device), NULL);
 
-        return root_device->priv->relative_location;
+        priv = gupnp_root_device_get_instance_private (root_device);
+
+        return priv->relative_location;
 }
 
 /**
@@ -683,9 +702,13 @@ gupnp_root_device_get_relative_location (GUPnPRootDevice *root_device)
 const char *
 gupnp_root_device_get_description_path (GUPnPRootDevice *root_device)
 {
+        GUPnPRootDevicePrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_ROOT_DEVICE (root_device), NULL);
 
-        return root_device->priv->description_path;
+        priv = gupnp_root_device_get_instance_private (root_device);
+
+        return priv->description_path;
 }
 
 /**
@@ -700,9 +723,13 @@ gupnp_root_device_get_description_path (GUPnPRootDevice *root_device)
 const char *
 gupnp_root_device_get_description_dir (GUPnPRootDevice *root_device)
 {
+        GUPnPRootDevicePrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_ROOT_DEVICE (root_device), NULL);
 
-        return root_device->priv->description_dir;
+        priv = gupnp_root_device_get_instance_private (root_device);
+
+        return priv->description_dir;
 }
 
 /**
@@ -718,7 +745,11 @@ gupnp_root_device_get_description_dir (GUPnPRootDevice *root_device)
 GSSDPResourceGroup *
 gupnp_root_device_get_ssdp_resource_group (GUPnPRootDevice *root_device)
 {
+        GUPnPRootDevicePrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_ROOT_DEVICE (root_device), NULL);
 
-        return root_device->priv->group;
+        priv = gupnp_root_device_get_instance_private (root_device);
+
+        return priv->group;
 }
diff --git a/libgupnp/gupnp-root-device.h b/libgupnp/gupnp-root-device.h
index 5891056..bc3ae0e 100644
--- a/libgupnp/gupnp-root-device.h
+++ b/libgupnp/gupnp-root-device.h
@@ -33,45 +33,15 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_root_device_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_ROOT_DEVICE \
                 (gupnp_root_device_get_type ())
-#define GUPNP_ROOT_DEVICE(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_ROOT_DEVICE, \
-                 GUPnPRootDevice))
-#define GUPNP_ROOT_DEVICE_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_ROOT_DEVICE, \
-                 GUPnPRootDeviceClass))
-#define GUPNP_IS_ROOT_DEVICE(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_ROOT_DEVICE))
-#define GUPNP_IS_ROOT_DEVICE_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_ROOT_DEVICE))
-#define GUPNP_ROOT_DEVICE_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_ROOT_DEVICE, \
-                 GUPnPRootDeviceClass))
-
-typedef struct _GUPnPRootDevicePrivate GUPnPRootDevicePrivate;
-typedef struct _GUPnPRootDevice GUPnPRootDevice;
-typedef struct _GUPnPRootDeviceClass GUPnPRootDeviceClass;
-
-/**
- * GUPnPRootDevice:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPRootDevice {
-        GUPnPDevice parent;
 
-        GUPnPRootDevicePrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPRootDevice,
+                          gupnp_root_device,
+                          GUPNP,
+                          ROOT_DEVICE,
+                          GUPnPDevice)
+
 
 struct _GUPnPRootDeviceClass {
         GUPnPDeviceClass parent_class;
diff --git a/libgupnp/gupnp-service-info.c b/libgupnp/gupnp-service-info.c
index 53d222a..69d711f 100644
--- a/libgupnp/gupnp-service-info.c
+++ b/libgupnp/gupnp-service-info.c
@@ -39,10 +39,6 @@
 #include "http-headers.h"
 #include "xml-util.h"
 
-G_DEFINE_ABSTRACT_TYPE (GUPnPServiceInfo,
-                        gupnp_service_info,
-                        G_TYPE_OBJECT);
-
 struct _GUPnPServiceInfoPrivate {
         GUPnPContext *context;
 
@@ -60,6 +56,12 @@ struct _GUPnPServiceInfoPrivate {
         GList *pending_gets;
 };
 
+typedef struct _GUPnPServiceInfoPrivate GUPnPServiceInfoPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GUPnPServiceInfo,
+                                     gupnp_service_info,
+                                     G_TYPE_OBJECT);
+
 enum {
         PROP_0,
         PROP_CONTEXT,
@@ -95,9 +97,6 @@ get_scpd_url_data_free (GetSCPDURLData *data)
 static void
 gupnp_service_info_init (GUPnPServiceInfo *info)
 {
-        info->priv = G_TYPE_INSTANCE_GET_PRIVATE (info,
-                                                  GUPNP_TYPE_SERVICE_INFO,
-                                                  GUPnPServiceInfoPrivate);
 }
 
 static void
@@ -107,30 +106,32 @@ gupnp_service_info_set_property (GObject      *object,
                                  GParamSpec   *pspec)
 {
         GUPnPServiceInfo *info;
+        GUPnPServiceInfoPrivate *priv;
 
         info = GUPNP_SERVICE_INFO (object);
+        priv = gupnp_service_info_get_instance_private (info);
 
         switch (property_id) {
         case PROP_CONTEXT:
-                info->priv->context = g_object_ref (g_value_get_object (value));
+                priv->context = g_object_ref (g_value_get_object (value));
                 break;
         case PROP_LOCATION:
-                info->priv->location = g_value_dup_string (value);
+                priv->location = g_value_dup_string (value);
                 break;
         case PROP_UDN:
-                info->priv->udn = g_value_dup_string (value);
+                priv->udn = g_value_dup_string (value);
                 break;
         case PROP_SERVICE_TYPE:
-                info->priv->service_type = g_value_dup_string (value);
+                priv->service_type = g_value_dup_string (value);
                 break;
         case PROP_URL_BASE:
-                info->priv->url_base = g_value_dup_boxed (value);
+                priv->url_base = g_value_dup_boxed (value);
                 break;
         case PROP_DOCUMENT:
-                info->priv->doc = g_value_dup_object (value);
+                priv->doc = g_value_dup_object (value);
                 break;
         case PROP_ELEMENT:
-                info->priv->element = g_value_get_pointer (value);
+                priv->element = g_value_get_pointer (value);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -145,29 +146,27 @@ gupnp_service_info_get_property (GObject    *object,
                                  GParamSpec *pspec)
 {
         GUPnPServiceInfo *info;
+        GUPnPServiceInfoPrivate *priv;
 
         info = GUPNP_SERVICE_INFO (object);
+        priv = gupnp_service_info_get_instance_private (info);
 
         switch (property_id) {
         case PROP_CONTEXT:
-                g_value_set_object (value,
-                                    info->priv->context);
+                g_value_set_object (value, priv->context);
                 break;
         case PROP_LOCATION:
-                g_value_set_string (value,
-                                    info->priv->location);
+                g_value_set_string (value, priv->location);
                 break;
         case PROP_UDN:
-                g_value_set_string (value,
-                                    info->priv->udn);
+                g_value_set_string (value, priv->udn);
                 break;
         case PROP_SERVICE_TYPE:
                 g_value_set_string (value,
                                     gupnp_service_info_get_service_type (info));
                 break;
         case PROP_URL_BASE:
-                g_value_set_boxed (value,
-                                   info->priv->url_base);
+                g_value_set_boxed (value, priv->url_base);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -179,19 +178,21 @@ static void
 gupnp_service_info_dispose (GObject *object)
 {
         GUPnPServiceInfo *info;
+        GUPnPServiceInfoPrivate *priv;
 
         info = GUPNP_SERVICE_INFO (object);
+        priv = gupnp_service_info_get_instance_private (info);
 
         /* Cancel any pending SCPD GETs */
-        if (info->priv->context) {
+        if (priv->context) {
                 SoupSession *session;
 
-                session = gupnp_context_get_session (info->priv->context);
+                session = gupnp_context_get_session (priv->context);
 
-                while (info->priv->pending_gets) {
+                while (priv->pending_gets) {
                         GetSCPDURLData *data;
 
-                        data = info->priv->pending_gets->data;
+                        data = priv->pending_gets->data;
 
                         if (data->cancellable)
                                 g_cancellable_disconnect (data->cancellable,
@@ -203,19 +204,19 @@ gupnp_service_info_dispose (GObject *object)
 
                         get_scpd_url_data_free (data);
 
-                        info->priv->pending_gets =
-                                g_list_delete_link (info->priv->pending_gets,
-                                                    info->priv->pending_gets);
+                        priv->pending_gets =
+                                g_list_delete_link (priv->pending_gets,
+                                                    priv->pending_gets);
                 }
 
                 /* Unref context */
-                g_object_unref (info->priv->context);
-                info->priv->context = NULL;
+                g_object_unref (priv->context);
+                priv->context = NULL;
         }
 
-        if (info->priv->doc) {
-                g_object_unref (info->priv->doc);
-                info->priv->doc = NULL;
+        if (priv->doc) {
+                g_object_unref (priv->doc);
+                priv->doc = NULL;
         }
 
         G_OBJECT_CLASS (gupnp_service_info_parent_class)->dispose (object);
@@ -225,14 +226,16 @@ static void
 gupnp_service_info_finalize (GObject *object)
 {
         GUPnPServiceInfo *info;
+        GUPnPServiceInfoPrivate *priv;
 
         info = GUPNP_SERVICE_INFO (object);
+        priv = gupnp_service_info_get_instance_private (info);
 
-        g_free (info->priv->location);
-        g_free (info->priv->udn);
-        g_free (info->priv->service_type);
+        g_free (priv->location);
+        g_free (priv->udn);
+        g_free (priv->service_type);
 
-        soup_uri_free (info->priv->url_base);
+        soup_uri_free (priv->url_base);
 
         G_OBJECT_CLASS (gupnp_service_info_parent_class)->finalize (object);
 }
@@ -249,8 +252,6 @@ gupnp_service_info_class_init (GUPnPServiceInfoClass *klass)
         object_class->dispose      = gupnp_service_info_dispose;
         object_class->finalize     = gupnp_service_info_finalize;
 
-        g_type_class_add_private (klass, sizeof (GUPnPServiceInfoPrivate));
-
         /**
          * GUPnPServiceInfo:context:
          *
@@ -395,9 +396,13 @@ gupnp_service_info_class_init (GUPnPServiceInfoClass *klass)
 GUPnPContext *
 gupnp_service_info_get_context (GUPnPServiceInfo *info)
 {
+        GUPnPServiceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);
 
-        return info->priv->context;
+        priv = gupnp_service_info_get_instance_private (info);
+
+        return priv->context;
 }
 
 /**
@@ -411,9 +416,13 @@ gupnp_service_info_get_context (GUPnPServiceInfo *info)
 const char *
 gupnp_service_info_get_location (GUPnPServiceInfo *info)
 {
+        GUPnPServiceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);
 
-        return info->priv->location;
+        priv = gupnp_service_info_get_instance_private (info);
+
+        return priv->location;
 }
 
 /**
@@ -427,9 +436,13 @@ gupnp_service_info_get_location (GUPnPServiceInfo *info)
 const SoupURI *
 gupnp_service_info_get_url_base (GUPnPServiceInfo *info)
 {
+        GUPnPServiceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);
 
-        return info->priv->url_base;
+        priv = gupnp_service_info_get_instance_private (info);
+
+        return priv->url_base;
 }
 
 /**
@@ -443,9 +456,13 @@ gupnp_service_info_get_url_base (GUPnPServiceInfo *info)
 const char *
 gupnp_service_info_get_udn (GUPnPServiceInfo *info)
 {
+        GUPnPServiceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);
 
-        return info->priv->udn;
+        priv = gupnp_service_info_get_instance_private (info);
+
+        return priv->udn;
 }
 
 /**
@@ -459,15 +476,19 @@ gupnp_service_info_get_udn (GUPnPServiceInfo *info)
 const char *
 gupnp_service_info_get_service_type (GUPnPServiceInfo *info)
 {
+        GUPnPServiceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);
 
-        if (!info->priv->service_type) {
-                info->priv->service_type =
+        priv = gupnp_service_info_get_instance_private (info);
+
+        if (!priv->service_type) {
+                priv->service_type =
                         xml_util_get_child_element_content_glib
-                                (info->priv->element, "serviceType");
+                                (priv->element, "serviceType");
         }
 
-        return info->priv->service_type;
+        return priv->service_type;
 }
 
 /**
@@ -481,9 +502,13 @@ gupnp_service_info_get_service_type (GUPnPServiceInfo *info)
 char *
 gupnp_service_info_get_id (GUPnPServiceInfo *info)
 {
+        GUPnPServiceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_glib (info->priv->element,
+        priv = gupnp_service_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_glib (priv->element,
                                                         "serviceId");
 }
 
@@ -498,11 +523,15 @@ gupnp_service_info_get_id (GUPnPServiceInfo *info)
 char *
 gupnp_service_info_get_scpd_url (GUPnPServiceInfo *info)
 {
+        GUPnPServiceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_url (info->priv->element,
+        priv = gupnp_service_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_url (priv->element,
                                                        "SCPDURL",
-                                                       info->priv->url_base);
+                                                       priv->url_base);
 }
 
 /**
@@ -516,11 +545,15 @@ gupnp_service_info_get_scpd_url (GUPnPServiceInfo *info)
 char *
 gupnp_service_info_get_control_url (GUPnPServiceInfo *info)
 {
+        GUPnPServiceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_url (info->priv->element,
+        priv = gupnp_service_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_url (priv->element,
                                                        "controlURL",
-                                                       info->priv->url_base);
+                                                       priv->url_base);
 }
 
 /**
@@ -534,11 +567,15 @@ gupnp_service_info_get_control_url (GUPnPServiceInfo *info)
 char *
 gupnp_service_info_get_event_subscription_url (GUPnPServiceInfo *info)
 {
+        GUPnPServiceInfoPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);
 
-        return xml_util_get_child_element_content_url (info->priv->element,
+        priv = gupnp_service_info_get_instance_private (info);
+
+        return xml_util_get_child_element_content_url (priv->element,
                                                        "eventSubURL",
-                                                       info->priv->url_base);
+                                                       priv->url_base);
 }
 
 /*
@@ -551,6 +588,7 @@ got_scpd_url (G_GNUC_UNUSED SoupSession *session,
 {
         GUPnPServiceIntrospection *introspection;
         GError *error;
+        GUPnPServiceInfoPrivate *priv;
 
         introspection = NULL;
         error = NULL;
@@ -584,8 +622,8 @@ got_scpd_url (G_GNUC_UNUSED SoupSession *session,
                 g_cancellable_disconnect (data->cancellable,
                                           data->cancelled_id);
 
-        data->info->priv->pending_gets =
-                g_list_remove (data->info->priv->pending_gets, data);
+        priv = gupnp_service_info_get_instance_private (data->info);
+        priv->pending_gets = g_list_remove (priv->pending_gets, data);
 
         data->callback (data->info,
                         introspection,
@@ -606,17 +644,19 @@ cancellable_cancelled_cb (GCancellable *cancellable,
         GetSCPDURLData *data;
         SoupSession *session;
         GError *error;
+        GUPnPServiceInfoPrivate *priv;
 
         data = user_data;
         info = data->info;
 
-        session = gupnp_context_get_session (info->priv->context);
+        priv = gupnp_service_info_get_instance_private (info);
+
+        session = gupnp_context_get_session (priv->context);
         soup_session_cancel_message (session,
                                      data->message,
                                      SOUP_STATUS_CANCELLED);
 
-        info->priv->pending_gets =
-                g_list_remove (info->priv->pending_gets, data);
+        priv->pending_gets = g_list_remove (priv->pending_gets, data);
 
         error = g_error_new (G_IO_ERROR,
                              G_IO_ERROR_CANCELLED,
@@ -678,6 +718,7 @@ gupnp_service_info_get_introspection_async_full
         GetSCPDURLData *data;
         char *scpd_url;
         SoupSession *session;
+        GUPnPServiceInfoPrivate *priv;
 
         g_return_if_fail (GUPNP_IS_SERVICE_INFO (info));
         g_return_if_fail (callback != NULL);
@@ -715,11 +756,10 @@ gupnp_service_info_get_introspection_async_full
         data->user_data = user_data;
 
         /* Send off the message */
-        info->priv->pending_gets =
-                g_list_prepend (info->priv->pending_gets,
-                                data);
+        priv = gupnp_service_info_get_instance_private (info);
+        priv->pending_gets = g_list_prepend (priv->pending_gets, data);
 
-        session = gupnp_context_get_session (info->priv->context);
+        session = gupnp_context_get_session (priv->context);
 
         soup_session_queue_message (session,
                                     data->message,
diff --git a/libgupnp/gupnp-service-info.h b/libgupnp/gupnp-service-info.h
index 023df1b..25cb8ab 100644
--- a/libgupnp/gupnp-service-info.h
+++ b/libgupnp/gupnp-service-info.h
@@ -31,45 +31,14 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_service_info_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_SERVICE_INFO \
                 (gupnp_service_info_get_type ())
-#define GUPNP_SERVICE_INFO(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_SERVICE_INFO, \
-                 GUPnPServiceInfo))
-#define GUPNP_SERVICE_INFO_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_SERVICE_INFO, \
-                 GUPnPServiceInfoClass))
-#define GUPNP_IS_SERVICE_INFO(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_SERVICE_INFO))
-#define GUPNP_IS_SERVICE_INFO_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_SERVICE_INFO))
-#define GUPNP_SERVICE_INFO_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_SERVICE_INFO, \
-                 GUPnPServiceInfoClass))
-
-typedef struct _GUPnPServiceInfoPrivate GUPnPServiceInfoPrivate;
-typedef struct _GUPnPServiceInfo GUPnPServiceInfo;
-typedef struct _GUPnPServiceInfoClass GUPnPServiceInfoClass;
-
-/**
- * GUPnPServiceInfo:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPServiceInfo {
-        GObject parent;
 
-        GUPnPServiceInfoPrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPServiceInfo,
+                          gupnp_service_info,
+                          GUPNP,
+                          SERVICE_INFO,
+                          GObject)
 
 struct _GUPnPServiceInfoClass {
         GObjectClass parent_class;
diff --git a/libgupnp/gupnp-service-introspection.c b/libgupnp/gupnp-service-introspection.c
index 0d06af4..9463b34 100644
--- a/libgupnp/gupnp-service-introspection.c
+++ b/libgupnp/gupnp-service-introspection.c
@@ -55,9 +55,9 @@
 
 #define MAX_FIXED_14_4 99999999999999.9999
 
-G_DEFINE_TYPE (GUPnPServiceIntrospection,
-               gupnp_service_introspection,
-               G_TYPE_OBJECT);
+struct _GUPnPServiceIntrospection {
+        GObject parent;
+};
 
 struct _GUPnPServiceIntrospectionPrivate {
         GList *variables;
@@ -68,6 +68,12 @@ struct _GUPnPServiceIntrospectionPrivate {
         GList *variable_names;
 };
 
+typedef struct _GUPnPServiceIntrospectionPrivate
+                GUPnPServiceIntrospectionPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPServiceIntrospection,
+                            gupnp_service_introspection,
+                            G_TYPE_OBJECT);
 enum {
         PROP_0,
         PROP_SCPD
@@ -104,10 +110,6 @@ gupnp_service_state_variable_info_free
 static void
 gupnp_service_introspection_init (GUPnPServiceIntrospection *introspection)
 {
-        introspection->priv =
-                G_TYPE_INSTANCE_GET_PRIVATE (introspection,
-                                             GUPNP_TYPE_SERVICE_INTROSPECTION,
-                                             GUPnPServiceIntrospectionPrivate);
 }
 
 static void
@@ -169,24 +171,26 @@ static void
 gupnp_service_introspection_finalize (GObject *object)
 {
         GUPnPServiceIntrospection *introspection;
+        GUPnPServiceIntrospectionPrivate *priv;
 
         introspection = GUPNP_SERVICE_INTROSPECTION (object);
+        priv = gupnp_service_introspection_get_instance_private (introspection);
 
-        g_list_free_full (introspection->priv->variables,
+        g_list_free_full (priv->variables,
                           (GDestroyNotify) gupnp_service_state_variable_info_free);
 
-        g_list_free_full (introspection->priv->actions,
+        g_list_free_full (priv->actions,
                           (GDestroyNotify) gupnp_service_action_info_free);
 
         /* Contents don't need to be freed, they were owned by priv->variables
          */
-        if (introspection->priv->variable_names)
-                g_list_free (introspection->priv->variable_names);
+        if (priv->variable_names)
+                g_list_free (priv->variable_names);
 
         /* Contents don't need to be freed, they were owned by priv->actions
          */
-        if (introspection->priv->action_names)
-                g_list_free (introspection->priv->action_names);
+        if (priv->action_names)
+                g_list_free (priv->action_names);
 }
 
 static void
@@ -199,9 +203,6 @@ gupnp_service_introspection_class_init (GUPnPServiceIntrospectionClass *klass)
         object_class->set_property = gupnp_service_introspection_set_property;
         object_class->finalize     = gupnp_service_introspection_finalize;
 
-        g_type_class_add_private (klass,
-                                  sizeof (GUPnPServiceIntrospectionPrivate));
-
         /**
          * GUPnPServiceIntrospection:scpd:
          *
@@ -664,16 +665,19 @@ construct_introspection_info (GUPnPServiceIntrospection *introspection,
                               xmlDoc                    *scpd)
 {
         xmlNode *element;
+        GUPnPServiceIntrospectionPrivate *priv;
 
         g_return_if_fail (scpd != NULL);
 
+        priv = gupnp_service_introspection_get_instance_private (introspection);
+
         /* Get actionList element */
         element = xml_util_get_element ((xmlNode *) scpd,
                                         "scpd",
                                         "actionList",
                                         NULL);
         if (element)
-                introspection->priv->actions = get_actions (element);
+                priv->actions = get_actions (element);
 
         /* Get serviceStateTable element */
         element = xml_util_get_element ((xmlNode *) scpd,
@@ -681,7 +685,7 @@ construct_introspection_info (GUPnPServiceIntrospection *introspection,
                                         "serviceStateTable",
                                         NULL);
         if (element)
-                introspection->priv->variables = get_state_variables (element);
+                priv->variables = get_state_variables (element);
 }
 
 static void
@@ -718,6 +722,7 @@ GUPnPServiceIntrospection *
 gupnp_service_introspection_new (xmlDoc *scpd)
 {
         GUPnPServiceIntrospection *introspection;
+        GUPnPServiceIntrospectionPrivate *priv;
 
         g_return_val_if_fail (scpd != NULL, NULL);
 
@@ -725,8 +730,10 @@ gupnp_service_introspection_new (xmlDoc *scpd)
                                       "scpd", scpd,
                                       NULL);
 
-        if (introspection->priv->actions == NULL &&
-            introspection->priv->variables == NULL) {
+        priv = gupnp_service_introspection_get_instance_private (introspection);
+
+        if (priv->actions == NULL &&
+            priv->variables == NULL) {
                 g_object_unref (introspection);
                 introspection = NULL;
         }
@@ -747,16 +754,20 @@ const GList *
 gupnp_service_introspection_list_action_names
                         (GUPnPServiceIntrospection *introspection)
 {
-        if (introspection->priv->actions == NULL)
+        GUPnPServiceIntrospectionPrivate *priv;
+
+        priv = gupnp_service_introspection_get_instance_private (introspection);
+
+        if (priv->actions == NULL)
                 return NULL;
 
-        if (introspection->priv->action_names == NULL) {
-                g_list_foreach (introspection->priv->actions,
+        if (priv->action_names == NULL) {
+                g_list_foreach (priv->actions,
                                 collect_action_names,
-                                &introspection->priv->action_names);
+                                &priv->action_names);
         }
 
-        return introspection->priv->action_names;
+        return priv->action_names;
 }
 
 /**
@@ -774,7 +785,11 @@ const GList *
 gupnp_service_introspection_list_actions
                         (GUPnPServiceIntrospection *introspection)
 {
-        return introspection->priv->actions;
+        GUPnPServiceIntrospectionPrivate *priv;
+
+        priv = gupnp_service_introspection_get_instance_private (introspection);
+
+        return priv->actions;
 }
 
 /**
@@ -793,7 +808,11 @@ const GList *
 gupnp_service_introspection_list_state_variables
                         (GUPnPServiceIntrospection *introspection)
 {
-        return introspection->priv->variables;
+        GUPnPServiceIntrospectionPrivate *priv;
+
+        priv = gupnp_service_introspection_get_instance_private (introspection);
+
+        return priv->variables;
 }
 
 /**
@@ -809,16 +828,20 @@ const GList *
 gupnp_service_introspection_list_state_variable_names
                         (GUPnPServiceIntrospection *introspection)
 {
-        if (introspection->priv->variables == NULL)
+        GUPnPServiceIntrospectionPrivate *priv;
+
+        priv = gupnp_service_introspection_get_instance_private (introspection);
+
+        if (priv->variables == NULL)
                 return NULL;
 
-        if (introspection->priv->variable_names == NULL) {
-                g_list_foreach (introspection->priv->variables,
+        if (priv->variable_names == NULL) {
+                g_list_foreach (priv->variables,
                                 collect_variable_names,
-                                &introspection->priv->variable_names);
+                                &priv->variable_names);
         }
 
-        return introspection->priv->variable_names;
+        return priv->variable_names;
 }
 
 static gint
@@ -844,12 +867,15 @@ gupnp_service_introspection_get_state_variable
                          const gchar               *variable_name)
 {
         GList *variable_node;
+        GUPnPServiceIntrospectionPrivate *priv;
+
+        priv = gupnp_service_introspection_get_instance_private (introspection);
 
-        if (introspection->priv->variables == NULL)
+        if (priv->variables == NULL)
                 return NULL;
 
         variable_node = g_list_find_custom (
-                                introspection->priv->variables,
+                                priv->variables,
                                 (gpointer) variable_name,
                                 (GCompareFunc) state_variable_search_func);
         if (variable_node == NULL)
@@ -881,14 +907,16 @@ gupnp_service_introspection_get_action
                          const gchar               *action_name)
 {
         GList *action_node;
+        GUPnPServiceIntrospectionPrivate *priv;
+
+        priv = gupnp_service_introspection_get_instance_private (introspection);
 
-        if (introspection->priv->variables == NULL)
+        if (priv->variables == NULL)
                 return NULL;
 
-        action_node = g_list_find_custom (
-                                introspection->priv->actions,
-                                (gpointer) action_name,
-                                (GCompareFunc) action_search_func);
+        action_node = g_list_find_custom (priv->actions,
+                                          (gpointer) action_name,
+                                          (GCompareFunc) action_search_func);
         if (action_node == NULL)
                 return NULL;
 
diff --git a/libgupnp/gupnp-service-introspection.h b/libgupnp/gupnp-service-introspection.h
index 556df63..a13ea84 100644
--- a/libgupnp/gupnp-service-introspection.h
+++ b/libgupnp/gupnp-service-introspection.h
@@ -28,29 +28,14 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_service_introspection_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_SERVICE_INTROSPECTION \
                 (gupnp_service_introspection_get_type ())
-#define GUPNP_SERVICE_INTROSPECTION(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_SERVICE_INTROSPECTION, \
-                 GUPnPServiceIntrospection))
-#define GUPNP_SERVICE_INTROSPECTION_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_SERVICE_INTROSPECTION, \
-                 GUPnPServiceIntrospectionClass))
-#define GUPNP_IS_SERVICE_INTROSPECTION(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_SERVICE_INTROSPECTION))
-#define GUPNP_IS_SERVICE_INTROSPECTION_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_SERVICE_INTROSPECTION))
-#define GUPNP_SERVICE_INTROSPECTION_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_SERVICE_INTROSPECTION, \
-                 GUPnPServiceIntrospectionClass))
+
+G_DECLARE_FINAL_TYPE (GUPnPServiceIntrospection,
+                      gupnp_service_introspection,
+                      GUPNP,
+                      SERVICE_INTROSPECTION,
+                      GObject)
 
 /**
  * GUPnPServiceActionArgDirection:
@@ -127,28 +112,6 @@ typedef struct {
         GList   *allowed_values;
 } GUPnPServiceStateVariableInfo;
 
-typedef struct _GUPnPServiceIntrospectionPrivate
-                GUPnPServiceIntrospectionPrivate;
-typedef struct _GUPnPServiceIntrospection
-                GUPnPServiceIntrospection;
-typedef struct _GUPnPServiceIntrospectionClass
-                GUPnPServiceIntrospectionClass;
-
-/**
- * GUPnPServiceIntrospection:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPServiceIntrospection {
-        GObject parent;
-
-        GUPnPServiceIntrospectionPrivate *priv;
-};
-
-struct _GUPnPServiceIntrospectionClass {
-        GObjectClass parent_class;
-};
 
 const GList *
 gupnp_service_introspection_list_action_names
diff --git a/libgupnp/gupnp-service-proxy.c b/libgupnp/gupnp-service-proxy.c
index 65c6b85..9c262e5 100644
--- a/libgupnp/gupnp-service-proxy.c
+++ b/libgupnp/gupnp-service-proxy.c
@@ -44,10 +44,6 @@
 #include "http-headers.h"
 #include "gvalue-util.h"
 
-G_DEFINE_TYPE (GUPnPServiceProxy,
-               gupnp_service_proxy,
-               GUPNP_TYPE_SERVICE_INFO);
-
 struct _GUPnPServiceProxyPrivate {
         gboolean subscribed;
 
@@ -67,6 +63,11 @@ struct _GUPnPServiceProxyPrivate {
         GList *pending_notifies; /* Pending notifications to be sent (xmlDoc) */
         GSource *notify_idle_src; /* Idle handler src of notification emiter */
 };
+typedef struct _GUPnPServiceProxyPrivate GUPnPServiceProxyPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPServiceProxy,
+                            gupnp_service_proxy,
+                            GUPNP_TYPE_SERVICE_INFO);
 
 enum {
         PROP_0,
@@ -129,6 +130,18 @@ gupnp_service_proxy_action_ref (GUPnPServiceProxyAction *action);
 static void
 gupnp_service_proxy_action_unref (GUPnPServiceProxyAction *action);
 
+static void
+gupnp_service_proxy_remove_action (GUPnPServiceProxy       *proxy,
+                                   GUPnPServiceProxyAction *action)
+{
+        GUPnPServiceProxyPrivate *priv;
+
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+
+        priv->pending_actions = g_list_remove (priv->pending_actions,
+                                               action);
+}
+
 static GUPnPServiceProxyAction *
 gupnp_service_proxy_action_ref (GUPnPServiceProxyAction *action)
 {
@@ -152,8 +165,7 @@ gupnp_service_proxy_action_unref (GUPnPServiceProxyAction *action)
                 if (action->proxy != NULL) {
                         g_object_remove_weak_pointer (G_OBJECT (action->proxy),
                                                       (gpointer *)&(action->proxy));
-                        action->proxy->priv->pending_actions =
-                                g_list_remove (action->proxy->priv->pending_actions, action);
+                        gupnp_service_proxy_remove_action (action->proxy, action);
                 }
 
                 if (action->msg != NULL)
@@ -216,17 +228,15 @@ static void
 gupnp_service_proxy_init (GUPnPServiceProxy *proxy)
 {
         static int proxy_counter = 0;
-
-        proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy,
-                                                   GUPNP_TYPE_SERVICE_PROXY,
-                                                   GUPnPServiceProxyPrivate);
+        GUPnPServiceProxyPrivate *priv;
 
         /* Generate unique path */
-        proxy->priv->path = g_strdup_printf ("/ServiceProxy%d", proxy_counter);
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+        priv->path = g_strdup_printf ("/ServiceProxy%d", proxy_counter);
         proxy_counter++;
 
         /* Set up notify hash */
-        proxy->priv->notify_hash =
+        priv->notify_hash =
                 g_hash_table_new_full (g_str_hash,
                                        g_str_equal,
                                        g_free,
@@ -261,13 +271,14 @@ gupnp_service_proxy_get_property (GObject    *object,
                                   GParamSpec *pspec)
 {
         GUPnPServiceProxy *proxy;
+        GUPnPServiceProxyPrivate *priv;
 
         proxy = GUPNP_SERVICE_PROXY (object);
+        priv = gupnp_service_proxy_get_instance_private (proxy);
 
         switch (property_id) {
         case PROP_SUBSCRIBED:
-                g_value_set_boolean (value,
-                                     proxy->priv->subscribed);
+                g_value_set_boolean (value, priv->subscribed);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -279,17 +290,19 @@ static void
 gupnp_service_proxy_dispose (GObject *object)
 {
         GUPnPServiceProxy *proxy;
+        GUPnPServiceProxyPrivate *priv;
         GObjectClass *object_class;
         GUPnPContext *context;
         SoupSession *session;
 
         proxy = GUPNP_SERVICE_PROXY (object);
+        priv = gupnp_service_proxy_get_instance_private (proxy);
 
         /* Unsubscribe */
-        if (proxy->priv->subscribed) {
+        if (priv->subscribed) {
                 unsubscribe (proxy);
 
-                proxy->priv->subscribed = FALSE;
+                priv->subscribed = FALSE;
         }
 
         context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (proxy));
@@ -299,17 +312,17 @@ gupnp_service_proxy_dispose (GObject *object)
             SoupServer *server;
 
             server = gupnp_context_get_server (context);
-            soup_server_remove_handler (server, proxy->priv->path);
+            soup_server_remove_handler (server, priv->path);
         }
 
         /* Cancel pending actions */
-        while (proxy->priv->pending_actions) {
+        while (priv->pending_actions) {
                 GUPnPServiceProxyAction *action;
 
-                action = proxy->priv->pending_actions->data;
-                proxy->priv->pending_actions =
-                        g_list_delete_link (proxy->priv->pending_actions,
-                                            proxy->priv->pending_actions);
+                action = priv->pending_actions->data;
+                priv->pending_actions =
+                        g_list_delete_link (priv->pending_actions,
+                                            priv->pending_actions);
 
                 gupnp_service_proxy_cancel_action (proxy, action);
         }
@@ -320,29 +333,29 @@ gupnp_service_proxy_dispose (GObject *object)
         else
                 session = NULL; /* Not the first time dispose is called. */
 
-        while (proxy->priv->pending_messages) {
+        while (priv->pending_messages) {
                 SoupMessage *msg;
 
-                msg = proxy->priv->pending_messages->data;
+                msg = priv->pending_messages->data;
 
                 soup_session_cancel_message (session,
                                              msg,
                                              SOUP_STATUS_CANCELLED);
 
-                proxy->priv->pending_messages =
-                        g_list_delete_link (proxy->priv->pending_messages,
-                                            proxy->priv->pending_messages);
+                priv->pending_messages =
+                        g_list_delete_link (priv->pending_messages,
+                                            priv->pending_messages);
         }
 
         /* Cancel pending notifications */
-        if (proxy->priv->notify_idle_src) {
-                g_source_destroy (proxy->priv->notify_idle_src);
-                proxy->priv->notify_idle_src = NULL;
+        if (priv->notify_idle_src) {
+                g_source_destroy (priv->notify_idle_src);
+                priv->notify_idle_src = NULL;
         }
 
-        g_list_free_full (proxy->priv->pending_notifies,
+        g_list_free_full (priv->pending_notifies,
                           (GDestroyNotify) emit_notify_data_free);
-        proxy->priv->pending_notifies = NULL;
+        priv->pending_notifies = NULL;
 
         /* Call super */
         object_class = G_OBJECT_CLASS (gupnp_service_proxy_parent_class);
@@ -353,13 +366,15 @@ static void
 gupnp_service_proxy_finalize (GObject *object)
 {
         GUPnPServiceProxy *proxy;
+        GUPnPServiceProxyPrivate *priv;
         GObjectClass *object_class;
 
         proxy = GUPNP_SERVICE_PROXY (object);
+        priv = gupnp_service_proxy_get_instance_private (proxy);
 
-        g_free (proxy->priv->path);
+        g_free (priv->path);
 
-        g_hash_table_destroy (proxy->priv->notify_hash);
+        g_hash_table_destroy (priv->notify_hash);
 
         /* Call super */
         object_class = G_OBJECT_CLASS (gupnp_service_proxy_parent_class);
@@ -378,8 +393,6 @@ gupnp_service_proxy_class_init (GUPnPServiceProxyClass *klass)
         object_class->dispose      = gupnp_service_proxy_dispose;
         object_class->finalize     = gupnp_service_proxy_finalize;
 
-        g_type_class_add_private (klass, sizeof (GUPnPServiceProxyPrivate));
-
         /**
          * GUPnPServiceProxy:subscribed:
          *
@@ -791,9 +804,12 @@ begin_action_msg (GUPnPServiceProxy              *proxy,
                   gpointer                        user_data)
 {
         GUPnPServiceProxyAction *ret;
+        GUPnPServiceProxyPrivate *priv;
         char *control_url, *full_action;
         const char *service_type;
 
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+
         /* Create action structure */
         ret = g_slice_new (GUPnPServiceProxyAction);
         ret->ref_count = 1;
@@ -808,8 +824,7 @@ begin_action_msg (GUPnPServiceProxy              *proxy,
 
         ret->error = NULL;
 
-        proxy->priv->pending_actions =
-                g_list_prepend (proxy->priv->pending_actions, ret);
+        priv->pending_actions = g_list_prepend (priv->pending_actions, ret);
 
         /* Make sure we have a service type */
         service_type = gupnp_service_info_get_service_type
@@ -1556,14 +1571,17 @@ gupnp_service_proxy_add_notify_full (GUPnPServiceProxy              *proxy,
 {
         NotifyData *data;
         CallbackData *callback_data;
+        GUPnPServiceProxyPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_SERVICE_PROXY (proxy), FALSE);
         g_return_val_if_fail (variable, FALSE);
         g_return_val_if_fail (type, FALSE);
         g_return_val_if_fail (callback, FALSE);
 
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+
         /* See if we already have notifications set up for this variable */
-        data = g_hash_table_lookup (proxy->priv->notify_hash, variable);
+        data = g_hash_table_lookup (priv->notify_hash, variable);
         if (data == NULL) {
                 /* No, create one */
                 data = g_slice_new (NotifyData);
@@ -1572,7 +1590,7 @@ gupnp_service_proxy_add_notify_full (GUPnPServiceProxy              *proxy,
                 data->callbacks  = NULL;
                 data->next_emit   = NULL;
 
-                g_hash_table_insert (proxy->priv->notify_hash,
+                g_hash_table_insert (priv->notify_hash,
                                      g_strdup (variable),
                                      data);
         } else {
@@ -1659,13 +1677,16 @@ gupnp_service_proxy_remove_notify (GUPnPServiceProxy              *proxy,
         NotifyData *data;
         gboolean found;
         GList *l;
+        GUPnPServiceProxyPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_SERVICE_PROXY (proxy), FALSE);
         g_return_val_if_fail (variable, FALSE);
         g_return_val_if_fail (callback, FALSE);
 
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+
         /* Look up NotifyData for variable */
-        data = g_hash_table_lookup (proxy->priv->notify_hash, variable);
+        data = g_hash_table_lookup (priv->notify_hash, variable);
         if (data == NULL) {
                 g_warning ("No notifications found for variable %s",
                            variable);
@@ -1694,7 +1715,7 @@ gupnp_service_proxy_remove_notify (GUPnPServiceProxy              *proxy,
                                 g_list_delete_link (data->callbacks, l);
                         if (data->callbacks == NULL) {
                                 /* No callbacks left: Remove from hash */
-                                g_hash_table_remove (proxy->priv->notify_hash,
+                                g_hash_table_remove (priv->notify_hash,
                                                      variable);
                         }
 
@@ -1742,8 +1763,11 @@ emit_notification (GUPnPServiceProxy *proxy,
         NotifyData *data;
         GValue value = {0, };
         GList *l;
+        GUPnPServiceProxyPrivate *priv;
 
-        data = g_hash_table_lookup (proxy->priv->notify_hash, var_node->name);
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+
+        data = g_hash_table_lookup (priv->notify_hash, var_node->name);
         if (data == NULL)
                 return;
 
@@ -1780,6 +1804,7 @@ emit_notifications_for_doc (GUPnPServiceProxy *proxy,
 {
         NotifyData *data = NULL;
         xmlNode *node;
+        GUPnPServiceProxyPrivate *priv;
 
         node = xmlDocGetRootElement (doc);
 
@@ -1800,7 +1825,8 @@ emit_notifications_for_doc (GUPnPServiceProxy *proxy,
                 }
         }
 
-        data = g_hash_table_lookup (proxy->priv->notify_hash, "*");
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+        data = g_hash_table_lookup (priv->notify_hash, "*");
         if (data != NULL) {
                 GValue value = {0, };
                 GList *it = NULL;
@@ -1826,25 +1852,27 @@ static gboolean
 emit_notifications (gpointer user_data)
 {
         GUPnPServiceProxy *proxy = user_data;
+        GUPnPServiceProxyPrivate *priv;
         GList *pending_notify;
         gboolean resubscribe = FALSE;
 
         g_assert (user_data);
 
-        if (proxy->priv->sid == NULL)
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+        if (priv->sid == NULL)
                 /* No SID */
-                if (G_LIKELY (proxy->priv->subscribed))
+                if (G_LIKELY (priv->subscribed))
                         /* subscription in progress, delay emision! */
                         return TRUE;
 
-        for (pending_notify = proxy->priv->pending_notifies;
+        for (pending_notify = priv->pending_notifies;
              pending_notify != NULL;
              pending_notify = pending_notify->next) {
                 EmitNotifyData *emit_notify_data;
 
                 emit_notify_data = pending_notify->data;
 
-                if (emit_notify_data->seq > proxy->priv->seq) {
+                if (emit_notify_data->seq > priv->seq) {
                         /* Error procedure on missed event according to
                          * UDA 1.0, section 4.2, §5:
                          * Re-subscribe to get a new SID and SEQ */
@@ -1857,25 +1885,25 @@ emit_notifications (gpointer user_data)
                 /* UDA 1.0, section 4.2, §3: To prevent overflow, SEQ is set to
                  * 1, NOT 0, when encountering G_MAXUINT32. SEQ == 0 always
                  * indicates the initial event message. */
-                if (proxy->priv->seq < G_MAXUINT32)
-                        proxy->priv->seq++;
+                if (priv->seq < G_MAXUINT32)
+                        priv->seq++;
                 else
-                        proxy->priv->seq = 1;
+                        priv->seq = 1;
 
-                if (G_LIKELY (proxy->priv->sid != NULL &&
+                if (G_LIKELY (priv->sid != NULL &&
                               strcmp (emit_notify_data->sid,
-                                      proxy->priv->sid) == 0))
+                                      priv->sid) == 0))
                         /* Our SID, entertain! */
                         emit_notifications_for_doc (proxy,
                                                     emit_notify_data->doc);
         }
 
         /* Cleanup */
-        g_list_free_full (proxy->priv->pending_notifies,
+        g_list_free_full (priv->pending_notifies,
                           (GDestroyNotify) emit_notify_data_free);
-        proxy->priv->pending_notifies = NULL;
+        priv->pending_notifies = NULL;
 
-        proxy->priv->notify_idle_src = NULL;
+        priv->notify_idle_src = NULL;
 
         if (resubscribe) {
                 unsubscribe (proxy);
@@ -1898,6 +1926,7 @@ server_handler (G_GNUC_UNUSED SoupServer        *soup_server,
                 gpointer                         user_data)
 {
         GUPnPServiceProxy *proxy;
+        GUPnPServiceProxyPrivate *priv;
         const char *hdr, *nt, *nts;
         guint32 seq;
         guint64 seq_parsed;
@@ -1991,17 +2020,18 @@ server_handler (G_GNUC_UNUSED SoupServer        *soup_server,
          */
         emit_notify_data = emit_notify_data_new (hdr, seq, doc);
 
-        proxy->priv->pending_notifies =
-                g_list_append (proxy->priv->pending_notifies, emit_notify_data);
-        if (!proxy->priv->notify_idle_src) {
-                proxy->priv->notify_idle_src = g_idle_source_new();
-                g_source_set_callback (proxy->priv->notify_idle_src,
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+        priv->pending_notifies =
+                g_list_append (priv->pending_notifies, emit_notify_data);
+        if (!priv->notify_idle_src) {
+                priv->notify_idle_src = g_idle_source_new();
+                g_source_set_callback (priv->notify_idle_src,
                                        emit_notifications,
                                        proxy, NULL);
-                g_source_attach (proxy->priv->notify_idle_src,
+                g_source_attach (priv->notify_idle_src,
                                  g_main_context_get_thread_default ());
 
-                g_source_unref (proxy->priv->notify_idle_src);
+                g_source_unref (priv->notify_idle_src);
         }
 
         /* Everything went OK */
@@ -2031,17 +2061,19 @@ static gboolean
 subscription_expire (gpointer user_data)
 {
         GUPnPServiceProxy *proxy;
+        GUPnPServiceProxyPrivate *priv;
         GUPnPContext *context;
         SoupMessage *msg;
         SoupSession *session;
         char *sub_url, *timeout;
 
         proxy = GUPNP_SERVICE_PROXY (user_data);
+        priv = gupnp_service_proxy_get_instance_private (proxy);
 
         /* Reset timeout ID */
-        proxy->priv->subscription_timeout_src = NULL;
+        priv->subscription_timeout_src = NULL;
 
-        g_return_val_if_fail (proxy->priv->sid != NULL, FALSE);
+        g_return_val_if_fail (priv->sid != NULL, FALSE);
 
         /* Send renewal message */
         context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (proxy));
@@ -2059,7 +2091,7 @@ subscription_expire (gpointer user_data)
         /* Add headers */
         soup_message_headers_append (msg->request_headers,
                                     "SID",
-                                    proxy->priv->sid);
+                                    priv->sid);
 
         timeout = make_timeout_header (context);
         soup_message_headers_append (msg->request_headers,
@@ -2068,8 +2100,8 @@ subscription_expire (gpointer user_data)
         g_free (timeout);
 
         /* And send it off */
-        proxy->priv->pending_messages =
-                g_list_prepend (proxy->priv->pending_messages, msg);
+        priv->pending_messages =
+                g_list_prepend (priv->pending_messages, msg);
 
         session = gupnp_context_get_session (context);
 
@@ -2091,28 +2123,29 @@ subscribe_got_response (G_GNUC_UNUSED SoupSession *session,
                         GUPnPServiceProxy         *proxy)
 {
         GError *error;
+        GUPnPServiceProxyPrivate *priv;
 
         /* Cancelled? */
         if (msg->status_code == SOUP_STATUS_CANCELLED)
                 return;
 
         /* Remove from pending messages list */
-        proxy->priv->pending_messages =
-                g_list_remove (proxy->priv->pending_messages, msg);
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+        priv->pending_messages = g_list_remove (priv->pending_messages, msg);
 
         /* Remove subscription timeout */
-        if (proxy->priv->subscription_timeout_src) {
-                g_source_destroy (proxy->priv->subscription_timeout_src);
-                proxy->priv->subscription_timeout_src = NULL;
+        if (priv->subscription_timeout_src) {
+                g_source_destroy (priv->subscription_timeout_src);
+                priv->subscription_timeout_src = NULL;
         }
 
         /* Check whether the subscription is still wanted */
-        if (!proxy->priv->subscribed)
+        if (!priv->subscribed)
                 return;
 
         /* Reset SID */
-        g_free (proxy->priv->sid);
-        proxy->priv->sid = NULL;
+        g_free (priv->sid);
+        priv->sid = NULL;
 
         /* Check message status */
         if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
@@ -2132,7 +2165,7 @@ subscribe_got_response (G_GNUC_UNUSED SoupSession *session,
                         goto hdr_err;
                 }
 
-                proxy->priv->sid = g_strdup (hdr);
+                priv->sid = g_strdup (hdr);
 
                 /* Figure out when the subscription times out */
                 hdr = soup_message_headers_get_one (msg->response_headers,
@@ -2160,16 +2193,16 @@ subscribe_got_response (G_GNUC_UNUSED SoupSession *session,
                         timeout = g_random_int_range (1, timeout / 2);
 
                         /* Add actual timeout */
-                        proxy->priv->subscription_timeout_src =
+                        priv->subscription_timeout_src =
                                 g_timeout_source_new_seconds (timeout);
                         g_source_set_callback
-                                (proxy->priv->subscription_timeout_src,
+                                (priv->subscription_timeout_src,
                                  subscription_expire,
                                  proxy, NULL);
-                        g_source_attach (proxy->priv->subscription_timeout_src,
+                        g_source_attach (priv->subscription_timeout_src,
                                          g_main_context_get_thread_default ());
 
-                        g_source_unref (proxy->priv->subscription_timeout_src);
+                        g_source_unref (priv->subscription_timeout_src);
                 }
         } else {
                 GUPnPContext *context;
@@ -2187,9 +2220,9 @@ hdr_err:
                                         (GUPNP_SERVICE_INFO (proxy));
 
                 server = gupnp_context_get_server (context);
-                soup_server_remove_handler (server, proxy->priv->path);
+                soup_server_remove_handler (server, priv->path);
 
-                proxy->priv->subscribed = FALSE;
+                priv->subscribed = FALSE;
 
                 g_object_notify (G_OBJECT (proxy), "subscribed");
 
@@ -2210,6 +2243,7 @@ static void
 subscribe (GUPnPServiceProxy *proxy)
 {
         GUPnPContext *context;
+        GUPnPServiceProxyPrivate *priv;
         SoupMessage *msg;
         SoupSession *session;
         SoupServer *server;
@@ -2218,9 +2252,10 @@ subscribe (GUPnPServiceProxy *proxy)
         char *sub_url, *delivery_url, *timeout;
 
         /* Remove subscription timeout */
-        if (proxy->priv->subscription_timeout_src) {
-                g_source_destroy (proxy->priv->subscription_timeout_src);
-                proxy->priv->subscription_timeout_src = NULL;
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+        if (priv->subscription_timeout_src) {
+                g_source_destroy (priv->subscription_timeout_src);
+                priv->subscription_timeout_src = NULL;
         }
 
        context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (proxy));
@@ -2240,7 +2275,7 @@ subscribe (GUPnPServiceProxy *proxy)
                 GError *error;
 
                 /* Subscription failed. */
-                proxy->priv->subscribed = FALSE;
+                priv->subscribed = FALSE;
 
                 g_object_notify (G_OBJECT (proxy), "subscribed");
 
@@ -2261,7 +2296,7 @@ subscribe (GUPnPServiceProxy *proxy)
 
         /* Add headers */
         uri = _gupnp_context_get_server_uri (context);
-        soup_uri_set_path (uri, proxy->priv->path);
+        soup_uri_set_path (uri, priv->path);
         uri_string = soup_uri_to_string (uri, FALSE);
         soup_uri_free (uri);
         delivery_url = g_strdup_printf ("<%s>", uri_string);
@@ -2286,14 +2321,14 @@ subscribe (GUPnPServiceProxy *proxy)
         server = gupnp_context_get_server (context);
 
         soup_server_add_handler (server,
-                                 proxy->priv->path,
+                                 priv->path,
                                  server_handler,
                                  proxy,
                                  NULL);
 
         /* And send our subscription message off */
-        proxy->priv->pending_messages =
-                g_list_prepend (proxy->priv->pending_messages, msg);
+        priv->pending_messages =
+                g_list_prepend (priv->pending_messages, msg);
 
         session = gupnp_context_get_session (context);
 
@@ -2311,16 +2346,18 @@ static void
 unsubscribe (GUPnPServiceProxy *proxy)
 {
         GUPnPContext *context;
+        GUPnPServiceProxyPrivate *priv;
         SoupSession *session;
         SoupServer *server;
 
         context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (proxy));
+        priv = gupnp_service_proxy_get_instance_private (proxy);
 
         /* Remove server handler */
         server = gupnp_context_get_server (context);
-        soup_server_remove_handler (server, proxy->priv->path);
+        soup_server_remove_handler (server, priv->path);
 
-        if (proxy->priv->sid != NULL) {
+        if (priv->sid != NULL) {
                 SoupMessage *msg;
                 char *sub_url;
 
@@ -2336,7 +2373,7 @@ unsubscribe (GUPnPServiceProxy *proxy)
                         /* Add headers */
                         soup_message_headers_append (msg->request_headers,
                                                      "SID",
-                                                     proxy->priv->sid);
+                                                     priv->sid);
 
                         /* And queue it */
                         session = gupnp_context_get_session (context);
@@ -2345,17 +2382,17 @@ unsubscribe (GUPnPServiceProxy *proxy)
                 }
 
                 /* Reset SID */
-                g_free (proxy->priv->sid);
-                proxy->priv->sid = NULL;
+                g_free (priv->sid);
+                priv->sid = NULL;
 
                 /* Reset sequence number */
-                proxy->priv->seq = 0;
+                priv->seq = 0;
         }
 
         /* Remove subscription timeout */
-        if (proxy->priv->subscription_timeout_src) {
-                g_source_destroy (proxy->priv->subscription_timeout_src);
-                proxy->priv->subscription_timeout_src = NULL;
+        if (priv->subscription_timeout_src) {
+                g_source_destroy (priv->subscription_timeout_src);
+                priv->subscription_timeout_src = NULL;
         }
 }
 
@@ -2375,12 +2412,15 @@ void
 gupnp_service_proxy_set_subscribed (GUPnPServiceProxy *proxy,
                                     gboolean           subscribed)
 {
+        GUPnPServiceProxyPrivate *priv;
+
         g_return_if_fail (GUPNP_IS_SERVICE_PROXY (proxy));
 
-        if (proxy->priv->subscribed == subscribed)
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+        if (priv->subscribed == subscribed)
                 return;
 
-        proxy->priv->subscribed = subscribed;
+        priv->subscribed = subscribed;
 
         if (subscribed)
                 subscribe (proxy);
@@ -2401,7 +2441,11 @@ gupnp_service_proxy_set_subscribed (GUPnPServiceProxy *proxy,
 gboolean
 gupnp_service_proxy_get_subscribed (GUPnPServiceProxy *proxy)
 {
+        GUPnPServiceProxyPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_SERVICE_PROXY (proxy), FALSE);
 
-        return proxy->priv->subscribed;
+        priv = gupnp_service_proxy_get_instance_private (proxy);
+
+        return priv->subscribed;
 }
diff --git a/libgupnp/gupnp-service-proxy.h b/libgupnp/gupnp-service-proxy.h
index fd04ed6..d61ac69 100644
--- a/libgupnp/gupnp-service-proxy.h
+++ b/libgupnp/gupnp-service-proxy.h
@@ -27,48 +27,17 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_service_proxy_get_type (void) G_GNUC_CONST;
-
 GType
 gupnp_service_proxy_action_get_type (void) G_GNUC_CONST;
 
 #define GUPNP_TYPE_SERVICE_PROXY \
                 (gupnp_service_proxy_get_type ())
-#define GUPNP_SERVICE_PROXY(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_SERVICE_PROXY, \
-                 GUPnPServiceProxy))
-#define GUPNP_SERVICE_PROXY_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_SERVICE_PROXY, \
-                 GUPnPServiceProxyClass))
-#define GUPNP_IS_SERVICE_PROXY(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_SERVICE_PROXY))
-#define GUPNP_IS_SERVICE_PROXY_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_SERVICE_PROXY))
-#define GUPNP_SERVICE_PROXY_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_SERVICE_PROXY, \
-                 GUPnPServiceProxyClass))
-
-typedef struct _GUPnPServiceProxyPrivate GUPnPServiceProxyPrivate;
-typedef struct _GUPnPServiceProxy GUPnPServiceProxy;
-typedef struct _GUPnPServiceProxyClass GUPnPServiceProxyClass;
 
-/**
- * GUPnPServiceProxy:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPServiceProxy {
-        GUPnPServiceInfo parent;
-
-        GUPnPServiceProxyPrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPServiceProxy,
+                          gupnp_service_proxy,
+                          GUPNP,
+                          SERVICE_PROXY,
+                          GUPnPServiceInfo)
 
 struct _GUPnPServiceProxyClass {
         GUPnPServiceInfoClass parent_class;
diff --git a/libgupnp/gupnp-service.c b/libgupnp/gupnp-service.c
index 18ecc39..70e1a48 100644
--- a/libgupnp/gupnp-service.c
+++ b/libgupnp/gupnp-service.c
@@ -47,9 +47,6 @@
 
 #define SUBSCRIPTION_TIMEOUT 300 /* DLNA (7.2.22.1) enforced */
 
-G_DEFINE_TYPE (GUPnPService,
-               gupnp_service,
-               GUPNP_TYPE_SERVICE_INFO);
 
 struct _GUPnPServicePrivate {
         GUPnPRootDevice           *root_device;
@@ -70,6 +67,11 @@ struct _GUPnPServicePrivate {
 
         GList                     *pending_autoconnect;
 };
+typedef struct _GUPnPServicePrivate GUPnPServicePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPService,
+                            gupnp_service,
+                            GUPNP_TYPE_SERVICE_INFO);
 
 enum {
         PROP_0,
@@ -120,31 +122,45 @@ subscription_data_can_delete (SubscriptionData *data) {
     return data->initial_state_sent && data->to_delete;
 }
 
+
 static void
 send_initial_state (SubscriptionData *data);
 
+static void
+gupnp_service_remove_subscription (GUPnPService *service,
+                                   const char *sid)
+{
+        GUPnPServicePrivate *priv;
+
+        priv = gupnp_service_get_instance_private (service);
+
+        g_hash_table_remove (priv->subscriptions, sid);
+}
+
 static SoupSession *
 gupnp_service_get_session (GUPnPService *service)
 {
-        if (! service->priv->session) {
+        GUPnPServicePrivate *priv;
+
+        priv = gupnp_service_get_instance_private (service);
+        if (!priv->session) {
                 /* Create a dedicated session for this service to
                  * ensure that notifications are sent in the proper
                  * order. The session from GUPnPContext may use
                  * multiple connections.
                  */
-                service->priv->session = soup_session_new_with_options (SOUP_SESSION_MAX_CONNS_PER_HOST, 1,
+                priv->session = soup_session_new_with_options (SOUP_SESSION_MAX_CONNS_PER_HOST, 1,
                                                                         NULL);
 
                 if (g_getenv ("GUPNP_DEBUG")) {
                         SoupLogger *logger;
                         logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1);
-                        soup_session_add_feature (
-                                        service->priv->session,
-                                        SOUP_SESSION_FEATURE (logger));
+                        soup_session_add_feature (priv->session,
+                                                  SOUP_SESSION_FEATURE (logger));
                 }
         }
 
-        return service->priv->session;
+        return priv->session;
 }
 
 static void
@@ -809,17 +825,17 @@ gupnp_service_action_get_message (GUPnPServiceAction *action)
 static void
 gupnp_service_init (GUPnPService *service)
 {
-        service->priv = G_TYPE_INSTANCE_GET_PRIVATE (service,
-                                                     GUPNP_TYPE_SERVICE,
-                                                     GUPnPServicePrivate);
+        GUPnPServicePrivate *priv;
 
-        service->priv->subscriptions =
+        priv = gupnp_service_get_instance_private (service);
+
+        priv->subscriptions =
                 g_hash_table_new_full (g_str_hash,
                                        g_str_equal,
                                        NULL,
                                        (GDestroyNotify) subscription_data_free);
 
-        service->priv->notify_queue = g_queue_new ();
+        priv->notify_queue = g_queue_new ();
 }
 
 /* Generate a new action response node for @action_name */
@@ -1120,7 +1136,7 @@ generate_sid (void)
 
 
         uuid = guul_get_uuid ();
-        ret = g_strdup_printf ("uuid:%s", uuid);
+        ret = g_strconcat ("uuid:", uuid, NULL);
         g_free (uuid);
 
         return ret;
@@ -1134,7 +1150,7 @@ subscription_timeout (gpointer user_data)
 
         data = user_data;
 
-        g_hash_table_remove (data->service->priv->subscriptions, data->sid);
+        gupnp_service_remove_subscription (data->service, data->sid);
 
         return FALSE;
 }
@@ -1145,11 +1161,14 @@ send_initial_state (SubscriptionData *data)
         GQueue *queue;
         char *mem;
         GList *l;
+        GUPnPServicePrivate *priv;
+
+        priv = gupnp_service_get_instance_private (data->service);
 
         /* Send initial event message */
         queue = g_queue_new ();
 
-        for (l = data->service->priv->state_variables; l; l = l->next) {
+        for (l = priv->state_variables; l; l = l->next) {
                 NotifyData *ndata;
 
                 ndata = g_slice_new0 (NotifyData);
@@ -1189,6 +1208,9 @@ subscribe (GUPnPService *service,
 {
         SubscriptionData *data;
         char *start, *end, *uri;
+        GUPnPServicePrivate *priv;
+
+        priv = gupnp_service_get_instance_private (service);
 
         data = g_slice_new0 (SubscriptionData);
 
@@ -1236,7 +1258,7 @@ subscribe (GUPnPService *service,
         g_source_unref (data->timeout_src);
 
         /* Add to hash */
-        g_hash_table_insert (service->priv->subscriptions,
+        g_hash_table_insert (priv->subscriptions,
                              data->sid,
                              data);
 
@@ -1253,8 +1275,11 @@ resubscribe (GUPnPService *service,
              const char   *sid)
 {
         SubscriptionData *data;
+        GUPnPServicePrivate *priv;
 
-        data = g_hash_table_lookup (service->priv->subscriptions, sid);
+        priv = gupnp_service_get_instance_private (service);
+
+        data = g_hash_table_lookup (priv->subscriptions, sid);
         if (!data) {
                 soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
 
@@ -1289,11 +1314,14 @@ unsubscribe (GUPnPService *service,
              const char   *sid)
 {
         SubscriptionData *data;
+        GUPnPServicePrivate *priv;
+
+        priv = gupnp_service_get_instance_private (service);
 
-        data = g_hash_table_lookup (service->priv->subscriptions, sid);
+        data = g_hash_table_lookup (priv->subscriptions, sid);
         if (data) {
                 if (data->initial_state_sent)
-                        g_hash_table_remove (service->priv->subscriptions,
+                        g_hash_table_remove (priv->subscriptions,
                                              sid);
                 else
                         data->to_delete = TRUE;
@@ -1386,27 +1414,30 @@ got_introspection (GUPnPServiceInfo          *info,
         const GList *state_variables, *l;
         GHashTableIter iter;
         gpointer data;
+        GUPnPServicePrivate *priv;
+
+        priv = gupnp_service_get_instance_private (service);
 
         if (introspection) {
                 /* Handle pending auto-connects */
-                service->priv->introspection  = g_object_ref (introspection);
+                priv->introspection  = g_object_ref (introspection);
 
                 /* _autoconnect() just calls prepend() so we reverse the list
                  * here.
                  */
-                service->priv->pending_autoconnect =
-                            g_list_reverse (service->priv->pending_autoconnect);
+                priv->pending_autoconnect =
+                            g_list_reverse (priv->pending_autoconnect);
 
                 /* Re-call _autoconnect(). This will not fill
                  * pending_autoconnect because we set the introspection member
                  * variable before */
-                for (l = service->priv->pending_autoconnect; l; l = l->next)
+                for (l = priv->pending_autoconnect; l; l = l->next)
                         gupnp_service_signals_autoconnect (service,
                                                            l->data,
                                                            NULL);
 
-                g_list_free (service->priv->pending_autoconnect);
-                service->priv->pending_autoconnect = NULL;
+                g_list_free (priv->pending_autoconnect);
+                priv->pending_autoconnect = NULL;
 
                 state_variables =
                         gupnp_service_introspection_list_state_variables
@@ -1420,8 +1451,8 @@ got_introspection (GUPnPServiceInfo          *info,
                         if (!variable->send_events)
                                 continue;
 
-                        service->priv->state_variables =
-                                g_list_prepend (service->priv->state_variables,
+                        priv->state_variables =
+                                g_list_prepend (priv->state_variables,
                                                 g_strdup (variable->name));
                 }
 
@@ -1431,7 +1462,7 @@ got_introspection (GUPnPServiceInfo          *info,
                            "The initial event message will not be sent.",
                            error ? error->message : "No error");
 
-        g_hash_table_iter_init (&iter, service->priv->subscriptions);
+        g_hash_table_iter_init (&iter, priv->subscriptions);
 
         while (g_hash_table_iter_next (&iter, NULL, &data)) {
                 send_initial_state ((SubscriptionData *) data);
@@ -1517,12 +1548,14 @@ notify_available_cb (GObject                  *object,
                      gpointer                  user_data)
 {
         GUPnPService *service;
+        GUPnPServicePrivate *priv;
 
         service = GUPNP_SERVICE (user_data);
+        priv = gupnp_service_get_instance_private (service);
 
         if (!gupnp_root_device_get_available (GUPNP_ROOT_DEVICE (object))) {
                 /* Root device now unavailable: Purge subscriptions */
-                g_hash_table_remove_all (service->priv->subscriptions);
+                g_hash_table_remove_all (priv->subscriptions);
         }
 }
 
@@ -1533,22 +1566,23 @@ gupnp_service_set_property (GObject      *object,
                             GParamSpec   *pspec)
 {
         GUPnPService *service;
+        GUPnPServicePrivate *priv;
 
         service = GUPNP_SERVICE (object);
+        priv = gupnp_service_get_instance_private (service);
 
         switch (property_id) {
         case PROP_ROOT_DEVICE: {
                 GUPnPRootDevice **dev;
 
-                service->priv->root_device = g_value_get_object (value);
-                dev = &(service->priv->root_device);
+                priv->root_device = g_value_get_object (value);
+                dev = &(priv->root_device);
 
-                g_object_add_weak_pointer
-                        (G_OBJECT (service->priv->root_device),
-                         (gpointer *) dev);
+                g_object_add_weak_pointer (G_OBJECT (priv->root_device),
+                                           (gpointer *) dev);
 
-                service->priv->notify_available_id =
-                        g_signal_connect_object (service->priv->root_device,
+                priv->notify_available_id =
+                        g_signal_connect_object (priv->root_device,
                                                  "notify::available",
                                                  G_CALLBACK
                                                         (notify_available_cb),
@@ -1570,12 +1604,14 @@ gupnp_service_get_property (GObject    *object,
                             GParamSpec *pspec)
 {
         GUPnPService *service;
+        GUPnPServicePrivate *priv;
 
         service = GUPNP_SERVICE (object);
+        priv = gupnp_service_get_instance_private (service);
 
         switch (property_id) {
         case PROP_ROOT_DEVICE:
-                g_value_set_object (value, service->priv->root_device);
+                g_value_set_object (value, priv->root_device);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -1587,6 +1623,7 @@ static void
 gupnp_service_dispose (GObject *object)
 {
         GUPnPService *service;
+        GUPnPServicePrivate *priv;
         GObjectClass *object_class;
         GUPnPServiceInfo *info;
         GUPnPContext *context;
@@ -1594,6 +1631,7 @@ gupnp_service_dispose (GObject *object)
         char *path;
 
         service = GUPNP_SERVICE (object);
+        priv = gupnp_service_get_instance_private (service);
 
         /* Get server */
         info = GUPNP_SERVICE_INFO (service);
@@ -1613,26 +1651,25 @@ gupnp_service_dispose (GObject *object)
         g_free (path);
         g_free (url);
 
-        if (service->priv->root_device) {
-                GUPnPRootDevice **dev = &(service->priv->root_device);
+        if (priv->root_device) {
+                GUPnPRootDevice **dev = &(priv->root_device);
 
                 if (g_signal_handler_is_connected
-                        (service->priv->root_device,
-                         service->priv->notify_available_id)) {
+                        (priv->root_device,
+                         priv->notify_available_id)) {
                         g_signal_handler_disconnect
-                                (service->priv->root_device,
-                                 service->priv->notify_available_id);
+                                (priv->root_device,
+                                 priv->notify_available_id);
                 }
 
-                g_object_remove_weak_pointer
-                        (G_OBJECT (service->priv->root_device),
-                         (gpointer *) dev);
+                g_object_remove_weak_pointer (G_OBJECT (priv->root_device),
+                                              (gpointer *) dev);
 
-                service->priv->root_device = NULL;
+                priv->root_device = NULL;
         }
 
         /* Cancel pending messages */
-        g_hash_table_remove_all (service->priv->subscriptions);
+        g_hash_table_remove_all (priv->subscriptions);
 
         /* Call super */
         object_class = G_OBJECT_CLASS (gupnp_service_parent_class);
@@ -1643,31 +1680,33 @@ static void
 gupnp_service_finalize (GObject *object)
 {
         GUPnPService *service;
+        GUPnPServicePrivate *priv;
         GObjectClass *object_class;
         NotifyData *data;
 
         service = GUPNP_SERVICE (object);
+        priv = gupnp_service_get_instance_private (service);
 
         /* Free subscription hash */
-        g_hash_table_destroy (service->priv->subscriptions);
+        g_hash_table_destroy (priv->subscriptions);
 
         /* Free state variable list */
-        g_list_free_full (service->priv->state_variables, g_free);
+        g_list_free_full (priv->state_variables, g_free);
 
         /* Free notify queue */
-        while ((data = g_queue_pop_head (service->priv->notify_queue)))
+        while ((data = g_queue_pop_head (priv->notify_queue)))
                 notify_data_free (data);
 
-        g_queue_free (service->priv->notify_queue);
+        g_queue_free (priv->notify_queue);
 
-        if (service->priv->session) {
-                g_object_unref (service->priv->session);
-                service->priv->session = NULL;
+        if (priv->session) {
+                g_object_unref (priv->session);
+                priv->session = NULL;
         }
 
-        if (service->priv->introspection) {
-                g_object_unref (service->priv->introspection);
-                service->priv->introspection = NULL;
+        if (priv->introspection) {
+                g_object_unref (priv->introspection);
+                priv->introspection = NULL;
         }
 
         /* Call super */
@@ -1688,8 +1727,6 @@ gupnp_service_class_init (GUPnPServiceClass *klass)
         object_class->dispose      = gupnp_service_dispose;
         object_class->finalize     = gupnp_service_finalize;
 
-        g_type_class_add_private (klass, sizeof (GUPnPServicePrivate));
-
         /**
          * GUPnPService:root-device:
          *
@@ -1869,8 +1906,7 @@ notify_got_response (G_GNUC_UNUSED SoupSession *session,
 
         } else if (msg->status_code == SOUP_STATUS_PRECONDITION_FAILED) {
                 /* Precondition failed: Cancel subscription */
-                g_hash_table_remove (data->service->priv->subscriptions,
-                                     data->sid);
+                gupnp_service_remove_subscription (data->service, data->sid);
 
         } else {
                 /* Other failure: Try next callback or signal failure. */
@@ -2022,12 +2058,15 @@ static void
 flush_notifications (GUPnPService *service)
 {
         char *mem;
+        GUPnPServicePrivate *priv;
+
+        priv = gupnp_service_get_instance_private (service);
 
         /* Create property set */
-        mem = create_property_set (service->priv->notify_queue);
+        mem = create_property_set (priv->notify_queue);
 
         /* And send it off */
-        g_hash_table_foreach (service->priv->subscriptions,
+        g_hash_table_foreach (priv->subscriptions,
                               notify_subscriber,
                               mem);
 
@@ -2049,11 +2088,14 @@ gupnp_service_notify_value (GUPnPService *service,
                             const GValue *value)
 {
         NotifyData *data;
+        GUPnPServicePrivate *priv;
 
         g_return_if_fail (GUPNP_IS_SERVICE (service));
         g_return_if_fail (variable != NULL);
         g_return_if_fail (G_IS_VALUE (value));
 
+        priv = gupnp_service_get_instance_private (service);
+
         /* Queue */
         data = g_slice_new0 (NotifyData);
 
@@ -2062,10 +2104,10 @@ gupnp_service_notify_value (GUPnPService *service,
         g_value_init (&data->value, G_VALUE_TYPE (value));
         g_value_copy (value, &data->value);
 
-        g_queue_push_tail (service->priv->notify_queue, data);
+        g_queue_push_tail (priv->notify_queue, data);
 
         /* And flush, if not frozen */
-        if (!service->priv->notify_frozen)
+        if (!priv->notify_frozen)
                 flush_notifications (service);
 }
 
@@ -2079,9 +2121,13 @@ gupnp_service_notify_value (GUPnPService *service,
 void
 gupnp_service_freeze_notify (GUPnPService *service)
 {
+        GUPnPServicePrivate *priv;
+
         g_return_if_fail (GUPNP_IS_SERVICE (service));
 
-        service->priv->notify_frozen = TRUE;
+        priv = gupnp_service_get_instance_private (service);
+
+        priv->notify_frozen = TRUE;
 }
 
 /**
@@ -2093,11 +2139,15 @@ gupnp_service_freeze_notify (GUPnPService *service)
 void
 gupnp_service_thaw_notify (GUPnPService *service)
 {
+        GUPnPServicePrivate *priv;
+
         g_return_if_fail (GUPNP_IS_SERVICE (service));
 
-        service->priv->notify_frozen = FALSE;
+        priv = gupnp_service_get_instance_private (service);
+
+        priv->notify_frozen = FALSE;
 
-        if (g_queue_get_length (service->priv->notify_queue) == 0)
+        if (g_queue_get_length (priv->notify_queue) == 0)
                 return; /* Empty notify queue */
 
         flush_notifications (service);
@@ -2261,16 +2311,19 @@ gupnp_service_signals_autoconnect (GUPnPService *service,
         GUPnPServiceIntrospection *introspection;
         const GList               *names;
         GModule                   *module;
+        GUPnPServicePrivate       *priv;
 
         g_return_if_fail (GUPNP_IS_SERVICE (service));
 
-        introspection = service->priv->introspection;
+        priv = gupnp_service_get_instance_private (service);
+
+        introspection = priv->introspection;
 
         if (!introspection) {
                 /* Initial introspection is not done yet, delay until we
                  * received that */
-                service->priv->pending_autoconnect =
-                    g_list_prepend (service->priv->pending_autoconnect,
+                priv->pending_autoconnect =
+                    g_list_prepend (priv->pending_autoconnect,
                                     user_data);
 
                 return;
diff --git a/libgupnp/gupnp-service.h b/libgupnp/gupnp-service.h
index be50af0..1b424d9 100644
--- a/libgupnp/gupnp-service.h
+++ b/libgupnp/gupnp-service.h
@@ -28,29 +28,14 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_service_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_SERVICE \
                 (gupnp_service_get_type ())
-#define GUPNP_SERVICE(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_SERVICE, \
-                 GUPnPService))
-#define GUPNP_SERVICE_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_SERVICE, \
-                 GUPnPServiceClass))
-#define GUPNP_IS_SERVICE(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_SERVICE))
-#define GUPNP_IS_SERVICE_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_SERVICE))
-#define GUPNP_SERVICE_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_SERVICE, \
-                 GUPnPServiceClass))
+
+G_DECLARE_DERIVABLE_TYPE (GUPnPService,
+                          gupnp_service,
+                          GUPNP,
+                          SERVICE,
+                          GUPnPServiceInfo)
 
 /**
  * GUPnPServiceAction:
@@ -64,22 +49,6 @@ gupnp_service_action_get_type (void) G_GNUC_CONST;
 
 #define GUPNP_TYPE_SERVICE_ACTION (gupnp_service_action_get_type ())
 
-typedef struct _GUPnPServicePrivate GUPnPServicePrivate;
-typedef struct _GUPnPService GUPnPService;
-typedef struct _GUPnPServiceClass GUPnPServiceClass;
-
-/**
- * GUPnPService:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPService {
-        GUPnPServiceInfo parent;
-
-        GUPnPServicePrivate *priv;
-};
-
 struct _GUPnPServiceClass {
         GUPnPServiceInfoClass parent_class;
 
diff --git a/libgupnp/gupnp-simple-context-manager.c b/libgupnp/gupnp-simple-context-manager.c
index 7efaf38..08c350a 100644
--- a/libgupnp/gupnp-simple-context-manager.c
+++ b/libgupnp/gupnp-simple-context-manager.c
@@ -36,15 +36,16 @@
 #include "gupnp-simple-context-manager.h"
 #include "gupnp-context.h"
 
-G_DEFINE_ABSTRACT_TYPE (GUPnPSimpleContextManager,
-                        gupnp_simple_context_manager,
-                        GUPNP_TYPE_CONTEXT_MANAGER);
-
 struct _GUPnPSimpleContextManagerPrivate {
         GList *contexts; /* List of GUPnPContext instances */
 
         GSource *idle_context_creation_src;
 };
+typedef struct _GUPnPSimpleContextManagerPrivate GUPnPSimpleContextManagerPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GUPnPSimpleContextManager,
+                                     gupnp_simple_context_manager,
+                                     GUPNP_TYPE_CONTEXT_MANAGER);
 
 static GList*
 gupnp_simple_context_manager_get_interfaces (GUPnPSimpleContextManager *manager)
@@ -60,10 +61,12 @@ create_and_signal_context (const char                *interface,
                            GUPnPSimpleContextManager *manager)
 {
         GUPnPContext *context;
+        GUPnPSimpleContextManagerPrivate *priv;
         guint port;
 
         GError *error;
 
+        priv = gupnp_simple_context_manager_get_instance_private (manager);
         g_object_get (manager,
                       "port", &port,
                       NULL);
@@ -92,7 +95,7 @@ create_and_signal_context (const char                *interface,
                                "context-available",
                                context);
 
-        manager->priv->contexts = g_list_append (manager->priv->contexts,
+        priv->contexts = g_list_append (priv->contexts,
                                                  context);
 }
 
@@ -104,10 +107,13 @@ create_contexts (gpointer data)
 {
         GUPnPSimpleContextManager *manager = (GUPnPSimpleContextManager *) data;
         GList *ifaces;
+        GUPnPSimpleContextManagerPrivate *priv;
+
+        priv = gupnp_simple_context_manager_get_instance_private (manager);
 
-        manager->priv->idle_context_creation_src = NULL;
+        priv->idle_context_creation_src = NULL;
 
-        if (manager->priv->contexts != NULL)
+        if (priv->contexts != NULL)
                return FALSE;
 
         ifaces = gupnp_simple_context_manager_get_interfaces (manager);
@@ -123,47 +129,48 @@ create_contexts (gpointer data)
 static void
 destroy_contexts (GUPnPSimpleContextManager *manager)
 {
-        while (manager->priv->contexts) {
+        GUPnPSimpleContextManagerPrivate *priv;
+
+        priv = gupnp_simple_context_manager_get_instance_private (manager);
+        while (priv->contexts) {
                 GUPnPContext *context;
 
-                context = GUPNP_CONTEXT (manager->priv->contexts->data);
+                context = GUPNP_CONTEXT (priv->contexts->data);
 
                 g_signal_emit_by_name (manager,
                                        "context-unavailable",
                                        context);
                 g_object_unref (context);
 
-                manager->priv->contexts = g_list_delete_link
-                                        (manager->priv->contexts,
-                                         manager->priv->contexts);
+                priv->contexts = g_list_delete_link (priv->contexts,
+                                                     priv->contexts);
         }
 }
 
 static void
 schedule_contexts_creation (GUPnPSimpleContextManager *manager)
 {
-        manager->priv->idle_context_creation_src = NULL;
+        GUPnPSimpleContextManagerPrivate *priv;
+
+        priv = gupnp_simple_context_manager_get_instance_private (manager);
+        priv->idle_context_creation_src = NULL;
 
         /* Create contexts in mainloop so that is happens after user has hooked
          * to the "context-available" signal.
          */
-        manager->priv->idle_context_creation_src = g_idle_source_new ();
-        g_source_attach (manager->priv->idle_context_creation_src,
+        priv->idle_context_creation_src = g_idle_source_new ();
+        g_source_attach (priv->idle_context_creation_src,
                          g_main_context_get_thread_default ());
-        g_source_set_callback (manager->priv->idle_context_creation_src,
+        g_source_set_callback (priv->idle_context_creation_src,
                                create_contexts,
                                manager,
                                NULL);
-        g_source_unref (manager->priv->idle_context_creation_src);
+        g_source_unref (priv->idle_context_creation_src);
 }
 
 static void
 gupnp_simple_context_manager_init (GUPnPSimpleContextManager *manager)
 {
-        manager->priv =
-                G_TYPE_INSTANCE_GET_PRIVATE (manager,
-                                             GUPNP_TYPE_SIMPLE_CONTEXT_MANAGER,
-                                             GUPnPSimpleContextManagerPrivate);
 }
 
 static void
@@ -186,14 +193,16 @@ gupnp_simple_context_manager_dispose (GObject *object)
 {
         GUPnPSimpleContextManager *manager;
         GObjectClass *object_class;
+        GUPnPSimpleContextManagerPrivate *priv;
 
         manager = GUPNP_SIMPLE_CONTEXT_MANAGER (object);
+        priv = gupnp_simple_context_manager_get_instance_private (manager);
 
         destroy_contexts (manager);
 
-        if (manager->priv->idle_context_creation_src) {
-                g_source_destroy (manager->priv->idle_context_creation_src);
-                manager->priv->idle_context_creation_src = NULL;
+        if (priv->idle_context_creation_src) {
+                g_source_destroy (priv->idle_context_creation_src);
+                priv->idle_context_creation_src = NULL;
         }
 
 
@@ -211,7 +220,4 @@ gupnp_simple_context_manager_class_init (GUPnPSimpleContextManagerClass *klass)
 
         object_class->constructed  = gupnp_simple_context_manager_constructed;
         object_class->dispose      = gupnp_simple_context_manager_dispose;
-
-        g_type_class_add_private (klass,
-                                  sizeof (GUPnPSimpleContextManagerPrivate));
 }
diff --git a/libgupnp/gupnp-simple-context-manager.h b/libgupnp/gupnp-simple-context-manager.h
index 8674d18..812c228 100644
--- a/libgupnp/gupnp-simple-context-manager.h
+++ b/libgupnp/gupnp-simple-context-manager.h
@@ -34,34 +34,15 @@ gupnp_simple_context_manager_get_type (void) G_GNUC_CONST;
 
 #define GUPNP_TYPE_SIMPLE_CONTEXT_MANAGER \
                 (gupnp_simple_context_manager_get_type ())
-#define GUPNP_SIMPLE_CONTEXT_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_SIMPLE_CONTEXT_MANAGER, \
-                 GUPnPSimpleContextManager))
-#define GUPNP_SIMPLE_CONTEXT_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_SIMPLE_CONTEXT_MANAGER, \
-                 GUPnPSimpleContextManagerClass))
-#define GUPNP_IS_SIMPLE_CONTEXT_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_SIMPLE_CONTEXT_MANAGER))
-#define GUPNP_IS_SIMPLE_CONTEXT_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_SIMPLE_CONTEXT_MANAGER))
-#define GUPNP_SIMPLE_CONTEXT_MANAGER_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_SIMPLE_CONTEXT_MANAGER, \
-                 GUPnPSimpleContextManagerClass))
 
-typedef struct _GUPnPSimpleContextManagerPrivate GUPnPSimpleContextManagerPrivate;
+G_GNUC_INTERNAL
+G_DECLARE_DERIVABLE_TYPE (GUPnPSimpleContextManager,
+                          gupnp_simple_context_manager,
+                          GUPNP,
+                          SIMPLE_CONTEXT_MANAGER,
+                          GUPnPContextManager)
 
-typedef struct {
-        GUPnPContextManager parent;
-
-        GUPnPSimpleContextManagerPrivate *priv;
-} GUPnPSimpleContextManager;
-
-typedef struct {
+struct _GUPnPSimpleContextManagerClass {
         GUPnPContextManagerClass parent_class;
 
         /* vfuncs */
@@ -71,7 +52,7 @@ typedef struct {
         void (* _gupnp_reserved2) (void);
         void (* _gupnp_reserved3) (void);
         void (* _gupnp_reserved4) (void);
-} GUPnPSimpleContextManagerClass;
+};
 
 G_END_DECLS
 
diff --git a/libgupnp/gupnp-unix-context-manager.c b/libgupnp/gupnp-unix-context-manager.c
index 4b5c85e..ecaeb15 100644
--- a/libgupnp/gupnp-unix-context-manager.c
+++ b/libgupnp/gupnp-unix-context-manager.c
@@ -49,6 +49,10 @@
 #include "gupnp-unix-context-manager.h"
 #include "gupnp-context.h"
 
+struct _GUPnPUnixContextManager {
+        GUPnPSimpleContextManager parent;
+};
+
 G_DEFINE_TYPE (GUPnPUnixContextManager,
                gupnp_unix_context_manager,
                GUPNP_TYPE_SIMPLE_CONTEXT_MANAGER);
diff --git a/libgupnp/gupnp-unix-context-manager.h b/libgupnp/gupnp-unix-context-manager.h
index a19f305..de9d8b2 100644
--- a/libgupnp/gupnp-unix-context-manager.h
+++ b/libgupnp/gupnp-unix-context-manager.h
@@ -28,46 +28,15 @@
 
 G_BEGIN_DECLS
 
-G_GNUC_INTERNAL GType
-gupnp_unix_context_manager_get_type (void) G_GNUC_CONST;
+
 
 #define GUPNP_TYPE_UNIX_CONTEXT_MANAGER \
                 (gupnp_unix_context_manager_get_type ())
-#define GUPNP_UNIX_CONTEXT_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_UNIX_CONTEXT_MANAGER, \
-                 GUPnPUnixContextManager))
-#define GUPNP_UNIX_CONTEXT_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_UNIX_CONTEXT_MANAGER, \
-                 GUPnPUnixContextManagerClass))
-#define GUPNP_IS_UNIX_CONTEXT_MANAGER(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_UNIX_CONTEXT_MANAGER))
-#define GUPNP_IS_UNIX_CONTEXT_MANAGER_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_UNIX_CONTEXT_MANAGER))
-#define GUPNP_UNIX_CONTEXT_MANAGER_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_UNIX_CONTEXT_MANAGER, \
-                 GUPnPUnixContextManagerClass))
-
-typedef struct _GUPnPUnixContextManagerPrivate GUPnPUnixContextManagerPrivate;
-
-typedef struct {
-        GUPnPSimpleContextManager parent;
-} GUPnPUnixContextManager;
-
-typedef struct {
-        GUPnPSimpleContextManagerClass parent_class;
-
-        /* future padding */
-        void (* _gupnp_reserved1) (void);
-        void (* _gupnp_reserved2) (void);
-        void (* _gupnp_reserved3) (void);
-        void (* _gupnp_reserved4) (void);
-} GUPnPUnixContextManagerClass;
-
+G_DECLARE_FINAL_TYPE (GUPnPUnixContextManager,
+                      gupnp_unix_context_manager,
+                      GUPNP,
+                      UNIX_CONTEXT_MANAGER,
+                      GUPnPSimpleContextManager)
 G_END_DECLS
 
 #endif /* GUPNP_UNIX_CONTEXT_MANAGER_H */
diff --git a/libgupnp/gupnp-white-list.c b/libgupnp/gupnp-white-list.c
index f38fd5d..cdbff35 100644
--- a/libgupnp/gupnp-white-list.c
+++ b/libgupnp/gupnp-white-list.c
@@ -35,14 +35,15 @@
 
 #include "gupnp-white-list.h"
 
-G_DEFINE_TYPE (GUPnPWhiteList,
-               gupnp_white_list,
-               G_TYPE_OBJECT);
-
 struct _GUPnPWhiteListPrivate {
         gboolean enabled;
         GList *entries;
 };
+typedef struct _GUPnPWhiteListPrivate GUPnPWhiteListPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GUPnPWhiteList,
+                            gupnp_white_list,
+                            G_TYPE_OBJECT);
 
 enum {
         PROP_0,
@@ -59,11 +60,11 @@ enum {
 static void
 gupnp_white_list_init (GUPnPWhiteList *list)
 {
-        list->priv = G_TYPE_INSTANCE_GET_PRIVATE (list,
-                                                  GUPNP_TYPE_WHITE_LIST,
-                                                  GUPnPWhiteListPrivate);
+        GUPnPWhiteListPrivate *priv;
 
-        list->priv->entries = NULL;
+        priv = gupnp_white_list_get_instance_private (list);
+
+        priv->entries = NULL;
 }
 
 static void
@@ -73,15 +74,17 @@ gupnp_white_list_set_property (GObject      *object,
                                GParamSpec   *pspec)
 {
         GUPnPWhiteList *list;
+        GUPnPWhiteListPrivate *priv;
 
         list = GUPNP_WHITE_LIST (object);
+        priv = gupnp_white_list_get_instance_private (list);
 
         switch (property_id) {
         case PROP_ENABLED:
-                list->priv->enabled = g_value_get_boolean (value);
+                priv->enabled = g_value_get_boolean (value);
                 break;
         case PROP_ENTRIES:
-                list->priv->entries = g_value_get_pointer (value);
+                priv->entries = g_value_get_pointer (value);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -96,15 +99,17 @@ gupnp_white_list_get_property (GObject    *object,
                                GParamSpec *pspec)
 {
         GUPnPWhiteList *list;
+        GUPnPWhiteListPrivate *priv;
 
         list = GUPNP_WHITE_LIST (object);
+        priv = gupnp_white_list_get_instance_private (list);
 
         switch (property_id) {
         case PROP_ENABLED:
-                g_value_set_boolean (value, list->priv->enabled);
+                g_value_set_boolean (value, priv->enabled);
                 break;
         case PROP_ENTRIES:
-                g_value_set_pointer (value, list->priv->entries);
+                g_value_set_pointer (value, priv->entries);
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -117,11 +122,13 @@ gupnp_white_list_class_finalize (GObject *object)
 {
         GUPnPWhiteList *list;
         GObjectClass *object_class;
+        GUPnPWhiteListPrivate *priv;
 
         list = GUPNP_WHITE_LIST (object);
+        priv = gupnp_white_list_get_instance_private (list);
 
-        g_list_free_full (list->priv->entries, g_free);
-        list->priv->entries = NULL;
+        g_list_free_full (priv->entries, g_free);
+        priv->entries = NULL;
 
         /* Call super */
         object_class = G_OBJECT_CLASS (gupnp_white_list_parent_class);
@@ -139,8 +146,6 @@ gupnp_white_list_class_init (GUPnPWhiteListClass *klass)
         object_class->get_property = gupnp_white_list_get_property;
         object_class->finalize     = gupnp_white_list_class_finalize;
 
-        g_type_class_add_private (klass, sizeof (GUPnPWhiteListPrivate));
-
         /**
          * GUPnPWhiteList:enabled:
          *
@@ -207,9 +212,12 @@ gupnp_white_list_new (void)
 void
 gupnp_white_list_set_enabled (GUPnPWhiteList *white_list, gboolean enable)
 {
+        GUPnPWhiteListPrivate *priv;
+
         g_return_if_fail (GUPNP_IS_WHITE_LIST (white_list));
 
-        white_list->priv->enabled = enable;
+        priv = gupnp_white_list_get_instance_private (white_list);
+        priv->enabled = enable;
         g_object_notify (G_OBJECT (white_list), "enabled");
 }
 
@@ -226,9 +234,13 @@ gupnp_white_list_set_enabled (GUPnPWhiteList *white_list, gboolean enable)
 gboolean
 gupnp_white_list_get_enabled (GUPnPWhiteList *white_list)
 {
+        GUPnPWhiteListPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_WHITE_LIST (white_list), FALSE);
 
-        return white_list->priv->enabled;
+        priv = gupnp_white_list_get_instance_private (white_list);
+
+        return priv->enabled;
 }
 
 /**
@@ -244,9 +256,13 @@ gupnp_white_list_get_enabled (GUPnPWhiteList *white_list)
 gboolean
 gupnp_white_list_is_empty (GUPnPWhiteList *white_list)
 {
+        GUPnPWhiteListPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_WHITE_LIST (white_list), TRUE);
 
-        return (white_list->priv->entries == NULL);
+        priv = gupnp_white_list_get_instance_private (white_list);
+
+        return (priv->entries == NULL);
 }
 
 /**
@@ -271,9 +287,10 @@ gupnp_white_list_add_entry (GUPnPWhiteList *white_list, const gchar* entry)
         g_return_val_if_fail (GUPNP_IS_WHITE_LIST (white_list), FALSE);
         g_return_val_if_fail ((entry != NULL), FALSE);
 
-        priv = white_list->priv;
+        priv = gupnp_white_list_get_instance_private (white_list);
 
-        s_entry = g_list_find_custom (priv->entries, entry,
+        s_entry = g_list_find_custom (priv->entries,
+                                      entry,
                                       (GCompareFunc) g_ascii_strcasecmp);
 
         if (s_entry == NULL) {
@@ -329,9 +346,10 @@ gupnp_white_list_remove_entry (GUPnPWhiteList *white_list, const gchar* entry)
         g_return_val_if_fail (GUPNP_IS_WHITE_LIST (white_list), FALSE);
         g_return_val_if_fail ((entry != NULL), FALSE);
 
-        priv = white_list->priv;
+        priv = gupnp_white_list_get_instance_private (white_list);
 
-        s_entry = g_list_find_custom (priv->entries, entry,
+        s_entry = g_list_find_custom (priv->entries,
+                                      entry,
                                       (GCompareFunc) g_ascii_strcasecmp);
 
         if (s_entry != NULL) {
@@ -358,9 +376,13 @@ gupnp_white_list_remove_entry (GUPnPWhiteList *white_list, const gchar* entry)
 GList *
 gupnp_white_list_get_entries (GUPnPWhiteList *white_list)
 {
+        GUPnPWhiteListPrivate *priv;
+
         g_return_val_if_fail (GUPNP_IS_WHITE_LIST (white_list), NULL);
 
-        return white_list->priv->entries;
+        priv = gupnp_white_list_get_instance_private (white_list);
+
+        return priv->entries;
 }
 
 /**
@@ -380,7 +402,7 @@ gupnp_white_list_clear (GUPnPWhiteList *white_list)
 
         g_return_if_fail (GUPNP_IS_WHITE_LIST(white_list));
 
-        priv = white_list->priv;
+        priv = gupnp_white_list_get_instance_private (white_list);
         g_list_free_full (priv->entries, g_free);
         priv->entries = NULL;
         g_object_notify (G_OBJECT (white_list), "entries");
@@ -411,17 +433,19 @@ gupnp_white_list_check_context (GUPnPWhiteList *white_list,
         const char *host_ip;
         const char *network;
         gboolean match = FALSE;
+        GUPnPWhiteListPrivate *priv;
 
         g_return_val_if_fail (GUPNP_IS_WHITE_LIST (white_list), FALSE);
         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), FALSE);
 
         client = GSSDP_CLIENT (context);
+        priv = gupnp_white_list_get_instance_private (white_list);
 
         interface = gssdp_client_get_interface (client);
         host_ip = gssdp_client_get_host_ip (client);
         network = gssdp_client_get_network (client);
 
-        l = white_list->priv->entries;
+        l = priv->entries;
 
         while (l && !match) {
                 match = (interface && !strcmp (l->data, interface)) ||
diff --git a/libgupnp/gupnp-white-list.h b/libgupnp/gupnp-white-list.h
index 347b652..c0ea15e 100644
--- a/libgupnp/gupnp-white-list.h
+++ b/libgupnp/gupnp-white-list.h
@@ -27,45 +27,14 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_white_list_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_WHITE_LIST \
                 (gupnp_white_list_get_type ())
-#define GUPNP_WHITE_LIST(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_WHITE_LIST, \
-                 GUPnPWhiteList))
-#define GUPNP_WHITE_LIST_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_WHITE_LIST, \
-                 GUPnPWhiteListClass))
-#define GUPNP_IS_WHITE_LIST(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_WHITE_LIST))
-#define GUPNP_IS_WHITE_LIST_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_WHITE_LIST))
-#define GUPNP_WHITE_LIST_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_WHITE_LIST, \
-                 GUPnPWhiteListClass))
-
-typedef struct _GUPnPWhiteListPrivate GUPnPWhiteListPrivate;
-typedef struct _GUPnPWhiteList GUPnPWhiteList;
-typedef struct _GUPnPWhiteListClass GUPnPWhiteListClass;
-
-/**
- * GUPnPWhiteList:
- *
- * This struct contains private data only, and should be accessed using the
- * functions below.
- */
-struct _GUPnPWhiteList {
-        GObject parent;
 
-        GUPnPWhiteListPrivate *priv;
-};
+G_DECLARE_DERIVABLE_TYPE (GUPnPWhiteList,
+                          gupnp_white_list,
+                          GUPNP,
+                          WHITE_LIST,
+                          GObject)
 
 struct _GUPnPWhiteListClass {
         GObjectClass parent_class;
diff --git a/libgupnp/gupnp-xml-doc.c b/libgupnp/gupnp-xml-doc.c
index 9c4740a..d3a7c7c 100644
--- a/libgupnp/gupnp-xml-doc.c
+++ b/libgupnp/gupnp-xml-doc.c
@@ -36,6 +36,18 @@
 #include "gupnp-xml-doc.h"
 #include "gupnp-error.h"
 
+/**
+ * GUPnPXMLDoc:
+ * @doc: Pointer to the document.
+ *
+ * Reference-counting wrapper for libxml's #xmlDoc
+ */
+struct _GUPnPXMLDoc {
+        GObject parent;
+        /*< public >*/
+        xmlDoc *doc;
+};
+
 G_DEFINE_TYPE (GUPnPXMLDoc,
                gupnp_xml_doc,
                G_TYPE_OBJECT);
@@ -130,3 +142,8 @@ gupnp_xml_doc_new_from_path (const char *path,
 
         return gupnp_xml_doc_new (doc);
 }
+
+const xmlDoc *
+gupnp_xml_doc_get_doc (GUPnPXMLDoc *doc) {
+    return doc->doc;
+}
diff --git a/libgupnp/gupnp-xml-doc.h b/libgupnp/gupnp-xml-doc.h
index 4891f76..a7ba324 100644
--- a/libgupnp/gupnp-xml-doc.h
+++ b/libgupnp/gupnp-xml-doc.h
@@ -30,48 +30,14 @@
 
 G_BEGIN_DECLS
 
-GType
-gupnp_xml_doc_get_type (void) G_GNUC_CONST;
-
 #define GUPNP_TYPE_XML_DOC \
                 (gupnp_xml_doc_get_type ())
-#define GUPNP_XML_DOC(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-                 GUPNP_TYPE_XML_DOC, \
-                 GUPnPXMLDoc))
-#define GUPNP_XML_DOC_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_CAST ((obj), \
-                 GUPNP_TYPE_XML_DOC, \
-                 GUPnPXMLDocClass))
-#define GUPNP_IS_XML_DOC(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-                 GUPNP_TYPE_XML_DOC))
-#define GUPNP_IS_XML_DOC_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
-                 GUPNP_TYPE_XML_DOC))
-#define GUPNP_XML_DOC_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-                 GUPNP_TYPE_XML_DOC, \
-                 GUPnPXMLDocClass))
-
-typedef struct _GUPnPXMLDoc GUPnPXMLDoc;
-typedef struct _GUPnPXMLDocClass GUPnPXMLDocClass;
-
-/**
- * GUPnPXMLDoc:
- * @doc: Pointer to the document.
- *
- * Reference-counting wrapper for libxml's #xmlDoc
- */
-struct _GUPnPXMLDoc {
-        GObject parent;
-        /*< public >*/
-        xmlDoc *doc;
-};
 
-struct _GUPnPXMLDocClass {
-        GObjectClass parent_class;
-};
+G_DECLARE_FINAL_TYPE (GUPnPXMLDoc,
+                      gupnp_xml_doc,
+                      GUPNP,
+                      XML_DOC,
+                      GObject)
 
 GUPnPXMLDoc *
 gupnp_xml_doc_new                       (xmlDoc         *xml_doc);
@@ -80,6 +46,9 @@ GUPnPXMLDoc *
 gupnp_xml_doc_new_from_path             (const char     *path,
                                          GError        **error);
 
+const xmlDoc *
+gupnp_xml_doc_get_doc                   (GUPnPXMLDoc    *xml_doc);
+
 G_END_DECLS
 
 #endif /* GUPNP_XML_DOC_H */
diff --git a/meson.build b/meson.build
index e948cb0..93fff47 100644
--- a/meson.build
+++ b/meson.build
@@ -29,9 +29,10 @@ add_global_arguments('-DHAVE_CONFIG_H=1', language : 'c')
 guul = subproject('guul', default_options : ['default_library=static'])
 
 dependencies = [
-    dependency('glib-2.0', version : '>= 2.40'),
-    dependency('gio-2.0', version : '>= 2.40'),
-    dependency('gmodule-2.0', version : '>= 2.40'),
+    dependency('glib-2.0', version : '>= 2.44'),
+    dependency('gio-2.0', version : '>= 2.44'),
+    dependency('gmodule-2.0', version : '>= 2.44'),
+    dependency('gobject-2.0', version : '>= 2.44'),
     dependency('gssdp-1.2', version : '>= 1.1'),
     dependency('libsoup-2.4', version : '>= 2.48.0'),
     dependency('libxml-2.0'),


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