mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	pulse-server: use channelmap
Convert to an from pulse enum to id in the message layer so that we can always just deal with native spa types. Use the channelmap in stream-restore Parse the channelmap from properties.
This commit is contained in:
		
							parent
							
								
									2b95afeddc
								
							
						
					
					
						commit
						f95f278067
					
				
					 5 changed files with 108 additions and 49 deletions
				
			
		| 
						 | 
					@ -135,7 +135,7 @@ static int do_extension_stream_restore_read(struct client *client, uint32_t comm
 | 
				
			||||||
		if (key_to_name(item->key, name, sizeof(name)) < 0)
 | 
							if (key_to_name(item->key, name, sizeof(name)) < 0)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_info("%s -> %s", item->key, name);
 | 
							pw_log_debug("%s -> %s: %s", item->key, name, item->value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spa_json_init(&it[0], item->value, strlen(item->value));
 | 
							spa_json_init(&it[0], item->value, strlen(item->value));
 | 
				
			||||||
		if (spa_json_enter_object(&it[0], &it[1]) <= 0)
 | 
							if (spa_json_enter_object(&it[0], &it[1]) <= 0)
 | 
				
			||||||
| 
						 | 
					@ -151,6 +151,7 @@ static int do_extension_stream_restore_read(struct client *client, uint32_t comm
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else if (strncmp(value, "\"volumes\"", len) == 0) {
 | 
								else if (strncmp(value, "\"volumes\"", len) == 0) {
 | 
				
			||||||
 | 
									vol = VOLUME_INIT;
 | 
				
			||||||
				if (spa_json_enter_array(&it[1], &it[2]) <= 0)
 | 
									if (spa_json_enter_array(&it[1], &it[2]) <= 0)
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,6 +160,17 @@ static int do_extension_stream_restore_read(struct client *client, uint32_t comm
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								else if (strncmp(value, "\"channels\"", len) == 0) {
 | 
				
			||||||
 | 
									if (spa_json_enter_array(&it[1], &it[2]) <= 0)
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									for (map.channels = 0; map.channels < CHANNELS_MAX; map.channels++) {
 | 
				
			||||||
 | 
										char chname[16];
 | 
				
			||||||
 | 
						                                if (spa_json_get_string(&it[2], chname, sizeof(chname)) <= 0)
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										map.map[map.channels] = channel_name2id(chname);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			else if (strncmp(value, "\"target-node\"", len) == 0) {
 | 
								else if (strncmp(value, "\"target-node\"", len) == 0) {
 | 
				
			||||||
				if (spa_json_get_string(&it[1], device_name, sizeof(device_name)) <= 0)
 | 
									if (spa_json_get_string(&it[1], device_name, sizeof(device_name)) <= 0)
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
| 
						 | 
					@ -191,7 +203,7 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com
 | 
				
			||||||
		return -EPROTO;
 | 
							return -EPROTO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (m->offset < m->length) {
 | 
						while (m->offset < m->length) {
 | 
				
			||||||
		const char *name, *device_name;
 | 
							const char *name, *device_name = NULL;
 | 
				
			||||||
		struct channel_map map;
 | 
							struct channel_map map;
 | 
				
			||||||
		struct volume vol;
 | 
							struct volume vol;
 | 
				
			||||||
		bool mute = false;
 | 
							bool mute = false;
 | 
				
			||||||
| 
						 | 
					@ -201,6 +213,9 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com
 | 
				
			||||||
		size_t size;
 | 
							size_t size;
 | 
				
			||||||
		char key[1024];
 | 
							char key[1024];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spa_zero(map);
 | 
				
			||||||
 | 
							spa_zero(vol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		message_get(m,
 | 
							message_get(m,
 | 
				
			||||||
			TAG_STRING, &name,
 | 
								TAG_STRING, &name,
 | 
				
			||||||
			TAG_CHANNEL_MAP, &map,
 | 
								TAG_CHANNEL_MAP, &map,
 | 
				
			||||||
| 
						 | 
					@ -214,18 +229,26 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		f = open_memstream(&ptr, &size);
 | 
							f = open_memstream(&ptr, &size);
 | 
				
			||||||
		fprintf(f, "{");
 | 
							fprintf(f, "{");
 | 
				
			||||||
		fprintf(f, " \"mute\": %s ", mute ? "true" : "false");
 | 
							fprintf(f, " \"mute\": %s", mute ? "true" : "false");
 | 
				
			||||||
 | 
							if (vol.channels > 0) {
 | 
				
			||||||
			fprintf(f, ", \"volumes\": [");
 | 
								fprintf(f, ", \"volumes\": [");
 | 
				
			||||||
			for (i = 0; i < vol.channels; i++)
 | 
								for (i = 0; i < vol.channels; i++)
 | 
				
			||||||
				fprintf(f, "%s%f", (i == 0 ? " ":", "), vol.values[i]);
 | 
									fprintf(f, "%s%f", (i == 0 ? " ":", "), vol.values[i]);
 | 
				
			||||||
		fprintf(f, " ] ");
 | 
								fprintf(f, " ]");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (map.channels > 0) {
 | 
				
			||||||
 | 
								fprintf(f, ", \"channels\": [");
 | 
				
			||||||
 | 
								for (i = 0; i < map.channels; i++)
 | 
				
			||||||
 | 
									fprintf(f, "%s\"%s\"", (i == 0 ? " ":", "), channel_id2name(map.map[i]));
 | 
				
			||||||
 | 
								fprintf(f, " ]");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (device_name != NULL && device_name[0])
 | 
							if (device_name != NULL && device_name[0])
 | 
				
			||||||
			fprintf(f, ", \"target-node\": \"%s\"", device_name);
 | 
								fprintf(f, ", \"target-node\": \"%s\"", device_name);
 | 
				
			||||||
		fprintf(f, "}");
 | 
							fprintf(f, " }");
 | 
				
			||||||
		fclose(f);
 | 
							fclose(f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (key_from_name(name, key, sizeof(key)) >= 0) {
 | 
							if (key_from_name(name, key, sizeof(key)) >= 0) {
 | 
				
			||||||
			pw_log_info("%s -> %s", name, key);
 | 
								pw_log_debug("%s -> %s: %s", name, key, ptr);
 | 
				
			||||||
			pw_manager_set_metadata(client->manager,
 | 
								pw_manager_set_metadata(client->manager,
 | 
				
			||||||
					client->metadata_routes,
 | 
										client->metadata_routes,
 | 
				
			||||||
					PW_ID_CORE, key, "Spa:String:JSON", "%s", ptr);
 | 
										PW_ID_CORE, key, "Spa:String:JSON", "%s", ptr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,21 +72,24 @@ static inline uint32_t format_pa2id(enum sample_format format)
 | 
				
			||||||
	return audio_formats[format].format;
 | 
						return audio_formats[format].format;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline const char *format_pa2name(enum sample_format format)
 | 
					static inline const char *format_id2name(uint32_t format)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (format < 0 || (size_t)format >= SPA_N_ELEMENTS(audio_formats))
 | 
						int i;
 | 
				
			||||||
		return "invalid";
 | 
						for (i = 0; spa_type_audio_format[i].name; i++) {
 | 
				
			||||||
	return audio_formats[format].name;
 | 
							if (spa_type_audio_format[i].type == format)
 | 
				
			||||||
 | 
								return spa_debug_type_short_name(spa_type_audio_format[i].name);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "UNKNOWN";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline enum sample_format format_name2pa(const char *name, size_t size)
 | 
					static inline uint32_t format_paname2id(const char *name, size_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	size_t i;
 | 
						size_t i;
 | 
				
			||||||
	for (i = 0; i < SPA_N_ELEMENTS(audio_formats); i++) {
 | 
						for (i = 0; i < SPA_N_ELEMENTS(audio_formats); i++) {
 | 
				
			||||||
		if (strncmp(name, audio_formats[i].name, size) == 0)
 | 
							if (strncmp(name, audio_formats[i].name, size) == 0)
 | 
				
			||||||
			return i;
 | 
								return audio_formats[i].format;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return SAMPLE_INVALID;
 | 
						return SPA_AUDIO_FORMAT_UNKNOWN;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline enum sample_format format_id2pa(uint32_t id)
 | 
					static inline enum sample_format format_id2pa(uint32_t id)
 | 
				
			||||||
| 
						 | 
					@ -100,26 +103,42 @@ static inline enum sample_format format_id2pa(uint32_t id)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sample_spec {
 | 
					struct sample_spec {
 | 
				
			||||||
	enum sample_format format;
 | 
						uint32_t format;
 | 
				
			||||||
	uint32_t rate;
 | 
						uint32_t rate;
 | 
				
			||||||
	uint8_t channels;
 | 
						uint8_t channels;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#define SAMPLE_SPEC_INIT	(struct sample_spec) {			\
 | 
					#define SAMPLE_SPEC_INIT	(struct sample_spec) {			\
 | 
				
			||||||
					.format = SAMPLE_FLOAT32LE,	\
 | 
										.format = SPA_AUDIO_FORMAT_F32,	\
 | 
				
			||||||
					.rate = 44100,			\
 | 
										.rate = 44100,			\
 | 
				
			||||||
					.channels = 2,			\
 | 
										.channels = 2,			\
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline uint32_t sample_spec_frame_size(const struct sample_spec *ss)
 | 
					static inline uint32_t sample_spec_frame_size(const struct sample_spec *ss)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (ss->format < 0 || (size_t)ss->format >= SPA_N_ELEMENTS(audio_formats))
 | 
						switch (ss->format) {
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_U8:
 | 
				
			||||||
 | 
							return ss->channels;
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_S16_LE:
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_S16_BE:
 | 
				
			||||||
 | 
							return 2 * ss->channels;
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_S24_LE:
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_S24_BE:
 | 
				
			||||||
 | 
							return 3 * ss->channels;
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_F32_LE:
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_F32_BE:
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_S32_LE:
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_S32_BE:
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_S24_32_LE:
 | 
				
			||||||
 | 
						case SPA_AUDIO_FORMAT_S24_32_BE:
 | 
				
			||||||
 | 
							return 4 * ss->channels;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	return audio_formats[ss->format].size * ss->channels;
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool sample_spec_valid(const struct sample_spec *ss)
 | 
					static inline bool sample_spec_valid(const struct sample_spec *ss)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return (ss->format < SAMPLE_MAX &&
 | 
						return (sample_spec_frame_size(ss) > 0 &&
 | 
				
			||||||
	    ss->rate > 0 && ss->rate <= RATE_MAX &&
 | 
						    ss->rate > 0 && ss->rate <= RATE_MAX &&
 | 
				
			||||||
	    ss->channels > 0 && ss->channels <= CHANNELS_MAX);
 | 
						    ss->channels > 0 && ss->channels <= CHANNELS_MAX);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -256,13 +275,13 @@ static const struct channel audio_channels[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct channel_map {
 | 
					struct channel_map {
 | 
				
			||||||
	uint8_t channels;
 | 
						uint8_t channels;
 | 
				
			||||||
	enum channel_position map[CHANNELS_MAX];
 | 
						uint32_t map[CHANNELS_MAX];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHANNEL_MAP_INIT	(struct channel_map) {				\
 | 
					#define CHANNEL_MAP_INIT	(struct channel_map) {				\
 | 
				
			||||||
					.channels = 2,				\
 | 
										.channels = 2,				\
 | 
				
			||||||
					.map[0] = CHANNEL_POSITION_FRONT_LEFT,	\
 | 
										.map[0] = SPA_AUDIO_CHANNEL_FL,		\
 | 
				
			||||||
					.map[1] = CHANNEL_POSITION_FRONT_RIGHT,	\
 | 
										.map[1] = SPA_AUDIO_CHANNEL_FR,		\
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline uint32_t channel_pa2id(enum channel_position channel)
 | 
					static inline uint32_t channel_pa2id(enum channel_position channel)
 | 
				
			||||||
| 
						 | 
					@ -272,11 +291,24 @@ static inline uint32_t channel_pa2id(enum channel_position channel)
 | 
				
			||||||
        return audio_channels[channel].channel;
 | 
					        return audio_channels[channel].channel;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline const char *channel_pa2name(enum channel_position channel)
 | 
					static inline const char *channel_id2name(uint32_t channel)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
        if (channel < 0 || (size_t)channel >= SPA_N_ELEMENTS(audio_channels))
 | 
						int i;
 | 
				
			||||||
                return "invalid";
 | 
						for (i = 0; spa_type_audio_channel[i].name; i++) {
 | 
				
			||||||
        return audio_channels[channel].name;
 | 
							if (spa_type_audio_channel[i].type == channel)
 | 
				
			||||||
 | 
								return spa_debug_type_short_name(spa_type_audio_channel[i].name);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "UNK";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint32_t channel_name2id(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; spa_type_audio_channel[i].name; i++) {
 | 
				
			||||||
 | 
							if (strcmp(name, spa_type_audio_channel[i].name) == 0)
 | 
				
			||||||
 | 
								return spa_type_audio_channel[i].type;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return SPA_AUDIO_CHANNEL_UNKNOWN;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline enum channel_position channel_id2pa(uint32_t id, uint32_t *aux)
 | 
					static inline enum channel_position channel_id2pa(uint32_t id, uint32_t *aux)
 | 
				
			||||||
| 
						 | 
					@ -290,14 +322,14 @@ static inline enum channel_position channel_id2pa(uint32_t id, uint32_t *aux)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline enum channel_position channel_name2pa(const char *name, size_t size)
 | 
					static inline uint32_t channel_paname2id(const char *name, size_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	size_t i;
 | 
						size_t i;
 | 
				
			||||||
	for (i = 0; i < SPA_N_ELEMENTS(audio_channels); i++) {
 | 
						for (i = 0; i < SPA_N_ELEMENTS(audio_channels); i++) {
 | 
				
			||||||
		if (strncmp(name, audio_channels[i].name, size) == 0)
 | 
							if (strncmp(name, audio_channels[i].name, size) == 0)
 | 
				
			||||||
			return i;
 | 
								return audio_channels[i].channel;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return CHANNEL_POSITION_INVALID;
 | 
						return SPA_AUDIO_CHANNEL_UNKNOWN;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -305,7 +337,7 @@ static inline void channel_map_to_positions(const struct channel_map *map, uint3
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	for (i = 0; i < map->channels; i++)
 | 
						for (i = 0; i < map->channels; i++)
 | 
				
			||||||
		pos[i] = channel_pa2id(map->map[i]);
 | 
							pos[i] = map->map[i];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool channel_map_valid(const struct channel_map *map)
 | 
					static inline bool channel_map_valid(const struct channel_map *map)
 | 
				
			||||||
| 
						 | 
					@ -314,7 +346,7 @@ static inline bool channel_map_valid(const struct channel_map *map)
 | 
				
			||||||
	if (map->channels == 0 || map->channels > CHANNELS_MAX)
 | 
						if (map->channels == 0 || map->channels > CHANNELS_MAX)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	for (i = 0; i < map->channels; i++)
 | 
						for (i = 0; i < map->channels; i++)
 | 
				
			||||||
		if (map->map[i] < 0 || map->map[i] >= CHANNEL_POSITION_MAX)
 | 
							if (map->map[i] >= CHANNEL_POSITION_MAX)
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -349,7 +381,7 @@ static void format_info_clear(struct format_info *info)
 | 
				
			||||||
static int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, struct channel_map *map)
 | 
					static int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, struct channel_map *map)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct spa_audio_info info = { 0 };
 | 
						struct spa_audio_info info = { 0 };
 | 
				
			||||||
	uint32_t i, aux = 0;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        spa_format_parse(param, &info.media_type, &info.media_subtype);
 | 
					        spa_format_parse(param, &info.media_type, &info.media_subtype);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -360,17 +392,14 @@ static int format_parse_param(const struct spa_pod *param, struct sample_spec *s
 | 
				
			||||||
                return -ENOTSUP;
 | 
					                return -ENOTSUP;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
	if (ss) {
 | 
						if (ss) {
 | 
				
			||||||
	        ss->format = format_id2pa(info.info.raw.format);
 | 
						        ss->format = info.info.raw.format;
 | 
				
			||||||
	        if (ss->format == SAMPLE_INVALID)
 | 
					 | 
				
			||||||
	                return -ENOTSUP;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	        ss->rate = info.info.raw.rate;
 | 
						        ss->rate = info.info.raw.rate;
 | 
				
			||||||
	        ss->channels = info.info.raw.channels;
 | 
						        ss->channels = info.info.raw.channels;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (map) {
 | 
						if (map) {
 | 
				
			||||||
		map->channels = info.info.raw.channels;
 | 
							map->channels = info.info.raw.channels;
 | 
				
			||||||
		for (i = 0; i < map->channels; i++)
 | 
							for (i = 0; i < map->channels; i++)
 | 
				
			||||||
			map->map[i] = channel_id2pa(info.info.raw.position[i], &aux);
 | 
								map->map[i] = info.info.raw.position[i];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -381,7 +410,7 @@ static const struct spa_pod *format_build_param(struct spa_pod_builder *b,
 | 
				
			||||||
	struct spa_audio_info_raw info;
 | 
						struct spa_audio_info_raw info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info = SPA_AUDIO_INFO_RAW_INIT(
 | 
						info = SPA_AUDIO_INFO_RAW_INIT(
 | 
				
			||||||
			.format = format_pa2id(spec->format),
 | 
								.format = spec->format,
 | 
				
			||||||
			.channels = spec->channels,
 | 
								.channels = spec->channels,
 | 
				
			||||||
			.rate = spec->rate);
 | 
								.rate = spec->rate);
 | 
				
			||||||
	if (map)
 | 
						if (map)
 | 
				
			||||||
| 
						 | 
					@ -406,8 +435,8 @@ static const struct spa_pod *format_info_build_param(struct spa_pod_builder *b,
 | 
				
			||||||
	if (str[0] != '\"')
 | 
						if (str[0] != '\"')
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	size = strcspn(++str, "\"");
 | 
						size = strcspn(++str, "\"");
 | 
				
			||||||
	ss.format = format_name2pa(str, size);
 | 
						ss.format = format_paname2id(str, size);
 | 
				
			||||||
	if (ss.format == SAMPLE_INVALID)
 | 
						if (ss.format == SPA_AUDIO_FORMAT_UNKNOWN)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = pw_properties_get(info->props, "format.rate")) == NULL)
 | 
						if ((str = pw_properties_get(info->props, "format.rate")) == NULL)
 | 
				
			||||||
| 
						 | 
					@ -421,7 +450,7 @@ static const struct spa_pod *format_info_build_param(struct spa_pod_builder *b,
 | 
				
			||||||
	if ((str = pw_properties_get(info->props, "format.channel_map")) != NULL) {
 | 
						if ((str = pw_properties_get(info->props, "format.channel_map")) != NULL) {
 | 
				
			||||||
		while ((*str == '\"' || *str == ',') &&
 | 
							while ((*str == '\"' || *str == ',') &&
 | 
				
			||||||
		    (size = strcspn(++str, "\",")) > 0) {
 | 
							    (size = strcspn(++str, "\",")) > 0) {
 | 
				
			||||||
			map.map[map.channels++] = channel_name2pa(str, size);
 | 
								map.map[map.channels++] = channel_paname2id(str, size);
 | 
				
			||||||
			str += size;
 | 
								str += size;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (map.channels == ss.channels)
 | 
							if (map.channels == ss.channels)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,7 +164,7 @@ static int read_sample_spec(struct message *m, struct sample_spec *ss)
 | 
				
			||||||
	uint8_t tmp;
 | 
						uint8_t tmp;
 | 
				
			||||||
	if ((res = read_u8(m, &tmp)) < 0)
 | 
						if ((res = read_u8(m, &tmp)) < 0)
 | 
				
			||||||
		return res;
 | 
							return res;
 | 
				
			||||||
	ss->format = tmp;
 | 
						ss->format = format_pa2id(tmp);
 | 
				
			||||||
	if ((res = read_u8(m, &ss->channels)) < 0)
 | 
						if ((res = read_u8(m, &ss->channels)) < 0)
 | 
				
			||||||
		return res;
 | 
							return res;
 | 
				
			||||||
	return read_u32(m, &ss->rate);
 | 
						return read_u32(m, &ss->rate);
 | 
				
			||||||
| 
						 | 
					@ -264,7 +264,7 @@ static int read_channel_map(struct message *m, struct channel_map *map)
 | 
				
			||||||
	for (i = 0; i < map->channels; i ++) {
 | 
						for (i = 0; i < map->channels; i ++) {
 | 
				
			||||||
		if ((res = read_u8(m, &tmp)) < 0)
 | 
							if ((res = read_u8(m, &tmp)) < 0)
 | 
				
			||||||
			return res;
 | 
								return res;
 | 
				
			||||||
		map->map[i] = tmp;
 | 
							map->map[i] = channel_pa2id(tmp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -498,7 +498,7 @@ static void write_64(struct message *m, uint8_t tag, uint64_t val)
 | 
				
			||||||
static void write_sample_spec(struct message *m, struct sample_spec *ss)
 | 
					static void write_sample_spec(struct message *m, struct sample_spec *ss)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	write_8(m, TAG_SAMPLE_SPEC);
 | 
						write_8(m, TAG_SAMPLE_SPEC);
 | 
				
			||||||
	write_8(m, ss->format);
 | 
						write_8(m, format_id2pa(ss->format));
 | 
				
			||||||
	write_8(m, ss->channels);
 | 
						write_8(m, ss->channels);
 | 
				
			||||||
	write_32(m, ss->rate);
 | 
						write_32(m, ss->rate);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -527,10 +527,11 @@ static void write_timeval(struct message *m, struct timeval *tv)
 | 
				
			||||||
static void write_channel_map(struct message *m, struct channel_map *map)
 | 
					static void write_channel_map(struct message *m, struct channel_map *map)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint8_t i;
 | 
						uint8_t i;
 | 
				
			||||||
 | 
						uint32_t aux = 0;
 | 
				
			||||||
	write_8(m, TAG_CHANNEL_MAP);
 | 
						write_8(m, TAG_CHANNEL_MAP);
 | 
				
			||||||
	write_8(m, map->channels);
 | 
						write_8(m, map->channels);
 | 
				
			||||||
	for (i = 0; i < map->channels; i ++)
 | 
						for (i = 0; i < map->channels; i ++)
 | 
				
			||||||
		write_8(m, map->map[i]);
 | 
							write_8(m, channel_id2pa(map->map[i], &aux));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void write_volume(struct message *m, float vol)
 | 
					static void write_volume(struct message *m, float vol)
 | 
				
			||||||
| 
						 | 
					@ -768,7 +769,7 @@ static int message_dump(enum spa_log_level level, struct message *m)
 | 
				
			||||||
			if ((res = read_sample_spec(m, &ss)) < 0)
 | 
								if ((res = read_sample_spec(m, &ss)) < 0)
 | 
				
			||||||
				return res;
 | 
									return res;
 | 
				
			||||||
			pw_log(level, "%u: ss: format:%s rate:%d channels:%u", o,
 | 
								pw_log(level, "%u: ss: format:%s rate:%d channels:%u", o,
 | 
				
			||||||
					format_pa2name(ss.format), ss.rate,
 | 
										format_id2name(ss.format), ss.rate,
 | 
				
			||||||
					ss.channels);
 | 
										ss.channels);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -802,7 +803,7 @@ static int message_dump(enum spa_log_level level, struct message *m)
 | 
				
			||||||
				return res;
 | 
									return res;
 | 
				
			||||||
			pw_log(level, "%u: channelmap: channels:%u", o, map.channels);
 | 
								pw_log(level, "%u: channelmap: channels:%u", o, map.channels);
 | 
				
			||||||
			for (i = 0; i < map.channels; i++)
 | 
								for (i = 0; i < map.channels; i++)
 | 
				
			||||||
				pw_log(level, "    %d: %s", i, channel_pa2name(map.map[i]));
 | 
									pw_log(level, "    %d: %s", i, channel_id2name(map.map[i]));
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		case TAG_CVOLUME:
 | 
							case TAG_CVOLUME:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,7 @@
 | 
				
			||||||
#include <spa/utils/result.h>
 | 
					#include <spa/utils/result.h>
 | 
				
			||||||
#include <spa/debug/dict.h>
 | 
					#include <spa/debug/dict.h>
 | 
				
			||||||
#include <spa/debug/mem.h>
 | 
					#include <spa/debug/mem.h>
 | 
				
			||||||
 | 
					#include <spa/debug/types.h>
 | 
				
			||||||
#include <spa/param/audio/raw.h>
 | 
					#include <spa/param/audio/raw.h>
 | 
				
			||||||
#include <spa/pod/pod.h>
 | 
					#include <spa/pod/pod.h>
 | 
				
			||||||
#include <spa/param/audio/format-utils.h>
 | 
					#include <spa/param/audio/format-utils.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,7 @@ struct volume {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct volume_info {
 | 
					struct volume_info {
 | 
				
			||||||
	struct volume volume;
 | 
						struct volume volume;
 | 
				
			||||||
 | 
						struct channel_map map;
 | 
				
			||||||
	bool mute;
 | 
						bool mute;
 | 
				
			||||||
	float level;
 | 
						float level;
 | 
				
			||||||
	float base;
 | 
						float base;
 | 
				
			||||||
| 
						 | 
					@ -87,6 +88,10 @@ static int volume_parse_param(const struct spa_pod *param, struct volume_info *i
 | 
				
			||||||
				info->steps = 0x10000u * step;
 | 
									info->steps = 0x10000u * step;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							case SPA_PROP_channelMap:
 | 
				
			||||||
 | 
								info->map.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Id,
 | 
				
			||||||
 | 
										info->map.map, SPA_AUDIO_MAX_CHANNELS);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue