1 /*****************************************************************************
2 * specific.c: Win32 specific initilization
3 *****************************************************************************
4 * Copyright (C) 2001-2004, 2010 VLC authors and VideoLAN
6 * Authors: Samuel Hocevar <sam@zoy.org>
7 * Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
29 #include <vlc_common.h>
30 #include "../libvlc.h"
31 #include <vlc_playlist.h>
34 #include "../config/vlc_getopt.h"
36 #if !defined( UNDER_CE )
37 # include <mmsystem.h>
42 /*****************************************************************************
43 * system_Init: initialize winsock and misc other things.
44 *****************************************************************************/
45 void system_Init( void )
49 #if !defined( UNDER_CE )
53 /* WinSock Library Init. */
54 if( !WSAStartup( MAKEWORD( 2, 2 ), &Data ) )
56 /* Aah, pretty useless check, we should always have Winsock 2.2
57 * since it appeared in Win98. */
58 if( LOBYTE( Data.wVersion ) != 2 || HIBYTE( Data.wVersion ) != 2 )
59 /* We could not find a suitable WinSock DLL. */
62 /* Everything went ok. */
66 /* Let's try with WinSock 1.1 */
67 if( !WSAStartup( MAKEWORD( 1, 1 ), &Data ) )
69 /* Confirm that the WinSock DLL supports 1.1.*/
70 if( LOBYTE( Data.wVersion ) != 1 || HIBYTE( Data.wVersion ) != 1 )
71 /* We could not find a suitable WinSock DLL. */
74 /* Everything went ok. */
78 fprintf( stderr, "error: can't initialize WinSocks\n" );
81 /*****************************************************************************
82 * system_Configure: check for system specific configuration options.
83 *****************************************************************************/
84 static unsigned __stdcall IPCHelperThread( void * );
85 LRESULT CALLBACK WMCOPYWNDPROC( HWND, UINT, WPARAM, LPARAM );
86 static vlc_object_t *p_helper = NULL;
87 static unsigned long hIPCHelper;
88 static HANDLE hIPCHelperReady;
97 void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_argv[] )
99 #if !defined( UNDER_CE )
100 /* Raise default priority of the current process */
101 #ifndef ABOVE_NORMAL_PRIORITY_CLASS
102 # define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
104 if( var_InheritBool( p_this, "high-priority" ) )
106 if( SetPriorityClass( GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS )
107 || SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) )
109 msg_Dbg( p_this, "raised process priority" );
113 msg_Dbg( p_this, "could not raise process priority" );
117 if( var_InheritBool( p_this, "one-instance" )
118 || ( var_InheritBool( p_this, "one-instance-when-started-from-file" )
119 && var_InheritBool( p_this, "started-from-file" ) ) )
123 msg_Info( p_this, "one instance mode ENABLED");
125 /* Use a named mutex to check if another instance is already running */
126 if( !( hmutex = CreateMutex( 0, TRUE, L"VLC ipc "VERSION ) ) )
128 /* Failed for some reason. Just ignore the option and go on as
130 msg_Err( p_this, "one instance mode DISABLED "
131 "(mutex couldn't be created)" );
135 if( GetLastError() != ERROR_ALREADY_EXISTS )
137 /* We are the 1st instance. */
139 vlc_custom_create( p_this, sizeof(*p_helper), "ipc helper" );
141 /* Run the helper thread */
142 hIPCHelperReady = CreateEvent( NULL, FALSE, FALSE, NULL );
143 hIPCHelper = _beginthreadex( NULL, 0, IPCHelperThread, p_helper,
146 WaitForSingleObject( hIPCHelperReady, INFINITE );
149 msg_Err( p_this, "one instance mode DISABLED "
150 "(IPC helper thread couldn't be created)" );
151 vlc_object_release (p_helper);
154 CloseHandle( hIPCHelperReady );
156 /* Initialization done.
157 * Release the mutex to unblock other instances */
158 ReleaseMutex( hmutex );
162 /* Another instance is running */
166 /* Wait until the 1st instance is initialized */
167 WaitForSingleObject( hmutex, INFINITE );
169 /* Locate the window created by the IPC helper thread of the
171 if( !( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) )
173 msg_Err( p_this, "one instance mode DISABLED "
174 "(couldn't find 1st instance of program)" );
175 ReleaseMutex( hmutex );
179 /* We assume that the remaining parameters are filenames
180 * and their input options */
183 COPYDATASTRUCT wm_data;
185 vlc_ipc_data_t *p_data;
186 size_t i_data = sizeof (*p_data);
188 for( i_opt = 0; i_opt < i_argc; i_opt++ )
190 i_data += sizeof (size_t);
191 i_data += strlen( ppsz_argv[ i_opt ] ) + 1;
194 p_data = malloc( i_data );
195 p_data->argc = i_argc;
196 p_data->enqueue = var_InheritBool( p_this, "playlist-enqueue" );
198 for( i_opt = 0; i_opt < i_argc; i_opt++ )
200 size_t i_len = strlen( ppsz_argv[ i_opt ] ) + 1;
201 /* Windows will never switch to an architecture
202 * with stronger alignment requirements, right. */
203 *((size_t *)(p_data->data + i_data)) = i_len;
204 i_data += sizeof (size_t);
205 memcpy( &p_data->data[i_data], ppsz_argv[ i_opt ], i_len );
208 i_data += sizeof (*p_data);
210 /* Send our playlist items to the 1st instance */
212 wm_data.cbData = i_data;
213 wm_data.lpData = p_data;
214 SendMessage( ipcwindow, WM_COPYDATA, 0, (LPARAM)&wm_data );
217 /* Initialization done.
218 * Release the mutex to unblock other instances */
219 ReleaseMutex( hmutex );
230 static unsigned __stdcall IPCHelperThread( void *data )
232 vlc_object_t *p_this = data;
237 CreateWindow( L"STATIC", /* name of window class */
238 L"VLC ipc "VERSION, /* window title bar text */
239 0, /* window style */
240 0, /* default X coordinate */
241 0, /* default Y coordinate */
242 0, /* window width */
243 0, /* window height */
244 NULL, /* no parent window */
245 NULL, /* no menu in this window */
246 GetModuleHandle(NULL), /* handle of this program instance */
247 NULL ); /* sent to WM_CREATE */
249 SetWindowLongPtr( ipcwindow, GWLP_WNDPROC, (LRESULT)WMCOPYWNDPROC );
250 SetWindowLongPtr( ipcwindow, GWLP_USERDATA, (LONG_PTR)p_this );
252 /* Signal the creation of the thread and events queue */
253 SetEvent( hIPCHelperReady );
255 while( GetMessage( &message, NULL, 0, 0 ) )
257 TranslateMessage( &message );
258 DispatchMessage( &message );
263 LRESULT CALLBACK WMCOPYWNDPROC( HWND hwnd, UINT uMsg, WPARAM wParam,
266 if( uMsg == WM_QUIT )
268 PostQuitMessage( 0 );
270 else if( uMsg == WM_COPYDATA )
272 COPYDATASTRUCT *pwm_data = (COPYDATASTRUCT*)lParam;
273 vlc_object_t *p_this;
274 playlist_t *p_playlist;
276 p_this = (vlc_object_t *)
277 (uintptr_t)GetWindowLongPtr( hwnd, GWLP_USERDATA );
279 if( !p_this ) return 0;
281 /* Add files to the playlist */
282 p_playlist = pl_Get( p_this );
284 if( pwm_data->lpData )
287 vlc_ipc_data_t *p_data = (vlc_ipc_data_t *)pwm_data->lpData;
289 int i_argc = p_data->argc, i_opt, i_options;
291 ppsz_argv = (char **)malloc( i_argc * sizeof(char *) );
292 for( i_opt = 0; i_opt < i_argc; i_opt++ )
294 ppsz_argv[i_opt] = p_data->data + i_data + sizeof(size_t);
295 i_data += sizeof(size_t) + *((size_t *)(p_data->data + i_data));
298 for( i_opt = 0; i_opt < i_argc; i_opt++ )
302 /* Count the input options */
303 while( i_opt + i_options + 1 < i_argc &&
304 *ppsz_argv[ i_opt + i_options + 1 ] == ':' )
309 char *psz_URI = make_URI( ppsz_argv[i_opt], NULL );
310 playlist_AddExt( p_playlist, psz_URI,
311 NULL, PLAYLIST_APPEND |
312 ( ( i_opt || p_data->enqueue ) ? 0 : PLAYLIST_GO ),
315 (char const **)( i_options ? &ppsz_argv[i_opt+1] : NULL ),
316 VLC_INPUT_OPTION_TRUSTED,
327 return DefWindowProc( hwnd, uMsg, wParam, lParam );
330 /*****************************************************************************
331 * system_End: terminate winsock.
332 *****************************************************************************/
333 void system_End( void )
337 /* FIXME: thread-safety... */
340 if( ( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) != 0 )
342 SendMessage( ipcwindow, WM_QUIT, 0, 0 );
344 vlc_object_release (p_helper);
348 #if !defined( UNDER_CE )