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 " [ --midi OR -X midi-driver ]\n"
00104 " [ --verbose OR -v ]\n"
00105 #ifdef __linux__
00106 " [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n"
00107 #endif
00108 " [ --replace-registry ]\n"
00109 " [ --silent OR -s ]\n"
00110 " [ --sync OR -S ]\n"
00111 " [ --temporary OR -T ]\n"
00112 " [ --version OR -V ]\n"
00113 " -d backend [ ... backend args ... ]\n"
00114 #ifdef __APPLE__
00115 " Available backends may include: coreaudio, dummy or net.\n\n"
00116 #endif
00117 #ifdef WIN32
00118 " Available backends may include: portaudio, dummy or net.\n\n"
00119 #endif
00120 #ifdef __linux__
00121 " Available backends may include: alsa, dummy, freebob, firewire, net, oss or sun.\n\n"
00122 #endif
00123 #if defined(__sun__) || defined(sun)
00124 " Available backends may include: boomer, oss, dummy or net.\n\n"
00125 #endif
00126 " jackdmp -d backend --help\n"
00127 " to display options for each backend\n\n");
00128 }
00129
00130
00131 static jackctl_driver_t *
00132 jackctl_server_get_driver(
00133 jackctl_server_t *server,
00134 const char *driver_name)
00135 {
00136 const JSList * node_ptr;
00137
00138 node_ptr = jackctl_server_get_drivers_list(server);
00139
00140 while (node_ptr)
00141 {
00142 if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
00143 {
00144 return (jackctl_driver_t *)node_ptr->data;
00145 }
00146
00147 node_ptr = jack_slist_next(node_ptr);
00148 }
00149
00150 return NULL;
00151 }
00152
00153 static jackctl_parameter_t *
00154 jackctl_get_parameter(
00155 const JSList * parameters_list,
00156 const char * parameter_name)
00157 {
00158 while (parameters_list)
00159 {
00160 if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
00161 {
00162 return (jackctl_parameter_t *)parameters_list->data;
00163 }
00164
00165 parameters_list = jack_slist_next(parameters_list);
00166 }
00167
00168 return NULL;
00169 }
00170
00171 int main(int argc, char* argv[])
00172 {
00173 jackctl_server_t * server_ctl;
00174 const JSList * server_parameters;
00175 const char* server_name = "default";
00176 jackctl_driver_t * audio_driver_ctl;
00177 jackctl_driver_t * midi_driver_ctl;
00178 jackctl_driver_t * loopback_driver_ctl;
00179 int replace_registry = 0;
00180
00181 const char *options = "-d:X:P:uvshVrRL:STFl:t:mn:p:"
00182 #ifdef __linux__
00183 "c:"
00184 #endif
00185 ;
00186
00187 struct option long_options[] = {
00188 #ifdef __linux__
00189 { "clock-source", 1, 0, 'c' },
00190 #endif
00191 { "loopback-driver", 1, 0, 'L' },
00192 { "audio-driver", 1, 0, 'd' },
00193 { "midi-driver", 1, 0, 'X' },
00194 { "verbose", 0, 0, 'v' },
00195 { "help", 0, 0, 'h' },
00196 { "port-max", 1, 0, 'p' },
00197 { "no-mlock", 0, 0, 'm' },
00198 { "name", 0, 0, 'n' },
00199 { "unlock", 0, 0, 'u' },
00200 { "realtime", 0, 0, 'R' },
00201 { "no-realtime", 0, 0, 'r' },
00202 { "replace-registry", 0, &replace_registry, 0 },
00203 { "loopback", 0, 0, 'L' },
00204 { "realtime-priority", 1, 0, 'P' },
00205 { "timeout", 1, 0, 't' },
00206 { "temporary", 0, 0, 'T' },
00207 { "version", 0, 0, 'V' },
00208 { "silent", 0, 0, 's' },
00209 { "sync", 0, 0, 'S' },
00210 { 0, 0, 0, 0 }
00211 };
00212
00213 int i,opt = 0;
00214 int option_index = 0;
00215 bool seen_audio_driver = false;
00216 bool seen_midi_driver = false;
00217 char *audio_driver_name = NULL;
00218 char **audio_driver_args = NULL;
00219 int audio_driver_nargs = 1;
00220 char *midi_driver_name = NULL;
00221 char **midi_driver_args = NULL;
00222 int midi_driver_nargs = 1;
00223 int port_max = 512;
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 port_max = (unsigned int)atol(optarg);
00295 break;
00296
00297 case 'm':
00298 do_mlock = 0;
00299 break;
00300
00301 case 'u':
00302 do_unlock = 1;
00303 break;
00304
00305 case 'v':
00306 param = jackctl_get_parameter(server_parameters, "verbose");
00307 if (param != NULL) {
00308 value.b = true;
00309 jackctl_parameter_set_value(param, &value);
00310 }
00311 break;
00312
00313 case 's':
00314 jack_set_error_function(silent_jack_error_callback);
00315 break;
00316
00317 case 'S':
00318 param = jackctl_get_parameter(server_parameters, "sync");
00319 if (param != NULL) {
00320 value.b = true;
00321 jackctl_parameter_set_value(param, &value);
00322 }
00323 break;
00324
00325 case 'n':
00326 server_name = optarg;
00327 param = jackctl_get_parameter(server_parameters, "name");
00328 if (param != NULL) {
00329 strncpy(value.str, optarg, JACK_PARAM_STRING_MAX);
00330 jackctl_parameter_set_value(param, &value);
00331 }
00332 break;
00333
00334 case 'P':
00335 param = jackctl_get_parameter(server_parameters, "realtime-priority");
00336 if (param != NULL) {
00337 value.i = atoi(optarg);
00338 jackctl_parameter_set_value(param, &value);
00339 }
00340 break;
00341
00342 case 'r':
00343 param = jackctl_get_parameter(server_parameters, "realtime");
00344 if (param != NULL) {
00345 value.b = false;
00346 jackctl_parameter_set_value(param, &value);
00347 }
00348 break;
00349
00350 case 'R':
00351 param = jackctl_get_parameter(server_parameters, "realtime");
00352 if (param != NULL) {
00353 value.b = true;
00354 jackctl_parameter_set_value(param, &value);
00355 }
00356 break;
00357
00358 case 'T':
00359 param = jackctl_get_parameter(server_parameters, "temporary");
00360 if (param != NULL) {
00361 value.b = true;
00362 jackctl_parameter_set_value(param, &value);
00363 }
00364 break;
00365
00366 case 't':
00367 param = jackctl_get_parameter(server_parameters, "client-timeout");
00368 if (param != NULL) {
00369 value.i = atoi(optarg);
00370 jackctl_parameter_set_value(param, &value);
00371 }
00372 break;
00373
00374 case 'V':
00375 show_version = true;
00376 break;
00377
00378 default:
00379 fprintf(stderr, "unknown option character %c\n", optopt);
00380
00381
00382 case 'h':
00383 usage(stdout);
00384 goto fail_free1;
00385 }
00386 }
00387
00388
00389 param = jackctl_get_parameter(server_parameters, "replace-registry");
00390 if (param != NULL) {
00391 value.b = replace_registry;
00392 jackctl_parameter_set_value(param, &value);
00393 }
00394
00395 if (show_version) {
00396 printf( "jackdmp version " VERSION
00397 " tmpdir " jack_server_dir
00398 " protocol %d"
00399 "\n", JACK_PROTOCOL_VERSION);
00400 return -1;
00401 }
00402
00403 if (!seen_audio_driver) {
00404 usage(stderr);
00405 goto fail_free1;
00406 }
00407
00408
00409 audio_driver_ctl = jackctl_server_get_driver(server_ctl, audio_driver_name);
00410 if (audio_driver_ctl == NULL) {
00411 fprintf(stderr, "Unkown driver \"%s\"\n", audio_driver_name);
00412 goto fail_free1;
00413 }
00414
00415 if (optind < argc) {
00416 audio_driver_nargs = 1 + argc - optind;
00417 } else {
00418 audio_driver_nargs = 1;
00419 }
00420
00421 if (audio_driver_nargs == 0) {
00422 fprintf(stderr, "No driver specified ... hmm. JACK won't do"
00423 " anything when run like this.\n");
00424 goto fail_free1;
00425 }
00426
00427 audio_driver_args = (char **) malloc(sizeof(char *) * audio_driver_nargs);
00428 audio_driver_args[0] = audio_driver_name;
00429
00430 for (i = 1; i < audio_driver_nargs; i++) {
00431 audio_driver_args[i] = argv[optind++];
00432 }
00433
00434 if (jackctl_parse_driver_params(audio_driver_ctl, audio_driver_nargs, audio_driver_args)) {
00435 goto fail_free1;
00436 }
00437
00438
00439 if (!jackctl_server_start(server_ctl, audio_driver_ctl)) {
00440 fprintf(stderr, "Failed to start server\n");
00441 goto fail_free1;
00442 }
00443
00444
00445 if (seen_midi_driver) {
00446
00447 midi_driver_ctl = jackctl_server_get_driver(server_ctl, midi_driver_name);
00448 if (midi_driver_ctl == NULL) {
00449 fprintf(stderr, "Unkown driver \"%s\"\n", midi_driver_name);
00450 goto fail_free2;
00451 }
00452
00453 jackctl_server_add_slave(server_ctl, midi_driver_ctl);
00454 }
00455
00456
00457 if (loopback > 0) {
00458 loopback_driver_ctl = jackctl_server_get_driver(server_ctl, "loopback");
00459 if (loopback_driver_ctl != NULL) {
00460 const JSList * loopback_parameters = jackctl_driver_get_parameters(loopback_driver_ctl);
00461 param = jackctl_get_parameter(loopback_parameters, "channels");
00462 if (param != NULL) {
00463 value.ui = loopback;
00464 jackctl_parameter_set_value(param, &value);
00465 }
00466 jackctl_server_add_slave(server_ctl, loopback_driver_ctl);
00467 }
00468 }
00469
00470 notify_server_start(server_name);
00471
00472
00473 signals = jackctl_setup_signals(0);
00474 jackctl_wait_signals(signals);
00475
00476 if (!jackctl_server_stop(server_ctl))
00477 fprintf(stderr, "Cannot stop server...\n");
00478
00479 jackctl_server_destroy(server_ctl);
00480 notify_server_stop(server_name);
00481 return 0;
00482
00483 fail_free1:
00484 jackctl_server_destroy(server_ctl);
00485 return -1;
00486
00487 fail_free2:
00488 jackctl_server_stop(server_ctl);
00489 jackctl_server_destroy(server_ctl);
00490 notify_server_stop(server_name);
00491 return -1;
00492 }