Commit d76bc0b9 authored by Thomas Guillem's avatar Thomas Guillem

upnp: make pf_readdir interruptible

parent 7dce9c04
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <vlc_access.h> #include <vlc_access.h>
#include <vlc_plugin.h> #include <vlc_plugin.h>
#include <vlc_interrupt.h>
#include <vlc_services_discovery.h> #include <vlc_services_discovery.h>
#include <assert.h> #include <assert.h>
...@@ -620,6 +621,60 @@ int MediaServerList::Callback( Upnp_EventType event_type, void* p_event, void* p ...@@ -620,6 +621,60 @@ int MediaServerList::Callback( Upnp_EventType event_type, void* p_event, void* p
namespace Access namespace Access
{ {
Upnp_i11e_cb::Upnp_i11e_cb( Upnp_FunPtr callback, void *cookie )
: refCount_( 2 ) /* 2: owned by the caller, and the Upnp Async function */
, callback_( callback )
, cookie_( cookie )
{
vlc_mutex_init( &lock_ );
vlc_sem_init( &sem_, 0 );
}
Upnp_i11e_cb::~Upnp_i11e_cb()
{
vlc_mutex_destroy( &lock_ );
vlc_sem_destroy( &sem_ );
}
void Upnp_i11e_cb::waitAndRelease( void )
{
vlc_sem_wait_i11e( &sem_ );
vlc_mutex_lock( &lock_ );
if ( --refCount_ == 0 )
{
/* The run callback is processed, we can destroy this object */
vlc_mutex_unlock( &lock_ );
delete this;
} else
{
/* Interrupted, let the run callback destroy this object */
vlc_mutex_unlock( &lock_ );
}
}
int Upnp_i11e_cb::run( Upnp_EventType eventType, void *p_event, void *p_cookie )
{
Upnp_i11e_cb *self = static_cast<Upnp_i11e_cb*>( p_cookie );
vlc_mutex_lock( &self->lock_ );
if ( --self->refCount_ == 0 )
{
/* Interrupted, we can destroy self */
vlc_mutex_unlock( &self->lock_ );
delete self;
return 0;
}
/* Process the user callback_ */
self->callback_( eventType, p_event, self->cookie_);
vlc_mutex_unlock( &self->lock_ );
/* Signal that the callback is processed */
vlc_sem_post( &self->sem_ );
return 0;
}
MediaServer::MediaServer( access_t *p_access ) MediaServer::MediaServer( access_t *p_access )
: psz_root_( NULL ) : psz_root_( NULL )
, psz_objectId_( NULL ) , psz_objectId_( NULL )
...@@ -670,6 +725,24 @@ input_item_t* MediaServer::newItem(const char* title, const char*, const char*, ...@@ -670,6 +725,24 @@ input_item_t* MediaServer::newItem(const char* title, const char*, const char*,
duration, ITEM_TYPE_FILE, 1 ); duration, ITEM_TYPE_FILE, 1 );
} }
int MediaServer::sendActionCb( Upnp_EventType eventType,
void *p_event, void *p_cookie )
{
if( eventType != UPNP_CONTROL_ACTION_COMPLETE )
return 0;
IXML_Document** pp_sendActionResult = (IXML_Document** )p_cookie;
Upnp_Action_Complete *p_result = (Upnp_Action_Complete *)p_event;
/* The only way to dup the result is to print it and parse it again */
DOMString tmpStr = ixmlPrintNode( ( IXML_Node * ) p_result->ActionResult );
if (tmpStr == NULL)
return 0;
*pp_sendActionResult = ixmlParseBuffer( tmpStr );
ixmlFreeDOMString( tmpStr );
return 0;
}
/* Access part */ /* Access part */
IXML_Document* MediaServer::_browseAction( const char* psz_object_id_, IXML_Document* MediaServer::_browseAction( const char* psz_object_id_,
const char* psz_browser_flag_, const char* psz_browser_flag_,
...@@ -679,9 +752,13 @@ IXML_Document* MediaServer::_browseAction( const char* psz_object_id_, ...@@ -679,9 +752,13 @@ IXML_Document* MediaServer::_browseAction( const char* psz_object_id_,
{ {
IXML_Document* p_action = NULL; IXML_Document* p_action = NULL;
IXML_Document* p_response = NULL; IXML_Document* p_response = NULL;
Upnp_i11e_cb *i11eCb = NULL;
int i_res; int i_res;
if ( vlc_killed() )
return NULL;
i_res = UpnpAddToAction( &p_action, "Browse", i_res = UpnpAddToAction( &p_action, "Browse",
CONTENT_DIRECTORY_SERVICE_TYPE, "ObjectID", psz_object_id_ ); CONTENT_DIRECTORY_SERVICE_TYPE, "ObjectID", psz_object_id_ );
...@@ -741,21 +818,23 @@ IXML_Document* MediaServer::_browseAction( const char* psz_object_id_, ...@@ -741,21 +818,23 @@ IXML_Document* MediaServer::_browseAction( const char* psz_object_id_,
goto browseActionCleanup; goto browseActionCleanup;
} }
i_res = UpnpSendAction( access_->p_sys->p_upnp->handle(), /* Setup an interruptible callback that will call sendActionCb if not
* interrupted by vlc_interrupt_kill */
i11eCb = new Upnp_i11e_cb( sendActionCb, &p_response );
i_res = UpnpSendActionAsync( access_->p_sys->p_upnp->handle(),
psz_root_, psz_root_,
CONTENT_DIRECTORY_SERVICE_TYPE, CONTENT_DIRECTORY_SERVICE_TYPE,
NULL, /* ignored in SDK, must be NULL */ NULL, /* ignored in SDK, must be NULL */
p_action, p_action,
&p_response ); Upnp_i11e_cb::run, i11eCb );
if ( i_res != UPNP_E_SUCCESS ) if ( i_res != UPNP_E_SUCCESS )
{ {
msg_Err( access_, "%s when trying the send() action with URL: %s", msg_Err( access_, "%s when trying the send() action with URL: %s",
UpnpGetErrorMessage( i_res ), access_->psz_location ); UpnpGetErrorMessage( i_res ), access_->psz_location );
ixmlDocument_free( p_response );
p_response = NULL;
} }
/* Wait for the callback to fill p_response or wait for an interrupt */
i11eCb->waitAndRelease();
browseActionCleanup: browseActionCleanup:
ixmlDocument_free( p_action ); ixmlDocument_free( p_action );
......
...@@ -118,6 +118,22 @@ private: ...@@ -118,6 +118,22 @@ private:
namespace Access namespace Access
{ {
class Upnp_i11e_cb
{
public:
Upnp_i11e_cb( Upnp_FunPtr callback, void *cookie );
~Upnp_i11e_cb();
void waitAndRelease( void );
static int run( Upnp_EventType, void *, void *);
private:
sem_t sem_;
vlc_mutex_t lock_;
int refCount_;
Upnp_FunPtr callback_;
void* cookie_;
};
class MediaServer class MediaServer
{ {
public: public:
...@@ -135,6 +151,7 @@ private: ...@@ -135,6 +151,7 @@ private:
IXML_Document* _browseAction(const char*, const char*, IXML_Document* _browseAction(const char*, const char*,
const char*, const char*, const char* ); const char*, const char*, const char* );
static int sendActionCb( Upnp_EventType, void *, void *);
private: private:
char* psz_root_; char* psz_root_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment