*
* 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
*
#include <vlc_plugin.h>
#include <vlc_playlist.h>
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-static int Open( vlc_object_t* );
-static void Close( vlc_object_t* );
-
-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 )
-vlc_module_end ()
-
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-
// Constants
const char* MEDIA_SERVER_DEVICE_TYPE = "urn:schemas-upnp-org:device:MediaServer:1";
class MediaServerList;
class Item;
class Container;
-class Lockable;
-// Cookie that is passed to the callback
+// VLC handle
-typedef struct
+struct services_discovery_sys_t
{
- services_discovery_t* serviceDiscovery;
UpnpClient_Handle clientHandle;
MediaServerList* serverList;
- Lockable* lock;
-} Cookie;
-
+};
// Class definitions...
class Lockable
{
public:
+
Lockable()
{
vlc_mutex_init( &_mutex );
void unlock() { vlc_mutex_unlock( &_mutex ); }
private:
+
vlc_mutex_t _mutex;
};
public:
Locker( Lockable* l )
{
- _lockable = l;
- _lockable->lock();
+ _lockable = l;
+ _lockable->lock();
}
~Locker()
{
- _lockable->unlock();
+ _lockable->unlock();
}
private:
{
public:
- static void parseDeviceDescription( IXML_Document* doc, const char* location, Cookie* cookie );
+ static void parseDeviceDescription( IXML_Document* doc,
+ const char* location,
+ services_discovery_t* p_sd );
- MediaServer( const char* UDN, const char* friendlyName, Cookie* cookie );
+ MediaServer( const char* UDN,
+ const char* friendlyName,
+ services_discovery_t* p_sd );
+
~MediaServer();
const char* getUDN() const;
bool _fetchContents( Container* parent );
void _buildPlaylist( Container* container );
- IXML_Document* _browseAction( const char*, const char*, const char*, const char*, const char*, const char* );
+
+ IXML_Document* _browseAction( const char*, const char*,
+ const char*, const char*, const char*, const char* );
- Cookie* _cookie;
+ services_discovery_t* _p_sd;
Container* _contents;
playlist_item_t* _playlistNode;
{
public:
- MediaServerList( Cookie* cookie );
+ MediaServerList( services_discovery_t* p_sd );
~MediaServerList();
bool addServer( MediaServer* s );
private:
- Cookie* _cookie;
+ services_discovery_t* _p_sd;
std::vector<MediaServer*> _list;
};
{
public:
- Item( Container* parent, const char* objectID, const char* title, const char* resource );
+ Item( Container* parent,
+ const char* objectID,
+ const char* title,
+ const char* resource );
const char* getObjectID() const;
const char* getTitle() const;
};
-
-// VLC handle
-
-struct services_discovery_sys_t
-{
- playlist_t *p_playlist;
- playlist_item_t *p_node_cat;
- playlist_item_t *p_node_one;
- Cookie cookie;
-};
-
-
-
// VLC callback prototypes
-static playlist_t *pl_Get( services_discovery_t *p_sd )
-{
- return p_sd->p_sys->p_playlist;
-}
+static int Open( vlc_object_t* );
+static void Close( vlc_object_t* );
+static void Run( services_discovery_t *p_sd );
+
+// 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 );
+vlc_module_end();
// More prototypes...
-static int Callback( Upnp_EventType eventType, void* event, void* pCookie );
+static Lockable* CallbackLock;
+static int Callback( Upnp_EventType eventType, void* event, void* user_data );
-const char* xml_getChildElementValue( IXML_Element* parent, const char* tagName );
-IXML_Document* parseBrowseResult( IXML_Document* doc );
+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 )
{
+ int 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 ) );
- playlist_t *p_playlist = pl_Hold( p_sd );
+ calloc( 1, sizeof( services_discovery_sys_t ) );
p_sd->p_sys = p_sys;
- p_sys->p_playlist = p_playlist;
- Cookie *cookie = &p_sys->cookie;
- /* Create our playlist node */
- PL_LOCK;
- playlist_NodesPairCreate( p_playlist, _("Devices"),
- &p_sys->p_node_cat, &p_sys->p_node_one,
- true );
- PL_UNLOCK;
-
- cookie->serviceDiscovery = p_sd;
- cookie->lock = new Lockable();
- cookie->serverList = new MediaServerList( cookie );
+ services_discovery_SetLocalizedName( p_sd, _("UPnP devices") );
- int res = UpnpInit( 0, 0 );
+ res = UpnpInit( 0, 0 );
if( res != UPNP_E_SUCCESS )
{
msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
- goto shutDown;
+ return VLC_EGENERIC;
}
- res = UpnpRegisterClient( Callback, cookie, &cookie->clientHandle );
+ p_sys->serverList = new MediaServerList( p_sd );
+ CallbackLock = new Lockable();
+
+ res = UpnpRegisterClient( Callback, p_sys, &p_sys->clientHandle );
if( res != UPNP_E_SUCCESS )
{
msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
- goto shutDown;
+ Close( (vlc_object_t*) p_sd );
+ return VLC_EGENERIC;
}
- res = UpnpSearchAsync( cookie->clientHandle, 5, MEDIA_SERVER_DEVICE_TYPE,
- cookie );
+ res = UpnpSearchAsync( p_sys->clientHandle, 5,
+ MEDIA_SERVER_DEVICE_TYPE, p_sd );
+
if( res != UPNP_E_SUCCESS )
{
msg_Err( p_sd, "%s", UpnpGetErrorMessage( res ) );
- goto shutDown;
+ Close( (vlc_object_t*) p_sd );
+ return VLC_EGENERIC;
}
return VLC_SUCCESS;
-
- shutDown:
- Close( p_this );
- return VLC_EGENERIC;
}
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;
- playlist_t *p_playlist = p_sys->p_playlist;
UpnpFinish();
- delete p_sys->cookie.serverList;
- delete p_sys->cookie.lock;
+ delete p_sd->p_sys->serverList;
+ delete CallbackLock;
- PL_LOCK;
- playlist_NodeDelete( p_playlist, p_sys->p_node_one, true, true );
- playlist_NodeDelete( p_playlist, p_sys->p_node_cat, true, true );
- PL_UNLOCK;
- pl_Release( p_sd );
- free( p_sys );
+ free( p_sd->p_sys );
}
+static void Run( services_discovery_t* p_sd )
+{
+
+ msg_Dbg( p_sd, "UPnP discovery started" );
+ while( vlc_object_alive (p_sd) )
+ {
+ msleep( 500 );
+ }
+
+ msg_Dbg( p_sd, "UPnP discovery stopped" );
+
+}
+
+
// 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* parent,
+ const char* tagName )
{
if ( !parent ) return 0;
if ( !tagName ) return 0;
// Extracts the result document from a SOAP response
IXML_Document* parseBrowseResult( IXML_Document* doc )
{
+ ixmlRelaxParser(1);
+
if ( !doc ) return 0;
- IXML_NodeList* resultList = ixmlDocument_getElementsByTagName( doc, "Result" );
+ IXML_NodeList* resultList = ixmlDocument_getElementsByTagName( doc,
+ "Result" );
+
if ( !resultList ) return 0;
IXML_Node* resultNode = ixmlNodeList_item( resultList, 0 );
// Handles all UPnP events
-static int Callback( Upnp_EventType eventType, void* event, void* pCookie )
+static int Callback( Upnp_EventType eventType, void* event, void* user_data )
{
- Cookie* cookie = ( Cookie* )pCookie;
+ Locker locker( CallbackLock );
- Locker locker( cookie->lock );
+ services_discovery_t *p_sd = ( services_discovery_t* ) user_data;
+ services_discovery_sys_t* p_sys = p_sd->p_sys;
switch( eventType ) {
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;
+ msg_Dbg( p_sd,
+ "%s:%d: Could not download device description!",
+ __FILE__, __LINE__ );
+ return res;
}
- MediaServer::parseDeviceDescription( descriptionDoc, discovery->Location, cookie );
+ MediaServer::parseDeviceDescription( descriptionDoc,
+ discovery->Location, p_sd );
ixmlDocument_free( descriptionDoc );
}
{
struct Upnp_Discovery* discovery = ( struct Upnp_Discovery* )event;
- cookie->serverList->removeServer( discovery->DeviceId );
+ p_sys->serverList->removeServer( discovery->DeviceId );
}
break;
{
Upnp_Event* e = ( Upnp_Event* )event;
- MediaServer* server = cookie->serverList->getServerBySID( e->Sid );
+ MediaServer* server = p_sys->serverList->getServerBySID( e->Sid );
if ( server ) server->fetchContents();
}
break;
Upnp_Event_Subscribe* s = ( Upnp_Event_Subscribe* )event;
- MediaServer* server = cookie->serverList->getServerBySID( s->Sid );
+ MediaServer* server = p_sys->serverList->getServerBySID( s->Sid );
if ( server ) 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__, eventType );
break;
}
// MediaServer...
-void MediaServer::parseDeviceDescription( IXML_Document* doc, const char* location, Cookie* cookie )
+void MediaServer::parseDeviceDescription( IXML_Document* doc,
+ const char* 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; }
+ 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 ) )
+ if ( !urlList )
{
- IXML_Node* textNode = ixmlNode_getFirstChild( urlNode );
- if ( textNode ) baseURL = ixmlNode_getNodeValue( textNode );
- }
- ixmlNodeList_free( 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" );
+ 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++ )
+ for ( unsigned int i = 0; i < ixmlNodeList_length( deviceList ); i++ )
{
- 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;
+ IXML_Element* deviceElement =
+ ( IXML_Element* ) ixmlNodeList_item( deviceList, i );
- // Try to subscribe to ContentDirectory service
-
- char* url = ( char* )malloc( strlen( baseURL ) + strlen( eventSubURL ) + 1 );
- if ( url )
+ const char* deviceType = xml_getChildElementValue( deviceElement,
+ "deviceType" );
+ if ( !deviceType )
{
- char* s1 = strdup( baseURL );
- char* s2 = strdup( eventSubURL );
-
- if ( UpnpResolveURL( s1, s2, url ) == UPNP_E_SUCCESS )
- {
- // msg_Dbg( cookie->serviceDiscovery, "CDS EVENT URL: %s", url );
-
- server->setContentDirectoryEventURL( url );
- server->subscribeToContentDirectory();
- }
-
- free( s1 );
- free( s2 );
- free( url );
+ msg_Dbg( p_sd,
+ "%s:%d: no deviceType!",
+ __FILE__, __LINE__ );
+ continue;
}
- // Try to browse content directory...
+ if ( strcmp( MEDIA_SERVER_DEVICE_TYPE, deviceType ) != 0 )
+ continue;
- url = ( char* )malloc( strlen( baseURL ) + strlen( controlURL ) + 1 );
- if ( url )
+ const char* UDN = xml_getChildElementValue( deviceElement, "UDN" );
+ if ( !UDN )
{
- char* s1 = strdup( baseURL );
- char* s2 = strdup( controlURL );
-
- if ( UpnpResolveURL( s1, s2, url ) == UPNP_E_SUCCESS )
+ 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( cookie->serviceDiscovery, "CDS CTRL URL: %s", url );
-
- server->setContentDirectoryControlURL( url );
- server->fetchContents();
+ msg_Dbg( p_sd, "%s:%d: no friendlyName!", __FILE__, __LINE__ );
+ continue;
}
- free( s1 );
- free( s2 );
- free( url );
- }
- }
+ MediaServer* server = new MediaServer( UDN, friendlyName, p_sd );
+
+ if ( !p_sd->p_sys->serverList->addServer( server ) )
+ {
- ixmlNodeList_free( serviceList );
- }
- }
+ delete server;
+ server = 0;
+ continue;
+ }
- ixmlNodeList_free( deviceList );
+ // 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 );
}
}
-MediaServer::MediaServer( const char* UDN, const char* friendlyName, Cookie* cookie )
+MediaServer::MediaServer( const char* UDN,
+ const char* friendlyName,
+ services_discovery_t* p_sd )
{
- _cookie = cookie;
+ _p_sd = p_sd;
_UDN = UDN;
_friendlyName = friendlyName;
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;
}
const char* url = getContentDirectoryEventURL();
if ( !url || strcmp( url, "" ) == 0 )
{
- msg_Dbg( _cookie->serviceDiscovery, "No subscription url set!" );
- return;
+ msg_Dbg( _p_sd, "No subscription url set!" );
+ return;
}
int timeOut = 1810;
Upnp_SID sid;
- int res = UpnpSubscribe( _cookie->clientHandle, url, &timeOut, sid );
+ int res = UpnpSubscribe( _p_sd->p_sys->clientHandle, url, &timeOut, sid );
if ( res == UPNP_E_SUCCESS )
{
- _subscriptionTimeOut = timeOut;
- memcpy( _subscriptionID, sid, sizeof( Upnp_SID ) );
+ _subscriptionTimeOut = 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( 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* pObjectID,
+ const char* pBrowseFlag,
+ const char* pFilter,
+ const char* pStartingIndex,
+ const char* pRequestedCount,
+ const char* pSortCriteria )
{
IXML_Document* action = 0;
IXML_Document* response = 0;
-
const char* url = getContentDirectoryControlURL();
- if ( !url || strcmp( url, "" ) == 0 ) { msg_Dbg( _cookie->serviceDiscovery, "No subscription url set!" ); return 0; }
+
+ if ( !url || strcmp( url, "" ) == 0 )
+ {
+ msg_Dbg( _p_sd, "No subscription url set!" );
+ return 0;
+ }
char* ObjectID = strdup( pObjectID );
char* BrowseFlag = strdup( pBrowseFlag );
char* StartingIndex = strdup( pStartingIndex );
char* RequestedCount = strdup( pRequestedCount );
char* SortCriteria = strdup( pSortCriteria );
-
char* serviceType = strdup( CONTENT_DIRECTORY_SERVICE_TYPE );
int res;
- 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; }
+ res = UpnpAddToAction( &action, "Browse",
+ serviceType, "ObjectID", ObjectID );
+
+ if ( res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( res ) );
+ goto browseActionCleanup;
+ }
- 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; }
+ res = UpnpAddToAction( &action, "Browse",
+ serviceType, "BrowseFlag", BrowseFlag );
+
+ if ( res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( 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; }
+ res = UpnpAddToAction( &action, "Browse",
+ serviceType, "Filter", Filter );
+
+ if ( res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( res ) );
+ goto browseActionCleanup;
+ }
- 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; }
+ res = UpnpAddToAction( &action, "Browse",
+ serviceType, "StartingIndex", StartingIndex );
- 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; }
+ if ( res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( res ) );
+ goto browseActionCleanup;
+ }
+
+ res = UpnpAddToAction( &action, "Browse",
+ serviceType, "RequestedCount", RequestedCount );
- 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 ( res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( res ) ); goto browseActionCleanup; }
- res = UpnpSendAction( _cookie->clientHandle,
+ res = UpnpAddToAction( &action, "Browse",
+ serviceType, "SortCriteria", SortCriteria );
+
+ if ( res != UPNP_E_SUCCESS )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR: %s", __FILE__, __LINE__,
+ UpnpGetErrorMessage( res ) );
+ goto browseActionCleanup;
+ }
+
+ res = UpnpSendAction( _p_sd->p_sys->clientHandle,
url,
CONTENT_DIRECTORY_SERVICE_TYPE,
0,
action,
&response );
+
if ( 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( res ), url );
+
+ ixmlDocument_free( response );
+ response = 0;
}
browseActionCleanup:
void MediaServer::fetchContents()
{
Container* root = new Container( 0, "0", getFriendlyName() );
- playlist_t * p_playlist = pl_Get( _cookie->serviceDiscovery );
+ playlist_t * p_playlist = pl_Hold( _p_sd );
_fetchContents( root );
if ( _contents )
_contents->setPlaylistNode( _playlistNode );
_buildPlaylist( _contents );
+ pl_Release ( _p_sd );
}
bool MediaServer::_fetchContents( Container* parent )
{
- if (!parent) { msg_Dbg( _cookie->serviceDiscovery, "%s:%d: parent==NULL", __FILE__, __LINE__ ); return false; }
+ 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( _cookie->serviceDiscovery, "%s:%d: ERROR!", __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( _cookie->serviceDiscovery, "%s:%d: ERROR!", __FILE__, __LINE__ ); return false; }
+
+ if ( !result )
+ {
+ msg_Dbg( _p_sd,
+ "%s:%d: ERROR! browse() response parsing failed",
+ __FILE__, __LINE__ );
+ return false;
+ }
- IXML_NodeList* containerNodeList = ixmlDocument_getElementsByTagName( result, "container" );
+ 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
+ for ( unsigned int i = 0;
+ i < ixmlNodeList_length( containerNodeList ); i++ )
{
- Container* container = new Container( parent, objectID, title );
- parent->addContainer( container );
+ 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 );
+ }
- if ( childCount > 0 ) _fetchContents( container );
- }
- }
+ else
+ {
+ Container* container = new Container( parent, objectID, title );
+ parent->addContainer( container );
- ixmlNodeList_free( containerNodeList );
+ 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 );
-
- 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 );
+ {
+ 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;
}
void MediaServer::_buildPlaylist( Container* parent )
{
- playlist_t *p_playlist = pl_Get( _cookie->serviceDiscovery );
+ playlist_t *p_playlist = pl_Hold( _p_sd );
for ( unsigned int i = 0; i < parent->getNumContainers(); i++ )
{
Container* container = parent->getContainer( i );
playlist_item_t* parentNode = parent->getPlaylistNode();
char* title = strdup( container->getTitle() );
- playlist_item_t* node = playlist_NodeCreate( p_playlist, title, parentNode, 0, NULL );
+ PL_LOCK;
+ playlist_item_t* node = playlist_NodeCreate( p_playlist,
+ title, parentNode, 0, NULL );
+ PL_UNLOCK;
free( title );
container->setPlaylistNode( node );
Item* item = parent->getItem( i );
playlist_item_t* parentNode = parent->getPlaylistNode();
- input_item_t* p_input = input_item_New( _cookie->serviceDiscovery,
+ input_item_t* p_input = input_item_New( _p_sd,
item->getResource(),
item->getTitle() );
int i_cat;
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 );
+ playlist_item_t *p_node =
+ playlist_ItemGetById( p_playlist, i_cat, false );
assert( p_node );
item->setPlaylistNode( p_node );
}
+ pl_Release( _p_sd );
}
void MediaServer::setPlaylistNode( playlist_item_t* playlistNode )
// 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];
}
}
{
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;
+ services_discovery_sys_t* p_sys = p_sd->p_sys;
+ playlist_item_t *p_node_cat;
+ playlist_item_t *p_node_one;
+ playlist_t* p_playlist = pl_Hold( _p_sd );
+
+ for(int i = 0; i < p_playlist->i_sds; i++ )
+ {
+ if(p_playlist->pp_sds[i]->p_sd == p_sd )
+ {
+ p_node_cat = p_playlist->pp_sds[i]->p_cat;
+ p_node_one = p_playlist->pp_sds[i]->p_one;
+ break;
+ }
+ }
+
+ assert (p_node_cat);
+ assert (p_node_one);
+
+ _list.push_back( s );
+
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 );
+ PL_LOCK;
+ playlist_item_t* node =
+ playlist_NodeCreate( p_playlist, name, p_node_cat, 0, NULL );
+ PL_UNLOCK;
+ pl_Release( _p_sd );
free( name );
s->setPlaylistNode( node );
for ( unsigned int i = 0; i < _list.size(); i++ )
{
if( strcmp( UDN, _list[i]->getUDN() ) == 0 )
- {
- result = _list[i];
- break;
- }
+ {
+ result = _list[i];
+ break;
+ }
}
return result;
for ( unsigned int i = 0; i < _list.size(); i++ )
{
- if ( _list[i]->compareSID( sid ) )
- {
- server = _list[i];
- break;
- }
+ if ( _list[i]->compareSID( sid ) )
+ {
+ server = _list[i];
+ break;
+ }
}
return server;
MediaServer* server = getServer( UDN );
if ( !server ) return;
- msg_Dbg( _cookie->serviceDiscovery, "Removing server '%s'", server->getFriendlyName() );
+ msg_Dbg( _p_sd,
+ "Removing server '%s'", server->getFriendlyName() );
std::vector<MediaServer*>::iterator it;
for ( it = _list.begin(); it != _list.end(); it++ )
{
if ( *it == server )
- {
- _list.erase( it );
- delete server;
- break;
- }
+ {
+ _list.erase( it );
+ delete server;
+ break;
+ }
}
}
// Container...
-Container::Container( Container* parent, const char* objectID, const char* title )
+Container::Container( Container* parent,
+ const char* objectID,
+ const char* title )
{
_parent = parent;
{
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];
}
}