Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2001-2003 Paul Davis 00003 Copyright (C) 2004-2008 Grame 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU Lesser General Public License as published by 00007 the Free Software Foundation; either version 2.1 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 00019 */ 00020 #if !defined(WIN32) || defined(__CYGWIN__) 00021 00022 #ifdef PTHREAD_WIN32 // Added by JE - 13-02-2010 00023 #include <ptw32/pthread.h> // Makes sure we #include the ptw32 version for 00024 #endif // consistency - even though we won't need it ! 00025 00026 #include "JackConstants.h" 00027 #include "JackChannel.h" 00028 #include "JackLibGlobals.h" 00029 #include "JackServerLaunch.h" 00030 #include "JackPlatformPlug.h" 00031 00032 #include <sys/wait.h> 00033 00034 using namespace Jack; 00035 00036 #if defined(USE_LIBDBUS_AUTOLAUNCH) 00037 00038 #include <dbus/dbus.h> 00039 00040 static int start_server_dbus(const char* server_name) 00041 { 00042 DBusError err; 00043 DBusConnection *conn; 00044 DBusMessage *msg; 00045 00046 // initialise the errors 00047 dbus_error_init(&err); 00048 00049 // connect to the bus 00050 conn = dbus_bus_get(DBUS_BUS_SESSION, &err); 00051 if (dbus_error_is_set(&err)) { 00052 fprintf(stderr, "Connection Error (%s)\n", err.message); 00053 dbus_error_free(&err); 00054 } 00055 if (NULL == conn) { 00056 return 1; 00057 } 00058 00059 msg = dbus_message_new_method_call( 00060 "org.jackaudio.service", // target for the method call 00061 "/org/jackaudio/Controller", // object to call on 00062 "org.jackaudio.JackControl", // interface to call on 00063 "StartServer"); // method name 00064 if (NULL == msg) { 00065 fprintf(stderr, "Message Null\n"); 00066 return 1; 00067 } 00068 00069 // send message and get a handle for a reply 00070 if (!dbus_connection_send(conn, msg, NULL)) 00071 { 00072 fprintf(stderr, "Out Of Memory!\n"); 00073 return 1; 00074 } 00075 00076 dbus_message_unref(msg); 00077 dbus_connection_flush(conn); 00078 dbus_error_free(&err); 00079 00080 return 0; 00081 } 00082 00083 #elif defined(USE_CLASSIC_AUTOLAUNCH) 00084 00085 /* Exec the JACK server in this process. Does not return. */ 00086 static void start_server_classic_aux(const char* server_name) 00087 { 00088 FILE* fp = 0; 00089 char filename[255]; 00090 char arguments[255]; 00091 char buffer[255]; 00092 char* command = 0; 00093 size_t pos = 0; 00094 size_t result = 0; 00095 char** argv = 0; 00096 int i = 0; 00097 int good = 0; 00098 int res; 00099 00100 snprintf(filename, 255, "%s/.jackdrc", getenv("HOME")); 00101 fp = fopen(filename, "r"); 00102 00103 if (!fp) { 00104 fp = fopen("/etc/jackdrc", "r"); 00105 } 00106 /* if still not found, check old config name for backwards compatability */ 00107 if (!fp) { 00108 fp = fopen("/etc/jackd.conf", "r"); 00109 } 00110 00111 if (fp) { 00112 arguments[0] = '\0'; 00113 res = fscanf(fp, "%s", buffer); 00114 while (res != 0 && res != EOF) { 00115 strcat(arguments, buffer); 00116 strcat(arguments, " "); 00117 res = fscanf(fp, "%s", buffer); 00118 } 00119 if (strlen(arguments) > 0) { 00120 good = 1; 00121 } 00122 fclose(fp); 00123 } 00124 00125 if (!good) { 00126 command = (char*)(JACK_LOCATION "/jackd"); 00127 strncpy(arguments, JACK_LOCATION "/jackd -T -d "JACK_DEFAULT_DRIVER, 255); 00128 } else { 00129 result = strcspn(arguments, " "); 00130 command = (char*)malloc(result + 1); 00131 strncpy(command, arguments, result); 00132 command[result] = '\0'; 00133 } 00134 00135 argv = (char**)malloc(255); 00136 00137 while (1) { 00138 /* insert -T and -nserver_name in front of arguments */ 00139 if (i == 1) { 00140 argv[i] = (char*)malloc(strlen ("-T") + 1); 00141 strcpy (argv[i++], "-T"); 00142 if (server_name) { 00143 size_t optlen = strlen("-n"); 00144 char* buf = (char*)malloc(optlen + strlen(server_name) + 1); 00145 strcpy(buf, "-n"); 00146 strcpy(buf + optlen, server_name); 00147 argv[i++] = buf; 00148 } 00149 } 00150 00151 result = strcspn(arguments + pos, " "); 00152 if (result == 0) { 00153 break; 00154 } 00155 argv[i] = (char*)malloc(result + 1); 00156 strncpy(argv[i], arguments + pos, result); 00157 argv[i][result] = '\0'; 00158 pos += result + 1; 00159 ++i; 00160 } 00161 argv[i] = 0; 00162 execv(command, argv); 00163 00164 /* If execv() succeeds, it does not return. There's no point 00165 * in calling jack_error() here in the child process. */ 00166 fprintf(stderr, "exec of JACK server (command = \"%s\") failed: %s\n", command, strerror(errno)); 00167 } 00168 00169 static int start_server_classic(const char* server_name) 00170 { 00171 /* The double fork() forces the server to become a child of 00172 * init, which will always clean up zombie process state on 00173 * termination. This even works in cases where the server 00174 * terminates but this client does not. 00175 * 00176 * Since fork() is usually implemented using copy-on-write 00177 * virtual memory tricks, the overhead of the second fork() is 00178 * probably relatively small. 00179 */ 00180 00181 int status; 00182 pid_t first_child_pid; 00183 00184 first_child_pid = fork(); 00185 switch (first_child_pid) { 00186 case 0: /* child process */ 00187 switch (fork()) { 00188 case 0: /* grandchild process */ 00189 start_server_classic_aux(server_name); 00190 _exit(99); /* exec failed */ 00191 case - 1: 00192 _exit(98); 00193 default: 00194 _exit(0); 00195 } 00196 case - 1: /* fork() error */ 00197 return 1; /* failed to start server */ 00198 } 00199 waitpid(first_child_pid, &status, 0); 00200 00201 /* only the original parent process goes here */ 00202 return 0; /* (probably) successful */ 00203 } 00204 00205 #endif 00206 00207 static int start_server(const char* server_name, jack_options_t options) 00208 { 00209 if ((options & JackNoStartServer) || getenv("JACK_NO_START_SERVER")) { 00210 return 1; 00211 } 00212 00213 #if defined(USE_LIBDBUS_AUTOLAUNCH) 00214 return start_server_dbus(server_name); 00215 #elif defined(USE_CLASSIC_AUTOLAUNCH) 00216 return start_server_classic(server_name); 00217 #else 00218 fprintf(stderr, "Automatic start of JACK server is disabled at configure time\n"); 00219 return 1; 00220 #endif 00221 } 00222 00223 static int server_connect(char* server_name) 00224 { 00225 JackClientChannel channel; 00226 int res = channel.ServerCheck(server_name); 00227 channel.Close(); 00228 JackSleep(2000); // Added by JE - 02-01-2009 (gives 00229 // the channel some time to close) 00230 return res; 00231 } 00232 00233 int try_start_server(jack_varargs_t* va, jack_options_t options, jack_status_t* status) 00234 { 00235 if (server_connect(va->server_name) < 0) { 00236 int trys; 00237 if (start_server(va->server_name, options)) { 00238 int my_status1 = *status | JackFailure | JackServerFailed; 00239 *status = (jack_status_t)my_status1; 00240 return -1; 00241 } 00242 trys = 5; 00243 do { 00244 sleep(1); 00245 if (--trys < 0) { 00246 int my_status1 = *status | JackFailure | JackServerFailed; 00247 *status = (jack_status_t)my_status1; 00248 return -1; 00249 } 00250 } while (server_connect(va->server_name) < 0); 00251 int my_status1 = *status | JackServerStarted; 00252 *status = (jack_status_t)my_status1; 00253 } 00254 00255 return 0; 00256 } 00257 00258 #endif // !defined(WIN32) || defined(__CYGWIN__)