>From 9fcd5b022542443f25a3fb75180e81127f3a34e8 Mon Sep 17 00:00:00 2001
From: Erwan Tulou <erwan10@videolan.org>
Date: Sun, 13 Jun 2010 15:52:24 +0200
Subject: [PATCH] msw: create a basic vout provider when no other provider is available

This is meant to simplify the msw code (the way it is done with xcb)
---
 configure.ac                        |    6 +
 modules/video_output/msw/basicwin.c |  435 +++++++++++++++++++++++++++++++++++
 2 files changed, 441 insertions(+), 0 deletions(-)
 create mode 100644 modules/video_output/msw/basicwin.c

diff --git a/configure.ac b/configure.ac
index 3f4f216..fbd7004 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3538,6 +3538,12 @@ then
   VLC_ADD_PLUGIN([panoramix])
 fi
 
+if test "${SYS}" = "mingw32" -o "${SYS}" = "mingwce"
+then
+  VLC_ADD_PLUGIN([basicwin])
+  VLC_ADD_LIBS([basicwin],[-lgdi32])
+fi
+
 AC_ARG_ENABLE(directx,
   [  --enable-directx        Win32 DirectX support (default enabled on Win32)])
 if test "${enable_directx}" != "no"
diff --git a/modules/video_output/msw/basicwin.c b/modules/video_output/msw/basicwin.c
new file mode 100644
index 0000000..2ad1093
--- /dev/null
+++ b/modules/video_output/msw/basicwin.c
@@ -0,0 +1,435 @@
+/**
+ * @file window.c
+ * @brief C Bindings window provider module for VLC media player
+ */
+/*****************************************************************************
+ * Copyright © 2010 Erwan Tulou
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <assert.h>
+
+#include <windows.h>
+#include <windowsx.h>
+#include <shellapi.h>
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_vout_window.h>
+
+
+static int  Open (vlc_object_t *);
+static void Close (vlc_object_t *);
+
+/*
+ * Module descriptor
+ */
+vlc_module_begin ()
+    set_shortname (N_("window"))
+    set_description (N_("video window"))
+    set_category (CAT_VIDEO)
+    set_subcategory (SUBCAT_VIDEO_VOUT)
+    set_capability ("vout window hwnd", 10)
+    set_callbacks (Open, Close)
+
+vlc_module_end ()
+
+static int Control (vout_window_t *, int, va_list ap);
+static void *Thread (void *);
+
+struct vout_window_sys_t
+{
+    /* */
+    vlc_thread_t thread;
+    vlc_mutex_t  lock;
+    vlc_cond_t   wait;
+    bool         ready;
+    bool         error;
+
+    HWND         hwnd;
+    int          i_window_style;
+
+    /* Title */
+    char *psz_title;
+
+    bool use_desktop;
+};
+
+static int Open (vlc_object_t*);
+static void Close (vlc_object_t*);
+static int Control (vout_window_t*, int, va_list);
+
+static void WindowCreate (vout_window_t*);
+static void WindowDelete (vout_window_t*);
+static void StartThread( vout_window_t* );
+static void StopThread( vout_window_t* );
+
+static LRESULT CALLBACK DirectXEventProc( HWND, UINT, WPARAM, LPARAM );
+
+#define IDM_TOGGLE_ON_TOP  (WM_USER + 1)
+
+/**
+ * Create a Win32 window.
+ */
+static int Open (vlc_object_t *obj)
+{
+    vout_window_t *wnd = (vout_window_t *)obj;
+
+    vout_window_sys_t *sys = wnd->sys = calloc ( 1, sizeof (*sys));
+    if (!sys)
+        return VLC_ENOMEM;
+
+    vlc_mutex_init( &sys->lock );
+    vlc_cond_init( &sys->wait );
+
+
+    StartThread( wnd );
+
+    vlc_mutex_lock( &sys->lock );
+    while( !sys->ready )
+        vlc_cond_wait( &sys->wait, &sys->lock );
+    bool error = sys->error;
+    if( error )
+    {
+        msg_Err( wnd, "spawing a thread failed" );
+        StopThread( wnd );
+    }
+    vlc_mutex_unlock( &sys->lock );
+
+    if( error )
+    {
+        free( sys );
+        return VLC_EGENERIC;
+    }
+
+    wnd->handle.hwnd = sys->hwnd;
+    wnd->control = Control;
+
+    fprintf(stderr, "\n\___________FIN OPEN MODDULE SUCCESSFUL");fflush(stderr);
+    return VLC_SUCCESS;
+}
+
+
+/**
+ * Destroys the win32 window.
+ */
+static void Close (vlc_object_t *obj)
+{
+    vout_window_t *wnd = (vout_window_t *)obj;
+    vout_window_sys_t *sys = wnd->sys;
+
+    vlc_mutex_lock( &sys->lock );
+    StopThread( wnd );
+    vlc_mutex_unlock( &sys->lock );
+
+    vlc_cond_destroy ( &sys->wait );
+    vlc_mutex_destroy ( &sys->lock );
+    free (sys);
+}
+
+
+/** thread for win32 events handling */
+static void *Thread (void *data)
+{
+    vout_window_t *wnd = data;
+    vout_window_sys_t *sys = wnd->sys;
+
+    int canc = vlc_savecancel ();
+
+    vlc_mutex_lock( &sys->lock );
+
+    WindowCreate( wnd );
+    if( !sys->hwnd )
+    {
+        sys->error = true;
+        sys->ready = true;
+        vlc_cond_signal( &sys->wait );
+        vlc_mutex_unlock( &sys->lock );
+        return NULL;
+    }
+
+    wnd->handle.hwnd = sys->hwnd;
+    vout_window_SendEventSetup( wnd );
+
+    sys->ready = true;
+    vlc_cond_signal( &sys->wait );
+    vlc_mutex_unlock( &sys->lock );
+
+    /* GetMessage will sleep if there's no message in the queue */
+    MSG msg;
+    while( GetMessage( &msg, 0, 0, 0 ) > 0 )
+    {
+        TranslateMessage(&msg);
+        DispatchMessage(&msg);
+
+    } /* End Main loop */
+
+    msg_Dbg( wnd, "EventThread terminating" );
+
+
+    vlc_mutex_lock( &sys->lock );
+    vout_window_SendEventCleanup( wnd );
+    WindowDelete( wnd );
+    vlc_mutex_unlock( &sys->lock );
+
+    vlc_restorecancel(canc);
+    return NULL;
+}
+
+static int Control (vout_window_t *wnd, int cmd, va_list ap)
+{
+    vout_window_sys_t *sys = wnd->sys;
+
+    switch (cmd)
+    {
+        case VOUT_WINDOW_SET_SIZE:
+        {
+            unsigned width = va_arg (ap, unsigned);
+            unsigned height = va_arg (ap, unsigned);
+
+            SetWindowPos( sys->hwnd, 0, 0, 0, width, height,
+                          SWP_NOMOVE|SWP_NOZORDER|SWP_ASYNCWINDOWPOS);
+            return VLC_EGENERIC;
+        }
+
+        case VOUT_WINDOW_SET_STATE:
+        {
+            unsigned state = va_arg (ap, unsigned);
+            return VLC_EGENERIC;
+        }
+
+        case VOUT_WINDOW_SET_FULLSCREEN:
+        {
+            bool fs = va_arg (ap, int);
+            if (!fs && var_GetBool (wnd, "video-wallpaper"))
+                return VLC_EGENERIC;
+            return VLC_EGENERIC;
+        }
+
+        default:
+            msg_Err (wnd, "request %d not implemented", cmd);
+            return VLC_EGENERIC;
+    }
+}
+
+
+static void WindowCreate( vout_window_t* wnd )
+{
+    vout_window_sys_t *sys = (vout_window_sys_t *)wnd->sys;
+
+    HINSTANCE  hInstance;
+    HMENU      hMenu;
+    RECT       rect_window;
+    WNDCLASS   wc;                            /* window class components */
+    HICON      vlc_icon;
+    char       vlc_path[MAX_PATH+1];
+    int        i_style, i_stylex;
+
+    msg_Dbg( wnd, "WindowCreate" );
+
+/***
+    if( wnd->cfg->use_desktop )
+    {
+        // 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 )
+        {
+            sys->hwnd = hwnd;
+            sys->use_desktop = true;
+            return;
+        }
+        else
+        {
+            msg_Err( wnd, "Couldn't find desktop icon window. "
+                         "Desktop mode can't be established." );
+        }
+    }
+**/
+
+    /* Get this module's instance */
+    hInstance = GetModuleHandle(NULL);
+
+    /* Get the Icon from the main app */
+    vlc_icon = NULL;
+#ifndef UNDER_CE
+    if( GetModuleFileName( NULL, vlc_path, MAX_PATH ) )
+    {
+        vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
+    }
+#endif
+
+    /* Fill in the window class structure */
+    wc.style         = CS_OWNDC|CS_DBLCLKS;          /* style: dbl click */
+    wc.lpfnWndProc   = (WNDPROC)DirectXEventProc;       /* event handler */
+    wc.cbClsExtra    = 0;                         /* no extra class data */
+    wc.cbWndExtra    = 0;                        /* no extra window data */
+    wc.hInstance     = hInstance;                            /* instance */
+    wc.hIcon         = vlc_icon;                /* load the vlc big icon */
+    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);    /* default cursor */
+    wc.hbrBackground = GetStockObject(BLACK_BRUSH);  /* background color */
+    wc.lpszMenuName  = NULL;                                  /* no menu */
+    wc.lpszClassName = _T("VLC basic window");    /* use a special class */
+
+    /* Register the window class */
+    if( !RegisterClass(&wc) )
+    {
+        WNDCLASS wndclass;
+
+        if( vlc_icon )
+            DestroyIcon( vlc_icon );
+
+        /* Check why it failed. If it's because one already exists
+         * then fine, otherwise return with an error. */
+        if( !GetClassInfo( hInstance, _T("VLC basic window"), &wndclass ) )
+        {
+            msg_Err( wnd, "WindowCreate RegisterClass FAILED (err=%lu)",
+                              GetLastError() );
+            return;
+        }
+    }
+
+    /* When you create a window you give the dimensions you wish it to
+     * have. Unfortunatly these dimensions will include the borders and
+     * titlebar. We use the following function to find out the size of
+     * the window corresponding to the useable surface we want */
+    rect_window.left   = 10;
+    rect_window.top    = 10;
+    rect_window.right  = rect_window.left + wnd->cfg->width;
+    rect_window.bottom = rect_window.top  + wnd->cfg->height;
+
+    if( var_GetBool( wnd, "video-deco" ) )
+    {
+        /* Open with window decoration */
+        AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 );
+        i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN;
+        i_stylex = 0;
+    }
+    else
+    {
+        /* No window decoration */
+        AdjustWindowRect( &rect_window, WS_POPUP, 0 );
+        i_style = WS_POPUP|WS_VISIBLE|WS_CLIPCHILDREN;
+        i_stylex = 0; // WS_EX_TOOLWINDOW; Is TOOLWINDOW really needed ?
+                      // It messes up the fullscreen window.
+    }
+
+    sys->i_window_style = i_style;
+
+    /* Create the window */
+    sys->hwnd =
+        CreateWindowEx( WS_EX_NOPARENTNOTIFY | i_stylex,
+                    _T("VLC basic window"),          /* name of window class */
+                    _T(VOUT_TITLE) _T(" (DirectX Output)"),  /* window title */
+                    i_style,                                 /* window style */
+                    (UINT)(wnd->cfg->x),             /* default X coordinate */
+                    (UINT)(wnd->cfg->y),             /* default Y coordinate */
+                    rect_window.right - rect_window.left,    /* window width */
+                    rect_window.bottom - rect_window.top,   /* window height */
+                    NULL,                                   /* parent window */
+                    NULL,                          /* no menu in this window */
+                    hInstance,            /* handle of this program instance */
+                    (LPVOID)NULL );                /* send NULL to WM_CREATE */
+
+    if( !sys->hwnd )
+    {
+        msg_Err( wnd, "WindowCreate create window FAILED (err=%lu)", GetLastError() );
+        return;
+    }
+
+    /* Append a "Always On Top" entry in the system menu */
+    hMenu = GetSystemMenu( sys->hwnd, FALSE );
+    AppendMenu( hMenu, MF_SEPARATOR, 0, _T("") );
+    AppendMenu( hMenu, MF_STRING | MF_UNCHECKED,
+                       IDM_TOGGLE_ON_TOP, _T("Always on &Top") );
+
+    /* Now display the window */
+    ShowWindow( sys->hwnd, SW_SHOW );
+
+    msg_Dbg( wnd, "main window created and displayed" );
+
+}
+
+static void WindowDelete (vout_window_t* wnd)
+{
+    vout_window_sys_t *sys = (vout_window_sys_t *)wnd->sys;
+
+    if( !sys->hwnd || sys->use_desktop )
+        return;
+
+    DestroyWindow( sys->hwnd );
+    sys->hwnd = NULL;
+}
+
+static void StartThread( vout_window_t* wnd )
+{
+    vout_window_sys_t *sys = (vout_window_sys_t *)wnd->sys;
+
+    if( vlc_clone( &sys->thread, Thread, wnd, VLC_THREAD_PRIORITY_LOW ) )
+    {
+        sys->ready = true;
+        sys->error = true;
+        msg_Err( wnd, "cannot create vout window provider thread" );
+    }
+}
+
+static void StopThread( vout_window_t* wnd )
+{
+    vout_window_sys_t *sys = (vout_window_sys_t *)wnd->sys;
+
+    HWND hwnd = sys->hwnd;
+    vlc_thread_t thread = sys->thread;
+
+    if( hwnd )
+        PostMessage ( sys->hwnd, WM_CLOSE, 0, 0 );
+    if( thread )
+        vlc_join ( thread, NULL );
+}
+
+
+static LRESULT CALLBACK DirectXEventProc( HWND hwnd, UINT message,
+                                          WPARAM wParam, LPARAM lParam )
+{
+
+#ifndef UNDER_CE
+    /* Catch the screensaver and the monitor turn-off */
+    if( message == WM_SYSCOMMAND &&
+        ( (wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER ) )
+    {
+        return 0; /* this stops them from happening */
+    }
+#endif
+
+    switch( message )
+    {
+        /* the window has been closed so shut down everything now */
+        case WM_DESTROY:
+            PostQuitMessage( 0 );
+            break;
+    }
+
+    /* Let windows handle the message */
+    return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
-- 
1.5.6.5


