git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@1516 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.64
| @@ -4,6 +4,10 @@ | |||
| 2007-08-21 Stephane Letz <letz@grame.fr> | |||
| * Automatic server launch. | |||
| 2007-08-20 Stephane Letz <letz@grame.fr> | |||
| * Add "systemic" latencies management in CoreAudio driver. | |||
| 2007-08-16 Stephane Letz <letz@grame.fr> | |||
| @@ -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 | |||
| @@ -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) | |||
| @@ -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 | |||
| @@ -27,6 +27,7 @@ This program is free software; you can redistribute it and/or modify | |||
| #include <map> | |||
| #endif | |||
| #include "JackGlobals.h" | |||
| #include "JackGraphManager.h" | |||
| #include "JackTime.h" | |||
| #include <assert.h> | |||
| @@ -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 | |||
| @@ -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 */ | |||
| @@ -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; | |||
| @@ -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); | |||
| @@ -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); | |||
| @@ -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); | |||
| @@ -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; | |||
| }; | |||
| @@ -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; | |||
| @@ -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); | |||