/* Copyright (C) 2001-2003 Paul Davis Copyright (C) 2004-2008 Grame Copyright (C) 2011 John Emmas This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "JackChannel.h" #include "JackLibGlobals.h" #include "JackServerLaunch.h" #include "JackPlatformPlug.h" using namespace Jack; #include #include #include #include #include #if defined(_MSC_VER) || defined(__MINGW__) || defined(__MINGW32__) static char* find_path_to_jackdrc(char *path_to_jackdrc) { char user_jackdrc[1024]; char *ret = NULL; user_jackdrc[0] = user_jackdrc[1] = 0; // Initialise if (S_OK == SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, user_jackdrc)) { // The above call should have given us the path to the user's home folder char ch = user_jackdrc[strlen(user_jackdrc)-1]; if (('/' != ch) && ('\\' != ch)) strcat(user_jackdrc, "\\"); if (user_jackdrc[1] == ':') { // Assume we have a valid path strcat(user_jackdrc, ".jackdrc"); strcpy(path_to_jackdrc, user_jackdrc); ret = path_to_jackdrc; } else path_to_jackdrc[0] = '\0'; } else path_to_jackdrc[0] = '\0'; return (ret); } #else static char* find_path_to_jackdrc(char *path_to_jackdrc) { return 0; } #endif /* 'start_server_aux()' - this function might need to be modified (though probably * not) to cope with compilers other than MSVC (e.g. MinGW). The function * 'find_path_to_jackdrc()' might also need to be written for MinGW, though for * Cygwin, JackPosixServerLaunch.cpp can be used instead of this file. */ #include static int start_server_aux(const char* server_name) { FILE* fp = 0; size_t pos = 0; size_t result = 0; int i = 0; int good = 0; int ret = 0; char* command = 0; char** argv = 0; char* p; char* back_slash; char* forward_slash; char arguments [256]; char buffer [MAX_PATH]; char filename [MAX_PATH]; char curr_wd [MAX_PATH]; curr_wd[0] = '\0'; if (find_path_to_jackdrc(filename)) fp = fopen(filename, "r"); /* if still not found, check old config name for backwards compatibility */ /* JE - hopefully won't be needed for the Windows build if (!fp) { fp = fopen("/etc/jackd.conf", "r"); } */ if (fp) { arguments[0] = '\0'; fgets(filename, MAX_PATH, fp); _strlwr(filename); if ((p = strstr(filename, ".exe"))) { p += 4; *p = '\0'; pos = (size_t)(p - filename); fseek(fp, 0, SEEK_SET); if ((command = (char*)malloc(pos+1))) ret = fread(command, 1, pos, fp); if (ret && !ferror(fp)) { command[pos] = '\0'; // NULL terminator back_slash = strrchr(command, '\\'); forward_slash = strrchr(command, '/'); if (back_slash > forward_slash) p = back_slash + 1; else p = forward_slash + 1; strcpy(buffer, p); 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) { strcpy(buffer, JACK_LOCATION "/jackd.exe"); command = (char*)malloc((strlen(buffer))+1); strcpy(command, buffer); strncpy(arguments, "jackd.exe -S -d " JACK_DEFAULT_DRIVER, 255); } int buffer_termination; bool verbose_mode = false; argv = (char**)malloc(255); pos = 0; while (1) { /* insert -T and -n server_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; } } // Only get the next character if there's more than 1 character if ((pos < strlen(arguments)) && (arguments[pos+1]) && (arguments[pos+1] != ' ')) { strncpy(buffer, arguments + pos++, 1); buffer_termination = 1; } else { buffer[0] = '\0'; buffer_termination = 0; } buffer[1] = '\0'; if (buffer[0] == '\"') result = strcspn(arguments + pos, "\""); else result = strcspn(arguments + pos, " "); if (0 == result) break; else { strcat(buffer, arguments + pos); // Terminate the buffer buffer[result + buffer_termination] = '\0'; if (buffer[0] == '\"') { strcat(buffer, "\""); ++result; } argv[i] = (char*)malloc(strlen(buffer) + 1); strcpy(argv[i], buffer); pos += (result + 1); ++i; if ((0 == strcmp(buffer, "-v")) || (0 == strcmp(buffer, "--verbose"))) verbose_mode = true; } } argv[i] = 0; #ifdef SUPPORT_PRE_1_9_8_SERVER // Get the current working directory if (_getcwd(curr_wd, MAX_PATH)) { strcpy(temp_wd, command); back_slash = strrchr(temp_wd, '\\'); forward_slash = strrchr(temp_wd, '/'); if (back_slash > forward_slash) p = back_slash; else p = forward_slash; *p = '\0'; // Accommodate older versions of Jack (pre v1.9.8) which // might need to be started from their installation folder. _chdir(temp_wd); } #endif if (verbose_mode) { // Launch the server with a console... (note that // if the client is a console app, the server might // also use the client's console) ret = _spawnv(_P_NOWAIT, command, argv); } else { // Launch the server silently... (without a console) ret = _spawnv(_P_DETACH, command, argv); } Sleep(2500); // Give it some time to launch if ((-1) == ret) fprintf(stderr, "Execution of JACK server (command = \"%s\") failed: %s\n", command, strerror(errno)); if (strlen(curr_wd)) { // Change the cwd back to its original setting _chdir(curr_wd); } if (command) free(command); if (argv) { for (i = 0; argv[i] != 0; i++) free (argv[i]); free(argv); } return (ret == (-1) ? false : true); } static int start_server(const char* server_name, jack_options_t options) { if ((options & JackNoStartServer) || getenv("JACK_NO_START_SERVER")) { return 1; } return (((-1) != (start_server_aux(server_name)) ? 0 : (-1))); } static int server_connect(const char* server_name) { JackClientChannel channel; int res = channel.ServerCheck(server_name); channel.Close(); /* JackSleep(2000); // Added by JE - 02-01-2009 (gives // the channel some time to close) */ JackSleep(500); return res; } 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(1000); 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; }