DrvHostALSAAudio.cpp revision 1705f7565ed8533058b8541d72d6c5d4453de00f
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/* $Id$ */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @file
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * VBox audio devices: ALSA audio driver.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync/*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Copyright (C) 2006-2015 Oracle Corporation
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync *
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * available from http://www.virtualbox.org. This file is free software;
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * General Public License (GPL) as published by the Free Software
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * --------------------------------------------------------------------
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * This code is based on: alsaaudio.c
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * QEMU ALSA audio driver
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Copyright (c) 2005 Vassili Karpov (malc)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Permission is hereby granted, free of charge, to any person obtaining a copy
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * of this software and associated documentation files (the "Software"), to deal
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * in the Software without restriction, including without limitation the rights
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * copies of the Software, and to permit persons to whom the Software is
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * furnished to do so, subject to the following conditions:
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The above copyright notice and this permission notice shall be included in
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * all copies or substantial portions of the Software.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8112e0942f1128329b99b22a20b395963d4abceavboxsync * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
8112e0942f1128329b99b22a20b395963d4abceavboxsync * THE SOFTWARE.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Header Files *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/alloc.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <VBox/vmm/pdmaudioifs.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncRT_C_DECLS_BEGIN
8112e0942f1128329b99b22a20b395963d4abceavboxsync #include "alsa_stubs.h"
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync #include "alsa_mangling.h"
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncRT_C_DECLS_END
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <alsa/asoundlib.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include "DrvAudio.h"
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include "AudioMixBuffer.h"
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include "VBoxDD.h"
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include "vl_vbox.h"
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#ifdef LOG_GROUP
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync# undef LOG_GROUP
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#endif
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define LOG_GROUP LOG_GROUP_DEV_AUDIO
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <VBox/log.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct ALSAAUDIOSTREAMIN
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOHSTSTRMIN pStreamIn;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_t *phPCM;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync void *pvBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} ALSAAUDIOSTREAMIN, *PALSAAUDIOSTREAMIN;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct ALSAAUDIOSTREAMOUT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOHSTSTRMOUT pStreamOut;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_t *phPCM;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync void *pvBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} ALSAAUDIOSTREAMOUT, *PALSAAUDIOSTREAMOUT;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/* latency = period_size * periods / (rate * bytes_per_frame) */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct ALSAAUDIOCFG
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int size_in_usec_in;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int size_in_usec_out;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync const char *pcm_name_in;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync const char *pcm_name_out;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned int buffer_size_in;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned int period_size_in;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned int buffer_size_out;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned int period_size_out;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned int threshold;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int buffer_size_in_overriden;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int period_size_in_overriden;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int buffer_size_out_overriden;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int period_size_out_overriden;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} ALSAAUDIOCFG, *PALSAAUDIOCFG;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioRecover(snd_pcm_t *phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic ALSAAUDIOCFG s_ALSAConf =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#ifdef HIGH_LATENCY
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 1,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 1,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#endif
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "default",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "default",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#ifdef HIGH_LATENCY
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 400000,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 400000 / 4,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 400000,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 400000 / 4,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync# define DEFAULT_BUFFER_SIZE 1024
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync# define DEFAULT_PERIOD_SIZE 256
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync DEFAULT_BUFFER_SIZE * 4,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync DEFAULT_PERIOD_SIZE * 4,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync DEFAULT_BUFFER_SIZE,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync DEFAULT_PERIOD_SIZE,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#endif
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Host Alsa audio driver instance data.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @implements PDMIAUDIOCONNECTOR
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct DRVHOSTALSAAUDIO
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer to the driver instance structure. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMDRVINS pDrvIns;
8112e0942f1128329b99b22a20b395963d4abceavboxsync /** Pointer to host audio interface. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDMIHOSTAUDIO IHostAudio;
8112e0942f1128329b99b22a20b395963d4abceavboxsync /** Error count for not flooding the release log.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * UINT32_MAX for unlimited logging. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t cLogErrors;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} DRVHOSTALSAAUDIO, *PDRVHOSTALSAAUDIO;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct ALSAAUDIOSTREAMCFG
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned int freq;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_format_t fmt;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int nchannels;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned long buffer_size;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned long period_size;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_uframes_t samples;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} ALSAAUDIOSTREAMCFG, *PALSAAUDIOSTREAMCFG;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioClose(snd_pcm_t **pphPCM)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pphPCM || !*pphPCM)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = snd_pcm_close(*pphPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (rc2)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Closing PCM descriptor failed: %s\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_strerror(rc2)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pphPCM = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic snd_pcm_format_t drvHostALSAAudioFmtToALSA(PDMAUDIOFMT fmt)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync switch (fmt)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case AUD_FMT_S8:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync return SND_PCM_FORMAT_S8;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync case AUD_FMT_U8:
8112e0942f1128329b99b22a20b395963d4abceavboxsync return SND_PCM_FORMAT_U8;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case AUD_FMT_S16:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return SND_PCM_FORMAT_S16_LE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case AUD_FMT_U16:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return SND_PCM_FORMAT_U16_LE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync case AUD_FMT_S32:
8112e0942f1128329b99b22a20b395963d4abceavboxsync return SND_PCM_FORMAT_S32_LE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case AUD_FMT_U32:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return SND_PCM_FORMAT_U32_LE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertMsgFailed(("Format %ld not supported\n", fmt));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return SND_PCM_FORMAT_U8;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioALSAToFmt(snd_pcm_format_t fmt,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOFMT *pFmt, PDMAUDIOENDIANESS *pEndianness)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pFmt, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pEndianness is optional. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (fmt)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case SND_PCM_FORMAT_S8:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pFmt = AUD_FMT_S8;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pEndianness)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pEndianness = PDMAUDIOENDIANESS_LITTLE;
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync case SND_PCM_FORMAT_U8:
8112e0942f1128329b99b22a20b395963d4abceavboxsync *pFmt = AUD_FMT_U8;
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pEndianness)
8112e0942f1128329b99b22a20b395963d4abceavboxsync *pEndianness = PDMAUDIOENDIANESS_LITTLE;
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync case SND_PCM_FORMAT_S16_LE:
8112e0942f1128329b99b22a20b395963d4abceavboxsync *pFmt = AUD_FMT_S16;
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pEndianness)
8112e0942f1128329b99b22a20b395963d4abceavboxsync *pEndianness = PDMAUDIOENDIANESS_LITTLE;
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync case SND_PCM_FORMAT_U16_LE:
8112e0942f1128329b99b22a20b395963d4abceavboxsync *pFmt = AUD_FMT_U16;
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pEndianness)
8112e0942f1128329b99b22a20b395963d4abceavboxsync *pEndianness = PDMAUDIOENDIANESS_LITTLE;
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case SND_PCM_FORMAT_S16_BE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pFmt = AUD_FMT_S16;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pEndianness)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pEndianness = PDMAUDIOENDIANESS_BIG;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case SND_PCM_FORMAT_U16_BE:
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync *pFmt = AUD_FMT_U16;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pEndianness)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pEndianness = PDMAUDIOENDIANESS_BIG;
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case SND_PCM_FORMAT_S32_LE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pFmt = AUD_FMT_S32;
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync if (pEndianness)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pEndianness = PDMAUDIOENDIANESS_LITTLE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case SND_PCM_FORMAT_U32_LE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pFmt = AUD_FMT_U32;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pEndianness)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pEndianness = PDMAUDIOENDIANESS_LITTLE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case SND_PCM_FORMAT_S32_BE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pFmt = AUD_FMT_S32;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pEndianness)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pEndianness = PDMAUDIOENDIANESS_BIG;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case SND_PCM_FORMAT_U32_BE:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync *pFmt = AUD_FMT_U32;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync if (pEndianness)
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync *pEndianness = PDMAUDIOENDIANESS_BIG;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync break;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync default:
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertMsgFailed(("Format %ld not supported\n", fmt));
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VERR_NOT_SUPPORTED;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VINF_SUCCESS;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic int drvHostALSAAudioALSAGetShift(snd_pcm_format_t fmt, unsigned *puShift)
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertPtrReturn(puShift, VERR_INVALID_POINTER);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync switch (fmt)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync case SND_PCM_FORMAT_S8:
8112e0942f1128329b99b22a20b395963d4abceavboxsync case SND_PCM_FORMAT_U8:
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync *puShift = 0;
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case SND_PCM_FORMAT_S16_LE:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case SND_PCM_FORMAT_U16_LE:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case SND_PCM_FORMAT_S16_BE:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case SND_PCM_FORMAT_U16_BE:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync *puShift = 1;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync break;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case SND_PCM_FORMAT_S32_LE:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case SND_PCM_FORMAT_U32_LE:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case SND_PCM_FORMAT_S32_BE:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync case SND_PCM_FORMAT_U32_BE:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync *puShift = 2;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync break;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync default:
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync AssertMsgFailed(("Format %ld not supported\n", fmt));
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VERR_NOT_SUPPORTED;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioSetThreshold(snd_pcm_t *phPCM,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_uframes_t threshold)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_sw_params_t *pSWParms = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_sw_params_alloca(&pSWParms);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pSWParms)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VERR_NO_MEMORY;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync do
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync int err = snd_pcm_sw_params_current(phPCM, pSWParms);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (err < 0)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogRel(("ALSA: Failed to get current software parameters for threshold: %s\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_strerror(err)));
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = VERR_ACCESS_DENIED;
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync err = snd_pcm_sw_params_set_start_threshold(phPCM, pSWParms, threshold);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (err < 0)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set software threshold to %ld: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync threshold, snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_ACCESS_DENIED;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_sw_params(phPCM, pSWParms);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set new software parameters for threshold: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_ACCESS_DENIED;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("Setting threshold to %RU32\n", threshold));
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = VINF_SUCCESS;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync while (0);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic int drvHostALSAAudioOpen(bool fIn,
8112e0942f1128329b99b22a20b395963d4abceavboxsync PALSAAUDIOSTREAMCFG pCfgReq,
8112e0942f1128329b99b22a20b395963d4abceavboxsync PALSAAUDIOSTREAMCFG pCfgObt,
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_pcm_t **pphPCM)
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync{
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync snd_pcm_t *phPCM = NULL;
8112e0942f1128329b99b22a20b395963d4abceavboxsync int rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync unsigned int cChannels = pCfgReq->nchannels;
8112e0942f1128329b99b22a20b395963d4abceavboxsync unsigned int uFreq = pCfgReq->freq;
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_pcm_uframes_t obt_buffer_size;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync do
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync const char *pszDev = fIn ? s_ALSAConf.pcm_name_in : s_ALSAConf.pcm_name_out;
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!pszDev)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogRel(("ALSA: Invalid or no %s device name set\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync fIn ? "input" : "output"));
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = VERR_INVALID_PARAMETER;
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int err = snd_pcm_open(&phPCM, pszDev,
8112e0942f1128329b99b22a20b395963d4abceavboxsync fIn ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync SND_PCM_NONBLOCK);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (err < 0)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogRel(("ALSA: Failed to open \"%s\" as %s: %s\n", pszDev,
8112e0942f1128329b99b22a20b395963d4abceavboxsync fIn ? "ADC" : "DAC", snd_strerror(err)));
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_pcm_hw_params_t *pHWParms;
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_pcm_hw_params_alloca(&pHWParms); /** @todo Check for successful allocation? */
8112e0942f1128329b99b22a20b395963d4abceavboxsync err = snd_pcm_hw_params_any(phPCM, pHWParms);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to initialize hardware parameters: %s\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_access(phPCM, pHWParms,
8112e0942f1128329b99b22a20b395963d4abceavboxsync SND_PCM_ACCESS_RW_INTERLEAVED);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set access type: %s\n", snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_format(phPCM, pHWParms, pCfgReq->fmt);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set audio format to %d: %s\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync pCfgReq->fmt, snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_rate_near(phPCM, pHWParms, &uFreq, 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set frequency to %dHz: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCfgReq->freq, snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_channels_near(phPCM, pHWParms, &cChannels);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set number of channels to %d\n", pCfgReq->nchannels));
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if ( cChannels != 1
8112e0942f1128329b99b22a20b395963d4abceavboxsync && cChannels != 2)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogRel(("ALSA: Number of audio channels (%u) not supported\n", cChannels));
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync unsigned int period_size = pCfgReq->period_size;
8112e0942f1128329b99b22a20b395963d4abceavboxsync unsigned int buffer_size = pCfgReq->buffer_size;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if ( !((fIn && s_ALSAConf.size_in_usec_in)
8112e0942f1128329b99b22a20b395963d4abceavboxsync || (!fIn && s_ALSAConf.size_in_usec_out)))
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!buffer_size)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync buffer_size = DEFAULT_BUFFER_SIZE;
8112e0942f1128329b99b22a20b395963d4abceavboxsync period_size = DEFAULT_PERIOD_SIZE;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (buffer_size)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync if ( ( fIn && s_ALSAConf.size_in_usec_in)
8112e0942f1128329b99b22a20b395963d4abceavboxsync || (!fIn && s_ALSAConf.size_in_usec_out))
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (period_size)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_period_time_near(phPCM, pHWParms,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync &period_size, 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set period time %d\n", pCfgReq->period_size));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_buffer_time_near(phPCM, pHWParms,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync &buffer_size, 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set buffer time %d\n", pCfgReq->buffer_size));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_uframes_t period_size_f = (snd_pcm_uframes_t)period_size;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_uframes_t buffer_size_f = (snd_pcm_uframes_t)buffer_size;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_uframes_t minval;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (period_size_f)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync minval = period_size_f;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int dir = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_get_period_size_min(pHWParms,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync &minval, &dir);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Could not determine minimal period size\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Minimal period size is: %ld\n", minval));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (period_size_f < minval)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ( ( fIn && s_ALSAConf.period_size_in_overriden)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync || (!fIn && s_ALSAConf.period_size_out_overriden))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Period size %RU32 is less than minimal period size %RU32\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync period_size_f, minval));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync period_size_f = minval;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_period_size_near(phPCM, pHWParms,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync &period_size_f, 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Period size is: %RU32\n", period_size_f));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set period size %d (%s)\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync period_size_f, snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Calculate default buffer size here since it might have been changed
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * in the _near functions */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync buffer_size_f = 4 * period_size_f;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync minval = buffer_size_f;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_get_buffer_size_min(pHWParms, &minval);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Could not retrieve minimal buffer size\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Minimal buffer size is: %RU32\n", minval));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (buffer_size_f < minval)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ( ( fIn && s_ALSAConf.buffer_size_in_overriden)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync || (!fIn && s_ALSAConf.buffer_size_out_overriden))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Buffer size %RU32 is less than minimal buffer size %RU32\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync buffer_size_f, minval));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync buffer_size_f = minval;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_buffer_size_near(phPCM,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pHWParms, &buffer_size_f);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Buffer size is: %RU32\n", buffer_size_f));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set buffer size %d: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync buffer_size_f, snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Warning: Buffer size is not set\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params(phPCM, pHWParms);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to apply audio parameters\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_get_buffer_size(pHWParms, &obt_buffer_size);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to get buffer size\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_uframes_t obt_period_size;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int dir = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_get_period_size(pHWParms, &obt_period_size, &dir);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to get period size\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
c0b47c53336892431c7a2d8666600ffed91c11f1vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Freq=%dHz, period size=%RU32, buffer size=%RU32\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCfgReq->freq, obt_period_size, obt_buffer_size));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_prepare(phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Could not prepare hPCM %p\n", (void *)phPCM));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ( !fIn
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync && s_ALSAConf.threshold)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned uShift;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioALSAGetShift(pCfgReq->fmt, &uShift);
87d9823b393efbc674b3f3b0ff96998ca89e89b7vboxsync if (RT_SUCCESS(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int bytes_per_sec = uFreq
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync << (cChannels == 2)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync << uShift;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_uframes_t threshold
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync = (s_ALSAConf.threshold * bytes_per_sec) / 1000;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioSetThreshold(phPCM, threshold);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync while (0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_SUCCESS(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCfgObt->fmt = pCfgReq->fmt;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCfgObt->nchannels = cChannels;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCfgObt->freq = uFreq;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCfgObt->samples = obt_buffer_size;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pphPCM = phPCM;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvHostALSAAudioClose(&phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFuncLeaveRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#ifdef DEBUG
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic void drvHostALSAAudioErrorHandler(const char *file, int line, const char *function,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int err, const char *fmt, ...)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** @todo Implement me! */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#endif
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioGetAvail(snd_pcm_t *phPCM, snd_pcm_sframes_t *pFramesAvail)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(phPCM, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pFramesAvail, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_sframes_t framesAvail;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync framesAvail = snd_pcm_avail_update(phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (framesAvail < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (framesAvail == -EPIPE)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioRecover(phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_SUCCESS(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync framesAvail = snd_pcm_avail_update(phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_ACCESS_DENIED; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (framesAvail >= 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pFramesAvail = framesAvail;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
5045ab9ca39fa0b301f4020b7a072406eb0ecea2vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioRecover(snd_pcm_t *phPCM)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(phPCM, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int err = snd_pcm_prepare(phPCM);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Failed to recover stream %p: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync phPCM, snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VERR_ACCESS_DENIED; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioResume(snd_pcm_t *phPCM)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(phPCM, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int err = snd_pcm_resume(phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFunc(("Failed to resume stream %p: %s\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync phPCM, snd_strerror(err)));
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VERR_ACCESS_DENIED; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioStreamCtl(snd_pcm_t *phPCM, bool fPause)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int err;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (fPause)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_drop(phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("Error stopping stream %p: %s\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync phPCM, snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VERR_ACCESS_DENIED;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_prepare (phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (err < 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("Error preparing stream %p: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync phPCM, snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VERR_ACCESS_DENIED;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VINF_SUCCESS;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioInit(PPDMIHOSTAUDIO pInterface)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync NOREF(pInterface);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFuncEnter();
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync int rc = audioLoadAlsaLib();
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (RT_FAILURE(rc))
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogRel(("ALSA: Failed to load the ALSA shared library, rc=%Rrc\n", rc));
8112e0942f1128329b99b22a20b395963d4abceavboxsync else
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync#ifdef DEBUG
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_lib_error_set_handler(drvHostALSAAudioErrorHandler);
8112e0942f1128329b99b22a20b395963d4abceavboxsync#endif
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
8112e0942f1128329b99b22a20b395963d4abceavboxsync uint32_t *pcSamplesCaptured)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync NOREF(pInterface);
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_pcm_sframes_t cAvail;
8112e0942f1128329b99b22a20b395963d4abceavboxsync int rc = drvHostALSAAudioGetAvail(pThisStrmIn->phPCM, &cAvail);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (RT_FAILURE(rc))
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFunc(("Error getting number of captured frames, rc=%Rrc\n", rc));
8112e0942f1128329b99b22a20b395963d4abceavboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!cAvail) /* No data yet? */
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_pcm_state_t state = snd_pcm_state(pThisStrmIn->phPCM);
8112e0942f1128329b99b22a20b395963d4abceavboxsync switch (state)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync case SND_PCM_STATE_PREPARED:
8112e0942f1128329b99b22a20b395963d4abceavboxsync cAvail = audioMixBufFree(&pHstStrmIn->MixBuf);
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync case SND_PCM_STATE_SUSPENDED:
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = drvHostALSAAudioResume(pThisStrmIn->phPCM);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (RT_FAILURE(rc))
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlow(("Resuming suspended input stream\n"));
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("No frames available, state=%d\n", state));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!cAvail)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pcSamplesCaptured)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pcSamplesCaptured = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(cAvail);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbToRead = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cAvail);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("cbToRead=%zu, cAvail=%RI32\n", cbToRead, cAvail));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t cWrittenTotal = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_uframes_t cToRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_sframes_t cRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync while (cbToRead)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cToRead = RT_MIN(AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cbToRead),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, pThisStrmIn->cbBuf));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertBreakStmt(cToRead, rc = VERR_NO_DATA);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cRead = snd_pcm_readi(pThisStrmIn->phPCM, pThisStrmIn->pvBuf, cToRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (cRead <= 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (cRead)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case 0:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Failed to read %RI32 frames\n", cRead));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_ACCESS_DENIED;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case -EAGAIN:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case -EPIPE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioRecover(pThisStrmIn->phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("Recovered from capturing\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync continue;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("Failed to read %RI32 input frames, rc=%Rrc\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cRead, rc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t cWritten;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = audioMixBufWriteCirc(&pHstStrmIn->MixBuf,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThisStrmIn->pvBuf, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cRead),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync &cWritten);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(cbToRead >= cbWritten);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbToRead -= cbWritten;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cWrittenTotal += cWritten;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_SUCCESS(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t cProcessed = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (cWrittenTotal)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = audioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync &cProcessed);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pcSamplesCaptured)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pcSamplesCaptured = cWrittenTotal;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 processed), rc=%Rrc\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cWrittenTotal, cProcessed, rc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFuncLeaveRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t *pcSamplesPlayed)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NOREF(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t cbReadTotal = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync do
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_sframes_t cAvail;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioGetAvail(pThisStrmOut->phPCM, &cAvail);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Error getting number of playback frames, rc=%Rrc\n", rc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbToRead = RT_MIN(AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cAvail),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvAudioHstOutSamplesLive(pHstStrmOut, NULL /* pcStreamsLive */)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("cbToRead=%zu, cbAvail=%zu\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbToRead, AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cAvail)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t cRead, cbRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_sframes_t cWritten;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync while (cbToRead)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = audioMixBufReadCirc(&pHstStrmOut->MixBuf, pThisStrmOut->pvBuf, cbToRead, &cRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertBreak(cbRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cWritten = snd_pcm_writei(pThisStrmOut->phPCM, pThisStrmOut->pvBuf, cRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (cWritten <= 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (cWritten)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case 0:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Failed to write %RI32 frames\n", cRead));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_ACCESS_DENIED;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case -EPIPE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = drvHostALSAAudioRecover(pThisStrmOut->phPCM);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (RT_FAILURE(rc))
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("Recovered from playback\n"));
8112e0942f1128329b99b22a20b395963d4abceavboxsync continue;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync case -ESTRPIPE:
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Stream was suspended and waiting for a recovery. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = drvHostALSAAudioResume(pThisStrmOut->phPCM);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (RT_FAILURE(rc))
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to resume output stream\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("Resumed suspended output stream\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync continue;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("Failed to write %RI32 output frames, rc=%Rrc\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cRead, rc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(cbToRead >= cRead);
8865816a3d875ec1a036af307fbb484af107f014vboxsync cbToRead -= cbRead;
8865816a3d875ec1a036af307fbb484af107f014vboxsync cbReadTotal += cbRead;
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync }
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync while (0);
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (RT_SUCCESS(rc))
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbReadTotal);
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (cReadTotal)
8865816a3d875ec1a036af307fbb484af107f014vboxsync audioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (pcSamplesPlayed)
8865816a3d875ec1a036af307fbb484af107f014vboxsync *pcSamplesPlayed = cReadTotal;
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n",
8865816a3d875ec1a036af307fbb484af107f014vboxsync cReadTotal, cbReadTotal, rc));
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync LogFlowFuncLeaveRC(rc);
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync return rc;
8865816a3d875ec1a036af307fbb484af107f014vboxsync}
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
8865816a3d875ec1a036af307fbb484af107f014vboxsync{
8865816a3d875ec1a036af307fbb484af107f014vboxsync NOREF(pInterface);
8865816a3d875ec1a036af307fbb484af107f014vboxsync AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync drvHostALSAAudioClose(&pThisStrmIn->phPCM);
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (pThisStrmIn->pvBuf)
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync RTMemFree(pThisStrmIn->pvBuf);
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThisStrmIn->pvBuf = NULL;
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync return VINF_SUCCESS;
8865816a3d875ec1a036af307fbb484af107f014vboxsync}
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
8865816a3d875ec1a036af307fbb484af107f014vboxsync{
8865816a3d875ec1a036af307fbb484af107f014vboxsync NOREF(pInterface);
8865816a3d875ec1a036af307fbb484af107f014vboxsync AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync drvHostALSAAudioClose(&pThisStrmOut->phPCM);
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (pThisStrmOut->pvBuf)
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync RTMemFree(pThisStrmOut->pvBuf);
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThisStrmOut->pvBuf = NULL;
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioInitOut(PPDMIHOSTAUDIO pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t *pcSamples)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NOREF(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_t *phPCM = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync do
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync ALSAAUDIOSTREAMCFG req;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.fmt = drvHostALSAAudioFmtToALSA(pCfg->enmFormat);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.freq = pCfg->uHz;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.nchannels = pCfg->cChannels;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.period_size = s_ALSAConf.period_size_out;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.buffer_size = s_ALSAConf.buffer_size_out;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync ALSAAUDIOSTREAMCFG obt;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioOpen(false /* false */, &req, &obt, &phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOFMT enmFormat;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOENDIANESS enmEnd;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioALSAToFmt(obt.fmt, &enmFormat, &enmEnd);
1ab072338283b0c700d1ef4958511296a4d0ca41vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOSTREAMCFG streamCfg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync streamCfg.uHz = obt.freq;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync streamCfg.cChannels = obt.nchannels;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync streamCfg.enmFormat = enmFormat;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync streamCfg.enmEndianness = enmEnd;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvAudioStreamCfgToProps(&streamCfg, &pHstStrmOut->Props);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertBreakStmt(obt.samples, rc = VERR_INVALID_PARAMETER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbBuf = obt.samples * (1 << pHstStrmOut->Props.cShift);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertBreakStmt(cbBuf, rc = VERR_INVALID_PARAMETER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThisStrmOut->pvBuf = RTMemAlloc(cbBuf);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pThisStrmOut->pvBuf)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Not enough memory for output DAC buffer (%RU32 samples, each %d bytes)\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync obt.samples, 1 << pHstStrmOut->Props.cShift));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_NO_MEMORY;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThisStrmOut->cbBuf = cbBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThisStrmOut->phPCM = phPCM;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pcSamples)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pcSamples = obt.samples;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync while (0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvHostALSAAudioClose(&phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFuncLeaveRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioInitIn(PPDMIHOSTAUDIO pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIORECSOURCE enmRecSource,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t *pcSamples)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NOREF(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync snd_pcm_t *phPCM = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync do
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync ALSAAUDIOSTREAMCFG req;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.fmt = drvHostALSAAudioFmtToALSA(pCfg->enmFormat);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.freq = pCfg->uHz;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.nchannels = pCfg->cChannels;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.period_size = s_ALSAConf.period_size_in;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.buffer_size = s_ALSAConf.buffer_size_in;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync ALSAAUDIOSTREAMCFG obt;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioOpen(true /* fIn */, &req, &obt, &phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOFMT enmFormat;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOENDIANESS enmEnd;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioALSAToFmt(obt.fmt, &enmFormat, &enmEnd);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOSTREAMCFG streamCfg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync streamCfg.uHz = obt.freq;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync streamCfg.cChannels = obt.nchannels;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync streamCfg.enmFormat = enmFormat;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync streamCfg.enmEndianness = enmEnd;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvAudioStreamCfgToProps(&streamCfg, &pHstStrmIn->Props);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertBreakStmt(obt.samples, rc = VERR_INVALID_PARAMETER);
8112e0942f1128329b99b22a20b395963d4abceavboxsync size_t cbBuf = obt.samples * (1 << pHstStrmIn->Props.cShift);
ae26c174345e4ed5710e3f9138b9166b4a160abdvboxsync AssertBreakStmt(cbBuf, rc = VERR_INVALID_PARAMETER);
ae26c174345e4ed5710e3f9138b9166b4a160abdvboxsync pThisStrmIn->pvBuf = RTMemAlloc(cbBuf);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!pThisStrmIn->pvBuf)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Not enough memory for input ADC buffer (%RU32 samples, each %d bytes)\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync obt.samples, 1 << pHstStrmIn->Props.cShift));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_NO_MEMORY;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThisStrmIn->cbBuf = cbBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThisStrmIn->phPCM = phPCM;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pcSamples)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pcSamples = obt.samples;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync while (0);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (RT_FAILURE(rc))
8112e0942f1128329b99b22a20b395963d4abceavboxsync drvHostALSAAudioClose(&phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFuncLeaveRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(bool) drvHostALSAAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NOREF(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NOREF(enmDir);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return true; /* Always all enabled. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOSTREAMCMD enmStreamCmd)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NOREF(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (enmStreamCmd)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case PDMAUDIOSTREAMCMD_ENABLE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioStreamCtl(pThisStrmIn->phPCM, false /* fStop */);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case PDMAUDIOSTREAMCMD_DISABLE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioStreamCtl(pThisStrmIn->phPCM, true /* fStop */);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertMsgFailed(("Invalid command %ld\n", enmStreamCmd));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_INVALID_PARAMETER;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIOSTREAMCMD enmStreamCmd)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NOREF(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (enmStreamCmd)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case PDMAUDIOSTREAMCMD_ENABLE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioStreamCtl(pThisStrmOut->phPCM, false /* fStop */);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case PDMAUDIOSTREAMCMD_DISABLE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioStreamCtl(pThisStrmOut->phPCM, true /* fStop */);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertMsgFailed(("Invalid command %ld\n", enmStreamCmd));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_INVALID_PARAMETER;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync NOREF(pInterface);
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCfg->cbStreamOut = sizeof(ALSAAUDIOSTREAMOUT);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCfg->cbStreamIn = sizeof(ALSAAUDIOSTREAMIN);
8112e0942f1128329b99b22a20b395963d4abceavboxsync pCfg->cMaxHstStrmsOut = INT_MAX;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCfg->cMaxHstStrmsIn = INT_MAX;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(void) drvHostALSAAudioShutdown(PPDMIHOSTAUDIO pInterface)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NOREF(pInterface);
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(void *) drvHostALSAAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVHOSTALSAAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTALSAAUDIO);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Construct a DirectSound Audio driver instance.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc FNPDMDRVCONSTRUCT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostAlsaAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVHOSTALSAAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTALSAAUDIO);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("Audio: Initializing ALSA driver\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Init the static parts.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->pDrvIns = pDrvIns;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IBase */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pDrvIns->IBase.pfnQueryInterface = drvHostALSAAudioQueryInterface;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IHostAudio */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMAUDIO_IHOSTAUDIO_CALLBACKS(drvHostALSAAudio);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Char driver registration record.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncconst PDMDRVREG g_DrvHostALSAAudio =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32Version */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDM_DRVREG_VERSION,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szName */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "ALSAAudio",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szRCMod */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szR0Mod */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pszDescription */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "ALSA host audio driver",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* fFlags */
1256c6853363727c70b1b5075e5a747510858b94vboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* fClass. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDM_DRVREG_CLASS_AUDIO,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cMaxInstances */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync ~0U,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cbInstance */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync sizeof(DRVHOSTALSAAUDIO),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnConstruct */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvHostAlsaAudioConstruct,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDestruct */
1ab072338283b0c700d1ef4958511296a4d0ca41vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnRelocate */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnIOCtl */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnPowerOn */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnReset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnPowerOff */
NULL,
/* pfnSoftReset */
NULL,
/* u32EndVersion */
PDM_DRVREG_VERSION
};
static struct audio_option alsa_options[] =
{
{"DACSizeInUsec", AUD_OPT_BOOL, &s_ALSAConf.size_in_usec_out,
"DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
{"DACPeriodSize", AUD_OPT_INT, &s_ALSAConf.period_size_out,
"DAC period size", &s_ALSAConf.period_size_out_overriden, 0},
{"DACBufferSize", AUD_OPT_INT, &s_ALSAConf.buffer_size_out,
"DAC buffer size", &s_ALSAConf.buffer_size_out_overriden, 0},
{"ADCSizeInUsec", AUD_OPT_BOOL, &s_ALSAConf.size_in_usec_in,
"ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
{"ADCPeriodSize", AUD_OPT_INT, &s_ALSAConf.period_size_in,
"ADC period size", &s_ALSAConf.period_size_in_overriden, 0},
{"ADCBufferSize", AUD_OPT_INT, &s_ALSAConf.buffer_size_in,
"ADC buffer size", &s_ALSAConf.buffer_size_in_overriden, 0},
{"Threshold", AUD_OPT_INT, &s_ALSAConf.threshold,
"(undocumented)", NULL, 0},
{"DACDev", AUD_OPT_STR, &s_ALSAConf.pcm_name_out,
"DAC device name (for instance dmix)", NULL, 0},
{"ADCDev", AUD_OPT_STR, &s_ALSAConf.pcm_name_in,
"ADC device name", NULL, 0},
NULL
};