[vlc-commits] commit: skins2: improve callback system (Erwan Tulou )

git at videolan.org git at videolan.org
Sat Jul 31 18:05:06 CEST 2010


vlc | branch: master | Erwan Tulou <erwan10 at videolan.org> | Wed Jul 28 22:37:51 2010 +0200| [50200d70d0dc4497191e363ac06590bb5cd077c8] | committer: Erwan Tulou 

skins2: improve callback system

This patch is mainly intended to work out the async queue getting
bigger and bigger when skins cannot keep up with command processing.
Since flushing the queue is an infinite loop, this ends up in vlc
hanging (frozen GUI). This happens when skins are complex (many controls,
many timers, animated images, scrolling text, ...)

With this patch, new commands of a given type can now replace pending
commands not yet processed when that makes sense (e.g position, volume, ...).
The position is really the one responsible for overflooding the queue.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=50200d70d0dc4497191e363ac06590bb5cd077c8
---

 modules/gui/skins2/commands/cmd_callbacks.hpp |   69 +++++++-----------
 modules/gui/skins2/src/vlcproc.cpp            |   96 +++++++++++++++++++------
 modules/gui/skins2/src/vlcproc.hpp            |    4 +
 3 files changed, 103 insertions(+), 66 deletions(-)

diff --git a/modules/gui/skins2/commands/cmd_callbacks.hpp b/modules/gui/skins2/commands/cmd_callbacks.hpp
index 579c6fa..ff222bb 100644
--- a/modules/gui/skins2/commands/cmd_callbacks.hpp
+++ b/modules/gui/skins2/commands/cmd_callbacks.hpp
@@ -28,60 +28,41 @@
 #include "cmd_generic.hpp"
 #include "../src/vlcproc.hpp"
 
-class CmdLabeled : public CmdGeneric
-{
-private:
-    vlc_object_t *m_pObj;
-    vlc_value_t   m_newVal;
-protected:
-    void execute_on( void (VlcProc::*on_label)(vlc_object_t *,vlc_value_t) )
-    {
-        if( !m_pObj )
-            return;
-
-        (VlcProc::instance( getIntf() )->*on_label)( m_pObj, m_newVal );
 
-        vlc_object_release( m_pObj );
-        m_pObj =  NULL;
-    }
-    CmdLabeled( intf_thread_t *pIntf, vlc_object_t *pObj, vlc_value_t newVal )
-              : CmdGeneric( pIntf ), m_pObj( pObj ), m_newVal( newVal )
+class CmdCallback : public CmdGeneric
+{
+public:
+    CmdCallback( intf_thread_t *pIntf, vlc_object_t *pObj, vlc_value_t newVal,
+                 void (VlcProc::*func)(vlc_object_t *,vlc_value_t),
+                 string label )
+        : CmdGeneric( pIntf ), m_pObj( pObj ), m_newVal( newVal ),
+          m_pfExecute( func ), m_label( label )
     {
         if( m_pObj )
             vlc_object_hold( m_pObj );
     }
-public:
-    virtual ~CmdLabeled() {
+    virtual ~CmdCallback()
+    {
         if( m_pObj )
             vlc_object_release( m_pObj );
     }
-};
-
-#define ADD_COMMAND( label )                                            \
-    class Cmd_##label : public CmdLabeled                               \
-    {   public:                                                         \
-        Cmd_##label( intf_thread_t *I, vlc_object_t *O, vlc_value_t V ) \
-                   : CmdLabeled (I, O, V) { }                           \
-        virtual string getType() const { return #label; }               \
-        virtual void execute() { execute_on( &VlcProc::on_##label ); }  \
-    };
-
-ADD_COMMAND( item_current_changed )
-ADD_COMMAND( intf_event_changed )
-ADD_COMMAND( bit_rate_changed )
-ADD_COMMAND( sample_rate_changed )
-ADD_COMMAND( can_record_changed )
-
-ADD_COMMAND( random_changed )
-ADD_COMMAND( loop_changed )
-ADD_COMMAND( repeat_changed )
-
-ADD_COMMAND( volume_changed )
+    virtual void execute()
+    {
+        if( !m_pObj || !m_pfExecute )
+            return;
 
-ADD_COMMAND( audio_filter_changed )
+        (VlcProc::instance( getIntf() )->*m_pfExecute)( m_pObj, m_newVal );
 
-ADD_COMMAND( intf_show_changed )
+        vlc_object_release( m_pObj );
+        m_pObj = NULL;
+    }
+    virtual string getType() const { return m_label; }
 
-#undef ADD_COMMAND
+private:
+    vlc_object_t* m_pObj;
+    vlc_value_t   m_newVal;
+    string        m_label;
+    void (VlcProc::*m_pfExecute)(vlc_object_t *,vlc_value_t);
+};
 
 #endif
diff --git a/modules/gui/skins2/src/vlcproc.cpp b/modules/gui/skins2/src/vlcproc.cpp
index 78f58c7..a0a0e34 100644
--- a/modules/gui/skins2/src/vlcproc.cpp
+++ b/modules/gui/skins2/src/vlcproc.cpp
@@ -254,7 +254,7 @@ int VlcProc::onInputNew( vlc_object_t *pObj, const char *pVariable,
     VlcProc *pThis = (VlcProc*)pParam;
     input_thread_t *pInput = static_cast<input_thread_t*>(newval.p_address);
 
-    var_AddCallback( pInput, "intf-event", onGenericCallback, pThis );
+    var_AddCallback( pInput, "intf-event", onGenericCallback2, pThis );
     var_AddCallback( pInput, "bit-rate", onGenericCallback, pThis );
     var_AddCallback( pInput, "sample-rate", onGenericCallback, pThis );
     var_AddCallback( pInput, "can-record", onGenericCallback, pThis );
@@ -375,40 +375,92 @@ int VlcProc::onGenericCallback( vlc_object_t *pObj, const char *pVariable,
     VlcProc *pThis = (VlcProc*)pParam;
     AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
 
-    CmdGeneric *pCmd = NULL;
-
-#define ADD_CALLBACK_ENTRY( var, label ) \
+#define ADD_CALLBACK_ENTRY( var, func, remove ) \
     { \
     if( strcmp( pVariable, var ) == 0 ) \
-        pCmd = new Cmd_##label( pThis->getIntf(), pObj, newVal ); \
+    { \
+        string label = var; \
+        CmdGeneric *pCmd = new CmdCallback( pThis->getIntf(), pObj, newVal, \
+                                            &VlcProc::func, label ); \
+        if( pCmd ) \
+            pQueue->push( CmdGenericPtr( pCmd ), remove ); \
+        return VLC_SUCCESS; \
+    } \
     }
 
-    ADD_CALLBACK_ENTRY( "item-current", item_current_changed )
-    ADD_CALLBACK_ENTRY( "volume-change", volume_changed )
+    ADD_CALLBACK_ENTRY( "item-current", on_item_current_changed, false )
+    ADD_CALLBACK_ENTRY( "volume-change", on_volume_changed, true )
 
-    ADD_CALLBACK_ENTRY( "intf-event", intf_event_changed )
-    ADD_CALLBACK_ENTRY( "bit-rate", bit_rate_changed )
-    ADD_CALLBACK_ENTRY( "sample-rate", sample_rate_changed )
-    ADD_CALLBACK_ENTRY( "can-record", can_record_changed )
+    ADD_CALLBACK_ENTRY( "bit-rate", on_bit_rate_changed, false )
+    ADD_CALLBACK_ENTRY( "sample-rate", on_sample_rate_changed, false )
+    ADD_CALLBACK_ENTRY( "can-record", on_can_record_changed, false )
 
-    ADD_CALLBACK_ENTRY( "random", random_changed )
-    ADD_CALLBACK_ENTRY( "loop", loop_changed )
-    ADD_CALLBACK_ENTRY( "repeat", repeat_changed )
+    ADD_CALLBACK_ENTRY( "random", on_random_changed, false )
+    ADD_CALLBACK_ENTRY( "loop", on_loop_changed, false )
+    ADD_CALLBACK_ENTRY( "repeat", on_repeat_changed, false )
 
-    ADD_CALLBACK_ENTRY( "audio-filter", audio_filter_changed )
+    ADD_CALLBACK_ENTRY( "audio-filter", on_audio_filter_changed, false )
 
-    ADD_CALLBACK_ENTRY( "intf-show", intf_show_changed )
+    ADD_CALLBACK_ENTRY( "intf-show", on_intf_show_changed, false )
 
 #undef ADD_CALLBACK_ENTRY
 
-    if( pCmd )
-        pQueue->push( CmdGenericPtr( pCmd ), false );
-    else
-        msg_Err( pObj, "no Callback entry provided for %s", pVariable );
+    msg_Err( pThis->getIntf(), "no callback entry for %s", pVariable );
+    return VLC_EGENERIC;
+}
 
-    return VLC_SUCCESS;
+
+int VlcProc::onGenericCallback2( vlc_object_t *pObj, const char *pVariable,
+                                 vlc_value_t oldVal, vlc_value_t newVal,
+                                 void *pParam )
+{
+    VlcProc *pThis = (VlcProc*)pParam;
+    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
+
+    /**
+     * For intf-event, commands are labeled based on the value of newVal.
+     *
+     * For some values (e.g position), only keep the latest command
+     * when there are multiple pending commands (remove=true).
+     *
+     * for others, don't discard commands (remove=false)
+     **/
+    if( strcmp( pVariable, "intf-event" ) == 0 )
+    {
+        stringstream label;
+        bool b_remove;
+        switch( newVal.i_int )
+        {
+            case INPUT_EVENT_STATE:
+            case INPUT_EVENT_POSITION:
+            case INPUT_EVENT_ES:
+            case INPUT_EVENT_CHAPTER:
+            case INPUT_EVENT_RECORD:
+                b_remove = true;
+                break;
+            case INPUT_EVENT_VOUT:
+            case INPUT_EVENT_AOUT:
+            case INPUT_EVENT_DEAD:
+                b_remove = false;
+                break;
+            default:
+                return VLC_SUCCESS;
+        }
+        label <<  pVariable << "_" << newVal.i_int;
+        CmdGeneric *pCmd = new CmdCallback( pThis->getIntf(), pObj, newVal,
+                                            &VlcProc::on_intf_event_changed,
+                                            label.str() );
+        if( pCmd )
+            pQueue->push( CmdGenericPtr( pCmd ), b_remove );
+
+        return VLC_SUCCESS;
+    }
+
+    msg_Err( pThis->getIntf(), "no callback entry for %s", pVariable );
+    return VLC_EGENERIC;
 }
 
+
 #define SET_BOOL(m,v)         ((VarBoolImpl*)(m).get())->set(v)
 #define SET_STREAMTIME(m,v,b) ((StreamTime*)(m).get())->set(v,b)
 #define SET_TEXT(m,v)         ((VarText*)(m).get())->set(v)
@@ -554,7 +606,7 @@ void VlcProc::on_intf_event_changed( vlc_object_t* p_obj, vlc_value_t newVal )
         case INPUT_EVENT_DEAD:
             msg_Dbg( getIntf(), "end of input detected for %p", pInput );
 
-            var_DelCallback( pInput, "intf-event", onGenericCallback, this );
+            var_DelCallback( pInput, "intf-event", onGenericCallback2, this );
             var_DelCallback( pInput, "bit-rate", onGenericCallback, this );
             var_DelCallback( pInput, "sample-rate", onGenericCallback, this );
             var_DelCallback( pInput, "can-record" , onGenericCallback, this );
diff --git a/modules/gui/skins2/src/vlcproc.hpp b/modules/gui/skins2/src/vlcproc.hpp
index 1a19bcb..64c7942 100644
--- a/modules/gui/skins2/src/vlcproc.hpp
+++ b/modules/gui/skins2/src/vlcproc.hpp
@@ -221,6 +221,10 @@ private:
                                   vlc_value_t oldVal, vlc_value_t newVal,
                                   void *pParam );
 
+    /// Generic Callback for intf-event
+    static int onGenericCallback2( vlc_object_t *pObj, const char *pVariable,
+                                   vlc_value_t oldVal, vlc_value_t newVal,
+                                   void *pParam );
 };
 
 



More information about the vlc-commits mailing list