1 /*****************************************************************************
2 * specific.c: OS/2 specific features
3 *****************************************************************************
4 * Copyright (C) 2010 KO Myung-Hun
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
25 #include <vlc_common.h>
26 #include "../libvlc.h"
27 #include <vlc_playlist.h>
33 #define VLC_IPC_PIPE "\\PIPE\\VLC\\IPC\\"VERSION
35 #define IPC_CMD_GO 0x00
36 #define IPC_CMD_ENQUEUE 0x01
37 #define IPC_CMD_QUIT 0xFF
39 extern int _fmode_bin;
41 static HPIPE hpipeIPC = NULLHANDLE;
42 static int tidIPCFirst = -1;
43 static int tidIPCHelper = -1;
45 static void IPCHelperThread( void *arg )
47 vlc_object_t *p_this = arg;
56 /* Add files to the playlist */
57 playlist_t *p_playlist = pl_Get( p_this );
61 DosConnectNPipe( hpipeIPC );
64 DosRead( hpipeIPC, &ulCmd, sizeof( ulCmd ), &cbActual );
65 if( ulCmd == IPC_CMD_QUIT )
68 /* Read a count of arguments */
69 DosRead( hpipeIPC, &i_argc, sizeof( i_argc ), &cbActual );
71 ppsz_argv = malloc( i_argc * sizeof( *ppsz_argv ));
73 for( int i_opt = 0; i_opt < i_argc; i_opt++ )
75 /* Read a length of argv */
76 DosRead( hpipeIPC, &i_len, sizeof( i_len ), &cbActual );
78 ppsz_argv[ i_opt ] = malloc( i_len );
81 DosRead( hpipeIPC, ppsz_argv[ i_opt ], i_len, &cbActual );
84 for( int i_opt = 0; i_opt < i_argc;)
88 /* Count the input options */
89 while( i_opt + i_options + 1 < i_argc &&
90 *ppsz_argv[ i_opt + i_options + 1 ] == ':' )
93 playlist_AddExt( p_playlist, ppsz_argv[ i_opt ], NULL,
95 (( i_opt || ulCmd == IPC_CMD_ENQUEUE ) ?
97 PLAYLIST_END, -1, i_options,
99 ( i_options ? &ppsz_argv[ i_opt + 1 ] :
101 VLC_INPUT_OPTION_TRUSTED,
104 for( ; i_options >= 0; i_options-- )
105 free( ppsz_argv[ i_opt++ ]);
109 } while( !DosDisConnectNPipe( hpipeIPC ) && ulCmd != IPC_CMD_QUIT );
111 vlc_object_release( p_this );
113 DosClose( hpipeIPC );
114 hpipeIPC = NULLHANDLE;
120 void system_Init( void )
122 /* Set the default file-translation mode */
124 setmode( fileno( stdin ), O_BINARY ); /* Needed for pipes */
127 void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_argv[] )
129 if( var_InheritBool( p_this, "high-priority" ) )
131 if( !DosSetPriority( PRTYS_PROCESS, PRTYC_REGULAR, PRTYD_MAXIMUM, 0 ) )
133 msg_Dbg( p_this, "raised process priority" );
137 msg_Dbg( p_this, "could not raise process priority" );
141 if( var_InheritBool( p_this, "one-instance" )
142 || ( var_InheritBool( p_this, "one-instance-when-started-from-file" )
143 && var_InheritBool( p_this, "started-from-file" ) ) )
149 msg_Info( p_this, "one instance mode ENABLED");
151 /* Use a named pipe to check if another instance is already running */
154 rc = DosOpen( VLC_IPC_PIPE, &hpipe, &ulAction, 0, 0,
155 OPEN_ACTION_OPEN_IF_EXISTS,
156 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE |
157 OPEN_FLAGS_FAIL_ON_ERROR,
160 if( rc == ERROR_PIPE_BUSY )
161 DosWaitNPipe( VLC_IPC_PIPE, -1 );
168 rc = DosCreateNPipe( VLC_IPC_PIPE, &hpipeIPC,
170 NP_WAIT | NP_TYPE_MESSAGE |
171 NP_READMODE_MESSAGE | 0x01,
175 /* Failed to create a named pipe. Just ignore the option and
176 * go on as normal. */
177 msg_Err( p_this, "one instance mode DISABLED "
178 "(a named pipe couldn't be created)" );
182 /* We are the 1st instance. */
183 vlc_object_t* p_helper = vlc_custom_create( p_this,
187 /* Save the tid of the first instance */
188 tidIPCFirst = _gettid();
190 /* Run the helper thread */
191 tidIPCHelper = _beginthread( IPCHelperThread, NULL, 1024 * 1024,
193 if( tidIPCHelper == -1 )
195 msg_Err( p_this, "one instance mode DISABLED "
196 "(IPC helper thread couldn't be created)");
197 vlc_object_release( p_helper );
204 /* Another instance is running */
205 ULONG ulCmd = var_InheritBool( p_this, "playlist-enqueue") ?
206 IPC_CMD_ENQUEUE : IPC_CMD_GO;
209 /* Write a command */
210 DosWrite( hpipe, &ulCmd, sizeof( ulCmd ), &cbActual );
212 /* We assume that the remaining parameters are filenames
213 * and their input options */
215 /* Write a count of arguments */
216 DosWrite( hpipe, &i_argc, sizeof( i_argc ), &cbActual );
218 for( int i_opt = 0; i_opt < i_argc; i_opt++ )
220 /* We need to resolve relative paths in this instance */
222 if( strstr( ppsz_argv[ i_opt ], "://" ))
223 mrl = strdup( ppsz_argv[ i_opt ] );
225 mrl = vlc_path2uri( ppsz_argv[ i_opt ], NULL );
228 mrl = ( char * )ppsz_argv[ i_opt ];
230 size_t i_len = strlen( mrl ) + 1;
232 /* Write a length of an argument */
233 DosWrite( hpipe, &i_len, sizeof( i_len ), &cbActual );
235 /* Write an argument */
236 DosWrite( hpipe, mrl, i_len, &cbActual );
238 if( mrl != ppsz_argv[ i_opt ])
242 /* Close a named pipe of a client side */
253 * Cleans up after system_Init() and system_Configure().
255 void system_End(void)
257 if( tidIPCFirst == _gettid())
266 rc = DosOpen( VLC_IPC_PIPE, &hpipe, &ulAction, 0, 0,
267 OPEN_ACTION_OPEN_IF_EXISTS,
268 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE |
269 OPEN_FLAGS_FAIL_ON_ERROR,
272 if( rc == ERROR_PIPE_BUSY )
273 DosWaitNPipe( VLC_IPC_PIPE, -1 );
278 /* Ask for IPCHelper to quit */
279 ULONG ulCmd = IPC_CMD_QUIT;
280 DosWrite( hpipe, &ulCmd, sizeof( ulCmd ), &cbActual );
284 TID tid = tidIPCHelper;
285 DosWaitThread( &tid, DCWW_WAIT );