Herqq
|
This is a class for creating and hosting HServerDevice
instances on the network.
More...
#include <HDeviceHost>
Public Types | |
enum | DeviceHostError { UndefinedError = -1, NoError = 0, AlreadyInitializedError = 1, InvalidConfigurationError = 2, InvalidDeviceDescriptionError = 3, InvalidServiceDescriptionError = 4, CommunicationsError = 5, NotStarted = 6, ResourceConflict = 7 } |
Public Slots | |
void | quit () |
Public Member Functions | |
HDeviceHost (QObject *parent=0) | |
virtual | ~HDeviceHost () |
HServerDevice * | device (const HUdn &udn, TargetDeviceType target=RootDevices) const |
HServerDevices | rootDevices () const |
bool | init (const HDeviceHostConfiguration &configuration) |
DeviceHostError | error () const |
QString | errorDescription () const |
bool | isStarted () const |
bool | add (const HDeviceConfiguration &configuration) |
Protected Member Functions | |
const HDeviceHostConfiguration * | configuration () const |
const HDeviceHostRuntimeStatus * | runtimeStatus () const |
void | setError (DeviceHostError error, const QString &errorDescr) |
Private Member Functions | |
virtual bool | doInit () |
virtual void | doQuit () |
virtual bool | acceptSubscription (HServerService *targetService, const HEndpoint &source, bool isNew) |
This is a class for creating and hosting HServerDevice
instances on the network.
As the name implies, this is the class in the HUPnP library used to expose UPnP devices to UPnP control points. The class hosts instances of HServerDevice, which means that the class takes care of all of the UPnP mechanics detaching the HServerDevice from it. This separation leaves the HServerDevice to model the UPnP device structure and to focus on the functionality of the specific device type. This is what the HUPnP Device Model is all about.
Hosting a device is simple, assuming you have the necessary device and service descriptions ready and the HUPnP device and service classes implemented. Basically, you only need to:
HDeviceHost
inside a HDeviceHostConfiguration instance HDeviceHost
HDeviceHost
is run.As an example, consider the following:
// myclass.h #include "my_hdevice.h" // your code containing the type MyHDevice #include <HUpnpCore/HDeviceHost> #include <HUpnpCore/HDeviceModelCreator> #include <QtCore/QObject> class MyClass : public QObject { Q_OBJECT private: Herqq::Upnp::HDeviceHost* m_deviceHost; public: MyClass(QObject* parent = 0); }; class MyCreator : public Herqq::Upnp::HDeviceModelCreator { private: // overridden from HDeviceModelCreator virtual MyCreator* newInstance() const; public: // overridden from HDeviceModelCreator virtual MyHServerDevice* createDevice( const Herqq::Upnp::HDeviceInfo& info) const; // overridden from HDeviceModelCreator virtual MyHServerService* createService( const Herqq::Upnp::HServiceInfo& serviceInfo, const Herqq::Upnp::HDeviceInfo& parentDeviceInfo) const; }; // myclass.cpp MyCreator* MyCreator::newInstance() const { return new MyCreator(); } MyHServerDevice* MyCreator::createDevice(const Herqq::Upnp::HDeviceInfo& info) const { if (info.deviceType().toString() == "urn:herqq-org:device:MyDevice:1") { return new MyHServerDevice(); } return 0; } MyHServerService* MyCreator::createService( const Herqq::Upnp::HServiceInfo& serviceInfo, const Herqq::Upnp::HDeviceInfo& parentDeviceInfo) const { if (serviceInfo.serviceType().toString() == "urn:herqq-org:service:MyService:1") { return new HMyServerService(); } // Note, parentDeviceInfo is not needed in this case, but there are // scenarios when it is mandatory to know information of the parent // device to create the correct HServerService type. return 0; } MyClass::MyClass(QObject* parent) : QObject(parent), m_deviceHost(new Herqq::Upnp::HDeviceHost(this)) { Herqq::Upnp::HDeviceHostConfiguration hostConf; hostConf.setDeviceModelCreator(MyCreator()); Herqq::Upnp::HDeviceConfiguration deviceConf; deviceConf.setPathToDeviceDescription("my_hdevice_devicedescription.xml"); hostConf.add(deviceConf); if (!m_deviceHost->init(hostConf)) { // The initialization failed, perhaps you should do something? // for starters, you can call error() to check the error type and // errorDescription() for a human-readable description of // the error that occurred. return; } // The host is running and your device should now be accessible to // UPnP Control points until the host is destroyed (assuming the current // thread has an event loop). }
There are a few noteworthy issues in the example above.
HDeviceHost
is alive. When the device host is destroyed every UPnP device it hosted are destroyed as well.HDeviceHost
requires an event loop to function.HDeviceHost
instance to host a single UPnP root device, but the same host could be used to host multiple UPnP root devices. Certainly you can create multiple HDeviceHost
instances that each host a single root HServerDevice within a thread, even sharing an event loop. However, using a single HDeviceHost
for multiple root HServerDevice instances reduces resource usage in various ways and makes all the configured UPnP root devices accessible to you from the same HDeviceHost
instance.HDeviceHost
has thread affinity, which mandates that the HDeviceHost
and any object managed by it must be destroyed in the thread in which the HDeviceHost
at the time lives. You can use QObject::moveToThread()
on the HDeviceHost
, which causes the device host and every object managed by it to be moved to the chosen thread. However, you cannot move individual objects managed by HDeviceHost
.HDeviceHost
is the owner of the instances of HServerDevice
it manages. It manages the memory of every object it has created. In other words, a device host never transfers the ownership of the HServerDevice objects it manages; HDeviceHost always destroys every HServerDevice it manages when it is being destroyed.enum DeviceHostError |
Specifies return values that some of the methods of the class may return.
HDeviceHost | ( | QObject * | parent = 0 | ) | [explicit] |
Creates a new instance.
parent | specifies the parent QObject . |
~HDeviceHost | ( | ) | [virtual] |
Destroys the instance.
Destroys the device host and every hosted device.
bool doInit | ( | ) | [private, virtual] |
Performs the initialization of a derived class.
The HDeviceHost
uses two-phase initialization in which the user first constructs an instance and then calls init() in order to ready the object for use. This method is called by the HDeviceHost
during its private initialization after all the private data structures are constructed, but before any network operations are performed. At this point no HTTP or SSDP requests are served.
You can override this method to perform any further initialization of a derived class.
void doQuit | ( | ) | [private, virtual] |
Performs the de-initialization of a derived class.
Since it is possible to shutdown a device host without actually destroying the instance by calling quit(), derived classes have the possibility to run their own shutdown procedure by overriding this method. This method is called before the HDeviceHost
cleans its private data structures but after it has stopped listening requests from the network.
bool acceptSubscription | ( | HServerService * | targetService, |
const HEndpoint & | source, | ||
bool | isNew | ||
) | [private, virtual] |
Checks if a (re-)subscription should be accepted.
Derived classes can opt to override this method to decide what event subscriptions are accepted and what are not.
targetService | specifies the target of the subscription. |
source | specifies the location where the subscription came. |
isNew | indicates the type of the subscription. The value is true in case the subscription is new and false in case the subscription is a renewal to an existing subscription. |
const HDeviceHostConfiguration * configuration | ( | ) | const [protected] |
Returns the configuration used to initialize the device host.
const HDeviceHostRuntimeStatus * runtimeStatus | ( | ) | const [protected] |
Returns the object that details information of the status of a device host.
void setError | ( | DeviceHostError | error, |
const QString & | errorDescr | ||
) | [protected] |
Sets the type and description of the last error occurred.
error | specifies the error type. |
errorDescr | specifies a human readable description of the error. |
HServerDevice * device | ( | const HUdn & | udn, |
TargetDeviceType | target = RootDevices |
||
) | const |
Returns a root device with the specified Unique Device Name.
udn | specifies the Unique Device Name of the desired root device. |
target | specifies the type of devices that are included in the search. |
HServerDevices rootDevices | ( | ) | const |
Returns a list of UPnP root devices the host is currently managing.
The returned list contains pointers to root HServerDevice objects that are currently hosted by this instance.
bool init | ( | const HDeviceHostConfiguration & | configuration | ) |
Initializes the device host and the devices it is supposed to host.
configuration | specifies the configuration for the instance. The object has to contain at least one device configuration. |
DeviceHostError error | ( | ) | const |
Returns the type of the last error occurred.
QString errorDescription | ( | ) | const |
Returns a human readable description of the last error occurred.
bool isStarted | ( | ) | const |
Indicates whether or not the host is successfully started.
bool add | ( | const HDeviceConfiguration & | configuration | ) |
Adds a new root device configuration to the device host.
If the provided configuration is valid, the device host creates a new device model instance, announces the new resource(s) to the network and adds the device model available into the control of this instance.
configuration | specifies the new root device to add. |
void quit | ( | ) | [slot] |
Quits the device host and destroys the UPnP devices it is hosting.
Note that this is automatically called when the device host is destroyed.