]> git.sesse.net Git - vlc/blobdiff - modules/control/ntservice.c
Use var_InheritString for --decklink-video-connection.
[vlc] / modules / control / ntservice.c
old mode 100755 (executable)
new mode 100644 (file)
index 0b1b130..c36adef
@@ -1,10 +1,10 @@
 /*****************************************************************************
  * ntservice.c: Windows NT/2K/XP service interface
  *****************************************************************************
- * Copyright (C) 2001 VideoLAN
- * $Id: ntservice.c,v 1.1 2003/08/13 23:26:55 gbazin Exp $
+ * Copyright (C) 2004 the VideoLAN team
+ * $Id$
  *
- * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ * Authors: Gildas Bazin <gbazin@videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include <stdlib.h>
-#include <vlc/vlc.h>
-#include <vlc/intf.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_interface.h>
 
 #define VLCSERVICENAME "VLC media player"
 
 static int  Activate( vlc_object_t * );
 static void Close   ( vlc_object_t * );
 
-#define INSTALL_TEXT N_( "Install NT/2K/XP service" )
+#define INSTALL_TEXT N_( "Install Windows Service" )
 #define INSTALL_LONGTEXT N_( \
-    "If enabled the interface will install the service and exit." )
-#define UNINSTALL_TEXT N_( "Uninstall NT/2K/XP service" )
+    "Install the Service and exit." )
+#define UNINSTALL_TEXT N_( "Uninstall Windows Service" )
 #define UNINSTALL_LONGTEXT N_( \
-    "If enabled the interface will uninstall the service and exit." )
-#define NAME_TEXT N_( "Display name of the service" )
+    "Uninstall the Service and exit." )
+#define NAME_TEXT N_( "Display name of the Service" )
 #define NAME_LONGTEXT N_( \
-    "This allows you to change the display name of the service." )
-
-vlc_module_begin();
-    set_description( _("Windows NT/2K/XP service interface") );
-    add_category_hint( N_("NT service"), NULL, VLC_TRUE );
-    add_bool( "ntservice-install", 0, NULL, INSTALL_TEXT, INSTALL_LONGTEXT, VLC_TRUE );
-    add_bool( "ntservice-uninstall", 0, NULL, INSTALL_TEXT, INSTALL_LONGTEXT, VLC_TRUE );
-    add_string ( "ntservice-name", VLCSERVICENAME, NULL, NAME_TEXT, NAME_LONGTEXT, VLC_TRUE );
-
-    set_capability( "interface", 0 );
-    set_callbacks( Activate, Close );
-vlc_module_end();
+    "Change the display name of the Service." )
+#define OPTIONS_TEXT N_("Configuration options")
+#define OPTIONS_LONGTEXT N_( \
+    "Configuration options that will be " \
+    "used by the Service (eg. --foo=bar --no-foobar). It should be specified "\
+    "at install time so the Service is properly configured.")
+#define EXTRAINTF_TEXT N_("Extra interface modules")
+#define EXTRAINTF_LONGTEXT N_( \
+    "Additional interfaces spawned by the " \
+    "Service. It should be specified at install time so the Service is " \
+    "properly configured. Use a comma separated list of interface modules. " \
+    "(common values are: logger, sap, rc, http)")
+
+vlc_module_begin ()
+    set_shortname( N_("NT Service"))
+    set_description( N_("Windows Service interface") )
+    set_category( CAT_INTERFACE )
+    set_subcategory( SUBCAT_INTERFACE_CONTROL )
+    add_bool( "ntservice-install", false, NULL,
+              INSTALL_TEXT, INSTALL_LONGTEXT, true )
+    add_bool( "ntservice-uninstall", false, NULL,
+              UNINSTALL_TEXT, UNINSTALL_LONGTEXT, true )
+    add_string ( "ntservice-name", VLCSERVICENAME, NULL,
+                 NAME_TEXT, NAME_LONGTEXT, true )
+    add_string ( "ntservice-options", NULL, NULL,
+                 OPTIONS_TEXT, OPTIONS_LONGTEXT, true )
+    add_string ( "ntservice-extraintf", NULL, NULL,
+                 EXTRAINTF_TEXT, EXTRAINTF_LONGTEXT, true )
+
+    set_capability( "interface", 0 )
+    set_callbacks( Activate, Close )
+vlc_module_end ()
 
 struct intf_sys_t
 {
@@ -83,9 +107,6 @@ static int Activate( vlc_object_t *p_this )
 {
     intf_thread_t *p_intf = (intf_thread_t*)p_this;
 
-    /* Only works on NT/2K/XP */
-    if( !IS_WINNT ) return VLC_EGENERIC;
-
     p_intf->pf_run = Run;
     return VLC_SUCCESS;
 }
@@ -95,6 +116,7 @@ static int Activate( vlc_object_t *p_this )
  *****************************************************************************/
 void Close( vlc_object_t *p_this )
 {
+    (void)p_this;
 }
 
 /*****************************************************************************
@@ -102,25 +124,27 @@ void Close( vlc_object_t *p_this )
  *****************************************************************************/
 static void Run( intf_thread_t *p_intf )
 {
+    intf_sys_t sys;
     SERVICE_TABLE_ENTRY dispatchTable[] =
     {
-        { VLCSERVICENAME, &ServiceDispatch },
+        { (LPTSTR)VLCSERVICENAME, &ServiceDispatch },
         { NULL, NULL }
     };
 
+    int canc = vlc_savecancel();
     p_global_intf = p_intf;
-    p_intf->p_sys = alloca( sizeof( intf_sys_t ) );
-    p_intf->p_sys->psz_service = config_GetPsz( p_intf, "ntservice-name" );
+    p_intf->p_sys = &sys;
+    p_intf->p_sys->psz_service = var_InheritString( p_intf, "ntservice-name" );
     p_intf->p_sys->psz_service = p_intf->p_sys->psz_service ?
         p_intf->p_sys->psz_service : strdup(VLCSERVICENAME);
 
-    if( config_GetInt( p_intf, "ntservice-install" ) )
+    if( var_InheritBool( p_intf, "ntservice-install" ) )
     {
         NTServiceInstall( p_intf );
         return;
     }
 
-    if( config_GetInt( p_intf, "ntservice-uninstall" ) )
+    if( var_InheritBool( p_intf, "ntservice-uninstall" ) )
     {
         NTServiceUninstall( p_intf );
         return;
@@ -128,13 +152,14 @@ static void Run( intf_thread_t *p_intf )
 
     if( StartServiceCtrlDispatcher( dispatchTable ) == 0 )
     {
-        msg_Err( p_intf, "StartServiceCtrlDispatcher failed" );
+        msg_Err( p_intf, "StartServiceCtrlDispatcher failed" ); /* str review */
     }
 
     free( p_intf->p_sys->psz_service );
 
     /* Make sure we exit (In case other interfaces have been spawned) */
-    p_intf->p_vlc->b_die = VLC_TRUE;
+    libvlc_Quit( p_intf->p_libvlc );
+    vlc_restorecancel( canc );
 }
 
 /*****************************************************************************
@@ -143,11 +168,12 @@ static void Run( intf_thread_t *p_intf )
 static int NTServiceInstall( intf_thread_t *p_intf )
 {
     intf_sys_t *p_sys  = p_intf->p_sys;
-    char psz_path[MAX_PATH], psz_pathtmp[MAX_PATH];
+    char psz_path[10*MAX_PATH], psz_pathtmp[MAX_PATH], *psz_extra;
     SC_HANDLE handle = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
     if( handle == NULL )
     {
-        msg_Err( p_intf, "Could not connect to SCM database" );
+        msg_Err( p_intf,
+                 "could not connect to Services Control Manager database" );
         return VLC_EGENERIC;
     }
 
@@ -156,6 +182,22 @@ static int NTServiceInstall( intf_thread_t *p_intf )
     GetModuleFileName( NULL, psz_pathtmp, MAX_PATH );
     sprintf( psz_path, "\"%s\" -I "MODULE_STRING, psz_pathtmp );
 
+    psz_extra = var_InheritString( p_intf, "ntservice-extraintf" );
+    if( psz_extra )
+    {
+        strcat( psz_path, " --ntservice-extraintf " );
+        strcat( psz_path, psz_extra );
+        free( psz_extra );
+    }
+
+    psz_extra = var_InheritString( p_intf, "ntservice-options" );
+    if( psz_extra && *psz_extra )
+    {
+        strcat( psz_path, " " );
+        strcat( psz_path, psz_extra );
+        free( psz_extra );
+    }
+
     SC_HANDLE service =
         CreateService( handle, p_sys->psz_service, p_sys->psz_service,
                        GENERIC_READ | GENERIC_EXECUTE,
@@ -166,18 +208,20 @@ static int NTServiceInstall( intf_thread_t *p_intf )
     {
         if( GetLastError() != ERROR_SERVICE_EXISTS )
         {
-            msg_Err( p_intf, "Could not create new service" );
+            msg_Err( p_intf, "could not create new service: \"%s\" (%s)",
+                     p_sys->psz_service ,psz_path );
             CloseServiceHandle( handle );
             return VLC_EGENERIC;
         }
         else
         {
-            msg_Warn( p_intf, "Service already exists" );
+            msg_Warn( p_intf, "service \"%s\" already exists",
+                      p_sys->psz_service );
         }
     }
     else
     {
-        msg_Warn( p_intf, "Service successfuly created" );
+        msg_Warn( p_intf, "service successfuly created" );
     }
 
     if( service ) CloseServiceHandle( service );
@@ -193,7 +237,8 @@ static int NTServiceUninstall( intf_thread_t *p_intf )
     SC_HANDLE handle = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
     if( handle == NULL )
     {
-        msg_Err( p_intf, "Could not connect to SCM database" );
+        msg_Err( p_intf,
+                 "could not connect to Services Control Manager database" );
         return VLC_EGENERIC;
     }
 
@@ -201,7 +246,7 @@ static int NTServiceUninstall( intf_thread_t *p_intf )
     SC_HANDLE service = OpenService( handle, p_sys->psz_service, DELETE );
     if( service == NULL )
     {
-        msg_Err( p_intf, "Could not open service" );
+        msg_Err( p_intf, "could not open service" );
         CloseServiceHandle( handle );
         return VLC_EGENERIC;
     }
@@ -209,11 +254,12 @@ static int NTServiceUninstall( intf_thread_t *p_intf )
     /* Remove the service */
     if( !DeleteService( service ) )
     {
-        msg_Err( p_intf, "Could not delete service" );
+        msg_Err( p_intf, "could not delete service \"%s\"",
+                 p_sys->psz_service );
     }
     else
     {
-        msg_Dbg( p_intf, "Service deleted successfuly" );
+        msg_Dbg( p_intf, "service deleted successfuly" );
     }
 
     CloseServiceHandle( service );
@@ -224,8 +270,11 @@ static int NTServiceUninstall( intf_thread_t *p_intf )
 
 static void WINAPI ServiceDispatch( DWORD numArgs, char **args )
 {
+    (void)numArgs;
+    (void)args;
     intf_thread_t *p_intf = (intf_thread_t *)p_global_intf;
     intf_sys_t    *p_sys  = p_intf->p_sys;
+    char *psz_modules, *psz_parser;
 
     /* We have to initialize the service-specific stuff */
     memset( &p_sys->status, 0, sizeof(SERVICE_STATUS) );
@@ -237,14 +286,45 @@ static void WINAPI ServiceDispatch( DWORD numArgs, char **args )
         RegisterServiceCtrlHandler( p_sys->psz_service, &ServiceCtrlHandler );
     if( p_sys->hStatus == (SERVICE_STATUS_HANDLE)0 )
     {
-        msg_Err( p_intf, "Failed to register service control handler" );
+        msg_Err( p_intf, "failed to register service control handler" );
         return;
     }
 
+    /*
+     * Load background interfaces
+     */
+    psz_modules = var_InheritString( p_intf, "ntservice-extraintf" );
+    psz_parser = psz_modules;
+    while( psz_parser && *psz_parser )
+    {
+        char *psz_module, *psz_temp;
+        psz_module = psz_parser;
+        psz_parser = strchr( psz_module, ',' );
+        if( psz_parser )
+        {
+            *psz_parser = '\0';
+            psz_parser++;
+        }
+
+        if( asprintf( &psz_temp, "%s,none", psz_module ) != -1 )
+        {
+            /* Try to create the interface */
+            if( intf_Create( p_intf, psz_temp ) )
+            {
+                msg_Err( p_intf, "interface \"%s\" initialization failed",
+                         psz_temp );
+                free( psz_temp );
+                continue;
+            }
+            free( psz_temp );
+        }
+    }
+    free( psz_modules );
+
     /* Initialization complete - report running status */
-    p_sys->status.dwCurrentState = SERVICE_RUNNING; 
-    p_sys->status.dwCheckPoint   = 0; 
-    p_sys->status.dwWaitHint     = 0; 
+    p_sys->status.dwCurrentState = SERVICE_RUNNING;
+    p_sys->status.dwCheckPoint   = 0;
+    p_sys->status.dwWaitHint     = 0;
 
     SetServiceStatus( p_sys->hStatus, &p_sys->status );
 }