jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

319 lines
7.7KB

  1. /*
  2. Copyright (C) 2001-2003 Paul Davis
  3. Copyright (C) 2004-2008 Grame
  4. Copyright (C) 2011 John Emmas
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as published by
  7. the Free Software Foundation; either version 2.1 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  16. */
  17. #include "JackChannel.h"
  18. #include "JackLibGlobals.h"
  19. #include "JackServerLaunch.h"
  20. #include "JackPlatformPlug.h"
  21. using namespace Jack;
  22. #include <shlobj.h>
  23. #include <process.h>
  24. #include <string.h>
  25. #include <fcntl.h>
  26. #include <io.h>
  27. #if defined(_MSC_VER) || defined(__MINGW__) || defined(__MINGW32__)
  28. static char*
  29. find_path_to_jackdrc(char *path_to_jackdrc)
  30. {
  31. char user_jackdrc[1024];
  32. char *ret = NULL;
  33. user_jackdrc[0] = user_jackdrc[1] = 0; // Initialise
  34. if (S_OK == SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, user_jackdrc))
  35. {
  36. // The above call should have given us the path to the user's home folder
  37. char ch = user_jackdrc[strlen(user_jackdrc)-1];
  38. if (('/' != ch) && ('\\' != ch))
  39. strcat(user_jackdrc, "\\");
  40. if (user_jackdrc[1] == ':')
  41. {
  42. // Assume we have a valid path
  43. strcat(user_jackdrc, ".jackdrc");
  44. strcpy(path_to_jackdrc, user_jackdrc);
  45. ret = path_to_jackdrc;
  46. }
  47. else
  48. path_to_jackdrc[0] = '\0';
  49. }
  50. else
  51. path_to_jackdrc[0] = '\0';
  52. return (ret);
  53. }
  54. #else
  55. static char*
  56. find_path_to_jackdrc(char *path_to_jackdrc)
  57. {
  58. return 0;
  59. }
  60. #endif
  61. /* 'start_server_aux()' - this function might need to be modified (though probably
  62. * not) to cope with compilers other than MSVC (e.g. MinGW). The function
  63. * 'find_path_to_jackdrc()' might also need to be written for MinGW, though for
  64. * Cygwin, JackPosixServerLaunch.cpp can be used instead of this file.
  65. */
  66. #include <direct.h>
  67. static int start_server_aux(const char* server_name)
  68. {
  69. FILE* fp = 0;
  70. size_t pos = 0;
  71. size_t result = 0;
  72. int i = 0;
  73. int good = 0;
  74. int ret = 0;
  75. char* command = 0;
  76. char** argv = 0;
  77. char* p;
  78. char* back_slash;
  79. char* forward_slash;
  80. char arguments [256];
  81. char buffer [MAX_PATH];
  82. char filename [MAX_PATH];
  83. char curr_wd [MAX_PATH];
  84. curr_wd[0] = '\0';
  85. if (find_path_to_jackdrc(filename))
  86. fp = fopen(filename, "r");
  87. /* if still not found, check old config name for backwards compatibility */
  88. /* JE - hopefully won't be needed for the Windows build
  89. if (!fp) {
  90. fp = fopen("/etc/jackd.conf", "r");
  91. }
  92. */
  93. if (fp) {
  94. arguments[0] = '\0';
  95. fgets(filename, MAX_PATH, fp);
  96. _strlwr(filename);
  97. if ((p = strstr(filename, ".exe"))) {
  98. p += 4;
  99. *p = '\0';
  100. pos = (size_t)(p - filename);
  101. fseek(fp, 0, SEEK_SET);
  102. if ((command = (char*)malloc(pos+1)))
  103. ret = fread(command, 1, pos, fp);
  104. if (ret && !ferror(fp)) {
  105. command[pos] = '\0'; // NULL terminator
  106. back_slash = strrchr(command, '\\');
  107. forward_slash = strrchr(command, '/');
  108. if (back_slash > forward_slash)
  109. p = back_slash + 1;
  110. else
  111. p = forward_slash + 1;
  112. strcpy(buffer, p);
  113. while (ret != 0 && ret != EOF) {
  114. strcat(arguments, buffer);
  115. strcat(arguments, " ");
  116. ret = fscanf(fp, "%s", buffer);
  117. }
  118. if (strlen(arguments) > 0) {
  119. good = 1;
  120. }
  121. }
  122. }
  123. fclose(fp);
  124. }
  125. if (!good) {
  126. strcpy(buffer, JACK_LOCATION "/jackd.exe");
  127. command = (char*)malloc((strlen(buffer))+1);
  128. strcpy(command, buffer);
  129. strncpy(arguments, "jackd.exe -S -d " JACK_DEFAULT_DRIVER, 255);
  130. }
  131. int buffer_termination;
  132. bool verbose_mode = false;
  133. argv = (char**)malloc(255);
  134. pos = 0;
  135. while (1) {
  136. /* insert -T and -n server_name in front of arguments */
  137. if (i == 1) {
  138. argv[i] = (char*)malloc(strlen ("-T") + 1);
  139. strcpy (argv[i++], "-T");
  140. if (server_name) {
  141. size_t optlen = strlen("-n");
  142. char* buf = (char*)malloc(optlen + strlen(server_name) + 1);
  143. strcpy(buf, "-n");
  144. strcpy(buf + optlen, server_name);
  145. argv[i++] = buf;
  146. }
  147. }
  148. // Only get the next character if there's more than 1 character
  149. if ((pos < strlen(arguments)) && (arguments[pos+1]) && (arguments[pos+1] != ' ')) {
  150. strncpy(buffer, arguments + pos++, 1);
  151. buffer_termination = 1;
  152. } else {
  153. buffer[0] = '\0';
  154. buffer_termination = 0;
  155. }
  156. buffer[1] = '\0';
  157. if (buffer[0] == '\"')
  158. result = strcspn(arguments + pos, "\"");
  159. else
  160. result = strcspn(arguments + pos, " ");
  161. if (0 == result)
  162. break;
  163. else
  164. {
  165. strcat(buffer, arguments + pos);
  166. // Terminate the buffer
  167. buffer[result + buffer_termination] = '\0';
  168. if (buffer[0] == '\"') {
  169. strcat(buffer, "\"");
  170. ++result;
  171. }
  172. argv[i] = (char*)malloc(strlen(buffer) + 1);
  173. strcpy(argv[i], buffer);
  174. pos += (result + 1);
  175. ++i;
  176. if ((0 == strcmp(buffer, "-v")) || (0 == strcmp(buffer, "--verbose")))
  177. verbose_mode = true;
  178. }
  179. }
  180. argv[i] = 0;
  181. #ifdef SUPPORT_PRE_1_9_8_SERVER
  182. // Get the current working directory
  183. if (_getcwd(curr_wd, MAX_PATH)) {
  184. strcpy(temp_wd, command);
  185. back_slash = strrchr(temp_wd, '\\');
  186. forward_slash = strrchr(temp_wd, '/');
  187. if (back_slash > forward_slash)
  188. p = back_slash;
  189. else
  190. p = forward_slash;
  191. *p = '\0';
  192. // Accommodate older versions of Jack (pre v1.9.8) which
  193. // might need to be started from their installation folder.
  194. _chdir(temp_wd);
  195. }
  196. #endif
  197. if (verbose_mode) {
  198. // Launch the server with a console... (note that
  199. // if the client is a console app, the server might
  200. // also use the client's console)
  201. ret = _spawnv(_P_NOWAIT, command, argv);
  202. } else {
  203. // Launch the server silently... (without a console)
  204. ret = _spawnv(_P_DETACH, command, argv);
  205. }
  206. Sleep(2500); // Give it some time to launch
  207. if ((-1) == ret)
  208. fprintf(stderr, "Execution of JACK server (command = \"%s\") failed: %s\n", command, strerror(errno));
  209. if (strlen(curr_wd)) {
  210. // Change the cwd back to its original setting
  211. _chdir(curr_wd);
  212. }
  213. if (command)
  214. free(command);
  215. if (argv) {
  216. for (i = 0; argv[i] != 0; i++)
  217. free (argv[i]);
  218. free(argv);
  219. }
  220. return (ret == (-1) ? false : true);
  221. }
  222. static int start_server(const char* server_name, jack_options_t options)
  223. {
  224. if ((options & JackNoStartServer) || getenv("JACK_NO_START_SERVER")) {
  225. return 1;
  226. }
  227. return (((-1) != (start_server_aux(server_name)) ? 0 : (-1)));
  228. }
  229. static int server_connect(const char* server_name)
  230. {
  231. JackClientChannel channel;
  232. int res = channel.ServerCheck(server_name);
  233. channel.Close();
  234. /*
  235. JackSleep(2000); // Added by JE - 02-01-2009 (gives
  236. // the channel some time to close)
  237. */
  238. JackSleep(500);
  239. return res;
  240. }
  241. int try_start_server(jack_varargs_t* va, jack_options_t options, jack_status_t* status)
  242. {
  243. if (server_connect(va->server_name) < 0) {
  244. int trys;
  245. if (start_server(va->server_name, options)) {
  246. int my_status1 = *status | JackFailure | JackServerFailed;
  247. *status = (jack_status_t)my_status1;
  248. return -1;
  249. }
  250. trys = 5;
  251. do {
  252. Sleep(1000);
  253. if (--trys < 0) {
  254. int my_status1 = *status | JackFailure | JackServerFailed;
  255. *status = (jack_status_t)my_status1;
  256. return -1;
  257. }
  258. } while (server_connect(va->server_name) < 0);
  259. int my_status1 = *status | JackServerStarted;
  260. *status = (jack_status_t)my_status1;
  261. }
  262. return 0;
  263. }