DrvHostALSAAudio.cpp revision 1705f7565ed8533058b8541d72d6c5d4453de00f
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * VBox audio devices: ALSA audio driver.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Copyright (C) 2006-2015 Oracle Corporation
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 * This code is based on: alsaaudio.c
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * QEMU ALSA audio driver
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Copyright (c) 2005 Vassili Karpov (malc)
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:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The above copyright notice and this permission notice shall be included in
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * all copies or substantial portions of the Software.
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* Header Files *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/* latency = period_size * periods / (rate * bytes_per_frame) */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct ALSAAUDIOCFG
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned int threshold;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioRecover(snd_pcm_t *phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Host Alsa audio driver instance data.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @implements PDMIAUDIOCONNECTOR
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer to the driver instance structure. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /** Pointer to host audio interface. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /** Error count for not flooding the release log.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * UINT32_MAX for unlimited logging. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned int freq;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned long buffer_size;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned long period_size;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioClose(snd_pcm_t **pphPCM)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Closing PCM descriptor failed: %s\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic snd_pcm_format_t drvHostALSAAudioFmtToALSA(PDMAUDIOFMT fmt)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertMsgFailed(("Format %ld not supported\n", fmt));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioALSAToFmt(snd_pcm_format_t fmt,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pEndianness is optional. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertMsgFailed(("Format %ld not supported\n", fmt));
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic int drvHostALSAAudioALSAGetShift(snd_pcm_format_t fmt, unsigned *puShift)
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync AssertMsgFailed(("Format %ld not supported\n", fmt));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioSetThreshold(snd_pcm_t *phPCM,
8112e0942f1128329b99b22a20b395963d4abceavboxsync int err = snd_pcm_sw_params_current(phPCM, pSWParms);
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogRel(("ALSA: Failed to get current software parameters for threshold: %s\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync err = snd_pcm_sw_params_set_start_threshold(phPCM, pSWParms, threshold);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set software threshold to %ld: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set new software parameters for threshold: %s\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("Setting threshold to %RU32\n", threshold));
8112e0942f1128329b99b22a20b395963d4abceavboxsync const char *pszDev = fIn ? s_ALSAConf.pcm_name_in : s_ALSAConf.pcm_name_out;
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogRel(("ALSA: Invalid or no %s device name set\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync fIn ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogRel(("ALSA: Failed to open \"%s\" as %s: %s\n", pszDev,
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_pcm_hw_params_alloca(&pHWParms); /** @todo Check for successful allocation? */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to initialize hardware parameters: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_access(phPCM, pHWParms,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set access type: %s\n", snd_strerror(err)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_format(phPCM, pHWParms, pCfgReq->fmt);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set audio format to %d: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_rate_near(phPCM, pHWParms, &uFreq, 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set frequency to %dHz: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_channels_near(phPCM, pHWParms, &cChannels);
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 LogRel(("ALSA: Number of audio channels (%u) not supported\n", cChannels));
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_period_time_near(phPCM, pHWParms,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set period time %d\n", pCfgReq->period_size));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_buffer_time_near(phPCM, pHWParms,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set buffer time %d\n", pCfgReq->buffer_size));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
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 err = snd_pcm_hw_params_get_period_size_min(pHWParms,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Could not determine minimal period size\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Minimal period size is: %ld\n", minval));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Period size %RU32 is less than minimal period size %RU32\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_period_size_near(phPCM, pHWParms,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Period size is: %RU32\n", period_size_f));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set period size %d (%s)\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Calculate default buffer size here since it might have been changed
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * in the _near functions */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_get_buffer_size_min(pHWParms, &minval);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Could not retrieve minimal buffer size\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Minimal buffer size is: %RU32\n", minval));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Buffer size %RU32 is less than minimal buffer size %RU32\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_set_buffer_size_near(phPCM,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Buffer size is: %RU32\n", buffer_size_f));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to set buffer size %d: %s\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to apply audio parameters\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_get_buffer_size(pHWParms, &obt_buffer_size);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync err = snd_pcm_hw_params_get_period_size(pHWParms, &obt_period_size, &dir);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Freq=%dHz, period size=%RU32, buffer size=%RU32\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Could not prepare hPCM %p\n", (void *)phPCM));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_GENERAL_FAILURE; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioALSAGetShift(pCfgReq->fmt, &uShift);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioSetThreshold(phPCM, threshold);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic void drvHostALSAAudioErrorHandler(const char *file, int line, const char *function,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** @todo Implement me! */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioGetAvail(snd_pcm_t *phPCM, snd_pcm_sframes_t *pFramesAvail)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pFramesAvail, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_ACCESS_DENIED; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioRecover(snd_pcm_t *phPCM)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VERR_ACCESS_DENIED; /** @todo Find a better rc. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VERR_ACCESS_DENIED; /** @todo Find a better rc. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvHostALSAAudioStreamCtl(snd_pcm_t *phPCM, bool fPause)
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioInit(PPDMIHOSTAUDIO pInterface)
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogRel(("ALSA: Failed to load the ALSA shared library, rc=%Rrc\n", rc));
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_lib_error_set_handler(drvHostALSAAudioErrorHandler);
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
8112e0942f1128329b99b22a20b395963d4abceavboxsync PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
8112e0942f1128329b99b22a20b395963d4abceavboxsync int rc = drvHostALSAAudioGetAvail(pThisStrmIn->phPCM, &cAvail);
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFunc(("Error getting number of captured frames, rc=%Rrc\n", rc));
8112e0942f1128329b99b22a20b395963d4abceavboxsync snd_pcm_state_t state = snd_pcm_state(pThisStrmIn->phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("No frames available, state=%d\n", state));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbToRead = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cAvail);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("cbToRead=%zu, cAvail=%RI32\n", cbToRead, cAvail));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cToRead = RT_MIN(AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cbToRead),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, pThisStrmIn->cbBuf));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cRead = snd_pcm_readi(pThisStrmIn->phPCM, pThisStrmIn->pvBuf, cToRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("Failed to read %RI32 input frames, rc=%Rrc\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThisStrmIn->pvBuf, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cRead),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = audioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 processed), rc=%Rrc\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioGetAvail(pThisStrmOut->phPCM, &cAvail);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Error getting number of playback frames, rc=%Rrc\n", rc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbToRead = RT_MIN(AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvAudioHstOutSamplesLive(pHstStrmOut, NULL /* pcStreamsLive */)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbToRead, AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cAvail)));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = audioMixBufReadCirc(&pHstStrmOut->MixBuf, pThisStrmOut->pvBuf, cbToRead, &cRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cWritten = snd_pcm_writei(pThisStrmOut->phPCM, pThisStrmOut->pvBuf, cRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFunc(("Failed to write %RI32 frames\n", cRead));
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Stream was suspended and waiting for a recovery. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Failed to resume output stream\n"));
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("Resumed suspended output stream\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("Failed to write %RI32 output frames, rc=%Rrc\n",
8865816a3d875ec1a036af307fbb484af107f014vboxsync uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbReadTotal);
8865816a3d875ec1a036af307fbb484af107f014vboxsync audioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
8865816a3d875ec1a036af307fbb484af107f014vboxsync LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n",
8865816a3d875ec1a036af307fbb484af107f014vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
8865816a3d875ec1a036af307fbb484af107f014vboxsync PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
8865816a3d875ec1a036af307fbb484af107f014vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
8865816a3d875ec1a036af307fbb484af107f014vboxsync AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
8865816a3d875ec1a036af307fbb484af107f014vboxsync PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioInitOut(PPDMIHOSTAUDIO pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.fmt = drvHostALSAAudioFmtToALSA(pCfg->enmFormat);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioOpen(false /* false */, &req, &obt, &phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioALSAToFmt(obt.fmt, &enmFormat, &enmEnd);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvAudioStreamCfgToProps(&streamCfg, &pHstStrmOut->Props);
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 LogRel(("ALSA: Not enough memory for output DAC buffer (%RU32 samples, each %d bytes)\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioInitIn(PPDMIHOSTAUDIO pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync req.fmt = drvHostALSAAudioFmtToALSA(pCfg->enmFormat);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioOpen(true /* fIn */, &req, &obt, &phPCM);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioALSAToFmt(obt.fmt, &enmFormat, &enmEnd);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvAudioStreamCfgToProps(&streamCfg, &pHstStrmIn->Props);
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);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogRel(("ALSA: Not enough memory for input ADC buffer (%RU32 samples, each %d bytes)\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(bool) drvHostALSAAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return true; /* Always all enabled. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioStreamCtl(pThisStrmIn->phPCM, false /* fStop */);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioStreamCtl(pThisStrmIn->phPCM, true /* fStop */);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertMsgFailed(("Invalid command %ld\n", enmStreamCmd));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioStreamCtl(pThisStrmOut->phPCM, false /* fStop */);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvHostALSAAudioStreamCtl(pThisStrmOut->phPCM, true /* fStop */);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertMsgFailed(("Invalid command %ld\n", enmStreamCmd));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostALSAAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(void) drvHostALSAAudioShutdown(PPDMIHOSTAUDIO pInterface)
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(void *) drvHostALSAAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
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 * Construct a DirectSound Audio driver instance.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc FNPDMDRVCONSTRUCT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvHostAlsaAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVHOSTALSAAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTALSAAUDIO);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Init the static parts.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IBase */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pDrvIns->IBase.pfnQueryInterface = drvHostALSAAudioQueryInterface;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IHostAudio */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Char driver registration record.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32Version */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szName */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "ALSAAudio",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szRCMod */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szR0Mod */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pszDescription */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "ALSA host audio driver",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* fFlags */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* fClass. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cMaxInstances */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cbInstance */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnConstruct */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDestruct */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnRelocate */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnIOCtl */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnPowerOn */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnReset */
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,