/*****************************************************************************
- * Upnp_intell.cpp : UPnP discovery module (Intel SDK)
+ * Upnp_intel.cpp : UPnP discovery module (Intel SDK)
*****************************************************************************
- * Copyright (C) 2004-2006 the VideoLAN team
+ * Copyright (C) 2004-2008 the VideoLAN team
* $Id$
*
* Authors: RĂ©mi Denis-Courmont <rem # videolan.org> (original plugin)
* Christian Henz <henz # c-lab.de>
+ * Mirsal Ennaime <mirsal dot ennaime at gmail dot com>
*
* UPnP Plugin using the Intel SDK (libupnp) instead of CyberLink
*
/*
\TODO: Debug messages: "__FILE__, __LINE__" ok ???, Wrn/Err ???
- \TODO: Change names to VLC standard ???
- \TODO: Rewrite this using the new service discovery API (see sap.c, shout.c).
*/
-
-
-#include <vector>
-#include <string>
-
-#include <upnp/upnp.h>
-#include <upnp/upnptools.h>
-
#undef PACKAGE_NAME
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include <vlc_common.h>
-#include <vlc_plugin.h>
-#include <vlc_playlist.h>
+#include "upnp_intel.hpp"
-
-// VLC handle
-
-struct services_discovery_sys_t
-{
- playlist_t *p_playlist;
- playlist_item_t *p_node_cat;
- playlist_item_t *p_node_one;
-};
+#include <vlc_plugin.h>
+#include <vlc_services_discovery.h>
// 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;
-
-// Cookie that is passed to the callback
-
-typedef struct
-{
- services_discovery_t* serviceDiscovery;
- UpnpClient_Handle clientHandle;
- MediaServerList* serverList;
-} Cookie;
-
-
-// Class definitions...
-
-class Lockable
-{
-public:
-
- Lockable( Cookie* c )
- {
- 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, 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
+// VLC handle
+struct services_discovery_sys_t
{
-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;
+ UpnpClient_Handle client_handle;
+ MediaServerList* p_server_list;
+ vlc_mutex_t callback_lock;
};
-
// VLC callback prototypes
-
static int Open( vlc_object_t* );
static void Close( vlc_object_t* );
-static void Run( services_discovery_t *p_sd );
-static playlist_t *pl_Get( services_discovery_t *p_sd )
-{
- return p_sd->p_sys->p_playlist;
-}
+VLC_SD_PROBE_HELPER("upnp_intel", "Universal Plug'n'Play", SD_CAT_LAN)
// 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();
// More prototypes...
-static Lockable* CallbackLock;
-static int Callback( Upnp_EventType eventType, void* event, void* pCookie );
+static int Callback( Upnp_EventType event_type, void* p_event, void* p_user_data );
+
+const char* xml_getChildElementValue( IXML_Element* p_parent,
+ const char* psz_tag_name );
-const char* xml_getChildElementValue( IXML_Element* parent, const char* tagName );
-IXML_Document* parseBrowseResult( IXML_Document* doc );
+IXML_Document* parseBrowseResult( IXML_Document* p_doc );
// VLC callbacks...
static int Open( vlc_object_t *p_this )
{
+ int i_res;
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 ) );
-
- p_sd->pf_run = Run;
- p_sd->p_sys = p_sys;
- p_sys->p_playlist = pl_Yield( p_sd );
-
- /* Create our playlist node */
- vlc_object_lock( p_sys->p_playlist );
- playlist_NodesPairCreate( pl_Get( p_sd ), _("Devices"),
- &p_sys->p_node_cat, &p_sys->p_node_one,
- true );
- vlc_object_unlock( p_sys->p_playlist );
-
- 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;
-
- vlc_object_lock( p_sys->p_playlist );
- playlist_NodeDelete( pl_Get( p_sd ), p_sys->p_node_one, true,
- true );
- playlist_NodeDelete( pl_Get( p_sd ), p_sys->p_node_cat, true,
- true );
- vlc_object_unlock( p_sys->p_playlist );
- pl_Release( p_sd );
- free( p_sys );
-}
+ calloc( 1, sizeof( services_discovery_sys_t ) );
-static void Run( services_discovery_t* p_sd )
-{
- int res;
+ if(!(p_sd->p_sys = p_sys))
+ return VLC_ENOMEM;
- res = UpnpInit( 0, 0 );
- if( res != UPNP_E_SUCCESS )
+ i_res = UpnpInit( 0, 0 );
+ if( i_res != UPNP_E_SUCCESS )
{
- msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
- return;
+ msg_Err( p_sd, "%s", UpnpGetErrorMessage( i_res ) );
+ free( p_sys );
+ return VLC_EGENERIC;
}
- Cookie cookie;
- cookie.serviceDiscovery = p_sd;
- cookie.serverList = new MediaServerList( &cookie );
+ p_sys->p_server_list = new MediaServerList( p_sd );
+ vlc_mutex_init( &p_sys->callback_lock );
- CallbackLock = new Lockable( &cookie );
-
- res = UpnpRegisterClient( Callback, &cookie, &cookie.clientHandle );
- if( res != UPNP_E_SUCCESS )
+ i_res = UpnpRegisterClient( Callback, p_sd, &p_sys->client_handle );
+ if( i_res != UPNP_E_SUCCESS )
{
- msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
- goto shutDown;
+ msg_Err( p_sd, "%s", UpnpGetErrorMessage( i_res ) );
+ Close( (vlc_object_t*) p_sd );
+ return VLC_EGENERIC;
}
- res = UpnpSearchAsync( cookie.clientHandle, 5, MEDIA_SERVER_DEVICE_TYPE, &cookie );
- if( res != UPNP_E_SUCCESS )
+ i_res = UpnpSearchAsync( p_sys->client_handle, 5,
+ MEDIA_SERVER_DEVICE_TYPE, p_sd );
+
+ if( i_res != UPNP_E_SUCCESS )
{
- msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
- goto shutDown;
+ msg_Err( p_sd, "%s", UpnpGetErrorMessage( i_res ) );
+ Close( (vlc_object_t*) p_sd );
+ return VLC_EGENERIC;
}
- msg_Dbg( p_sd, "UPnP discovery started" );
- while( vlc_object_alive (p_sd) )
+ i_res = UpnpSetMaxContentLength( 262144 );
+ if( i_res != UPNP_E_SUCCESS )
{
- msleep( 500 );
+ msg_Err( p_sd, "%s", UpnpGetErrorMessage( i_res ) );
+ Close( (vlc_object_t*) p_sd );
+ return VLC_EGENERIC;
}
- msg_Dbg( p_sd, "UPnP discovery stopped" );
+ return VLC_SUCCESS;
+}
+
+static void Close( vlc_object_t *p_this )
+{
+ services_discovery_t *p_sd = ( services_discovery_t* )p_this;
- shutDown:
UpnpFinish();
- delete cookie.serverList;
- delete CallbackLock;
-}
+ delete p_sd->p_sys->p_server_list;
+ vlc_mutex_destroy( &p_sd->p_sys->callback_lock );
+ free( p_sd->p_sys );
+}
// XML utility functions:
// Returns the value of a child element, or 0 on error
-const char* xml_getChildElementValue( IXML_Element* parent, const char* tagName )
+const char* xml_getChildElementValue( IXML_Element* p_parent,
+ const char* psz_tag_name_ )
{
- if ( !parent ) return 0;
- if ( !tagName ) return 0;
+ if ( !p_parent ) return 0;
+ if ( !psz_tag_name_ ) return 0;
- char* s = strdup( tagName );
- IXML_NodeList* nodeList = ixmlElement_getElementsByTagName( parent, s );
- free( s );
- if ( !nodeList ) return 0;
+ char* psz_tag_name = strdup( psz_tag_name_ );
+ IXML_NodeList* p_node_list = ixmlElement_getElementsByTagName( p_parent, psz_tag_name );
+ free( psz_tag_name );
+ if ( !p_node_list ) return 0;
- IXML_Node* element = ixmlNodeList_item( nodeList, 0 );
- ixmlNodeList_free( nodeList );
- if ( !element ) return 0;
+ IXML_Node* p_element = ixmlNodeList_item( p_node_list, 0 );
+ ixmlNodeList_free( p_node_list );
+ if ( !p_element ) return 0;
- IXML_Node* textNode = ixmlNode_getFirstChild( element );
- if ( !textNode ) return 0;
+ IXML_Node* p_text_node = ixmlNode_getFirstChild( p_element );
+ if ( !p_text_node ) return 0;
- return ixmlNode_getNodeValue( textNode );
+ return ixmlNode_getNodeValue( p_text_node );
}
// Extracts the result document from a SOAP response
-IXML_Document* parseBrowseResult( IXML_Document* doc )
+IXML_Document* parseBrowseResult( IXML_Document* p_doc )
{
- if ( !doc ) return 0;
+ ixmlRelaxParser(1);
- IXML_NodeList* resultList = ixmlDocument_getElementsByTagName( doc, "Result" );
- if ( !resultList ) return 0;
+ if ( !p_doc ) return 0;
- IXML_Node* resultNode = ixmlNodeList_item( resultList, 0 );
+ IXML_NodeList* p_result_list = ixmlDocument_getElementsByTagName( p_doc,
+ "Result" );
- ixmlNodeList_free( resultList );
+ if ( !p_result_list ) return 0;
- if ( !resultNode ) return 0;
+ IXML_Node* p_result_node = ixmlNodeList_item( p_result_list, 0 );
- IXML_Node* textNode = ixmlNode_getFirstChild( resultNode );
- if ( !textNode ) return 0;
+ ixmlNodeList_free( p_result_list );
- const char* resultString = ixmlNode_getNodeValue( textNode );
- char* resultXML = strdup( resultString );
+ if ( !p_result_node ) return 0;
- IXML_Document* browseDoc = ixmlParseBuffer( resultXML );
+ IXML_Node* p_text_node = ixmlNode_getFirstChild( p_result_node );
+ if ( !p_text_node ) return 0;
- free( resultXML );
+ const char* psz_result_string = ixmlNode_getNodeValue( p_text_node );
+ char* psz_result_xml = strdup( psz_result_string );
- return browseDoc;
+ IXML_Document* p_browse_doc = ixmlParseBuffer( psz_result_xml );
+
+ free( psz_result_xml );
+
+ return p_browse_doc;
}
// Handles all UPnP events
-static int Callback( Upnp_EventType eventType, void* event, void* pCookie )
+static int Callback( Upnp_EventType event_type, void* p_event, void* p_user_data )
{
- Locker locker( CallbackLock );
-
- Cookie* cookie = ( Cookie* )pCookie;
-
- switch( eventType ) {
+ services_discovery_t* p_sd = ( services_discovery_t* ) p_user_data;
+ services_discovery_sys_t* p_sys = p_sd->p_sys;
+ vlc_mutex_locker locker( &p_sys->callback_lock );
+ switch( event_type )
+ {
case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
case UPNP_DISCOVERY_SEARCH_RESULT:
{
- struct Upnp_Discovery* discovery = ( struct Upnp_Discovery* )event;
+ struct Upnp_Discovery* p_discovery = ( struct Upnp_Discovery* )p_event;
- IXML_Document *descriptionDoc = 0;
+ IXML_Document *p_description_doc = 0;
- int res;
- res = UpnpDownloadXmlDoc( discovery->Location, &descriptionDoc );
- if ( res != UPNP_E_SUCCESS )
+ int i_res;
+ i_res = UpnpDownloadXmlDoc( p_discovery->Location, &p_description_doc );
+ if ( i_res != UPNP_E_SUCCESS )
{
- msg_Dbg( cookie->serviceDiscovery, "%s:%d: Could not download device description!", __FILE__, __LINE__ );
- return res;
+ msg_Dbg( p_sd,
+ "%s:%d: Could not download device description!",
+ __FILE__, __LINE__ );
+ return i_res;
}
- MediaServer::parseDeviceDescription( descriptionDoc, discovery->Location, cookie );
+ MediaServer::parseDeviceDescription( p_description_doc,
+ p_discovery->Location, p_sd );
- ixmlDocument_free( descriptionDoc );
+ ixmlDocument_free( p_description_doc );
}
break;
case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
{
- struct Upnp_Discovery* discovery = ( struct Upnp_Discovery* )event;
+ struct Upnp_Discovery* p_discovery = ( struct Upnp_Discovery* )p_event;
- cookie->serverList->removeServer( discovery->DeviceId );
+ p_sys->p_server_list->removeServer( p_discovery->DeviceId );
}
break;
case UPNP_EVENT_RECEIVED:
{
- Upnp_Event* e = ( Upnp_Event* )event;
+ Upnp_Event* p_e = ( Upnp_Event* )p_event;
- MediaServer* server = cookie->serverList->getServerBySID( e->Sid );
- if ( server ) server->fetchContents();
+ MediaServer* p_server = p_sys->p_server_list->getServerBySID( p_e->Sid );
+ if ( p_server ) p_server->fetchContents();
}
break;
{
// Re-subscribe...
- Upnp_Event_Subscribe* s = ( Upnp_Event_Subscribe* )event;
+ Upnp_Event_Subscribe* p_s = ( Upnp_Event_Subscribe* )p_event;
- MediaServer* server = cookie->serverList->getServerBySID( s->Sid );
- if ( server ) server->subscribeToContentDirectory();
+ MediaServer* p_server = p_sys->p_server_list->getServerBySID( p_s->Sid );
+ if ( p_server ) p_server->subscribeToContentDirectory();
}
break;
case UPNP_EVENT_SUBSCRIBE_COMPLETE:
- msg_Warn( cookie->serviceDiscovery, "subscription complete" );
+ msg_Warn( p_sd, "subscription complete" );
break;
-
+
case UPNP_DISCOVERY_SEARCH_TIMEOUT:
- msg_Warn( cookie->serviceDiscovery, "search timeout" );
+ msg_Warn( p_sd, "search timeout" );
break;
-
+
default:
- msg_Dbg( cookie->serviceDiscovery, "%s:%d: DEBUG: UNHANDLED EVENT ( TYPE=%d )", __FILE__, __LINE__, eventType );
+ msg_Dbg( p_sd,
+ "%s:%d: DEBUG: UNHANDLED EVENT ( TYPE=%d )",
+ __FILE__, __LINE__, event_type );
break;
}
// MediaServer...
-void MediaServer::parseDeviceDescription( IXML_Document* doc, const char* location, Cookie* cookie )
+void MediaServer::parseDeviceDescription( IXML_Document* p_doc,
+ const char* p_location,
+ services_discovery_t* p_sd )
{
- 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 ( !p_doc )
{
- if ( IXML_Node* urlNode = ixmlNodeList_item( urlList, 0 ) )
- {
- IXML_Node* textNode = ixmlNode_getFirstChild( urlNode );
- if ( textNode ) baseURL = ixmlNode_getNodeValue( textNode );
+ msg_Dbg( p_sd, "%s:%d: NULL", __FILE__, __LINE__ );
+ return;
}
- ixmlNodeList_free( urlList );
+ if ( !p_location )
+ {
+ msg_Dbg( p_sd, "%s:%d: NULL", __FILE__, __LINE__ );
+ return;
}
- // Get devices
+ const char* psz_base_url = p_location;
- IXML_NodeList* deviceList = ixmlDocument_getElementsByTagName( doc, "device" );
- if ( deviceList )
- {
+ // Try to extract baseURL
- for ( unsigned int i = 0; i < ixmlNodeList_length( deviceList ); i++ )
+ IXML_NodeList* p_url_list = ixmlDocument_getElementsByTagName( p_doc, "baseURL" );
+ if ( !p_url_list )
{
- 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;
+ 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 );
}
- // Check for ContentDirectory service...
+ ixmlNodeList_free( p_url_list );
+ }
- 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 );
+ // Get devices
- const char* serviceType = xml_getChildElementValue( serviceElement, "serviceType" );
- if ( !serviceType ) continue;
- if ( strcmp( CONTENT_DIRECTORY_SERVICE_TYPE, serviceType ) != 0 ) continue;
+ IXML_NodeList* p_device_list =
+ ixmlDocument_getElementsByTagName( p_doc, "device" );
- const char* eventSubURL = xml_getChildElementValue( serviceElement, "eventSubURL" );
- if ( !eventSubURL ) continue;
+ 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* controlURL = xml_getChildElementValue( serviceElement, "controlURL" );
- if ( !controlURL ) continue;
+ const char* psz_device_type = xml_getChildElementValue( p_device_element,
+ "deviceType" );
+ if ( !psz_device_type )
+ {
+ msg_Dbg( p_sd,
+ "%s:%d: no deviceType!",
+ __FILE__, __LINE__ );
+ continue;
+ }
- // Try to subscribe to ContentDirectory service
+ if ( strcmp( MEDIA_SERVER_DEVICE_TYPE, psz_device_type ) != 0 )
+ continue;
- char* url = ( char* )malloc( strlen( baseURL ) + strlen( eventSubURL ) + 1 );
- if ( url )
+ const char* psz_udn = xml_getChildElementValue( p_device_element, "UDN" );
+ if ( !psz_udn )
{
- char* s1 = strdup( baseURL );
- char* s2 = strdup( eventSubURL );
+ msg_Dbg( p_sd, "%s:%d: no UDN!",
+ __FILE__, __LINE__ );
+ continue;
+ }
- if ( UpnpResolveURL( s1, s2, url ) == UPNP_E_SUCCESS )
- {
- // msg_Dbg( cookie->serviceDiscovery, "CDS EVENT URL: %s", url );
+ if ( p_sd->p_sys->p_server_list->getServer( psz_udn ) != 0 )
+ continue;
- server->setContentDirectoryEventURL( url );
- server->subscribeToContentDirectory();
- }
+ const char* psz_friendly_name =
+ xml_getChildElementValue( p_device_element,
+ "friendlyName" );
- free( s1 );
- free( s2 );
- free( url );
+ if ( !psz_friendly_name )
+ {
+ msg_Dbg( p_sd, "%s:%d: no friendlyName!", __FILE__, __LINE__ );
+ continue;
}
- // Try to browse content directory...
-
- url = ( char* )malloc( strlen( baseURL ) + strlen( controlURL ) + 1 );
- if ( url )
- {
- char* s1 = strdup( baseURL );
- char* s2 = strdup( controlURL );
+ MediaServer* p_server = new MediaServer( psz_udn, psz_friendly_name, p_sd );
- if ( UpnpResolveURL( s1, s2, url ) == UPNP_E_SUCCESS )
+ if ( !p_sd->p_sys->p_server_list->addServer( p_server ) )
{
- // msg_Dbg( cookie->serviceDiscovery, "CDS CTRL URL: %s", url );
-
- server->setContentDirectoryControlURL( url );
- server->fetchContents();
- }
- free( s1 );
- free( s2 );
- free( url );
+ delete p_server;
+ p_server = 0;
+ continue;
}
- }
- ixmlNodeList_free( serviceList );
- }
- }
-
- ixmlNodeList_free( deviceList );
+ // 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 )
+ continue;
+
+ if ( strcmp( CONTENT_DIRECTORY_SERVICE_TYPE,
+ psz_service_type ) != 0 )
+ continue;
+
+ const char* psz_event_sub_url =
+ xml_getChildElementValue( p_service_element,
+ "eventSubURL" );
+ if ( !psz_event_sub_url )
+ continue;
+
+ const char* psz_control_url =
+ xml_getChildElementValue( p_service_element,
+ "controlURL" );
+ if ( !psz_control_url )
+ 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 )
+ {
+ char* psz_s1 = strdup( psz_base_url );
+ char* psz_s2 = strdup( psz_event_sub_url );
+
+ if ( UpnpResolveURL( psz_s1, psz_s2, psz_url ) ==
+ UPNP_E_SUCCESS )
+ {
+ p_server->setContentDirectoryEventURL( psz_url );
+ p_server->subscribeToContentDirectory();
+ }
+
+ free( psz_s1 );
+ free( psz_s2 );
+ free( psz_url );
+ }
+
+ // Try to browse content directory...
+
+ psz_url = ( char* ) malloc( strlen( psz_base_url ) +
+ strlen( psz_control_url ) + 1 );
+ if ( psz_url )
+ {
+ char* psz_s1 = strdup( psz_base_url );
+ char* psz_s2 = strdup( psz_control_url );
+
+ if ( UpnpResolveURL( psz_s1, psz_s2, psz_url ) ==
+ UPNP_E_SUCCESS )
+ {
+ p_server->setContentDirectoryControlURL( psz_url );
+ p_server->fetchContents();
+ }
+
+ free( psz_s1 );
+ free( psz_s2 );
+ free( psz_url );
+ }
+ }
+ ixmlNodeList_free( p_service_list );
+ }
+ }
+ ixmlNodeList_free( p_device_list );
}
}
-MediaServer::MediaServer( const char* UDN, const char* friendlyName, Cookie* cookie )
+MediaServer::MediaServer( const char* psz_udn,
+ const char* psz_friendly_name,
+ services_discovery_t* p_sd )
{
- _cookie = cookie;
+ _p_sd = p_sd;
- _UDN = UDN;
- _friendlyName = friendlyName;
+ _UDN = psz_udn;
+ _friendlyName = psz_friendly_name;
- _contents = 0;
- _playlistNode = 0;
+ _contents = NULL;
+ _inputItem = NULL;
}
MediaServer::~MediaServer()
{
- if ( _contents )
- {
- vlc_object_lock( _cookie->serviceDiscovery->p_sys->p_playlist );
- playlist_NodeDelete( pl_Get( _cookie->serviceDiscovery ) ,
- _playlistNode, true, true );
- vlc_object_unlock( _cookie->serviceDiscovery->p_sys->p_playlist );
- }
-
delete _contents;
}
return s;
}
-void MediaServer::setContentDirectoryEventURL( const char* url )
+void MediaServer::setContentDirectoryEventURL( const char* psz_url )
{
- _contentDirectoryEventURL = url;
+ _contentDirectoryEventURL = psz_url;
}
const char* MediaServer::getContentDirectoryEventURL() const
return s;
}
-void MediaServer::setContentDirectoryControlURL( const char* url )
+void MediaServer::setContentDirectoryControlURL( const char* psz_url )
{
- _contentDirectoryControlURL = url;
+ _contentDirectoryControlURL = psz_url;
}
const char* MediaServer::getContentDirectoryControlURL() const
void MediaServer::subscribeToContentDirectory()
{
- const char* url = getContentDirectoryEventURL();
- if ( !url || strcmp( url, "" ) == 0 )
+ const char* psz_url = getContentDirectoryEventURL();
+ if ( !psz_url || strcmp( psz_url, "" ) == 0 )
{
- msg_Dbg( _cookie->serviceDiscovery, "No subscription url set!" );
- return;
+ msg_Dbg( _p_sd, "No subscription url set!" );
+ return;
}
- int timeOut = 1810;
+ int i_timeout = 1810;
Upnp_SID sid;
- int res = UpnpSubscribe( _cookie->clientHandle, url, &timeOut, sid );
+ int i_res = UpnpSubscribe( _p_sd->p_sys->client_handle, psz_url, &i_timeout, sid );
- if ( res == UPNP_E_SUCCESS )
+ if ( i_res == UPNP_E_SUCCESS )
{
- _subscriptionTimeOut = timeOut;
- memcpy( _subscriptionID, sid, sizeof( Upnp_SID ) );
+ _subscriptionTimeOut = i_timeout;
+ memcpy( _subscriptionID, sid, sizeof( Upnp_SID ) );
}
else
{
- msg_Dbg( _cookie->serviceDiscovery, "%s:%d: WARNING: '%s': %s", __FILE__, __LINE__, getFriendlyName(), UpnpGetErrorMessage( res ) );
+ msg_Dbg( _p_sd,
+ "%s:%d: WARNING: '%s': %s", __FILE__, __LINE__,
+ getFriendlyName(), UpnpGetErrorMessage( i_res ) );
}
}
-IXML_Document* MediaServer::_browseAction( const char* pObjectID, const char* pBrowseFlag, const char* pFilter,
- const char* pStartingIndex, const char* pRequestedCount, const char* pSortCriteria )
+IXML_Document* MediaServer::_browseAction( const char* psz_object_id_,
+ const char* psz_browser_flag_,
+ const char* psz_filter_,
+ const char* psz_starting_index_,
+ const char* psz_requested_count_,
+ const char* psz_sort_criteria_ )
{
- IXML_Document* action = 0;
- IXML_Document* response = 0;
+ IXML_Document* p_action = 0;
+ IXML_Document* p_response = 0;
+ const char* psz_url = getContentDirectoryControlURL();
+
+ if ( !psz_url || strcmp( psz_url, "" ) == 0 )
+ {
+ msg_Dbg( _p_sd, "No subscription url set!" );
+ return 0;
+ }
+
+ char* psz_object_id = strdup( psz_object_id_ );
+ char* psz_browse_flag = strdup( psz_browser_flag_ );
+ char* psz_filter = strdup( psz_filter_ );
+ char* psz_starting_index = strdup( psz_starting_index_ );
+ char* psz_requested_count = strdup( psz_requested_count_ );
+ char* psz_sort_criteria = strdup( psz_sort_criteria_ );
+ char* psz_service_type = strdup( CONTENT_DIRECTORY_SERVICE_TYPE );
+
+ int i_res;
+
+ i_res = UpnpAddToAction( &p_action, "Browse",
+ psz_service_type, "ObjectID", psz_object_id );
+
+ if ( i_res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( i_res ) );
+ goto browseActionCleanup;
+ }
- const char* url = getContentDirectoryControlURL();
- if ( !url || strcmp( url, "" ) == 0 ) { msg_Dbg( _cookie->serviceDiscovery, "No subscription url set!" ); return 0; }
+ i_res = UpnpAddToAction( &p_action, "Browse",
+ psz_service_type, "BrowseFlag", psz_browse_flag );
- char* ObjectID = strdup( pObjectID );
- char* BrowseFlag = strdup( pBrowseFlag );
- char* Filter = strdup( pFilter );
- char* StartingIndex = strdup( pStartingIndex );
- char* RequestedCount = strdup( pRequestedCount );
- char* SortCriteria = strdup( pSortCriteria );
+ if ( i_res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( i_res ) );
+ goto browseActionCleanup;
+ }
- char* serviceType = strdup( CONTENT_DIRECTORY_SERVICE_TYPE );
+ i_res = UpnpAddToAction( &p_action, "Browse",
+ psz_service_type, "Filter", psz_filter );
- int res;
+ if ( i_res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( i_res ) );
+ goto browseActionCleanup;
+ }
- res = UpnpAddToAction( &action, "Browse", serviceType, "ObjectID", ObjectID );
- if ( res != UPNP_E_SUCCESS ) { /* msg_Dbg( _cookie->serviceDiscovery, "%s:%d: ERROR: %s", __FILE__, __LINE__, UpnpGetErrorMessage( res ) ); */ goto browseActionCleanup; }
+ i_res = UpnpAddToAction( &p_action, "Browse",
+ psz_service_type, "StartingIndex", psz_starting_index );
- res = UpnpAddToAction( &action, "Browse", serviceType, "BrowseFlag", BrowseFlag );
- if ( res != UPNP_E_SUCCESS ) { /* msg_Dbg( _cookie->serviceDiscovery, "%s:%d: ERROR: %s", __FILE__, __LINE__, UpnpGetErrorMessage( res ) ); */ goto browseActionCleanup; }
+ if ( i_res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( i_res ) );
+ goto browseActionCleanup;
+ }
- res = UpnpAddToAction( &action, "Browse", serviceType, "Filter", Filter );
- if ( res != UPNP_E_SUCCESS ) { /* msg_Dbg( _cookie->serviceDiscovery, "%s:%d: ERROR: %s", __FILE__, __LINE__, UpnpGetErrorMessage( res ) ); */ goto browseActionCleanup; }
+ i_res = UpnpAddToAction( &p_action, "Browse",
+ psz_service_type, "RequestedCount", psz_requested_count );
- res = UpnpAddToAction( &action, "Browse", serviceType, "StartingIndex", StartingIndex );
- if ( res != UPNP_E_SUCCESS ) { /* msg_Dbg( _cookie->serviceDiscovery, "%s:%d: ERROR: %s", __FILE__, __LINE__, UpnpGetErrorMessage( res ) ); */ goto browseActionCleanup; }
+ if ( i_res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( i_res ) ); goto browseActionCleanup; }
- res = UpnpAddToAction( &action, "Browse", serviceType, "RequestedCount", RequestedCount );
- if ( res != UPNP_E_SUCCESS ) { /* msg_Dbg( _cookie->serviceDiscovery, "%s:%d: ERROR: %s", __FILE__, __LINE__, UpnpGetErrorMessage( res ) ); */ goto browseActionCleanup; }
+ i_res = UpnpAddToAction( &p_action, "Browse",
+ psz_service_type, "SortCriteria", psz_sort_criteria );
- res = UpnpAddToAction( &action, "Browse", serviceType, "SortCriteria", SortCriteria );
- if ( res != UPNP_E_SUCCESS ) { /* msg_Dbg( _cookie->serviceDiscovery, "%s:%d: ERROR: %s", __FILE__, __LINE__, UpnpGetErrorMessage( res ) ); */ goto browseActionCleanup; }
+ if ( i_res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( i_res ) );
+ goto browseActionCleanup;
+ }
- res = UpnpSendAction( _cookie->clientHandle,
- url,
+ i_res = UpnpSendAction( _p_sd->p_sys->client_handle,
+ psz_url,
CONTENT_DIRECTORY_SERVICE_TYPE,
0,
- action,
- &response );
- if ( res != UPNP_E_SUCCESS )
+ p_action,
+ &p_response );
+
+ if ( i_res != UPNP_E_SUCCESS )
{
- msg_Dbg( _cookie->serviceDiscovery, "%s:%d: ERROR: %s", __FILE__, __LINE__, UpnpGetErrorMessage( res ) );
- ixmlDocument_free( response );
- response = 0;
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s when trying the send() action with URL: %s",
+ __FILE__, __LINE__,
+ UpnpGetErrorMessage( i_res ), psz_url );
+
+ ixmlDocument_free( p_response );
+ p_response = 0;
}
browseActionCleanup:
- free( ObjectID );
- free( BrowseFlag );
- free( Filter );
- free( StartingIndex );
- free( RequestedCount );
- free( SortCriteria );
+ free( psz_object_id );
+ free( psz_browse_flag );
+ free( psz_filter );
+ free( psz_starting_index );
+ free( psz_requested_count );
+ free( psz_sort_criteria );
- free( serviceType );
+ free( psz_service_type );
- ixmlDocument_free( action );
- return response;
+ ixmlDocument_free( p_action );
+ return p_response;
}
void MediaServer::fetchContents()
{
Container* root = new Container( 0, "0", getFriendlyName() );
- playlist_t * p_playlist = pl_Get( _cookie->serviceDiscovery );
_fetchContents( root );
- if ( _contents )
- {
- PL_LOCK;
- playlist_NodeEmpty( p_playlist, _playlistNode, true );
- PL_UNLOCK;
- delete _contents;
- }
-
_contents = root;
- _contents->setPlaylistNode( _playlistNode );
+ _contents->setInputItem( _inputItem );
- _buildPlaylist( _contents );
+ _buildPlaylist( _contents, NULL );
}
-bool MediaServer::_fetchContents( Container* parent )
+bool MediaServer::_fetchContents( Container* p_parent )
{
- if (!parent) { msg_Dbg( _cookie->serviceDiscovery, "%s:%d: parent==NULL", __FILE__, __LINE__ ); return false; }
+ if (!p_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( _cookie->serviceDiscovery, "%s:%d: ERROR!", __FILE__, __LINE__ ); return false; }
+ IXML_Document* p_response = _browseAction( p_parent->getObjectID(),
+ "BrowseDirectChildren",
+ "*", "0", "0", "" );
+ if ( !p_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( _cookie->serviceDiscovery, "%s:%d: ERROR!", __FILE__, __LINE__ ); return false; }
+ IXML_Document* result = parseBrowseResult( p_response );
+ ixmlDocument_free( p_response );
- IXML_NodeList* containerNodeList = ixmlDocument_getElementsByTagName( result, "container" );
- if ( containerNodeList )
+ if ( !result )
{
- for ( unsigned int i = 0; i < ixmlNodeList_length( containerNodeList ); i++ )
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR! browse() response parsing failed",
+ __FILE__, __LINE__ );
+ return false;
+ }
+
+ IXML_NodeList* containerNodeList =
+ ixmlDocument_getElementsByTagName( result, "container" );
+
+ if ( containerNodeList )
{
- IXML_Element* containerElement = ( IXML_Element* )ixmlNodeList_item( containerNodeList, i );
+ 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* objectID = ixmlElement_getAttribute( containerElement,
+ "id" );
+ if ( !objectID )
+ continue;
- const char* childCountStr = ixmlElement_getAttribute( containerElement, "childCount" );
- if ( !childCountStr ) continue;
- int childCount = atoi( childCountStr );
+ const char* childCountStr =
+ ixmlElement_getAttribute( containerElement, "childCount" );
- const char* title = xml_getChildElementValue( containerElement, "dc:title" );
- if ( !title ) continue;
+ if ( !childCountStr )
+ continue;
- const char* resource = xml_getChildElementValue( containerElement, "res" );
+ int childCount = atoi( childCountStr );
+ const char* title = xml_getChildElementValue( containerElement,
+ "dc:title" );
- 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 ( !title )
+ continue;
- if ( childCount > 0 ) _fetchContents( container );
- }
- }
+ const char* resource = xml_getChildElementValue( containerElement,
+ "res" );
+
+ if ( resource && childCount < 1 )
+ {
+ Item* item = new Item( p_parent, objectID, title, resource );
+ p_parent->addItem( item );
+ }
- ixmlNodeList_free( containerNodeList );
+ else
+ {
+ Container* container = new Container( p_parent, objectID, title );
+ p_parent->addContainer( container );
+
+ if ( childCount > 0 )
+ _fetchContents( container );
+ }
+ }
+ ixmlNodeList_free( containerNodeList );
}
- IXML_NodeList* itemNodeList = ixmlDocument_getElementsByTagName( result, "item" );
+ 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 );
+ {
+ IXML_Element* itemElement =
+ ( IXML_Element* )ixmlNodeList_item( itemNodeList, i );
- const char* objectID = ixmlElement_getAttribute( itemElement, "id" );
- if ( !objectID ) continue;
+ const char* objectID =
+ ixmlElement_getAttribute( itemElement, "id" );
- const char* title = xml_getChildElementValue( itemElement, "dc:title" );
- if ( !title ) continue;
+ if ( !objectID )
+ continue;
- const char* resource = xml_getChildElementValue( itemElement, "res" );
- if ( !resource ) continue;
+ const char* title =
+ xml_getChildElementValue( itemElement, "dc:title" );
- Item* item = new Item( parent, objectID, title, resource );
- parent->addItem( item );
- }
+ if ( !title )
+ continue;
+
+ const char* resource =
+ xml_getChildElementValue( itemElement, "res" );
- ixmlNodeList_free( itemNodeList );
+ if ( !resource )
+ continue;
+
+ Item* item = new Item( p_parent, objectID, title, resource );
+ p_parent->addItem( item );
+ }
+ ixmlNodeList_free( itemNodeList );
}
ixmlDocument_free( result );
-
return true;
}
-void MediaServer::_buildPlaylist( Container* parent )
+void MediaServer::_buildPlaylist( Container* p_parent, input_item_node_t *p_input_node )
{
- playlist_t *p_playlist = pl_Get( _cookie->serviceDiscovery );
- for ( unsigned int i = 0; i < parent->getNumContainers(); i++ )
+ bool send = p_input_node == NULL;
+ if( send )
+ p_input_node = input_item_node_Create( p_parent->getInputItem() );
+
+ for ( unsigned int i = 0; i < p_parent->getNumContainers(); i++ )
{
- Container* container = parent->getContainer( i );
- playlist_item_t* parentNode = parent->getPlaylistNode();
+ Container* container = p_parent->getContainer( i );
- char* title = strdup( container->getTitle() );
- playlist_item_t* node = playlist_NodeCreate( p_playlist, title, parentNode, 0, NULL );
- free( title );
+ input_item_t* p_input_item = input_item_New( _p_sd, "vlc://nop", container->getTitle() );
+ input_item_node_t *p_new_node =
+ input_item_node_AppendItem( p_input_node, p_input_item );
- container->setPlaylistNode( node );
- _buildPlaylist( container );
+ container->setInputItem( p_input_item );
+ _buildPlaylist( container, p_new_node );
}
- for ( unsigned int i = 0; i < parent->getNumItems(); i++ )
+ for ( unsigned int i = 0; i < p_parent->getNumItems(); i++ )
{
- Item* item = parent->getItem( i );
- playlist_item_t* parentNode = parent->getPlaylistNode();
+ Item* item = p_parent->getItem( i );
- input_item_t* p_input = input_ItemNew( _cookie->serviceDiscovery,
+ input_item_t* p_input_item = input_item_New( _p_sd,
item->getResource(),
item->getTitle() );
- int i_cat;
- /* FIXME: playlist_AddInput() can fail */
- playlist_BothAddInput( p_playlist, p_input, parentNode,
- PLAYLIST_APPEND, PLAYLIST_END, &i_cat, NULL,
- pl_Unlocked );
- vlc_gc_decref( p_input );
- /* TODO: do this better by storing ids */
- playlist_item_t *p_node = playlist_ItemGetById( p_playlist, i_cat, false );
- assert( p_node );
- item->setPlaylistNode( p_node );
+ assert( 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::setPlaylistNode( playlist_item_t* playlistNode )
+void MediaServer::setInputItem( input_item_t* p_input_item )
{
- _playlistNode = playlistNode;
+ if(_inputItem == p_input_item)
+ return;
+
+ if(_inputItem)
+ vlc_gc_decref( _inputItem );
+
+ vlc_gc_incref( p_input_item );
+ _inputItem = p_input_item;
}
bool MediaServer::compareSID( const char* sid )
// MediaServerList...
-MediaServerList::MediaServerList( Cookie* cookie )
+MediaServerList::MediaServerList( services_discovery_t* p_sd )
{
- _cookie = cookie;
+ _p_sd = p_sd;
}
MediaServerList::~MediaServerList()
{
for ( unsigned int i = 0; i < _list.size(); i++ )
{
- delete _list[i];
+ delete _list[i];
}
}
bool MediaServerList::addServer( MediaServer* s )
{
+ input_item_t* p_input_item = NULL;
if ( getServer( s->getUDN() ) != 0 ) return false;
- msg_Dbg( _cookie->serviceDiscovery, "Adding server '%s'", s->getFriendlyName() );
+ msg_Dbg( _p_sd, "Adding server '%s'",
+ s->getFriendlyName() );
- _list.push_back( s );
+ services_discovery_t* p_sd = _p_sd;
+
+ p_input_item = input_item_New( p_sd, "vlc://nop", s->getFriendlyName() );
+ s->setInputItem( p_input_item );
- char* name = strdup( s->getFriendlyName() );
- vlc_object_lock( _cookie->serviceDiscovery->p_sys->p_playlist );
- playlist_item_t* node = playlist_NodeCreate(
- pl_Get( _cookie->serviceDiscovery ), name,
- _cookie->serviceDiscovery->p_sys->p_node_cat,
- 0, NULL );
- vlc_object_unlock( _cookie->serviceDiscovery->p_sys->p_playlist );
- free( name );
- s->setPlaylistNode( node );
+ services_discovery_AddItem( p_sd, p_input_item, NULL );
+
+ _list.push_back( s );
return true;
}
-MediaServer* MediaServerList::getServer( const char* UDN )
+MediaServer* MediaServerList::getServer( const char* psz_udn )
{
MediaServer* result = 0;
for ( unsigned int i = 0; i < _list.size(); i++ )
{
- if( strcmp( UDN, _list[i]->getUDN() ) == 0 )
- {
- result = _list[i];
- break;
- }
+ if( strcmp( psz_udn, _list[i]->getUDN() ) == 0 )
+ {
+ result = _list[i];
+ break;
+ }
}
return result;
MediaServer* MediaServerList::getServerBySID( const char* sid )
{
- MediaServer* server = 0;
+ MediaServer* p_server = 0;
for ( unsigned int i = 0; i < _list.size(); i++ )
{
- if ( _list[i]->compareSID( sid ) )
- {
- server = _list[i];
- break;
- }
+ if ( _list[i]->compareSID( sid ) )
+ {
+ p_server = _list[i];
+ break;
+ }
}
- return server;
+ return p_server;
}
-void MediaServerList::removeServer( const char* UDN )
+void MediaServerList::removeServer( const char* psz_udn )
{
- MediaServer* server = getServer( UDN );
- if ( !server ) return;
+ MediaServer* p_server = getServer( psz_udn );
+ if ( !p_server ) return;
- msg_Dbg( _cookie->serviceDiscovery, "Removing server '%s'", server->getFriendlyName() );
+ msg_Dbg( _p_sd,
+ "Removing server '%s'", p_server->getFriendlyName() );
std::vector<MediaServer*>::iterator it;
for ( it = _list.begin(); it != _list.end(); it++ )
{
- if ( *it == server )
- {
- _list.erase( it );
- delete server;
- break;
- }
+ if ( *it == p_server )
+ {
+ _list.erase( it );
+ delete p_server;
+ break;
+ }
}
}
// Item...
-Item::Item( Container* parent, const char* objectID, const char* title, const char* resource )
+Item::Item( Container* p_parent, const char* psz_object_id, const char* psz_title,
+ const char* psz_resource )
{
- _parent = parent;
+ _parent = p_parent;
+
+ _objectID = psz_object_id;
+ _title = psz_title;
+ _resource = psz_resource;
- _objectID = objectID;
- _title = title;
- _resource = resource;
+ _inputItem = NULL;
+}
- _playlistNode = 0;
+Item::~Item()
+{
+ if(_inputItem)
+ vlc_gc_decref( _inputItem );
}
const char* Item::getObjectID() const
return _resource.c_str();
}
-void Item::setPlaylistNode( playlist_item_t* node )
+void Item::setInputItem( input_item_t* p_input_item )
{
- _playlistNode = node;
+ if(_inputItem == p_input_item)
+ return;
+
+ if(_inputItem)
+ vlc_gc_decref( _inputItem );
+
+ vlc_gc_incref( p_input_item );
+ _inputItem = p_input_item;
}
-playlist_item_t* Item::getPlaylistNode() const
+input_item_t* Item::getInputItem() const
{
- return _playlistNode;
+ return _inputItem;
}
// Container...
-Container::Container( Container* parent, const char* objectID, const char* title )
+Container::Container( Container* p_parent,
+ const char* psz_object_id,
+ const char* psz_title )
{
- _parent = parent;
+ _parent = p_parent;
- _objectID = objectID;
- _title = title;
+ _objectID = psz_object_id;
+ _title = psz_title;
- _playlistNode = 0;
+ _inputItem = NULL;
}
Container::~Container()
{
for ( unsigned int i = 0; i < _containers.size(); i++ )
{
- delete _containers[i];
+ delete _containers[i];
}
for ( unsigned int i = 0; i < _items.size(); i++ )
{
- delete _items[i];
+ delete _items[i];
}
+
+ if(_inputItem )
+ vlc_gc_decref( _inputItem );
}
void Container::addItem( Item* item )
_items.push_back( item );
}
-void Container::addContainer( Container* container )
+void Container::addContainer( Container* p_container )
{
- _containers.push_back( container );
+ _containers.push_back( p_container );
}
const char* Container::getObjectID() const
return _containers.size();
}
-Item* Container::getItem( unsigned int i ) const
+Item* Container::getItem( unsigned int i_index ) const
{
- if ( i < _items.size() ) return _items[i];
+ if ( i_index < _items.size() ) return _items[i_index];
return 0;
}
-Container* Container::getContainer( unsigned int i ) const
+Container* Container::getContainer( unsigned int i_index ) const
{
- if ( i < _containers.size() ) return _containers[i];
+ if ( i_index < _containers.size() ) return _containers[i_index];
return 0;
}
-void Container::setPlaylistNode( playlist_item_t* node )
+Container* Container::getParent()
+{
+ return _parent;
+}
+
+void Container::setInputItem( input_item_t* p_input_item )
{
- _playlistNode = node;
+ if(_inputItem == p_input_item)
+ return;
+
+ if(_inputItem)
+ vlc_gc_decref( _inputItem );
+
+ vlc_gc_incref( p_input_item );
+ _inputItem = p_input_item;
}
-playlist_item_t* Container::getPlaylistNode() const
+input_item_t* Container::getInputItem() const
{
- return _playlistNode;
+ return _inputItem;
}