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