diff --git a/pipewire-pulseaudio/src/context.c b/pipewire-pulseaudio/src/context.c index 62238613b..d1056e478 100644 --- a/pipewire-pulseaudio/src/context.c +++ b/pipewire-pulseaudio/src/context.c @@ -142,7 +142,7 @@ struct global *pa_context_find_global_by_name(pa_context *c, uint32_t mask, cons (str = pw_properties_get(g->props, PW_KEY_NODE_NAME)) != NULL && strcmp(str, name) == 0) return g; - if (g->id == id) + if (g->id == id || (g->id == (id & PA_IDX_MASK_DSP))) return g; } return NULL; @@ -153,25 +153,26 @@ struct global *pa_context_find_linked(pa_context *c, uint32_t idx) struct global *g, *f; spa_list_for_each(g, &c->globals, link) { - if (strcmp(g->type, PW_TYPE_INTERFACE_EndpointLink) != 0) + uint32_t src_node_id, dst_node_id; + + if (strcmp(g->type, PW_TYPE_INTERFACE_Link) != 0) continue; - pw_log_debug("context %p: %p %d %d:%d %d:%d", c, g, idx, - g->link_info.output->id, g->link_info.output->endpoint_info.node_id, - g->link_info.input->id, g->link_info.input->endpoint_info.node_id); + src_node_id = g->link_info.src->port_info.node_id; + dst_node_id = g->link_info.dst->port_info.node_id; - if (g->link_info.input->id == idx || - g->link_info.input->endpoint_info.node_id == idx) - f = g->link_info.output; - else if (g->link_info.output->id == idx || - g->link_info.output->endpoint_info.node_id == idx) - f = g->link_info.input; + pw_log_debug("context %p: %p %d %d %d", c, g, idx, + src_node_id, dst_node_id); + + if (src_node_id == idx) + f = pa_context_find_global(c, dst_node_id); + else if (dst_node_id == idx) + f = pa_context_find_global(c, src_node_id); else continue; - if (f == NULL || ((f->mask & (PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SINK)) == 0)) + if (f == NULL) continue; - return f; } return NULL; @@ -185,6 +186,15 @@ static void emit_event(pa_context *c, struct global *g, pa_subscription_event_ty event | g->event, g->id, c->subscribe_userdata); + + if (g->mask == (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE)) { + pw_log_debug("context %p: obj %d: emit %d:%d", c, g->node_info.monitor, + event, PA_SUBSCRIPTION_EVENT_SOURCE); + c->subscribe_callback(c, + event | PA_SUBSCRIPTION_EVENT_SOURCE, + g->node_info.monitor, + c->subscribe_userdata); + } } } @@ -197,16 +207,15 @@ static void update_device_props(struct global *g) pa_proplist_sets(i->proplist, PA_PROP_DEVICE_ICON_NAME, s); } -static void device_event_info(void *object, const struct pw_device_info *update) +static void device_event_info(void *object, const struct pw_device_info *info) { struct global *g = object; pa_card_info *i = &g->card_info.info; const char *str; uint32_t n; - struct pw_device_info *info; - pw_log_debug("global %p: id:%d change-mask:%08lx", g, g->id, update->change_mask); - info = g->info = pw_device_info_update(g->info, update); + pw_log_debug("global %p: id:%d change-mask:%"PRIu64, g, g->id, info->change_mask); + info = g->info = pw_device_info_update(g->info, info); i->index = g->id; i->name = info->props ? @@ -224,8 +233,7 @@ static void device_event_info(void *object, const struct pw_device_info *update) } update_device_props(g); } - info->change_mask = update->change_mask; - if (update->change_mask & PW_DEVICE_CHANGE_MASK_PARAMS) { + if (info->change_mask & PW_DEVICE_CHANGE_MASK_PARAMS) { for (n = 0; n < info->n_params; n++) { if (!(info->params[n].flags & SPA_PARAM_INFO_READ)) continue; @@ -318,39 +326,20 @@ static void device_destroy(void *data) pw_device_info_free(global->info); } -static void endpoint_event_info(void *object, const struct pw_endpoint_info *update) +static void node_event_info(void *object, const struct pw_node_info *info) { struct global *g = object; - struct pw_endpoint_info *info = g->info; uint32_t i; - pw_log_debug("update %d %08x", g->id, update->change_mask); - if (info == NULL) { - info = g->info = calloc(1, sizeof(*info)); - info->id = update->id; - info->name = update->name ? strdup(update->name) : NULL; - info->media_class = update->media_class ? strdup(update->media_class) : NULL; - info->direction = update->direction; - info->flags = update->flags; - } - info->change_mask = update->change_mask; + pw_log_debug("update %d %"PRIu64, g->id, info->change_mask); + g->info = pw_node_info_update(g->info, info); - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_STREAMS) - info->n_streams = update->n_streams; - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_SESSION) - info->session_id = update->session_id; - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS && !g->subscribed) { + if (info->change_mask & PW_NODE_CHANGE_MASK_PARAMS && !g->subscribed) { uint32_t subscribed[32], n_subscribed = 0; - info->n_params = update->n_params; - free(info->params); - info->params = malloc(info->n_params * sizeof(struct spa_param_info)); - memcpy(info->params, update->params, - info->n_params * sizeof(struct spa_param_info)); - for (i = 0; i < info->n_params; i++) { switch (info->params[i].id) { - case SPA_PARAM_EnumRoute: + case SPA_PARAM_EnumFormat: case SPA_PARAM_Props: subscribed[n_subscribed++] = info->params[i].id; break; @@ -359,32 +348,11 @@ static void endpoint_event_info(void *object, const struct pw_endpoint_info *upd } } if (n_subscribed > 0) { - pw_endpoint_subscribe_params((struct pw_endpoint*)g->proxy, + pw_node_subscribe_params((struct pw_node*)g->proxy, subscribed, n_subscribed); g->subscribed = true; } } - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) { - if (info->props) - pw_properties_free ((struct pw_properties *)info->props); - info->props = - (struct spa_dict *) pw_properties_new_dict (update->props); - -#if 0 - i->name = info->props ? - spa_dict_lookup(info->props, PW_KEY_ENDPOINT_NAME) : "unknown"; - str = info->props ? spa_dict_lookup(info->props, PW_KEY_MODULE_ID) : NULL; - i->owner_module = str ? (unsigned)atoi(str) : SPA_ID_INVALID; - i->driver = info->props ? - spa_dict_lookup(info->props, PW_KEY_DEVICE_API) : "unknown"; - - if (i->proplist) - pa_proplist_update_dict(i->proplist, info->props); - else { - i->proplist = pa_proplist_new_dict(info->props); - } -#endif - } g->pending_seq = pw_proxy_sync(g->proxy, 0); } @@ -396,22 +364,22 @@ static void parse_props(struct global *g, const struct spa_pod *param) SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_volume: - spa_pod_get_float(&prop->value, &g->endpoint_info.volume); + spa_pod_get_float(&prop->value, &g->node_info.volume); break; case SPA_PROP_mute: - spa_pod_get_bool(&prop->value, &g->endpoint_info.mute); + spa_pod_get_bool(&prop->value, &g->node_info.mute); break; case SPA_PROP_channelVolumes: { uint32_t n_vals; n_vals = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - g->endpoint_info.channel_volumes, SPA_AUDIO_MAX_CHANNELS); + g->node_info.channel_volumes, SPA_AUDIO_MAX_CHANNELS); - if (n_vals != g->endpoint_info.n_channel_volumes) { + if (n_vals != g->node_info.n_channel_volumes) { emit_event(g->context, g, PA_SUBSCRIPTION_EVENT_REMOVE); emit_event(g->context, g, PA_SUBSCRIPTION_EVENT_NEW); - g->endpoint_info.n_channel_volumes = n_vals; + g->node_info.n_channel_volumes = n_vals; } break; } @@ -421,12 +389,7 @@ static void parse_props(struct global *g, const struct spa_pod *param) } } -/* routing information on the endpoint is mapped to sink/source ports. */ -static void parse_route(struct global *g, const struct spa_pod *param) -{ -} - -static void endpoint_event_param(void *object, int seq, +static void node_event_param(void *object, int seq, uint32_t id, uint32_t index, uint32_t next, const struct spa_pod *param) { @@ -437,31 +400,22 @@ static void endpoint_event_param(void *object, int seq, case SPA_PARAM_Props: parse_props(g, param); break; - case SPA_PARAM_EnumRoute: - parse_route(g, param); - break; default: break; } } -static const struct pw_endpoint_events endpoint_events = { - PW_VERSION_ENDPOINT_EVENTS, - .info = endpoint_event_info, - .param = endpoint_event_param, +static const struct pw_node_events node_events = { + PW_VERSION_NODE_EVENTS, + .info = node_event_info, + .param = node_event_param, }; -static void endpoint_destroy(void *data) +static void node_destroy(void *data) { struct global *global = data; - if (global->info) { - struct pw_endpoint_info *info = global->info; - free(info->name); - free(info->params); - if (info->props) - pw_properties_free ((struct pw_properties *)info->props); - free(info); - } + if (global->info) + pw_node_info_free(global->info); } static void module_event_info(void *object, const struct pw_module_info *info) @@ -574,8 +528,9 @@ static const struct pw_proxy_events proxy_events = { static int set_mask(pa_context *c, struct global *g) { const char *str; - const void *events = NULL; - pw_destroy_t destroy; + struct global *f; + const void *events = NULL; + pw_destroy_t destroy; uint32_t client_version; if (strcmp(g->type, PW_TYPE_INTERFACE_Device) == 0) { @@ -586,7 +541,6 @@ static int set_mask(pa_context *c, struct global *g) if (strcmp(str, "Audio/Device") != 0) return 0; - /* devices are turned into card objects */ pw_log_debug("found card %d", g->id); g->mask = PA_SUBSCRIPTION_MASK_CARD; g->event = PA_SUBSCRIPTION_EVENT_CARD; @@ -595,37 +549,28 @@ static int set_mask(pa_context *c, struct global *g) client_version = PW_VERSION_DEVICE; destroy = device_destroy; spa_list_init(&g->card_info.profiles); - } else if (strcmp(g->type, PW_TYPE_INTERFACE_Endpoint) == 0) { + } else if (strcmp(g->type, PW_TYPE_INTERFACE_Node) == 0) { if (g->props == NULL) return 0; - if ((str = pw_properties_get(g->props, PW_KEY_PRIORITY_SESSION)) != NULL) - g->priority_session = pw_properties_parse_int(str); + if ((str = pw_properties_get(g->props, PW_KEY_PRIORITY_MASTER)) != NULL) + g->priority_master = pw_properties_parse_int(str); if ((str = pw_properties_get(g->props, PW_KEY_MEDIA_CLASS)) == NULL) { - pw_log_warn("endpoint %d without "PW_KEY_MEDIA_CLASS, g->id); + pw_log_debug("node %d without "PW_KEY_MEDIA_CLASS, g->id); return 0; } - g->endpoint_info.monitor = SPA_ID_INVALID; - /* endpoints get transformed into sink/source or sink_input/source_output */ if (strcmp(str, "Audio/Sink") == 0) { pw_log_debug("found sink %d", g->id); - g->mask = PA_SUBSCRIPTION_MASK_SINK; + g->mask = PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE; g->event = PA_SUBSCRIPTION_EVENT_SINK; + g->node_info.monitor = g->id | PA_IDX_FLAG_DSP; } else if (strcmp(str, "Audio/Source") == 0) { pw_log_debug("found source %d", g->id); g->mask = PA_SUBSCRIPTION_MASK_SOURCE; g->event = PA_SUBSCRIPTION_EVENT_SOURCE; - if ((str = pw_properties_get(g->props, PW_KEY_ENDPOINT_MONITOR)) != NULL) { - struct global *f; - f = pa_context_find_global(c, pw_properties_parse_int(str)); - if (f != NULL) { - g->endpoint_info.monitor = f->id; - f->endpoint_info.monitor = g->id; - } - } } else if (strcmp(str, "Stream/Output/Audio") == 0) { pw_log_debug("found sink input %d", g->id); @@ -638,36 +583,26 @@ static int set_mask(pa_context *c, struct global *g) g->event = PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT; } - if ((str = pw_properties_get(g->props, PW_KEY_ENDPOINT_CLIENT_ID)) != NULL) - g->endpoint_info.client_id = atoi(str); - else if ((str = pw_properties_get(g->props, PW_KEY_CLIENT_ID)) != NULL) - g->endpoint_info.client_id = atoi(str); + if ((str = pw_properties_get(g->props, PW_KEY_CLIENT_ID)) != NULL) + g->node_info.client_id = atoi(str); if ((str = pw_properties_get(g->props, PW_KEY_DEVICE_ID)) != NULL) - g->endpoint_info.device_id = atoi(str); - if ((str = pw_properties_get(g->props, PW_KEY_NODE_ID)) != NULL) { - pa_stream *s; - g->endpoint_info.node_id = atoi(str); - spa_list_for_each(s, &c->streams, link) { - if (pw_stream_get_node_id(s->stream) == g->endpoint_info.node_id) - s->endpoint_id = g->id; - } - } + g->node_info.device_id = atoi(str); - events = &endpoint_events; - client_version = PW_VERSION_ENDPOINT; - destroy = endpoint_destroy; - g->endpoint_info.volume = 1.0; - g->endpoint_info.mute = false; - } else if (strcmp(g->type, PW_TYPE_INTERFACE_EndpointStream) == 0) { + events = &node_events; + client_version = PW_VERSION_NODE; + destroy = node_destroy; + g->node_info.volume = 1.0; + g->node_info.mute = false; + } else if (strcmp(g->type, PW_TYPE_INTERFACE_Port) == 0) { if (g->props == NULL) return 0; - if ((str = pw_properties_get(g->props, PW_KEY_ENDPOINT_ID)) == NULL) { - pw_log_warn("endpoint stream %d without "PW_KEY_ENDPOINT_ID, g->id); + if ((str = pw_properties_get(g->props, PW_KEY_NODE_ID)) == NULL) { + pw_log_warn("port %d without "PW_KEY_NODE_ID, g->id); return 0; } - /* streams get transformed into profiles on the device */ - pw_log_debug("found endpoint stream %d", g->id); + g->port_info.node_id = atoi(str); + pw_log_debug("found port %d node %d", g->id, g->port_info.node_id); } else if (strcmp(g->type, PW_TYPE_INTERFACE_Module) == 0) { pw_log_debug("found module %d", g->id); g->mask = PA_SUBSCRIPTION_MASK_MODULE; @@ -682,23 +617,29 @@ static int set_mask(pa_context *c, struct global *g) events = &client_events; client_version = PW_VERSION_CLIENT; destroy = client_destroy; - } else if (strcmp(g->type, PW_TYPE_INTERFACE_EndpointLink) == 0) { - if ((str = pw_properties_get(g->props, PW_KEY_ENDPOINT_LINK_OUTPUT_ENDPOINT)) == NULL) + } else if (strcmp(g->type, PW_TYPE_INTERFACE_Link) == 0) { + if ((str = pw_properties_get(g->props, PW_KEY_LINK_OUTPUT_PORT)) == NULL) return 0; - g->link_info.output = pa_context_find_global(c, pw_properties_parse_int(str)); - if ((str = pw_properties_get(g->props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT)) == NULL) + g->link_info.src = pa_context_find_global(c, pw_properties_parse_int(str)); + if ((str = pw_properties_get(g->props, PW_KEY_LINK_INPUT_PORT)) == NULL) return 0; - g->link_info.input = pa_context_find_global(c, pw_properties_parse_int(str)); + g->link_info.dst = pa_context_find_global(c, pw_properties_parse_int(str)); - if (g->link_info.output == NULL || g->link_info.input == NULL) + if (g->link_info.src == NULL || g->link_info.dst == NULL) return 0; - pw_log_debug("link %d->%d", g->link_info.output->id, g->link_info.input->id); + pw_log_debug("link %d:%d->%d:%d", + g->link_info.src->port_info.node_id, + g->link_info.src->id, + g->link_info.dst->port_info.node_id, + g->link_info.dst->id); - if (!g->link_info.output->init) - emit_event(c, g->link_info.output, PA_SUBSCRIPTION_EVENT_CHANGE); - if (!g->link_info.input->init) - emit_event(c, g->link_info.input, PA_SUBSCRIPTION_EVENT_CHANGE); + if ((f = pa_context_find_global(c, g->link_info.src->port_info.node_id)) != NULL && + !f->init) + emit_event(c, f, PA_SUBSCRIPTION_EVENT_CHANGE); + if ((f = pa_context_find_global(c, g->link_info.dst->port_info.node_id)) != NULL && + !f->init) + emit_event(c, f, PA_SUBSCRIPTION_EVENT_CHANGE); } else { return 0; @@ -729,11 +670,12 @@ static inline void insert_global(pa_context *c, struct global *global) struct global *g, *t; spa_list_for_each_safe(g, t, &c->globals, link) { - if (g->priority_session <= global->priority_session) { + if (g->priority_master < global->priority_master) { + g = spa_list_prev(g, link); break; } } - spa_list_append(&g->link, &global->link); + spa_list_prepend(&g->link, &global->link); } static void registry_event_global(void *data, uint32_t id, diff --git a/pipewire-pulseaudio/src/internal.h b/pipewire-pulseaudio/src/internal.h index da5060405..95831924e 100644 --- a/pipewire-pulseaudio/src/internal.h +++ b/pipewire-pulseaudio/src/internal.h @@ -34,7 +34,6 @@ #include #include -#include /* Some PulseAudio API added const qualifiers in 13.0 */ #if PA_MAJOR >= 13 @@ -216,6 +215,9 @@ struct param { void *param; }; +#define PA_IDX_FLAG_DSP 0x800000U +#define PA_IDX_MASK_DSP 0x7fffffU + struct global { struct spa_list link; uint32_t id; @@ -226,7 +228,7 @@ struct global { pa_subscription_mask_t mask; pa_subscription_event_type_t event; - int priority_session; + int priority_master; int pending_seq; int init:1; int subscribed:1; @@ -239,15 +241,12 @@ struct global { struct spa_hook object_listener; union { - /* for links, globals are endpoints */ + /* for links */ struct { - struct global *output; - struct global *input; + struct global *src; + struct global *dst; } link_info; - struct { - uint32_t endpoint_id; - } stream_info; - /* for endpoints */ + /* for sink/source */ struct { uint32_t client_id; uint32_t monitor; @@ -256,8 +255,10 @@ struct global { uint32_t n_channel_volumes; float channel_volumes[SPA_AUDIO_MAX_CHANNELS]; uint32_t device_id; + } node_info; + struct { uint32_t node_id; - } endpoint_info; + } port_info; /* for devices */ struct { struct spa_list profiles; @@ -341,7 +342,6 @@ struct pa_stream { pa_format_info *req_formats[PA_MAX_FORMATS]; pa_format_info *format; - uint32_t endpoint_id; uint32_t stream_index; pa_buffer_attr buffer_attr; diff --git a/pipewire-pulseaudio/src/introspect.c b/pipewire-pulseaudio/src/introspect.c index b449624fb..1151c6ef2 100644 --- a/pipewire-pulseaudio/src/introspect.c +++ b/pipewire-pulseaudio/src/introspect.c @@ -90,7 +90,7 @@ static int wait_globals(pa_context *c, pa_subscription_mask_t mask, pa_operation static void sink_callback(struct sink_data *d) { struct global *g = d->global; - struct pw_endpoint_info *info = g->info; + struct pw_node_info *info = g->info; const char *str; uint32_t n; pa_sink_info i; @@ -98,36 +98,31 @@ static void sink_callback(struct sink_data *d) pa_format_info *ip[1]; spa_zero(i); - if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_ENDPOINT_NAME))) + if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_NODE_NAME))) i.name = str; else i.name = "unknown"; - pw_log_debug("sink %d %s monitor %d", g->id, i.name, g->endpoint_info.monitor); + pw_log_debug("sink %d %s monitor %d", g->id, i.name, g->node_info.monitor); i.index = g->id; - if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_ENDPOINT_NAME))) + if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_NODE_DESCRIPTION))) i.description = str; else - i.description = "unknown"; + i.description = "Unknown"; i.sample_spec.format = PA_SAMPLE_S16LE; i.sample_spec.rate = 44100; - if (g->endpoint_info.n_channel_volumes) - i.sample_spec.channels = g->endpoint_info.n_channel_volumes; + if (g->node_info.n_channel_volumes) + i.sample_spec.channels = g->node_info.n_channel_volumes; else i.sample_spec.channels = 2; pa_channel_map_init_auto(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); i.owner_module = 0; i.volume.channels = i.sample_spec.channels; for (n = 0; n < i.volume.channels; n++) - i.volume.values[n] = g->endpoint_info.volume * g->endpoint_info.channel_volumes[n] * PA_VOLUME_NORM; - i.mute = g->endpoint_info.mute; - if (g->endpoint_info.monitor != SPA_ID_INVALID) { - i.monitor_source = g->endpoint_info.monitor; - i.monitor_source_name = "unknown"; - } else { - i.monitor_source = PA_INVALID_INDEX; - i.monitor_source_name = NULL; - } + i.volume.values[n] = g->node_info.volume * g->node_info.channel_volumes[n] * PA_VOLUME_NORM; + i.mute = g->node_info.mute; + i.monitor_source = g->node_info.monitor; + i.monitor_source_name = "unknown"; i.latency = 0; i.driver = "PipeWire"; i.flags = PA_SINK_HARDWARE | @@ -137,7 +132,7 @@ static void sink_callback(struct sink_data *d) i.proplist = pa_proplist_new_dict(info->props); i.configured_latency = 0; i.base_volume = PA_VOLUME_NORM; - //i.state = node_state_to_sink(info->state); + i.state = node_state_to_sink(info->state); i.n_volume_steps = PA_VOLUME_NORM+1; i.card = PA_INVALID_INDEX; i.n_ports = 0; @@ -288,7 +283,7 @@ static void set_stream_volume(pa_context *c, pa_stream *s, const pa_cvolume *vol } } -static void set_endpoint_volume(pa_context *c, struct global *g, const pa_cvolume *volume, bool mute) +static void set_node_volume(pa_context *c, struct global *g, const pa_cvolume *volume, bool mute) { char buf[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); @@ -302,22 +297,22 @@ static void set_endpoint_volume(pa_context *c, struct global *g, const pa_cvolum vols = channel_volumes; n_channel_volumes = volume->channels; - if (n_channel_volumes == g->endpoint_info.n_channel_volumes && - memcmp(g->endpoint_info.channel_volumes, vols, n_channel_volumes * sizeof(float)) == 0 && - mute == g->endpoint_info.mute) + if (n_channel_volumes == g->node_info.n_channel_volumes && + memcmp(g->node_info.channel_volumes, vols, n_channel_volumes * sizeof(float)) == 0 && + mute == g->node_info.mute) return; - memcpy(g->endpoint_info.channel_volumes, vols, n_channel_volumes * sizeof(float)); - g->endpoint_info.n_channel_volumes = n_channel_volumes; + memcpy(g->node_info.channel_volumes, vols, n_channel_volumes * sizeof(float)); + g->node_info.n_channel_volumes = n_channel_volumes; } else { - n_channel_volumes = g->endpoint_info.n_channel_volumes; - vols = g->endpoint_info.channel_volumes; - if (mute == g->endpoint_info.mute) + n_channel_volumes = g->node_info.n_channel_volumes; + vols = g->node_info.channel_volumes; + if (mute == g->node_info.mute) return; } - g->endpoint_info.mute = mute; + g->node_info.mute = mute; - pw_endpoint_set_param((struct pw_endpoint*)g->proxy, + pw_node_set_param((struct pw_node*)g->proxy, SPA_PARAM_Props, 0, spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, @@ -350,7 +345,7 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c if (!(g->mask & PA_SUBSCRIPTION_MASK_SINK)) return NULL; - set_endpoint_volume(c, g, volume, g->endpoint_info.mute); + set_node_volume(c, g, volume, g->node_info.mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -379,7 +374,7 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name if ((g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_SINK, name)) == NULL) return NULL; - set_endpoint_volume(c, g, volume, g->endpoint_info.mute); + set_node_volume(c, g, volume, g->node_info.mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -409,7 +404,7 @@ pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int if (!(g->mask & PA_SUBSCRIPTION_MASK_SINK)) return NULL; - set_endpoint_volume(c, g, NULL, mute); + set_node_volume(c, g, NULL, mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -437,7 +432,7 @@ pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, if ((g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_SINK, name)) == NULL) return NULL; - set_endpoint_volume(c, g, NULL, mute); + set_node_volume(c, g, NULL, mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -539,7 +534,7 @@ static pa_source_state_t node_state_to_source(enum pw_node_state s) static void source_callback(struct source_data *d) { struct global *g = d->global; - struct pw_endpoint_info *info = g->info; + struct pw_node_info *info = g->info; const char *str; uint32_t n; pa_source_info i; @@ -551,30 +546,31 @@ static void source_callback(struct source_data *d) PA_SOURCE_DECIBEL_VOLUME; spa_zero(i); - if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_ENDPOINT_NAME))) + if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_NODE_NAME))) i.name = str; else i.name = "unknown"; i.index = g->id; - if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_ENDPOINT_NAME))) + if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_NODE_DESCRIPTION))) i.description = str; else i.description = "unknown"; i.sample_spec.format = PA_SAMPLE_S16LE; i.sample_spec.rate = 44100; - if (g->endpoint_info.n_channel_volumes) - i.sample_spec.channels = g->endpoint_info.n_channel_volumes; + if (g->node_info.n_channel_volumes) + i.sample_spec.channels = g->node_info.n_channel_volumes; else i.sample_spec.channels = 2; pa_channel_map_init_auto(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); i.owner_module = 0; i.volume.channels = i.sample_spec.channels; for (n = 0; n < i.volume.channels; n++) - i.volume.values[n] = g->endpoint_info.volume * g->endpoint_info.channel_volumes[n] * PA_VOLUME_NORM; - i.mute = g->endpoint_info.mute; - if (g->endpoint_info.monitor != SPA_ID_INVALID) { - i.monitor_of_sink = g->endpoint_info.monitor; + i.volume.values[n] = g->node_info.volume * g->node_info.channel_volumes[n] * PA_VOLUME_NORM; + i.mute = g->node_info.mute; + if (g->mask & PA_SUBSCRIPTION_MASK_SINK) { + i.monitor_of_sink = g->id; i.monitor_of_sink_name = "unknown"; + i.index = g->node_info.monitor; } else { i.monitor_of_sink = PA_INVALID_INDEX; i.monitor_of_sink_name = NULL; @@ -586,7 +582,7 @@ static void source_callback(struct source_data *d) i.proplist = pa_proplist_new_dict(info->props); i.configured_latency = 0; i.base_volume = PA_VOLUME_NORM; - //i.state = node_state_to_source(info->state); + i.state = node_state_to_source(info->state); i.n_volume_steps = PA_VOLUME_NORM+1; i.card = PA_INVALID_INDEX; i.n_ports = 0; @@ -655,8 +651,10 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, p pw_log_debug("context %p: index %d", c, idx); - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE)) + if (((g = pa_context_find_global(c, idx)) == NULL || + !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE)) && + (((g = pa_context_find_global(c, idx & PA_IDX_MASK_DSP)) == NULL || + !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE)))) return NULL; o = pa_operation_new(c, NULL, source_info, sizeof(struct source_data)); @@ -731,7 +729,7 @@ pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, if (!(g->mask & PA_SUBSCRIPTION_MASK_SOURCE)) return NULL; - set_endpoint_volume(c, g, volume, g->endpoint_info.mute); + set_node_volume(c, g, volume, g->node_info.mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -760,7 +758,7 @@ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *na if ((g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_SOURCE, name)) == NULL) return NULL; - set_endpoint_volume(c, g, volume, g->endpoint_info.mute); + set_node_volume(c, g, volume, g->node_info.mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -790,7 +788,7 @@ pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, i if (!(g->mask & PA_SUBSCRIPTION_MASK_SOURCE)) return NULL; - set_endpoint_volume(c, g, NULL, mute); + set_node_volume(c, g, NULL, mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -818,7 +816,7 @@ pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name if ((g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_SOURCE, name)) == NULL) return NULL; - set_endpoint_volume(c, g, NULL, mute); + set_node_volume(c, g, NULL, mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -1483,8 +1481,8 @@ struct sink_input_data { static void sink_input_callback(struct sink_input_data *d) { struct global *g = d->global, *cl; - struct pw_endpoint_info *info = g->info; - const char *name; + struct pw_node_info *info = g->info; + const char *name = NULL; uint32_t n; pa_sink_input_info i; pa_format_info ii[1]; @@ -1493,24 +1491,24 @@ static void sink_input_callback(struct sink_input_data *d) if (info == NULL) return; - s = find_stream(d->context, g->endpoint_info.node_id); + s = find_stream(d->context, g->id); if (info->props) { if ((name = spa_dict_lookup(info->props, PW_KEY_MEDIA_NAME)) == NULL && (name = spa_dict_lookup(info->props, PW_KEY_APP_NAME)) == NULL && - (name = spa_dict_lookup(info->props, PW_KEY_ENDPOINT_NAME)) == NULL) - name = "unknown"; + (name = spa_dict_lookup(info->props, PW_KEY_NODE_NAME)) == NULL) + name = NULL; } - else + if (name == NULL) name = "unknown"; - cl = pa_context_find_global(d->context, g->endpoint_info.client_id); + cl = pa_context_find_global(d->context, g->node_info.client_id); spa_zero(i); i.index = g->id; i.name = name; i.owner_module = PA_INVALID_INDEX; - i.client = g->endpoint_info.client_id; + i.client = g->node_info.client_id; if (s) { i.sink = s->device_index; } @@ -1531,7 +1529,7 @@ static void sink_input_callback(struct sink_input_data *d) else { i.sample_spec.format = PA_SAMPLE_S16LE; i.sample_spec.rate = 44100; - i.sample_spec.channels = g->endpoint_info.n_channel_volumes; + i.sample_spec.channels = g->node_info.n_channel_volumes; if (i.sample_spec.channels == 0) i.sample_spec.channels = 2; pa_channel_map_init_auto(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); @@ -1542,9 +1540,9 @@ static void sink_input_callback(struct sink_input_data *d) pa_cvolume_init(&i.volume); i.volume.channels = i.sample_spec.channels; for (n = 0; n < i.volume.channels; n++) - i.volume.values[n] = g->endpoint_info.volume * g->endpoint_info.channel_volumes[n] * PA_VOLUME_NORM; + i.volume.values[n] = g->node_info.volume * g->node_info.channel_volumes[n] * PA_VOLUME_NORM; - i.mute = g->endpoint_info.mute; + i.mute = g->node_info.mute; i.buffer_usec = 0; i.sink_usec = 0; i.resample_method = "PipeWire resampler"; @@ -1699,7 +1697,7 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons set_stream_volume(c, s, volume, s->mute); } else if (g) { - set_endpoint_volume(c, g, volume, g->endpoint_info.mute); + set_node_volume(c, g, volume, g->node_info.mute); } o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -1731,7 +1729,7 @@ pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mu set_stream_volume(c, s, NULL, mute); } else if (g) { - set_endpoint_volume(c, g, NULL, mute); + set_node_volume(c, g, NULL, mute); } o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -1782,7 +1780,7 @@ struct source_output_data { static void source_output_callback(struct source_output_data *d) { struct global *g = d->global, *l, *cl; - struct pw_endpoint_info *info = g->info; + struct pw_node_info *info = g->info; const char *name = NULL; uint32_t n; pa_source_output_info i; @@ -1793,25 +1791,24 @@ static void source_output_callback(struct source_output_data *d) if (info == NULL) return; - s = find_stream(d->context, g->endpoint_info.node_id); + s = find_stream(d->context, g->id); - name = info->name; - if (name == NULL && info->props) { + if (info->props) { if ((name = spa_dict_lookup(info->props, PW_KEY_MEDIA_NAME)) == NULL && (name = spa_dict_lookup(info->props, PW_KEY_APP_NAME)) == NULL && - (name = spa_dict_lookup(info->props, PW_KEY_ENDPOINT_NAME)) == NULL) + (name = spa_dict_lookup(info->props, PW_KEY_NODE_NAME)) == NULL) name = NULL; } if (name == NULL) name = "unknown"; - cl = pa_context_find_global(d->context, g->endpoint_info.client_id); + cl = pa_context_find_global(d->context, g->node_info.client_id); spa_zero(i); i.index = g->id; - i.name = name ? name : "Unknown"; + i.name = name; i.owner_module = PA_INVALID_INDEX; - i.client = g->endpoint_info.client_id; + i.client = g->node_info.client_id; if (s) { i.source = s->device_index; } @@ -1831,7 +1828,7 @@ static void source_output_callback(struct source_output_data *d) else { i.sample_spec.format = PA_SAMPLE_S16LE; i.sample_spec.rate = 44100; - i.sample_spec.channels = g->endpoint_info.n_channel_volumes; + i.sample_spec.channels = g->node_info.n_channel_volumes; if (i.sample_spec.channels == 0) i.sample_spec.channels = 2; pa_channel_map_init_auto(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); @@ -1842,9 +1839,9 @@ static void source_output_callback(struct source_output_data *d) pa_cvolume_init(&i.volume); i.volume.channels = i.sample_spec.channels; for (n = 0; n < i.volume.channels; n++) - i.volume.values[n] = g->endpoint_info.volume * g->endpoint_info.channel_volumes[n] * PA_VOLUME_NORM; + i.volume.values[n] = g->node_info.volume * g->node_info.channel_volumes[n] * PA_VOLUME_NORM; - i.mute = g->endpoint_info.mute; + i.mute = g->node_info.mute; i.buffer_usec = 0; i.source_usec = 0; i.resample_method = "PipeWire resampler"; @@ -1994,7 +1991,7 @@ pa_operation* pa_context_set_source_output_volume(pa_context *c, uint32_t idx, c set_stream_volume(c, s, volume, s->mute); } else if (g) { - set_endpoint_volume(c, g, volume, g->endpoint_info.mute); + set_node_volume(c, g, volume, g->node_info.mute); } o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -2024,7 +2021,7 @@ pa_operation* pa_context_set_source_output_mute(pa_context *c, uint32_t idx, int set_stream_volume(c, s, NULL, mute); } else if (g) { - set_endpoint_volume(c, g, NULL, mute); + set_node_volume(c, g, NULL, mute); } o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; diff --git a/pipewire-pulseaudio/src/stream.c b/pipewire-pulseaudio/src/stream.c index 929abc633..2173834ba 100644 --- a/pipewire-pulseaudio/src/stream.c +++ b/pipewire-pulseaudio/src/stream.c @@ -200,7 +200,7 @@ static void configure_device(pa_stream *s) else { if (s->direction == PA_STREAM_RECORD) { if (g->mask == (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE)) - s->device_index = g->endpoint_info.monitor; + s->device_index = g->node_info.monitor; else s->device_index = g->id; } @@ -208,7 +208,7 @@ static void configure_device(pa_stream *s) s->device_index = g->id; } - if ((str = pw_properties_get(g->props, PW_KEY_ENDPOINT_NAME)) == NULL) + if ((str = pw_properties_get(g->props, PW_KEY_NODE_NAME)) == NULL) s->device_name = strdup("unknown"); else s->device_name = strdup(str); @@ -565,7 +565,6 @@ static pa_stream* stream_new(pa_context *c, const char *name, s->context = c; spa_list_init(&s->pending); - s->endpoint_id = SPA_ID_INVALID; s->direction = PA_STREAM_NODIRECTION; s->state = PA_STREAM_UNCONNECTED; s->flags = 0; @@ -737,10 +736,8 @@ uint32_t pa_stream_get_index(PA_CONST pa_stream *s) spa_assert(s); spa_assert(s->refcount >= 1); - if (s->endpoint_id != SPA_ID_INVALID) - idx = s->endpoint_id; - else - idx = pw_stream_get_node_id(s->stream); + + idx = pw_stream_get_node_id(s->stream); pw_log_debug("stream %p: index %u", s, idx); return idx; }