mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	jackdbus-detect: Passthrough more arguments to sink and source
module-jackdbus-detect now accepts sink_name, sink_properties, sink_client_name, sink_channel_map, source_name, source_properties, source_client_name, and source_channel_map arguments that will be passed through to module-jack-source and module-jack-sink (without the sink and source prefixes, except where needed).
This commit is contained in:
		
							parent
							
								
									a17d00c3d2
								
							
						
					
					
						commit
						8342c12339
					
				
					 1 changed files with 148 additions and 21 deletions
				
			
		| 
						 | 
					@ -25,12 +25,14 @@
 | 
				
			||||||
#include <config.h>
 | 
					#include <config.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <pulse/proplist.h>
 | 
				
			||||||
#include <pulse/xmalloc.h>
 | 
					#include <pulse/xmalloc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <pulsecore/log.h>
 | 
					#include <pulsecore/log.h>
 | 
				
			||||||
#include <pulsecore/modargs.h>
 | 
					#include <pulsecore/modargs.h>
 | 
				
			||||||
#include <pulsecore/core-util.h>
 | 
					#include <pulsecore/core-util.h>
 | 
				
			||||||
#include <pulsecore/dbus-shared.h>
 | 
					#include <pulsecore/dbus-shared.h>
 | 
				
			||||||
 | 
					#include <pulsecore/strbuf.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PA_MODULE_AUTHOR("David Henningsson");
 | 
					PA_MODULE_AUTHOR("David Henningsson");
 | 
				
			||||||
PA_MODULE_DESCRIPTION("Adds JACK sink/source ports when JACK is started");
 | 
					PA_MODULE_DESCRIPTION("Adds JACK sink/source ports when JACK is started");
 | 
				
			||||||
| 
						 | 
					@ -38,8 +40,16 @@ PA_MODULE_LOAD_ONCE(true);
 | 
				
			||||||
PA_MODULE_VERSION(PACKAGE_VERSION);
 | 
					PA_MODULE_VERSION(PACKAGE_VERSION);
 | 
				
			||||||
PA_MODULE_USAGE(
 | 
					PA_MODULE_USAGE(
 | 
				
			||||||
    "channels=<number of channels> "
 | 
					    "channels=<number of channels> "
 | 
				
			||||||
    "source_channels=<number of channels> "
 | 
					    "sink_name=<name for the sink> "
 | 
				
			||||||
 | 
					    "sink_properties=<properties for the card> "
 | 
				
			||||||
 | 
					    "sink_client_name=<jack client name> "
 | 
				
			||||||
    "sink_channels=<number of channels> "
 | 
					    "sink_channels=<number of channels> "
 | 
				
			||||||
 | 
					    "sink_channel_map=<channel map> "
 | 
				
			||||||
 | 
					    "source_name=<name for the source> "
 | 
				
			||||||
 | 
					    "source_properties=<properties for the source> "
 | 
				
			||||||
 | 
					    "source_client_name=<jack client name> "
 | 
				
			||||||
 | 
					    "source_channels=<number of channels> "
 | 
				
			||||||
 | 
					    "source_channel_map=<channel map> "
 | 
				
			||||||
    "connect=<connect ports?>");
 | 
					    "connect=<connect ports?>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define JACK_SERVICE_NAME "org.jackaudio.service"
 | 
					#define JACK_SERVICE_NAME "org.jackaudio.service"
 | 
				
			||||||
| 
						 | 
					@ -61,8 +71,16 @@ PA_MODULE_USAGE(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char* const valid_modargs[] = {
 | 
					static const char* const valid_modargs[] = {
 | 
				
			||||||
    "channels",
 | 
					    "channels",
 | 
				
			||||||
    "source_channels",
 | 
					    "sink_name",
 | 
				
			||||||
 | 
					    "sink_properties",
 | 
				
			||||||
 | 
					    "sink_client_name",
 | 
				
			||||||
    "sink_channels",
 | 
					    "sink_channels",
 | 
				
			||||||
 | 
					    "sink_channel_map",
 | 
				
			||||||
 | 
					    "source_name",
 | 
				
			||||||
 | 
					    "source_properties",
 | 
				
			||||||
 | 
					    "source_client_name",
 | 
				
			||||||
 | 
					    "source_channels",
 | 
				
			||||||
 | 
					    "source_channel_map",
 | 
				
			||||||
    "connect",
 | 
					    "connect",
 | 
				
			||||||
    NULL
 | 
					    NULL
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -76,6 +94,19 @@ static const char* const modnames[JACK_SS_COUNT] = {
 | 
				
			||||||
    "module-jack-source"
 | 
					    "module-jack-source"
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char* const modtypes[JACK_SS_COUNT] = {
 | 
				
			||||||
 | 
					    "sink",
 | 
				
			||||||
 | 
					    "source"
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct moddata {
 | 
				
			||||||
 | 
					    char *name;
 | 
				
			||||||
 | 
					    pa_proplist *proplist;
 | 
				
			||||||
 | 
					    char *client_name;
 | 
				
			||||||
 | 
					    uint32_t channels;
 | 
				
			||||||
 | 
					    pa_channel_map channel_map;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct userdata {
 | 
					struct userdata {
 | 
				
			||||||
    pa_module *module;
 | 
					    pa_module *module;
 | 
				
			||||||
    pa_core *core;
 | 
					    pa_core *core;
 | 
				
			||||||
| 
						 | 
					@ -83,13 +114,13 @@ struct userdata {
 | 
				
			||||||
    bool filter_added, match_added;
 | 
					    bool filter_added, match_added;
 | 
				
			||||||
    bool is_service_started;
 | 
					    bool is_service_started;
 | 
				
			||||||
    bool autoconnect_ports;
 | 
					    bool autoconnect_ports;
 | 
				
			||||||
    uint32_t channels[JACK_SS_COUNT];
 | 
					    struct moddata mod_args[JACK_SS_COUNT];
 | 
				
			||||||
    /* Using index here protects us from module unloading without us knowing */
 | 
					    /* Using index here protects us from module unloading without us knowing */
 | 
				
			||||||
    int jack_module_index[JACK_SS_COUNT];
 | 
					    int jack_module_index[JACK_SS_COUNT];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ensure_ports_stopped(struct userdata* u) {
 | 
					static void ensure_ports_stopped(struct userdata* u) {
 | 
				
			||||||
    int i;
 | 
					    unsigned i;
 | 
				
			||||||
    pa_assert(u);
 | 
					    pa_assert(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < JACK_SS_COUNT; i++)
 | 
					    for (i = 0; i < JACK_SS_COUNT; i++)
 | 
				
			||||||
| 
						 | 
					@ -100,19 +131,81 @@ static void ensure_ports_stopped(struct userdata* u) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char* proplist_to_arg(pa_proplist *p) {
 | 
				
			||||||
 | 
					    const char *key;
 | 
				
			||||||
 | 
					    void *state = NULL;
 | 
				
			||||||
 | 
					    pa_strbuf *buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    buf = pa_strbuf_new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while ((key = pa_proplist_iterate(p, &state))) {
 | 
				
			||||||
 | 
					        const char *v;
 | 
				
			||||||
 | 
					        char *escaped;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!pa_strbuf_isempty(buf))
 | 
				
			||||||
 | 
					            pa_strbuf_puts(buf, " ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((v = pa_proplist_gets(p, key))) {
 | 
				
			||||||
 | 
					            pa_strbuf_printf(buf, "%s=\"", key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            escaped = pa_escape(v, "\"'");
 | 
				
			||||||
 | 
					            pa_strbuf_puts(buf, escaped);
 | 
				
			||||||
 | 
					            pa_xfree(escaped);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pa_strbuf_puts(buf, "\"");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            const void *value;
 | 
				
			||||||
 | 
					            size_t nbytes;
 | 
				
			||||||
 | 
					            char *c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pa_assert_se(pa_proplist_get(p, key, &value, &nbytes) == 0);
 | 
				
			||||||
 | 
					            c = pa_xmalloc(nbytes*2+1);
 | 
				
			||||||
 | 
					            pa_hexstr((const uint8_t*) value, nbytes, c, nbytes*2+1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pa_strbuf_printf(buf, "%s=hex:%s", key, c);
 | 
				
			||||||
 | 
					            pa_xfree(c);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return pa_strbuf_to_string_free(buf);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ensure_ports_started(struct userdata* u) {
 | 
					static void ensure_ports_started(struct userdata* u) {
 | 
				
			||||||
    int i;
 | 
					    unsigned i;
 | 
				
			||||||
 | 
					    char *escaped;
 | 
				
			||||||
    pa_assert(u);
 | 
					    pa_assert(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < JACK_SS_COUNT; i++)
 | 
					    for (i = 0; i < JACK_SS_COUNT; i++)
 | 
				
			||||||
        if (!u->jack_module_index[i]) {
 | 
					        if (!u->jack_module_index[i]) {
 | 
				
			||||||
            char* args;
 | 
					            pa_strbuf *args_buf = pa_strbuf_new();
 | 
				
			||||||
            pa_module* m;
 | 
					            char *args;
 | 
				
			||||||
            if (u->channels[i] > 0) {
 | 
					            pa_module *m;
 | 
				
			||||||
                args = pa_sprintf_malloc("connect=%s channels=%" PRIu32, pa_yes_no(u->autoconnect_ports), u->channels[i]);
 | 
					            pa_strbuf_printf(args_buf, "connect=%s", pa_yes_no(u->autoconnect_ports));
 | 
				
			||||||
            } else {
 | 
					            if (u->mod_args[i].name) {
 | 
				
			||||||
                args = pa_sprintf_malloc("connect=%s", pa_yes_no(u->autoconnect_ports));
 | 
					                escaped = pa_escape(u->mod_args[i].name, "'");
 | 
				
			||||||
 | 
					                pa_strbuf_printf(args_buf, " %s_name='%s'", modtypes[i], escaped);
 | 
				
			||||||
 | 
					                pa_xfree(escaped);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if (!pa_proplist_isempty(u->mod_args[i].proplist)) {
 | 
				
			||||||
 | 
					                escaped = proplist_to_arg(u->mod_args[i].proplist);
 | 
				
			||||||
 | 
					                pa_strbuf_printf(args_buf, " %s_properties='%s'", modtypes[i], escaped);
 | 
				
			||||||
 | 
					                pa_xfree(escaped);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (u->mod_args[i].client_name) {
 | 
				
			||||||
 | 
					                escaped = pa_escape(u->mod_args[i].client_name, "'");
 | 
				
			||||||
 | 
					                pa_strbuf_printf(args_buf, " client_name='%s'", escaped);
 | 
				
			||||||
 | 
					                pa_xfree(escaped);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (u->mod_args[i].channels > 0)
 | 
				
			||||||
 | 
					                pa_strbuf_printf(args_buf, " channels=%" PRIu32, u->mod_args[i].channels);
 | 
				
			||||||
 | 
					            if (u->mod_args[i].channel_map.channels > 0) {
 | 
				
			||||||
 | 
					                char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
 | 
				
			||||||
 | 
					                pa_channel_map_snprint(cm, sizeof(cm), &u->mod_args[i].channel_map);
 | 
				
			||||||
 | 
					                pa_strbuf_printf(args_buf, " channel_map='%s'", cm);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            args = pa_strbuf_to_string_free(args_buf);
 | 
				
			||||||
            pa_module_load(&m, u->core, modnames[i], args);
 | 
					            pa_module_load(&m, u->core, modnames[i], args);
 | 
				
			||||||
            pa_xfree(args);
 | 
					            pa_xfree(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -218,7 +311,9 @@ int pa__init(pa_module *m) {
 | 
				
			||||||
    struct userdata *u = NULL;
 | 
					    struct userdata *u = NULL;
 | 
				
			||||||
    pa_modargs *ma;
 | 
					    pa_modargs *ma;
 | 
				
			||||||
    uint32_t channels = 0;
 | 
					    uint32_t channels = 0;
 | 
				
			||||||
    int i;
 | 
					    unsigned i;
 | 
				
			||||||
 | 
					    char argname[32];
 | 
				
			||||||
 | 
					    const char *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(m);
 | 
					    pa_assert(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -243,20 +338,42 @@ int pa__init(pa_module *m) {
 | 
				
			||||||
        pa_log("Failed to parse channels= argument.");
 | 
					        pa_log("Failed to parse channels= argument.");
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < JACK_SS_COUNT; i++) {
 | 
					    for (i = 0; i < JACK_SS_COUNT; i++) {
 | 
				
			||||||
        u->channels[i] = channels;
 | 
					        pa_snprintf(argname, sizeof(argname), "%s_name", modtypes[i]);
 | 
				
			||||||
    }
 | 
					        name = pa_modargs_get_value(ma, argname, NULL);
 | 
				
			||||||
 | 
					        u->mod_args[i].name = pa_xstrdup(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (pa_modargs_get_value_u32(ma, "source_channels", &u->channels[JACK_SS_SOURCE]) < 0 || (u->channels[JACK_SS_SOURCE] > 0 && !pa_channels_valid(u->channels[JACK_SS_SOURCE]))) {
 | 
					        u->mod_args[i].proplist = pa_proplist_new();
 | 
				
			||||||
        pa_log("Failed to parse source_channels= argument.");
 | 
					        pa_snprintf(argname, sizeof(argname), "%s_properties", modtypes[i]);
 | 
				
			||||||
 | 
					        if (pa_modargs_get_proplist(ma, argname, u->mod_args[i].proplist, PA_UPDATE_REPLACE) < 0) {
 | 
				
			||||||
 | 
					            pa_log("Invalid %s properties", modtypes[i]);
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (pa_modargs_get_value_u32(ma, "sink_channels", &u->channels[JACK_SS_SINK]) < 0 || (u->channels[JACK_SS_SINK] > 0 && !pa_channels_valid(u->channels[JACK_SS_SINK]))) {
 | 
					        pa_snprintf(argname, sizeof(argname), "%s_client_name", modtypes[i]);
 | 
				
			||||||
        pa_log("Failed to parse sink_channels= argument.");
 | 
					        name = pa_modargs_get_value(ma, argname, NULL);
 | 
				
			||||||
 | 
					        u->mod_args[i].client_name = pa_xstrdup(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        u->mod_args[i].channels = channels;
 | 
				
			||||||
 | 
					        pa_snprintf(argname, sizeof(argname), "%s_channels", modtypes[i]);
 | 
				
			||||||
 | 
					        if (pa_modargs_get_value_u32(ma, argname, &u->mod_args[i].channels) < 0
 | 
				
			||||||
 | 
					                || (u->mod_args[i].channels > 0 && !pa_channels_valid(u->mod_args[i].channels))) {
 | 
				
			||||||
 | 
					            pa_log("Failed to parse %s= argument.", argname);
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pa_channel_map_init(&u->mod_args[i].channel_map);
 | 
				
			||||||
 | 
					        pa_snprintf(argname, sizeof(argname), "%s_channel_map", modtypes[i]);
 | 
				
			||||||
 | 
					        if (pa_modargs_get_value(ma, argname, NULL)) {
 | 
				
			||||||
 | 
					            if (pa_modargs_get_channel_map(ma, argname, &u->mod_args[i].channel_map) < 0
 | 
				
			||||||
 | 
					                    || (u->mod_args[i].channels > 0 && u->mod_args[i].channel_map.channels != u->mod_args[i].channels)) {
 | 
				
			||||||
 | 
					                pa_log("Failed to parse %s= argument.", argname);
 | 
				
			||||||
 | 
					                goto fail;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!(connection = pa_dbus_bus_get(m->core, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
 | 
					    if (!(connection = pa_dbus_bus_get(m->core, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (connection)
 | 
					        if (connection)
 | 
				
			||||||
| 
						 | 
					@ -298,6 +415,7 @@ fail:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa__done(pa_module *m) {
 | 
					void pa__done(pa_module *m) {
 | 
				
			||||||
    struct userdata *u;
 | 
					    struct userdata *u;
 | 
				
			||||||
 | 
					    unsigned i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(m);
 | 
					    pa_assert(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,5 +438,14 @@ void pa__done(pa_module *m) {
 | 
				
			||||||
        pa_dbus_connection_unref(u->connection);
 | 
					        pa_dbus_connection_unref(u->connection);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < JACK_SS_COUNT; i++) {
 | 
				
			||||||
 | 
					        pa_xfree(u->mod_args[i].name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (u->mod_args[i].proplist)
 | 
				
			||||||
 | 
					            pa_proplist_free(u->mod_args[i].proplist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pa_xfree(u->mod_args[i].client_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_xfree(u);
 | 
					    pa_xfree(u);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue