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 [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n"
00098 " [ --name OR -n server-name ]\n"
00099 " [ --timeout OR -t client-timeout-in-msecs ]\n"
00100 " [ --loopback OR -L loopback-port-number ]\n"
00101 " [ --midi OR -X midi-driver ]\n"
00102 " [ --verbose OR -v ]\n"
00103 #ifdef __linux__
00104 " [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n"
00105 #endif
00106 " [ --replace-registry OR -r ]\n"
00107 " [ --silent OR -s ]\n"
00108 " [ --sync OR -S ]\n"
00109 " [ --temporary OR -T ]\n"
00110 " [ --version OR -V ]\n"
00111 " -d audio-driver [ ... driver args ... ]\n"
00112 " where driver can be `alsa', `coreaudio', 'portaudio' or `dummy'\n"
00113 " jackdmp -d driver --help\n"
00114 " to display options for each driver\n\n");
00115 }
00116
00117
00118 static jackctl_driver_t *
00119 jackctl_server_get_driver(
00120 jackctl_server_t *server,
00121 const char *driver_name)
00122 {
00123 const JSList * node_ptr;
00124
00125 node_ptr = jackctl_server_get_drivers_list(server);
00126
00127 while (node_ptr)
00128 {
00129 if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
00130 {
00131 return (jackctl_driver_t *)node_ptr->data;
00132 }
00133
00134 node_ptr = jack_slist_next(node_ptr);
00135 }
00136
00137 return NULL;
00138 }
00139
00140 static jackctl_parameter_t *
00141 jackctl_get_parameter(
00142 const JSList * parameters_list,
00143 const char * parameter_name)
00144 {
00145 while (parameters_list)
00146 {
00147 if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
00148 {
00149 return (jackctl_parameter_t *)parameters_list->data;
00150 }
00151
00152 parameters_list = jack_slist_next(parameters_list);
00153 }
00154
00155 return NULL;
00156 }
00157
00158 int main(int argc, char* argv[])
00159 {
00160 jackctl_server_t * server_ctl;
00161 const JSList * server_parameters;
00162 const char* server_name = "default";
00163 jackctl_driver_t * audio_driver_ctl;
00164 jackctl_driver_t * midi_driver_ctl;
00165 jackctl_driver_t * loopback_driver_ctl;
00166
00167 #ifdef __linux__
00168 const char *options = "-ad:X:P:uvrshVRL:STFl:t:mn:p:c:L:";
00169 #else
00170 const char *options = "-ad:X:P:uvrshVRL:STFl:t:mn:p:L:";
00171 #endif
00172
00173 struct option long_options[] = {
00174 #ifdef __linux__
00175 { "clock-source", 1, 0, 'c' },
00176 #endif
00177 { "loopback-driver", 1, 0, 'L' },
00178 { "audio-driver", 1, 0, 'd' },
00179 { "midi-driver", 1, 0, 'X' },
00180 { "verbose", 0, 0, 'v' },
00181 { "help", 0, 0, 'h' },
00182 { "port-max", 1, 0, 'p' },
00183 { "no-mlock", 0, 0, 'm' },
00184 { "name", 0, 0, 'n' },
00185 { "unlock", 0, 0, 'u' },
00186 { "realtime", 0, 0, 'R' },
00187 { "replace-registry", 0, 0, 'r' },
00188 { "loopback", 0, 0, 'L' },
00189 { "realtime-priority", 1, 0, 'P' },
00190 { "timeout", 1, 0, 't' },
00191 { "temporary", 0, 0, 'T' },
00192 { "version", 0, 0, 'V' },
00193 { "silent", 0, 0, 's' },
00194 { "sync", 0, 0, 'S' },
00195 { 0, 0, 0, 0 }
00196 };
00197
00198 int i,opt = 0;
00199 int option_index = 0;
00200 bool seen_audio_driver = false;
00201 bool seen_midi_driver = false;
00202 char *audio_driver_name = NULL;
00203 char **audio_driver_args = NULL;
00204 int audio_driver_nargs = 1;
00205 char *midi_driver_name = NULL;
00206 char **midi_driver_args = NULL;
00207 int midi_driver_nargs = 1;
00208 int port_max = 512;
00209 int do_mlock = 1;
00210 int do_unlock = 0;
00211 int loopback = 0;
00212 bool show_version = false;
00213 sigset_t signals;
00214 jackctl_parameter_t* param;
00215 union jackctl_parameter_value value;
00216
00217 copyright(stdout);
00218 #if defined(JACK_DBUS) && defined(__linux__)
00219 server_ctl = jackctl_server_create(audio_acquire, audio_release);
00220 #else
00221 server_ctl = jackctl_server_create(NULL, NULL);
00222 #endif
00223 if (server_ctl == NULL) {
00224 fprintf(stderr, "Failed to create server object\n");
00225 return -1;
00226 }
00227
00228 server_parameters = jackctl_server_get_parameters(server_ctl);
00229 opterr = 0;
00230 while (!seen_audio_driver &&
00231 (opt = getopt_long(argc, argv, options,
00232 long_options, &option_index)) != EOF) {
00233 switch (opt) {
00234
00235 #ifdef __linux__
00236 case 'c':
00237 param = jackctl_get_parameter(server_parameters, "clock-source");
00238 if (param != NULL) {
00239 if (tolower (optarg[0]) == 'h') {
00240 value.ui = JACK_TIMER_HPET;
00241 jackctl_parameter_set_value(param, &value);
00242 } else if (tolower (optarg[0]) == 'c') {
00243 value.ui = JACK_TIMER_CYCLE_COUNTER;
00244 jackctl_parameter_set_value(param, &value);
00245 } else if (tolower (optarg[0]) == 's') {
00246 value.ui = JACK_TIMER_SYSTEM_CLOCK;
00247 jackctl_parameter_set_value(param, &value);
00248 } else {
00249 usage(stdout);
00250 goto fail_free;
00251 }
00252 }
00253 break;
00254 #endif
00255
00256 case 'd':
00257 seen_audio_driver = true;
00258 audio_driver_name = optarg;
00259 break;
00260
00261 case 'L':
00262 loopback = atoi(optarg);
00263 break;
00264
00265 case 'X':
00266 seen_midi_driver = true;
00267 midi_driver_name = optarg;
00268 break;
00269
00270 case 'p':
00271 port_max = (unsigned int)atol(optarg);
00272 break;
00273
00274 case 'm':
00275 do_mlock = 0;
00276 break;
00277
00278 case 'u':
00279 do_unlock = 1;
00280 break;
00281
00282 case 'v':
00283 param = jackctl_get_parameter(server_parameters, "verbose");
00284 if (param != NULL) {
00285 value.b = true;
00286 jackctl_parameter_set_value(param, &value);
00287 }
00288 break;
00289
00290 case 's':
00291 jack_set_error_function(silent_jack_error_callback);
00292 break;
00293
00294 case 'S':
00295 param = jackctl_get_parameter(server_parameters, "sync");
00296 if (param != NULL) {
00297 value.b = true;
00298 jackctl_parameter_set_value(param, &value);
00299 }
00300 break;
00301
00302 case 'n':
00303 server_name = optarg;
00304 param = jackctl_get_parameter(server_parameters, "name");
00305 if (param != NULL) {
00306 strncpy(value.str, optarg, JACK_PARAM_STRING_MAX);
00307 jackctl_parameter_set_value(param, &value);
00308 }
00309 break;
00310
00311 case 'P':
00312 param = jackctl_get_parameter(server_parameters, "realtime-priority");
00313 if (param != NULL) {
00314 value.i = atoi(optarg);
00315 jackctl_parameter_set_value(param, &value);
00316 }
00317 break;
00318
00319 case 'r':
00320 param = jackctl_get_parameter(server_parameters, "replace-registry");
00321 if (param != NULL) {
00322 value.b = true;
00323 jackctl_parameter_set_value(param, &value);
00324 }
00325 break;
00326
00327 case 'R':
00328 param = jackctl_get_parameter(server_parameters, "realtime");
00329 if (param != NULL) {
00330 value.b = true;
00331 jackctl_parameter_set_value(param, &value);
00332 }
00333 break;
00334
00335 case 'T':
00336 param = jackctl_get_parameter(server_parameters, "temporary");
00337 if (param != NULL) {
00338 value.b = true;
00339 jackctl_parameter_set_value(param, &value);
00340 }
00341 break;
00342
00343 case 't':
00344 param = jackctl_get_parameter(server_parameters, "client-timeout");
00345 if (param != NULL) {
00346 value.i = atoi(optarg);
00347 jackctl_parameter_set_value(param, &value);
00348 }
00349 break;
00350
00351 case 'V':
00352 show_version = true;
00353 break;
00354
00355 default:
00356 fprintf(stderr, "unknown option character %c\n", optopt);
00357
00358
00359 case 'h':
00360 usage(stdout);
00361 goto fail_free;
00362 }
00363 }
00364
00365 if (show_version) {
00366 printf( "jackdmp version " VERSION
00367 " tmpdir " jack_server_dir
00368 " protocol %d"
00369 "\n", JACK_PROTOCOL_VERSION);
00370 return -1;
00371 }
00372
00373 if (!seen_audio_driver) {
00374 usage(stderr);
00375 goto fail_free;
00376 }
00377
00378
00379 audio_driver_ctl = jackctl_server_get_driver(server_ctl, audio_driver_name);
00380 if (audio_driver_ctl == NULL) {
00381 fprintf(stderr, "Unkown driver \"%s\"\n", audio_driver_name);
00382 goto fail_free;
00383 }
00384
00385 if (optind < argc) {
00386 audio_driver_nargs = 1 + argc - optind;
00387 } else {
00388 audio_driver_nargs = 1;
00389 }
00390
00391 if (audio_driver_nargs == 0) {
00392 fprintf(stderr, "No driver specified ... hmm. JACK won't do"
00393 " anything when run like this.\n");
00394 goto fail_free;
00395 }
00396
00397 audio_driver_args = (char **) malloc(sizeof(char *) * audio_driver_nargs);
00398 audio_driver_args[0] = audio_driver_name;
00399
00400 for (i = 1; i < audio_driver_nargs; i++) {
00401 audio_driver_args[i] = argv[optind++];
00402 }
00403
00404 if (jackctl_parse_driver_params(audio_driver_ctl, audio_driver_nargs, audio_driver_args)) {
00405 goto fail_free;
00406 }
00407
00408
00409 if (!jackctl_server_start(server_ctl, audio_driver_ctl)) {
00410 fprintf(stderr, "Failed to start server\n");
00411 goto fail_free;
00412 }
00413
00414
00415 if (seen_midi_driver) {
00416
00417 midi_driver_ctl = jackctl_server_get_driver(server_ctl, midi_driver_name);
00418 if (midi_driver_ctl == NULL) {
00419 fprintf(stderr, "Unkown driver \"%s\"\n", midi_driver_name);
00420 goto fail_free;
00421 }
00422
00423 jackctl_server_add_slave(server_ctl, midi_driver_ctl);
00424 }
00425
00426
00427 if (loopback > 0) {
00428 loopback_driver_ctl = jackctl_server_get_driver(server_ctl, "loopback");
00429 if (loopback_driver_ctl != NULL) {
00430 const JSList * loopback_parameters = jackctl_driver_get_parameters(loopback_driver_ctl);
00431 param = jackctl_get_parameter(loopback_parameters, "channels");
00432 if (param != NULL) {
00433 value.ui = loopback;
00434 jackctl_parameter_set_value(param, &value);
00435 }
00436 jackctl_server_add_slave(server_ctl, loopback_driver_ctl);
00437 }
00438 }
00439
00440 notify_server_start(server_name);
00441
00442
00443 signals = jackctl_setup_signals(0);
00444 jackctl_wait_signals(signals);
00445
00446 if (!jackctl_server_stop(server_ctl))
00447 fprintf(stderr, "Cannot stop server...\n");
00448
00449 fail_free:
00450
00451 jackctl_server_destroy(server_ctl);
00452 notify_server_stop(server_name);
00453 return 1;
00454 }