+int filter_chain_AppendFromString( filter_chain_t *p_chain,
+ const char *psz_string )
+{
+ const int i_ret = filter_chain_AppendFromStringInternal( p_chain, psz_string );
+ if( i_ret < 0 )
+ return i_ret;
+
+ /* FIXME That one seems bad if a error is returned */
+ return UpdateBufferFunctions( p_chain );
+}
+
+int filter_chain_DeleteFilter( filter_chain_t *p_chain, filter_t *p_filter )
+{
+ const int i_ret = filter_chain_DeleteFilterInternal( p_chain, p_filter );
+ if( i_ret < 0 )
+ return i_ret;
+
+ /* FIXME That one seems bad if a error is returned */
+ return UpdateBufferFunctions( p_chain );
+}
+
+int filter_chain_GetLength( filter_chain_t *p_chain )
+{
+ return vlc_array_count( &p_chain->filters );
+}
+
+const es_format_t *filter_chain_GetFmtOut( filter_chain_t *p_chain )
+{
+
+ if( p_chain->b_allow_fmt_out_change )
+ return &p_chain->fmt_out;
+
+ const int i_count = vlc_array_count( &p_chain->filters );
+ if( i_count > 0 )
+ {
+ filter_t *p_last = vlc_array_item_at_index( &p_chain->filters, i_count - 1 );
+ return &p_last->fmt_out;
+ }
+
+ /* Unless filter_chain_Reset has been called we are doomed */
+ return &p_chain->fmt_out;
+}
+
+picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic )
+{
+ for( int i = 0; i < vlc_array_count( &p_chain->filters ); i++ )
+ {
+ filter_t *p_filter = vlc_array_item_at_index( &p_chain->filters, i );
+
+ p_pic = p_filter->pf_video_filter( p_filter, p_pic );
+ if( !p_pic )
+ break;
+ }
+ return p_pic;
+}
+
+block_t *filter_chain_AudioFilter( filter_chain_t *p_chain, block_t *p_block )
+{
+ for( int i = 0; i < vlc_array_count( &p_chain->filters ); i++ )
+ {
+ filter_t *p_filter = vlc_array_item_at_index( &p_chain->filters, i );
+
+ p_block = p_filter->pf_audio_filter( p_filter, p_block );
+ if( !p_block )
+ break;
+ }
+ return p_block;
+}
+
+void filter_chain_SubFilter( filter_chain_t *p_chain,
+ mtime_t display_date )
+{
+ for( int i = 0; i < vlc_array_count( &p_chain->filters ); i++ )
+ {
+ filter_t *p_filter = vlc_array_item_at_index( &p_chain->filters, i );
+
+ subpicture_t *p_subpic = p_filter->pf_sub_filter( p_filter, display_date );
+ /* XXX I find that spu_t cast ugly */
+ if( p_subpic )
+ spu_DisplaySubpicture( (spu_t*)p_chain->p_this, p_subpic );
+ }
+}
+
+int filter_chain_MouseFilter( filter_chain_t *p_chain, vlc_mouse_t *p_dst, const vlc_mouse_t *p_src )
+{
+ vlc_mouse_t current = *p_src;
+
+ for( int i = vlc_array_count( &p_chain->filters ) - 1; i >= 0; i-- )
+ {
+ filter_t *p_filter = vlc_array_item_at_index( &p_chain->filters, i );
+ vlc_mouse_t *p_mouse = vlc_array_item_at_index( &p_chain->mouses, i );
+
+ if( p_filter->pf_mouse && p_mouse )
+ {
+ vlc_mouse_t old = *p_mouse;
+ vlc_mouse_t filtered;
+
+ *p_mouse = current;
+ if( p_filter->pf_mouse( p_filter, &filtered, &old, ¤t ) )
+ return VLC_EGENERIC;
+ current = filtered;
+ }
+ }
+
+ *p_dst = current;
+ return VLC_SUCCESS;
+}
+
+
+/* Helpers */