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 int JackServerGlobals::fRTNotificationSocket;
00035 std::map<std::string, JackDriverInfo*> JackServerGlobals::fSlavesList;
00036 std::map<std::string, int> JackServerGlobals::fInternalsList;
00037
00038 bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL;
00039 void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL;
00040
00041 int JackServerGlobals::Start(const char* server_name,
00042 jack_driver_desc_t* driver_desc,
00043 JSList* driver_params,
00044 int sync,
00045 int temporary,
00046 int time_out_ms,
00047 int rt,
00048 int priority,
00049 int port_max,
00050 int verbose,
00051 jack_timer_type_t clock)
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, 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 int do_mlock = 1;
00104 unsigned int port_max = 128;
00105 int do_unlock = 0;
00106 int temporary = 0;
00107
00108 int opt = 0;
00109 int option_index = 0;
00110 char *master_driver_name = NULL;
00111 char **master_driver_args = NULL;
00112 JSList* master_driver_params = NULL;
00113 jack_driver_desc_t* driver_desc;
00114 jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK;
00115 int driver_nargs = 1;
00116 JSList* drivers = NULL;
00117 int loopback = 0;
00118 int sync = 0;
00119 int rc, i;
00120 int ret;
00121 int replace_registry = 0;
00122
00123 FILE* fp = 0;
00124 char filename[255];
00125 char buffer[255];
00126 int argc = 0;
00127 char* argv[32];
00128
00129
00130 if (fUserCount++ == 0) {
00131
00132 jack_log("JackServerGlobals Init");
00133
00134 const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:"
00135 #ifdef __linux__
00136 "c:"
00137 #endif
00138 ;
00139
00140 struct option long_options[] = {
00141 #ifdef __linux__
00142 { "clock-source", 1, 0, 'c' },
00143 #endif
00144 { "loopback-driver", 1, 0, 'L' },
00145 { "audio-driver", 1, 0, 'd' },
00146 { "midi-driver", 1, 0, 'X' },
00147 { "internal-client", 1, 0, 'I' },
00148 { "verbose", 0, 0, 'v' },
00149 { "help", 0, 0, 'h' },
00150 { "port-max", 1, 0, 'p' },
00151 { "no-mlock", 0, 0, 'm' },
00152 { "name", 1, 0, 'n' },
00153 { "unlock", 0, 0, 'u' },
00154 { "realtime", 0, 0, 'R' },
00155 { "no-realtime", 0, 0, 'r' },
00156 { "replace-registry", 0, &replace_registry, 0 },
00157 { "loopback", 0, 0, 'L' },
00158 { "realtime-priority", 1, 0, 'P' },
00159 { "timeout", 1, 0, 't' },
00160 { "temporary", 0, 0, 'T' },
00161 { "version", 0, 0, 'V' },
00162 { "silent", 0, 0, 's' },
00163 { "sync", 0, 0, 'S' },
00164 { 0, 0, 0, 0 }
00165 };
00166
00167 snprintf(filename, 255, "%s/.jackdrc", getenv("HOME"));
00168 fp = fopen(filename, "r");
00169
00170 if (!fp) {
00171 fp = fopen("/etc/jackdrc", "r");
00172 }
00173
00174 if (!fp) {
00175 fp = fopen("/etc/jackd.conf", "r");
00176 }
00177
00178 argc = 0;
00179 if (fp) {
00180 ret = fscanf(fp, "%s", buffer);
00181 while (ret != 0 && ret != EOF) {
00182 argv[argc] = (char*)malloc(64);
00183 strcpy(argv[argc], buffer);
00184 ret = fscanf(fp, "%s", buffer);
00185 argc++;
00186 }
00187 fclose(fp);
00188 }
00189
00190
00191
00192
00193
00194
00195
00196 opterr = 0;
00197 optind = 1;
00198
00199 while (!master_driver_name &&
00200 (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) {
00201
00202 switch (opt) {
00203
00204 case 'c':
00205 if (tolower (optarg[0]) == 'h') {
00206 clock_source = JACK_TIMER_HPET;
00207 } else if (tolower (optarg[0]) == 'c') {
00208 clock_source = JACK_TIMER_CYCLE_COUNTER;
00209 } else if (tolower (optarg[0]) == 's') {
00210 clock_source = JACK_TIMER_SYSTEM_CLOCK;
00211 } else {
00212 jack_error("unknown option character %c", optopt);
00213 }
00214 break;
00215
00216 case 'd':
00217 master_driver_name = optarg;
00218 break;
00219
00220 case 'L':
00221 loopback = atoi(optarg);
00222 break;
00223
00224 case 'X':
00225 fSlavesList[optarg] = NULL;
00226 break;
00227
00228 case 'I':
00229 fInternalsList[optarg] = -1;
00230 break;
00231
00232 case 'p':
00233 port_max = (unsigned int)atol(optarg);
00234 break;
00235
00236 case 'm':
00237 do_mlock = 0;
00238 break;
00239
00240 case 'u':
00241 do_unlock = 1;
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 #endif
00321
00322 rc = jack_register_server(server_name, false);
00323 switch (rc) {
00324 case EEXIST:
00325 jack_error("`%s' server already active", server_name);
00326 goto error;
00327 case ENOSPC:
00328 jack_error("too many servers already active");
00329 goto error;
00330 case ENOMEM:
00331 jack_error("no access to shm registry");
00332 goto error;
00333 default:
00334 jack_info("server `%s' registered", server_name);
00335 }
00336
00337
00338 jack_cleanup_shm();
00339 JackTools::CleanupFiles(server_name);
00340
00341 if (!realtime && client_timeout == 0)
00342 client_timeout = 500;
00343
00344 for (i = 0; i < argc; i++) {
00345 free(argv[i]);
00346 }
00347
00348 int res = Start(server_name, driver_desc, master_driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source);
00349 if (res < 0) {
00350 jack_error("Cannot start server... exit");
00351 Delete();
00352 jack_cleanup_shm();
00353 JackTools::CleanupFiles(server_name);
00354 jack_unregister_server(server_name);
00355 goto error;
00356 }
00357
00358
00359 std::map<std::string, JackDriverInfo*>::iterator it1;
00360 for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) {
00361 const char* name = ((*it1).first).c_str();
00362 driver_desc = jack_find_driver_descriptor(drivers, name);
00363 if (!driver_desc) {
00364 jack_error("jackdmp: unknown slave driver '%s'", name);
00365 } else {
00366 (*it1).second = fInstance->AddSlave(driver_desc, NULL);
00367 }
00368 }
00369
00370
00371 if (loopback > 0) {
00372 driver_desc = jack_find_driver_descriptor(drivers, "loopback");
00373 if (!driver_desc) {
00374 jack_error("jackdmp: unknown driver '%s'", "loopback");
00375 } else {
00376 fSlavesList["loopback"] = fInstance->AddSlave(driver_desc, NULL);
00377 }
00378 }
00379
00380
00381 std::map<std::string, int>::iterator it2;
00382 for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) {
00383 int status, refnum;
00384 const char* name = ((*it2).first).c_str();
00385 fInstance->InternalClientLoad2(name, name, NULL, JackNullOption, &refnum, -1, &status);
00386 (*it2).second = refnum;
00387 }
00388 }
00389
00390 if (master_driver_params)
00391 jack_free_driver_params(master_driver_params);
00392 return true;
00393
00394 error:
00395 jack_log("JackServerGlobals Init error");
00396 if (master_driver_params)
00397 jack_free_driver_params(master_driver_params);
00398 Destroy();
00399 return false;
00400 }
00401
00402 void JackServerGlobals::Destroy()
00403 {
00404 if (--fUserCount == 0) {
00405 jack_log("JackServerGlobals Destroy");
00406 Stop();
00407 Delete();
00408 jack_cleanup_shm();
00409 JackTools::CleanupFiles(server_name);
00410 jack_unregister_server(server_name);
00411 }
00412 }
00413
00414 }
00415
00416