/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | CMediaCrawler::OnBrowseRoot +---------------------------------------------------------------------*/ NPT_Result CMediaCrawler::OnBrowseRoot(PLT_ActionReference& action) { NPT_String browseFlagValue; if (NPT_FAILED(action->GetArgumentValue("BrowseFlag", browseFlagValue))) { NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - invalid arguments."); return NPT_FAILURE; } /* extract browseFlag */ BrowseFlags browseFlag; if (NPT_FAILED(GetBrowseFlag(browseFlagValue, browseFlag))) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowseRoot - BrowseFlag value not allowed."); action->SetError(402,"Invalid BrowseFlag arg."); return NPT_FAILURE; } if (browseFlag == BROWSEMETADATA) { PLT_MediaContainer item; item.m_Title = "Root"; item.m_ParentID = "-1"; item.m_ObjectID = "0"; item.m_ChildrenCount = GetMediaServers().GetItemCount(); item.m_ObjectClass.type = "object.container"; /* convert item to didl */ NPT_String filter; action->GetArgumentValue("Filter", filter); NPT_String tmp; NPT_CHECK_SEVERE(PLT_Didl::ToDidl(item, filter, tmp)); /* add didl header and footer */ NPT_String didl = didl_header + tmp + didl_footer; action->SetArgumentValue("Result", didl); action->SetArgumentValue("NumberReturned", "1"); action->SetArgumentValue("TotalMatches", "1"); // update ID may be wrong here, it should be the one of the container? action->SetArgumentValue("UpdateId", "1"); // TODO: We need to keep track of the overall updateID of the CDS } else { NPT_String startingInd; NPT_String reqCount; NPT_String filter; NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); unsigned long start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { return NPT_FAILURE; } unsigned long cur_index = 0; unsigned long num_returned = 0; unsigned long total_matches = 0; //unsigned long update_id = 0; PLT_MediaContainer item; NPT_String tmp; NPT_String didl = didl_header; // populate a list of containers (one container per known servers) const NPT_Lock<PLT_DeviceDataReferenceList>& devices = GetMediaServers(); NPT_Lock<PLT_DeviceDataReferenceList>::Iterator entry = devices.GetFirstItem(); while (entry) { PLT_DeviceDataReference device = (*entry); item.m_Title = device->GetFriendlyName(); item.m_ObjectID = FormatObjectId(device->GetUUID(), "0"); item.m_ParentID = "0"; item.m_ObjectClass.type = "object.container"; if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) { NPT_CHECK_SEVERE(PLT_Didl::ToDidl(item, filter, tmp)); didl += tmp; num_returned++; } cur_index++; total_matches++; ++entry; } didl += didl_footer; action->SetArgumentValue("Result", didl); action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned)); action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches)); action->SetArgumentValue("UpdateId", "1"); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | CMediaCrawler::OnBrowseDevice +---------------------------------------------------------------------*/ NPT_Result CMediaCrawler::OnBrowseDevice(PLT_ActionReference& action, const char* server_uuid, const char* server_object_id, NPT_SocketInfo* info /* = NULL */) { NPT_Result res; PLT_DeviceDataReference device; { // look for device first const NPT_Lock<PLT_DeviceDataReferenceList>& devices = GetMediaServers(); //NPT_AutoLock lock(devices); if (NPT_FAILED(NPT_ContainerFind(devices, PLT_DeviceDataFinder(server_uuid), device))) { /* error */ NPT_LOG_WARNING("CMediaCrawler::OnBrowseDevice - device not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } } // look for args and convert them NPT_String browseFlagValue; NPT_String startingInd; NPT_String reqCount; NPT_String filter; NPT_String sort; NPT_CHECK_SEVERE(action->GetArgumentValue("BrowseFlag", browseFlagValue)); NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_CHECK_SEVERE(action->GetArgumentValue("SortCriteria", sort)); unsigned long start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { return NPT_FAILURE; } // create a container for our result // this will be filled in by OnBrowseResponse CMediaCrawlerBrowseInfoReference browse_info(new CMediaCrawlerBrowseInfo()); browse_info->shared_var.SetValue(0); // send off the browse packet. Note that this will // not block. The shared variable is used to block // until the response has been received. res = Browse(device, server_object_id, start_index, req_count, (browseFlagValue == "BrowseMetadata")?1:0, filter, sort, new CMediaCrawlerBrowseInfoReference(browse_info)); NPT_CHECK_SEVERE(res); // wait 30 secs for response res = browse_info->shared_var.WaitUntilEquals(1, 30000); NPT_CHECK_SEVERE(res); // did the browse fail? if (NPT_FAILED(browse_info->res)) { action->SetError(browse_info->code, ""); return NPT_FAILURE; } action->SetArgumentValue("Result", UpdateDidl(server_uuid, browse_info->didl, info)); action->SetArgumentValue("NumberReturned", browse_info->nr); action->SetArgumentValue("TotalMatches", browse_info->tm); action->SetArgumentValue("UpdateId", browse_info->uid); action->SetArgumentValue("ObjectID", FormatObjectId(server_uuid, browse_info->object_id)); return NPT_SUCCESS; }
std::string QuickIndexImpl::GetEntryPath( const Entry *entry ) { return FormatObjectId(entry->oid); }