Switch to unified view

a/doc/libupnpp-ctl.txt b/doc/libupnpp-ctl.txt
1
= Libupnpp for Control Points
1
= Libupnpp for Control Points
2
2
3
Libupnpp is a C++ wrapper for libupnp, a.k.a Portable UPnP, which is a
3
Libupnpp is a C++ wrapper for link:http://pupnp.sourceforge.net/[libupnp],
4
direct descendant of the Open Source SDK released by Intel in support of
4
a.k.a Portable UPnP, which is a direct descendant of the Open Source SDK
5
UPnP development.
5
released by Intel in support of UPnP development.
6
6
7
The Control Point side of libupnpp allows a C++ program to discover
7
Libupnpp can be used to implement UPnP devices and services, or Control
8
Points.
9
10
The Control Point side of libupnpp, which is documented here, allows a C++
8
devices, and exchange commands and status with them.
11
program to discover UPnP devices, and exchange commands and status with
12
them.
9
13
10
The library has a number of predefined modules for controlling specific
14
The library has a number of predefined modules for controlling specific
11
AVTransport or OpenHome audio services, and it is relatively easy to add
15
AVTransport or OpenHome audio services, and it is relatively easy to add
12
modules for other services externally (the internal modules have no more
16
modules for other services externally (the internal modules have no more
13
access to library internals than an external module would).
17
access to library internals than an external module would).
14
18
15
Limitations:
19
Limitations:
16
20
17
- The underlying libupnp only supports a single IP interface.
21
- The underlying libupnp only supports a single IP interface.
18
 The libupnpp methods are blocking, it is supposed that you will be using
22
- The libupnpp methods are blocking. Multithreading will be needed to
19
  threads to achieve any needed parallelism in your program.
23
  achieve parallelism in your program (in any case the underlying libupnp
24
  uses threads, so multithreading support is a requirement).
25
26
link:refdoc/html/index.html[Reference documentation (doxygen)]
20
27
21
== The Library object
28
== The Library object
22
29
23
The library is represented by a global singleton with a number of utility
30
The library is represented by a global singleton with a number of utility
24
methods, mostly related to setting parameters for the underlying libupnp
31
methods, mostly related to setting parameters for the underlying libupnp
...
...
61
In libupnpp, the content of the main description document for a given
68
In libupnpp, the content of the main description document for a given
62
device is provided by a
69
device is provided by a
63
link:refdoc/html/classUPnPClient_1_1UPnPDeviceDesc.html[UPnPClient::UPnPDeviceDesc]
70
link:refdoc/html/classUPnPClient_1_1UPnPDeviceDesc.html[UPnPClient::UPnPDeviceDesc]
64
object.
71
object.
65
72
66
If you are mostly using the devices and services predefined in the library,
73
When using the devices and services predefined by the library, this is
67
this is largely an opaque structure, which you will get through the
74
largely an opaque structure, which you will get through the discovery
68
discovery interface, and pass to an actual device constructor.
75
interface, and pass to a Device or Service constructor.
69
76
70
== Devices
77
== Devices
71
78
72
UPnP device are entities which can contain other, embedded devices, and
79
UPnP devices are entities which can contain other, embedded devices, and
73
services.
80
services.
74
81
75
Embedded devices are quite rare, and in my experience badly supported by
82
Embedded devices are quite rare, and in my experience badly supported by
76
typical control points.
83
common control points.
77
84
78
In general, the service is the interesting entity, and the wise approach is
85
In general, the service is the interesting entity, and the wise approach is
79
the Pythonic "quacks like a duck" one: if a device has the service you
86
the Pythonic "quacks like a duck" one: if a device has the service you
80
need, you can use it.
87
need, you can use it.
81
88
82
For example the predefined 'MediaRenderer' class in libupnpp does not even
89
For example the predefined 'MediaRenderer' class in libupnpp does not even
83
bother to verify its own type when built from a description: it just
90
bother to verify its own type when built from a description: it just
84
provides methods to query and retrieve handles to interesting services
91
provides methods to query and retrieve handles to interesting services
85
usually found in a Media Renderer (both OpenHome and UPnP AV). In most
92
usually found in a Media Renderer (both OpenHome and UPnP AV). In most
86
cases, not all services will be available, and the caller will compose an "a
93
cases, not all services will be available, and the caller will compose an "a
87
la carte" object to serve its need (e.g. using either UPnP AV Rendering
94
la carte" object to serve its needs (e.g. using either UPnP AV Rendering
88
Control or OpenHome Volume for controlling volume, depending on
95
Control or OpenHome Volume for controlling volume, depending on
89
availability).
96
availability).
90
97
91
As another example, the 'myrdcvolume' program from the libupnpp samples
98
As another example, the 'myrdcvolume' program from the libupnpp samples
92
shows how to implement a service interface without using the predefined
99
shows how to implement a service interface without using the predefined
...
...
95
the appropriate service
102
the appropriate service
96
(i.e. 'urn:schemas-upnp-org:service:RenderingControl'), and action
103
(i.e. 'urn:schemas-upnp-org:service:RenderingControl'), and action
97
('Volume').
104
('Volume').
98
105
99
The library predefines two device classes, for Media Server devices and
106
The library predefines two device classes, for Media Server devices and
100
Media Renderer ones. In both cases the only use for the class is to retrieve
107
Media Renderer ones. Both are convenience classes with utility code to
101
handles to the underlying services.
108
build the underlying service objects and retrieve handles for them.
102
109
103
110
104
== Services
111
== Services
105
112
106
Most UPnP functionality is provided through services, which are end points
113
Most UPnP functionality is provided through services, which are end points
...
...
110
(some of which also work with video). You will usually not need to bother
117
(some of which also work with video). You will usually not need to bother
111
constructing the service interface objects: rather you will let the device
118
constructing the service interface objects: rather you will let the device
112
classes do it and return a handle (but there is nothing to prevent you from
119
classes do it and return a handle (but there is nothing to prevent you from
113
building the service objects directly).
120
building the service objects directly).
114
121
115
It also has helper functions for helping with the independant implementation
122
The library also has helper functions for helping with the independant
116
of a service interface. 
123
implementation of a service interface.
117
124
118
== Predefined Service classes
125
== Predefined Service classes
119
126
120
* link:refdoc/html/classUPnPClient_1_1RenderingControl.html[UPnP AV
127
* link:refdoc/html/classUPnPClient_1_1RenderingControl.html[UPnP AV
121
  Rendering Control] 
128
  Rendering Control] 
...
...
132
139
133
The role of most methods in these classes is to marshal the input data into
140
The role of most methods in these classes is to marshal the input data into
134
SOAP format, perform the SOAP call, then marshal and return the output
141
SOAP format, perform the SOAP call, then marshal and return the output
135
data. They are all synchronous.
142
data. They are all synchronous.
136
143
144
== Eventing
145
146
UPnP services can report changes in their state to Control Points through
147
events. In practise, the Control Point implements an internal HTTP server
148
to which the services connect to report events.
149
150
Event reporting is not active by default and needs to be activated by the
151
Control Point by 'subscribing' to the service.
152
153
Users of Service classes can receive asynchronous events by calling the
154
link:refdoc/html/classUPnPClient_1_1Service.html#a2d9aad17b90587f8c6a3791944edcdde[installReporter()]
155
method, to specify what functions should be called when an event arrives.
156
157
NOTE: The event functions are called from a separate thread
158
and some synchronization will usually be required.
159
160
Some details of event handling in libupnpp have changed as of version
161
0.16.
162
163
== Event handling in version 0.15 and before
164
165
Services implemented by the library always subscribe to events. This
166
happens in the object constructor, by a call to the class derived
167
registerCallback() method. Example:
168
169
----
170
avtransport.hxx:
171
172
class AVTransport : public Service {
173
   ...
174
    AVTransport(const UPnPDeviceDesc& device,
175
                const UPnPServiceDesc& service)
176
        : Service(device, service) {
177
        registerCallback();
178
    }
179
...
180
181
avtransport.cxx:
182
183
void AVTransport::registerCallback()
184
{
185
    Service::registerCallback(bind(&AVTransport::evtCallback, this, _1));
186
}
187
----
188
189
'Service::registerCallback()' performs the UPnP subscription and takes note
190
of the function to call when an event arrive.
191
192
This means that a subscription (needing a network exchange) is performed
193
each time a Service object is built, even if events are not actually needed
194
by the user.
195
196
The Service base class destructor erases the callback hook and cancels the
197
event subscription.
198
199
=== Event handling for version 0.16 and later
200
201
As of version 0.16 of the library, the event subscription is only performed
202
if and when 'installReporter()' is called. If you don't need events, you
203
will not incur their overhead.
204
205
== Logging
206
207
Both 'libupnp' and 'libupnpp' have configurable error and debug logging.
208
209
=== libupnp logging
210
211
The log from 'libupnp' is very detailed and mostly useful for low level
212
debugging of UPnP issues. The logging functions in 'libupnp' are
213
conditionnally compiled, and may not be enabled for your distribution (you
214
can check UPNP_HAVE_DEBUG in 'include/upnp/upnpconfig.h').
215
216
If the 'libupnp' logging functions are enabled, you can control them
217
through the
218
link:refdoc/html/classUPnPP_1_1LibUPnP.html#afb21929cea7859786d93dec1086563bc[LibUPnP::setLogFileName()]
219
and 'LibUPnP::setLogLevel()' methods.
220
221
=== libupnpp logging
222
223
'libupnpp' logging is distinct from the 'libupnp' functions, and always
224
enabled, at a configurable level of verbosity.
225
226
The log is initialized by a call to
227
link:refdoc/html/classLogger.html[Logger::getTheLog()]. The
228
verbosity level can be adjusted through 'setLogLevel()', and macros are
229
used to emit the actual messages. The printing is based on the C++ iostreams.
230
231
See libupnpp/log.h for more details.
232
233
Exemple:
234
235
----
236
    if (Logger::getTheLog(logfilename) == 0) {
237
        cerr << "Can't initialize log" << endl;
238
        return 1;
239
    }
240
    Logger::getTheLog("")->setLogLevel(Logger::LLINF);
241
242
    ...
243
244
    LOGINF("Message at level INFO, it outputs some value: " << value);
245
----
246
247
Of course you can use the 'LOGXX' macros in your own code.
248
249
137
== Implementing a Service class
250
== Implementing a Service class
138
251
252
If you want to access a service for which no predefined class exists in
253
libupnpp, you need to define its interface yourself, by deriving the
254
'libupnpp' link:refdoc/html/classUPnPClient_1_1Service.html[Service] class.
255
256
The methods in the base class and in the helper modules make it very easy
257
to write the derived class.
258
259
NOTE: libupnpp has no provision to use the service description XML document
260
to define the service client methods. However, the device side has a script
261
to turn a service description into an implementation device-side skeleton.
262
263
The derived class main constructor will take Device and Service description
264
structures are arguments and will need to call the base class
265
constructor. Example:
266
267
----
268
class OHPlaylist : public Service {
269
public:
270
271
    OHPlaylist(const UPnPDeviceDesc& device, const UPnPServiceDesc& service)
272
        : Service(device, service) {
273
    }
274
    ...
275
----
276
277
If there are initialization steps which are specific to the service type,
278
they should be done inside the 'serviceInit()' method, which 
279
should be called from the constructor (see below for a more detailed
280
description). Most services don't need 'serviceInit()', so an empty
281
implementation is provided by the base class.
282
283
Action methods are then just ordinary methods, which will call the base
284
class methods to perform the networky things.
285
286
Example of an action setting a value:
287
288
----
289
int RenderingControl::setMute(bool mute, const string& channel)
290
{
291
    SoapOutgoing args(getServiceType(), "SetMute");
292
    args("InstanceID", "0")("Channel", channel)
293
    ("DesiredMute", SoapHelp::i2s(mute?1:0));
294
    SoapIncoming data;
295
    return runAction(args, data);
296
}
297
----
298
299
The link:refdoc/html/classUPnPP_1_1SoapOutgoing.html[SoapOutgoing]
300
constructor takes a service type and action name arguments. Its 'operator ()'
301
accepts additional named string arguments.
302
303
The
304
link:refdoc/html/classUPnPClient_1_1Service.html#a7eee43639eff25893117ab52b0b036db[Service::runAction()]
305
method performs the SOAP call and provides any resulting data in a
306
link:refdoc/html/classUPnPP_1_1SoapIncoming.html[SoapIncoming] object, from
307
which named values can be easily extracted. There is no return data in the
308
above example, see below for an action using 'SoapIncoming::get()' to
309
extract data.
310
311
Example of an action retrieving a value (note there is nothing to prevent
312
an action to both set and retrieve data).
313
314
----
315
bool RenderingControl::getMute(const string& channel)
316
{
317
    SoapOutgoing args(getServiceType(), "GetMute");
318
    args("InstanceID", "0")("Channel", channel);
319
    SoapIncoming data;
320
    int ret = runAction(args, data);
321
    if (ret != UPNP_E_SUCCESS) {
322
        return false;
323
    }
324
    bool mute;
325
    if (!data.get("CurrentMute", &mute)) {
326
        LOGERR("RenderingControl:getMute: missing CurrentMute in response"
327
               << endl);
328
        return false;
329
    }
330
    return mute;
331
}
332
----
333
334
There are utility methods in the base class for actions which either
335
transport no data, or send or receive a single value:
336
link:refdoc/html/classUPnPClient_1_1Service.html#a9ec23e2f36c2bbdefaac4991d80d6063[runTrivialAction()],
337
link:///net/y/home/dockes/projets/mpdupnp/0.16-libupnpp/doc/refdoc/html/classUPnPClient_1_1Service.html#a7cde71d714f07a6bb655760238e52e25[runSimpleAction()],
338
link:refdoc/html/classUPnPClient_1_1Service.html#a1de907ba9604a20aaf3611e71ded445d[runSimpleGet()]
339
340
341
=== Methods which may need reimplementation
342
343
----
344
virtual bool UPnPClient::Service::serviceTypeMatch(const std::string& tp)=0;  
345
----
346
347
This is only needed for library version 0.16 and later. It is used by the
348
base class to find a matching service description in the device description
349
service list, which is done when calling
350
link:refdoc/html/classUPnPClient_1_1Service.html#afb13c0cc50b44c9c62e024961cf23b75[initFromDescription()].
351
352
The latter method is useful for building an object in two phases, first an
353
empty constructor, then initialization from the device description.
354
355
Derived classes compare the service types in the list with their own type
356
string.
357
358
----
359
virtual bool UPnPClient::Service::serviceInit(const UPnPDeviceDesc& device,
360
                                          const UPnPServiceDesc& service);
361
----
362
363
This is the part of the initialization specific to the service type. When
364
it is called, the Service class is fully initialized. Most services
365
don't need to do anything in there. An example of use would be the
366
Rendering Control service calling the device to retrieve the range of
367
volume control values.
368
369
An empty implementation is provided by the base class.
370
371
The method is called from
372
link:refdoc/html/classUPnPClient_1_1Service.html#afb13c0cc50b44c9c62e024961cf23b75[initFromDescription()],
373
and, if it does anything, it should be called from the non-empty derived class
374
constructor too.
375
139
== Eventing
376
=== Eventing
140
377
141
== Logging
378
Derived service classes can define a
379
link:refdoc/html/classUPnPClient_1_1Service.html#ac4ba122d2fe124eff620c62cbf5ac1a1[registerCallBack()]
380
method to register a function to be called when an event arrives. 
381
'registerCallBack()' will be called by 'Service::installReporter()' when
382
the user register their interest in events. In turn, 'registerCallback()'
383
should call
384
link:refdoc/html/classUPnPClient_1_1Service.html#a8b8580b88b4fbfc1de18a14d7811169d[Service::registerCallBack(evtCBFunc)]
385
to register their actual callback routine.
386
387
Callback functions can be any 'std::function' taking appropriate arguments,
388
usually a member function of the service object.