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.

316 lines
7.4KB

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