vlc/modules/control/win_msg.c

214 lines
6.9 KiB
C

/*****************************************************************************
* 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
#define VLC_MODULE_LICENSE VLC_LICENSE_GPL_2_PLUS
#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 <vlc_input_item.h>
#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 void add_to_playlist(intf_thread_t *intf, const char *uri,
bool play_now, int options_count,
const char *const *options)
{
vlc_playlist_t *playlist = vlc_intf_GetMainPlaylist(intf);
input_item_t *media = input_item_New(uri, NULL);
if (!media)
return;
input_item_AddOptions(media, options_count, options, VLC_INPUT_OPTION_TRUSTED);
vlc_playlist_Lock(playlist);
vlc_playlist_AppendOne(playlist, media);
if (play_now)
vlc_playlist_Start(playlist);
vlc_playlist_Unlock(playlist);
input_item_Release(media);
}
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 = vlc_alloc( 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 );
add_to_playlist(intf, (psz_URI != NULL) ? psz_URI : ppsz_argv[i_opt],
(i_opt == 0 && !p_data->enqueue), i_options,
(char const **)( i_options ? &ppsz_argv[i_opt+1] : NULL ));
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;
vlc_thread_set_name("vlc-ctrl-win");
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))
{
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_("WinMsg"))
set_description(N_("Windows messages interface"))
set_subcategory(SUBCAT_INTERFACE_CONTROL)
set_capability("interface", 0)
set_callbacks(Open, Close)
vlc_module_end()