Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2001-2003 Paul Davis 00003 Copyright (C) 2004-2008 Grame 00004 Copyright (C) 2011 John Emmas 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU Lesser General Public License as published by 00008 the Free Software Foundation; either version 2.1 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00019 00020 */ 00021 00022 #include "JackChannel.h" 00023 #include "JackLibGlobals.h" 00024 #include "JackServerLaunch.h" 00025 #include "JackPlatformPlug.h" 00026 00027 using namespace Jack; 00028 00029 #include <shlobj.h> 00030 #include <process.h> 00031 #include <string.h> 00032 #include <fcntl.h> 00033 #include <io.h> 00034 00035 #if defined(_MSC_VER) || defined(__MINGW__) || defined(__MINGW32__) 00036 00037 static char* 00038 find_path_to_jackdrc(char *path_to_jackdrc) 00039 { 00040 char user_jackdrc[1024]; 00041 char *ret = NULL; 00042 00043 user_jackdrc[0] = user_jackdrc[1] = 0; // Initialise 00044 00045 if (S_OK == SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, user_jackdrc)) 00046 { 00047 // The above call should have given us the path to the user's home folder 00048 char ch = user_jackdrc[strlen(user_jackdrc)-1]; 00049 00050 if (('/' != ch) && ('\\' != ch)) 00051 strcat(user_jackdrc, "\\"); 00052 00053 if (user_jackdrc[1] == ':') 00054 { 00055 // Assume we have a valid path 00056 strcat(user_jackdrc, ".jackdrc"); 00057 strcpy(path_to_jackdrc, user_jackdrc); 00058 00059 ret = path_to_jackdrc; 00060 } 00061 else 00062 path_to_jackdrc[0] = '\0'; 00063 } 00064 else 00065 path_to_jackdrc[0] = '\0'; 00066 00067 return (ret); 00068 } 00069 00070 #else 00071 00072 static char* 00073 find_path_to_jackdrc(char *path_to_jackdrc) 00074 { 00075 return 0; 00076 } 00077 00078 #endif 00079 00080 /* 'start_server_aux()' - this function might need to be modified (though probably 00081 * not) to cope with compilers other than MSVC (e.g. MinGW). The function 00082 * 'find_path_to_jackdrc()' might also need to be written for MinGW, though for 00083 * Cygwin, JackPosixServerLaunch.cpp can be used instead of this file. 00084 */ 00085 00086 #include <direct.h> 00087 00088 static int start_server_aux(const char* server_name) 00089 { 00090 FILE* fp = 0; 00091 size_t pos = 0; 00092 size_t result = 0; 00093 int i = 0; 00094 int good = 0; 00095 int ret = 0; 00096 char* command = 0; 00097 char** argv = 0; 00098 char* p; 00099 char* back_slash; 00100 char* forward_slash; 00101 char arguments [256]; 00102 char buffer [MAX_PATH]; 00103 char filename [MAX_PATH]; 00104 char curr_wd [MAX_PATH]; 00105 00106 curr_wd[0] = '\0'; 00107 if (find_path_to_jackdrc(filename)) 00108 fp = fopen(filename, "r"); 00109 00110 /* if still not found, check old config name for backwards compatability */ 00111 /* JE - hopefully won't be needed for the Windows build 00112 if (!fp) { 00113 fp = fopen("/etc/jackd.conf", "r"); 00114 } 00115 */ 00116 00117 if (fp) { 00118 arguments[0] = '\0'; 00119 00120 fgets(filename, MAX_PATH, fp); 00121 _strlwr(filename); 00122 if ((p = strstr(filename, ".exe"))) { 00123 p += 4; 00124 *p = '\0'; 00125 pos = (size_t)(p - filename); 00126 fseek(fp, 0, SEEK_SET); 00127 00128 if ((command = (char*)malloc(pos+1))) 00129 ret = fread(command, 1, pos, fp); 00130 00131 if (ret && !ferror(fp)) { 00132 command[pos] = '\0'; // NULL terminator 00133 back_slash = strrchr(command, '\\'); 00134 forward_slash = strrchr(command, '/'); 00135 if (back_slash > forward_slash) 00136 p = back_slash + 1; 00137 else 00138 p = forward_slash + 1; 00139 00140 strcpy(buffer, p); 00141 while (ret != 0 && ret != EOF) { 00142 strcat(arguments, buffer); 00143 strcat(arguments, " "); 00144 ret = fscanf(fp, "%s", buffer); 00145 } 00146 00147 if (strlen(arguments) > 0) { 00148 good = 1; 00149 } 00150 } 00151 } 00152 00153 fclose(fp); 00154 } 00155 00156 if (!good) { 00157 strcpy(buffer, JACK_LOCATION "/jackd.exe"); 00158 command = (char*)malloc((strlen(buffer))+1); 00159 strcpy(command, buffer); 00160 strncpy(arguments, "jackd.exe -S -d " JACK_DEFAULT_DRIVER, 255); 00161 } 00162 00163 int buffer_termination; 00164 bool verbose_mode = false; 00165 argv = (char**)malloc(255); 00166 pos = 0; 00167 00168 while (1) { 00169 /* insert -T and -n server_name in front of arguments */ 00170 if (i == 1) { 00171 argv[i] = (char*)malloc(strlen ("-T") + 1); 00172 strcpy (argv[i++], "-T"); 00173 if (server_name) { 00174 size_t optlen = strlen("-n"); 00175 char* buf = (char*)malloc(optlen + strlen(server_name) + 1); 00176 strcpy(buf, "-n"); 00177 strcpy(buf + optlen, server_name); 00178 argv[i++] = buf; 00179 } 00180 } 00181 00182 // Only get the next character if there's more than 1 character 00183 if ((pos < strlen(arguments)) && (arguments[pos+1]) && (arguments[pos+1] != ' ')) { 00184 strncpy(buffer, arguments + pos++, 1); 00185 buffer_termination = 1; 00186 } else { 00187 buffer[0] = '\0'; 00188 buffer_termination = 0; 00189 } 00190 00191 buffer[1] = '\0'; 00192 if (buffer[0] == '\"') 00193 result = strcspn(arguments + pos, "\""); 00194 else 00195 result = strcspn(arguments + pos, " "); 00196 00197 if (0 == result) 00198 break; 00199 else 00200 { 00201 strcat(buffer, arguments + pos); 00202 00203 // Terminate the buffer 00204 buffer[result + buffer_termination] = '\0'; 00205 if (buffer[0] == '\"') { 00206 strcat(buffer, "\""); 00207 ++result; 00208 } 00209 00210 argv[i] = (char*)malloc(strlen(buffer) + 1); 00211 strcpy(argv[i], buffer); 00212 pos += (result + 1); 00213 ++i; 00214 00215 if ((0 == strcmp(buffer, "-v")) || (0 == strcmp(buffer, "--verbose"))) 00216 verbose_mode = true; 00217 } 00218 } 00219 00220 argv[i] = 0; 00221 00222 #ifdef SUPPORT_PRE_1_9_8_SERVER 00223 // Get the current working directory 00224 if (_getcwd(curr_wd, MAX_PATH)) { 00225 strcpy(temp_wd, command); 00226 back_slash = strrchr(temp_wd, '\\'); 00227 forward_slash = strrchr(temp_wd, '/'); 00228 if (back_slash > forward_slash) 00229 p = back_slash; 00230 else 00231 p = forward_slash; 00232 *p = '\0'; 00233 00234 // Accommodate older versions of Jack (pre v1.9.8) which 00235 // might need to be started from their installation folder. 00236 _chdir(temp_wd); 00237 } 00238 #endif 00239 00240 if (verbose_mode) { 00241 // Launch the server with a console... (note that 00242 // if the client is a console app, the server might 00243 // also use the client's console) 00244 ret = _spawnv(_P_NOWAIT, command, argv); 00245 } else { 00246 // Launch the server silently... (without a console) 00247 ret = _spawnv(_P_DETACH, command, argv); 00248 } 00249 00250 Sleep(2500); // Give it some time to launch 00251 00252 if ((-1) == ret) 00253 fprintf(stderr, "Execution of JACK server (command = \"%s\") failed: %s\n", command, strerror(errno)); 00254 00255 if (strlen(curr_wd)) { 00256 // Change the cwd back to its original setting 00257 _chdir(curr_wd); 00258 } 00259 00260 if (command) 00261 free(command); 00262 00263 if (argv) { 00264 for (i = 0; argv[i] != 0; i++) 00265 free (argv[i]); 00266 00267 free(argv); 00268 } 00269 00270 return (ret == (-1) ? false : true); 00271 } 00272 00273 static int start_server(const char* server_name, jack_options_t options) 00274 { 00275 if ((options & JackNoStartServer) || getenv("JACK_NO_START_SERVER")) { 00276 return 1; 00277 } 00278 00279 return (((-1) != (start_server_aux(server_name)) ? 0 : (-1))); 00280 } 00281 00282 static int server_connect(const char* server_name) 00283 { 00284 JackClientChannel channel; 00285 int res = channel.ServerCheck(server_name); 00286 channel.Close(); 00287 /* 00288 JackSleep(2000); // Added by JE - 02-01-2009 (gives 00289 // the channel some time to close) 00290 */ 00291 JackSleep(500); 00292 return res; 00293 } 00294 00295 int try_start_server(jack_varargs_t* va, jack_options_t options, jack_status_t* status) 00296 { 00297 if (server_connect(va->server_name) < 0) { 00298 int trys; 00299 if (start_server(va->server_name, options)) { 00300 int my_status1 = *status | JackFailure | JackServerFailed; 00301 *status = (jack_status_t)my_status1; 00302 return -1; 00303 } 00304 trys = 5; 00305 do { 00306 Sleep(1000); 00307 if (--trys < 0) { 00308 int my_status1 = *status | JackFailure | JackServerFailed; 00309 *status = (jack_status_t)my_status1; 00310 return -1; 00311 } 00312 } while (server_connect(va->server_name) < 0); 00313 int my_status1 = *status | JackServerStarted; 00314 *status = (jack_status_t)my_status1; 00315 } 00316 00317 return 0; 00318 }