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"
40 static int system_InitWSA(int hi, int lo)
44 if (WSAStartup(MAKEWORD(hi, lo), &data) == 0)
46 if (LOBYTE(data.wVersion) == 2 && HIBYTE(data.wVersion) == 2)
48 /* Winsock DLL is not usable */
55 * Initializes MME timer, Winsock.
57 void system_Init(void)
63 if (system_InitWSA(2, 2) && system_InitWSA(1, 1))
64 fputs("Error: cannot initialize Winsocks\n", stderr);
67 /*****************************************************************************
68 * system_Configure: check for system specific configuration options.
69 *****************************************************************************/
70 static unsigned __stdcall IPCHelperThread( void * );
71 LRESULT CALLBACK WMCOPYWNDPROC( HWND, UINT, WPARAM, LPARAM );
72 static vlc_object_t *p_helper = NULL;
73 static unsigned long hIPCHelper;
74 static HANDLE hIPCHelperReady;
83 void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_argv[] )
86 /* Raise default priority of the current process */
87 #ifndef ABOVE_NORMAL_PRIORITY_CLASS
88 # define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
90 if( var_InheritBool( p_this, "high-priority" ) )
92 if( SetPriorityClass( GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS )
93 || SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) )
95 msg_Dbg( p_this, "raised process priority" );
99 msg_Dbg( p_this, "could not raise process priority" );
103 if( var_InheritBool( p_this, "one-instance" )
104 || ( var_InheritBool( p_this, "one-instance-when-started-from-file" )
105 && var_InheritBool( p_this, "started-from-file" ) ) )
109 msg_Info( p_this, "one instance mode ENABLED");
111 /* Use a named mutex to check if another instance is already running */
112 if( !( hmutex = CreateMutex( 0, TRUE, L"VLC ipc " TEXT(VERSION) ) ) )
114 /* Failed for some reason. Just ignore the option and go on as
116 msg_Err( p_this, "one instance mode DISABLED "
117 "(mutex couldn't be created)" );
121 if( GetLastError() != ERROR_ALREADY_EXISTS )
123 /* We are the 1st instance. */
125 vlc_custom_create( p_this, sizeof(*p_helper), "ipc helper" );
127 /* Run the helper thread */
128 hIPCHelperReady = CreateEvent( NULL, FALSE, FALSE, NULL );
129 hIPCHelper = _beginthreadex( NULL, 0, IPCHelperThread, p_helper,
132 WaitForSingleObject( hIPCHelperReady, INFINITE );
135 msg_Err( p_this, "one instance mode DISABLED "
136 "(IPC helper thread couldn't be created)" );
137 vlc_object_release (p_helper);
140 CloseHandle( hIPCHelperReady );
142 /* Initialization done.
143 * Release the mutex to unblock other instances */
144 ReleaseMutex( hmutex );
148 /* Another instance is running */
152 /* Wait until the 1st instance is initialized */
153 WaitForSingleObject( hmutex, INFINITE );
155 /* Locate the window created by the IPC helper thread of the
157 if( !( ipcwindow = FindWindow( 0, L"VLC ipc " TEXT(VERSION) ) ) )
159 msg_Err( p_this, "one instance mode DISABLED "
160 "(couldn't find 1st instance of program)" );
161 ReleaseMutex( hmutex );
165 /* We assume that the remaining parameters are filenames
166 * and their input options */
169 COPYDATASTRUCT wm_data;
171 vlc_ipc_data_t *p_data;
172 size_t i_data = sizeof (*p_data);
174 for( i_opt = 0; i_opt < i_argc; i_opt++ )
176 i_data += sizeof (size_t);
177 i_data += strlen( ppsz_argv[ i_opt ] ) + 1;
180 p_data = malloc( i_data );
181 p_data->argc = i_argc;
182 p_data->enqueue = var_InheritBool( p_this, "playlist-enqueue" );
184 for( i_opt = 0; i_opt < i_argc; i_opt++ )
186 size_t i_len = strlen( ppsz_argv[ i_opt ] ) + 1;
187 /* Windows will never switch to an architecture
188 * with stronger alignment requirements, right. */
189 *((size_t *)(p_data->data + i_data)) = i_len;
190 i_data += sizeof (size_t);
191 memcpy( &p_data->data[i_data], ppsz_argv[ i_opt ], i_len );
194 i_data += sizeof (*p_data);
196 /* Send our playlist items to the 1st instance */
198 wm_data.cbData = i_data;
199 wm_data.lpData = p_data;
200 SendMessage( ipcwindow, WM_COPYDATA, 0, (LPARAM)&wm_data );
203 /* Initialization done.
204 * Release the mutex to unblock other instances */
205 ReleaseMutex( hmutex );
215 #if !VLC_WINSTORE_APP
216 static unsigned __stdcall IPCHelperThread( void *data )
218 vlc_object_t *p_this = data;
223 CreateWindow( L"STATIC", /* name of window class */
224 L"VLC ipc " TEXT(VERSION), /* window title bar text */
225 0, /* window style */
226 0, /* default X coordinate */
227 0, /* default Y coordinate */
228 0, /* window width */
229 0, /* window height */
230 NULL, /* no parent window */
231 NULL, /* no menu in this window */
232 GetModuleHandle(NULL), /* handle of this program instance */
233 NULL ); /* sent to WM_CREATE */
235 SetWindowLongPtr( ipcwindow, GWLP_WNDPROC, (LRESULT)WMCOPYWNDPROC );
236 SetWindowLongPtr( ipcwindow, GWLP_USERDATA, (LONG_PTR)p_this );
238 /* Signal the creation of the thread and events queue */
239 SetEvent( hIPCHelperReady );
241 while( GetMessage( &message, NULL, 0, 0 ) )
243 TranslateMessage( &message );
244 DispatchMessage( &message );
249 LRESULT CALLBACK WMCOPYWNDPROC( HWND hwnd, UINT uMsg, WPARAM wParam,
252 if( uMsg == WM_QUIT )
254 PostQuitMessage( 0 );
256 else if( uMsg == WM_COPYDATA )
258 COPYDATASTRUCT *pwm_data = (COPYDATASTRUCT*)lParam;
259 vlc_object_t *p_this;
260 playlist_t *p_playlist;
262 p_this = (vlc_object_t *)
263 (uintptr_t)GetWindowLongPtr( hwnd, GWLP_USERDATA );
265 if( !p_this ) return 0;
267 /* Add files to the playlist */
268 p_playlist = pl_Get( p_this );
270 if( pwm_data->lpData )
273 vlc_ipc_data_t *p_data = (vlc_ipc_data_t *)pwm_data->lpData;
275 int i_argc = p_data->argc, i_opt, i_options;
277 ppsz_argv = (char **)malloc( i_argc * sizeof(char *) );
278 for( i_opt = 0; i_opt < i_argc; i_opt++ )
280 ppsz_argv[i_opt] = p_data->data + i_data + sizeof(size_t);
281 i_data += sizeof(size_t) + *((size_t *)(p_data->data + i_data));
284 for( i_opt = 0; i_opt < i_argc; i_opt++ )
288 /* Count the input options */
289 while( i_opt + i_options + 1 < i_argc &&
290 *ppsz_argv[ i_opt + i_options + 1 ] == ':' )
295 #warning URI conversion must be done in calling process instead!
296 /* FIXME: This breaks relative paths if calling vlc.exe is
297 * started from a different working directory. */
298 char *psz_URI = NULL;
299 if( strstr( ppsz_argv[i_opt], "://" ) == NULL )
300 psz_URI = vlc_path2uri( ppsz_argv[i_opt], NULL );
301 playlist_AddExt( p_playlist,
302 (psz_URI != NULL) ? psz_URI : ppsz_argv[i_opt],
303 NULL, PLAYLIST_APPEND |
304 ( ( i_opt || p_data->enqueue ) ? 0 : PLAYLIST_GO ),
307 (char const **)( i_options ? &ppsz_argv[i_opt+1] : NULL ),
308 VLC_INPUT_OPTION_TRUSTED,
319 return DefWindowProc( hwnd, uMsg, wParam, lParam );
324 * Cleans up after system_Init() and system_Configure().
326 void system_End(void)
328 #if !VLC_WINSTORE_APP
331 /* FIXME: thread-safety... */
334 if( ( ipcwindow = FindWindow( 0, L"VLC ipc " TEXT(VERSION) ) ) != 0 )
336 SendMessage( ipcwindow, WM_QUIT, 0, 0 );
338 vlc_object_release (p_helper);
345 /* XXX: In theory, we should not call this if WSAStartup() failed. */