VirtualBox

Changeset 89532 in vbox


Ignore:
Timestamp:
Jun 7, 2021 12:31:09 AM (3 years ago)
Author:
vboxsync
Message:

DrvHostAudioPulseAudio: Implemented input/output device selection. bugref:9890

File:
1 edited

Legend:

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

    r89531 r89532  
    199199     *  Specify UINT32_MAX for unlimited logging. */
    200200    uint32_t                cLogErrors;
    201     /** The stream (base) name; needed for distinguishing
    202      *  streams in the PulseAudio mixer controls if multiple
    203      *  VMs are running at the same time. */
    204     char                    szStreamName[64];
    205201    /** Don't want to put this on the stack... */
    206202    DRVHSTAUDPASTATECHGCTX  InitStateChgCtx;
    207203    /** Pointer to host audio interface. */
    208204    PDMIHOSTAUDIO           IHostAudio;
     205    /** Upwards notification interface. */
     206    PPDMIHOSTAUDIOPORT      pIHostAudioPort;
     207
     208    /** The stream (base) name.
     209     * This is needed for distinguishing streams in the PulseAudio mixer controls if
     210     * multiple VMs are running at the same time. */
     211    char                    szStreamName[64];
     212    /** The name of the input device to use. Empty string for default. */
     213    char                    szInputDev[256];
     214    /** The name of the output device to use. Empty string for default. */
     215    char                    szOutputDev[256];
    209216} DRVHSTAUDPA;
    210217
     
    690697
    691698/**
     699 * @interface_method_impl{PDMIHOSTAUDIO,pfnSetDevice}
     700 */
     701static DECLCALLBACK(int) drvHstAudPaHA_SetDevice(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir, const char *pszId)
     702{
     703    PDRVHSTAUDPA pThis = RT_FROM_MEMBER(pInterface, DRVHSTAUDPA, IHostAudio);
     704
     705    /*
     706     * Validate and normalize input.
     707     */
     708    AssertReturn(enmDir == PDMAUDIODIR_IN || enmDir == PDMAUDIODIR_OUT || enmDir == PDMAUDIODIR_DUPLEX, VERR_INVALID_PARAMETER);
     709    AssertPtrNullReturn(pszId, VERR_INVALID_POINTER);
     710    if (!pszId || !*pszId)
     711        pszId = "";
     712    else
     713    {
     714        size_t cch = strlen(pszId);
     715        AssertReturn(cch < sizeof(pThis->szInputDev), VERR_INVALID_NAME);
     716    }
     717    LogFunc(("enmDir=%d pszId=%s\n", enmDir, pszId));
     718
     719    /*
     720     * Update input.
     721     */
     722    if (enmDir == PDMAUDIODIR_IN || enmDir == PDMAUDIODIR_DUPLEX)
     723    {
     724        pa_threaded_mainloop_lock(pThis->pMainLoop);
     725        if (strcmp(pThis->szInputDev, pszId) == 0)
     726            pa_threaded_mainloop_unlock(pThis->pMainLoop);
     727        else
     728        {
     729            LogRel(("PulseAudio: Changing input device: '%s' -> '%s'\n", pThis->szInputDev, pszId));
     730            RTStrCopy(pThis->szInputDev, sizeof(pThis->szInputDev), pszId);
     731            PPDMIHOSTAUDIOPORT pIHostAudioPort = pThis->pIHostAudioPort;
     732            pa_threaded_mainloop_unlock(pThis->pMainLoop);
     733            if (pIHostAudioPort)
     734            {
     735                LogFlowFunc(("Notifying parent driver about input device change...\n"));
     736                pIHostAudioPort->pfnNotifyDeviceChanged(pIHostAudioPort, PDMAUDIODIR_IN, NULL /*pvUser*/);
     737            }
     738        }
     739    }
     740
     741    /*
     742     * Update output.
     743     */
     744    if (enmDir == PDMAUDIODIR_OUT || enmDir == PDMAUDIODIR_DUPLEX)
     745    {
     746        pa_threaded_mainloop_lock(pThis->pMainLoop);
     747        if (strcmp(pThis->szOutputDev, pszId) == 0)
     748            pa_threaded_mainloop_unlock(pThis->pMainLoop);
     749        else
     750        {
     751            LogRel(("PulseAudio: Changing output device: '%s' -> '%s'\n", pThis->szOutputDev, pszId));
     752            RTStrCopy(pThis->szOutputDev, sizeof(pThis->szOutputDev), pszId);
     753            PPDMIHOSTAUDIOPORT pIHostAudioPort = pThis->pIHostAudioPort;
     754            pa_threaded_mainloop_unlock(pThis->pMainLoop);
     755            if (pIHostAudioPort)
     756            {
     757                LogFlowFunc(("Notifying parent driver about output device change...\n"));
     758                pIHostAudioPort->pfnNotifyDeviceChanged(pIHostAudioPort, PDMAUDIODIR_OUT, NULL /*pvUser*/);
     759            }
     760        }
     761    }
     762
     763    return VINF_SUCCESS;
     764}
     765
     766
     767
     768
     769/**
    692770 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
    693771 */
     
    9541032        LogFunc(("Input stream attributes: maxlength=%d fragsize=%d\n",
    9551033                 pStreamPA->BufAttr.maxlength, pStreamPA->BufAttr.fragsize));
    956         rc = pa_stream_connect_record(pStream, NULL /*dev*/, &pStreamPA->BufAttr, (pa_stream_flags_t)fFlags);
     1034        rc = pa_stream_connect_record(pStream, pThis->szInputDev[0] ? pThis->szInputDev : NULL,
     1035                                      &pStreamPA->BufAttr, (pa_stream_flags_t)fFlags);
    9571036    }
    9581037    else
     
    9601039        LogFunc(("Output buffer attributes: maxlength=%d tlength=%d prebuf=%d minreq=%d\n",
    9611040                 pStreamPA->BufAttr.maxlength, pStreamPA->BufAttr.tlength, pStreamPA->BufAttr.prebuf, pStreamPA->BufAttr.minreq));
    962         rc = pa_stream_connect_playback(pStream, NULL /*dev*/, &pStreamPA->BufAttr, (pa_stream_flags_t)fFlags,
     1041        rc = pa_stream_connect_playback(pStream, pThis->szOutputDev[0] ? pThis->szOutputDev : NULL, &pStreamPA->BufAttr, (pa_stream_flags_t)fFlags,
    9631042                                        NULL /*volume*/, NULL /*sync_stream*/);
    9641043    }
     
    21422221    pThis->IHostAudio.pfnGetConfig                  = drvHstAudPaHA_GetConfig;
    21432222    pThis->IHostAudio.pfnGetDevices                 = drvHstAudPaHA_GetDevices;
    2144     pThis->IHostAudio.pfnSetDevice                  = NULL;
     2223    pThis->IHostAudio.pfnSetDevice                  = drvHstAudPaHA_SetDevice;
    21452224    pThis->IHostAudio.pfnGetStatus                  = drvHstAudPaHA_GetStatus;
    21462225    pThis->IHostAudio.pfnDoOnWorkerThread           = NULL;
     
    21652244     * Read configuration.
    21662245     */
    2167     int rc2 = CFGMR3QueryString(pCfg, "VmName", pThis->szStreamName, sizeof(pThis->szStreamName));
    2168     AssertMsgRCReturn(rc2, ("Confguration error: No/bad \"VmName\" value, rc=%Rrc\n", rc2), rc2);
     2246    PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "VmName|InputDeviceID|OutputDeviceID", "");
     2247    int rc = CFGMR3QueryString(pCfg, "VmName", pThis->szStreamName, sizeof(pThis->szStreamName));
     2248    AssertMsgRCReturn(rc, ("Confguration error: No/bad \"VmName\" value, rc=%Rrc\n", rc), rc);
     2249    rc = CFGMR3QueryStringDef(pCfg, "InputDeviceID", pThis->szInputDev, sizeof(pThis->szInputDev), "");
     2250    AssertMsgRCReturn(rc, ("Confguration error: Failed to read \"InputDeviceID\" as string: rc=%Rrc\n", rc), rc);
     2251    rc = CFGMR3QueryStringDef(pCfg, "OutputDeviceID", pThis->szOutputDev, sizeof(pThis->szOutputDev), "");
     2252    AssertMsgRCReturn(rc, ("Confguration error: Failed to read \"OutputDeviceID\" as string: rc=%Rrc\n", rc), rc);
     2253
     2254    /*
     2255     * Query the notification interface from the driver/device above us.
     2256     */
     2257    pThis->pIHostAudioPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHOSTAUDIOPORT);
     2258    AssertReturn(pThis->pIHostAudioPort, VERR_PDM_MISSING_INTERFACE_ABOVE);
    21692259
    21702260    /*
    21712261     * Load the pulse audio library.
    21722262     */
    2173     int rc = audioLoadPulseLib();
     2263    rc = audioLoadPulseLib();
    21742264    if (RT_SUCCESS(rc))
    21752265        LogRel(("PulseAudio: Using version %s\n", pa_get_library_version()));
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