/* * Fetches and parses the UPNP response */ bool MediaServer::fetchContents() { IXML_Document* p_response = _browseAction( m_psz_objectId, "BrowseDirectChildren", "*", // Some servers don't understand "0" as "no-limit" "1000", /* RequestedCount */ "" /* SortCriteria */ ); if ( !p_response ) { msg_Err( m_access, "No response from browse() action" ); return false; } IXML_Document* p_result = parseBrowseResult( p_response ); ixmlDocument_free( p_response ); if ( !p_result ) { msg_Err( m_access, "browse() response parsing failed" ); return false; } #ifndef NDEBUG msg_Dbg( m_access, "Got DIDL document: %s", ixmlPrintDocument( p_result ) ); #endif IXML_NodeList* containerNodeList = ixmlDocument_getElementsByTagName( p_result, "container" ); if ( containerNodeList ) { for ( unsigned int i = 0; i < ixmlNodeList_length( containerNodeList ); i++ ) addContainer( (IXML_Element*)ixmlNodeList_item( containerNodeList, i ) ); ixmlNodeList_free( containerNodeList ); } IXML_NodeList* itemNodeList = ixmlDocument_getElementsByTagName( p_result, "item" ); if ( itemNodeList ) { for ( unsigned int i = 0; i < ixmlNodeList_length( itemNodeList ); i++ ) addItem( (IXML_Element*)ixmlNodeList_item( itemNodeList, i ) ); ixmlNodeList_free( itemNodeList ); } ixmlDocument_free( p_result ); return true; }
/* * Fetches and parses the UPNP response */ void MediaServer::fetchContents() { const char* objectID = ""; vlc_url_t url; vlc_UrlParse( &url, access_->psz_location, '?'); if ( url.psz_option && !strncmp( url.psz_option, "ObjectID=", strlen( "ObjectID=" ) ) ) { objectID = &url.psz_option[strlen( "ObjectID=" )]; } IXML_Document* p_response = _browseAction( objectID, "BrowseDirectChildren", "id,dc:title,res," /* Filter */ "sec:CaptionInfo,sec:CaptionInfoEx," "pv:subtitlefile", "0", /* RequestedCount */ "" /* SortCriteria */ ); vlc_UrlClean( &url ); if ( !p_response ) { msg_Err( access_, "No response from browse() action" ); return; } xmlDocument_ = parseBrowseResult( p_response ); ixmlDocument_free( p_response ); if ( !xmlDocument_ ) { msg_Err( access_, "browse() response parsing failed" ); return; } #ifndef NDEBUG msg_Dbg( access_, "Got DIDL document: %s", ixmlPrintDocument( xmlDocument_ ) ); #endif containerNodeList_ = ixmlDocument_getElementsByTagName( xmlDocument_, "container" ); itemNodeList_ = ixmlDocument_getElementsByTagName( xmlDocument_, "item" ); }
bool MediaServer::_fetchContents( Container* parent ) { if (!parent) { msg_Dbg( _p_sd, "%s:%d: parent==NULL", __FILE__, __LINE__ ); return false; } IXML_Document* response = _browseAction( parent->getObjectID(), "BrowseDirectChildren", "*", "0", "0", "" ); if ( !response ) { msg_Dbg( _p_sd, "%s:%d: ERROR! No response from browse() action", __FILE__, __LINE__ ); return false; } IXML_Document* result = parseBrowseResult( response ); ixmlDocument_free( response ); if ( !result ) { msg_Dbg( _p_sd, "%s:%d: ERROR! browse() response parsing failed", __FILE__, __LINE__ ); return false; } IXML_NodeList* containerNodeList = ixmlDocument_getElementsByTagName( result, "container" ); if ( containerNodeList ) { for ( unsigned int i = 0; i < ixmlNodeList_length( containerNodeList ); i++ ) { IXML_Element* containerElement = ( IXML_Element* )ixmlNodeList_item( containerNodeList, i ); const char* objectID = ixmlElement_getAttribute( containerElement, "id" ); if ( !objectID ) continue; const char* childCountStr = ixmlElement_getAttribute( containerElement, "childCount" ); if ( !childCountStr ) continue; int childCount = atoi( childCountStr ); const char* title = xml_getChildElementValue( containerElement, "dc:title" ); if ( !title ) continue; const char* resource = xml_getChildElementValue( containerElement, "res" ); if ( resource && childCount < 1 ) { Item* item = new Item( parent, objectID, title, resource ); parent->addItem( item ); } else { Container* container = new Container( parent, objectID, title ); parent->addContainer( container ); if ( childCount > 0 ) _fetchContents( container ); } } ixmlNodeList_free( containerNodeList ); } IXML_NodeList* itemNodeList = ixmlDocument_getElementsByTagName( result, "item" ); if ( itemNodeList ) { for ( unsigned int i = 0; i < ixmlNodeList_length( itemNodeList ); i++ ) { IXML_Element* itemElement = ( IXML_Element* )ixmlNodeList_item( itemNodeList, i ); const char* objectID = ixmlElement_getAttribute( itemElement, "id" ); if ( !objectID ) continue; const char* title = xml_getChildElementValue( itemElement, "dc:title" ); if ( !title ) continue; const char* resource = xml_getChildElementValue( itemElement, "res" ); if ( !resource ) continue; Item* item = new Item( parent, objectID, title, resource ); parent->addItem( item ); } ixmlNodeList_free( itemNodeList ); } ixmlDocument_free( result ); return true; }
/* * Fetches and parses the UPNP response */ bool MediaServer::_fetchContents( Container* p_parent ) { if (!p_parent) { msg_Err( _p_sd, "No parent" ); return false; } IXML_Document* p_response = _browseAction( p_parent->getObjectID(), "BrowseDirectChildren", "*", "0", "0", "" ); if ( !p_response ) { msg_Err( _p_sd, "No response from browse() action" ); return false; } IXML_Document* p_result = parseBrowseResult( p_response ); ixmlDocument_free( p_response ); if ( !p_result ) { msg_Err( _p_sd, "browse() response parsing failed" ); return false; } #ifndef NDEBUG else { msg_Dbg( _p_sd, "Got DIDL document: %s", ixmlPrintDocument( p_result ) ); } #endif IXML_NodeList* containerNodeList = ixmlDocument_getElementsByTagName( p_result, "container" ); if ( containerNodeList ) { for ( unsigned int i = 0; i < ixmlNodeList_length( containerNodeList ); i++ ) { IXML_Element* containerElement = ( IXML_Element* )ixmlNodeList_item( containerNodeList, i ); const char* objectID = ixmlElement_getAttribute( containerElement, "id" ); if ( !objectID ) continue; const char* title = xml_getChildElementValue( containerElement, "dc:title" ); if ( !title ) continue; Container* container = new Container( p_parent, objectID, title ); p_parent->addContainer( container ); _fetchContents( container ); } ixmlNodeList_free( containerNodeList ); } IXML_NodeList* itemNodeList = ixmlDocument_getElementsByTagName( p_result, "item" ); if ( itemNodeList ) { for ( unsigned int i = 0; i < ixmlNodeList_length( itemNodeList ); i++ ) { IXML_Element* itemElement = ( IXML_Element* )ixmlNodeList_item( itemNodeList, i ); const char* objectID = ixmlElement_getAttribute( itemElement, "id" ); if ( !objectID ) continue; const char* title = xml_getChildElementValue( itemElement, "dc:title" ); if ( !title ) continue; const char* resource = xml_getChildElementValue( itemElement, "res" ); if ( !resource ) continue; const char* psz_duration = xml_getChildElementAttributeValue( itemElement, "res", "duration" ); mtime_t i_duration = -1; int i_hours, i_minutes, i_seconds, i_decis; if ( psz_duration ) { if( sscanf( psz_duration, "%02d:%02d:%02d.%d", &i_hours, &i_minutes, &i_seconds, &i_decis )) i_duration = INT64_C(1000000) * ( i_hours*3600 + i_minutes*60 + i_seconds ) + INT64_C(100000) * i_decis; } Item* item = new Item( p_parent, objectID, title, resource, i_duration ); p_parent->addItem( item ); } ixmlNodeList_free( itemNodeList ); } ixmlDocument_free( p_result ); return true; }
/* * Fetches and parses the UPNP response */ bool MediaServer::_fetchContents( Container* p_parent, int i_offset ) { if (!p_parent) { msg_Err( _p_sd, "No parent" ); return false; } char* psz_starting_index; if( asprintf( &psz_starting_index, "%d", i_offset ) < 0 ) { msg_Err( _p_sd, "asprintf error:%d", i_offset ); return false; } IXML_Document* p_response = _browseAction( p_parent->getObjectID(), "BrowseDirectChildren", "*", /* Filter */ psz_starting_index, /* StartingIndex */ "0", /* RequestedCount */ "" /* SortCriteria */ ); free( psz_starting_index ); if ( !p_response ) { msg_Err( _p_sd, "No response from browse() action" ); return false; } IXML_Document* p_result = parseBrowseResult( p_response ); int i_number_returned = xml_getNumber( p_response, "NumberReturned" ); int i_total_matches = xml_getNumber( p_response , "TotalMatches" ); #ifndef NDEBUG msg_Dbg( _p_sd, "i_offset[%d]i_number_returned[%d]_total_matches[%d]\n", i_offset, i_number_returned, i_total_matches ); #endif ixmlDocument_free( p_response ); if ( !p_result ) { msg_Err( _p_sd, "browse() response parsing failed" ); return false; } #ifndef NDEBUG msg_Dbg( _p_sd, "Got DIDL document: %s", ixmlPrintDocument( p_result ) ); #endif IXML_NodeList* containerNodeList = ixmlDocument_getElementsByTagName( p_result, "container" ); if ( containerNodeList ) { for ( unsigned int i = 0; i < ixmlNodeList_length( containerNodeList ); i++ ) { IXML_Element* containerElement = ( IXML_Element* )ixmlNodeList_item( containerNodeList, i ); const char* objectID = ixmlElement_getAttribute( containerElement, "id" ); if ( !objectID ) continue; const char* title = xml_getChildElementValue( containerElement, "dc:title" ); if ( !title ) continue; Container* container = new Container( p_parent, objectID, title ); p_parent->addContainer( container ); _fetchContents( container, 0 ); } ixmlNodeList_free( containerNodeList ); } IXML_NodeList* itemNodeList = ixmlDocument_getElementsByTagName( p_result, "item" ); if ( itemNodeList ) { for ( unsigned int i = 0; i < ixmlNodeList_length( itemNodeList ); i++ ) { IXML_Element* itemElement = ( IXML_Element* )ixmlNodeList_item( itemNodeList, i ); const char* objectID = ixmlElement_getAttribute( itemElement, "id" ); if ( !objectID ) continue; const char* title = xml_getChildElementValue( itemElement, "dc:title" ); if ( !title ) continue; const char* resource = xml_getChildElementValue( itemElement, "res" ); if ( !resource ) continue; const char* psz_duration = xml_getChildElementAttributeValue( itemElement, "res", "duration" ); mtime_t i_duration = -1; int i_hours, i_minutes, i_seconds, i_decis; if ( psz_duration ) { if( sscanf( psz_duration, "%02d:%02d:%02d.%d", &i_hours, &i_minutes, &i_seconds, &i_decis )) i_duration = INT64_C(1000000) * ( i_hours*3600 + i_minutes*60 + i_seconds ) + INT64_C(100000) * i_decis; } Item* item = new Item( p_parent, objectID, title, resource, i_duration ); p_parent->addItem( item ); } ixmlNodeList_free( itemNodeList ); } ixmlDocument_free( p_result ); if( i_offset + i_number_returned < i_total_matches ) return _fetchContents( p_parent, i_offset + i_number_returned ); return true; }
/*---------------------------------------------------------------------------*/ void browseMediaServer ( UPnPRuntime *rt, UPnPControlPoint *cp ) { UPnPControlDeviceHandle dh; struct actionUserData userData; char deviceUrl[256]; int index; userData.done = 0; userData.errorCode = 0; /* Search by Media Server's UUID for unique media server */ UPnP_ControlFindDevicesByUUID(cp, MEDIA_SERVER_UDN, SEARCH_DURATION, deviceUrl, 1); printf("\nOpening device at %s...", deviceUrl); dh = UPnP_ControlOpenDevice(cp, deviceUrl); if (dh != 0) { UPnPControlServiceIterator i; printf("device open.\n\nLooking for ContentDirectory:1 service..."); /* find the ContentDirectory:1 service and invoke an action on it */ if (UPnP_ControlGetServicesByType(dh, &i, "ContentDirectory:1") >= 0) { UPNP_CHAR* serviceId = UPnP_ControlNextService(&i); if (serviceId) { RTPXML_Document* action; /* Invoking 'Browse' action. This action contains 6 'in' arguments. */ action = UPnP_CreateAction( UPnP_ControlGetServiceType(dh,serviceId),"Browse"); if (action) { /* In Arguments */ UPnP_SetActionArg (action, "ObjectID", "0"); UPnP_SetActionArg (action, "BrowseFlag", "BrowseDirectChildren"); UPnP_SetActionArg (action, "Filter", "*"); UPnP_SetActionArg (action, "StartingIndex", "0"); UPnP_SetActionArg (action, "RequestedCount", BROWSE_ELEMENT_COUNT); UPnP_SetActionArg (action, "SortCriteria", ""); /* Out Arguments */ userData.numOutElements = 4; userData.outVariableName[0] = rtp_strdup("Result"); userData.outVariableName[1] = rtp_strdup("NumberReturned"); userData.outVariableName[2] = rtp_strdup("TotalMatches"); userData.outVariableName[3] = rtp_strdup("UpdateID"); if (UPnP_ControlInvokeAction (dh, serviceId, "Browse", action, &userData, 1) >= 0) { /* catch errors if any */ if (userData.errorCode != 0) { if (userData.errorDescription) { printf("\nError occured in Browse request \n"); printf("Error Code - %d\n", userData.errorCode); printf("Error Description - %s\n", userData.errorDescription); rtp_free(userData.errorDescription); } } else { printf("--------------------------------------\n"); printf(" Browse Results \n"); printf("Total Matches - %s \n", userData.outVariableValue[2]); parseBrowseResult(userData.outVariableValue[0]); printf("--------------------------------------\n"); } } /* free the xml document */ rtpxmlDocument_free (action); for (index = 0; index < userData.numOutElements; index++) { rtp_free(userData.outVariableName[index]); if(userData.outVariableValue[index]) { rtp_free(userData.outVariableValue[index]); } } } else { printf (" could not create action!\n"); } } } } }