Browse Source

Automatic server launch in wrapper layer.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@1955 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.71
sletz 17 years ago
parent
commit
9c0761b379
4 changed files with 140 additions and 15 deletions
  1. +1
    -0
      ChangeLog
  2. +1
    -1
      Todo
  3. +133
    -14
      common/JackAPIWrapper.cpp
  4. +5
    -0
      common/JackInternalClient.cpp

+ 1
- 0
ChangeLog View File

@@ -23,6 +23,7 @@ Nedko Arnaudov
* Marc-Olivier Barre library related scons patch. * Marc-Olivier Barre library related scons patch.
* Nedko Arnaudov FULL_MIMIC patch. * Nedko Arnaudov FULL_MIMIC patch.
* Automatic server launch in wrapper layer.


2008-03-11 Stephane Letz <letz@grame.fr> 2008-03-11 Stephane Letz <letz@grame.fr>


+ 1
- 1
Todo View File

@@ -3,7 +3,7 @@
--------------------- ---------------------




2008-03-12 : Do not start the client RT thread if no callback or thread routine has been setup (no use of jack_set_process_callback or jack_set_process_thread). This require change in the server to avoid signaling the client in this case.
2008-03-12 : Do not start the client RT thread if no callback or thread routine has been setup (no use of jack_set_process_callback or jack_set_process_thread). This require change in the server to avoid signaling the client in this case. Check direct access from server internal clients (see comment in JackInternalClient::JackInternalClient() in JackInternalClient.cpp)


2008-02-07 : Pipelining idea: 2008-02-07 : Pipelining idea:




+ 133
- 14
common/JackAPIWrapper.cpp View File

@@ -20,13 +20,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "types.h" #include "types.h"
#include "jack.h" #include "jack.h"
#include "JackExports.h" #include "JackExports.h"

// TODO
//#include "varargs.h"
//#include "JackTools.h"
//#include "JackConstants.h"
//#include "JackServerLaunch.h"

#include "varargs.h"
#include "JackConstants.h"
#include <dlfcn.h> #include <dlfcn.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
@@ -213,9 +208,6 @@ extern "C"
} }
#endif #endif


// TODO
//using namespace Jack;

#define JACK_LIB "libjack.so.0.0" #define JACK_LIB "libjack.so.0.0"
#define JACKMP_LIB "libjackmp.so" #define JACKMP_LIB "libjackmp.so"


@@ -227,6 +219,136 @@ static void close_library();
static void (*error_fun)(const char *) = 0; static void (*error_fun)(const char *) = 0;
static void (*info_fun)(const char *) = 0; static void (*info_fun)(const char *) = 0;


static void RewriteName(const char* name, char* new_name)
{
size_t i;
for (i = 0; i < strlen(name); i++) {
if ((name[i] == '/') || (name[i] == '\\'))
new_name[i] = '_';
else
new_name[i] = name[i];
}
new_name[i] = '\0';
}

/* 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;
}
fclose(fp);
}

if (!good) {
command = (char*)(JACK_LOCATION "/jackd");
strncpy(arguments, JACK_LOCATION "/jackd -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));
}

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 */
}

static void jack_log(const char *fmt,...) static void jack_log(const char *fmt,...)
{ {
/* /*
@@ -1016,7 +1138,6 @@ EXPORT jack_client_t * jack_client_open(const char *ext_client_name, jack_option
return res; return res;
} else { } else {
/*
jack_varargs_t va; // variable arguments jack_varargs_t va; // variable arguments
jack_status_t my_status; jack_status_t my_status;
char client_name[JACK_CLIENT_NAME_SIZE]; char client_name[JACK_CLIENT_NAME_SIZE];
@@ -1026,7 +1147,7 @@ EXPORT jack_client_t * jack_client_open(const char *ext_client_name, jack_option
return NULL; return NULL;
} }
JackTools::RewriteName(ext_client_name, client_name);
RewriteName(ext_client_name, client_name);


if (status == NULL) // no status from caller? if (status == NULL) // no status from caller?
status = &my_status; // use local status word status = &my_status; // use local status word
@@ -1056,8 +1177,6 @@ EXPORT jack_client_t * jack_client_open(const char *ext_client_name, jack_option
} else { } else {
return NULL; return NULL;
} }
*/
return NULL;
} }
} }




+ 5
- 0
common/JackInternalClient.cpp View File

@@ -56,6 +56,11 @@ JackSynchro** GetSynchroTable()
JackInternalClient::JackInternalClient(JackServer* server, JackSynchro** table): JackClient(table) JackInternalClient::JackInternalClient(JackServer* server, JackSynchro** table): JackClient(table)
{ {
fClientControl = new JackClientControl(); fClientControl = new JackClientControl();
/*
TODO: here we use a "direct access" to server internal, which is not safe if library clients access the server using
the "command thread" at the same time. So using the "command thread" also for internal clients would be safer.
We may want to keep the "direct access" to server internal mode for "server embeded in client process" kind of use.
*/
fChannel = new JackInternalClientChannel(server); fChannel = new JackInternalClientChannel(server);
} }




Loading…
Cancel
Save