Apparently blogging about new features is now a requirement when committing to GUPnP repository! I should really start reading the small print before signing…

So, I improved gupnp-binding-tool a bit. For those who didn’t guess from the name, it is a GUPnP binding generator, a bit like dbus-binding-tool. It lets you, the UPnP application developer, deal with an API specific to your UPnP service (or control point) and hides most of the uglyness that naturally follows from GUPnPService and GUPnPServiceProxy being very generic.

Here are the main new features:

  • server (device) side bindings in addition to control point bindings: “–mode server”
  • state variable notifications support
  • “–prefix” option

You can take a look at the updated server tutorial , but what it really boils down to is in this example. First, implementation of the SetTarget action handler without wrappers:

static gboolean status;

void
set_target_cb (GUPnPService *service,
               GUPnPServiceAction *action,
               gpointer user_data)
{
  /* get new value */
  gupnp_service_action_get
      (action,
       "NewTargetValue", G_TYPE_BOOLEAN, &status,
       NULL);
  /* change notification */
  gupnp_service_notify
      (service,
       "Status", G_TYPE_BOOLEAN, status,
       NULL);

  gupnp_service_action_return (action);
}

...

/* connect handler */
g_signal_connect (service,
                  "action-invoked::SetTarget",
                  G_CALLBACK (set_target_cb),
                  NULL);

Notice the magic strings defining method and variable names and the type definitions that can’t be checked at compile-time? Getting those wrong will mean a run-time error in the best case, and they definitely won’t be available in your editors auto-completion.

Now take a look at the same handler using bindings generated with “–mode server –prefix switch” from the SwitchPower service definition (see gupnp/examples/SwitchPower1.xml):

static gboolean status;

static void
set_target_cb (GUPnPService *service,
               GUPnPServiceAction *action,
               gpointer user_data)
{
  /* get new value  */
  switch_set_target_action_get (action, &status);

  /* change notification */
  switch_status_variable_notify (service, status);

  gupnp_service_action_return (action);
}

...

/* connect handler*/
switch_set_target_action_connect (service,
                                  G_CALLBACK(set_target_cb),
                                  NULL);

Better, eh?

PS: The standard device/service definitions are available at http://upnp.org/standardizeddcps/default.asp.