summaryrefslogtreecommitdiffstats
path: root/src/pipewire/introspect.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/pipewire/introspect.c590
1 files changed, 590 insertions, 0 deletions
diff --git a/src/pipewire/introspect.c b/src/pipewire/introspect.c
new file mode 100644
index 0000000..e52ef28
--- /dev/null
+++ b/src/pipewire/introspect.c
@@ -0,0 +1,590 @@
+/* PipeWire
+ *
+ * Copyright © 2018 Wim Taymans
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <string.h>
+
+#include <spa/pod/builder.h>
+
+#include "pipewire/pipewire.h"
+
+#include "pipewire/core.h"
+
+SPA_EXPORT
+const char *pw_node_state_as_string(enum pw_node_state state)
+{
+ switch (state) {
+ case PW_NODE_STATE_ERROR:
+ return "error";
+ case PW_NODE_STATE_CREATING:
+ return "creating";
+ case PW_NODE_STATE_SUSPENDED:
+ return "suspended";
+ case PW_NODE_STATE_IDLE:
+ return "idle";
+ case PW_NODE_STATE_RUNNING:
+ return "running";
+ }
+ return "invalid-state";
+}
+
+SPA_EXPORT
+const char *pw_direction_as_string(enum pw_direction direction)
+{
+ switch (direction) {
+ case PW_DIRECTION_INPUT:
+ return "input";
+ case PW_DIRECTION_OUTPUT:
+ return "output";
+ }
+ return "invalid";
+}
+
+SPA_EXPORT
+const char *pw_link_state_as_string(enum pw_link_state state)
+{
+ switch (state) {
+ case PW_LINK_STATE_ERROR:
+ return "error";
+ case PW_LINK_STATE_UNLINKED:
+ return "unlinked";
+ case PW_LINK_STATE_INIT:
+ return "init";
+ case PW_LINK_STATE_NEGOTIATING:
+ return "negotiating";
+ case PW_LINK_STATE_ALLOCATING:
+ return "allocating";
+ case PW_LINK_STATE_PAUSED:
+ return "paused";
+ case PW_LINK_STATE_ACTIVE:
+ return "active";
+ }
+ return "invalid-state";
+}
+
+static void pw_spa_dict_destroy(struct spa_dict *dict)
+{
+ const struct spa_dict_item *item;
+
+ spa_dict_for_each(item, dict) {
+ free((void *) item->key);
+ free((void *) item->value);
+ }
+ free((void*)dict->items);
+ free(dict);
+}
+
+static struct spa_dict *pw_spa_dict_copy(struct spa_dict *dict)
+{
+ struct spa_dict *copy;
+ struct spa_dict_item *items;
+ uint32_t i;
+
+ if (dict == NULL)
+ return NULL;
+
+ copy = calloc(1, sizeof(struct spa_dict));
+ if (copy == NULL)
+ goto no_mem;
+ copy->items = items = calloc(dict->n_items, sizeof(struct spa_dict_item));
+ if (copy->items == NULL)
+ goto no_items;
+ copy->n_items = dict->n_items;
+
+ for (i = 0; i < dict->n_items; i++) {
+ items[i].key = strdup(dict->items[i].key);
+ items[i].value = dict->items[i].value ? strdup(dict->items[i].value) : NULL;
+ }
+ return copy;
+
+ no_items:
+ free(copy);
+ no_mem:
+ return NULL;
+}
+
+SPA_EXPORT
+struct pw_core_info *pw_core_info_merge(struct pw_core_info *info,
+ const struct pw_core_info *update, bool reset)
+{
+ if (update == NULL)
+ return info;
+
+ if (info == NULL) {
+ info = calloc(1, sizeof(struct pw_core_info));
+ if (info == NULL)
+ return NULL;
+
+ info->id = update->id;
+ info->cookie = update->cookie;
+ info->user_name = update->user_name ? strdup(update->user_name) : NULL;
+ info->host_name = update->host_name ? strdup(update->host_name) : NULL;
+ info->version = update->version ? strdup(update->version) : NULL;
+ info->name = update->name ? strdup(update->name) : NULL;
+ }
+ if (reset)
+ info->change_mask = 0;
+ info->change_mask |= update->change_mask;
+
+ if (update->change_mask & PW_CORE_CHANGE_MASK_PROPS) {
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ info->props = pw_spa_dict_copy(update->props);
+ }
+ return info;
+}
+
+SPA_EXPORT
+struct pw_core_info *pw_core_info_update(struct pw_core_info *info,
+ const struct pw_core_info *update)
+{
+ return pw_core_info_merge(info, update, true);
+}
+
+SPA_EXPORT
+void pw_core_info_free(struct pw_core_info *info)
+{
+ free((void *) info->user_name);
+ free((void *) info->host_name);
+ free((void *) info->version);
+ free((void *) info->name);
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ free(info);
+}
+
+SPA_EXPORT
+struct pw_node_info *pw_node_info_merge(struct pw_node_info *info,
+ const struct pw_node_info *update, bool reset)
+{
+ if (update == NULL)
+ return info;
+
+ if (info == NULL) {
+ info = calloc(1, sizeof(struct pw_node_info));
+ if (info == NULL)
+ return NULL;
+
+ info->id = update->id;
+ info->max_input_ports = update->max_input_ports;
+ info->max_output_ports = update->max_output_ports;
+ }
+ if (reset)
+ info->change_mask = 0;
+ info->change_mask |= update->change_mask;
+
+ if (update->change_mask & PW_NODE_CHANGE_MASK_INPUT_PORTS) {
+ info->n_input_ports = update->n_input_ports;
+ }
+ if (update->change_mask & PW_NODE_CHANGE_MASK_OUTPUT_PORTS) {
+ info->n_output_ports = update->n_output_ports;
+ }
+ if (update->change_mask & PW_NODE_CHANGE_MASK_STATE) {
+ info->state = update->state;
+ free((void *) info->error);
+ info->error = update->error ? strdup(update->error) : NULL;
+ }
+ if (update->change_mask & PW_NODE_CHANGE_MASK_PROPS) {
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ info->props = pw_spa_dict_copy(update->props);
+ }
+ if (update->change_mask & PW_NODE_CHANGE_MASK_PARAMS) {
+ uint32_t i, n_params = update->n_params;
+ void *np;
+
+ np = pw_reallocarray(info->params, n_params, sizeof(struct spa_param_info));
+ if (np == NULL) {
+ free(info->params);
+ info->params = NULL;
+ info->n_params = n_params = 0;
+ }
+ info->params = np;
+
+ for (i = 0; i < SPA_MIN(info->n_params, n_params); i++) {
+ info->params[i].id = update->params[i].id;
+ if (reset)
+ info->params[i].user = 0;
+ if (info->params[i].flags != update->params[i].flags) {
+ info->params[i].flags = update->params[i].flags;
+ info->params[i].user++;
+ }
+ }
+ info->n_params = n_params;
+ for (; i < info->n_params; i++) {
+ info->params[i].id = update->params[i].id;
+ info->params[i].flags = update->params[i].flags;
+ info->params[i].user = 1;
+ }
+ }
+ return info;
+}
+
+SPA_EXPORT
+struct pw_node_info *pw_node_info_update(struct pw_node_info *info,
+ const struct pw_node_info *update)
+{
+ return pw_node_info_merge(info, update, true);
+}
+
+SPA_EXPORT
+void pw_node_info_free(struct pw_node_info *info)
+{
+ free((void *) info->error);
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ free((void *) info->params);
+ free(info);
+}
+
+SPA_EXPORT
+struct pw_port_info *pw_port_info_merge(struct pw_port_info *info,
+ const struct pw_port_info *update, bool reset)
+{
+
+ if (update == NULL)
+ return info;
+
+ if (info == NULL) {
+ info = calloc(1, sizeof(struct pw_port_info));
+ if (info == NULL)
+ return NULL;
+
+ info->id = update->id;
+ info->direction = update->direction;
+ }
+ if (reset)
+ info->change_mask = 0;
+ info->change_mask |= update->change_mask;
+
+ if (update->change_mask & PW_PORT_CHANGE_MASK_PROPS) {
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ info->props = pw_spa_dict_copy(update->props);
+ }
+ if (update->change_mask & PW_PORT_CHANGE_MASK_PARAMS) {
+ uint32_t i, n_params = update->n_params;
+ void *np;
+
+ np = pw_reallocarray(info->params, n_params, sizeof(struct spa_param_info));
+ if (np == NULL) {
+ free(info->params);
+ info->params = NULL;
+ info->n_params = n_params = 0;
+ }
+ info->params = np;
+
+ for (i = 0; i < SPA_MIN(info->n_params, n_params); i++) {
+ info->params[i].id = update->params[i].id;
+ if (reset)
+ info->params[i].user = 0;
+ if (info->params[i].flags != update->params[i].flags) {
+ info->params[i].flags = update->params[i].flags;
+ info->params[i].user++;
+ }
+ }
+ info->n_params = n_params;
+ for (; i < info->n_params; i++) {
+ info->params[i].id = update->params[i].id;
+ info->params[i].flags = update->params[i].flags;
+ info->params[i].user = 1;
+ }
+ }
+ return info;
+}
+
+SPA_EXPORT
+struct pw_port_info *pw_port_info_update(struct pw_port_info *info,
+ const struct pw_port_info *update)
+{
+ return pw_port_info_merge(info, update, true);
+}
+
+SPA_EXPORT
+void pw_port_info_free(struct pw_port_info *info)
+{
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ free((void *) info->params);
+ free(info);
+}
+
+SPA_EXPORT
+struct pw_factory_info *pw_factory_info_merge(struct pw_factory_info *info,
+ const struct pw_factory_info *update, bool reset)
+{
+ if (update == NULL)
+ return info;
+
+ if (info == NULL) {
+ info = calloc(1, sizeof(struct pw_factory_info));
+ if (info == NULL)
+ return NULL;
+
+ info->id = update->id;
+ info->name = update->name ? strdup(update->name) : NULL;
+ info->type = update->type ? strdup(update->type) : NULL;
+ info->version = update->version;
+ }
+ if (reset)
+ info->change_mask = 0;
+ info->change_mask |= update->change_mask;
+
+ if (update->change_mask & PW_FACTORY_CHANGE_MASK_PROPS) {
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ info->props = pw_spa_dict_copy(update->props);
+ }
+ return info;
+}
+
+SPA_EXPORT
+struct pw_factory_info *pw_factory_info_update(struct pw_factory_info *info,
+ const struct pw_factory_info *update)
+{
+ return pw_factory_info_merge(info, update, true);
+}
+
+SPA_EXPORT
+void pw_factory_info_free(struct pw_factory_info *info)
+{
+ free((void *) info->name);
+ free((void *) info->type);
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ free(info);
+}
+
+SPA_EXPORT
+struct pw_module_info *pw_module_info_merge(struct pw_module_info *info,
+ const struct pw_module_info *update, bool reset)
+{
+ if (update == NULL)
+ return info;
+
+ if (info == NULL) {
+ info = calloc(1, sizeof(struct pw_module_info));
+ if (info == NULL)
+ return NULL;
+
+ info->id = update->id;
+ info->name = update->name ? strdup(update->name) : NULL;
+ info->filename = update->filename ? strdup(update->filename) : NULL;
+ info->args = update->args ? strdup(update->args) : NULL;
+ }
+ if (reset)
+ info->change_mask = 0;
+ info->change_mask |= update->change_mask;
+
+ if (update->change_mask & PW_MODULE_CHANGE_MASK_PROPS) {
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ info->props = pw_spa_dict_copy(update->props);
+ }
+ return info;
+}
+
+SPA_EXPORT
+struct pw_module_info *pw_module_info_update(struct pw_module_info *info,
+ const struct pw_module_info *update)
+{
+ return pw_module_info_merge(info, update, true);
+}
+
+SPA_EXPORT
+void pw_module_info_free(struct pw_module_info *info)
+{
+ free((void *) info->name);
+ free((void *) info->filename);
+ free((void *) info->args);
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ free(info);
+}
+
+SPA_EXPORT
+struct pw_device_info *pw_device_info_merge(struct pw_device_info *info,
+ const struct pw_device_info *update, bool reset)
+{
+ if (update == NULL)
+ return info;
+
+ if (info == NULL) {
+ info = calloc(1, sizeof(struct pw_device_info));
+ if (info == NULL)
+ return NULL;
+
+ info->id = update->id;
+ }
+ if (reset)
+ info->change_mask = 0;
+ info->change_mask |= update->change_mask;
+
+ if (update->change_mask & PW_DEVICE_CHANGE_MASK_PROPS) {
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ info->props = pw_spa_dict_copy(update->props);
+ }
+ if (update->change_mask & PW_DEVICE_CHANGE_MASK_PARAMS) {
+ uint32_t i, n_params = update->n_params;
+ void *np;
+
+ np = pw_reallocarray(info->params, n_params, sizeof(struct spa_param_info));
+ if (np == NULL) {
+ free(info->params);
+ info->params = NULL;
+ info->n_params = n_params = 0;
+ }
+ info->params = np;
+
+ for (i = 0; i < SPA_MIN(info->n_params, n_params); i++) {
+ info->params[i].id = update->params[i].id;
+ if (reset)
+ info->params[i].user = 0;
+ if (info->params[i].flags != update->params[i].flags) {
+ info->params[i].flags = update->params[i].flags;
+ info->params[i].user++;
+ }
+ }
+ info->n_params = n_params;
+ for (; i < info->n_params; i++) {
+ info->params[i].id = update->params[i].id;
+ info->params[i].flags = update->params[i].flags;
+ info->params[i].user = 1;
+ }
+ }
+ return info;
+}
+
+SPA_EXPORT
+struct pw_device_info *pw_device_info_update(struct pw_device_info *info,
+ const struct pw_device_info *update)
+{
+ return pw_device_info_merge(info, update, true);
+}
+
+SPA_EXPORT
+void pw_device_info_free(struct pw_device_info *info)
+{
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ free((void *) info->params);
+ free(info);
+}
+
+SPA_EXPORT
+struct pw_client_info *pw_client_info_merge(struct pw_client_info *info,
+ const struct pw_client_info *update, bool reset)
+{
+ if (update == NULL)
+ return info;
+
+ if (info == NULL) {
+ info = calloc(1, sizeof(struct pw_client_info));
+ if (info == NULL)
+ return NULL;
+
+ info->id = update->id;
+ }
+ if (reset)
+ info->change_mask = 0;
+ info->change_mask |= update->change_mask;
+
+ if (update->change_mask & PW_CLIENT_CHANGE_MASK_PROPS) {
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ info->props = pw_spa_dict_copy(update->props);
+ }
+ return info;
+}
+
+SPA_EXPORT
+struct pw_client_info *pw_client_info_update(struct pw_client_info *info,
+ const struct pw_client_info *update)
+{
+ return pw_client_info_merge(info, update, true);
+}
+
+SPA_EXPORT
+void pw_client_info_free(struct pw_client_info *info)
+{
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ free(info);
+}
+
+SPA_EXPORT
+struct pw_link_info *pw_link_info_merge(struct pw_link_info *info,
+ const struct pw_link_info *update, bool reset)
+{
+ if (update == NULL)
+ return info;
+
+ if (info == NULL) {
+ info = calloc(1, sizeof(struct pw_link_info));
+ if (info == NULL)
+ return NULL;
+
+ info->id = update->id;
+ info->output_node_id = update->output_node_id;
+ info->output_port_id = update->output_port_id;
+ info->input_node_id = update->input_node_id;
+ info->input_port_id = update->input_port_id;
+ }
+ if (reset)
+ info->change_mask = 0;
+ info->change_mask |= update->change_mask;
+
+ if (update->change_mask & PW_LINK_CHANGE_MASK_STATE) {
+ info->state = update->state;
+ free((void *) info->error);
+ info->error = update->error ? strdup(update->error) : NULL;
+ }
+ if (update->change_mask & PW_LINK_CHANGE_MASK_FORMAT) {
+ free(info->format);
+ info->format = update->format ? spa_pod_copy(update->format) : NULL;
+ }
+ if (update->change_mask & PW_LINK_CHANGE_MASK_PROPS) {
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ info->props = pw_spa_dict_copy(update->props);
+ }
+ return info;
+}
+
+SPA_EXPORT
+struct pw_link_info *pw_link_info_update(struct pw_link_info *info,
+ const struct pw_link_info *update)
+{
+ return pw_link_info_merge(info, update, true);
+}
+
+SPA_EXPORT
+void pw_link_info_free(struct pw_link_info *info)
+{
+ free((void *) info->error);
+ free(info->format);
+ if (info->props)
+ pw_spa_dict_destroy(info->props);
+ free(info);
+}