+
+uint32_t pa_context_get_index(pa_context *c) {
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
+ PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
+ PA_CHECK_VALIDITY_RETURN_ANY(c, c->version >= 13, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX);
+
+ return c->client_index;
+}
+
+pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, pa_proplist *p, pa_context_success_cb_t cb, void *userdata) {
+ pa_operation *o;
+ pa_tagstruct *t;
+ uint32_t tag;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_UPDATE_CLIENT_PROPLIST, &tag);
+ pa_tagstruct_putu32(t, (uint32_t) mode);
+ pa_tagstruct_put_proplist(t, p);
+
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+ /* Please note that we don't update c->proplist here, because we
+ * don't export that field */
+
+ return o;
+}
+
+pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata) {
+ pa_operation *o;
+ pa_tagstruct *t;
+ uint32_t tag;
+ const char * const *k;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, keys && keys[0], PA_ERR_INVALID);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_CLIENT_PROPLIST, &tag);
+
+ for (k = keys; *k; k++)
+ pa_tagstruct_puts(t, *k);
+
+ pa_tagstruct_puts(t, NULL);
+
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+ /* Please note that we don't update c->proplist here, because we
+ * don't export that field */
+
+ return o;
+}
+
+void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_context *c = userdata;
+ uint32_t idx;
+ const char *name;
+
+ pa_assert(pd);
+ pa_assert(command == PA_COMMAND_EXTENSION);
+ pa_assert(t);
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ pa_context_ref(c);
+
+ if (c->version < 15) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (pa_tagstruct_getu32(t, &idx) < 0 ||
+ pa_tagstruct_gets(t, &name) < 0) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (pa_streq(name, "module-device-manager"))
+ pa_ext_device_manager_command(c, tag, t);
+ else if (pa_streq(name, "module-device-restore"))
+ pa_ext_device_restore_command(c, tag, t);
+ else if (pa_streq(name, "module-stream-restore"))
+ pa_ext_stream_restore_command(c, tag, t);
+ else
+ pa_log(_("Received message for unknown extension '%s'"), name);
+
+finish:
+ pa_context_unref(c);
+}
+
+void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_context *c = userdata;
+ pa_proplist *pl = NULL;
+ const char *event;
+
+ pa_assert(pd);
+ pa_assert(command == PA_COMMAND_CLIENT_EVENT);
+ pa_assert(t);
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ pa_context_ref(c);
+
+ if (c->version < 15) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ pl = pa_proplist_new();
+
+ if (pa_tagstruct_gets(t, &event) < 0 ||
+ pa_tagstruct_get_proplist(t, pl) < 0 ||
+ !pa_tagstruct_eof(t) || !event) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (c->event_callback)
+ c->event_callback(c, event, pl, c->event_userdata);
+
+finish:
+ pa_context_unref(c);
+
+ if (pl)
+ pa_proplist_free(pl);
+}
+
+pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) {
+ struct timeval tv;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+ pa_assert(c->mainloop);
+
+ if (usec == PA_USEC_INVALID)
+ return c->mainloop->time_new(c->mainloop, NULL, cb, userdata);
+
+ pa_timeval_rtstore(&tv, usec, c->use_rtclock);
+
+ return c->mainloop->time_new(c->mainloop, &tv, cb, userdata);
+}
+
+void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec) {
+ struct timeval tv;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+ pa_assert(c->mainloop);
+
+ if (usec == PA_USEC_INVALID)
+ c->mainloop->time_restart(e, NULL);
+ else {
+ pa_timeval_rtstore(&tv, usec, c->use_rtclock);
+ c->mainloop->time_restart(e, &tv);
+ }
+}
+
+size_t pa_context_get_tile_size(pa_context *c, const pa_sample_spec *ss) {
+ size_t fs, mbs;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, (size_t) -1);
+ PA_CHECK_VALIDITY_RETURN_ANY(c, !ss || pa_sample_spec_valid(ss), PA_ERR_INVALID, (size_t) -1);
+
+ fs = ss ? pa_frame_size(ss) : 1;
+ mbs = PA_ROUND_DOWN(pa_mempool_block_size_max(c->mempool), fs);
+ return PA_MAX(mbs, fs);
+}
+
+int pa_context_load_cookie_from_file(pa_context *c, const char *cookie_file_path) {
+ pa_assert(c);
+ pa_assert(cookie_file_path);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
+ PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
+
+ return pa_client_conf_load_cookie_from_file(c->conf, cookie_file_path);
+}