diff --git a/pipewire-pulseaudio/src/context.c b/pipewire-pulseaudio/src/context.c index 13585d56a..754ff3818 100644 --- a/pipewire-pulseaudio/src/context.c +++ b/pipewire-pulseaudio/src/context.c @@ -1627,7 +1627,7 @@ static void do_default_node(pa_operation *o, void *userdata) if (error != 0) pa_context_set_error(c, error); if (d->cb) - d->cb(c, error != 0 ? -1 : 1, d->userdata); + d->cb(c, error != 0 ? 0 : 1, d->userdata); pa_operation_done(o); pa_xfree(d->name); } diff --git a/pipewire-pulseaudio/src/introspect.c b/pipewire-pulseaudio/src/introspect.c index 29a00ab3e..085cb0773 100644 --- a/pipewire-pulseaudio/src/introspect.c +++ b/pipewire-pulseaudio/src/introspect.c @@ -73,27 +73,6 @@ static pa_sink_state_t node_state_to_sink(enum pw_node_state s) } } -static int wait_global(pa_context *c, struct global *g, pa_operation *o) -{ - if (g->init) { - pa_operation_sync(o); - return -EBUSY; - } - return 0; -} - -static int wait_globals(pa_context *c, pa_subscription_mask_t mask, pa_operation *o) -{ - struct global *g; - spa_list_for_each(g, &c->globals, link) { - if (!(g->mask & mask)) - continue; - if (wait_global(c, g, o) < 0) - return -EBUSY; - } - return 0; -} - static int has_profile(pa_card_profile_info2 **list, pa_card_profile_info2 *active) { for(;*list; list++) { @@ -103,7 +82,7 @@ static int has_profile(pa_card_profile_info2 **list, pa_card_profile_info2 *acti return 0; } -static void sink_callback(pa_context *c, struct global *g, struct sink_data *d) +static int sink_callback(pa_context *c, struct global *g, struct sink_data *d) { struct global *cg; struct pw_node_info *info = g->info; @@ -192,6 +171,7 @@ static void sink_callback(pa_context *c, struct global *g, struct sink_data *d) d->cb(c, &i, 0, d->userdata); pa_proplist_free(i.proplist); pa_proplist_free(ii[0].plist); + return 0; } static void sink_info(pa_operation *o, void *userdata) @@ -199,7 +179,7 @@ static void sink_info(pa_operation *o, void *userdata) struct sink_data *d = userdata; struct global *g; pa_context *c = o->context; - int eol = 1; + int error = 0; if (d->name) { g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_SINK, d->name); @@ -213,14 +193,13 @@ static void sink_info(pa_operation *o, void *userdata) pw_log_debug("%p", c); if (g) { - if (wait_global(c, g, o) < 0) - return; - sink_callback(c, g, d); + error = sink_callback(c, g, d); } else { - pa_context_set_error(c, PA_ERR_INVALID); - eol = -1; + error = PA_ERR_INVALID; } - d->cb(c, NULL, eol, d->userdata); + if (error) + pa_context_set_error(c, error); + d->cb(c, NULL, error ? -1 : 1, d->userdata); pa_operation_done(o); } @@ -282,8 +261,6 @@ static void sink_info_list(pa_operation *o, void *userdata) pa_context *c = o->context; struct global *g; - if (wait_globals(c, PA_SUBSCRIPTION_MASK_SINK, o) < 0) - return; spa_list_for_each(g, &c->globals, link) { if (!(g->mask & PA_SUBSCRIPTION_MASK_SINK)) continue; @@ -509,7 +486,7 @@ static void do_node_volume_mute(pa_operation *o, void *userdata) if (error != 0) pa_context_set_error(c, error); if (d->cb) - d->cb(c, error ? error : 1, d->userdata); + d->cb(c, error ? 0 : 1, d->userdata); pa_operation_done(o); } @@ -752,7 +729,7 @@ static void do_device_route(pa_operation *o, void *userdata) if (error != 0) pa_context_set_error(c, error); if (d->cb) - d->cb(c, error != 0 ? -1 : 1, d->userdata); + d->cb(c, error != 0 ? 0 : 1, d->userdata); pa_operation_done(o); pa_xfree(d->port); } @@ -828,7 +805,7 @@ static pa_source_state_t node_state_to_source(enum pw_node_state s) return PA_SOURCE_INVALID_STATE; } } -static void source_callback(pa_context *c, struct global *g, struct source_data *d) +static int source_callback(pa_context *c, struct global *g, struct source_data *d) { struct global *cg; struct pw_node_info *info = g->info; @@ -937,6 +914,7 @@ static void source_callback(pa_context *c, struct global *g, struct source_data d->cb(c, &i, 0, d->userdata); pa_proplist_free(i.proplist); pa_proplist_free(ii[0].plist); + return 0; } static void source_info(pa_operation *o, void *userdata) @@ -944,7 +922,7 @@ static void source_info(pa_operation *o, void *userdata) struct source_data *d = userdata; pa_context *c = o->context; struct global *g; - int eol = 1; + int error; if (d->name) { g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_SOURCE, d->name); @@ -958,14 +936,13 @@ static void source_info(pa_operation *o, void *userdata) } if (g) { - if (wait_global(c, g, o) < 0) - return; - source_callback(c, g, d); + error = source_callback(c, g, d); } else { - pa_context_set_error(c, PA_ERR_INVALID); - eol = -1; + error = PA_ERR_INVALID; } - d->cb(c, NULL, eol, d->userdata); + if (error) + pa_context_set_error(c, error); + d->cb(c, NULL, error ? -1 : 1, d->userdata); pa_operation_done(o); } @@ -1026,8 +1003,6 @@ static void source_info_list(pa_operation *o, void *userdata) pa_context *c = o->context; struct global *g; - if (wait_globals(c, PA_SUBSCRIPTION_MASK_SOURCE, o) < 0) - return; spa_list_for_each(g, &c->globals, link) { if (!(g->mask & PA_SUBSCRIPTION_MASK_SOURCE)) continue; @@ -1261,7 +1236,6 @@ pa_operation* pa_context_set_source_port_by_name(pa_context *c, const char*name, } struct server_data { - pa_context *context; pa_server_info_cb_t cb; void *userdata; struct global *global; @@ -1294,9 +1268,8 @@ static const char *get_default_name(pa_context *c, uint32_t mask) return "unknown"; } -static void server_callback(struct server_data *d) +static void server_callback(struct server_data *d, pa_context *c) { - pa_context *c = d->context; const struct pw_core_info *info = c->core_info; const char *str; pa_server_info i; @@ -1316,13 +1289,13 @@ static void server_callback(struct server_data *d) i.default_source_name = get_default_name(c, PA_SUBSCRIPTION_MASK_SOURCE); i.cookie = info->cookie; pa_channel_map_init_extend(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); - d->cb(d->context, &i, d->userdata); + d->cb(c, &i, d->userdata); } static void server_info(pa_operation *o, void *userdata) { struct server_data *d = userdata; - server_callback(d); + server_callback(d, o->context); pa_operation_done(o); } @@ -1340,7 +1313,6 @@ pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, o = pa_operation_new(c, NULL, server_info, sizeof(struct server_data)); d = o->userdata; - d->context = c; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); @@ -1349,31 +1321,36 @@ pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, } struct module_data { - pa_context *context; + uint32_t idx; pa_module_info_cb_t cb; void *userdata; - struct global *global; }; -static void module_callback(struct module_data *d) +static int module_callback(pa_context *c, struct module_data *d, struct global *g) { - struct global *g = d->global; - d->cb(d->context, &g->module_info.info, 0, d->userdata); + d->cb(c, &g->module_info.info, 0, d->userdata); + return 0; } static void module_info(pa_operation *o, void *userdata) { struct module_data *d = userdata; - int eol = 1; + pa_context *c = o->context; + struct global *g; + int error; - if (d->global) { - module_callback(d); + if ((g = pa_context_find_global(c, d->idx)) == NULL || + !(g->mask & PA_SUBSCRIPTION_MASK_MODULE)) + g = NULL; + + if (g) { + error = module_callback(c, d, g); } else { - pa_context_set_error(d->context, PA_ERR_INVALID); - eol = -1; + error = PA_ERR_INVALID; } - d->cb(d->context, NULL, eol, d->userdata); - + if (error) + pa_context_set_error(c, error); + d->cb(c, NULL, error ? -1 : 1, d->userdata); pa_operation_done(o); } @@ -1381,7 +1358,6 @@ SPA_EXPORT pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_info_cb_t cb, void *userdata) { pa_operation *o; - struct global *g; struct module_data *d; pa_assert(c); @@ -1390,16 +1366,13 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_ PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_MODULE)) - g = NULL; + pa_context_ensure_registry(c); o = pa_operation_new(c, NULL, module_info, sizeof(struct module_data)); d = o->userdata; - d->context = c; + d->idx = idx; d->cb = cb; d->userdata = userdata; - d->global = g; pa_operation_sync(o); return o; @@ -1408,14 +1381,13 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_ static void module_info_list(pa_operation *o, void *userdata) { struct module_data *d = userdata; - pa_context *c = d->context; + pa_context *c = o->context; struct global *g; spa_list_for_each(g, &c->globals, link) { if (!(g->mask & PA_SUBSCRIPTION_MASK_MODULE)) continue; - d->global = g; - module_callback(d); + module_callback(c, d, g); } d->cb(c, NULL, 1, d->userdata); pa_operation_done(o); @@ -1437,7 +1409,6 @@ pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t o = pa_operation_new(c, NULL, module_info_list, sizeof(struct module_data)); d = o->userdata; - d->context = c; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); @@ -1470,31 +1441,36 @@ pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_s } struct client_data { - pa_context *context; + uint32_t idx; pa_client_info_cb_t cb; void *userdata; - struct global *global; }; -static void client_callback(struct client_data *d) +static int client_callback(pa_context *c, struct client_data *d, struct global *g) { - struct global *g = d->global; - d->cb(d->context, &g->client_info.info, 0, d->userdata); + d->cb(c, &g->client_info.info, 0, d->userdata); + return 0; } static void client_info(pa_operation *o, void *userdata) { struct client_data *d = userdata; - int eol = 1; + pa_context *c = o->context; + struct global *g; + int error; - if (d->global) { - client_callback(d); + if ((g = pa_context_find_global(c, d->idx)) == NULL || + !(g->mask & PA_SUBSCRIPTION_MASK_CLIENT)) + g = NULL; + + if (g) { + error = client_callback(c, d, g); } else { - pa_context_set_error(d->context, PA_ERR_INVALID); - eol = -1; + error = PA_ERR_INVALID; } - d->cb(d->context, NULL, eol, d->userdata); - + if (error) + pa_context_set_error(c, error); + d->cb(c, NULL, error ? -1 : 1, d->userdata); pa_operation_done(o); } @@ -1502,7 +1478,6 @@ SPA_EXPORT pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_info_cb_t cb, void *userdata) { pa_operation *o; - struct global *g; struct client_data *d; pa_assert(c); @@ -1511,16 +1486,13 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_ PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_CLIENT)) - g = NULL; + pa_context_ensure_registry(c); o = pa_operation_new(c, NULL, client_info, sizeof(struct client_data)); d = o->userdata; - d->context = c; + d->idx = idx; d->cb = cb; d->userdata = userdata; - d->global = g; pa_operation_sync(o); return o; @@ -1529,14 +1501,13 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_ static void client_info_list(pa_operation *o, void *userdata) { struct client_data *d = userdata; - pa_context *c = d->context; + pa_context *c = o->context; struct global *g; spa_list_for_each(g, &c->globals, link) { if (!(g->mask & PA_SUBSCRIPTION_MASK_CLIENT)) continue; - d->global = g; - client_callback(d); + client_callback(c, d, g); } d->cb(c, NULL, 1, d->userdata); pa_operation_done(o); @@ -1558,7 +1529,6 @@ pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t o = pa_operation_new(c, NULL, client_info_list, sizeof(struct client_data)); d = o->userdata; - d->context = c; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); @@ -1566,27 +1536,49 @@ pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t return o; } +struct kill_client { + uint32_t idx; + pa_context_success_cb_t cb; + void *userdata; +}; + +static void do_kill_client(pa_operation *o, void *userdata) +{ + struct kill_client *d = userdata; + pa_context *c = o->context; + struct global *g; + int error = 0; + + if ((g = pa_context_find_global(c, d->idx)) == NULL || + !(g->mask & PA_SUBSCRIPTION_MASK_CLIENT)) + g = NULL; + + if (g) { + pw_registry_destroy(c->registry, g->id); + } else { + error = PA_ERR_INVALID; + } + if (error != 0) + pa_context_set_error(c, error); + if (d->cb) + d->cb(c, error ? 0 : 1, d->userdata); + pa_operation_done(o); +} + SPA_EXPORT pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) { - struct global *g; pa_operation *o; - struct success_ack *d; - int error = 0; + struct kill_client *d; PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_CLIENT)) { - error = PA_ERR_INVALID; - } else { - pw_registry_destroy(c->registry, g->id); - } + pa_context_ensure_registry(c); - o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); + o = pa_operation_new(c, NULL, do_kill_client, sizeof(struct kill_client)); d = o->userdata; + d->idx = idx; d->cb = cb; - d->error = error; d->userdata = userdata; pa_operation_sync(o); @@ -1594,36 +1586,44 @@ pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_suc } struct card_data { - pa_context *context; pa_card_info_cb_t cb; pa_context_success_cb_t success_cb; + char *name; + uint32_t idx; void *userdata; - struct global *global; char *profile; }; -static void card_callback(struct card_data *d) +static int card_callback(pa_context *c, struct card_data *d, struct global *g) { - struct global *g = d->global; pa_card_info *i = &g->card_info.info; - d->cb(d->context, i, 0, d->userdata); + d->cb(c, i, 0, d->userdata); + return 0; } static void card_info(pa_operation *o, void *userdata) { struct card_data *d = userdata; - int eol = 1; + pa_context *c = o->context; + struct global *g; + int error; - if (d->global) { - if (wait_global(d->context, d->global, o) < 0) - return; - card_callback(d); + if (d->name) { + g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_CARD, d->name); + pa_xfree(d->name); + } else if ((g = pa_context_find_global(c, d->idx)) == NULL || + !(g->mask & PA_SUBSCRIPTION_MASK_CARD)) + g = NULL; + + if (g) { + error = card_callback(c, d, g); } else { - pa_context_set_error(d->context, PA_ERR_INVALID); - eol = -1; + error = PA_ERR_INVALID; } - d->cb(d->context, NULL, eol, d->userdata); - + if (error != 0) + pa_context_set_error(c, error); + if (d->cb) + d->cb(c, NULL, error ? -1 : 1, d->userdata); pa_operation_done(o); } @@ -1631,7 +1631,6 @@ SPA_EXPORT pa_operation* pa_context_get_card_info_by_index(pa_context *c, uint32_t idx, pa_card_info_cb_t cb, void *userdata) { pa_operation *o; - struct global *g; struct card_data *d; pa_assert(c); @@ -1642,17 +1641,13 @@ pa_operation* pa_context_get_card_info_by_index(pa_context *c, uint32_t idx, pa_ PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); pw_log_debug("context %p: %u", c, idx); - - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_CARD)) - g = NULL; + pa_context_ensure_registry(c); o = pa_operation_new(c, NULL, card_info, sizeof(struct card_data)); d = o->userdata; - d->context = c; + d->idx = idx; d->cb = cb; d->userdata = userdata; - d->global = g; pa_operation_sync(o); return o; } @@ -1661,7 +1656,6 @@ SPA_EXPORT pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char *name, pa_card_info_cb_t cb, void *userdata) { pa_operation *o; - struct global *g; struct card_data *d; pa_assert(c); @@ -1672,15 +1666,13 @@ pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char *name, PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); pw_log_debug("context %p: %s", c, name); - - g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_CARD, name); + pa_context_ensure_registry(c); o = pa_operation_new(c, NULL, card_info, sizeof(struct card_data)); d = o->userdata; - d->context = c; + d->name = pa_xstrdup(name); d->cb = cb; d->userdata = userdata; - d->global = g; pa_operation_sync(o); return o; } @@ -1688,16 +1680,13 @@ pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char *name, static void card_info_list(pa_operation *o, void *userdata) { struct card_data *d = userdata; - pa_context *c = d->context; + pa_context *c = o->context; struct global *g; - if (wait_globals(c, PA_SUBSCRIPTION_MASK_CARD, o) < 0) - return; spa_list_for_each(g, &c->globals, link) { if (!(g->mask & PA_SUBSCRIPTION_MASK_CARD)) continue; - d->global = g; - card_callback(d); + card_callback(c, d, g); } d->cb(c, NULL, 1, d->userdata); pa_operation_done(o); @@ -1720,7 +1709,6 @@ pa_operation* pa_context_get_card_info_list(pa_context *c, pa_card_info_cb_t cb, o = pa_operation_new(c, NULL, card_info_list, sizeof(struct card_data)); d = o->userdata; - d->context = c; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); @@ -1731,16 +1719,23 @@ pa_operation* pa_context_get_card_info_list(pa_context *c, pa_card_info_cb_t cb, static void card_profile(pa_operation *o, void *userdata) { struct card_data *d = userdata; - struct global *g = d->global; - pa_context *c = d->context; - int res = 0; + struct global *g; + pa_context *c = o->context; + int error = 0; uint32_t id = SPA_ID_INVALID; char buf[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); struct param *p; + if (d->name) { + g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_CARD, d->name); + pa_xfree(d->name); + } else if ((g = pa_context_find_global(c, d->idx)) == NULL || + !(g->mask & PA_SUBSCRIPTION_MASK_CARD)) + g = NULL; + if (g == NULL) { - pa_context_set_error(c, PA_ERR_INVALID); + error = PA_ERR_INVALID; goto done; } @@ -1760,11 +1755,13 @@ static void card_profile(pa_operation *o, void *userdata) break; } } - if (id == SPA_ID_INVALID) - goto done;; + if (id == SPA_ID_INVALID) { + error = PA_ERR_INVALID; + goto done; + } if (!SPA_FLAG_IS_SET(g->permissions, PW_PERM_W | PW_PERM_X)) { - pa_context_set_error(c, PA_ERR_ACCESS); + error = PA_ERR_ACCESS; goto done; } @@ -1773,10 +1770,11 @@ static void card_profile(pa_operation *o, void *userdata) spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile, SPA_PARAM_PROFILE_index, SPA_POD_Int(id))); - res = 1; done: + if (error) + pa_context_set_error(c, error); if (d->success_cb) - d->success_cb(c, res, d->userdata); + d->success_cb(c, error ? 0 : 1, d->userdata); pa_operation_done(o); free(d->profile); } @@ -1785,7 +1783,6 @@ SPA_EXPORT pa_operation* pa_context_set_card_profile_by_index(pa_context *c, uint32_t idx, const char*profile, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; - struct global *g; struct card_data *d; pa_assert(c); @@ -1794,18 +1791,14 @@ pa_operation* pa_context_set_card_profile_by_index(pa_context *c, uint32_t idx, PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_CARD)) - g = NULL; - pw_log_debug("Card set profile %s", profile); + pa_context_ensure_registry(c); o = pa_operation_new(c, NULL, card_profile, sizeof(struct card_data)); d = o->userdata; - d->context = c; + d->idx = idx; d->success_cb = cb; d->userdata = userdata; - d->global = g; d->profile = strdup(profile); pa_operation_sync(o); @@ -1816,7 +1809,6 @@ SPA_EXPORT pa_operation* pa_context_set_card_profile_by_name(pa_context *c, const char*name, const char*profile, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; - struct global *g; struct card_data *d; pa_assert(c); @@ -1825,16 +1817,14 @@ pa_operation* pa_context_set_card_profile_by_name(pa_context *c, const char*name PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); - g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_CARD, name); - pw_log_debug("Card set profile %s", profile); + pa_context_ensure_registry(c); o = pa_operation_new(c, NULL, card_profile, sizeof(struct card_data)); d = o->userdata; - d->context = c; + d->name = pa_xstrdup(name); d->success_cb = cb; d->userdata = userdata; - d->global = g; d->profile = strdup(profile); pa_operation_sync(o); @@ -1869,15 +1859,14 @@ static pa_stream *find_stream(pa_context *c, uint32_t idx) } struct sink_input_data { - pa_context *context; pa_sink_input_info_cb_t cb; + uint32_t idx; void *userdata; - struct global *global; }; -static void sink_input_callback(struct sink_input_data *d) +static int sink_input_callback(pa_context *c, struct sink_input_data *d, struct global *g) { - struct global *g = d->global, *cl; + struct global *cl; struct pw_node_info *info = g->info; const char *name = NULL; uint32_t n; @@ -1886,9 +1875,9 @@ static void sink_input_callback(struct sink_input_data *d) pa_stream *s; if (info == NULL) - return; + return PA_ERR_INVALID; - s = find_stream(d->context, g->id); + s = find_stream(c, g->id); if (info->props) { if ((name = spa_dict_lookup(info->props, PW_KEY_MEDIA_NAME)) == NULL && @@ -1899,7 +1888,7 @@ static void sink_input_callback(struct sink_input_data *d) if (name == NULL) name = "unknown"; - cl = pa_context_find_global(d->context, g->node_info.client_id); + cl = pa_context_find_global(c, g->node_info.client_id); spa_zero(i); i.index = g->id; @@ -1911,7 +1900,7 @@ static void sink_input_callback(struct sink_input_data *d) } else { struct global *l; - l = pa_context_find_linked(d->context, g->id); + l = pa_context_find_linked(c, g->id); i.sink = l ? l->id : PA_INVALID_INDEX; } if (s && s->sample_spec.channels > 0) { @@ -1951,27 +1940,33 @@ static void sink_input_callback(struct sink_input_data *d) i.has_volume = true; i.volume_writable = true; - pw_log_debug("context %p: sink info for %d sink:%d", g->context, i.index, i.sink); + pw_log_debug("context %p: sink info for %d sink:%d", c, i.index, i.sink); - d->cb(d->context, &i, 0, d->userdata); + d->cb(c, &i, 0, d->userdata); pa_proplist_free(i.proplist); + return 0; } static void sink_input_info(pa_operation *o, void *userdata) { struct sink_input_data *d = userdata; - int eol = 1; + pa_context *c = o->context; + struct global *g; + int error; - if (d->global) { - if (wait_global(d->context, d->global, o) < 0) - return; - sink_input_callback(d); + if ((g = pa_context_find_global(c, d->idx)) == NULL || + !(g->mask & PA_SUBSCRIPTION_MASK_SINK_INPUT)) + g = NULL; + + if (g) { + error = sink_input_callback(c, d, g); } else { - pa_context_set_error(d->context, PA_ERR_INVALID); - eol = -1; + error = PA_ERR_INVALID; } - d->cb(d->context, NULL, eol, d->userdata); + if (error) + pa_context_set_error(c, PA_ERR_INVALID); + d->cb(c, NULL, error ? -1 : 1, d->userdata); pa_operation_done(o); } @@ -1979,7 +1974,6 @@ SPA_EXPORT pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata) { pa_operation *o; - struct global *g; struct sink_input_data *d; pa_assert(c); @@ -1989,17 +1983,13 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); pw_log_debug("context %p: info for %d", c, idx); - - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_SINK_INPUT)) - g = NULL; + pa_context_ensure_registry(c); o = pa_operation_new(c, NULL, sink_input_info, sizeof(struct sink_input_data)); d = o->userdata; - d->context = c; + d->idx = idx; d->cb = cb; d->userdata = userdata; - d->global = g; pa_operation_sync(o); return o; @@ -2008,16 +1998,13 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin static void sink_input_info_list(pa_operation *o, void *userdata) { struct sink_input_data *d = userdata; - pa_context *c = d->context; + pa_context *c = o->context; struct global *g; - if (wait_globals(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, o) < 0) - return; spa_list_for_each(g, &c->globals, link) { if (!(g->mask & PA_SUBSCRIPTION_MASK_SINK_INPUT)) continue; - d->global = g; - sink_input_callback(d); + sink_input_callback(c, d, g); } d->cb(c, NULL, 1, d->userdata); pa_operation_done(o); @@ -2040,7 +2027,6 @@ pa_operation* pa_context_get_sink_input_info_list(pa_context *c, pa_sink_input_i o = pa_operation_new(c, NULL, sink_input_info_list, sizeof(struct sink_input_data)); d = o->userdata; - d->context = c; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); @@ -2096,7 +2082,7 @@ done: if (error != 0) pa_context_set_error(c, error); if (d->cb) - d->cb(c, error != 0 ? -1 : 1, d->userdata); + d->cb(c, error != 0 ? 0 : 1, d->userdata); pa_operation_done(o); pa_xfree(d->target_name); } @@ -2107,6 +2093,8 @@ pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, co pa_operation *o; struct target_node *d; + pa_context_ensure_registry(c); + o = pa_operation_new(c, NULL, do_target_node, sizeof(struct target_node)); d = o->userdata; d->idx = idx; @@ -2127,6 +2115,8 @@ pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, u pa_operation *o; struct target_node *d; + pa_context_ensure_registry(c); + o = pa_operation_new(c, NULL, do_target_node, sizeof(struct target_node)); d = o->userdata; d->idx = idx; @@ -2141,35 +2131,64 @@ pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, u return o; } +struct stream_volume { + uint32_t idx; + uint32_t mask; + bool have_volume; + pa_cvolume volume; + int mute; + pa_context_success_cb_t cb; + void *userdata; +}; +static void do_stream_volume_mute(pa_operation *o, void *userdata) +{ + struct stream_volume *d = userdata; + pa_context *c = o->context; + struct global *g; + int error = 0; + pa_stream *s; + + if ((s = find_stream(c, d->idx)) == NULL) { + if ((g = pa_context_find_global(c, d->idx)) == NULL || + !(g->mask & d->mask)) + g = NULL; + } + if (s) { + error = set_stream_volume(c, s, + d->have_volume ? &d->volume : NULL, + d->have_volume ? s->mute : d->mute); + } else if (g) { + error = set_node_volume(c, g, + d->have_volume ? &d->volume : NULL, + d->have_volume ? g->node_info.mute : d->mute); + } else { + error = PA_ERR_INVALID; + } + + if (error != 0) + pa_context_set_error(c, error); + if (d->cb) + d->cb(c, error != 0 ? 0 : 1, d->userdata); + pa_operation_done(o); +} SPA_EXPORT pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { - pa_stream *s; - struct global *g; pa_operation *o; - struct success_ack *d; - int error; + struct stream_volume *d; pw_log_debug("contex %p: index %d", c, idx); + pa_context_ensure_registry(c); - if ((s = find_stream(c, idx)) == NULL) { - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_SINK_INPUT)) - g = NULL; - } - if (s) { - error = set_stream_volume(c, s, volume, s->mute); - } else if (g) { - error = set_node_volume(c, g, volume, g->node_info.mute); - } else { - error = PA_ERR_INVALID; - } - o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); + o = pa_operation_new(c, NULL, do_stream_volume_mute, sizeof(struct stream_volume)); d = o->userdata; + d->idx = idx; + d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT; + d->volume = *volume; + d->have_volume = true; d->cb = cb; - d->error = error; d->userdata = userdata; pa_operation_sync(o); @@ -2179,52 +2198,44 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons SPA_EXPORT pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) { - pa_stream *s; - struct global *g; pa_operation *o; - struct success_ack *d; - int error; + struct stream_volume *d; pw_log_debug("contex %p: index %d", c, idx); + pa_context_ensure_registry(c); - if ((s = find_stream(c, idx)) == NULL) { - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_SINK_INPUT)) - g = NULL; - } - - if (s) { - error = set_stream_volume(c, s, NULL, mute); - } else if (g) { - error = set_node_volume(c, g, NULL, mute); - } else { - error = PA_ERR_INVALID; - } - o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); + o = pa_operation_new(c, NULL, do_stream_volume_mute, sizeof(struct stream_volume)); d = o->userdata; + d->idx = idx; + d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT; + d->mute = mute; d->cb = cb; - d->error = error; d->userdata = userdata; pa_operation_sync(o); return o; } -SPA_EXPORT -pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) -{ - pa_stream *s; - struct global *g; - pa_operation *o; - struct success_ack *d; - int error = 0; +struct kill_stream { + uint32_t idx; + uint32_t mask; + pa_context_success_cb_t cb; + void *userdata; +}; - if ((s = find_stream(c, idx)) == NULL) { - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_SINK_INPUT)) +static void do_kill_stream(pa_operation *o, void *userdata) +{ + struct kill_stream *d = userdata; + pa_context *c = o->context; + struct global *g; + int error = 0; + pa_stream *s; + + if ((s = find_stream(c, d->idx)) == NULL) { + if ((g = pa_context_find_global(c, d->idx)) == NULL || + !(g->mask & d->mask)) g = NULL; } - if (s) { pw_stream_destroy(s->stream); } else if (g) { @@ -2232,10 +2243,27 @@ pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context } else { error = PA_ERR_INVALID; } - o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); + if (error != 0) + pa_context_set_error(c, error); + if (d->cb) + d->cb(c, error != 0 ? 0 : 1, d->userdata); + pa_operation_done(o); +} + +SPA_EXPORT +pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) +{ + pa_operation *o; + struct kill_stream *d; + + pw_log_debug("contex %p: index %d", c, idx); + pa_context_ensure_registry(c); + + o = pa_operation_new(c, NULL, do_kill_stream, sizeof(struct kill_stream)); d = o->userdata; + d->idx = idx; + d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT; d->cb = cb; - d->error = error; d->userdata = userdata; pa_operation_sync(o); @@ -2243,15 +2271,14 @@ pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context } struct source_output_data { - pa_context *context; + uint32_t idx; pa_source_output_info_cb_t cb; void *userdata; - struct global *global; }; -static void source_output_callback(struct source_output_data *d) +static int source_output_callback(struct source_output_data *d, pa_context *c, struct global *g) { - struct global *g = d->global, *l, *cl; + struct global *l, *cl; struct pw_node_info *info = g->info; const char *name = NULL; uint32_t n; @@ -2261,9 +2288,9 @@ static void source_output_callback(struct source_output_data *d) pw_log_debug("index %d", g->id); if (info == NULL) - return; + return PA_ERR_INVALID; - s = find_stream(d->context, g->id); + s = find_stream(c, g->id); if (info->props) { if ((name = spa_dict_lookup(info->props, PW_KEY_MEDIA_NAME)) == NULL && @@ -2274,7 +2301,7 @@ static void source_output_callback(struct source_output_data *d) if (name == NULL) name = "unknown"; - cl = pa_context_find_global(d->context, g->node_info.client_id); + cl = pa_context_find_global(c, g->node_info.client_id); spa_zero(i); i.index = g->id; @@ -2285,7 +2312,7 @@ static void source_output_callback(struct source_output_data *d) i.source = s->device_index; } else { - l = pa_context_find_linked(d->context, g->id); + l = pa_context_find_linked(c, g->id); i.source = l ? l->id : PA_INVALID_INDEX; } if (s && s->sample_spec.channels > 0) { @@ -2325,25 +2352,31 @@ static void source_output_callback(struct source_output_data *d) i.has_volume = true; i.volume_writable = true; - d->cb(d->context, &i, 0, d->userdata); + d->cb(c, &i, 0, d->userdata); pa_proplist_free(i.proplist); + return 0; } static void source_output_info(pa_operation *o, void *userdata) { struct source_output_data *d = userdata; - int eol = 1; + pa_context *c = o->context; + struct global *g; + int error; - if (d->global) { - if (wait_global(d->context, d->global, o) < 0) - return; - source_output_callback(d); + if ((g = pa_context_find_global(c, d->idx)) == NULL || + !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)) + g = NULL; + + if (g) { + error = source_output_callback(d, c, g); } else { - pa_context_set_error(d->context, PA_ERR_INVALID); - eol = -1; + error = PA_ERR_INVALID; } - d->cb(d->context, NULL, eol, d->userdata); + if (error) + pa_context_set_error(c, error); + d->cb(c, NULL, error ? -1 : 1, d->userdata); pa_operation_done(o); } @@ -2351,7 +2384,6 @@ SPA_EXPORT pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_source_output_info_cb_t cb, void *userdata) { pa_operation *o; - struct global *g; struct source_output_data *d; pa_assert(c); @@ -2360,16 +2392,13 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_ PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)) - g = NULL; + pa_context_ensure_registry(c); o = pa_operation_new(c, NULL, source_output_info, sizeof(struct source_output_data)); d = o->userdata; - d->context = c; + d->idx = idx; d->cb = cb; d->userdata = userdata; - d->global = g; pa_operation_sync(o); return o; @@ -2378,17 +2407,13 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_ static void source_output_info_list(pa_operation *o, void *userdata) { struct source_output_data *d = userdata; - pa_context *c = d->context; + pa_context *c = o->context; struct global *g; - if (wait_globals(c, PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, o) < 0) - return; - spa_list_for_each(g, &c->globals, link) { if (!(g->mask & PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)) continue; - d->global = g; - source_output_callback(d); + source_output_callback(d, c, g); } d->cb(c, NULL, 1, d->userdata); pa_operation_done(o); @@ -2410,7 +2435,6 @@ pa_operation* pa_context_get_source_output_info_list(pa_context *c, pa_source_ou o = pa_operation_new(c, NULL, source_output_info_list, sizeof(struct source_output_data)); d = o->userdata; - d->context = c; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); @@ -2424,6 +2448,8 @@ pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, pa_operation *o; struct target_node *d; + pa_context_ensure_registry(c); + o = pa_operation_new(c, NULL, do_target_node, sizeof(struct target_node)); d = o->userdata; d->idx = idx; @@ -2444,6 +2470,8 @@ pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx pa_operation *o; struct target_node *d; + pa_context_ensure_registry(c); + o = pa_operation_new(c, NULL, do_target_node, sizeof(struct target_node)); d = o->userdata; d->idx = idx; @@ -2461,31 +2489,19 @@ pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx SPA_EXPORT pa_operation* pa_context_set_source_output_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { - pa_stream *s; - struct global *g; pa_operation *o; - struct success_ack *d; - int error; + struct stream_volume *d; pw_log_debug("contex %p: index %d", c, idx); + pa_context_ensure_registry(c); - if ((s = find_stream(c, idx)) == NULL) { - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)) - g = NULL; - } - - if (s) { - error = set_stream_volume(c, s, volume, s->mute); - } else if (g) { - error = set_node_volume(c, g, volume, g->node_info.mute); - } else { - error = PA_ERR_INVALID; - } - o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); + o = pa_operation_new(c, NULL, do_stream_volume_mute, sizeof(struct stream_volume)); d = o->userdata; + d->idx = idx; + d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT; + d->volume = *volume; + d->have_volume = true; d->cb = cb; - d->error = error; d->userdata = userdata; pa_operation_sync(o); @@ -2495,28 +2511,18 @@ pa_operation* pa_context_set_source_output_volume(pa_context *c, uint32_t idx, c SPA_EXPORT pa_operation* pa_context_set_source_output_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) { - pa_stream *s; - struct global *g; pa_operation *o; - struct success_ack *d; - int error; + struct stream_volume *d; - if ((s = find_stream(c, idx)) == NULL) { - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)) - g = NULL; - } - if (s) { - error = set_stream_volume(c, s, NULL, mute); - } else if (g) { - error = set_node_volume(c, g, NULL, mute); - } else { - error = PA_ERR_INVALID; - } - o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); + pw_log_debug("contex %p: index %d", c, idx); + pa_context_ensure_registry(c); + + o = pa_operation_new(c, NULL, do_stream_volume_mute, sizeof(struct stream_volume)); d = o->userdata; + d->idx = idx; + d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT; + d->mute = mute; d->cb = cb; - d->error = error; d->userdata = userdata; pa_operation_sync(o); @@ -2526,29 +2532,17 @@ pa_operation* pa_context_set_source_output_mute(pa_context *c, uint32_t idx, int SPA_EXPORT pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) { - pa_stream *s; - struct global *g; pa_operation *o; - struct success_ack *d; - int error = 0; + struct kill_stream *d; - if ((s = find_stream(c, idx)) == NULL) { - if ((g = pa_context_find_global(c, idx)) == NULL || - !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)) - g = NULL; - } + pw_log_debug("contex %p: index %d", c, idx); + pa_context_ensure_registry(c); - if (s) { - pw_stream_destroy(s->stream); - } else if (g) { - pw_registry_destroy(c->registry, g->id); - } else { - error = PA_ERR_INVALID; - } - o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack)); + o = pa_operation_new(c, NULL, do_kill_stream, sizeof(struct kill_stream)); d = o->userdata; + d->idx = idx; + d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT; d->cb = cb; - d->error = error; d->userdata = userdata; pa_operation_sync(o);