]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/video.cpp
* modules/gui/wxwindows: small cleanup + renamed wxwin-size-to-video into wxwin-autosize.
[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 /*****************************************************************************
103  * Constructor.
104  *****************************************************************************/
105 VideoWindow::VideoWindow( intf_thread_t *_p_intf, wxWindow *_p_parent ):
106     wxWindow( _p_parent, -1 )
107 {
108     /* Initializations */
109     p_intf = _p_intf;
110     p_parent = _p_parent;
111
112     vlc_mutex_init( p_intf, &lock );
113
114     b_auto_size = config_GetInt( p_intf, "wxwin-autosize" );
115
116     p_vout = NULL;
117
118     m_hide_timer.SetOwner( this, ID_HIDE_TIMER );
119
120     p_intf->pf_request_window = ::GetWindow;
121     p_intf->pf_release_window = ::ReleaseWindow;
122     p_intf->pf_control_window = ::ControlWindow;
123
124     p_intf->p_sys->p_video_window = this;
125
126     wxSize child_size = wxSize(0,0);
127     if( !b_auto_size )
128     {
129         // Maybe this size should be an option
130         child_size = wxSize( wxSystemSettings::GetMetric(wxSYS_SCREEN_X) / 2,
131                              wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) / 2 );
132
133         SetSize( child_size );
134     }
135
136     p_child_window = new wxWindow( this, -1, wxDefaultPosition, child_size );
137
138     p_child_window->Show();
139     Show();
140     b_shown = VLC_TRUE;
141
142     p_child_window->SetBackgroundColour( *wxBLACK );
143     SetBackgroundColour( *wxBLACK );
144
145     p_intf->p_sys->p_video_sizer = new wxBoxSizer( wxHORIZONTAL );
146     p_intf->p_sys->p_video_sizer->Add( this, 1, wxEXPAND );
147
148     ReleaseWindow( NULL );
149 }
150
151 VideoWindow::~VideoWindow()
152 {
153     vlc_mutex_lock( &lock );
154     if( p_vout )
155     {
156         if( !p_intf->psz_switch_intf )
157         {
158             if( vout_Control( p_vout, VOUT_CLOSE ) != VLC_SUCCESS )
159                 vout_Control( p_vout, VOUT_REPARENT );
160         }
161         else
162         {
163             if( vout_Control( p_vout, VOUT_REPARENT ) != VLC_SUCCESS )
164                 vout_Control( p_vout, VOUT_CLOSE );
165         }
166     }
167
168     p_intf->pf_request_window = NULL;
169     p_intf->pf_release_window = NULL;
170     p_intf->pf_control_window = NULL;
171     vlc_mutex_unlock( &lock );
172
173     vlc_mutex_destroy( &lock );
174 }
175
176 /*****************************************************************************
177  * Private methods.
178  *****************************************************************************/
179 static void *GetWindow( intf_thread_t *p_intf, vout_thread_t *p_vout,
180                         int *pi_x_hint, int *pi_y_hint,
181                         unsigned int *pi_width_hint,
182                         unsigned int *pi_height_hint )
183 {
184     return p_intf->p_sys->p_video_window->GetWindow( p_vout,
185                                                      pi_x_hint, pi_y_hint,
186                                                      pi_width_hint,
187                                                      pi_height_hint );
188 }
189
190 /* Part of the hack to get the X11 window handle from the GtkWidget */
191 #ifdef __WXGTK__
192 extern "C" {
193 #ifdef __WXGTK20__
194     int gdk_x11_drawable_get_xid( void * );
195 #endif
196     void *gtk_widget_get_parent_window( void * );
197 }
198 #endif
199
200 void *VideoWindow::GetWindow( vout_thread_t *_p_vout,
201                               int *pi_x_hint, int *pi_y_hint,
202                               unsigned int *pi_width_hint,
203                               unsigned int *pi_height_hint )
204 {
205 #if defined(__WXGTK__) || defined(WIN32)
206     vlc_mutex_lock( &lock );
207
208     if( p_vout )
209     {
210         vlc_mutex_unlock( &lock );
211         msg_Dbg( p_intf, "Video window already in use" );
212         return NULL;
213     }
214
215     p_vout = _p_vout;
216
217     wxSizeEvent event( wxSize(*pi_width_hint, *pi_height_hint),
218                        UpdateSize_Event );
219     AddPendingEvent( event );
220     vlc_mutex_unlock( &lock );
221
222 #ifdef __WXGTK__
223     GtkWidget *p_widget = p_child_window->GetHandle();
224
225 #ifdef __WXGTK20__
226     return (void *)gdk_x11_drawable_get_xid(
227                gtk_widget_get_parent_window( p_widget ) );
228 #elif defined(__WXGTK__)
229     return (void *)*(int *)( (char *)gtk_widget_get_parent_window( p_widget )
230                + 2 * sizeof(void *) );
231 #endif
232
233 #elif defined(WIN32)
234     return (void*)GetHandle();
235
236 #endif
237
238 #else // defined(__WXGTK__) || defined(WIN32)
239     return NULL;
240
241 #endif
242 }
243
244 static void ReleaseWindow( intf_thread_t *p_intf, void *p_window )
245 {
246     return p_intf->p_sys->p_video_window->ReleaseWindow( p_window );
247 }
248
249 void VideoWindow::ReleaseWindow( void *p_window )
250 {
251     vlc_mutex_lock( &lock );
252     p_vout = NULL;
253     vlc_mutex_unlock( &lock );
254
255     if( !b_auto_size ) return;
256
257 #if defined(__WXGTK__) || defined(WIN32)
258     wxSizeEvent event( wxSize(0, 0), UpdateHide_Event );
259     AddPendingEvent( event );
260 #endif
261 }
262
263 void VideoWindow::UpdateSize( wxEvent &_event )
264 {
265     m_hide_timer.Stop();
266
267     if( !b_auto_size ) return;
268
269     wxSizeEvent * event = (wxSizeEvent*)(&_event);
270     if( !b_shown )
271     {
272         p_intf->p_sys->p_video_sizer->Show( this, TRUE );
273         p_intf->p_sys->p_video_sizer->Layout();
274         SetFocus();
275         b_shown = VLC_TRUE;
276     }
277     p_intf->p_sys->p_video_sizer->SetMinSize( event->GetSize() );
278
279     wxCommandEvent intf_event( wxEVT_INTF, 0 );
280     p_parent->AddPendingEvent( intf_event );
281 }
282
283 void VideoWindow::UpdateHide( wxEvent &_event )
284 {
285     if( b_auto_size) m_hide_timer.Start( 200, wxTIMER_ONE_SHOT );
286 }
287
288 void VideoWindow::OnHideTimer( wxTimerEvent& WXUNUSED(event))
289 {
290     //wxSizeEvent * event = (wxSizeEvent*)(&_event);
291     if( b_shown )
292     {
293         p_intf->p_sys->p_video_sizer->Show( this, FALSE );
294         p_intf->p_sys->p_video_sizer->Layout();
295         b_shown = VLC_FALSE;
296
297         SetSize(0,0);
298         Show();
299     }
300     //ok I cheat here, but is it ever not 0,0?
301     p_intf->p_sys->p_video_sizer->SetMinSize( wxSize(0,0) );
302
303     wxCommandEvent intf_event( wxEVT_INTF, 0 );
304     p_parent->AddPendingEvent( intf_event );
305 }
306
307 void VideoWindow::OnControlEvent( wxCommandEvent &event )
308 {
309     switch( event.GetId() )
310     {
311     case SetStayOnTop_Event:
312         wxCommandEvent intf_event( wxEVT_INTF, 1 );
313         intf_event.SetInt( event.GetInt() );
314         p_parent->AddPendingEvent( intf_event );
315         break;
316     }
317 }
318
319 static int ControlWindow( intf_thread_t *p_intf, void *p_window,
320                           int i_query, va_list args )
321 {
322     return p_intf->p_sys->p_video_window->ControlWindow( p_window, i_query,
323                                                          args );
324 }
325
326 int VideoWindow::ControlWindow( void *p_window, int i_query, va_list args )
327 {
328     int i_ret = VLC_EGENERIC;
329
330     vlc_mutex_lock( &lock );
331
332     switch( i_query )
333     {
334         case VOUT_SET_ZOOM:
335         {
336             if( !b_auto_size ) break;
337
338             double f_arg = va_arg( args, double );
339
340             /* Update dimensions */
341             wxSizeEvent event( wxSize((int)(p_vout->i_window_width * f_arg),
342                                       (int)(p_vout->i_window_height * f_arg)),
343                                UpdateSize_Event );
344
345               
346             AddPendingEvent( event );
347
348             i_ret = VLC_SUCCESS;
349         }
350         break;
351
352         case VOUT_SET_STAY_ON_TOP:
353         {
354             int i_arg = va_arg( args, int );
355             wxCommandEvent event( wxEVT_VLC_VIDEO, SetStayOnTop_Event );
356             event.SetInt( i_arg );
357             AddPendingEvent( event );
358
359             i_ret = VLC_SUCCESS;
360         }
361         break;
362
363         default:
364             msg_Dbg( p_intf, "control query not supported" );
365             break;
366     }
367
368     vlc_mutex_unlock( &lock );
369
370     return i_ret;
371 }