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 "JackLockedEngine.h"
22 #include "JackTools.h"
27 static char* server_name
= NULL
;
32 JackServer
* JackServerGlobals::fInstance
;
33 unsigned int JackServerGlobals::fUserCount
;
34 std::map
<std::string
, JackDriverInfo
*> JackServerGlobals::fSlavesList
;
35 std::map
<std::string
, int> JackServerGlobals::fInternalsList
;
37 bool (* JackServerGlobals::on_device_acquire
)(const char * device_name
) = NULL
;
38 void (* JackServerGlobals::on_device_release
)(const char * device_name
) = NULL
;
40 int JackServerGlobals::Start(const char* server_name
,
41 jack_driver_desc_t
* driver_desc
,
42 JSList
* driver_params
,
50 jack_timer_type_t clock
,
51 char self_connect_mode
)
53 jack_log("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld ", sync
, time_out_ms
, rt
, priority
, verbose
);
54 new JackServer(sync
, temporary
, time_out_ms
, rt
, priority
, port_max
, verbose
, clock
, self_connect_mode
, server_name
); // Will setup fInstance and fUserCount globals
55 int res
= fInstance
->Open(driver_desc
, driver_params
);
56 return (res
< 0) ? res
: fInstance
->Start();
59 void JackServerGlobals::Stop()
61 jack_log("Jackdmp: server close");
66 void JackServerGlobals::Delete()
68 jack_log("Jackdmp: delete server");
71 std::map
<std::string
, JackDriverInfo
*>::iterator it1
;
72 for (it1
= fSlavesList
.begin(); it1
!= fSlavesList
.end(); it1
++) {
73 JackDriverInfo
* info
= (*it1
).second
;
75 fInstance
->RemoveSlave((info
));
82 std::map
<std::string
, int> ::iterator it2
;
83 for (it2
= fInternalsList
.begin(); it2
!= fInternalsList
.end(); it2
++) {
85 int refnum
= (*it2
).second
;
87 // Client object is internally kept in JackEngine, and will be deallocated in InternalClientUnload
88 fInstance
->GetEngine()->InternalClientUnload(refnum
, &status
);
91 fInternalsList
.clear();
97 bool JackServerGlobals::Init()
100 int client_timeout
= 0; /* msecs; if zero, use period size. */
101 int realtime_priority
= 10;
103 unsigned int port_max
= 128;
107 int option_index
= 0;
108 char *master_driver_name
= NULL
;
109 char **master_driver_args
= NULL
;
110 JSList
* master_driver_params
= NULL
;
111 jack_driver_desc_t
* driver_desc
;
112 jack_timer_type_t clock_source
= JACK_TIMER_SYSTEM_CLOCK
;
113 int driver_nargs
= 1;
114 JSList
* drivers
= NULL
;
119 int replace_registry
= 0;
127 // First user starts the server
128 if (fUserCount
++ == 0) {
130 jack_log("JackServerGlobals Init");
132 const char *options
= "-d:X:I:P:uvshVrRL:STFl:t:mn:p:"
138 struct option long_options
[] = {
140 { "clock-source", 1, 0, 'c' },
142 { "loopback-driver", 1, 0, 'L' },
143 { "audio-driver", 1, 0, 'd' },
144 { "midi-driver", 1, 0, 'X' },
145 { "internal-client", 1, 0, 'I' },
146 { "verbose", 0, 0, 'v' },
147 { "help", 0, 0, 'h' },
148 { "port-max", 1, 0, 'p' },
149 { "no-mlock", 0, 0, 'm' },
150 { "name", 1, 0, 'n' },
151 { "unlock", 0, 0, 'u' },
152 { "realtime", 0, 0, 'R' },
153 { "no-realtime", 0, 0, 'r' },
154 { "replace-registry", 0, &replace_registry
, 0 },
155 { "loopback", 0, 0, 'L' },
156 { "realtime-priority", 1, 0, 'P' },
157 { "timeout", 1, 0, 't' },
158 { "temporary", 0, 0, 'T' },
159 { "version", 0, 0, 'V' },
160 { "silent", 0, 0, 's' },
161 { "sync", 0, 0, 'S' },
165 snprintf(filename
, 255, "%s/.jackdrc", getenv("HOME"));
166 fp
= fopen(filename
, "r");
169 fp
= fopen("/etc/jackdrc", "r");
171 // if still not found, check old config name for backwards compatability
173 fp
= fopen("/etc/jackd.conf", "r");
178 res
= fscanf(fp
, "%s", buffer
);
179 while (res
!= 0 && res
!= EOF
) {
180 argv
[argc
] = (char*)malloc(64);
181 strcpy(argv
[argc
], buffer
);
182 res
= fscanf(fp
, "%s", buffer
);
191 char* argv[] = {"jackdmp", "-R", "-v", "-d", "coreaudio", "-p", "512", "-d", "~:Aggregate:0", "-r", "48000", "-i", "2", "-o", "2" };
195 optind
= 1; // Important : to reset argv parsing
197 while (!master_driver_name
&&
198 (opt
= getopt_long(argc
, argv
, options
, long_options
, &option_index
)) != EOF
) {
203 if (tolower (optarg
[0]) == 'h') {
204 clock_source
= JACK_TIMER_HPET
;
205 } else if (tolower (optarg
[0]) == 'c') {
206 /* For backwards compatibility with scripts, allow
207 * the user to request the cycle clock on the
208 * command line, but use the system clock instead
210 clock_source
= JACK_TIMER_SYSTEM_CLOCK
;
211 } else if (tolower (optarg
[0]) == 's') {
212 clock_source
= JACK_TIMER_SYSTEM_CLOCK
;
214 jack_error("unknown option character %c", optopt
);
219 master_driver_name
= optarg
;
223 loopback
= atoi(optarg
);
227 fSlavesList
[optarg
] = NULL
;
231 fInternalsList
[optarg
] = -1;
235 port_max
= (unsigned int)atol(optarg
);
253 server_name
= optarg
;
257 realtime_priority
= atoi(optarg
);
273 client_timeout
= atoi(optarg
);
277 jack_error("unknown option character %c", optopt
);
282 drivers
= jack_drivers_load(drivers
);
284 jack_error("jackdmp: no drivers found; exiting");
288 driver_desc
= jack_find_driver_descriptor(drivers
, master_driver_name
);
290 jack_error("jackdmp: unknown master driver '%s'", master_driver_name
);
295 driver_nargs
= 1 + argc
- optind
;
300 if (driver_nargs
== 0) {
301 jack_error("No driver specified ... hmm. JACK won't do"
302 " anything when run like this.");
306 master_driver_args
= (char**)malloc(sizeof(char*) * driver_nargs
);
307 master_driver_args
[0] = master_driver_name
;
309 for (i
= 1; i
< driver_nargs
; i
++) {
310 master_driver_args
[i
] = argv
[optind
++];
313 if (jack_parse_driver_params(driver_desc
, driver_nargs
, master_driver_args
, &master_driver_params
)) {
318 if (server_name
== NULL
) {
319 server_name
= (char*)JackTools::DefaultServerName();
323 rc
= jack_register_server(server_name
, false);
326 jack_error("`%s' server already active", server_name
);
329 jack_error("too many servers already active");
332 jack_error("no access to shm registry");
335 jack_info("server `%s' registered", server_name
);
338 /* clean up shared memory and files from any previous instance of this server name */
340 JackTools::CleanupFiles(server_name
);
342 if (!realtime
&& client_timeout
== 0) {
343 client_timeout
= 500; /* 0.5 sec; usable when non realtime. */
346 for (i
= 0; i
< argc
; i
++) {
350 int res
= Start(server_name
, driver_desc
, master_driver_params
, sync
, temporary
, client_timeout
, realtime
, realtime_priority
, port_max
, verbose_aux
, clock_source
, JACK_DEFAULT_SELF_CONNECT_MODE
);
352 jack_error("Cannot start server... exit");
355 JackTools::CleanupFiles(server_name
);
356 jack_unregister_server(server_name
);
361 std::map
<std::string
, JackDriverInfo
*>::iterator it1
;
362 for (it1
= fSlavesList
.begin(); it1
!= fSlavesList
.end(); it1
++) {
363 const char* name
= ((*it1
).first
).c_str();
364 driver_desc
= jack_find_driver_descriptor(drivers
, name
);
366 jack_error("jackdmp: unknown slave driver '%s'", name
);
368 (*it1
).second
= fInstance
->AddSlave(driver_desc
, NULL
);
374 driver_desc
= jack_find_driver_descriptor(drivers
, "loopback");
376 jack_error("jackdmp: unknown driver '%s'", "loopback");
378 fSlavesList
["loopback"] = fInstance
->AddSlave(driver_desc
, NULL
);
383 std::map
<std::string
, int>::iterator it2
;
384 for (it2
= fInternalsList
.begin(); it2
!= fInternalsList
.end(); it2
++) {
386 const char* name
= ((*it2
).first
).c_str();
387 fInstance
->InternalClientLoad2(name
, name
, NULL
, JackNullOption
, &refnum
, -1, &status
);
388 (*it2
).second
= refnum
;
392 if (master_driver_params
) {
393 jack_free_driver_params(master_driver_params
);
398 jack_log("JackServerGlobals Init error");
399 if (master_driver_params
) {
400 jack_free_driver_params(master_driver_params
);
406 void JackServerGlobals::Destroy()
408 if (--fUserCount
== 0) {
409 jack_log("JackServerGlobals Destroy");
413 JackTools::CleanupFiles(server_name
);
414 jack_unregister_server(server_name
);
418 } // end of namespace