+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Helper thread for object variables callbacks.
+ * Only used to avoid deadlocks when using the video embedded mode.
+ *****************************************************************************/
+typedef struct suxor_thread_t
+{
+ VLC_COMMON_MEMBERS
+ input_thread_t *p_input;
+
+} suxor_thread_t;
+
+static void SuxorRestartVideoES( suxor_thread_t *p_this )
+{
+ vlc_value_t val;
+
+ /* Now restart current video stream */
+ var_Get( p_this->p_input, "video-es", &val );
+ if( val.i_int >= 0 )
+ {
+ vlc_value_t val_es;
+ val_es.i_int = -VIDEO_ES;
+ var_Set( p_this->p_input, "video-es", val_es );
+ var_Set( p_this->p_input, "video-es", val );
+ }
+
+ vlc_object_release( p_this->p_input );
+
+#ifdef WIN32
+ CloseHandle( p_this->thread_id );
+#endif
+
+ vlc_object_destroy( p_this );
+}
+
+/*****************************************************************************
+ * object variables callbacks: a bunch of object variables are used by the
+ * interfaces to interact with the vout.
+ *****************************************************************************/
+static int DeinterlaceCallback( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ input_thread_t *p_input;
+ vlc_value_t val;
+
+ char *psz_mode = newval.psz_string;
+ char *psz_filter, *psz_deinterlace = NULL;
+
+ var_Get( p_vout, "filter", &val );
+ psz_filter = val.psz_string;
+ if( psz_filter ) psz_deinterlace = strstr( psz_filter, "deinterlace" );
+
+ if( !psz_mode || !*psz_mode )
+ {
+ if( psz_deinterlace )
+ {
+ char *psz_src = psz_deinterlace + sizeof("deinterlace") - 1;
+ if( psz_src[0] == ',' ) psz_src++;
+ memmove( psz_deinterlace, psz_src, strlen(psz_src) + 1 );
+ }
+ }
+ else if( !psz_deinterlace )
+ {
+ psz_filter = realloc( psz_filter, strlen( psz_filter ) +
+ sizeof(",deinterlace") );
+ if( psz_filter && *psz_filter ) strcat( psz_filter, "," );
+ strcat( psz_filter, "deinterlace" );
+ }
+
+ p_input = (input_thread_t *)vlc_object_find( p_this, VLC_OBJECT_INPUT,
+ FIND_PARENT );
+ if( !p_input ) return VLC_EGENERIC;
+
+ if( psz_mode && *psz_mode )
+ {
+ /* Modify input as well because the vout might have to be restarted */
+ val.psz_string = psz_mode;
+ var_Create( p_input, "deinterlace-mode", VLC_VAR_STRING );
+ var_Set( p_input, "deinterlace-mode", val );
+ }
+ vlc_object_release( p_input );
+
+ val.b_bool = VLC_TRUE;
+ var_Set( p_vout, "intf-change", val );
+
+ val.psz_string = psz_filter;
+ var_Set( p_vout, "filter", val );
+ if( psz_filter ) free( psz_filter );
+
+ return VLC_SUCCESS;
+}
+
+static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ input_thread_t *p_input;
+ vlc_value_t val;
+
+ p_input = (input_thread_t *)vlc_object_find( p_this, VLC_OBJECT_INPUT,
+ FIND_PARENT );
+ if (!p_input)
+ {
+ msg_Err( p_vout, "Input not found" );
+ return( VLC_EGENERIC );
+ }
+
+ val.b_bool = VLC_TRUE;
+ var_Set( p_vout, "intf-change", val );
+
+ /* Modify input as well because the vout might have to be restarted */
+ val.psz_string = newval.psz_string;
+ var_Create( p_input, "filter", VLC_VAR_STRING );
+ var_Set( p_input, "filter", val );
+
+ /* Now restart current video stream */
+ var_Get( p_input, "video-es", &val );
+ if( val.i_int >= 0 )
+ {
+ p_vout->b_filter_change = VLC_TRUE;
+ suxor_thread_t *p_suxor =
+ vlc_object_create( p_vout, sizeof(suxor_thread_t) );
+ p_suxor->p_input = p_input;
+ vlc_object_yield( p_input );
+ vlc_thread_create( p_suxor, "suxor", SuxorRestartVideoES,
+ VLC_THREAD_PRIORITY_LOW, VLC_FALSE );
+ }
+
+ vlc_object_release( p_input );
+
+ return VLC_SUCCESS;