1 /*****************************************************************************
2 * wrapper.c: a "video filter2" with mouse to "video filter" wrapper.
3 *****************************************************************************
4 * Copyright (C) 2009 Laurent Aimar
7 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
36 #include <vlc_filter.h>
38 #include "filter_common.h"
40 /*****************************************************************************
42 *****************************************************************************/
43 static int Open ( vlc_object_t *, const char *psz_name );
44 static void Close( vlc_object_t * );
46 #define DECLARE_OPEN(name) \
47 static int Open##name ( vlc_object_t *p_this ) { return Open( p_this, #name ); }
53 #define DECLARE_MODULE(name) \
54 set_description( "Video filter "#name" wrapper" ) \
55 set_shortname( "Video filter"#name" wrapper" ) \
56 set_capability( "video filter", 0 ) \
57 set_callbacks( Open##name, Close ) \
61 set_category( CAT_VIDEO )
62 set_subcategory( SUBCAT_VIDEO_VFILTER )
64 DECLARE_MODULE(magnify)
70 /*****************************************************************************
72 *****************************************************************************/
73 static int Init ( vout_thread_t * );
74 static void End ( vout_thread_t * );
75 static void Render ( vout_thread_t *, picture_t * );
76 static int Control ( vout_thread_t *, int, va_list );
80 vout_thread_t *p_vout;
85 filter_chain_t *p_chain;
89 static int MouseEvent( vlc_object_t *, char const *,
90 vlc_value_t, vlc_value_t, void * );
92 static int FilterAllocationInit ( filter_t *, void * );
93 static void FilterAllocationClean( filter_t * );
96 * Open our wrapper instance.
98 static int Open( vlc_object_t *p_this, const char *psz_name )
100 vout_thread_t *p_vout = (vout_thread_t *)p_this;
103 msg_Err( p_vout, "Opening video filter wrapper for %s", psz_name );
105 /* Try to open our filter */
106 filter_chain_t *p_chain =
107 filter_chain_New( p_vout, "video filter2", false,
108 FilterAllocationInit, FilterAllocationClean, p_vout );
113 es_format_Init( &fmt, VIDEO_ES, p_vout->render.i_chroma );
114 video_format_Setup( &fmt.video, p_vout->render.i_chroma,
115 p_vout->render.i_width, p_vout->render.i_height,
116 p_vout->render.i_aspect );
118 filter_chain_Reset( p_chain, &fmt, &fmt );
121 filter_chain_AppendFilter( p_chain, psz_name, NULL, &fmt, &fmt );
125 msg_Err( p_vout, "Failed to open filter '%s'", psz_name );
126 filter_chain_Delete( p_chain );
130 p_vout->p_sys = p_sys = malloc( sizeof(*p_sys) );
133 filter_chain_Delete( p_chain );
137 vlc_mutex_init( &p_sys->lock );
138 p_sys->p_chain = p_chain;
139 p_sys->p_vout = NULL;
140 vlc_mouse_Init( &p_sys->mouse );
142 p_vout->pf_init = Init;
143 p_vout->pf_end = End;
144 p_vout->pf_manage = NULL;
145 p_vout->pf_render = Render;
146 p_vout->pf_display = NULL;
147 p_vout->pf_control = Control;
153 * Close our wrapper instance
155 static void Close( vlc_object_t *p_this )
157 vout_thread_t *p_vout = (vout_thread_t *)p_this;
158 vout_sys_t *p_sys = p_vout->p_sys;
160 filter_chain_Delete( p_sys->p_chain );
161 vlc_mutex_destroy( &p_sys->lock );
162 es_format_Clean( &p_sys->fmt );
164 free( p_vout->p_sys );
168 * Initialise our wrapper
170 static int Init( vout_thread_t *p_vout )
172 vout_sys_t *p_sys = p_vout->p_sys;
174 assert( p_vout->render.i_chroma == p_sys->fmt.video.i_chroma &&
175 p_vout->render.i_width == p_sys->fmt.video.i_width &&
176 p_vout->render.i_height == p_sys->fmt.video.i_height );
178 /* Initialize the output structure */
179 I_OUTPUTPICTURES = 0;
180 p_vout->output.i_chroma = p_vout->render.i_chroma;
181 p_vout->output.i_width = p_vout->render.i_width;
182 p_vout->output.i_height = p_vout->render.i_height;
183 p_vout->output.i_aspect = p_vout->render.i_aspect;
185 p_vout->fmt_out = p_vout->fmt_in;
187 /* Try to open the real video output */
188 msg_Dbg( p_vout, "spawning the real video output" );
190 video_format_t fmt = p_vout->fmt_out;
191 p_sys->p_vout = vout_Create( p_vout, &fmt );
194 msg_Err( p_vout, "cannot open vout, aborting" );
198 vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
200 vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
206 * Clean up our wrapper
208 static void End( vout_thread_t *p_vout )
210 vout_sys_t *p_sys = p_vout->p_sys;
212 vout_filter_DelChild( p_vout, p_sys->p_vout, MouseEvent );
213 vout_CloseAndRelease( p_sys->p_vout );
215 vout_filter_ReleaseDirectBuffers( p_vout );
219 * Control the real vout
221 static int Control( vout_thread_t *p_vout, int i_query, va_list args )
223 return vout_vaControl( p_vout->p_sys->p_vout, i_query, args );
229 static void Render( vout_thread_t *p_vout, picture_t *p_src )
231 vout_sys_t *p_sys = p_vout->p_sys;
233 vlc_mutex_lock( &p_sys->lock );
234 picture_t *p_dst = filter_chain_VideoFilter( p_sys->p_chain, p_src );
236 vout_DisplayPicture( p_sys->p_vout, p_dst );
237 vlc_mutex_unlock( &p_sys->lock );
241 * Callback for mouse events
243 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
244 vlc_value_t oldval, vlc_value_t newval, void *p_data )
246 vout_thread_t *p_vout = p_data;
247 vout_sys_t *p_sys = p_vout->p_sys;
250 vlc_mouse_Init( &m );
251 m.i_x = var_GetInteger( p_sys->p_vout, "mouse-x" );
252 m.i_y = var_GetInteger( p_sys->p_vout, "mouse-y" );
253 m.i_pressed = var_GetInteger( p_sys->p_vout, "mouse-button-down" );
255 vlc_mutex_lock( &p_sys->lock );
258 vlc_mouse_t omouse = p_sys->mouse;
260 int i_ret = filter_chain_MouseFilter( p_sys->p_chain, &nmouse, &m );
262 p_sys->mouse = nmouse;
263 vlc_mutex_unlock( &p_sys->lock );
268 if( vlc_mouse_HasMoved( &omouse, &nmouse ) )
270 var_SetInteger( p_vout, "mouse-x", nmouse.i_x );
271 var_SetInteger( p_vout, "mouse-y", nmouse.i_y );
272 var_SetBool( p_vout, "mouse-moved", true );
274 if( vlc_mouse_HasButton( &omouse, &nmouse ) )
276 var_SetInteger( p_vout, "mouse-button-down", nmouse.i_pressed );
277 if( vlc_mouse_HasPressed( &omouse, &nmouse, MOUSE_BUTTON_LEFT ) )
278 var_SetBool( p_vout, "mouse-clicked", true );
280 if( m.b_double_click )
282 /* Nothing with current API */
283 msg_Warn( p_vout, "Ignoring double click" );
289 static picture_t *VideoBufferNew( filter_t *p_filter )
291 vout_thread_t *p_vout = (vout_thread_t*)p_filter->p_owner;
292 vout_sys_t *p_sys = p_vout->p_sys;
294 picture_t *p_picture;
297 p_picture = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 );
301 if( !vlc_object_alive( p_vout ) || p_vout->b_error )
303 msleep( VOUT_OUTMEM_SLEEP );
306 static void VideoBufferDelete( filter_t *p_filter, picture_t *p_picture )
308 VLC_UNUSED(p_filter); VLC_UNUSED(p_picture);
309 /* FIXME is there anything to do ? */
312 static int FilterAllocationInit( filter_t *p_filter, void *p_data )
314 VLC_UNUSED( p_data );
316 p_filter->pf_vout_buffer_new = VideoBufferNew;
317 p_filter->pf_vout_buffer_del = VideoBufferDelete;
318 p_filter->p_owner = p_data;
322 static void FilterAllocationClean( filter_t *p_filter )
324 p_filter->pf_vout_buffer_new = NULL;
325 p_filter->pf_vout_buffer_del = NULL;