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);
 | 
						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;
 | 
						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) {
 | 
						pw_array_for_each(item, &impl->samples.items) {
 | 
				
			||||||
		struct sample *s = item->data;
 | 
							struct sample *s = item->data;
 | 
				
			||||||
                if (!pw_map_item_is_free(item) &&
 | 
					                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,
 | 
								impl, client->name, commands[command].name, tag,
 | 
				
			||||||
			channel, name);
 | 
								channel, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sample = find_sample(impl, name);
 | 
						sample = find_sample(impl, SPA_ID_INVALID, name);
 | 
				
			||||||
	if (sample == NULL) {
 | 
						if (sample == NULL) {
 | 
				
			||||||
		sample = calloc(1, sizeof(struct sample));
 | 
							sample = calloc(1, sizeof(struct sample));
 | 
				
			||||||
		if (sample == NULL)
 | 
							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);
 | 
						pw_properties_update(props, &client->props->dict);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sample = find_sample(impl, name);
 | 
						sample = find_sample(impl, SPA_ID_INVALID, name);
 | 
				
			||||||
	if (sample == NULL)
 | 
						if (sample == NULL)
 | 
				
			||||||
		goto error_noent;
 | 
							goto error_noent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2357,7 +2361,7 @@ static int do_remove_sample(struct client *client, uint32_t command, uint32_t ta
 | 
				
			||||||
			name);
 | 
								name);
 | 
				
			||||||
	if (name == NULL)
 | 
						if (name == NULL)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	if ((sample = find_sample(impl, name)) == NULL)
 | 
						if ((sample = find_sample(impl, SPA_ID_INVALID, name)) == NULL)
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	broadcast_subscribe_event(impl,
 | 
						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;
 | 
							sel.key = PW_KEY_DEVICE_NAME;
 | 
				
			||||||
		fill_func = fill_card_info;
 | 
							fill_func = fill_card_info;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case COMMAND_GET_SAMPLE_INFO:
 | 
					 | 
				
			||||||
		sel.key = "";
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case COMMAND_GET_SINK_INFO:
 | 
						case COMMAND_GET_SINK_INFO:
 | 
				
			||||||
		sel.type = is_sink;
 | 
							sel.type = is_sink;
 | 
				
			||||||
		sel.key = PW_KEY_NODE_NAME;
 | 
							sel.key = PW_KEY_NODE_NAME;
 | 
				
			||||||
| 
						 | 
					@ -3768,6 +3769,87 @@ error:
 | 
				
			||||||
	return res;
 | 
						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 info_list_data {
 | 
				
			||||||
	struct client *client;
 | 
						struct client *client;
 | 
				
			||||||
	struct message *reply;
 | 
						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:
 | 
						case COMMAND_GET_CARD_INFO_LIST:
 | 
				
			||||||
		info.fill_func = fill_card_info;
 | 
							info.fill_func = fill_card_info;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case COMMAND_GET_SAMPLE_INFO_LIST:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case COMMAND_GET_SINK_INFO_LIST:
 | 
						case COMMAND_GET_SINK_INFO_LIST:
 | 
				
			||||||
		info.fill_func = fill_sink_info;
 | 
							info.fill_func = fill_sink_info;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -4258,7 +4338,7 @@ static const struct command commands[COMMAND_MAX] =
 | 
				
			||||||
	[COMMAND_GET_CLIENT_INFO] = { "GET_CLIENT_INFO", do_get_info, },
 | 
						[COMMAND_GET_CLIENT_INFO] = { "GET_CLIENT_INFO", do_get_info, },
 | 
				
			||||||
	[COMMAND_GET_SINK_INPUT_INFO] = { "GET_SINK_INPUT_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_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_GET_CARD_INFO] = { "GET_CARD_INFO", do_get_info, },
 | 
				
			||||||
	[COMMAND_SUBSCRIBE] = { "SUBSCRIBE", do_subscribe, },
 | 
						[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_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_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_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_GET_CARD_INFO_LIST] = { "GET_CARD_INFO_LIST", do_get_info_list, },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[COMMAND_SET_SINK_VOLUME] = { "SET_SINK_VOLUME", do_set_volume, },
 | 
						[COMMAND_SET_SINK_VOLUME] = { "SET_SINK_VOLUME", do_set_volume, },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue