"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_( \
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,
#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 */
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 ) )
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 );
+ }
+}
+