Init engine fields, cleanup.
[jack2.git] / common / JackServerGlobals.cpp
blobfcad0a7165a77bb940e3610e7a4fa257a6ed7970
1 /*
2 Copyright (C) 2005 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (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 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "JackServerGlobals.h"
21 #include "JackTools.h"
22 #include "shm.h"
23 #include <getopt.h>
24 #include <errno.h>
26 static char* server_name = NULL;
28 namespace Jack
31 JackServer* JackServerGlobals::fInstance;
32 unsigned int JackServerGlobals::fUserCount;
33 bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL;
34 void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL;
36 int JackServerGlobals::Start(const char* server_name,
37 jack_driver_desc_t* driver_desc,
38 JSList* driver_params,
39 int sync,
40 int temporary,
41 int time_out_ms,
42 int rt,
43 int priority,
44 int port_max,
45 int verbose,
46 jack_timer_type_t clock)
48 jack_log("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld ", sync, time_out_ms, rt, priority, verbose);
49 new JackServer(sync, temporary, time_out_ms, rt, priority, port_max, verbose, clock, server_name); // Will setup fInstance and fUserCount globals
50 int res = fInstance->Open(driver_desc, driver_params);
51 return (res < 0) ? res : fInstance->Start();
54 void JackServerGlobals::Stop()
56 jack_log("Jackdmp: server close");
57 fInstance->Stop();
58 fInstance->Close();
61 void JackServerGlobals::Delete()
63 jack_log("Jackdmp: delete server");
64 delete fInstance;
65 fInstance = NULL;
68 bool JackServerGlobals::Init()
70 int realtime = 0;
71 int client_timeout = 0; /* msecs; if zero, use period size. */
72 int realtime_priority = 10;
73 int verbose_aux = 0;
74 int do_mlock = 1;
75 unsigned int port_max = 128;
76 int do_unlock = 0;
77 int temporary = 0;
79 int opt = 0;
80 int option_index = 0;
81 int seen_driver = 0;
82 char *driver_name = NULL;
83 char **driver_args = NULL;
84 JSList* driver_params = NULL;
85 int driver_nargs = 1;
86 JSList* drivers = NULL;
87 int show_version = 0;
88 int sync = 0;
89 int rc, i;
90 int ret;
92 FILE* fp = 0;
93 char filename[255];
94 char buffer[255];
95 int argc = 0;
96 char* argv[32];
97 jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK;
99 // First user starts the server
100 if (fUserCount++ == 0) {
102 jack_log("JackServerGlobals Init");
104 jack_driver_desc_t* driver_desc;
105 const char *options = "-ad:P:uvshVRL:STFl:t:mn:p:c:";
106 static struct option long_options[] = {
107 { "clock-source", 1, 0, 'c' },
108 { "driver", 1, 0, 'd' },
109 { "verbose", 0, 0, 'v' },
110 { "help", 0, 0, 'h' },
111 { "port-max", 1, 0, 'p' },
112 { "no-mlock", 0, 0, 'm' },
113 { "name", 0, 0, 'n' },
114 { "unlock", 0, 0, 'u' },
115 { "realtime", 0, 0, 'R' },
116 { "realtime-priority", 1, 0, 'P' },
117 { "timeout", 1, 0, 't' },
118 { "temporary", 0, 0, 'T' },
119 { "version", 0, 0, 'V' },
120 { "silent", 0, 0, 's' },
121 { "sync", 0, 0, 'S' },
122 { 0, 0, 0, 0 }
125 snprintf(filename, 255, "%s/.jackdrc", getenv("HOME"));
126 fp = fopen(filename, "r");
128 if (!fp) {
129 fp = fopen("/etc/jackdrc", "r");
131 // if still not found, check old config name for backwards compatability
132 if (!fp) {
133 fp = fopen("/etc/jackd.conf", "r");
136 argc = 0;
137 if (fp) {
138 ret = fscanf(fp, "%s", buffer);
139 while (ret != 0 && ret != EOF) {
140 argv[argc] = (char*)malloc(64);
141 strcpy(argv[argc], buffer);
142 ret = fscanf(fp, "%s", buffer);
143 argc++;
145 fclose(fp);
149 For testing
150 int argc = 15;
151 char* argv[] = {"jackdmp", "-R", "-v", "-d", "coreaudio", "-p", "512", "-d", "~:Aggregate:0", "-r", "48000", "-i", "2", "-o", "2" };
154 opterr = 0;
155 optind = 1; // Important : to reset argv parsing
157 while (!seen_driver &&
158 (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) {
160 switch (opt) {
162 case 'c':
163 if (tolower (optarg[0]) == 'h') {
164 clock_source = JACK_TIMER_HPET;
165 } else if (tolower (optarg[0]) == 'c') {
166 clock_source = JACK_TIMER_CYCLE_COUNTER;
167 } else if (tolower (optarg[0]) == 's') {
168 clock_source = JACK_TIMER_SYSTEM_CLOCK;
169 } else {
170 jack_error("unknown option character %c", optopt);
172 break;
174 case 'd':
175 seen_driver = 1;
176 driver_name = optarg;
177 break;
179 case 'v':
180 verbose_aux = 1;
181 break;
183 case 'S':
184 sync = 1;
185 break;
187 case 'n':
188 server_name = optarg;
189 break;
191 case 'm':
192 do_mlock = 0;
193 break;
195 case 'p':
196 port_max = (unsigned int)atol(optarg);
197 break;
199 case 'P':
200 realtime_priority = atoi(optarg);
201 break;
203 case 'R':
204 realtime = 1;
205 break;
207 case 'T':
208 temporary = 1;
209 break;
211 case 't':
212 client_timeout = atoi(optarg);
213 break;
215 case 'u':
216 do_unlock = 1;
217 break;
219 case 'V':
220 show_version = 1;
221 break;
223 default:
224 jack_error("unknown option character %c", optopt);
225 break;
229 drivers = jack_drivers_load(drivers);
230 if (!drivers) {
231 jack_error("jackdmp: no drivers found; exiting");
232 goto error;
235 driver_desc = jack_find_driver_descriptor(drivers, driver_name);
236 if (!driver_desc) {
237 jack_error("jackdmp: unknown driver '%s'", driver_name);
238 goto error;
241 if (optind < argc) {
242 driver_nargs = 1 + argc - optind;
243 } else {
244 driver_nargs = 1;
247 if (driver_nargs == 0) {
248 jack_error("No driver specified ... hmm. JACK won't do"
249 " anything when run like this.");
250 goto error;
253 driver_args = (char**)malloc(sizeof(char*) * driver_nargs);
254 driver_args[0] = driver_name;
256 for (i = 1; i < driver_nargs; i++) {
257 driver_args[i] = argv[optind++];
260 if (jack_parse_driver_params(driver_desc, driver_nargs, driver_args, &driver_params)) {
261 goto error;
264 #ifndef WIN32
265 if (server_name == NULL)
266 server_name = (char*)JackTools::DefaultServerName();
267 #endif
269 rc = jack_register_server(server_name, false);
270 switch (rc) {
271 case EEXIST:
272 jack_error("`%s' server already active", server_name);
273 goto error;
274 case ENOSPC:
275 jack_error("too many servers already active");
276 goto error;
277 case ENOMEM:
278 jack_error("no access to shm registry");
279 goto error;
280 default:
281 jack_info("server `%s' registered", server_name);
284 /* clean up shared memory and files from any previous instance of this server name */
285 jack_cleanup_shm();
286 JackTools::CleanupFiles(server_name);
288 if (!realtime && client_timeout == 0)
289 client_timeout = 500; /* 0.5 sec; usable when non realtime. */
291 for (i = 0; i < argc; i++) {
292 free(argv[i]);
295 int res = Start(server_name, driver_desc, driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source);
296 if (res < 0) {
297 jack_error("Cannot start server... exit");
298 Delete();
299 jack_cleanup_shm();
300 JackTools::CleanupFiles(server_name);
301 jack_unregister_server(server_name);
302 goto error;
306 if (driver_params)
307 jack_free_driver_params(driver_params);
308 return true;
310 error:
311 if (driver_params)
312 jack_free_driver_params(driver_params);
313 fUserCount--;
314 return false;
317 void JackServerGlobals::Destroy()
319 if (--fUserCount == 0) {
320 jack_log("JackServerGlobals Destroy");
321 Stop();
322 Delete();
323 jack_cleanup_shm();
324 JackTools::CleanupFiles(server_name);
325 jack_unregister_server(server_name);
329 } // end of namespace