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)
61 if (system_InitWSA(2, 2) && system_InitWSA(1, 1))
62 fputs("Error: cannot initialize Winsocks\n", stderr);
65 /*****************************************************************************
66 * system_Configure: check for system specific configuration options.
67 *****************************************************************************/
68 static unsigned __stdcall IPCHelperThread( void * );
69 LRESULT CALLBACK WMCOPYWNDPROC( HWND, UINT, WPARAM, LPARAM );
70 static vlc_object_t *p_helper = NULL;
71 static unsigned long hIPCHelper;
72 static HANDLE hIPCHelperReady;
81 void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_argv[] )
83 #if !defined(WINAPI_FAMILY_APP)
84 /* Raise default priority of the current process */
85 #ifndef ABOVE_NORMAL_PRIORITY_CLASS
86 # define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
88 if( var_InheritBool( p_this, "high-priority" ) )
90 if( SetPriorityClass( GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS )
91 || SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) )
93 msg_Dbg( p_this, "raised process priority" );
97 msg_Dbg( p_this, "could not raise process priority" );
101 if( var_InheritBool( p_this, "one-instance" )
102 || ( var_InheritBool( p_this, "one-instance-when-started-from-file" )
103 && var_InheritBool( p_this, "started-from-file" ) ) )
107 msg_Info( p_this, "one instance mode ENABLED");
109 /* Use a named mutex to check if another instance is already running */
110 if( !( hmutex = CreateMutex( 0, TRUE, L"VLC ipc "VERSION ) ) )
112 /* Failed for some reason. Just ignore the option and go on as
114 msg_Err( p_this, "one instance mode DISABLED "
115 "(mutex couldn't be created)" );
119 if( GetLastError() != ERROR_ALREADY_EXISTS )
121 /* We are the 1st instance. */
123 vlc_custom_create( p_this, sizeof(*p_helper), "ipc helper" );
125 /* Run the helper thread */
126 hIPCHelperReady = CreateEvent( NULL, FALSE, FALSE, NULL );
127 hIPCHelper = _beginthreadex( NULL, 0, IPCHelperThread, p_helper,
130 WaitForSingleObject( hIPCHelperReady, INFINITE );
133 msg_Err( p_this, "one instance mode DISABLED "
134 "(IPC helper thread couldn't be created)" );
135 vlc_object_release (p_helper);
138 CloseHandle( hIPCHelperReady );
140 /* Initialization done.
141 * Release the mutex to unblock other instances */
142 ReleaseMutex( hmutex );
146 /* Another instance is running */
150 /* Wait until the 1st instance is initialized */
151 WaitForSingleObject( hmutex, INFINITE );
153 /* Locate the window created by the IPC helper thread of the
155 if( !( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) )
157 msg_Err( p_this, "one instance mode DISABLED "
158 "(couldn't find 1st instance of program)" );
159 ReleaseMutex( hmutex );
163 /* We assume that the remaining parameters are filenames
164 * and their input options */
167 COPYDATASTRUCT wm_data;
169 vlc_ipc_data_t *p_data;
170 size_t i_data = sizeof (*p_data);
172 for( i_opt = 0; i_opt < i_argc; i_opt++ )
174 i_data += sizeof (size_t);
175 i_data += strlen( ppsz_argv[ i_opt ] ) + 1;
178 p_data = malloc( i_data );
179 p_data->argc = i_argc;
180 p_data->enqueue = var_InheritBool( p_this, "playlist-enqueue" );
182 for( i_opt = 0; i_opt < i_argc; i_opt++ )
184 size_t i_len = strlen( ppsz_argv[ i_opt ] ) + 1;
185 /* Windows will never switch to an architecture
186 * with stronger alignment requirements, right. */
187 *((size_t *)(p_data->data + i_data)) = i_len;
188 i_data += sizeof (size_t);
189 memcpy( &p_data->data[i_data], ppsz_argv[ i_opt ], i_len );
192 i_data += sizeof (*p_data);
194 /* Send our playlist items to the 1st instance */
196 wm_data.cbData = i_data;
197 wm_data.lpData = p_data;
198 SendMessage( ipcwindow, WM_COPYDATA, 0, (LPARAM)&wm_data );
201 /* Initialization done.
202 * Release the mutex to unblock other instances */
203 ReleaseMutex( hmutex );
213 #if !defined(WINAPI_FAMILY_APP)
214 static unsigned __stdcall IPCHelperThread( void *data )
216 vlc_object_t *p_this = data;
221 CreateWindow( L"STATIC", /* name of window class */
222 L"VLC ipc "VERSION, /* window title bar text */
223 0, /* window style */
224 0, /* default X coordinate */
225 0, /* default Y coordinate */
226 0, /* window width */
227 0, /* window height */
228 NULL, /* no parent window */
229 NULL, /* no menu in this window */
230 GetModuleHandle(NULL), /* handle of this program instance */
231 NULL ); /* sent to WM_CREATE */
233 SetWindowLongPtr( ipcwindow, GWLP_WNDPROC, (LRESULT)WMCOPYWNDPROC );
234 SetWindowLongPtr( ipcwindow, GWLP_USERDATA, (LONG_PTR)p_this );
236 /* Signal the creation of the thread and events queue */
237 SetEvent( hIPCHelperReady );
239 while( GetMessage( &message, NULL, 0, 0 ) )
241 TranslateMessage( &message );
242 DispatchMessage( &message );
247 LRESULT CALLBACK WMCOPYWNDPROC( HWND hwnd, UINT uMsg, WPARAM wParam,
250 if( uMsg == WM_QUIT )
252 PostQuitMessage( 0 );
254 else if( uMsg == WM_COPYDATA )
256 COPYDATASTRUCT *pwm_data = (COPYDATASTRUCT*)lParam;
257 vlc_object_t *p_this;
258 playlist_t *p_playlist;
260 p_this = (vlc_object_t *)
261 (uintptr_t)GetWindowLongPtr( hwnd, GWLP_USERDATA );
263 if( !p_this ) return 0;
265 /* Add files to the playlist */
266 p_playlist = pl_Get( p_this );
268 if( pwm_data->lpData )
271 vlc_ipc_data_t *p_data = (vlc_ipc_data_t *)pwm_data->lpData;
273 int i_argc = p_data->argc, i_opt, i_options;
275 ppsz_argv = (char **)malloc( i_argc * sizeof(char *) );
276 for( i_opt = 0; i_opt < i_argc; i_opt++ )
278 ppsz_argv[i_opt] = p_data->data + i_data + sizeof(size_t);
279 i_data += sizeof(size_t) + *((size_t *)(p_data->data + i_data));
282 for( i_opt = 0; i_opt < i_argc; i_opt++ )
286 /* Count the input options */
287 while( i_opt + i_options + 1 < i_argc &&
288 *ppsz_argv[ i_opt + i_options + 1 ] == ':' )
293 #warning URI conversion must be done in calling process instead!
294 /* FIXME: This breaks relative paths if calling vlc.exe is
295 * started from a different working directory. */
296 char *psz_URI = NULL;
297 if( strstr( ppsz_argv[i_opt], "://" ) == NULL )
298 psz_URI = vlc_path2uri( ppsz_argv[i_opt], NULL );
299 playlist_AddExt( p_playlist,
300 (psz_URI != NULL) ? psz_URI : ppsz_argv[i_opt],
301 NULL, PLAYLIST_APPEND |
302 ( ( i_opt || p_data->enqueue ) ? 0 : PLAYLIST_GO ),
305 (char const **)( i_options ? &ppsz_argv[i_opt+1] : NULL ),
306 VLC_INPUT_OPTION_TRUSTED,
317 return DefWindowProc( hwnd, uMsg, wParam, lParam );
322 * Cleans up after system_Init() and system_Configure().
324 void system_End(void)
326 #if !defined(WINAPI_FAMILY_APP)
329 /* FIXME: thread-safety... */
332 if( ( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) != 0 )
334 SendMessage( ipcwindow, WM_QUIT, 0, 0 );
336 vlc_object_release (p_helper);
343 /* XXX: In theory, we should not call this if WSAStartup() failed. */