From d4cf47ec558a0404bcc8c266dcab0c08cd5982ec Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 18 Mar 2019 16:11:23 +0100 Subject: [PATCH] context: use subscribe params Improve volume setting --- src/context.c | 15 +++++--- src/internal.h | 3 +- src/introspect.c | 98 ++++++++++++++++++++++++++---------------------- 3 files changed, 64 insertions(+), 52 deletions(-) diff --git a/src/context.c b/src/context.c index d1fe8dfab..c9772af11 100644 --- a/src/context.c +++ b/src/context.c @@ -310,21 +310,24 @@ static void node_event_info(void *object, const struct pw_node_info *info) pw_log_debug("update %d %"PRIu64, g->id, info->change_mask); g->info = pw_node_info_update(g->info, info); - if (info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) { - for (i = 0; i < info->n_params; i++) { - if (!(info->params[i].flags & SPA_PARAM_INFO_READ)) - continue; + if (info->change_mask & PW_NODE_CHANGE_MASK_PARAMS && !g->subscribed) { + uint32_t subscribed[32], n_subscribed = 0; + for (i = 0; i < info->n_params; i++) { switch (info->params[i].id) { case SPA_PARAM_EnumFormat: case SPA_PARAM_Props: - pw_node_proxy_enum_params((struct pw_node_proxy*)g->proxy, - 0, info->params[i].id, 0, -1, NULL); + subscribed[n_subscribed++] = info->params[i].id; break; default: break; } } + if (n_subscribed > 0) { + pw_node_proxy_subscribe_params((struct pw_node_proxy*)g->proxy, + subscribed, n_subscribed); + g->subscribed = true; + } } g->pending_seq = pw_proxy_sync(g->proxy, 0); } diff --git a/src/internal.h b/src/internal.h index 99fbcee21..2b57638ef 100644 --- a/src/internal.h +++ b/src/internal.h @@ -219,7 +219,6 @@ struct global { uint32_t id; uint32_t parent_id; uint32_t type; - int init:1; struct pw_properties *props; pa_context *context; @@ -227,6 +226,8 @@ struct global { pa_subscription_event_type_t event; int pending_seq; + int init:1; + int subscribed:1; void *info; pw_destroy_t destroy; diff --git a/src/introspect.c b/src/introspect.c index 0b78ca23f..cd8a411da 100644 --- a/src/introspect.c +++ b/src/introspect.c @@ -243,46 +243,43 @@ pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, return o; } -static void set_stream_volume(pa_context *c, pa_stream *s) +static void set_stream_volume(pa_context *c, pa_stream *s, float volume, bool mute) { - float v = s->mute ? 0.0f : s->volume; - pw_stream_set_control(s->stream, SPA_PROP_volume, v); + if (s->volume != volume || s->mute != mute) { + s->volume = volume; + s->mute = mute; + + pw_stream_set_control(s->stream, + SPA_PROP_volume, s->volume, + SPA_PROP_mute, s->mute ? 1.0f : 0.0f, + 0); + } } -static void set_node_volume(pa_context *c, struct global *g, const pa_cvolume *volume) -{ - char buf[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); - float v; - - v = pa_cvolume_avg(volume) / (float) PA_VOLUME_NORM; - - pw_node_proxy_set_param((struct pw_node_proxy*)g->proxy, - SPA_PARAM_Props, 0, - spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, - SPA_PROP_volume, SPA_POD_Float(v))); -} - -static void set_node_mute(pa_context *c, struct global *g, bool mute) +static void set_node_volume(pa_context *c, struct global *g, float volume, bool mute) { char buf[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); - pw_node_proxy_set_param((struct pw_node_proxy*)g->proxy, - SPA_PARAM_Props, 0, - spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, - SPA_PROP_mute, SPA_POD_Bool(mute))); + if (g->node_info.volume != volume || g->node_info.mute != mute) { + g->node_info.volume = volume; + g->node_info.mute = mute; + pw_node_proxy_set_param((struct pw_node_proxy*)g->proxy, + SPA_PARAM_Props, 0, + spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, + SPA_PROP_volume, SPA_POD_Float(volume), + SPA_PROP_mute, SPA_POD_Bool(mute))); + } } - SPA_EXPORT pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; struct global *g; struct success_ack *d; + float v; pa_assert(c); pa_assert(c->refcount >= 1); @@ -298,7 +295,8 @@ 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_node_volume(c, g, volume); + v = pa_cvolume_avg(volume) / (float) PA_VOLUME_NORM; + set_node_volume(c, g, v, g->node_info.mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -314,6 +312,7 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name pa_operation *o; struct global *g; struct success_ack *d; + float v; pa_assert(c); pa_assert(c->refcount >= 1); @@ -327,7 +326,8 @@ 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_node_volume(c, g, volume); + v = pa_cvolume_avg(volume) / (float) PA_VOLUME_NORM; + set_node_volume(c, g, v, g->node_info.mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -357,7 +357,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_node_mute(c, g, mute); + set_node_volume(c, g, g->node_info.volume, mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -385,7 +385,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_node_mute(c, g, mute); + set_node_volume(c, g, g->node_info.volume, mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -614,6 +614,7 @@ pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, pa_operation *o; struct global *g; struct success_ack *d; + float v; pa_assert(c); pa_assert(c->refcount >= 1); @@ -629,7 +630,8 @@ 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_node_volume(c, g, volume); + v = pa_cvolume_avg(volume) / (float) PA_VOLUME_NORM; + set_node_volume(c, g, v, g->node_info.mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -645,6 +647,7 @@ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *na pa_operation *o; struct global *g; struct success_ack *d; + float v; pa_assert(c); pa_assert(c->refcount >= 1); @@ -658,7 +661,8 @@ 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_node_volume(c, g, volume); + v = pa_cvolume_avg(volume) / (float) PA_VOLUME_NORM; + set_node_volume(c, g, v, g->node_info.mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -688,7 +692,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_node_mute(c, g, mute); + set_node_volume(c, g, g->node_info.volume, mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -716,7 +720,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_node_mute(c, g, mute); + set_node_volume(c, g, g->node_info.volume, mute); o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -1501,6 +1505,7 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons struct global *g; pa_operation *o; struct success_ack *d; + float v; pw_log_debug("contex %p: index %d", c, idx); @@ -1511,12 +1516,13 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons return NULL; } + v = pa_cvolume_avg(volume) / (float) PA_VOLUME_NORM; + if (s) { - s->volume = pa_cvolume_avg(volume) / (float) PA_VOLUME_NORM; - set_stream_volume(c, s); + set_stream_volume(c, s, v, s->mute); } else if (g) { - set_node_volume(c, g, volume); + set_node_volume(c, g, v, g->node_info.mute); } o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -1535,6 +1541,8 @@ pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mu pa_operation *o; struct success_ack *d; + pw_log_debug("contex %p: index %d", c, idx); + if ((s = find_stream(c, idx)) == NULL) { if ((g = pa_context_find_global(c, idx)) == NULL) return NULL; @@ -1543,11 +1551,10 @@ pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mu } if (s) { - s->mute = mute; - set_stream_volume(c, s); + set_stream_volume(c, s, s->volume, mute); } else if (g) { - set_node_mute(c, g, mute); + set_node_volume(c, g, g->node_info.volume, mute); } o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -1770,6 +1777,7 @@ pa_operation* pa_context_set_source_output_volume(pa_context *c, uint32_t idx, c struct global *g; pa_operation *o; struct success_ack *d; + float v; pw_log_debug("contex %p: index %d", c, idx); @@ -1780,12 +1788,13 @@ pa_operation* pa_context_set_source_output_volume(pa_context *c, uint32_t idx, c return NULL; } + v = pa_cvolume_avg(volume) / (float) PA_VOLUME_NORM; + if (s) { - s->volume = pa_cvolume_avg(volume) / (float) PA_VOLUME_NORM; - set_stream_volume(c, s); + set_stream_volume(c, s, v, s->mute); } else if (g) { - set_node_volume(c, g, volume); + set_node_volume(c, g, v, g->node_info.mute); } o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata; @@ -1812,11 +1821,10 @@ pa_operation* pa_context_set_source_output_mute(pa_context *c, uint32_t idx, int } if (s) { - s->mute = mute; - set_stream_volume(c, s); + set_stream_volume(c, s, s->volume, mute); } else if (g) { - set_node_mute(c, g, mute); + set_node_volume(c, g, g->node_info.volume, mute); } o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); d = o->userdata;