VirtualBox

Changeset 73403 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 31, 2018 8:59:13 AM (6 years ago)
Author:
vboxsync
Message:

Audio/Mixer: Added support for setting / getting an (input) sink's current recording source via AudioMixerSink[Get|Set]RecordingSource().

Location:
trunk/src/VBox/Devices/Audio
Files:
4 edited

Legend:

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

    r73391 r73403  
    7070static int audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
    7171static void audioMixerSinkReset(PAUDMIXSINK pSink);
     72static int audioMixerSinkSetRecSourceInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
    7273static int audioMixerSinkUpdateInternal(PAUDMIXSINK pSink);
    7374
     
    614615     * Always use the sink's PCM audio format as the host side when creating a stream for it.
    615616     */
     617    AssertMsg(DrvAudioHlpPCMPropsAreValid(&pSink->PCMProps),
     618              ("%s: Does not (yet) have a format set when it must\n", pSink->pszName));
     619
    616620    PDMAUDIOSTREAMCFG CfgHost;
    617621    rc = DrvAudioHlpPCMPropsToStreamCfg(&pSink->PCMProps, &CfgHost);
     
    858862# error "Implement me!"
    859863#else
    860         /* Return how much data we can deliver since the last read. */
    861         cbReadable = DrvAudioHlpMsToBytes(RTTimeMilliTS() - pSink->tsLastReadWrittenMs, &pSink->PCMProps);
     864        PAUDMIXSTREAM pStreamRecSource = pSink->In.pStreamRecSource;
     865        if (!pStreamRecSource)
     866        {
     867            Log3Func(("[%s] No recording source specified, skipping ...\n", pSink->pszName));
     868        }
     869        else
     870        {
     871            AssertPtr(pStreamRecSource->pConn);
     872            cbReadable = pStreamRecSource->pConn->pfnStreamGetReadable(pStreamRecSource->pConn, pStreamRecSource->pStream);
     873        }
    862874#endif
    863875    }
     
    869881
    870882    return cbReadable;
     883}
     884
     885/**
     886 * Returns the sink's current recording source.
     887 *
     888 * @return  Mixer stream which currently is set as current recording source, NULL if none is set.
     889 * @param   pSink               Audio mixer sink to return current recording source for.
     890 */
     891PAUDMIXSTREAM AudioMixerSinkGetRecordingSource(PAUDMIXSINK pSink)
     892{
     893    int rc = RTCritSectEnter(&pSink->CritSect);
     894    if (RT_FAILURE(rc))
     895        return NULL;
     896
     897    AssertMsg(pSink->enmDir == AUDMIXSINKDIR_INPUT, ("Specified sink is not an input sink\n"));
     898
     899    PAUDMIXSTREAM pStream = pSink->In.pStreamRecSource;
     900
     901    int rc2 = RTCritSectLeave(&pSink->CritSect);
     902    AssertRC(rc2);
     903
     904    return pStream;
    871905}
    872906
     
    10671101              ("Can't read from a sink which is not an input sink\n"));
    10681102
     1103    uint32_t cbRead = 0;
     1104
     1105    /* Flag indicating whether this sink is in a 'clean' state,
     1106     * e.g. there is no more data to read from. */
     1107    bool fClean = true;
     1108
     1109    PAUDMIXSTREAM pStreamRecSource = pSink->In.pStreamRecSource;
     1110    if (!pStreamRecSource)
     1111    {
     1112        Log3Func(("[%s] No recording source specified, skipping ...\n", pSink->pszName));
     1113    }
     1114    else if (!(pStreamRecSource->pConn->pfnStreamGetStatus(pStreamRecSource->pConn, pStreamRecSource->pStream) & PDMAUDIOSTREAMSTS_FLAG_ENABLED))
     1115    {
     1116        Log3Func(("[%s] Stream '%s' disabled, skipping ...\n", pSink->pszName, pStreamRecSource->pszName));
     1117    }
     1118    else
     1119    {
     1120        uint32_t cbToRead    = RT_MIN(cbBuf,
     1121                                      pStreamRecSource->pConn->pfnStreamGetReadable(pStreamRecSource->pConn,
     1122                                                                                    pStreamRecSource->pStream));
     1123        while (cbToRead)
     1124        {
     1125            uint32_t cbReadStrm;
     1126            AssertPtr(pStreamRecSource->pConn);
    10691127#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
    10701128# error "Implement me!"
    10711129#else
    1072     uint8_t *pvMixBuf = (uint8_t *)RTMemAlloc(cbBuf);
    1073     if (!pvMixBuf)
    1074     {
    1075         int rc2 = RTCritSectLeave(&pSink->CritSect);
    1076         AssertRC(rc2);
    1077 
    1078         return VERR_NO_MEMORY;
    1079     }
     1130            rc = pStreamRecSource->pConn->pfnStreamRead(pStreamRecSource->pConn, pStreamRecSource->pStream,
     1131                                                        (uint8_t *)pvBuf + cbRead, cbToRead, &cbReadStrm);
    10801132#endif
    1081 
    1082     uint32_t cbRead = 0;
    1083 
    1084     /* Flag indicating whether this sink is in a 'clean' state,
    1085      * e.g. there is no more data to read from. */
    1086     bool fClean = true;
    1087 
    1088     PAUDMIXSTREAM pMixStream;
    1089     RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
    1090     {
    1091         if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTREAMSTS_FLAG_ENABLED))
    1092         {
    1093             Log3Func(("[%s] Stream '%s' disabled, skipping ...\n", pSink->pszName, pMixStream->pszName));
    1094             continue;
    1095         }
    1096 
    1097         uint32_t cbTotalRead = 0;
    1098         uint32_t cbToRead    = cbBuf;
    1099 
    1100         int rc2 = VINF_SUCCESS;
    1101 
    1102         while (cbToRead)
    1103         {
    1104             uint32_t cbReadStrm;
    1105             AssertPtr(pMixStream->pConn);
    1106 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
    1107 # error "Implement me!"
    1108 #else
    1109             rc2 = pMixStream->pConn->pfnStreamRead(pMixStream->pConn, pMixStream->pStream,
    1110                                                    (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbReadStrm);
    1111 #endif
    1112             if (RT_FAILURE(rc2))
    1113                 LogFunc(("[%s] Failed reading from stream '%s': %Rrc\n", pSink->pszName, pMixStream->pszName, rc2));
    1114 
    1115             Log3Func(("[%s] Stream '%s': Read %RU32 bytes\n", pSink->pszName, pMixStream->pszName, cbReadStrm));
    1116 
    1117             if (   RT_FAILURE(rc2)
     1133            if (RT_FAILURE(rc))
     1134                LogFunc(("[%s] Failed reading from stream '%s': %Rrc\n", pSink->pszName, pStreamRecSource->pszName, rc));
     1135
     1136            Log3Func(("[%s] Stream '%s': Read %RU32 bytes\n", pSink->pszName, pStreamRecSource->pszName, cbReadStrm));
     1137
     1138            if (   RT_FAILURE(rc)
    11181139                || !cbReadStrm)
    11191140                break;
    11201141
    1121             /** @todo Right now we only handle one stream (the last one added in fact). */
    1122 
    11231142            AssertBreakStmt(cbReadStrm <= cbToRead, rc = VERR_BUFFER_OVERFLOW);
    1124             cbToRead    -= cbReadStrm;
    1125             cbTotalRead += cbReadStrm;
    1126         }
    1127 
    1128         if (RT_FAILURE(rc2))
    1129             continue;
    1130 
    1131         cbRead = RT_MAX(cbRead, cbTotalRead);
    1132 
    1133         uint32_t cbReadable = pMixStream->pConn->pfnStreamGetReadable(pMixStream->pConn, pMixStream->pStream);
     1143            cbToRead -= cbReadStrm;
     1144            cbRead   += cbReadStrm;
     1145            Assert(cbRead <= cbBuf);
     1146        }
     1147
     1148        uint32_t cbReadable = pStreamRecSource->pConn->pfnStreamGetReadable(pStreamRecSource->pConn, pStreamRecSource->pStream);
    11341149
    11351150        /* Still some data available? Then sink is not clean (yet). */
    11361151        if (cbReadable)
    11371152            fClean = false;
    1138     }
    1139 
    1140     if (RT_SUCCESS(rc))
    1141     {
    1142         if (fClean)
    1143             pSink->fStatus &= ~AUDMIXSINK_STS_DIRTY;
    1144 
    1145         /* Update our last read time stamp. */
    1146         pSink->tsLastReadWrittenMs = RTTimeMilliTS();
    1147 
    1148 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
    1149 # error "Implement me!"
    1150 #else
    1151         Assert(cbRead <= cbBuf);
    1152         if (cbRead)
    1153             memcpy(pvBuf, pvMixBuf, cbRead);
     1153
     1154        if (RT_SUCCESS(rc))
     1155        {
     1156            if (fClean)
     1157                pSink->fStatus &= ~AUDMIXSINK_STS_DIRTY;
     1158
     1159            /* Update our last read time stamp. */
     1160            pSink->tsLastReadWrittenMs = RTTimeMilliTS();
     1161
     1162#ifdef VBOX_AUDIO_MIXER_DEBUG
     1163            int rc2 = DrvAudioHlpFileWrite(pSink->Dbg.pFile, pvBuf, cbRead, 0 /* fFlags */);
     1164            AssertRC(rc2);
    11541165#endif
    1155 
    1156 #ifdef VBOX_AUDIO_MIXER_DEBUG
    1157         int rc2 = DrvAudioHlpFileWrite(pSink->Dbg.pFile, pvBuf, cbRead, 0 /* fFlags */);
    1158         AssertRC(rc2);
    1159 #endif
    1160         if (pcbRead)
    1161             *pcbRead = cbRead;
    1162     }
    1163 
    1164 #ifndef VBOX_AUDIO_MIXER_WITH_MIXBUF
    1165     RTMemFree(pvMixBuf);
    1166 #endif
     1166            if (pcbRead)
     1167                *pcbRead = cbRead;
     1168        }
     1169    }
    11671170
    11681171#ifdef LOG_ENABLED
     
    12081211    RTListNodeRemove(&pStream->Node);
    12091212
     1213    int rc = VINF_SUCCESS;
     1214
     1215    if (pSink->enmDir == AUDMIXSINKDIR_INPUT)
     1216    {
     1217        /* Make sure to also un-set the recording source if this stream was set
     1218         * as the recording source before. */
     1219        if (pStream == pSink->In.pStreamRecSource)
     1220            rc = audioMixerSinkSetRecSourceInternal(pSink, NULL);
     1221    }
     1222
    12101223    /* Set sink to NULL so that we know we're not part of any sink anymore. */
    12111224    pStream->pSink = NULL;
    12121225
    1213     return VINF_SUCCESS;
     1226    return rc;
    12141227}
    12151228
     
    14351448
    14361449/**
    1437  * Set the volume of an individual sink.
     1450 * Set the current recording source of an input mixer sink, internal version.
     1451 *
     1452 * @return  IPRT status code.
     1453 * @param   pSink               Input mixer sink to set recording source for.
     1454 * @param   pStream             Mixer stream to set as current recording source. Must be an input stream.
     1455 *                              Specify NULL to un-set the current recording source.
     1456 */
     1457static int audioMixerSinkSetRecSourceInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)
     1458{
     1459    AssertMsg(pSink->enmDir == AUDMIXSINKDIR_INPUT, ("Specified sink is not an input sink\n"));
     1460
     1461    if (pStream) /* Can be NULL if un-setting. */
     1462    {
     1463        AssertPtr(pStream->pStream);
     1464        AssertMsg(pStream->pStream->enmDir == PDMAUDIODIR_IN, ("Specified stream is not an input stream\n"));
     1465    }
     1466
     1467    pSink->In.pStreamRecSource = pStream;
     1468
     1469    LogFunc(("[%s] Recording source is now '%s'\n",
     1470             pSink->pszName, pSink->In.pStreamRecSource ? pSink->In.pStreamRecSource->pszName : "<None>"));
     1471    return VINF_SUCCESS;
     1472}
     1473
     1474/**
     1475 * Set the current recording source of an input mixer sink.
     1476 *
     1477 * @return  IPRT status code.
     1478 * @param   pSink               Input mixer sink to set recording source for.
     1479 * @param   pStream             Mixer stream to set as current recording source. Must be an input stream.
     1480 */
     1481int AudioMixerSinkSetRecordingSource(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)
     1482{
     1483    AssertPtrReturn(pSink, VERR_INVALID_POINTER);
     1484    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1485
     1486    int rc = RTCritSectEnter(&pSink->CritSect);
     1487    if (RT_FAILURE(rc))
     1488        return rc;
     1489
     1490    rc = audioMixerSinkSetRecSourceInternal(pSink, pStream);
     1491
     1492    int rc2 = RTCritSectLeave(&pSink->CritSect);
     1493    AssertRC(rc2);
     1494
     1495    return rc;
     1496}
     1497
     1498/**
     1499 * Sets the volume of an individual sink.
    14381500 *
    14391501 * @returns IPRT status code.
  • trunk/src/VBox/Devices/Audio/AudioMixer.h

    r73391 r73403  
    144144    uint32_t       cbReadable;
    145145#endif
     146    /** The current recording source. Can be NULL if not set. */
     147    PAUDMIXSTREAM  pStreamRecSource;
    146148} AUDMIXSINKIN;
    147149
     
    244246uint32_t AudioMixerSinkGetWritable(PAUDMIXSINK pSink);
    245247AUDMIXSINKDIR AudioMixerSinkGetDir(PAUDMIXSINK pSink);
     248PAUDMIXSTREAM AudioMixerSinkGetRecordingSource(PAUDMIXSINK pSink);
    246249PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex);
    247250AUDMIXSINKSTS AudioMixerSinkGetStatus(PAUDMIXSINK pSink);
     
    254257void AudioMixerSinkGetFormat(PAUDMIXSINK pSink, PPDMAUDIOPCMPROPS pPCMProps);
    255258int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMAUDIOPCMPROPS pPCMProps);
     259int AudioMixerSinkSetRecordingSource(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
    256260int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol);
    257261int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
  • trunk/src/VBox/Devices/Audio/DevHDA.cpp

    r73209 r73403  
    24212421        PAUDMIXSTREAM pMixStrm;
    24222422        rc = AudioMixerSinkCreateStream(pMixSink, pDrv->pConnector, pStreamCfg, 0 /* fFlags */, &pMixStrm);
     2423        LogFlowFunc(("LUN#%RU8: Created stream \"%s\" for sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
    24232424        if (RT_SUCCESS(rc))
    24242425        {
    24252426            rc = AudioMixerSinkAddStream(pMixSink, pMixStrm);
    2426             LogFlowFunc(("LUN#%RU8: Added \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
     2427            LogFlowFunc(("LUN#%RU8: Added stream \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
     2428            if (RT_SUCCESS(rc))
     2429            {
     2430                /* If this is an input stream, always set the latest (added) stream
     2431                 * as the recording source.
     2432                 * @todo Make the recording source dynamic (CFGM?). */
     2433                if (pStreamCfg->enmDir == PDMAUDIODIR_IN)
     2434                {
     2435                    rc = AudioMixerSinkSetRecordingSource(pMixSink, pMixStrm);
     2436                    LogFlowFunc(("LUN#%RU8: Recording source is now \"%s\", rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
     2437                    LogRel2(("HDA: Set recording source to '%s'\n", pStreamCfg->szName));
     2438                }
     2439            }
    24272440        }
    24282441
  • trunk/src/VBox/Devices/Audio/DevIchAc97.cpp

    r73370 r73403  
    15591559        PAUDMIXSTREAM pMixStrm;
    15601560        rc = AudioMixerSinkCreateStream(pMixSink, pDrv->pConnector, pStreamCfg, 0 /* fFlags */, &pMixStrm);
     1561        LogFlowFunc(("LUN#%RU8: Created stream \"%s\" for sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
    15611562        if (RT_SUCCESS(rc))
    15621563        {
    15631564            rc = AudioMixerSinkAddStream(pMixSink, pMixStrm);
    1564             LogFlowFunc(("LUN#%RU8: Created stream \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc));
     1565            LogFlowFunc(("LUN#%RU8: Added stream \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
     1566            if (RT_SUCCESS(rc))
     1567            {
     1568                /* If this is an input stream, always set the latest (added) stream
     1569                 * as the recording source.
     1570                 * @todo Make the recording source dynamic (CFGM?). */
     1571                if (pStreamCfg->enmDir == PDMAUDIODIR_IN)
     1572                {
     1573                    rc = AudioMixerSinkSetRecordingSource(pMixSink, pMixStrm);
     1574                    LogFlowFunc(("LUN#%RU8: Recording source is now \"%s\", rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
     1575                    LogRel2(("HDA: Set recording source to '%s'\n", pStreamCfg->szName));
     1576                }
     1577            }
    15651578        }
    15661579
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