VirtualBox

Changeset 88047 in vbox


Ignore:
Timestamp:
Mar 9, 2021 2:06:20 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143178
Message:

Audio: Moved the host audio device enumeration code to PDM (VBox/vmm/pdmaudiohostenuminline.h). bugref:9890

Location:
trunk
Files:
5 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmaudiohostenuminline.h

    r88045 r88047  
    11/* $Id$ */
    22/** @file
    3  * Intermedia audio driver, common routines.
    4  *
    5  * These are also used in the drivers which are bound to Main, e.g. the VRDE
    6  * or the video audio recording drivers.
     3 * PDM - Audio Helpers, Inlined Code. (DEV,++)
     4 *
     5 * This is all inlined because it's too tedious to create a couple libraries to
     6 * contain it all (same bad excuse as for intnetinline.h & pdmnetinline.h).
    77 */
    88
     
    1717 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
    1818 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    19  */
     19 *
     20 * The contents of this file may alternatively be used under the terms
     21 * of the Common Development and Distribution License Version 1.0
     22 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
     23 * VirtualBox OSE distribution, in which case the provisions of the
     24 * CDDL are applicable instead of those of the GPL.
     25 *
     26 * You may elect to license modified versions of this file under the
     27 * terms and conditions of either the GPL or the CDDL or both.
     28 */
     29
     30#ifndef VBOX_INCLUDED_vmm_pdmaudiohostenuminline_h
     31#define VBOX_INCLUDED_vmm_pdmaudiohostenuminline_h
     32#ifndef RT_WITHOUT_PRAGMA_ONCE
     33# pragma once
     34#endif
    2035
    2136
     
    2338*   Header Files                                                                                                                 *
    2439*********************************************************************************************************************************/
    25 #include <iprt/alloc.h>
     40#include <VBox/err.h>
     41#include <VBox/log.h>
     42#include <VBox/vmm/pdmaudioifs.h>
     43#include <VBox/vmm/pdmaudioinline.h>
     44
     45#include <iprt/asm.h>
    2646#include <iprt/asm-math.h>
    2747#include <iprt/assert.h>
    28 #include <iprt/dir.h>
    29 #include <iprt/file.h>
     48#include <iprt/mem.h>
    3049#include <iprt/string.h>
    31 #include <iprt/uuid.h>
    32 
    33 #define LOG_GROUP LOG_GROUP_DRV_AUDIO
    34 #include <VBox/log.h>
    35 
    36 #include <VBox/err.h>
    37 #include <VBox/vmm/pdmdev.h>
    38 #include <VBox/vmm/pdm.h>
    39 #include <VBox/vmm/pdmaudioinline.h>
    40 #include <VBox/vmm/mm.h>
    41 
    42 #include <ctype.h>
    43 #include <stdlib.h>
    44 
    45 #include "DrvAudio.h"
    46 #include "AudioMixBuffer.h"
    47 
    48 
    49 /*********************************************************************************************************************************
    50 *   Structures and Typedefs                                                                                                      *
    51 *********************************************************************************************************************************/
    52 /**
    53  * Structure for building up a .WAV file header.
    54  */
    55 typedef struct AUDIOWAVFILEHDR
    56 {
    57     uint32_t u32RIFF;
    58     uint32_t u32Size;
    59     uint32_t u32WAVE;
    60 
    61     uint32_t u32Fmt;
    62     uint32_t u32Size1;
    63     uint16_t u16AudioFormat;
    64     uint16_t u16NumChannels;
    65     uint32_t u32SampleRate;
    66     uint32_t u32ByteRate;
    67     uint16_t u16BlockAlign;
    68     uint16_t u16BitsPerSample;
    69 
    70     uint32_t u32ID2;
    71     uint32_t u32Size2;
    72 } AUDIOWAVFILEHDR, *PAUDIOWAVFILEHDR;
    73 AssertCompileSize(AUDIOWAVFILEHDR, 11*4);
    74 
    75 /**
    76  * Structure for keeeping the internal .WAV file data
    77  */
    78 typedef struct AUDIOWAVFILEDATA
    79 {
    80     /** The file header/footer. */
    81     AUDIOWAVFILEHDR Hdr;
    82 } AUDIOWAVFILEDATA, *PAUDIOWAVFILEDATA;
    83 
    84 
    85 
    86 #if 0 /* unused, no header prototypes */
    87 
    88 /**
    89  * Retrieves the matching PDMAUDIOFMT for the given bits + signing flag.
    90  *
    91  * @return  Matching PDMAUDIOFMT value.
    92  * @retval  PDMAUDIOFMT_INVALID if unsupported @a cBits value.
    93  *
    94  * @param   cBits       The number of bits in the audio format.
    95  * @param   fSigned     Whether the audio format is signed @c true or not.
    96  */
    97 PDMAUDIOFMT DrvAudioAudFmtBitsToFormat(uint8_t cBits, bool fSigned)
    98 {
    99     if (fSigned)
    100     {
    101         switch (cBits)
    102         {
    103             case 8:  return PDMAUDIOFMT_S8;
    104             case 16: return PDMAUDIOFMT_S16;
    105             case 32: return PDMAUDIOFMT_S32;
    106             default: AssertMsgFailedReturn(("Bogus audio bits %RU8\n", cBits), PDMAUDIOFMT_INVALID);
    107         }
    108     }
    109     else
    110     {
    111         switch (cBits)
    112         {
    113             case 8:  return PDMAUDIOFMT_U8;
    114             case 16: return PDMAUDIOFMT_U16;
    115             case 32: return PDMAUDIOFMT_U32;
    116             default: AssertMsgFailedReturn(("Bogus audio bits %RU8\n", cBits), PDMAUDIOFMT_INVALID);
    117         }
    118     }
    119 }
    120 
    121 /**
    122  * Returns an unique file name for this given audio connector instance.
    123  *
    124  * @return  Allocated file name. Must be free'd using RTStrFree().
    125  * @param   uInstance           Driver / device instance.
    126  * @param   pszPath             Path name of the file to delete. The path must exist.
    127  * @param   pszSuffix           File name suffix to use.
    128  */
    129 char *DrvAudioDbgGetFileNameA(uint8_t uInstance, const char *pszPath, const char *pszSuffix)
    130 {
    131     char szFileName[64];
    132     RTStrPrintf(szFileName, sizeof(szFileName), "drvAudio%RU8-%s", uInstance, pszSuffix);
    133 
    134     char szFilePath[RTPATH_MAX];
    135     int rc2 = RTStrCopy(szFilePath, sizeof(szFilePath), pszPath);
    136     AssertRC(rc2);
    137     rc2 = RTPathAppend(szFilePath, sizeof(szFilePath), szFileName);
    138     AssertRC(rc2);
    139 
    140     return RTStrDup(szFilePath);
    141 }
    142 
    143 #endif /* unused */
     50
    14451
    14552/**
     
    15259 *                  after it in its private structure.
    15360 */
    154 PPDMAUDIOHOSTDEV PDMAudioDeviceAlloc(size_t cb)
     61DECLINLINE(PPDMAUDIOHOSTDEV) PDMAudioDeviceAlloc(size_t cb)
    15562{
    15663    AssertReturn(cb >= sizeof(PDMAUDIOHOSTDEV), NULL);
     
    17582 * @param   pDev    The device to free.  NULL is ignored.
    17683 */
    177 void PDMAudioDeviceFree(PPDMAUDIOHOSTDEV pDev)
     84DECLINLINE(void) PDMAudioDeviceFree(PPDMAUDIOHOSTDEV pDev)
    17885{
    17986    if (pDev)
     
    195102 * @param   fOnlyCoreData
    196103 */
    197 PPDMAUDIOHOSTDEV PDMAudioDeviceDup(PPDMAUDIOHOSTDEV pDev, bool fOnlyCoreData)
     104DECLINLINE(PPDMAUDIOHOSTDEV) PDMAudioDeviceDup(PPDMAUDIOHOSTDEV pDev, bool fOnlyCoreData)
    198105{
    199106    AssertPtrReturn(pDev, NULL);
     
    220127 * @param   pDevEnm     The enumeration to initialize.
    221128 */
    222 void PDMAudioHostEnumInit(PPDMAUDIOHOSTENUM pDevEnm)
     129DECLINLINE(void) PDMAudioHostEnumInit(PPDMAUDIOHOSTENUM pDevEnm)
    223130{
    224131    AssertPtr(pDevEnm);
     
    237144 * @param   pDevEnm     The host audio device enumeration to delete.
    238145 */
    239 void PDMAudioHostEnumDelete(PPDMAUDIOHOSTENUM pDevEnm)
     146DECLINLINE(void) PDMAudioHostEnumDelete(PPDMAUDIOHOSTENUM pDevEnm)
    240147{
    241148    if (pDevEnm)
     
    268175 * @param  pDev                 Device to add. The pointer will be owned by the device enumeration  then.
    269176 */
    270 void PDMAudioHostEnumAppend(PPDMAUDIOHOSTENUM pDevEnm, PPDMAUDIOHOSTDEV pDev)
     177DECLINLINE(void) PDMAudioHostEnumAppend(PPDMAUDIOHOSTENUM pDevEnm, PPDMAUDIOHOSTDEV pDev)
    271178{
    272179    AssertPtr(pDevEnm);
     
    290197 *                          backends have data that can be copied.
    291198 */
    292 int PDMAudioHostEnumCopy(PPDMAUDIOHOSTENUM pDstDevEnm, PCPDMAUDIOHOSTENUM pSrcDevEnm,
    293                          PDMAUDIODIR enmUsage, bool fOnlyCoreData)
     199DECLINLINE(int) PDMAudioHostEnumCopy(PPDMAUDIOHOSTENUM pDstDevEnm, PCPDMAUDIOHOSTENUM pSrcDevEnm,
     200                                     PDMAUDIODIR enmUsage, bool fOnlyCoreData)
    294201{
    295202    AssertPtrReturn(pDstDevEnm, VERR_INVALID_POINTER);
     
    327234 *                      PDMAUDIOHOSTDEV_F_DEFAULT set.
    328235 */
    329 PPDMAUDIOHOSTDEV PDMAudioHostEnumGetDefault(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)
     236DECLINLINE(PPDMAUDIOHOSTDEV) PDMAudioHostEnumGetDefault(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)
    330237{
    331238    AssertPtrReturn(pDevEnm, NULL);
     
    354261 *                      Pass PDMAUDIODIR_INVALID to get the total number of devices.
    355262 */
    356 uint32_t PDMAudioHostEnumCountMatching(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)
     263DECLINLINE(uint32_t) PDMAudioHostEnumCountMatching(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)
    357264{
    358265    AssertPtrReturn(pDevEnm, 0);
     
    373280}
    374281
     282/** The max string length for all PDMAUDIOHOSTDEV_F_XXX.
     283 * @sa PDMAudioDeviceFlagsToString */
     284#define PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN    (7 * 8)
     285
     286/**
     287 * Converts an audio device flags to a string.
     288 *
     289 * @returns
     290 * @param   pszDst      Destination buffer with a size of at least
     291 *                      PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN bytes (including
     292 *                      the string terminator).
     293 * @param   fFlags      Audio flags (PDMAUDIOHOSTDEV_F_XXX) to convert.
     294 */
     295DECLINLINE(const char *) PDMAudioDeviceFlagsToString(char pszDst[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN], uint32_t fFlags)
     296{
     297    static const struct { const char *pszMnemonic; uint32_t cchMnemonic; uint32_t fFlag; } s_aFlags[] =
     298    {
     299        { RT_STR_TUPLE("DEFAULT "), PDMAUDIOHOSTDEV_F_DEFAULT },
     300        { RT_STR_TUPLE("HOTPLUG "), PDMAUDIOHOSTDEV_F_HOTPLUG },
     301        { RT_STR_TUPLE("BUGGY "),   PDMAUDIOHOSTDEV_F_BUGGY   },
     302        { RT_STR_TUPLE("IGNORE "),  PDMAUDIOHOSTDEV_F_IGNORE  },
     303        { RT_STR_TUPLE("LOCKED "),  PDMAUDIOHOSTDEV_F_LOCKED  },
     304        { RT_STR_TUPLE("DEAD "),    PDMAUDIOHOSTDEV_F_DEAD    },
     305        { RT_STR_TUPLE("NO_DUP "),  PDMAUDIOHOSTDEV_F_NO_DUP  },
     306    };
     307    size_t offDst = 0;
     308    for (uint32_t i = 0; i < RT_ELEMENTS(s_aFlags); i++)
     309        if (fFlags & s_aFlags[i].fFlag)
     310        {
     311            fFlags &= ~s_aFlags[i].fFlag;
     312            memcpy(&pszDst[offDst], s_aFlags[i].pszMnemonic, s_aFlags[i].cchMnemonic);
     313            offDst += s_aFlags[i].cchMnemonic;
     314        }
     315    Assert(fFlags == 0);
     316    Assert(offDst < PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN);
     317
     318    if (offDst)
     319        pszDst[offDst - 1] = '\0';
     320    else
     321        memcpy(pszDst, "NONE", sizeof("NONE"));
     322    return pszDst;
     323}
     324
    375325/**
    376326 * Logs an audio device enumeration.
     
    379329 * @param  pszDesc  Logging description (prefix).
    380330 */
    381 void PDMAudioHostEnumLog(PCPDMAUDIOHOSTENUM pDevEnm, const char *pszDesc)
     331DECLINLINE(void) PDMAudioHostEnumLog(PCPDMAUDIOHOSTENUM pDevEnm, const char *pszDesc)
    382332{
    383333    AssertPtrReturnVoid(pDevEnm);
     
    390340    RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, Node)
    391341    {
    392         char *pszFlags = DrvAudioHlpAudDevFlagsToStrA(pDev->fFlags);
    393 
     342        char szFlags[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN];
    394343        LogFunc(("Device '%s':\n", pDev->szName));
    395344        LogFunc(("  Usage           = %s\n",             PDMAudioDirGetName(pDev->enmUsage)));
    396         LogFunc(("  Flags           = %s\n",             pszFlags ? pszFlags : "<NONE>"));
     345        LogFunc(("  Flags           = %s\n",             PDMAudioDeviceFlagsToString(szFlags, pDev->fFlags)));
    397346        LogFunc(("  Input channels  = %RU8\n",           pDev->cMaxInputChannels));
    398347        LogFunc(("  Output channels = %RU8\n",           pDev->cMaxOutputChannels));
    399348        LogFunc(("  cbExtra         = %RU32 bytes\n",    pDev->cbSelf - sizeof(PDMAUDIOHOSTDEV)));
    400 
    401         if (pszFlags)
    402             RTStrFree(pszFlags);
    403     }
    404 }
    405 
    406 /**
    407  * Converts an audio device flags to a string.
    408  *
    409  * @returns Stringified audio flags. Must be free'd with RTStrFree().
    410  *          NULL if no flags set.
    411  * @param   fFlags      Audio flags (PDMAUDIOHOSTDEV_F_XXX) to convert.
    412  */
    413 char *DrvAudioHlpAudDevFlagsToStrA(uint32_t fFlags)
    414 {
    415 #define APPEND_FLAG_TO_STR(_aFlag)              \
    416     if (fFlags & PDMAUDIOHOSTDEV_F_##_aFlag)    \
    417     {                                           \
    418         if (pszFlags)                           \
    419         {                                       \
    420             rc2 = RTStrAAppend(&pszFlags, " "); \
    421             if (RT_FAILURE(rc2))                \
    422                 break;                          \
    423         }                                       \
    424                                                 \
    425         rc2 = RTStrAAppend(&pszFlags, #_aFlag); \
    426         if (RT_FAILURE(rc2))                    \
    427             break;                              \
    428     }                                           \
    429 
    430     char *pszFlags = NULL;
    431     int rc2 = VINF_SUCCESS;
    432 
    433     do
    434     {
    435         APPEND_FLAG_TO_STR(DEFAULT);
    436         APPEND_FLAG_TO_STR(HOTPLUG);
    437         APPEND_FLAG_TO_STR(BUGGY);
    438         APPEND_FLAG_TO_STR(IGNORE);
    439         APPEND_FLAG_TO_STR(LOCKED);
    440         APPEND_FLAG_TO_STR(DEAD);
    441         APPEND_FLAG_TO_STR(NO_DUP);
    442 
    443     } while (0);
    444 
    445     if (!pszFlags)
    446         rc2 = RTStrAAppend(&pszFlags, "NONE");
    447 
    448     if (   RT_FAILURE(rc2)
    449         && pszFlags)
    450     {
    451         RTStrFree(pszFlags);
    452         pszFlags = NULL;
    453     }
    454 
    455 #undef APPEND_FLAG_TO_STR
    456 
    457     return pszFlags;
    458 }
    459 
    460 /**
    461  * Converts a given string to an audio format.
    462  *
    463  * @returns Audio format for the given string, or PDMAUDIOFMT_INVALID if not found.
    464  * @param   pszFmt              String to convert to an audio format.
    465  */
    466 PDMAUDIOFMT DrvAudioHlpStrToAudFmt(const char *pszFmt)
    467 {
    468     AssertPtrReturn(pszFmt, PDMAUDIOFMT_INVALID);
    469 
    470     if (!RTStrICmp(pszFmt, "u8"))
    471         return PDMAUDIOFMT_U8;
    472     if (!RTStrICmp(pszFmt, "u16"))
    473         return PDMAUDIOFMT_U16;
    474     if (!RTStrICmp(pszFmt, "u32"))
    475         return PDMAUDIOFMT_U32;
    476     if (!RTStrICmp(pszFmt, "s8"))
    477         return PDMAUDIOFMT_S8;
    478     if (!RTStrICmp(pszFmt, "s16"))
    479         return PDMAUDIOFMT_S16;
    480     if (!RTStrICmp(pszFmt, "s32"))
    481         return PDMAUDIOFMT_S32;
    482 
    483     AssertMsgFailed(("Invalid audio format '%s'\n", pszFmt));
    484     return PDMAUDIOFMT_INVALID;
    485 }
    486 
    487 /**
    488  * Checks whether a given stream configuration is valid or not.
    489  *
    490  * @note    See notes on DrvAudioHlpPcmPropsAreValid().
    491  *
    492  * Returns @c true if configuration is valid, @c false if not.
    493  * @param   pCfg                Stream configuration to check.
    494  */
    495 bool DrvAudioHlpStreamCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg)
    496 {
    497     AssertPtrReturn(pCfg, false);
    498 
    499     AssertReturn(PDMAudioStrmCfgIsValid(pCfg), false);
    500 
    501     bool fValid = (   pCfg->enmDir == PDMAUDIODIR_IN
    502                    || pCfg->enmDir == PDMAUDIODIR_OUT);
    503 
    504     fValid &= (   pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED
    505                || pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
    506 
    507     if (fValid)
    508         fValid = DrvAudioHlpPcmPropsAreValid(&pCfg->Props);
    509 
    510     return fValid;
    511 }
    512 
    513 /**
    514  * Calculates the audio bit rate of the given bits per sample, the Hz and the number
    515  * of audio channels.
    516  *
    517  * Divide the result by 8 to get the byte rate.
    518  *
    519  * @returns Bitrate.
    520  * @param   cBits               Number of bits per sample.
    521  * @param   uHz                 Hz (Hertz) rate.
    522  * @param   cChannels           Number of audio channels.
    523  */
    524 uint32_t DrvAudioHlpCalcBitrate(uint8_t cBits, uint32_t uHz, uint8_t cChannels)
    525 {
    526     return cBits * uHz * cChannels;
    527 }
    528 
    529 
    530 /**
    531  * Checks whether given PCM properties are valid or not.
    532  *
    533  * @note  This is more of a supported than valid check.  There is code for
    534  *        unsigned samples elsewhere (like DrvAudioHlpClearBuf()), but this
    535  *        function will flag such properties as not valid.
    536  *
    537  * @todo  r=bird: See note and explain properly.
    538  *
    539  * @returns @c true if the properties are valid, @c false if not.
    540  * @param   pProps      The PCM properties to check.
    541  */
    542 bool DrvAudioHlpPcmPropsAreValid(PCPDMAUDIOPCMPROPS pProps)
    543 {
    544     AssertPtrReturn(pProps, false);
    545 
    546     AssertReturn(PDMAudioPropsAreValid(pProps), false);
    547 
    548     /** @todo r=bird: This code is cannot make up its mind whether to return on
    549      *        false, or whether to return at the end. (hint: just return
    550      *        immediately, duh.) */
    551 
    552     /* Minimum 1 channel (mono), maximum 7.1 (= 8) channels. */
    553     bool fValid = (   pProps->cChannels >= 1
    554                    && pProps->cChannels <= 8);
    555 
    556     if (fValid)
    557     {
    558         switch (pProps->cbSample)
    559         {
    560             case 1: /* 8 bit */
    561                if (pProps->fSigned)
    562                    fValid = false;
    563                break;
    564             case 2: /* 16 bit */
    565                 if (!pProps->fSigned)
    566                     fValid = false;
    567                 break;
    568             /** @todo Do we need support for 24 bit samples? */
    569             case 4: /* 32 bit */
    570                 if (!pProps->fSigned)
    571                     fValid = false;
    572                 break;
    573             default:
    574                 fValid = false;
    575                 break;
    576         }
    577     }
    578 
    579     if (!fValid)
    580         return false;
    581 
    582     fValid &= pProps->uHz > 0;
    583     fValid &= pProps->cShift == PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cbSample, pProps->cChannels);
    584     fValid &= pProps->fSwapEndian == false; /** @todo Handling Big Endian audio data is not supported yet. */
    585 
    586     return fValid;
    587 }
    588 
    589 
    590 /*********************************************************************************************************************************
    591 *   Audio File Helpers                                                                                                           *
    592 *********************************************************************************************************************************/
    593 
    594 /**
    595  * Sanitizes the file name component so that unsupported characters
    596  * will be replaced by an underscore ("_").
    597  *
    598  * @return  IPRT status code.
    599  * @param   pszPath             Path to sanitize.
    600  * @param   cbPath              Size (in bytes) of path to sanitize.
    601  */
    602 int DrvAudioHlpFileNameSanitize(char *pszPath, size_t cbPath)
    603 {
    604     RT_NOREF(cbPath);
    605     int rc = VINF_SUCCESS;
    606 #ifdef RT_OS_WINDOWS
    607     /* Filter out characters not allowed on Windows platforms, put in by
    608        RTTimeSpecToString(). */
    609     /** @todo Use something like RTPathSanitize() if available later some time. */
    610     static RTUNICP const s_uszValidRangePairs[] =
    611     {
    612         ' ', ' ',
    613         '(', ')',
    614         '-', '.',
    615         '0', '9',
    616         'A', 'Z',
    617         'a', 'z',
    618         '_', '_',
    619         0xa0, 0xd7af,
    620         '\0'
    621     };
    622     ssize_t cReplaced = RTStrPurgeComplementSet(pszPath, s_uszValidRangePairs, '_' /* Replacement */);
    623     if (cReplaced < 0)
    624         rc = VERR_INVALID_UTF8_ENCODING;
    625 #else
    626     RT_NOREF(pszPath);
    627 #endif
    628     return rc;
    629 }
    630 
    631 /**
    632  * Constructs an unique file name, based on the given path and the audio file type.
    633  *
    634  * @returns IPRT status code.
    635  * @param   pszFile             Where to store the constructed file name.
    636  * @param   cchFile             Size (in characters) of the file name buffer.
    637  * @param   pszPath             Base path to use.
    638  *                              If NULL or empty, the system's temporary directory will be used.
    639  * @param   pszName             A name for better identifying the file.
    640  * @param   uInstance           Device / driver instance which is using this file.
    641  * @param   enmType             Audio file type to construct file name for.
    642  * @param   fFlags              File naming flags, PDMAUDIOFILENAME_FLAGS_XXX.
    643  */
    644 int DrvAudioHlpFileNameGet(char *pszFile, size_t cchFile, const char *pszPath, const char *pszName,
    645                            uint32_t uInstance, PDMAUDIOFILETYPE enmType, uint32_t fFlags)
    646 {
    647     AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
    648     AssertReturn(cchFile,    VERR_INVALID_PARAMETER);
    649     /* pszPath can be NULL. */
    650     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    651     /** @todo Validate fFlags. */
    652 
    653     int rc;
    654 
    655     char *pszPathTmp = NULL;
    656 
    657     do
    658     {
    659         if (   pszPath == NULL
    660             || !strlen(pszPath))
    661         {
    662             char szTemp[RTPATH_MAX];
    663             rc = RTPathTemp(szTemp, sizeof(szTemp));
    664             if (RT_SUCCESS(rc))
    665             {
    666                 pszPathTmp = RTStrDup(szTemp);
    667             }
    668             else
    669                 break;
    670         }
    671         else
    672             pszPathTmp = RTStrDup(pszPath);
    673 
    674         AssertPtrBreakStmt(pszPathTmp, rc = VERR_NO_MEMORY);
    675 
    676         char szFilePath[RTPATH_MAX];
    677         rc = RTStrCopy(szFilePath, sizeof(szFilePath), pszPathTmp);
    678         AssertRCBreak(rc);
    679 
    680         /* Create it when necessary. */
    681         if (!RTDirExists(szFilePath))
    682         {
    683             rc = RTDirCreateFullPath(szFilePath, RTFS_UNIX_IRWXU);
    684             if (RT_FAILURE(rc))
    685                 break;
    686         }
    687 
    688         char szFileName[RTPATH_MAX];
    689         szFileName[0] = '\0';
    690 
    691         if (fFlags & PDMAUDIOFILENAME_FLAGS_TS)
    692         {
    693             RTTIMESPEC time;
    694             if (!RTTimeSpecToString(RTTimeNow(&time), szFileName, sizeof(szFileName)))
    695             {
    696                 rc = VERR_BUFFER_OVERFLOW;
    697                 break;
    698             }
    699 
    700             rc = DrvAudioHlpFileNameSanitize(szFileName, sizeof(szFileName));
    701             if (RT_FAILURE(rc))
    702                 break;
    703 
    704             rc = RTStrCat(szFileName, sizeof(szFileName), "-");
    705             if (RT_FAILURE(rc))
    706                 break;
    707         }
    708 
    709         rc = RTStrCat(szFileName, sizeof(szFileName), pszName);
    710         if (RT_FAILURE(rc))
    711             break;
    712 
    713         rc = RTStrCat(szFileName, sizeof(szFileName), "-");
    714         if (RT_FAILURE(rc))
    715             break;
    716 
    717         char szInst[16];
    718         RTStrPrintf2(szInst, sizeof(szInst), "%RU32", uInstance);
    719         rc = RTStrCat(szFileName, sizeof(szFileName), szInst);
    720         if (RT_FAILURE(rc))
    721             break;
    722 
    723         switch (enmType)
    724         {
    725             case PDMAUDIOFILETYPE_RAW:
    726                 rc = RTStrCat(szFileName, sizeof(szFileName), ".pcm");
    727                 break;
    728 
    729             case PDMAUDIOFILETYPE_WAV:
    730                 rc = RTStrCat(szFileName, sizeof(szFileName), ".wav");
    731                 break;
    732 
    733             default:
    734                 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
    735                 break;
    736         }
    737 
    738         if (RT_FAILURE(rc))
    739             break;
    740 
    741         rc = RTPathAppend(szFilePath, sizeof(szFilePath), szFileName);
    742         if (RT_FAILURE(rc))
    743             break;
    744 
    745         rc = RTStrCopy(pszFile, cchFile, szFilePath);
    746 
    747     } while (0);
    748 
    749     RTStrFree(pszPathTmp);
    750 
    751     LogFlowFuncLeaveRC(rc);
    752     return rc;
    753 }
    754 
    755 /**
    756  * Creates an audio file.
    757  *
    758  * @returns IPRT status code.
    759  * @param   enmType             Audio file type to open / create.
    760  * @param   pszFile             File path of file to open or create.
    761  * @param   fFlags              Audio file flags, PDMAUDIOFILE_FLAGS_XXX.
    762  * @param   ppFile              Where to store the created audio file handle.
    763  *                              Needs to be destroyed with DrvAudioHlpFileDestroy().
    764  */
    765 int DrvAudioHlpFileCreate(PDMAUDIOFILETYPE enmType, const char *pszFile, uint32_t fFlags, PPDMAUDIOFILE *ppFile)
    766 {
    767     AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
    768     /** @todo Validate fFlags. */
    769 
    770     PPDMAUDIOFILE pFile = (PPDMAUDIOFILE)RTMemAlloc(sizeof(PDMAUDIOFILE));
    771     if (!pFile)
    772         return VERR_NO_MEMORY;
    773 
    774     int rc = VINF_SUCCESS;
    775 
    776     switch (enmType)
    777     {
    778         case PDMAUDIOFILETYPE_RAW:
    779         case PDMAUDIOFILETYPE_WAV:
    780             pFile->enmType = enmType;
    781             break;
    782 
    783         default:
    784             rc = VERR_INVALID_PARAMETER;
    785             break;
    786     }
    787 
    788     if (RT_SUCCESS(rc))
    789     {
    790         RTStrPrintf(pFile->szName, RT_ELEMENTS(pFile->szName), "%s", pszFile);
    791         pFile->hFile  = NIL_RTFILE;
    792         pFile->fFlags = fFlags;
    793         pFile->pvData = NULL;
    794         pFile->cbData = 0;
    795     }
    796 
    797     if (RT_FAILURE(rc))
    798     {
    799         RTMemFree(pFile);
    800         pFile = NULL;
    801     }
    802     else
    803         *ppFile = pFile;
    804 
    805     return rc;
    806 }
    807 
    808 /**
    809  * Destroys a formerly created audio file.
    810  *
    811  * @param   pFile               Audio file (object) to destroy.
    812  */
    813 void DrvAudioHlpFileDestroy(PPDMAUDIOFILE pFile)
    814 {
    815     if (!pFile)
    816         return;
    817 
    818     DrvAudioHlpFileClose(pFile);
    819 
    820     RTMemFree(pFile);
    821     pFile = NULL;
    822 }
    823 
    824 /**
    825  * Opens or creates an audio file.
    826  *
    827  * @returns IPRT status code.
    828  * @param   pFile               Pointer to audio file handle to use.
    829  * @param   fOpen               Open flags.
    830  *                              Use PDMAUDIOFILE_DEFAULT_OPEN_FLAGS for the default open flags.
    831  * @param   pProps              PCM properties to use.
    832  */
    833 int DrvAudioHlpFileOpen(PPDMAUDIOFILE pFile, uint32_t fOpen, PCPDMAUDIOPCMPROPS pProps)
    834 {
    835     AssertPtrReturn(pFile,   VERR_INVALID_POINTER);
    836     /** @todo Validate fOpen flags. */
    837     AssertPtrReturn(pProps,  VERR_INVALID_POINTER);
    838 
    839     int rc;
    840 
    841     if (pFile->enmType == PDMAUDIOFILETYPE_RAW)
    842     {
    843         rc = RTFileOpen(&pFile->hFile, pFile->szName, fOpen);
    844     }
    845     else if (pFile->enmType == PDMAUDIOFILETYPE_WAV)
    846     {
    847         Assert(pProps->cChannels);
    848         Assert(pProps->uHz);
    849         Assert(pProps->cbSample);
    850 
    851         pFile->pvData = (PAUDIOWAVFILEDATA)RTMemAllocZ(sizeof(AUDIOWAVFILEDATA));
    852         if (pFile->pvData)
    853         {
    854             pFile->cbData = sizeof(PAUDIOWAVFILEDATA);
    855 
    856             PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData;
    857             AssertPtr(pData);
    858 
    859             /* Header. */
    860             pData->Hdr.u32RIFF          = AUDIO_MAKE_FOURCC('R','I','F','F');
    861             pData->Hdr.u32Size          = 36;
    862             pData->Hdr.u32WAVE          = AUDIO_MAKE_FOURCC('W','A','V','E');
    863 
    864             pData->Hdr.u32Fmt           = AUDIO_MAKE_FOURCC('f','m','t',' ');
    865             pData->Hdr.u32Size1         = 16; /* Means PCM. */
    866             pData->Hdr.u16AudioFormat   = 1;  /* PCM, linear quantization. */
    867             pData->Hdr.u16NumChannels   = pProps->cChannels;
    868             pData->Hdr.u32SampleRate    = pProps->uHz;
    869             pData->Hdr.u32ByteRate      = PDMAudioPropsGetBitrate(pProps) / 8;
    870             pData->Hdr.u16BlockAlign    = pProps->cChannels * pProps->cbSample;
    871             pData->Hdr.u16BitsPerSample = pProps->cbSample * 8;
    872 
    873             /* Data chunk. */
    874             pData->Hdr.u32ID2           = AUDIO_MAKE_FOURCC('d','a','t','a');
    875             pData->Hdr.u32Size2         = 0;
    876 
    877             rc = RTFileOpen(&pFile->hFile, pFile->szName, fOpen);
    878             if (RT_SUCCESS(rc))
    879             {
    880                 rc = RTFileWrite(pFile->hFile, &pData->Hdr, sizeof(pData->Hdr), NULL);
    881                 if (RT_FAILURE(rc))
    882                 {
    883                     RTFileClose(pFile->hFile);
    884                     pFile->hFile = NIL_RTFILE;
    885                 }
    886             }
    887 
    888             if (RT_FAILURE(rc))
    889             {
    890                 RTMemFree(pFile->pvData);
    891                 pFile->pvData = NULL;
    892                 pFile->cbData = 0;
    893             }
    894         }
    895         else
    896             rc = VERR_NO_MEMORY;
    897     }
    898     else
    899         rc = VERR_INVALID_PARAMETER;
    900 
    901     if (RT_SUCCESS(rc))
    902     {
    903         LogRel2(("Audio: Opened file '%s'\n", pFile->szName));
    904     }
    905     else
    906         LogRel(("Audio: Failed opening file '%s', rc=%Rrc\n", pFile->szName, rc));
    907 
    908     return rc;
    909 }
    910 
    911 /**
    912  * Closes an audio file.
    913  *
    914  * @returns IPRT status code.
    915  * @param   pFile               Audio file handle to close.
    916  */
    917 int DrvAudioHlpFileClose(PPDMAUDIOFILE pFile)
    918 {
    919     if (!pFile)
    920         return VINF_SUCCESS;
    921 
    922     size_t cbSize = DrvAudioHlpFileGetDataSize(pFile);
    923 
    924     int rc = VINF_SUCCESS;
    925 
    926     if (pFile->enmType == PDMAUDIOFILETYPE_RAW)
    927     {
    928         if (RTFileIsValid(pFile->hFile))
    929             rc = RTFileClose(pFile->hFile);
    930     }
    931     else if (pFile->enmType == PDMAUDIOFILETYPE_WAV)
    932     {
    933         if (RTFileIsValid(pFile->hFile))
    934         {
    935             PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData;
    936             if (pData) /* The .WAV file data only is valid when a file actually has been created. */
    937             {
    938                 /* Update the header with the current data size. */
    939                 RTFileWriteAt(pFile->hFile, 0, &pData->Hdr, sizeof(pData->Hdr), NULL);
    940             }
    941 
    942             rc = RTFileClose(pFile->hFile);
    943         }
    944 
    945         if (pFile->pvData)
    946         {
    947             RTMemFree(pFile->pvData);
    948             pFile->pvData = NULL;
    949         }
    950     }
    951     else
    952         AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
    953 
    954     if (   RT_SUCCESS(rc)
    955         && !cbSize
    956         && !(pFile->fFlags & PDMAUDIOFILE_FLAGS_KEEP_IF_EMPTY))
    957     {
    958         rc = DrvAudioHlpFileDelete(pFile);
    959     }
    960 
    961     pFile->cbData = 0;
    962 
    963     if (RT_SUCCESS(rc))
    964     {
    965         pFile->hFile = NIL_RTFILE;
    966         LogRel2(("Audio: Closed file '%s' (%zu bytes)\n", pFile->szName, cbSize));
    967     }
    968     else
    969         LogRel(("Audio: Failed closing file '%s', rc=%Rrc\n", pFile->szName, rc));
    970 
    971     return rc;
    972 }
    973 
    974 /**
    975  * Deletes an audio file.
    976  *
    977  * @returns IPRT status code.
    978  * @param   pFile               Audio file handle to delete.
    979  */
    980 int DrvAudioHlpFileDelete(PPDMAUDIOFILE pFile)
    981 {
    982     AssertPtrReturn(pFile, VERR_INVALID_POINTER);
    983 
    984     int rc = RTFileDelete(pFile->szName);
    985     if (RT_SUCCESS(rc))
    986     {
    987         LogRel2(("Audio: Deleted file '%s'\n", pFile->szName));
    988     }
    989     else if (rc == VERR_FILE_NOT_FOUND) /* Don't bitch if the file is not around (anymore). */
    990         rc = VINF_SUCCESS;
    991 
    992     if (RT_FAILURE(rc))
    993         LogRel(("Audio: Failed deleting file '%s', rc=%Rrc\n", pFile->szName, rc));
    994 
    995     return rc;
    996 }
    997 
    998 /**
    999  * Returns the raw audio data size of an audio file.
    1000  *
    1001  * Note: This does *not* include file headers and other data which does
    1002  *       not belong to the actual PCM audio data.
    1003  *
    1004  * @returns Size (in bytes) of the raw PCM audio data.
    1005  * @param   pFile               Audio file handle to retrieve the audio data size for.
    1006  */
    1007 size_t DrvAudioHlpFileGetDataSize(PPDMAUDIOFILE pFile)
    1008 {
    1009     AssertPtrReturn(pFile, 0);
    1010 
    1011     size_t cbSize = 0;
    1012 
    1013     if (pFile->enmType == PDMAUDIOFILETYPE_RAW)
    1014     {
    1015         cbSize = RTFileTell(pFile->hFile);
    1016     }
    1017     else if (pFile->enmType == PDMAUDIOFILETYPE_WAV)
    1018     {
    1019         PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData;
    1020         if (pData) /* The .WAV file data only is valid when a file actually has been created. */
    1021             cbSize = pData->Hdr.u32Size2;
    1022     }
    1023 
    1024     return cbSize;
    1025 }
    1026 
    1027 /**
    1028  * Returns whether the given audio file is open and in use or not.
    1029  *
    1030  * @return  bool                True if open, false if not.
    1031  * @param   pFile               Audio file handle to check open status for.
    1032  */
    1033 bool DrvAudioHlpFileIsOpen(PPDMAUDIOFILE pFile)
    1034 {
    1035     if (!pFile)
    1036         return false;
    1037 
    1038     return RTFileIsValid(pFile->hFile);
    1039 }
    1040 
    1041 /**
    1042  * Write PCM data to a wave (.WAV) file.
    1043  *
    1044  * @returns IPRT status code.
    1045  * @param   pFile               Audio file handle to write PCM data to.
    1046  * @param   pvBuf               Audio data to write.
    1047  * @param   cbBuf               Size (in bytes) of audio data to write.
    1048  * @param   fFlags              Additional write flags. Not being used at the moment and must be 0.
    1049  */
    1050 int DrvAudioHlpFileWrite(PPDMAUDIOFILE pFile, const void *pvBuf, size_t cbBuf, uint32_t fFlags)
    1051 {
    1052     AssertPtrReturn(pFile, VERR_INVALID_POINTER);
    1053     AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
    1054 
    1055     AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /** @todo fFlags are currently not implemented. */
    1056 
    1057     if (!cbBuf)
    1058         return VINF_SUCCESS;
    1059 
    1060     AssertReturn(RTFileIsValid(pFile->hFile), VERR_WRONG_ORDER);
    1061 
    1062     int rc;
    1063 
    1064     if (pFile->enmType == PDMAUDIOFILETYPE_RAW)
    1065     {
    1066         rc = RTFileWrite(pFile->hFile, pvBuf, cbBuf, NULL);
    1067     }
    1068     else if (pFile->enmType == PDMAUDIOFILETYPE_WAV)
    1069     {
    1070         PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData;
    1071         AssertPtr(pData);
    1072 
    1073         rc = RTFileWrite(pFile->hFile, pvBuf, cbBuf, NULL);
    1074         if (RT_SUCCESS(rc))
    1075         {
    1076             pData->Hdr.u32Size  += (uint32_t)cbBuf;
    1077             pData->Hdr.u32Size2 += (uint32_t)cbBuf;
    1078         }
    1079     }
    1080     else
    1081         rc = VERR_NOT_SUPPORTED;
    1082 
    1083     return rc;
    1084 }
    1085 
     349    }
     350}
     351
     352#endif /* VBOX_INCLUDED_vmm_pdmaudiohostenuminline_h */
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r88045 r88047  
    3030#include <VBox/vmm/pdmaudioifs.h>
    3131#include <VBox/vmm/pdmaudioinline.h>
     32#include <VBox/vmm/pdmaudiohostenuminline.h>
    3233
    3334#include <iprt/alloc.h>
     
    21762177                if (fLog)
    21772178                {
    2178                     char *pszFlags = DrvAudioHlpAudDevFlagsToStrA(pDev->fFlags);
    2179 
     2179                    char szFlags[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN];
    21802180                    LogRel(("Audio: Device '%s':\n", pDev->szName));
    2181                     LogRel(("Audio: \tUsage           = %s\n",   PDMAudioDirGetName(pDev->enmUsage)));
    2182                     LogRel(("Audio: \tFlags           = %s\n",   pszFlags ? pszFlags : "<NONE>"));
    2183                     LogRel(("Audio: \tInput channels  = %RU8\n", pDev->cMaxInputChannels));
    2184                     LogRel(("Audio: \tOutput channels = %RU8\n", pDev->cMaxOutputChannels));
    2185 
    2186                     if (pszFlags)
    2187                         RTStrFree(pszFlags);
     2181                    LogRel(("Audio:   Usage           = %s\n",   PDMAudioDirGetName(pDev->enmUsage)));
     2182                    LogRel(("Audio:   Flags           = %s\n",   PDMAudioDeviceFlagsToString(szFlags, pDev->fFlags)));
     2183                    LogRel(("Audio:   Input channels  = %RU8\n", pDev->cMaxInputChannels));
     2184                    LogRel(("Audio:   Output channels = %RU8\n", pDev->cMaxOutputChannels));
    21882185                }
    21892186            }
  • trunk/src/VBox/Devices/Audio/DrvAudio.h

    r88045 r88047  
    207207/** @}  */
    208208
    209 /** @name Audio device methods.
    210  * @{ */
    211 PPDMAUDIOHOSTDEV PDMAudioDeviceAlloc(size_t cb);
    212 void            PDMAudioDeviceFree(PPDMAUDIOHOSTDEV pDev);
    213 PPDMAUDIOHOSTDEV PDMAudioDeviceDup(const PPDMAUDIOHOSTDEV pDev, bool fOnlyCoreData);
    214 /** @}  */
    215 
    216 /** @name Audio device enumeration methods.
    217  * @{ */
    218 void            PDMAudioHostEnumInit(PPDMAUDIOHOSTENUM pDevEnm);
    219 void            PDMAudioHostEnumDelete(PPDMAUDIOHOSTENUM pDevEnm);
    220 void            PDMAudioHostEnumAppend(PPDMAUDIOHOSTENUM pDevEnm, PPDMAUDIOHOSTDEV pDev);
    221 int             PDMAudioHostEnumCopy(PPDMAUDIOHOSTENUM pDstDevEnm, PCPDMAUDIOHOSTENUM pSrcDevEnm,
    222                                      PDMAUDIODIR enmUsage, bool fOnlyCoreData);
    223 PPDMAUDIOHOSTDEV PDMAudioHostEnumGetDefault(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmDir);
    224 uint32_t        PDMAudioHostEnumCountMatching(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage);
    225 void            PDMAudioHostEnumLog(PCPDMAUDIOHOSTENUM pDevEnm, const char *pszDesc);
    226 /** @}  */
    227 
    228209/** @name Audio string-ify methods.
    229210 * @{ */
    230211PDMAUDIOFMT DrvAudioHlpStrToAudFmt(const char *pszFmt);
    231 char *DrvAudioHlpAudDevFlagsToStrA(uint32_t fFlags);
    232212/** @}  */
    233213
  • trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp

    r88045 r88047  
    142142
    143143#endif /* unused */
    144 
    145 /**
    146  * Allocates an audio device.
    147  *
    148  * @returns Newly allocated audio device, or NULL on failure.
    149  * @param   cb      The total device structure size.   This must be at least the
    150  *                  size of PDMAUDIOHOSTDEV.  The idea is that the caller extends
    151  *                  the PDMAUDIOHOSTDEV structure and appends additional data
    152  *                  after it in its private structure.
    153  */
    154 PPDMAUDIOHOSTDEV PDMAudioDeviceAlloc(size_t cb)
    155 {
    156     AssertReturn(cb >= sizeof(PDMAUDIOHOSTDEV), NULL);
    157     AssertReturn(cb < _4M, NULL);
    158 
    159     PPDMAUDIOHOSTDEV pDev = (PPDMAUDIOHOSTDEV)RTMemAllocZ(RT_ALIGN_Z(cb, 64));
    160     if (pDev)
    161     {
    162         pDev->uMagic = PDMAUDIOHOSTDEV_MAGIC;
    163         pDev->cbSelf = (uint32_t)cb;
    164         RTListInit(&pDev->Node);
    165 
    166         //pDev->cMaxInputChannels  = 0;
    167         //pDev->cMaxOutputChannels = 0;
    168     }
    169     return pDev;
    170 }
    171 
    172 /**
    173  * Frees an audio device allocated by PDMAudioDeviceAlloc.
    174  *
    175  * @param   pDev    The device to free.  NULL is ignored.
    176  */
    177 void PDMAudioDeviceFree(PPDMAUDIOHOSTDEV pDev)
    178 {
    179     if (pDev)
    180     {
    181         Assert(pDev->uMagic == PDMAUDIOHOSTDEV_MAGIC);
    182         Assert(pDev->cRefCount == 0);
    183         pDev->uMagic = PDMAUDIOHOSTDEV_MAGIC_DEAD;
    184         pDev->cbSelf = 0;
    185 
    186         RTMemFree(pDev);
    187     }
    188 }
    189 
    190 /**
    191  * Duplicates an audio device entry.
    192  *
    193  * @returns Duplicated audio device entry on success, or NULL on failure.
    194  * @param   pDev            The audio device enum entry to duplicate.
    195  * @param   fOnlyCoreData
    196  */
    197 PPDMAUDIOHOSTDEV PDMAudioDeviceDup(PPDMAUDIOHOSTDEV pDev, bool fOnlyCoreData)
    198 {
    199     AssertPtrReturn(pDev, NULL);
    200     Assert(pDev->uMagic == PDMAUDIOHOSTDEV_MAGIC);
    201     Assert(fOnlyCoreData || !(pDev->fFlags & PDMAUDIOHOSTDEV_F_NO_DUP));
    202 
    203     uint32_t cbToDup = fOnlyCoreData ? sizeof(PDMAUDIOHOSTDEV) : pDev->cbSelf;
    204     AssertReturn(cbToDup >= sizeof(*pDev), NULL);
    205 
    206     PPDMAUDIOHOSTDEV pDevDup = PDMAudioDeviceAlloc(cbToDup);
    207     if (pDevDup)
    208     {
    209         memcpy(pDevDup, pDev, cbToDup);
    210         RTListInit(&pDevDup->Node);
    211         pDev->cbSelf = cbToDup;
    212     }
    213 
    214     return pDevDup;
    215 }
    216 
    217 /**
    218  * Initializes a host audio device enumeration.
    219  *
    220  * @param   pDevEnm     The enumeration to initialize.
    221  */
    222 void PDMAudioHostEnumInit(PPDMAUDIOHOSTENUM pDevEnm)
    223 {
    224     AssertPtr(pDevEnm);
    225 
    226     pDevEnm->uMagic   = PDMAUDIOHOSTENUM_MAGIC;
    227     pDevEnm->cDevices = 0;
    228     RTListInit(&pDevEnm->LstDevices);
    229 }
    230 
    231 /**
    232  * Deletes the host audio device enumeration and frees all device entries
    233  * associated with it.
    234  *
    235  * The user must call PDMAudioHostEnumInit again to use it again.
    236  *
    237  * @param   pDevEnm     The host audio device enumeration to delete.
    238  */
    239 void PDMAudioHostEnumDelete(PPDMAUDIOHOSTENUM pDevEnm)
    240 {
    241     if (pDevEnm)
    242     {
    243         AssertPtr(pDevEnm);
    244         AssertReturnVoid(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC);
    245 
    246         PPDMAUDIOHOSTDEV pDev, pDevNext;
    247         RTListForEachSafe(&pDevEnm->LstDevices, pDev, pDevNext, PDMAUDIOHOSTDEV, Node)
    248         {
    249             RTListNodeRemove(&pDev->Node);
    250 
    251             PDMAudioDeviceFree(pDev);
    252 
    253             pDevEnm->cDevices--;
    254         }
    255 
    256         /* Sanity. */
    257         Assert(RTListIsEmpty(&pDevEnm->LstDevices));
    258         Assert(pDevEnm->cDevices == 0);
    259 
    260         pDevEnm->uMagic = ~PDMAUDIOHOSTENUM_MAGIC;
    261     }
    262 }
    263 
    264 /**
    265  * Adds an audio device to a device enumeration.
    266  *
    267  * @param  pDevEnm              Device enumeration to add device to.
    268  * @param  pDev                 Device to add. The pointer will be owned by the device enumeration  then.
    269  */
    270 void PDMAudioHostEnumAppend(PPDMAUDIOHOSTENUM pDevEnm, PPDMAUDIOHOSTDEV pDev)
    271 {
    272     AssertPtr(pDevEnm);
    273     AssertPtr(pDev);
    274     Assert(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC);
    275 
    276     RTListAppend(&pDevEnm->LstDevices, &pDev->Node);
    277     pDevEnm->cDevices++;
    278 }
    279 
    280 /**
    281  * Appends copies of matching host device entries from one to another enumeration.
    282  *
    283  * @returns IPRT status code.
    284  * @param   pDstDevEnm      The target to append copies of matching device to.
    285  * @param   pSrcDevEnm      The source to copy matching devices from.
    286  * @param   enmUsage        The usage to match for copying.
    287  *                          Use PDMAUDIODIR_INVALID to match all entries.
    288  * @param   fOnlyCoreData   Set this to only copy the PDMAUDIOHOSTDEV part.
    289  *                          Careful with passing @c false here as not all
    290  *                          backends have data that can be copied.
    291  */
    292 int PDMAudioHostEnumCopy(PPDMAUDIOHOSTENUM pDstDevEnm, PCPDMAUDIOHOSTENUM pSrcDevEnm,
    293                          PDMAUDIODIR enmUsage, bool fOnlyCoreData)
    294 {
    295     AssertPtrReturn(pDstDevEnm, VERR_INVALID_POINTER);
    296     AssertReturn(pDstDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, VERR_WRONG_ORDER);
    297 
    298     AssertPtrReturn(pSrcDevEnm, VERR_INVALID_POINTER);
    299     AssertReturn(pSrcDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, VERR_WRONG_ORDER);
    300 
    301     PPDMAUDIOHOSTDEV pSrcDev;
    302     RTListForEach(&pSrcDevEnm->LstDevices, pSrcDev, PDMAUDIOHOSTDEV, Node)
    303     {
    304         if (   enmUsage == pSrcDev->enmUsage
    305             || enmUsage == PDMAUDIODIR_INVALID /*all*/)
    306         {
    307             PPDMAUDIOHOSTDEV pDstDev = PDMAudioDeviceDup(pSrcDev, fOnlyCoreData);
    308             AssertReturn(pDstDev, VERR_NO_MEMORY);
    309 
    310             PDMAudioHostEnumAppend(pDstDevEnm, pDstDev);
    311         }
    312     }
    313 
    314     return VINF_SUCCESS;
    315 }
    316 
    317 /**
    318  * Get the default device with the given usage.
    319  *
    320  * This assumes that only one default device per usage is set, if there should
    321  * be more than one, the first one is returned.
    322  *
    323  * @returns Default device if found, or NULL if not.
    324  * @param   pDevEnm     Device enumeration to get default device for.
    325  * @param   enmUsage    Usage to get default device for.
    326  *                      Pass PDMAUDIODIR_INVALID to get the first device with
    327  *                      PDMAUDIOHOSTDEV_F_DEFAULT set.
    328  */
    329 PPDMAUDIOHOSTDEV PDMAudioHostEnumGetDefault(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)
    330 {
    331     AssertPtrReturn(pDevEnm, NULL);
    332     AssertReturn(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, NULL);
    333 
    334     PPDMAUDIOHOSTDEV pDev;
    335     RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, Node)
    336     {
    337         if (pDev->fFlags & PDMAUDIOHOSTDEV_F_DEFAULT)
    338         {
    339             if (   enmUsage == pDev->enmUsage
    340                 || enmUsage == PDMAUDIODIR_INVALID)
    341                 return pDev;
    342         }
    343     }
    344 
    345     return NULL;
    346 }
    347 
    348 /**
    349  * Get the number of device with the given usage.
    350  *
    351  * @returns Number of matching devices.
    352  * @param   pDevEnm     Device enumeration to get default device for.
    353  * @param   enmUsage    Usage to count devices for.
    354  *                      Pass PDMAUDIODIR_INVALID to get the total number of devices.
    355  */
    356 uint32_t PDMAudioHostEnumCountMatching(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)
    357 {
    358     AssertPtrReturn(pDevEnm, 0);
    359     AssertReturn(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, 0);
    360 
    361     if (enmUsage == PDMAUDIODIR_INVALID)
    362         return pDevEnm->cDevices;
    363 
    364     uint32_t        cDevs = 0;
    365     PPDMAUDIOHOSTDEV pDev;
    366     RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, Node)
    367     {
    368         if (enmUsage == pDev->enmUsage)
    369             cDevs++;
    370     }
    371 
    372     return cDevs;
    373 }
    374 
    375 /**
    376  * Logs an audio device enumeration.
    377  *
    378  * @param  pDevEnm  Device enumeration to log.
    379  * @param  pszDesc  Logging description (prefix).
    380  */
    381 void PDMAudioHostEnumLog(PCPDMAUDIOHOSTENUM pDevEnm, const char *pszDesc)
    382 {
    383     AssertPtrReturnVoid(pDevEnm);
    384     AssertPtrReturnVoid(pszDesc);
    385     AssertReturnVoid(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC);
    386 
    387     LogFunc(("%s: %RU32 devices\n", pszDesc, pDevEnm->cDevices));
    388 
    389     PPDMAUDIOHOSTDEV pDev;
    390     RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, Node)
    391     {
    392         char *pszFlags = DrvAudioHlpAudDevFlagsToStrA(pDev->fFlags);
    393 
    394         LogFunc(("Device '%s':\n", pDev->szName));
    395         LogFunc(("  Usage           = %s\n",             PDMAudioDirGetName(pDev->enmUsage)));
    396         LogFunc(("  Flags           = %s\n",             pszFlags ? pszFlags : "<NONE>"));
    397         LogFunc(("  Input channels  = %RU8\n",           pDev->cMaxInputChannels));
    398         LogFunc(("  Output channels = %RU8\n",           pDev->cMaxOutputChannels));
    399         LogFunc(("  cbExtra         = %RU32 bytes\n",    pDev->cbSelf - sizeof(PDMAUDIOHOSTDEV)));
    400 
    401         if (pszFlags)
    402             RTStrFree(pszFlags);
    403     }
    404 }
    405 
    406 /**
    407  * Converts an audio device flags to a string.
    408  *
    409  * @returns Stringified audio flags. Must be free'd with RTStrFree().
    410  *          NULL if no flags set.
    411  * @param   fFlags      Audio flags (PDMAUDIOHOSTDEV_F_XXX) to convert.
    412  */
    413 char *DrvAudioHlpAudDevFlagsToStrA(uint32_t fFlags)
    414 {
    415 #define APPEND_FLAG_TO_STR(_aFlag)              \
    416     if (fFlags & PDMAUDIOHOSTDEV_F_##_aFlag)    \
    417     {                                           \
    418         if (pszFlags)                           \
    419         {                                       \
    420             rc2 = RTStrAAppend(&pszFlags, " "); \
    421             if (RT_FAILURE(rc2))                \
    422                 break;                          \
    423         }                                       \
    424                                                 \
    425         rc2 = RTStrAAppend(&pszFlags, #_aFlag); \
    426         if (RT_FAILURE(rc2))                    \
    427             break;                              \
    428     }                                           \
    429 
    430     char *pszFlags = NULL;
    431     int rc2 = VINF_SUCCESS;
    432 
    433     do
    434     {
    435         APPEND_FLAG_TO_STR(DEFAULT);
    436         APPEND_FLAG_TO_STR(HOTPLUG);
    437         APPEND_FLAG_TO_STR(BUGGY);
    438         APPEND_FLAG_TO_STR(IGNORE);
    439         APPEND_FLAG_TO_STR(LOCKED);
    440         APPEND_FLAG_TO_STR(DEAD);
    441         APPEND_FLAG_TO_STR(NO_DUP);
    442 
    443     } while (0);
    444 
    445     if (!pszFlags)
    446         rc2 = RTStrAAppend(&pszFlags, "NONE");
    447 
    448     if (   RT_FAILURE(rc2)
    449         && pszFlags)
    450     {
    451         RTStrFree(pszFlags);
    452         pszFlags = NULL;
    453     }
    454 
    455 #undef APPEND_FLAG_TO_STR
    456 
    457     return pszFlags;
    458 }
    459144
    460145/**
  • trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp

    r88045 r88047  
    2323#include <VBox/log.h>
    2424#include <VBox/vmm/pdmaudioinline.h>
     25#include <VBox/vmm/pdmaudiohostenuminline.h>
    2526
    2627#include "DrvAudio.h"
  • trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp

    r88045 r88047  
    3131
    3232#include <VBox/vmm/pdmaudioinline.h>
     33#include <VBox/vmm/pdmaudiohostenuminline.h>
    3334
    3435#include "DrvAudio.h"
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette