]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/video.cpp
fcf317d60ac7a2c8ff098cd2126292ffa725f5da
[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 };
50
51 class VideoWindow: public wxWindow
52 {
53 public:
54     /* Constructor */
55     VideoWindow( intf_thread_t *_p_intf, wxWindow *p_parent );
56     virtual ~VideoWindow();
57
58     void *GetWindow( vout_thread_t *p_vout, int *, int *,
59                      unsigned int *, unsigned int * );
60     void ReleaseWindow( void * );
61     int  ControlWindow( void *, int, va_list );
62
63 private:
64     intf_thread_t *p_intf;
65     vout_thread_t *p_vout;
66     wxWindow *p_parent;
67     vlc_mutex_t lock;
68
69     wxWindow *p_child_window;
70
71     void UpdateSize( wxSizeEvent & );
72     void UpdateHide( wxSizeEvent & );
73     void OnControlEvent( wxCommandEvent & );
74
75     DECLARE_EVENT_TABLE();
76 };
77
78 DEFINE_LOCAL_EVENT_TYPE( wxEVT_VLC_VIDEO );
79
80 BEGIN_EVENT_TABLE(VideoWindow, wxWindow)
81     EVT_CUSTOM( wxEVT_SIZE, UpdateSize_Event, VideoWindow::UpdateSize )
82     EVT_CUSTOM( wxEVT_SIZE, UpdateHide_Event, VideoWindow::UpdateHide )
83     EVT_COMMAND( SetStayOnTop_Event, wxEVT_VLC_VIDEO,
84                  VideoWindow::OnControlEvent )
85 END_EVENT_TABLE()
86
87 /*****************************************************************************
88  * Public methods.
89  *****************************************************************************/
90 wxWindow *VideoWindow( intf_thread_t *p_intf, wxWindow *p_parent )
91 {
92     return new VideoWindow::VideoWindow( p_intf, p_parent );
93 }
94
95 /*****************************************************************************
96  * Constructor.
97  *****************************************************************************/
98 VideoWindow::VideoWindow( intf_thread_t *_p_intf, wxWindow *_p_parent ):
99     wxWindow( _p_parent, -1 )
100 {
101     /* Initializations */
102     p_intf = _p_intf;
103     p_parent = _p_parent;
104
105     vlc_mutex_init( p_intf, &lock );
106
107     p_vout = NULL;
108
109     p_intf->pf_request_window = ::GetWindow;
110     p_intf->pf_release_window = ::ReleaseWindow;
111     p_intf->pf_control_window = ::ControlWindow;
112
113     p_intf->p_sys->p_video_window = this;
114     p_child_window = new wxWindow( this, -1, wxDefaultPosition, wxSize(0,0) );
115     p_child_window->Show();
116     Show();
117
118     p_intf->p_sys->p_video_sizer = new wxBoxSizer( wxHORIZONTAL );
119     p_intf->p_sys->p_video_sizer->Add( this, 1, wxEXPAND );
120
121     ReleaseWindow( NULL );
122 }
123
124 VideoWindow::~VideoWindow()
125 {
126     vlc_mutex_lock( &lock );
127     if( p_vout )
128     {
129         if( !p_intf->psz_switch_intf )
130         {
131             if( vout_Control( p_vout, VOUT_CLOSE ) != VLC_SUCCESS )
132                 vout_Control( p_vout, VOUT_REPARENT );
133         }
134         else
135         {
136             if( vout_Control( p_vout, VOUT_REPARENT ) != VLC_SUCCESS )
137                 vout_Control( p_vout, VOUT_CLOSE );
138         }
139     }
140
141     p_intf->pf_request_window = NULL;
142     p_intf->pf_release_window = NULL;
143     p_intf->pf_control_window = NULL;
144     vlc_mutex_unlock( &lock );
145
146     vlc_mutex_destroy( &lock );
147 }
148
149 /*****************************************************************************
150  * Private methods.
151  *****************************************************************************/
152 static void *GetWindow( intf_thread_t *p_intf, vout_thread_t *p_vout,
153                         int *pi_x_hint, int *pi_y_hint,
154                         unsigned int *pi_width_hint,
155                         unsigned int *pi_height_hint )
156 {
157     return p_intf->p_sys->p_video_window->GetWindow( p_vout,
158                                                      pi_x_hint, pi_y_hint,
159                                                      pi_width_hint,
160                                                      pi_height_hint );
161 }
162
163 /* Part of the hack to get the X11 window handle from the GtkWidget */
164 #ifdef __WXGTK__
165 extern "C" {
166 #ifdef __WXGTK20__
167     int gdk_x11_drawable_get_xid( void * );
168 #endif
169     void *gtk_widget_get_parent_window( void * );
170 }
171 #endif
172
173 void *VideoWindow::GetWindow( vout_thread_t *_p_vout,
174                               int *pi_x_hint, int *pi_y_hint,
175                               unsigned int *pi_width_hint,
176                               unsigned int *pi_height_hint )
177 {
178 #if defined(__WXGTK__) || defined(WIN32)
179     vlc_mutex_lock( &lock );
180
181     if( p_vout )
182     {
183         vlc_mutex_unlock( &lock );
184         msg_Dbg( p_intf, "Video window already in use" );
185         return NULL;
186     }
187
188     p_vout = _p_vout;
189
190     wxSizeEvent event( wxSize(*pi_width_hint, *pi_height_hint),
191                        UpdateSize_Event );
192     AddPendingEvent( event );
193     vlc_mutex_unlock( &lock );
194
195 #ifdef __WXGTK__
196     GtkWidget *p_widget = p_child_window->GetHandle();
197
198 #ifdef __WXGTK20__
199     return (void *)gdk_x11_drawable_get_xid(
200                gtk_widget_get_parent_window( p_widget ) );
201 #elif defined(__WXGTK__)
202     return (void *)*(int *)( (char *)gtk_widget_get_parent_window( p_widget )
203                + 2 * sizeof(void *) );
204 #endif
205
206 #elif defined(WIN32)
207     return (void*)GetHandle();
208
209 #endif
210
211 #else // defined(__WXGTK__) || defined(WIN32)
212     return NULL;
213
214 #endif
215 }
216
217 static void ReleaseWindow( intf_thread_t *p_intf, void *p_window )
218 {
219     return p_intf->p_sys->p_video_window->ReleaseWindow( p_window );
220 }
221
222 void VideoWindow::ReleaseWindow( void *p_window )
223 {
224     vlc_mutex_lock( &lock );
225
226     p_vout = NULL;
227
228 #if defined(__WXGTK__) || defined(WIN32)
229     wxSizeEvent event( wxSize(0, 0), UpdateHide_Event );
230     AddPendingEvent( event );
231 #endif
232
233     vlc_mutex_unlock( &lock );
234 }
235
236 void VideoWindow::UpdateSize( wxSizeEvent &event )
237 {
238     if( !IsShown() )
239     {
240         p_intf->p_sys->p_video_sizer->Show( this, TRUE );
241         p_intf->p_sys->p_video_sizer->Layout();
242         SetFocus();
243     }
244     p_intf->p_sys->p_video_sizer->SetMinSize( event.GetSize() );
245
246     wxCommandEvent intf_event( wxEVT_INTF, 0 );
247     p_parent->AddPendingEvent( intf_event );
248 }
249
250 void VideoWindow::UpdateHide( wxSizeEvent &event )
251 {
252     if( IsShown() )
253     {
254         p_intf->p_sys->p_video_sizer->Show( this, FALSE );
255         p_intf->p_sys->p_video_sizer->Layout();
256     }
257     p_intf->p_sys->p_video_sizer->SetMinSize( event.GetSize() );
258
259     wxCommandEvent intf_event( wxEVT_INTF, 0 );
260     p_parent->AddPendingEvent( intf_event );
261 }
262
263 void VideoWindow::OnControlEvent( wxCommandEvent &event )
264 {
265     switch( event.GetId() )
266     {
267     case SetStayOnTop_Event:
268         wxCommandEvent intf_event( wxEVT_INTF, 1 );
269         intf_event.SetInt( event.GetInt() );
270         p_parent->AddPendingEvent( intf_event );
271         break;
272     }
273 }
274
275 static int ControlWindow( intf_thread_t *p_intf, void *p_window,
276                           int i_query, va_list args )
277 {
278     return p_intf->p_sys->p_video_window->ControlWindow( p_window, i_query,
279                                                          args );
280 }
281
282 int VideoWindow::ControlWindow( void *p_window, int i_query, va_list args )
283 {
284     int i_ret = VLC_EGENERIC;
285
286     vlc_mutex_lock( &lock );
287
288     switch( i_query )
289     {
290         case VOUT_SET_ZOOM:
291         {
292             double f_arg = va_arg( args, double );
293
294             /* Update dimensions */
295             wxSizeEvent event( wxSize(p_vout->i_window_width * f_arg,
296                                       p_vout->i_window_height * f_arg),
297                                UpdateSize_Event );
298             AddPendingEvent( event );
299
300             i_ret = VLC_SUCCESS;
301         }
302         break;
303
304         case VOUT_SET_STAY_ON_TOP:
305         {
306             int i_arg = va_arg( args, int );
307             wxCommandEvent event( wxEVT_VLC_VIDEO, SetStayOnTop_Event );
308             event.SetInt( i_arg );
309             AddPendingEvent( event );
310
311             i_ret = VLC_SUCCESS;
312         }
313         break;
314
315         default:
316             msg_Dbg( p_intf, "control query not supported" );
317             break;
318     }
319
320     vlc_mutex_unlock( &lock );
321
322     return i_ret;
323 }