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.
27 #include "JackServer.h"
28 #include "JackConstants.h"
29 #include "driver_interface.h"
30 #include "JackDriverLoader.h"
35 static JackServer
* fServer
;
36 static char *server_name
= "default";
37 static int realtime_priority
= 10;
38 static int do_mlock
= 1;
39 static unsigned int port_max
= 128;
40 static int realtime
= 0;
41 static int loopback
= 0;
42 static int temporary
= 0;
43 static int client_timeout
= 0; /* msecs; if zero, use period size. */
44 static int do_unlock
= 0;
45 static JSList
* drivers
= NULL
;
47 static int xverbose
= 0;
49 #define DEFAULT_TMP_DIR "/tmp"
50 char *jack_tmpdir
= DEFAULT_TMP_DIR
;
54 void jack_print_driver_options (jack_driver_desc_t
* desc
, FILE *file
);
55 void jack_print_driver_param_usage (jack_driver_desc_t
* desc
, unsigned long param
, FILE *file
);
56 int jack_parse_driver_params (jack_driver_desc_t
* desc
, int argc
, char* argv
[], JSList
** param_ptr
);
57 static void silent_jack_error_callback (const char *desc
)
60 static void copyright(FILE* file
)
62 fprintf (file
, "jackdmp " VERSION
"\n"
63 "Copyright 2001-2005 Paul Davis and others.\n"
64 "Copyright 2004-2006 Grame.\n"
65 "jackdmp comes with ABSOLUTELY NO WARRANTY\n"
66 "This is free software, and you are welcome to redistribute it\n"
67 "under certain conditions; see the file COPYING for details\n");
70 static void usage (FILE *file
)
74 "usage: jackdmp [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n"
75 " [ --name OR -n server-name ]\n"
76 // " [ --no-mlock OR -m ]\n"
77 // " [ --unlock OR -u ]\n"
78 " [ --timeout OR -t client-timeout-in-msecs ]\n"
79 " [ --loopback OR -L loopback-port-number ]\n"
80 // " [ --port-max OR -p maximum-number-of-ports]\n"
81 " [ --verbose OR -v ]\n"
82 " [ --silent OR -s ]\n"
84 " [ --version OR -V ]\n"
85 " -d driver [ ... driver args ... ]\n"
86 " where driver can be `alsa', `coreaudio', 'portaudio' or `dummy'\n"
87 " jackdmp -d driver --help\n"
88 " to display options for each driver\n\n");
91 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
)
93 printf("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld \n", sync
, time_out_ms
, rt
, priority
, verbose
);
94 fServer
= new JackServer(sync
, time_out_ms
, rt
, priority
, loopback
, verbose
);
95 int res
= fServer
->Open(driver_desc
, driver_params
);
96 return (res
< 0) ? res
: fServer
->Start();
103 printf("Jackdmp: server close\n");
105 printf("Jackdmp: delete server\n");
109 static int JackDelete()
112 printf("Jackdmp: delete server\n");
116 static void intrpt(int signum
)
118 printf("jack main caught signal %d\n", signum
);
119 (void) signal(SIGINT
, SIG_DFL
);
124 static char* jack_default_server_name(void)
127 if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL)
128 server_name = "default";
132 // returns the name of the per-user subdirectory of jack_tmpdir
133 static char* jack_user_dir(void)
135 static char user_dir[PATH_MAX] = "";
137 // format the path name on the first call
138 if (user_dir[0] == '\0') {
139 snprintf (user_dir, sizeof (user_dir), "%s/jack-%d",
140 jack_tmpdir, _getuid ());
146 // returns the name of the per-server subdirectory of jack_user_dir()
148 static char* get_jack_server_dir(const char * toto)
150 static char server_dir[PATH_MAX] = "";
152 // format the path name on the first call
153 if (server_dir[0] == '\0') {
154 snprintf (server_dir, sizeof (server_dir), "%s/%s",
155 jack_user_dir (), server_name);
161 static void jack_cleanup_files (const char *server_name)
164 struct dirent *dirent;
165 char *dir_name = get_jack_server_dir (server_name);
167 // nothing to do if the server directory does not exist
168 if ((dir = opendir (dir_name)) == NULL) {
172 // unlink all the files in this directory, they are mine
173 while ((dirent = readdir (dir)) != NULL) {
175 char fullpath[PATH_MAX];
177 if ((strcmp (dirent->d_name, ".") == 0)
178 || (strcmp (dirent->d_name, "..") == 0)) {
182 snprintf (fullpath, sizeof (fullpath), "%s/%s",
183 dir_name, dirent->d_name);
185 if (unlink (fullpath)) {
186 jack_error ("cannot unlink `%s' (%s)", fullpath,
193 // now, delete the per-server subdirectory, itself
194 if (rmdir (dir_name)) {
195 jack_error ("cannot remove `%s' (%s)", dir_name,
199 // finally, delete the per-user subdirectory, if empty
200 if (rmdir (jack_user_dir ())) {
201 if (errno != ENOTEMPTY) {
202 jack_error ("cannot remove `%s' (%s)",
203 jack_user_dir (), strerror (errno));
210 BOOL CtrlHandler( DWORD fdwCtrlType )
212 switch( fdwCtrlType )
214 // Handle the CTRL-C signal.
216 printf( "Ctrl-C event\n\n" );
221 // CTRL-CLOSE: confirm that the user wants to exit.
222 case CTRL_CLOSE_EVENT:
224 printf( "Ctrl-Close event\n\n" );
228 // Pass other signals to the next handler.
229 case CTRL_BREAK_EVENT:
231 printf( "Ctrl-Break event\n\n" );
234 case CTRL_LOGOFF_EVENT:
236 printf( "Ctrl-Logoff event\n\n" );
239 case CTRL_SHUTDOWN_EVENT:
241 printf( "Ctrl-Shutdown event\n\n" );
251 int main(int argc
, char* argv
[])
253 jack_driver_desc_t
* driver_desc
;
254 const char *options
= "-ad:P:uvshVRL:STFl:t:mn:p:";
255 struct option long_options
[] = {
256 { "driver", 1, 0, 'd'
258 { "verbose", 0, 0, 'v' },
259 { "help", 0, 0, 'h' },
260 { "port-max", 1, 0, 'p' },
261 { "no-mlock", 0, 0, 'm' },
262 { "name", 0, 0, 'n' },
263 { "unlock", 0, 0, 'u' },
264 { "realtime", 0, 0, 'R' },
265 { "loopback", 0, 0, 'L' },
266 { "realtime-priority", 1, 0, 'P' },
267 { "timeout", 1, 0, 't' },
268 { "temporary", 0, 0, 'T' },
269 { "version", 0, 0, 'V' },
270 { "silent", 0, 0, 's' },
271 { "sync", 0, 0, 'S' },
275 int option_index
= 0;
277 char *driver_name
= NULL
;
278 char **driver_args
= NULL
;
279 JSList
* driver_params
;
280 int driver_nargs
= 1;
281 int show_version
= 0;
287 // Creates wait event
288 if ((waitEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
)) == NULL
) {
289 printf("CreateEvent fails err = %ld\n", GetLastError());
294 while (!seen_driver
&&
295 (opt
= getopt_long(argc
, argv
, options
,
296 long_options
, &option_index
)) != EOF
) {
301 driver_name
= optarg
;
310 //jack_set_error_function(silent_jack_error_callback);
318 server_name
= optarg
;
326 port_max
= (unsigned int)atol(optarg
);
330 realtime_priority
= atoi(optarg
);
338 loopback
= atoi(optarg
);
346 client_timeout
= atoi(optarg
);
358 fprintf(stderr
, "unknown option character %c\n",
373 drivers
= jack_drivers_load (drivers
);
375 fprintf (stderr
, "jackdmp: no drivers found; exiting\n");
380 driver_desc
= jack_find_driver_descriptor (drivers
, driver_name
);
382 fprintf (stderr
, "jackdmp: unknown driver '%s'\n", driver_name
);
388 driver_nargs
= 1 + argc
- optind
;
393 if (driver_nargs
== 0) {
394 fprintf (stderr
, "No driver specified ... hmm. JACK won't do"
395 " anything when run like this.\n");
399 driver_args
= (char **) malloc (sizeof (char *) * driver_nargs
);
400 driver_args
[0] = driver_name
;
402 for (i
= 1; i
< driver_nargs
; i
++) {
403 driver_args
[i
] = argv
[optind
++];
406 if (jack_parse_driver_params (driver_desc
, driver_nargs
,
407 driver_args
, &driver_params
)) {
412 //if (server_name == NULL)
413 // server_name = jack_default_server_name ();
417 rc
= jack_register_server (server_name
);
420 fprintf (stderr
, "`%s' server already active\n", server_name
);
424 fprintf (stderr
, "too many servers already active\n");
428 fprintf (stderr
, "no access to shm registry\n");
433 fprintf (stderr
, "server `%s' registered\n",
438 /* clean up shared memory and files from any previous
439 * instance of this server name */
441 // jack_cleanup_files(server_name);
443 if (!realtime
&& client_timeout
== 0)
444 client_timeout
= 500; /* 0.5 sec; usable when non realtime. */
446 int res
= JackStart(driver_desc
, driver_params
, sync
, client_timeout
, realtime
, realtime_priority
, loopback
, xverbose
);
448 printf("Cannot start server... exit\n");
454 if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) )
456 printf( "\nThe Control Handler is installed.\n" );
458 printf( "\nERROR: Could not set control handler");
463 (void) signal(SIGINT
, intrpt
);
464 (void) signal(SIGABRT
, intrpt
);
465 (void) signal(SIGTERM
, intrpt
);
467 if ((res
= WaitForSingleObject(waitEvent
, INFINITE
)) != WAIT_OBJECT_0
) {
468 printf("WaitForSingleObject fails err = %ld\n", GetLastError());
472 printf("Type 'q' to quit\n");
473 while ((c = getchar()) != 'q') {}
480 // jack_cleanup_files(server_name);
481 jack_unregister_server(server_name
);
483 CloseHandle(waitEvent
);