1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2009 the VideoLAN team
7 * Authors: Erwan Tulou <brezhoneg1 at yahoo.fr>
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.
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.
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 *****************************************************************************/
29 #include <vlc_vout_display.h>
31 #include "vout_manager.hpp"
32 #include "window_manager.hpp"
33 #include "vlcproc.hpp"
34 #include "../commands/async_queue.hpp"
35 #include "../commands/cmd_show_window.hpp"
36 #include "../commands/cmd_resize.hpp"
37 #include "../commands/cmd_voutwindow.hpp"
38 #include "../commands/cmd_on_top.hpp"
42 VoutManager *VoutManager::instance( intf_thread_t *pIntf )
44 if( pIntf->p_sys->p_voutManager == NULL )
46 pIntf->p_sys->p_voutManager = new VoutManager( pIntf );
49 return pIntf->p_sys->p_voutManager;
53 void VoutManager::destroy( intf_thread_t *pIntf )
55 delete pIntf->p_sys->p_voutManager;
56 pIntf->p_sys->p_voutManager = NULL;
60 VoutManager::VoutManager( intf_thread_t *pIntf ): SkinObject( pIntf ),
61 m_pVoutMainWindow( NULL ), m_pFscWindow( NULL ), m_pCtrlVideoVec(),
62 m_pCtrlVideoVecBackup(), m_SavedWndVec()
64 m_pVoutMainWindow = new VoutMainWindow( getIntf() );
66 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
67 int width = pOsFactory->getScreenWidth();
68 int height = pOsFactory->getScreenHeight();
70 m_pVoutMainWindow->move( 0, 0 );
71 m_pVoutMainWindow->resize( width, height );
75 VoutManager::~VoutManager( )
77 delete m_pVoutMainWindow;
81 void VoutManager::registerCtrlVideo( CtrlVideo* p_CtrlVideo )
83 m_pCtrlVideoVec.push_back( p_CtrlVideo );
87 void VoutManager::registerFSC( TopWindow* p_Win )
91 int x = p_Win->getLeft();
92 int y = p_Win->getTop();
93 p_Win->setParent( m_pVoutMainWindow, x , y, 0, 0 );
97 void VoutManager::saveVoutConfig( )
99 // Save width/height to be consistent across themes
100 // and detach Video Controls
101 vector<SavedWnd>::iterator it;
102 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
104 if( (*it).pCtrlVideo )
106 // detach vout thread from VideoControl
107 (*it).pCtrlVideo->detachVoutWindow( );
109 // memorize width/height before VideoControl is destroyed
110 (*it).width = (*it).pCtrlVideo->getPosition()->getWidth();
111 (*it).height = (*it).pCtrlVideo->getPosition()->getHeight();
112 (*it).pCtrlVideo = NULL;
116 // Create a backup copy and reset original for new theme
117 m_pCtrlVideoVecBackup = m_pCtrlVideoVec;
118 m_pCtrlVideoVec.clear();
122 void VoutManager::restoreVoutConfig( bool b_success )
126 // loading new theme failed, restoring previous theme
127 m_pCtrlVideoVec = m_pCtrlVideoVecBackup;
130 // reattach vout(s) to Video Controls
131 vector<SavedWnd>::iterator it;
132 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
134 CtrlVideo* pCtrlVideo = getBestCtrlVideo();
137 pCtrlVideo->attachVoutWindow( (*it).pVoutWindow );
138 (*it).pCtrlVideo = pCtrlVideo;
144 void VoutManager::discardVout( CtrlVideo* pCtrlVideo )
146 vector<SavedWnd>::iterator it;
147 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
149 if( (*it).pCtrlVideo == pCtrlVideo )
151 // detach vout thread from VideoControl
152 (*it).pCtrlVideo->detachVoutWindow( );
153 (*it).width = (*it).pCtrlVideo->getPosition()->getWidth();
154 (*it).height = (*it).pCtrlVideo->getPosition()->getHeight();
155 (*it).pCtrlVideo = NULL;
162 void VoutManager::requestVout( CtrlVideo* pCtrlVideo )
164 vector<SavedWnd>::iterator it;
165 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
167 if( (*it).pCtrlVideo == NULL )
169 pCtrlVideo->attachVoutWindow( (*it).pVoutWindow,
170 (*it).width, (*it).height );
171 (*it).pCtrlVideo = pCtrlVideo;
178 CtrlVideo* VoutManager::getBestCtrlVideo( )
180 // try to find an unused useable VideoControl
182 vector<CtrlVideo*>::const_iterator it;
183 for( it = m_pCtrlVideoVec.begin(); it != m_pCtrlVideoVec.end(); it++ )
185 if( (*it)->isUseable() && !(*it)->isUsed() )
195 void* VoutManager::acceptWnd( vout_window_t* pWnd )
197 int width = (int)pWnd->cfg->width;
198 int height = (int)pWnd->cfg->height;
200 // Creation of a dedicated Window per vout thread
201 VoutWindow* pVoutWindow = new VoutWindow( getIntf(), pWnd, width, height,
202 (GenericWindow*) m_pVoutMainWindow );
204 void* handle = pVoutWindow->getOSHandle();
206 // try to find a video Control within the theme
207 CtrlVideo* pCtrlVideo = getBestCtrlVideo();
210 // A Video Control is available
211 // directly attach vout thread to it
212 pCtrlVideo->attachVoutWindow( pVoutWindow );
215 // save vout characteristics
216 m_SavedWndVec.push_back( SavedWnd( pWnd, pVoutWindow, pCtrlVideo ) );
218 msg_Dbg( pWnd, "New vout : handle = %p, Ctrl = %p, w x h = %dx%d",
219 handle, pCtrlVideo, width, height );
225 void VoutManager::releaseWnd( vout_window_t *pWnd )
227 // remove vout thread from savedVec
228 vector<SavedWnd>::iterator it;
229 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
231 if( (*it).pWnd == pWnd )
233 msg_Dbg( getIntf(), "vout released vout=%p, VideoCtrl=%p",
234 pWnd, (*it).pCtrlVideo );
236 // if a video control was being used, detach from it
237 if( (*it).pCtrlVideo )
239 (*it).pCtrlVideo->detachVoutWindow( );
243 delete (*it).pVoutWindow;
244 m_SavedWndVec.erase( it );
251 void VoutManager::setSizeWnd( vout_window_t *pWnd, int width, int height )
253 msg_Dbg( pWnd, "setSize (%dx%d) received from vout threadr",
256 vector<SavedWnd>::iterator it;
257 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
259 if( (*it).pWnd == pWnd )
261 VoutWindow* pVoutWindow = (*it).pVoutWindow;
263 pVoutWindow->setOriginalWidth( width );
264 pVoutWindow->setOriginalHeight( height );
266 CtrlVideo* pCtrlVideo = pVoutWindow->getCtrlVideo();
269 pCtrlVideo->resizeControl( width, height );
276 void VoutManager::setFullscreenWnd( vout_window_t *pWnd, bool b_fullscreen )
278 msg_Dbg( pWnd, "setFullscreen (%d) received from vout thread",
279 b_fullscreen ? 1 : 0 );
281 VlcProc::instance( getIntf() )->setFullscreenVar( b_fullscreen );
285 m_pVoutMainWindow->show();
289 m_pVoutMainWindow->hide();
293 // Functions called by window provider
294 // ///////////////////////////////////
296 void *VoutManager::getWindow( intf_thread_t *pIntf, vout_window_t *pWnd )
298 // Theme may have been destroyed
299 if( !pIntf->p_sys->p_theme )
302 vlc_mutex_lock( &pIntf->p_sys->vout_lock );
303 pIntf->p_sys->b_vout_ready = false;
304 pIntf->p_sys->handle = NULL;
306 CmdNewVoutWindow *pCmd =
307 new CmdNewVoutWindow( pIntf, pWnd );
309 AsyncQueue *pQueue = AsyncQueue::instance( pIntf );
310 pQueue->push( CmdGenericPtr( pCmd ), false );
312 while( !pIntf->p_sys->b_vout_ready )
313 vlc_cond_wait( &pIntf->p_sys->vout_wait, &pIntf->p_sys->vout_lock );
315 void* handle = pIntf->p_sys->handle;
316 vlc_mutex_unlock( &pIntf->p_sys->vout_lock );
322 void VoutManager::releaseWindow( intf_thread_t *pIntf, vout_window_t *pWnd )
324 vlc_mutex_lock( &pIntf->p_sys->vout_lock );
325 pIntf->p_sys->b_vout_ready = false;
327 CmdReleaseVoutWindow *pCmd =
328 new CmdReleaseVoutWindow( pIntf, pWnd );
330 AsyncQueue *pQueue = AsyncQueue::instance( pIntf );
331 pQueue->push( CmdGenericPtr( pCmd ), false );
333 while( !pIntf->p_sys->b_vout_ready )
334 vlc_cond_wait( &pIntf->p_sys->vout_wait, &pIntf->p_sys->vout_lock );
336 vlc_mutex_unlock( &pIntf->p_sys->vout_lock );
340 int VoutManager::controlWindow( struct vout_window_t *pWnd,
341 int query, va_list args )
343 intf_thread_t *pIntf = (intf_thread_t *)pWnd->sys;
344 VoutManager *pThis = pIntf->p_sys->p_voutManager;
348 case VOUT_WINDOW_SET_SIZE:
350 unsigned int i_width = va_arg( args, unsigned int );
351 unsigned int i_height = va_arg( args, unsigned int );
353 if( i_width && i_height )
355 // Post a vout resize command
356 CmdResizeVout *pCmd =
357 new CmdResizeVout( pThis->getIntf(),
358 pWnd, (int)i_width, (int)i_height );
360 AsyncQueue::instance( pThis->getIntf() );
361 pQueue->push( CmdGenericPtr( pCmd ) );
366 case VOUT_WINDOW_SET_FULLSCREEN:
368 bool b_fullscreen = va_arg( args, int );
370 // Post a vout resize command
371 CmdSetFullscreen* pCmd =
372 new CmdSetFullscreen( pThis->getIntf(), pWnd, b_fullscreen );
374 AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
375 pQueue->push( CmdGenericPtr( pCmd ) );
380 case VOUT_WINDOW_SET_STATE:
382 unsigned i_arg = va_arg( args, unsigned );
383 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
385 // Post a SetOnTop command
387 new CmdSetOnTop( pThis->getIntf(), on_top );
389 AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
390 pQueue->push( CmdGenericPtr( pCmd ) );
397 msg_Dbg( pWnd, "control query not supported" );