void HControlPointPrivate::deviceModelBuildDone(const Herqq::Upnp::HUdn& udn) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); DeviceBuildTask* build = m_deviceBuildTasks.get(udn); Q_ASSERT(build); if (m_state == Initialized) { // The check is done because it is possible that a user has called // HControlPoint::quit() before this event is delivered. if (build->completionValue() == 0) { HLOG_INFO(QString("Device model for [%1] built successfully.").arg( udn.toString())); HDefaultClientDevice* device = build->createdDevice(); Q_ASSERT(device); for (qint32 i = 0; i < build->m_locations.size(); ++i) { device->addLocation(build->m_locations[i]); } processDeviceOnline(device, true); } else { HLOG_WARN(QString("Device model for [%1] could not be built: %2.").arg( udn.toString(), build->errorString())); } } m_deviceBuildTasks.remove(udn); }
qint32 HServerAction::invoke( const HActionArguments& inArgs, HActionArguments* outArgs) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); *outArgs = h_ptr->m_info->outputArguments(); return h_ptr->m_actionInvoke(inArgs, outArgs); }
qint32 HRenderingControlService::getVolumeDB( quint32 instanceId, const HChannel& channel, qint16* currentVolumeDb) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } bool ok = false; *currentVolumeDb = mediaConnection->rendererConnectionInfo()->volumeDb(channel, &ok); if (!ok) { return HRenderingControlInfo::InvalidChannel; } return UpnpSuccess; }
qint32 HRenderingControlService::getLoudness( quint32 instanceId, const HChannel& channel, bool* loudnessOn) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } bool ok = false; *loudnessOn = mediaConnection->rendererConnectionInfo()->loudnessEnabled(channel, &ok); if (!ok) { return HRenderingControlInfo::InvalidChannel; } return UpnpSuccess; }
void DeviceBuildTask::run() { HLOG2(H_AT, H_FUN, m_owner->m_loggingIdentifier); QString err; QScopedPointer<HDefaultClientDevice> device; device.reset( m_owner->buildDevice(m_locations[0], m_cacheControlMaxAge, &err)); // the returned device is a fully built root device containing every // embedded device and service advertised in the device and service descriptions // otherwise, the creation failed if (!device.data()) { HLOG_WARN(QString("Couldn't create a device: %1").arg(err)); m_completionValue = -1; m_errorString = err; } else { device->moveToThread(m_owner->thread()); m_completionValue = 0; m_createdDevice.swap(device); } emit done(m_udn); }
void HControlPoint::setError(ControlPointError error, const QString& errorStr) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); h_ptr->m_lastError = error; h_ptr->m_lastErrorDescription = errorStr; }
void HControlPointPrivate::processDeviceOnline( HDefaultClientDevice* device, bool newDevice) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HControlPoint::DeviceDiscoveryAction actionToTake = q_ptr->acceptRootDevice(device); bool subscribe = false; switch(actionToTake) { case HControlPoint::IgnoreDevice: HLOG_DBG(QString("Discarding device with UDN %1").arg( device->info().udn().toString())); if (newDevice) { delete device; device = 0; } break; case HControlPoint::AddDevice: break; case HControlPoint::AddDevice_SubscribeEventsIfConfigured: subscribe = m_configuration->subscribeToEvents(); break; case HControlPoint::AddDevice_SubscribeAllEvents: subscribe = true; break; default: Q_ASSERT(false); break; }; if (device) { if (newDevice) { if (!addRootDevice(device)) { delete device; return; } } if (subscribe) { m_eventSubscriber->subscribe( device, VisitThisRecursively, m_configuration->desiredSubscriptionTimeout()); } } }
HControlPoint::HControlPoint( const HControlPointConfiguration& configuration, QObject* parent) : QObject(parent), h_ptr(new HControlPointPrivate()) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); h_ptr->m_configuration.reset(configuration.clone()); h_ptr->setParent(this); h_ptr->q_ptr = this; }
void HDataRetriever::timerEvent(QTimerEvent* event) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_WARN(QString("Request timed out.")); quit(); killTimer(event->timerId()); m_success = false; }
bool HDataRetriever::retrieveIcon( const QUrl& deviceLocation, const QUrl& iconUrl, QByteArray* data) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG(QString( "Attempting to retrieve icon [%1] from: [%2]").arg( iconUrl.toString(), deviceLocation.toString())); return retrieveData(deviceLocation, iconUrl, data); }
bool HControlPointPrivate::addRootDevice(HDefaultClientDevice* newRootDevice) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); Q_ASSERT(thread() == QThread::currentThread()); HDefaultClientDevice* existingDevice = static_cast<HDefaultClientDevice*>( m_deviceStorage.searchDeviceByUdn( newRootDevice->info().udn(), AllDevices)); if (existingDevice) { // it seems that the device we've built has already been added // (it is possible, although unlikely, we begin multiple device build // processes of the same device tree) // in this case we only make sure that the device's location list is // updated if necessary existingDevice = static_cast<HDefaultClientDevice*>(existingDevice->rootDevice()); existingDevice->addLocations(newRootDevice->locations()); return false; } if (q_ptr->acceptRootDevice(newRootDevice) == HControlPoint::IgnoreDevice) { HLOG_DBG(QString("Device [%1] rejected").arg( newRootDevice->info().udn().toString())); return false; } newRootDevice->setParent(this); newRootDevice->startStatusNotifier(HDefaultClientDevice::All); bool ok = connect( newRootDevice, SIGNAL(statusTimeout(HDefaultClientDevice*)), this, SLOT(deviceExpired(HDefaultClientDevice*))); Q_ASSERT(ok); Q_UNUSED(ok) if (!m_deviceStorage.addRootDevice(newRootDevice)) { HLOG_WARN(QString( "Failed to add root device [UDN: %1]: %2").arg( newRootDevice->info().udn().toSimpleUuid(), m_deviceStorage.lastError())); return false; } emit q_ptr->rootDeviceOnline(newRootDevice); return true; }
/******************************************************************************* * DeviceBuildTask ******************************************************************************/ DeviceBuildTask::~DeviceBuildTask() { HLOG2(H_AT, H_FUN, m_owner->m_loggingIdentifier); if (m_createdDevice.data()) { m_createdDevice->deleteLater(); } m_createdDevice.take(); }
void HDeviceHostHttpServer::incomingUnsubscriptionRequest( HMessagingInfo* mi, const HUnsubscribeRequest& usreq) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG("Unsubscription received."); bool ok = m_eventNotifier.removeSubscriber(usreq); mi->setKeepAlive(false); m_httpHandler->send( mi, HHttpMessageCreator::createResponse(ok ? Ok : PreconditionFailed, *mi)); }
HDeviceHostHttpServer::~HDeviceHostHttpServer() { HLOG2(H_AT, H_FUN, m_loggingIdentifier); QList<QPair<QPointer<HHttpAsyncOperation>, HOpInfo> >::iterator it = m_ops.begin(); for(; it != m_ops.end(); ++it) { if (it->first) { it->first->deleteLater(); } } }
qint32 HRenderingControlService::setLoudness( quint32 instanceId, const HChannel& channel, bool loudnessOn) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } return mediaConnection->setLoudness(channel, loudnessOn); }
qint32 HRenderingControlService::setVolumeDB( quint32 instanceId, const HChannel& channel, qint16 desiredVolumeDb) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } return mediaConnection->setVolumeDb(channel, desiredVolumeDb); }
qint32 HRenderingControlService::setVerticalKeystone( quint32 instanceId, qint16 desiredVerticalKeyStone) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } return mediaConnection->setVerticalKeystone(desiredVerticalKeyStone); }
qint32 HRenderingControlService::setColorTemperature( quint32 instanceId, quint16 desiredColorTemperature) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } return mediaConnection->setRcsValue( HRendererConnectionInfo::ColorTemperature, desiredColorTemperature); }
qint32 HRenderingControlService::setBlueVideoBlackLevel( quint32 instanceId, quint16 desiredBlueVideoBlackLevel) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } return mediaConnection->setRcsValue( HRendererConnectionInfo::BlueVideoBlackLevel, desiredBlueVideoBlackLevel); }
bool HControlPointPrivate::processDeviceOffline( const HResourceUnavailable& msg, const HEndpoint& /*source*/, HControlPointSsdpHandler* /*origin*/) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); Q_ASSERT(thread() == QThread::currentThread()); HDefaultClientDevice* device = static_cast<HDefaultClientDevice*>( m_deviceStorage.searchDeviceByUdn(msg.usn().udn(), AllDevices)); if (!device) { // the device is not known by us. // note that even service announcements contain the "UDN", which identifies // the device that contains them. return true; } if (device->deviceStatus()->online()) { HLOG_INFO(QString("Resource [%1] is unavailable.").arg( msg.usn().resourceType().toString())); // according to the UDA v1.1 specification, if a bye bye message of any kind // is received, the control point can assume that nothing in that // device tree is available anymore HDefaultClientDevice* root = static_cast<HDefaultClientDevice*>(device->rootDevice()); Q_ASSERT(root); root->deviceStatus()->setOnline(false); m_eventSubscriber->remove(root, true); root->clearLocations(); root->stopStatusNotifier(HDefaultClientDevice::All); emit q_ptr->rootDeviceOffline(root); } return true; }
qint32 HRenderingControlService::getColorTemperature( quint32 instanceId, quint16* currentColorTemperature) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } *currentColorTemperature = mediaConnection->rendererConnectionInfo()->rcsValue(HRendererConnectionInfo::ColorTemperature); return UpnpSuccess; }
bool HDataRetriever::retrieveDeviceDescription( const QUrl& deviceLocation, QString* data) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG(QString( "Attempting to fetch a device description from: [%1]").arg( deviceLocation.toString())); QByteArray tmp; if (!retrieveData(deviceLocation, QUrl(), &tmp)) { return false; } *data = QString::fromUtf8(tmp); return true; }
qint32 HRenderingControlService::getVerticalKeystone( quint32 instanceId, qint16* currentVerticalKeyStone) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } *currentVerticalKeyStone = mediaConnection->rendererConnectionInfo()->verticalKeystone(); return UpnpSuccess; }
/******************************************************************************* * HControlPoint ******************************************************************************/ HControlPoint::HControlPoint(QObject* parent) : QObject(parent), h_ptr(new HControlPointPrivate()) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); h_ptr->m_configuration.reset(new HControlPointConfiguration()); h_ptr->setParent(this); h_ptr->q_ptr = this; bool ok = connect( h_ptr->m_nam, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*))); Q_ASSERT(ok); Q_UNUSED(ok) }
void HControlPointPrivate::deviceExpired(HDefaultClientDevice* source) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); Q_ASSERT(thread() == QThread::currentThread()); // according to the UDA v1.1 a "device tree" (root, embedded and services) // are "timed out" only when every advertisement has timed out. source = static_cast<HDefaultClientDevice*>(source->rootDevice()); if (source->isTimedout(HDefaultClientDevice::All)) { source->deviceStatus()->setOnline(false); m_eventSubscriber->cancel( source, VisitThisRecursively, false); emit q_ptr->rootDeviceOffline(source); } }
bool HControlPointPrivate::processDeviceDiscovery( const Msg& msg, const HEndpoint& source, HControlPointSsdpHandler*) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); const HUdn& resourceUdn = msg.usn().udn(); HDefaultClientDevice* device = static_cast<HDefaultClientDevice*>( m_deviceStorage.searchDeviceByUdn(msg.usn().udn(), AllDevices)); if (device) { // according to the UDA v1.1 spec, if a control point receives an // alive announcement of any type for a device tree, the control point // can assume that all devices and services are available. // ==> reset timeouts for entire device tree and all services. device = static_cast<HDefaultClientDevice*>(device->rootDevice()); device->startStatusNotifier(HDefaultClientDevice::All); // it cannot be that only some embedded device is available at certain // interface, since the device description is always fetched from the // the location that the root device specifies ==> the entire device // tree has to be available at that location. if (device->addLocation(msg.location())) { HLOG_DBG(QString("Existing device [%1] now available at [%2]").arg( resourceUdn.toString(), msg.location().toString())); } if (!device->deviceStatus()->online()) { device->deviceStatus()->setOnline(true); emit q_ptr->rootDeviceOnline(device); processDeviceOnline(device, false); } return true; } // it does not matter if the device is an embedded device, since the // location of the device always points to the root device's description // and the internal device model is built of that. Hence, any advertisement // will do to build the entire model correctly. DeviceBuildTask* dbp = m_deviceBuildTasks.get(msg); if (dbp) { if (!dbp->m_locations.contains(msg.location())) { dbp->m_locations.push_back(msg.location()); } return true; } if (!q_ptr->acceptResource(msg.usn(), source)) { HLOG_DBG(QString("Resource advertisement [%1] rejected").arg( msg.usn().toString())); return true; } DeviceBuildTask* newBuildTask = new DeviceBuildTask(this, msg); newBuildTask->setAutoDelete(false); m_deviceBuildTasks.add(newBuildTask); bool ok = connect( newBuildTask, SIGNAL(done(Herqq::Upnp::HUdn)), this, SLOT(deviceModelBuildDone(Herqq::Upnp::HUdn))); Q_ASSERT(ok); Q_UNUSED(ok) HLOG_INFO(QString( "New resource [%1] is available @ [%2]. " "Attempting to build the device model.").arg( msg.usn().toString(), msg.location().toString())); m_threadPool->start(newBuildTask); return true; }
void HDeviceHostHttpServer::incomingControlRequest( HMessagingInfo* mi, const HInvokeActionRequest& invokeActionRequest) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG(QString("Control message to [%1] received.").arg( invokeActionRequest.soapAction())); QUuid udn = extractUdn(invokeActionRequest.serviceUrl()); HServerDevice* device = !udn.isNull() ? m_deviceStorage.searchDeviceByUdn(HUdn(udn), AllDevices) : 0; HServerService* service = 0; if (!device) { // the request did not have the UDN prefix, which means that either // 1) the request was for a ControlURL that was defined as an absolute URL // in the device description or // 2) the request is invalid service = m_deviceStorage.searchServiceByControlUrl( invokeActionRequest.serviceUrl()); if (!service) { HLOG_WARN(QString( "Ignoring invalid action invocation to: [%1].").arg( invokeActionRequest.serviceUrl().toString())); mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( BadRequest, *mi)); return; } } else if (!service) { service = m_deviceStorage.searchServiceByControlUrl( device, extractRequestExludingUdn(invokeActionRequest.serviceUrl())); } if (!service) { HLOG_WARN(QString("Ignoring invalid action invocation to: [%1].").arg( invokeActionRequest.serviceUrl().toString())); mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( BadRequest, *mi)); return; } const QtSoapMessage* soapMsg = invokeActionRequest.soapMsg(); const QtSoapType& method = soapMsg->method(); if (!method.isValid()) { HLOG_WARN("Invalid control method."); mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( BadRequest, *mi)); return; } HServerAction* action = service->actions().value(method.name().name()); if (!action) { HLOG_WARN(QString("The service has no action named [%1].").arg( method.name().name())); mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( *mi, UpnpInvalidArgs, soapMsg->toXmlString())); return; } HActionArguments iargs = action->info().inputArguments(); HActionArguments::iterator it = iargs.begin(); for(; it != iargs.end(); ++it) { HActionArgument iarg = *it; const QtSoapType& arg = method[iarg.name()]; if (!arg.isValid()) { mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( *mi, UpnpInvalidArgs, soapMsg->toXmlString())); return; } if (!iarg.setValue( HUpnpDataTypes::convertToRightVariantType( arg.value().toString(), iarg.dataType()))) { mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( *mi, UpnpInvalidArgs, soapMsg->toXmlString())); return; } } HActionArguments outArgs = action->info().outputArguments(); qint32 retVal = action->invoke(iargs, &outArgs); if (retVal != UpnpSuccess) { mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( *mi, retVal, soapMsg->toXmlString())); return; } QtSoapNamespaces::instance().registerNamespace( "u", service->info().serviceType().toString()); QtSoapMessage soapResponse; soapResponse.setMethod(QtSoapQName( QString("%1%2").arg(action->info().name(), "Response"), service->info().serviceType().toString())); foreach(const HActionArgument& oarg, outArgs) { QtSoapType* soapArg = new SoapType(oarg.name(), oarg.dataType(), oarg.value()); soapResponse.addMethodArgument(soapArg); }
bool HControlPoint::init() { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); Q_ASSERT_X( thread() == QThread::currentThread(), H_AT, "The control point has to be initialized in the thread in which it is " "currently located."); if (h_ptr->m_state == HControlPointPrivate::Initialized) { setError( AlreadyInitializedError, "The control point is already initialized"); return false; } Q_ASSERT(h_ptr->m_state == HControlPointPrivate::Uninitialized); bool ok = true; const QList<QHostAddress> addrs = h_ptr->m_configuration->networkAddressesToUse(); h_ptr->m_state = HControlPointPrivate::Initializing; HLOG_INFO("ControlPoint initializing."); h_ptr->m_eventSubscriber = new HEventSubscriptionManager(h_ptr); ok = connect( h_ptr->m_eventSubscriber, SIGNAL(subscribed(Herqq::Upnp::HClientService*)), this, SIGNAL(subscriptionSucceeded(Herqq::Upnp::HClientService*))); ok = connect( h_ptr->m_eventSubscriber, SIGNAL(subscriptionFailed(Herqq::Upnp::HClientService*)), this, SIGNAL(subscriptionFailed(Herqq::Upnp::HClientService*))); Q_ASSERT(ok); ok = connect( h_ptr->m_eventSubscriber, SIGNAL(unsubscribed(Herqq::Upnp::HClientService*)), h_ptr, SLOT(unsubscribed(Herqq::Upnp::HClientService*))); Q_ASSERT(ok); h_ptr->m_server = new ControlPointHttpServer(h_ptr); if (!doInit()) { // it is assumed that the derived class filled the error and // error description ok = false; goto end; } if (!h_ptr->m_server->init(convertHostAddressesToEndpoints(addrs))) { setError(CommunicationsError, "Failed to start HTTP server"); ok = false; goto end; } foreach(const QHostAddress& ha, addrs) { quint32 netwAddr; ok = HSysInfo::instance().localNetwork(ha, &netwAddr); Q_ASSERT(ok); HControlPointSsdpHandler* ssdp = new HControlPointSsdpHandler(h_ptr); if (!ssdp->init(ha)) { delete ssdp; setError(CommunicationsError, "Failed to start SSDP"); ok = false; goto end; } h_ptr->m_ssdps.append(qMakePair(netwAddr, ssdp)); }
void HDeviceHostHttpServer::incomingSubscriptionRequest( HMessagingInfo* mi, const HSubscribeRequest& sreq) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG("Subscription received."); QUuid udn = extractUdn(sreq.eventUrl()); HServerDevice* device = !udn.isNull() ? m_deviceStorage.searchDeviceByUdn(HUdn(udn), AllDevices) : 0; HServerService* service = 0; if (!device) { // the request did not have the UDN prefix, which means that either // 1) the request was for a EventUrl that was defined as an absolute URL // in the device description or // 2) the request is invalid service = m_deviceStorage.searchServiceByEventUrl(sreq.eventUrl()); if (!service) { HLOG_WARN(QString( "Ignoring invalid event subscription to: [%1].").arg( sreq.eventUrl().toString())); mi->setKeepAlive(false); m_httpHandler->send( mi, HHttpMessageCreator::createResponse(BadRequest, *mi)); return; } } else if (!service) { service = m_deviceStorage.searchServiceByEventUrl( device, extractRequestExludingUdn(sreq.eventUrl())); } if (!service) { HLOG_WARN(QString("Subscription defined as [%1] is invalid.").arg( sreq.eventUrl().path())); mi->setKeepAlive(false); m_httpHandler->send( mi, HHttpMessageCreator::createResponse(BadRequest, *mi)); return; } // The UDA v1.1 does not specify what to do when a subscription is received // to a service that is not evented. A "safe" route was taken here and // all subscriptions are accepted rather than returning some error. However, // in such a case the timeout is adjusted to a day and no events are ever sent. HSid sid; StatusCode sc; if (sreq.isRenewal()) { sc = m_eventNotifier.renewSubscription(sreq, &sid); } else { sc = m_eventNotifier.addSubscriber(service, sreq, &sid); } if (sc != Ok) { mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse(sc, *mi)); return; } HServiceEventSubscriber* subscriber = m_eventNotifier.remoteClient(sid); HSubscribeResponse response( subscriber->sid(), HSysInfo::instance().herqqProductTokens(), subscriber->timeout()); HHttpAsyncOperation* op = m_httpHandler->send(mi, HHttpMessageCreator::create(response, *mi)); if (op) { HOpInfo opInfo(service, sreq, subscriber); m_ops.append(qMakePair(QPointer<HHttpAsyncOperation>(op), opInfo)); } }
qint32 HRenderingControlService::getStateVariables( quint32 instanceId, const QSet<QString>& stateVariableNames, QString* stateVariableValuePairs) { HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier); Q_ASSERT(stateVariableValuePairs); HRendererConnection* mediaConnection = m_owner->findConnectionByRcsId(instanceId); if (!mediaConnection) { return HRenderingControlInfo::InvalidInstanceId; } QString retVal; QXmlStreamWriter writer(&retVal); writer.setCodec("UTF-8"); writer.writeStartDocument(); writer.writeStartElement("stateVariableValuePairs"); writer.writeDefaultNamespace("urn:schemas-upnp-org:av:avs"); writer.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); writer.writeAttribute("xsi:schemaLocation", "urn:schemas-upnp-org:av:avs" \ "http://www.upnp.org/schemas/av/avs.xsd"); QSet<QString> stateVarNames; if (stateVariableNames.contains("*")) { stateVarNames = HRenderingControlInfo::stateVariablesSetupData().names(); QSet<QString>::iterator it = stateVarNames.begin(); for(; it != stateVarNames.end();) { if (it->startsWith("A_ARG") || *it == "LastChange" || *it == "PresetNameList") { it = stateVarNames.erase(it); } else { ++it; } } } else { stateVarNames = stateVariableNames; } foreach(QString svName, stateVarNames) { bool ok = false; svName = svName.trimmed(); if (HRendererConnectionInfo::hasChannelAssociated(svName)) { foreach(const HChannel& ch, HChannel::allChannels()) { QString value = mediaConnection->value(svName, ch, &ok); if (ok && !value.isEmpty()) { writer.writeStartElement("stateVariable"); writer.writeAttribute("variableName", svName); writer.writeAttribute("channel", ch.toString()); writer.writeCharacters(value); writer.writeEndElement(); } } }