mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	pulse-server: implement sample introspection
This commit is contained in:
		
							parent
							
								
									827d3ff271
								
							
						
					
					
						commit
						8f1eed6ab1
					
				
					 1 changed files with 91 additions and 11 deletions
				
			
		| 
						 | 
				
			
			@ -236,9 +236,13 @@ static void sample_free(struct sample *sample)
 | 
			
		|||
	free(sample);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct sample *find_sample(struct impl *impl, const char *name)
 | 
			
		||||
static struct sample *find_sample(struct impl *impl, uint32_t idx, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	union pw_map_item *item;
 | 
			
		||||
 | 
			
		||||
	if (idx != SPA_ID_INVALID)
 | 
			
		||||
		return pw_map_lookup(&impl->samples, idx);
 | 
			
		||||
 | 
			
		||||
	pw_array_for_each(item, &impl->samples.items) {
 | 
			
		||||
		struct sample *s = item->data;
 | 
			
		||||
                if (!pw_map_item_is_free(item) &&
 | 
			
		||||
| 
						 | 
				
			
			@ -2187,7 +2191,7 @@ static int do_finish_upload_stream(struct client *client, uint32_t command, uint
 | 
			
		|||
			impl, client->name, commands[command].name, tag,
 | 
			
		||||
			channel, name);
 | 
			
		||||
 | 
			
		||||
	sample = find_sample(impl, name);
 | 
			
		||||
	sample = find_sample(impl, SPA_ID_INVALID, name);
 | 
			
		||||
	if (sample == NULL) {
 | 
			
		||||
		sample = calloc(1, sizeof(struct sample));
 | 
			
		||||
		if (sample == NULL)
 | 
			
		||||
| 
						 | 
				
			
			@ -2300,7 +2304,7 @@ static int do_play_sample(struct client *client, uint32_t command, uint32_t tag,
 | 
			
		|||
 | 
			
		||||
	pw_properties_update(props, &client->props->dict);
 | 
			
		||||
 | 
			
		||||
	sample = find_sample(impl, name);
 | 
			
		||||
	sample = find_sample(impl, SPA_ID_INVALID, name);
 | 
			
		||||
	if (sample == NULL)
 | 
			
		||||
		goto error_noent;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2357,7 +2361,7 @@ static int do_remove_sample(struct client *client, uint32_t command, uint32_t ta
 | 
			
		|||
			name);
 | 
			
		||||
	if (name == NULL)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	if ((sample = find_sample(impl, name)) == NULL)
 | 
			
		||||
	if ((sample = find_sample(impl, SPA_ID_INVALID, name)) == NULL)
 | 
			
		||||
		return -ENOENT;
 | 
			
		||||
 | 
			
		||||
	broadcast_subscribe_event(impl,
 | 
			
		||||
| 
						 | 
				
			
			@ -3695,9 +3699,6 @@ static int do_get_info(struct client *client, uint32_t command, uint32_t tag, st
 | 
			
		|||
		sel.key = PW_KEY_DEVICE_NAME;
 | 
			
		||||
		fill_func = fill_card_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case COMMAND_GET_SAMPLE_INFO:
 | 
			
		||||
		sel.key = "";
 | 
			
		||||
		break;
 | 
			
		||||
	case COMMAND_GET_SINK_INFO:
 | 
			
		||||
		sel.type = is_sink;
 | 
			
		||||
		sel.key = PW_KEY_NODE_NAME;
 | 
			
		||||
| 
						 | 
				
			
			@ -3768,6 +3769,87 @@ error:
 | 
			
		|||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fill_sample_info(struct client *client, struct message *m,
 | 
			
		||||
		struct sample *sample)
 | 
			
		||||
{
 | 
			
		||||
	struct volume vol = VOLUME_INIT;
 | 
			
		||||
 | 
			
		||||
	message_put(m,
 | 
			
		||||
		TAG_U32, sample->index,
 | 
			
		||||
		TAG_STRING, sample->name,
 | 
			
		||||
		TAG_CVOLUME, &vol,
 | 
			
		||||
		TAG_USEC, 0,				/* length */
 | 
			
		||||
		TAG_SAMPLE_SPEC, &sample->ss,
 | 
			
		||||
		TAG_CHANNEL_MAP, &sample->map,
 | 
			
		||||
		TAG_U32, sample->length,
 | 
			
		||||
		TAG_BOOLEAN, false,			/* lazy */
 | 
			
		||||
		TAG_STRING, NULL,			/* filename */
 | 
			
		||||
		TAG_INVALID);
 | 
			
		||||
 | 
			
		||||
	if (client->version >= 13) {
 | 
			
		||||
		message_put(m,
 | 
			
		||||
			TAG_PROPLIST, sample->props,
 | 
			
		||||
			TAG_INVALID);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_get_sample_info(struct client *client, uint32_t command, uint32_t tag, struct message *m)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = client->impl;
 | 
			
		||||
	struct message *reply = NULL;
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
	const char *name;
 | 
			
		||||
	struct sample *sample;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	if ((res = message_get(m,
 | 
			
		||||
			TAG_U32, &id,
 | 
			
		||||
			TAG_STRING, &name,
 | 
			
		||||
			TAG_INVALID)) < 0)
 | 
			
		||||
		return -EPROTO;
 | 
			
		||||
 | 
			
		||||
	if ((id == SPA_ID_INVALID && name == NULL) ||
 | 
			
		||||
	    (id != SPA_ID_INVALID && name != NULL))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	pw_log_info(NAME" %p: [%s] %s tag:%u idx:%u name:%s", impl, client->name,
 | 
			
		||||
			commands[command].name, tag, id, name);
 | 
			
		||||
 | 
			
		||||
	if ((sample = find_sample(impl, id, name)) == NULL)
 | 
			
		||||
		return -ENOENT;
 | 
			
		||||
 | 
			
		||||
	reply = reply_new(client, tag);
 | 
			
		||||
	if ((res = fill_sample_info(client, reply, sample)) < 0)
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	return send_message(client, reply);
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	if (reply)
 | 
			
		||||
		message_free(client, reply, false, false);
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_get_sample_info_list(struct client *client, uint32_t command, uint32_t tag, struct message *m)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = client->impl;
 | 
			
		||||
	struct message *reply;
 | 
			
		||||
	union pw_map_item *item;
 | 
			
		||||
 | 
			
		||||
	pw_log_info(NAME" %p: [%s] %s tag:%u", impl, client->name,
 | 
			
		||||
			commands[command].name, tag);
 | 
			
		||||
 | 
			
		||||
	reply = reply_new(client, tag);
 | 
			
		||||
	pw_array_for_each(item, &impl->samples.items) {
 | 
			
		||||
		struct sample *s = item->data;
 | 
			
		||||
                if (pw_map_item_is_free(item))
 | 
			
		||||
			continue;
 | 
			
		||||
		fill_sample_info(client, reply, s);
 | 
			
		||||
	}
 | 
			
		||||
	return send_message(client, reply);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct info_list_data {
 | 
			
		||||
	struct client *client;
 | 
			
		||||
	struct message *reply;
 | 
			
		||||
| 
						 | 
				
			
			@ -3803,8 +3885,6 @@ static int do_get_info_list(struct client *client, uint32_t command, uint32_t ta
 | 
			
		|||
	case COMMAND_GET_CARD_INFO_LIST:
 | 
			
		||||
		info.fill_func = fill_card_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case COMMAND_GET_SAMPLE_INFO_LIST:
 | 
			
		||||
		break;
 | 
			
		||||
	case COMMAND_GET_SINK_INFO_LIST:
 | 
			
		||||
		info.fill_func = fill_sink_info;
 | 
			
		||||
		break;
 | 
			
		||||
| 
						 | 
				
			
			@ -4258,7 +4338,7 @@ static const struct command commands[COMMAND_MAX] =
 | 
			
		|||
	[COMMAND_GET_CLIENT_INFO] = { "GET_CLIENT_INFO", do_get_info, },
 | 
			
		||||
	[COMMAND_GET_SINK_INPUT_INFO] = { "GET_SINK_INPUT_INFO", do_get_info, },
 | 
			
		||||
	[COMMAND_GET_SOURCE_OUTPUT_INFO] = { "GET_SOURCE_OUTPUT_INFO", do_get_info, },
 | 
			
		||||
	[COMMAND_GET_SAMPLE_INFO] = { "GET_SAMPLE_INFO", do_get_info, },
 | 
			
		||||
	[COMMAND_GET_SAMPLE_INFO] = { "GET_SAMPLE_INFO", do_get_sample_info, },
 | 
			
		||||
	[COMMAND_GET_CARD_INFO] = { "GET_CARD_INFO", do_get_info, },
 | 
			
		||||
	[COMMAND_SUBSCRIBE] = { "SUBSCRIBE", do_subscribe, },
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4268,7 +4348,7 @@ static const struct command commands[COMMAND_MAX] =
 | 
			
		|||
	[COMMAND_GET_CLIENT_INFO_LIST] = { "GET_CLIENT_INFO_LIST", do_get_info_list, },
 | 
			
		||||
	[COMMAND_GET_SINK_INPUT_INFO_LIST] = { "GET_SINK_INPUT_INFO_LIST", do_get_info_list, },
 | 
			
		||||
	[COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = { "GET_SOURCE_OUTPUT_INFO_LIST", do_get_info_list, },
 | 
			
		||||
	[COMMAND_GET_SAMPLE_INFO_LIST] = { "GET_SAMPLE_INFO_LIST", do_get_info_list, },
 | 
			
		||||
	[COMMAND_GET_SAMPLE_INFO_LIST] = { "GET_SAMPLE_INFO_LIST", do_get_sample_info_list, },
 | 
			
		||||
	[COMMAND_GET_CARD_INFO_LIST] = { "GET_CARD_INFO_LIST", do_get_info_list, },
 | 
			
		||||
 | 
			
		||||
	[COMMAND_SET_SINK_VOLUME] = { "SET_SINK_VOLUME", do_set_volume, },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue