VirtualBox

Changeset 89596 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Jun 10, 2021 11:37:53 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145039
Message:

DrvHostAudioWasApi: Implemented pfnSetDevice and the InputDeviceID/OutputDeviceID config values associated with it. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvHostAudioWasApi.cpp

    r89551 r89596  
    232232    /** The upwards interface. */
    233233    PPDMIHOSTAUDIOPORT              pIHostAudioPort;
    234     /** The output device ID, NULL for default. */
     234    /** The output device ID, NULL for default.
     235     * Protected by DrvHostAudioWasMmNotifyClient::m_CritSect. */
    235236    PRTUTF16                        pwszOutputDevId;
    236     /** The input device ID, NULL for default. */
     237    /** The input device ID, NULL for default.
     238     * Protected by DrvHostAudioWasMmNotifyClient::m_CritSect.  */
    237239    PRTUTF16                        pwszInputDevId;
    238240
     
    16621664
    16631665/**
     1666 * Worker for drvHostAudioWasHA_SetDevice.
     1667 */
     1668static int drvHostAudioWasSetDeviceWorker(PDRVHOSTAUDIOWAS pThis, const char *pszId, PRTUTF16 *ppwszDevId, IMMDevice **ppIDevice,
     1669                                          EDataFlow enmFlow, PDMAUDIODIR enmDir, const char *pszWhat)
     1670{
     1671    pThis->pNotifyClient->lockEnter();
     1672
     1673    /*
     1674     * Did anything actually change?
     1675     */
     1676    if (    (pszId == NULL) != (*ppwszDevId == NULL)
     1677        || (   pszId
     1678            && RTUtf16ICmpUtf8(*ppwszDevId, pszId) != 0))
     1679    {
     1680        /*
     1681         * Duplicate the ID.
     1682         */
     1683        PRTUTF16 pwszDevId = NULL;
     1684        if (pszId)
     1685        {
     1686            int rc = RTStrToUtf16(pszId, &pwszDevId);
     1687            AssertRCReturnStmt(rc, pThis->pNotifyClient->lockLeave(), rc);
     1688        }
     1689
     1690        /*
     1691         * Try get the device.
     1692         */
     1693        IMMDevice *pIDevice = NULL;
     1694        HRESULT    hrc;
     1695        if (pwszDevId)
     1696            hrc = pThis->pIEnumerator->GetDevice(pwszDevId, &pIDevice);
     1697        else
     1698            hrc = pThis->pIEnumerator->GetDefaultAudioEndpoint(enmFlow, eMultimedia, &pIDevice);
     1699        LogFlowFunc(("Got device %p (%Rhrc)\n", pIDevice, hrc));
     1700        if (FAILED(hrc))
     1701        {
     1702            LogRel(("WasAPI: Failed to get IMMDevice for %s audio device '%s' (SetDevice): %Rhrc\n",
     1703                    pszWhat, pszId ? pszId : "{default}", hrc));
     1704            pIDevice = NULL;
     1705        }
     1706
     1707        /*
     1708         * Make the switch.
     1709         */
     1710        LogRel(("PulseAudio: Changing %s device: '%ls' -> '%s'\n",
     1711                pszWhat, *ppwszDevId ? *ppwszDevId : L"{Default}", pszId ? pszId : "{Default}"));
     1712
     1713        if (*ppIDevice)
     1714            (*ppIDevice)->Release();
     1715        *ppIDevice = pIDevice;
     1716
     1717        RTUtf16Free(*ppwszDevId);
     1718        *ppwszDevId = pwszDevId;
     1719
     1720        /*
     1721         * Only notify the driver above us.
     1722         */
     1723        PPDMIHOSTAUDIOPORT const pIHostAudioPort = pThis->pIHostAudioPort;
     1724        pThis->pNotifyClient->lockLeave();
     1725
     1726        if (pIHostAudioPort)
     1727        {
     1728            LogFlowFunc(("Notifying parent driver about %s device change...\n", pszWhat));
     1729            pIHostAudioPort->pfnNotifyDeviceChanged(pIHostAudioPort, enmDir, NULL);
     1730        }
     1731    }
     1732    else
     1733    {
     1734        pThis->pNotifyClient->lockLeave();
     1735        LogFunc(("No %s device change\n", pszWhat));
     1736    }
     1737
     1738    return VINF_SUCCESS;
     1739}
     1740
     1741
     1742/**
     1743 * @interface_method_impl{PDMIHOSTAUDIO,pfnSetDevice}
     1744 */
     1745static DECLCALLBACK(int) drvHostAudioWasHA_SetDevice(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir, const char *pszId)
     1746{
     1747    PDRVHOSTAUDIOWAS pThis = RT_FROM_MEMBER(pInterface, DRVHOSTAUDIOWAS, IHostAudio);
     1748
     1749    /*
     1750     * Validate and normalize input.
     1751     */
     1752    AssertReturn(enmDir == PDMAUDIODIR_IN || enmDir == PDMAUDIODIR_OUT || enmDir == PDMAUDIODIR_DUPLEX, VERR_INVALID_PARAMETER);
     1753    AssertPtrNullReturn(pszId, VERR_INVALID_POINTER);
     1754    if (!pszId || !*pszId)
     1755        pszId = NULL;
     1756    else
     1757        AssertReturn(strlen(pszId) < 1024, VERR_INVALID_NAME);
     1758    LogFunc(("enmDir=%d pszId=%s\n", enmDir, pszId));
     1759
     1760    /*
     1761     * Do the updating.
     1762     */
     1763    if (enmDir == PDMAUDIODIR_IN || enmDir == PDMAUDIODIR_DUPLEX)
     1764    {
     1765        int rc = drvHostAudioWasSetDeviceWorker(pThis, pszId, &pThis->pwszInputDevId, &pThis->pIDeviceInput,
     1766                                                eCapture, PDMAUDIODIR_IN, "input");
     1767        AssertRCReturn(rc, rc);
     1768    }
     1769
     1770    if (enmDir == PDMAUDIODIR_OUT || enmDir == PDMAUDIODIR_DUPLEX)
     1771    {
     1772        int rc = drvHostAudioWasSetDeviceWorker(pThis, pszId, &pThis->pwszOutputDevId, &pThis->pIDeviceOutput,
     1773                                                eRender, PDMAUDIODIR_OUT, "output");
     1774        AssertRCReturn(rc, rc);
     1775    }
     1776
     1777    return VINF_SUCCESS;
     1778}
     1779
     1780
     1781/**
    16641782 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
    16651783 */
     
    18641982    if (!pIDevice)
    18651983    {
    1866         /** @todo we can eliminate this too...   */
     1984        /* This might not strictly be necessary anymore, however it shouldn't
     1985           hurt and may be useful when using specific devices. */
    18671986        HRESULT hrc;
    18681987        if (pwszDevId)
     
    29883107    pThis->IHostAudio.pfnGetConfig                  = drvHostAudioWasHA_GetConfig;
    29893108    pThis->IHostAudio.pfnGetDevices                 = drvHostAudioWasHA_GetDevices;
    2990     pThis->IHostAudio.pfnSetDevice                  = NULL;
     3109    pThis->IHostAudio.pfnSetDevice                  = drvHostAudioWasHA_SetDevice;
    29913110    pThis->IHostAudio.pfnGetStatus                  = drvHostAudioWasHA_GetStatus;
    29923111    pThis->IHostAudio.pfnDoOnWorkerThread           = drvHostAudioWasHA_DoOnWorkerThread;
     
    30113130     * Validate and read the configuration.
    30123131     */
    3013     PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "VmName|VmUuid", "");
    3014     /** @todo make it possible to override the default device selection. */
     3132    PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "VmName|VmUuid|InputDeviceID|OutputDeviceID", "");
     3133
     3134    char szTmp[1024];
     3135    int rc = CFGMR3QueryStringDef(pCfg, "InputDeviceID", szTmp, sizeof(szTmp), "");
     3136    AssertMsgRCReturn(rc, ("Confguration error: Failed to read \"InputDeviceID\" as string: rc=%Rrc\n", rc), rc);
     3137    if (szTmp[0])
     3138    {
     3139        rc = RTStrToUtf16(szTmp, &pThis->pwszInputDevId);
     3140        AssertRCReturn(rc, rc);
     3141    }
     3142
     3143    rc = CFGMR3QueryStringDef(pCfg, "OutputDeviceID", szTmp, sizeof(szTmp), "");
     3144    AssertMsgRCReturn(rc, ("Confguration error: Failed to read \"OutputDeviceID\" as string: rc=%Rrc\n", rc), rc);
     3145    if (szTmp[0])
     3146    {
     3147        rc = RTStrToUtf16(szTmp, &pThis->pwszOutputDevId);
     3148        AssertRCReturn(rc, rc);
     3149    }
    30153150
    30163151    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
     
    30213156     * Initialize the critical sections early.
    30223157     */
    3023     int rc = RTCritSectRwInit(&pThis->CritSectStreamList);
     3158    rc = RTCritSectRwInit(&pThis->CritSectStreamList);
    30243159    AssertRCReturn(rc, rc);
    30253160
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