diff options
author | Ross Burton <ross@openedhand.com> | 2008-06-09 13:42:14 +0000 |
---|---|---|
committer | Ross Burton <ross@openedhand.com> | 2008-06-09 13:42:14 +0000 |
commit | ce9c398e01e3c7aa4ae49f9bf34b92cc8374817b (patch) | |
tree | b62a04dfc60901b30ee3333993e2d8b90791d051 /examples | |
parent | 32612c9952d3a3e95e6cc2282a55c6bd6114d32b (diff) | |
download | gupnp-ce9c398e01e3c7aa4ae49f9bf34b92cc8374817b.tar.gz |
2008-06-09 Ross Burton <ross@openedhand.com>
* examples/:
* Makefile.am:
* configure.ac:
Add some basic but non-trivial examples.
git-svn-id: https://svn.o-hand.com/repos/gupnp/trunk/gupnp@1042 d8cb91d7-bff9-0310-92b9-80b65e4482b2
Diffstat (limited to 'examples')
-rw-r--r-- | examples/BinaryLight1.xml | 25 | ||||
-rw-r--r-- | examples/Makefile.am | 11 | ||||
-rw-r--r-- | examples/SwitchPower1.xml | 51 | ||||
-rw-r--r-- | examples/light-client.c | 127 | ||||
-rw-r--r-- | examples/light-server.c | 143 |
5 files changed, 357 insertions, 0 deletions
diff --git a/examples/BinaryLight1.xml b/examples/BinaryLight1.xml new file mode 100644 index 0000000..07798b1 --- /dev/null +++ b/examples/BinaryLight1.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<root xmlns="urn:schemas-upnp-org:device-1-0"> + <specVersion> + <major>1</major> + <minor>0</minor> + </specVersion> + + <device> + <deviceType>urn:schemas-upnp-org:device:BinaryLight:1</deviceType> + <friendlyName>Test Light</friendlyName> + <manufacturer>OpenedHand</manufacturer> + <modelName>Test Light</modelName> + <UDN>uuid:cc93d8e6-6b8b-4f60-87ca-228c36b5b0e8</UDN> + + <serviceList> + <service> + <serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType> + <serviceId>urn:upnp-org:serviceId:SwitchPower:1</serviceId> + <SCPDURL>/SwitchPower1.xml</SCPDURL> + <controlURL>/SwitchPower/Control</controlURL> + <eventSubURL>/SwitchPower/Event</eventSubURL> + </service> + </serviceList> + </device> +</root> diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..90b1cde --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,11 @@ +AM_CFLAGS = $(LIBGUPNP_CFLAGS) -I$(top_srcdir) +LDADD = $(top_builddir)/libgupnp/libgupnp-1.0.la + +noinst_PROGRAMS = light-server light-client + +light_server_SOURCES = light-server.c +light_server_LDFLAGS = -export-dynamic + +light_client_SOURCES = light-client.c + +MAINTAINERCLEANFILES = Makefile.in diff --git a/examples/SwitchPower1.xml b/examples/SwitchPower1.xml new file mode 100644 index 0000000..0204b15 --- /dev/null +++ b/examples/SwitchPower1.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<scpd xmlns="urn:schemas-upnp-org:service-1-0"> + <specVersion> + <major>1</major> + <minor>0</minor> + </specVersion> + <actionList> + <action> + <name>SetTarget</name> + <argumentList> + <argument> + <name>NewTargetValue</name> + <relatedStateVariable>Target</relatedStateVariable> + <direction>in</direction> + </argument> + </argumentList> + </action> + <action> + <name>GetTarget</name> + <argumentList> + <argument> + <name>RetTargetValue</name> + <relatedStateVariable>Target</relatedStateVariable> + <direction>out</direction> + </argument> + </argumentList> + </action> + <action> + <name>GetStatus</name> + <argumentList> + <argument> + <name>ResultStatus</name> + <relatedStateVariable>Status</relatedStateVariable> + <direction>out</direction> + </argument> + </argumentList> + </action> + </actionList> + <serviceStateTable> + <stateVariable sendEvents="no"> + <name>Target</name> + <dataType>boolean</dataType> + <defaultValue>0</defaultValue> + </stateVariable> + <stateVariable sendEvents="yes"> + <name>Status</name> + <dataType>boolean</dataType> + <defaultValue>0</defaultValue> + </stateVariable> + </serviceStateTable> +</scpd> diff --git a/examples/light-client.c b/examples/light-client.c new file mode 100644 index 0000000..af1df80 --- /dev/null +++ b/examples/light-client.c @@ -0,0 +1,127 @@ +/* + * Example UPnP device/service, implementing the BinaryLight device and + * SwitchPower services to emulate a light switch. + * + * The user interface is as minimal as possible so that the GUPnP concepts and + * best practises are more apparent. For a better implementation of + * BinaryLight, see gupnp-tools. + * + * This example code is in the public domain. + */ + +#include <libgupnp/gupnp.h> + +static GMainLoop *main_loop; + +static enum { + OFF = 0, + ON = 1, + TOGGLE +} mode; + +static void +service_proxy_available_cb (GUPnPControlPoint *cp, GUPnPServiceProxy *proxy) +{ + GError *error = NULL; + gboolean target; + + if (mode == TOGGLE) { + /* We're toggling, so first fetch the current status */ + if (!gupnp_service_proxy_send_action + (proxy, "GetStatus", &error, + /* IN args */ NULL, + /* OUT args */ "ResultStatus", G_TYPE_BOOLEAN, &target, NULL)) { + goto error; + } + /* And then toggle it */ + target = ! target; + } else { + /* Mode is a boolean, so the target is the mode thanks to our well chosen + enumeration values. */ + target = mode; + } + + /* Set the target */ + if (!gupnp_service_proxy_send_action (proxy, "SetTarget", &error, + /* IN args */ + "NewTargetValue", G_TYPE_BOOLEAN, target, NULL, + /* OUT args */ + NULL)) { + goto error; + } else { + g_print ("Set switch to %s.\n", target ? "on" : "off"); + } + + done: + /* Only manipulate the first light switch that is found */ + g_main_loop_quit (main_loop); + return; + + error: + g_printerr ("Cannot set switch: %s\n", error->message); + g_error_free (error); + goto done; +} + +static void +usage (void) +{ + g_printerr ("$ light-client [on|off|toggle]\n"); +} + +int +main (int argc, char **argv) +{ + GError *error = NULL; + GUPnPContext *context; + GUPnPControlPoint *cp; + + g_thread_init (NULL); + g_type_init (); + + /* Check and parse command line arguments */ + if (argc != 2) { + usage (); + return 1; + } + + if (g_str_equal (argv[1], "on")) { + mode = ON; + } else if (g_str_equal (argv[1], "off")) { + mode = OFF; + } else if (g_str_equal (argv[1], "toggle")) { + mode = TOGGLE; + } else { + usage (); + return 1; + } + + /* Create the UPnP context */ + context = gupnp_context_new (NULL, NULL, 0, &error); + if (error) { + g_error (error->message); + } + + /* Create the control point, searching for SwitchPower services */ + cp = gupnp_control_point_new (context, "urn:schemas-upnp-org:service:SwitchPower:1"); + + /* Connect to the service-found callback */ + g_signal_connect (cp, + "service-proxy-available", + G_CALLBACK (service_proxy_available_cb), + NULL); + + /* Start searching when the main loop runs */ + gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE); + + /* Run the main loop */ + main_loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (main_loop); + + /* Cleanup */ + g_main_loop_unref (main_loop); + g_object_unref (cp); + g_object_unref (context); + + return EXIT_SUCCESS; +} diff --git a/examples/light-server.c b/examples/light-server.c new file mode 100644 index 0000000..c132032 --- /dev/null +++ b/examples/light-server.c @@ -0,0 +1,143 @@ +/* + * Example UPnP device/service, implementing the BinaryLight device and + * SwitchPower services to emulate a light switch. + * + * The user interface is as minimal as possible so that the GUPnP concepts and + * best practises are more apparent. For a better implementation of + * BinaryLight, see gupnp-tools. + * + * This example code is in the public domain. + */ + +#include <libgupnp/gupnp.h> + +static gboolean status; + +/* + * Action handlers + */ + +/* SetTarget */ +void +set_target_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data) +{ + gboolean target; + + /* Get the new target value */ + gupnp_service_action_get (action, + "NewTargetValue", G_TYPE_BOOLEAN, &target, + NULL); + + /* If the new target doesn't match the current status, change the status and + emit a notification that the status has changed. */ + if (target != status) { + status = target; + gupnp_service_notify (service, + "Status", G_TYPE_BOOLEAN, status, + NULL); + + g_print ("The light is now %s.\n", status ? "on" : "off"); + } + + /* Return success to the client */ + gupnp_service_action_return (action); +} + +/* GetTarget */ +void +get_target_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data) +{ + gupnp_service_action_set (action, + "RetTargetValue", G_TYPE_BOOLEAN, status, + NULL); + gupnp_service_action_return (action); +} + +/* GetStatus */ +void +get_status_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data) +{ + gupnp_service_action_set (action, + "ResultStatus", G_TYPE_BOOLEAN, status, + NULL); + gupnp_service_action_return (action); +} + +/* + * State Variable query handlers + */ + +/* Target */ +void +query_target_cb (GUPnPService *service, char *variable, GValue *value, gpointer user_data) +{ + g_value_init (value, G_TYPE_BOOLEAN); + g_value_set_boolean (value, status); +} + +/* Status */ +void +query_status_cb (GUPnPService *service, char *variable, GValue *value, gpointer user_data) +{ + g_value_init (value, G_TYPE_BOOLEAN); + g_value_set_boolean (value, status); +} + + +int +main (int argc, char **argv) +{ + GMainLoop *main_loop; + GError *error = NULL; + GUPnPContext *context; + GUPnPRootDevice *dev; + GUPnPServiceInfo *service; + + g_thread_init (NULL); + g_type_init (); + + /* By default the light is off */ + status = FALSE; + g_print ("The light is now %s.\n", status ? "on" : "off"); + + /* Create the UPnP context */ + context = gupnp_context_new (NULL, NULL, 0, &error); + if (error) { + g_error (error->message); + } + + /* Host the device and service description files */ + gupnp_context_host_path (context, "BinaryLight1.xml", "/BinaryLight1.xml"); + gupnp_context_host_path (context, "SwitchPower1.xml", "/SwitchPower1.xml"); + + /* Create root device */ + dev = gupnp_root_device_new (context, "/BinaryLight1.xml"); + gupnp_root_device_set_available (dev, TRUE); + + /* Get the switch service from the root device */ + service = gupnp_device_info_get_service + (GUPNP_DEVICE_INFO (dev), "urn:schemas-upnp-org:service:SwitchPower:1"); + if (!service) + g_error ("Cannot get SwitchPower1 service"); + + /* Autoconnect the action and state variable handlers. This connects + query_target_cb and query_status_cb to the Target and Status state + variables query callbacks, and set_target_cb, get_target_cb and + get_status_cb to SetTarget, GetTarget and GetStatus actions + respectively. */ + gupnp_service_signals_autoconnect (GUPNP_SERVICE (service), NULL, &error); + if (error) + g_error ("Failed to autoconnect signals: %s", error->message); + + /* Run the main loop */ + main_loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (main_loop); + + /* Cleanup */ + g_main_loop_unref (main_loop); + g_object_unref (service); + g_object_unref (dev); + g_object_unref (context); + + return EXIT_SUCCESS; +} |