mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	media-session/pulse-server: more error checks + minor fixes
This commit is contained in:
		
							parent
							
								
									f330446291
								
							
						
					
					
						commit
						2681b8236b
					
				
					 10 changed files with 79 additions and 54 deletions
				
			
		| 
						 | 
				
			
			@ -908,6 +908,7 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id,
 | 
			
		|||
	if (impl->conn &&
 | 
			
		||||
	    (card = spa_dict_lookup(info->props, SPA_KEY_API_ALSA_CARD)) != NULL) {
 | 
			
		||||
		const char *reserve;
 | 
			
		||||
		const char *path = spa_dict_lookup(info->props, SPA_KEY_API_ALSA_PATH);
 | 
			
		||||
 | 
			
		||||
		device->priority -= atol(card) * 64;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -920,9 +921,10 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id,
 | 
			
		|||
 | 
			
		||||
		if (device->reserve == NULL) {
 | 
			
		||||
			pw_log_warn("can't create device reserve for %s: %m", reserve);
 | 
			
		||||
		} else if (path) {
 | 
			
		||||
			rd_device_set_application_device_name(device->reserve, path);
 | 
			
		||||
		} else {
 | 
			
		||||
			rd_device_set_application_device_name(device->reserve,
 | 
			
		||||
				spa_dict_lookup(info->props, SPA_KEY_API_ALSA_PATH));
 | 
			
		||||
			pw_log_warn("empty reserve device path for %s", reserve);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (device->reserve != NULL)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -536,7 +536,7 @@ static int find_node(void *data, struct node *node)
 | 
			
		|||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (strcmp(node->media, find->media) != 0) {
 | 
			
		||||
	if (node->media && strcmp(node->media, find->media) != 0) {
 | 
			
		||||
		pw_log_debug(".. incompatible media %s <-> %s", node->media, find->media);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -158,11 +158,13 @@ static char *serialize_props(struct stream *str, const struct spa_pod *param)
 | 
			
		|||
	SPA_POD_OBJECT_FOREACH(obj, prop) {
 | 
			
		||||
		switch (prop->key) {
 | 
			
		||||
		case SPA_PROP_volume:
 | 
			
		||||
			spa_pod_get_float(&prop->value, &val);
 | 
			
		||||
			if (spa_pod_get_float(&prop->value, &val) < 0)
 | 
			
		||||
				continue;
 | 
			
		||||
			fprintf(f, "%s\"volume\": %f", (comma ? ", " : ""), val);
 | 
			
		||||
			break;
 | 
			
		||||
		case SPA_PROP_mute:
 | 
			
		||||
			spa_pod_get_bool(&prop->value, &b);
 | 
			
		||||
			if (spa_pod_get_bool(&prop->value, &b) < 0)
 | 
			
		||||
				continue;
 | 
			
		||||
			fprintf(f, "%s\"mute\": %s", (comma ? ", " : ""), b ? "true" : "false");
 | 
			
		||||
			break;
 | 
			
		||||
		case SPA_PROP_channelVolumes:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -615,7 +615,8 @@ static uint32_t collect_transport_codec_info(struct pw_manager_object *card,
 | 
			
		|||
 | 
			
		||||
		/* Codec description list */
 | 
			
		||||
		spa_pod_parser_pod(&prs, (struct spa_pod *)labels);
 | 
			
		||||
		spa_pod_parser_push_struct(&prs, &f);
 | 
			
		||||
		if (spa_pod_parser_push_struct(&prs, &f) < 0)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		while (1) {
 | 
			
		||||
			int32_t id;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -212,13 +212,14 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com
 | 
			
		|||
		spa_zero(map);
 | 
			
		||||
		spa_zero(vol);
 | 
			
		||||
 | 
			
		||||
		message_get(m,
 | 
			
		||||
		if (message_get(m,
 | 
			
		||||
				TAG_STRING, &name,
 | 
			
		||||
				TAG_CHANNEL_MAP, &map,
 | 
			
		||||
				TAG_CVOLUME, &vol,
 | 
			
		||||
				TAG_STRING, &device_name,
 | 
			
		||||
				TAG_BOOLEAN, &mute,
 | 
			
		||||
			TAG_INVALID);
 | 
			
		||||
				TAG_INVALID) < 0)
 | 
			
		||||
			return -EPROTO;
 | 
			
		||||
 | 
			
		||||
		if (name == NULL || name[0] == '\0')
 | 
			
		||||
			return -EPROTO;
 | 
			
		||||
| 
						 | 
				
			
			@ -247,9 +248,10 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com
 | 
			
		|||
 | 
			
		||||
		if (key_from_name(name, key, sizeof(key)) >= 0) {
 | 
			
		||||
			pw_log_debug("%s -> %s: %s", name, key, ptr);
 | 
			
		||||
			pw_manager_set_metadata(client->manager,
 | 
			
		||||
			if (pw_manager_set_metadata(client->manager,
 | 
			
		||||
							client->metadata_routes,
 | 
			
		||||
					PW_ID_CORE, key, "Spa:String:JSON", "%s", ptr);
 | 
			
		||||
							PW_ID_CORE, key, "Spa:String:JSON", "%s", ptr) < 0)
 | 
			
		||||
				pw_log_warn(NAME ": failed to set metadata %s = %s", key, ptr);
 | 
			
		||||
		}
 | 
			
		||||
		free(ptr);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -537,7 +537,8 @@ static int format_parse_param(const struct spa_pod *param, struct sample_spec *s
 | 
			
		|||
	struct spa_audio_info info = { 0 };
 | 
			
		||||
	uint32_t i;
 | 
			
		||||
 | 
			
		||||
        spa_format_parse(param, &info.media_type, &info.media_subtype);
 | 
			
		||||
	if (spa_format_parse(param, &info.media_type, &info.media_subtype) < 0)
 | 
			
		||||
		return -ENOTSUP;
 | 
			
		||||
 | 
			
		||||
	if (info.media_type != SPA_MEDIA_TYPE_audio ||
 | 
			
		||||
	    info.media_subtype != SPA_MEDIA_SUBTYPE_raw ||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -522,11 +522,13 @@ destroy_proxy(void *data)
 | 
			
		|||
{
 | 
			
		||||
	struct object *o = data;
 | 
			
		||||
 | 
			
		||||
	spa_assert(o->info);
 | 
			
		||||
 | 
			
		||||
	if (o->info->events)
 | 
			
		||||
		spa_hook_remove(&o->object_listener);
 | 
			
		||||
	spa_hook_remove(&o->proxy_listener);
 | 
			
		||||
 | 
			
		||||
	if (o->info && o->info->destroy)
 | 
			
		||||
	if (o->info->destroy)
 | 
			
		||||
                o->info->destroy(o);
 | 
			
		||||
 | 
			
		||||
        o->this.proxy = NULL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -326,7 +326,7 @@ static int read_format_info(struct message *m, struct format_info *info)
 | 
			
		|||
static int message_get(struct message *m, ...)
 | 
			
		||||
{
 | 
			
		||||
	va_list va;
 | 
			
		||||
	int res;
 | 
			
		||||
	int res = 0;
 | 
			
		||||
 | 
			
		||||
	va_start(va, m);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -342,102 +342,109 @@ static int message_get(struct message *m, ...)
 | 
			
		|||
		switch (dtag) {
 | 
			
		||||
		case TAG_STRING:
 | 
			
		||||
			if (tag != TAG_STRING)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_string(m, va_arg(va, char**))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_STRING_NULL:
 | 
			
		||||
			if (tag != TAG_STRING)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			*va_arg(va, char**) = NULL;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_U8:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_u8(m, va_arg(va, uint8_t*))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_U32:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_u32(m, va_arg(va, uint32_t*))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_S64:
 | 
			
		||||
		case TAG_U64:
 | 
			
		||||
		case TAG_USEC:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_u64(m, va_arg(va, uint64_t*))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_SAMPLE_SPEC:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_sample_spec(m, va_arg(va, struct sample_spec*))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_ARBITRARY:
 | 
			
		||||
		{
 | 
			
		||||
			const void **val = va_arg(va, const void**);
 | 
			
		||||
			size_t *len = va_arg(va, size_t*);
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_arbitrary(m, val, len)) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case TAG_BOOLEAN_TRUE:
 | 
			
		||||
			if (tag != TAG_BOOLEAN)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			*va_arg(va, bool*) = true;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_BOOLEAN_FALSE:
 | 
			
		||||
			if (tag != TAG_BOOLEAN)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			*va_arg(va, bool*) = false;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_TIMEVAL:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_timeval(m, va_arg(va, struct timeval*))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_CHANNEL_MAP:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_channel_map(m, va_arg(va, struct channel_map*))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_CVOLUME:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_cvolume(m, va_arg(va, struct volume*))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_PROPLIST:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_props(m, va_arg(va, struct pw_properties*), true)) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_VOLUME:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_volume(m, va_arg(va, float*))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		case TAG_FORMAT_INFO:
 | 
			
		||||
			if (dtag != tag)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
				goto invalid;
 | 
			
		||||
			if ((res = read_format_info(m, va_arg(va, struct format_info*))) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
				goto done;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	res = 0;
 | 
			
		||||
	goto done;
 | 
			
		||||
 | 
			
		||||
invalid:
 | 
			
		||||
	res = -EINVAL;
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
	va_end(va);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ensure_size(struct message *m, uint32_t size)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1914,7 +1914,7 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
 | 
			
		|||
	struct channel_map map;
 | 
			
		||||
	uint32_t sink_index, syncid;
 | 
			
		||||
	const char *sink_name;
 | 
			
		||||
	struct buffer_attr attr;
 | 
			
		||||
	struct buffer_attr attr = { 0 };
 | 
			
		||||
	bool corked = false,
 | 
			
		||||
		no_remap = false,
 | 
			
		||||
		no_remix = false,
 | 
			
		||||
| 
						 | 
				
			
			@ -2178,8 +2178,8 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
 | 
			
		|||
		fail_on_suspend = false,
 | 
			
		||||
		relative_volume = false,
 | 
			
		||||
		passthrough = false;
 | 
			
		||||
	uint32_t direct_on_input_idx;
 | 
			
		||||
	struct volume volume;
 | 
			
		||||
	uint32_t direct_on_input_idx = SPA_ID_INVALID;
 | 
			
		||||
	struct volume volume = VOLUME_INIT;
 | 
			
		||||
	struct pw_properties *props = NULL;
 | 
			
		||||
	uint8_t n_formats = 0;
 | 
			
		||||
	struct stream *stream = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -2287,6 +2287,8 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
 | 
			
		|||
				TAG_BOOLEAN, &passthrough,
 | 
			
		||||
				TAG_INVALID)) < 0)
 | 
			
		||||
			goto error_protocol;
 | 
			
		||||
	} else {
 | 
			
		||||
		volume_set = false;
 | 
			
		||||
	}
 | 
			
		||||
	if (sample_spec_valid(&ss)) {
 | 
			
		||||
		if (n_params < MAX_FORMATS &&
 | 
			
		||||
| 
						 | 
				
			
			@ -4576,7 +4578,10 @@ error:
 | 
			
		|||
static uint64_t bytes_to_usec(uint64_t length, const struct sample_spec *ss)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t u;
 | 
			
		||||
	u = length / sample_spec_frame_size(ss);
 | 
			
		||||
	uint64_t frame_size = sample_spec_frame_size(ss);
 | 
			
		||||
	if (frame_size == 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
	u = length / frame_size;
 | 
			
		||||
	u *= SPA_USEC_PER_SEC;
 | 
			
		||||
	u /= ss->rate;
 | 
			
		||||
	return u;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,13 +91,15 @@ static int volume_parse_param(const struct spa_pod *param, struct volume_info *i
 | 
			
		|||
	SPA_POD_OBJECT_FOREACH(obj, prop) {
 | 
			
		||||
		switch (prop->key) {
 | 
			
		||||
		case SPA_PROP_volume:
 | 
			
		||||
			spa_pod_get_float(&prop->value, &info->level);
 | 
			
		||||
			if (spa_pod_get_float(&prop->value, &info->level) < 0)
 | 
			
		||||
				continue;
 | 
			
		||||
			SPA_FLAG_UPDATE(info->flags, VOLUME_HW_VOLUME,
 | 
			
		||||
                                        prop->flags & SPA_POD_PROP_FLAG_HARDWARE);
 | 
			
		||||
 | 
			
		||||
			break;
 | 
			
		||||
		case SPA_PROP_mute:
 | 
			
		||||
			spa_pod_get_bool(&prop->value, &info->mute);
 | 
			
		||||
			if (spa_pod_get_bool(&prop->value, &info->mute) < 0)
 | 
			
		||||
				continue;
 | 
			
		||||
			SPA_FLAG_UPDATE(info->flags, VOLUME_HW_MUTE,
 | 
			
		||||
                                        prop->flags & SPA_POD_PROP_FLAG_HARDWARE);
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +110,8 @@ static int volume_parse_param(const struct spa_pod *param, struct volume_info *i
 | 
			
		|||
                                        prop->flags & SPA_POD_PROP_FLAG_HARDWARE);
 | 
			
		||||
			break;
 | 
			
		||||
		case SPA_PROP_volumeBase:
 | 
			
		||||
			spa_pod_get_float(&prop->value, &info->base);
 | 
			
		||||
			if (spa_pod_get_float(&prop->value, &info->base) < 0)
 | 
			
		||||
				continue;
 | 
			
		||||
			break;
 | 
			
		||||
		case SPA_PROP_volumeStep:
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue