Jack2 1.9.12

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