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 *****************************************************************************/
30 #include "vout_manager.hpp"
31 #include "window_manager.hpp"
32 #include "vlcproc.hpp"
33 #include "../commands/async_queue.hpp"
34 #include "../commands/cmd_show_window.hpp"
35 #include "../commands/cmd_resize.hpp"
36 #include "../commands/cmd_voutwindow.hpp"
40 VoutManager *VoutManager::instance( intf_thread_t *pIntf )
42 if( pIntf->p_sys->p_voutManager == NULL )
44 pIntf->p_sys->p_voutManager = new VoutManager( pIntf );
47 return pIntf->p_sys->p_voutManager;
51 void VoutManager::destroy( intf_thread_t *pIntf )
53 delete pIntf->p_sys->p_voutManager;
54 pIntf->p_sys->p_voutManager = NULL;
58 VoutManager::VoutManager( intf_thread_t *pIntf ): SkinObject( pIntf ),
59 m_pVoutMainWindow( NULL ), m_pCtrlVideoVec(),
60 m_pCtrlVideoVecBackup(), m_SavedWndVec()
62 m_pVoutMainWindow = new VoutMainWindow( getIntf() );
66 VoutManager::~VoutManager( )
68 delete m_pVoutMainWindow;
72 void VoutManager::registerCtrlVideo( CtrlVideo* p_CtrlVideo )
74 m_pCtrlVideoVec.push_back( p_CtrlVideo );
78 void VoutManager::saveVoutConfig( )
80 // Save width/height to be consistent across themes
81 // and detach Video Controls
82 vector<SavedWnd>::iterator it;
83 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
85 if( (*it).pCtrlVideo )
87 // detach vout thread from VideoControl
88 (*it).pCtrlVideo->detachVoutWindow( );
90 // memorize width/height before VideoControl is destroyed
91 (*it).width = (*it).pCtrlVideo->getPosition()->getWidth();
92 (*it).height = (*it).pCtrlVideo->getPosition()->getHeight();
93 (*it).pCtrlVideo = NULL;
97 // Create a backup copy and reset original for new theme
98 m_pCtrlVideoVecBackup = m_pCtrlVideoVec;
99 m_pCtrlVideoVec.clear();
103 void VoutManager::restoreVoutConfig( bool b_success )
107 // loading new theme failed, restoring previous theme
108 m_pCtrlVideoVec = m_pCtrlVideoVecBackup;
111 // reattach vout(s) to Video Controls
112 vector<SavedWnd>::iterator it;
113 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
115 CtrlVideo* pCtrlVideo = getBestCtrlVideo();
118 pCtrlVideo->attachVoutWindow( (*it).pVoutWindow );
119 (*it).pCtrlVideo = pCtrlVideo;
125 void VoutManager::discardVout( CtrlVideo* pCtrlVideo )
127 vector<SavedWnd>::iterator it;
128 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
130 if( (*it).pCtrlVideo == pCtrlVideo )
132 // detach vout thread from VideoControl
133 (*it).pCtrlVideo->detachVoutWindow( );
134 (*it).width = (*it).pCtrlVideo->getPosition()->getWidth();
135 (*it).height = (*it).pCtrlVideo->getPosition()->getHeight();
136 (*it).pCtrlVideo = NULL;
143 void VoutManager::requestVout( CtrlVideo* pCtrlVideo )
145 vector<SavedWnd>::iterator it;
146 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
148 if( (*it).pCtrlVideo == NULL )
150 pCtrlVideo->attachVoutWindow( (*it).pVoutWindow,
151 (*it).width, (*it).height );
152 (*it).pCtrlVideo = pCtrlVideo;
159 CtrlVideo* VoutManager::getBestCtrlVideo( )
161 // try to find an unused useable VideoControl
163 vector<CtrlVideo*>::const_iterator it;
164 for( it = m_pCtrlVideoVec.begin(); it != m_pCtrlVideoVec.end(); it++ )
166 if( (*it)->isUseable() && !(*it)->isUsed() )
176 void* VoutManager::acceptWnd( vout_window_t* pWnd )
178 int width = (int)pWnd->cfg->width;
179 int height = (int)pWnd->cfg->height;
181 // Creation of a dedicated Window per vout thread
182 VoutWindow* pVoutWindow = new VoutWindow( getIntf(), pWnd, width, height,
183 (GenericWindow*) m_pVoutMainWindow );
185 void* handle = pVoutWindow->getOSHandle();
187 // try to find a video Control within the theme
188 CtrlVideo* pCtrlVideo = getBestCtrlVideo();
191 // A Video Control is available
192 // directly attach vout thread to it
193 pCtrlVideo->attachVoutWindow( pVoutWindow );
196 // save vout characteristics
197 m_SavedWndVec.push_back( SavedWnd( pWnd, pVoutWindow, pCtrlVideo ) );
199 msg_Dbg( pWnd, "New vout : handle = %p, Ctrl = %p, w x h = %dx%d",
200 handle, pCtrlVideo, width, height );
206 void VoutManager::releaseWnd( vout_window_t *pWnd )
208 // remove vout thread from savedVec
209 vector<SavedWnd>::iterator it;
210 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
212 if( (*it).pWnd == pWnd )
214 msg_Dbg( getIntf(), "vout released vout=%p, VideoCtrl=%p",
215 pWnd, (*it).pCtrlVideo );
217 // if a video control was being used, detach from it
218 if( (*it).pCtrlVideo )
220 (*it).pCtrlVideo->detachVoutWindow( );
224 delete (*it).pVoutWindow;
225 m_SavedWndVec.erase( it );
232 void VoutManager::setSizeWnd( vout_window_t *pWnd, int width, int height )
234 msg_Dbg( pWnd, "setSize (%dx%d) received from vout threadr",
237 vector<SavedWnd>::iterator it;
238 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
240 if( (*it).pWnd == pWnd )
242 VoutWindow* pVoutWindow = (*it).pVoutWindow;
244 pVoutWindow->setOriginalWidth( width );
245 pVoutWindow->setOriginalHeight( height );
247 CtrlVideo* pCtrlVideo = pVoutWindow->getCtrlVideo();
250 pCtrlVideo->resizeControl( width, height );
257 void VoutManager::setFullscreenWnd( vout_window_t *pWnd, bool b_fullscreen )
259 msg_Dbg( pWnd, "setFullscreen (%d) received from vout thread",
260 b_fullscreen ? 1 : 0 );
262 vector<SavedWnd>::iterator it;
263 for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); it++ )
265 if( (*it).pWnd == pWnd )
267 VoutWindow* pVoutWindow = (*it).pVoutWindow;
269 pVoutWindow->setFullscreen( b_fullscreen );
275 // Functions called by window provider
276 // ///////////////////////////////////
278 void *VoutManager::getWindow( intf_thread_t *pIntf, vout_window_t *pWnd )
280 // Theme may have been destroyed
281 if( !pIntf->p_sys->p_theme )
284 vlc_mutex_lock( &pIntf->p_sys->vout_lock );
285 pIntf->p_sys->b_vout_ready = false;
286 pIntf->p_sys->handle = NULL;
288 CmdNewVoutWindow *pCmd =
289 new CmdNewVoutWindow( pIntf, pWnd );
291 AsyncQueue *pQueue = AsyncQueue::instance( pIntf );
292 pQueue->push( CmdGenericPtr( pCmd ), false );
294 while( !pIntf->p_sys->b_vout_ready )
295 vlc_cond_wait( &pIntf->p_sys->vout_wait, &pIntf->p_sys->vout_lock );
297 void* handle = pIntf->p_sys->handle;
298 vlc_mutex_unlock( &pIntf->p_sys->vout_lock );
304 void VoutManager::releaseWindow( intf_thread_t *pIntf, vout_window_t *pWnd )
306 vlc_mutex_lock( &pIntf->p_sys->vout_lock );
307 pIntf->p_sys->b_vout_ready = false;
309 CmdReleaseVoutWindow *pCmd =
310 new CmdReleaseVoutWindow( pIntf, pWnd );
312 AsyncQueue *pQueue = AsyncQueue::instance( pIntf );
313 pQueue->push( CmdGenericPtr( pCmd ), false );
315 while( !pIntf->p_sys->b_vout_ready )
316 vlc_cond_wait( &pIntf->p_sys->vout_wait, &pIntf->p_sys->vout_lock );
318 vlc_mutex_unlock( &pIntf->p_sys->vout_lock );
322 int VoutManager::controlWindow( struct vout_window_t *pWnd,
323 int query, va_list args )
325 intf_thread_t *pIntf = (intf_thread_t *)pWnd->sys;
326 VoutManager *pThis = pIntf->p_sys->p_voutManager;
330 case VOUT_WINDOW_SET_SIZE:
332 unsigned int i_width = va_arg( args, unsigned int );
333 unsigned int i_height = va_arg( args, unsigned int );
335 if( i_width && i_height )
337 // Post a vout resize command
338 CmdResizeVout *pCmd =
339 new CmdResizeVout( pThis->getIntf(),
340 pWnd, (int)i_width, (int)i_height );
342 AsyncQueue::instance( pThis->getIntf() );
343 pQueue->push( CmdGenericPtr( pCmd ) );
348 case VOUT_WINDOW_SET_FULLSCREEN:
350 bool b_fullscreen = va_arg( args, int );
352 // Post a vout resize command
353 CmdSetFullscreen* pCmd =
354 new CmdSetFullscreen( pThis->getIntf(), pWnd, b_fullscreen );
356 AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
357 pQueue->push( CmdGenericPtr( pCmd ) );
363 msg_Dbg( pWnd, "control query not supported" );