[vlc-commits] upnp: make pf_readdir interruptible
Thomas Guillem
git at videolan.org
Wed Dec 9 12:11:12 CET 2015
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | 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_;
More information about the vlc-commits
mailing list