]> git.sesse.net Git - vlc/commitdiff
Fixed a lot of issues regarding fullscreen/mouse in vout-filter.
authorLaurent Aimar <fenrir@videolan.org>
Thu, 2 Apr 2009 21:04:56 +0000 (23:04 +0200)
committerLaurent Aimar <fenrir@videolan.org>
Thu, 2 Apr 2009 21:21:58 +0000 (23:21 +0200)
Please stress the vout-filters and report any regressions.

modules/video_filter/clone.c
modules/video_filter/crop.c
modules/video_filter/deinterlace.c
modules/video_filter/filter_common.h
modules/video_filter/logo.c
modules/video_filter/magnify.c
modules/video_filter/opencv_wrapper.c
modules/video_filter/panoramix.c
modules/video_filter/puzzle.c
modules/video_filter/transform.c
modules/video_filter/wall.c

index 6339b6e84c7e9f4700438e55f5d5384767fe01cd..d2db3697f16b3f9a40fa8482831de5315f65511d 100644 (file)
@@ -49,8 +49,10 @@ static void Render    ( vout_thread_t *, picture_t * );
 
 static void RemoveAllVout  ( vout_thread_t *p_vout );
 
-static int  SendEvents( vlc_object_t *, char const *,
-                        vlc_value_t, vlc_value_t, void * );
+static int  FullscreenEventUp( vlc_object_t *, char const *,
+                               vlc_value_t, vlc_value_t, void * );
+static int  FullscreenEventDown( vlc_object_t *, char const *,
+                                 vlc_value_t, vlc_value_t, void * );
 
 /*****************************************************************************
  * Module descriptor
@@ -213,8 +215,7 @@ static int Create( vlc_object_t *p_this )
  *****************************************************************************/
 static int Init( vout_thread_t *p_vout )
 {
-    int   i_index, i_vout;
-    picture_t *p_pic;
+    int   i_vout;
     char *psz_default_vout;
     video_format_t fmt;
 
@@ -265,14 +266,12 @@ static int Init( vout_thread_t *p_vout )
             RemoveAllVout( p_vout );
             return VLC_EGENERIC;
         }
-
-        ADD_CALLBACKS( p_vout->p_sys->pp_vout[ i_vout ], SendEvents );
+        vout_filter_SetupChild( p_vout, p_vout->p_sys->pp_vout[i_vout],
+                                NULL, FullscreenEventUp, FullscreenEventDown, true );
     }
 
     free( psz_default_vout );
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
-
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
     return VLC_SUCCESS;
 }
@@ -282,18 +281,9 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
-
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
-    {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
-    }
-
     RemoveAllVout( p_vout );
+
+    vout_filter_ReleaseDirectBuffers( p_vout );
 }
 
 /*****************************************************************************
@@ -380,43 +370,64 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
  *****************************************************************************/
 static void RemoveAllVout( vout_thread_t *p_vout )
 {
-    while( p_vout->p_sys->i_clones )
+    vout_sys_t *p_sys = p_vout->p_sys;
+
+    while( p_sys->i_clones )
     {
-         --p_vout->p_sys->i_clones;
-         DEL_CALLBACKS( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones],
-                        SendEvents );
-         vout_CloseAndRelease( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones] );
+         p_sys->i_clones--;
+
+         vout_filter_SetupChild( p_vout, p_sys->pp_vout[p_sys->i_clones],
+                                 NULL, FullscreenEventUp, FullscreenEventDown, false );
+         vout_CloseAndRelease( p_sys->pp_vout[p_sys->i_clones] );
     }
 }
 
-/*****************************************************************************
- * SendEvents: forward mouse and keyboard events to the parent p_vout
- *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
+/**
+ * Forward fullscreen event to/from the childrens.
+ * FIXME pretty much duplicated from wall.c
+ */
+static bool IsFullscreenActive( vout_thread_t *p_vout )
 {
-    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
-    var_Set( (vlc_object_t *)p_data, psz_var, newval );
+    vout_sys_t *p_sys = p_vout->p_sys;
+    for( int i = 0; i < p_sys->i_clones; i++ )
+    {
+        if( var_GetBool( p_sys->pp_vout[i], "fullscreen" ) )
+            return true;
+    }
+    return false;
+}
+static int FullscreenEventUp( vlc_object_t *p_this, char const *psz_var,
+                              vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+    vout_thread_t *p_vout = p_data;
+    VLC_UNUSED(oldval); VLC_UNUSED(p_this); VLC_UNUSED(psz_var); VLC_UNUSED(newval);
 
+    const bool b_fullscreen = IsFullscreenActive( p_vout );
+    if( !var_GetBool( p_vout, "fullscreen" ) != !b_fullscreen )
+        return var_SetBool( p_vout, "fullscreen", b_fullscreen );
     return VLC_SUCCESS;
 }
-
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
+static int FullscreenEventDown( vlc_object_t *p_this, char const *psz_var,
+                                vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
-    VLC_UNUSED(p_data); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    int i_vout;
+    vout_thread_t *p_vout = (vout_thread_t*)p_this;
+    vout_sys_t *p_sys = p_vout->p_sys;
+    VLC_UNUSED(oldval); VLC_UNUSED(p_data); VLC_UNUSED(psz_var);
 
-    for( i_vout = 0; i_vout < p_vout->p_sys->i_clones; i_vout++ )
+    const bool b_fullscreen = IsFullscreenActive( p_vout );
+    if( !b_fullscreen != !newval.b_bool )
     {
-        var_Set( p_vout->p_sys->pp_vout[ i_vout ], psz_var, newval );
-
-        if( !strcmp( psz_var, "fullscreen" ) ) break;
+        for( int i = 0; i < p_sys->i_clones; i++ )
+        {
+            vout_thread_t *p_child = p_sys->pp_vout[i];
+            if( !var_GetBool( p_child, "fullscreen" ) != !newval.b_bool )
+            {
+                var_SetBool( p_child, "fullscreen", newval.b_bool );
+                if( newval.b_bool )
+                    return VLC_SUCCESS;
+            }
+        }
     }
-
     return VLC_SUCCESS;
 }
+
index 6a930359c6725719dbc7b4739a95b6e88a4f8855..355b0292f8cebb5b3ac441c389efe23e14616664 100644 (file)
@@ -56,7 +56,7 @@ static void Render    ( vout_thread_t *, picture_t * );
 
 static void UpdateStats    ( vout_thread_t *, picture_t * );
 
-static int  SendEvents( vlc_object_t *, char const *,
+static int  MouseEvent( vlc_object_t *, char const *,
                         vlc_value_t, vlc_value_t, void * );
 
 #ifdef BEST_AUTOCROP
@@ -200,9 +200,7 @@ static int Create( vlc_object_t *p_this )
  *****************************************************************************/
 static int Init( vout_thread_t *p_vout )
 {
-    int   i_index;
     char *psz_var;
-    picture_t *p_pic;
     video_format_t fmt;
 
     I_OUTPUTPICTURES = 0;
@@ -384,11 +382,9 @@ static int Init( vout_thread_t *p_vout )
     var_AddCallback( p_vout, "ratio-crop", FilterCallback, NULL );
 #endif
 
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
-    ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
-
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
 
     return VLC_SUCCESS;
 }
@@ -398,21 +394,15 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
-    if( p_vout->p_sys->p_vout )
-        DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+    vout_sys_t *p_sys = p_vout->p_sys;
 
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
+    if( p_sys->p_vout )
     {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+        vout_filter_DelChild( p_vout, p_sys->p_vout, MouseEvent );
+        vout_CloseAndRelease( p_sys->p_vout );
     }
 
-    if( p_vout->p_sys->p_vout )
-        vout_CloseAndRelease( p_vout->p_sys->p_vout );
+    vout_filter_ReleaseDirectBuffers( p_vout );
 }
 
 /*****************************************************************************
@@ -455,7 +445,7 @@ static int Manage( vout_thread_t *p_vout )
 
     if( p_vout->p_sys->p_vout )
     {
-        DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+        vout_filter_DelChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
         vout_CloseAndRelease( p_vout->p_sys->p_vout );
     }
 
@@ -475,7 +465,7 @@ static int Manage( vout_thread_t *p_vout )
                         _("VLC could not open the video output module.") );
         return VLC_EGENERIC;
     }
-    ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+    vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
 
     p_vout->p_sys->b_changed = false;
     p_vout->p_sys->i_lastchange = 0;
@@ -829,41 +819,23 @@ static void UpdateStats( vout_thread_t *p_vout, picture_t *p_pic )
     p_vout->p_sys->b_changed = true;
 }
 
-/*****************************************************************************
- * SendEvents: forward mouse and keyboard events to the parent p_vout
- *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *_p_vout )
+/**
+ * Forward mouse event with proper conversion.
+ */
+static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
+                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
+    vout_thread_t *p_vout = p_data;
     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)_p_vout;
-    vlc_value_t sentval = newval;
 
-    /* Translate the mouse coordinates */
+    /* Translate the mouse coordinates
+     * FIXME missing lock */
     if( !strcmp( psz_var, "mouse-x" ) )
-    {
-        sentval.i_int += p_vout->p_sys->i_x;
-    }
+        newval.i_int += p_vout->p_sys->i_x;
     else if( !strcmp( psz_var, "mouse-y" ) )
-    {
-        sentval.i_int += p_vout->p_sys->i_y;
-    }
+        newval.i_int += p_vout->p_sys->i_y;
 
-    var_Set( p_vout, psz_var, sentval );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VLC_UNUSED(p_data); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    var_Set( p_vout->p_sys->p_vout, psz_var, newval );
-    return VLC_SUCCESS;
+    return var_Set( p_vout, psz_var, newval );
 }
 
 #ifdef BEST_AUTOCROP
index d3319e533156cc1d68891cba0f133cbc1c45d94a..3f8726385162bbf4a2b1709add006e7a7ef87030 100644 (file)
@@ -64,6 +64,9 @@ static int  Init      ( vout_thread_t * );
 static void End       ( vout_thread_t * );
 static void Render    ( vout_thread_t *, picture_t * );
 
+static int  MouseEvent( vlc_object_t *p_this, char const *psz_var,
+                        vlc_value_t oldval, vlc_value_t newval, void *p_data );
+
 static void RenderDiscard( vout_thread_t *, picture_t *, picture_t *, int );
 static void RenderBob    ( vout_thread_t *, picture_t *, picture_t *, int );
 static void RenderMean   ( vout_thread_t *, picture_t *, picture_t * );
@@ -91,9 +94,6 @@ static void EndMMX       ( void );
 static void End3DNow     ( void );
 #endif
 
-static int  SendEvents   ( vlc_object_t *, char const *,
-                           vlc_value_t, vlc_value_t, void * );
-
 static void SetFilterMethod( vout_thread_t *p_vout, char *psz_method );
 static vout_thread_t *SpawnRealVout( vout_thread_t *p_vout );
 
@@ -363,9 +363,6 @@ static bool IsChromaSupported( vlc_fourcc_t i_chroma )
  *****************************************************************************/
 static int Init( vout_thread_t *p_vout )
 {
-    int i_index;
-    picture_t *p_pic;
-
     I_OUTPUTPICTURES = 0;
 
     if( !IsChromaSupported( p_vout->render.i_chroma ) )
@@ -392,11 +389,9 @@ static int Init( vout_thread_t *p_vout )
 
     var_AddCallback( p_vout, "deinterlace-mode", FilterCallback, NULL );
 
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
-
-    ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
 
     return VLC_SUCCESS;
 }
@@ -419,22 +414,15 @@ static vout_thread_t *SpawnRealVout( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
-
-    if( p_vout->p_sys->p_vout )
-        DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+    vout_sys_t *p_sys = p_vout->p_sys;
 
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
+    if( p_sys->p_vout )
     {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+        vout_filter_DelChild( p_vout, p_sys->p_vout, MouseEvent );
+        vout_CloseAndRelease( p_sys->p_vout );
     }
 
-    if( p_vout->p_sys->p_vout )
-        vout_CloseAndRelease( p_vout->p_sys->p_vout );
+    vout_filter_ReleaseDirectBuffers( p_vout );
 }
 
 /*****************************************************************************
@@ -449,6 +437,21 @@ static void Destroy( vlc_object_t *p_this )
     free( p_vout->p_sys );
 }
 
+/**
+ * Forward mouse event with proper conversion.
+ */
+static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
+                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+    vout_thread_t *p_vout = p_data;
+    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
+
+    if( !strcmp( psz_var, "mouse-y" ) && p_vout->p_sys->b_half_height )
+        newval.i_int *= 2;
+
+    return var_Set( p_vout, psz_var, newval );
+}
+
 /*****************************************************************************
  * Render: displays previously rendered output
  *****************************************************************************
@@ -1669,24 +1672,6 @@ static void RenderX( picture_t *p_outpic, picture_t *p_pic )
 #endif
 }
 
-/*****************************************************************************
- * SendEvents: forward mouse and keyboard events to the parent p_vout
- *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *_p_vout )
-{
-    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)_p_vout;
-    vlc_value_t sentval = newval;
-
-    if( !strcmp( psz_var, "mouse-y" ) && p_vout->p_sys->b_half_height )
-        sentval.i_int *= 2;
-
-    var_Set( p_vout, psz_var, sentval );
-
-    return VLC_SUCCESS;
-}
-
 /*****************************************************************************
  * FilterCallback: called when changing the deinterlace method on the fly.
  *****************************************************************************/
@@ -1713,7 +1698,7 @@ static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd,
     /* We need to kill the old vout */
     if( p_vout->p_sys->p_vout )
     {
-        DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+        vout_filter_DelChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
         vout_CloseAndRelease( p_vout->p_sys->p_vout );
     }
 
@@ -1729,25 +1714,12 @@ static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd,
         return VLC_EGENERIC;
     }
 
-    ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+    vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
 
     vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
     return VLC_SUCCESS;
 }
 
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VLC_UNUSED(p_data); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    var_Set( p_vout->p_sys->p_vout, psz_var, newval );
-    return VLC_SUCCESS;
-}
-
-
 /*****************************************************************************
  * video filter2 functions
  *****************************************************************************/
index ad1a976cbeaf4f1595a541c4dd5861641fefdfa4..2f3e40e9870d66f911eeb1333f7c1108296c8159 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
-#define ALLOCATE_DIRECTBUFFERS( i_max ) \
-    /* Try to initialize i_max direct buffers */                              \
-    while( I_OUTPUTPICTURES < ( i_max ) )                                     \
-    {                                                                         \
-        p_pic = NULL;                                                         \
-                                                                              \
-        /* Find an empty picture slot */                                      \
-        for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )          \
-        {                                                                     \
-            if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )       \
-            {                                                                 \
-                p_pic = p_vout->p_picture + i_index;                          \
-                break;                                                        \
-            }                                                                 \
-        }                                                                     \
-                                                                              \
-        if( p_pic == NULL )                                                   \
-        {                                                                     \
-            break;                                                            \
-        }                                                                     \
-                                                                              \
-        /* Allocate the picture */                                            \
-        vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic, p_vout->output.i_chroma, \
-                              p_vout->output.i_width,                         \
-                              p_vout->output.i_height,                        \
-                              p_vout->output.i_aspect );                      \
-                                                                              \
-        if( !p_pic->i_planes )                                                \
-        {                                                                     \
-            break;                                                            \
-        }                                                                     \
-                                                                              \
-        p_pic->i_status = DESTROYED_PICTURE;                                  \
-        p_pic->i_type   = DIRECT_PICTURE;                                     \
-                                                                              \
-        PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;                         \
-                                                                              \
-        I_OUTPUTPICTURES++;                                                   \
-    }                                                                         \
+/**
+ * Initialize i_max direct buffers for a vout_thread_t.
+ */
+static inline void vout_filter_AllocateDirectBuffers( vout_thread_t *p_vout, int i_max )
+{
+    I_OUTPUTPICTURES = 0;
 
-/*****************************************************************************
- * SetParentVal: forward variable value to parent whithout triggering the
- *               callback
- *****************************************************************************/
-static int SetParentVal( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
+    /* Try to initialize i_max direct buffers */
+    while( I_OUTPUTPICTURES < i_max )
+    {
+        picture_t *p_pic = NULL;
+
+        /* Find an empty picture slot */
+        for( int i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+        {
+            if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+            {
+                p_pic = p_vout->p_picture + i_index;
+                break;
+            }
+        }
+
+        if( p_pic == NULL )
+            break;
+
+        /* Allocate the picture */
+        vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic, p_vout->output.i_chroma,
+                              p_vout->output.i_width,
+                              p_vout->output.i_height,
+                              p_vout->output.i_aspect );
+
+        if( !p_pic->i_planes )
+            break;
+
+        p_pic->i_status = DESTROYED_PICTURE;
+        p_pic->i_type   = DIRECT_PICTURE;
+
+        PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+        I_OUTPUTPICTURES++;
+    }
+}
+
+static inline void vout_filter_ReleaseDirectBuffers( vout_thread_t *p_vout )
+{
+    for( int i_index = I_OUTPUTPICTURES-1; i_index >= 0; i_index-- )
+        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
+}
+
+/**
+ * Internal helper to forward an event from p_this to p_data
+ */
+static inline int ForwardEvent( vlc_object_t *p_this, char const *psz_var,
+                                vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
-    var_Change( (vlc_object_t *)p_data, psz_var, VLC_VAR_SETVALUE,
-                 &newval, NULL );
+    vlc_object_t *p_dst = (vlc_object_t*)p_data;
+
+    return var_Set( p_dst, psz_var, newval );
+}
+/**
+ * Internal helper to forward fullscreen event from p_this to p_data.
+ */
+static inline int ForwardFullscreen( vlc_object_t *p_this, char const *psz_var,
+                                     vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
+    vlc_object_t *p_dst = (vlc_object_t*)p_data;
+
+    if( !var_GetBool( p_dst, "fullscreen" ) != !newval.b_bool )
+        return var_SetBool( p_dst, psz_var, newval.b_bool );
     return VLC_SUCCESS;
 }
+/**
+ * Install/remove all callbacks needed for proper event handling inside
+ * a vout-filter.
+ */
+static inline void vout_filter_SetupChild( vout_thread_t *p_parent, vout_thread_t *p_child,
+                                           vlc_callback_t pf_mouse_event,
+                                           vlc_callback_t pf_fullscreen_up,
+                                           vlc_callback_t pf_fullscreen_down,
+                                           bool b_init )
+{
+    int (*pf_execute)( vlc_object_t *, const char *, vlc_callback_t, void * );
+
+    if( b_init )
+        pf_execute = __var_AddCallback;
+    else
+        pf_execute = __var_DelCallback;
+
+    /* */
+    if( !pf_mouse_event )
+        pf_mouse_event = ForwardEvent;
+    pf_execute( VLC_OBJECT(p_child), "mouse-x",           pf_mouse_event, p_parent );
+    pf_execute( VLC_OBJECT(p_child), "mouse-y",           pf_mouse_event, p_parent );
+    pf_execute( VLC_OBJECT(p_child), "mouse-moved",       pf_mouse_event, p_parent );
+    pf_execute( VLC_OBJECT(p_child), "mouse-clicked",     pf_mouse_event, p_parent );
+    pf_execute( VLC_OBJECT(p_child), "mouse-button-down", pf_mouse_event, p_parent );
+
+    /* */
+    pf_execute( VLC_OBJECT(p_parent), "autoscale",    ForwardEvent, p_child );
+    pf_execute( VLC_OBJECT(p_parent), "scale",        ForwardEvent, p_child );
+    pf_execute( VLC_OBJECT(p_parent), "aspect-ratio", ForwardEvent, p_child );
+    pf_execute( VLC_OBJECT(p_parent), "crop",         ForwardEvent, p_child );
+
+    /* */
+    if( !pf_fullscreen_up )
+        pf_fullscreen_up = ForwardFullscreen;
+    if( !pf_fullscreen_down )
+        pf_fullscreen_down = ForwardFullscreen;
+    pf_execute( VLC_OBJECT(p_child),  "fullscreen", pf_fullscreen_up,   p_parent );
+    pf_execute( VLC_OBJECT(p_parent), "fullscreen", pf_fullscreen_down, p_child );
+}
+
+#define vout_filter_AddChild( a, b, c ) vout_filter_SetupChild( a, b, c, NULL, NULL, true )
+#define vout_filter_DelChild( a, b, c ) vout_filter_SetupChild( a, b, c, NULL, NULL, false )
 
-#define ADD_CALLBACKS( newvout, handler ) \
-    var_AddCallback( newvout, "fullscreen", SetParentVal, p_vout );           \
-    var_AddCallback( newvout, "mouse-x", SendEvents, p_vout );                \
-    var_AddCallback( newvout, "mouse-y", SendEvents, p_vout );                \
-    var_AddCallback( newvout, "mouse-moved", SendEvents, p_vout );            \
-    var_AddCallback( newvout, "mouse-clicked", SendEvents, p_vout );
-
-#define DEL_CALLBACKS( newvout, handler ) \
-    var_DelCallback( newvout, "fullscreen", SetParentVal, p_vout );           \
-    var_DelCallback( newvout, "mouse-x", SendEvents, p_vout );                \
-    var_DelCallback( newvout, "mouse-y", SendEvents, p_vout );                \
-    var_DelCallback( newvout, "mouse-moved", SendEvents, p_vout );            \
-    var_DelCallback( newvout, "mouse-clicked", SendEvents, p_vout );
-
-#define ADD_PARENT_CALLBACKS( handler ) \
-    var_AddCallback( p_vout, "fullscreen", handler, NULL );                   \
-    var_AddCallback( p_vout, "autoscale", handler, NULL );                    \
-    var_AddCallback( p_vout, "scale", handler, NULL );                 \
-    var_AddCallback( p_vout, "aspect-ratio", handler, NULL );                 \
-    var_AddCallback( p_vout, "crop", handler, NULL );
-
-#define DEL_PARENT_CALLBACKS( handler ) \
-    var_DelCallback( p_vout, "fullscreen", handler, NULL );                   \
-    var_DelCallback( p_vout, "autoscale", handler, NULL );                    \
-    var_DelCallback( p_vout, "scale", handler, NULL );                 \
-    var_DelCallback( p_vout, "aspect-ratio", handler, NULL );                 \
-    var_DelCallback( p_vout, "crop", handler, NULL );
-
-static int  SendEventsToChild( vlc_object_t *, char const *,
-                               vlc_value_t, vlc_value_t, void * );
index 598cca72fec2565dcb463a9cd251be5fa70d441c..ea3841380a15f55d144191d8e05d8b0d43bfd4a4 100644 (file)
@@ -33,6 +33,7 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_vout.h>
+#include <assert.h>
 
 #include "vlc_filter.h"
 #include "filter_common.h"
@@ -53,8 +54,6 @@ static int  Init      ( vout_thread_t * );
 static void End       ( vout_thread_t * );
 static void Render    ( vout_thread_t *, picture_t * );
 
-static int  SendEvents( vlc_object_t *, char const *,
-                        vlc_value_t, vlc_value_t, void * );
 static int  MouseEvent( vlc_object_t *, char const *,
                         vlc_value_t , vlc_value_t , void * );
 static int  Control   ( vout_thread_t *, int, va_list );
@@ -364,7 +363,6 @@ static int Init( vout_thread_t *p_vout )
 {
     vout_sys_t *p_sys = p_vout->p_sys;
     picture_t *p_pic;
-    int i_index;
     video_format_t fmt;
     logo_list_t *p_logo_list = p_sys->p_logo_list;
 
@@ -459,12 +457,9 @@ static int Init( vout_thread_t *p_vout )
         return VLC_EGENERIC;
     }
 
-    var_AddCallback( p_sys->p_vout, "mouse-x", MouseEvent, p_vout);
-    var_AddCallback( p_sys->p_vout, "mouse-y", MouseEvent, p_vout);
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
-    ADD_CALLBACKS( p_sys->p_vout, SendEvents );
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AddChild( p_vout, p_sys->p_vout, MouseEvent );
 
     return VLC_SUCCESS;
 }
@@ -475,24 +470,12 @@ static int Init( vout_thread_t *p_vout )
 static void End( vout_thread_t *p_vout )
 {
     vout_sys_t *p_sys = p_vout->p_sys;
-    int i_index;
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
-
-    DEL_CALLBACKS( p_sys->p_vout, SendEvents );
-
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
-    {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
-    }
-
-    var_DelCallback( p_sys->p_vout, "mouse-x", MouseEvent, p_vout);
-    var_DelCallback( p_sys->p_vout, "mouse-y", MouseEvent, p_vout);
 
+    vout_filter_DelChild( p_vout, p_sys->p_vout, MouseEvent );
     vout_CloseAndRelease( p_sys->p_vout );
 
+    vout_filter_ReleaseDirectBuffers( p_vout );
+
     if( p_sys->p_blend->p_module )
         module_unneed( p_sys->p_blend, p_sys->p_blend->p_module );
     vlc_object_detach( p_sys->p_blend );
@@ -594,66 +577,58 @@ static void Render( vout_thread_t *p_vout, picture_t *p_inpic )
     vout_DisplayPicture( p_sys->p_vout, p_outpic );
 }
 
-/*****************************************************************************
- * SendEvents: forward mouse and keyboard events to the parent p_vout
- *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
-    var_Set( (vlc_object_t *)p_data, psz_var, newval );
-    return VLC_SUCCESS;
-}
-
 /*****************************************************************************
  * MouseEvent: callback for mouse events
  *****************************************************************************/
 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
-    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t*)p_data;
-    vout_sys_t *p_sys = p_vout->p_sys;
-    vlc_value_t valb;
-    int i_delta;
-
-    var_Get( p_vout->p_sys->p_vout, "mouse-button-down", &valb );
+    vout_thread_t *p_vout = p_data;
+    assert( p_this == VLC_OBJECT(p_vout->p_sys->p_vout) );
+    VLC_UNUSED(oldval);
 
-    i_delta = newval.i_int - oldval.i_int;
+    vout_sys_t *p_sys = p_vout->p_sys;
+    const int i_delta = newval.i_int - oldval.i_int;
+    const int i_bdown = var_GetInteger( p_sys->p_vout, "mouse-button-down" );
 
-    if( (valb.i_int & 0x1) == 0 )
-    {
-        return VLC_SUCCESS;
-    }
+    if( (i_bdown & 0x1) == 0 )
+        goto forward;
 
+    int i_x, i_y;
+    int i_dx = 0;
+    int i_dy = 0;
     if( psz_var[6] == 'x' )
     {
-        vlc_value_t valy;
-        var_Get( p_vout->p_sys->p_vout, "mouse-y", &valy );
-        if( newval.i_int >= (int)p_sys->posx &&
-            valy.i_int >= (int)p_sys->posy &&
-            newval.i_int <= (int)(p_sys->posx + p_sys->i_width) &&
-            valy.i_int <= (int)(p_sys->posy + p_sys->i_height) )
-        {
-            p_sys->posx = __MIN( __MAX( p_sys->posx + i_delta, 0 ),
-                          p_vout->output.i_width - p_sys->i_width );
-        }
+        i_y = var_GetInteger( p_sys->p_vout, "mouse-y" );
+        i_x = newval.i_int;
+        i_dx = i_delta;
     }
     else if( psz_var[6] == 'y' )
     {
-        vlc_value_t valx;
-        var_Get( p_vout->p_sys->p_vout, "mouse-x", &valx );
-        if( valx.i_int >= (int)p_sys->posx &&
-            newval.i_int >= (int)p_sys->posy &&
-            valx.i_int <= (int)(p_sys->posx + p_sys->i_width) &&
-            newval.i_int <= (int)(p_sys->posy + p_sys->i_height) )
-        {
-            p_sys->posy = __MIN( __MAX( p_sys->posy + i_delta, 0 ),
-                          p_vout->output.i_height - p_sys->i_height );
-        }
+        i_y = newval.i_int;
+        i_x = var_GetInteger( p_sys->p_vout, "mouse-x" );
+        i_dy = i_delta;
+    }
+    else
+    {
+        goto forward;
     }
 
+    /* FIXME missing lock */
+    if( i_x < (int)p_sys->posx ||
+        i_y < (int)p_sys->posy ||
+        i_x > (int)(p_sys->posx + p_sys->i_width) ||
+        i_y > (int)(p_sys->posy + p_sys->i_height) )
+        goto forward;
+
+    p_sys->posx = __MIN( __MAX( p_sys->posx + i_dx, 0 ),
+                         p_vout->output.i_width - p_sys->i_width );
+    p_sys->posy = __MIN( __MAX( p_sys->posy + i_dy, 0 ),
+                         p_vout->output.i_height - p_sys->i_height );
     return VLC_SUCCESS;
+
+forward:
+    return var_Set( p_vout, psz_var, newval );
 }
 
 /*****************************************************************************
@@ -664,18 +639,6 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args )
     return vout_vaControl( p_vout->p_sys->p_vout, i_query, args );
 }
 
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VLC_UNUSED(p_data); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    var_Set( p_vout->p_sys->p_vout, psz_var, newval );
-    return VLC_SUCCESS;
-}
-
 /*****************************************************************************
  * filter_sys_t: logo filter descriptor
  *****************************************************************************/
@@ -769,11 +732,6 @@ static void DestroyFilter( vlc_object_t *p_this )
     filter_t *p_filter = (filter_t *)p_this;
     filter_sys_t *p_sys = p_filter->p_sys;
 
-    vlc_mutex_destroy( &p_sys->p_logo_list->lock );
-    FreeLogoList( p_sys->p_logo_list );
-    free( p_sys->p_logo_list );
-    free( p_sys );
-
     /* Delete the logo variables from INPUT */
     var_Destroy( p_filter->p_libvlc, "logo-file" );
     var_Destroy( p_filter->p_libvlc, "logo-x" );
@@ -782,6 +740,11 @@ static void DestroyFilter( vlc_object_t *p_this )
     var_Destroy( p_filter->p_libvlc, "logo-repeat" );
     var_Destroy( p_filter->p_libvlc, "logo-position" );
     var_Destroy( p_filter->p_libvlc, "logo-transparency" );
+
+    vlc_mutex_destroy( &p_sys->p_logo_list->lock );
+    FreeLogoList( p_sys->p_logo_list );
+    free( p_sys->p_logo_list );
+    free( p_sys );
 }
 
 /*****************************************************************************
index d7ce91afbfbabdc421923458505397b2e611c35b..aef6837a77d6968e921661d7c32459caed3db770 100644 (file)
@@ -34,6 +34,7 @@
 #include <vlc_vout.h>
 
 #include <math.h>
+#include <assert.h>
 
 #include "filter_common.h"
 #include "filter_picture.h"
@@ -64,10 +65,8 @@ static int  Init      ( vout_thread_t * );
 static void End       ( vout_thread_t * );
 static void Render    ( vout_thread_t *, picture_t * );
 
-static int  SendEvents   ( vlc_object_t *, char const *,
-                           vlc_value_t, vlc_value_t, void * );
-static int  MouseEvent   ( vlc_object_t *, char const *,
-                           vlc_value_t, vlc_value_t, void * );
+static int  MouseEvent( vlc_object_t *, char const *,
+                        vlc_value_t, vlc_value_t, void * );
 
 static void DrawZoomStatus( uint8_t *, int i_pitch, int i_width, int i_height,
                             int i_offset_x, int i_offset_y, bool b_visible );
@@ -144,13 +143,12 @@ static int Create( vlc_object_t *p_this )
  *****************************************************************************/
 static int Init( vout_thread_t *p_vout )
 {
-    int i_index;
-    picture_t *p_pic;
     video_format_t fmt;
 
-    memset( &fmt, 0, sizeof(video_format_t) );
     I_OUTPUTPICTURES = 0;
 
+    memset( &fmt, 0, sizeof(video_format_t) );
+
     /* Initialize the output structure */
     p_vout->output.i_chroma = p_vout->render.i_chroma;
     p_vout->output.i_width  = p_vout->render.i_width;
@@ -180,14 +178,9 @@ static int Init( vout_thread_t *p_vout )
     p_vout->p_sys->i_last_activity = mdate();
     p_vout->p_sys->i_hide_timeout = 1000 * var_GetInteger( p_vout, "mouse-hide-timeout" );
 
-    var_AddCallback( p_vout->p_sys->p_vout, "mouse-x", MouseEvent, p_vout );
-    var_AddCallback( p_vout->p_sys->p_vout, "mouse-y", MouseEvent, p_vout );
-    var_AddCallback( p_vout->p_sys->p_vout, "mouse-clicked",
-                     MouseEvent, p_vout);
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
-    ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
 
     return VLC_SUCCESS;
 }
@@ -197,26 +190,14 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
+    vout_sys_t *p_sys = p_vout->p_sys;
 
-    DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+    vout_filter_DelChild( p_vout, p_sys->p_vout, MouseEvent );
+    vout_CloseAndRelease( p_sys->p_vout );
 
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
-    {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
-    }
-
-    var_DelCallback( p_vout->p_sys->p_vout, "mouse-x", MouseEvent, p_vout);
-    var_DelCallback( p_vout->p_sys->p_vout, "mouse-y", MouseEvent, p_vout);
-    var_DelCallback( p_vout->p_sys->p_vout, "mouse-clicked", MouseEvent, p_vout);
+    vout_filter_ReleaseDirectBuffers( p_vout );
 
     vlc_mutex_destroy( &p_vout->p_sys->lock );
-
-    vout_CloseAndRelease( p_vout->p_sys->p_vout );
 }
 
 /*****************************************************************************
@@ -432,40 +413,16 @@ static void DrawRectangle( uint8_t *pb_dst, int i_pitch, int i_width, int i_heig
     vlc_memset( &pb_dst[(y+i_h-1) * i_pitch + x], 0xff, i_w );
 }
 
-/*****************************************************************************
- * SendEvents: forward mouse and keyboard events to the parent p_vout
- *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
-    var_Set( (vlc_object_t *)p_data, psz_var, newval );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VLC_UNUSED(p_data); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    var_Set( p_vout->p_sys->p_vout, psz_var, newval );
-    return VLC_SUCCESS;
-}
-
 /*****************************************************************************
  * MouseEvent: callback for mouse events
  *****************************************************************************/
 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
-    vout_thread_t *p_vout = (vout_thread_t*)p_data;
+    vout_thread_t *p_vout = p_data;
     vlc_value_t vald,valx,valy;
 
-    VLC_UNUSED(p_this);
+    assert( p_this == VLC_OBJECT(p_vout->p_sys->p_vout) );
 
 #define MOUSE_DOWN    1
 #define MOUSE_CLICKED 2
@@ -567,5 +524,7 @@ static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
     p_vout->p_sys->i_last_activity = mdate();
     vlc_mutex_unlock( &p_vout->p_sys->lock );
 
+    /* FIXME forward event when not grabbed */
+
     return VLC_SUCCESS;
 }
index 64c1d590599479dc215fc5467c20fcbbaf4ddd74..1ccbaae89e4170856ad579d9f87e2076889be971 100644 (file)
@@ -57,8 +57,6 @@ static int  Init      ( vout_thread_t * );
 static void End       ( vout_thread_t * );
 static void Render    ( vout_thread_t *, picture_t * );
 
-static int  SendEvents( vlc_object_t *, char const *,
-                        vlc_value_t, vlc_value_t, void * );
 static void ReleaseImages( vout_thread_t *p_vout );
 static void VlcPictureToIplImage( vout_thread_t *p_vout, picture_t *p_in );
 
@@ -297,8 +295,6 @@ static int Create( vlc_object_t *p_this )
  *****************************************************************************/
 static int Init( vout_thread_t *p_vout )
 {
-    int i_index;
-    picture_t *p_pic;
     video_format_t fmt;
     vout_sys_t *p_sys = p_vout->p_sys;
     I_OUTPUTPICTURES = 0;
@@ -358,11 +354,9 @@ static int Init( vout_thread_t *p_vout )
         return VLC_EGENERIC;
     }
 
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
-    ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
-
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, NULL, NULL, true );
 
     return VLC_SUCCESS;
 }
@@ -372,30 +366,22 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
+    vout_sys_t *p_sys = p_vout->p_sys;
 
-    DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+    vout_filter_DelChild( p_vout, p_sys->p_vout, NULL, NULL, true );
+    vout_CloseAndRelease( p_sys->p_vout );
 
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
-    {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
-    }
+    vout_filter_ReleaseDirectBuffers( p_vout );
 
-    if ( p_vout->p_sys->p_opencv )
+    ifp_sys->p_opencv )
     {
         //release the internal opencv filter
-        if( p_vout->p_sys->p_opencv->p_module )
-            module_unneed( p_vout->p_sys->p_opencv, p_vout->p_sys->p_opencv->p_module );
-        vlc_object_detach( p_vout->p_sys->p_opencv );
-        vlc_object_release( p_vout->p_sys->p_opencv );
-        p_vout->p_sys->p_opencv = NULL;
+        if( p_sys->p_opencv->p_module )
+            module_unneed( p_sys->p_opencv, p_sys->p_opencv->p_module );
+        vlc_object_detach( p_sys->p_opencv );
+        vlc_object_release( p_sys->p_opencv );
+        p_sys->p_opencv = NULL;
     }
-
-    vout_CloseAndRelease( p_vout->p_sys->p_vout );
 }
 
 /*****************************************************************************
@@ -595,24 +581,3 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
     vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
 }
 
-/*****************************************************************************
- * SendEvents: forward mouse and keyboard events to the parent p_vout
- *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    var_Set( (vlc_object_t *)p_data, psz_var, newval );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    var_Set( p_vout->p_sys->p_vout, psz_var, newval );
-    return VLC_SUCCESS;
-}
index 7d2066993b0facd68029fdcb07c4e68936f8c2fb..73c92814fbbafb454b33f6cafdfe91fd6845aa51 100644 (file)
@@ -33,6 +33,7 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_vout.h>
+#include <assert.h>
 
 #include "filter_common.h"
 
@@ -72,8 +73,12 @@ static void RenderPackedRGB   ( vout_thread_t *, picture_t * );
 
 static void RemoveAllVout  ( vout_thread_t *p_vout );
 
-static int  SendEvents( vlc_object_t *, char const *,
+static int  MouseEvent( vlc_object_t *, char const *,
                         vlc_value_t, vlc_value_t, void * );
+static int  FullscreenEventUp( vlc_object_t *, char const *,
+                               vlc_value_t, vlc_value_t, void * );
+static int  FullscreenEventDown( vlc_object_t *, char const *,
+                                 vlc_value_t, vlc_value_t, void * );
 
 /*****************************************************************************
  * Module descriptor
@@ -646,7 +651,6 @@ static int AdjustHeight( vout_thread_t *p_vout )
 static int Init( vout_thread_t *p_vout )
 {
     int i_index, i_row, i_col;
-    picture_t *p_pic;
 
     I_OUTPUTPICTURES = 0;
 
@@ -839,7 +843,9 @@ static int Init( vout_thread_t *p_vout )
                 RemoveAllVout( p_vout );
                 return VLC_EGENERIC;
             }
-            ADD_CALLBACKS( p_entry->p_vout, SendEvents );
+            vout_filter_SetupChild( p_vout, p_entry->p_vout,
+                                    MouseEvent, FullscreenEventUp, FullscreenEventDown, true );
+
 #ifdef OVERLAP
             p_entry->p_vout->i_alignment = 0;
             if (i_col == 0)
@@ -867,9 +873,7 @@ static int Init( vout_thread_t *p_vout )
         }
     }
 
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
-
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
     return VLC_SUCCESS;
 }
@@ -879,19 +883,10 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
-
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
-    {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
-    }
-
     RemoveAllVout( p_vout );
 
+    vout_filter_ReleaseDirectBuffers( p_vout );
+
 #ifdef OVERLAP
     var_SetInteger( p_vout, "bz-length", p_vout->p_sys->bz_length);
 #endif
@@ -1841,13 +1836,16 @@ static void RenderPackedYUV( vout_thread_t *p_vout, picture_t *p_pic )
  *****************************************************************************/
 static void RemoveAllVout( vout_thread_t *p_vout )
 {
+    vout_sys_t *p_sys = p_vout->p_sys;
+
     for( int i = 0; i < p_vout->p_sys->i_vout; i++ )
     {
-        if( p_vout->p_sys->pp_vout[i].b_active )
+        if( p_sys->pp_vout[i].b_active )
         {
-            DEL_CALLBACKS( p_vout->p_sys->pp_vout[i].p_vout, SendEvents );
-            vout_CloseAndRelease( p_vout->p_sys->pp_vout[i].p_vout );
-            p_vout->p_sys->pp_vout[i].p_vout = NULL;
+            vout_filter_SetupChild( p_vout, p_sys->pp_vout[i].p_vout,
+                                    MouseEvent, FullscreenEventUp, FullscreenEventDown, true );
+            vout_CloseAndRelease( p_sys->pp_vout[i].p_vout );
+            p_sys->pp_vout[i].p_vout = NULL;
         }
     }
 }
@@ -1855,78 +1853,102 @@ static void RemoveAllVout( vout_thread_t *p_vout )
 /*****************************************************************************
  * SendEvents: forward mouse and keyboard events to the parent p_vout
  *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *_p_vout )
+static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
+                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
+    vout_thread_t *p_vout = p_data;
+    vout_sys_t *p_sys = p_vout->p_sys;
     VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)_p_vout;
     int i_vout;
-    vlc_value_t sentval = newval;
 
     /* Find the video output index */
-    for( i_vout = 0; i_vout < p_vout->p_sys->i_vout; i_vout++ )
+    for( i_vout = 0; i_vout < p_sys->i_vout; i_vout++ )
     {
-        if( p_this == (vlc_object_t *)p_vout->p_sys->pp_vout[ i_vout ].p_vout )
-        {
+        if( p_sys->pp_vout[i_vout].b_active &&
+            p_this == VLC_OBJECT(p_sys->pp_vout[i_vout].p_vout) )
             break;
-        }
-    }
-
-    if( i_vout == p_vout->p_sys->i_vout )
-    {
-        return VLC_EGENERIC;
     }
+    assert( i_vout < p_vout->p_sys->i_vout );
 
     /* Translate the mouse coordinates */
     if( !strcmp( psz_var, "mouse-x" ) )
     {
 #ifdef OVERLAP
-        int i_overlap = ((p_vout->p_sys->i_col > 2) ? 0 : 2 * p_vout->p_sys->i_halfLength);
-           sentval.i_int += (p_vout->output.i_width - i_overlap)
+        int i_overlap = ((p_sys->i_col > 2) ? 0 : 2 * p_sys->i_halfLength);
+           newval.i_int += (p_vout->output.i_width - i_overlap)
 #else
-           sentval.i_int += p_vout->output.i_width
+           newval.i_int += p_vout->output.i_width
 #endif
-                         * (i_vout % p_vout->p_sys->i_col)
-                          / p_vout->p_sys->i_col;
+                         * (i_vout % p_sys->i_col)
+                          / p_sys->i_col;
     }
     else if( !strcmp( psz_var, "mouse-y" ) )
     {
 #ifdef OVERLAP
-        int i_overlap = ((p_vout->p_sys->i_row > 2) ? 0 : 2 * p_vout->p_sys->i_halfHeight);
-           sentval.i_int += (p_vout->output.i_height - i_overlap)
+        int i_overlap = ((p_sys->i_row > 2) ? 0 : 2 * p_sys->i_halfHeight);
+           newval.i_int += (p_vout->output.i_height - i_overlap)
 #else
-           sentval.i_int += p_vout->output.i_height
+           newval.i_int += p_vout->output.i_height
 #endif
 //bug fix in Wall plug-in
 //                         * (i_vout / p_vout->p_sys->i_row)
-                         * (i_vout / p_vout->p_sys->i_col)
-                          / p_vout->p_sys->i_row;
+                         * (i_vout / p_sys->i_col)
+                          / p_sys->i_row;
     }
 
-    var_Set( p_vout, psz_var, sentval );
+    return var_Set( p_vout, psz_var, newval );
+}
 
-    return VLC_SUCCESS;
+/**
+ * Forward fullscreen event to/from the childrens.
+ * FIXME pretty much duplicated from wall.c
+ */
+static bool IsFullscreenActive( vout_thread_t *p_vout )
+{
+    vout_sys_t *p_sys = p_vout->p_sys;
+    for( int i = 0; i < p_sys->i_vout; i++ )
+    {
+        if( p_sys->pp_vout[i].b_active &&
+            var_GetBool( p_sys->pp_vout[i].p_vout, "fullscreen" ) )
+            return true;
+    }
+    return false;
 }
+static int FullscreenEventUp( vlc_object_t *p_this, char const *psz_var,
+                              vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+    vout_thread_t *p_vout = p_data;
+    VLC_UNUSED(oldval); VLC_UNUSED(p_this); VLC_UNUSED(psz_var); VLC_UNUSED(newval);
 
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
+    const bool b_fullscreen = IsFullscreenActive( p_vout );
+    if( !var_GetBool( p_vout, "fullscreen" ) != !b_fullscreen )
+        return var_SetBool( p_vout, "fullscreen", b_fullscreen );
+    return VLC_SUCCESS;
+}
+static int FullscreenEventDown( vlc_object_t *p_this, char const *psz_var,
+                                vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
-    VLC_UNUSED(oldval); VLC_UNUSED(p_data);
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    int i_row, i_col, i_vout = 0;
+    vout_thread_t *p_vout = (vout_thread_t*)p_this;
+    vout_sys_t *p_sys = p_vout->p_sys;
+    VLC_UNUSED(oldval); VLC_UNUSED(p_data); VLC_UNUSED(psz_var);
 
-    for( i_row = 0; i_row < p_vout->p_sys->i_row; i_row++ )
+    const bool b_fullscreen = IsFullscreenActive( p_vout );
+    if( !b_fullscreen != !newval.b_bool )
     {
-        for( i_col = 0; i_col < p_vout->p_sys->i_col; i_col++ )
+        for( int i = 0; i < p_sys->i_vout; i++ )
         {
-            var_Set( p_vout->p_sys->pp_vout[ i_vout ].p_vout, psz_var, newval);
-            if( !strcmp( psz_var, "fullscreen" ) ) break;
-            i_vout++;
+            if( !p_sys->pp_vout[i].b_active )
+                continue;
+
+            vout_thread_t *p_child = p_sys->pp_vout[i].p_vout;
+            if( !var_GetBool( p_child, "fullscreen" ) != !newval.b_bool )
+            {
+                var_SetBool( p_child, "fullscreen", newval.b_bool );
+                if( newval.b_bool )
+                    return VLC_SUCCESS;
+            }
         }
     }
-
     return VLC_SUCCESS;
 }
+
index 5e402c55d3acbd321d60e59dd2faf2b7bcfabde2..f62cb21327754bb5078388c79eb02599acbc99e2 100644 (file)
@@ -50,8 +50,6 @@ static int  Init      ( vout_thread_t * );
 static void End       ( vout_thread_t * );
 static void Render    ( vout_thread_t *, picture_t * );
 
-static int  SendEvents   ( vlc_object_t *, char const *,
-                           vlc_value_t, vlc_value_t, void * );
 static int  MouseEvent   ( vlc_object_t *, char const *,
                            vlc_value_t, vlc_value_t, void * );
 
@@ -242,8 +240,6 @@ static int Create( vlc_object_t *p_this )
  *****************************************************************************/
 static int Init( vout_thread_t *p_vout )
 {
-    int i_index;
-    picture_t *p_pic;
     video_format_t fmt;
     memset( &fmt, 0, sizeof( video_format_t ) );
 
@@ -270,14 +266,9 @@ static int Init( vout_thread_t *p_vout )
         return VLC_EGENERIC;
     }
 
-    var_AddCallback( p_vout->p_sys->p_vout, "mouse-x", MouseEvent, p_vout );
-    var_AddCallback( p_vout->p_sys->p_vout, "mouse-y", MouseEvent, p_vout );
-    var_AddCallback( p_vout->p_sys->p_vout, "mouse-clicked",
-                     MouseEvent, p_vout);
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
-    ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
 
     return VLC_SUCCESS;
 }
@@ -287,24 +278,12 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
+    vout_sys_t *p_sys = p_vout->p_sys;
 
-    DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+    vout_filter_DelChild( p_vout, p_sys->p_vout, MouseEvent );
+    vout_CloseAndRelease( p_sys->p_vout );
 
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
-    {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
-    }
-
-    var_DelCallback( p_vout->p_sys->p_vout, "mouse-x", MouseEvent, p_vout);
-    var_DelCallback( p_vout->p_sys->p_vout, "mouse-y", MouseEvent, p_vout);
-    var_DelCallback( p_vout->p_sys->p_vout, "mouse-clicked", MouseEvent, p_vout);
-
-    vout_CloseAndRelease( p_vout->p_sys->p_vout );
+    vout_filter_ReleaseDirectBuffers( p_vout );
 }
 
 #define SHUFFLE_WIDTH 81
@@ -457,42 +436,18 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
     vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
 }
 
-/*****************************************************************************
- * SendEvents: forward mouse and keyboard events to the parent p_vout
- *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
-
-    var_Set( (vlc_object_t *)p_data, psz_var, newval );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VLC_UNUSED(p_data); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    var_Set( p_vout->p_sys->p_vout, psz_var, newval );
-    return VLC_SUCCESS;
-}
-
 /*****************************************************************************
  * MouseEvent: callback for mouse events
  *****************************************************************************/
 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
-    VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(newval);
-    vout_thread_t *p_vout = (vout_thread_t*)p_data;
+    vout_thread_t *p_vout = p_data;
+    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
     int i_x, i_y;
     int i_v;
 
+    /* FIXME missing lock */
 #define MOUSE_DOWN    1
 #define MOUSE_CLICKED 2
 #define MOUSE_MOVE_X  4
@@ -552,6 +507,8 @@ static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
             p_vout->p_sys->b_finished = finished( p_vout->p_sys );
         }
     }
+    /* FIXME do we want to forward it or not ? */
+    var_Set( p_vout, psz_var, newval );
     return VLC_SUCCESS;
 }
 
index aadef39412c3a17182e3f0522a2be4a9b0ac0fe3..0409cf1acb126d2dd18f6c027694f55e707e65c6 100644 (file)
@@ -56,7 +56,7 @@ static void FilterPlanar( vout_thread_t *, const picture_t *, picture_t * );
 static void FilterI422( vout_thread_t *, const picture_t *, picture_t * );
 static void FilterYUYV( vout_thread_t *, const picture_t *, picture_t * );
 
-static int  SendEvents( vlc_object_t *, char const *,
+static int  MouseEvent( vlc_object_t *, char const *,
                         vlc_value_t, vlc_value_t, void * );
 
 /*****************************************************************************
@@ -216,8 +216,6 @@ static int Create( vlc_object_t *p_this )
  *****************************************************************************/
 static int Init( vout_thread_t *p_vout )
 {
-    int i_index;
-    picture_t *p_pic;
     video_format_t fmt;
 
     I_OUTPUTPICTURES = 0;
@@ -260,11 +258,9 @@ static int Init( vout_thread_t *p_vout )
         return VLC_EGENERIC;
     }
 
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
-
-    ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
 
     return VLC_SUCCESS;
 }
@@ -274,20 +270,12 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
+    vout_sys_t *p_sys = p_vout->p_sys;
 
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_DelChild( p_vout, p_sys->p_vout, MouseEvent );
+    vout_CloseAndRelease( p_sys->p_vout );
 
-    DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
-
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
-    {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
-    }
-
-    vout_CloseAndRelease( p_vout->p_sys->p_vout );
+    vout_filter_ReleaseDirectBuffers( p_vout );
 }
 
 /*****************************************************************************
@@ -334,32 +322,32 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
     vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
 }
 
-/*****************************************************************************
- * SendEvents: forward mouse and keyboard events to the parent p_vout
- *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *_p_vout )
+/**
+ * Forward mouse event with proper conversion.
+ */
+static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
+                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
+    vout_thread_t *p_vout = p_data;
     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)_p_vout;
-    vlc_value_t sentval = newval;
 
-    /* Translate the mouse coordinates */
+    /* Translate the mouse coordinates
+     * FIXME missing lock */
     if( !strcmp( psz_var, "mouse-x" ) )
     {
         switch( p_vout->p_sys->i_mode )
         {
         case TRANSFORM_MODE_270:
-            sentval.i_int = p_vout->p_sys->p_vout->output.i_width
-                             - sentval.i_int;
+            newval.i_int = p_vout->p_sys->p_vout->output.i_width
+                             - newval.i_int;
         case TRANSFORM_MODE_90:
-            var_Set( p_vout, "mouse-y", sentval );
-            return VLC_SUCCESS;
+            psz_var = "mouse-y";
+            break;
 
         case TRANSFORM_MODE_180:
         case TRANSFORM_MODE_HFLIP:
-            sentval.i_int = p_vout->p_sys->p_vout->output.i_width
-                             - sentval.i_int;
+            newval.i_int = p_vout->p_sys->p_vout->output.i_width
+                             - newval.i_int;
             break;
 
         case TRANSFORM_MODE_VFLIP:
@@ -372,16 +360,16 @@ static int SendEvents( vlc_object_t *p_this, char const *psz_var,
         switch( p_vout->p_sys->i_mode )
         {
         case TRANSFORM_MODE_90:
-            sentval.i_int = p_vout->p_sys->p_vout->output.i_height
-                             - sentval.i_int;
+            newval.i_int = p_vout->p_sys->p_vout->output.i_height
+                             - newval.i_int;
         case TRANSFORM_MODE_270:
-            var_Set( p_vout, "mouse-x", sentval );
-            return VLC_SUCCESS;
+            psz_var = "mouse-x";
+            break;
 
         case TRANSFORM_MODE_180:
         case TRANSFORM_MODE_VFLIP:
-            sentval.i_int = p_vout->p_sys->p_vout->output.i_height
-                             - sentval.i_int;
+            newval.i_int = p_vout->p_sys->p_vout->output.i_height
+                             - newval.i_int;
             break;
 
         case TRANSFORM_MODE_HFLIP:
@@ -390,21 +378,7 @@ static int SendEvents( vlc_object_t *p_this, char const *psz_var,
         }
     }
 
-    var_Set( p_vout, psz_var, sentval );
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VLC_UNUSED(p_data); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    var_Set( p_vout->p_sys->p_vout, psz_var, newval );
-    return VLC_SUCCESS;
+    return var_Set( p_vout, psz_var, newval );
 }
 
 static void FilterPlanar( vout_thread_t *p_vout,
index bb58190335405db01e8430875b5b66084463dfcf..397dc07966098bf479154feed939e9e65e7c9895 100644 (file)
@@ -32,6 +32,7 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_vout.h>
+#include <assert.h>
 
 #include "filter_common.h"
 
@@ -47,8 +48,12 @@ static void Render    ( vout_thread_t *, picture_t * );
 
 static void RemoveAllVout  ( vout_thread_t *p_vout );
 
-static int  SendEvents( vlc_object_t *, char const *,
+static int  MouseEvent( vlc_object_t *, char const *,
                         vlc_value_t, vlc_value_t, void * );
+static int  FullscreenEventUp( vlc_object_t *, char const *,
+                               vlc_value_t, vlc_value_t, void * );
+static int  FullscreenEventDown( vlc_object_t *, char const *,
+                                 vlc_value_t, vlc_value_t, void * );
 
 /*****************************************************************************
  * Module descriptor
@@ -237,9 +242,8 @@ static int Create( vlc_object_t *p_this )
  *****************************************************************************/
 static int Init( vout_thread_t *p_vout )
 {
-    int i_index, i_row, i_col, i_width, i_height, i_left, i_top;
+    int i_row, i_col, i_width, i_height, i_left, i_top;
     unsigned int i_target_width,i_target_height;
-    picture_t *p_pic;
     video_format_t fmt;
     int i_aspect = 4*VOUT_ASPECT_FACTOR/3;
     int i_align = 0;
@@ -430,16 +434,13 @@ static int Init( vout_thread_t *p_vout )
                 RemoveAllVout( p_vout );
                 return VLC_EGENERIC;
             }
-            ADD_CALLBACKS(
-                p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].p_vout,
-                SendEvents );
+            vout_filter_SetupChild( p_vout, p_vout->p_sys->pp_vout[p_vout->p_sys->i_vout].p_vout,
+                                    MouseEvent, FullscreenEventUp, FullscreenEventDown, true );
             p_vout->p_sys->i_vout++;
         }
     }
 
-    ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
-
-    ADD_PARENT_CALLBACKS( SendEventsToChild );
+    vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
     return VLC_SUCCESS;
 }
@@ -449,18 +450,9 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
-
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
-    {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
-    }
-
     RemoveAllVout( p_vout );
+
+    vout_filter_ReleaseDirectBuffers( p_vout );
 }
 
 /*****************************************************************************
@@ -575,82 +567,98 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
  *****************************************************************************/
 static void RemoveAllVout( vout_thread_t *p_vout )
 {
-    while( p_vout->p_sys->i_vout )
+    vout_sys_t *p_sys = p_vout->p_sys;
+
+    while( p_sys->i_vout )
     {
-         --p_vout->p_sys->i_vout;
-         if( p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].b_active )
-         {
-             DEL_CALLBACKS(
-                 p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].p_vout,
-                 SendEvents );
-             vout_CloseAndRelease( p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].p_vout );
-         }
+        p_sys->i_vout--;
+        if( p_sys->pp_vout[p_sys->i_vout ].b_active )
+        {
+            vout_filter_SetupChild( p_vout, p_sys->pp_vout[p_sys->i_vout].p_vout,
+                                    MouseEvent, FullscreenEventUp, FullscreenEventDown, false );
+            vout_CloseAndRelease( p_sys->pp_vout[p_sys->i_vout].p_vout );
+        }
     }
 }
 
-/*****************************************************************************
- * SendEvents: forward mouse and keyboard events to the parent p_vout
- *****************************************************************************/
-static int SendEvents( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *_p_vout )
+/**
+ * Forward mouse event with proper conversion.
+ */
+static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
+                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
+    vout_thread_t *p_vout = p_data;
+    vout_sys_t *p_sys = p_vout->p_sys;
     VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)_p_vout;
     int i_vout;
-    vlc_value_t sentval = newval;
 
     /* Find the video output index */
-    for( i_vout = 0; i_vout < p_vout->p_sys->i_vout; i_vout++ )
+    for( i_vout = 0; i_vout < p_sys->i_vout; i_vout++ )
     {
-        if( p_this == (vlc_object_t *)p_vout->p_sys->pp_vout[ i_vout ].p_vout )
-        {
+        if( p_sys->pp_vout[i_vout].b_active &&
+            p_this == VLC_OBJECT(p_sys->pp_vout[i_vout].p_vout) )
             break;
-        }
-    }
-
-    if( i_vout == p_vout->p_sys->i_vout )
-    {
-        return VLC_EGENERIC;
     }
+    assert( i_vout < p_vout->p_sys->i_vout );
 
     /* Translate the mouse coordinates */
     if( !strcmp( psz_var, "mouse-x" ) )
-    {
-        sentval.i_int += p_vout->output.i_width
-                          * (i_vout % p_vout->p_sys->i_col)
-                          / p_vout->p_sys->i_col;
-    }
+        newval.i_int += p_vout->output.i_width * (i_vout % p_sys->i_col) / p_sys->i_col;
     else if( !strcmp( psz_var, "mouse-y" ) )
+        newval.i_int += p_vout->output.i_height * (i_vout / p_sys->i_row) / p_sys->i_row;
+
+    return var_Set( p_vout, psz_var, newval );
+}
+
+/**
+ * Forward fullscreen event to/from the childrens.
+ */
+static bool IsFullscreenActive( vout_thread_t *p_vout )
+{
+    vout_sys_t *p_sys = p_vout->p_sys;
+    for( int i = 0; i < p_sys->i_vout; i++ )
     {
-        sentval.i_int += p_vout->output.i_height
-                          * (i_vout / p_vout->p_sys->i_row)
-                          / p_vout->p_sys->i_row;
+        if( p_sys->pp_vout[i].b_active &&
+            var_GetBool( p_sys->pp_vout[i].p_vout, "fullscreen" ) )
+            return true;
     }
+    return false;
+}
+static int FullscreenEventUp( vlc_object_t *p_this, char const *psz_var,
+                              vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+    vout_thread_t *p_vout = p_data;
+    VLC_UNUSED(oldval); VLC_UNUSED(p_this); VLC_UNUSED(psz_var); VLC_UNUSED(newval);
 
-    var_Set( p_vout, psz_var, sentval );
-
+    const bool b_fullscreen = IsFullscreenActive( p_vout );
+    if( !var_GetBool( p_vout, "fullscreen" ) != !b_fullscreen )
+        return var_SetBool( p_vout, "fullscreen", b_fullscreen );
     return VLC_SUCCESS;
 }
-
-/*****************************************************************************
- * SendEventsToChild: forward events to the child/children vout
- *****************************************************************************/
-static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
+static int FullscreenEventDown( vlc_object_t *p_this, char const *psz_var,
+                                vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
-    VLC_UNUSED(p_data); VLC_UNUSED(oldval);
-    vout_thread_t *p_vout = (vout_thread_t *)p_this;
-    int i_row, i_col, i_vout = 0;
+    vout_thread_t *p_vout = (vout_thread_t*)p_this;
+    vout_sys_t *p_sys = p_vout->p_sys;
+    VLC_UNUSED(oldval); VLC_UNUSED(p_data); VLC_UNUSED(psz_var);
 
-    for( i_row = 0; i_row < p_vout->p_sys->i_row; i_row++ )
+    const bool b_fullscreen = IsFullscreenActive( p_vout );
+    if( !b_fullscreen != !newval.b_bool )
     {
-        for( i_col = 0; i_col < p_vout->p_sys->i_col; i_col++ )
+        for( int i = 0; i < p_sys->i_vout; i++ )
         {
-            var_Set( p_vout->p_sys->pp_vout[ i_vout ].p_vout, psz_var, newval);
-            if( !strcmp( psz_var, "fullscreen" ) ) break;
-            i_vout++;
+            if( !p_sys->pp_vout[i].b_active )
+                continue;
+
+            vout_thread_t *p_child = p_sys->pp_vout[i].p_vout;
+            if( !var_GetBool( p_child, "fullscreen" ) != !newval.b_bool )
+            {
+                var_SetBool( p_child, "fullscreen", newval.b_bool );
+                if( newval.b_bool )
+                    return VLC_SUCCESS;
+            }
         }
     }
-
     return VLC_SUCCESS;
 }
+