/*---------------------------------------------------------------------- | 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_AutoLock lock((NPT_Mutex&)devices); 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, const NPT_HttpRequestContext& context) { NPT_Result res; PLT_DeviceDataReference device; { // look for device first const NPT_Lock<PLT_DeviceDataReferenceList>& devices = GetMediaServers(); NPT_AutoLock lock((NPT_Mutex&)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, &context.GetLocalAddress())); 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; }
/*---------------------------------------------------------------------- | NPT_BufferedInputStream::Read +---------------------------------------------------------------------*/ NPT_Result NPT_BufferedInputStream::Read(void* buffer, NPT_Size bytes_to_read, NPT_Size* bytes_read) { NPT_Result result = NPT_SUCCESS; NPT_Size total_read = 0; NPT_Size buffered; // check for a possible shortcut if (bytes_to_read == 0) return NPT_SUCCESS; // skip a newline char if needed if (m_SkipNewline) { m_SkipNewline = false; result = Read(buffer, 1, NULL); if (NPT_FAILED(result)) goto done; NPT_Byte c = *(NPT_Byte*)buffer; if (c != '\n') { buffer = (void*)((NPT_Byte*)buffer+1); --bytes_to_read; total_read = 1; } } // compute how much is buffered buffered = m_Buffer.valid-m_Buffer.offset; if (bytes_to_read > buffered) { // there is not enough in the buffer, take what's there if (buffered) { NPT_CopyMemory(buffer, m_Buffer.data + m_Buffer.offset, buffered); buffer = (void*)((NPT_Byte*)buffer+buffered); m_Buffer.offset += buffered; bytes_to_read -= buffered; total_read += buffered; goto done; } // read the rest from the source if (m_Buffer.size == 0) { // unbuffered mode, read directly into the supplied buffer if (m_Buffer.data != NULL) ReleaseBuffer(); // cleanup if necessary NPT_Size local_read = 0; result = m_Source->Read(buffer, bytes_to_read, &local_read); if (NPT_SUCCEEDED(result)) { total_read += local_read; } goto done; } else { // refill the buffer result = FillBuffer(); if (NPT_FAILED(result)) goto done; buffered = m_Buffer.valid; if (bytes_to_read > buffered) bytes_to_read = buffered; } } // get what we can from the buffer if (bytes_to_read) { NPT_CopyMemory(buffer, m_Buffer.data + m_Buffer.offset, bytes_to_read); m_Buffer.offset += bytes_to_read; total_read += bytes_to_read; } done: m_Position += total_read; if (bytes_read) *bytes_read = total_read; if (result == NPT_ERROR_EOS) { m_Eos = true; if (total_read != 0) { // we have reached the end of the stream, but we have read // some chars, so do not return EOS now return NPT_SUCCESS; } } return result; }
/*---------------------------------------------------------------------- | CUPnPRenderer::UpdateState +---------------------------------------------------------------------*/ void CUPnPRenderer::UpdateState() { NPT_AutoLock lock(m_state); PLT_Service *avt; if (NPT_FAILED(FindServiceByType("urn:schemas-upnp-org:service:AVTransport:1", avt))) return; /* don't update state while transitioning */ NPT_String state; avt->GetStateVariableValue("TransportState", state); if(state == "TRANSITIONING") return; avt->SetStateVariable("TransportStatus", "OK"); if (g_application.IsPlaying() || g_application.IsPaused()) { avt->SetStateVariable("NumberOfTracks", "1"); avt->SetStateVariable("CurrentTrack", "1"); CStdString buffer = g_infoManager.GetCurrentPlayTime(TIME_FORMAT_HH_MM_SS); avt->SetStateVariable("RelativeTimePosition", buffer.c_str()); avt->SetStateVariable("AbsoluteTimePosition", buffer.c_str()); buffer = g_infoManager.GetDuration(TIME_FORMAT_HH_MM_SS); if (buffer.length() > 0) { avt->SetStateVariable("CurrentTrackDuration", buffer.c_str()); avt->SetStateVariable("CurrentMediaDuration", buffer.c_str()); } else { avt->SetStateVariable("CurrentTrackDuration", "00:00:00"); avt->SetStateVariable("CurrentMediaDuration", "00:00:00"); } } else if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) { avt->SetStateVariable("TransportState", "PLAYING"); avt->SetStateVariable("AVTransportURI" , g_infoManager.GetPictureLabel(SLIDE_FILE_PATH)); avt->SetStateVariable("CurrentTrackURI", g_infoManager.GetPictureLabel(SLIDE_FILE_PATH)); avt->SetStateVariable("TransportPlaySpeed", "1"); CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (slideshow) { CStdString index; index.Format("%d", slideshow->NumSlides()); avt->SetStateVariable("NumberOfTracks", index.c_str()); index.Format("%d", slideshow->CurrentSlide()); avt->SetStateVariable("CurrentTrack", index.c_str()); } avt->SetStateVariable("CurrentTrackMetadata", ""); avt->SetStateVariable("AVTransportURIMetaData", ""); } else { avt->SetStateVariable("TransportState", "STOPPED"); avt->SetStateVariable("TransportPlaySpeed", "1"); avt->SetStateVariable("NumberOfTracks", "0"); avt->SetStateVariable("CurrentTrack", "0"); avt->SetStateVariable("RelativeTimePosition", "00:00:00"); avt->SetStateVariable("AbsoluteTimePosition", "00:00:00"); avt->SetStateVariable("CurrentTrackDuration", "00:00:00"); avt->SetStateVariable("CurrentMediaDuration", "00:00:00"); } }
/*---------------------------------------------------------------------- | NPT_BufferedInputStream::ReadLine +---------------------------------------------------------------------*/ NPT_Result NPT_BufferedInputStream::ReadLine(char* buffer, NPT_Size size, NPT_Size* chars_read, bool break_on_cr) { NPT_Result result = NPT_SUCCESS; char* buffer_start = buffer; char* buffer_end = buffer_start+size-1; bool skip_newline = false; // check parameters if (buffer == NULL || size < 1) { if (chars_read) *chars_read = 0; return NPT_ERROR_INVALID_PARAMETERS; } // read until EOF or newline for (;;) { while (m_Buffer.offset != m_Buffer.valid) { // there is some data left in the buffer NPT_Byte c = m_Buffer.data[m_Buffer.offset++]; if (c == '\r') { if (break_on_cr) { skip_newline = true; goto done; } } else if (c == '\n') { if (m_SkipNewline && (buffer == buffer_start)) { continue; } goto done; } else { if (buffer == buffer_end) { result = NPT_ERROR_NOT_ENOUGH_SPACE; goto done; } *buffer++ = c; } } if (m_Buffer.size == 0 && !m_Eos) { // unbuffered mode if (m_Buffer.data != NULL) ReleaseBuffer(); while (NPT_SUCCEEDED(result = m_Source->Read(buffer, 1, NULL))) { if (*buffer == '\r') { if (break_on_cr) { skip_newline = true; goto done; } } else if (*buffer == '\n') { goto done; } else { if (buffer == buffer_end) { result = NPT_ERROR_NOT_ENOUGH_SPACE; goto done; } ++buffer; } } } else { // refill the buffer result = FillBuffer(); } if (NPT_FAILED(result)) goto done; } done: // update the newline skipping state m_SkipNewline = skip_newline; // NULL-terminate the line *buffer = '\0'; // return what we have m_Position += (NPT_Size)(buffer-buffer_start); if (chars_read) *chars_read = (NPT_Size)(buffer-buffer_start); if (result == NPT_ERROR_EOS) { m_Eos = true; if (buffer != buffer_start) { // we have reached the end of the stream, but we have read // some chars, so do not return EOS now return NPT_SUCCESS; } } return result; }
NPT_Result GPAC_MediaRenderer::OnAction(PLT_ActionReference& action, const PLT_HttpRequestContext& context) { NPT_COMPILER_UNUSED(context); /* parse the action name */ NPT_String name = action->GetActionDesc().GetName(); m_ip_src = context.GetRemoteAddress().GetIpAddress().ToString(); /* Is it a ConnectionManager Service Action ? */ if (name.Compare("GetCurrentConnectionIDs", true) == 0) { if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) { return NPT_FAILURE; } return NPT_SUCCESS; } if (name.Compare("GetProtocolInfo", true) == 0) { if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) { return NPT_FAILURE; } return NPT_SUCCESS; } if (name.Compare("GetCurrentConnectionInfo", true) == 0) { return OnGetCurrentConnectionInfo(action); } if (name.Compare("StopForMigration", true) == 0) { NPT_String res = m_pUPnP->OnMigrate(); m_pMigrationService->SetStateVariable("MigrationStatus", "OK"); m_pMigrationService->SetStateVariable("MigrationMetaData", res); if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) { return NPT_FAILURE; } return NPT_SUCCESS; } /* Is it a AVTransport Service Action ? */ // since all actions take an instance ID and we only support 1 instance // verify that the Instance ID is 0 and return an error here now if not NPT_String serviceType = action->GetActionDesc().GetService()->GetServiceType(); if (serviceType.Compare("urn:schemas-upnp-org:service:AVTransport:1", true) == 0) { if (NPT_FAILED(action->VerifyArgumentValue("InstanceID", "0"))) { action->SetError(802,"Not valid InstanceID."); return NPT_FAILURE; } } if (name.Compare("GetCurrentTransportActions", true) == 0) { if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) { return NPT_FAILURE; } return NPT_SUCCESS; } if (name.Compare("GetDeviceCapabilities", true) == 0) { if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) { return NPT_FAILURE; } return NPT_SUCCESS; } if (name.Compare("GetMediaInfo", true) == 0) { if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) { return NPT_FAILURE; } return NPT_SUCCESS; } if (name.Compare("GetPositionInfo", true) == 0) { if (m_pUPnP->m_pTerm->root_scene) { char szVal[100]; m_pAVService->SetStateVariable("CurrentTrack", "0"); format_time_string(szVal, m_Duration); m_pAVService->SetStateVariable("CurrentTrackDuration", szVal); m_pAVService->SetStateVariable("CurrentTrackMetadata", ""); m_pAVService->SetStateVariable("CurrentTrackURI", ""); format_time_string(szVal, m_Time); m_pAVService->SetStateVariable("RelativeTimePosition", szVal); m_pAVService->SetStateVariable("AbsoluteTimePosition", szVal); m_pAVService->SetStateVariable("RelativeCounterPosition", "2147483647"); // means NOT_IMPLEMENTED m_pAVService->SetStateVariable("AbsoluteCounterPosition", "2147483647"); // means NOT_IMPLEMENTED } else { if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) { return NPT_FAILURE; } } return NPT_SUCCESS; } if (name.Compare("GetTransportInfo", true) == 0) { if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) { return NPT_FAILURE; } return NPT_SUCCESS; } if (name.Compare("GetTransportSettings", true) == 0) { if (NPT_FAILED(action->SetArgumentsOutFromStateVariable())) { return NPT_FAILURE; } return NPT_SUCCESS; } if (name.Compare("Next", true) == 0) { return OnNext(action); } if (name.Compare("Pause", true) == 0) { return OnPause(action); } if (name.Compare("Play", true) == 0) { return OnPlay(action); } if (name.Compare("Previous", true) == 0) { return OnPrevious(action); } if (name.Compare("Seek", true) == 0) { return OnSeek(action); } if (name.Compare("Stop", true) == 0) { return OnStop(action); } if (name.Compare("SetAVTransportURI", true) == 0) { return OnSetAVTransportURI(action); } if (name.Compare("SetPlayMode", true) == 0) { return OnSetPlayMode(action); } /* Is it a RendererControl Service Action ? */ if (serviceType.Compare("urn:schemas-upnp-org:service:RenderingControl:1", true) == 0) { /* we only support master channel */ if (NPT_FAILED(action->VerifyArgumentValue("Channel", "Master"))) { action->SetError(402,"Invalid Args."); return NPT_FAILURE; } } if ((name.Compare("GetVolume", true) == 0) || (name.Compare("GetVolumeRangeDB", true) == 0) ) { NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable()); return NPT_SUCCESS; } if (name.Compare("GetMute", true) == 0) { NPT_CHECK_SEVERE(action->SetArgumentsOutFromStateVariable()); return NPT_SUCCESS; } if (name.Compare("SetVolume", true) == 0) { return OnSetVolume(action); } if (name.Compare("SetVolumeDB", true) == 0) { return OnSetVolumeDB(action); } if (name.Compare("SetMute", true) == 0) { return OnSetMute(action); } action->SetError(401,"No Such Action."); return NPT_FAILURE; }
/*---------------------------------------------------------------------- | 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_INFO_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; }
/*---------------------------------------------------------------------- | 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; }