1 /*****************************************************************************
2 * vout_manager.cpp
3 *****************************************************************************
4 * Copyright (C) 2009 the VideoLAN team
5 * $Id: e555e5e6f9acae915ce761b166a4bb9490abc490 $
6 *
7 * Authors: Erwan Tulou <brezhoneg1 at yahoo.fr>
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 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include "vout_manager.hpp"
29 #include "vlcproc.hpp"
30 #include "os_factory.hpp"
31
32
33
instance(intf_thread_t * pIntf)34 VoutManager *VoutManager::instance( intf_thread_t *pIntf )
35 {
36 if( pIntf->p_sys->p_voutManager == NULL )
37 {
38 pIntf->p_sys->p_voutManager = new VoutManager( pIntf );
39 }
40
41 return pIntf->p_sys->p_voutManager;
42 }
43
44
destroy(intf_thread_t * pIntf)45 void VoutManager::destroy( intf_thread_t *pIntf )
46 {
47 delete pIntf->p_sys->p_voutManager;
48 pIntf->p_sys->p_voutManager = NULL;
49 }
50
51
VoutManager(intf_thread_t * pIntf)52 VoutManager::VoutManager( intf_thread_t *pIntf ): SkinObject( pIntf ),
53 m_pCtrlVideoVec(), m_pCtrlVideoVecBackup(), m_SavedWndVec(),
54 m_pVoutMainWindow( NULL ), m_pFscWindow( NULL )
55 {
56 m_pVoutMainWindow = new VoutMainWindow( getIntf() );
57
58 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
59 int width = pOsFactory->getScreenWidth();
60 int height = pOsFactory->getScreenHeight();
61
62 m_pVoutMainWindow->move( 0, 0 );
63 m_pVoutMainWindow->resize( width, height );
64
65 VarBool &rFullscreen = VlcProc::instance( getIntf() )->getFullscreenVar();
66 rFullscreen.addObserver( this );
67 }
68
69
~VoutManager()70 VoutManager::~VoutManager( )
71 {
72 VarBool &rFullscreen = VlcProc::instance( getIntf() )->getFullscreenVar();
73 rFullscreen.delObserver( this );
74
75 delete m_pVoutMainWindow;
76 }
77
78
registerCtrlVideo(CtrlVideo * p_CtrlVideo)79 void VoutManager::registerCtrlVideo( CtrlVideo* p_CtrlVideo )
80 {
81 m_pCtrlVideoVec.push_back( p_CtrlVideo );
82 }
83
84
registerFSC(FscWindow * p_Win)85 void VoutManager::registerFSC( FscWindow* p_Win )
86 {
87 m_pFscWindow = p_Win;
88 }
89
90
saveVoutConfig()91 void VoutManager::saveVoutConfig( )
92 {
93 // Save width/height to be consistent across themes
94 // and detach Video Controls
95 std::vector<SavedWnd>::iterator it;
96 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); ++it )
97 {
98 if( it->pCtrlVideo )
99 {
100 // detach vout thread from VideoControl
101 it->pCtrlVideo->detachVoutWindow( );
102
103 // memorize width/height before VideoControl is destroyed
104 it->width = it->pCtrlVideo->getPosition()->getWidth();
105 it->height = it->pCtrlVideo->getPosition()->getHeight();
106 it->pCtrlVideo = NULL;
107 }
108 }
109
110 // Create a backup copy and reset original for new theme
111 m_pCtrlVideoVecBackup = m_pCtrlVideoVec;
112 m_pCtrlVideoVec.clear();
113 }
114
115
restoreVoutConfig(bool b_success)116 void VoutManager::restoreVoutConfig( bool b_success )
117 {
118 if( !b_success )
119 {
120 // loading new theme failed, restoring previous theme
121 m_pCtrlVideoVec = m_pCtrlVideoVecBackup;
122 }
123
124 // reattach vout(s) to Video Controls
125 std::vector<SavedWnd>::iterator it;
126 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); ++it )
127 {
128 CtrlVideo* pCtrlVideo = getBestCtrlVideo();
129 if( pCtrlVideo )
130 {
131 pCtrlVideo->attachVoutWindow( it->pVoutWindow );
132 it->pCtrlVideo = pCtrlVideo;
133 }
134 }
135 }
136
137
discardVout(CtrlVideo * pCtrlVideo)138 void VoutManager::discardVout( CtrlVideo* pCtrlVideo )
139 {
140 std::vector<SavedWnd>::iterator it;
141 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); ++it )
142 {
143 if( it->pCtrlVideo == pCtrlVideo )
144 {
145 // detach vout thread from VideoControl
146 it->pCtrlVideo->detachVoutWindow( );
147 it->width = it->pCtrlVideo->getPosition()->getWidth();
148 it->height = it->pCtrlVideo->getPosition()->getHeight();
149 it->pCtrlVideo = NULL;
150 break;
151 }
152 }
153 }
154
155
requestVout(CtrlVideo * pCtrlVideo)156 void VoutManager::requestVout( CtrlVideo* pCtrlVideo )
157 {
158 std::vector<SavedWnd>::iterator it;
159 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); ++it )
160 {
161 if( it->pCtrlVideo == NULL )
162 {
163 pCtrlVideo->attachVoutWindow( it->pVoutWindow,
164 it->width, it->height );
165 it->pCtrlVideo = pCtrlVideo;
166 break;
167 }
168 }
169 }
170
171
getBestCtrlVideo()172 CtrlVideo* VoutManager::getBestCtrlVideo( )
173 {
174 std::vector<CtrlVideo*>::const_iterator it;
175
176 // first, look up a video control that is visible and unused
177 for( it = m_pCtrlVideoVec.begin(); it != m_pCtrlVideoVec.end(); ++it )
178 {
179 if( (*it)->isUseable() && !(*it)->isUsed() )
180 {
181 return (*it);
182 }
183 }
184
185 return NULL;
186 }
187
188
189
190 // Functions called by window provider
191 // ///////////////////////////////////
192
acceptWnd(vout_window_t * pWnd,int width,int height)193 void VoutManager::acceptWnd( vout_window_t* pWnd, int width, int height )
194 {
195 // Creation of a dedicated Window per vout thread
196 VoutWindow* pVoutWindow = new VoutWindow( getIntf(), pWnd, width, height,
197 (GenericWindow*) m_pVoutMainWindow );
198
199 // try to find a video Control within the theme
200 CtrlVideo* pCtrlVideo = getBestCtrlVideo();
201 if( pCtrlVideo )
202 {
203 // A Video Control is available
204 // directly attach vout thread to it
205 pCtrlVideo->attachVoutWindow( pVoutWindow );
206 }
207 else
208 {
209 pVoutWindow->setCtrlVideo( NULL );
210 }
211
212 // save vout characteristics
213 m_SavedWndVec.push_back( SavedWnd( pWnd, pVoutWindow, pCtrlVideo ) );
214
215 msg_Dbg( pWnd, "New vout : Ctrl = %p, w x h = %ix%i",
216 (void *)pCtrlVideo, width, height );
217 }
218
219
releaseWnd(vout_window_t * pWnd)220 void VoutManager::releaseWnd( vout_window_t* pWnd )
221 {
222 // remove vout thread from savedVec
223 std::vector<SavedWnd>::iterator it;
224 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); ++it )
225 {
226 if( it->pWnd == pWnd )
227 {
228 msg_Dbg( getIntf(), "vout released vout=%p, VideoCtrl=%p",
229 (void *)pWnd, it->pCtrlVideo );
230
231 // if a video control was being used, detach from it
232 if( it->pCtrlVideo )
233 {
234 it->pCtrlVideo->detachVoutWindow( );
235 }
236
237 // remove resources
238 delete it->pVoutWindow;
239 m_SavedWndVec.erase( it );
240 break;
241 }
242 }
243
244 // force fullscreen to false so that user regains control
245 VlcProc::instance( getIntf() )->setFullscreenVar( false );
246 }
247
248
setSizeWnd(vout_window_t * pWnd,int width,int height)249 void VoutManager::setSizeWnd( vout_window_t *pWnd, int width, int height )
250 {
251 msg_Dbg( pWnd, "setSize (%ix%i) received from vout thread",
252 width, height );
253
254 std::vector<SavedWnd>::iterator it;
255 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); ++it )
256 {
257 if( it->pWnd == pWnd )
258 {
259 VoutWindow* pVoutWindow = it->pVoutWindow;
260
261 pVoutWindow->setOriginalWidth( width );
262 pVoutWindow->setOriginalHeight( height );
263
264 CtrlVideo* pCtrlVideo = pVoutWindow->getCtrlVideo();
265 if( pCtrlVideo )
266 {
267 pCtrlVideo->resizeControl( width, height );
268 }
269 break;
270 }
271 }
272 }
273
274
setFullscreenWnd(vout_window_t * pWnd,bool b_fullscreen)275 void VoutManager::setFullscreenWnd( vout_window_t *pWnd, bool b_fullscreen )
276 {
277 msg_Dbg( pWnd, "setFullscreen (%i) received from vout thread",
278 b_fullscreen );
279
280 // reconfigure the fullscreen window (multiple screens)
281 if( b_fullscreen )
282 {
283 std::vector<SavedWnd>::iterator it;
284 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); ++it )
285 {
286 if( it->pWnd == pWnd )
287 {
288 VoutWindow* pVoutWindow = it->pVoutWindow;
289 configureFullscreen( *pVoutWindow );
290 break;
291 }
292 }
293 }
294
295 // set fullscreen
296 VlcProc::instance( getIntf() )->setFullscreenVar( b_fullscreen );
297 }
298
299
hideMouseWnd(vout_window_t * pWnd,bool hide)300 void VoutManager::hideMouseWnd( vout_window_t *pWnd, bool hide )
301 {
302 msg_Dbg( pWnd, "hide mouse (%i) received from vout thread", hide );
303 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
304 if( hide )
305 pOsFactory->changeCursor( OSFactory::kNoCursor );
306 else
307 pOsFactory->changeCursor( OSFactory::kDefaultArrow );
308 }
309
310
onUpdate(Subject<VarBool> & rVariable,void * arg)311 void VoutManager::onUpdate( Subject<VarBool> &rVariable, void *arg )
312 {
313 (void)arg;
314 VarBool &rFullscreen = VlcProc::instance( getIntf() )->getFullscreenVar();
315 if( &rVariable == &rFullscreen )
316 {
317 if( rFullscreen.get() )
318 m_pVoutMainWindow->show();
319 else
320 m_pVoutMainWindow->hide();
321 }
322 }
323
324
configureFullscreen(VoutWindow & rWindow)325 void VoutManager::configureFullscreen( VoutWindow& rWindow )
326 {
327 int numScr = var_InheritInteger( getIntf(), "qt-fullscreen-screennumber" );
328
329 int x, y, w, h;
330 if( numScr >= 0 )
331 {
332 // select screen requested by user
333 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
334 pOsFactory->getMonitorInfo( numScr, &x, &y, &w, &h );
335 }
336 else
337 {
338 // select screen where display is already occurring
339 rWindow.getMonitorInfo( &x, &y, &w, &h );
340 }
341
342 // move and resize fullscreen
343 m_pVoutMainWindow->move( x, y );
344 m_pVoutMainWindow->resize( w, h );
345
346 // ensure the fs controller is also moved
347 if( m_pFscWindow )
348 {
349 m_pFscWindow->moveTo( x, y, w, h );
350 }
351 }
352