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