vlc | branch: master | Thomas Guillem <[email protected]> | Tue Dec 8 10:34:35 2015 +0100| [d76bc0b91a275006f337ddcf3de8a0fef7060b89] | committer: Thomas Guillem
upnp: make pf_readdir interruptible > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=d76bc0b91a275006f337ddcf3de8a0fef7060b89 --- modules/services_discovery/upnp.cpp | 89 +++++++++++++++++++++++++++++++++-- modules/services_discovery/upnp.hpp | 17 +++++++ 2 files changed, 101 insertions(+), 5 deletions(-) diff --git a/modules/services_discovery/upnp.cpp b/modules/services_discovery/upnp.cpp index 5dfaf3f..3b092c5 100644 --- a/modules/services_discovery/upnp.cpp +++ b/modules/services_discovery/upnp.cpp @@ -30,6 +30,7 @@ #include <vlc_access.h> #include <vlc_plugin.h> +#include <vlc_interrupt.h> #include <vlc_services_discovery.h> #include <assert.h> @@ -620,6 +621,60 @@ int MediaServerList::Callback( Upnp_EventType event_type, void* p_event, void* p 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 ) : psz_root_( NULL ) , psz_objectId_( NULL ) @@ -670,6 +725,24 @@ input_item_t* MediaServer::newItem(const char* title, const char*, const char*, 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 */ IXML_Document* MediaServer::_browseAction( const char* psz_object_id_, const char* psz_browser_flag_, @@ -679,9 +752,13 @@ IXML_Document* MediaServer::_browseAction( const char* psz_object_id_, { IXML_Document* p_action = NULL; IXML_Document* p_response = NULL; + Upnp_i11e_cb *i11eCb = NULL; int i_res; + if ( vlc_killed() ) + return NULL; + i_res = UpnpAddToAction( &p_action, "Browse", CONTENT_DIRECTORY_SERVICE_TYPE, "ObjectID", psz_object_id_ ); @@ -741,21 +818,23 @@ IXML_Document* MediaServer::_browseAction( const char* psz_object_id_, 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_, CONTENT_DIRECTORY_SERVICE_TYPE, NULL, /* ignored in SDK, must be NULL */ p_action, - &p_response ); + Upnp_i11e_cb::run, i11eCb ); if ( i_res != UPNP_E_SUCCESS ) { msg_Err( access_, "%s when trying the send() action with URL: %s", 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: ixmlDocument_free( p_action ); diff --git a/modules/services_discovery/upnp.hpp b/modules/services_discovery/upnp.hpp index 8b6e9f9..e59af18 100644 --- a/modules/services_discovery/upnp.hpp +++ b/modules/services_discovery/upnp.hpp @@ -118,6 +118,22 @@ private: 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 { public: @@ -135,6 +151,7 @@ private: IXML_Document* _browseAction(const char*, const char*, const char*, const char*, const char* ); + static int sendActionCb( Upnp_EventType, void *, void *); private: char* psz_root_; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
