From 2b95afeddc87ffb948b684bc3969b7cf8bff38cb Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 23 Nov 2020 15:34:24 +0100 Subject: [PATCH] media-session: add and parse channelmap in routes and stream --- src/examples/media-session/default-routes.c | 51 +++++++++++++++++++ src/examples/media-session/restore-stream.c | 54 ++++++++++++++++++++- 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/src/examples/media-session/default-routes.c b/src/examples/media-session/default-routes.c index ea1741507..4900d474a 100644 --- a/src/examples/media-session/default-routes.c +++ b/src/examples/media-session/default-routes.c @@ -115,6 +115,26 @@ static void add_idle_timeout(struct impl *impl) pw_loop_update_timer(main_loop, impl->idle_timeout, &value, NULL, false); } +static uint32_t channel_from_name(const char *name) +{ + int i; + for (i = 0; spa_type_audio_channel[i].name; i++) { + if (strcmp(name, spa_debug_type_short_name(spa_type_audio_channel[i].name)) == 0) + return spa_type_audio_channel[i].type; + } + return SPA_AUDIO_CHANNEL_UNKNOWN; +} + +static const char *channel_to_name(uint32_t channel) +{ + int i; + for (i = 0; spa_type_audio_channel[i].name; i++) { + if (spa_type_audio_channel[i].type == channel) + return spa_debug_type_short_name(spa_type_audio_channel[i].name); + } + return "UNK"; +} + static char *serialize_props(struct device *dev, const struct spa_pod *param) { struct spa_pod_prop *prop; @@ -152,6 +172,20 @@ static char *serialize_props(struct device *dev, const struct spa_pod *param) fprintf(f, " ]"); break; } + case SPA_PROP_channelMap: + { + uint32_t i, n_vals; + uint32_t map[SPA_AUDIO_MAX_CHANNELS]; + + n_vals = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, + map, SPA_AUDIO_MAX_CHANNELS); + + fprintf(f, "%s\"channels\": [", (comma ? ", " : "")); + for (i = 0; i < n_vals; i++) + fprintf(f, "%s\"%s\"", (i == 0 ? " " : ", "), channel_to_name(map[i])); + fprintf(f, " ]"); + break; + } default: continue; } @@ -216,6 +250,23 @@ static int restore_route(struct device *dev, const char *val, uint32_t index, ui spa_pod_builder_prop(&b, SPA_PROP_channelVolumes, 0); spa_pod_builder_array(&b, sizeof(float), SPA_TYPE_Float, n_vols, vols); + } + else if (strncmp(value, "\"channels\"", len) == 0) { + uint32_t n_ch; + uint32_t map[SPA_AUDIO_MAX_CHANNELS]; + + if (spa_json_enter_array(&it[1], &it[2]) <= 0) + continue; + + for (n_ch = 0; n_ch < SPA_AUDIO_MAX_CHANNELS; n_ch++) { + char chname[16]; + if (spa_json_get_string(&it[2], chname, sizeof(chname)) <= 0) + break; + map[n_ch] = channel_from_name(chname); + } + spa_pod_builder_prop(&b, SPA_PROP_channelMap, 0); + spa_pod_builder_array(&b, sizeof(uint32_t), SPA_TYPE_Id, + n_ch, map); } else { if (spa_json_next(&it[1], &value) <= 0) break; diff --git a/src/examples/media-session/restore-stream.c b/src/examples/media-session/restore-stream.c index 0bbb70b18..5590e1196 100644 --- a/src/examples/media-session/restore-stream.c +++ b/src/examples/media-session/restore-stream.c @@ -122,6 +122,26 @@ static void session_destroy(void *data) free(impl); } +static uint32_t channel_from_name(const char *name) +{ + int i; + for (i = 0; spa_type_audio_channel[i].name; i++) { + if (strcmp(name, spa_debug_type_short_name(spa_type_audio_channel[i].name)) == 0) + return spa_type_audio_channel[i].type; + } + return SPA_AUDIO_CHANNEL_UNKNOWN; +} + +static const char *channel_to_name(uint32_t channel) +{ + int i; + for (i = 0; spa_type_audio_channel[i].name; i++) { + if (spa_type_audio_channel[i].type == channel) + return spa_debug_type_short_name(spa_type_audio_channel[i].name); + } + return "UNK"; +} + static char *serialize_props(struct stream *str, const struct spa_pod *param) { struct spa_pod_prop *prop; @@ -159,13 +179,28 @@ static char *serialize_props(struct stream *str, const struct spa_pod *param) fprintf(f, " ]"); break; } + case SPA_PROP_channelMap: + { + uint32_t i, n_ch; + uint32_t map[SPA_AUDIO_MAX_CHANNELS]; + + n_ch = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, + map, SPA_AUDIO_MAX_CHANNELS); + + fprintf(f, "%s\"channels\": [", (comma ? ", " : "")); + for (i = 0; i < n_ch; i++) + fprintf(f, "%s\"%s\"", (i == 0 ? " ":", "), channel_to_name(map[i])); + fprintf(f, " ]"); + break; + } default: continue; } comma = true; } if (str->obj->target_node != NULL) - fprintf(f, "\"target-node\": \"%s\"", str->obj->target_node); + fprintf(f, "%s\"target-node\": \"%s\"", + (comma ? ", " : ""), str->obj->target_node); fprintf(f, " }"); fclose(f); @@ -279,6 +314,23 @@ static int restore_stream(struct stream *str, const char *val) spa_pod_builder_array(&b, sizeof(float), SPA_TYPE_Float, n_vols, vols); } + else if (strncmp(value, "\"channels\"", len) == 0) { + uint32_t n_ch; + uint32_t map[SPA_AUDIO_MAX_CHANNELS]; + + if (spa_json_enter_array(&it[1], &it[2]) <= 0) + continue; + + for (n_ch = 0; n_ch < SPA_AUDIO_MAX_CHANNELS; n_ch++) { + char chname[16]; + if (spa_json_get_string(&it[2], chname, sizeof(chname)) <= 0) + break; + map[n_ch] = channel_from_name(chname); + } + spa_pod_builder_prop(&b, SPA_PROP_channelMap, 0); + spa_pod_builder_array(&b, sizeof(uint32_t), SPA_TYPE_Id, + n_ch, map); + } else if (strncmp(value, "\"target-node\"", len) == 0) { char name[1024];