From e8fcf232588d73d0176e86e5bf5f7e7171b8e78c Mon Sep 17 00:00:00 2001 From: sletz Date: Mon, 20 Aug 2007 07:31:02 +0000 Subject: [PATCH] Automatic server launch git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@1516 0c269be4-1314-0410-8aa9-9f06e86f4224 --- ChangeLog | 4 + common/JackAPI.cpp | 160 ---------------------- common/JackChannel.h | 5 + common/JackLibAPI.cpp | 11 +- common/JackLibGlobals.h | 1 + common/JackServerAPI.cpp | 10 +- common/JackServerGlobals.cpp | 17 ++- common/JackSocketClientChannel.cpp | 14 ++ common/JackSocketClientChannel.h | 2 + macosx/JackMachClientChannel.cpp | 13 ++ macosx/JackMachClientChannel.h | 4 +- macosx/Jackdmp.xcodeproj/project.pbxproj | 8 ++ windows/JackWinNamedPipeClientChannel.cpp | 47 ++++--- windows/JackWinNamedPipeClientChannel.h | 2 + 14 files changed, 108 insertions(+), 190 deletions(-) diff --git a/ChangeLog b/ChangeLog index f1cf10e8..a9f8b55b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,10 @@ 2007-08-21 Stephane Letz + * Automatic server launch. + +2007-08-20 Stephane Letz + * Add "systemic" latencies management in CoreAudio driver. 2007-08-16 Stephane Letz diff --git a/common/JackAPI.cpp b/common/JackAPI.cpp index 9ff5d2fc..b261317e 100644 --- a/common/JackAPI.cpp +++ b/common/JackAPI.cpp @@ -1202,7 +1202,6 @@ EXPORT int jack_port_name_size(void) } // transport.h - EXPORT int jack_release_timebase(jack_client_t* ext_client) { #ifdef __CLIENTDEBUG__ @@ -1342,7 +1341,6 @@ EXPORT void jack_transport_stop(jack_client_t* ext_client) } // deprecated - EXPORT void jack_get_transport_info(jack_client_t* ext_client, jack_transport_info_t* tinfo) { jack_error("jack_get_transport_info: deprecated"); @@ -1358,7 +1356,6 @@ EXPORT void jack_set_transport_info(jack_client_t* ext_client, jack_transport_in } // statistics.h - EXPORT float jack_get_max_delayed_usecs(jack_client_t* ext_client) { #ifdef __CLIENTDEBUG__ @@ -1386,7 +1383,6 @@ EXPORT void jack_reset_max_delayed_usecs(jack_client_t* ext_client) } // thread.h - EXPORT int jack_acquire_real_time_scheduling(pthread_t thread, int priority) { #ifdef __APPLE__ @@ -1426,7 +1422,6 @@ EXPORT int jack_drop_real_time_scheduling(pthread_t thread) } // intclient.h - EXPORT char* jack_get_internal_client_name(jack_client_t* ext_client, jack_intclient_t intclient) { JackLog("jack_get_internal_client_name: not yet implemented\n"); @@ -1451,158 +1446,3 @@ EXPORT jack_status_t jack_internal_client_unload(jack_client_t* ext_client, jack return JackFailure; } -// Automatic jack server launch - -#ifndef WIN32 - -#define JACK_LOCATION -#define JACK_DEFAULT_DRIVER - -/* Exec the JACK server in this process. Does not return. */ -static void start_server_aux(const char *server_name) -{ - FILE* fp = 0; - char filename[255]; - char arguments[255]; - char buffer[255]; - char* command = 0; - size_t pos = 0; - size_t result = 0; - char** argv = 0; - int i = 0; - int good = 0; - int ret; - - snprintf(filename, 255, "%s/.jackdrc", getenv("HOME")); - fp = fopen(filename, "r"); - - if (!fp) { - fp = fopen("/etc/jackdrc", "r"); - } - /* if still not found, check old config name for backwards compatability */ - if (!fp) { - fp = fopen("/etc/jackd.conf", "r"); - } - - if (fp) { - arguments[0] = '\0'; - ret = fscanf(fp, "%s", buffer); - while(ret != 0 && ret != EOF) { - strcat(arguments, buffer); - strcat(arguments, " "); - ret = fscanf(fp, "%s", buffer); - } - if (strlen(arguments) > 0) { - good = 1; - } - } - - if (!good) { - command = JACK_LOCATION "/jackdmp"; - strncpy(arguments, JACK_LOCATION "/jackdmp -T -d "JACK_DEFAULT_DRIVER, 255); - } else { - result = strcspn(arguments, " "); - command = (char *) malloc(result+1); - strncpy(command, arguments, result); - command[result] = '\0'; - } - - argv = (char **)malloc(255); - - while (1) { - /* insert -T and -nserver_name in front of arguments */ - if (i == 1) { - argv[i] = (char *) malloc(strlen ("-T") + 1); - strcpy (argv[i++], "-T"); - if (server_name) { - size_t optlen = strlen ("-n"); - char* buf = (char*)malloc(optlen + strlen (server_name) + 1); - strcpy(buf, "-n"); - strcpy(buf+optlen, server_name); - argv[i++] = buf; - } - } - - result = strcspn(arguments + pos, " "); - if (result == 0) { - break; - } - argv[i] = (char*)malloc(result + 1); - strncpy(argv[i], arguments+pos, result); - argv[i][result] = '\0'; - pos += result + 1; - ++i; - } - argv[i] = 0; - execv(command, argv); - - /* If execv() succeeds, it does not return. There's no point - * in calling jack_error() here in the child process. */ - fprintf(stderr, "exec of JACK server (command = \"%s\") failed: %s\n", command, strerror(errno)); -} - -static int start_server(const char *server_name, jack_options_t options) -{ - if ((options & JackNoStartServer) || getenv("JACK_NO_START_SERVER")) { - return 1; - } - - /* The double fork() forces the server to become a child of - * init, which will always clean up zombie process state on - * termination. This even works in cases where the server - * terminates but this client does not. - * - * Since fork() is usually implemented using copy-on-write - * virtual memory tricks, the overhead of the second fork() is - * probably relatively small. - */ - switch (fork()) { - case 0: /* child process */ - switch (fork()) { - case 0: /* grandchild process */ - start_server_aux(server_name); - _exit(99); /* exec failed */ - case -1: - _exit(98); - default: - _exit(0); - } - case -1: /* fork() error */ - return 1; /* failed to start server */ - } - - /* only the original parent process goes here */ - return 0; /* (probably) successful */ -} - -int server_connect(char* name) -{ - return -1; -} - -int try_start_server(jack_varargs_t* va, jack_options_t options, jack_status_t* status) -{ - if (server_connect(va->server_name) < 0) { - int trys; - if (start_server(va->server_name, options)) { - int my_status1 = *status | JackFailure | JackServerFailed; - *status = (jack_status_t)my_status1; - return -1; - } - trys = 5; - do { - sleep(1); - if (--trys < 0) { - int my_status1 = *status | JackFailure | JackServerFailed; - *status = (jack_status_t)my_status1; - return -1; - } - } while (server_connect(va->server_name) < 0); - int my_status1 = *status | JackServerStarted; - *status = (jack_status_t)my_status1; - } - - return 0; -} - -#endif diff --git a/common/JackChannel.h b/common/JackChannel.h index 5fcc0ae6..f12e1392 100644 --- a/common/JackChannel.h +++ b/common/JackChannel.h @@ -67,6 +67,11 @@ class JackClientChannelInterface virtual void Stop() {} + virtual int ServerCheck(const char* server_name) + { + return -1; + } + virtual void ClientCheck(const char* name, char* name_res, int options, int* status, int* result) {} virtual void ClientOpen(const char* name, int* shared_engine, int* shared_client, int* shared_graph, int* result) diff --git a/common/JackLibAPI.cpp b/common/JackLibAPI.cpp index 76880e77..b09198ff 100644 --- a/common/JackLibAPI.cpp +++ b/common/JackLibAPI.cpp @@ -21,10 +21,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackDebugClient.h" #include "JackLibClient.h" #include "JackChannel.h" -#include "JackGraphManager.h" #include "JackLibGlobals.h" #include "JackGlobals.h" -#include "varargs.h" +#include "JackServerLaunch.h" using namespace Jack; @@ -86,6 +85,14 @@ static jack_client_t* jack_client_open_aux(const char* client_name, jack_options } JackLibGlobals::Init(); // jack library initialisation + +#ifndef WIN32 + if (try_start_server(&va, options, status)) { + jack_error("jack server is not running or cannot be started"); + JackLibGlobals::Destroy(); // jack library destruction + return 0; + } +#endif #ifdef __CLIENTDEBUG__ JackClient* client = new JackDebugClient(new JackLibClient(GetSynchroTable())); // Debug mode diff --git a/common/JackLibGlobals.h b/common/JackLibGlobals.h index b905d90b..f45f40a7 100644 --- a/common/JackLibGlobals.h +++ b/common/JackLibGlobals.h @@ -27,6 +27,7 @@ This program is free software; you can redistribute it and/or modify #include #endif #include "JackGlobals.h" +#include "JackGraphManager.h" #include "JackTime.h" #include diff --git a/common/JackServerAPI.cpp b/common/JackServerAPI.cpp index ec33ed3b..eab942ed 100644 --- a/common/JackServerAPI.cpp +++ b/common/JackServerAPI.cpp @@ -28,7 +28,7 @@ This program is free software; you can redistribute it and/or modify #include "JackDebugClient.h" #include "JackServerGlobals.h" #include "JackError.h" -#include "varargs.h" +#include "JackServerLaunch.h" /* TODO: @@ -141,6 +141,14 @@ EXPORT jack_client_t* jack_client_open(const char* client_name, jack_options_t o JackServerGlobals::Init(); // jack server initialisation +#ifndef WIN32 + if (try_start_server(&va, options, status)) { + jack_error("jack server is not running or cannot be started"); + JackServerGlobals::Destroy(); // jack library destruction + return 0; + } +#endif + #ifdef __CLIENTDEBUG__ JackClient* client = new JackDebugClient(new JackInternalClient(JackServer::fInstance, GetSynchroTable())); // Debug mode #else diff --git a/common/JackServerGlobals.cpp b/common/JackServerGlobals.cpp index 3154945d..34a40639 100644 --- a/common/JackServerGlobals.cpp +++ b/common/JackServerGlobals.cpp @@ -16,10 +16,10 @@ This program is free software; you can redistribute it and/or modify Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif + +#ifdef WIN32 +#pragma warning (disable : 4786) +#endif #include "JackServerGlobals.h" #include "JackError.h" @@ -181,7 +181,6 @@ int JackServerGlobals::JackDelete() } // Temporary : to test - JackServerGlobals::JackServerGlobals() { jack_driver_desc_t* driver_desc; @@ -323,24 +322,24 @@ JackServerGlobals::JackServerGlobals() return ; } - driver_args = (char **) malloc (sizeof (char *) * driver_nargs); + driver_args = (char**) malloc(sizeof(char *) * driver_nargs); driver_args[0] = driver_name; for (i = 1; i < driver_nargs; i++) { driver_args[i] = argv[optind++]; } - if (jack_parse_driver_params (driver_desc, driver_nargs, + if (jack_parse_driver_params(driver_desc, driver_nargs, driver_args, &driver_params)) { return ; } #ifndef WIN32 if (server_name == NULL) - server_name = jack_default_server_name (); + server_name = jack_default_server_name(); #endif - rc = jack_register_server (server_name); + rc = jack_register_server(server_name); /* clean up shared memory and files from any previous * instance of this server name */ diff --git a/common/JackSocketClientChannel.cpp b/common/JackSocketClientChannel.cpp index 9cc13408..683ad900 100644 --- a/common/JackSocketClientChannel.cpp +++ b/common/JackSocketClientChannel.cpp @@ -38,6 +38,20 @@ JackSocketClientChannel::~JackSocketClientChannel() delete fNotificationSocket; } +int JackSocketClientChannel::ServerCheck(const char* server_name) +{ + JackLog("JackSocketClientChannel::ServerCheck = %s\n", server_name); + + // Connect to server + if (fRequestSocket.Connect(jack_server_dir, 0) < 0) { + jack_error("Cannot connect to server socket"); + fRequestSocket.Close(); + return -1; + } else { + return 0; + } +} + int JackSocketClientChannel::Open(const char* name, char* name_res, JackClient* obj, jack_options_t options, jack_status_t* status) { int result = 0; diff --git a/common/JackSocketClientChannel.h b/common/JackSocketClientChannel.h index 92c89ec6..ac84e393 100644 --- a/common/JackSocketClientChannel.h +++ b/common/JackSocketClientChannel.h @@ -56,6 +56,8 @@ class JackSocketClientChannel : public JackClientChannelInterface, public JackRu int Start(); void Stop(); + + int ServerCheck(const char* server_name); void ClientCheck(const char* name, char* name_res, int options, int* status, int* result); void ClientOpen(const char* name, int* shared_engine, int* shared_client, int* shared_graph, int* result); diff --git a/macosx/JackMachClientChannel.cpp b/macosx/JackMachClientChannel.cpp index d5b9def0..cd3f0937 100644 --- a/macosx/JackMachClientChannel.cpp +++ b/macosx/JackMachClientChannel.cpp @@ -41,6 +41,19 @@ JackMachClientChannel::~JackMachClientChannel() // Server <===> client +int JackMachClientChannel::ServerCheck(const char* server_name) +{ + JackLog("JackMachClientChannel::ServerCheck = %s\n", server_name); + + // Connect to server + if (!fServerPort.ConnectPort(jack_server_entry)) { + jack_error("Cannot connect to server Mach port"); + return -1; + } else { + return 0; + } +} + int JackMachClientChannel::Open(const char* name, char* name_res, JackClient* client, jack_options_t options, jack_status_t* status) { JackLog("JackMachClientChannel::Open name = %s\n", name); diff --git a/macosx/JackMachClientChannel.h b/macosx/JackMachClientChannel.h index 452a2ef7..be2d9cfa 100644 --- a/macosx/JackMachClientChannel.h +++ b/macosx/JackMachClientChannel.h @@ -53,7 +53,9 @@ class JackMachClientChannel : public JackClientChannelInterface, public JackRunn int Start(); void Stop(); - + + int ServerCheck(const char* server_name); + void ClientCheck(const char* name, char* name_res, int options, int* status, int* result); void ClientOpen(const char* name, int* shared_engine, int* shared_client, int* shared_graph, int* result); void ClientClose(int refnum, int* result); diff --git a/macosx/Jackdmp.xcodeproj/project.pbxproj b/macosx/Jackdmp.xcodeproj/project.pbxproj index 0cde1453..c771f1a8 100644 --- a/macosx/Jackdmp.xcodeproj/project.pbxproj +++ b/macosx/Jackdmp.xcodeproj/project.pbxproj @@ -43,6 +43,9 @@ /* Begin PBXBuildFile section */ 4B3F49080AD8503300491C6E /* jack_cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3F49070AD8503300491C6E /* jack_cpu.c */; }; + 4B44FAE60C7598370033A72C /* JackServerLaunch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B44FAE50C7598370033A72C /* JackServerLaunch.cpp */; }; + 4B44FAE70C7598370033A72C /* JackServerLaunch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B44FAE50C7598370033A72C /* JackServerLaunch.cpp */; }; + 4B44FAE80C7598370033A72C /* JackServerLaunch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B44FAE50C7598370033A72C /* JackServerLaunch.cpp */; }; 4B60CE490AAABA31004956AA /* connect.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B60CE480AAABA31004956AA /* connect.c */; }; 4B60CE4A0AAABA31004956AA /* connect.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B60CE480AAABA31004956AA /* connect.c */; }; 4B699BAA097D421600A18468 /* Jackdmp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8D2250834F06A00C94B91 /* Jackdmp.cpp */; }; @@ -442,6 +445,7 @@ 4B395C9706AEF53800923527 /* JackCoreAudioDriver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JackCoreAudioDriver.h; sourceTree = SOURCE_ROOT; }; 4B3F49070AD8503300491C6E /* jack_cpu.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = jack_cpu.c; path = ../tests/jack_cpu.c; sourceTree = SOURCE_ROOT; }; 4B4259E5076B635E00C1ECE1 /* JackMacEngineRPC.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JackMacEngineRPC.cpp; sourceTree = SOURCE_ROOT; }; + 4B44FAE50C7598370033A72C /* JackServerLaunch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackServerLaunch.cpp; path = ../common/JackServerLaunch.cpp; sourceTree = SOURCE_ROOT; }; 4B464301076CAC7700E5077C /* Jack-Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = "Jack-Info.plist"; sourceTree = SOURCE_ROOT; }; 4B56880F08B5C8620022B32D /* JackFifo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackFifo.cpp; path = ../common/JackFifo.cpp; sourceTree = SOURCE_ROOT; }; 4B56881008B5C8620022B32D /* JackFifo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackFifo.h; path = ../common/JackFifo.h; sourceTree = SOURCE_ROOT; }; @@ -1056,6 +1060,7 @@ 4B98AE000931D30C0091932A /* JackDebugClient.cpp */, 4BF8D1E90834EF7500C94B91 /* JackAPI.cpp */, 4BE50F650B01E96200C05E63 /* JackAPIWrapper.cpp */, + 4B44FAE50C7598370033A72C /* JackServerLaunch.cpp */, 4BD56D75079687EB006D44F9 /* Internal */, 4BD56D73079687AD006D44F9 /* External */, 4BA550F905E241D900569492 /* Library */, @@ -2010,6 +2015,7 @@ buildActionMask = 2147483647; files = ( 4B699BAA097D421600A18468 /* Jackdmp.cpp in Sources */, + 4B44FAE60C7598370033A72C /* JackServerLaunch.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2046,6 +2052,7 @@ 4B699C3F097D421600A18468 /* ringbuffer.c in Sources */, 4B699C40097D421600A18468 /* JackDebugClient.cpp in Sources */, 4BD4B4E409BACEF300750C0F /* JackTransportEngine.cpp in Sources */, + 4B44FAE70C7598370033A72C /* JackServerLaunch.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2096,6 +2103,7 @@ 4BD4B4D909BACD9600750C0F /* JackTransportEngine.cpp in Sources */, 4BC216850A444BAD00BDA09F /* JackServerAPI.cpp in Sources */, 4BC216890A444BDE00BDA09F /* JackServerGlobals.cpp in Sources */, + 4B44FAE80C7598370033A72C /* JackServerLaunch.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/windows/JackWinNamedPipeClientChannel.cpp b/windows/JackWinNamedPipeClientChannel.cpp index df8ad6c9..b9a85949 100644 --- a/windows/JackWinNamedPipeClientChannel.cpp +++ b/windows/JackWinNamedPipeClientChannel.cpp @@ -36,35 +36,48 @@ JackWinNamedPipeClientChannel::~JackWinNamedPipeClientChannel() delete fThread; } +int JackWinNamedPipeClientChannel::ServerCheck(const char* server_name) +{ + JackLog("JackWinNamedPipeClientChannel::ServerCheck = %s\n", server_name); + + // Connect to server + if (fRequestPipe.Connect(jack_server_dir, 0) < 0) { + jack_error("Cannot connect to server pipe"); + return -1; + } else { + return 0; + } +} + int JackWinNamedPipeClientChannel::Open(const char* name, char* name_res, JackClient* obj, jack_options_t options, jack_status_t* status) -{ +{ int result = 0; JackLog("JackWinNamedPipeClientChannel::Open name = %s\n", name); - - /* + + /* 16/08/07: was called before doing "fRequestPipe.Connect" .... still necessary? if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) { jack_error("Cannot bind pipe"); goto error; - } + } */ if (fRequestPipe.Connect(jack_server_dir, 0) < 0) { jack_error("Cannot connect to server pipe"); goto error; - } - - // Check name in server - ClientCheck(name, name_res, (int)options, (int*)status, &result); - if (result < 0) { - jack_error("Client name = %s conflits with another running client", name); - goto error; - } - - if (fNotificationListenPipe.Bind(jack_client_dir, name_res, 0) < 0) { - jack_error("Cannot bind pipe"); - goto error; - } + } + + // Check name in server + ClientCheck(name, name_res, (int)options, (int*)status, &result); + if (result < 0) { + jack_error("Client name = %s conflits with another running client", name); + goto error; + } + + if (fNotificationListenPipe.Bind(jack_client_dir, name_res, 0) < 0) { + jack_error("Cannot bind pipe"); + goto error; + } fClient = obj; diff --git a/windows/JackWinNamedPipeClientChannel.h b/windows/JackWinNamedPipeClientChannel.h index 2b4e1b5c..b77387be 100644 --- a/windows/JackWinNamedPipeClientChannel.h +++ b/windows/JackWinNamedPipeClientChannel.h @@ -55,6 +55,8 @@ class JackWinNamedPipeClientChannel : public JackClientChannelInterface, public int Start(); void Stop(); + + int ServerCheck(const char* server_name); void ClientCheck(const char* name, char* name_res, int options, int* status, int* result); void ClientOpen(const char* name, int* shared_engine, int* shared_client, int* shared_graph, int* result);