Add a desktop mode to the Direct3d video output. This allow displaying video on a...
authorAdrien Maglo <magsoft@videolan.org>
Sat, 25 Jul 2009 13:37:38 +0000 (15:37 +0200)
committerJean-Baptiste Kempf <jb@videolan.org>
Sat, 25 Jul 2009 13:54:07 +0000 (15:54 +0200)
Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
modules/gui/qt4/menus.cpp
modules/video_output/msw/direct3d.c
modules/video_output/msw/events.c
modules/video_output/msw/vout.h

index f47a270..2a91f8b 100644 (file)
@@ -220,6 +220,7 @@ static int VideoAutoMenuBuilder( vout_thread_t *p_object,
     PUSH_VAR( "video-on-top" );
 #ifdef WIN32
     PUSH_VAR( "directx-wallpaper" );
+    PUSH_VAR( "direct3d-desktop" );
 #endif
     PUSH_VAR( "video-snapshot" );
     PUSH_VAR( "zoom" );
@@ -558,6 +559,7 @@ QMenu *QVLCMenu::VideoMenu( intf_thread_t *p_intf, QMenu *current )
         ACT_ADDCHECK( current, "video-on-top", qtr( "Always &On Top" ) );
 #ifdef WIN32
         ACT_ADDCHECK( current, "directx-wallpaper", qtr( "DirectX Wallpaper" ) );
+        ACT_ADDCHECK( current, "direct3d-desktop", qtr( "Direct3D Desktop mode" ) );
 #endif
         ACT_ADD( current, "video-snapshot", qtr( "Sna&pshot" ) );
 
index 7aaa410..f552c2d 100644 (file)
@@ -80,6 +80,10 @@ static int Direct3DVoutCreateScene      ( vout_thread_t * );
 static void Direct3DVoutReleaseScene    ( vout_thread_t * );
 static void Direct3DVoutRenderScene     ( vout_thread_t *, picture_t * );
 
+static int DesktopCallback( vlc_object_t *p_this, char const *psz_cmd,
+                            vlc_value_t oldval, vlc_value_t newval,
+                            void *p_data );
+
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
@@ -111,10 +115,18 @@ static int OpenVideoVista( vlc_object_t *obj )
     return IsVistaOrAbove() ? OpenVideo( obj ) : VLC_EGENERIC;
 }
 
+#define DESKTOP_TEXT N_("Enable desktop mode ")
+#define DESKTOP_LONGTEXT N_( \
+    "The desktop mode allows you to display the video on the desktop." )
+
 vlc_module_begin ()
     set_shortname( "Direct3D" )
     set_category( CAT_VIDEO )
     set_subcategory( SUBCAT_VIDEO_VOUT )
+
+    add_bool( "direct3d-desktop", 0, NULL, DESKTOP_TEXT, DESKTOP_LONGTEXT,
+              true )
+
     set_description( N_("DirectX 3D video output") )
     set_capability( "video output", 50 )
     add_shortcut( "direct3d" )
@@ -158,6 +170,7 @@ typedef struct
  *****************************************************************************/
 static int OpenVideo( vlc_object_t *p_this )
 {
+    vlc_value_t val;
     vout_thread_t * p_vout = (vout_thread_t *)p_this;
 
     /* Allocate structure */
@@ -183,6 +196,7 @@ static int OpenVideo( vlc_object_t *p_this )
     p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
     p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
     p_vout->p_sys->i_changes = 0;
+    p_vout->p_sys->b_desktop = false;
     vlc_mutex_init( &p_vout->p_sys->lock );
     SetRectEmpty( &p_vout->p_sys->rect_display );
     SetRectEmpty( &p_vout->p_sys->rect_parent );
@@ -208,6 +222,13 @@ static int OpenVideo( vlc_object_t *p_this )
         /* Trigger a callback right now */
         var_TriggerCallback( p_vout, "video-on-top" );
 
+        /* Trigger a callback right now */
+        var_Create( p_vout, "direct3d-desktop", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
+        val.psz_string = _("Desktop");
+        var_Change( p_vout, "direct3d-desktop", VLC_VAR_SETTEXT, &val, NULL );
+        var_AddCallback( p_vout, "direct3d-desktop", DesktopCallback, NULL );
+        var_TriggerCallback( p_vout, "direct3d-desktop" );
+
         DisableScreensaver ( p_vout );
 
         return VLC_SUCCESS;
@@ -332,6 +353,7 @@ static int Manage( vout_thread_t *p_vout )
                           rect_parent.right - rect_parent.left,
                           rect_parent.bottom - rect_parent.top,
                           SWP_NOZORDER );
+            UpdateRects( p_vout, true );
         }
     }
     else
@@ -363,6 +385,35 @@ static int Manage( vout_thread_t *p_vout )
 #endif
         p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
     }
+    
+    /*
+            * Desktop mode change
+            */
+    if( p_vout->p_sys->i_changes & DX_DESKTOP_CHANGE )
+    {
+        /* Close the direct3d instance attached to the current output window. */
+        End( p_vout );
+        StopEventThread( p_vout );
+        /* Set the switching mode flag */
+        p_vout->p_sys->i_changes |= SWITCHING_MODE_FLAG;
+        /* Reset the flag */
+        p_vout->p_sys->i_changes &= ~DX_DESKTOP_CHANGE;
+    }
+    
+    if( p_vout->p_sys->i_changes & EVENT_THREAD_ENDED
+        && p_vout->p_sys->i_changes & SWITCHING_MODE_FLAG )
+    {
+        /* Open the direct3d output and attaches it to the new window */
+        p_vout->p_sys->b_desktop = !p_vout->p_sys->b_desktop;
+        p_vout->pf_display = FirstDisplay;
+
+        CreateEventThread( p_vout );
+        Init( p_vout );
+
+        /* Reset the flags */
+        p_vout->p_sys->i_changes &= ~EVENT_THREAD_ENDED;
+        p_vout->p_sys->i_changes &= ~SWITCHING_MODE_FLAG;
+    }
 
     /* autoscale toggle */
     if( p_vout->i_changes & VOUT_SCALE_CHANGE )
@@ -493,6 +544,10 @@ static int Manage( vout_thread_t *p_vout )
 static void Display( vout_thread_t *p_vout, picture_t *p_pic )
 {
     LPDIRECT3DDEVICE9       p_d3ddev = p_vout->p_sys->p_d3ddev;
+
+    if( p_vout->p_sys->i_changes & SWITCHING_MODE_FLAG )
+        return;
+
     // Present the back buffer contents to the display
     // stretching and filtering happens here
     HRESULT hr = IDirect3DDevice9_Present(p_d3ddev,
@@ -1266,6 +1321,9 @@ static void Direct3DVoutRenderScene( vout_thread_t *p_vout, picture_t *p_pic )
     HRESULT hr;
     float f_width, f_height;
 
+    if( p_vout->p_sys->i_changes & SWITCHING_MODE_FLAG )
+        return;
+    
     // check if device is still available
     hr = IDirect3DDevice9_TestCooperativeLevel(p_d3ddev);
     if( FAILED(hr) )
@@ -1423,3 +1481,36 @@ static void Direct3DVoutRenderScene( vout_thread_t *p_vout, picture_t *p_pic )
     }
 }
 
+
+/*****************************************************************************
+ * DesktopCallback: desktop mode variable callback
+ *****************************************************************************/
+static int DesktopCallback( vlc_object_t *p_this, char const *psz_cmd,
+                            vlc_value_t oldval, vlc_value_t newval,
+                            void *p_data )
+{
+    VLC_UNUSED( psz_cmd );
+    VLC_UNUSED( oldval );
+    VLC_UNUSED( p_data );
+
+    vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+    if( (newval.b_bool && !p_vout->p_sys->b_desktop) ||
+        (!newval.b_bool && p_vout->p_sys->b_desktop) )
+    {
+        playlist_t *p_playlist = pl_Hold( p_vout );
+
+        if( p_playlist )
+        {
+            /* Modify playlist as well because the vout might have to be
+             * restarted */
+            var_Create( p_playlist, "direct3d-desktop", VLC_VAR_BOOL );
+            var_Set( p_playlist, "direct3d-desktop", newval );
+            pl_Release( p_vout );
+        }
+
+        p_vout->p_sys->i_changes |= DX_DESKTOP_CHANGE;
+    }
+
+    return VLC_SUCCESS;
+}
index db9b27e..2ffa549 100644 (file)
@@ -383,11 +383,11 @@ void* EventThread( vlc_object_t *p_this )
 
     msg_Dbg( p_event, "DirectXEventThread terminating" );
 
-    /* clear the changes formerly signaled */
-    p_event->p_vout->p_sys->i_changes = 0;
-
     DirectXCloseWindow( p_event->p_vout );
     vlc_restorecancel (canc);
+    
+    /* clear the changes formerly signaled */
+    p_event->p_vout->p_sys->i_changes = EVENT_THREAD_ENDED;
     return NULL;
 }
 
@@ -416,14 +416,31 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
     /* Get this module's instance */
     hInstance = GetModuleHandle(NULL);
 
-    /* If an external window was specified, we'll draw in it. */
-    p_vout->p_sys->parent_window =
-        vout_RequestHWND( p_vout, &p_vout->p_sys->i_window_x,
+    #ifdef MODULE_NAME_IS_direct3d
+    if( !p_vout->p_sys->b_desktop )
+    {
+    #endif
+        /* If an external window was specified, we'll draw in it. */
+        p_vout->p_sys->parent_window =
+            vout_RequestHWND( p_vout, &p_vout->p_sys->i_window_x,
                             &p_vout->p_sys->i_window_y,
                             &p_vout->p_sys->i_window_width,
                             &p_vout->p_sys->i_window_height );
-    if( p_vout->p_sys->parent_window )
-        p_vout->p_sys->hparent = p_vout->p_sys->parent_window->handle.hwnd;
+        if( p_vout->p_sys->parent_window )
+            p_vout->p_sys->hparent = p_vout->p_sys->parent_window->handle.hwnd;
+    #ifdef MODULE_NAME_IS_direct3d
+    }
+    else
+    {
+        /* Find Program Manager */
+        HWND hwnd = FindWindow( _T("Progman"), NULL );
+        if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
+        if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
+        if( !hwnd )
+            msg_Err( p_vout, "Couldn't find desktop icon window. Desktop mode can't be established." );
+        p_vout->p_sys->hparent = hwnd;
+    }
+    #endif
 
     /* We create the window ourself, there is no previous window proc. */
     p_vout->p_sys->pf_wndproc = NULL;
@@ -601,7 +618,10 @@ static void DirectXCloseWindow( vout_thread_t *p_vout )
     DestroyWindow( p_vout->p_sys->hwnd );
     if( p_vout->p_sys->hfswnd ) DestroyWindow( p_vout->p_sys->hfswnd );
 
-    vout_ReleaseWindow( p_vout->p_sys->parent_window );
+    #ifdef MODULE_NAME_IS_direct3d
+    if( !p_vout->p_sys->b_desktop )
+    #endif
+        vout_ReleaseWindow( p_vout->p_sys->parent_window );
     p_vout->p_sys->hwnd = NULL;
 
     /* We don't unregister the Window Class because it could lead to race
@@ -1322,5 +1342,6 @@ void StopEventThread( vout_thread_t *p_vout )
         vlc_object_release( p_vout->p_sys->p_event );
     }
 
-    vlc_mutex_destroy( &p_vout->p_sys->lock );
+    if( !p_vout->p_sys->i_changes & SWITCHING_MODE_FLAG )
+        vlc_mutex_destroy( &p_vout->p_sys->lock );
 }
index d8f3b76..be29493 100644 (file)
@@ -168,6 +168,9 @@ struct vout_sys_t
 #endif
 
 #ifdef MODULE_NAME_IS_direct3d
+    /* show video on desktop window ? */
+    bool      b_desktop;
+
     // core objects
     HINSTANCE               hd3d9_dll;       /* handle of the opened d3d9 dll */
     LPDIRECT3D9             p_d3dobj;
@@ -270,6 +273,9 @@ void StopEventThread ( vout_thread_t *p_vout );
 #define IDM_TOGGLE_ON_TOP WM_USER + 1
 #define DX_POSITION_CHANGE 0x1000
 #define DX_WALLPAPER_CHANGE 0x2000
+#define DX_DESKTOP_CHANGE 0x4000
+#define EVENT_THREAD_ENDED 0x6000
+#define SWITCHING_MODE_FLAG 0x8000
 
 /*****************************************************************************
  * WinCE helpers