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