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