/*---------------------------------------------------------------------- | PLT_DeviceData::GetDescription +---------------------------------------------------------------------*/ NPT_Result PLT_DeviceData::GetDescription(NPT_XmlElementNode* root, NPT_XmlElementNode** device_out) { NPT_XmlElementNode* device = new NPT_XmlElementNode("device"); if (device_out) *device_out = device; NPT_CHECK_SEVERE(root->AddChild(device)); // device properties NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "deviceType", m_DeviceType)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "friendlyName", m_FriendlyName)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "manufacturer", m_Manufacturer)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "manufacturerURL", m_ManufacturerURL)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelDescription", m_ModelDescription)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelName", m_ModelName)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelURL", m_ModelURL)); if (!m_ModelNumber.IsEmpty()) NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "modelNumber", m_ModelNumber)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "serialNumber", m_SerialNumber)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "UDN", "uuid:" + m_UUID)); if (!m_PresentationURL.IsEmpty()) { NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device, "presentationURL", m_PresentationURL)); } // Extra info not in UPnP specs NPT_CHECK(OnAddExtraInfo(device)); // DLNA support if (!m_DlnaDoc.IsEmpty()) { NPT_XmlElementNode* dlnadoc = new NPT_XmlElementNode("dlna", "X_DLNADOC"); NPT_CHECK_SEVERE(dlnadoc->SetNamespaceUri("dlna", "urn:schemas-dlna-org:device-1-0")); dlnadoc->AddText(m_DlnaDoc); device->AddChild(dlnadoc); } if (!m_DlnaCap.IsEmpty()) { NPT_XmlElementNode* dlnacap = new NPT_XmlElementNode("dlna", "X_DLNACAP"); NPT_CHECK_SEVERE(dlnacap->SetNamespaceUri("dlna", "urn:schemas-dlna-org:device-1-0")); dlnacap->AddText(m_DlnaCap); device->AddChild(dlnacap); } // icons if (m_Icons.GetItemCount()) { NPT_XmlElementNode* icons = new NPT_XmlElementNode("iconList"); NPT_CHECK_SEVERE(device->AddChild(icons)); for (NPT_Cardinal i=0; i<m_Icons.GetItemCount(); i++) { NPT_XmlElementNode* icon = new NPT_XmlElementNode("icon"); NPT_CHECK_SEVERE(icons->AddChild(icon)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "mimetype", m_Icons[i].m_MimeType)); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "width", NPT_String::FromInteger(m_Icons[i].m_Width))); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "height", NPT_String::FromInteger(m_Icons[i].m_Height))); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "depth", NPT_String::FromInteger(m_Icons[i].m_Depth))); NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon, "url", m_Icons[i].m_UrlPath)); } } // services NPT_XmlElementNode* services = new NPT_XmlElementNode("serviceList"); NPT_CHECK_SEVERE(device->AddChild(services)); NPT_CHECK_SEVERE(m_Services.ApplyUntil(PLT_GetDescriptionIterator<PLT_Service*>(services), NPT_UntilResultNotEquals(NPT_SUCCESS))); // PS3 support if (!m_AggregationFlags.IsEmpty()) { NPT_XmlElementNode* aggr = new NPT_XmlElementNode("av", "aggregationFlags"); NPT_CHECK_SEVERE(aggr->SetNamespaceUri("av", "urn:schemas-sonycom:av")); aggr->AddText(m_AggregationFlags); device->AddChild(aggr); } // embedded devices if (m_EmbeddedDevices.GetItemCount()) { NPT_XmlElementNode* deviceList = new NPT_XmlElementNode("deviceList"); NPT_CHECK_SEVERE(device->AddChild(deviceList)); NPT_CHECK_SEVERE(m_EmbeddedDevices.ApplyUntil( PLT_GetDescriptionIterator<PLT_DeviceDataReference>(deviceList), NPT_UntilResultNotEquals(NPT_SUCCESS))); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | CMediaCrawler::UpdateDidl +---------------------------------------------------------------------*/ NPT_String CMediaCrawler::UpdateDidl(const char* server_uuid, const NPT_String& didl, NPT_SocketInfo* info) { NPT_String new_didl; NPT_String str; NPT_XmlNode* node = NULL; NPT_XmlWriter writer; NPT_OutputStreamReference stream(new NPT_StringOutputStream(&new_didl)); NPT_LOG_FINE("Parsing Didl..."); NPT_XmlElementNode* tree = NULL; NPT_XmlParser parser; if (NPT_FAILED(parser.Parse(didl, node)) || !node || !node->AsElementNode()) { goto cleanup; } tree = node->AsElementNode(); NPT_LOG_FINE("Processing Didl xml..."); if (tree->GetTag().Compare("DIDL-Lite", true)) { goto cleanup; } // iterate through children NPT_Result res; for (NPT_List<NPT_XmlNode*>::Iterator children = tree->GetChildren().GetFirstItem(); children; children++) { NPT_XmlElementNode* child = (*children)->AsElementNode(); if (!child) continue; // object id remapping NPT_XmlAttribute* attribute_id; res = PLT_XmlHelper::GetAttribute(child, "id", attribute_id); if (NPT_SUCCEEDED(res) && attribute_id) { attribute_id->SetValue(FormatObjectId(server_uuid, attribute_id->GetValue())); } // parent ID remapping NPT_XmlAttribute* attribute_parent_id; res = PLT_XmlHelper::GetAttribute(child, "parentID", attribute_parent_id); if (NPT_SUCCEEDED(res)) { attribute_parent_id->SetValue(attribute_parent_id->GetValue().Compare("-1")?FormatObjectId(server_uuid, attribute_parent_id->GetValue()):"0"); } // resources remapping NPT_Array<NPT_XmlElementNode*> res; PLT_XmlHelper::GetChildren(child, res, "res"); if (res.GetItemCount() > 0) { for (unsigned int i=0; i<res.GetItemCount(); i++) { NPT_XmlElementNode* resource = res[i]; NPT_XmlAttribute* attribute_prot; const NPT_String* url; if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(resource, "protocolInfo", attribute_prot)) && (url = resource->GetText())) { // special case for Windows Media Connect // When a browse is done on the same machine, WMC uses localhost // instead of the IP for all resources urls which means we cannot advertise that // since it would be useless for a remote device // so we try to replace it with the right IP address by looking at which interface we received the // initial browse request on to make sure the remote device will be able to access the modified resource // urls (in case the local PC has more than 1 NICs) // replace the url NPT_List<NPT_XmlNode*>& children = resource->GetChildren(); NPT_HttpUrl http_url(NPT_Uri::PercentDecode(*url)); if ((http_url.GetHost() == "localhost" || http_url.GetHost() == "127.0.0.1") && info) { if (info->local_address.GetIpAddress().AsLong()) { http_url.SetHost(info->local_address.GetIpAddress().ToString()); // replace text children.Apply(NPT_ObjectDeleter<NPT_XmlNode>()); children.Clear(); resource->AddText(http_url.ToString()); url = resource->GetText(); } } CStreamHandler* handler = NULL; NPT_Result res = NPT_ContainerFind(m_StreamHandlers, CStreamHandlerFinder(attribute_prot->GetValue(), *url), handler); if (NPT_SUCCEEDED(res)) { handler->ModifyResource(resource); } } } } } // serialize modified node into new didl writer.Serialize(*node, *stream); delete node; return new_didl; cleanup: delete node; return didl; }