Commit 36ac118c authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

win32: move single instance back-end to separate interface

parent 9a144c02
...@@ -55,6 +55,7 @@ control_LTLIBRARIES += libxcb_hotkeys_plugin.la ...@@ -55,6 +55,7 @@ control_LTLIBRARIES += libxcb_hotkeys_plugin.la
endif endif
libwin_hotkeys_plugin_la_SOURCES = globalhotkeys/win32.c libwin_hotkeys_plugin_la_SOURCES = globalhotkeys/win32.c
libwin_msg_plugin_la_SOURCES = win_msg.c
if HAVE_WIN32 if HAVE_WIN32
control_LTLIBRARIES += libwin_hotkeys_plugin.la control_LTLIBRARIES += libwin_hotkeys_plugin.la libwin_msg_plugin.la
endif endif
/*****************************************************************************
* ntservice.c: Windows NT/2K/XP service interface
*****************************************************************************
* Copyright (C) 2001-2004, 2010 VLC authors and VideoLAN
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Gildas Bazin <gbazin@videolan.org>
*
* 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_common.h>
#include <vlc_plugin.h>
#include <vlc_interface.h>
#include <vlc_playlist.h>
#include <vlc_url.h> // FIXME: move URL generation to calling process
#include <windows.h>
struct intf_sys_t
{
HWND window;
HANDLE ready;
vlc_thread_t thread;
};
/* Must be same as in src/win32/specific.c */
typedef struct
{
int argc;
int enqueue;
char data[];
} vlc_ipc_data_t;
static LRESULT CALLBACK WMCOPYWNDPROC(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
if( uMsg == WM_QUIT )
{
PostQuitMessage( 0 );
}
else if( uMsg == WM_COPYDATA )
{
COPYDATASTRUCT *pwm_data = (COPYDATASTRUCT*)lParam;
intf_thread_t *intf = (intf_thread_t *)(uintptr_t)
GetWindowLongPtr( hwnd, GWLP_USERDATA );
if( intf == NULL )
return 0; /* XXX: is this even possible? */
/* Add files to the playlist */
if( pwm_data->lpData )
{
char **ppsz_argv;
vlc_ipc_data_t *p_data = (vlc_ipc_data_t *)pwm_data->lpData;
size_t i_data = 0;
int i_argc = p_data->argc, i_opt, i_options;
ppsz_argv = (char **)malloc( i_argc * sizeof(char *) );
for( i_opt = 0; i_opt < i_argc; i_opt++ )
{
ppsz_argv[i_opt] = p_data->data + i_data + sizeof(size_t);
i_data += sizeof(size_t) + *((size_t *)(p_data->data + i_data));
}
for( i_opt = 0; i_opt < i_argc; i_opt++ )
{
i_options = 0;
/* Count the input options */
while( i_opt + i_options + 1 < i_argc &&
*ppsz_argv[ i_opt + i_options + 1 ] == ':' )
{
i_options++;
}
#warning URI conversion must be done in calling process instead!
/* FIXME: This breaks relative paths if calling vlc.exe is
* started from a different working directory. */
char *psz_URI = NULL;
if( strstr( ppsz_argv[i_opt], "://" ) == NULL )
psz_URI = vlc_path2uri( ppsz_argv[i_opt], NULL );
playlist_AddExt( pl_Get(intf),
(psz_URI != NULL) ? psz_URI : ppsz_argv[i_opt],
NULL, PLAYLIST_APPEND |
( ( i_opt || p_data->enqueue ) ? 0 : PLAYLIST_GO ),
PLAYLIST_END, -1,
i_options,
(char const **)( i_options ? &ppsz_argv[i_opt+1] : NULL ),
VLC_INPUT_OPTION_TRUSTED,
true, pl_Unlocked );
i_opt += i_options;
free( psz_URI );
}
free( ppsz_argv );
}
}
return DefWindowProc( hwnd, uMsg, wParam, lParam );
}
static void *HelperThread(void *data)
{
intf_thread_t *intf = data;
intf_sys_t *sys = intf->p_sys;
HWND ipcwindow =
CreateWindow(L"STATIC", /* name of window class */
L"VLC ipc " TEXT(VERSION), /* window title bar text */
0, /* window style */
0, /* default X coordinate */
0, /* default Y coordinate */
0, /* window width */
0, /* window height */
NULL, /* no parent window */
NULL, /* no menu in this window */
GetModuleHandle(NULL), /* handle of this program instance */
NULL) ; /* sent to WM_CREATE */
SetWindowLongPtr(ipcwindow, GWLP_WNDPROC, (LRESULT)WMCOPYWNDPROC);
SetWindowLongPtr(ipcwindow, GWLP_USERDATA, (uintptr_t)data);
sys->window = ipcwindow;
/* Signal the creation of the thread and events queue */
SetEvent(sys->ready);
MSG message;
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return NULL;
}
static int Open(vlc_object_t *obj)
{
intf_thread_t *intf = (intf_thread_t *)obj;
intf_sys_t *sys = malloc(sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
intf->p_sys = sys;
/* Run the helper thread */
sys->ready = CreateEvent(NULL, FALSE, FALSE, NULL);
if (vlc_clone(&sys->thread, HelperThread, intf, VLC_THREAD_PRIORITY_LOW))
{
free(sys);
msg_Err(intf, "one instance mode DISABLED "
"(IPC helper thread couldn't be created)");
return VLC_ENOMEM;
}
WaitForSingleObject(sys->ready, INFINITE);
CloseHandle(sys->ready);
return VLC_SUCCESS;
}
static void Close(vlc_object_t *obj)
{
intf_thread_t *intf = (intf_thread_t *)obj;
intf_sys_t *sys = intf->p_sys;
SendMessage(sys->window, WM_QUIT, 0, 0);
vlc_join(sys->thread, NULL);
free(sys);
}
vlc_module_begin()
set_shortname(N_("Windows "))
set_description(N_("Windows Service interface"))
set_category(CAT_INTERFACE)
set_subcategory(SUBCAT_INTERFACE_CONTROL)
set_capability("interface", 0)
set_callbacks(Open, Close)
vlc_module_end()
...@@ -27,11 +27,9 @@ ...@@ -27,11 +27,9 @@
#define UNICODE #define UNICODE
#include <vlc_common.h> #include <vlc_common.h>
#include "../libvlc.h" #include "libvlc.h"
#include <vlc_playlist.h> #include "../lib/libvlc_internal.h"
#include <vlc_url.h> #include "config/vlc_getopt.h"
#include "../config/vlc_getopt.h"
#include <mmsystem.h> #include <mmsystem.h>
#include <winsock.h> #include <winsock.h>
...@@ -67,12 +65,8 @@ void system_Init(void) ...@@ -67,12 +65,8 @@ void system_Init(void)
/***************************************************************************** /*****************************************************************************
* system_Configure: check for system specific configuration options. * system_Configure: check for system specific configuration options.
*****************************************************************************/ *****************************************************************************/
static unsigned __stdcall IPCHelperThread( void * );
LRESULT CALLBACK WMCOPYWNDPROC( HWND, UINT, WPARAM, LPARAM );
static vlc_object_t *p_helper = NULL;
static unsigned long hIPCHelper;
static HANDLE hIPCHelperReady;
/* Must be same as in modules/control/win_msg.c */
typedef struct typedef struct
{ {
int argc; int argc;
...@@ -120,25 +114,7 @@ void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_ ...@@ -120,25 +114,7 @@ void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_
if( GetLastError() != ERROR_ALREADY_EXISTS ) if( GetLastError() != ERROR_ALREADY_EXISTS )
{ {
/* We are the 1st instance. */ libvlc_InternalAddIntf( p_this, "win32msg,none" );
p_helper =
vlc_custom_create( p_this, sizeof(*p_helper), "ipc helper" );
/* Run the helper thread */
hIPCHelperReady = CreateEvent( NULL, FALSE, FALSE, NULL );
hIPCHelper = _beginthreadex( NULL, 0, IPCHelperThread, p_helper,
0, NULL );
if( hIPCHelper )
WaitForSingleObject( hIPCHelperReady, INFINITE );
else
{
msg_Err( p_this, "one instance mode DISABLED "
"(IPC helper thread couldn't be created)" );
vlc_object_release (p_helper);
p_helper = NULL;
}
CloseHandle( hIPCHelperReady );
/* Initialization done. /* Initialization done.
* Release the mutex to unblock other instances */ * Release the mutex to unblock other instances */
ReleaseMutex( hmutex ); ReleaseMutex( hmutex );
...@@ -212,133 +188,12 @@ void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_ ...@@ -212,133 +188,12 @@ void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_
#endif #endif
} }
#if !VLC_WINSTORE_APP
static unsigned __stdcall IPCHelperThread( void *data )
{
vlc_object_t *p_this = data;
HWND ipcwindow;
MSG message;
ipcwindow =
CreateWindow( L"STATIC", /* name of window class */
L"VLC ipc " TEXT(VERSION), /* window title bar text */
0, /* window style */
0, /* default X coordinate */
0, /* default Y coordinate */
0, /* window width */
0, /* window height */
NULL, /* no parent window */
NULL, /* no menu in this window */
GetModuleHandle(NULL), /* handle of this program instance */
NULL ); /* sent to WM_CREATE */
SetWindowLongPtr( ipcwindow, GWLP_WNDPROC, (LRESULT)WMCOPYWNDPROC );
SetWindowLongPtr( ipcwindow, GWLP_USERDATA, (LONG_PTR)p_this );
/* Signal the creation of the thread and events queue */
SetEvent( hIPCHelperReady );
while( GetMessage( &message, NULL, 0, 0 ) )
{
TranslateMessage( &message );
DispatchMessage( &message );
}
return 0;
}
LRESULT CALLBACK WMCOPYWNDPROC( HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam )
{
if( uMsg == WM_QUIT )
{
PostQuitMessage( 0 );
}
else if( uMsg == WM_COPYDATA )
{
COPYDATASTRUCT *pwm_data = (COPYDATASTRUCT*)lParam;
vlc_object_t *p_this;
playlist_t *p_playlist;
p_this = (vlc_object_t *)
(uintptr_t)GetWindowLongPtr( hwnd, GWLP_USERDATA );
if( !p_this ) return 0;
/* Add files to the playlist */
p_playlist = pl_Get( p_this );
if( pwm_data->lpData )
{
char **ppsz_argv;
vlc_ipc_data_t *p_data = (vlc_ipc_data_t *)pwm_data->lpData;
size_t i_data = 0;
int i_argc = p_data->argc, i_opt, i_options;
ppsz_argv = (char **)malloc( i_argc * sizeof(char *) );
for( i_opt = 0; i_opt < i_argc; i_opt++ )
{
ppsz_argv[i_opt] = p_data->data + i_data + sizeof(size_t);
i_data += sizeof(size_t) + *((size_t *)(p_data->data + i_data));
}
for( i_opt = 0; i_opt < i_argc; i_opt++ )
{
i_options = 0;
/* Count the input options */
while( i_opt + i_options + 1 < i_argc &&
*ppsz_argv[ i_opt + i_options + 1 ] == ':' )
{
i_options++;
}
#warning URI conversion must be done in calling process instead!
/* FIXME: This breaks relative paths if calling vlc.exe is
* started from a different working directory. */
char *psz_URI = NULL;
if( strstr( ppsz_argv[i_opt], "://" ) == NULL )
psz_URI = vlc_path2uri( ppsz_argv[i_opt], NULL );
playlist_AddExt( p_playlist,
(psz_URI != NULL) ? psz_URI : ppsz_argv[i_opt],
NULL, PLAYLIST_APPEND |
( ( i_opt || p_data->enqueue ) ? 0 : PLAYLIST_GO ),
PLAYLIST_END, -1,
i_options,
(char const **)( i_options ? &ppsz_argv[i_opt+1] : NULL ),
VLC_INPUT_OPTION_TRUSTED,
true, pl_Unlocked );
i_opt += i_options;
free( psz_URI );
}
free( ppsz_argv );
}
}
return DefWindowProc( hwnd, uMsg, wParam, lParam );
}
#endif
/** /**
* Cleans up after system_Init() and system_Configure(). * Cleans up after system_Init() and system_Configure().
*/ */
void system_End(void) void system_End(void)
{ {
#if !VLC_WINSTORE_APP #if !VLC_WINSTORE_APP
HWND ipcwindow;
/* FIXME: thread-safety... */
if (p_helper)
{
if( ( ipcwindow = FindWindow( 0, L"VLC ipc " TEXT(VERSION) ) ) != 0 )
{
SendMessage( ipcwindow, WM_QUIT, 0, 0 );
}
vlc_object_release (p_helper);
p_helper = NULL;
}
timeEndPeriod(5); timeEndPeriod(5);
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment