diff options
-rw-r--r-- | jackd/jackd.1.in | 40 | ||||
-rw-r--r-- | jackd/jackd.c | 157 |
2 files changed, 136 insertions, 61 deletions
diff --git a/jackd/jackd.1.in b/jackd/jackd.1.in index 4f406c0..9b8c757 100644 --- a/jackd/jackd.1.in +++ b/jackd/jackd.1.in @@ -30,7 +30,6 @@ Select the audio interface backend. The current list of supported backends is: \fBalsa\fR, \fBcoreaudio\fR, \fBdummy\fR, \fBfreebob\fR, \fBoss\fR \fBsun\fR and \fBportaudio\fR. They are not all available on all platforms. All \fIbackend\-parameters\fR are optional. - .TP \fB\-h, \-\-help\fR .br @@ -42,6 +41,41 @@ show how to list them. \fB\-m, \-\-no\-mlock\fR Do not attempt to lock memory, even if \fB\-\-realtime\fR. .TP +\fB\-A \fIdevice\fR, \fB\-A \fIdevice%p\fR, \fB\-A \fIdevice%c\fR +.br +(Linux-only) A simplified way to add additional audio I/O hardware to an instance +of JACK. This argument is actually just a wrapper around the -I +(internal client) version, requiring only the name of the ALSA "card" +to be used. The name should \fBNOT\fR include any ALSA device access +prefix (e.g. "hw:" or "plughw:") but can include a +subdevice. If %p is added to the device name, it will be made +available for playback only. If %c is added to the device name, it +will be made available for capture (recording) only. If neither %p nor +%c is added, it will be made available (if possible) for both capture +and playback. Although device names may be visible in various places +on your system, the file /proc/asound/cards shows them inside square +braces. +.br +Examples: +.br +-A SB (adds playback and capture for the "SB" device) +.br +-A Codec,1%c (adds capture (recording) for the 2nd subdevice of the "Codec" device) +.br +-A MT1a2%p (adds playback the 1st subdevice of the "MT1a2" device) +.br +The use of -A CARD is actually equivalent to -I foo:zalsa_in/-dhw:CARD +\fIand\fR -I CARD:zalsa_out/-dhw:CARD. +.br +The use of -A CARD%p is actually equivalent to -I CARD:zalsa_out/-dhw:CARD. +.br +The use of -A CARD%c is actually equivalent to -I CARD:zalsa_in/-dhw:CARD +.br +.br +Note that this option (like -I) can be used regardless of the backend +used, so even if you do not use the ALSA backend, you can still add +ALSA-supported devices to an instance of JACK. +.TP \fB\-I, \-\-internal-client \fIclient-spec\fR .br Load \fIclient-name\fR as an internal client. May be used multiple @@ -49,9 +83,9 @@ times. The form of \fIclient-spec\fR can be any of the following: .br client-path .br -client-name/client-path +client-name:client-path .br -client-name/client-path/init-string +client-name:client-path/init-string .br client-path/init-string .br diff --git a/jackd/jackd.c b/jackd/jackd.c index ee3af43..0aab9e1 100644 --- a/jackd/jackd.c +++ b/jackd/jackd.c @@ -100,72 +100,112 @@ jack_load_internal_clients (JSList* load_list) char* str = (char*) node->data; jack_request_t req; + char* colon = strchr (str, ':'); char* slash = strchr (str, '/'); - char* sslash; - char* client_name; - char* path; + char* client_name = NULL; + char* path = NULL; char* args = NULL; char* rest = NULL; + int free_path = 0; + int free_name = 0; + size_t len; - /* parse each argument/load_list member for the form foo,arg-list - and split it apart if the slash is there. - */ + /* possible argument forms: - if (slash == NULL) { - /* path (also client name) */ - client_name = str; - path = client_name; - } else { - /* we want to copy the text up to the slash, not - including the slash. - */ - size_t len = slash - str; - /* add 1 to leave space for a NULL */ - client_name = (char*) malloc (len + 1); - memcpy (client_name, str, len); - client_name[len] = '\0'; + client-name:client-type/args + client-type/args + client-name:client-type + client-type - /* is there another slash ? */ + 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 + */ - sslash = strchr (slash+1, '/'); + if ((slash == NULL && colon == NULL) || (slash && colon && colon > slash)) { - if (sslash) { + /* client-type */ - /* client-name/path/args */ - - len = sslash - (slash+1); - - if (len) { - /* add 1 to leave space for a NULL */ - path = (char*) malloc (len + 1); - memcpy (path, slash + 1, len); - path[len] = '\0'; - } else { - path = client_name; - } + client_name = str; + path = client_name; + + } else if (slash && colon) { + + /* client-name:client-type/args */ - rest = sslash + 1; + 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 { - /* client-name/path */ - path = slash + 1; + 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) { - /* we want to skip the text before the slash (len) - * plus the slash itself - */ + /* client-type/args */ - if (rest) { + len = slash - str; - len = strlen (rest); + 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'; - } + 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)); @@ -184,17 +224,18 @@ jack_load_internal_clients (JSList* load_list) jack_intclient_load_request (engine, &req); pthread_mutex_unlock (&engine->request_lock); - if (slash) { + if (free_name) { free (client_name); - if (args) { - free (args); - } + } + if (free_path) { + free (path); + } + if (args) { + free (args); } } } - - static int jack_main (jack_driver_desc_t * driver_desc, JSList * driver_params, JSList * slave_names, JSList * load_list) { @@ -721,24 +762,24 @@ main (int argc, char *argv[]) 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", + 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", + 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", + 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", + snprintf (alsa_add_args, sizeof (alsa_add_args), "%s_rec:%s/-dhw:%s", optarg, alsa_add_client_name_capture, optarg); |