2 Copyright (C) 2001 Paul Davis
3 Copyright (C) 2004-2006 Grame
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sys/types.h>
29 #include "JackServer.h"
30 #include "JackConstants.h"
31 #include "driver_interface.h"
32 #include "driver_parse.h"
33 #include "JackDriverLoader.h"
35 #include "JackError.h"
41 static JackServer
* fServer
;
42 static char* server_name
= NULL
;
43 static int realtime_priority
= 10;
44 static int do_mlock
= 1;
45 static unsigned int port_max
= 128;
46 static int realtime
= 0;
47 static int loopback
= 0;
48 static int temporary
= 0;
49 static int client_timeout
= 0; /* msecs; if zero, use period size. */
50 static int do_unlock
= 0;
51 static JSList
* drivers
= NULL
;
53 static sigset_t signals
;
55 #define DEFAULT_TMP_DIR "/tmp"
56 char* jack_tmpdir
= DEFAULT_TMP_DIR
;
58 static void silent_jack_error_callback (const char *desc
)
61 static void copyright(FILE* file
)
63 fprintf (file
, "jackdmp " VERSION
"\n"
64 "Copyright 2001-2005 Paul Davis and others.\n"
65 "Copyright 2004-2007 Grame.\n"
66 "jackdmp comes with ABSOLUTELY NO WARRANTY\n"
67 "This is free software, and you are welcome to redistribute it\n"
68 "under certain conditions; see the file COPYING for details\n");
71 static void usage (FILE* file
)
75 "usage: jackdmp [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n"
76 " [ --name OR -n server-name ]\n"
77 // " [ --no-mlock OR -m ]\n"
78 // " [ --unlock OR -u ]\n"
79 " [ --timeout OR -t client-timeout-in-msecs ]\n"
80 " [ --loopback OR -L loopback-port-number ]\n"
81 // " [ --port-max OR -p maximum-number-of-ports]\n"
82 " [ --verbose OR -v ]\n"
83 " [ --silent OR -s ]\n"
85 " [ --version OR -V ]\n"
86 " -d driver [ ... driver args ... ]\n"
87 " where driver can be `alsa', `coreaudio', 'portaudio' or `dummy'\n"
88 " jackdmp -d driver --help\n"
89 " to display options for each driver\n\n");
93 static void DoNothingHandler(int sig
)
95 /* this is used by the child (active) process, but it never
96 gets called unless we are already shutting down after
100 snprintf(buf
, sizeof(buf
), "received signal %d during shutdown (ignored)\n", sig
);
101 write(1, buf
, strlen(buf
));
104 static int JackStart(jack_driver_desc_t
* driver_desc
, JSList
* driver_params
, int sync
, int time_out_ms
, int rt
, int priority
, int loopback
, int verbose
)
106 JackLog("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld \n", sync
, time_out_ms
, rt
, priority
, verbose
);
107 fServer
= new JackServer(sync
, time_out_ms
, rt
, priority
, loopback
, verbose
);
108 int res
= fServer
->Open(driver_desc
, driver_params
);
109 return (res
< 0) ? res
: fServer
->Start();
112 static int JackStop()
116 JackLog("Jackdmp: server close\n");
118 JackLog("Jackdmp: delete server\n");
122 static int JackDelete()
125 JackLog("Jackdmp: delete server\n");
129 static void FilterSIGPIPE()
133 sigaddset(&set
, SIGPIPE
);
134 //sigprocmask(SIG_BLOCK, &set, 0);
135 pthread_sigmask(SIG_BLOCK
, &set
, 0);
138 static char* jack_default_server_name(void)
141 if ((server_name
= getenv("JACK_DEFAULT_SERVER")) == NULL
)
142 server_name
= "default";
146 /* returns the name of the per-user subdirectory of jack_tmpdir */
147 static char* jack_user_dir(void)
149 static char user_dir
[PATH_MAX
] = "";
151 /* format the path name on the first call */
152 if (user_dir
[0] == '\0') {
153 snprintf (user_dir
, sizeof (user_dir
), "%s/jack-%d",
154 jack_tmpdir
, getuid ());
160 /* returns the name of the per-server subdirectory of jack_user_dir() */
162 static char* get_jack_server_dir(const char* toto
)
164 static char server_dir
[PATH_MAX
] = "";
166 // format the path name on the first call
167 if (server_dir
[0] == '\0') {
168 snprintf (server_dir
, sizeof (server_dir
), "%s/%s",
169 jack_user_dir (), server_name
);
176 jack_cleanup_files (const char *server_name
)
179 struct dirent
*dirent
;
180 char *dir_name
= get_jack_server_dir (server_name
);
182 /* On termination, we remove all files that jackd creates so
183 * subsequent attempts to start jackd will not believe that an
184 * instance is already running. If the server crashes or is
185 * terminated with SIGKILL, this is not possible. So, cleanup
186 * is also attempted when jackd starts.
188 * There are several tricky issues. First, the previous JACK
189 * server may have run for a different user ID, so its files
190 * may be inaccessible. This is handled by using a separate
191 * JACK_TMP_DIR subdirectory for each user. Second, there may
192 * be other servers running with different names. Each gets
193 * its own subdirectory within the per-user directory. The
194 * current process has already registered as `server_name', so
195 * we know there is no other server actively using that name.
198 /* nothing to do if the server directory does not exist */
199 if ((dir
= opendir (dir_name
)) == NULL
) {
203 /* unlink all the files in this directory, they are mine */
204 while ((dirent
= readdir (dir
)) != NULL
) {
206 char fullpath
[PATH_MAX
];
208 if ((strcmp (dirent
->d_name
, ".") == 0)
209 || (strcmp (dirent
->d_name
, "..") == 0)) {
213 snprintf (fullpath
, sizeof (fullpath
), "%s/%s",
214 dir_name
, dirent
->d_name
);
216 if (unlink (fullpath
)) {
217 jack_error ("cannot unlink `%s' (%s)", fullpath
,
224 /* now, delete the per-server subdirectory, itself */
225 if (rmdir (dir_name
)) {
226 jack_error ("cannot remove `%s' (%s)", dir_name
,
230 /* finally, delete the per-user subdirectory, if empty */
231 if (rmdir (jack_user_dir ())) {
232 if (errno
!= ENOTEMPTY
) {
233 jack_error ("cannot remove `%s' (%s)",
234 jack_user_dir (), strerror (errno
));
241 int main(int argc
, char* argv
[])
245 struct sigaction action
;
248 jack_driver_desc_t
* driver_desc
;
249 const char *options
= "-ad:P:uvshVRL:STFl:t:mn:p:";
250 struct option long_options
[] = {
251 { "driver", 1, 0, 'd'
253 { "verbose", 0, 0, 'v' },
254 { "help", 0, 0, 'h' },
255 { "port-max", 1, 0, 'p' },
256 { "no-mlock", 0, 0, 'm' },
257 { "name", 0, 0, 'n' },
258 { "unlock", 0, 0, 'u' },
259 { "realtime", 0, 0, 'R' },
260 { "loopback", 0, 0, 'L' },
261 { "realtime-priority", 1, 0, 'P' },
262 { "timeout", 1, 0, 't' },
263 { "temporary", 0, 0, 'T' },
264 { "version", 0, 0, 'V' },
265 { "silent", 0, 0, 's' },
266 { "sync", 0, 0, 'S' },
270 int option_index
= 0;
272 char *driver_name
= NULL
;
273 char **driver_args
= NULL
;
274 JSList
* driver_params
;
275 int driver_nargs
= 1;
276 int show_version
= 0;
281 while (!seen_driver
&&
282 (opt
= getopt_long(argc
, argv
, options
,
283 long_options
, &option_index
)) != EOF
) {
288 driver_name
= optarg
;
296 jack_set_error_function(silent_jack_error_callback
);
304 server_name
= optarg
;
312 port_max
= (unsigned int)atol(optarg
);
316 realtime_priority
= atoi(optarg
);
324 loopback
= atoi(optarg
);
332 client_timeout
= atoi(optarg
);
344 fprintf(stderr
, "unknown option character %c\n",
355 printf ( "jackd version " VERSION
356 " tmpdir " DEFAULT_TMP_DIR
357 " protocol " PROTOCOL_VERSION
368 drivers
= jack_drivers_load (drivers
);
370 fprintf (stderr
, "jackdmp: no drivers found; exiting\n");
374 driver_desc
= jack_find_driver_descriptor (drivers
, driver_name
);
376 fprintf (stderr
, "jackdmp: unknown driver '%s'\n", driver_name
);
381 driver_nargs
= 1 + argc
- optind
;
386 if (driver_nargs
== 0) {
387 fprintf (stderr
, "No driver specified ... hmm. JACK won't do"
388 " anything when run like this.\n");
392 driver_args
= (char **) malloc (sizeof (char *) * driver_nargs
);
393 driver_args
[0] = driver_name
;
395 for (i
= 1; i
< driver_nargs
; i
++) {
396 driver_args
[i
] = argv
[optind
++];
399 if (jack_parse_driver_params (driver_desc
, driver_nargs
,
400 driver_args
, &driver_params
)) {
404 if (server_name
== NULL
)
405 server_name
= jack_default_server_name ();
409 rc
= jack_register_server (server_name
);
412 fprintf (stderr
, "`%s' server already active\n", server_name
);
415 fprintf (stderr
, "too many servers already active\n");
418 fprintf (stderr
, "no access to shm registry\n");
422 fprintf (stderr
, "server `%s' registered\n",
426 /* clean up shared memory and files from any previous
427 * instance of this server name */
429 jack_cleanup_files(server_name
);
431 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
433 sigemptyset(&signals
);
434 sigaddset(&signals
, SIGHUP
);
435 sigaddset(&signals
, SIGINT
);
436 sigaddset(&signals
, SIGQUIT
);
437 sigaddset(&signals
, SIGPIPE
);
438 sigaddset(&signals
, SIGTERM
);
439 sigaddset(&signals
, SIGUSR1
);
440 sigaddset(&signals
, SIGUSR2
);
442 // all child threads will inherit this mask unless they
443 // explicitly reset it
446 pthread_sigmask(SIG_BLOCK
, &signals
, 0);
448 if (!realtime
&& client_timeout
== 0)
449 client_timeout
= 500; /* 0.5 sec; usable when non realtime. */
451 int res
= JackStart(driver_desc
, driver_params
, sync
, client_timeout
, realtime
, realtime_priority
, loopback
, jack_verbose
);
453 jack_error("Cannot start server... exit");
459 For testing purpose...
460 InternalMetro* client1 = new InternalMetro(1200, 0.4, 20, 80, "metro1");
461 InternalMetro* client2 = new InternalMetro(600, 0.4, 20, 150, "metro2");
462 InternalMetro* client3 = new InternalMetro(1000, 0.4, 20, 110, "metro3");
463 InternalMetro* client4 = new InternalMetro(1200, 0.4, 20, 80, "metro4");
464 InternalMetro* client5 = new InternalMetro(1500, 0.4, 20, 60, "metro5");
465 InternalMetro* client6 = new InternalMetro(1200, 0.4, 20, 84, "metro6");
466 InternalMetro* client7 = new InternalMetro(600, 0.4, 20, 160, "metro7");
467 InternalMetro* client8 = new InternalMetro(1000, 0.4, 20, 113, "metro8");
468 InternalMetro* client9 = new InternalMetro(1200, 0.4, 20, 84, "metro9");
469 InternalMetro* client10 = new InternalMetro(1500, 0.4, 20, 70, "metro10");
472 // install a do-nothing handler because otherwise pthreads
473 // behaviour is undefined when we enter sigwait.
475 sigfillset(&allsignals
);
476 action
.sa_handler
= DoNothingHandler
;
477 action
.sa_mask
= allsignals
;
478 action
.sa_flags
= SA_RESTART
| SA_RESETHAND
;
480 for (i
= 1; i
< NSIG
; i
++) {
481 if (sigismember(&signals
, i
)) {
482 sigaction(i
, &action
, 0);
489 sigwait(&signals
, &sig
);
491 fprintf(stderr
, "jack main caught signal %d\n", sig
);
495 //jack_dump_configuration(engine, 1);
507 if (sig
!= SIGSEGV
) {
508 // unblock signals so we can see them during shutdown.
509 // this will help prod developers not to lose sight of
510 // bugs that cause segfaults etc. during shutdown.
511 sigprocmask(SIG_UNBLOCK
, &signals
, 0);
517 jack_cleanup_files(server_name
);
518 jack_unregister_server(server_name
);
525 int main(int argc
, char* argv
[])
528 long sample_sate
= lopt(argv
, "-r", 44100);
529 long buffer_size
= lopt(argv
, "-p", 512);
530 long chan_in
= lopt(argv
, "-i", 2);
531 long chan_out
= lopt(argv
, "-o", 2);
532 long audiodevice
= lopt(argv
, "-I", -1);
533 long sync
= lopt(argv
, "-s", 0);
534 long timeout
= lopt(argv
, "-t", 100 * 1000);
535 const char* name
= flag(argv
, "-n", "Built-in Audio");
536 long rt
= lopt(argv
, "-R", 0);
537 verbose
= lopt(argv
, "-v", 0);
544 printf("jackdmp: sample_sate = %ld buffer_size = %ld chan_in = %ld chan_out = %ld name = %s sync-mode = %ld\n",
545 sample_sate
, buffer_size
, chan_in
, chan_out
, name
, sync
);
546 assert(buffer_size
<= BUFFER_SIZE_MAX
);
548 int res
= JackStart(sample_sate
, buffer_size
, chan_in
, chan_out
, name
, audiodevice
, sync
, timeout
, rt
);
550 jack_error("Cannot start server... exit");
555 while (((c
= getchar()) != 'q')) {
560 fServer
->PrintState();