>From 9fcd5b022542443f25a3fb75180e81127f3a34e8 Mon Sep 17 00:00:00 2001 From: Erwan Tulou 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 +#endif + +#include +#include + +#include +#include +#include + +#include +#include +#include + + +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