X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fservices_discovery%2Fupnp_intel.cpp;h=427c27ec438e049c94877070449ee25552164fbf;hb=2d5d004768fa322a36b95524a05f0f52e7822469;hp=645fb048397057fc82beb1b447d1fbeb0daf8e1c;hpb=c31a81335ee64828c956b611840ad7fdffc0c0af;p=vlc diff --git a/modules/services_discovery/upnp_intel.cpp b/modules/services_discovery/upnp_intel.cpp index 645fb04839..427c27ec43 100644 --- a/modules/services_discovery/upnp_intel.cpp +++ b/modules/services_discovery/upnp_intel.cpp @@ -29,241 +29,45 @@ \TODO: Debug messages: "__FILE__, __LINE__" ok ???, Wrn/Err ??? \TODO: Change names to VLC standard ??? */ - - -#include -#include - -#include -#include - #undef PACKAGE_NAME #ifdef HAVE_CONFIG_H # include "config.h" #endif -#include +#include "upnp_intel.hpp" + #include #include -// Constants +// Constants const 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"; -// Classes - -class MediaServer; -class MediaServerList; -class Item; -class Container; -class Lockable; - // VLC handle - struct services_discovery_sys_t { UpnpClient_Handle clientHandle; MediaServerList* serverList; - Lockable* callbackLock; -}; - -// Class definitions... - -class Lockable -{ -public: - - Lockable() - { - vlc_mutex_init( &_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, - services_discovery_t* p_sd ); - - MediaServer( const char* UDN, - const char* friendlyName, - services_discovery_t* p_sd ); - - ~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 setInputItem( input_item_t* p_input_item ); - - 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* ); - - services_discovery_t* _p_sd; - - Container* _contents; - input_item_t* _inputItem; - - std::string _UDN; - std::string _friendlyName; - - std::string _contentDirectoryEventURL; - std::string _contentDirectoryControlURL; - - int _subscriptionTimeOut; - Upnp_SID _subscriptionID; -}; - - -class MediaServerList -{ -public: - - MediaServerList( services_discovery_t* p_sd ); - ~MediaServerList(); - - bool addServer( MediaServer* s ); - void removeServer( const char* UDN ); - - MediaServer* getServer( const char* UDN ); - MediaServer* getServerBySID( const char* ); - -private: - - services_discovery_t* _p_sd; - - std::vector _list; -}; - - -class Item -{ -public: - - Item( Container* parent, - const char* objectID, - const char* title, - const char* resource ); - ~Item(); - - const char* getObjectID() const; - const char* getTitle() const; - const char* getResource() const; - - void setInputItem( input_item_t* p_input_item ); - input_item_t* getInputItem() const ; - -private: - - input_item_t* _inputItem; - - 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; - Container* getParent(); - - void setInputItem( input_item_t* p_input_item ); - input_item_t* getInputItem() const; - -private: - - input_item_t* _inputItem; - - Container* _parent; - - std::string _objectID; - std::string _title; - std::vector _items; - std::vector _containers; + vlc_mutex_t callbackLock; }; // VLC callback prototypes - static int Open( vlc_object_t* ); static void Close( vlc_object_t* ); +VLC_SD_PROBE_HELPER("upnp", N_("Universal Plug'n'Play")) // Module descriptor vlc_module_begin(); -set_shortname( "UPnP" ); -set_description( N_( "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 ); + set_shortname( "UPnP" ); + set_description( N_( "Universal Plug'n'Play" ) ); + set_category( CAT_PLAYLIST ); + set_subcategory( SUBCAT_PLAYLIST_SD ); + set_capability( "services_discovery", 0 ); + set_callbacks( Open, Close ); + + VLC_SD_PROBE_SUBMODULE vlc_module_end(); @@ -289,17 +93,16 @@ static int Open( vlc_object_t *p_this ) if(!(p_sd->p_sys = p_sys)) return VLC_ENOMEM; - services_discovery_SetLocalizedName( p_sd, _("UPnP devices") ); - res = UpnpInit( 0, 0 ); if( res != UPNP_E_SUCCESS ) { msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) ); + free( p_sys ); return VLC_EGENERIC; } p_sys->serverList = new MediaServerList( p_sd ); - p_sys->callbackLock = new Lockable(); + vlc_mutex_init( &p_sys->callbackLock ); res = UpnpRegisterClient( Callback, p_sd, &p_sys->clientHandle ); if( res != UPNP_E_SUCCESS ) @@ -311,7 +114,7 @@ static int Open( vlc_object_t *p_this ) res = UpnpSearchAsync( p_sys->clientHandle, 5, MEDIA_SERVER_DEVICE_TYPE, p_sd ); - + if( res != UPNP_E_SUCCESS ) { msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) ); @@ -328,7 +131,7 @@ static void Close( vlc_object_t *p_this ) UpnpFinish(); delete p_sd->p_sys->serverList; - delete p_sd->p_sys->callbackLock; + vlc_mutex_destroy( &p_sd->p_sys->callbackLock ); free( p_sd->p_sys ); } @@ -394,7 +197,7 @@ static int Callback( Upnp_EventType eventType, void* event, void* user_data ) { services_discovery_t *p_sd = ( services_discovery_t* ) user_data; services_discovery_sys_t* p_sys = p_sd->p_sys; - Locker locker( p_sys->callbackLock ); + vlc_mutex_locker locker( &p_sys->callbackLock ); switch( eventType ) { @@ -454,11 +257,11 @@ static int Callback( Upnp_EventType eventType, void* event, void* user_data ) case UPNP_EVENT_SUBSCRIBE_COMPLETE: msg_Warn( p_sd, "subscription complete" ); break; - + case UPNP_DISCOVERY_SEARCH_TIMEOUT: msg_Warn( p_sd, "search timeout" ); break; - + default: msg_Dbg( p_sd, "%s:%d: DEBUG: UNHANDLED EVENT ( TYPE=%d )", @@ -479,14 +282,14 @@ void MediaServer::parseDeviceDescription( IXML_Document* doc, services_discovery_t* p_sd ) { if ( !doc ) - { - msg_Dbg( p_sd, "%s:%d: NULL", __FILE__, __LINE__ ); + { + msg_Dbg( p_sd, "%s:%d: NULL", __FILE__, __LINE__ ); return; } - + if ( !location ) { - msg_Dbg( p_sd, "%s:%d: NULL", __FILE__, __LINE__ ); + msg_Dbg( p_sd, "%s:%d: NULL", __FILE__, __LINE__ ); return; } @@ -511,7 +314,7 @@ void MediaServer::parseDeviceDescription( IXML_Document* doc, IXML_NodeList* deviceList = ixmlDocument_getElementsByTagName( doc, "device" ); - + if ( deviceList ) { for ( unsigned int i = 0; i < ixmlNodeList_length( deviceList ); i++ ) @@ -539,14 +342,14 @@ void MediaServer::parseDeviceDescription( IXML_Document* doc, __FILE__, __LINE__ ); continue; } - + if ( p_sd->p_sys->serverList->getServer( UDN ) != 0 ) continue; const char* friendlyName = - xml_getChildElementValue( deviceElement, + xml_getChildElementValue( deviceElement, "friendlyName" ); - + if ( !friendlyName ) { msg_Dbg( p_sd, "%s:%d: no friendlyName!", __FILE__, __LINE__ ); @@ -554,7 +357,7 @@ void MediaServer::parseDeviceDescription( IXML_Document* doc, } MediaServer* server = new MediaServer( UDN, friendlyName, p_sd ); - + if ( !p_sd->p_sys->serverList->addServer( server ) ) { @@ -734,7 +537,7 @@ IXML_Document* MediaServer::_browseAction( const char* pObjectID, IXML_Document* action = 0; IXML_Document* response = 0; const char* url = getContentDirectoryControlURL(); - + if ( !url || strcmp( url, "" ) == 0 ) { msg_Dbg( _p_sd, "No subscription url set!" ); @@ -753,8 +556,8 @@ IXML_Document* MediaServer::_browseAction( const char* pObjectID, res = UpnpAddToAction( &action, "Browse", serviceType, "ObjectID", ObjectID ); - - if ( res != UPNP_E_SUCCESS ) + + if ( res != UPNP_E_SUCCESS ) { msg_Dbg( _p_sd, "%s:%d: ERROR: %s", __FILE__, __LINE__, @@ -764,7 +567,7 @@ IXML_Document* MediaServer::_browseAction( const char* pObjectID, res = UpnpAddToAction( &action, "Browse", serviceType, "BrowseFlag", BrowseFlag ); - + if ( res != UPNP_E_SUCCESS ) { msg_Dbg( _p_sd, @@ -775,7 +578,7 @@ IXML_Document* MediaServer::_browseAction( const char* pObjectID, res = UpnpAddToAction( &action, "Browse", serviceType, "Filter", Filter ); - + if ( res != UPNP_E_SUCCESS ) { msg_Dbg( _p_sd, @@ -806,7 +609,7 @@ IXML_Document* MediaServer::_browseAction( const char* pObjectID, res = UpnpAddToAction( &action, "Browse", serviceType, "SortCriteria", SortCriteria ); - + if ( res != UPNP_E_SUCCESS ) { msg_Dbg( _p_sd, @@ -821,7 +624,7 @@ IXML_Document* MediaServer::_browseAction( const char* pObjectID, 0, action, &response ); - + if ( res != UPNP_E_SUCCESS ) { msg_Dbg( _p_sd, @@ -853,18 +656,10 @@ void MediaServer::fetchContents() Container* root = new Container( 0, "0", getFriendlyName() ); _fetchContents( root ); - // if ( _contents ) - // { - // PL_LOCK; - // playlist_NodeEmpty( p_playlist, _playlistNode, true ); - // PL_UNLOCK; - // delete _contents; - // } - _contents = root; _contents->setInputItem( _inputItem ); - _buildPlaylist( _contents ); + _buildPlaylist( _contents, NULL ); } bool MediaServer::_fetchContents( Container* parent ) @@ -889,7 +684,7 @@ bool MediaServer::_fetchContents( Container* parent ) IXML_Document* result = parseBrowseResult( response ); ixmlDocument_free( response ); - + if ( !result ) { msg_Dbg( _p_sd, @@ -900,7 +695,7 @@ bool MediaServer::_fetchContents( Container* parent ) IXML_NodeList* containerNodeList = ixmlDocument_getElementsByTagName( result, "container" ); - + if ( containerNodeList ) { for ( unsigned int i = 0; @@ -916,17 +711,17 @@ bool MediaServer::_fetchContents( Container* parent ) 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" ); @@ -959,19 +754,19 @@ bool MediaServer::_fetchContents( Container* parent ) 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; @@ -985,17 +780,22 @@ bool MediaServer::_fetchContents( Container* parent ) return true; } -void MediaServer::_buildPlaylist( Container* parent ) +void MediaServer::_buildPlaylist( Container* parent, input_item_node_t *p_input_node ) { + bool send = p_input_node == NULL; + if( send ) + p_input_node = input_item_node_Create( parent->getInputItem() ); + for ( unsigned int i = 0; i < parent->getNumContainers(); i++ ) { Container* container = parent->getContainer( i ); - input_item_t* p_input_item = input_item_New( _p_sd, "vlc://nop", parent->getTitle() ); - input_item_AddSubItem( parent->getInputItem(), p_input_item ); + input_item_t* p_input_item = input_item_New( _p_sd, "vlc://nop", parent->getTitle() ); + input_item_node_t *p_new_node = + input_item_node_AppendItem( p_input_node, p_input_item ); container->setInputItem( p_input_item ); - _buildPlaylist( container ); + _buildPlaylist( container, p_new_node ); } for ( unsigned int i = 0; i < parent->getNumItems(); i++ ) @@ -1006,9 +806,12 @@ void MediaServer::_buildPlaylist( Container* parent ) item->getResource(), item->getTitle() ); assert( p_input_item ); - input_item_AddSubItem( parent->getInputItem(), p_input_item ); + input_item_node_AppendItem( p_input_node, p_input_item ); item->setInputItem( p_input_item ); } + + if( send ) + input_item_node_PostAndDelete( p_input_node ); } void MediaServer::setInputItem( input_item_t* p_input_item ) @@ -1054,7 +857,7 @@ bool MediaServerList::addServer( MediaServer* s ) services_discovery_t* p_sd = _p_sd; - p_input_item = input_item_New( p_sd, "vlc://nop", s->getFriendlyName() ); + p_input_item = input_item_New( p_sd, "vlc://nop", s->getFriendlyName() ); s->setInputItem( p_input_item ); services_discovery_AddItem( p_sd, p_input_item, NULL );