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.

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