[vlc-devel] [PATCH] os2: implement one-instance feature
KO Myung-Hun
komh78 at gmail.com
Sun Nov 11 08:25:32 CET 2012
---
src/libvlc-module.c | 9 ++-
src/libvlc.c | 2 +-
src/libvlc.h | 4 +-
src/os2/specific.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 247 insertions(+), 4 deletions(-)
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 7dd880b..59302d2 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -1094,6 +1094,13 @@ static const char *const ppsz_prefres[] = {
"to play the file with the already running instance or enqueue it. " \
"This option requires the D-Bus session daemon to be active " \
"and the running instance of VLC to use D-Bus control interface.")
+#elif 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 " \
+ "open a file in your file manager. This option will allow you " \
+ "to play the file with the already running instance or enqueue it. ")
#endif
#define STARTEDFROMFILE_TEXT N_("VLC is started from file association")
@@ -2044,7 +2051,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,
diff --git a/src/libvlc.c b/src/libvlc.c
index 65e27fe..7dd511b 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -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
}
diff --git a/src/libvlc.h b/src/libvlc.h
index 5d557c8..4392f48 100644
--- a/src/libvlc.h
+++ b/src/libvlc.h
@@ -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 *);
diff --git a/src/os2/specific.c b/src/os2/specific.c
index 9cc2e09..c76f52e 100644
--- a/src/os2/specific.c
+++ b/src/os2/specific.c
@@ -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 );
+ }
+}
+
--
1.7.3.2
More information about the vlc-devel
mailing list