Changeset 73403 in vbox for trunk/src/VBox
- Timestamp:
- Jul 31, 2018 8:59:13 AM (6 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r73391 r73403 70 70 static int audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 71 71 static void audioMixerSinkReset(PAUDMIXSINK pSink); 72 static int audioMixerSinkSetRecSourceInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 72 73 static int audioMixerSinkUpdateInternal(PAUDMIXSINK pSink); 73 74 … … 614 615 * Always use the sink's PCM audio format as the host side when creating a stream for it. 615 616 */ 617 AssertMsg(DrvAudioHlpPCMPropsAreValid(&pSink->PCMProps), 618 ("%s: Does not (yet) have a format set when it must\n", pSink->pszName)); 619 616 620 PDMAUDIOSTREAMCFG CfgHost; 617 621 rc = DrvAudioHlpPCMPropsToStreamCfg(&pSink->PCMProps, &CfgHost); … … 858 862 # error "Implement me!" 859 863 #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 } 862 874 #endif 863 875 } … … 869 881 870 882 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 */ 891 PAUDMIXSTREAM 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; 871 905 } 872 906 … … 1067 1101 ("Can't read from a sink which is not an input sink\n")); 1068 1102 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); 1069 1127 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF 1070 1128 # error "Implement me!" 1071 1129 #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); 1080 1132 #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) 1118 1139 || !cbReadStrm) 1119 1140 break; 1120 1141 1121 /** @todo Right now we only handle one stream (the last one added in fact). */1122 1123 1142 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); 1134 1149 1135 1150 /* Still some data available? Then sink is not clean (yet). */ 1136 1151 if (cbReadable) 1137 1152 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); 1154 1165 #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 } 1167 1170 1168 1171 #ifdef LOG_ENABLED … … 1208 1211 RTListNodeRemove(&pStream->Node); 1209 1212 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 1210 1223 /* Set sink to NULL so that we know we're not part of any sink anymore. */ 1211 1224 pStream->pSink = NULL; 1212 1225 1213 return VINF_SUCCESS;1226 return rc; 1214 1227 } 1215 1228 … … 1435 1448 1436 1449 /** 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 */ 1457 static 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 */ 1481 int 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. 1438 1500 * 1439 1501 * @returns IPRT status code. -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r73391 r73403 144 144 uint32_t cbReadable; 145 145 #endif 146 /** The current recording source. Can be NULL if not set. */ 147 PAUDMIXSTREAM pStreamRecSource; 146 148 } AUDMIXSINKIN; 147 149 … … 244 246 uint32_t AudioMixerSinkGetWritable(PAUDMIXSINK pSink); 245 247 AUDMIXSINKDIR AudioMixerSinkGetDir(PAUDMIXSINK pSink); 248 PAUDMIXSTREAM AudioMixerSinkGetRecordingSource(PAUDMIXSINK pSink); 246 249 PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex); 247 250 AUDMIXSINKSTS AudioMixerSinkGetStatus(PAUDMIXSINK pSink); … … 254 257 void AudioMixerSinkGetFormat(PAUDMIXSINK pSink, PPDMAUDIOPCMPROPS pPCMProps); 255 258 int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMAUDIOPCMPROPS pPCMProps); 259 int AudioMixerSinkSetRecordingSource(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 256 260 int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol); 257 261 int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten); -
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r73209 r73403 2421 2421 PAUDMIXSTREAM pMixStrm; 2422 2422 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)); 2423 2424 if (RT_SUCCESS(rc)) 2424 2425 { 2425 2426 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 } 2427 2440 } 2428 2441 -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r73370 r73403 1559 1559 PAUDMIXSTREAM pMixStrm; 1560 1560 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)); 1561 1562 if (RT_SUCCESS(rc)) 1562 1563 { 1563 1564 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 } 1565 1578 } 1566 1579
Note:
See TracChangeset
for help on using the changeset viewer.