]> git.sesse.net Git - vlc/commitdiff
skins2 vout manager
authorErwan Tulou <brezhoneg1@yahoo.fr>
Sat, 14 Mar 2009 23:10:49 +0000 (00:10 +0100)
committerRémi Denis-Courmont <remi@remlab.net>
Mon, 16 Mar 2009 20:09:45 +0000 (22:09 +0200)
Signed-off-by: Rémi Denis-Courmont <remi@remlab.net>
28 files changed:
modules/gui/skins2/Modules.am
modules/gui/skins2/commands/cmd_change_skin.cpp
modules/gui/skins2/commands/cmd_resize.cpp
modules/gui/skins2/commands/cmd_resize.hpp
modules/gui/skins2/controls/ctrl_generic.hpp
modules/gui/skins2/controls/ctrl_video.cpp
modules/gui/skins2/controls/ctrl_video.hpp
modules/gui/skins2/src/generic_layout.cpp
modules/gui/skins2/src/generic_layout.hpp
modules/gui/skins2/src/generic_window.cpp
modules/gui/skins2/src/generic_window.hpp
modules/gui/skins2/src/os_window.hpp
modules/gui/skins2/src/skin_common.hpp
modules/gui/skins2/src/skin_main.cpp
modules/gui/skins2/src/theme_loader.cpp
modules/gui/skins2/src/vlcproc.cpp
modules/gui/skins2/src/vlcproc.hpp
modules/gui/skins2/src/vout_manager.cpp [new file with mode: 0644]
modules/gui/skins2/src/vout_manager.hpp [new file with mode: 0644]
modules/gui/skins2/src/vout_window.cpp
modules/gui/skins2/src/vout_window.hpp
modules/gui/skins2/src/window_manager.cpp
modules/gui/skins2/win32/win32_window.cpp
modules/gui/skins2/win32/win32_window.hpp
modules/gui/skins2/x11/x11_factory.cpp
modules/gui/skins2/x11/x11_loop.cpp
modules/gui/skins2/x11/x11_window.cpp
modules/gui/skins2/x11/x11_window.hpp

index b975e1a13a07db32c903003d7adbaec8d6958cb0..fc8a6c2bdaa7803126ed033568237d3e3c4e5967 100644 (file)
@@ -151,6 +151,8 @@ SOURCES_skins2 = \
        src/vlcproc.hpp \
        src/vout_window.cpp \
        src/vout_window.hpp \
+       src/vout_manager.cpp \
+       src/vout_manager.hpp \
        src/window_manager.cpp \
        src/window_manager.hpp \
        \
index ce31e23df6b0ab818618e00a3c978a224bbe451c..27d28d58cbe898ece88886a960eba7a5de741b76 100644 (file)
@@ -29,6 +29,8 @@
 #include "../src/theme.hpp"
 #include "../src/theme_loader.hpp"
 #include "../src/window_manager.hpp"
+#include "../src/vout_manager.hpp"
+#include "../src/vlcproc.hpp"
 
 
 void CmdChangeSkin::execute()
@@ -42,6 +44,9 @@ void CmdChangeSkin::execute()
         pOldTheme->getWindowManager().hideAll();
     }
 
+    VoutManager::instance( getIntf() )->lockVout();
+    VoutManager::instance( getIntf() )->saveVoutConfig();
+
     ThemeLoader loader( getIntf() );
     if( loader.load( m_file ) )
     {
@@ -49,16 +54,23 @@ void CmdChangeSkin::execute()
         msg_Info( getIntf(), "new theme successfully loaded (%s)",
                  m_file.c_str() );
         delete pOldTheme;
+
+        // restore vout config
+        VoutManager::instance( getIntf() )->restoreVoutConfig( true );
+        VoutManager::instance( getIntf() )->unlockVout();
     }
     else if( pOldTheme )
     {
         msg_Warn( getIntf(), "a problem occurred when loading the new theme,"
                   " restoring the previous one" );
         getIntf()->p_sys->p_theme = pOldTheme;
+        VoutManager::instance( getIntf() )->restoreVoutConfig( false );
+        VoutManager::instance( getIntf() )->unlockVout();
         pOldTheme->getWindowManager().restoreVisibility();
     }
     else
     {
+        VoutManager::instance( getIntf() )->unlockVout();
         msg_Err( getIntf(), "cannot load the theme, aborting" );
         // Quit
         CmdQuit cmd( getIntf() );
index ea3e4bc66fbd7ebccd914bc4bd85ef959bc52b88..5a768daf8b1a7da363c1d528304b21692964725b 100644 (file)
@@ -26,6 +26,9 @@
 #include "../src/generic_layout.hpp"
 #include "../src/window_manager.hpp"
 #include "../src/vlcproc.hpp"
+#include "../src/vout_window.hpp"
+#include "../controls/ctrl_video.hpp"
+#include <vlc_vout.h>
 
 
 CmdResize::CmdResize( intf_thread_t *pIntf, const WindowManager &rWindowManager,
@@ -57,3 +60,16 @@ void CmdResizeVout::execute()
     rVoutSize.setSize( m_width, m_height );
 }
 
+
+CmdResizeInnerVout::CmdResizeInnerVout( intf_thread_t *pIntf,
+                    CtrlVideo* pCtrlVideo )
+         : CmdGeneric( pIntf ), m_pCtrlVideo( pCtrlVideo )
+{
+}
+
+
+void CmdResizeInnerVout::execute()
+{
+    m_pCtrlVideo->resizeInnerVout();
+}
+
index c554c1800fe2241775cd1451f0604d6e7cd9be83..3233dd3eacaba29afc1952ef9226da609ed588e5 100644 (file)
 #define CMD_RESIZE_HPP
 
 #include "cmd_generic.hpp"
+#include <vlc_vout.h>
 
 class WindowManager;
 class GenericLayout;
+class CtrlVideo;
+class VoutWindow;
 
 
 /// Command to resize a layout
@@ -74,4 +77,22 @@ class CmdResizeVout: public CmdGeneric
 };
 
 
+/// Command to resize the inner vout window
+class CmdResizeInnerVout: public CmdGeneric
+{
+    public:
+        /// Resize the given layout
+        CmdResizeInnerVout( intf_thread_t *pIntf, CtrlVideo* pCtrlVideo );
+        virtual ~CmdResizeInnerVout() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "resize inner vout"; }
+
+    private:
+        CtrlVideo* m_pCtrlVideo;
+};
+
 #endif
index 7ab7ea459392575c93f9dd7edadb4c294189b983..d0ed05da85ca8ef0f68bfd1e4ff842f530b63ca2 100644 (file)
@@ -125,18 +125,21 @@ class CtrlGeneric: public SkinObject, public Observer<VarBool>
         /// Overload this method to get notified of bool variable changes
         virtual void onVarBoolUpdate( VarBool &rVar ) {}
 
-    private:
+        /// Method called when an observed bool variable is changed
+        virtual void onUpdate( Subject<VarBool> &rVariable , void* );
+
         /// Associated layout
         GenericLayout *m_pLayout;
+
+        /// Visibility variable
+        VarBool *m_pVisible;
+
+    private:
         /// Position in the layout
         Position *m_pPosition;
         /// Help text
         UString m_help;
-        /// Visibilty variable
-        VarBool *m_pVisible;
 
-        /// Method called when an observed bool variable is changed
-        virtual void onUpdate( Subject<VarBool> &rVariable , void* );
 };
 
 typedef CountedPtr<CtrlGeneric> CtrlGenericPtr;
index 424a314c61635a90e43967649f73ad510a42264f..16c8e48ab7fa7c52784496678893b492347ea463 100644 (file)
@@ -26,6 +26,7 @@
 #include "../src/vout_window.hpp"
 #include "../src/os_graphics.hpp"
 #include "../src/vlcproc.hpp"
+#include "../src/vout_manager.hpp"
 #include "../src/window_manager.hpp"
 #include "../commands/async_queue.hpp"
 #include "../commands/cmd_resize.hpp"
 CtrlVideo::CtrlVideo( intf_thread_t *pIntf, GenericLayout &rLayout,
                       bool autoResize, const UString &rHelp,
                       VarBool *pVisible ):
-    CtrlGeneric( pIntf, rHelp, pVisible ), m_pVout( NULL ),
-    m_rLayout( rLayout ), m_xShift( 0 ), m_yShift( 0 )
+    CtrlGeneric( pIntf, rHelp, pVisible ), m_rLayout( rLayout ),
+    m_xShift( 0 ), m_yShift( 0 ), m_bAutoResize( autoResize ),
+    m_pVoutWindow( NULL ), m_bIsUseable( false )
 {
     // Observe the vout size variable if the control is auto-resizable
-    if( autoResize )
+    if( m_bAutoResize )
     {
         VarBox &rVoutSize = VlcProc::instance( pIntf )->getVoutSizeVar();
         rVoutSize.addObserver( this );
     }
+
+    // observe visibility variable
+    if( m_pVisible )
+        m_pVisible->addObserver( this );
 }
 
 
@@ -51,7 +57,10 @@ CtrlVideo::~CtrlVideo()
     VarBox &rVoutSize = VlcProc::instance( getIntf() )->getVoutSizeVar();
     rVoutSize.delObserver( this );
 
-    delete m_pVout;
+    //m_pLayout->getActiveVar().delObserver( this );
+
+    if( m_pVisible )
+        m_pVisible->delObserver( this );
 }
 
 
@@ -69,10 +78,10 @@ bool CtrlVideo::mouseOver( int x, int y ) const
 void CtrlVideo::onResize()
 {
     const Position *pPos = getPosition();
-    if( pPos && m_pVout )
+    if( pPos && m_pVoutWindow )
     {
-        m_pVout->move( pPos->getLeft(), pPos->getTop() );
-        m_pVout->resize( pPos->getWidth(), pPos->getHeight() );
+        m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
+        m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
     }
 }
 
@@ -98,10 +107,26 @@ void CtrlVideo::draw( OSGraphics &rImage, int xDest, int yDest )
 }
 
 
-void CtrlVideo::onUpdate( Subject<VarBox> &rVoutSize, void *arg )
+void CtrlVideo::setLayout( GenericLayout *pLayout,
+                           const Position &rPosition )
 {
-    int newWidth = ((VarBox&)rVoutSize).getWidth() + m_xShift;
-    int newHeight = ((VarBox&)rVoutSize).getHeight() + m_yShift;
+    CtrlGeneric::setLayout( pLayout, rPosition );
+    m_pLayout->getActiveVar().addObserver( this );
+
+    m_bIsUseable = isVisible() && m_pLayout->getActiveVar().get();
+
+    // register Video Control
+    VoutManager::instance( getIntf() )->registerCtrlVideo( this );
+
+    msg_Dbg( getIntf(),"New VideoControl detected(%x), useability=%s",
+                           this, m_bIsUseable ? "true" : "false" );
+}
+
+
+void CtrlVideo::resizeControl( int width, int height )
+{
+    int newWidth = width + m_xShift;
+    int newHeight = height + m_yShift;
 
     // Create a resize command
     // FIXME: this way of getting the window manager kind of sucks
@@ -112,32 +137,101 @@ void CtrlVideo::onUpdate( Subject<VarBox> &rVoutSize, void *arg )
                                       m_rLayout, newWidth, newHeight );
     // Push the command in the asynchronous command queue
     AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
-    pQueue->push( CmdGenericPtr( pCmd ) );
+    pQueue->push( CmdGenericPtr( pCmd ), false );
 
     // FIXME: this should be a command too
     rWindowManager.stopResize();
+
+    pCmd = new CmdResizeInnerVout( getIntf(), this );
+    pQueue->push( CmdGenericPtr( pCmd ), false );
+
+    TopWindow* pWin = getWindow();
+    rWindowManager.show( *pWin );
 }
 
 
-void CtrlVideo::setVisible( bool visible )
+void CtrlVideo::onUpdate( Subject<VarBox> &rVoutSize, void *arg )
 {
-    if( visible )
+    int newWidth = ((VarBox&)rVoutSize).getWidth() + m_xShift;
+    int newHeight = ((VarBox&)rVoutSize).getHeight() + m_yShift;
+
+    resizeControl( newWidth, newHeight );
+}
+
+
+void CtrlVideo::onUpdate( Subject<VarBool> &rVariable, void *arg  )
+{
+    // Visibility changed
+    if( &rVariable == m_pVisible )
+    {
+        msg_Dbg( getIntf(), "VideoCtrl : Visibility changed (visible=%d)",
+                                  isVisible() );
+    }
+
+    // Active Layout changed
+    if( &rVariable == &m_pLayout->getActiveVar() )
+    {
+        msg_Dbg( getIntf(), "VideoCtrl : Active Layout changed (isActive=%d)",
+                      m_pLayout->getActiveVar().get() );
+    }
+
+    m_bIsUseable = isVisible() && m_pLayout->getActiveVar().get();
+
+    if( m_bIsUseable && !isUsed() )
+    {
+        VoutManager::instance( getIntf() )->requestVout( this );
+    }
+    else if( !m_bIsUseable && isUsed() )
     {
-        GenericWindow *pParent = getWindow();
-        const Position *pPos = getPosition();
-        // Create a child window for the vout if it doesn't exist yet
-        if( !m_pVout && pParent && pPos )
-        {
-            m_pVout = new VoutWindow( getIntf(), pPos->getLeft(),
-                                      pPos->getTop(), false, false, *pParent );
-            m_pVout->resize( pPos->getWidth(), pPos->getHeight() );
-            m_pVout->show();
-        }
+        VoutManager::instance( getIntf() )->discardVout( this );
     }
-    else
+}
+
+void CtrlVideo::attachVoutWindow( VoutWindow* pVoutWindow )
+{
+    int width = pVoutWindow->getOriginalWidth();
+    int height = pVoutWindow->getOriginalHeight();
+
+    WindowManager &rWindowManager =
+        getIntf()->p_sys->p_theme->getWindowManager();
+    TopWindow* pWin = getWindow();
+    rWindowManager.show( *pWin );
+
+    if( m_bAutoResize && width && height )
     {
-        delete m_pVout;
-        m_pVout = NULL;
+        int newWidth = width + m_xShift;
+        int newHeight = height + m_yShift;
+
+        rWindowManager.startResize( m_rLayout, WindowManager::kResizeSE );
+        rWindowManager.resize( m_rLayout, newWidth, newHeight );
+        rWindowManager.stopResize();
     }
+
+    pVoutWindow->setCtrlVideo( this );
+
+    m_pVoutWindow = pVoutWindow;
+}
+
+
+void CtrlVideo::detachVoutWindow( )
+{
+    m_pVoutWindow->setCtrlVideo( NULL );
+    m_pVoutWindow = NULL;
+}
+
+
+void CtrlVideo::resizeInnerVout( )
+{
+    WindowManager &rWindowManager =
+         getIntf()->p_sys->p_theme->getWindowManager();
+    TopWindow* pWin = getWindow();
+
+    const Position *pPos = getPosition();
+
+    m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
+    m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
+
+    rWindowManager.show( *pWin );
+    m_pVoutWindow->show();
 }
 
index 7869bd1e263efd3dc6fb00f146b8549ecb232da3..d7b67d5706b94665dee3e612ef656751b769fa59 100644 (file)
@@ -26,8 +26,9 @@
 
 #include "ctrl_generic.hpp"
 #include "../utils/position.hpp"
+#include "../src/vout_window.hpp"
+#include <vlc_vout.h>
 
-class VoutWindow;
 
 /// Control video
 class CtrlVideo: public CtrlGeneric, public Observer<VarBox>
@@ -58,16 +59,52 @@ class CtrlVideo: public CtrlGeneric, public Observer<VarBox>
         /// Method called when the vout size is updated
         virtual void onUpdate( Subject<VarBox> &rVoutSize, void* );
 
-        /// Called by the layout when the control is show/hidden
-        void setVisible( bool visible );
+        /// Method called when visibility or ActiveLayout is updated
+        virtual void onUpdate( Subject<VarBool> &rVariable , void* );
+
+        // Attach a voutWindow to a Video Control
+        void attachVoutWindow( VoutWindow* pVoutWindow );
+
+        // Detach a voutWindow from a Video Control
+        void detachVoutWindow( );
+
+        // Update the inner part of the Video Control
+        void resizeInnerVout( );
+
+        // Get TopWindow associated with the video control
+        virtual TopWindow* getWindow() { return CtrlGeneric::getWindow(); }
+
+        // Get the VoutWindow associated with the video control
+        virtual VoutWindow* getVoutWindow() { return m_pVoutWindow; }
+
+        /// Set the position and the associated layout of the control
+        virtual void setLayout( GenericLayout *pLayout,
+                                const Position &rPosition );
+
+        // resize the video Control
+        virtual void resizeControl( int width, int height );
+
+        // Is this control useable (visibility requirements)
+        virtual bool isUseable() { return m_bIsUseable; }
+
+        // Is this control used
+        virtual bool isUsed() { return m_pVoutWindow ? true : false; }
 
     private:
-        /// Vout window
-        VoutWindow *m_pVout;
         /// Associated layout
         GenericLayout &m_rLayout;
+
+        /// Autoresize parameter
+        bool m_bAutoResize;
+
         /// Difference between layout size and video size
         int m_xShift, m_yShift;
+
+        /// Is the video Control useable
+        bool m_bIsUseable;
+
+        /// Vout window
+        VoutWindow *m_pVoutWindow;
 };
 
 #endif
index 3b8e65e56676fb67aa2e61c0ae964009b40d89a5..dbc3cf67f56127efe61287e9449ecf353a01d099 100644 (file)
@@ -31,6 +31,7 @@
 #include "../controls/ctrl_generic.hpp"
 #include "../controls/ctrl_video.hpp"
 #include "../utils/var_bool.hpp"
+#include <set>
 
 
 GenericLayout::GenericLayout( intf_thread_t *pIntf, int width, int height,
@@ -38,7 +39,7 @@ GenericLayout::GenericLayout( intf_thread_t *pIntf, int width, int height,
                               int maxHeight ):
     SkinObject( pIntf ), m_pWindow( NULL ), m_rect( 0, 0, width, height ),
     m_minWidth( minWidth ), m_maxWidth( maxWidth ),
-    m_minHeight( minHeight ), m_maxHeight( maxHeight ), m_pVideoControl( NULL ),
+    m_minHeight( minHeight ), m_maxHeight( maxHeight ), m_pVideoCtrlSet(),
     m_visible( false ), m_pVarActive( NULL )
 {
     // Get the OSFactory
@@ -122,7 +123,7 @@ void GenericLayout::addControl( CtrlGeneric *pControl,
         // Check if it is a video control
         if( pControl->getType() == "video" )
         {
-            m_pVideoControl = (CtrlVideo*)pControl;
+            m_pVideoCtrlSet.insert( (CtrlVideo*)pControl );
         }
     }
     else
@@ -233,38 +234,126 @@ void GenericLayout::refreshRect( int x, int y, int width, int height )
             height = m_rect.getHeight() - y;
 
         // Refresh the window... but do not paint on a visible video control!
-        if( !m_pVideoControl || !m_pVideoControl->isVisible() )
+        if( !m_pVideoCtrlSet.size() )
         {
             // No video control, we can safely repaint the rectangle
             pWindow->refresh( x, y, width, height );
         }
         else
         {
-            // Bad luck, there is a video control somewhere (not necessarily
-            // in the repainting zone, btw).
-            // We will divide the repainting into 4 regions (top, left, bottom
-            // and right). The overlapping parts (i.e. the corners) of these
-            // regions will be painted twice, because otherwise the algorithm
-            // becomes a real mess :)
-
-            // Use short variable names for convenience
-            int xx = m_pVideoControl->getPosition()->getLeft();
-            int yy = m_pVideoControl->getPosition()->getTop();
-            int ww = m_pVideoControl->getPosition()->getWidth();
-            int hh = m_pVideoControl->getPosition()->getHeight();
-
-            // Top part:
-            if( y < yy )
-                pWindow->refresh( x, y, width, yy - y );
-            // Left part:
-            if( x < xx )
-                pWindow->refresh( x, y, xx - x, height );
-            // Bottom part
-            if( y + height > yy + hh )
-                pWindow->refresh( x, yy + hh, width, y + height - (yy + hh) );
-            // Right part
-            if( x + width > xx + ww )
-                pWindow->refresh( xx + ww, y, x + width - (xx + ww), height );
+            // video control(s) present, we need more calculations
+            computeRefresh( x, y, width, height );
+        }
+    }
+}
+
+class rect
+{
+public:
+  rect( int v_x = 0, int v_y = 0,
+          int v_width = 0, int v_height = 0 )
+     : x( v_x), y( v_y ), width( v_width), height( v_height)
+    {}
+    ~rect(){}
+    int x;
+    int y;
+    int width;
+    int height;
+
+    static bool isIncluded( rect& rect2, rect& rect1 )
+    {
+        int x1 = rect1.x;
+        int y1 = rect1.y;
+        int w1 = rect1.width;
+        int h1 = rect1.height;
+
+        int x2 = rect2.x;
+        int y2 = rect2.y;
+        int w2 = rect2.width;
+        int h2 = rect2.height;
+
+        return  x2 >= x1 && x2 < x1 + w1
+            &&  y2 >= y1 && y2 < y1 + h1
+            &&  w2 <= w1
+            &&  h2 <= h1;
+    }
+};
+
+void GenericLayout::computeRefresh( int x, int y, int width, int height )
+{
+    int w = width;
+    int h = height;
+    TopWindow *pWindow = getWindow();
+
+    set<int> x_set;
+    set<int> y_set;
+    vector<rect> rect_set;
+
+    x_set.insert( x + w );
+    y_set.insert( y + h );
+
+    // retrieve video controls being used
+    // and remember their rectangles
+    set<CtrlVideo*>::const_iterator it;
+    for( it = m_pVideoCtrlSet.begin(); it != m_pVideoCtrlSet.end(); it++ )
+    {
+        if( (*it)->isUsed() )
+        {
+            int xx = (*it)->getPosition()->getLeft();
+            int yy = (*it)->getPosition()->getTop();
+            int ww = (*it)->getPosition()->getWidth();
+            int hh = (*it)->getPosition()->getHeight();
+
+            rect r(xx, yy, ww, hh );
+            rect_set.push_back( r );
+
+            if( xx > x && xx < x + w )
+                x_set.insert( xx );
+            if( xx + ww > x && xx + ww < x + w )
+                x_set.insert( xx + ww );
+            if( yy > y && yy < y + h )
+                y_set.insert( yy );
+            if( yy + hh > y && yy + hh < y + h )
+                y_set.insert( yy + hh );
+        }
+    }
+
+    // for each subregion, test whether they are part
+    // of the video control(s) or not
+    set<int>::const_iterator it_x;
+    set<int>::const_iterator it_y;
+    int x_prev, y_prev;
+
+    for( x_prev = x, it_x = x_set.begin();
+         it_x != x_set.end(); x_prev = *it_x, it_x++ )
+    {
+        int x0 = x_prev;
+        int w0 = *it_x - x_prev;
+
+        for( y_prev = y, it_y = y_set.begin();
+             it_y != y_set.end(); y_prev = *it_y, it_y++ )
+        {
+            int y0 = y_prev;
+            int h0 = *it_y - y_prev;
+
+            rect r( x0, y0, w0, h0 );
+            bool b_refresh = true;
+
+            vector<rect>::iterator it;
+            for( it = rect_set.begin(); it != rect_set.end(); it++ )
+            {
+                rect r_ctrl = *it;
+                if( rect::isIncluded( r, r_ctrl ) )
+                {
+                    b_refresh = false;
+                    break;
+                }
+            }
+
+            // subregion is not part of a video control
+            // needs to be refreshed
+            if( b_refresh )
+                pWindow->refresh( x0, y0, w0 ,h0 );
         }
     }
 }
@@ -287,22 +376,11 @@ void GenericLayout::onShow()
     m_visible = true;
 
     refreshAll();
-    // TODO find a better way to handle the vout ?
-    if( m_pVideoControl )
-    {
-        m_pVideoControl->setVisible( true );
-    }
 }
 
 
 void GenericLayout::onHide()
 {
     m_visible = false;
-
-    // TODO find a better way to handle the vout ?
-    if( m_pVideoControl )
-    {
-        m_pVideoControl->setVisible( false );
-    }
 }
 
index 7574f1fc087ca01f9e4fd5cd2bd05d8fbbcf4719..9e6871af221a9222a654fd038d369b4503cb9ab9 100644 (file)
@@ -105,6 +105,9 @@ class GenericLayout: public SkinObject
         virtual int getMinHeight() const { return m_minHeight; }
         virtual int getMaxHeight() const { return m_maxHeight; }
 
+        /// specific refresh window (if video controls)
+        virtual void computeRefresh( int x, int y, int width, int height );
+
         /// Resize the layout
         virtual void resize( int width, int height );
 
@@ -156,8 +159,8 @@ class GenericLayout: public SkinObject
         OSGraphics *m_pImage;
         /// List of the controls in the layout
         list<LayeredControl> m_controlList;
-        /// Video control
-        CtrlVideo *m_pVideoControl;
+        /// Video control(s)
+        set<CtrlVideo *> m_pVideoCtrlSet;
         /// List of the anchors in the layout
         list<Anchor*> m_anchorList;
         /// Flag to know if the layout is visible
index e96f8328cb3866eea6390c0c2ea84f4819aef9fc..cbad909af458d7a4e5ee652cb35cfe19d7e0d948 100644 (file)
@@ -98,6 +98,10 @@ void GenericWindow::move( int left, int top )
 
 void GenericWindow::resize( int width, int height )
 {
+    // don't try when value is 0 (may crash)
+    if( !width || ! height )
+        return;
+
     // Update the window size
     m_width = width;
     m_height = height;
@@ -157,3 +161,15 @@ void GenericWindow::innerHide()
     }
 }
 
+
+void* GenericWindow::getOSHandle() const
+{
+    return m_pOsWindow->getOSHandle();
+}
+
+
+void GenericWindow::setParent( GenericWindow* pParent, int x, int y, int w, int h )
+{
+    void* handle = pParent ? pParent->getOSHandle() : NULL;
+    m_pOsWindow->reparent( handle, x, y, w, h );
+}
index f3c5bfece01e6b56bb9f1e72d60277cecb1732e2..e75b733b7fda3ab91e12375263596ea5d900be59 100644 (file)
@@ -46,6 +46,8 @@ class GenericWindow: public SkinObject, public Observer<VarBool>
 {
     private:
         friend class WindowManager;
+        friend class VoutManager;
+        friend class CtrlVideo;
     public:
         GenericWindow( intf_thread_t *pIntf, int xPos, int yPos,
                        bool dragDrop, bool playOnDrop,
@@ -81,6 +83,12 @@ class GenericWindow: public SkinObject, public Observer<VarBool>
         /// Window type, mainly useful when overloaded (for VoutWindow)
         virtual string getType() const { return "Generic"; }
 
+        /// windows handle
+        void* getOSHandle() const;
+
+        /// reparent
+        void setParent( GenericWindow* pParent, int x, int y, int w, int h );
+
     protected:
         /// Get the OS window
         OSWindow *getOSWindow() const { return m_pOsWindow; }
index 439f206498163251212f2fbe19c6aa24be6a7d1a..f756afb300715dcabd3452711f37a134cd7f4e43 100644 (file)
@@ -56,6 +56,12 @@ class OSWindow: public SkinObject
         /// Toggle the window on top
         virtual void toggleOnTop( bool onTop ) const = 0;
 
+        /// getter for handler
+        virtual void* getOSHandle( ) const = 0;
+
+        /// reparent the window
+        virtual void reparent( void* OSHandle, int x, int y, int w, int h ) = 0;
+
     protected:
         OSWindow( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
 };
index ff169f9868e97ee0d7df9fc1fe96b43526200b92..684deaf532f5ce270999e6cdb1ba21e73f9873ec 100644 (file)
@@ -44,6 +44,7 @@ class OSFactory;
 class OSLoop;
 class VarManager;
 class VlcProc;
+class VoutManager;
 class Theme;
 class ThemeRepository;
 
@@ -132,6 +133,8 @@ struct intf_sys_t
     VarManager *p_varManager;
     /// VLC state handler
     VlcProc *p_vlcProc;
+    /// Vout manager
+    VoutManager *p_voutManager;
     /// Theme repository
     ThemeRepository *p_repository;
 
index 9590e777603cd16181fe30095db93aa96ce4a533..af25cb4b5442e4033f389a3bba30f1e5cda1531d 100644 (file)
@@ -42,6 +42,8 @@
 #include "theme_loader.hpp"
 #include "theme.hpp"
 #include "theme_repository.hpp"
+#include "vout_window.hpp"
+#include "vout_manager.hpp"
 #include "../parser/interpreter.hpp"
 #include "../commands/async_queue.hpp"
 #include "../commands/cmd_quit.hpp"
@@ -115,6 +117,7 @@ static int Open( vlc_object_t *p_this )
     p_intf->p_sys->p_osFactory = NULL;
     p_intf->p_sys->p_osLoop = NULL;
     p_intf->p_sys->p_varManager = NULL;
+    p_intf->p_sys->p_voutManager = NULL;
     p_intf->p_sys->p_vlcProc = NULL;
     p_intf->p_sys->p_repository = NULL;
 
@@ -170,6 +173,12 @@ static int Open( vlc_object_t *p_this )
 #endif
         return VLC_EGENERIC;
     }
+    if( VoutManager::instance( p_intf ) == NULL )
+    {
+        msg_Err( p_intf, "cannot instanciate VoutManager" );
+        vlc_object_release( p_intf->p_sys->p_playlist );
+        return VLC_EGENERIC;
+    }
     vlc_mutex_lock( &skin_load.mutex );
     skin_load.intf = p_intf;
     vlc_mutex_unlock( &skin_load.mutex );
@@ -237,13 +246,23 @@ static void Close( vlc_object_t *p_this )
 {
     intf_thread_t *p_intf = (intf_thread_t *)p_this;
 
+    msg_Dbg( p_intf, "closing skins2 module" );
+
     vlc_mutex_lock( &skin_load.mutex );
     skin_load.intf = NULL;
     vlc_mutex_unlock( &skin_load.mutex);
 
+    if( p_intf->p_sys->p_theme )
+    {
+        delete p_intf->p_sys->p_theme;
+        p_intf->p_sys->p_theme = NULL;
+        msg_Dbg( p_intf, "current theme deleted" );
+    }
+
     // Destroy "singleton" objects
     OSFactory::instance( p_intf )->destroyOSLoop();
     ThemeRepository::destroy( p_intf );
+    VoutManager::destroy( p_intf );
     //Dialogs::destroy( p_intf );
     Interpreter::destroy( p_intf );
     AsyncQueue::destroy( p_intf );
@@ -283,8 +302,6 @@ static void Run( intf_thread_t *p_intf )
     if( p_intf->p_sys->p_theme )
     {
         p_intf->p_sys->p_theme->saveConfig();
-        delete p_intf->p_sys->p_theme;
-        p_intf->p_sys->p_theme = NULL;
     }
 
     // cannot be called in "Close", because it refcounts skins2
@@ -304,15 +321,14 @@ static int WindowOpen( vlc_object_t *p_this )
     if( pIntf == NULL )
         return VLC_EGENERIC;
 
-    /* FIXME: most probably not thread-safe,
-     * albeit no worse than ever before */
-    pWnd->handle.hwnd = VlcProc::getWindow( pIntf, pWnd->vout,
-                                       &pWnd->pos_x, &pWnd->pos_y,
-                                       &pWnd->width, &pWnd->height );
+    vlc_object_release( pIntf );
+
+    pWnd->handle.hwnd = VoutManager::getWindow( pIntf, pWnd );
+
     if( pWnd->handle.hwnd )
     {
         pWnd->p_private = pIntf;
-        pWnd->control = &VlcProc::controlWindow;
+        pWnd->control = &VoutManager::controlWindow;
         return VLC_SUCCESS;
     }
     else
@@ -326,7 +342,7 @@ static void WindowClose( vlc_object_t *p_this )
     vout_window_t *pWnd = (vout_window_t *)p_this;
     intf_thread_t *pIntf = (intf_thread_t *)p_this->p_private;
 
-    VlcProc::releaseWindow( pIntf, pWnd->handle.hwnd );
+    VoutManager::releaseWindow( pIntf, pWnd );
 }
 
 //---------------------------------------------------------------------------
index 3f9f9bcace1c0f26bf8c046d61efb0f598ae5930..3f0d106271872170d709d81c1944fc88fe2e5d9a 100644 (file)
@@ -116,9 +116,6 @@ bool ThemeLoader::load( const string &fileName )
     }
     free( skin_last );
 
-    // The new theme cannot embed a video output yet
-    VlcProc::instance( getIntf() )->dropVout();
-
     return true;
 }
 
index 2d8abeaa7c109c4b03bf622545957fdbbec9a3f3..4c890150e2097bb449cf7c4b37a4dce13cfa9434 100644 (file)
@@ -177,6 +177,7 @@ VlcProc::~VlcProc()
     if( getIntf()->p_sys->p_input )
     {
         vlc_object_release( getIntf()->p_sys->p_input );
+        getIntf()->p_sys->p_input = NULL;
     }
 
     interaction_Unregister( getIntf() );
@@ -196,27 +197,6 @@ VlcProc::~VlcProc()
     var_DelCallback( getIntf(), "skin-to-load", onSkinToLoad, this );
 }
 
-#include <assert.h>
-
-void VlcProc::registerVoutWindow( void *pVoutWindow )
-{
-    m_handleSet.insert( pVoutWindow );
-    assert( !m_pVout );
-}
-
-
-void VlcProc::unregisterVoutWindow( void *pVoutWindow )
-{
-    m_handleSet.erase( pVoutWindow );
-}
-
-
-void VlcProc::dropVout()
-{
-    assert( !m_pVout );
-}
-
-
 void VlcProc::manage()
 {
     // Did the user request to quit vlc ?
@@ -556,73 +536,6 @@ void VlcProc::updateStreamName()
     pQueue->push( CmdGenericPtr( pCmdItem ) );
 }
 
-void *VlcProc::getWindow( intf_thread_t *pIntf, vout_thread_t *pVout,
-                          int *pXHint, int *pYHint,
-                          unsigned int *pWidthHint,
-                          unsigned int *pHeightHint )
-{
-    VlcProc *pThis = pIntf->p_sys->p_vlcProc;
-    if( pThis->m_handleSet.empty() )
-    {
-        return NULL;
-    }
-    else
-    {
-        pThis->m_pVout = pVout;
-        // Get the window handle
-        void *pWindow = *pThis->m_handleSet.begin();
-        // Post a resize vout command
-        CmdResizeVout *pCmd = new CmdResizeVout( pThis->getIntf(), pWindow,
-                                                 *pWidthHint, *pHeightHint );
-        AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
-        pQueue->push( CmdGenericPtr( pCmd ) );
-        return pWindow;
-    }
-}
-
-
-void VlcProc::releaseWindow( intf_thread_t *pIntf, void *pWindow )
-{
-    VlcProc *pThis = pIntf->p_sys->p_vlcProc;
-    pThis->m_pVout = NULL;
-}
-
-
-int VlcProc::controlWindow( struct vout_window_t *pWnd,
-                            int query, va_list args )
-{
-    intf_thread_t *pIntf = (intf_thread_t *)pWnd->p_private;
-    VlcProc *pThis = pIntf->p_sys->p_vlcProc;
-
-    switch( query )
-    {
-        case VOUT_SET_SIZE:
-        {
-            if( pThis->m_pVout )
-            {
-                unsigned int i_width  = va_arg( args, unsigned int );
-                unsigned int i_height = va_arg( args, unsigned int );
-                if( !i_width ) i_width = pThis->m_pVout->i_window_width;
-                if( !i_height ) i_height = pThis->m_pVout->i_window_height;
-
-                // Post a resize vout command
-                CmdResizeVout *pCmd =
-                    new CmdResizeVout( pThis->getIntf(), pWnd->handle.hwnd,
-                                       i_width, i_height );
-                AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
-                pQueue->push( CmdGenericPtr( pCmd ) );
-            }
-        }
-
-        default:
-            msg_Dbg( pWnd, "control query not supported" );
-            break;
-    }
-
-    return VLC_SUCCESS;
-}
-
-
 int VlcProc::onEqBandsChange( vlc_object_t *pObj, const char *pVariable,
                               vlc_value_t oldVal, vlc_value_t newVal,
                               void *pParam )
index c69b2e6e22ec4f69871f9f1aeb0fe3d1d804404c..42e0d95211229fec03f4778e058589544e0706e8 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <set>
 
+#include <vlc_vout.h>
 #include "../vars/equalizer.hpp"
 #include "../vars/playtree.hpp"
 #include "../vars/time.hpp"
@@ -34,6 +35,7 @@
 #include "../utils/position.hpp"
 #include "../utils/var_text.hpp"
 #include "../commands/cmd_generic.hpp"
+#include "../controls/ctrl_video.hpp"
 
 class OSTimer;
 class VarBool;
@@ -80,19 +82,9 @@ class VlcProc: public SkinObject
         /// Getter for the vout size variable
         VarBox &getVoutSizeVar() { return m_varVoutSize; }
 
-        /// Set the vout window handle
-        void registerVoutWindow( void *pVoutWindow );
-
-        /// Unset the vout window handle
-        void unregisterVoutWindow( void *pVoutWindow );
-
         /// Indicate whether the embedded video output is currently used
         bool isVoutUsed() const { return m_pVout != NULL; }
 
-        /// If an embedded video output is used, drop it (i.e. tell it to stop
-        /// using our window handle)
-        void dropVout();
-
     protected:
         // Protected because it is a singleton
         VlcProc( intf_thread_t *pIntf );
@@ -135,12 +127,6 @@ class VlcProc: public SkinObject
         /// Variable for DVD detection
         VariablePtr m_cVarDvdActive;
 
-        /// Set of handles of vout windows
-        /**
-         * When changing the skin, the handles of the 2 skins coexist in the
-         * set (but this is temporary, until the old theme is destroyed).
-         */
-        set<void *> m_handleSet;
         /// Vout thread
         vout_thread_t *m_pVout;
         /// Audio output
@@ -209,21 +195,6 @@ class VlcProc: public SkinObject
                                   vlc_value_t oldVal, vlc_value_t newVal,
                                   void *pParam );
 
-    public: /* FIXME: these used to be private for a reason */
-        /// Callback to request a vout window
-        static void *getWindow( intf_thread_t *pIntf, vout_thread_t *pVout,
-                                int *pXHint, int *pYHint,
-                                unsigned int *pWidthHint,
-                                unsigned int *pHeightHint );
-
-        /// Callback to release a vout window
-        static void releaseWindow( intf_thread_t *pIntf, void *pWindow );
-
-        /// Callback to change a vout window
-        static int controlWindow( struct vout_window_t *pWnd,
-                                  int query, va_list args );
-    private: /* end of FIXME */
-
         /// Callback for equalizer-bands variable
         static int onEqBandsChange( vlc_object_t *pObj, const char *pVariable,
                                     vlc_value_t oldVal, vlc_value_t newVal,
diff --git a/modules/gui/skins2/src/vout_manager.cpp b/modules/gui/skins2/src/vout_manager.cpp
new file mode 100644 (file)
index 0000000..fd0242d
--- /dev/null
@@ -0,0 +1,303 @@
+/*****************************************************************************
+ * vout_manager.cpp
+ *****************************************************************************
+ * Copyright (C) 2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Erwan Tulou <brezhoneg1 at yahoo.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_vout.h>
+#include <vlc_window.h>
+
+#include "vout_manager.hpp"
+#include "window_manager.hpp"
+#include "vlcproc.hpp"
+#include "../commands/async_queue.hpp"
+#include "../commands/cmd_show_window.hpp"
+#include "../commands/cmd_resize.hpp"
+
+
+
+VoutManager *VoutManager::instance( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_voutManager == NULL )
+    {
+        pIntf->p_sys->p_voutManager = new VoutManager( pIntf );
+    }
+
+    return pIntf->p_sys->p_voutManager;
+}
+
+
+void VoutManager::destroy( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_voutManager )
+    {
+        delete pIntf->p_sys->p_voutManager;
+        pIntf->p_sys->p_voutManager = NULL;
+    }
+}
+
+
+VoutManager::VoutManager( intf_thread_t *pIntf ): SkinObject( pIntf ),
+     m_pVoutMainWindow( NULL ), m_pCtrlVideoVec(),
+     m_pCtrlVideoVecBackup(), m_SavedVoutVec()
+{
+    vlc_mutex_init( &vout_lock );
+
+    m_pVoutMainWindow = new VoutMainWindow( getIntf() );
+}
+
+
+VoutManager::~VoutManager( )
+{
+    vlc_mutex_destroy( &vout_lock );
+
+    delete m_pVoutMainWindow;
+}
+
+
+void VoutManager::registerCtrlVideo( CtrlVideo* p_CtrlVideo )
+{
+    m_pCtrlVideoVec.push_back( p_CtrlVideo );
+}
+
+
+void VoutManager::saveVoutConfig( )
+{
+    // Save width/height to be consistent across themes
+    // and detach Video Controls
+    vector<SavedVout>::iterator it;
+    for( it = m_SavedVoutVec.begin(); it != m_SavedVoutVec.end(); it++ )
+    {
+        if( (*it).pCtrlVideo )
+        {
+            // detach vout thread from VideoControl
+            (*it).pCtrlVideo->detachVoutWindow( );
+
+            // memorize width/height before VideoControl is destroyed
+            (*it).width = (*it).pCtrlVideo->getPosition()->getWidth();
+            (*it).height = (*it).pCtrlVideo->getPosition()->getHeight();
+            (*it).pCtrlVideo = NULL;
+       }
+    }
+
+    // Create a backup copy and reset original for new theme
+    m_pCtrlVideoVecBackup = m_pCtrlVideoVec;
+    m_pCtrlVideoVec.clear();
+}
+
+
+void VoutManager::restoreVoutConfig( bool b_success )
+{
+    if( !b_success )
+    {
+        // loading new theme failed, restoring previous theme
+        m_pCtrlVideoVec = m_pCtrlVideoVecBackup;
+    }
+
+    // reattach vout(s) to Video Controls
+    vector<SavedVout>::iterator it;
+    for( it = m_SavedVoutVec.begin(); it != m_SavedVoutVec.end(); it++ )
+    {
+        CtrlVideo* pCtrlVideo = getBestCtrlVideo();
+        if( pCtrlVideo )
+        {
+            pCtrlVideo->attachVoutWindow( (*it).pVoutWindow );
+           (*it).pCtrlVideo = pCtrlVideo;
+        }
+    }
+}
+
+
+void VoutManager::discardVout( CtrlVideo* pCtrlVideo )
+{
+    vector<SavedVout>::iterator it;
+    for( it = m_SavedVoutVec.begin(); it != m_SavedVoutVec.end(); it++ )
+    {
+        if( (*it).pCtrlVideo == pCtrlVideo )
+        {
+            // detach vout thread from VideoControl
+            (*it).pCtrlVideo->detachVoutWindow( );
+            (*it).width = (*it).pCtrlVideo->getPosition()->getWidth();
+            (*it).height = (*it).pCtrlVideo->getPosition()->getHeight();
+            (*it).pCtrlVideo = NULL;
+            break;
+        }
+    }
+}
+
+
+void VoutManager::requestVout( CtrlVideo* pCtrlVideo )
+{
+    vector<SavedVout>::iterator it;
+    for( it = m_SavedVoutVec.begin(); it != m_SavedVoutVec.end(); it++ )
+    {
+        if( (*it).pCtrlVideo == NULL )
+        {
+            pCtrlVideo->attachVoutWindow( (*it).pVoutWindow );
+            (*it).pCtrlVideo = pCtrlVideo;
+            break;
+        }
+    }
+}
+
+
+CtrlVideo* VoutManager::getBestCtrlVideo( )
+{
+    // try to find an unused useable VideoControl
+
+    vector<CtrlVideo*>::const_iterator it;
+    for( it = m_pCtrlVideoVec.begin(); it != m_pCtrlVideoVec.end(); it++ )
+    {
+        if( (*it)->isUseable() && !(*it)->isUsed() )
+        {
+            return (*it);
+        }
+    }
+
+    return NULL;
+}
+
+
+void* VoutManager::acceptVout( vout_thread_t* pVout, int width, int height )
+{
+    // Creation of a dedicated Window per vout thread
+    VoutWindow* pVoutWindow = new VoutWindow( getIntf(), pVout, width, height,
+                                         (GenericWindow*) m_pVoutMainWindow );
+
+    void* handle = pVoutWindow->getOSHandle();
+
+    // try to find a video Control within the theme
+    CtrlVideo* pCtrlVideo = getBestCtrlVideo();
+    if( pCtrlVideo )
+    {
+        // A Video Control is available
+        // directly attach vout thread to it
+        pCtrlVideo->attachVoutWindow( pVoutWindow );
+    }
+
+    // save vout characteristics
+    m_SavedVoutVec.push_back( SavedVout( pVout, pVoutWindow, pCtrlVideo ) );
+
+    msg_Dbg( getIntf(), "New incoming vout=0x%x, handle=0x%x, VideoCtrl=0x%x",
+                        pVout, handle, pCtrlVideo );
+
+    return handle;
+}
+
+
+// Functions called by window provider
+// ///////////////////////////////////
+
+void *VoutManager::getWindow( intf_thread_t *pIntf, vout_window_t *pWnd )
+{
+    // Theme may have been destroyed
+    if( !pIntf->p_sys->p_theme )
+        return NULL;
+
+    VoutManager *pThis = pIntf->p_sys->p_voutManager;
+
+    vout_thread_t* pVout = pWnd->vout;
+    int width = (int)pWnd->width;
+    int height = (int)pWnd->height;
+
+    pThis->lockVout();
+
+    void* handle = pThis->acceptVout( pVout, width, height );
+
+    pThis->unlockVout();
+
+    return handle;
+}
+
+
+void VoutManager::releaseWindow( intf_thread_t *pIntf, vout_window_t *pWnd )
+{
+    VoutManager *pThis = pIntf->p_sys->p_voutManager;
+
+    // Theme may have been destroyed
+    if( !pIntf->p_sys->p_theme )
+        return;
+
+    vout_thread_t* pVout = pWnd->vout;
+
+    pThis->lockVout();
+
+    // remove vout thread from savedVec
+    vector<SavedVout>::iterator it;
+    for( it = pThis->m_SavedVoutVec.begin(); it != pThis->m_SavedVoutVec.end(); it++ )
+    {
+        if( (*it).pVout == pVout )
+        {
+            msg_Dbg( pIntf, "vout released vout=0x%x, VideoCtrl=0x%x",
+                             pVout, (*it).pCtrlVideo );
+
+            // if a video control was being used, detach from it
+            if( (*it).pCtrlVideo )
+            {
+                (*it).pCtrlVideo->detachVoutWindow( );
+            }
+
+            // remove resources
+            delete (*it).pVoutWindow;
+            pThis->m_SavedVoutVec.erase( it );
+            break;
+        }
+    }
+
+    pThis->unlockVout();
+}
+
+
+int VoutManager::controlWindow( struct vout_window_t *pWnd,
+                            int query, va_list args )
+{
+    intf_thread_t *pIntf = (intf_thread_t *)pWnd->p_private;
+    VoutManager *pThis = pIntf->p_sys->p_voutManager;
+
+    switch( query )
+    {
+        case VOUT_SET_SIZE:
+        {
+            unsigned int i_width  = va_arg( args, unsigned int );
+            unsigned int i_height = va_arg( args, unsigned int );
+
+            if( i_width && i_height )
+            {
+                // Post a resize vout command
+                CmdResizeVout *pCmd =
+                    new CmdResizeVout( pThis->getIntf(), pWnd->handle.hwnd,
+                                       i_width, i_height );
+                AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
+                pQueue->push( CmdGenericPtr( pCmd ) );
+            }
+        }
+
+        default:
+            msg_Dbg( pWnd, "control query not supported" );
+            break;
+    }
+
+    return VLC_SUCCESS;
+}
+
diff --git a/modules/gui/skins2/src/vout_manager.hpp b/modules/gui/skins2/src/vout_manager.hpp
new file mode 100644 (file)
index 0000000..1d658e8
--- /dev/null
@@ -0,0 +1,137 @@
+/*****************************************************************************
+ * vout_manager.hpp
+ *****************************************************************************
+ * Copyright (C) 2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Erwan Tulou < brezhoneg1 at yahoo.fr r>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VOUTMANAGER_HPP
+#define VOUTMANAGER_HPP
+
+#include <vector>
+
+#include <vlc_vout.h>
+#include <vlc_window.h>
+#include "../utils/position.hpp"
+#include "../commands/cmd_generic.hpp"
+#include "../controls/ctrl_video.hpp"
+
+class VarBool;
+class GenericWindow;
+
+#include <stdio.h>
+
+class SavedVout
+{
+public:
+    SavedVout( vout_thread_t* pVout, VoutWindow* pVoutWindow = NULL,
+               CtrlVideo* pCtrlVideo = NULL, int height = 0, int width = 0 ) :
+       pVout( pVout ), pVoutWindow( pVoutWindow ), pCtrlVideo( pCtrlVideo ),
+       height( height ), width( width ) {}
+
+    ~SavedVout() {}
+
+    vout_thread_t* pVout;
+    VoutWindow *pVoutWindow;
+    CtrlVideo *pCtrlVideo;
+    int height;
+    int width;
+};
+
+class VoutMainWindow: public GenericWindow
+{
+    public:
+
+        VoutMainWindow( intf_thread_t *pIntf, int left = 0, int top = 0 ) :
+                GenericWindow( pIntf, left, top, false, false, NULL )
+        {
+            resize( 10, 10 );
+            move( -50, -50 );
+        }
+        virtual ~VoutMainWindow() {}
+
+};
+
+
+/// Singleton object handling VLC internal state and playlist
+class VoutManager: public SkinObject
+{
+    public:
+        /// Get the instance of VoutManager
+        /// Returns NULL if the initialization of the object failed
+        static VoutManager *instance( intf_thread_t *pIntf );
+
+        /// Delete the instance of VoutManager
+        static void destroy( intf_thread_t *pIntf );
+
+        /// Callback to request a vout window
+        static void *getWindow( intf_thread_t *pIntf, vout_window_t *pWnd );
+
+        /// Accept Vout
+        void* acceptVout( vout_thread_t* pVout, int width, int height );
+
+        // Window provider (release)
+        static void releaseWindow( intf_thread_t *pIntf, vout_window_t *pWnd  );
+
+        /// Callback to change a vout window
+        static int controlWindow( struct vout_window_t *pWnd,
+                                  int query, va_list args );
+
+        // Register Video Controls (when building theme)
+        void registerCtrlVideo( CtrlVideo* p_CtrlVideo );
+
+        // save and restore vouts (when changing theme)
+        void saveVoutConfig( );
+        void restoreVoutConfig( bool b_success );
+
+        // save and restore vouts (when swapping Layout)
+        void discardVout( CtrlVideo* pCtrlVideo );
+        void requestVout( CtrlVideo* pCtrlVideo );
+
+        // get a VoutWindow
+        void* getHandle( vout_thread_t* pVout, int width, int height );
+
+        // get a useable video Control
+        CtrlVideo* getBestCtrlVideo( );
+
+        // get the VoutMainWindow
+        VoutMainWindow* getVoutMainWindow() { return m_pVoutMainWindow; }
+
+        // (un)lock functions to protect vout sets
+        void lockVout( ) { vlc_mutex_lock( &vout_lock ); }
+        void unlockVout( ) { vlc_mutex_unlock( &vout_lock ); }
+
+    protected:
+        // Protected because it is a singleton
+        VoutManager( intf_thread_t *pIntf );
+        virtual ~VoutManager();
+
+    private:
+
+        vector<CtrlVideo *> m_pCtrlVideoVec;
+        vector<CtrlVideo *> m_pCtrlVideoVecBackup;
+        vector<SavedVout> m_SavedVoutVec;
+
+        VoutMainWindow* m_pVoutMainWindow;
+
+        vlc_mutex_t vout_lock;
+};
+
+
+#endif
index ea380333275dd57d29221afae14ece4acd7814a7..830e06ffed2ae438ac5b361d107d70251af22bbc 100644 (file)
  *****************************************************************************/
 
 #include "vout_window.hpp"
+#include "vout_manager.hpp"
 #include "vlcproc.hpp"
+#include "theme.hpp"
 #include "os_factory.hpp"
 #include "os_graphics.hpp"
 #include "os_window.hpp"
 
+int VoutWindow::count = 0;
 
-VoutWindow::VoutWindow( intf_thread_t *pIntf, int left, int top,
-                        bool dragDrop, bool playOnDrop,
-                        GenericWindow &rParent ):
-    GenericWindow( pIntf, left, top, dragDrop, playOnDrop,
-                   &rParent ), m_pImage( NULL )
+VoutWindow::VoutWindow( intf_thread_t *pIntf, vout_thread_t* pVout,
+                        int width, int height, GenericWindow* pParent ) :
+      GenericWindow( pIntf, 0, 0, false, false, pParent ),
+      m_pVout( pVout ), original_width( width ), original_height( height ),
+      m_pParentWindow( pParent ), m_pImage( NULL )
 {
+    // counter for debug
+    count++;
+
+    if( m_pVout )
+        vlc_object_hold( m_pVout );
+
+    // needed on MS-Windows to prevent vlc hanging
+    show();
 }
 
 
 VoutWindow::~VoutWindow()
 {
     delete m_pImage;
+    if( m_pVout )
+        vlc_object_release( m_pVout );
 
-    // Get the VlcProc
-    VlcProc *pVlcProc = getIntf()->p_sys->p_vlcProc;
-
-    // Reparent the video output
-    if( pVlcProc && pVlcProc->isVoutUsed() )
-    {
-        pVlcProc->dropVout();
-    }
+    count--;
+    msg_Dbg( getIntf(), "VoutWindow count = %d", count );
 }
 
 
 void VoutWindow::resize( int width, int height )
 {
+    // don't try to resize with zero value
+    if( !width || !height )
+        return;
+
     // Get the OSFactory
     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
 
@@ -72,11 +83,7 @@ void VoutWindow::refresh( int left, int top, int width, int height )
 {
     if( m_pImage )
     {
-        // Get the VlcProc
-        VlcProc *pVlcProc = getIntf()->p_sys->p_vlcProc;
-
-        // Refresh only when there is no video!
-        if( pVlcProc && !pVlcProc->isVoutUsed() )
+        if( !m_pCtrlVideo )
         {
             m_pImage->copyToWindow( *getOSWindow(), left, top,
                                     width, height, left, top );
@@ -84,3 +91,27 @@ void VoutWindow::refresh( int left, int top, int width, int height )
     }
 }
 
+void VoutWindow::setCtrlVideo( CtrlVideo* pCtrlVideo )
+{
+    if( pCtrlVideo )
+    {
+        const Position *pPos = pCtrlVideo->getPosition();
+        int x = pPos->getLeft();
+        int y = pPos->getTop();
+        int w = pPos->getWidth();
+        int h = pPos->getHeight();
+
+        setParent( pCtrlVideo->getWindow(), x, y, w, h );
+        m_pParentWindow = pCtrlVideo->getWindow();
+    }
+    else
+    {
+        setParent( VoutManager::instance( getIntf() )->getVoutMainWindow(),
+                   0, 0, 0, 0 );
+        m_pParentWindow =
+                  VoutManager::instance( getIntf() )->getVoutMainWindow();
+    }
+
+    m_pCtrlVideo = pCtrlVideo;
+}
+
index df03c2b7a7f20d4f0f0bb9ec6c79b055f9a07abe..90d8225214a3d800358aec225f02a92f7f8ae801 100644 (file)
 #include "generic_window.hpp"
 
 class OSGraphics;
+class CtrlVideo;
 
 
 /// Class to handle a video output window
 class VoutWindow: private GenericWindow
 {
     public:
-        VoutWindow( intf_thread_t *pIntf, int xPos, int yPos,
-                    bool dragDrop, bool playOnDrop, GenericWindow &rParent );
+
+        VoutWindow( intf_thread_t *pIntf, vout_thread_t* pVout,
+                    int width, int height, GenericWindow* pParent = NULL );
         virtual ~VoutWindow();
 
+        // counter used for debugging purpose
+        static int count;
+
         /// Make some functions public
         //@{
         using GenericWindow::show;
         using GenericWindow::hide;
         using GenericWindow::move;
+        using GenericWindow::getOSHandle;
         //@}
 
         /// Resize the window
         virtual void resize( int width, int height );
 
+        /// get the parent  window
+        virtual GenericWindow* getWindow( ) { return m_pParentWindow; }
+
         /// Refresh an area of the window
         virtual void refresh( int left, int top, int width, int height );
 
+        /// set Video Control for VoutWindow
+        virtual void setCtrlVideo( CtrlVideo* pCtrlVideo );
+
+        /// get original size of vout
+        virtual int getOriginalWidth( ) { return original_width; }
+        virtual int getOriginalHeight( ) { return original_height; }
+
         virtual string getType() const { return "Vout"; }
 
     private:
+
         /// Image when there is no video
         OSGraphics *m_pImage;
+
+        /// vout thread
+        vout_thread_t* m_pVout;
+
+        /// original width and height
+        int original_width;
+        int original_height;
+
+        /// VideoControl attached to it
+        CtrlVideo* m_pCtrlVideo;
+
+        /// Parent Window
+        GenericWindow* m_pParentWindow;
 };
 
 typedef CountedPtr<VoutWindow> VoutWindowPtr;
index b2ccf99913ed0479a4ce7d85e55b10cccb9020c3..01385b5682af2d34042e11638a5c429b18bee4c4 100644 (file)
@@ -639,3 +639,4 @@ void WindowManager::setActiveLayout( TopWindow &rWindow,
     // Rebuild the dependencies
     stopMove();
 }
+
index 5758b37f7582aed3482d9e117eaedfa1d9872b22..2db62c20fd9d92e5b1e918eb6203e534a1ea6cce 100644 (file)
@@ -54,18 +54,19 @@ Win32Window::Win32Window( intf_thread_t *pIntf, GenericWindow &rWindow,
     if( pParentWindow )
     {
         // Child window (for vout)
-        HWND hParent = pParentWindow->getHandle();
+        m_hWnd_parent = pParentWindow->getHandle();
         m_hWnd = CreateWindowEx( WS_EX_TOOLWINDOW, "SkinWindowClass",
             "default name", WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT,
-            CW_USEDEFAULT, CW_USEDEFAULT, hParent, 0, hInst, NULL );
+            CW_USEDEFAULT, CW_USEDEFAULT, m_hWnd_parent, 0, hInst, NULL );
     }
     else
     {
         // Normal window
+        m_hWnd_parent = hParentWindow;
         m_hWnd = CreateWindowEx( WS_EX_TOOLWINDOW, "SkinWindowClass",
             "default name", WS_POPUP | WS_CLIPCHILDREN,
             CW_USEDEFAULT, CW_USEDEFAULT,
-            CW_USEDEFAULT, CW_USEDEFAULT, hParentWindow, 0, hInst, NULL );
+            CW_USEDEFAULT, CW_USEDEFAULT, m_hWnd_parent, 0, hInst, NULL );
     }
 
     if( !m_hWnd )
@@ -86,22 +87,11 @@ Win32Window::Win32Window( intf_thread_t *pIntf, GenericWindow &rWindow,
         // Register the window as a drop target
         RegisterDragDrop( m_hWnd, m_pDropTarget );
     }
-
-    // Set this window as a vout
-    if( m_pParent )
-    {
-        VlcProc::instance( getIntf() )->registerVoutWindow( (void*)m_hWnd );
-    }
 }
 
 
 Win32Window::~Win32Window()
 {
-    if( m_pParent )
-    {
-        VlcProc::instance( getIntf() )->unregisterVoutWindow( (void*)m_hWnd );
-    }
-
     Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( getIntf() );
     pFactory->m_windowMap[m_hWnd] = NULL;
 
@@ -119,6 +109,14 @@ Win32Window::~Win32Window()
 }
 
 
+void Win32Window::reparent( void* OSHandle, int x, int y, int w, int h )
+{
+    // Reparent the window
+    SetParent( m_hWnd, (HWND)OSHandle );
+    MoveWindow( m_hWnd, x, y, w, h, true );
+}
+
+
 void Win32Window::show( int left, int top ) const
 {
     ShowWindow( m_hWnd, SW_SHOW );
index 22e1cbe4e63dfbc8299b7b23b13d947559649525..966a463202bcb2b486e0c9e17c36e42b506f018f 100644 (file)
@@ -62,9 +62,17 @@ class Win32Window: public OSWindow
         /// Getter for the window handle
         HWND getHandle() const { return m_hWnd; }
 
+        /// Getter for the window handle
+        void* getOSHandle() const { return (void*) m_hWnd; }
+
+        /// reparent the window
+        void reparent( void* OSHandle, int x, int y, int w, int h );
+
     private:
         /// Window handle
         HWND m_hWnd;
+        /// Window parent's handle
+        HWND m_hWnd_parent;
         /// Indicates whether the window handles drag&drop events
         bool m_dragDrop;
         /// Drop target
index 815a169a47e91e29543a4e38f89b3ef519e432ea..fe80a7b768876803fdf63ae4679058e555824e87 100644 (file)
@@ -55,6 +55,10 @@ X11Factory::~X11Factory()
 
 bool X11Factory::init()
 {
+    // make sure xlib is safe-thread
+    if( !XInitThreads() )
+        msg_Err( getIntf(), "initializing xlib for multi-threading failed" );
+
     // Create the X11 display
     m_pDisplay = new X11Display( getIntf() );
 
index cc52fa699762c62fd287eb78fec11e9fadeaab96..f9cd7779d62c89a3227bdc2527943ed9eaab9656 100644 (file)
@@ -175,7 +175,6 @@ void X11Loop::handleX11Event()
 
     if( !pWin )
     {
-        msg_Warn( getIntf(), "no associated generic window" );
         return;
     }
 
index 03ec09fe978a3e048ff1e32f52be9b9ce9cd738a..3c205922f6d9501394f8ac25ad166379ca0c8e2f 100644 (file)
@@ -41,20 +41,36 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
     OSWindow( pIntf ), m_rDisplay( rDisplay ), m_pParent( pParentWindow ),
     m_dragDrop( dragDrop )
 {
-    Window parent;
     if (pParentWindow)
     {
-        parent = pParentWindow->m_wnd;
+        m_wnd_parent = pParentWindow->m_wnd;
     }
     else
     {
-        parent = DefaultRootWindow( XDISPLAY );
+        m_wnd_parent = DefaultRootWindow( XDISPLAY );
     }
     XSetWindowAttributes attr;
+    attr.event_mask = ExposureMask | StructureNotifyMask;
 
     // Create the window
-    m_wnd = XCreateWindow( XDISPLAY, parent, 0, 0, 1, 1, 0, 0,
-                           InputOutput, CopyFromParent, 0, &attr );
+    m_wnd = XCreateWindow( XDISPLAY, m_wnd_parent, -10, 0, 1, 1, 0, 0,
+                           InputOutput, CopyFromParent, CWEventMask, &attr );
+
+    // Make sure window is created before returning
+    XMapWindow( XDISPLAY, m_wnd );
+    bool b_map_notify = false;
+    do
+    {
+        XEvent xevent;
+        XWindowEvent( XDISPLAY, m_wnd, SubstructureNotifyMask |
+                      StructureNotifyMask, &xevent);
+        if( (xevent.type == MapNotify)
+             && (xevent.xmap.window == m_wnd ) )
+        {
+            b_map_notify = true;
+        }
+    } while( ! b_map_notify );
+    XUnmapWindow( XDISPLAY, m_wnd );
 
     // Set the colormap for 8bpp mode
     if( XPIXELSIZE == 1 )
@@ -109,22 +125,11 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
     // Associate the window to the main "parent" window
     XSetTransientForHint( XDISPLAY, m_wnd, m_rDisplay.getMainWindow() );
 
-    // Set this window as a vout
-    if( m_pParent )
-    {
-        VlcProc::instance( getIntf() )->registerVoutWindow( (void*)m_wnd );
-    }
-
 }
 
 
 X11Window::~X11Window()
 {
-    if( m_pParent )
-    {
-        VlcProc::instance( getIntf() )->unregisterVoutWindow( (void*)m_wnd );
-    }
-
     X11Factory *pFactory = (X11Factory*)X11Factory::instance( getIntf() );
     pFactory->m_windowMap[m_wnd] = NULL;
     pFactory->m_dndMap[m_wnd] = NULL;
@@ -137,6 +142,19 @@ X11Window::~X11Window()
     XSync( XDISPLAY, False );
 }
 
+void X11Window::reparent( void* OSHandle, int x, int y, int w, int h )
+{
+    // Reparent the window
+    Window new_parent =
+           OSHandle ? (Window) OSHandle : DefaultRootWindow( XDISPLAY );
+
+    if( w && h )
+        XResizeWindow( XDISPLAY, m_wnd, w, h );
+
+    XReparentWindow( XDISPLAY, m_wnd, new_parent, x, y);
+    m_wnd_parent = new_parent;
+}
+
 
 void X11Window::show( int left, int top ) const
 {
@@ -155,7 +173,10 @@ void X11Window::hide() const
 
 void X11Window::moveResize( int left, int top, int width, int height ) const
 {
-    XMoveResizeWindow( XDISPLAY, m_wnd, left, top, width, height );
+    if( width && height )
+        XMoveResizeWindow( XDISPLAY, m_wnd, left, top, width, height );
+    else
+        XMoveWindow( XDISPLAY, m_wnd, left, top );
 }
 
 
index 186a8c2edef955906a8c37a9aa83a50dda7b0d19..f20b06daf14ccbae666d620035481cf3291710f9 100644 (file)
@@ -65,11 +65,22 @@ class X11Window: public OSWindow
         /// Get the window ID
         Window getDrawable() const { return m_wnd; }
 
+        /// Getter for the handler
+        void* getOSHandle() const { return (void*) m_wnd; }
+
+        /// Getter for the handler
+        void* getParentOSHandle() const { return (void*) m_wnd_parent; }
+
+        /// reparent the window
+        void reparent( void* OSHandle, int x, int y, int w, int h );
+
     private:
         /// X11 display
         X11Display &m_rDisplay;
         /// Window ID
         Window m_wnd;
+        /// Window ID
+        Window m_wnd_parent;
         /// Parent window
         X11Window *m_pParent;
         /// Indicates whether the window handles drag&drop events