00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <iostream>
00022 #include <assert.h>
00023 #include <cassert>
00024 #include <csignal>
00025 #include <sys/types.h>
00026 #include <getopt.h>
00027 #include <cstring>
00028 #include <cstdio>
00029
00030 #include "types.h"
00031 #include "jack.h"
00032 #include "JackConstants.h"
00033 #include "JackDriverLoader.h"
00034
00035 #if defined(JACK_DBUS) && defined(__linux__)
00036 #include <dbus/dbus.h>
00037 #include "audio_reserve.h"
00038 #endif
00039
00040
00041
00042
00043
00044
00045
00046
00047 #ifdef __APPLE__
00048 #include <CoreFoundation/CFNotificationCenter.h>
00049 #include <CoreFoundation/CoreFoundation.h>
00050
00051 static void notify_server_start(const char* server_name)
00052 {
00053
00054 CFStringRef ref = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingMacRoman);
00055 CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(),
00056 CFSTR("com.grame.jackserver.start"),
00057 ref,
00058 NULL,
00059 kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions);
00060 CFRelease(ref);
00061 }
00062
00063 static void notify_server_stop(const char* server_name)
00064 {
00065
00066 CFStringRef ref1 = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingMacRoman);
00067 CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(),
00068 CFSTR("com.grame.jackserver.stop"),
00069 ref1,
00070 NULL,
00071 kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions);
00072 CFRelease(ref1);
00073 }
00074
00075 #else
00076
00077 static void notify_server_start(const char* server_name)
00078 {}
00079 static void notify_server_stop(const char* server_name)
00080 {}
00081
00082 #endif
00083
00084 static void copyright(FILE* file)
00085 {
00086 fprintf(file, "jackdmp " VERSION "\n"
00087 "Copyright 2001-2005 Paul Davis and others.\n"
00088 "Copyright 2004-2009 Grame.\n"
00089 "jackdmp comes with ABSOLUTELY NO WARRANTY\n"
00090 "This is free software, and you are welcome to redistribute it\n"
00091 "under certain conditions; see the file COPYING for details\n");
00092 }
00093
00094 static void usage(FILE* file)
00095 {
00096 fprintf(file, "\n"
00097 "usage: jackdmp [ --no-realtime OR -r ]\n"
00098 " [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n"
00099 " (the two previous arguments are mutually exclusive. The default is --realtime)\n"
00100 " [ --name OR -n server-name ]\n"
00101 " [ --timeout OR -t client-timeout-in-msecs ]\n"
00102 " [ --loopback OR -L loopback-port-number ]\n"
00103 " [ --port-max OR -p maximum-number-of-ports]\n"
00104 " [ --midi OR -X midi-driver ]\n"
00105 " [ --verbose OR -v ]\n"
00106 #ifdef __linux__
00107 " [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n"
00108 #endif
00109 " [ --replace-registry ]\n"
00110 " [ --silent OR -s ]\n"
00111 " [ --sync OR -S ]\n"
00112 " [ --temporary OR -T ]\n"
00113 " [ --version OR -V ]\n"
00114 " -d backend [ ... backend args ... ]\n"
00115 #ifdef __APPLE__
00116 " Available backends may include: coreaudio, dummy or net.\n\n"
00117 #endif
00118 #ifdef WIN32
00119 " Available backends may include: portaudio, dummy or net.\n\n"
00120 #endif
00121 #ifdef __linux__
00122 " Available backends may include: alsa, dummy, freebob, firewire or net\n\n"
00123 #endif
00124 #if defined(__sun__) || defined(sun)
00125 " Available backends may include: boomer, oss, dummy or net.\n\n"
00126 #endif
00127 " jackdmp -d backend --help\n"
00128 " to display options for each backend\n\n");
00129 }
00130
00131
00132 static jackctl_driver_t *
00133 jackctl_server_get_driver(
00134 jackctl_server_t *server,
00135 const char *driver_name)
00136 {
00137 const JSList * node_ptr;
00138
00139 node_ptr = jackctl_server_get_drivers_list(server);
00140
00141 while (node_ptr)
00142 {
00143 if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
00144 {
00145 return (jackctl_driver_t *)node_ptr->data;
00146 }
00147
00148 node_ptr = jack_slist_next(node_ptr);
00149 }
00150
00151 return NULL;
00152 }
00153
00154 static jackctl_parameter_t *
00155 jackctl_get_parameter(
00156 const JSList * parameters_list,
00157 const char * parameter_name)
00158 {
00159 while (parameters_list)
00160 {
00161 if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
00162 {
00163 return (jackctl_parameter_t *)parameters_list->data;
00164 }
00165
00166 parameters_list = jack_slist_next(parameters_list);
00167 }
00168
00169 return NULL;
00170 }
00171
00172 int main(int argc, char* argv[])
00173 {
00174 jackctl_server_t * server_ctl;
00175 const JSList * server_parameters;
00176 const char* server_name = "default";
00177 jackctl_driver_t * audio_driver_ctl;
00178 jackctl_driver_t * midi_driver_ctl;
00179 jackctl_driver_t * loopback_driver_ctl;
00180 int replace_registry = 0;
00181
00182 const char *options = "-d:X:P:uvshVrRL:STFl:t:mn:p:"
00183 #ifdef __linux__
00184 "c:"
00185 #endif
00186 ;
00187
00188 struct option long_options[] = {
00189 #ifdef __linux__
00190 { "clock-source", 1, 0, 'c' },
00191 #endif
00192 { "loopback-driver", 1, 0, 'L' },
00193 { "audio-driver", 1, 0, 'd' },
00194 { "midi-driver", 1, 0, 'X' },
00195 { "verbose", 0, 0, 'v' },
00196 { "help", 0, 0, 'h' },
00197 { "port-max", 1, 0, 'p' },
00198 { "no-mlock", 0, 0, 'm' },
00199 { "name", 0, 0, 'n' },
00200 { "unlock", 0, 0, 'u' },
00201 { "realtime", 0, 0, 'R' },
00202 { "no-realtime", 0, 0, 'r' },
00203 { "replace-registry", 0, &replace_registry, 0 },
00204 { "loopback", 0, 0, 'L' },
00205 { "realtime-priority", 1, 0, 'P' },
00206 { "timeout", 1, 0, 't' },
00207 { "temporary", 0, 0, 'T' },
00208 { "version", 0, 0, 'V' },
00209 { "silent", 0, 0, 's' },
00210 { "sync", 0, 0, 'S' },
00211 { 0, 0, 0, 0 }
00212 };
00213
00214 int i,opt = 0;
00215 int option_index = 0;
00216 bool seen_audio_driver = false;
00217 bool seen_midi_driver = false;
00218 char *audio_driver_name = NULL;
00219 char **audio_driver_args = NULL;
00220 int audio_driver_nargs = 1;
00221 char *midi_driver_name = NULL;
00222 char **midi_driver_args = NULL;
00223 int midi_driver_nargs = 1;
00224 int do_mlock = 1;
00225 int do_unlock = 0;
00226 int loopback = 0;
00227 bool show_version = false;
00228 sigset_t signals;
00229 jackctl_parameter_t* param;
00230 union jackctl_parameter_value value;
00231
00232 copyright(stdout);
00233 #if defined(JACK_DBUS) && defined(__linux__)
00234 server_ctl = jackctl_server_create(audio_acquire, audio_release);
00235 #else
00236 server_ctl = jackctl_server_create(NULL, NULL);
00237 #endif
00238 if (server_ctl == NULL) {
00239 fprintf(stderr, "Failed to create server object\n");
00240 return -1;
00241 }
00242
00243 server_parameters = jackctl_server_get_parameters(server_ctl);
00244
00245
00246 param = jackctl_get_parameter(server_parameters, "realtime");
00247 if (param != NULL) {
00248 value.b = true;
00249 jackctl_parameter_set_value(param, &value);
00250 }
00251
00252 opterr = 0;
00253 while (!seen_audio_driver &&
00254 (opt = getopt_long(argc, argv, options,
00255 long_options, &option_index)) != EOF) {
00256 switch (opt) {
00257
00258 #ifdef __linux__
00259 case 'c':
00260 param = jackctl_get_parameter(server_parameters, "clock-source");
00261 if (param != NULL) {
00262 if (tolower (optarg[0]) == 'h') {
00263 value.ui = JACK_TIMER_HPET;
00264 jackctl_parameter_set_value(param, &value);
00265 } else if (tolower (optarg[0]) == 'c') {
00266 value.ui = JACK_TIMER_CYCLE_COUNTER;
00267 jackctl_parameter_set_value(param, &value);
00268 } else if (tolower (optarg[0]) == 's') {
00269 value.ui = JACK_TIMER_SYSTEM_CLOCK;
00270 jackctl_parameter_set_value(param, &value);
00271 } else {
00272 usage(stdout);
00273 goto fail_free1;
00274 }
00275 }
00276 break;
00277 #endif
00278
00279 case 'd':
00280 seen_audio_driver = true;
00281 audio_driver_name = optarg;
00282 break;
00283
00284 case 'L':
00285 loopback = atoi(optarg);
00286 break;
00287
00288 case 'X':
00289 seen_midi_driver = true;
00290 midi_driver_name = optarg;
00291 break;
00292
00293 case 'p':
00294 param = jackctl_get_parameter(server_parameters, "port-max");
00295 if (param != NULL) {
00296 value.ui = atoi(optarg);
00297 jackctl_parameter_set_value(param, &value);
00298 }
00299 break;
00300
00301 case 'm':
00302 do_mlock = 0;
00303 break;
00304
00305 case 'u':
00306 do_unlock = 1;
00307 break;
00308
00309 case 'v':
00310 param = jackctl_get_parameter(server_parameters, "verbose");
00311 if (param != NULL) {
00312 value.b = true;
00313 jackctl_parameter_set_value(param, &value);
00314 }
00315 break;
00316
00317 case 's':
00318 jack_set_error_function(silent_jack_error_callback);
00319 break;
00320
00321 case 'S':
00322 param = jackctl_get_parameter(server_parameters, "sync");
00323 if (param != NULL) {
00324 value.b = true;
00325 jackctl_parameter_set_value(param, &value);
00326 }
00327 break;
00328
00329 case 'n':
00330 server_name = optarg;
00331 param = jackctl_get_parameter(server_parameters, "name");
00332 if (param != NULL) {
00333 strncpy(value.str, optarg, JACK_PARAM_STRING_MAX);
00334 jackctl_parameter_set_value(param, &value);
00335 }
00336 break;
00337
00338 case 'P':
00339 param = jackctl_get_parameter(server_parameters, "realtime-priority");
00340 if (param != NULL) {
00341 value.i = atoi(optarg);
00342 jackctl_parameter_set_value(param, &value);
00343 }
00344 break;
00345
00346 case 'r':
00347 param = jackctl_get_parameter(server_parameters, "realtime");
00348 if (param != NULL) {
00349 value.b = false;
00350 jackctl_parameter_set_value(param, &value);
00351 }
00352 break;
00353
00354 case 'R':
00355 param = jackctl_get_parameter(server_parameters, "realtime");
00356 if (param != NULL) {
00357 value.b = true;
00358 jackctl_parameter_set_value(param, &value);
00359 }
00360 break;
00361
00362 case 'T':
00363 param = jackctl_get_parameter(server_parameters, "temporary");
00364 if (param != NULL) {
00365 value.b = true;
00366 jackctl_parameter_set_value(param, &value);
00367 }
00368 break;
00369
00370 case 't':
00371 param = jackctl_get_parameter(server_parameters, "client-timeout");
00372 if (param != NULL) {
00373 value.i = atoi(optarg);
00374 jackctl_parameter_set_value(param, &value);
00375 }
00376 break;
00377
00378 case 'V':
00379 show_version = true;
00380 break;
00381
00382 default:
00383 fprintf(stderr, "unknown option character %c\n", optopt);
00384
00385
00386 case 'h':
00387 usage(stdout);
00388 goto fail_free1;
00389 }
00390 }
00391
00392
00393 param = jackctl_get_parameter(server_parameters, "replace-registry");
00394 if (param != NULL) {
00395 value.b = replace_registry;
00396 jackctl_parameter_set_value(param, &value);
00397 }
00398
00399 if (show_version) {
00400 printf( "jackdmp version " VERSION
00401 " tmpdir " jack_server_dir
00402 " protocol %d"
00403 "\n", JACK_PROTOCOL_VERSION);
00404 return -1;
00405 }
00406
00407 if (!seen_audio_driver) {
00408 usage(stderr);
00409 goto fail_free1;
00410 }
00411
00412
00413 audio_driver_ctl = jackctl_server_get_driver(server_ctl, audio_driver_name);
00414 if (audio_driver_ctl == NULL) {
00415 fprintf(stderr, "Unknown driver \"%s\"\n", audio_driver_name);
00416 goto fail_free1;
00417 }
00418
00419 if (optind < argc) {
00420 audio_driver_nargs = 1 + argc - optind;
00421 } else {
00422 audio_driver_nargs = 1;
00423 }
00424
00425 if (audio_driver_nargs == 0) {
00426 fprintf(stderr, "No driver specified ... hmm. JACK won't do"
00427 " anything when run like this.\n");
00428 goto fail_free1;
00429 }
00430
00431 audio_driver_args = (char **) malloc(sizeof(char *) * audio_driver_nargs);
00432 audio_driver_args[0] = audio_driver_name;
00433
00434 for (i = 1; i < audio_driver_nargs; i++) {
00435 audio_driver_args[i] = argv[optind++];
00436 }
00437
00438 if (jackctl_parse_driver_params(audio_driver_ctl, audio_driver_nargs, audio_driver_args)) {
00439 goto fail_free1;
00440 }
00441
00442
00443 if (!jackctl_server_start(server_ctl, audio_driver_ctl)) {
00444 fprintf(stderr, "Failed to start server\n");
00445 goto fail_free1;
00446 }
00447
00448
00449 if (seen_midi_driver) {
00450
00451 midi_driver_ctl = jackctl_server_get_driver(server_ctl, midi_driver_name);
00452 if (midi_driver_ctl == NULL) {
00453 fprintf(stderr, "Unknown driver \"%s\"\n", midi_driver_name);
00454 goto fail_free2;
00455 }
00456
00457 jackctl_server_add_slave(server_ctl, midi_driver_ctl);
00458 }
00459
00460
00461 if (loopback > 0) {
00462 loopback_driver_ctl = jackctl_server_get_driver(server_ctl, "loopback");
00463 if (loopback_driver_ctl != NULL) {
00464 const JSList * loopback_parameters = jackctl_driver_get_parameters(loopback_driver_ctl);
00465 param = jackctl_get_parameter(loopback_parameters, "channels");
00466 if (param != NULL) {
00467 value.ui = loopback;
00468 jackctl_parameter_set_value(param, &value);
00469 }
00470 jackctl_server_add_slave(server_ctl, loopback_driver_ctl);
00471 }
00472 }
00473
00474 notify_server_start(server_name);
00475
00476
00477 signals = jackctl_setup_signals(0);
00478 jackctl_wait_signals(signals);
00479
00480 if (!jackctl_server_stop(server_ctl))
00481 fprintf(stderr, "Cannot stop server...\n");
00482
00483 jackctl_server_destroy(server_ctl);
00484 notify_server_stop(server_name);
00485 return 0;
00486
00487 fail_free1:
00488 jackctl_server_destroy(server_ctl);
00489 return -1;
00490
00491 fail_free2:
00492 jackctl_server_stop(server_ctl);
00493 jackctl_server_destroy(server_ctl);
00494 notify_server_stop(server_name);
00495 return -1;
00496 }