Changeset 59987 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Mar 11, 2016 12:03:37 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 105954
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r59470 r59987 642 642 pStrmIn = &pDrv->LineIn; 643 643 644 rc= pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, enmRecSource, pCfg, &pStrmIn->pStrmIn);644 int rc2 = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, enmRecSource, pCfg, &pStrmIn->pStrmIn); 645 645 646 646 LogFlowFunc(("LUN#%RU8: Created input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc)); 647 if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */647 if (rc2 == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */ 648 648 { 649 649 AudioMixerRemoveStream(pSink, pStrmIn->phStrmIn); 650 rc = AudioMixerAddStreamIn(pSink,651 pDrv->pConnector, pStrmIn->pStrmIn,652 0 /* uFlags */, &pStrmIn->phStrmIn);650 rc2 = AudioMixerAddStreamIn(pSink, 651 pDrv->pConnector, pStrmIn->pStrmIn, 652 0 /* uFlags */, &pStrmIn->phStrmIn); 653 653 } 654 654 … … 2534 2534 AssertPtr(pCon); 2535 2535 2536 bool fValidLineIn = pCon->pfnIsValidIn (pCon, pDrv->LineIn.pStrmIn);2536 bool fValidLineIn = pCon->pfnIsValidIn (pCon, pDrv->LineIn.pStrmIn); 2537 2537 bool fValidMicIn = pCon->pfnIsValidIn (pCon, pDrv->MicIn.pStrmIn); 2538 2538 bool fValidOut = pCon->pfnIsValidOut(pCon, pDrv->Out.pStrmOut); … … 2559 2559 if (RT_SUCCESS(rc2)) 2560 2560 { 2561 if (backendCfg.c MaxHstStrmsIn)2561 if (backendCfg.cSources) 2562 2562 { 2563 2563 /* If the audio backend supports two or more input streams at once, 2564 2564 * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */ 2565 if (backendCfg.cMax HstStrmsIn >= 2)2565 if (backendCfg.cMaxStreamsIn >= 2) 2566 2566 fWarn = !fValidLineIn || !fValidMicIn; 2567 2567 /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and 2568 2568 * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize. 2569 2569 * One of the two simply is not in use then. */ 2570 else if (backendCfg.cMax HstStrmsIn == 1)2570 else if (backendCfg.cMaxStreamsIn == 1) 2571 2571 fWarn = !fValidLineIn && !fValidMicIn; 2572 2572 /* Don't warn if our backend is not able of supporting any input streams at all. */ … … 2574 2574 2575 2575 if ( !fWarn 2576 && backendCfg.c MaxHstStrmsOut)2576 && backendCfg.cSinks) 2577 2577 { 2578 2578 fWarn = !fValidOut; -
trunk/src/VBox/Devices/Audio/DevIchHda.cpp
r59470 r59987 4807 4807 if (RT_SUCCESS(rc2)) 4808 4808 { 4809 if (backendCfg.c MaxHstStrmsIn)4809 if (backendCfg.cSources) 4810 4810 { 4811 4811 #ifdef VBOX_WITH_HDA_MIC_IN 4812 4812 /* If the audio backend supports two or more input streams at once, 4813 4813 * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */ 4814 if (backendCfg.cMax HstStrmsIn >= 2)4814 if (backendCfg.cMaxStreamsIn >= 2) 4815 4815 fWarn = !fValidLineIn || !fValidMicIn; 4816 4816 /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and 4817 4817 * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize. 4818 4818 * One of the two simply is not in use then. */ 4819 else if (backendCfg.cMax HstStrmsIn == 1)4819 else if (backendCfg.cMaxStreamsIn == 1) 4820 4820 fWarn = !fValidLineIn && !fValidMicIn; 4821 4821 /* Don't warn if our backend is not able of supporting any input streams at all. */ … … 4827 4827 4828 4828 if ( !fWarn 4829 && backendCfg.c MaxHstStrmsOut)4829 && backendCfg.cSinks) 4830 4830 { 4831 4831 fWarn = !fValidOut; -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r59890 r59987 615 615 616 616 RTMemFree(pHstStrmOut); 617 pThis->c FreeOutputStreams++;617 pThis->cStreamsFreeOut++; 618 618 return VINF_SUCCESS; 619 619 } … … 749 749 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 750 750 751 if (!pThis->c FreeOutputStreams)751 if (!pThis->cStreamsFreeOut) 752 752 { 753 753 LogFlowFunc(("Maximum number of host output streams reached\n")); … … 801 801 { 802 802 RTListPrepend(&pThis->lstHstStrmOut, &pHstStrmOut->Node); 803 pThis->c FreeOutputStreams--;803 pThis->cStreamsFreeOut--; 804 804 } 805 805 … … 1005 1005 PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOHSTSTRMIN *ppHstStrmIn) 1006 1006 { 1007 if (!pThis->c FreeInputStreams)1007 if (!pThis->cStreamsFreeIn) 1008 1008 { 1009 1009 LogFlowFunc(("No more input streams free to use, bailing out\n")); … … 1057 1057 { 1058 1058 RTListPrepend(&pThis->lstHstStrmIn, &pHstStrmIn->Node); 1059 pThis->c FreeInputStreams--;1059 pThis->cStreamsFreeIn--; 1060 1060 } 1061 1061 … … 1237 1237 1238 1238 RTMemFree(pHstStrmIn); 1239 pThis->c FreeInputStreams++;1239 pThis->cStreamsFreeIn++; 1240 1240 } 1241 1241 } … … 1422 1422 AssertRC(rc); 1423 1423 1424 if (!pThis->BackendCfg.cMax HstStrmsOut)1424 if (!pThis->BackendCfg.cMaxStreamsOut) 1425 1425 { 1426 1426 int rc2 = RTCritSectLeave(&pThis->CritSect); … … 1669 1669 } 1670 1670 1671 uint32_t cMaxHstStrmsOut = pThis->BackendCfg.cMaxHstStrmsOut; 1672 size_t cbHstStrmsOut = pThis->BackendCfg.cbStreamOut; 1673 1674 if (cbHstStrmsOut) 1675 { 1676 pThis->cFreeOutputStreams = cMaxHstStrmsOut; 1671 if (pThis->BackendCfg.cbStreamOut) 1672 { 1673 pThis->cStreamsFreeOut = pThis->BackendCfg.cMaxStreamsOut; 1677 1674 } 1678 1675 else 1679 pThis->cFreeOutputStreams = 0; 1680 1681 uint32_t cMaxHstStrmsIn = pThis->BackendCfg.cMaxHstStrmsIn; 1682 size_t cbHstStrmIn = pThis->BackendCfg.cbStreamIn; 1683 1684 if (cbHstStrmIn) 1676 pThis->cStreamsFreeOut = 0; 1677 1678 if (pThis->BackendCfg.cbStreamIn) 1685 1679 { 1686 1680 /* … … 1689 1683 * - Our HDA emulation currently has only line input (hda.pi). 1690 1684 */ 1691 pThis->c FreeInputStreams = cMaxHstStrmsIn;1685 pThis->cStreamsFreeIn = pThis->BackendCfg.cMaxStreamsIn; 1692 1686 } 1693 1687 else 1694 pThis->cFreeInputStreams = 0; 1695 1696 LogFlowFunc(("cMaxHstStrmsOut=%RU32 (cb=%zu), cMaxHstStrmsIn=%RU32 (cb=%zu)\n", 1697 cMaxHstStrmsOut, cbHstStrmsOut, cMaxHstStrmsIn, cbHstStrmIn)); 1698 1699 LogFlowFunc(("cFreeInputStreams=%RU8, cFreeOutputStreams=%RU8\n", 1700 pThis->cFreeInputStreams, pThis->cFreeOutputStreams)); 1701 1702 LogRel(("Audio: Host audio backend supports %RU32 output streams and %RU32 input streams at once\n", 1703 /* Clamp for logging. Unlimited streams are defined by UINT32_MAX. */ 1704 RT_MIN(64, cMaxHstStrmsOut), RT_MIN(64, cMaxHstStrmsIn))); 1688 pThis->cStreamsFreeIn = 0; 1689 1690 LogFlowFunc(("cStreamsFreeIn=%RU8, cStreamsFreeOut=%RU8\n", pThis->cStreamsFreeIn, pThis->cStreamsFreeOut)); 1691 1692 LogRel2(("Audio: Host audio backend supports %RU32 input streams and %RU32 output streams at once\n", 1693 /* Clamp for logging. Unlimited streams are defined by UINT32_MAX. */ 1694 RT_MIN(64, pThis->cStreamsFreeIn), RT_MIN(64, pThis->cStreamsFreeOut))); 1705 1695 1706 1696 LogFlowFuncLeave(); … … 1792 1782 /** @todo Check for invalid options? */ 1793 1783 1794 pThis->c FreeOutputStreams= conf.fixed_out.cStreams;1795 pThis->c FreeInputStreams= conf.fixed_in.cStreams;1796 1797 if (!pThis->c FreeOutputStreams)1798 pThis->c FreeOutputStreams= 1;1799 1800 if (!pThis->c FreeInputStreams)1801 pThis->c FreeInputStreams= 1;1784 pThis->cStreamsFreeOut = conf.fixed_out.cStreams; 1785 pThis->cStreamsFreeIn = conf.fixed_in.cStreams; 1786 1787 if (!pThis->cStreamsFreeOut) 1788 pThis->cStreamsFreeOut = 1; 1789 1790 if (!pThis->cStreamsFreeIn) 1791 pThis->cStreamsFreeIn = 1; 1802 1792 } 1803 1793 … … 2055 2045 *ppGstStrmIn = pGstStrmIn; 2056 2046 } 2057 else2058 {2059 switch (rc)2060 {2061 case VERR_NO_MORE_HANDLES: /** @todo Find a better rc. */2062 LogRel(("Audio: Skipping to create input stream \"%s\", " \2063 "as the host audio backend reached its maximum of concurrent audio input streams\n", pszName));2064 break;2065 2066 default:2067 break;2068 }2069 }2070 2047 2071 2048 int rc2 = RTCritSectLeave(&pThis->CritSect); … … 2179 2156 } 2180 2157 #endif 2181 }2182 else2183 {2184 switch (rc)2185 {2186 case VERR_NO_MORE_HANDLES: /** @todo Find a better rc. */2187 LogRel(("Audio: Skipping to create output stream \"%s\", " \2188 "as the host audio backend reached its maximum of concurrent audio output streams\n", pszName));2189 break;2190 2191 default:2192 break;2193 }2194 2158 } 2195 2159 -
trunk/src/VBox/Devices/Audio/DrvAudio.h
r59470 r59987 96 96 /** Max. number of free input streams. 97 97 * UINT32_MAX for unlimited streams. */ 98 uint32_t c FreeInputStreams;98 uint32_t cStreamsFreeIn; 99 99 /** Max. number of free output streams. 100 100 * UINT32_MAX for unlimited streams. */ 101 uint32_t c FreeOutputStreams;101 uint32_t cStreamsFreeOut; 102 102 /** Audio configuration settings retrieved from the backend. */ 103 103 PDMAUDIOBACKENDCFG BackendCfg; -
trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp
r59470 r59987 5 5 6 6 /* 7 * Copyright (C) 2006-201 5Oracle Corporation7 * Copyright (C) 2006-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 57 57 58 58 #include <alsa/asoundlib.h> 59 #include <alsa/control.h> /* For device enumeration. */ 59 60 60 61 #include "DrvAudio.h" … … 62 63 63 64 #include "VBoxDD.h" 65 66 /********************************************************************************************************************************* 67 * Defines * 68 *********************************************************************************************************************************/ 69 70 /** Makes DRVHOSTALSAAUDIO out of PDMIHOSTAUDIO. */ 71 #define PDMIHOSTAUDIO_2_DRVHOSTALSAAUDIO(pInterface) \ 72 ( (PDRVHOSTALSAAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTALSAAUDIO, IHostAudio)) ) 73 74 /********************************************************************************************************************************* 75 * Structures * 76 *********************************************************************************************************************************/ 64 77 65 78 typedef struct ALSAAUDIOSTREAMIN … … 101 114 } ALSAAUDIOCFG, *PALSAAUDIOCFG; 102 115 103 static int drvHostALSAAudioRecover(snd_pcm_t *phPCM);116 static int alsaStreamRecover(snd_pcm_t *phPCM); 104 117 105 118 static ALSAAUDIOCFG s_ALSAConf = … … 162 175 } ALSAAUDIOSTREAMCFG, *PALSAAUDIOSTREAMCFG; 163 176 164 static int drvHostALSAAudioClose(snd_pcm_t **pphPCM) 165 { 166 if (!pphPCM || !*pphPCM) 167 return VINF_SUCCESS; 168 169 int rc; 170 int rc2 = snd_pcm_close(*pphPCM); 171 if (rc2) 172 { 173 LogRel(("ALSA: Closing PCM descriptor failed: %s\n", snd_strerror(rc2))); 174 rc = VERR_GENERAL_FAILURE; /** @todo */ 175 } 176 else 177 { 178 *pphPCM = NULL; 179 rc = VINF_SUCCESS; 180 } 181 182 return rc; 183 } 184 185 static snd_pcm_format_t drvHostALSAAudioFmtToALSA(PDMAUDIOFMT fmt) 177 178 179 static snd_pcm_format_t alsaAudioFmtToALSA(PDMAUDIOFMT fmt) 186 180 { 187 181 switch (fmt) … … 213 207 } 214 208 215 static int drvHostALSAAudioALSAToFmt(snd_pcm_format_t fmt,216 209 static int alsaALSAToAudioFmt(snd_pcm_format_t fmt, 210 PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pEndianness) 217 211 { 218 212 AssertPtrReturn(pFmt, VERR_INVALID_POINTER); … … 289 283 } 290 284 291 static int drvHostALSAAudioALSAGetShift(snd_pcm_format_t fmt, unsigned *puShift)285 static int alsaGetSampleShift(snd_pcm_format_t fmt, unsigned *puShift) 292 286 { 293 287 AssertPtrReturn(puShift, VERR_INVALID_POINTER); … … 322 316 } 323 317 324 static int drvHostALSAAudioSetThreshold(snd_pcm_t *phPCM, 325 snd_pcm_uframes_t threshold) 318 static int alsaStreamSetThreshold(snd_pcm_t *phPCM, snd_pcm_uframes_t threshold) 326 319 { 327 320 snd_pcm_sw_params_t *pSWParms = NULL; … … 368 361 } 369 362 370 static int drvHostALSAAudioOpen(bool fIn, 371 PALSAAUDIOSTREAMCFG pCfgReq, 372 PALSAAUDIOSTREAMCFG pCfgObt, 373 snd_pcm_t **pphPCM) 363 static int alsaStreamClose(snd_pcm_t **pphPCM) 364 { 365 if (!pphPCM || !*pphPCM) 366 return VINF_SUCCESS; 367 368 int rc; 369 int rc2 = snd_pcm_close(*pphPCM); 370 if (rc2) 371 { 372 LogRel(("ALSA: Closing PCM descriptor failed: %s\n", snd_strerror(rc2))); 373 rc = VERR_GENERAL_FAILURE; /** @todo */ 374 } 375 else 376 { 377 *pphPCM = NULL; 378 rc = VINF_SUCCESS; 379 } 380 381 return rc; 382 } 383 384 static int alsaStreamOpen(bool fIn, PALSAAUDIOSTREAMCFG pCfgReq, PALSAAUDIOSTREAMCFG pCfgObt, snd_pcm_t **pphPCM) 374 385 { 375 386 snd_pcm_t *phPCM = NULL; … … 624 635 { 625 636 unsigned uShift; 626 rc = drvHostALSAAudioALSAGetShift(pCfgReq->fmt, &uShift);637 rc = alsaGetSampleShift(pCfgReq->fmt, &uShift); 627 638 if (RT_SUCCESS(rc)) 628 639 { … … 634 645 = (s_ALSAConf.threshold * bytes_per_sec) / 1000; 635 646 636 rc = drvHostALSAAudioSetThreshold(phPCM, threshold);647 rc = alsaStreamSetThreshold(phPCM, threshold); 637 648 } 638 649 } … … 652 663 } 653 664 else 654 drvHostALSAAudioClose(&phPCM);665 alsaStreamClose(&phPCM); 655 666 656 667 LogFlowFuncLeaveRC(rc); … … 659 670 660 671 #ifdef DEBUG 661 static void drvHostALSAAudioErrorHandler(const char *file, int line, const char *function,662 672 static void alsaDbgErrorHandler(const char *file, int line, const char *function, 673 int err, const char *fmt, ...) 663 674 { 664 675 /** @todo Implement me! */ … … 666 677 #endif 667 678 668 static int drvHostALSAAudioGetAvail(snd_pcm_t *phPCM, snd_pcm_sframes_t *pFramesAvail)679 static int alsaStreamGetAvail(snd_pcm_t *phPCM, snd_pcm_sframes_t *pFramesAvail) 669 680 { 670 681 AssertPtrReturn(phPCM, VERR_INVALID_POINTER); … … 679 690 if (framesAvail == -EPIPE) 680 691 { 681 rc = drvHostALSAAudioRecover(phPCM);692 rc = alsaStreamRecover(phPCM); 682 693 if (RT_SUCCESS(rc)) 683 694 framesAvail = snd_pcm_avail_update(phPCM); … … 695 706 } 696 707 697 static int drvHostALSAAudioRecover(snd_pcm_t *phPCM)708 static int alsaStreamRecover(snd_pcm_t *phPCM) 698 709 { 699 710 AssertPtrReturn(phPCM, VERR_INVALID_POINTER); … … 709 720 } 710 721 711 static int drvHostALSAAudioResume(snd_pcm_t *phPCM)722 static int alsaStreamResume(snd_pcm_t *phPCM) 712 723 { 713 724 AssertPtrReturn(phPCM, VERR_INVALID_POINTER); … … 760 771 { 761 772 #ifdef DEBUG 762 snd_lib_error_set_handler( drvHostALSAAudioErrorHandler);773 snd_lib_error_set_handler(alsaDbgErrorHandler); 763 774 #endif 764 775 } … … 776 787 777 788 snd_pcm_sframes_t cAvail; 778 int rc = drvHostALSAAudioGetAvail(pThisStrmIn->phPCM, &cAvail);789 int rc = alsaStreamGetAvail(pThisStrmIn->phPCM, &cAvail); 779 790 if (RT_FAILURE(rc)) 780 791 { … … 794 805 case SND_PCM_STATE_SUSPENDED: 795 806 { 796 rc = drvHostALSAAudioResume(pThisStrmIn->phPCM);807 rc = alsaStreamResume(pThisStrmIn->phPCM); 797 808 if (RT_FAILURE(rc)) 798 809 break; … … 860 871 case -EPIPE: 861 872 { 862 rc = drvHostALSAAudioRecover(pThisStrmIn->phPCM);873 rc = alsaStreamRecover(pThisStrmIn->phPCM); 863 874 if (RT_FAILURE(rc)) 864 875 break; … … 932 943 { 933 944 snd_pcm_sframes_t cAvail; 934 rc = drvHostALSAAudioGetAvail(pThisStrmOut->phPCM, &cAvail);945 rc = alsaStreamGetAvail(pThisStrmOut->phPCM, &cAvail); 935 946 if (RT_FAILURE(rc)) 936 947 { … … 975 986 case -EPIPE: 976 987 { 977 rc = drvHostALSAAudioRecover(pThisStrmOut->phPCM);988 rc = alsaStreamRecover(pThisStrmOut->phPCM); 978 989 if (RT_FAILURE(rc)) 979 990 break; … … 986 997 { 987 998 /* Stream was suspended and waiting for a recovery. */ 988 rc = drvHostALSAAudioResume(pThisStrmOut->phPCM);999 rc = alsaStreamResume(pThisStrmOut->phPCM); 989 1000 if (RT_FAILURE(rc)) 990 1001 { … … 1046 1057 PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn; 1047 1058 1048 drvHostALSAAudioClose(&pThisStrmIn->phPCM);1059 alsaStreamClose(&pThisStrmIn->phPCM); 1049 1060 1050 1061 if (pThisStrmIn->pvBuf) … … 1064 1075 PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut; 1065 1076 1066 drvHostALSAAudioClose(&pThisStrmOut->phPCM);1077 alsaStreamClose(&pThisStrmOut->phPCM); 1067 1078 1068 1079 if (pThisStrmOut->pvBuf) … … 1091 1102 { 1092 1103 ALSAAUDIOSTREAMCFG req; 1093 req.fmt = drvHostALSAAudioFmtToALSA(pCfg->enmFormat);1104 req.fmt = alsaAudioFmtToALSA(pCfg->enmFormat); 1094 1105 req.freq = pCfg->uHz; 1095 1106 req.nchannels = pCfg->cChannels; … … 1098 1109 1099 1110 ALSAAUDIOSTREAMCFG obt; 1100 rc = drvHostALSAAudioOpen(false /* false */, &req, &obt, &phPCM);1111 rc = alsaStreamOpen(false /* false */, &req, &obt, &phPCM); 1101 1112 if (RT_FAILURE(rc)) 1102 1113 break; … … 1104 1115 PDMAUDIOFMT enmFormat; 1105 1116 PDMAUDIOENDIANNESS enmEnd; 1106 rc = drvHostALSAAudioALSAToFmt(obt.fmt, &enmFormat, &enmEnd);1117 rc = alsaALSAToAudioFmt(obt.fmt, &enmFormat, &enmEnd); 1107 1118 if (RT_FAILURE(rc)) 1108 1119 break; … … 1139 1150 1140 1151 if (RT_FAILURE(rc)) 1141 drvHostALSAAudioClose(&phPCM);1152 alsaStreamClose(&phPCM); 1142 1153 1143 1154 LogFlowFuncLeaveRC(rc); … … 1162 1173 { 1163 1174 ALSAAUDIOSTREAMCFG req; 1164 req.fmt = drvHostALSAAudioFmtToALSA(pCfg->enmFormat);1175 req.fmt = alsaAudioFmtToALSA(pCfg->enmFormat); 1165 1176 req.freq = pCfg->uHz; 1166 1177 req.nchannels = pCfg->cChannels; … … 1169 1180 1170 1181 ALSAAUDIOSTREAMCFG obt; 1171 rc = drvHostALSAAudioOpen(true /* fIn */, &req, &obt, &phPCM);1182 rc = alsaStreamOpen(true /* fIn */, &req, &obt, &phPCM); 1172 1183 if (RT_FAILURE(rc)) 1173 1184 break; … … 1175 1186 PDMAUDIOFMT enmFormat; 1176 1187 PDMAUDIOENDIANNESS enmEnd; 1177 rc = drvHostALSAAudioALSAToFmt(obt.fmt, &enmFormat, &enmEnd);1188 rc = alsaALSAToAudioFmt(obt.fmt, &enmFormat, &enmEnd); 1178 1189 if (RT_FAILURE(rc)) 1179 1190 break; … … 1210 1221 1211 1222 if (RT_FAILURE(rc)) 1212 drvHostALSAAudioClose(&phPCM);1223 alsaStreamClose(&phPCM); 1213 1224 1214 1225 LogFlowFuncLeaveRC(rc); … … 1290 1301 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1291 1302 1292 pCfg->cbStreamIn = sizeof(ALSAAUDIOSTREAMIN); 1293 pCfg->cbStreamOut = sizeof(ALSAAUDIOSTREAMOUT); 1303 pCfg->cbStreamIn = sizeof(ALSAAUDIOSTREAMIN); 1304 pCfg->cbStreamOut = sizeof(ALSAAUDIOSTREAMOUT); 1305 1306 pCfg->cSources = 0; 1307 pCfg->cSinks = 0; 1308 1309 /* Enumerate sound devices. */ 1310 char **pszHints; 1311 int err = snd_device_name_hint(-1 /* All cards */, "pcm", (void***)&pszHints); 1312 if (err == 0) 1313 { 1314 char** pszHintCur = pszHints; 1315 while (*pszHintCur != NULL) 1316 { 1317 char *pszDev = snd_device_name_get_hint(*pszHintCur, "NAME"); 1318 bool fSkip = !pszDev 1319 || !RTStrICmp("null", pszDev); 1320 if (fSkip) 1321 { 1322 if (pszDev) 1323 free(pszDev); 1324 pszHintCur++; 1325 continue; 1326 } 1327 1328 char *pszIOID = snd_device_name_get_hint(*pszHintCur, "IOID"); 1329 if (pszIOID) 1330 { 1331 if (!RTStrICmp("input", pszIOID)) 1332 pCfg->cSources++; 1333 else if (!RTStrICmp("output", pszIOID)) 1334 pCfg->cSinks++; 1335 } 1336 else /* NULL means bidirectional, input + output. */ 1337 { 1338 pCfg->cSources++; 1339 pCfg->cSinks++; 1340 } 1341 1342 LogRel2(("ALSA: Found %s device: %s\n", pszIOID ? RTStrToLower(pszIOID) : "bidirectional", pszDev)); 1343 1344 /* Special case for PulseAudio. */ 1345 if ( pszDev 1346 && RTStrIStr("pulse", pszDev) != NULL) 1347 LogRel2(("ALSA: PulseAudio plugin in use\n")); 1348 1349 if (pszIOID) 1350 free(pszIOID); 1351 1352 if (pszDev) 1353 free(pszDev); 1354 1355 pszHintCur++; 1356 } 1357 1358 LogRel2(("ALSA: Found %RU8 host playback devices\n", pCfg->cSinks)); 1359 LogRel2(("ALSA: Found %RU8 host capturing devices\n", pCfg->cSources)); 1360 1361 snd_device_name_free_hint((void **)pszHints); 1362 pszHints = NULL; 1363 } 1364 else 1365 LogRel2(("ALSA: Error enumerating PCM devices: %Rrc (%d)\n", RTErrConvertFromErrno(err), err)); 1294 1366 1295 1367 /* ALSA only allows one input and one output used at a time for 1296 * the selected device . */1297 pCfg->cMax HstStrmsIn= 1;1298 pCfg->cMax HstStrmsOut= 1;1368 * the selected device(s). */ 1369 pCfg->cMaxStreamsIn = 1; 1370 pCfg->cMaxStreamsOut = 1; 1299 1371 1300 1372 return VINF_SUCCESS; -
trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
r59470 r59987 311 311 } COREAUDIOSTREAMIN, *PCOREAUDIOSTREAMIN; 312 312 313 314 static int coreAudioInitIn(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples); 315 static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn); 316 static int coreAudioInitOut(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples); 317 static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut); 318 static OSStatus coreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID, UInt32 nAddresses, const AudioObjectPropertyAddress properties[], void *pvUser); 319 static OSStatus coreAudioPlaybackCb(void *pvUser, AudioUnitRenderActionFlags *pActionFlags, const AudioTimeStamp *pAudioTS, UInt32 uBusID, UInt32 cFrames, AudioBufferList* pBufData); 320 313 321 static int drvHostCoreAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, PDMAUDIOSTREAMCMD enmStreamCmd); 314 static int drvHostCoreAudio InitInput(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples);322 static int drvHostCoreAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd); 315 323 static int drvHostCoreAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn); 316 static int drvHostCoreAudioReinitInput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn);317 318 static int drvHostCoreAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd);319 static int drvHostCoreAudioInitOutput(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples);320 324 static int drvHostCoreAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut); 321 static int drvHostCoreAudioReinitOutput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut);322 static OSStatus drvHostCoreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID, UInt32 nAddresses, const AudioObjectPropertyAddress properties[], void *pvUser);323 static OSStatus drvHostCoreAudioPlaybackCallback(void *pvUser, AudioUnitRenderActionFlags *pActionFlags, const AudioTimeStamp *pAudioTS, UInt32 uBusID, UInt32 cFrames, AudioBufferList* pBufData);324 325 325 326 /* Callback for getting notified when the default input/output device has been changed. */ 326 static DECLCALLBACK(OSStatus) drvHostCoreAudioDefaultDeviceChanged(AudioObjectID propertyID,327 328 329 327 static DECLCALLBACK(OSStatus) coreAudioDefaultDeviceChanged(AudioObjectID propertyID, 328 UInt32 nAddresses, 329 const AudioObjectPropertyAddress properties[], 330 void *pvUser) 330 331 { 331 332 OSStatus err = noErr; … … 397 398 } 398 399 400 /** @todo Implement callback notification here to let the audio connector / device emulation 401 * know that something has changed. */ 402 399 403 return noErr; 400 404 } 401 405 402 static int drvHostCoreAudioReinitInput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)406 static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn) 403 407 { 404 408 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); … … 409 413 drvHostCoreAudioFiniIn(pInterface, &pStreamIn->streamIn); 410 414 411 drvHostCoreAudioInitInput(&pStreamIn->streamIn, NULL /* pcSamples */);415 coreAudioInitIn(&pStreamIn->streamIn, NULL /* pcSamples */); 412 416 drvHostCoreAudioControlIn(pInterface, &pStreamIn->streamIn, PDMAUDIOSTREAMCMD_ENABLE); 413 417 … … 415 419 } 416 420 417 static int drvHostCoreAudioReinitOutput(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)421 static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut) 418 422 { 419 423 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); … … 424 428 drvHostCoreAudioFiniOut(pInterface, &pStreamOut->streamOut); 425 429 426 drvHostCoreAudioInitOutput(&pStreamOut->streamOut, NULL /* pcSamples */);430 coreAudioInitOut(&pStreamOut->streamOut, NULL /* pcSamples */); 427 431 drvHostCoreAudioControlOut(pInterface, &pStreamOut->streamOut, PDMAUDIOSTREAMCMD_ENABLE); 428 432 … … 431 435 432 436 /* Callback for getting notified when some of the properties of an audio device has changed. */ 433 static DECLCALLBACK(OSStatus) drvHostCoreAudioRecordingAudioDevicePropertyChanged(AudioObjectID propertyID,434 435 436 437 static DECLCALLBACK(OSStatus) coreAudioRecordingAudioDevicePropertyChanged(AudioObjectID propertyID, 438 UInt32 cAdresses, 439 const AudioObjectPropertyAddress aProperties[], 440 void *pvUser) 437 441 { 438 442 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pvUser; … … 466 470 467 471 /* Callback to convert audio input data from one format to another. */ 468 static DECLCALLBACK(OSStatus) drvHostCoreAudioConverterCallback(AudioConverterRef converterID,469 470 471 472 472 static DECLCALLBACK(OSStatus) coreAudioConverterCb(AudioConverterRef converterID, 473 UInt32 *pcPackets, 474 AudioBufferList *pBufData, 475 AudioStreamPacketDescription **ppPacketDesc, 476 void *pvUser) 473 477 { 474 478 /** @todo Check incoming pointers. */ … … 521 525 522 526 /* Callback to feed audio input buffer. */ 523 static DECLCALLBACK(OSStatus) drvHostCoreAudioRecordingCallback(void*pvUser,524 525 526 527 528 527 static DECLCALLBACK(OSStatus) coreAudioRecordingCb(void *pvUser, 528 AudioUnitRenderActionFlags *pActionFlags, 529 const AudioTimeStamp *pAudioTS, 530 UInt32 uBusID, 531 UInt32 cFrames, 532 AudioBufferList *pBufData) 529 533 { 530 534 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pvUser; … … 596 600 AudioConverterReset(pStreamIn->converter); 597 601 598 err = AudioConverterFillComplexBuffer(pStreamIn->converter, drvHostCoreAudioConverterCallback, pStreamIn,602 err = AudioConverterFillComplexBuffer(pStreamIn->converter, coreAudioConverterCb, pStreamIn, 599 603 &ioOutputDataPacketSize, &tmpList, NULL); 600 604 if( err != noErr … … 692 696 693 697 /** @todo Eventually split up this function, as this already is huge! */ 694 static int drvHostCoreAudioInitInput(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples)698 static int coreAudioInitIn(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples) 695 699 { 696 700 OSStatus err = noErr; … … 833 837 AURenderCallbackStruct cb; 834 838 RT_ZERO(cb); 835 cb.inputProc = drvHostCoreAudioRecordingCallback;839 cb.inputProc = coreAudioRecordingCb; 836 840 cb.inputProcRefCon = pStreamIn; 837 841 … … 1023 1027 propAdr.mScope = kAudioUnitScope_Global; 1024 1028 err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr, 1025 drvHostCoreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);1029 coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn); 1026 1030 if (RT_UNLIKELY(err != noErr)) 1027 1031 LogRel(("CoreAudio: Failed to add the processor overload listener for input stream (%RI32)\n", err)); … … 1030 1034 propAdr.mScope = kAudioUnitScope_Global; 1031 1035 err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr, 1032 drvHostCoreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn);1036 coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn); 1033 1037 /* Not fatal. */ 1034 1038 if (RT_UNLIKELY(err != noErr)) … … 1059 1063 1060 1064 /** @todo Eventually split up this function, as this already is huge! */ 1061 static int drvHostCoreAudioInitOutput(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples)1065 static int coreAudioInitOut(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples) 1062 1066 { 1063 1067 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pHstStrmOut; … … 1188 1192 AURenderCallbackStruct cb; 1189 1193 RT_ZERO(cb); 1190 cb.inputProc = drvHostCoreAudioPlaybackCallback; /* pvUser */1194 cb.inputProc = coreAudioPlaybackCb; /* pvUser */ 1191 1195 cb.inputProcRefCon = pStreamOut; 1192 1196 … … 1297 1301 propAdr.mScope = kAudioUnitScope_Global; 1298 1302 err = AudioObjectAddPropertyListener(pStreamOut->deviceID, &propAdr, 1299 drvHostCoreAudioPlaybackAudioDevicePropertyChanged, (void *)pStreamOut);1303 coreAudioPlaybackAudioDevicePropertyChanged, (void *)pStreamOut); 1300 1304 if (err != noErr) 1301 1305 LogRel(("CoreAudio: Failed to register processor overload listener for output stream (%RI32)\n", err)); … … 1305 1309 propAdr.mScope = kAudioUnitScope_Global; 1306 1310 err = AudioObjectAddPropertyListener(pStreamOut->deviceID, &propAdr, 1307 drvHostCoreAudioPlaybackAudioDevicePropertyChanged, (void *)pStreamOut);1311 coreAudioPlaybackAudioDevicePropertyChanged, (void *)pStreamOut); 1308 1312 /* Not fatal. */ 1309 1313 if (err != noErr) … … 1333 1337 } 1334 1338 1339 1340 /* Callback for getting notified when some of the properties of an audio device has changed. */ 1341 static DECLCALLBACK(OSStatus) coreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID, 1342 UInt32 nAddresses, 1343 const AudioObjectPropertyAddress properties[], 1344 void *pvUser) 1345 { 1346 switch (propertyID) 1347 { 1348 #ifdef DEBUG 1349 case kAudioDeviceProcessorOverload: 1350 { 1351 Log2(("CoreAudio: [Output] Processor overload detected!\n")); 1352 break; 1353 } 1354 #endif /* DEBUG */ 1355 default: 1356 break; 1357 } 1358 1359 return noErr; 1360 } 1361 1362 /* Callback to feed audio output buffer. */ 1363 static DECLCALLBACK(OSStatus) coreAudioPlaybackCb(void *pvUser, 1364 AudioUnitRenderActionFlags *pActionFlags, 1365 const AudioTimeStamp *pAudioTS, 1366 UInt32 uBusID, 1367 UInt32 cFrames, 1368 AudioBufferList *pBufData) 1369 { 1370 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pvUser; 1371 PPDMAUDIOHSTSTRMOUT pHstStrmOut = &pStreamOut->streamOut; 1372 1373 if (ASMAtomicReadU32(&pStreamOut->status) != CA_STATUS_INIT) 1374 { 1375 pBufData->mBuffers[0].mDataByteSize = 0; 1376 return noErr; 1377 } 1378 1379 /* How much space is used in the ring buffer? */ 1380 size_t cbDataAvail = RT_MIN(RTCircBufUsed(pStreamOut->pBuf), pBufData->mBuffers[0].mDataByteSize); 1381 if (!cbDataAvail) 1382 { 1383 pBufData->mBuffers[0].mDataByteSize = 0; 1384 return noErr; 1385 } 1386 1387 uint8_t *pbSrc = NULL; 1388 size_t cbRead = 0; 1389 size_t cbToRead; 1390 while (cbDataAvail) 1391 { 1392 /* Try to acquire the necessary block from the ring buffer. */ 1393 RTCircBufAcquireReadBlock(pStreamOut->pBuf, cbDataAvail, (void **)&pbSrc, &cbToRead); 1394 1395 /* Break if nothing is used anymore. */ 1396 if (!cbToRead) 1397 break; 1398 1399 /* Copy the data from our ring buffer to the core audio buffer. */ 1400 memcpy((uint8_t *)pBufData->mBuffers[0].mData + cbRead, pbSrc, cbToRead); 1401 1402 /* Release the read buffer, so it could be used for new data. */ 1403 RTCircBufReleaseReadBlock(pStreamOut->pBuf, cbToRead); 1404 1405 /* Move offset. */ 1406 cbRead += cbToRead; 1407 Assert(pBufData->mBuffers[0].mDataByteSize >= cbRead); 1408 1409 Assert(cbToRead <= cbDataAvail); 1410 cbDataAvail -= cbToRead; 1411 } 1412 1413 /* Write the bytes to the core audio buffer which where really written. */ 1414 pBufData->mBuffers[0].mDataByteSize = cbRead; 1415 1416 LogFlowFunc(("CoreAudio: [Output] Read %zu / %zu bytes\n", cbRead, cbDataAvail)); 1417 1418 return noErr; 1419 } 1420 1335 1421 static DECLCALLBACK(int) drvHostCoreAudioInit(PPDMIHOSTAUDIO pInterface) 1336 1422 { … … 1356 1442 /* Check if the audio device should be reinitialized. If so do it. */ 1357 1443 if (ASMAtomicReadU32(&pStreamIn->status) == CA_STATUS_REINIT) 1358 drvHostCoreAudioReinitInput(pInterface, &pStreamIn->streamIn);1444 coreAudioReinitIn(pInterface, &pStreamIn->streamIn); 1359 1445 1360 1446 if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT) … … 1428 1514 } 1429 1515 1430 /* Callback for getting notified when some of the properties of an audio device has changed. */1431 static DECLCALLBACK(OSStatus) drvHostCoreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID,1432 UInt32 nAddresses,1433 const AudioObjectPropertyAddress properties[],1434 void *pvUser)1435 {1436 switch (propertyID)1437 {1438 #ifdef DEBUG1439 case kAudioDeviceProcessorOverload:1440 {1441 Log2(("CoreAudio: [Output] Processor overload detected!\n"));1442 break;1443 }1444 #endif /* DEBUG */1445 default:1446 break;1447 }1448 1449 return noErr;1450 }1451 1452 /* Callback to feed audio output buffer. */1453 static DECLCALLBACK(OSStatus) drvHostCoreAudioPlaybackCallback(void *pvUser,1454 AudioUnitRenderActionFlags *pActionFlags,1455 const AudioTimeStamp *pAudioTS,1456 UInt32 uBusID,1457 UInt32 cFrames,1458 AudioBufferList *pBufData)1459 {1460 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pvUser;1461 PPDMAUDIOHSTSTRMOUT pHstStrmOut = &pStreamOut->streamOut;1462 1463 if (ASMAtomicReadU32(&pStreamOut->status) != CA_STATUS_INIT)1464 {1465 pBufData->mBuffers[0].mDataByteSize = 0;1466 return noErr;1467 }1468 1469 /* How much space is used in the ring buffer? */1470 size_t cbDataAvail = RT_MIN(RTCircBufUsed(pStreamOut->pBuf), pBufData->mBuffers[0].mDataByteSize);1471 if (!cbDataAvail)1472 {1473 pBufData->mBuffers[0].mDataByteSize = 0;1474 return noErr;1475 }1476 1477 uint8_t *pbSrc = NULL;1478 size_t cbRead = 0;1479 size_t cbToRead;1480 while (cbDataAvail)1481 {1482 /* Try to acquire the necessary block from the ring buffer. */1483 RTCircBufAcquireReadBlock(pStreamOut->pBuf, cbDataAvail, (void **)&pbSrc, &cbToRead);1484 1485 /* Break if nothing is used anymore. */1486 if (!cbToRead)1487 break;1488 1489 /* Copy the data from our ring buffer to the core audio buffer. */1490 memcpy((uint8_t *)pBufData->mBuffers[0].mData + cbRead, pbSrc, cbToRead);1491 1492 /* Release the read buffer, so it could be used for new data. */1493 RTCircBufReleaseReadBlock(pStreamOut->pBuf, cbToRead);1494 1495 /* Move offset. */1496 cbRead += cbToRead;1497 Assert(pBufData->mBuffers[0].mDataByteSize >= cbRead);1498 1499 Assert(cbToRead <= cbDataAvail);1500 cbDataAvail -= cbToRead;1501 }1502 1503 /* Write the bytes to the core audio buffer which where really written. */1504 pBufData->mBuffers[0].mDataByteSize = cbRead;1505 1506 LogFlowFunc(("CoreAudio: [Output] Read %zu / %zu bytes\n", cbRead, cbDataAvail));1507 1508 return noErr;1509 }1510 1511 1516 static DECLCALLBACK(int) drvHostCoreAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, 1512 1517 uint32_t *pcSamplesPlayed) … … 1519 1524 /* Check if the audio device should be reinitialized. If so do it. */ 1520 1525 if (ASMAtomicReadU32(&pStreamOut->status) == CA_STATUS_REINIT) 1521 drvHostCoreAudioReinitOutput(pInterface, &pStreamOut->streamOut);1526 coreAudioReinitOut(pInterface, &pStreamOut->streamOut); 1522 1527 1523 1528 /* Not much else to do here. */ … … 1772 1777 #ifdef DEBUG 1773 1778 err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr, 1774 drvHostCoreAudioRecordingAudioDevicePropertyChanged, pStreamIn);1779 coreAudioRecordingAudioDevicePropertyChanged, pStreamIn); 1775 1780 /* Not Fatal */ 1776 1781 if (RT_UNLIKELY(err != noErr)) … … 1780 1785 propAdr.mSelector = kAudioDevicePropertyNominalSampleRate; 1781 1786 err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr, 1782 drvHostCoreAudioRecordingAudioDevicePropertyChanged, pStreamIn);1787 coreAudioRecordingAudioDevicePropertyChanged, pStreamIn); 1783 1788 /* Not Fatal */ 1784 1789 if (RT_UNLIKELY(err != noErr)) … … 1789 1794 propAdr.mSelector = kAudioHardwarePropertyDefaultInputDevice; 1790 1795 err = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propAdr, 1791 drvHostCoreAudioDefaultDeviceChanged, pStreamIn);1796 coreAudioDefaultDeviceChanged, pStreamIn); 1792 1797 if (RT_LIKELY(err == noErr)) 1793 1798 { … … 1872 1877 #ifdef DEBUG 1873 1878 err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr, 1874 drvHostCoreAudioPlaybackAudioDevicePropertyChanged, pStreamOut);1879 coreAudioPlaybackAudioDevicePropertyChanged, pStreamOut); 1875 1880 /* Not Fatal */ 1876 1881 if (RT_UNLIKELY(err != noErr)) … … 1880 1885 propAdr.mSelector = kAudioDevicePropertyNominalSampleRate; 1881 1886 err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr, 1882 drvHostCoreAudioPlaybackAudioDevicePropertyChanged, pStreamOut);1887 coreAudioPlaybackAudioDevicePropertyChanged, pStreamOut); 1883 1888 /* Not Fatal */ 1884 1889 if (RT_UNLIKELY(err != noErr)) … … 1891 1896 propAdr.mElement = kAudioObjectPropertyElementMaster; 1892 1897 err = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propAdr, 1893 drvHostCoreAudioDefaultDeviceChanged, pStreamOut);1898 coreAudioDefaultDeviceChanged, pStreamOut); 1894 1899 if (RT_LIKELY(err == noErr)) 1895 1900 { … … 1962 1967 } 1963 1968 #endif 1964 rc = drvHostCoreAudioInitInput(&pStreamIn->streamIn, pcSamples);1969 rc = coreAudioInitIn(&pStreamIn->streamIn, pcSamples); 1965 1970 } 1966 1971 … … 1973 1978 kAudioObjectPropertyElementMaster }; 1974 1979 OSStatus err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr, 1975 drvHostCoreAudioDefaultDeviceChanged, (void *)pStreamIn);1980 coreAudioDefaultDeviceChanged, (void *)pStreamIn); 1976 1981 /* Not fatal. */ 1977 1982 if (RT_LIKELY(err == noErr)) … … 2023 2028 #endif 2024 2029 2025 rc = drvHostCoreAudioInitOutput(pHstStrmOut, pcSamples);2030 rc = coreAudioInitOut(pHstStrmOut, pcSamples); 2026 2031 if (RT_FAILURE(rc)) 2027 2032 return rc; … … 2033 2038 kAudioObjectPropertyElementMaster }; 2034 2039 err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr, 2035 drvHostCoreAudioDefaultDeviceChanged, (void *)pStreamOut);2040 coreAudioDefaultDeviceChanged, (void *)pStreamOut); 2036 2041 /* Not fatal. */ 2037 2042 if (RT_LIKELY(err == noErr)) … … 2053 2058 } 2054 2059 2055 static DECLCALLBACK(int) drvHostCoreAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pAudioConf) 2056 { 2057 pAudioConf->cbStreamOut = sizeof(COREAUDIOSTREAMOUT); 2058 pAudioConf->cbStreamIn = sizeof(COREAUDIOSTREAMIN); 2059 pAudioConf->cMaxHstStrmsOut = 1; 2060 pAudioConf->cMaxHstStrmsIn = 2; 2060 static DECLCALLBACK(int) drvHostCoreAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 2061 { 2062 NOREF(pInterface); 2063 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 2064 2065 LogFlowFuncEnter(); 2066 2067 pCfg->cbStreamIn = sizeof(COREAUDIOSTREAMIN); 2068 pCfg->cbStreamOut = sizeof(COREAUDIOSTREAMOUT); 2069 pCfg->cMaxStreamsIn = UINT32_MAX; 2070 pCfg->cMaxStreamsOut = UINT32_MAX; 2071 2072 /** @todo Implement a proper device detection. */ 2073 pCfg->cDevsIn = 1; 2074 pCfg->cDevsOut = 1; 2061 2075 2062 2076 return VINF_SUCCESS; -
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r59890 r59987 91 91 { 92 92 PDMAUDIOHSTSTRMOUT strmOut; /* Always must come first! */ 93 LPDIRECTSOUND8 pDS; 93 LPDIRECTSOUND8 pDS; /** @todo Move this out of this structure! Not required per-stream (e.g. for multi-channel). */ 94 94 LPDIRECTSOUNDBUFFER8 pDSB; 95 95 DWORD cbPlayWritePos; … … 160 160 typedef struct DSOUNDENUMCBCTX 161 161 { 162 /** Pointer to host backend driver. */ 162 163 PDRVHOSTDSOUND pDrv; 163 PPDMAUDIOBACKENDCFG pCfg;164 164 /** Enumeration flags. */ 165 165 uint32_t fFlags; 166 /** Number of found input devices. */ 167 uint8_t cDevIn; 168 /** Number of found output devices. */ 169 uint8_t cDevOut; 166 170 } DSOUNDENUMCBCTX, *PDSOUNDENUMCBCTX; 167 171 … … 173 177 } DSOUNDDEV, *PDSOUNDDEV; 174 178 179 /********************************************************************************************************************************* 180 * Defines * 181 *********************************************************************************************************************************/ 182 175 183 /** Maximum number of attempts to restore the sound buffer before giving up. */ 176 184 #define DRV_DSOUND_RESTORE_ATTEMPTS_MAX 3 … … 179 187 #define PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface) \ 180 188 ( (PDRVHOSTDSOUND)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTDSOUND, IHostAudio)) ) 189 190 /********************************************************************************************************************************* 191 * Prototypes * 192 *********************************************************************************************************************************/ 181 193 182 194 static HRESULT directSoundPlayRestore(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB); … … 1243 1255 AssertPtrReturn(pCtx, FALSE); 1244 1256 AssertPtrReturn(pCtx->pDrv, FALSE); 1245 AssertPtrReturn(pCtx->pCfg, FALSE);1246 1257 1247 1258 if (!lpGUID) … … 1259 1270 return FALSE; /* Abort enumeration. */ 1260 1271 1261 pCtx-> pCfg->cMaxHstStrmsOut++;1272 pCtx->cDevOut++; 1262 1273 1263 1274 return TRUE; … … 1270 1281 AssertPtrReturn(pCtx, FALSE); 1271 1282 AssertPtrReturn(pCtx->pDrv, FALSE); 1272 AssertPtrReturn(pCtx->pCfg, FALSE);1273 1283 1274 1284 if (!lpGUID) … … 1283 1293 return FALSE; /* Abort enumeration. */ 1284 1294 1285 pCtx-> pCfg->cMaxHstStrmsIn++;1295 pCtx->cDevIn++; 1286 1296 1287 1297 return TRUE; … … 1293 1303 * @return IPRT status code. 1294 1304 * @param pThis Host audio driver instance. 1295 * @param p Cfg Where to store the enumeration results.1305 * @param pEnmCtx Enumeration context to use. 1296 1306 * @param fEnum Enumeration flags. 1297 1307 */ 1298 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, P PDMAUDIOBACKENDCFG pCfg, uint32_t fEnum)1299 { 1300 AssertPtrReturn(pThis, VERR_INVALID_POINTER);1301 AssertPtrReturn(p Cfg,VERR_INVALID_POINTER);1308 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PDSOUNDENUMCBCTX pEnmCtx, uint32_t fEnum) 1309 { 1310 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1311 AssertPtrReturn(pEnmCtx, VERR_INVALID_POINTER); 1302 1312 1303 1313 dsoundDevicesClear(pThis); 1304 1305 pCfg->cMaxHstStrmsOut = 0;1306 pCfg->cMaxHstStrmsIn = 0;1307 1314 1308 1315 RTLDRMOD hDSound = NULL; … … 1319 1326 if (RT_SUCCESS(rc)) 1320 1327 { 1321 DSOUNDENUMCBCTX ctx = { pThis, pCfg, fEnum }; 1322 1323 HRESULT hr = pfnDirectSoundEnumerateW(&dsoundDevicesEnumCbPlayback, &ctx); 1328 HRESULT hr = pfnDirectSoundEnumerateW(&dsoundDevicesEnumCbPlayback, pEnmCtx); 1324 1329 if (FAILED(hr)) 1325 1330 LogRel2(("DSound: Error enumerating host playback devices: %Rhrc\n", hr)); 1326 1331 1327 hr = pfnDirectSoundCaptureEnumerateW(&dsoundDevicesEnumCbCapture, &ctx);1332 hr = pfnDirectSoundCaptureEnumerateW(&dsoundDevicesEnumCbCapture, pEnmCtx); 1328 1333 if (FAILED(hr)) 1329 1334 LogRel2(("DSound: Error enumerating host capturing devices: %Rhrc\n", hr)); 1335 1336 if (fEnum & DSOUNDENUMCBFLAGS_LOG) 1337 { 1338 LogRel2(("DSound: Found %RU8 host playback devices\n", pEnmCtx->cDevOut)); 1339 LogRel2(("DSound: Found %RU8 host capturing devices\n", pEnmCtx->cDevIn)); 1340 } 1330 1341 } 1331 1342 … … 1357 1368 RT_ZERO(Cfg); 1358 1369 1359 Cfg.cbStreamOut = sizeof(DSOUNDSTREAMOUT); 1360 Cfg.cbStreamIn = sizeof(DSOUNDSTREAMIN); 1361 1362 int rc = dsoundDevicesEnumerate(pThis, &Cfg, fEnum); 1363 AssertRC(rc); 1364 1370 Cfg.cbStreamOut = sizeof(DSOUNDSTREAMOUT); 1371 Cfg.cbStreamIn = sizeof(DSOUNDSTREAMIN); 1372 1373 DSOUNDENUMCBCTX cbCtx = { pThis, fEnum, 0, 0 }; 1374 1375 int rc = dsoundDevicesEnumerate(pThis, &cbCtx, fEnum); 1376 if (RT_SUCCESS(rc)) 1377 { 1365 1378 #ifdef VBOX_WITH_AUDIO_CALLBACKS 1366 if ( pThis->fEnabledOut != RT_BOOL(Cfg.cMaxHstStrmsOut)1367 || pThis->fEnabledIn != RT_BOOL(Cfg.cMaxHstStrmsIn))1368 {1369 /** @todo Use a registered callback to the audio connector (e.g "OnConfigurationChanged") to1370 * let the connector know that something has changed within the host backend. */1371 }1379 if ( pThis->fEnabledOut != RT_BOOL(cbCtx.cDevOut) 1380 || pThis->fEnabledIn != RT_BOOL(cbCtx.cDevIn)) 1381 { 1382 /** @todo Use a registered callback to the audio connector (e.g "OnConfigurationChanged") to 1383 * let the connector know that something has changed within the host backend. */ 1384 } 1372 1385 #else 1373 pThis->fEnabledOut = RT_BOOL(Cfg.cMaxHstStrmsOut);1374 pThis->fEnabledIn = RT_BOOL(Cfg.cMaxHstStrmsIn);1386 pThis->fEnabledOut = RT_BOOL(cbCtx.cDevOut); 1387 pThis->fEnabledIn = RT_BOOL(cbCtx.cDevIn); 1375 1388 #endif 1376 1389 1377 if (pCfg) 1378 memcpy(pCfg, &Cfg, sizeof(PDMAUDIOBACKENDCFG)); 1390 Cfg.cSources = cbCtx.cDevIn; 1391 Cfg.cSinks = cbCtx.cDevOut; 1392 Cfg.cMaxStreamsIn = UINT32_MAX; 1393 Cfg.cMaxStreamsOut = UINT32_MAX; 1394 1395 if (pCfg) 1396 memcpy(pCfg, &Cfg, sizeof(PDMAUDIOBACKENDCFG)); 1397 } 1379 1398 1380 1399 LogFlowFuncLeaveRC(rc); … … 2096 2115 #endif 2097 2116 2098 PDMAUDIOBACKENDCFG Cfg; 2099 dsoundUpdateStatusInternalEx(pThis, &Cfg, DSOUNDENUMCBFLAGS_LOG /* fEnum */); 2100 2101 DSLOGREL(("DSound: Found %RU32 host playback devices\n", Cfg.cMaxHstStrmsOut)); 2102 DSLOGREL(("DSound: Found %RU32 host capturing devices\n", Cfg.cMaxHstStrmsIn)); 2117 dsoundUpdateStatusInternalEx(pThis, NULL /* pCfg */, DSOUNDENUMCBFLAGS_LOG /* fEnum */); 2103 2118 } 2104 2119 else -
trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp
r58983 r59987 6 6 7 7 /* 8 * Copyright (C) 2006-201 5Oracle Corporation8 * Copyright (C) 2006-2016 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 87 87 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 88 88 89 pCfg->cbStreamOut = sizeof(NULLAUDIOSTREAMOUT); 90 pCfg->cbStreamIn = sizeof(NULLAUDIOSTREAMIN); 91 92 pCfg->cMaxHstStrmsOut = 1; /* Output */ 93 pCfg->cMaxHstStrmsIn = 2; /* Line input + microphone input. */ 89 pCfg->cbStreamOut = sizeof(NULLAUDIOSTREAMOUT); 90 pCfg->cbStreamIn = sizeof(NULLAUDIOSTREAMIN); 91 92 /* The NULL backend has exactly one input source and one output sink. */ 93 pCfg->cSources = 1; 94 pCfg->cSinks = 1; 95 96 pCfg->cMaxStreamsOut = 1; /* Output */ 97 pCfg->cMaxStreamsIn = 2; /* Line input + microphone input. */ 94 98 95 99 return VINF_SUCCESS; -
trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp
r59097 r59987 5 5 6 6 /* 7 * Copyright (C) 2014-201 5Oracle Corporation7 * Copyright (C) 2014-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 34 34 #include <VBox/vmm/pdmaudioifs.h> 35 35 36 /********************************************************************************************************************************* 37 * Defines * 38 *********************************************************************************************************************************/ 39 40 #if ((SOUND_VERSION > 360) && (defined(OSS_SYSINFO))) 41 /* OSS > 3.6 has a new syscall available for querying a bit more detailed information 42 * about OSS' audio capabilities. */ 43 # define VBOX_WITH_OSS_SYSINFO 1 44 #endif 45 46 /** Makes DRVHOSTOSSAUDIO out of PDMIHOSTAUDIO. */ 47 #define PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface) \ 48 ( (PDRVHOSTOSSAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTOSSAUDIO, IHostAudio)) ) 49 50 /********************************************************************************************************************************* 51 * Structures * 52 *********************************************************************************************************************************/ 53 36 54 /** 37 55 * OSS host audio driver instance data. … … 67 85 int cbFragmentSize; 68 86 /** Own PCM buffer. */ 69 void *pv PCMBuf;87 void *pvBuf; 70 88 /** Size (in bytes) of own PCM buffer. */ 71 size_t cb PCMBuf;89 size_t cbBuf; 72 90 int old_optr; 73 91 } OSSAUDIOSTREAMIN, *POSSAUDIOSTREAMIN; … … 86 104 #endif 87 105 /** Own PCM buffer in case memory mapping is unavailable. */ 88 void *pv PCMBuf;106 void *pvBuf; 89 107 /** Size (in bytes) of own PCM buffer. */ 90 size_t cb PCMBuf;108 size_t cbBuf; 91 109 int old_optr; 92 110 } OSSAUDIOSTREAMOUT, *POSSAUDIOSTREAMOUT; … … 133 151 } 134 152 135 static int drvHostOSSAudioFmtToOSS(PDMAUDIOFMT fmt)153 static int ossAudioFmtToOSS(PDMAUDIOFMT fmt) 136 154 { 137 155 switch (fmt) … … 157 175 } 158 176 159 static int drvHostOSSAudioOSSToFmt(int fmt, 160 PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pENDIANNESS) 177 static int ossOSSToAudioFmt(int fmt, PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pENDIANNESS) 161 178 { 162 179 switch (fmt) … … 206 223 } 207 224 208 static int drvHostOSSAudioClose(int *phFile)225 static int ossStreamClose(int *phFile) 209 226 { 210 227 if (!phFile || !*phFile) … … 214 231 if (close(*phFile)) 215 232 { 216 LogRel(("OSS: Closing descriptor failed: %s\n", 217 strerror(errno))); 233 LogRel(("OSS: Closing stream failed: %s\n", strerror(errno))); 218 234 rc = VERR_GENERAL_FAILURE; /** @todo */ 219 235 } … … 227 243 } 228 244 229 static int drvHostOSSAudioOpen(bool fIn, 230 POSSAUDIOSTREAMCFG pReq, POSSAUDIOSTREAMCFG pObt, 231 int *phFile) 232 { 233 AssertPtrReturn(pReq, VERR_INVALID_POINTER); 234 AssertPtrReturn(pObt, VERR_INVALID_POINTER); 245 static int ossStreamOpen(const char *pszDev, int fOpen, POSSAUDIOSTREAMCFG pReq, POSSAUDIOSTREAMCFG pObt, int *phFile) 246 { 247 AssertPtrReturn(pszDev, VERR_INVALID_POINTER); 248 AssertPtrReturn(pReq, VERR_INVALID_POINTER); 249 AssertPtrReturn(pObt, VERR_INVALID_POINTER); 235 250 AssertPtrReturn(phFile, VERR_INVALID_POINTER); 236 251 237 252 int rc; 238 int hFile; 239 253 254 int hFile = -1; 240 255 do 241 256 { 242 const char *pszDev = fIn ? s_OSSConf.devpath_in : s_OSSConf.devpath_out; 243 if (!pszDev) 244 { 245 LogRel(("OSS: Invalid or no %s device name set\n", 246 fIn ? "input" : "output")); 247 rc = VERR_INVALID_PARAMETER; 248 break; 249 } 250 251 hFile = open(pszDev, (fIn ? O_RDONLY : O_WRONLY) | O_NONBLOCK); 257 hFile = open(pszDev, fOpen); 252 258 if (hFile == -1) 253 259 { 254 LogRel(("OSS: Failed to open %s: %s (%d)\n", pszDev, strerror(errno), errno));260 LogRel(("OSS: Failed to open %s: %s (%d)\n", pszDev, strerror(errno), errno)); 255 261 rc = RTErrConvertFromErrno(errno); 256 262 break; 257 263 } 258 264 259 int iFormat = drvHostOSSAudioFmtToOSS(pReq->enmFormat);265 int iFormat = ossAudioFmtToOSS(pReq->enmFormat); 260 266 if (ioctl(hFile, SNDCTL_DSP_SAMPLESIZE, &iFormat)) 261 267 { 262 LogRel(("OSS: Failed to set audio format to %ld errno=%s(%d)\n", iFormat, strerror(errno), errno));268 LogRel(("OSS: Failed to set audio format to %ld: %s (%d)\n", iFormat, strerror(errno), errno)); 263 269 rc = RTErrConvertFromErrno(errno); 264 270 break; … … 268 274 if (ioctl(hFile, SNDCTL_DSP_CHANNELS, &cChannels)) 269 275 { 270 LogRel(("OSS: Failed to set number of audio channels (%d): %s (%d)\n", pReq->cChannels, strerror(errno), errno));276 LogRel(("OSS: Failed to set number of audio channels (%d): %s (%d)\n", pReq->cChannels, strerror(errno), errno)); 271 277 rc = RTErrConvertFromErrno(errno); 272 278 break; … … 276 282 if (ioctl(hFile, SNDCTL_DSP_SPEED, &freq)) 277 283 { 278 LogRel(("OSS: Failed to set audio frequency (%dHZ): %s (%d)\n", pReq->uFreq, strerror(errno), errno));284 LogRel(("OSS: Failed to set audio frequency (%dHZ): %s (%d)\n", pReq->uFreq, strerror(errno), errno)); 279 285 rc = RTErrConvertFromErrno(errno); 280 286 break; … … 285 291 if (ioctl(hFile, SNDCTL_DSP_NONBLOCK)) 286 292 { 287 LogRel(("OSS: Failed to set non-blocking mode: %s (%d)\n", strerror(errno), errno));293 LogRel(("OSS: Failed to set non-blocking mode: %s (%d)\n", strerror(errno), errno)); 288 294 rc = RTErrConvertFromErrno(errno); 289 295 break; … … 293 299 if (ioctl(hFile, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) 294 300 { 295 LogRel(("OSS: Failed to set %RU16 fragments to %RU32 bytes each: %s (%d)\n",301 LogRel(("OSS: Failed to set %RU16 fragments to %RU32 bytes each: %s (%d)\n", 296 302 pReq->cFragments, pReq->cbFragmentSize, strerror(errno), errno)); 297 303 rc = RTErrConvertFromErrno(errno); … … 300 306 301 307 audio_buf_info abinfo; 302 if (ioctl(hFile, fIn? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo))303 { 304 LogRel(("OSS: Failed to retrieve buffer length: %s (%d)\n", strerror(errno), errno));308 if (ioctl(hFile, (fOpen & O_RDONLY) ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo)) 309 { 310 LogRel(("OSS: Failed to retrieve buffer length: %s (%d)\n", strerror(errno), errno)); 305 311 rc = RTErrConvertFromErrno(errno); 306 312 break; 307 313 } 308 314 309 rc = drvHostOSSAudioOSSToFmt(iFormat, &pObt->enmFormat, &pObt->enmENDIANNESS);315 rc = ossOSSToAudioFmt(iFormat, &pObt->enmFormat, &pObt->enmENDIANNESS); 310 316 if (RT_SUCCESS(rc)) 311 317 { … … 321 327 322 328 if (RT_FAILURE(rc)) 323 drvHostOSSAudioClose(&hFile);329 ossStreamClose(&hFile); 324 330 325 331 LogFlowFuncLeaveRC(rc); … … 362 368 { 363 369 DrvAudioClearBuf(&pHstStrmOut->Props, 364 pThisStrmOut->pv PCMBuf, pThisStrmOut->cbPCMBuf, AudioMixBufSize(&pHstStrmOut->MixBuf));370 pThisStrmOut->pvBuf, pThisStrmOut->cbBuf, AudioMixBufSize(&pHstStrmOut->MixBuf)); 365 371 366 372 mask = PCM_ENABLE_OUTPUT; … … 412 418 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 413 419 414 POSSAUDIOSTREAMIN p ThisStrmIn= (POSSAUDIOSTREAMIN)pHstStrmIn;420 POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pHstStrmIn; 415 421 416 422 int rc = VINF_SUCCESS; 417 size_t cbToRead = RT_MIN(p ThisStrmIn->cbPCMBuf,423 size_t cbToRead = RT_MIN(pStrm->cbBuf, 418 424 AudioMixBufFreeBytes(&pHstStrmIn->MixBuf)); 419 425 … … 427 433 while (cbToRead) 428 434 { 429 cbTemp = RT_MIN(cbToRead, p ThisStrmIn->cbPCMBuf);435 cbTemp = RT_MIN(cbToRead, pStrm->cbBuf); 430 436 AssertBreakStmt(cbTemp, rc = VERR_NO_DATA); 431 cbRead = read(pThisStrmIn->hFile, (uint8_t *)pThisStrmIn->pvPCMBuf + offWrite, cbTemp); 432 433 LogFlowFunc(("cbRead=%zi, cbTemp=%RU32, cbToRead=%zu\n", 434 cbRead, cbTemp, cbToRead)); 437 cbRead = read(pStrm->hFile, (uint8_t *)pStrm->pvBuf + offWrite, cbTemp); 438 439 LogFlowFunc(("cbRead=%zi, cbTemp=%RU32, cbToRead=%zu\n", cbRead, cbTemp, cbToRead)); 435 440 436 441 if (cbRead < 0) … … 451 456 452 457 default: 453 LogFlowFunc(("Failed to read %zu input frames, rc=%Rrc\n", 454 cbTemp, rc)); 455 rc = VERR_GENERAL_FAILURE; /** @todo */ 458 LogFlowFunc(("Failed to read %zu input frames, rc=%Rrc\n", cbTemp, rc)); 459 rc = VERR_GENERAL_FAILURE; /** @todo Fix this. */ 456 460 break; 457 461 } … … 463 467 { 464 468 uint32_t cWritten; 465 rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf, 466 pThisStrmIn->pvPCMBuf, cbRead, 467 &cWritten); 469 rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf, pStrm->pvBuf, cbRead, &cWritten); 468 470 if (RT_FAILURE(rc)) 469 471 break; … … 487 489 uint32_t cProcessed = 0; 488 490 if (cWrittenTotal) 489 rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal, 490 &cProcessed); 491 rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal, &cProcessed); 491 492 492 493 if (pcSamplesCaptured) … … 506 507 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 507 508 508 POSSAUDIOSTREAMIN p ThisStrmIn= (POSSAUDIOSTREAMIN)pHstStrmIn;509 POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pHstStrmIn; 509 510 510 511 LogFlowFuncEnter(); 511 512 512 if (pThisStrmIn->pvPCMBuf) 513 { 514 Assert(pThisStrmIn->cbPCMBuf); 515 516 RTMemFree(pThisStrmIn->pvPCMBuf); 517 pThisStrmIn->pvPCMBuf = NULL; 518 } 519 520 pThisStrmIn->cbPCMBuf = 0; 513 if (pStrm->pvBuf) 514 { 515 Assert(pStrm->cbBuf); 516 517 RTMemFree(pStrm->pvBuf); 518 pStrm->pvBuf = NULL; 519 } 520 521 pStrm->cbBuf = 0; 522 523 ossStreamClose(&pStrm->hFile); 521 524 522 525 return VINF_SUCCESS; … … 528 531 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 529 532 530 POSSAUDIOSTREAMOUT p ThisStrmOut= (POSSAUDIOSTREAMOUT)pHstStrmOut;533 POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pHstStrmOut; 531 534 532 535 LogFlowFuncEnter(); 533 536 534 537 #ifndef RT_OS_L4 535 if (!pThisStrmOut->fMemMapped) 536 { 537 if (pThisStrmOut->pvPCMBuf) 538 { 539 Assert(pThisStrmOut->cbPCMBuf); 540 541 RTMemFree(pThisStrmOut->pvPCMBuf); 542 pThisStrmOut->pvPCMBuf = NULL; 543 } 544 545 pThisStrmOut->cbPCMBuf = 0; 546 } 547 #endif 538 if (pStrm->fMemMapped) 539 { 540 if (pStrm->pvBuf) 541 { 542 Assert(pStrm->cbBuf); 543 544 int rc2 = munmap(pStrm->pvBuf, pStrm->cbBuf); 545 if (rc2 == 0) 546 { 547 pStrm->pvBuf = NULL; 548 pStrm->cbBuf = 0; 549 550 pStrm->fMemMapped = false; 551 } 552 else 553 LogRel(("OSS: Failed to memory unmap playback buffer on close: %s\n", strerror(errno))); 554 } 555 } 556 else 557 { 558 #endif 559 if (pStrm->pvBuf) 560 { 561 Assert(pStrm->cbBuf); 562 563 RTMemFree(pStrm->pvBuf); 564 pStrm->pvBuf = NULL; 565 } 566 567 pStrm->cbBuf = 0; 568 #ifndef RT_OS_L4 569 } 570 #endif 571 572 ossStreamClose(&pStrm->hFile); 548 573 549 574 return VINF_SUCCESS; … … 554 579 NOREF(pInterface); 555 580 581 pCfg->cbStreamIn = sizeof(OSSAUDIOSTREAMIN); 556 582 pCfg->cbStreamOut = sizeof(OSSAUDIOSTREAMOUT); 557 pCfg->cbStreamIn = sizeof(OSSAUDIOSTREAMIN); 558 pCfg->cMaxHstStrmsOut = INT_MAX; 559 pCfg->cMaxHstStrmsIn = INT_MAX; 583 584 pCfg->cSources = 0; 585 pCfg->cSinks = 0; 586 587 int hFile = open("/dev/dsp", O_WRONLY | O_NONBLOCK, 0); 588 if (hFile == -1) 589 { 590 /* Try opening the mixing device instead. */ 591 hFile = open("/dev/mixer", O_RDONLY | O_NONBLOCK, 0); 592 } 593 594 int ossVer = -1; 595 596 #ifdef VBOX_WITH_OSS_SYSINFO 597 oss_sysinfo ossInfo; 598 RT_ZERO(ossInfo); 599 #endif 600 601 if (hFile != -1) 602 { 603 int err = ioctl(hFile, OSS_GETVERSION, &ossVer); 604 if (err == 0) 605 { 606 LogRel2(("OSS: Using version: %d\n", ossVer)); 607 #ifdef VBOX_WITH_OSS_SYSINFO 608 err = ioctl(hFile, OSS_SYSINFO, &ossInfo); 609 if (err == 0) 610 { 611 LogRel2(("OSS: Number of DSPs: %d\n", ossVer.numaudios)); 612 LogRel2(("OSS: Number of mixers: %d\n", ossVer.nummixers)); 613 /** @todo Determine number of input devices + output devices. */ 614 } 615 else 616 { 617 #endif 618 /* Since we cannot query anything, assume that we have at least 619 * one input and one output if we found "/dev/dsp" or "/dev/mixer". */ 620 pCfg->cSources = 1; 621 pCfg->cSinks = 1; 622 623 pCfg->cMaxStreamsIn = UINT32_MAX; /* Line in + microphone in. */ 624 pCfg->cMaxStreamsOut = UINT32_MAX; 625 #ifdef VBOX_WITH_OSS_SYSINFO 626 } 627 #endif 628 } 629 else 630 LogRel(("OSS: Unable to determine installed version: %s (%d)\n", strerror(err), err)); 631 } 632 else 633 LogRel(("OSS: No devices found, audio is not available\n")); 560 634 561 635 return VINF_SUCCESS; … … 567 641 uint32_t *pcSamples) 568 642 { 569 NOREF(pInterface);643 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 570 644 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 571 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 572 573 POSSAUDIOSTREAMIN pThisStrmIn = (POSSAUDIOSTREAMIN)pHstStrmIn; 645 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 646 647 PDRVHOSTOSSAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface); 648 POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pHstStrmIn; 574 649 575 650 int rc; … … 587 662 reqStream.cbFragmentSize = s_OSSConf.fragsize; 588 663 589 rc = drvHostOSSAudioOpen(true /* fIn */, 590 &reqStream, &obtStream, &hFile); 664 rc = ossStreamOpen(s_OSSConf.devpath_in, O_RDONLY | O_NONBLOCK, &reqStream, &obtStream, &hFile); 591 665 if (RT_SUCCESS(rc)) 592 666 { 593 667 if (obtStream.cFragments * obtStream.cbFragmentSize & pHstStrmIn->Props.uAlign) 594 LogRel(("OSS: Warning: Misaligned DAC outputbuffer: Size = %zu, Alignment = %u\n",668 LogRel(("OSS: Warning: Misaligned capturing buffer: Size = %zu, Alignment = %u\n", 595 669 obtStream.cFragments * obtStream.cbFragmentSize, 596 670 pHstStrmIn->Props.uAlign + 1)); 597 598 pThisStrmIn->hFile = hFile;599 671 600 672 PDMAUDIOSTREAMCFG streamCfg; … … 617 689 { 618 690 size_t cbSample = (1 << pHstStrmIn->Props.cShift); 619 size_t cbBuf = cSamples * cbSample; 620 pThisStrmIn->pvPCMBuf = RTMemAlloc(cbBuf); 621 if (!pThisStrmIn->pvPCMBuf) 622 { 623 LogRel(("OSS: Failed allocating ADC buffer with %RU32 samples (%zu bytes per sample)\n", cSamples, cbSample)); 691 692 size_t cbBuf = cSamples * cbSample; 693 void *pvBuf = RTMemAlloc(cbBuf); 694 if (!pvBuf) 695 { 696 LogRel(("OSS: Failed allocating capturing buffer with %RU32 samples (%zu bytes per sample)\n", 697 cSamples, cbSample)); 624 698 rc = VERR_NO_MEMORY; 625 } 626 627 pThisStrmIn->cbPCMBuf = cbBuf; 699 break; 700 } 701 702 pStrm->hFile = hFile; 703 pStrm->pvBuf = pvBuf; 704 pStrm->cbBuf = cbBuf; 628 705 629 706 if (pcSamples) … … 634 711 635 712 if (RT_FAILURE(rc)) 636 drvHostOSSAudioClose(&hFile);713 ossStreamClose(&hFile); 637 714 638 715 LogFlowFuncLeaveRC(rc); … … 644 721 uint32_t *pcSamples) 645 722 { 646 NOREF(pInterface);723 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 647 724 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 648 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 649 650 POSSAUDIOSTREAMOUT pThisStrmOut = (POSSAUDIOSTREAMOUT)pHstStrmOut; 725 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 726 727 PDRVHOSTOSSAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface); 728 POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pHstStrmOut; 651 729 652 730 int rc; … … 664 742 reqStream.cbFragmentSize = s_OSSConf.fragsize; 665 743 666 rc = drvHostOSSAudioOpen(false /* fIn */, 667 &reqStream, &obtStream, &hFile); 744 rc = ossStreamOpen(s_OSSConf.devpath_out, O_WRONLY | O_NONBLOCK, &reqStream, &obtStream, &hFile); 668 745 if (RT_SUCCESS(rc)) 669 746 { 670 747 if (obtStream.cFragments * obtStream.cbFragmentSize & pHstStrmOut->Props.uAlign) 671 LogRel(("OSS: Warning: Misaligned DAC outputbuffer: Size = %zu, Alignment = %u\n",748 LogRel(("OSS: Warning: Misaligned playback buffer: Size = %zu, Alignment = %u\n", 672 749 obtStream.cFragments * obtStream.cbFragmentSize, 673 750 pHstStrmOut->Props.uAlign + 1)); 674 675 pThisStrmOut->hFile = hFile;676 751 677 752 PDMAUDIOSTREAMCFG streamCfg; … … 689 764 if (RT_SUCCESS(rc)) 690 765 { 766 pStrm->fMemMapped = false; 767 768 size_t cbSamples = cSamples << pHstStrmOut->Props.cShift; 769 Assert(cbSamples); 770 691 771 #ifndef RT_OS_L4 692 pThisStrmOut->fMemMapped = false;693 772 if (s_OSSConf.try_mmap) 694 773 { 695 pThisStrmOut->pvPCMBuf = mmap(0, cSamples << pHstStrmOut->Props.cShift, 696 PROT_READ | PROT_WRITE, MAP_SHARED, hFile, 0); 697 if (pThisStrmOut->pvPCMBuf == MAP_FAILED) 774 pStrm->pvBuf = mmap(0, cbSamples, PROT_READ | PROT_WRITE, MAP_SHARED, hFile, 0); 775 if (pStrm->pvBuf == MAP_FAILED) 698 776 { 699 LogRel(("OSS: Failed to memory map %zu bytes of DAC output file: %s\n", 700 cSamples << pHstStrmOut->Props.cShift, strerror(errno))); 777 LogRel(("OSS: Failed to memory map %zu bytes of playback buffer: %s\n", cbSamples, strerror(errno))); 701 778 rc = RTErrConvertFromErrno(errno); 702 779 break; … … 707 784 if (ioctl(hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0) 708 785 { 709 LogRel(("OSS: Failed to retrieve initial trigger mask: %s\n", 710 strerror(errno))); 786 LogRel(("OSS: Failed to retrieve initial trigger mask for playback buffer: %s\n", strerror(errno))); 711 787 rc = RTErrConvertFromErrno(errno); 712 788 /* Note: No break here, need to unmap file first! */ … … 717 793 if (ioctl (hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0) 718 794 { 719 LogRel(("OSS: Failed to retrieve PCM_ENABLE_OUTPUT mask: %s\n", 720 strerror(errno))); 795 LogRel(("OSS: Failed to retrieve PCM_ENABLE_OUTPUT mask: %s\n", strerror(errno))); 721 796 rc = RTErrConvertFromErrno(errno); 722 797 /* Note: No break here, need to unmap file first! */ 723 798 } 724 799 else 725 p ThisStrmOut->fMemMapped = true;800 pStrm->fMemMapped = true; 726 801 } 727 802 728 if ( !pThisStrmOut->fMemMapped)803 if (RT_FAILURE(rc)) 729 804 { 730 int rc2 = munmap(pThisStrmOut->pvPCMBuf, 731 cSamples << pHstStrmOut->Props.cShift); 805 int rc2 = munmap(pStrm->pvBuf, cbSamples); 732 806 if (rc2) 733 LogRel(("OSS: Failed to unmap DAC output file: %s\n", strerror(errno)));807 LogRel(("OSS: Failed to memory unmap playback buffer: %s\n", strerror(errno))); 734 808 break; 735 809 } … … 740 814 /* Memory mapping failed above? Try allocating an own buffer. */ 741 815 #ifndef RT_OS_L4 742 if (!pThisStrmOut->fMemMapped) 743 { 744 #endif 745 size_t cbSample = (1 << pHstStrmOut->Props.cShift); 746 size_t cbPCMBuf = cSamples * cbSample; 747 748 LogFlowFunc(("cSamples=%RU32\n", cSamples)); 749 750 pThisStrmOut->pvPCMBuf = RTMemAlloc(cbPCMBuf); 751 if (!pThisStrmOut->pvPCMBuf) 816 if (!pStrm->fMemMapped) 817 { 818 #endif 819 void *pvBuf = RTMemAlloc(cbSamples); 820 if (!pvBuf) 752 821 { 753 LogRel(("OSS: Failed allocating DAC buffer with %RU32 samples (%zu bytes per sample)\n", cSamples, cbSample));822 LogRel(("OSS: Failed allocating playback buffer with %RU32 samples (%zu bytes)\n", cSamples, cbSamples)); 754 823 rc = VERR_NO_MEMORY; 755 824 break; 756 825 } 757 826 758 pThisStrmOut->cbPCMBuf = cbPCMBuf; 827 pStrm->hFile = hFile; 828 pStrm->pvBuf = pvBuf; 829 pStrm->cbBuf = cbSamples; 759 830 #ifndef RT_OS_L4 760 831 } … … 767 838 768 839 if (RT_FAILURE(rc)) 769 drvHostOSSAudioClose(&hFile);840 ossStreamClose(&hFile); 770 841 771 842 LogFlowFuncLeaveRC(rc); … … 786 857 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 787 858 788 POSSAUDIOSTREAMOUT p ThisStrmOut= (POSSAUDIOSTREAMOUT)pHstStrmOut;859 POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pHstStrmOut; 789 860 790 861 int rc = VINF_SUCCESS; … … 800 871 801 872 #ifndef RT_OS_L4 802 if (p ThisStrmOut->fMemMapped)873 if (pStrm->fMemMapped) 803 874 { 804 875 /* Get current playback pointer. */ 805 int rc2 = ioctl(p ThisStrmOut->hFile, SNDCTL_DSP_GETOPTR, &cntinfo);876 int rc2 = ioctl(pStrm->hFile, SNDCTL_DSP_GETOPTR, &cntinfo); 806 877 if (!rc2) 807 878 { … … 813 884 814 885 /* Nothing to play? */ 815 if (cntinfo.ptr == p ThisStrmOut->old_optr)886 if (cntinfo.ptr == pStrm->old_optr) 816 887 break; 817 888 818 889 int cbData; 819 if (cntinfo.ptr > p ThisStrmOut->old_optr)820 cbData = cntinfo.ptr - p ThisStrmOut->old_optr;890 if (cntinfo.ptr > pStrm->old_optr) 891 cbData = cntinfo.ptr - pStrm->old_optr; 821 892 else 822 cbData = cbBuf + cntinfo.ptr - p ThisStrmOut->old_optr;893 cbData = cbBuf + cntinfo.ptr - pStrm->old_optr; 823 894 Assert(cbData); 824 895 … … 830 901 #endif 831 902 audio_buf_info abinfo; 832 int rc2 = ioctl(p ThisStrmOut->hFile, SNDCTL_DSP_GETOSPACE, &abinfo);903 int rc2 = ioctl(pStrm->hFile, SNDCTL_DSP_GETOSPACE, &abinfo); 833 904 if (rc2 < 0) 834 905 { 835 LogRel(("OSS: Failed to retrieve current playback buffer: %s\n", 836 strerror(errno))); 906 LogRel(("OSS: Failed to retrieve current playback buffer: %s\n", strerror(errno))); 837 907 rc = RTErrConvertFromErrno(errno); 838 908 break; … … 841 911 if ((size_t)abinfo.bytes > cbBuf) 842 912 { 843 LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%d\n", 844 abinfo.bytes, cbBuf)); 913 LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%zu\n", abinfo.bytes, cbBuf)); 845 914 abinfo.bytes = cbBuf; 846 915 /* Keep going. */ … … 849 918 if (abinfo.bytes < 0) 850 919 { 851 LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%d\n", 852 abinfo.bytes, cbBuf)); 920 LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%zu\n", abinfo.bytes, cbBuf)); 853 921 rc = VERR_INVALID_PARAMETER; 854 922 break; 855 923 } 856 924 857 cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, abinfo.bytes), 858 cLive); 925 cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, abinfo.bytes), cLive); 859 926 if (!cToRead) 860 927 break; … … 868 935 while (cbToRead) 869 936 { 870 rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, 871 pThisStrmOut->pvPCMBuf, cbToRead, &cRead); 937 rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pStrm->pvBuf, cbToRead, &cRead); 872 938 if (RT_FAILURE(rc)) 873 939 break; 874 940 875 941 cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead); 876 ssize_t cbWritten = write(pThisStrmOut->hFile, pThisStrmOut->pvPCMBuf, 877 cbRead); 942 ssize_t cbWritten = write(pStrm->hFile, pStrm->pvBuf, cbRead); 878 943 if (cbWritten == -1) 879 944 { … … 884 949 885 950 Assert(cbToRead >= cbRead); 886 cbToRead -= cbRead;951 cbToRead -= cbRead; 887 952 cbReadTotal += cbRead; 888 953 } … … 890 955 #ifndef RT_OS_L4 891 956 /* Update read pointer. */ 892 if (p ThisStrmOut->fMemMapped)893 p ThisStrmOut->old_optr = cntinfo.ptr;957 if (pStrm->fMemMapped) 958 pStrm->old_optr = cntinfo.ptr; 894 959 #endif 895 960 … … 905 970 *pcSamplesPlayed = cReadTotal; 906 971 907 LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n", 908 cReadTotal, cbReadTotal, rc)); 972 LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n", cReadTotal, cbReadTotal, rc)); 909 973 } 910 974 -
trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp
r59470 r59987 16 16 */ 17 17 18 19 18 /********************************************************************************************************************************* 20 19 * Header Files * … … 41 40 #include "VBoxDD.h" 42 41 42 /********************************************************************************************************************************* 43 * Defines * 44 *********************************************************************************************************************************/ 43 45 #define VBOX_PULSEAUDIO_MAX_LOG_REL_ERRORS 32 /** @todo Make this configurable thru driver options. */ 44 46 … … 51 53 #endif 52 54 53 /* 54 * We use a g_pMainLoop in a separate thread g_pContext. We have to call functions for 55 * manipulating objects either from callback functions or we have to protect 56 * these functions by pa_threaded_mainloop_lock() / pa_threaded_mainloop_unlock(). 57 */ 58 static struct pa_threaded_mainloop *g_pMainLoop; 59 static struct pa_context *g_pContext; 60 static volatile bool g_fAbortMainLoop; 55 /** No flags specified. */ 56 #define PULSEAUDIOENUMCBFLAGS_NONE 0 57 /** (Release) log found devices. */ 58 #define PULSEAUDIOENUMCBFLAGS_LOG RT_BIT(0) 59 60 /** Makes DRVHOSTPULSEAUDIO out of PDMIHOSTAUDIO. */ 61 #define PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface) \ 62 ( (PDRVHOSTPULSEAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPULSEAUDIO, IHostAudio)) ) 63 64 /********************************************************************************************************************************* 65 * Structures * 66 *********************************************************************************************************************************/ 61 67 62 68 /** … … 67 73 { 68 74 /** Pointer to the driver instance structure. */ 69 PPDMDRVINS pDrvIns; 75 PPDMDRVINS pDrvIns; 76 /** Pointer to PulseAudio's threaded main loop. */ 77 pa_threaded_mainloop *pMainLoop; 78 /** 79 * Pointer to our PulseAudio context. 80 * Note: We use a pMainLoop in a separate thread (pContext). 81 * So either use callback functions or protect these functions 82 * by pa_threaded_mainloop_lock() / pa_threaded_mainloop_unlock(). 83 */ 84 pa_context *pContext; 85 /** Shutdown indicator. */ 86 bool fLoopWait; 70 87 /** Pointer to host audio interface. */ 71 PDMIHOSTAUDIO IHostAudio;88 PDMIHOSTAUDIO IHostAudio; 72 89 /** Error count for not flooding the release log. 73 * UINT32_MAX for unlimited logging. */74 uint32_t cLogErrors;75 /** Configuration option: stream name. */76 char *pszStreamName;90 * Specify UINT32_MAX for unlimited logging. */ 91 uint32_t cLogErrors; 92 /** Configuration option: stream name. Optional. */ 93 char *pszStreamName; 77 94 } DRVHOSTPULSEAUDIO, *PDRVHOSTPULSEAUDIO; 78 95 … … 124 141 }; 125 142 126 /** Makes DRVHOSTPULSEAUDIO out of PDMIHOSTAUDIO. */ 127 #define PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface) \ 128 ( (PDRVHOSTPULSEAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPULSEAUDIO, IHostAudio)) ) 129 130 static int drvHostPulseAudioError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg); 131 static void drvHostPulseAudioCbSuccess(pa_stream *pStream, int fSuccess, void *pvContext); 143 /** 144 * Callback context for server enumeration callbacks. 145 */ 146 typedef struct PULSEAUDIOENUMCBCTX 147 { 148 /** Pointer to host backend driver. */ 149 PDRVHOSTPULSEAUDIO pDrv; 150 /** Enumeration flags. */ 151 uint32_t fFlags; 152 /** Number of found input devices. */ 153 uint8_t cDevIn; 154 /** Number of found output devices. */ 155 uint8_t cDevOut; 156 /** Name of default sink being used. Must be free'd using RTStrFree(). */ 157 char *pszDefaultSink; 158 /** Name of default source being used. Must be free'd using RTStrFree(). */ 159 char *pszDefaultSource; 160 } PULSEAUDIOENUMCBCTX, *PPULSEAUDIOENUMCBCTX; 161 162 /********************************************************************************************************************************* 163 * Prototypes * 164 *********************************************************************************************************************************/ 165 166 static int paEnumerate(PDRVHOSTPULSEAUDIO pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum); 167 static int paError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg); 168 static void paStreamCbSuccess(pa_stream *pStream, int fSuccess, void *pvContext); 132 169 133 170 /** … … 135 172 * mainloop might not have been entered yet. 136 173 */ 137 static void drvHostPulseAudioAbortMainLoop(void)138 { 139 g_fAbortMainLoop= true;140 pa_threaded_mainloop_signal( g_pMainLoop, 0);141 } 142 143 static pa_sample_format_t drvHostPulseAudioFmtToPulse(PDMAUDIOFMT fmt)174 static void paSignalWaiter(PDRVHOSTPULSEAUDIO pThis) 175 { 176 pThis->fLoopWait = true; 177 pa_threaded_mainloop_signal(pThis->pMainLoop, 0); 178 } 179 180 static pa_sample_format_t paFmtToPulse(PDMAUDIOFMT fmt) 144 181 { 145 182 switch (fmt) … … 163 200 } 164 201 165 static int drvHostPulseAudioPulseToFmt(pa_sample_format_t pulsefmt,166 202 static int paPulseToFmt(pa_sample_format_t pulsefmt, 203 PDMAUDIOFMT *pFmt, PDMAUDIOENDIANNESS *pEndianness) 167 204 { 168 205 switch (pulsefmt) … … 208 245 * Synchronously wait until an operation completed. 209 246 */ 210 static int drvHostPulseAudioWaitFor(pa_operation *pOP, RTMSINTERVAL cMsTimeout) 211 { 212 AssertPtrReturn(pOP, VERR_INVALID_POINTER); 247 static int paWaitForEx(PDRVHOSTPULSEAUDIO pThis, pa_operation *pOP, RTMSINTERVAL cMsTimeout) 248 { 249 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 250 AssertPtrReturn(pOP, VERR_INVALID_POINTER); 213 251 214 252 int rc = VINF_SUCCESS; 215 if (pOP) 216 { 217 uint64_t u64StartMs = RTTimeMilliTS(); 218 while (pa_operation_get_state(pOP) == PA_OPERATION_RUNNING) 219 { 220 if (!g_fAbortMainLoop) 221 pa_threaded_mainloop_wait(g_pMainLoop); 222 g_fAbortMainLoop = false; 223 224 uint64_t u64ElapsedMs = RTTimeMilliTS() - u64StartMs; 225 if (u64ElapsedMs >= cMsTimeout) 226 { 227 rc = VERR_TIMEOUT; 228 break; 229 } 230 } 231 232 pa_operation_unref(pOP); 233 } 253 254 uint64_t u64StartMs = RTTimeMilliTS(); 255 while (pa_operation_get_state(pOP) == PA_OPERATION_RUNNING) 256 { 257 if (!pThis->fLoopWait) 258 { 259 AssertPtr(pThis->pMainLoop); 260 pa_threaded_mainloop_wait(pThis->pMainLoop); 261 } 262 pThis->fLoopWait = false; 263 264 uint64_t u64ElapsedMs = RTTimeMilliTS() - u64StartMs; 265 if (u64ElapsedMs >= cMsTimeout) 266 { 267 rc = VERR_TIMEOUT; 268 break; 269 } 270 } 271 272 pa_operation_unref(pOP); 234 273 235 274 return rc; 275 } 276 277 static int paWaitFor(PDRVHOSTPULSEAUDIO pThis, pa_operation *pOP) 278 { 279 return paWaitForEx(pThis, pOP, 10 * 1000 /* 10s timeout */); 236 280 } 237 281 … … 239 283 * Context status changed. 240 284 */ 241 static void drvHostPulseAudioCbCtxState(pa_context *pContext, void *pvUser) 242 { 243 AssertPtrReturnVoid(pContext); 244 NOREF(pvUser); 245 246 switch (pa_context_get_state(pContext)) 285 static void paContextCbStateChanged(pa_context *pCtx, void *pvUser) 286 { 287 AssertPtrReturnVoid(pCtx); 288 289 PDRVHOSTPULSEAUDIO pThis = (PDRVHOSTPULSEAUDIO)pvUser; 290 AssertPtrReturnVoid(pThis); 291 292 switch (pa_context_get_state(pCtx)) 247 293 { 248 294 case PA_CONTEXT_READY: 249 295 case PA_CONTEXT_TERMINATED: 250 drvHostPulseAudioAbortMainLoop();296 paSignalWaiter(pThis); 251 297 break; 252 298 253 299 case PA_CONTEXT_FAILED: 254 LogRel(("PulseAudio: Audio input/output stopped!\n"));255 drvHostPulseAudioAbortMainLoop();300 LogRel(("PulseAudio: Audio context has failed, stopping\n")); 301 paSignalWaiter(pThis); 256 302 break; 257 303 … … 264 310 * Callback called when our pa_stream_drain operation was completed. 265 311 */ 266 static void drvHostPulseAudioCbStreamDrain(pa_stream *pStream, int fSuccess, void *pvContext)312 static void paStreamCbDrain(pa_stream *pStream, int fSuccess, void *pvUser) 267 313 { 268 314 AssertPtrReturnVoid(pStream); 269 315 270 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pv Context;316 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pvUser; 271 317 AssertPtrReturnVoid(pStrm); 272 318 … … 275 321 { 276 322 pa_operation_unref(pa_stream_cork(pStream, 1, 277 drvHostPulseAudioCbSuccess, pvContext));323 paStreamCbSuccess, pvUser)); 278 324 } 279 325 else 280 drvHostPulseAudioError(pStrm->pDrv, "Failed to drain stream");326 paError(pStrm->pDrv, "Failed to drain stream"); 281 327 282 328 pa_operation_unref(pStrm->pDrainOp); … … 287 333 * Stream status changed. 288 334 */ 289 static void drvHostPulseAudioCbStreamState(pa_stream *pStream, void *pvContext)335 static void paStreamCbStateChanged(pa_stream *pStream, void *pvUser) 290 336 { 291 337 AssertPtrReturnVoid(pStream); 292 NOREF(pvContext); 338 339 PDRVHOSTPULSEAUDIO pThis = (PDRVHOSTPULSEAUDIO)pvUser; 340 AssertPtrReturnVoid(pThis); 293 341 294 342 switch (pa_stream_get_state(pStream)) … … 297 345 case PA_STREAM_FAILED: 298 346 case PA_STREAM_TERMINATED: 299 drvHostPulseAudioAbortMainLoop();347 paSignalWaiter(pThis); 300 348 break; 301 349 … … 305 353 } 306 354 307 static void drvHostPulseAudioCbSuccess(pa_stream *pStream, int fSuccess, void *pvContext)355 static void paStreamCbSuccess(pa_stream *pStream, int fSuccess, void *pvUser) 308 356 { 309 357 AssertPtrReturnVoid(pStream); 310 358 311 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pv Context;359 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pvUser; 312 360 AssertPtrReturnVoid(pStrm); 313 361 … … 315 363 316 364 if (fSuccess) 317 drvHostPulseAudioAbortMainLoop();365 paSignalWaiter(pStrm->pDrv); 318 366 else 319 drvHostPulseAudioError(pStrm->pDrv, "Failed to finish stream operation"); 320 } 321 322 static int drvHostPulseAudioOpen(bool fIn, const char *pszName, 323 pa_sample_spec *pSampleSpec, pa_buffer_attr *pBufAttr, 324 pa_stream **ppStream) 325 { 326 AssertPtrReturn(pszName, VERR_INVALID_POINTER); 367 paError(pStrm->pDrv, "Failed to finish stream operation"); 368 } 369 370 static int paStreamOpen(PDRVHOSTPULSEAUDIO pThis, bool fIn, const char *pszName, 371 pa_sample_spec *pSampleSpec, pa_buffer_attr *pBufAttr, 372 pa_stream **ppStream) 373 { 374 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 375 AssertPtrReturn(pszName, VERR_INVALID_POINTER); 327 376 AssertPtrReturn(pSampleSpec, VERR_INVALID_POINTER); 328 AssertPtrReturn(pBufAttr, VERR_INVALID_POINTER);329 AssertPtrReturn(ppStream, VERR_INVALID_POINTER);377 AssertPtrReturn(pBufAttr, VERR_INVALID_POINTER); 378 AssertPtrReturn(ppStream, VERR_INVALID_POINTER); 330 379 331 380 if (!pa_sample_spec_valid(pSampleSpec)) … … 345 394 pa_sample_format_to_string(pSampleSpec->format))); 346 395 347 pa_threaded_mainloop_lock( g_pMainLoop);396 pa_threaded_mainloop_lock(pThis->pMainLoop); 348 397 349 398 do 350 399 { 351 if (!(pStream = pa_stream_new( g_pContext, pszName, pSampleSpec,400 if (!(pStream = pa_stream_new(pThis->pContext, pszName, pSampleSpec, 352 401 NULL /* pa_channel_map */))) 353 402 { … … 357 406 } 358 407 359 pa_stream_set_state_callback(pStream, drvHostPulseAudioCbStreamState, NULL);408 pa_stream_set_state_callback(pStream, paStreamCbStateChanged, pThis); 360 409 361 410 #if PA_API_VERSION >= 12 … … 379 428 { 380 429 LogRel(("PulseAudio: Could not connect input stream \"%s\": %s\n", 381 pszName, pa_strerror(pa_context_errno( g_pContext))));430 pszName, pa_strerror(pa_context_errno(pThis->pContext)))); 382 431 rc = VERR_AUDIO_BACKEND_INIT_FAILED; 383 432 break; … … 393 442 { 394 443 LogRel(("PulseAudio: Could not connect playback stream \"%s\": %s\n", 395 pszName, pa_strerror(pa_context_errno( g_pContext))));444 pszName, pa_strerror(pa_context_errno(pThis->pContext)))); 396 445 rc = VERR_AUDIO_BACKEND_INIT_FAILED; 397 446 break; … … 402 451 for (;;) 403 452 { 404 if (! g_fAbortMainLoop)405 pa_threaded_mainloop_wait( g_pMainLoop);406 g_fAbortMainLoop= false;407 408 pa_stream_state_t s state= pa_stream_get_state(pStream);409 if (s state== PA_STREAM_READY)453 if (!pThis->fLoopWait) 454 pa_threaded_mainloop_wait(pThis->pMainLoop); 455 pThis->fLoopWait = false; 456 457 pa_stream_state_t streamSt = pa_stream_get_state(pStream); 458 if (streamSt == PA_STREAM_READY) 410 459 break; 411 else if ( s state== PA_STREAM_FAILED412 || s state== PA_STREAM_TERMINATED)460 else if ( streamSt == PA_STREAM_FAILED 461 || streamSt == PA_STREAM_TERMINATED) 413 462 { 414 LogRel(("PulseAudio: Failed to initialize stream \"%s\" (state %ld)\n", 415 pszName, sstate)); 463 LogRel(("PulseAudio: Failed to initialize stream \"%s\" (state %ld)\n", pszName, streamSt)); 416 464 rc = VERR_AUDIO_BACKEND_INIT_FAILED; 417 465 break; … … 440 488 pa_stream_disconnect(pStream); 441 489 442 pa_threaded_mainloop_unlock( g_pMainLoop);490 pa_threaded_mainloop_unlock(pThis->pMainLoop); 443 491 444 492 if (RT_FAILURE(rc)) … … 456 504 static DECLCALLBACK(int) drvHostPulseAudioInit(PPDMIHOSTAUDIO pInterface) 457 505 { 458 NOREF(pInterface); 506 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 507 508 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 459 509 460 510 LogFlowFuncEnter(); … … 467 517 } 468 518 519 pThis->fLoopWait = false; 520 pThis->pMainLoop = NULL; 521 469 522 bool fLocked = false; 470 523 471 524 do 472 525 { 473 if (!( g_pMainLoop = pa_threaded_mainloop_new()))526 if (!(pThis->pMainLoop = pa_threaded_mainloop_new())) 474 527 { 475 528 LogRel(("PulseAudio: Failed to allocate main loop: %s\n", 476 pa_strerror(pa_context_errno( g_pContext))));529 pa_strerror(pa_context_errno(pThis->pContext)))); 477 530 rc = VERR_NO_MEMORY; 478 531 break; 479 532 } 480 533 481 if (!( g_pContext = pa_context_new(pa_threaded_mainloop_get_api(g_pMainLoop), "VirtualBox")))534 if (!(pThis->pContext = pa_context_new(pa_threaded_mainloop_get_api(pThis->pMainLoop), "VirtualBox"))) 482 535 { 483 536 LogRel(("PulseAudio: Failed to allocate context: %s\n", 484 pa_strerror(pa_context_errno( g_pContext))));537 pa_strerror(pa_context_errno(pThis->pContext)))); 485 538 rc = VERR_NO_MEMORY; 486 539 break; 487 540 } 488 541 489 if (pa_threaded_mainloop_start( g_pMainLoop) < 0)542 if (pa_threaded_mainloop_start(pThis->pMainLoop) < 0) 490 543 { 491 544 LogRel(("PulseAudio: Failed to start threaded mainloop: %s\n", 492 pa_strerror(pa_context_errno( g_pContext))));545 pa_strerror(pa_context_errno(pThis->pContext)))); 493 546 rc = VERR_AUDIO_BACKEND_INIT_FAILED; 494 547 break; 495 548 } 496 549 497 g_fAbortMainLoop = false; 498 pa_context_set_state_callback(g_pContext, drvHostPulseAudioCbCtxState, NULL); 499 pa_threaded_mainloop_lock(g_pMainLoop); 550 /* Install a global callback to known if something happens to our acquired context. */ 551 pa_context_set_state_callback(pThis->pContext, paContextCbStateChanged, pThis /* pvUserData */); 552 553 pa_threaded_mainloop_lock(pThis->pMainLoop); 500 554 fLocked = true; 501 555 502 if (pa_context_connect( g_pContext, NULL /* pszServer */,556 if (pa_context_connect(pThis->pContext, NULL /* pszServer */, 503 557 PA_CONTEXT_NOFLAGS, NULL) < 0) 504 558 { 505 559 LogRel(("PulseAudio: Failed to connect to server: %s\n", 506 pa_strerror(pa_context_errno( g_pContext))));560 pa_strerror(pa_context_errno(pThis->pContext)))); 507 561 rc = VERR_AUDIO_BACKEND_INIT_FAILED; 508 562 break; 509 563 } 510 564 511 /* Wait until the g_pContext is ready*/565 /* Wait until the pThis->pContext is ready. */ 512 566 for (;;) 513 567 { 514 if (! g_fAbortMainLoop)515 pa_threaded_mainloop_wait( g_pMainLoop);516 g_fAbortMainLoop= false;517 518 pa_context_state_t cstate = pa_context_get_state( g_pContext);568 if (!pThis->fLoopWait) 569 pa_threaded_mainloop_wait(pThis->pMainLoop); 570 pThis->fLoopWait = false; 571 572 pa_context_state_t cstate = pa_context_get_state(pThis->pContext); 519 573 if (cstate == PA_CONTEXT_READY) 520 574 break; … … 531 585 532 586 if (fLocked) 533 pa_threaded_mainloop_unlock( g_pMainLoop);587 pa_threaded_mainloop_unlock(pThis->pMainLoop); 534 588 535 589 if (RT_FAILURE(rc)) 536 590 { 537 if ( g_pMainLoop)538 pa_threaded_mainloop_stop( g_pMainLoop);539 540 if ( g_pContext)541 { 542 pa_context_disconnect( g_pContext);543 pa_context_unref( g_pContext);544 g_pContext = NULL;545 } 546 547 if ( g_pMainLoop)548 { 549 pa_threaded_mainloop_free( g_pMainLoop);550 g_pMainLoop = NULL;591 if (pThis->pMainLoop) 592 pa_threaded_mainloop_stop(pThis->pMainLoop); 593 594 if (pThis->pContext) 595 { 596 pa_context_disconnect(pThis->pContext); 597 pa_context_unref(pThis->pContext); 598 pThis->pContext = NULL; 599 } 600 601 if (pThis->pMainLoop) 602 { 603 pa_threaded_mainloop_free(pThis->pMainLoop); 604 pThis->pMainLoop = NULL; 551 605 } 552 606 } … … 560 614 uint32_t *pcSamples) 561 615 { 562 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);616 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 563 617 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 564 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);618 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 565 619 /* pcSamples is optional. */ 566 620 567 PDRVHOSTPULSEAUDIO p Drv= PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);568 PPULSEAUDIOSTREAM pThisStrmOut= (PPULSEAUDIOSTREAM)pHstStrmOut;621 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 622 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut; 569 623 570 624 LogFlowFuncEnter(); 571 625 572 p ThisStrmOut->pDrainOp = NULL;573 574 p ThisStrmOut->SampleSpec.format = drvHostPulseAudioFmtToPulse(pCfg->enmFormat);575 p ThisStrmOut->SampleSpec.rate = pCfg->uHz;576 p ThisStrmOut->SampleSpec.channels = pCfg->cChannels;626 pStrm->pDrainOp = NULL; 627 628 pStrm->SampleSpec.format = paFmtToPulse(pCfg->enmFormat); 629 pStrm->SampleSpec.rate = pCfg->uHz; 630 pStrm->SampleSpec.channels = pCfg->cChannels; 577 631 578 632 /* Note that setting maxlength to -1 does not work on PulseAudio servers 579 633 * older than 0.9.10. So use the suggested value of 3/2 of tlength */ 580 p ThisStrmOut->BufAttr.tlength = (pa_bytes_per_second(&pThisStrmOut->SampleSpec)634 pStrm->BufAttr.tlength = (pa_bytes_per_second(&pStrm->SampleSpec) 581 635 * s_pulseCfg.buffer_msecs_out) / 1000; 582 p ThisStrmOut->BufAttr.maxlength = (pThisStrmOut->BufAttr.tlength * 3) / 2;583 p ThisStrmOut->BufAttr.prebuf = -1; /* Same as tlength */584 p ThisStrmOut->BufAttr.minreq = -1; /* Pulse should set something sensible for minreq on it's own */636 pStrm->BufAttr.maxlength = (pStrm->BufAttr.tlength * 3) / 2; 637 pStrm->BufAttr.prebuf = -1; /* Same as tlength */ 638 pStrm->BufAttr.minreq = -1; /* Pulse should set something sensible for minreq on it's own */ 585 639 586 640 /* Note that the struct BufAttr is updated to the obtained values after this call! */ 587 641 char achName[64]; 588 RTStrPrintf(achName, sizeof(achName), "%.32s (out)", p Drv->pszStreamName);589 int rc = drvHostPulseAudioOpen(false /* fIn */, achName, &pThisStrmOut->SampleSpec, &pThisStrmOut->BufAttr, 590 &pThisStrmOut->pStream);642 RTStrPrintf(achName, sizeof(achName), "%.32s (out)", pThis->pszStreamName); 643 644 int rc = paStreamOpen(pThis, false /* fIn */, achName, &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->pStream); 591 645 if (RT_FAILURE(rc)) 592 646 return rc; 593 647 594 648 PDMAUDIOSTREAMCFG streamCfg; 595 rc = drvHostPulseAudioPulseToFmt(pThisStrmOut->SampleSpec.format,596 649 rc = paPulseToFmt(pStrm->SampleSpec.format, 650 &streamCfg.enmFormat, &streamCfg.enmEndianness); 597 651 if (RT_FAILURE(rc)) 598 652 { 599 LogRel(("PulseAudio: Cannot find audio output format %ld\n", p ThisStrmOut->SampleSpec.format));653 LogRel(("PulseAudio: Cannot find audio output format %ld\n", pStrm->SampleSpec.format)); 600 654 return rc; 601 655 } 602 656 603 streamCfg.uHz = p ThisStrmOut->SampleSpec.rate;604 streamCfg.cChannels = p ThisStrmOut->SampleSpec.channels;657 streamCfg.uHz = pStrm->SampleSpec.rate; 658 streamCfg.cChannels = pStrm->SampleSpec.channels; 605 659 606 660 rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmOut->Props); 607 661 if (RT_SUCCESS(rc)) 608 662 { 609 uint32_t cbBuf = RT_MIN(p ThisStrmOut->BufAttr.tlength * 2,610 p ThisStrmOut->BufAttr.maxlength); /** @todo Make this configurable! */663 uint32_t cbBuf = RT_MIN(pStrm->BufAttr.tlength * 2, 664 pStrm->BufAttr.maxlength); /** @todo Make this configurable! */ 611 665 if (cbBuf) 612 666 { 613 p ThisStrmOut->pvPCMBuf = RTMemAllocZ(cbBuf);614 if (p ThisStrmOut->pvPCMBuf)667 pStrm->pvPCMBuf = RTMemAllocZ(cbBuf); 668 if (pStrm->pvPCMBuf) 615 669 { 616 p ThisStrmOut->cbPCMBuf = cbBuf;670 pStrm->cbPCMBuf = cbBuf; 617 671 618 672 uint32_t cSamples = cbBuf >> pHstStrmOut->Props.cShift; … … 621 675 622 676 /* Save pointer to driver instance. */ 623 p ThisStrmOut->pDrv = pDrv;677 pStrm->pDrv = pThis; 624 678 625 679 LogFunc(("cbBuf=%RU32, cSamples=%RU32\n", cbBuf, cSamples)); … … 653 707 /* pcSamples is optional. */ 654 708 655 PDRVHOSTPULSEAUDIO p Drv= PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);656 PPULSEAUDIOSTREAM pThisStrmIn= (PPULSEAUDIOSTREAM)pHstStrmIn;709 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 710 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn; 657 711 658 712 LogFunc(("enmRecSrc=%ld\n", enmRecSource)); 659 713 660 p ThisStrmIn->SampleSpec.format = drvHostPulseAudioFmtToPulse(pCfg->enmFormat);661 p ThisStrmIn->SampleSpec.rate = pCfg->uHz;662 p ThisStrmIn->SampleSpec.channels = pCfg->cChannels;714 pStrm->SampleSpec.format = paFmtToPulse(pCfg->enmFormat); 715 pStrm->SampleSpec.rate = pCfg->uHz; 716 pStrm->SampleSpec.channels = pCfg->cChannels; 663 717 664 718 /* XXX check these values */ 665 p ThisStrmIn->BufAttr.fragsize = (pa_bytes_per_second(&pThisStrmIn->SampleSpec)719 pStrm->BufAttr.fragsize = (pa_bytes_per_second(&pStrm->SampleSpec) 666 720 * s_pulseCfg.buffer_msecs_in) / 1000; 667 p ThisStrmIn->BufAttr.maxlength = (pThisStrmIn->BufAttr.fragsize * 3) / 2;721 pStrm->BufAttr.maxlength = (pStrm->BufAttr.fragsize * 3) / 2; 668 722 /* Note: Other members of pa_buffer_attr are ignored for record streams. */ 669 723 670 724 char achName[64]; 671 RTStrPrintf(achName, sizeof(achName), "%.32s (in)", pDrv->pszStreamName); 672 int rc = drvHostPulseAudioOpen(true /* fIn */, achName, &pThisStrmIn->SampleSpec, &pThisStrmIn->BufAttr, 673 &pThisStrmIn->pStream); 725 RTStrPrintf(achName, sizeof(achName), "%.32s (in)", pThis->pszStreamName); 726 727 int rc = paStreamOpen(pThis, true /* fIn */, achName, &pStrm->SampleSpec, &pStrm->BufAttr, 728 &pStrm->pStream); 674 729 if (RT_FAILURE(rc)) 675 730 return rc; 676 731 677 732 PDMAUDIOSTREAMCFG streamCfg; 678 rc = drvHostPulseAudioPulseToFmt(pThisStrmIn->SampleSpec.format, &streamCfg.enmFormat,679 733 rc = paPulseToFmt(pStrm->SampleSpec.format, &streamCfg.enmFormat, 734 &streamCfg.enmEndianness); 680 735 if (RT_FAILURE(rc)) 681 736 { 682 LogRel(("PulseAudio: Cannot find audio capture format %ld\n", p ThisStrmIn->SampleSpec.format));737 LogRel(("PulseAudio: Cannot find audio capture format %ld\n", pStrm->SampleSpec.format)); 683 738 return rc; 684 739 } 685 740 686 streamCfg.uHz = p ThisStrmIn->SampleSpec.rate;687 streamCfg.cChannels = p ThisStrmIn->SampleSpec.channels;741 streamCfg.uHz = pStrm->SampleSpec.rate; 742 streamCfg.cChannels = pStrm->SampleSpec.channels; 688 743 689 744 rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmIn->Props); 690 745 if (RT_SUCCESS(rc)) 691 746 { 692 uint32_t cSamples = RT_MIN(p ThisStrmIn->BufAttr.fragsize * 10, pThisStrmIn->BufAttr.maxlength)747 uint32_t cSamples = RT_MIN(pStrm->BufAttr.fragsize * 10, pStrm->BufAttr.maxlength) 693 748 >> pHstStrmIn->Props.cShift; 694 749 LogFunc(("cShift=%RU8, cSamples=%RU32\n", pHstStrmIn->Props.cShift, cSamples)); … … 698 753 699 754 /* Save pointer to driver instance. */ 700 p ThisStrmIn->pDrv = pDrv;701 702 p ThisStrmIn->pu8PeekBuf = NULL;755 pStrm->pDrv = pThis; 756 757 pStrm->pu8PeekBuf = NULL; 703 758 } 704 759 … … 710 765 uint32_t *pcSamplesCaptured) 711 766 { 712 NOREF(pInterface);767 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 713 768 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 714 769 /* pcSamplesPlayed is optional. */ 715 770 716 PPULSEAUDIOSTREAM pThisStrmIn = (PPULSEAUDIOSTREAM)pHstStrmIn; 771 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 772 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn; 717 773 718 774 /* We should only call pa_stream_readable_size() once and trust the first value. */ 719 pa_threaded_mainloop_lock( g_pMainLoop);720 size_t cbAvail = pa_stream_readable_size(p ThisStrmIn->pStream);721 pa_threaded_mainloop_unlock( g_pMainLoop);775 pa_threaded_mainloop_lock(pThis->pMainLoop); 776 size_t cbAvail = pa_stream_readable_size(pStrm->pStream); 777 pa_threaded_mainloop_unlock(pThis->pMainLoop); 722 778 723 779 if (cbAvail == (size_t)-1) 724 return drvHostPulseAudioError(pThisStrmIn->pDrv, "Failed to determine input data size");780 return paError(pStrm->pDrv, "Failed to determine input data size"); 725 781 726 782 /* If the buffer was not dropped last call, add what remains. */ 727 if (p ThisStrmIn->pu8PeekBuf)728 { 729 Assert(p ThisStrmIn->cbPeekBuf >= pThisStrmIn->offPeekBuf);730 cbAvail += (p ThisStrmIn->cbPeekBuf - pThisStrmIn->offPeekBuf);783 if (pStrm->pu8PeekBuf) 784 { 785 Assert(pStrm->cbPeekBuf >= pStrm->offPeekBuf); 786 cbAvail += (pStrm->cbPeekBuf - pStrm->offPeekBuf); 731 787 } 732 788 … … 739 795 740 796 int rc = VINF_SUCCESS; 797 741 798 size_t cbToRead = RT_MIN(cbAvail, AudioMixBufFreeBytes(&pHstStrmIn->MixBuf)); 742 799 743 800 LogFlowFunc(("cbToRead=%zu, cbAvail=%zu, offPeekBuf=%zu, cbPeekBuf=%zu\n", 744 cbToRead, cbAvail, p ThisStrmIn->offPeekBuf, pThisStrmIn->cbPeekBuf));745 746 size_t offWrite= 0;801 cbToRead, cbAvail, pStrm->offPeekBuf, pStrm->cbPeekBuf)); 802 803 size_t offWrite = 0; 747 804 uint32_t cWrittenTotal = 0; 748 805 … … 750 807 { 751 808 /* If there is no data, do another peek. */ 752 if (!p ThisStrmIn->pu8PeekBuf)753 { 754 pa_threaded_mainloop_lock( g_pMainLoop);755 pa_stream_peek(p ThisStrmIn->pStream,756 (const void**)&p ThisStrmIn->pu8PeekBuf, &pThisStrmIn->cbPeekBuf);757 pa_threaded_mainloop_unlock( g_pMainLoop);758 759 p ThisStrmIn->offPeekBuf = 0;809 if (!pStrm->pu8PeekBuf) 810 { 811 pa_threaded_mainloop_lock(pThis->pMainLoop); 812 pa_stream_peek(pStrm->pStream, 813 (const void**)&pStrm->pu8PeekBuf, &pStrm->cbPeekBuf); 814 pa_threaded_mainloop_unlock(pThis->pMainLoop); 815 816 pStrm->offPeekBuf = 0; 760 817 761 818 /* No data anymore? 762 819 * Note: If there's a data hole (cbPeekBuf then contains the length of the hole) 763 820 * we need to drop the stream lateron. */ 764 if ( !p ThisStrmIn->pu8PeekBuf765 && !p ThisStrmIn->cbPeekBuf)821 if ( !pStrm->pu8PeekBuf 822 && !pStrm->cbPeekBuf) 766 823 { 767 824 break; … … 769 826 } 770 827 771 Assert(p ThisStrmIn->cbPeekBuf >= pThisStrmIn->offPeekBuf);772 size_t cbToWrite = RT_MIN(p ThisStrmIn->cbPeekBuf - pThisStrmIn->offPeekBuf, cbToRead);828 Assert(pStrm->cbPeekBuf >= pStrm->offPeekBuf); 829 size_t cbToWrite = RT_MIN(pStrm->cbPeekBuf - pStrm->offPeekBuf, cbToRead); 773 830 774 831 LogFlowFunc(("cbToRead=%zu, cbToWrite=%zu, offPeekBuf=%zu, cbPeekBuf=%zu, pu8PeekBuf=%p\n", 775 832 cbToRead, cbToWrite, 776 p ThisStrmIn->offPeekBuf, pThisStrmIn->cbPeekBuf, pThisStrmIn->pu8PeekBuf));833 pStrm->offPeekBuf, pStrm->cbPeekBuf, pStrm->pu8PeekBuf)); 777 834 778 835 if (cbToWrite) … … 780 837 uint32_t cWritten; 781 838 rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf, 782 p ThisStrmIn->pu8PeekBuf + pThisStrmIn->offPeekBuf,839 pStrm->pu8PeekBuf + pStrm->offPeekBuf, 783 840 cbToWrite, &cWritten); 784 841 if (RT_FAILURE(rc)) … … 790 847 cbToRead -= cbWritten; 791 848 cWrittenTotal += cWritten; 792 p ThisStrmIn->offPeekBuf += cbWritten;849 pStrm->offPeekBuf += cbWritten; 793 850 } 794 851 … … 796 853 !cbToWrite 797 854 /* Was there a hole in the peeking buffer? Drop it. */ 798 || !p ThisStrmIn->pu8PeekBuf855 || !pStrm->pu8PeekBuf 799 856 /* If the buffer is done, drop it. */ 800 || p ThisStrmIn->offPeekBuf == pThisStrmIn->cbPeekBuf)801 { 802 pa_threaded_mainloop_lock( g_pMainLoop);803 pa_stream_drop(p ThisStrmIn->pStream);804 pa_threaded_mainloop_unlock( g_pMainLoop);805 806 p ThisStrmIn->pu8PeekBuf = NULL;857 || pStrm->offPeekBuf == pStrm->cbPeekBuf) 858 { 859 pa_threaded_mainloop_lock(pThis->pMainLoop); 860 pa_stream_drop(pStrm->pStream); 861 pa_threaded_mainloop_unlock(pThis->pMainLoop); 862 863 pStrm->pu8PeekBuf = NULL; 807 864 } 808 865 } … … 829 886 uint32_t *pcSamplesPlayed) 830 887 { 831 NOREF(pInterface);888 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 832 889 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 833 890 /* pcSamplesPlayed is optional. */ 834 891 835 PPULSEAUDIOSTREAM pThisStrmOut = (PPULSEAUDIOSTREAM)pHstStrmOut; 892 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 893 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut; 836 894 837 895 int rc = VINF_SUCCESS; … … 848 906 } 849 907 850 pa_threaded_mainloop_lock( g_pMainLoop);908 pa_threaded_mainloop_lock(pThis->pMainLoop); 851 909 852 910 do 853 911 { 854 size_t cbWriteable = pa_stream_writable_size(p ThisStrmOut->pStream);912 size_t cbWriteable = pa_stream_writable_size(pStrm->pStream); 855 913 if (cbWriteable == (size_t)-1) 856 914 { 857 rc = drvHostPulseAudioError(pThisStrmOut->pDrv, "Failed to determine output data size");915 rc = paError(pStrm->pDrv, "Failed to determine output data size"); 858 916 break; 859 917 } … … 868 926 while (cbToRead) 869 927 { 870 rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, p ThisStrmOut->pvPCMBuf,871 RT_MIN(cbToRead, p ThisStrmOut->cbPCMBuf), &cRead);928 rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pStrm->pvPCMBuf, 929 RT_MIN(cbToRead, pStrm->cbPCMBuf), &cRead); 872 930 if ( !cRead 873 931 || RT_FAILURE(rc)) … … 877 935 878 936 cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead); 879 if (pa_stream_write(p ThisStrmOut->pStream, pThisStrmOut->pvPCMBuf, cbRead, NULL /* Cleanup callback */,937 if (pa_stream_write(pStrm->pStream, pStrm->pvPCMBuf, cbRead, NULL /* Cleanup callback */, 880 938 0, PA_SEEK_RELATIVE) < 0) 881 939 { 882 rc = drvHostPulseAudioError(pThisStrmOut->pDrv, "Failed to write to output stream");940 rc = paError(pStrm->pDrv, "Failed to write to output stream"); 883 941 break; 884 942 } … … 894 952 } while (0); 895 953 896 pa_threaded_mainloop_unlock( g_pMainLoop);954 pa_threaded_mainloop_unlock(pThis->pMainLoop); 897 955 898 956 if (RT_SUCCESS(rc)) … … 913 971 914 972 /** @todo Implement va handling. */ 915 static int drvHostPulseAudioError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg)973 static int paError(PDRVHOSTPULSEAUDIO pThis, const char *szMsg) 916 974 { 917 975 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 920 978 if (pThis->cLogErrors++ < VBOX_PULSEAUDIO_MAX_LOG_REL_ERRORS) 921 979 { 922 int rc2 = pa_context_errno( g_pContext);980 int rc2 = pa_context_errno(pThis->pContext); 923 981 LogRel(("PulseAudio: %s: %s\n", szMsg, pa_strerror(rc2))); 924 982 } … … 928 986 } 929 987 988 static DECLCALLBACK(void) paEnumSinkCb(pa_context *pCtx, const pa_sink_info *pInfo, int eol, void *pvUserData) 989 { 990 if (eol != 0) 991 return; 992 993 AssertPtrReturnVoid(pCtx); 994 AssertPtrReturnVoid(pInfo); 995 996 PPULSEAUDIOENUMCBCTX pCbCtx = (PPULSEAUDIOENUMCBCTX)pvUserData; 997 AssertPtrReturnVoid(pCbCtx); 998 AssertPtrReturnVoid(pCbCtx->pDrv); 999 1000 LogRel2(("PulseAudio: Using output sink '%s'\n", pInfo->name)); 1001 1002 /** @todo Store sinks + channel mapping in callback context as soon as we have surround support. */ 1003 pCbCtx->cDevOut++; 1004 1005 pa_threaded_mainloop_signal(pCbCtx->pDrv->pMainLoop, 0); 1006 } 1007 1008 static DECLCALLBACK(void) paEnumSourceCb(pa_context *pCtx, const pa_source_info *pInfo, int eol, void *pvUserData) 1009 { 1010 if (eol != 0) 1011 return; 1012 1013 AssertPtrReturnVoid(pCtx); 1014 AssertPtrReturnVoid(pInfo); 1015 1016 PPULSEAUDIOENUMCBCTX pCbCtx = (PPULSEAUDIOENUMCBCTX)pvUserData; 1017 AssertPtrReturnVoid(pCbCtx); 1018 AssertPtrReturnVoid(pCbCtx->pDrv); 1019 1020 LogRel2(("PulseAudio: Using input source '%s'\n", pInfo->name)); 1021 1022 /** @todo Store sources + channel mapping in callback context as soon as we have surround support. */ 1023 pCbCtx->cDevIn++; 1024 1025 pa_threaded_mainloop_signal(pCbCtx->pDrv->pMainLoop, 0); 1026 } 1027 1028 static DECLCALLBACK(void) paEnumServerCb(pa_context *pCtx, const pa_server_info *pInfo, void *pvUserData) 1029 { 1030 AssertPtrReturnVoid(pCtx); 1031 AssertPtrReturnVoid(pInfo); 1032 1033 PPULSEAUDIOENUMCBCTX pCbCtx = (PPULSEAUDIOENUMCBCTX)pvUserData; 1034 AssertPtrReturnVoid(pCbCtx); 1035 1036 PDRVHOSTPULSEAUDIO pThis = pCbCtx->pDrv; 1037 AssertPtrReturnVoid(pThis); 1038 1039 if (pInfo->default_sink_name) 1040 { 1041 Assert(RTStrIsValidEncoding(pInfo->default_sink_name)); 1042 pCbCtx->pszDefaultSink = RTStrDup(pInfo->default_sink_name); 1043 } 1044 1045 if (pInfo->default_sink_name) 1046 { 1047 Assert(RTStrIsValidEncoding(pInfo->default_source_name)); 1048 pCbCtx->pszDefaultSource = RTStrDup(pInfo->default_source_name); 1049 } 1050 1051 pa_threaded_mainloop_signal(pThis->pMainLoop, 0); 1052 } 1053 1054 static int paEnumerate(PDRVHOSTPULSEAUDIO pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum) 1055 { 1056 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1057 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1058 1059 PDMAUDIOBACKENDCFG Cfg; 1060 RT_ZERO(Cfg); 1061 1062 Cfg.cbStreamOut = sizeof(PULSEAUDIOSTREAM); 1063 Cfg.cbStreamIn = sizeof(PULSEAUDIOSTREAM); 1064 Cfg.cMaxStreamsOut = UINT32_MAX; 1065 Cfg.cMaxStreamsIn = UINT32_MAX; 1066 1067 PULSEAUDIOENUMCBCTX cbCtx; 1068 RT_ZERO(cbCtx); 1069 1070 cbCtx.pDrv = pThis; 1071 cbCtx.fFlags = fEnum; 1072 1073 bool fLog = (fEnum & PULSEAUDIOENUMCBFLAGS_LOG); 1074 1075 int rc = paWaitFor(pThis, pa_context_get_server_info(pThis->pContext, paEnumServerCb, &cbCtx)); 1076 if (RT_SUCCESS(rc)) 1077 { 1078 if (cbCtx.pszDefaultSink) 1079 { 1080 if (fLog) 1081 LogRel2(("PulseAudio: Default output sink is '%s'\n", cbCtx.pszDefaultSink)); 1082 1083 rc = paWaitFor(pThis, pa_context_get_sink_info_by_name(pThis->pContext, cbCtx.pszDefaultSink, 1084 paEnumSinkCb, &cbCtx)); 1085 if ( RT_FAILURE(rc) 1086 && fLog) 1087 { 1088 LogRel(("PulseAudio: Error enumerating properties for default output sink '%s'\n", cbCtx.pszDefaultSink)); 1089 } 1090 } 1091 else if (fLog) 1092 LogRel2(("PulseAudio: No default output sink found\n")); 1093 1094 if (RT_SUCCESS(rc)) 1095 { 1096 if (cbCtx.pszDefaultSource) 1097 { 1098 if (fLog) 1099 LogRel2(("PulseAudio: Default input source is '%s'\n", cbCtx.pszDefaultSource)); 1100 1101 rc = paWaitFor(pThis, pa_context_get_source_info_by_name(pThis->pContext, cbCtx.pszDefaultSource, 1102 paEnumSourceCb, &cbCtx)); 1103 if ( RT_FAILURE(rc) 1104 && fLog) 1105 { 1106 LogRel(("PulseAudio: Error enumerating properties for default input source '%s'\n", cbCtx.pszDefaultSource)); 1107 } 1108 } 1109 else if (fLog) 1110 LogRel2(("PulseAudio: No default input source found\n")); 1111 } 1112 1113 if (RT_SUCCESS(rc)) 1114 { 1115 Cfg.cSinks = cbCtx.cDevOut; 1116 Cfg.cSources = cbCtx.cDevIn; 1117 1118 if (fLog) 1119 { 1120 LogRel2(("PulseAudio: Found %RU8 host playback device(s)\n", cbCtx.cDevOut)); 1121 LogRel2(("PulseAudio: Found %RU8 host capturing device(s)\n", cbCtx.cDevIn)); 1122 } 1123 1124 if (pCfg) 1125 memcpy(pCfg, &Cfg, sizeof(PDMAUDIOBACKENDCFG)); 1126 } 1127 1128 if (cbCtx.pszDefaultSink) 1129 { 1130 RTStrFree(cbCtx.pszDefaultSink); 1131 cbCtx.pszDefaultSink = NULL; 1132 } 1133 1134 if (cbCtx.pszDefaultSource) 1135 { 1136 RTStrFree(cbCtx.pszDefaultSource); 1137 cbCtx.pszDefaultSource = NULL; 1138 } 1139 } 1140 else if (fLog) 1141 LogRel(("PulseAudio: Error enumerating PulseAudio server properties\n")); 1142 1143 LogFlowFuncLeaveRC(rc); 1144 return rc; 1145 } 1146 930 1147 static DECLCALLBACK(int) drvHostPulseAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn) 931 1148 { 932 NOREF(pInterface);1149 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 933 1150 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 934 1151 1152 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1153 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn; 1154 935 1155 LogFlowFuncEnter(); 936 1156 937 PPULSEAUDIOSTREAM pThisStrmIn = (PPULSEAUDIOSTREAM)pHstStrmIn; 938 if (pThisStrmIn->pStream) 939 { 940 pa_threaded_mainloop_lock(g_pMainLoop); 941 pa_stream_disconnect(pThisStrmIn->pStream); 942 pa_stream_unref(pThisStrmIn->pStream); 943 pa_threaded_mainloop_unlock(g_pMainLoop); 944 945 pThisStrmIn->pStream = NULL; 1157 if (pStrm->pStream) 1158 { 1159 pa_threaded_mainloop_lock(pThis->pMainLoop); 1160 pa_stream_disconnect(pStrm->pStream); 1161 pa_stream_unref(pStrm->pStream); 1162 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1163 1164 pStrm->pStream = NULL; 946 1165 } 947 1166 … … 951 1170 static DECLCALLBACK(int) drvHostPulseAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut) 952 1171 { 953 NOREF(pInterface);1172 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 954 1173 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 955 1174 1175 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1176 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut; 1177 956 1178 LogFlowFuncEnter(); 957 1179 958 PPULSEAUDIOSTREAM pThisStrmOut = (PPULSEAUDIOSTREAM)pHstStrmOut; 959 if (pThisStrmOut->pStream) 960 { 961 pa_threaded_mainloop_lock(g_pMainLoop); 962 pa_stream_disconnect(pThisStrmOut->pStream); 963 pa_stream_unref(pThisStrmOut->pStream); 964 pa_threaded_mainloop_unlock(g_pMainLoop); 965 966 pThisStrmOut->pStream = NULL; 967 } 968 969 if (pThisStrmOut->pvPCMBuf) 970 { 971 RTMemFree(pThisStrmOut->pvPCMBuf); 972 pThisStrmOut->pvPCMBuf = NULL; 973 974 pThisStrmOut->cbPCMBuf = 0; 1180 if (pStrm->pStream) 1181 { 1182 pa_threaded_mainloop_lock(pThis->pMainLoop); 1183 pa_stream_disconnect(pStrm->pStream); 1184 pa_stream_unref(pStrm->pStream); 1185 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1186 1187 pStrm->pStream = NULL; 1188 } 1189 1190 if (pStrm->pvPCMBuf) 1191 { 1192 RTMemFree(pStrm->pvPCMBuf); 1193 pStrm->pvPCMBuf = NULL; 1194 pStrm->cbPCMBuf = 0; 975 1195 } 976 1196 … … 981 1201 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd) 982 1202 { 983 NOREF(pInterface);1203 AssertPtrReturn(pInterface , VERR_INVALID_POINTER); 984 1204 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 985 1205 986 PPULSEAUDIOSTREAM pThisStrmOut = (PPULSEAUDIOSTREAM)pHstStrmOut; 1206 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1207 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut; 1208 987 1209 int rc = VINF_SUCCESS; 988 1210 … … 994 1216 case PDMAUDIOSTREAMCMD_RESUME: 995 1217 { 996 pa_threaded_mainloop_lock( g_pMainLoop);997 998 if ( p ThisStrmOut->pDrainOp999 && pa_operation_get_state(p ThisStrmOut->pDrainOp) != PA_OPERATION_DONE)1218 pa_threaded_mainloop_lock(pThis->pMainLoop); 1219 1220 if ( pStrm->pDrainOp 1221 && pa_operation_get_state(pStrm->pDrainOp) != PA_OPERATION_DONE) 1000 1222 { 1001 pa_operation_cancel(p ThisStrmOut->pDrainOp);1002 pa_operation_unref(p ThisStrmOut->pDrainOp);1003 1004 p ThisStrmOut->pDrainOp = NULL;1223 pa_operation_cancel(pStrm->pDrainOp); 1224 pa_operation_unref(pStrm->pDrainOp); 1225 1226 pStrm->pDrainOp = NULL; 1005 1227 } 1006 1228 else 1007 1229 { 1008 /* This should return immediately. */ 1009 rc = drvHostPulseAudioWaitFor(pa_stream_cork(pThisStrmOut->pStream, 0, 1010 drvHostPulseAudioCbSuccess, pThisStrmOut), 1011 15 * 1000 /* 15s timeout */); 1230 rc = paWaitFor(pThis, pa_stream_cork(pStrm->pStream, 0, paStreamCbSuccess, pStrm)); 1012 1231 } 1013 1232 1014 pa_threaded_mainloop_unlock( g_pMainLoop);1233 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1015 1234 break; 1016 1235 } … … 1021 1240 /* Pause audio output (the Pause bit of the AC97 x_CR register is set). 1022 1241 * Note that we must return immediately from here! */ 1023 pa_threaded_mainloop_lock( g_pMainLoop);1024 if (!p ThisStrmOut->pDrainOp)1242 pa_threaded_mainloop_lock(pThis->pMainLoop); 1243 if (!pStrm->pDrainOp) 1025 1244 { 1026 /* This should return immediately. */ 1027 rc = drvHostPulseAudioWaitFor(pa_stream_trigger(pThisStrmOut->pStream, 1028 drvHostPulseAudioCbSuccess, pThisStrmOut), 1029 15 * 1000 /* 15s timeout */); 1245 rc = paWaitFor(pThis, pa_stream_trigger(pStrm->pStream, paStreamCbSuccess, pStrm)); 1030 1246 if (RT_LIKELY(RT_SUCCESS(rc))) 1031 pThisStrmOut->pDrainOp = pa_stream_drain(pThisStrmOut->pStream, 1032 drvHostPulseAudioCbStreamDrain, pThisStrmOut); 1247 pStrm->pDrainOp = pa_stream_drain(pStrm->pStream, paStreamCbDrain, pStrm); 1033 1248 } 1034 pa_threaded_mainloop_unlock( g_pMainLoop);1249 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1035 1250 break; 1036 1251 } … … 1049 1264 PDMAUDIOSTREAMCMD enmStreamCmd) 1050 1265 { 1051 NOREF(pInterface);1266 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1052 1267 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 1053 1268 1054 PPULSEAUDIOSTREAM pThisStrmIn = (PPULSEAUDIOSTREAM)pHstStrmIn; 1269 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1270 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn; 1271 1055 1272 int rc = VINF_SUCCESS; 1056 1273 … … 1062 1279 case PDMAUDIOSTREAMCMD_RESUME: 1063 1280 { 1064 pa_threaded_mainloop_lock(g_pMainLoop); 1065 /* This should return immediately. */ 1066 rc = drvHostPulseAudioWaitFor(pa_stream_cork(pThisStrmIn->pStream, 0 /* Play / resume */, 1067 drvHostPulseAudioCbSuccess, pThisStrmIn), 1068 15 * 1000 /* 15s timeout */); 1069 pa_threaded_mainloop_unlock(g_pMainLoop); 1281 pa_threaded_mainloop_lock(pThis->pMainLoop); 1282 rc = paWaitFor(pThis, pa_stream_cork(pStrm->pStream, 0 /* Play / resume */, paStreamCbSuccess, pStrm)); 1283 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1070 1284 break; 1071 1285 } … … 1074 1288 case PDMAUDIOSTREAMCMD_PAUSE: 1075 1289 { 1076 pa_threaded_mainloop_lock( g_pMainLoop);1077 if (p ThisStrmIn->pu8PeekBuf) /* Do we need to drop the peek buffer?*/1290 pa_threaded_mainloop_lock(pThis->pMainLoop); 1291 if (pStrm->pu8PeekBuf) /* Do we need to drop the peek buffer?*/ 1078 1292 { 1079 pa_stream_drop(p ThisStrmIn->pStream);1080 p ThisStrmIn->pu8PeekBuf = NULL;1293 pa_stream_drop(pStrm->pStream); 1294 pStrm->pu8PeekBuf = NULL; 1081 1295 } 1082 /* This should return immediately. */ 1083 rc = drvHostPulseAudioWaitFor(pa_stream_cork(pThisStrmIn->pStream, 1 /* Stop / pause */, 1084 drvHostPulseAudioCbSuccess, pThisStrmIn), 1085 15 * 1000 /* 15s timeout */); 1086 pa_threaded_mainloop_unlock(g_pMainLoop); 1296 1297 rc = paWaitFor(pThis, pa_stream_cork(pStrm->pStream, 1 /* Stop / pause */, paStreamCbSuccess, pStrm)); 1298 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1087 1299 break; 1088 1300 } … … 1099 1311 static DECLCALLBACK(int) drvHostPulseAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 1100 1312 { 1101 NOREF(pInterface); 1102 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1103 1104 pCfg->cbStreamOut = sizeof(PULSEAUDIOSTREAM); 1105 pCfg->cbStreamIn = sizeof(PULSEAUDIOSTREAM); 1106 pCfg->cMaxHstStrmsOut = UINT32_MAX; 1107 pCfg->cMaxHstStrmsIn = UINT32_MAX; 1108 1109 return VINF_SUCCESS; 1313 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1314 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1315 1316 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1317 1318 return paEnumerate(pThis, pCfg, PULSEAUDIOENUMCBFLAGS_LOG /* fEnum */); 1110 1319 } 1111 1320 1112 1321 static DECLCALLBACK(void) drvHostPulseAudioShutdown(PPDMIHOSTAUDIO pInterface) 1113 1322 { 1114 NOREF(pInterface); 1323 AssertPtrReturnVoid(pInterface); 1324 1325 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1115 1326 1116 1327 LogFlowFuncEnter(); 1117 1328 1118 if ( g_pMainLoop)1119 pa_threaded_mainloop_stop( g_pMainLoop);1120 1121 if ( g_pContext)1122 { 1123 pa_context_disconnect( g_pContext);1124 pa_context_unref( g_pContext);1125 g_pContext = NULL;1126 } 1127 1128 if ( g_pMainLoop)1129 { 1130 pa_threaded_mainloop_free( g_pMainLoop);1131 g_pMainLoop = NULL;1329 if (pThis->pMainLoop) 1330 pa_threaded_mainloop_stop(pThis->pMainLoop); 1331 1332 if (pThis->pContext) 1333 { 1334 pa_context_disconnect(pThis->pContext); 1335 pa_context_unref(pThis->pContext); 1336 pThis->pContext = NULL; 1337 } 1338 1339 if (pThis->pMainLoop) 1340 { 1341 pa_threaded_mainloop_free(pThis->pMainLoop); 1342 pThis->pMainLoop = NULL; 1132 1343 } 1133 1344 -
trunk/src/VBox/Devices/Audio/alsa_mangling.h
r56292 r59987 6 6 7 7 /* 8 * Copyright (C) 2013-201 5Oracle Corporation8 * Copyright (C) 2013-2016 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 22 22 #define ALSA_MANGLER(symbol) VBox_##symbol 23 24 #define snd_device_name_hint ALSA_MANGLER(snd_device_name_hint) 25 #define snd_device_name_get_hint ALSA_MANGLER(snd_device_name_get_hint) 26 #define snd_device_name_free_hint ALSA_MANGLER(snd_device_name_free_hint) 23 27 24 28 #define snd_pcm_hw_params_any ALSA_MANGLER(snd_pcm_hw_params_any) -
trunk/src/VBox/Devices/Audio/alsa_stubs.c
r56648 r59987 5 5 6 6 /* 7 * Copyright (C) 2006-201 5Oracle Corporation7 * Copyright (C) 2006-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 35 35 return pfn_ ## function shortsig; \ 36 36 } 37 38 PROXY_STUB(snd_device_name_hint, int, 39 (int card, const char *iface, void ***hints), 40 (card, iface, hints)) 41 PROXY_STUB(snd_device_name_free_hint, int, 42 (void ***hints), 43 (hints)) 44 PROXY_STUB(snd_device_name_get_hint, char *, 45 (const void *hint, const char *id), 46 (hint, id)) 37 47 38 48 PROXY_STUB(snd_pcm_hw_params_any, int, … … 118 128 static SHARED_FUNC SharedFuncs[] = 119 129 { 130 ELEMENT(snd_device_name_hint), 131 ELEMENT(snd_device_name_get_hint), 132 ELEMENT(snd_device_name_free_hint), 133 120 134 ELEMENT(snd_pcm_hw_params_any), 121 135 ELEMENT(snd_pcm_close), -
trunk/src/VBox/Devices/Audio/pulse_mangling.h
r56292 r59987 6 6 7 7 /* 8 * Copyright (C) 2013-201 5Oracle Corporation8 * Copyright (C) 2013-2016 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 42 42 #define pa_context_connect PULSE_MANGLER(pa_context_connect) 43 43 #define pa_context_disconnect PULSE_MANGLER(pa_context_disconnect) 44 #define pa_context_get_server_info PULSE_MANGLER(pa_context_get_server_info) 45 #define pa_context_get_sink_info_by_name PULSE_MANGLER(pa_context_get_sink_info_by_name) 46 #define pa_context_get_source_info_by_name PULSE_MANGLER(pa_context_get_source_info_by_name) 44 47 #define pa_context_get_state PULSE_MANGLER(pa_context_get_state) 45 48 #define pa_context_unref PULSE_MANGLER(pa_context_unref) -
trunk/src/VBox/Devices/Audio/pulse_stubs.c
r56648 r59987 5 5 6 6 /* 7 * Copyright (C) 2006-201 5Oracle Corporation7 * Copyright (C) 2006-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 111 111 (p)) 112 112 PROXY_STUB (pa_context_connect, int, 113 (pa_context *c, const char *server, pa_context_flags_t flags, 114 const pa_spawn_api *api), 113 (pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api), 115 114 (c, server, flags, api)) 116 115 PROXY_STUB_VOID(pa_context_disconnect, 117 116 (pa_context *c), 118 117 (c)) 118 PROXY_STUB (pa_context_get_server_info, pa_operation*, 119 (pa_context *c, const char *name, pa_server_info_cb_t cb, void *userdata), 120 (c, name, cb, userdata)) 121 PROXY_STUB (pa_context_get_sink_info_by_name, pa_operation*, 122 (pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata), 123 (c, name, cb, userdata)) 124 PROXY_STUB (pa_context_get_source_info_by_name, pa_operation*, 125 (pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata), 126 (c, name, cb, userdata)) 119 127 PROXY_STUB (pa_context_get_state, pa_context_state_t, 120 128 (pa_context *c), … … 220 228 ELEMENT(pa_context_connect), 221 229 ELEMENT(pa_context_disconnect), 230 ELEMENT(pa_context_get_server_info), 231 ELEMENT(pa_context_get_sink_info_by_name), 232 ELEMENT(pa_context_get_source_info_by_name), 222 233 ELEMENT(pa_context_get_state), 223 234 ELEMENT(pa_context_unref), … … 285 296 return rc; 286 297 } 287
Note:
See TracChangeset
for help on using the changeset viewer.