]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/video.cpp
update module LIST file.
[vlc] / modules / gui / wxwidgets / video.cpp
1 /*****************************************************************************
2  * video.cpp : wxWidgets plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2004, 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc/vlc.h>
32 #include <vlc_vout.h>
33 #include <vlc_interface.h>
34
35 #include "video.hpp"
36 #include "interface.hpp"
37
38 static void *GetWindow( intf_thread_t *p_intf, vout_thread_t *,
39                         int *pi_x_hint, int *pi_y_hint,
40                         unsigned int *pi_width_hint,
41                         unsigned int *pi_height_hint );
42
43 static void ReleaseWindow( intf_thread_t *p_intf, void *p_window );
44
45 static int ControlWindow( intf_thread_t *p_intf, void *p_window,
46                           int i_query, va_list args );
47
48 /* IDs for the controls and the menu commands */
49 enum
50 {
51     UpdateSize_Event = wxID_HIGHEST + 1,
52     UpdateHide_Event,
53     SetStayOnTop_Event,
54     ID_HIDE_TIMER
55 };
56
57 DEFINE_LOCAL_EVENT_TYPE( wxEVT_VLC_VIDEO );
58
59 BEGIN_EVENT_TABLE(VideoWindow, wxWindow)
60     EVT_CUSTOM( wxEVT_SIZE, UpdateSize_Event, VideoWindow::UpdateSize )
61     EVT_CUSTOM( wxEVT_SIZE, UpdateHide_Event, VideoWindow::UpdateHide )
62     EVT_COMMAND( SetStayOnTop_Event, wxEVT_VLC_VIDEO,
63                  VideoWindow::OnControlEvent )
64     EVT_TIMER( ID_HIDE_TIMER, VideoWindow::OnHideTimer )
65 END_EVENT_TABLE()
66
67 /*****************************************************************************
68  * Public methods.
69  *****************************************************************************/
70 wxWindow *CreateVideoWindow( intf_thread_t *p_intf, wxWindow *p_parent )
71 {
72     return new VideoWindow( p_intf, p_parent );
73 }
74
75 void UpdateVideoWindow( intf_thread_t *p_intf, wxWindow *p_window )
76 {
77 #if wxCHECK_VERSION(2,5,3)
78     if( !p_intf->p_sys->b_video_autosize ) return;
79
80     if( p_window && mdate() - ((VideoWindow *)p_window)->i_creation_date < 2000000 )
81         return; /* Hack to prevent saving coordinates if window is not yet
82                  * properly created. Yuck :( */
83
84     if( p_window && p_intf->p_sys->p_video_sizer && p_window->IsShown() )
85         p_intf->p_sys->p_video_sizer->SetMinSize( p_window->GetSize() );
86 #endif
87 }
88
89 /*****************************************************************************
90  * Constructor.
91  *****************************************************************************/
92 VideoWindow::VideoWindow( intf_thread_t *_p_intf, wxWindow *_p_parent ):
93   wxWindow( _p_parent, -1, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN )
94 {
95     /* Initializations */
96     p_intf = _p_intf;
97     p_parent = _p_parent;
98     p_child_window = 0;
99
100     vlc_mutex_init( p_intf, &lock );
101
102     b_auto_size = p_intf->p_sys->b_video_autosize;
103
104     p_vout = NULL;
105     i_creation_date = 0;
106     m_hide_timer.SetOwner( this, ID_HIDE_TIMER );
107
108     p_intf->pf_request_window = ::GetWindow;
109     p_intf->pf_release_window = ::ReleaseWindow;
110     p_intf->pf_control_window = ::ControlWindow;
111
112     p_intf->p_sys->p_video_window = this;
113
114     wxSize child_size = wxSize(0,0);
115     if( !b_auto_size )
116     {
117         WindowSettings *ws = p_intf->p_sys->p_window_settings;
118         wxPoint p; bool b_shown;
119
120         // Maybe this size should be an option
121         child_size = wxSize( wxSystemSettings::GetMetric(wxSYS_SCREEN_X) / 2,
122                              wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) / 2 );
123
124         ws->GetSettings( WindowSettings::ID_VIDEO, b_shown, p, child_size );
125         SetSize( child_size );
126     }
127
128 #ifdef __WXGTK__
129     p_child_window = new wxWindow( this, -1, wxDefaultPosition, child_size,
130                                    wxCLIP_CHILDREN );
131 #endif
132
133     if( !b_auto_size )
134     {
135         SetBackgroundColour( *wxBLACK );
136         if( p_child_window ) p_child_window->SetBackgroundColour( *wxBLACK );
137     }
138
139     if( p_child_window ) p_child_window->Show();
140     Show();
141     b_shown = VLC_TRUE;
142
143     p_intf->p_sys->p_video_sizer = new wxBoxSizer( wxHORIZONTAL );
144 #if (wxCHECK_VERSION(2,5,3))
145     p_intf->p_sys->p_video_sizer->Add( this, 1, wxEXPAND|wxFIXED_MINSIZE );
146 #else
147     p_intf->p_sys->p_video_sizer->Add( this, 1, wxEXPAND );
148 #endif
149
150     ReleaseWindow( NULL );
151 }
152
153 VideoWindow::~VideoWindow()
154 {
155     vlc_mutex_lock( &lock );
156     if( p_vout )
157     {
158         if( !p_intf->psz_switch_intf )
159         {
160             if( vout_Control( p_vout, VOUT_CLOSE ) != VLC_SUCCESS )
161                 vout_Control( p_vout, VOUT_REPARENT, 0 );
162         }
163         else
164         {
165             if( vout_Control( p_vout, VOUT_REPARENT, 0 ) != VLC_SUCCESS )
166                 vout_Control( p_vout, VOUT_CLOSE );
167         }
168     }
169
170     p_intf->pf_request_window = NULL;
171     p_intf->pf_release_window = NULL;
172     p_intf->pf_control_window = NULL;
173     vlc_mutex_unlock( &lock );
174
175     if( !b_auto_size )
176     {
177         WindowSettings *ws = p_intf->p_sys->p_window_settings;
178         ws->SetSettings( WindowSettings::ID_VIDEO, true,
179                          GetPosition(), GetSize() );
180     }
181
182     vlc_mutex_destroy( &lock );
183 }
184
185 /*****************************************************************************
186  * Private methods.
187  *****************************************************************************/
188 static void *GetWindow( intf_thread_t *p_intf, vout_thread_t *p_vout,
189                         int *pi_x_hint, int *pi_y_hint,
190                         unsigned int *pi_width_hint,
191                         unsigned int *pi_height_hint )
192 {
193     return p_intf->p_sys->p_video_window->GetWindow( p_vout,
194                                                      pi_x_hint, pi_y_hint,
195                                                      pi_width_hint,
196                                                      pi_height_hint );
197 }
198
199 /* Part of the hack to get the X11 window handle from the GtkWidget */
200 #ifdef __WXGTK__
201 extern "C" {
202 #ifdef __WXGTK20__
203     int gdk_x11_drawable_get_xid( void * );
204 #endif
205     void *gtk_widget_get_parent_window( void * );
206 }
207 #endif
208
209 void *VideoWindow::GetWindow( vout_thread_t *_p_vout,
210                               int *pi_x_hint, int *pi_y_hint,
211                               unsigned int *pi_width_hint,
212                               unsigned int *pi_height_hint )
213 {
214 #if defined(__WXGTK__) || defined(WIN32)
215     vlc_mutex_lock( &lock );
216
217     if( p_vout )
218     {
219         vlc_mutex_unlock( &lock );
220         msg_Dbg( p_intf, "video window already in use" );
221         return NULL;
222     }
223
224     p_vout = _p_vout;
225
226     wxSizeEvent event( wxSize(*pi_width_hint, *pi_height_hint),
227                        UpdateSize_Event );
228     AddPendingEvent( event );
229     vlc_mutex_unlock( &lock );
230
231 #ifdef __WXGTK__
232     GtkWidget *p_widget = p_child_window->GetHandle();
233
234 #ifdef __WXGTK20__
235     return (void *)gdk_x11_drawable_get_xid(
236                gtk_widget_get_parent_window( p_widget ) );
237 #elif defined(__WXGTK__)
238     return (void *)*(int *)( (char *)gtk_widget_get_parent_window( p_widget )
239                + 2 * sizeof(void *) );
240 #endif
241
242 #elif defined(WIN32)
243     return (void*)GetHandle();
244
245 #endif
246
247 #else // defined(__WXGTK__) || defined(WIN32)
248     return NULL;
249
250 #endif
251 }
252
253 static void ReleaseWindow( intf_thread_t *p_intf, void *p_window )
254 {
255     return p_intf->p_sys->p_video_window->ReleaseWindow( p_window );
256 }
257
258 void VideoWindow::ReleaseWindow( void *p_window )
259 {
260     vlc_mutex_lock( &lock );
261     p_vout = NULL;
262     vlc_mutex_unlock( &lock );
263
264     if( !b_auto_size ) return;
265
266 #if defined(__WXGTK__) || defined(WIN32)
267     wxSizeEvent event( wxSize(0, 0), UpdateHide_Event );
268     AddPendingEvent( event );
269 #endif
270 }
271
272 void VideoWindow::UpdateSize( wxEvent &_event )
273 {
274     m_hide_timer.Stop();
275
276     if( !b_auto_size ) return;
277
278     wxSizeEvent * event = (wxSizeEvent*)(&_event);
279     if( !b_shown )
280     {
281         p_intf->p_sys->p_video_sizer->Show( this, TRUE );
282         p_intf->p_sys->p_video_sizer->Layout();
283         SetFocus();
284         b_shown = VLC_TRUE;
285     }
286
287     p_intf->p_sys->p_video_sizer->SetMinSize( event->GetSize() );
288
289     i_creation_date = mdate();
290     wxCommandEvent intf_event( wxEVT_INTF, 0 );
291     p_parent->AddPendingEvent( intf_event );
292 }
293
294 void VideoWindow::UpdateHide( wxEvent &_event )
295 {
296     if( b_auto_size ) m_hide_timer.Start( 200, wxTIMER_ONE_SHOT );
297 }
298
299 void VideoWindow::OnHideTimer( wxTimerEvent& WXUNUSED(event))
300 {
301     if( b_shown )
302     {
303         p_intf->p_sys->p_video_sizer->Show( this, FALSE );
304         SetSize( 0, 0 );
305         p_intf->p_sys->p_video_sizer->Layout();
306         b_shown = VLC_FALSE;
307     }
308     p_intf->p_sys->p_video_sizer->SetMinSize( wxSize(0,0) );
309
310     wxCommandEvent intf_event( wxEVT_INTF, 0 );
311     p_parent->AddPendingEvent( intf_event );
312 }
313
314 void VideoWindow::OnControlEvent( wxCommandEvent &event )
315 {
316     switch( event.GetId() )
317     {
318     case SetStayOnTop_Event:
319         wxCommandEvent intf_event( wxEVT_INTF, 1 );
320         intf_event.SetInt( event.GetInt() );
321         p_parent->AddPendingEvent( intf_event );
322         break;
323     }
324 }
325
326 static int ControlWindow( intf_thread_t *p_intf, void *p_window,
327                           int i_query, va_list args )
328 {
329     return p_intf->p_sys->p_video_window->ControlWindow( p_window, i_query,
330                                                          args );
331 }
332
333 int VideoWindow::ControlWindow( void *p_window, int i_query, va_list args )
334 {
335     int i_ret = VLC_EGENERIC;
336
337     vlc_mutex_lock( &lock );
338
339     switch( i_query )
340     {
341         case VOUT_GET_SIZE:
342         {
343             unsigned int *pi_width  = va_arg( args, unsigned int * );
344             unsigned int *pi_height = va_arg( args, unsigned int * );
345
346             *pi_width = GetSize().GetWidth();
347             *pi_height = GetSize().GetHeight();
348             i_ret = VLC_SUCCESS;
349         }
350         break;
351
352         case VOUT_SET_SIZE:
353         {
354             if( !b_auto_size ) break;
355
356             unsigned int i_width  = va_arg( args, unsigned int );
357             unsigned int i_height = va_arg( args, unsigned int );
358
359             if( !i_width && p_vout ) i_width = p_vout->i_window_width;
360             if( !i_height && p_vout ) i_height = p_vout->i_window_height;
361
362             /* Update dimensions */
363             wxSizeEvent event( wxSize( i_width, i_height ), UpdateSize_Event );
364
365             AddPendingEvent( event );
366
367             i_ret = VLC_SUCCESS;
368         }
369         break;
370
371         case VOUT_SET_STAY_ON_TOP:
372         {
373             int i_arg = va_arg( args, int );
374             wxCommandEvent event( wxEVT_VLC_VIDEO, SetStayOnTop_Event );
375             event.SetInt( i_arg );
376             AddPendingEvent( event );
377
378             i_ret = VLC_SUCCESS;
379         }
380         break;
381
382         default:
383             msg_Dbg( p_intf, "control query not supported" );
384             break;
385     }
386
387     vlc_mutex_unlock( &lock );
388
389     return i_ret;
390 }