~ubuntu-branches/debian/experimental/gupnp/experimental

« back to all changes in this revision

Viewing changes to doc/html/server-tutorial.html

  • Committer: Bazaar Package Importer
  • Author(s): Ross Burton
  • Date: 2008-06-30 09:32:18 UTC
  • mfrom: (1.2.1 upstream) (2.1.5 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080630093218-vmb4elru8cn18579
Tags: 0.12.1-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
2
<html>
 
3
<head>
 
4
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 
5
<title>Writing a UPnP Service</title>
 
6
<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
 
7
<link rel="start" href="index.html" title="GUPnP Reference Manual">
 
8
<link rel="up" href="tutorial.html" title="Part I. Tutorial">
 
9
<link rel="prev" href="client-tutorial.html" title="Writing a UPnP Client">
 
10
<link rel="next" href="api.html" title="Part II. Reference">
 
11
<meta name="generator" content="GTK-Doc V1.10 (XML mode)">
 
12
<link rel="stylesheet" href="style.css" type="text/css">
 
13
<link rel="part" href="tutorial.html" title="Part I. Tutorial">
 
14
<link rel="chapter" href="overview.html" title="Overview">
 
15
<link rel="chapter" href="client-tutorial.html" title="Writing a UPnP Client">
 
16
<link rel="chapter" href="server-tutorial.html" title="Writing a UPnP Service">
 
17
<link rel="part" href="api.html" title="Part II. Reference">
 
18
<link rel="chapter" href="api-device-info.html" title="Device Information">
 
19
<link rel="chapter" href="api-device-control.html" title="Device Control">
 
20
<link rel="chapter" href="api-device-impl.html" title="Device Implementation">
 
21
<link rel="chapter" href="api-utility.html" title="Utility Functions">
 
22
<link rel="chapter" href="api-tools.html" title="Tools">
 
23
<link rel="part" href="schemas.html" title="Part III. XML Schemas">
 
24
<link rel="chapter" href="schemas-device.html" title="Device Description">
 
25
<link rel="chapter" href="schemas-service.html" title="Service Description">
 
26
<link rel="glossary" href="glossary.html" title="Glossary">
 
27
<link rel="index" href="ix01.html" title="Index">
 
28
</head>
 
29
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
 
30
<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"><tr valign="middle">
 
31
<td><a accesskey="p" href="client-tutorial.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"></a></td>
 
32
<td><a accesskey="u" href="tutorial.html"><img src="up.png" width="24" height="24" border="0" alt="Up"></a></td>
 
33
<td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"></a></td>
 
34
<th width="100%" align="center">GUPnP Reference Manual</th>
 
35
<td><a accesskey="n" href="api.html"><img src="right.png" width="24" height="24" border="0" alt="Next"></a></td>
 
36
</tr></table>
 
37
<div class="chapter" lang="en">
 
38
<div class="titlepage"><div><div><h2 class="title">
 
39
<a name="server-tutorial"></a>Writing a UPnP Service</h2></div></div></div>
 
40
<div class="simplesect" lang="en">
 
41
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
 
42
<a name="id2582304"></a>Introduction</h2></div></div></div>
 
43
<p>
 
44
      This chapter explains how to implement a UPnP service using GUPnP. For
 
45
      this example we will create a virtual UPnP-enabled light bulb.
 
46
    </p>
 
47
<p>
 
48
      Before any code can be written, the device and services that it implement
 
49
      need to be described in XML.  Although this can be frustrating, if you are
 
50
      implementing a standardised service (see <a class="ulink" href="http://upnp.org/standardizeddcps/" target="_top">http://upnp.org/standardizeddcps/</a> for the list of standard devices
 
51
      and services) then the service description is already written for you and
 
52
      the device description is trivial.  UPnP has standardised <a class="ulink" href="http://upnp.org/standardizeddcps/lighting.asp" target="_top">Lighting
 
53
      Controls</a>, so we'll be using the device and service types defined
 
54
      there.
 
55
    </p>
 
56
</div>
 
57
<div class="simplesect" lang="en">
 
58
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
 
59
<a name="id2605390"></a>Defining the Device</h2></div></div></div>
 
60
<p>
 
61
      The first step is to write the <em class="firstterm">device description</em>
 
62
      file.  This is a short XML document which describes the device and what
 
63
      services it provides (for more details see the <a class="ulink" href="http://upnp.org/specs/arch/UPnP-DeviceArchitecture-v1.0.pdf" target="_top">UPnP
 
64
      Device Architecture</a> specification, section 2.1).  We'll be using
 
65
      the <code class="literal">BinaryLight1</code> device type, but if none of the
 
66
      existing device types are suitable a custom device type can be created.
 
67
    </p>
 
68
<pre class="programlisting">&lt;?xml version="1.0" encoding="utf-8"?&gt;
 
69
&lt;root xmlns="urn:schemas-upnp-org:device-1-0"&gt;
 
70
  &lt;specVersion&gt;
 
71
    &lt;major&gt;1&lt;/major&gt;
 
72
    &lt;minor&gt;0&lt;/minor&gt;
 
73
  &lt;/specVersion&gt;
 
74
 
 
75
  &lt;device&gt;
 
76
    &lt;deviceType&gt;urn:schemas-upnp-org:device:BinaryLight:1&lt;/deviceType&gt;
 
77
    &lt;friendlyName&gt;Kitchen Lights&lt;/friendlyName&gt;
 
78
    &lt;manufacturer&gt;OpenedHand&lt;/manufacturer&gt;
 
79
    &lt;modelName&gt;Virtual Light&lt;/modelName&gt;
 
80
    &lt;UDN&gt;uuid:cc93d8e6-6b8b-4f60-87ca-228c36b5b0e8&lt;/UDN&gt;
 
81
    
 
82
    &lt;serviceList&gt;
 
83
      &lt;service&gt;
 
84
        &lt;serviceType&gt;urn:schemas-upnp-org:service:SwitchPower:1&lt;/serviceType&gt;
 
85
        &lt;serviceId&gt;urn:upnp-org:serviceId:SwitchPower:1&lt;/serviceId&gt;
 
86
        &lt;SCPDURL&gt;/SwitchPower1.xml&lt;/SCPDURL&gt;
 
87
        &lt;controlURL&gt;/SwitchPower/Control&lt;/controlURL&gt;
 
88
        &lt;eventSubURL&gt;/SwitchPower/Event&lt;/eventSubURL&gt;
 
89
      &lt;/service&gt;
 
90
    &lt;/serviceList&gt;
 
91
  &lt;/device&gt;
 
92
&lt;/root&gt;
 
93
</pre>
 
94
<p>
 
95
      The <code class="sgmltag-element">specVersion</code> tag defines what version of the UPnP
 
96
      Device Architecture the document conforms to.  At the time of writing the
 
97
      only version is 1.0.
 
98
    </p>
 
99
<p>
 
100
      Next there is the root <code class="sgmltag-element">device</code> tag.  This contains
 
101
      metadata about the device, lists the services it provides and any
 
102
      sub-devices present (there are none in this example).  The
 
103
      <code class="sgmltag-element">deviceType</code> tag specifies the type of the device.
 
104
    </p>
 
105
<p>
 
106
      Next we have <code class="sgmltag-element">friendlyName</code>,
 
107
      <code class="sgmltag-element">manufacturer</code> and <code class="sgmltag-element">modelName</code>.  The
 
108
      friendly name is a human-readable name for the device, the manufacturer
 
109
      and model name are self-explanatory.
 
110
    </p>
 
111
<p>
 
112
      Next there is the UDN, or <em class="firstterm">Unique Device Name</em>.  This
 
113
      is an identifier which is unique for each device but persistent for each
 
114
      particular device.  Although it has to start with <code class="literal">uuid:</code>
 
115
      note that it doesn't have to be an UUID.  There are several alternatives
 
116
      here: for example it could be computed at built-time if the software will
 
117
      only be used on a single machine, or it could be calculated using the
 
118
      device's serial number or MAC address.
 
119
    </p>
 
120
<p>
 
121
      Finally we have the <code class="sgmltag-element">serviceList</code> which describes the
 
122
      services this device provides.  Each service has a service type (again
 
123
      there are types defined for standardised services or you can create your
 
124
      own), service identifier, and three URLs.  As a service type we're using
 
125
      the standard <code class="literal">SwitchPower1</code> service.  The
 
126
      <code class="sgmltag-element">SCPDURL</code> field specifies where the <em class="firstterm">Service
 
127
      Control Protocol Document</em> can be found, this describes the
 
128
      service in more detail and will be covered next.  Finally there are the
 
129
      control and event URLs, which need to be unique on the device and will be
 
130
      managed by GUPnP.
 
131
    </p>
 
132
</div>
 
133
<div class="simplesect" lang="en">
 
134
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
 
135
<a name="id2626610"></a>Defining Services</h2></div></div></div>
 
136
<p>
 
137
      Becase we are using a standard service we can use the service description
 
138
      from the specification.  This is the <code class="literal">SwitchPower1</code>
 
139
      service description file:
 
140
    </p>
 
141
<pre class="programlisting">&lt;?xml version="1.0" encoding="utf-8"?&gt;
 
142
&lt;scpd xmlns="urn:schemas-upnp-org:service-1-0"&gt;
 
143
  &lt;specVersion&gt;
 
144
    &lt;major&gt;1&lt;/major&gt;
 
145
    &lt;minor&gt;0&lt;/minor&gt;
 
146
  &lt;/specVersion&gt;
 
147
  &lt;actionList&gt;
 
148
    &lt;action&gt;
 
149
      &lt;name&gt;SetTarget&lt;/name&gt;
 
150
      &lt;argumentList&gt;
 
151
        &lt;argument&gt;
 
152
          &lt;name&gt;NewTargetValue&lt;/name&gt;
 
153
          &lt;relatedStateVariable&gt;Target&lt;/relatedStateVariable&gt;
 
154
          &lt;direction&gt;in&lt;/direction&gt;
 
155
        &lt;/argument&gt;
 
156
      &lt;/argumentList&gt;
 
157
    &lt;/action&gt;
 
158
    &lt;action&gt;
 
159
      &lt;name&gt;GetTarget&lt;/name&gt;
 
160
      &lt;argumentList&gt;
 
161
        &lt;argument&gt;
 
162
          &lt;name&gt;RetTargetValue&lt;/name&gt;
 
163
          &lt;relatedStateVariable&gt;Target&lt;/relatedStateVariable&gt;
 
164
          &lt;direction&gt;out&lt;/direction&gt;
 
165
        &lt;/argument&gt;
 
166
      &lt;/argumentList&gt;
 
167
    &lt;/action&gt;
 
168
    &lt;action&gt;
 
169
      &lt;name&gt;GetStatus&lt;/name&gt;
 
170
      &lt;argumentList&gt;
 
171
        &lt;argument&gt;
 
172
          &lt;name&gt;ResultStatus&lt;/name&gt;
 
173
          &lt;relatedStateVariable&gt;Status&lt;/relatedStateVariable&gt;
 
174
          &lt;direction&gt;out&lt;/direction&gt;
 
175
        &lt;/argument&gt;
 
176
      &lt;/argumentList&gt;
 
177
    &lt;/action&gt;
 
178
  &lt;/actionList&gt;
 
179
  &lt;serviceStateTable&gt;
 
180
    &lt;stateVariable sendEvents="no"&gt;
 
181
      &lt;name&gt;Target&lt;/name&gt;
 
182
      &lt;dataType&gt;boolean&lt;/dataType&gt;
 
183
      &lt;defaultValue&gt;0&lt;/defaultValue&gt;
 
184
    &lt;/stateVariable&gt;
 
185
    &lt;stateVariable sendEvents="yes"&gt;
 
186
      &lt;name&gt;Status&lt;/name&gt;
 
187
      &lt;dataType&gt;boolean&lt;/dataType&gt;
 
188
      &lt;defaultValue&gt;0&lt;/defaultValue&gt;
 
189
    &lt;/stateVariable&gt;
 
190
  &lt;/serviceStateTable&gt;
 
191
&lt;/scpd&gt;
 
192
</pre>
 
193
<p>
 
194
      Again, the <code class="sgmltag-element">specVersion</code> tag defines the UPnP version
 
195
      that is being used.  The rest of the document consists of an
 
196
      <code class="sgmltag-element">actionList</code> defining the <a class="glossterm" href="glossary.html#action"><em class="glossterm">actions</em></a> available and a
 
197
      <code class="sgmltag-element">serviceStateTable</code> defining the <a class="glossterm" href="glossary.html#state-variable"><em class="glossterm">state variables</em></a>.
 
198
    </p>
 
199
<p>
 
200
      Every <code class="sgmltag-element">action</code> has a <code class="sgmltag-element">name</code> and a list
 
201
      of <code class="sgmltag-element">argument</code>s.  Arguments also have a name, a direction
 
202
      (<code class="literal">in</code> or <code class="literal">out</code> for input or output
 
203
      arguments) and a related state variable.  The state variable is used to
 
204
      determine the type of the argument, and as such is a required element.
 
205
      This can lead to the creation of otherwise unused state variables to
 
206
      define the type for an argument (the <code class="literal">WANIPConnection</code>
 
207
      service is a good example of this), thanks to the legacy behind UPnP.
 
208
    </p>
 
209
<p>
 
210
      <code class="sgmltag-element">stateVariable</code>s need to specify their
 
211
      <code class="sgmltag-element">name</code> and <code class="sgmltag-element">dataType</code>.  State variables
 
212
      by default send notifications when they change, to specify that a variable
 
213
      doesn't do this set the <code class="sgmltag-element">sendEvents</code> attribute to
 
214
      <code class="literal">no</code>.  Finally there are optional
 
215
      <code class="sgmltag-element">defaultValue</code>, <code class="sgmltag-element">allowedValueList</code> and
 
216
      <code class="sgmltag-element">allowedValueRange</code> elements which specify what the
 
217
      default and valid values for the variable.
 
218
    </p>
 
219
<p>
 
220
      For the full specification of the service definition file, including a
 
221
      complete list of valid <code class="sgmltag-element">dataType</code>s, see section 2.3 of
 
222
      the <a class="ulink" href="http://upnp.org/specs/arch/UPnP-DeviceArchitecture-v1.0.pdf" target="_top">UPnP
 
223
      Device Architecture</a>.
 
224
    </p>
 
225
</div>
 
226
<div class="simplesect" lang="en">
 
227
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
 
228
<a name="id2623799"></a>Implementing the Device</h2></div></div></div>
 
229
<p>
 
230
      Before starting to implement the device, some boilerplate code is needed
 
231
      to initialise GUPnP.  GLib types and threading needs to be initialised,
 
232
      and then a GUPnP context can be created using <a class="link" href="GUPnPContext.html#gupnp-context-new" title="gupnp_context_new ()"><code class="function">gupnp_context_new()</code></a>.
 
233
    </p>
 
234
<pre class="programlisting">GUPnPContext *context;
 
235
/* Initialize required subsystems */
 
236
g_thread_init (NULL);
 
237
g_type_init ();
 
238
/* Create the GUPnP context with default host and port */
 
239
context = gupnp_context_new (NULL, NULL, 0, NULL);</pre>
 
240
<p>
 
241
      UPnP uses HTTP to provide the device and service description files, so
 
242
      next we tell GUPnP to publish them.  This is done with
 
243
      <a class="link" href="GUPnPContext.html#gupnp-context-host-path" title="gupnp_context_host_path ()"><code class="function">gupnp_context_host_path()</code></a> which takes a local filename to send when a
 
244
      certain server path is requested.
 
245
    </p>
 
246
<pre class="programlisting">gupnp_context_host_path (context, "BinaryLight1.xml", "/BinaryLight1.xml");
 
247
gupnp_context_host_path (context, "SwitchPower1.xml", "/SwitchPower1.xml");</pre>
 
248
<p>
 
249
      Next the root device can be created. 
 
250
    </p>
 
251
<pre class="programlisting">GUPnPRootDevice *dev;
 
252
/* Create the root device object */
 
253
dev = gupnp_root_device_new (context, "/BinaryLight1.xml");
 
254
/* Activate the root device, so that it announces itself */
 
255
gupnp_root_device_set_available (dev, TRUE);</pre>
 
256
<p>
 
257
      GUPnP scans the device description and any service description files it
 
258
      refers to, so if the main loop was entered now the device and service
 
259
      would be available on the network, albeit with no functionality.  The
 
260
      remaining task is to implement the services.
 
261
    </p>
 
262
</div>
 
263
<div class="simplesect" lang="en">
 
264
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
 
265
<a name="id2586848"></a>Implementing a Service</h2></div></div></div>
 
266
<p>
 
267
      To implement a service we first fetch the <a class="link" href="GUPnPService.html" title="GUPnPService"><span class="type">GUPnPService</span></a> from the root
 
268
      device using <a class="link" href="GUPnPDeviceInfo.html#gupnp-device-info-get-service" title="gupnp_device_info_get_service ()"><code class="function">gupnp_device_info_get_service()</code></a> (<a class="link" href="GUPnPRootDevice.html" title="GUPnPRootDevice"><span class="type">GUPnPRootDevice</span></a> is a
 
269
      subclass of <a class="link" href="GUPnPDevice.html" title="GUPnPDevice"><span class="type">GUPnPDevice</span></a>, which implements <a class="link" href="GUPnPDeviceInfo.html" title="GUPnPDeviceInfo"><span class="type">GUPnPDeviceInfo</span></a>).  This
 
270
      returns a <a class="link" href="GUPnPServiceInfo.html" title="GUPnPServiceInfo"><span class="type">GUPnPServiceInfo</span></a> which again is an interface, implemented by
 
271
      <a class="link" href="GUPnPService.html" title="GUPnPService"><span class="type">GUPnPService</span></a> (on the server) and <a class="link" href="GUPnPServiceProxy.html" title="GUPnPServiceProxy"><span class="type">GUPnPServiceProxy</span></a> (on the client).
 
272
    </p>
 
273
<pre class="programlisting">GUPnPServiceInfo *service;
 
274
service = gupnp_device_info_get_service
 
275
  (GUPNP_DEVICE_INFO (dev), "urn:schemas-upnp-org:service:SwitchPower:1");</pre>
 
276
<p>
 
277
      <a class="link" href="GUPnPService.html" title="GUPnPService"><span class="type">GUPnPService</span></a> handles interacting with the network itself, leaving the
 
278
      implementation of the service itself to signal handlers that we need to
 
279
      connect.  There are two signals: <a class="link" href="GUPnPService.html#GUPnPService-action-invoked" title='The "action-invoked" signal'><span class="type">"action-invoked"</span></a> and
 
280
      <a class="link" href="GUPnPService.html#GUPnPService-query-variable" title='The "query-variable" signal'><span class="type">"query-variable"</span></a>.  <a class="link" href="GUPnPService.html#GUPnPService-action-invoked" title='The "action-invoked" signal'><span class="type">"action-invoked"</span></a> is emitted
 
281
      when a client invokes an action: the handler is passed a
 
282
      <a class="link" href="GUPnPService.html#GUPnPServiceAction" title="GUPnPServiceAction"><span class="type">GUPnPServiceAction</span></a> object that identifies which action was invoked, and
 
283
      is used to return values using <a class="link" href="GUPnPService.html#gupnp-service-action-set" title="gupnp_service_action_set ()"><code class="function">gupnp_service_action_set()</code></a>.
 
284
      <a class="link" href="GUPnPService.html#GUPnPService-query-variable" title='The "query-variable" signal'><span class="type">"query-variable"</span></a> is emitted for evented variables when a
 
285
      control point subscribes to the service (to announce the initial value),
 
286
      or whenever a client queries the value of a state variable (note that this
 
287
      is now deprecated behaviour for UPnP control points): the handler is
 
288
      passed the variable name and a <span class="type">GValue</span> which should be set to the current
 
289
      value of the variable.
 
290
    </p>
 
291
<p>
 
292
      There are two approaches that clients can take to handle these signals.
 
293
      They can either connect a single handler to <a class="link" href="GUPnPService.html#GUPnPService-action-invoked" title='The "action-invoked" signal'><span class="type">"action-invoked"</span></a>
 
294
      or <a class="link" href="GUPnPService.html#GUPnPService-query-variable" title='The "query-variable" signal'><span class="type">"query-variable"</span></a> and examine the arguments to decide what
 
295
      action to take.  Alternatively, handlers can be targetted at specific
 
296
      actions or variables by using the <em class="firstterm">signal detail</em>
 
297
      when connecting.  For example, this causes
 
298
      <code class="function">on_get_status_action</code> to be called when the
 
299
      <code class="function">GetStatus</code> action is invoked:
 
300
    </p>
 
301
<pre class="programlisting">static void on_get_status_action (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data);
 
302
 
303
g_signal_connect (service, "action-invoked::GetStatus", G_CALLBACK (on_get_status_action), NULL);</pre>
 
304
<p>
 
305
      The implementation of action handlers is quite simple.  The handler is
 
306
      passed a <a class="link" href="GUPnPService.html#GUPnPServiceAction" title="GUPnPServiceAction"><span class="type">GUPnPServiceAction</span></a> object which represents the in-progress
 
307
      action.  If required it can be queried using
 
308
      <a class="link" href="GUPnPService.html#gupnp-service-action-get-name" title="gupnp_service_action_get_name ()"><code class="function">gupnp_service_action_get_name()</code></a> to identify the action (this isn't
 
309
      required if detailed signals were connected).  Any
 
310
      <em class="firstterm">in</em> arguments can be retrieving using
 
311
      <a class="link" href="GUPnPService.html#gupnp-service-action-get" title="gupnp_service_action_get ()"><code class="function">gupnp_service_action_get()</code></a>, and then return values can be set using
 
312
      <a class="link" href="GUPnPService.html#gupnp-service-action-set" title="gupnp_service_action_set ()"><code class="function">gupnp_service_action_set()</code></a>.  Once the action has been performed, either
 
313
      <a class="link" href="GUPnPService.html#gupnp-service-action-return" title="gupnp_service_action_return ()"><code class="function">gupnp_service_action_return()</code></a> or <a class="link" href="GUPnPService.html#gupnp-service-action-return-error" title="gupnp_service_action_return_error ()"><code class="function">gupnp_service_action_return_error()</code></a>
 
314
      should be called to either return successfully or return an error code.
 
315
      If any evented state variables were modified during the action then a
 
316
      notification should be emitted using <a class="link" href="GUPnPService.html#gupnp-service-notify" title="gupnp_service_notify ()"><code class="function">gupnp_service_notify()</code></a>.  This is an
 
317
      example implementation of <code class="function">GetStatus</code> and
 
318
      <code class="function">SetTarget</code>:
 
319
    </p>
 
320
<pre class="programlisting">static gboolean status;
 
321
 
 
322
static void
 
323
get_status_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
 
324
{
 
325
  gupnp_service_action_set (action,
 
326
                            "ResultStatus", G_TYPE_BOOLEAN, status,
 
327
                            NULL);
 
328
  gupnp_service_action_return (action);
 
329
}
 
330
 
 
331
void
 
332
set_target_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
 
333
{
 
334
  gupnp_service_action_get (action,
 
335
                            "NewTargetValue", G_TYPE_BOOLEAN, &amp;status,
 
336
                            NULL);
 
337
  gupnp_service_action_return (action);
 
338
  gupnp_service_notify (service, "Status", G_TYPE_STRING, status, NULL);
 
339
}
 
340
 
341
g_signal_connect (service, "action-invoked::GetStatus", G_CALLBACK (get_status_cb), NULL);
 
342
g_signal_connect (service, "action-invoked::SetTarget", G_CALLBACK (set_target_cb), NULL);</pre>
 
343
<p>
 
344
      State variable query handlers are called with the name of the variable and
 
345
      a <span class="type">GValue</span>.  This value should be initialized with the relevant type and
 
346
      then set to the current value.  Again signal detail can be used to connect
 
347
      handlers to specific state variable callbacks.
 
348
    </p>
 
349
<pre class="programlisting">static gboolean status;
 
350
 
 
351
static void
 
352
query_status_cb (GUPnPService *service, char *variable, GValue *value, gpointer user_data)
 
353
{
 
354
  g_value_init (value, G_TYPE_BOOLEAN);
 
355
  g_value_set_boolean (value, status);
 
356
}
 
357
 
358
g_signal_connect (service, "query-variable::Status", G_CALLBACK (query_status_cb), NULL);</pre>
 
359
<p>
 
360
      For services which have many actions and variables there is a convenience
 
361
      method <a class="link" href="GUPnPService.html#gupnp-service-signals-autoconnect" title="gupnp_service_signals_autoconnect ()"><code class="function">gupnp_service_signals_autoconnect()</code></a> which will automatically
 
362
      connect specially named handlers to signals.  See the documentation for
 
363
      full details on how it works.
 
364
    </p>
 
365
<p>
 
366
      The service is now fully implemented.  To complete it, enter a GLib main
 
367
      loop and wait for a client to connect.  The complete source code for this
 
368
      example is available as <code class="filename">examples/light-server.c</code> in
 
369
      the GUPnP sources.
 
370
    </p>
 
371
</div>
 
372
</div>
 
373
<div class="footer">
 
374
<hr>
 
375
          Generated by GTK-Doc V1.10</div>
 
376
</body>
 
377
</html>