diff --git a/src/modules/module-protocol-pulse/collect.c b/src/modules/module-protocol-pulse/collect.c index 2ae92b5b4..78a00fb42 100644 --- a/src/modules/module-protocol-pulse/collect.c +++ b/src/modules/module-protocol-pulse/collect.c @@ -232,7 +232,7 @@ uint32_t find_profile_id(struct pw_manager_object *card, const char *name) } void collect_device_info(struct pw_manager_object *device, struct pw_manager_object *card, - struct device_info *dev_info, bool monitor) + struct device_info *dev_info, bool monitor, struct defs *defs) { struct pw_manager_param *p; @@ -266,12 +266,14 @@ void collect_device_info(struct pw_manager_object *device, struct pw_manager_obj { struct spa_pod *copy = spa_pod_copy(p->param); spa_pod_fixate(copy); - format_parse_param(copy, &dev_info->ss, &dev_info->map); + format_parse_param(copy, &dev_info->ss, &dev_info->map, + &defs->sample_spec, &defs->channel_map); free(copy); break; } case SPA_PARAM_Format: - format_parse_param(p->param, &dev_info->ss, &dev_info->map); + format_parse_param(p->param, &dev_info->ss, &dev_info->map, + NULL, NULL); break; case SPA_PARAM_Props: diff --git a/src/modules/module-protocol-pulse/collect.h b/src/modules/module-protocol-pulse/collect.h index 56bbc4c4a..ad15846ea 100644 --- a/src/modules/module-protocol-pulse/collect.h +++ b/src/modules/module-protocol-pulse/collect.h @@ -32,6 +32,7 @@ #include #include +#include "internal.h" #include "format.h" #include "volume.h" @@ -79,7 +80,7 @@ struct device_info { } void collect_device_info(struct pw_manager_object *device, struct pw_manager_object *card, - struct device_info *dev_info, bool monitor); + struct device_info *dev_info, bool monitor, struct defs *defs); /* ========================================================================== */ diff --git a/src/modules/module-protocol-pulse/format.c b/src/modules/module-protocol-pulse/format.c index 04bd6f2bd..7c111a695 100644 --- a/src/modules/module-protocol-pulse/format.c +++ b/src/modules/module-protocol-pulse/format.c @@ -424,7 +424,27 @@ static enum encoding format_encoding_from_id(uint32_t id) return ENCODING_ANY; } -int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, struct channel_map *map) +static inline int +audio_raw_parse_opt(const struct spa_pod *format, struct spa_audio_info_raw *info) +{ + struct spa_pod *position = NULL; + int res; + info->flags = 0; + res = spa_pod_parse_object(format, + SPA_TYPE_OBJECT_Format, NULL, + SPA_FORMAT_AUDIO_format, SPA_POD_OPT_Id(&info->format), + SPA_FORMAT_AUDIO_rate, SPA_POD_OPT_Int(&info->rate), + SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels), + SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); + if (position == NULL || + !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) + SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); + + return res; +} + +int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, struct channel_map *map, + const struct sample_spec *def_ss, const struct channel_map *def_map) { struct spa_audio_info info = { 0 }; uint32_t i; @@ -437,8 +457,15 @@ int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, stru switch (info.media_subtype) { case SPA_MEDIA_SUBTYPE_raw: - if (spa_format_audio_raw_parse(param, &info.info.raw) < 0) - return -ENOTSUP; + if (def_ss != NULL) { + if (ss != NULL) + *ss = *def_ss; + if (audio_raw_parse_opt(param, &info.info.raw) < 0) + return -ENOTSUP; + } else { + if (spa_format_audio_raw_parse(param, &info.info.raw) < 0) + return -ENOTSUP; + } break; case SPA_MEDIA_SUBTYPE_iec958: { @@ -458,9 +485,12 @@ int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, stru return -ENOTSUP; } if (ss) { - ss->format = info.info.raw.format; - ss->rate = info.info.raw.rate; - ss->channels = info.info.raw.channels; + if (info.info.raw.format) + ss->format = info.info.raw.format; + if (info.info.raw.rate) + ss->rate = info.info.raw.rate; + if (info.info.raw.channels) + ss->channels = info.info.raw.channels; } if (map) { map->channels = info.info.raw.channels; diff --git a/src/modules/module-protocol-pulse/format.h b/src/modules/module-protocol-pulse/format.h index 2173bedc7..0acdce349 100644 --- a/src/modules/module-protocol-pulse/format.h +++ b/src/modules/module-protocol-pulse/format.h @@ -205,7 +205,8 @@ void channel_map_parse(const char *str, struct channel_map *map); bool channel_map_valid(const struct channel_map *map); int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, - struct channel_map *map); + struct channel_map *map, const struct sample_spec *def_ss, + const struct channel_map *def_map); const struct spa_pod *format_build_param(struct spa_pod_builder *b, uint32_t id, const struct sample_spec *spec, const struct channel_map *map); diff --git a/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c b/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c index c58fd0d46..f850bef77 100644 --- a/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c +++ b/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c @@ -233,6 +233,7 @@ static char* channel_map_snprint(char *s, size_t l, const struct channel_map *ma static void get_service_data(struct module_zeroconf_publish_data *d, struct service *s, struct pw_manager_object *o) { + struct impl *impl = d->module->impl; bool is_sink = pw_manager_object_is_sink(o); bool is_source = pw_manager_object_is_source(o); struct pw_node_info *info = o->info; @@ -265,7 +266,7 @@ static void get_service_data(struct module_zeroconf_publish_data *d, if (card) collect_card_info(card, &card_info); - collect_device_info(o, card, &dev_info, false); + collect_device_info(o, card, &dev_info, false, &impl->defs); if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_API)) != NULL) { if (pw_manager_object_is_sink(o)) diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c index e3039a580..e88b58847 100644 --- a/src/modules/module-protocol-pulse/pulse-server.c +++ b/src/modules/module-protocol-pulse/pulse-server.c @@ -981,7 +981,7 @@ static void stream_param_changed(void *data, uint32_t id, const struct spa_pod * if (id != SPA_PARAM_Format || param == NULL) return; - if ((res = format_parse_param(param, &stream->ss, &stream->map)) < 0) { + if ((res = format_parse_param(param, &stream->ss, &stream->map, NULL, NULL)) < 0) { pw_stream_set_error(stream->stream, res, "format not supported"); return; } @@ -2669,7 +2669,7 @@ static int do_set_volume(struct client *client, uint32_t command, uint32_t tag, struct selector sel = { .id = card_id, .type = pw_manager_object_is_card, }; card = select_object(manager, &sel); } - collect_device_info(o, card, &dev_info, is_monitor); + collect_device_info(o, card, &dev_info, is_monitor, &impl->defs); if (dev_info.have_volume && volume_compare(&dev_info.volume_info.volume, &volume) == 0) @@ -2735,7 +2735,7 @@ static int do_set_mute(struct client *client, uint32_t command, uint32_t tag, st struct selector sel = { .id = card_id, .type = pw_manager_object_is_card, }; card = select_object(manager, &sel); } - collect_device_info(o, card, &dev_info, is_monitor); + collect_device_info(o, card, &dev_info, is_monitor, &impl->defs); if (dev_info.have_volume && dev_info.volume_info.mute == mute) @@ -3406,6 +3406,7 @@ static int fill_card_info(struct client *client, struct message *m, static int fill_sink_info(struct client *client, struct message *m, struct pw_manager_object *o) { + struct impl *impl = client->impl; struct pw_node_info *info = o->info; struct pw_manager *manager = client->manager; const char *name, *desc, *str; @@ -3447,7 +3448,7 @@ static int fill_sink_info(struct client *client, struct message *m, if (card) collect_card_info(card, &card_info); - collect_device_info(o, card, &dev_info, false); + collect_device_info(o, card, &dev_info, false, &impl->defs); if (!sample_spec_valid(&dev_info.ss) || !channel_map_valid(&dev_info.map) || @@ -3576,6 +3577,7 @@ static int fill_sink_info(struct client *client, struct message *m, static int fill_source_info(struct client *client, struct message *m, struct pw_manager_object *o) { + struct impl *impl = client->impl; struct pw_node_info *info = o->info; struct pw_manager *manager = client->manager; bool is_monitor; @@ -3622,7 +3624,7 @@ static int fill_source_info(struct client *client, struct message *m, if (card) collect_card_info(card, &card_info); - collect_device_info(o, card, &dev_info, is_monitor); + collect_device_info(o, card, &dev_info, is_monitor, &impl->defs); if (!sample_spec_valid(&dev_info.ss) || !channel_map_valid(&dev_info.map) || @@ -3740,6 +3742,7 @@ static const char *get_media_name(struct pw_node_info *info) static int fill_sink_input_info(struct client *client, struct message *m, struct pw_manager_object *o) { + struct impl *impl = client->impl; struct pw_node_info *info = o->info; struct pw_manager *manager = client->manager; struct pw_manager_object *peer; @@ -3756,7 +3759,7 @@ static int fill_sink_input_info(struct client *client, struct message *m, (str = spa_dict_lookup(info->props, PW_KEY_CLIENT_ID)) != NULL) client_id = (uint32_t)atoi(str); - collect_device_info(o, NULL, &dev_info, false); + collect_device_info(o, NULL, &dev_info, false, &impl->defs); if (!sample_spec_valid(&dev_info.ss) || !channel_map_valid(&dev_info.map) || @@ -3810,6 +3813,7 @@ static int fill_sink_input_info(struct client *client, struct message *m, static int fill_source_output_info(struct client *client, struct message *m, struct pw_manager_object *o) { + struct impl *impl = client->impl; struct pw_node_info *info = o->info; struct pw_manager *manager = client->manager; struct pw_manager_object *peer; @@ -3827,7 +3831,7 @@ static int fill_source_output_info(struct client *client, struct message *m, (str = spa_dict_lookup(info->props, PW_KEY_CLIENT_ID)) != NULL) client_id = (uint32_t)atoi(str); - collect_device_info(o, NULL, &dev_info, false); + collect_device_info(o, NULL, &dev_info, false, &impl->defs); if (!sample_spec_valid(&dev_info.ss) || !channel_map_valid(&dev_info.map) ||