diff options
Diffstat (limited to 'jackd/jackd.c')
-rw-r--r-- | jackd/jackd.c | 670 |
1 files changed, 339 insertions, 331 deletions
diff --git a/jackd/jackd.c b/jackd/jackd.c index 1a59b84..0faae93 100644 --- a/jackd/jackd.c +++ b/jackd/jackd.c @@ -1,7 +1,7 @@ /* -*- mode: c; c-file-style: "bsd"; -*- */ /* Copyright (C) 2001-2005 Paul Davis - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ + */ #include <config.h> @@ -73,19 +73,20 @@ static jack_nframes_t frame_time_offset = 0; static int nozombies = 0; static int timeout_count_threshold = 0; -extern int sanitycheck (int, int); +extern int sanitycheck(int, int); static jack_driver_desc_t * -jack_find_driver_descriptor (const char * name); +jack_find_driver_descriptor(const char * name); -static void +static void do_nothing_handler (int sig) { /* this is used by the child (active) process, but it never gets called unless we are already shutting down after another signal. - */ + */ char buf[64]; + snprintf (buf, sizeof(buf), "received signal %d during shutdown (ignored)\n", sig); write (1, buf, strlen (buf)); @@ -93,147 +94,147 @@ do_nothing_handler (int sig) static void jack_load_internal_clients (JSList* load_list) -{ +{ JSList * node; - for (node = load_list; node; node = jack_slist_next (node)) { - - char* str = (char*) node->data; - jack_request_t req; - char* colon = strchr (str, ':'); - char* slash = strchr (str, '/'); - char* client_name = NULL; - char* path = NULL; - char* args = NULL; - char* rest = NULL; - int free_path = 0; - int free_name = 0; - size_t len; - - /* possible argument forms: - - client-name:client-type/args - client-type/args - client-name:client-type - client-type - - client-name is the desired JACK client name. - client-type is basically the name of the DLL/DSO without any suffix. - args is a string whose contents will be passed to the client as - it is instantiated - */ - - if ((slash == NULL && colon == NULL) || (slash && colon && colon > slash)) { - - /* client-type */ - - client_name = str; - path = client_name; - - } else if (slash && colon) { - - /* client-name:client-type/args */ - - len = colon - str; - if (len) { - /* add 1 to leave space for a NULL */ - client_name = (char*) malloc (len + 1); - free_name = 1; - memcpy (client_name, str, len); - client_name[len] = '\0'; - } - - len = slash - (colon+1); - if (len) { - /* add 1 to leave space for a NULL */ - path = (char*) malloc (len + 1); - free_path = 1; - memcpy (path, colon + 1, len); - path[len] = '\0'; - } else { - path = client_name; - } - - rest = slash + 1; - len = strlen (rest); - - if (len) { - /* add 1 to leave space for a NULL */ - args = (char*) malloc (len + 1); - memcpy (args, rest, len); - args[len] = '\0'; - } - - } else if (slash && colon == NULL) { - - /* client-type/args */ - - len = slash - str; - - if (len) { - /* add 1 to leave space for a NULL */ - path = (char *) malloc (len + 1); - free_path = 1; - memcpy (path, str, len); - path[len] = '\0'; - } - - rest = slash + 1; - len = strlen (rest); - - if (len) { - /* add 1 to leave space for a NULL */ - args = (char*) malloc (len + 1); - memcpy (args, rest, len); - args[len] = '\0'; - } - } else { - - /* client-name:client-type */ - - len = colon - str; - - if (len) { - /* add 1 to leave space for a NULL */ - client_name = (char *) malloc (len + 1); - free_name = 1; - memcpy (client_name, str, len); - client_name[len] = '\0'; - path = colon + 1; - } - } - - if (client_name == NULL || path == NULL) { - fprintf (stderr, "incorrect format for internal client specification (%s)\n", str); - exit (1); - } - - memset (&req, 0, sizeof (req)); - req.type = IntClientLoad; - req.x.intclient.options = 0; - strncpy (req.x.intclient.name, client_name, sizeof (req.x.intclient.name)); - strncpy (req.x.intclient.path, path, sizeof (req.x.intclient.path)); - - if (args) { - strncpy (req.x.intclient.init, args, sizeof (req.x.intclient.init)); - } else { - req.x.intclient.init[0] = '\0'; - } - - pthread_mutex_lock (&engine->request_lock); - jack_intclient_load_request (engine, &req); - pthread_mutex_unlock (&engine->request_lock); - - if (free_name) { - free (client_name); - } - if (free_path) { - free (path); - } - if (args) { - free (args); - } - } + for (node = load_list; node; node = jack_slist_next (node)) { + + char* str = (char*)node->data; + jack_request_t req; + char* colon = strchr (str, ':'); + char* slash = strchr (str, '/'); + char* client_name = NULL; + char* path = NULL; + char* args = NULL; + char* rest = NULL; + int free_path = 0; + int free_name = 0; + size_t len; + + /* possible argument forms: + + client-name:client-type/args + client-type/args + client-name:client-type + client-type + + client-name is the desired JACK client name. + client-type is basically the name of the DLL/DSO without any suffix. + args is a string whose contents will be passed to the client as + it is instantiated + */ + + if ((slash == NULL && colon == NULL) || (slash && colon && colon > slash)) { + + /* client-type */ + + client_name = str; + path = client_name; + + } else if (slash && colon) { + + /* client-name:client-type/args */ + + len = colon - str; + if (len) { + /* add 1 to leave space for a NULL */ + client_name = (char*)malloc (len + 1); + free_name = 1; + memcpy (client_name, str, len); + client_name[len] = '\0'; + } + + len = slash - (colon + 1); + if (len) { + /* add 1 to leave space for a NULL */ + path = (char*)malloc (len + 1); + free_path = 1; + memcpy (path, colon + 1, len); + path[len] = '\0'; + } else { + path = client_name; + } + + rest = slash + 1; + len = strlen (rest); + + if (len) { + /* add 1 to leave space for a NULL */ + args = (char*)malloc (len + 1); + memcpy (args, rest, len); + args[len] = '\0'; + } + + } else if (slash && colon == NULL) { + + /* client-type/args */ + + len = slash - str; + + if (len) { + /* add 1 to leave space for a NULL */ + path = (char*)malloc (len + 1); + free_path = 1; + memcpy (path, str, len); + path[len] = '\0'; + } + + rest = slash + 1; + len = strlen (rest); + + if (len) { + /* add 1 to leave space for a NULL */ + args = (char*)malloc (len + 1); + memcpy (args, rest, len); + args[len] = '\0'; + } + } else { + + /* client-name:client-type */ + + len = colon - str; + + if (len) { + /* add 1 to leave space for a NULL */ + client_name = (char*)malloc (len + 1); + free_name = 1; + memcpy (client_name, str, len); + client_name[len] = '\0'; + path = colon + 1; + } + } + + if (client_name == NULL || path == NULL) { + fprintf (stderr, "incorrect format for internal client specification (%s)\n", str); + exit (1); + } + + memset (&req, 0, sizeof(req)); + req.type = IntClientLoad; + req.x.intclient.options = 0; + strncpy (req.x.intclient.name, client_name, sizeof(req.x.intclient.name)); + strncpy (req.x.intclient.path, path, sizeof(req.x.intclient.path)); + + if (args) { + strncpy (req.x.intclient.init, args, sizeof(req.x.intclient.init)); + } else { + req.x.intclient.init[0] = '\0'; + } + + pthread_mutex_lock (&engine->request_lock); + jack_intclient_load_request (engine, &req); + pthread_mutex_unlock (&engine->request_lock); + + if (free_name) { + free (client_name); + } + if (free_path) { + free (path); + } + if (args) { + free (args); + } + } } static int @@ -248,7 +249,7 @@ jack_main (jack_driver_desc_t * driver_desc, JSList * driver_params, JSList * sl /* ensure that we are in our own process group so that kill (SIG, -pgrp) does the right thing. - */ + */ setsid (); @@ -258,14 +259,14 @@ jack_main (jack_driver_desc_t * driver_desc, JSList * driver_params, JSList * sl POSIX says that signals are delivered like this: - * if a thread has blocked that signal, it is not + * if a thread has blocked that signal, it is not a candidate to receive the signal. - * of all threads not blocking the signal, pick + * of all threads not blocking the signal, pick one at random, and deliver the signal. - this means that a simple-minded multi-threaded program can - expect to get POSIX signals delivered randomly to any one - of its threads, + this means that a simple-minded multi-threaded program can + expect to get POSIX signals delivered randomly to any one + of its threads, here, we block all signals that we think we might receive and want to catch. all "child" threads will inherit this @@ -278,50 +279,51 @@ jack_main (jack_driver_desc_t * driver_desc, JSList * driver_params, JSList * sl importantly, we are free to call async-unsafe functions, because the code is executing in normal thread context after a return from sigwait(). - */ + */ sigemptyset (&signals); - sigaddset(&signals, SIGHUP); - sigaddset(&signals, SIGINT); - sigaddset(&signals, SIGQUIT); - sigaddset(&signals, SIGPIPE); - sigaddset(&signals, SIGTERM); - sigaddset(&signals, SIGUSR1); - sigaddset(&signals, SIGUSR2); + sigaddset (&signals, SIGHUP); + sigaddset (&signals, SIGINT); + sigaddset (&signals, SIGQUIT); + sigaddset (&signals, SIGPIPE); + sigaddset (&signals, SIGTERM); + sigaddset (&signals, SIGUSR1); + sigaddset (&signals, SIGUSR2); /* all child threads will inherit this mask unless they - * explicitly reset it + * explicitly reset it */ pthread_sigmask (SIG_BLOCK, &signals, 0); - if (!realtime && client_timeout == 0) + if (!realtime && client_timeout == 0) { client_timeout = 500; /* 0.5 sec; usable when non realtime. */ + } /* get the engine/driver started */ - if ((engine = jack_engine_new (realtime, realtime_priority, + if ((engine = jack_engine_new (realtime, realtime_priority, do_mlock, do_unlock, server_name, temporary, verbose, client_timeout, - port_max, getpid(), frame_time_offset, + port_max, getpid (), frame_time_offset, nozombies, timeout_count_threshold, drivers)) == 0) { jack_error ("cannot create engine"); return -1; } jack_info ("loading driver .."); - + if (jack_engine_load_driver (engine, driver_desc, driver_params)) { jack_error ("cannot load driver module %s", - driver_desc->name); + driver_desc->name); goto error; } - for (node=slave_names; node; node=jack_slist_next(node)) { + for (node = slave_names; node; node = jack_slist_next (node)) { char *sl_name = node->data; - jack_driver_desc_t *sl_desc = jack_find_driver_descriptor(sl_name); + jack_driver_desc_t *sl_desc = jack_find_driver_descriptor (sl_name); if (sl_desc) { - jack_engine_load_slave_driver(engine, sl_desc, NULL); + jack_engine_load_slave_driver (engine, sl_desc, NULL); } } @@ -331,25 +333,25 @@ jack_main (jack_driver_desc_t * driver_desc, JSList * driver_params, JSList * sl goto error; } - jack_load_internal_clients (load_list); + jack_load_internal_clients (load_list); /* install a do-nothing handler because otherwise pthreads behaviour is undefined when we enter sigwait. - */ + */ sigfillset (&allsignals); action.sa_handler = do_nothing_handler; action.sa_mask = allsignals; - action.sa_flags = SA_RESTART|SA_RESETHAND; + action.sa_flags = SA_RESTART | SA_RESETHAND; for (i = 1; i < NSIG; i++) { if (sigismember (&signals, i)) { sigaction (i, &action, 0); - } + } } - + if (verbose) { - jack_info ("%d waiting for signals", getpid()); + jack_info ("%d waiting for signals", getpid ()); } waiting = TRUE; @@ -358,10 +360,10 @@ jack_main (jack_driver_desc_t * driver_desc, JSList * driver_params, JSList * sl sigwait (&signals, &sig); jack_info ("jack main caught signal %d", sig); - + switch (sig) { case SIGUSR1: - jack_dump_configuration(engine, 1); + jack_dump_configuration (engine, 1); break; case SIGUSR2: /* driver exit */ @@ -371,20 +373,20 @@ jack_main (jack_driver_desc_t * driver_desc, JSList * driver_params, JSList * sl waiting = FALSE; break; } - } - + } + if (sig != SIGSEGV) { /* unblock signals so we can see them during shutdown. this will help prod developers not to lose sight of bugs that cause segfaults etc. during shutdown. - */ + */ sigprocmask (SIG_UNBLOCK, &signals, 0); } - + jack_engine_delete (engine); return 1; - + error: jack_engine_delete (engine); return -1; @@ -402,7 +404,7 @@ jack_drivers_get_descriptor (JSList * drivers, const char * sofile) int err; char* driver_dir; - if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { + if ((driver_dir = getenv ("JACK_DRIVER_DIR")) == 0) { driver_dir = ADDON_DIR; } filename = malloc (strlen (driver_dir) + 1 + strlen (sofile) + 1); @@ -412,17 +414,17 @@ jack_drivers_get_descriptor (JSList * drivers, const char * sofile) jack_info ("getting driver descriptor from %s", filename); } - if ((dlhandle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL)) == NULL) { + if ((dlhandle = dlopen (filename, RTLD_NOW | RTLD_GLOBAL)) == NULL) { jack_error ("could not open driver .so '%s': %s\n", filename, dlerror ()); free (filename); return NULL; } so_get_descriptor = (JackDriverDescFunction) - dlsym (dlhandle, "driver_get_descriptor"); + dlsym (dlhandle, "driver_get_descriptor"); if ((dlerr = dlerror ()) != NULL) { - jack_error("%s", dlerr); + jack_error ("%s", dlerr); dlclose (dlhandle); free (filename); return NULL; @@ -441,7 +443,7 @@ jack_drivers_get_descriptor (JSList * drivers, const char * sofile) /* check it doesn't exist already */ for (node = drivers; node; node = jack_slist_next (node)) { - other_descriptor = (jack_driver_desc_t *) node->data; + other_descriptor = (jack_driver_desc_t*)node->data; if (strcmp (descriptor->name, other_descriptor->name) == 0) { jack_error ("the drivers in '%s' and '%s' both have the name '%s'; using the first\n", @@ -469,7 +471,7 @@ jack_drivers_load () jack_driver_desc_t * desc; char* driver_dir; - if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { + if ((driver_dir = getenv ("JACK_DRIVER_DIR")) == 0) { driver_dir = ADDON_DIR; } @@ -481,7 +483,7 @@ jack_drivers_load () driver_dir, strerror (errno)); return NULL; } - + while ( (dir_entry = readdir (dir_stream)) ) { /* check the filename is of the right format */ if (strncmp ("jack_", dir_entry->d_name, 5) != 0) { @@ -520,26 +522,26 @@ jack_drivers_load () static void copyright (FILE* file) { fprintf (file, "jackd " VERSION "\n" -"Copyright 2001-2009 Paul Davis, Stephane Letz, Jack O'Quinn, Torben Hohn and others.\n" -"jackd comes with ABSOLUTELY NO WARRANTY\n" -"This is free software, and you are welcome to redistribute it\n" -"under certain conditions; see the file COPYING for details\n\n"); + "Copyright 2001-2009 Paul Davis, Stephane Letz, Jack O'Quinn, Torben Hohn and others.\n" + "jackd comes with ABSOLUTELY NO WARRANTY\n" + "This is free software, and you are welcome to redistribute it\n" + "under certain conditions; see the file COPYING for details\n\n"); } -static void usage (FILE *file) +static void usage (FILE *file) { copyright (file); fprintf (file, "\n" -"usage: jackd [ server options ] -d backend [ ... backend options ... ]\n" -" (see the manual page for jackd for a complete list of options)\n\n" + "usage: jackd [ server options ] -d backend [ ... backend options ... ]\n" + " (see the manual page for jackd for a complete list of options)\n\n" #ifdef __APPLE__ -" Available backends may include: coreaudio, dummy, net, portaudio.\n\n" -#else -" Available backends may include: alsa, dummy, freebob, firewire, net, oss, sun, or portaudio.\n\n" + " Available backends may include: coreaudio, dummy, net, portaudio.\n\n" +#else + " Available backends may include: alsa, dummy, freebob, firewire, net, oss, sun, or portaudio.\n\n" #endif -" jackd -d backend --help\n" -" to display options for each backend\n\n"); -} + " jackd -d backend --help\n" + " to display options for each backend\n\n"); +} static jack_driver_desc_t * jack_find_driver_descriptor (const char * name) @@ -548,7 +550,7 @@ jack_find_driver_descriptor (const char * name) JSList * node; for (node = drivers; node; node = jack_slist_next (node)) { - desc = (jack_driver_desc_t *) node->data; + desc = (jack_driver_desc_t*)node->data; if (strcmp (desc->name, name) != 0) { desc = NULL; @@ -565,8 +567,9 @@ jack_cleanup_files (const char *server_name) { DIR *dir; struct dirent *dirent; - char dir_name[PATH_MAX+1] = ""; - jack_server_dir (server_name, dir_name); + char dir_name[PATH_MAX + 1] = ""; + + jack_server_dir (server_name, dir_name); /* On termination, we remove all files that jackd creates so * subsequent attempts to start jackd will not believe that an @@ -592,27 +595,27 @@ jack_cleanup_files (const char *server_name) /* unlink all the files in this directory, they are mine */ while ((dirent = readdir (dir)) != NULL) { - char fullpath[PATH_MAX+1]; + char fullpath[PATH_MAX + 1]; if ((strcmp (dirent->d_name, ".") == 0) || (strcmp (dirent->d_name, "..") == 0)) { continue; } - snprintf (fullpath, sizeof (fullpath), "%s/%s", + snprintf (fullpath, sizeof(fullpath), "%s/%s", dir_name, dirent->d_name); if (unlink (fullpath)) { jack_error ("cannot unlink `%s' (%s)", fullpath, strerror (errno)); } - } + } closedir (dir); /* now, delete the per-server subdirectory, itself */ if (rmdir (dir_name)) { - jack_error ("cannot remove `%s' (%s)", dir_name, + jack_error ("cannot remove `%s' (%s)", dir_name, strerror (errno)); } @@ -633,20 +636,20 @@ maybe_use_capabilities () /* check to see if there is a pipe in the right descriptor */ if ((status = fstat (PIPE_WRITE_FD, &pipe_stat)) == 0 && - S_ISFIFO(pipe_stat.st_mode)) { + S_ISFIFO (pipe_stat.st_mode)) { /* tell jackstart we are up and running */ - char c = 1; + char c = 1; - if (write (PIPE_WRITE_FD, &c, 1) != 1) { - jack_error ("cannot write to jackstart sync " - "pipe %d (%s)", PIPE_WRITE_FD, - strerror (errno)); - } + if (write (PIPE_WRITE_FD, &c, 1) != 1) { + jack_error ("cannot write to jackstart sync " + "pipe %d (%s)", PIPE_WRITE_FD, + strerror (errno)); + } - if (close(PIPE_WRITE_FD) != 0) { - jack_error("jackd: error on startup pipe close: %s", - strerror (errno)); + if (close (PIPE_WRITE_FD) != 0) { + jack_error ("jackd: error on startup pipe close: %s", + strerror (errno)); } else { /* wait for jackstart process to set our capabilities */ if (wait (&status) == -1) { @@ -660,10 +663,10 @@ maybe_use_capabilities () } } } -#endif /* USE_CAPABILITIES */ +#endif /* USE_CAPABILITIES */ } -int +int main (int argc, char *argv[]) { @@ -677,38 +680,38 @@ main (int argc, char *argv[]) #else const char *options = "d:P:uvshVrRZTFlI:t:mM:n:Np:c:X:C:"; #endif - struct option long_options[] = - { + struct option long_options[] = + { /* keep ordered by single-letter option code */ #ifdef HAVE_ZITA_BRIDGE_DEPS - { "alsa-add", 1, 0, 'A' }, + { "alsa-add", 1, 0, 'A' }, #endif - { "clock-source", 1, 0, 'c' }, - { "driver", 1, 0, 'd' }, - { "help", 0, 0, 'h' }, - { "tmpdir-location", 0, 0, 'l' }, - { "internal-client", 0, 0, 'I' }, - { "no-mlock", 0, 0, 'm' }, - { "midi-bufsize", 1, 0, 'M' }, - { "name", 1, 0, 'n' }, - { "no-sanity-checks", 0, 0, 'N' }, - { "port-max", 1, 0, 'p' }, - { "realtime-priority", 1, 0, 'P' }, - { "no-realtime", 0, 0, 'r' }, - { "realtime", 0, 0, 'R' }, - { "replace-registry", 0, &replace_registry, 0 }, - { "silent", 0, 0, 's' }, - { "sync", 0, 0, 'S' }, - { "timeout", 1, 0, 't' }, - { "temporary", 0, 0, 'T' }, - { "unlock", 0, 0, 'u' }, - { "version", 0, 0, 'V' }, - { "verbose", 0, 0, 'v' }, - { "slave-driver", 1, 0, 'X' }, - { "nozombies", 0, 0, 'Z' }, - { "timeout-thres", 2, 0, 'C' }, - { 0, 0, 0, 0 } + { "clock-source", 1, 0, 'c' }, + { "driver", 1, 0, 'd' }, + { "help", 0, 0, 'h' }, + { "tmpdir-location", 0, 0, 'l' }, + { "internal-client", 0, 0, 'I' }, + { "no-mlock", 0, 0, 'm' }, + { "midi-bufsize", 1, 0, 'M' }, + { "name", 1, 0, 'n' }, + { "no-sanity-checks", 0, 0, 'N' }, + { "port-max", 1, 0, 'p' }, + { "realtime-priority", 1, 0, 'P' }, + { "no-realtime", 0, 0, 'r' }, + { "realtime", 0, 0, 'R' }, + { "replace-registry", 0, &replace_registry, 0 }, + { "silent", 0, 0, 's' }, + { "sync", 0, 0, 'S' }, + { "timeout", 1, 0, 't' }, + { "temporary", 0, 0, 'T' }, + { "unlock", 0, 0, 'u' }, + { "version", 0, 0, 'V' }, + { "verbose", 0, 0, 'v' }, + { "slave-driver", 1, 0, 'X' }, + { "nozombies", 0, 0, 'Z' }, + { "timeout-thres", 2, 0, 'C' }, + { 0, 0, 0, 0 } }; int opt = 0; int option_index = 0; @@ -717,16 +720,16 @@ main (int argc, char *argv[]) char **driver_args = NULL; JSList * driver_params; JSList * slave_drivers = NULL; - JSList * load_list = NULL; + JSList * load_list = NULL; size_t midi_buffer_size = 0; int driver_nargs = 1; int i; int rc; #ifdef HAVE_ZITA_BRIDGE_DEPS - const char* alsa_add_client_name_playback = "zalsa_out"; - const char* alsa_add_client_name_capture = "zalsa_in"; - char alsa_add_args[64]; - char* dirstr; + const char* alsa_add_client_name_playback = "zalsa_out"; + const char* alsa_add_client_name_capture = "zalsa_in"; + char alsa_add_args[64]; + char* dirstr; #endif setvbuf (stdout, NULL, _IOLBF, 0); @@ -739,37 +742,37 @@ main (int argc, char *argv[]) switch (opt) { #ifdef HAVE_ZITA_BRIDGE_DEPS - case 'A': - /* add a new internal client named after the ALSA device name - given as optarg, using the last character 'p' or 'c' to - indicate playback or capture. If there isn't one, - assume capture (common case: USB mics etc.) - */ - if ((dirstr = strstr (optarg, "%p")) != NULL && dirstr == (optarg + strlen(optarg) - 2)) { - snprintf (alsa_add_args, sizeof (alsa_add_args), "%.*s_play:%s/-dhw:%.*s", - (int) strlen (optarg) - 2, optarg, - alsa_add_client_name_playback, - (int) strlen (optarg) - 2, optarg); - load_list = jack_slist_append(load_list, strdup (alsa_add_args)); - } else if ((dirstr = strstr (optarg, "%c")) != NULL && dirstr == (optarg + strlen(optarg) - 2)) { - snprintf (alsa_add_args, sizeof (alsa_add_args), "%.*s_rec:%s/-dhw:%.*s", - (int) strlen (optarg) - 2, optarg, - alsa_add_client_name_capture, - (int) strlen (optarg) - 2, optarg); - load_list = jack_slist_append(load_list, strdup (alsa_add_args)); - } else { - snprintf (alsa_add_args, sizeof (alsa_add_args), "%s_play:%s/-dhw:%s", - optarg, - alsa_add_client_name_playback, - optarg); - load_list = jack_slist_append(load_list, strdup (alsa_add_args)); - snprintf (alsa_add_args, sizeof (alsa_add_args), "%s_rec:%s/-dhw:%s", - optarg, - alsa_add_client_name_capture, - optarg); - load_list = jack_slist_append(load_list, strdup (alsa_add_args)); - } - break; + case 'A': + /* add a new internal client named after the ALSA device name + given as optarg, using the last character 'p' or 'c' to + indicate playback or capture. If there isn't one, + assume capture (common case: USB mics etc.) + */ + if ((dirstr = strstr (optarg, "%p")) != NULL && dirstr == (optarg + strlen (optarg) - 2)) { + snprintf (alsa_add_args, sizeof(alsa_add_args), "%.*s_play:%s/-dhw:%.*s", + (int)strlen (optarg) - 2, optarg, + alsa_add_client_name_playback, + (int)strlen (optarg) - 2, optarg); + load_list = jack_slist_append (load_list, strdup (alsa_add_args)); + } else if ((dirstr = strstr (optarg, "%c")) != NULL && dirstr == (optarg + strlen (optarg) - 2)) { + snprintf (alsa_add_args, sizeof(alsa_add_args), "%.*s_rec:%s/-dhw:%.*s", + (int)strlen (optarg) - 2, optarg, + alsa_add_client_name_capture, + (int)strlen (optarg) - 2, optarg); + load_list = jack_slist_append (load_list, strdup (alsa_add_args)); + } else { + snprintf (alsa_add_args, sizeof(alsa_add_args), "%s_play:%s/-dhw:%s", + optarg, + alsa_add_client_name_playback, + optarg); + load_list = jack_slist_append (load_list, strdup (alsa_add_args)); + snprintf (alsa_add_args, sizeof(alsa_add_args), "%s_rec:%s/-dhw:%s", + optarg, + alsa_add_client_name_capture, + optarg); + load_list = jack_slist_append (load_list, strdup (alsa_add_args)); + } + break; #endif case 'c': @@ -791,10 +794,11 @@ main (int argc, char *argv[]) break; case 'C': - if (optarg) + if (optarg) { timeout_count_threshold = atoi (optarg); - else + } else { timeout_count_threshold = 250; + } break; case 'd': @@ -803,7 +807,7 @@ main (int argc, char *argv[]) break; case 'D': - frame_time_offset = JACK_MAX_FRAMES - atoi(optarg); + frame_time_offset = JACK_MAX_FRAMES - atoi (optarg); break; case 'l': @@ -811,16 +815,16 @@ main (int argc, char *argv[]) printf ("%s\n", jack_tmpdir); exit (0); - case 'I': - load_list = jack_slist_append(load_list, optarg); - break; + case 'I': + load_list = jack_slist_append (load_list, optarg); + break; case 'm': do_mlock = 0; break; case 'M': - midi_buffer_size = (unsigned int) atol (optarg); + midi_buffer_size = (unsigned int)atol (optarg); break; case 'n': @@ -832,7 +836,7 @@ main (int argc, char *argv[]) break; case 'p': - port_max = (unsigned int) atol (optarg); + port_max = (unsigned int)atol (optarg); break; case 'P': @@ -852,9 +856,9 @@ main (int argc, char *argv[]) jack_set_error_function (silent_jack_error_callback); break; - case 'S': - /* this option is for jack2 only (synchronous mode) */ - break; + case 'S': + /* this option is for jack2 only (synchronous mode) */ + break; case 'T': temporary = 1; @@ -877,7 +881,7 @@ main (int argc, char *argv[]) break; case 'X': - slave_drivers = jack_slist_append(slave_drivers, optarg); + slave_drivers = jack_slist_append (slave_drivers, optarg); break; case 'Z': nozombies = 1; @@ -886,7 +890,7 @@ main (int argc, char *argv[]) default: jack_error ("Unknown option character %c", optopt); - /*fallthru*/ + /*fallthru*/ case 'h': usage (stdout); return -1; @@ -894,10 +898,10 @@ main (int argc, char *argv[]) } if (show_version) { - printf ( "jackd version " VERSION - " tmpdir " DEFAULT_TMP_DIR - " protocol " PROTOCOL_VERSION - "\n"); + printf ( "jackd version " VERSION + " tmpdir " DEFAULT_TMP_DIR + " protocol " PROTOCOL_VERSION + "\n"); return 0; } @@ -912,26 +916,26 @@ main (int argc, char *argv[]) exit (1); } - /* DIRTY HACK needed to pick up -X supplied as part of ALSA driver args. This is legacy - hack to make control apps like qjackctl based on the < 0.124 command line interface - continue to work correctly. - - If -X seq was given as part of the driver args, load the ALSA MIDI slave driver. - */ - - for (i = seen_driver; i < argc; ++i) { - if (strcmp (argv[i], "-X") == 0) { - if (argc >= i + 2) { - if (strcmp (argv[i+1], "seq") == 0) { - slave_drivers = jack_slist_append (slave_drivers,"alsa_midi"); - } - } - break; - } else if (strcmp (argv[i], "-Xseq") == 0) { - slave_drivers = jack_slist_append (slave_drivers,"alsa_midi"); - break; - } - } + /* DIRTY HACK needed to pick up -X supplied as part of ALSA driver args. This is legacy + hack to make control apps like qjackctl based on the < 0.124 command line interface + continue to work correctly. + + If -X seq was given as part of the driver args, load the ALSA MIDI slave driver. + */ + + for (i = seen_driver; i < argc; ++i) { + if (strcmp (argv[i], "-X") == 0) { + if (argc >= i + 2) { + if (strcmp (argv[i + 1], "seq") == 0) { + slave_drivers = jack_slist_append (slave_drivers, "alsa_midi"); + } + } + break; + } else if (strcmp (argv[i], "-Xseq") == 0) { + slave_drivers = jack_slist_append (slave_drivers, "alsa_midi"); + break; + } + } drivers = jack_drivers_load (); @@ -939,7 +943,7 @@ main (int argc, char *argv[]) fprintf (stderr, "jackd: no drivers found; exiting\n"); exit (1); } - + if (midi_buffer_size != 0) { jack_port_type_info_t* port_type = &jack_builtin_port_types[JACK_MIDI_PORT_TYPE]; port_type->buffer_size = midi_buffer_size * jack_midi_internal_event_size (); @@ -967,20 +971,20 @@ main (int argc, char *argv[]) return -1; } - driver_args = (char **) malloc (sizeof (char *) * driver_nargs); + driver_args = (char**)malloc (sizeof(char *) * driver_nargs); driver_args[0] = driver_name; - - for (i = 1; i < driver_nargs; i++) { + + for (i = 1; i < driver_nargs; i++) driver_args[i] = argv[optind++]; - } if (jack_parse_driver_params (desc, driver_nargs, driver_args, &driver_params)) { exit (0); } - if (server_name == NULL) + if (server_name == NULL) { server_name = jack_default_server_name (); + } rc = jack_register_server (server_name, replace_registry); switch (rc) { @@ -994,9 +998,10 @@ main (int argc, char *argv[]) fprintf (stderr, "no access to shm registry\n"); exit (3); default: - if (verbose) + if (verbose) { fprintf (stderr, "server `%s' registered\n", server_name); + } } /* clean up shared memory and files from any previous @@ -1008,14 +1013,17 @@ main (int argc, char *argv[]) jack_main (desc, driver_params, slave_drivers, load_list); /* clean up shared memory and files from this server instance */ - if (verbose) + if (verbose) { fprintf (stderr, "cleaning up shared memory\n"); + } jack_cleanup_shm (); - if (verbose) + if (verbose) { fprintf (stderr, "cleaning up files\n"); + } jack_cleanup_files (server_name); - if (verbose) + if (verbose) { fprintf (stderr, "unregistering server `%s'\n", server_name); + } jack_unregister_server (server_name); exit (0); |