Commit 00c5b9f8 authored by KO Myung-Hun's avatar KO Myung-Hun Committed by Jean-Baptiste Kempf

OS/2: implement one-instance feature

Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent b4bbf339
......@@ -1078,12 +1078,12 @@ static const char *const ppsz_prefres[] = {
"Log all VLC messages to syslog (UNIX systems)." )
#define ONEINSTANCE_TEXT N_("Allow only one running instance")
#if defined( WIN32 )
#if defined( WIN32 ) || defined( __OS2__ )
#define ONEINSTANCE_LONGTEXT N_( \
"Allowing only one running instance of VLC can sometimes be useful, " \
"for example if you associated VLC with some media types and you " \
"don't want a new instance of VLC to be opened each time you " \
"double-click on a file in the explorer. This option will allow you " \
"open a file in your file manager. This option will allow you " \
"to play the file with the already running instance or enqueue it.")
#elif defined( HAVE_DBUS )
#define ONEINSTANCE_LONGTEXT N_( \
......@@ -2044,7 +2044,7 @@ vlc_module_begin ()
add_bool( "playlist-autostart", true,
AUTOSTART_TEXT, AUTOSTART_LONGTEXT, false )
add_bool( "playlist-cork", true, CORK_TEXT, CORK_LONGTEXT, false )
#if defined(WIN32) || defined(HAVE_DBUS)
#if defined(WIN32) || defined(HAVE_DBUS) || defined(__OS2__)
add_bool( "one-instance", 0, ONEINSTANCE_TEXT,
ONEINSTANCE_LONGTEXT, true )
add_bool( "started-from-file", 0, STARTEDFROMFILE_TEXT,
......
......@@ -662,7 +662,7 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
module_EndBank (true);
vlc_DeinitActions( p_libvlc, priv->actions );
#ifdef WIN32
#if defined(WIN32) || defined(__OS2__)
system_End( );
#endif
}
......
......@@ -41,10 +41,12 @@ size_t vlc_towc (const char *str, uint32_t *restrict pwc);
*/
void system_Init ( void );
void system_Configure ( libvlc_int_t *, int, const char *const [] );
#ifdef WIN32
#if defined(WIN32) || defined(__OS2__)
void system_End(void);
#ifndef __OS2__
size_t EnumClockSource( vlc_object_t *, const char *, char ***, char *** );
#endif
#endif
void vlc_CPU_init(void);
void vlc_CPU_dump(vlc_object_t *);
......
......@@ -24,12 +24,99 @@
#include <vlc_common.h>
#include "../libvlc.h"
#include <vlc_playlist.h>
#include <vlc_url.h>
#include <fcntl.h>
#include <io.h>
#define VLC_IPC_PIPE "\\PIPE\\VLC\\IPC\\"VERSION
#define IPC_CMD_GO 0x00
#define IPC_CMD_ENQUEUE 0x01
#define IPC_CMD_QUIT 0xFF
extern int _fmode_bin;
static HPIPE hpipeIPC = NULLHANDLE;
static int tidIPCFirst = -1;
static int tidIPCHelper = -1;
static void IPCHelperThread( void *arg )
{
vlc_object_t *p_this = arg;
ULONG ulCmd;
int i_argc;
char **ppsz_argv;
size_t i_len;
ULONG cbActual;
int i_options;
/* Add files to the playlist */
playlist_t *p_playlist = pl_Get( p_this );
do
{
DosConnectNPipe( hpipeIPC );
/* Read command */
DosRead( hpipeIPC, &ulCmd, sizeof( ulCmd ), &cbActual );
if( ulCmd == IPC_CMD_QUIT )
continue;
/* Read a count of arguments */
DosRead( hpipeIPC, &i_argc, sizeof( i_argc ), &cbActual );
ppsz_argv = malloc( i_argc * sizeof( *ppsz_argv ));
for( int i_opt = 0; i_opt < i_argc; i_opt++ )
{
/* Read a length of argv */
DosRead( hpipeIPC, &i_len, sizeof( i_len ), &cbActual );
ppsz_argv[ i_opt ] = malloc( i_len );
/* Read argv */
DosRead( hpipeIPC, ppsz_argv[ i_opt ], i_len, &cbActual );
}
for( int i_opt = 0; i_opt < i_argc;)
{
i_options = 0;
/* Count the input options */
while( i_opt + i_options + 1 < i_argc &&
*ppsz_argv[ i_opt + i_options + 1 ] == ':' )
i_options++;
playlist_AddExt( p_playlist, ppsz_argv[ i_opt ], NULL,
PLAYLIST_APPEND |
(( i_opt || ulCmd == IPC_CMD_ENQUEUE ) ?
0 : PLAYLIST_GO ),
PLAYLIST_END, -1, i_options,
( char const ** )
( i_options ? &ppsz_argv[ i_opt + 1 ] :
NULL ),
VLC_INPUT_OPTION_TRUSTED,
true, pl_Unlocked );
for( ; i_options >= 0; i_options-- )
free( ppsz_argv[ i_opt++ ]);
}
free( ppsz_argv );
} while( !DosDisConnectNPipe( hpipeIPC ) && ulCmd != IPC_CMD_QUIT );
vlc_object_release( p_this );
DosClose( hpipeIPC );
hpipeIPC = NULLHANDLE;
tidIPCFirst = -1;
tidIPCHelper = -1;
}
void system_Init( void )
{
/* Set the default file-translation mode */
......@@ -39,7 +126,6 @@ void system_Init( void )
void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_argv[] )
{
VLC_UNUSED( i_argc ); VLC_UNUSED( ppsz_argv );
if( var_InheritBool( p_this, "high-priority" ) )
{
if( !DosSetPriority( PRTYS_PROCESS, PRTYC_REGULAR, PRTYD_MAXIMUM, 0 ) )
......@@ -51,4 +137,152 @@ void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_
msg_Dbg( p_this, "could not raise process priority" );
}
}
if( var_InheritBool( p_this, "one-instance" )
|| ( var_InheritBool( p_this, "one-instance-when-started-from-file" )
&& var_InheritBool( p_this, "started-from-file" ) ) )
{
HPIPE hpipe;
ULONG ulAction;
ULONG rc;
msg_Info( p_this, "one instance mode ENABLED");
/* Use a named pipe to check if another instance is already running */
for(;;)
{
rc = DosOpen( VLC_IPC_PIPE, &hpipe, &ulAction, 0, 0,
OPEN_ACTION_OPEN_IF_EXISTS,
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE |
OPEN_FLAGS_FAIL_ON_ERROR,
NULL );
if( rc == ERROR_PIPE_BUSY )
DosWaitNPipe( VLC_IPC_PIPE, -1 );
else
break;
}
if( rc )
{
rc = DosCreateNPipe( VLC_IPC_PIPE, &hpipeIPC,
NP_ACCESS_DUPLEX,
NP_WAIT | NP_TYPE_MESSAGE |
NP_READMODE_MESSAGE | 0x01,
32768, 32768, 0 );
if( rc )
{
/* Failed to create a named pipe. Just ignore the option and
* go on as normal. */
msg_Err( p_this, "one instance mode DISABLED "
"(a named pipe couldn't be created)" );
return;
}
/* We are the 1st instance. */
vlc_object_t* p_helper = vlc_custom_create( p_this,
sizeof( *p_helper ),
"ipc helper" );
/* Save the tid of the first instance */
tidIPCFirst = _gettid();
/* Run the helper thread */
tidIPCHelper = _beginthread( IPCHelperThread, NULL, 1024 * 1024,
p_helper );
if( tidIPCHelper == -1 )
{
msg_Err( p_this, "one instance mode DISABLED "
"(IPC helper thread couldn't be created)");
vlc_object_release( p_helper );
tidIPCFirst = -1;
}
}
else
{
/* Another instance is running */
ULONG ulCmd = var_InheritBool( p_this, "playlist-enqueue") ?
IPC_CMD_ENQUEUE : IPC_CMD_GO;
ULONG cbActual;
/* Write a command */
DosWrite( hpipe, &ulCmd, sizeof( ulCmd ), &cbActual );
/* We assume that the remaining parameters are filenames
* and their input options */
/* Write a count of arguments */
DosWrite( hpipe, &i_argc, sizeof( i_argc ), &cbActual );
for( int i_opt = 0; i_opt < i_argc; i_opt++ )
{
/* We need to resolve relative paths in this instance */
char *mrl;
if( strstr( ppsz_argv[ i_opt ], "://" ))
mrl = strdup( ppsz_argv[ i_opt ] );
else
mrl = vlc_path2uri( ppsz_argv[ i_opt ], NULL );
if( !mrl )
mrl = ( char * )ppsz_argv[ i_opt ];
size_t i_len = strlen( mrl ) + 1;
/* Write a length of an argument */
DosWrite( hpipe, &i_len, sizeof( i_len ), &cbActual );
/* Write an argument */
DosWrite( hpipe, mrl, i_len, &cbActual );
if( mrl != ppsz_argv[ i_opt ])
free( mrl );
}
/* Close a named pipe of a client side */
DosClose( hpipe );
/* Bye bye */
system_End();
exit( 0 );
}
}
}
/**
* Cleans up after system_Init() and system_Configure().
*/
void system_End(void)
{
if( tidIPCFirst == _gettid())
{
HPIPE hpipe;
ULONG ulAction;
ULONG cbActual;
ULONG rc;
do
{
rc = DosOpen( VLC_IPC_PIPE, &hpipe, &ulAction, 0, 0,
OPEN_ACTION_OPEN_IF_EXISTS,
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE |
OPEN_FLAGS_FAIL_ON_ERROR,
NULL );
if( rc == ERROR_PIPE_BUSY )
DosWaitNPipe( VLC_IPC_PIPE, -1 );
else if( rc )
DosSleep( 1 );
} while( rc );
/* Ask for IPCHelper to quit */
ULONG ulCmd = IPC_CMD_QUIT;
DosWrite( hpipe, &ulCmd, sizeof( ulCmd ), &cbActual );
DosClose( hpipe );
TID tid = tidIPCHelper;
DosWaitThread( &tid, DCWW_WAIT );
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment