From patchwork Thu Aug 17 12:00:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 9906003 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F16406038C for ; Thu, 17 Aug 2017 12:05:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 066EF28841 for ; Thu, 17 Aug 2017 12:05:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EF7F928AF5; Thu, 17 Aug 2017 12:05:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ED7E62889E for ; Thu, 17 Aug 2017 12:05:49 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id F2630267755; Thu, 17 Aug 2017 14:00:38 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 1AF9D266EEA; Thu, 17 Aug 2017 14:00:34 +0200 (CEST) Received: from smtp-proxy003.phy.lolipop.jp (smtp-proxy003.phy.lolipop.jp [157.7.104.44]) by alsa0.perex.cz (Postfix) with ESMTP id 18E3C266F03 for ; Thu, 17 Aug 2017 14:00:16 +0200 (CEST) Received: from smtp-proxy003.phy.lolipop.lan (HELO smtp-proxy003.phy.lolipop.jp) (172.19.44.44) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp-proxy003.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Thu, 17 Aug 2017 21:00:14 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp-proxy003.phy.lolipop.jp (LOLIPOP-Fsecure); Thu, 17 Aug 2017 21:00:04 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: tiwai@suse.de, perex@perex.cz Date: Thu, 17 Aug 2017 21:00:02 +0900 Message-Id: <20170817120004.15326-22-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170817120004.15326-1-o-takashi@sakamocchi.jp> References: <20170817120004.15326-1-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, clemens@ladisch.de Subject: [alsa-devel] [RFC][PATCH 21/23] aplay: add a parser for channel map API X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP Current implementation of aplay uses channel map API, by an option '--chmap' (-m). This API allows applications to get/set channel position by getting position array; e.g. 'FR,FL'. However, current implementation of ALSA PCM cure disallows applications to set it as they prefer. This commit adds partly support for this API. --- aplay/options.c | 28 +++++++++++++++++++++++--- aplay/options.h | 1 + aplay/xfer-alsa.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- aplay/xfer-alsa.h | 2 ++ 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/aplay/options.c b/aplay/options.c index c16269d..7663703 100644 --- a/aplay/options.c +++ b/aplay/options.c @@ -199,7 +199,8 @@ static int apply_policies(struct context_options *opts, const char *cntr_format_literal, const char *node_literal, const char *sample_format_literal, - const char *vu_mode_literal) + const char *vu_mode_literal, + const char *chmap_literal) { int err; @@ -232,6 +233,20 @@ static int apply_policies(struct context_options *opts, return err; } + if (chmap_literal) { + snd_pcm_chmap_t *chmap; + chmap = snd_pcm_chmap_parse_string(chmap_literal); + if (chmap == NULL) { + printf(_("Unable to parse channel map string: '%s'\n"), + chmap_literal); + return -EINVAL; + } + free(chmap); + opts->chmap_literal = strdup(chmap_literal); + if (opts->chmap_literal == NULL) + return -ENOMEM; + } + if (opts->samples_per_frame > 0) { if (opts->samples_per_frame < 1 || opts->samples_per_frame > 256) { @@ -316,7 +331,7 @@ static int apply_policies(struct context_options *opts, int context_options_init(struct context_options *opts, int argc, char *const *argv, snd_pcm_stream_t direction) { - static const char *s_opts = "hqid:vt:D:c:f:r:MNF:A:R:T:B:IV:"; + static const char *s_opts = "hqid:vt:D:c:f:r:MNF:A:R:T:B:IV:m:"; static const struct option l_opts[] = { /* For generic purposes. */ {"help", 0, 0, 'h'}, @@ -353,12 +368,14 @@ int context_options_init(struct context_options *opts, int argc, {"dump-hw-params", 0, 0, OPT_DUMP_HWPARAMS}, {"fatal-errors", 0, 0, OPT_FATAL_ERRORS}, {"vumeter", 1, 0, 'V'}, + {"chmap", 1, 0, 'm'}, {NULL, 0, 0, 0}, }; const char *cntr_format_literal = NULL; const char *node_literal = NULL; const char *sample_format_literal = NULL; const char *vu_mode_literal = NULL; + const char *chmap_literal = NULL; int c; int err = 0; @@ -428,6 +445,8 @@ int context_options_init(struct context_options *opts, int argc, opts->dump_hw_params = true; else if (c == OPT_FATAL_ERRORS) opts->fatal_errors = true; + else if (c == 'm') + chmap_literal = optarg; else continue; @@ -441,7 +460,7 @@ int context_options_init(struct context_options *opts, int argc, return apply_policies(opts, direction, cntr_format_literal, node_literal, sample_format_literal, - vu_mode_literal); + vu_mode_literal, chmap_literal); } /* @@ -614,6 +633,9 @@ void context_options_destroy(struct context_options *opts) } if (opts->node) free(opts->node); + if (opts->chmap_literal) + free(opts->chmap_literal); opts->paths = NULL; opts->node = NULL; + opts->chmap_literal = NULL; } diff --git a/aplay/options.h b/aplay/options.h index 2536275..3bece52 100644 --- a/aplay/options.h +++ b/aplay/options.h @@ -53,6 +53,7 @@ struct context_options { bool fatal_errors; enum vumeter_mode vu_mode; + char *chmap_literal; char **paths; unsigned int path_count; diff --git a/aplay/xfer-alsa.c b/aplay/xfer-alsa.c index 2092f3e..e939005 100644 --- a/aplay/xfer-alsa.c +++ b/aplay/xfer-alsa.c @@ -53,7 +53,18 @@ static int set_access_hw_param(snd_pcm_t *handle, return err; } -static void dump_available_hw_params(snd_pcm_hw_params_t *hw_params, +static void dump_chmap(const snd_pcm_chmap_t *chmap) +{ + int i; + + printf(" channels: %u\n", chmap->channels); + for (i = 0; i < chmap->channels; ++i) + printf(" ch%u: %s\n", + i, snd_pcm_chmap_name(chmap->pos[i])); +} + +static void dump_available_hw_params(snd_pcm_t *handle, + snd_pcm_hw_params_t *hw_params, const char *const node) { unsigned int min_i, max_i; @@ -61,6 +72,7 @@ static void dump_available_hw_params(snd_pcm_hw_params_t *hw_params, snd_pcm_access_mask_t *access_mask; snd_pcm_format_mask_t *format_mask; snd_pcm_subformat_mask_t *subformat_mask; + snd_pcm_chmap_query_t **maps; int i; int err; @@ -158,6 +170,19 @@ static void dump_available_hw_params(snd_pcm_hw_params_t *hw_params, continue; printf(" '%s'\n", snd_pcm_subformat_name(i)); } + + maps = snd_pcm_query_chmaps(handle); + if (maps == NULL) + return; + + printf(" available channel maps:\n"); + for (i = 0; maps[i] != NULL; ++i) { + printf(" %u: %s\n", i, + snd_pcm_chmap_type_name(maps[i]->type)); + dump_chmap(&maps[i]->map); + } + snd_pcm_free_chmaps(maps); + printf("\n"); } @@ -204,8 +229,19 @@ static int xfer_alsa_init(struct xfer_context *xfer, if (err < 0) return err; + if (opts->chmap_literal != NULL) { + state->chmap = snd_pcm_chmap_parse_string(opts->chmap_literal); + if (state->chmap == NULL) + return -ENOMEM; + + if (xfer->verbose) { + printf("Chmap argument:\n"); + dump_chmap(state->chmap); + } + } + if (xfer->verbose) - dump_available_hw_params(state->hw_params, node); + dump_available_hw_params(state->handle, state->hw_params, node); return set_access_hw_param(state->handle, state->hw_params, opts); } @@ -262,6 +298,14 @@ static int configure_requested_params(struct alsa_state *state, } if (samples_per_frame > 0) { + if (state->chmap) { + if (samples_per_frame != state->chmap->channels) { + printf(_("Mismatch between channel number and " + "given map: %u %u\n"), + samples_per_frame, state->chmap->channels); + } + } + err = snd_pcm_hw_params_set_channels(state->handle, state->hw_params, samples_per_frame); @@ -319,6 +363,7 @@ static int retrieve_actual_params(snd_pcm_hw_params_t *hw_params, static void dump_sw_params(struct alsa_state *state) { snd_pcm_uframes_t val_l; + snd_pcm_chmap_t *chmap; int val_i; int err; @@ -354,6 +399,13 @@ static void dump_sw_params(struct alsa_state *state) return; printf(" silence-size: %lu\n", val_l); + chmap = snd_pcm_get_chmap(state->handle); + if (chmap != NULL) { + printf(" current-chmap:\n"); + dump_chmap(chmap); + free(chmap); + } + printf("\n"); } @@ -539,6 +591,10 @@ static void xfer_alsa_destroy(struct xfer_context *xfer) snd_pcm_sw_params_free(state->sw_params); state->hw_params = NULL; state->sw_params = NULL; + + if (state->chmap) + free(state->chmap); + state->chmap = NULL; } const struct xfer_data xfer_alsa = { diff --git a/aplay/xfer-alsa.h b/aplay/xfer-alsa.h index 8702685..0257702 100644 --- a/aplay/xfer-alsa.h +++ b/aplay/xfer-alsa.h @@ -38,6 +38,8 @@ struct alsa_state { void *private_data; bool verbose; + + snd_pcm_chmap_t *chmap; }; struct xfer_alsa_io_ops {