vlc/vlc-2.0 | branch: master | Naohiro KORIYAMA <nkoriy...@gmail.com> | Mon Apr 30 17:57:19 2012 +0900| [3cabdc21d79e61947800d7d7f6f729d9bdec647b] | committer: Jean-Baptiste Kempf
upnp: fetch all media items correctly. Close #6716 Signed-off-by: Jean-Baptiste Kempf <j...@videolan.org> (cherry picked from commit 83a9c8442f393e4ada4c0cdccfebb41b67a17851) Signed-off-by: Jean-Baptiste Kempf <j...@videolan.org> > http://git.videolan.org/gitweb.cgi/vlc/vlc-2.0.git/?a=commit;h=3cabdc21d79e61947800d7d7f6f729d9bdec647b --- modules/services_discovery/upnp.cpp | 87 +++++++++++++++++++++++++++++++---- modules/services_discovery/upnp.hpp | 2 +- 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/modules/services_discovery/upnp.cpp b/modules/services_discovery/upnp.cpp index 666eaf2..4795486 100644 --- a/modules/services_discovery/upnp.cpp +++ b/modules/services_discovery/upnp.cpp @@ -89,8 +89,14 @@ const char* xml_getChildElementAttributeValue( IXML_Element* p_parent, const char* psz_tag_name_, const char* psz_attribute_ ); +const char* xml_getChildElementValue( IXML_Document* p_doc, + const char* psz_tag_name ); + IXML_Document* parseBrowseResult( IXML_Document* p_doc ); +int parseBrowseNumberValue( IXML_Document* p_doc, + const char* psz_tag_name ); + /* * Initializes UPNP instance. */ @@ -214,16 +220,16 @@ const char* xml_getChildElementAttributeValue( IXML_Element* p_parent, } /* - * Extracts the result document from a SOAP response + * Returns the value of a child element, or NULL on error */ -IXML_Document* parseBrowseResult( IXML_Document* p_doc ) +const char* xml_getChildElementValue( IXML_Document* p_doc, + const char* psz_tag_name_ ) { - ixmlRelaxParser( 1 ); - if ( !p_doc ) return 0; + if ( !psz_tag_name_ ) return 0; IXML_NodeList* p_result_list = ixmlDocument_getElementsByTagName( p_doc, - "Result" ); + psz_tag_name_ ); if ( !p_result_list ) return 0; @@ -236,13 +242,47 @@ IXML_Document* parseBrowseResult( IXML_Document* p_doc ) IXML_Node* p_text_node = ixmlNode_getFirstChild( p_result_node ); if ( !p_text_node ) return 0; - const char* psz_result_string = ixmlNode_getNodeValue( p_text_node ); + return ixmlNode_getNodeValue( p_text_node ); +} + +/* + * Extracts the result document from a SOAP response + */ +IXML_Document* parseBrowseResult( IXML_Document* p_doc ) +{ + ixmlRelaxParser( 1 ); + + const char* psz_result_string = xml_getChildElementValue( p_doc, "Result" ); + if( !psz_result_string ) return 0; IXML_Document* p_browse_doc = ixmlParseBuffer( psz_result_string ); return p_browse_doc; } +/* + * Get the number value from a SOAP response + */ +int parseBrowseNumberValue( IXML_Document* p_doc, + const char* psz_tag_name_ ) +{ + ixmlRelaxParser( 1 ); + + const char* psz_number_string = xml_getChildElementValue( p_doc, + psz_tag_name_ ); + if( !psz_number_string ) return 0; + + char *psz_end; + long l = strtol( psz_number_string, &psz_end, 10 ); + if( *psz_end || l < 0 || l > INT_MAX ) + { + return 0; + } + else + { + return (int)l; + } +} /* * Handles all UPnP events @@ -709,7 +749,7 @@ void MediaServer::fetchContents() Container* root = new Container( 0, "0", getFriendlyName() ); - _fetchContents( root ); + _fetchContents( root, 0 ); _p_contents = root; _p_contents->setInputItem( _p_input_item ); @@ -720,7 +760,7 @@ void MediaServer::fetchContents() /* * Fetches and parses the UPNP response */ -bool MediaServer::_fetchContents( Container* p_parent ) +bool MediaServer::_fetchContents( Container* p_parent, int i_starting_index ) { if (!p_parent) { @@ -728,9 +768,21 @@ bool MediaServer::_fetchContents( Container* p_parent ) return false; } + char* psz_starting_index; + if( asprintf( &psz_starting_index, "%d", i_starting_index ) < 0 ) + { + msg_Err( _p_sd, "asprintf error:%d", i_starting_index ); + return false; + } + IXML_Document* p_response = _browseAction( p_parent->getObjectID(), "BrowseDirectChildren", - "*", "0", "0", "" ); + "*", /* Filter */ + psz_starting_index, /* StartingIndex */ + "0", /* RequestedCount */ + "" /* SortCriteria */ + ); + free( psz_starting_index ); if ( !p_response ) { msg_Err( _p_sd, "No response from browse() action" ); @@ -738,6 +790,12 @@ bool MediaServer::_fetchContents( Container* p_parent ) } IXML_Document* p_result = parseBrowseResult( p_response ); + int i_number_returned = parseBrowseNumberValue( p_response, "NumberReturned" ); + int i_total_matches = parseBrowseNumberValue( p_response , "TotalMatches" ); +#ifndef NDEBUG + msg_Dbg( _p_sd, "i_starting_index[%d]i_number_returned[%d]_total_matches[%d]\n", + i_starting_index, i_number_returned, i_total_matches ); +#endif ixmlDocument_free( p_response ); if ( !p_result ) @@ -777,7 +835,7 @@ bool MediaServer::_fetchContents( Container* p_parent ) Container* container = new Container( p_parent, objectID, title ); p_parent->addContainer( container ); - _fetchContents( container ); + _fetchContents( container, 0 ); } ixmlNodeList_free( containerNodeList ); } @@ -833,6 +891,15 @@ bool MediaServer::_fetchContents( Container* p_parent ) } ixmlDocument_free( p_result ); + + if( i_starting_index + i_number_returned < i_total_matches ) + { + if( !_fetchContents( p_parent, i_starting_index + i_number_returned ) ) + { + return false; + } + } + return true; } diff --git a/modules/services_discovery/upnp.hpp b/modules/services_discovery/upnp.hpp index ee41181..aa11ddf 100644 --- a/modules/services_discovery/upnp.hpp +++ b/modules/services_discovery/upnp.hpp @@ -69,7 +69,7 @@ public: private: - bool _fetchContents( Container* p_parent ); + bool _fetchContents( Container* p_parent, int i_starting_index ); void _buildPlaylist( Container* p_container, input_item_node_t *p_item_node ); IXML_Document* _browseAction( const char*, const char*, _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org http://mailman.videolan.org/listinfo/vlc-commits