Jack2 1.9.8
|
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 *ptr = NULL; 00042 char *ret = NULL; 00043 00044 user_jackdrc[0] = user_jackdrc[1] = 0; // Initialise 00045 00046 if (S_OK == SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, user_jackdrc)) 00047 { 00048 // The above call should have given us the path to the user's home folder 00049 char ch = user_jackdrc[strlen(user_jackdrc)-1]; 00050 00051 if (('/' != ch) && ('\\' != ch)) 00052 strcat(user_jackdrc, "\\"); 00053 00054 if (user_jackdrc[1] == ':') 00055 { 00056 // Assume we have a valid path 00057 strcat(user_jackdrc, ".jackdrc"); 00058 strcpy(path_to_jackdrc, user_jackdrc); 00059 00060 ret = path_to_jackdrc; 00061 } 00062 else 00063 path_to_jackdrc[0] = '\0'; 00064 } 00065 else 00066 path_to_jackdrc[0] = '\0'; 00067 00068 return (ret); 00069 } 00070 00071 #else 00072 00073 static char* 00074 find_path_to_jackdrc(char *path_to_jackdrc) 00075 { 00076 return 0; 00077 } 00078 00079 #endif 00080 00081 /* 'start_server_aux()' - this function might need to be modified (though probably 00082 * not) to cope with compilers other than MSVC (e.g. MinGW). The function 00083 * 'find_path_to_jackdrc()' might also need to be written for MinGW, though for 00084 * Cygwin, JackPosixServerLaunch.cpp can be used instead of this file. 00085 */ 00086 00087 #include <direct.h> 00088 00089 static int start_server_aux(const char* server_name) 00090 { 00091 FILE* fp = 0; 00092 size_t pos = 0; 00093 size_t result = 0; 00094 int i = 0; 00095 int good = 0; 00096 int ret = 0; 00097 char* command = 0; 00098 char** argv = 0; 00099 char* p; 00100 char* back_slash; 00101 char* forward_slash; 00102 char arguments [256]; 00103 char buffer [MAX_PATH]; 00104 char filename [MAX_PATH]; 00105 char curr_wd [MAX_PATH]; 00106 char temp_wd [MAX_PATH]; 00107 00108 curr_wd[0] = '\0'; 00109 if (find_path_to_jackdrc(filename)) 00110 fp = fopen(filename, "r"); 00111 00112 /* if still not found, check old config name for backwards compatability */ 00113 /* JE - hopefully won't be needed for the Windows build 00114 if (!fp) { 00115 fp = fopen("/etc/jackd.conf", "r"); 00116 } 00117 */ 00118 00119 if (fp) { 00120 arguments[0] = '\0'; 00121 00122 fgets(filename, MAX_PATH, fp); 00123 _strlwr(filename); 00124 if (p = strstr(filename, ".exe")) { 00125 p += 4; 00126 *p = '\0'; 00127 pos = (size_t)(p - filename); 00128 fseek(fp, 0, SEEK_SET); 00129 00130 if (command = (char*)malloc(pos+1)) 00131 ret = fread(command, 1, pos, fp); 00132 00133 if (ret && !ferror(fp)) { 00134 command[pos] = '\0'; // NULL terminator 00135 back_slash = strrchr(command, '\\'); 00136 forward_slash = strrchr(command, '/'); 00137 if (back_slash > forward_slash) 00138 p = back_slash + 1; 00139 else 00140 p = forward_slash + 1; 00141 00142 strcpy(buffer, p); 00143 while (ret != 0 && ret != EOF) { 00144 strcat(arguments, buffer); 00145 strcat(arguments, " "); 00146 ret = fscanf(fp, "%s", buffer); 00147 } 00148 00149 if (strlen(arguments) > 0) { 00150 good = 1; 00151 } 00152 } 00153 } 00154 00155 fclose(fp); 00156 } 00157 00158 if (!good) { 00159 strcpy(buffer, JACK_LOCATION "/jackd.exe"); 00160 command = (char*)malloc((strlen(buffer))+1); 00161 strcpy(command, buffer); 00162 strncpy(arguments, "jackd.exe -S -d " JACK_DEFAULT_DRIVER, 255); 00163 } 00164 00165 int buffer_termination; 00166 bool verbose_mode = false; 00167 argv = (char**)malloc(255); 00168 pos = 0; 00169 00170 while (1) { 00171 /* insert -T and -n server_name in front of arguments */ 00172 if (i == 1) { 00173 argv[i] = (char*)malloc(strlen ("-T") + 1); 00174 strcpy (argv[i++], "-T"); 00175 if (server_name) { 00176 size_t optlen = strlen("-n"); 00177 char* buf = (char*)malloc(optlen + strlen(server_name) + 1); 00178 strcpy(buf, "-n"); 00179 strcpy(buf + optlen, server_name); 00180 argv[i++] = buf; 00181 } 00182 } 00183 00184 // Only get the next character if there's more than 1 character 00185 if ((pos < strlen(arguments)) && (arguments[pos+1]) && (arguments[pos+1] != ' ')) { 00186 strncpy(buffer, arguments + pos++, 1); 00187 buffer_termination = 1; 00188 } else { 00189 buffer[0] = '\0'; 00190 buffer_termination = 0; 00191 } 00192 00193 buffer[1] = '\0'; 00194 if (buffer[0] == '\"') 00195 result = strcspn(arguments + pos, "\""); 00196 else 00197 result = strcspn(arguments + pos, " "); 00198 00199 if (0 == result) 00200 break; 00201 else 00202 { 00203 strcat(buffer, arguments + pos); 00204 00205 // Terminate the buffer 00206 buffer[result + buffer_termination] = '\0'; 00207 if (buffer[0] == '\"') { 00208 strcat(buffer, "\""); 00209 ++result; 00210 } 00211 00212 argv[i] = (char*)malloc(strlen(buffer) + 1); 00213 strcpy(argv[i], buffer); 00214 pos += (result + 1); 00215 ++i; 00216 00217 if ((0 == strcmp(buffer, "-v")) || (0 == strcmp(buffer, "--verbose"))) 00218 verbose_mode = true; 00219 } 00220 } 00221 00222 argv[i] = 0; 00223 00224 #ifdef SUPPORT_PRE_1_9_8_SERVER 00225 // Get the current working directory 00226 if (_getcwd(curr_wd, MAX_PATH)) { 00227 strcpy(temp_wd, command); 00228 back_slash = strrchr(temp_wd, '\\'); 00229 forward_slash = strrchr(temp_wd, '/'); 00230 if (back_slash > forward_slash) 00231 p = back_slash; 00232 else 00233 p = forward_slash; 00234 *p = '\0'; 00235 00236 // Accommodate older versions of Jack (pre v1.9.8) which 00237 // might need to be started from their installation folder. 00238 _chdir(temp_wd); 00239 } 00240 #endif 00241 00242 if (verbose_mode) { 00243 // Launch the server with a console... (note that 00244 // if the client is a console app, the server might 00245 // also use the client's console) 00246 ret = _spawnv(_P_NOWAIT, command, argv); 00247 } else { 00248 // Launch the server silently... (without a console) 00249 ret = _spawnv(_P_DETACH, command, argv); 00250 } 00251 00252 Sleep(2500); // Give it some time to launch 00253 00254 if ((-1) == ret) 00255 fprintf(stderr, "Execution of JACK server (command = \"%s\") failed: %s\n", command, strerror(errno)); 00256 00257 if (strlen(curr_wd)) { 00258 // Change the cwd back to its original setting 00259 _chdir(curr_wd); 00260 } 00261 00262 if (command) 00263 free(command); 00264 00265 if (argv) { 00266 for (i = 0; argv[i] != 0; i++) 00267 free (argv[i]); 00268 00269 free(argv); 00270 } 00271 00272 return (ret == (-1) ? false : true); 00273 } 00274 00275 static int start_server(const char* server_name, jack_options_t options) 00276 { 00277 if ((options & JackNoStartServer) || getenv("JACK_NO_START_SERVER")) { 00278 return 1; 00279 } 00280 00281 return (((-1) != (start_server_aux(server_name)) ? 0 : (-1))); 00282 } 00283 00284 static int server_connect(const char* server_name) 00285 { 00286 JackClientChannel channel; 00287 int res = channel.ServerCheck(server_name); 00288 channel.Close(); 00289 JackSleep(2000); // Added by JE - 02-01-2009 (gives 00290 // the channel some time to close) 00291 return res; 00292 } 00293 00294 int try_start_server(jack_varargs_t* va, jack_options_t options, jack_status_t* status) 00295 { 00296 if (server_connect(va->server_name) < 0) { 00297 int trys; 00298 if (start_server(va->server_name, options)) { 00299 int my_status1 = *status | JackFailure | JackServerFailed; 00300 *status = (jack_status_t)my_status1; 00301 return -1; 00302 } 00303 trys = 5; 00304 do { 00305 Sleep(1000); 00306 if (--trys < 0) { 00307 int my_status1 = *status | JackFailure | JackServerFailed; 00308 *status = (jack_status_t)my_status1; 00309 return -1; 00310 } 00311 } while (server_connect(va->server_name) < 0); 00312 int my_status1 = *status | JackServerStarted; 00313 *status = (jack_status_t)my_status1; 00314 } 00315 00316 return 0; 00317 }