diff options
Diffstat (limited to 'lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp')
-rw-r--r-- | lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp | 711 |
1 files changed, 711 insertions, 0 deletions
diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp new file mode 100644 index 0000000..8686aa9 --- /dev/null +++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaServer.cpp @@ -0,0 +1,711 @@ +/***************************************************************** +| +| Platinum - AV Media Server Device +| +| Copyright (c) 2004-2010, Plutinosoft, LLC. +| All rights reserved. +| http://www.plutinosoft.com +| +| This program is free software; you can redistribute it and/or +| modify it under the terms of the GNU General Public License +| as published by the Free Software Foundation; either version 2 +| of the License, or (at your option) any later version. +| +| OEMs, ISVs, VARs and other distributors that combine and +| distribute commercially licensed software with Platinum software +| and do not wish to distribute the source code for the commercially +| licensed software under version 2, or (at your option) any later +| version, of the GNU General Public License (the "GPL") must enter +| into a commercial license agreement with Plutinosoft, LLC. +| licensing@plutinosoft.com +| +| This program is distributed in the hope that it will be useful, +| but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +| GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License +| along with this program; see the file LICENSE.txt. If not, write to +| the Free Software Foundation, Inc., +| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +| http://www.gnu.org/licenses/gpl-2.0.html +| +****************************************************************/ + +/*---------------------------------------------------------------------- +| includes ++---------------------------------------------------------------------*/ +#include "PltUPnP.h" +#include "PltMediaServer.h" +#include "PltMediaItem.h" +#include "PltService.h" +#include "PltTaskManager.h" +#include "PltHttpServer.h" +#include "PltDidl.h" + +NPT_SET_LOCAL_LOGGER("platinum.media.server") + +/*---------------------------------------------------------------------- +| forward references ++---------------------------------------------------------------------*/ +extern NPT_UInt8 MS_ConnectionManagerSCPD[]; +extern NPT_UInt8 MS_ContentDirectorywSearchSCPD[]; + +const char* BrowseFlagsStr[] = { + "BrowseMetadata", + "BrowseDirectChildren" +}; + +/*---------------------------------------------------------------------- +| PLT_MediaServer::PLT_MediaServer ++---------------------------------------------------------------------*/ +PLT_MediaServer::PLT_MediaServer(const char* friendly_name, + bool show_ip /* = false */, + const char* uuid /* = NULL */, + NPT_UInt16 port /* = 0 */, + bool port_rebind /* = false */) : + PLT_DeviceHost("/DeviceDescription.xml", + uuid, + "urn:schemas-upnp-org:device:MediaServer:1", + friendly_name, + show_ip, + port, + port_rebind), + m_Delegate(NULL) +{ + m_ModelDescription = "Plutinosoft AV Media Server Device"; + m_ModelName = "AV Media Server Device"; + m_ModelURL = "http://www.plutinosoft.com/platinum"; + m_DlnaDoc = "DMS-1.50"; +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::~PLT_MediaServer ++---------------------------------------------------------------------*/ +PLT_MediaServer::~PLT_MediaServer() +{ +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::SetupServices ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::SetupServices() +{ + NPT_Reference<PLT_Service> service; + + { + service = new PLT_Service( + this, + "urn:schemas-upnp-org:service:ContentDirectory:1", + "urn:upnp-org:serviceId:ContentDirectory", + "ContentDirectory"); + NPT_CHECK_FATAL(service->SetSCPDXML((const char*) MS_ContentDirectorywSearchSCPD)); + NPT_CHECK_FATAL(AddService(service.AsPointer())); + + service->SetStateVariable("ContainerUpdateIDs", ""); + service->SetStateVariableRate("ContainerUpdateIDs", NPT_TimeInterval(2.)); + service->SetStateVariable("SystemUpdateID", "0"); + service->SetStateVariableRate("SystemUpdateID", NPT_TimeInterval(2.)); + service->SetStateVariable("SearchCapability", "@id,@refID,dc:title,upnp:class,upnp:genre,upnp:artist,upnp:author,upnp:author@role,upnp:album,dc:creator,res@size,res@duration,res@protocolInfo,res@protection,dc:publisher,dc:language,upnp:originalTrackNumber,dc:date,upnp:producer,upnp:rating,upnp:actor,upnp:director,upnp:toc,dc:description,microsoft:userRatingInStars,microsoft:userEffectiveRatingInStars,microsoft:userRating,microsoft:userEffectiveRating,microsoft:serviceProvider,microsoft:artistAlbumArtist,microsoft:artistPerformer,microsoft:artistConductor,microsoft:authorComposer,microsoft:authorOriginalLyricist,microsoft:authorWriter,upnp:userAnnotation,upnp:channelName,upnp:longDescription,upnp:programTitle"); + service->SetStateVariable("SortCapability", "dc:title,upnp:genre,upnp:album,dc:creator,res@size,res@duration,res@bitrate,dc:publisher,dc:language,upnp:originalTrackNumber,dc:date,upnp:producer,upnp:rating,upnp:actor,upnp:director,upnp:toc,dc:description,microsoft:year,microsoft:userRatingInStars,microsoft:userEffectiveRatingInStars,microsoft:userRating,microsoft:userEffectiveRating,microsoft:serviceProvider,microsoft:artistAlbumArtist,microsoft:artistPerformer,microsoft:artistConductor,microsoft:authorComposer,microsoft:authorOriginalLyricist,microsoft:authorWriter,microsoft:sourceUrl,upnp:userAnnotation,upnp:channelName,upnp:longDescription,upnp:programTitle"); + + service.Detach(); + service = NULL; + } + + { + service = new PLT_Service( + this, + "urn:schemas-upnp-org:service:ConnectionManager:1", + "urn:upnp-org:serviceId:ConnectionManager", + "ConnectionManager"); + NPT_CHECK_FATAL(service->SetSCPDXML((const char*) MS_ConnectionManagerSCPD)); + NPT_CHECK_FATAL(AddService(service.AsPointer())); + + service->SetStateVariable("CurrentConnectionIDs", "0"); + service->SetStateVariable("SinkProtocolInfo", ""); + service->SetStateVariable("SourceProtocolInfo", "http-get:*:*:*"); + + service.Detach(); + service = NULL; + } + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::UpdateSystemUpdateID ++---------------------------------------------------------------------*/ +void +PLT_MediaServer::UpdateSystemUpdateID(NPT_UInt32 update) +{ + NPT_COMPILER_UNUSED(update); +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::UpdateContainerUpdateID ++---------------------------------------------------------------------*/ +void PLT_MediaServer::UpdateContainerUpdateID(const char* id, NPT_UInt32 update) +{ + NPT_COMPILER_UNUSED(id); + NPT_COMPILER_UNUSED(update); +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnAction ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnAction(PLT_ActionReference& action, + const PLT_HttpRequestContext& context) +{ + /* parse the action name */ + NPT_String name = action->GetActionDesc().GetName(); + + // ContentDirectory + if (name.Compare("Browse", true) == 0) { + return OnBrowse(action, context); + } + if (name.Compare("Search", true) == 0) { + return OnSearch(action, context); + } + if (name.Compare("UpdateObject", true) == 0) { + return OnUpdate(action, context); + } + if (name.Compare("GetSystemUpdateID", true) == 0) { + return OnGetSystemUpdateID(action, context); + } + if (name.Compare("GetSortCapabilities", true) == 0) { + return OnGetSortCapabilities(action, context); + } + if (name.Compare("GetSearchCapabilities", true) == 0) { + return OnGetSearchCapabilities(action, context); + } + + // ConnectionMananger + if (name.Compare("GetCurrentConnectionIDs", true) == 0) { + return OnGetCurrentConnectionIDs(action, context); + } + if (name.Compare("GetProtocolInfo", true) == 0) { + return OnGetProtocolInfo(action, context); + } + if (name.Compare("GetCurrentConnectionInfo", true) == 0) { + return OnGetCurrentConnectionInfo(action, context); + } + + action->SetError(401,"No Such Action."); + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| PLT_FileMediaServer::ProcessHttpGetRequest ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::ProcessHttpGetRequest(NPT_HttpRequest& request, + const NPT_HttpRequestContext& context, + NPT_HttpResponse& response) +{ + /* Try to handle file request */ + if (m_Delegate) return m_Delegate->ProcessFileRequest(request, context, response); + + return NPT_ERROR_NO_SUCH_ITEM; +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnGetCurrentConnectionIDs ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnGetCurrentConnectionIDs(PLT_ActionReference& action, + const PLT_HttpRequestContext& context) +{ + NPT_COMPILER_UNUSED(context); + + return action->SetArgumentsOutFromStateVariable(); +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnGetProtocolInfo ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnGetProtocolInfo(PLT_ActionReference& action, + const PLT_HttpRequestContext& context) +{ + NPT_COMPILER_UNUSED(context); + + return action->SetArgumentsOutFromStateVariable(); +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnGetCurrentConnectionInfo ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnGetCurrentConnectionInfo(PLT_ActionReference& action, + const PLT_HttpRequestContext& context) +{ + NPT_COMPILER_UNUSED(context); + + if (NPT_FAILED(action->VerifyArgumentValue("ConnectionID", "0"))) { + action->SetError(706,"No Such Connection."); + return NPT_FAILURE; + } + + if (NPT_FAILED(action->SetArgumentValue("RcsID", "-1"))){ + return NPT_FAILURE; + } + if (NPT_FAILED(action->SetArgumentValue("AVTransportID", "-1"))) { + return NPT_FAILURE; + } + if (NPT_FAILED(action->SetArgumentValue("ProtocolInfo", "http-get:*:*:*"))) { + return NPT_FAILURE; + } + if (NPT_FAILED(action->SetArgumentValue("PeerConnectionManager", "/"))) { + return NPT_FAILURE; + } + if (NPT_FAILED(action->SetArgumentValue("PeerConnectionID", "-1"))) { + return NPT_FAILURE; + } + if (NPT_FAILED(action->SetArgumentValue("Direction", "Output"))) { + return NPT_FAILURE; + } + if (NPT_FAILED(action->SetArgumentValue("Status", "Unknown"))) { + return NPT_FAILURE; + } + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnGetSortCapabilities ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnGetSortCapabilities(PLT_ActionReference& action, + const PLT_HttpRequestContext& context) +{ + NPT_COMPILER_UNUSED(context); + + return action->SetArgumentsOutFromStateVariable(); +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnGetSearchCapabilities ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnGetSearchCapabilities(PLT_ActionReference& action, + const PLT_HttpRequestContext& context) +{ + NPT_COMPILER_UNUSED(context); + + return action->SetArgumentsOutFromStateVariable(); +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnGetSystemUpdateID ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnGetSystemUpdateID(PLT_ActionReference& action, + const PLT_HttpRequestContext& context) +{ + NPT_COMPILER_UNUSED(context); + + return action->SetArgumentsOutFromStateVariable(); +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::ParseBrowseFlag ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::ParseBrowseFlag(const char* str, BrowseFlags& flag) +{ + if (NPT_String::Compare(str, BrowseFlagsStr[0], true) == 0) { + flag = BROWSEMETADATA; + return NPT_SUCCESS; + } + if (NPT_String::Compare(str, BrowseFlagsStr[1], true) == 0) { + flag = BROWSEDIRECTCHILDREN; + return NPT_SUCCESS; + } + return NPT_FAILURE; +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::ParseSort ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::ParseSort(const NPT_String& sort, NPT_List<NPT_String>& list) +{ + // reset output params first + list.Clear(); + + // easy out + if (sort.GetLength() == 0 || sort == "*") return NPT_SUCCESS; + + list = sort.Split(","); + + // verify each property has a namespace + NPT_List<NPT_String>::Iterator property = list.GetFirstItem(); + while (property) { + NPT_List<NPT_String> parsed_property = (*property).Split(":"); + if (parsed_property.GetItemCount() != 2) + parsed_property = (*property).Split("@"); + if (parsed_property.GetItemCount() != 2 || + (!(*property).StartsWith("-") && !(*property).StartsWith("+"))) { + NPT_LOG_WARNING_1("Invalid SortCriteria property %s", (*property).GetChars()); + return NPT_FAILURE; + } + property++; + } + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::ParseTagList ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::ParseTagList(const NPT_String& updates, NPT_Map<NPT_String,NPT_String>& tags) +{ + // reset output params first + tags.Clear(); + + NPT_List<NPT_String> split = updates.Split(","); + NPT_XmlNode* node = NULL; + NPT_XmlElementNode* didl_partial = NULL; + NPT_XmlParser parser; + + // as these are single name value pairs, separated by commas we wrap in a tag + // to create a valid tree + NPT_String xml("<TagValueList>"); + for (NPT_List<NPT_String>::Iterator entry = split.GetFirstItem(); entry; entry++) { + NPT_String& element = (*entry); + if (element.IsEmpty()) + xml.Append("<empty>empty</empty>"); + else + xml.Append(element); + } + xml.Append("</TagValueList>"); + + NPT_LOG_FINE("Parsing TagList..."); + NPT_CHECK_LABEL_SEVERE(parser.Parse(xml, node), cleanup); + if (!node || !node->AsElementNode()) { + NPT_LOG_SEVERE("Invalid node type"); + goto cleanup; + } + + didl_partial = node->AsElementNode(); + if (didl_partial->GetTag().Compare("TagValueList", true)) { + NPT_LOG_SEVERE("Invalid node tag"); + goto cleanup; + } + + for (NPT_List<NPT_XmlNode*>::Iterator children = didl_partial->GetChildren().GetFirstItem(); children; children++) { + NPT_XmlElementNode* child = (*children)->AsElementNode(); + if (!child) continue; + const NPT_String *txt = child->GetText(); + tags[child->GetTag()] = txt ? txt->GetChars() : ""; + } + + return NPT_SUCCESS; + +cleanup: + if (node) delete node; + return NPT_FAILURE; +} + + +/*---------------------------------------------------------------------- +| 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; +} + +/*---------------------------------------------------------------------- +| 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::OnUpdate ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnUpdate(PLT_ActionReference& action, + const PLT_HttpRequestContext& context) +{ + if (!m_Delegate) + return NPT_ERROR_NOT_IMPLEMENTED; + + int err; + const char* msg = NULL; + + NPT_String object_id, current_xml, new_xml; + NPT_Map<NPT_String,NPT_String> curr_values; + NPT_Map<NPT_String,NPT_String> new_values; + + NPT_CHECK_LABEL(action->GetArgumentValue("ObjectID", object_id), args); + NPT_CHECK_LABEL(object_id.IsEmpty(),args); + NPT_CHECK_LABEL(action->GetArgumentValue("CurrentTagValue", current_xml), args); + NPT_CHECK_LABEL(action->GetArgumentValue("NewTagValue", new_xml), args); + + if (NPT_FAILED(ParseTagList(current_xml, curr_values))) { + err = 702; + msg = "Invalid currentTagvalue"; + goto failure; + } + if (NPT_FAILED(ParseTagList(new_xml, new_values))) { + err = 703; + msg = "Invalid newTagValue"; + goto failure; + } + + if (curr_values.GetEntryCount() != new_values.GetEntryCount()) { + err = 706; + msg = "Paramater mismatch"; + goto failure; + } + + return m_Delegate->OnUpdateObject(action, object_id, curr_values, new_values, context); + +args: + err = 402; + msg = "Invalid args"; + +failure: + NPT_LOG_WARNING_1("%s", msg); + action->SetError(err, msg); + return NPT_FAILURE; +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnBrowseMetadata ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnBrowseMetadata(PLT_ActionReference& action, + const char* object_id, + const char* filter, + NPT_UInt32 starting_index, + NPT_UInt32 requested_count, + const char* sort_criteria, + const PLT_HttpRequestContext& context) +{ + if (m_Delegate) { + return m_Delegate->OnBrowseMetadata(action, + object_id, + filter, + starting_index, + requested_count, + sort_criteria, + context); + } + return NPT_ERROR_NOT_IMPLEMENTED; +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnBrowseDirectChildren ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnBrowseDirectChildren(PLT_ActionReference& action, + const char* object_id, + const char* filter, + NPT_UInt32 starting_index, + NPT_UInt32 requested_count, + const char* sort_criteria, + const PLT_HttpRequestContext& context) +{ + if (m_Delegate) { + return m_Delegate->OnBrowseDirectChildren(action, + object_id, + filter, + starting_index, + requested_count, + sort_criteria, + context); + } + return NPT_ERROR_NOT_IMPLEMENTED; +} + +/*---------------------------------------------------------------------- +| PLT_MediaServer::OnSearchContainer ++---------------------------------------------------------------------*/ +NPT_Result +PLT_MediaServer::OnSearchContainer(PLT_ActionReference& action, + const char* object_id, + const char* search_criteria, + const char* filter, + NPT_UInt32 starting_index, + NPT_UInt32 requested_count, + const char* sort_criteria, + const PLT_HttpRequestContext& context) +{ + if (m_Delegate) { + return m_Delegate->OnSearchContainer(action, + object_id, + search_criteria, + filter, + starting_index, + requested_count, + sort_criteria, + context); + } + return NPT_ERROR_NOT_IMPLEMENTED; +} |