00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "JackServerGlobals.h"
00021 #include "JackLockedEngine.h"
00022 #include "JackTools.h"
00023 #include "shm.h"
00024 #include <getopt.h>
00025 #include <errno.h>
00026 #include <sys/utsname.h>
00027
00028 static char* server_name = NULL;
00029
00030 namespace Jack
00031 {
00032
00033 JackServer* JackServerGlobals::fInstance;
00034 unsigned int JackServerGlobals::fUserCount;
00035 int JackServerGlobals::fRTNotificationSocket;
00036 std::map<std::string, JackDriverInfo*> JackServerGlobals::fSlavesList;
00037 std::map<std::string, int> JackServerGlobals::fInternalsList;
00038
00039 bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL;
00040 void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL;
00041
00042 int JackServerGlobals::Start(const char* server_name,
00043 jack_driver_desc_t* driver_desc,
00044 JSList* driver_params,
00045 int sync,
00046 int temporary,
00047 int time_out_ms,
00048 int rt,
00049 int priority,
00050 int port_max,
00051 int verbose,
00052 jack_timer_type_t clock)
00053 {
00054 jack_log("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld ", sync, time_out_ms, rt, priority, verbose);
00055 new JackServer(sync, temporary, time_out_ms, rt, priority, port_max, verbose, clock, server_name);
00056 int res = fInstance->Open(driver_desc, driver_params);
00057 return (res < 0) ? res : fInstance->Start();
00058 }
00059
00060 void JackServerGlobals::Stop()
00061 {
00062 jack_log("Jackdmp: server close");
00063 fInstance->Stop();
00064 fInstance->Close();
00065 }
00066
00067 void JackServerGlobals::Delete()
00068 {
00069 jack_log("Jackdmp: delete server");
00070
00071
00072 std::map<std::string, JackDriverInfo*>::iterator it1;
00073 for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) {
00074 JackDriverInfo* info = (*it1).second;
00075 if (info) {
00076 fInstance->RemoveSlave((info));
00077 delete (info);
00078 }
00079 }
00080 fSlavesList.clear();
00081
00082
00083 std::map<std::string, int> ::iterator it2;
00084 for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) {
00085 int status;
00086 int refnum = (*it2).second;
00087 if (refnum > 0) {
00088
00089 fInstance->GetEngine()->InternalClientUnload(refnum, &status);
00090 }
00091 }
00092 fInternalsList.clear();
00093
00094 delete fInstance;
00095 fInstance = NULL;
00096 }
00097
00098 bool JackServerGlobals::Init()
00099 {
00100 struct utsname utsname;
00101 int success;
00102 success = uname( &utsname );
00103
00104 int realtime = 0;
00105 int client_timeout = 0;
00106 int realtime_priority;
00107 if( success == 0 && strstr( utsname.version, "ccrma" ) )
00108 realtime_priority = 60;
00109 else
00110 realtime_priority = 20;
00111 int verbose_aux = 0;
00112 int do_mlock = 1;
00113 unsigned int port_max = 128;
00114 int do_unlock = 0;
00115 int temporary = 0;
00116
00117 int opt = 0;
00118 int option_index = 0;
00119 char *master_driver_name = NULL;
00120 char **master_driver_args = NULL;
00121 JSList* master_driver_params = NULL;
00122 jack_driver_desc_t* driver_desc;
00123 jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK;
00124 int driver_nargs = 1;
00125 JSList* drivers = NULL;
00126 int loopback = 0;
00127 int sync = 0;
00128 int rc, i;
00129 int ret;
00130 int replace_registry = 0;
00131
00132 FILE* fp = 0;
00133 char filename[255];
00134 char buffer[255];
00135 int argc = 0;
00136 char* argv[32];
00137
00138
00139 if (fUserCount++ == 0) {
00140
00141 jack_log("JackServerGlobals Init");
00142
00143 const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:"
00144 #ifdef __linux__
00145 "c:"
00146 #endif
00147 ;
00148
00149 struct option long_options[] = {
00150 #ifdef __linux__
00151 { "clock-source", 1, 0, 'c' },
00152 #endif
00153 { "loopback-driver", 1, 0, 'L' },
00154 { "audio-driver", 1, 0, 'd' },
00155 { "midi-driver", 1, 0, 'X' },
00156 { "internal-client", 1, 0, 'I' },
00157 { "verbose", 0, 0, 'v' },
00158 { "help", 0, 0, 'h' },
00159 { "port-max", 1, 0, 'p' },
00160 { "no-mlock", 0, 0, 'm' },
00161 { "name", 1, 0, 'n' },
00162 { "unlock", 0, 0, 'u' },
00163 { "realtime", 0, 0, 'R' },
00164 { "no-realtime", 0, 0, 'r' },
00165 { "replace-registry", 0, &replace_registry, 0 },
00166 { "loopback", 0, 0, 'L' },
00167 { "realtime-priority", 1, 0, 'P' },
00168 { "timeout", 1, 0, 't' },
00169 { "temporary", 0, 0, 'T' },
00170 { "version", 0, 0, 'V' },
00171 { "silent", 0, 0, 's' },
00172 { "sync", 0, 0, 'S' },
00173 { 0, 0, 0, 0 }
00174 };
00175
00176 snprintf(filename, 255, "%s/.jackdrc", getenv("HOME"));
00177 fp = fopen(filename, "r");
00178
00179 if (!fp) {
00180 fp = fopen("/etc/jackdrc", "r");
00181 }
00182
00183 if (!fp) {
00184 fp = fopen("/etc/jackd.conf", "r");
00185 }
00186
00187 argc = 0;
00188 if (fp) {
00189 ret = fscanf(fp, "%s", buffer);
00190 while (ret != 0 && ret != EOF) {
00191 argv[argc] = (char*)malloc(64);
00192 strcpy(argv[argc], buffer);
00193 ret = fscanf(fp, "%s", buffer);
00194 argc++;
00195 }
00196 fclose(fp);
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 opterr = 0;
00206 optind = 1;
00207
00208 while (!master_driver_name &&
00209 (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) {
00210
00211 switch (opt) {
00212
00213 case 'c':
00214 if (tolower (optarg[0]) == 'h') {
00215 clock_source = JACK_TIMER_HPET;
00216 } else if (tolower (optarg[0]) == 'c') {
00217 clock_source = JACK_TIMER_CYCLE_COUNTER;
00218 } else if (tolower (optarg[0]) == 's') {
00219 clock_source = JACK_TIMER_SYSTEM_CLOCK;
00220 } else {
00221 jack_error("unknown option character %c", optopt);
00222 }
00223 break;
00224
00225 case 'd':
00226 master_driver_name = optarg;
00227 break;
00228
00229 case 'L':
00230 loopback = atoi(optarg);
00231 break;
00232
00233 case 'X':
00234 fSlavesList[optarg] = NULL;
00235 break;
00236
00237 case 'I':
00238 fInternalsList[optarg] = -1;
00239 break;
00240
00241 case 'p':
00242 port_max = (unsigned int)atol(optarg);
00243 break;
00244
00245 case 'm':
00246 do_mlock = 0;
00247 break;
00248
00249 case 'u':
00250 do_unlock = 1;
00251 break;
00252
00253 case 'v':
00254 verbose_aux = 1;
00255 break;
00256
00257 case 'S':
00258 sync = 1;
00259 break;
00260
00261 case 'n':
00262 server_name = optarg;
00263 break;
00264
00265 case 'P':
00266 realtime_priority = atoi(optarg);
00267 break;
00268
00269 case 'r':
00270 realtime = 0;
00271 break;
00272
00273 case 'R':
00274 realtime = 1;
00275 break;
00276
00277 case 'T':
00278 temporary = 1;
00279 break;
00280
00281 case 't':
00282 client_timeout = atoi(optarg);
00283 break;
00284
00285 default:
00286 jack_error("unknown option character %c", optopt);
00287 break;
00288 }
00289 }
00290
00291 drivers = jack_drivers_load(drivers);
00292 if (!drivers) {
00293 jack_error("jackdmp: no drivers found; exiting");
00294 goto error;
00295 }
00296
00297 driver_desc = jack_find_driver_descriptor(drivers, master_driver_name);
00298 if (!driver_desc) {
00299 jack_error("jackdmp: unknown master driver '%s'", master_driver_name);
00300 goto error;
00301 }
00302
00303 if (optind < argc) {
00304 driver_nargs = 1 + argc - optind;
00305 } else {
00306 driver_nargs = 1;
00307 }
00308
00309 if (driver_nargs == 0) {
00310 jack_error("No driver specified ... hmm. JACK won't do"
00311 " anything when run like this.");
00312 goto error;
00313 }
00314
00315 master_driver_args = (char**)malloc(sizeof(char*) * driver_nargs);
00316 master_driver_args[0] = master_driver_name;
00317
00318 for (i = 1; i < driver_nargs; i++) {
00319 master_driver_args[i] = argv[optind++];
00320 }
00321
00322 if (jack_parse_driver_params(driver_desc, driver_nargs, master_driver_args, &master_driver_params)) {
00323 goto error;
00324 }
00325
00326 #ifndef WIN32
00327 if (server_name == NULL)
00328 server_name = (char*)JackTools::DefaultServerName();
00329 #endif
00330
00331 rc = jack_register_server(server_name, false);
00332 switch (rc) {
00333 case EEXIST:
00334 jack_error("`%s' server already active", server_name);
00335 goto error;
00336 case ENOSPC:
00337 jack_error("too many servers already active");
00338 goto error;
00339 case ENOMEM:
00340 jack_error("no access to shm registry");
00341 goto error;
00342 default:
00343 jack_info("server `%s' registered", server_name);
00344 }
00345
00346
00347 jack_cleanup_shm();
00348 JackTools::CleanupFiles(server_name);
00349
00350 if (!realtime && client_timeout == 0)
00351 client_timeout = 500;
00352
00353 for (i = 0; i < argc; i++) {
00354 free(argv[i]);
00355 }
00356
00357 int res = Start(server_name, driver_desc, master_driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source);
00358 if (res < 0) {
00359 jack_error("Cannot start server... exit");
00360 Delete();
00361 jack_cleanup_shm();
00362 JackTools::CleanupFiles(server_name);
00363 jack_unregister_server(server_name);
00364 goto error;
00365 }
00366
00367
00368 std::map<std::string, JackDriverInfo*>::iterator it1;
00369 for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) {
00370 const char* name = ((*it1).first).c_str();
00371 driver_desc = jack_find_driver_descriptor(drivers, name);
00372 if (!driver_desc) {
00373 jack_error("jackdmp: unknown slave driver '%s'", name);
00374 } else {
00375 (*it1).second = fInstance->AddSlave(driver_desc, NULL);
00376 }
00377 }
00378
00379
00380 if (loopback > 0) {
00381 driver_desc = jack_find_driver_descriptor(drivers, "loopback");
00382 if (!driver_desc) {
00383 jack_error("jackdmp: unknown driver '%s'", "loopback");
00384 } else {
00385 fSlavesList["loopback"] = fInstance->AddSlave(driver_desc, NULL);
00386 }
00387 }
00388
00389
00390 std::map<std::string, int>::iterator it2;
00391 for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) {
00392 int status, refnum;
00393 const char* name = ((*it2).first).c_str();
00394 fInstance->InternalClientLoad2(name, name, NULL, JackNullOption, &refnum, -1, &status);
00395 (*it2).second = refnum;
00396 }
00397 }
00398
00399 if (master_driver_params)
00400 jack_free_driver_params(master_driver_params);
00401 return true;
00402
00403 error:
00404 jack_log("JackServerGlobals Init error");
00405 if (master_driver_params)
00406 jack_free_driver_params(master_driver_params);
00407 Destroy();
00408 return false;
00409 }
00410
00411 void JackServerGlobals::Destroy()
00412 {
00413 if (--fUserCount == 0) {
00414 jack_log("JackServerGlobals Destroy");
00415 Stop();
00416 Delete();
00417 jack_cleanup_shm();
00418 JackTools::CleanupFiles(server_name);
00419 jack_unregister_server(server_name);
00420 }
00421 }
00422
00423 }
00424
00425