Version 0.62
[jack2.git] / windows / JackdmpWIN32.cpp
blobac5d5f918604e0195aeb23e0be4715b5d2b80189
1 /*
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.
21 #include <iostream>
22 #include <assert.h>
23 #include <process.h>
24 #include <getopt.h>
25 #include <signal.h>
27 #include "JackServer.h"
28 #include "JackConstants.h"
29 #include "driver_interface.h"
30 #include "JackDriverLoader.h"
31 #include "shm.h"
33 using namespace Jack;
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;
46 static int sync = 0;
47 static int xverbose = 0;
49 #define DEFAULT_TMP_DIR "/tmp"
50 char *jack_tmpdir = DEFAULT_TMP_DIR;
52 HANDLE waitEvent;
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)
72 copyright (file);
73 fprintf (file, "\n"
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"
83 " [ --sync 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();
99 static int JackStop()
101 fServer->Stop();
102 fServer->Close();
103 printf("Jackdmp: server close\n");
104 delete fServer;
105 printf("Jackdmp: delete server\n");
106 return 0;
109 static int JackDelete()
111 delete fServer;
112 printf("Jackdmp: delete server\n");
113 return 0;
116 static void intrpt(int signum)
118 printf("jack main caught signal %d\n", signum);
119 (void) signal(SIGINT, SIG_DFL);
120 SetEvent(waitEvent);
124 static char* jack_default_server_name(void)
126 char *server_name;
127 if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL)
128 server_name = "default";
129 return server_name;
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 ());
143 return user_dir;
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);
158 return server_dir;
161 static void jack_cleanup_files (const char *server_name)
163 DIR *dir;
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) {
169 return;
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)) {
179 continue;
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,
187 strerror (errno));
191 closedir (dir);
193 // now, delete the per-server subdirectory, itself
194 if (rmdir (dir_name)) {
195 jack_error ("cannot remove `%s' (%s)", dir_name,
196 strerror (errno));
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.
215 case CTRL_C_EVENT:
216 printf( "Ctrl-C event\n\n" );
217 Beep( 750, 300 );
218 SetEvent(waitEvent);
219 return( TRUE );
221 // CTRL-CLOSE: confirm that the user wants to exit.
222 case CTRL_CLOSE_EVENT:
223 Beep( 600, 200 );
224 printf( "Ctrl-Close event\n\n" );
225 SetEvent(waitEvent);
226 return( TRUE );
228 // Pass other signals to the next handler.
229 case CTRL_BREAK_EVENT:
230 Beep( 900, 200 );
231 printf( "Ctrl-Break event\n\n" );
232 return FALSE;
234 case CTRL_LOGOFF_EVENT:
235 Beep( 1000, 200 );
236 printf( "Ctrl-Logoff event\n\n" );
237 return FALSE;
239 case CTRL_SHUTDOWN_EVENT:
240 Beep( 750, 500 );
241 printf( "Ctrl-Shutdown event\n\n" );
242 return FALSE;
244 default:
245 return FALSE;
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' },
272 { 0, 0, 0, 0 }
274 int opt = 0;
275 int option_index = 0;
276 int seen_driver = 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;
282 int sync = 0;
283 int i;
284 int rc;
285 char c;
287 // Creates wait event
288 if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
289 printf("CreateEvent fails err = %ld\n", GetLastError());
290 return 0;
293 opterr = 0;
294 while (!seen_driver &&
295 (opt = getopt_long(argc, argv, options,
296 long_options, &option_index)) != EOF) {
297 switch (opt) {
299 case 'd':
300 seen_driver = 1;
301 driver_name = optarg;
302 break;
304 case 'v':
305 xverbose = 1;
306 break;
308 case 's':
309 // steph
310 //jack_set_error_function(silent_jack_error_callback);
311 break;
313 case 'S':
314 sync = 1;
315 break;
317 case 'n':
318 server_name = optarg;
319 break;
321 case 'm':
322 do_mlock = 0;
323 break;
325 case 'p':
326 port_max = (unsigned int)atol(optarg);
327 break;
329 case 'P':
330 realtime_priority = atoi(optarg);
331 break;
333 case 'R':
334 realtime = 1;
335 break;
337 case 'L':
338 loopback = atoi(optarg);
339 break;
341 case 'T':
342 temporary = 1;
343 break;
345 case 't':
346 client_timeout = atoi(optarg);
347 break;
349 case 'u':
350 do_unlock = 1;
351 break;
353 case 'V':
354 show_version = 1;
355 break;
357 default:
358 fprintf(stderr, "unknown option character %c\n",
359 optopt);
360 /*fallthru*/
361 case 'h':
362 usage(stdout);
363 return -1;
367 if (!seen_driver) {
368 usage (stderr);
369 //exit (1);
370 return 0;
373 drivers = jack_drivers_load (drivers);
374 if (!drivers) {
375 fprintf (stderr, "jackdmp: no drivers found; exiting\n");
376 //exit (1);
377 return 0;
380 driver_desc = jack_find_driver_descriptor (drivers, driver_name);
381 if (!driver_desc) {
382 fprintf (stderr, "jackdmp: unknown driver '%s'\n", driver_name);
383 //exit (1);
384 return 0;
387 if (optind < argc) {
388 driver_nargs = 1 + argc - optind;
389 } else {
390 driver_nargs = 1;
393 if (driver_nargs == 0) {
394 fprintf (stderr, "No driver specified ... hmm. JACK won't do"
395 " anything when run like this.\n");
396 return -1;
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)) {
408 // exit (0);
409 return 0;
412 //if (server_name == NULL)
413 // server_name = jack_default_server_name ();
415 copyright (stdout);
417 rc = jack_register_server (server_name);
418 switch (rc) {
419 case EEXIST:
420 fprintf (stderr, "`%s' server already active\n", server_name);
421 //exit (1);
422 return 0;
423 case ENOSPC:
424 fprintf (stderr, "too many servers already active\n");
425 //exit (2);
426 return 0;
427 case ENOMEM:
428 fprintf (stderr, "no access to shm registry\n");
429 //exit (3);
430 return 0;
431 default:
432 if (xverbose)
433 fprintf (stderr, "server `%s' registered\n",
434 server_name);
438 /* clean up shared memory and files from any previous
439 * instance of this server name */
440 jack_cleanup_shm();
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);
447 if (res < 0) {
448 printf("Cannot start server... exit\n");
449 JackDelete();
450 return 0;
454 if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) )
456 printf( "\nThe Control Handler is installed.\n" );
457 } else {
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') {}
477 JackStop();
479 jack_cleanup_shm();
480 // jack_cleanup_files(server_name);
481 jack_unregister_server(server_name);
483 CloseHandle(waitEvent);
484 return 1;