Exemple #1
0
std::string MediaServerList::getIconURL( IXML_Element* p_device_elem, const char* psz_base_url )
{
    std::string res;
    IXML_NodeList* p_icon_lists = ixmlElement_getElementsByTagName( p_device_elem, "iconList" );
    if ( p_icon_lists == NULL )
        return res;
    IXML_Element* p_icon_list = (IXML_Element*)ixmlNodeList_item( p_icon_lists, 0 );
    if ( p_icon_list != NULL )
    {
        IXML_NodeList* p_icons = ixmlElement_getElementsByTagName( p_icon_list, "icon" );
        if ( p_icons != NULL )
        {
            unsigned int maxWidth = 0;
            unsigned int maxHeight = 0;
            for ( unsigned int i = 0; i < ixmlNodeList_length( p_icons ); ++i )
            {
                IXML_Element* p_icon = (IXML_Element*)ixmlNodeList_item( p_icons, i );
                const char* widthStr = xml_getChildElementValue( p_icon, "width" );
                const char* heightStr = xml_getChildElementValue( p_icon, "height" );
                if ( widthStr == NULL || heightStr == NULL )
                    continue;
                unsigned int width = atoi( widthStr );
                unsigned int height = atoi( heightStr );
                if ( width <= maxWidth || height <= maxHeight )
                    continue;
                const char* iconUrl = xml_getChildElementValue( p_icon, "url" );
                if ( iconUrl == NULL )
                    continue;
                maxWidth = width;
                maxHeight = height;
                res = iconUrl;
            }
            ixmlNodeList_free( p_icons );
        }
    }
    ixmlNodeList_free( p_icon_lists );

    if ( res.empty() == false )
    {
        vlc_url_t url;
        vlc_UrlParse( &url, psz_base_url );
        char* psz_url;
        if ( asprintf( &psz_url, "%s://%s:%u%s", url.psz_protocol, url.psz_host, url.i_port, res.c_str() ) < 0 )
            res.clear();
        else
        {
            res = psz_url;
            free( psz_url );
        }
        vlc_UrlClean( &url );
    }
    return res;
}
Exemple #2
0
/*
 * Extracts the result document from a SOAP response
 */
IXML_Document* parseBrowseResult( IXML_Document* p_doc )
{
    assert( p_doc );

    const char* psz_result_string = xml_getChildElementValue( p_doc, "Result" );

    if( !psz_result_string )
        return NULL;

    IXML_Document* p_browse_doc = ixmlParseBuffer( psz_result_string );

    return p_browse_doc;
}
Exemple #3
0
/*
 * Extracts the result document from a SOAP response
 */
IXML_Document* parseBrowseResult( IXML_Document* p_doc )
{
    assert( p_doc );

    // ixml*_getElementsByTagName will ultimately only case the pointer to a Node
    // pointer, and pass it to a private function. Don't bother have a IXML_Document
    // version of getChildElementValue
    const char* psz_raw_didl = xml_getChildElementValue( (IXML_Element*)p_doc, "Result" );

    if( !psz_raw_didl )
        return NULL;

    /* First, try parsing the buffer as is */
    IXML_Document* p_result_doc = ixmlParseBuffer( psz_raw_didl );
    if( !p_result_doc ) {
        /* Missing namespaces confuse the ixml parser. This is a very ugly
         * hack but it is needeed until devices start sending valid XML.
         *
         * It works that way:
         *
         * The DIDL document is extracted from the Result tag, then wrapped into
         * a valid XML header and a new root tag which contains missing namespace
         * definitions so the ixml parser understands it.
         *
         * If you know of a better workaround, please oh please fix it */
        const char* psz_xml_result_fmt = "<?xml version=\"1.0\" ?>"
                                         "<Result xmlns:sec=\"urn:samsung:metadata:2009\">%s</Result>";

        char* psz_xml_result_string = NULL;
        if( -1 == asprintf( &psz_xml_result_string,
                            psz_xml_result_fmt,
                            psz_raw_didl) )
            return NULL;

        p_result_doc = ixmlParseBuffer( psz_xml_result_string );
        free( psz_xml_result_string );
    }

    if( !p_result_doc )
        return NULL;

    IXML_NodeList *p_elems = ixmlDocument_getElementsByTagName( p_result_doc,
                             "DIDL-Lite" );

    IXML_Node *p_node = ixmlNodeList_item( p_elems, 0 );
    ixmlNodeList_free( p_elems );

    return (IXML_Document*)p_node;
}
Exemple #4
0
/*
 * Get the number value from a SOAP response
 */
int xml_getNumber( IXML_Document* p_doc,
                   const char* psz_tag_name )
{
    assert( p_doc );
    assert( psz_tag_name );

    const char* psz = xml_getChildElementValue( p_doc, psz_tag_name );

    if( !psz )
        return 0;

    char *psz_end;
    long l = strtol( psz, &psz_end, 10 );

    if( *psz_end || l < 0 || l > INT_MAX )
        return 0;

    return (int)l;
}
Exemple #5
0
bool MediaServer::addContainer( IXML_Element* containerElement )
{
    char* psz_url;

    const char* objectID = ixmlElement_getAttribute( containerElement, "id" );
    if ( !objectID )
        return false;

    const char* title = xml_getChildElementValue( containerElement, "dc:title" );
    if ( !title )
        return false;

    if( asprintf( &psz_url, "upnp://%s?ObjectID=%s", m_psz_root, objectID ) < 0 )
        return false;

    input_item_t* p_item = input_item_NewDirectory( psz_url, title, ITEM_NET );
    free( psz_url);
    if ( !p_item )
        return false;
    input_item_CopyOptions( p_item, m_node->p_item );
    input_item_node_AppendItem( m_node, p_item );
    input_item_Release( p_item );
    return true;
}
Exemple #6
0
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;
}
Exemple #7
0
void MediaServer::parseDeviceDescription( IXML_Document* doc,
                                          const char*    location,
                                          services_discovery_t* p_sd )
{
    if ( !doc )
    { 
        msg_Dbg( p_sd, "%s:%d: NULL", __FILE__, __LINE__ ); 
        return;
    }
    
    if ( !location )
    {
        msg_Dbg( p_sd, "%s:%d: NULL", __FILE__, __LINE__ ); 
        return;
    }

    const char* baseURL = location;

    // Try to extract baseURL

    IXML_NodeList* urlList = ixmlDocument_getElementsByTagName( doc, "baseURL" );
    if ( !urlList )
    {

        if ( IXML_Node* urlNode = ixmlNodeList_item( urlList, 0 ) )
        {
            IXML_Node* textNode = ixmlNode_getFirstChild( urlNode );
            if ( textNode ) baseURL = ixmlNode_getNodeValue( textNode );
        }

        ixmlNodeList_free( urlList );
    }

    // Get devices

    IXML_NodeList* deviceList =
                ixmlDocument_getElementsByTagName( doc, "device" );
    
    if ( deviceList )
    {
        for ( unsigned int i = 0; i < ixmlNodeList_length( deviceList ); i++ )
        {
            IXML_Element* deviceElement =
                   ( IXML_Element* ) ixmlNodeList_item( deviceList, i );

            const char* deviceType = xml_getChildElementValue( deviceElement,
                                                               "deviceType" );
            if ( !deviceType )
            {
                msg_Dbg( p_sd,
                        "%s:%d: no deviceType!",
                        __FILE__, __LINE__ );
                continue;
            }

            if ( strcmp( MEDIA_SERVER_DEVICE_TYPE, deviceType ) != 0 )
                continue;

            const char* UDN = xml_getChildElementValue( deviceElement, "UDN" );
            if ( !UDN )
            {
                msg_Dbg( p_sd, "%s:%d: no UDN!",
                        __FILE__, __LINE__ );
                continue;
            }
            
            if ( p_sd->p_sys->serverList->getServer( UDN ) != 0 )
                continue;

            const char* friendlyName =
                       xml_getChildElementValue( deviceElement, 
                                                 "friendlyName" );
            
            if ( !friendlyName )
            {
                msg_Dbg( p_sd, "%s:%d: no friendlyName!", __FILE__, __LINE__ );
                continue;
            }

            MediaServer* server = new MediaServer( UDN, friendlyName, p_sd );
            
            if ( !p_sd->p_sys->serverList->addServer( server ) )
            {

                delete server;
                server = 0;
                continue;
            }

            // Check for ContentDirectory service...
            IXML_NodeList* serviceList =
                       ixmlElement_getElementsByTagName( deviceElement,
                                                         "service" );
            if ( serviceList )
            {
                for ( unsigned int j = 0;
                      j < ixmlNodeList_length( serviceList ); j++ )
                {
                    IXML_Element* serviceElement =
                        ( IXML_Element* ) ixmlNodeList_item( serviceList, j );

                    const char* serviceType =
                        xml_getChildElementValue( serviceElement,
                                                  "serviceType" );
                    if ( !serviceType )
                        continue;

                    if ( strcmp( CONTENT_DIRECTORY_SERVICE_TYPE,
                                serviceType ) != 0 )
                        continue;

                    const char* eventSubURL =
                        xml_getChildElementValue( serviceElement,
                                                  "eventSubURL" );
                    if ( !eventSubURL )
                        continue;

                    const char* controlURL =
                        xml_getChildElementValue( serviceElement,
                                                  "controlURL" );
                    if ( !controlURL )
                        continue;

                    // Try to subscribe to ContentDirectory service

                    char* url = ( char* ) malloc( strlen( baseURL ) +
                            strlen( eventSubURL ) + 1 );
                    if ( url )
                    {
                        char* s1 = strdup( baseURL );
                        char* s2 = strdup( eventSubURL );

                        if ( UpnpResolveURL( s1, s2, url ) ==
                                UPNP_E_SUCCESS )
                        {
                            server->setContentDirectoryEventURL( url );
                            server->subscribeToContentDirectory();
                        }

                        free( s1 );
                        free( s2 );
                        free( url );
                    }

                    // Try to browse content directory...

                    url = ( char* ) malloc( strlen( baseURL ) +
                            strlen( controlURL ) + 1 );
                    if ( url )
                    {
                        char* s1 = strdup( baseURL );
                        char* s2 = strdup( controlURL );

                        if ( UpnpResolveURL( s1, s2, url ) ==
                                UPNP_E_SUCCESS )
                        {
                            server->setContentDirectoryControlURL( url );
                            server->fetchContents();
                        }

                        free( s1 );
                        free( s2 );
                        free( url );
                    }
               }
               ixmlNodeList_free( serviceList );
           }
       }
       ixmlNodeList_free( deviceList );
    }
}
Exemple #8
0
void MediaServerList::parseNewServer( IXML_Document *doc, const std::string &location )
{
    if ( !doc )
    {
        msg_Err( m_sd, "Null IXML_Document" );
        return;
    }

    if ( location.empty() )
    {
        msg_Err( m_sd, "Empty location" );
        return;
    }

    const char* psz_base_url = location.c_str();

    /* Try to extract baseURL */
    IXML_NodeList* p_url_list = ixmlDocument_getElementsByTagName( doc, "URLBase" );
    if ( p_url_list )
    {
        if ( IXML_Node* p_url_node = ixmlNodeList_item( p_url_list, 0 ) )
        {
            IXML_Node* p_text_node = ixmlNode_getFirstChild( p_url_node );
            if ( p_text_node )
                psz_base_url = ixmlNode_getNodeValue( p_text_node );
        }
        ixmlNodeList_free( p_url_list );
    }

    /* Get devices */
    IXML_NodeList* p_device_list = ixmlDocument_getElementsByTagName( doc, "device" );

    if ( !p_device_list )
        return;

    for ( unsigned int i = 0; i < ixmlNodeList_length( p_device_list ); i++ )
    {
        IXML_Element* p_device_element = ( IXML_Element* ) ixmlNodeList_item( p_device_list, i );

        if( !p_device_element )
            continue;

        const char* psz_device_type = xml_getChildElementValue( p_device_element, "deviceType" );

        if ( !psz_device_type )
        {
            msg_Warn( m_sd, "No deviceType found!" );
            continue;
        }

        if ( strncmp( MEDIA_SERVER_DEVICE_TYPE, psz_device_type,
                      strlen( MEDIA_SERVER_DEVICE_TYPE ) - 1 )
                && strncmp( SATIP_SERVER_DEVICE_TYPE, psz_device_type,
                            strlen( SATIP_SERVER_DEVICE_TYPE ) - 1 ) )
            continue;

        const char* psz_udn = xml_getChildElementValue( p_device_element,
                              "UDN" );
        if ( !psz_udn )
        {
            msg_Warn( m_sd, "No UDN!" );
            continue;
        }

        /* Check if server is already added */
        if ( getServer( psz_udn ) )
        {
            msg_Warn( m_sd, "Server with uuid '%s' already exists.", psz_udn );
            continue;
        }

        const char* psz_friendly_name =
            xml_getChildElementValue( p_device_element,
                                      "friendlyName" );

        if ( !psz_friendly_name )
        {
            msg_Dbg( m_sd, "No friendlyName!" );
            continue;
        }

        std::string iconUrl = getIconURL( p_device_element, psz_base_url );

        // We now have basic info, we need to get the content browsing url
        // so the access module can browse without fetching the manifest again

        if ( !strncmp( SATIP_SERVER_DEVICE_TYPE, psz_device_type,
                       strlen( SATIP_SERVER_DEVICE_TYPE ) - 1 ) )
        {
            SD::MediaServerDesc* p_server = NULL;

            vlc_url_t url;
            vlc_UrlParse( &url, psz_base_url );

            char *psz_satip_channellist = config_GetPsz(m_sd, "satip-channelist");
            if( !psz_satip_channellist ) {
                break;
            }

            /* a user may have provided a custom playlist url */
            if (strncmp(psz_satip_channellist, "CustomList", 10) == 0) {
                char *psz_satip_playlist_url = config_GetPsz( m_sd, "satip-channellist-url" );
                if ( psz_satip_playlist_url ) {
                    p_server = new(std::nothrow) SD::MediaServerDesc( psz_udn, psz_friendly_name, psz_satip_playlist_url, iconUrl );

                    if( likely( p_server ) ) {
                        p_server->satIpHost = url.psz_host;
                        p_server->isSatIp = true;
                        if( !addServer( p_server ) ) {
                            delete p_server;
                        }
                    }

                    /* to comply with the SAT>IP specification, we don't fall back on another channel list if this path failed */
                    free( psz_satip_playlist_url );
                    vlc_UrlClean( &url );
                    continue;
                }
            }

            /* If requested by the user, check for a SAT>IP m3u list, which may be provided by some rare devices */
            if (strncmp(psz_satip_channellist, "ServerList", 10) == 0) {
                const char* psz_m3u_url = xml_getChildElementValue( p_device_element, "satip:X_SATIPM3U" );
                if ( psz_m3u_url ) {
                    if ( strncmp( "http", psz_m3u_url, 4) )
                    {
                        char* psz_url = NULL;
                        if ( UpnpResolveURL2( psz_base_url, psz_m3u_url, &psz_url ) == UPNP_E_SUCCESS )
                        {
                            p_server = new(std::nothrow) SD::MediaServerDesc( psz_udn, psz_friendly_name, psz_url, iconUrl );
                            free(psz_url);
                        }
                    } else {
                        p_server = new(std::nothrow) SD::MediaServerDesc( psz_udn, psz_friendly_name, psz_m3u_url, iconUrl );
                    }

                    if ( unlikely( !p_server ) )
                        break;

                    p_server->satIpHost = url.psz_host;
                    p_server->isSatIp = true;
                    if ( !addServer( p_server ) )
                        delete p_server;

                    free(psz_satip_channellist);
                } else {
                    msg_Warn( m_sd, "SAT>IP server '%s' did not provide a playlist", url.psz_host);
                }

                /* to comply with the SAT>IP specifications, we don't fallback on another channel list if this path failed */
                vlc_UrlClean( &url );
                continue;
            }

            /* Normally, fetch a playlist from the web,
             * which will be processed by a lua script a bit later */
            char *psz_url;
            if (asprintf( &psz_url, "http://www.satip.info/Playlists/%s.m3u",
                          psz_satip_channellist ) < 0 ) {
                vlc_UrlClean( &url );
                free( psz_satip_channellist );
                continue;
            }

            p_server = new(std::nothrow) SD::MediaServerDesc( psz_udn,
                    psz_friendly_name, psz_url, iconUrl );

            if( likely( p_server ) ) {
                p_server->satIpHost = url.psz_host;
                p_server->isSatIp = true;
                if( !addServer( p_server ) ) {
                    delete p_server;
                }
            }
            free( psz_url );
            free( psz_satip_channellist );
            vlc_UrlClean( &url );

            continue;
        }

        /* Check for ContentDirectory service. */
        IXML_NodeList* p_service_list = ixmlElement_getElementsByTagName( p_device_element, "service" );
        if ( !p_service_list )
            continue;
        for ( unsigned int j = 0; j < ixmlNodeList_length( p_service_list ); j++ )
        {
            IXML_Element* p_service_element = (IXML_Element*)ixmlNodeList_item( p_service_list, j );

            const char* psz_service_type = xml_getChildElementValue( p_service_element, "serviceType" );
            if ( !psz_service_type )
            {
                msg_Warn( m_sd, "No service type found." );
                continue;
            }

            int k = strlen( CONTENT_DIRECTORY_SERVICE_TYPE ) - 1;
            if ( strncmp( CONTENT_DIRECTORY_SERVICE_TYPE,
                          psz_service_type, k ) )
                continue;

            const char* psz_control_url = xml_getChildElementValue( p_service_element,
                                          "controlURL" );
            if ( !psz_control_url )
            {
                msg_Warn( m_sd, "No control url found." );
                continue;
            }

            /* Try to browse content directory. */
            char* psz_url = ( char* ) malloc( strlen( psz_base_url ) + strlen( psz_control_url ) + 1 );
            if ( psz_url )
            {
                if ( UpnpResolveURL( psz_base_url, psz_control_url, psz_url ) == UPNP_E_SUCCESS )
                {
                    SD::MediaServerDesc* p_server = new(std::nothrow) SD::MediaServerDesc( psz_udn,
                            psz_friendly_name, psz_url, iconUrl );
                    free( psz_url );
                    if ( unlikely( !p_server ) )
                        break;

                    if ( !addServer( p_server ) )
                    {
                        delete p_server;
                        continue;
                    }
                }
                else
                    free( psz_url );
            }
        }
        ixmlNodeList_free( p_service_list );
    }
    ixmlNodeList_free( p_device_list );
}
Exemple #9
0
bool MediaServer::addItem( IXML_Element* itemElement )
{
    ItemDescriptionHolder holder;

    if (!holder.init(itemElement))
        return false;
    /* Try to extract all resources in DIDL */
    IXML_NodeList* p_resource_list = ixmlDocument_getElementsByTagName( (IXML_Document*) itemElement, "res" );
    if ( !p_resource_list)
        return false;
    int list_lenght = ixmlNodeList_length( p_resource_list );
    if (list_lenght <= 0 ) {
        ixmlNodeList_free( p_resource_list );
        return false;
    }
    input_item_t *p_item = NULL;

    for (int index = 0; index < list_lenght; index++)
    {
        IXML_Element* p_resource = ( IXML_Element* ) ixmlNodeList_item( p_resource_list, index );
        const char* rez_type = ixmlElement_getAttribute( p_resource, "protocolInfo" );

        if (strncmp(rez_type, "http-get:*:video/", 17) == 0 && holder.media_type == ItemDescriptionHolder::VIDEO)
        {
            if (!p_item)
                p_item = holder.createNewItem(p_resource);
            holder.addSubtitleSlave(p_resource);
        }
        else if (strncmp(rez_type, "http-get:*:image/", 17) == 0)
            switch (holder.media_type)
            {
            case ItemDescriptionHolder::IMAGE:
                if (!p_item) {
                    p_item = holder.createNewItem(p_resource);
                    break;
                }
            case ItemDescriptionHolder::VIDEO:
            case ItemDescriptionHolder::AUDIO:
                holder.setArtworkURL(p_resource);
                break;
            }
        else if (strncmp(rez_type, "http-get:*:text/", 16) == 0)
            holder.addSlave(xml_getChildElementValue( p_resource, "res" ), SLAVE_TYPE_SPU);
        else if (strncmp(rez_type, "http-get:*:audio/", 17) == 0)
        {
            if (holder.media_type == ItemDescriptionHolder::AUDIO)
            {
                if (!p_item)
                    p_item = holder.createNewItem(p_resource);
            }
            else
                holder.addSlave(xml_getChildElementValue( p_resource, "res" ),
                                SLAVE_TYPE_AUDIO);
        }
    }
    ixmlNodeList_free( p_resource_list );
    if (!p_item)
        return false;
    holder.apply(p_item);
    input_item_CopyOptions( p_item, m_node->p_item );
    input_item_node_AppendItem( m_node, p_item );
    input_item_Release( p_item );
    return true;
}
Exemple #10
0
/*
 * 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;
}
Exemple #11
0
void MediaServer::parseDeviceDescription( IXML_Document* p_doc,
                                          const char*    p_location,
                                          services_discovery_t* p_sd )
{
    if ( !p_doc )
    {
        msg_Err( p_sd, "Null IXML_Document" );
        return;
    }

    if ( !p_location )
    {
        msg_Err( p_sd, "Null location" );
        return;
    }

    const char* psz_base_url = p_location;

    /* Try to extract baseURL */
    IXML_NodeList* p_url_list = ixmlDocument_getElementsByTagName( p_doc, "URLBase" );
    if ( p_url_list )
    {

        if ( IXML_Node* p_url_node = ixmlNodeList_item( p_url_list, 0 ) )
        {
            IXML_Node* p_text_node = ixmlNode_getFirstChild( p_url_node );
            if ( p_text_node ) psz_base_url = ixmlNode_getNodeValue( p_text_node );
        }

        ixmlNodeList_free( p_url_list );
    }

    /* Get devices */
    IXML_NodeList* p_device_list =
                ixmlDocument_getElementsByTagName( p_doc, "device" );

    if ( p_device_list )
    {
        for ( unsigned int i = 0; i < ixmlNodeList_length( p_device_list ); i++ )
        {
            IXML_Element* p_device_element =
                   ( IXML_Element* ) ixmlNodeList_item( p_device_list, i );

            const char* psz_device_type = xml_getChildElementValue( p_device_element,
                                                               "deviceType" );
            if ( !psz_device_type )
            {
                msg_Warn( p_sd, "No deviceType found!" );
                continue;
            }

            if ( strncmp( MEDIA_SERVER_DEVICE_TYPE, psz_device_type,
                    strlen( MEDIA_SERVER_DEVICE_TYPE ) - 1 ) != 0 )
                continue;

            const char* psz_udn = xml_getChildElementValue( p_device_element, "UDN" );
            if ( !psz_udn )
            {
                msg_Warn( p_sd, "No UDN!" );
                continue;
            }

            /* Check if server is already added */
            if ( p_sd->p_sys->p_server_list->getServer( psz_udn ) != 0 )
            {
                msg_Warn( p_sd, "Server with uuid '%s' already exists.", psz_udn );
                continue;
            }

            const char* psz_friendly_name =
                       xml_getChildElementValue( p_device_element,
                                                 "friendlyName" );

            if ( !psz_friendly_name )
            {
                msg_Dbg( p_sd, "No friendlyName!" );
                continue;
            }

            MediaServer* p_server = new MediaServer( psz_udn, psz_friendly_name, p_sd );

            if ( !p_sd->p_sys->p_server_list->addServer( p_server ) )
            {
                delete p_server;
                p_server = 0;
                continue;
            }

            /* Check for ContentDirectory service. */
            IXML_NodeList* p_service_list =
                       ixmlElement_getElementsByTagName( p_device_element,
                                                         "service" );
            if ( p_service_list )
            {
                for ( unsigned int j = 0;
                      j < ixmlNodeList_length( p_service_list ); j++ )
                {
                    IXML_Element* p_service_element =
                        ( IXML_Element* ) ixmlNodeList_item( p_service_list, j );

                    const char* psz_service_type =
                        xml_getChildElementValue( p_service_element,
                                                  "serviceType" );
                    if ( !psz_service_type )
                    {
                        msg_Warn( p_sd, "No service type found." );
                        continue;
                    }

                    int k = strlen( CONTENT_DIRECTORY_SERVICE_TYPE ) - 1;
                    if ( strncmp( CONTENT_DIRECTORY_SERVICE_TYPE,
                                psz_service_type, k ) != 0 )
                        continue;

		    p_server->_i_content_directory_service_version =
			psz_service_type[k];

                    const char* psz_event_sub_url =
                        xml_getChildElementValue( p_service_element,
                                                  "eventSubURL" );
                    if ( !psz_event_sub_url )
                    {
                        msg_Warn( p_sd, "No event subscription url found." );
                        continue;
                    }

                    const char* psz_control_url =
                        xml_getChildElementValue( p_service_element,
                                                  "controlURL" );
                    if ( !psz_control_url )
                    {
                        msg_Warn( p_sd, "No control url found." );
                        continue;
                    }

                    /* Try to subscribe to ContentDirectory service */

                    char* psz_url = ( char* ) malloc( strlen( psz_base_url ) +
                            strlen( psz_event_sub_url ) + 1 );
                    if ( psz_url )
                    {
                        if ( UpnpResolveURL( psz_base_url, psz_event_sub_url, psz_url ) ==
                                UPNP_E_SUCCESS )
                        {
                            p_server->setContentDirectoryEventURL( psz_url );
                            p_server->subscribeToContentDirectory();
                        }

                        free( psz_url );
                    }

                    /* Try to browse content directory. */

                    psz_url = ( char* ) malloc( strlen( psz_base_url ) +
                            strlen( psz_control_url ) + 1 );
                    if ( psz_url )
                    {
                        if ( UpnpResolveURL( psz_base_url, psz_control_url, psz_url ) ==
                                UPNP_E_SUCCESS )
                        {
                            p_server->setContentDirectoryControlURL( psz_url );
                            p_server->fetchContents();
                        }

                        free( psz_url );
                    }
               }
               ixmlNodeList_free( p_service_list );
           }
       }
       ixmlNodeList_free( p_device_list );
    }
}
Exemple #12
0
input_item_t* MediaServer::getNextItem()
{
    input_item_t *p_item = NULL;

    if( !xmlDocument_ )
    {
        fetchContents();
        if( !xmlDocument_ )
            return NULL;
    }

    if ( containerNodeList_ )
    {
        for ( ; !p_item && containerNodeIndex_ < ixmlNodeList_length( containerNodeList_ )
              ; containerNodeIndex_++ )
        {
            IXML_Element* containerElement = (IXML_Element*)ixmlNodeList_item( containerNodeList_,
                                                                                containerNodeIndex_ );

            const char* objectID = ixmlElement_getAttribute( containerElement,
                                                             "id" );
            if ( !objectID )
                continue;

            const char* title = xml_getChildElementValue( containerElement,
                                                          "dc:title" );
            if ( !title )
                continue;
            p_item = newItem(objectID, title);
        }
    }

    if( itemNodeList_ )
    {
        for ( ; !p_item && itemNodeIndex_ < ixmlNodeList_length( itemNodeList_ )
              ; itemNodeIndex_++ )
        {
            IXML_Element* itemElement =
                        ( IXML_Element* )ixmlNodeList_item( itemNodeList_,
                                                            itemNodeIndex_ );

            const char* objectID =
                        ixmlElement_getAttribute( itemElement, "id" );

            if ( !objectID )
                continue;

            const char* title =
                        xml_getChildElementValue( itemElement, "dc:title" );

            if ( !title )
                continue;

            const char* psz_subtitles = xml_getChildElementValue( itemElement,
                    "sec:CaptionInfo" );

            if ( !psz_subtitles )
                psz_subtitles = xml_getChildElementValue( itemElement,
                        "sec:CaptionInfoEx" );

            if ( !psz_subtitles )
                psz_subtitles = xml_getChildElementValue( itemElement,
                        "pv:subtitlefile" );

            /* Try to extract all resources in DIDL */
            IXML_NodeList* p_resource_list = ixmlDocument_getElementsByTagName( (IXML_Document*) itemElement, "res" );
            if ( p_resource_list && ixmlNodeList_length( p_resource_list ) > 0 )
            {
                mtime_t i_duration = -1;
                int i_hours, i_minutes, i_seconds;
                IXML_Element* p_resource = ( IXML_Element* ) ixmlNodeList_item( p_resource_list, 0 );
                const char* psz_resource_url = xml_getChildElementValue( p_resource, "res" );
                if( !psz_resource_url )
                    continue;
                const char* psz_duration = ixmlElement_getAttribute( p_resource, "duration" );

                if ( psz_duration )
                {
                    if( sscanf( psz_duration, "%d:%02d:%02d",
                        &i_hours, &i_minutes, &i_seconds ) )
                        i_duration = INT64_C(1000000) * ( i_hours*3600 +
                                                          i_minutes*60 +
                                                          i_seconds );
                }

                p_item = newItem( title, objectID, psz_subtitles, i_duration,
                                  psz_resource_url );
            }
            ixmlNodeList_free( p_resource_list );
        }
    }

    return p_item;
}
Exemple #13
0
void MediaServerList::parseNewServer( IXML_Document *doc, const std::string &location )
{
    if ( !doc )
    {
        msg_Err( p_sd_, "Null IXML_Document" );
        return;
    }

    if ( location.empty() )
    {
        msg_Err( p_sd_, "Empty location" );
        return;
    }

    const char* psz_base_url = location.c_str();

    /* Try to extract baseURL */
    IXML_NodeList* p_url_list = ixmlDocument_getElementsByTagName( doc, "URLBase" );
    if ( p_url_list )
    {
        if ( IXML_Node* p_url_node = ixmlNodeList_item( p_url_list, 0 ) )
        {
            IXML_Node* p_text_node = ixmlNode_getFirstChild( p_url_node );
            if ( p_text_node )
                psz_base_url = ixmlNode_getNodeValue( p_text_node );
        }
        ixmlNodeList_free( p_url_list );
    }

    /* Get devices */
    IXML_NodeList* p_device_list = ixmlDocument_getElementsByTagName( doc, "device" );

    if ( !p_device_list )
        return;
    for ( unsigned int i = 0; i < ixmlNodeList_length( p_device_list ); i++ )
    {
        IXML_Element* p_device_element = ( IXML_Element* ) ixmlNodeList_item( p_device_list, i );

        if( !p_device_element )
            continue;

        const char* psz_device_type = xml_getChildElementValue( p_device_element, "deviceType" );

        if ( !psz_device_type )
        {
            msg_Warn( p_sd_, "No deviceType found!" );
            continue;
        }

        if ( strncmp( MEDIA_SERVER_DEVICE_TYPE, psz_device_type,
                strlen( MEDIA_SERVER_DEVICE_TYPE ) - 1 ) )
            continue;

        const char* psz_udn = xml_getChildElementValue( p_device_element,
                                                        "UDN" );
        if ( !psz_udn )
        {
            msg_Warn( p_sd_, "No UDN!" );
            continue;
        }

        /* Check if server is already added */
        if ( p_sd_->p_sys->p_server_list->getServer( psz_udn ) )
        {
            msg_Warn( p_sd_, "Server with uuid '%s' already exists.", psz_udn );
            continue;
        }

        const char* psz_friendly_name =
                   xml_getChildElementValue( p_device_element,
                                             "friendlyName" );

        if ( !psz_friendly_name )
        {
            msg_Dbg( p_sd_, "No friendlyName!" );
            continue;
        }

        // We now have basic info, we need to get the content browsing url
        // so the access module can browse without fetching the manifest again

        /* Check for ContentDirectory service. */
        IXML_NodeList* p_service_list = ixmlElement_getElementsByTagName( p_device_element, "service" );
        if ( !p_service_list )
            continue;
        for ( unsigned int j = 0; j < ixmlNodeList_length( p_service_list ); j++ )
        {
            IXML_Element* p_service_element = (IXML_Element*)ixmlNodeList_item( p_service_list, j );

            const char* psz_service_type = xml_getChildElementValue( p_service_element, "serviceType" );
            if ( !psz_service_type )
            {
                msg_Warn( p_sd_, "No service type found." );
                continue;
            }

            int k = strlen( CONTENT_DIRECTORY_SERVICE_TYPE ) - 1;
            if ( strncmp( CONTENT_DIRECTORY_SERVICE_TYPE,
                        psz_service_type, k ) )
                continue;

            const char* psz_control_url = xml_getChildElementValue( p_service_element,
                                          "controlURL" );
            if ( !psz_control_url )
            {
                msg_Warn( p_sd_, "No control url found." );
                continue;
            }

            /* Try to browse content directory. */
            char* psz_url = ( char* ) malloc( strlen( psz_base_url ) + strlen( psz_control_url ) + 1 );
            if ( psz_url )
            {
                if ( UpnpResolveURL( psz_base_url, psz_control_url, psz_url ) == UPNP_E_SUCCESS )
                {
                    SD::MediaServerDesc* p_server = new(std::nothrow) SD::MediaServerDesc( psz_udn,
                            psz_friendly_name, psz_url );
                    free( psz_url );
                    if ( unlikely( !p_server ) )
                        break;

                    if ( !addServer( p_server ) )
                    {
                        delete p_server;
                        continue;
                    }
                }
                else
                    free( psz_url );
            }
        }
        ixmlNodeList_free( p_service_list );
    }
    ixmlNodeList_free( p_device_list );
}
Exemple #14
0
/*
 * 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;
}