2 Copyright (C) 2001-2003 Paul Davis
3 Copyright (C) 2004-2008 Grame
4 Copyright (C) 2011 John Emmas
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.
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.
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.
22 #include "JackChannel.h"
23 #include "JackLibGlobals.h"
24 #include "JackServerLaunch.h"
25 #include "JackPlatformPlug.h"
35 #if defined(_MSC_VER) || defined(__MINGW__) || defined(__MINGW32__)
38 find_path_to_jackdrc(char *path_to_jackdrc
)
40 char user_jackdrc
[1024];
43 user_jackdrc
[0] = user_jackdrc
[1] = 0; // Initialise
45 if (S_OK
== SHGetFolderPath(NULL
, CSIDL_PROFILE
, NULL
, SHGFP_TYPE_CURRENT
, user_jackdrc
))
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];
50 if (('/' != ch
) && ('\\' != ch
))
51 strcat(user_jackdrc
, "\\");
53 if (user_jackdrc
[1] == ':')
55 // Assume we have a valid path
56 strcat(user_jackdrc
, ".jackdrc");
57 strcpy(path_to_jackdrc
, user_jackdrc
);
59 ret
= path_to_jackdrc
;
62 path_to_jackdrc
[0] = '\0';
65 path_to_jackdrc
[0] = '\0';
73 find_path_to_jackdrc(char *path_to_jackdrc
)
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.
88 static int start_server_aux(const char* server_name
)
101 char arguments
[256];
102 char buffer
[MAX_PATH
];
103 char filename
[MAX_PATH
];
104 char curr_wd
[MAX_PATH
];
107 if (find_path_to_jackdrc(filename
))
108 fp
= fopen(filename
, "r");
110 /* if still not found, check old config name for backwards compatability */
111 /* JE - hopefully won't be needed for the Windows build
113 fp = fopen("/etc/jackd.conf", "r");
120 fgets(filename
, MAX_PATH
, fp
);
122 if ((p
= strstr(filename
, ".exe"))) {
125 pos
= (size_t)(p
- filename
);
126 fseek(fp
, 0, SEEK_SET
);
128 if ((command
= (char*)malloc(pos
+1)))
129 ret
= fread(command
, 1, pos
, fp
);
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
)
138 p
= forward_slash
+ 1;
141 while (ret
!= 0 && ret
!= EOF
) {
142 strcat(arguments
, buffer
);
143 strcat(arguments
, " ");
144 ret
= fscanf(fp
, "%s", buffer
);
147 if (strlen(arguments
) > 0) {
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);
163 int buffer_termination
;
164 bool verbose_mode
= false;
165 argv
= (char**)malloc(255);
169 /* insert -T and -n server_name in front of arguments */
171 argv
[i
] = (char*)malloc(strlen ("-T") + 1);
172 strcpy (argv
[i
++], "-T");
174 size_t optlen
= strlen("-n");
175 char* buf
= (char*)malloc(optlen
+ strlen(server_name
) + 1);
177 strcpy(buf
+ optlen
, server_name
);
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;
188 buffer_termination
= 0;
192 if (buffer
[0] == '\"')
193 result
= strcspn(arguments
+ pos
, "\"");
195 result
= strcspn(arguments
+ pos
, " ");
201 strcat(buffer
, arguments
+ pos
);
203 // Terminate the buffer
204 buffer
[result
+ buffer_termination
] = '\0';
205 if (buffer
[0] == '\"') {
206 strcat(buffer
, "\"");
210 argv
[i
] = (char*)malloc(strlen(buffer
) + 1);
211 strcpy(argv
[i
], buffer
);
215 if ((0 == strcmp(buffer
, "-v")) || (0 == strcmp(buffer
, "--verbose")))
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
)
234 // Accommodate older versions of Jack (pre v1.9.8) which
235 // might need to be started from their installation folder.
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
);
246 // Launch the server silently... (without a console)
247 ret
= _spawnv(_P_DETACH
, command
, argv
);
250 Sleep(2500); // Give it some time to launch
253 fprintf(stderr
, "Execution of JACK server (command = \"%s\") failed: %s\n", command
, strerror(errno
));
255 if (strlen(curr_wd
)) {
256 // Change the cwd back to its original setting
264 for (i
= 0; argv
[i
] != 0; i
++)
270 return (ret
== (-1) ? false : true);
273 static int start_server(const char* server_name
, jack_options_t options
)
275 if ((options
& JackNoStartServer
) || getenv("JACK_NO_START_SERVER")) {
279 return (((-1) != (start_server_aux(server_name
)) ? 0 : (-1)));
282 static int server_connect(const char* server_name
)
284 JackClientChannel channel
;
285 int res
= channel
.ServerCheck(server_name
);
288 JackSleep(2000); // Added by JE - 02-01-2009 (gives
289 // the channel some time to close)
295 int try_start_server(jack_varargs_t
* va
, jack_options_t options
, jack_status_t
* status
)
297 if (server_connect(va
->server_name
) < 0) {
299 if (start_server(va
->server_name
, options
)) {
300 int my_status1
= *status
| JackFailure
| JackServerFailed
;
301 *status
= (jack_status_t
)my_status1
;
308 int my_status1
= *status
| JackFailure
| JackServerFailed
;
309 *status
= (jack_status_t
)my_status1
;
312 } while (server_connect(va
->server_name
) < 0);
313 int my_status1
= *status
| JackServerStarted
;
314 *status
= (jack_status_t
)my_status1
;