/*---------------------------------------------------------------------- | PLT_MediaBrowser::OnSearchResponse +---------------------------------------------------------------------*/ NPT_Result PLT_MediaBrowser::OnSearchResponse(NPT_Result res, PLT_DeviceDataReference& device, PLT_ActionReference& action, void* userdata) { NPT_String value; PLT_BrowseInfo info; NPT_String unescaped; if (NPT_FAILED(res) || action->GetErrorCode() != 0) { goto bad_action; } if (NPT_FAILED(action->GetArgumentValue("ContainerId", info.object_id))) { goto bad_action; } if (NPT_FAILED(action->GetArgumentValue("UpdateID", value)) || value.GetLength() == 0 || NPT_FAILED(value.ToInteger(info.uid))) { goto bad_action; } if (NPT_FAILED(action->GetArgumentValue("NumberReturned", value)) || value.GetLength() == 0 || NPT_FAILED(value.ToInteger(info.nr))) { goto bad_action; } if (NPT_FAILED(action->GetArgumentValue("TotalMatches", value)) || value.GetLength() == 0 || NPT_FAILED(value.ToInteger(info.tm))) { goto bad_action; } if (NPT_FAILED(action->GetArgumentValue("Result", value)) || value.GetLength() == 0) { goto bad_action; } if (NPT_FAILED(PLT_Didl::FromDidl(value, info.items))) { goto bad_action; } if (m_Delegate) m_Delegate->OnSearchResult(NPT_SUCCESS, device, &info, userdata); return NPT_SUCCESS; bad_action: if (m_Delegate) m_Delegate->OnSearchResult(NPT_FAILURE, device, NULL, userdata); return NPT_FAILURE; }
/*---------------------------------------------------------------------- | PLT_MediaContainer::FromDidl +---------------------------------------------------------------------*/ NPT_Result PLT_MediaContainer::FromDidl(NPT_XmlElementNode* entry) { NPT_String str; /* reset first */ Reset(); // check entry type if (entry->GetTag().Compare("Container", true) != 0) return NPT_ERROR_INTERNAL; // check if item is searchable (is default true?) if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "searchable", str, "", 5))) { m_Searchable = PLT_Service::IsTrue(str); } // look for childCount if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(entry, "childCount", str, "", 256))) { NPT_UInt32 count; NPT_CHECK_SEVERE(str.ToInteger(count)); m_ChildrenCount = count; } // upnp:searchClass child elements NPT_Array<NPT_XmlElementNode*> children; PLT_XmlHelper::GetChildren(entry, children, "upnp:searchClass"); for (NPT_Cardinal i=0; i<children.GetItemCount(); i++) { PLT_SearchClass search_class; // extract url if (children[i]->GetText() == NULL) { NPT_LOG_WARNING_1("No searchClass text found in: %s", (const char*)PLT_XmlHelper::Serialize(*children[i])); continue; } // DLNA 7.3.17.4 search_class.type = children[i]->GetText()->SubString(0, 256); // extract optional attribute name PLT_XmlHelper::GetAttribute(children[i], "name", search_class.friendly_name); // includeDerived property if (NPT_FAILED(PLT_XmlHelper::GetAttribute(children[i], "includeDerived", str))) { NPT_LOG_WARNING_1("No required attribute searchClass@includeDerived found in: %s", (const char*)PLT_XmlHelper::Serialize(*children[i])); continue; } search_class.include_derived = PLT_Service::IsTrue(str); m_SearchClasses.Add(search_class); } return PLT_MediaObject::FromDidl(entry); }
/*---------------------------------------------------------------------- | NPT_LogConsoleHandler::Create +---------------------------------------------------------------------*/ NPT_Result NPT_LogConsoleHandler::Create(const char* logger_name, NPT_LogHandler*& handler) { /* compute a prefix for the configuration of this handler */ NPT_String logger_prefix = logger_name; logger_prefix += ".ConsoleHandler"; /* allocate a new object */ NPT_LogConsoleHandler* instance = new NPT_LogConsoleHandler(); handler = instance; /* configure the object */ NPT_String* colors; instance->m_UseColors = NPT_LOG_CONSOLE_HANDLER_DEFAULT_COLOR_MODE; colors = LogManager.GetConfigValue(logger_prefix,".colors"); if (colors) { if (NPT_LogManager::ConfigValueIsBooleanTrue(*colors)) { instance->m_UseColors = true; } else if (NPT_LogManager::ConfigValueIsBooleanFalse(*colors)) { instance->m_UseColors = false; } } NPT_String* outputs; instance->m_Outputs = OUTPUT_TO_DEBUG; outputs = LogManager.GetConfigValue(logger_prefix,".outputs"); if (outputs) { outputs->ToInteger(instance->m_Outputs, true); } NPT_String* filter; instance->m_FormatFilter = 0; filter = LogManager.GetConfigValue(logger_prefix,".filter"); if (filter) { filter->ToInteger(instance->m_FormatFilter, true); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpHelper::GetContentLength +---------------------------------------------------------------------*/ NPT_Result PLT_HttpHelper::GetContentLength(NPT_HttpMessage* message, NPT_Size& len) { long out; NPT_String value; if (NPT_FAILED(message->GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONTENT_LENGTH, value))) { return NPT_FAILURE; } NPT_Result res = value.ToInteger(out); len = out; return res; }
/*---------------------------------------------------------------------- | PLT_Didl::ParseTimeStamp +---------------------------------------------------------------------*/ NPT_Result PLT_Didl::ParseTimeStamp(const NPT_String& timestamp, NPT_UInt32& seconds) { // assume a timestamp in the format HH:MM:SS.FFF int separator; NPT_String str = timestamp; NPT_UInt32 value; // reset output params first seconds = 0; // remove milliseconds first if any if ((separator = str.ReverseFind('.')) != -1) { str = str.Left(separator); } // look for next separator if ((separator = str.ReverseFind(':')) == -1) return NPT_FAILURE; // extract seconds NPT_CHECK_WARNING(str.SubString(separator+1).ToInteger(value)); seconds = value; str = str.Left(separator); // look for next separator if ((separator = str.ReverseFind(':')) == -1) return NPT_FAILURE; // extract minutes NPT_CHECK_WARNING(str.SubString(separator+1).ToInteger(value)); seconds += 60*value; str = str.Left(separator); // extract hours NPT_CHECK_WARNING(str.ToInteger(value)); seconds += 3600*value; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_FileMediaServer::OnBrowseDirectChildren +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnBrowseDirectChildren(PLT_ActionReference& action, const char* object_id, const NPT_HttpRequestContext& context) { /* locate the file from the object ID */ NPT_String dir; if (NPT_FAILED(GetFilePath(object_id, dir))) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - ObjectID not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } /* retrieve the item type */ NPT_FileInfo info; NPT_Result res = NPT_File::GetInfo(dir, &info); if (NPT_FAILED(res)) { /* Object does not exist */ NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN failed for item %s", dir.GetChars()); action->SetError(800, "Can't retrieve info " + dir); return NPT_FAILURE; } if (info.m_Type != NPT_FileInfo::FILE_TYPE_DIRECTORY) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN not allowed on an item."); action->SetError(710, "item is not a container."); return NPT_FAILURE; } NPT_String filter; NPT_String startingInd; NPT_String reqCount; NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); NPT_UInt32 start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { action->SetError(412, "Precondition failed"); return NPT_FAILURE; } NPT_List<NPT_String> entries; res = NPT_File::ListDirectory(dir, entries, 0, 0); if (NPT_FAILED(res)) { NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowseDirectChildren - failed to open dir %s", (const char*) dir); return res; } unsigned long cur_index = 0; unsigned long num_returned = 0; unsigned long total_matches = 0; NPT_String didl = didl_header; PLT_MediaObjectReference item; for (NPT_List<NPT_String>::Iterator it = entries.GetFirstItem(); it; ++it) { NPT_String& filename = *it; item = BuildFromFilePath( NPT_FilePath::Create(dir, filename), true, &context.GetLocalAddress()); if (!item.IsNull()) { if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) { NPT_String tmp; NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp)); didl += tmp; num_returned++; } cur_index++; total_matches++; } }; didl += didl_footer; NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl)); NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned))); NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches))); // 0 means we don't know how many we have but most browsers don't like that!! NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1")); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_LogFileHandler::Create +---------------------------------------------------------------------*/ NPT_Result NPT_LogFileHandler::Create(const char* logger_name, NPT_LogHandler*& handler) { /* compute a prefix for the configuration of this handler */ NPT_String logger_prefix = logger_name; logger_prefix += ".FileHandler"; /* allocate a new object */ NPT_LogFileHandler* instance = new NPT_LogFileHandler(); handler = instance; /* filename */ NPT_String* filename_conf = LogManager.GetConfigValue(logger_prefix, ".filename"); if (filename_conf) { instance->m_Filename = *filename_conf; } else if (logger_name[0]) { NPT_String filename_synth = logger_name; filename_synth += ".log"; instance->m_Filename = filename_synth; } else { /* default name for the root logger */ instance->m_Filename = NPT_CONFIG_DEFAULT_LOG_FILE_HANDLER_FILENAME; } /* always flush flag */ NPT_String* flush = LogManager.GetConfigValue(logger_prefix, ".flush"); if (flush && NPT_LogManager::ConfigValueIsBooleanTrue(*flush)) { instance->m_Flush = true; } else { instance->m_Flush = false; } /* append mode */ instance->m_Append = true; NPT_String* append_mode = LogManager.GetConfigValue(logger_prefix, ".append"); if (append_mode && NPT_LogManager::ConfigValueIsBooleanFalse(*append_mode)) { instance->m_Append = false; } /* filter */ NPT_String* filter; instance->m_FormatFilter = 0; filter = LogManager.GetConfigValue(logger_prefix,".filter"); if (filter) { filter->ToInteger(instance->m_FormatFilter, true); } /* recycle */ NPT_String* recycle; instance->m_MaxFilesize = 0; recycle = LogManager.GetConfigValue(logger_prefix,".recycle"); if (recycle) { NPT_ParseInteger64(*recycle, instance->m_MaxFilesize, true); if (instance->m_MaxFilesize < NPT_LOG_FILE_HANDLER_MIN_RECYCLE_SIZE) { instance->m_MaxFilesize = NPT_LOG_FILE_HANDLER_MIN_RECYCLE_SIZE; } } /* open the log file */ return instance->Open(instance->m_Append); }
/*---------------------------------------------------------------------- | PLT_MediaServer::OnSearch +---------------------------------------------------------------------*/ NPT_Result PLT_MediaServer::OnSearch(PLT_ActionReference& action, const PLT_HttpRequestContext& context) { NPT_COMPILER_UNUSED(context); NPT_Result res; NPT_String container_id; NPT_String search; NPT_String filter; NPT_String start; NPT_String count; NPT_String sort; NPT_List<NPT_String> sort_list; if (NPT_FAILED(action->GetArgumentValue("ContainerId", container_id)) || NPT_FAILED(action->GetArgumentValue("SearchCriteria", search)) || NPT_FAILED(action->GetArgumentValue("Filter", filter)) || NPT_FAILED(action->GetArgumentValue("StartingIndex", start)) || NPT_FAILED(action->GetArgumentValue("RequestedCount", count)) || NPT_FAILED(action->GetArgumentValue("SortCriteria", sort))) { NPT_LOG_WARNING("Missing arguments"); action->SetError(402, "Invalid args"); return NPT_SUCCESS; } /* convert index and counts to int */ NPT_UInt32 starting_index, requested_count; if (NPT_FAILED(start.ToInteger(starting_index)) || NPT_FAILED(count.ToInteger(requested_count))) { NPT_LOG_WARNING_2("Invalid arguments (%s, %s)", start.GetChars(), count.GetChars()); action->SetError(402, "Invalid args"); return NPT_FAILURE; } /* parse sort criteria */ if (NPT_FAILED(ParseSort(sort, sort_list))) { NPT_LOG_WARNING_1("Unsupported or invalid sort criteria error (%s)", sort.GetChars()); action->SetError(709, "Unsupported or invalid sort criteria error"); return NPT_FAILURE; } NPT_LOG_INFO_5("Processing Search from %s with id=\"%s\", search=\"%s\", start=%d, count=%d", (const char*)context.GetRemoteAddress().GetIpAddress().ToString(), (const char*)container_id, (const char*)search, starting_index, requested_count); if (search.IsEmpty() || search == "*") { res = OnBrowseDirectChildren( action, container_id, filter, starting_index, requested_count, sort, context); } else { res = OnSearchContainer( action, container_id, search, filter, starting_index, requested_count, sort, context); } if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) { action->SetError(800, "Internal error"); } return res; }
/*---------------------------------------------------------------------- | PLT_MediaServer::OnBrowse +---------------------------------------------------------------------*/ NPT_Result PLT_MediaServer::OnBrowse(PLT_ActionReference& action, const PLT_HttpRequestContext& context) { NPT_Result res; NPT_String object_id; NPT_String browse_flag_val; NPT_String filter; NPT_String start; NPT_String count; NPT_String sort; NPT_List<NPT_String> sort_list; if (NPT_FAILED(action->GetArgumentValue("ObjectId", object_id)) || NPT_FAILED(action->GetArgumentValue("BrowseFlag", browse_flag_val)) || NPT_FAILED(action->GetArgumentValue("Filter", filter)) || NPT_FAILED(action->GetArgumentValue("StartingIndex", start)) || NPT_FAILED(action->GetArgumentValue("RequestedCount", count)) || NPT_FAILED(action->GetArgumentValue("SortCriteria", sort))) { NPT_LOG_WARNING("Missing arguments"); action->SetError(402, "Invalid args"); return NPT_SUCCESS; } /* extract flag */ BrowseFlags flag; if (NPT_FAILED(ParseBrowseFlag(browse_flag_val, flag))) { /* error */ NPT_LOG_WARNING_1("BrowseFlag value not allowed (%s)", (const char*)browse_flag_val); action->SetError(402, "Invalid args"); return NPT_SUCCESS; } /* convert index and counts to int */ NPT_UInt32 starting_index, requested_count; if (NPT_FAILED(start.ToInteger(starting_index)) || NPT_FAILED(count.ToInteger(requested_count)) || PLT_Didl::ConvertFilterToMask(filter) == 0) { NPT_LOG_WARNING_3("Invalid arguments (%s, %s, %s)", start.GetChars(), count.GetChars(), filter.GetChars()); action->SetError(402, "Invalid args"); return NPT_FAILURE; } /* parse sort criteria for validation */ if (NPT_FAILED(ParseSort(sort, sort_list))) { NPT_LOG_WARNING_1("Unsupported or invalid sort criteria error (%s)", sort.GetChars()); action->SetError(709, "Unsupported or invalid sort criteria error"); return NPT_FAILURE; } NPT_LOG_FINE_6("Processing %s from %s with id=\"%s\", filter=\"%s\", start=%d, count=%d", (const char*)browse_flag_val, (const char*)context.GetRemoteAddress().GetIpAddress().ToString(), (const char*)object_id, (const char*)filter, starting_index, requested_count); /* Invoke the browse function */ if (flag == BROWSEMETADATA) { res = OnBrowseMetadata( action, object_id, filter, starting_index, requested_count, sort, context); } else { res = OnBrowseDirectChildren( action, object_id, filter, starting_index, requested_count, sort, context); } if (NPT_FAILED(res) && (action->GetErrorCode() == 0)) { action->SetError(800, "Internal error"); } return res; }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | PLT_FileMediaServer::OnBrowseDirectChildren +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnBrowseDirectChildren(PLT_ActionReference& action, const char* object_id, NPT_SocketInfo* info /* = NULL */) { /* locate the file from the object ID */ NPT_String dir; if (NPT_FAILED(GetFilePath(object_id, dir))) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - ObjectID not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } /* retrieve the item type */ NPT_DirectoryEntryInfo entry_info; NPT_Result res = NPT_DirectoryEntry::GetInfo(dir, entry_info); if (NPT_FAILED(res)) { /* Object does not exist */ action->SetError(800, "Can't retrieve info " + dir); return NPT_FAILURE; } if (entry_info.type != NPT_DIRECTORY_TYPE) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN not allowed on an item."); action->SetError(710, "item is not a container."); return NPT_FAILURE; } NPT_String filter; NPT_String startingInd; NPT_String reqCount; NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); unsigned long start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { return NPT_FAILURE; } NPT_String path = dir; if (!path.EndsWith(m_DirDelimiter)) { path += m_DirDelimiter; } /* start iterating through the directory */ NPT_Directory directory(path); NPT_String entryName; res = directory.GetNextEntry(entryName); if (NPT_FAILED(res)) { NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowseDirectChildren - failed to open dir %s", (const char*) path); return res; } unsigned long cur_index = 0; unsigned long num_returned = 0; unsigned long total_matches = 0; //unsigned long update_id = 0; NPT_String didl = didl_header; PLT_MediaObjectReference item; do { item = BuildFromFilePath(path + entryName, true, info); if (!item.IsNull()) { if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) { NPT_String tmp; NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp)); didl += tmp; num_returned++; } cur_index++; total_matches++; } res = directory.GetNextEntry(entryName); } while (NPT_SUCCEEDED(res)); didl += didl_footer; NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl)); NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned))); NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches))); NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1")); return NPT_SUCCESS; }