⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 upnp_intel.cpp

📁 uclinux 下的vlc播放器源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * Upnp_intell.cpp :  UPnP discovery module (Intel SDK) ***************************************************************************** * Copyright (C) 2004-2006 the VideoLAN team * $Id: upnp_intel.cpp 16767 2006-09-21 14:32:45Z hartman $ * * Authors: Rémi Denis-Courmont <rem # videolan.org> (original plugin) *          Christian Henz <henz # c-lab.de> * * UPnP Plugin using the Intel SDK (libupnp) instead of CyberLink * * 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. * * 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; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//*  \TODO: Debug messages: "__FILE__, __LINE__" ok ???, Wrn/Err ???  \TODO: Change names to VLC standard ???*/#include <stdlib.h>#include <vector>#include <string>#include <upnp/upnp.h>#include <upnp/upnptools.h>#undef PACKAGE_NAME#include <vlc/vlc.h>#include <vlc/intf.h>#include "vlc_strings.h"// VLC handlestruct services_discovery_sys_t{    playlist_item_t *p_node;    playlist_t *p_playlist;};// Constantsconst char* MEDIA_SERVER_DEVICE_TYPE = "urn:schemas-upnp-org:device:MediaServer:1";const char* CONTENT_DIRECTORY_SERVICE_TYPE = "urn:schemas-upnp-org:service:ContentDirectory:1";// Classesclass MediaServer;class MediaServerList;class Item;class Container;// Cookie that is passed to the callbacktypedef struct{    services_discovery_t* serviceDiscovery;    UpnpClient_Handle clientHandle;    MediaServerList* serverList;} Cookie;// Class definitions...class Lockable{public:    Lockable( Cookie* c )    {    vlc_mutex_init( c->serviceDiscovery, &_mutex );    }    ~Lockable()    {    vlc_mutex_destroy( &_mutex );    }    void lock() { vlc_mutex_lock( &_mutex ); }    void unlock() { vlc_mutex_unlock( &_mutex ); }private:    vlc_mutex_t _mutex;};class Locker{public:    Locker( Lockable* l )    {    _lockable = l;    _lockable->lock();    }    ~Locker()    {    _lockable->unlock();    }private:    Lockable* _lockable;};class MediaServer{public:    static void parseDeviceDescription( IXML_Document* doc, const char* location, Cookie* cookie );    MediaServer( const char* UDN, const char* friendlyName, Cookie* cookie );    ~MediaServer();    const char* getUDN() const;    const char* getFriendlyName() const;    void setContentDirectoryEventURL( const char* url );    const char* getContentDirectoryEventURL() const;    void setContentDirectoryControlURL( const char* url );    const char* getContentDirectoryControlURL() const;    void subscribeToContentDirectory();    void fetchContents();    void setPlaylistNode( playlist_item_t* node );    bool compareSID( const char* sid );private:    bool _fetchContents( Container* parent );    void _buildPlaylist( Container* container );    IXML_Document* _browseAction( const char*, const char*, const char*, const char*, const char*, const char* );    Cookie* _cookie;    Container* _contents;    playlist_item_t* _playlistNode;    std::string _UDN;    std::string _friendlyName;    std::string _contentDirectoryEventURL;    std::string _contentDirectoryControlURL;    int _subscriptionTimeOut;    Upnp_SID _subscriptionID;};class MediaServerList{public:    MediaServerList( Cookie* cookie );    ~MediaServerList();    bool addServer( MediaServer* s );    void removeServer( const char* UDN );    MediaServer* getServer( const char* UDN );    MediaServer* getServerBySID( const char* );private:    Cookie* _cookie;    std::vector<MediaServer*> _list;};class Item{public:    Item( Container* parent, const char* objectID, const char* title, const char* resource );    const char* getObjectID() const;    const char* getTitle() const;    const char* getResource() const;    void setPlaylistNode( playlist_item_t* node );    playlist_item_t* getPlaylistNode() const ;private:    playlist_item_t* _playlistNode;    Container* _parent;    std::string _objectID;    std::string _title;    std::string _resource;};class Container{public:    Container( Container* parent, const char* objectID, const char* title );    ~Container();    void addItem( Item* item );    void addContainer( Container* container );    const char* getObjectID() const;    const char* getTitle() const;    unsigned int getNumItems() const;    unsigned int getNumContainers() const;    Item* getItem( unsigned int i ) const;    Container* getContainer( unsigned int i ) const;    void setPlaylistNode( playlist_item_t* node );    playlist_item_t* getPlaylistNode() const;private:    playlist_item_t* _playlistNode;    Container* _parent;    std::string _objectID;    std::string _title;    std::vector<Item*> _items;    std::vector<Container*> _containers;};// VLC callback prototypesstatic int Open( vlc_object_t* );static void Close( vlc_object_t* );static void Run( services_discovery_t *p_sd );// Module descriptorvlc_module_begin();set_shortname( "UPnP" );set_description( _( "Universal Plug'n'Play discovery ( Intel SDK )" ) );set_category( CAT_PLAYLIST );set_subcategory( SUBCAT_PLAYLIST_SD );set_capability( "services_discovery", 0 );set_callbacks( Open, Close );vlc_module_end();// More prototypes...static Lockable* CallbackLock;static int Callback( Upnp_EventType eventType, void* event, void* pCookie );const char* xml_getChildElementValue( IXML_Element* parent, const char* tagName );IXML_Document* parseBrowseResult( IXML_Document* doc );// VLC callbacks...static int Open( vlc_object_t *p_this ){    services_discovery_t *p_sd = ( services_discovery_t* )p_this;    services_discovery_sys_t *p_sys  = ( services_discovery_sys_t * )    malloc( sizeof( services_discovery_sys_t ) );    playlist_view_t *p_view;    vlc_value_t val;    p_sd->pf_run = Run;    p_sd->p_sys = p_sys;    /* Create our playlist node */    p_sys->p_playlist = ( playlist_t * )vlc_object_find( p_sd,                             VLC_OBJECT_PLAYLIST,                             FIND_ANYWHERE );    if( !p_sys->p_playlist )    {    msg_Warn( p_sd, "unable to find playlist, cancelling UPnP listening" );    return VLC_EGENERIC;    }    p_view = playlist_ViewFind( p_sys->p_playlist, VIEW_CATEGORY );    p_sys->p_node = playlist_NodeCreate( p_sys->p_playlist, VIEW_CATEGORY,                                         "UPnP", p_view->p_root );    p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG;    p_sys->p_node->i_flags &= ~PLAYLIST_SKIP_FLAG;    val.b_bool = VLC_TRUE;    var_Set( p_sys->p_playlist, "intf-change", val );    return VLC_SUCCESS;}static void Close( vlc_object_t *p_this ){    services_discovery_t *p_sd = ( services_discovery_t* )p_this;    services_discovery_sys_t *p_sys = p_sd->p_sys;    if( p_sys->p_playlist )    {    playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node, VLC_TRUE,                 VLC_TRUE );    vlc_object_release( p_sys->p_playlist );    }    free( p_sys );}static void Run( services_discovery_t* p_sd ){    int res;    res = UpnpInit( 0, 0 );    if( res != UPNP_E_SUCCESS )    {    msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );    return;    }    Cookie cookie;    cookie.serviceDiscovery = p_sd;    cookie.serverList = new MediaServerList( &cookie );    CallbackLock = new Lockable( &cookie );    res = UpnpRegisterClient( Callback, &cookie, &cookie.clientHandle );    if( res != UPNP_E_SUCCESS )    {    msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );    goto shutDown;    }    res = UpnpSearchAsync( cookie.clientHandle, 5, MEDIA_SERVER_DEVICE_TYPE, &cookie );    if( res != UPNP_E_SUCCESS )    {    msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );    goto shutDown;    }    msg_Dbg( p_sd, "UPnP discovery started" );    while( !p_sd->b_die )    {    msleep( 500 );    }    msg_Dbg( p_sd, "UPnP discovery stopped" ); shutDown:    UpnpFinish();    delete cookie.serverList;    delete CallbackLock;}// XML utility functions:// Returns the value of a child element, or 0 on errorconst char* xml_getChildElementValue( IXML_Element* parent, const char* tagName ){    if ( !parent ) return 0;    if ( !tagName ) return 0;    char* s = strdup( tagName );    IXML_NodeList* nodeList = ixmlElement_getElementsByTagName( parent, s );    free( s );    if ( !nodeList ) return 0;    IXML_Node* element = ixmlNodeList_item( nodeList, 0 );    ixmlNodeList_free( nodeList );    if ( !element ) return 0;    IXML_Node* textNode = ixmlNode_getFirstChild( element );    if ( !textNode ) return 0;    return ixmlNode_getNodeValue( textNode );}// Extracts the result document from a SOAP responseIXML_Document* parseBrowseResult( IXML_Document* doc ){    if ( !doc ) return 0;    IXML_NodeList* resultList = ixmlDocument_getElementsByTagName( doc, "Result" );    if ( !resultList ) return 0;    IXML_Node* resultNode = ixmlNodeList_item( resultList, 0 );    ixmlNodeList_free( resultList );    if ( !resultNode ) return 0;    IXML_Node* textNode = ixmlNode_getFirstChild( resultNode );    if ( !textNode ) return 0;    const char* resultString = ixmlNode_getNodeValue( textNode );    char* resultXML = strdup( resultString );        resolve_xml_special_chars( resultXML );    IXML_Document* browseDoc = ixmlParseBuffer( resultXML );    free( resultXML );    return browseDoc;}// Handles all UPnP eventsstatic int Callback( Upnp_EventType eventType, void* event, void* pCookie ){    Locker locker( CallbackLock );    Cookie* cookie = ( Cookie* )pCookie;    switch( eventType ) {    case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:    case UPNP_DISCOVERY_SEARCH_RESULT:    {        struct Upnp_Discovery* discovery = ( struct Upnp_Discovery* )event;        IXML_Document *descriptionDoc = 0;        int res;        res = UpnpDownloadXmlDoc( discovery->Location, &descriptionDoc );        if ( res != UPNP_E_SUCCESS )        {          msg_Dbg( cookie->serviceDiscovery, "%s:%d: Could not download device description!", __FILE__, __LINE__ );          return res;        }        MediaServer::parseDeviceDescription( descriptionDoc, discovery->Location, cookie );        ixmlDocument_free( descriptionDoc );    }    break;    case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:    {        struct Upnp_Discovery* discovery = ( struct Upnp_Discovery* )event;        cookie->serverList->removeServer( discovery->DeviceId );    }    break;    case UPNP_EVENT_RECEIVED:    {        Upnp_Event* e = ( Upnp_Event* )event;        MediaServer* server = cookie->serverList->getServerBySID( e->Sid );        if ( server ) server->fetchContents();    }    break;    case UPNP_EVENT_AUTORENEWAL_FAILED:    case UPNP_EVENT_SUBSCRIPTION_EXPIRED:    {        // Re-subscribe...        Upnp_Event_Subscribe* s = ( Upnp_Event_Subscribe* )event;        MediaServer* server = cookie->serverList->getServerBySID( s->Sid );        if ( server ) server->subscribeToContentDirectory();    }    break;    default:    msg_Dbg( cookie->serviceDiscovery, "%s:%d: DEBUG: UNHANDLED EVENT ( TYPE=%d )", __FILE__, __LINE__, eventType );    break;    }    return UPNP_E_SUCCESS;}// Class implementations...// MediaServer...void MediaServer::parseDeviceDescription( IXML_Document* doc, const char* location, Cookie* cookie ){    if ( !doc ) { msg_Dbg( cookie->serviceDiscovery, "%s:%d: NULL", __FILE__, __LINE__ ); return; }    if ( !location ) { msg_Dbg( cookie->serviceDiscovery, "%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( cookie->serviceDiscovery, "%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( cookie->serviceDiscovery, "%s:%d: no UDN!", __FILE__, __LINE__ ); continue; }        if ( cookie->serverList->getServer( UDN ) != 0 ) continue;        const char* friendlyName = xml_getChildElementValue( deviceElement, "friendlyName" );        if ( !friendlyName ) { msg_Dbg( cookie->serviceDiscovery, "%s:%d: no friendlyName!", __FILE__, __LINE__ ); continue; }        MediaServer* server = new MediaServer( UDN, friendlyName, cookie );        if ( !cookie->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" );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -