Changeset 53442 in vbox for trunk/src/VBox/Main/src-client
- Timestamp:
- Dec 4, 2014 1:49:43 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 97155
- Location:
- trunk
- Files:
-
- 1 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
trunk/src/VBox
-
trunk/src/VBox/Main/src-client/AudioSnifferInterface.cpp
r51612 r53442 26 26 #include <VBox/vmm/cfgm.h> 27 27 #include <VBox/err.h> 28 29 #ifdef LOG_GROUP 30 #undef LOG_GROUP 31 #endif 32 #define LOG_GROUP LOG_GROUP_DEV_AUDIO 33 #include <VBox/log.h> 28 34 29 35 // -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r53407 r53442 414 414 , mpVmm2UserMethods(NULL) 415 415 , m_pVMMDev(NULL) 416 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER 416 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 417 , mAudioVRDE(NULL) 418 #else 417 419 , mAudioSniffer(NULL) 418 420 #endif … … 596 598 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 597 599 unconst(mAudioVRDE) = new AudioVRDE(this); 598 Assert ComRCReturnRC(rc);600 AssertReturn(mAudioVRDE, E_FAIL); 599 601 #else 600 602 unconst(mAudioSniffer) = new AudioSniffer(this); 601 603 AssertReturn(mAudioSniffer, E_FAIL); 602 604 #endif 603 604 605 FirmwareType_T enmFirmwareType; 605 606 mMachine->COMGETTER(FirmwareType)(&enmFirmwareType); … … 730 731 } 731 732 #endif 732 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER 733 734 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 735 if (mAudioVRDE) 736 { 737 delete mAudioVRDE; 738 unconst(mAudioVRDE) = NULL; 739 } 740 #else 733 741 if (mAudioSniffer) 734 742 { … … 1433 1441 if (fu32Intercepted & VRDE_CLIENT_INTERCEPT_AUDIO) 1434 1442 { 1443 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1444 if (mAudioVRDE) 1445 mAudioVRDE->onVRDEInputIntercept(false /* fIntercept */); 1446 #else 1435 1447 mcAudioRefs--; 1436 1448 1437 1449 if (mcAudioRefs <= 0) 1438 1450 { 1439 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER1440 1451 if (mAudioSniffer) 1441 1452 { 1442 1453 PPDMIAUDIOSNIFFERPORT port = mAudioSniffer->getAudioSnifferPort(); 1443 1454 if (port) 1444 {1445 1455 port->pfnSetup(port, false, false); 1446 }1447 1456 } 1457 } 1448 1458 #endif 1449 }1450 1459 } 1451 1460 … … 1480 1489 AutoCaller autoCaller(this); 1481 1490 AssertComRCReturnVoid(autoCaller.rc()); 1482 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER 1483 LogFlowFunc(("mAudioSniffer %p, u32ClientId %d.\n", 1484 mAudioSniffer, u32ClientId)); 1485 NOREF(u32ClientId); 1486 #endif 1487 1491 1492 LogFlowFunc(("u32ClientId=%RU32\n", u32ClientId)); 1493 1494 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1495 if (mAudioVRDE) 1496 mAudioVRDE->onVRDEInputIntercept(true /* fIntercept */); 1497 #else 1488 1498 ++mcAudioRefs; 1489 1499 1490 1500 if (mcAudioRefs == 1) 1491 1501 { 1492 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER1493 1502 if (mAudioSniffer) 1494 1503 { 1495 1504 PPDMIAUDIOSNIFFERPORT port = mAudioSniffer->getAudioSnifferPort(); 1496 1505 if (port) 1497 {1498 1506 port->pfnSetup(port, true, true); 1499 1500 1507 } 1508 } 1501 1509 #endif 1502 }1503 1510 1504 1511 LogFlowFuncLeave(); -
trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
r53407 r53442 2612 2612 InsertConfigInteger(pCfg, "Object", (uintptr_t)pAudioSniffer); 2613 2613 #endif 2614 2615 2614 /* 2616 * AC'97 ICH / SoundBlaster16 audio / Intel HD Audio 2615 * AC'97 ICH / SoundBlaster16 audio / Intel HD Audio. 2617 2616 */ 2618 2617 BOOL fAudioEnabled = FALSE; … … 2630 2629 case AudioControllerType_AC97: 2631 2630 { 2632 /* default: ICH AC97*/2631 /* Default: ICH AC97. */ 2633 2632 InsertConfigNode(pDevices, "ichac97", &pDev); 2634 2633 InsertConfigNode(pDev, "0", &pInst); … … 2640 2639 case AudioControllerType_SB16: 2641 2640 { 2642 /* legacy SoundBlaster16*/2641 /* Legacy SoundBlaster16. */ 2643 2642 InsertConfigNode(pDevices, "sb16", &pDev); 2644 2643 InsertConfigNode(pDev, "0", &pInst); … … 2654 2653 case AudioControllerType_HDA: 2655 2654 { 2656 /* Intel HD Audio */2655 /* Intel HD Audio. */ 2657 2656 InsertConfigNode(pDevices, "hda", &pDev); 2658 2657 InsertConfigNode(pDev, "0", &pInst); … … 2663 2662 } 2664 2663 2665 /* the Audio driver*/2664 /* The audio driver. */ 2666 2665 InsertConfigNode(pInst, "LUN#0", &pLunL0); 2667 2666 InsertConfigString(pLunL0, "Driver", "AUDIO"); 2667 InsertConfigNode(pLunL0, "Config", &pCfg); 2668 2668 2669 2669 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2670 PCFGMNODE pLunL1; 2670 2671 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 2671 InsertConfig String(pLunL1, "Driver", "PulseAudio");2672 InsertConfigNode(pLunL1, "Config", &pCfg); 2672 2673 #endif 2673 2674 InsertConfigNode(pLunL0, "Config", &pCfg);2675 2676 2674 AudioDriverType_T audioDriver; 2677 2675 hrc = audioAdapter->COMGETTER(AudioDriver)(&audioDriver); H(); … … 2680 2678 case AudioDriverType_Null: 2681 2679 { 2680 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2681 InsertConfigString(pLunL1, "Driver", "NullAudio"); 2682 #else 2682 2683 InsertConfigString(pCfg, "AudioDriver", "null"); 2684 #endif 2683 2685 break; 2684 2686 } 2685 2687 #ifdef RT_OS_WINDOWS 2686 # ifdef VBOX_WITH_WINMM2688 # ifdef VBOX_WITH_WINMM 2687 2689 case AudioDriverType_WinMM: 2688 2690 { 2691 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2692 #error "Port WinMM audio backend!" /** @todo Still needed? */ 2693 #else 2689 2694 InsertConfigString(pCfg, "AudioDriver", "winmm"); 2695 #endif 2690 2696 break; 2691 2697 } 2692 # endif2698 # endif 2693 2699 case AudioDriverType_DirectSound: 2694 2700 { 2695 2701 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2696 InsertConfigString(p Cfg, "AudioDriver", "DSoundAudio");2702 InsertConfigString(pLunL1, "Driver", "DSoundAudio"); 2697 2703 #else 2698 2704 InsertConfigString(pCfg, "AudioDriver", "dsound"); … … 2704 2710 case AudioDriverType_SolAudio: 2705 2711 { 2712 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2713 #error "Port Solaris audio backend!" /** @todo Port Solaris driver. */ 2714 #else 2706 2715 InsertConfigString(pCfg, "AudioDriver", "solaudio"); 2707 break;2708 }2709 #endif2710 #ifdef RT_OS_LINUX2711 # ifdef VBOX_WITH_ALSA2712 case AudioDriverType_ALSA:2713 {2714 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER2715 InsertConfigString(pCfg, "AudioDriver", "AlsaAudio");2716 #else2717 InsertConfigString(pCfg, "AudioDriver", "alsa");2718 2716 #endif 2719 2717 break; 2720 2718 } 2719 #endif 2720 #ifdef VBOX_WITH_ALSA 2721 case AudioDriverType_ALSA: 2722 { 2723 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2724 InsertConfigString(pLunL1, "Driver", "AlsaAudio"); 2725 # else 2726 InsertConfigString(pCfg, "AudioDriver", "alsa"); 2721 2727 # endif 2722 # ifdef VBOX_WITH_PULSE 2728 break; 2729 } 2730 #endif 2731 #ifdef VBOX_WITH_PULSE 2723 2732 case AudioDriverType_Pulse: 2724 2733 { 2725 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER2726 InsertConfigString(p Cfg, "AudioDriver", "PulseAudio");2727 # else2734 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2735 InsertConfigString(pLunL1, "Driver", "PulseAudio"); 2736 # else 2728 2737 InsertConfigString(pCfg, "AudioDriver", "pulse"); 2738 # endif 2739 break; 2740 } 2729 2741 #endif 2730 break;2731 }2732 # endif2733 #endif /* RT_OS_LINUX */2734 2742 #if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(VBOX_WITH_SOLARIS_OSS) 2735 2743 case AudioDriverType_OSS: 2736 2744 { 2737 InsertConfigString(pCfg, "AudioDriver", "oss"); 2745 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2746 #error "Port OSS audio backend!" /** @todo Port OSS driver. */ 2747 # else 2748 InsertConfigString(pCfg, "AudioDriver", "ossaudio"); 2749 # endif 2738 2750 break; 2739 2751 } 2740 #endif2741 #ifdef RT_OS_FREEBSD2742 # ifdef VBOX_WITH_PULSE2743 case AudioDriverType_Pulse:2744 {2745 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER2746 InsertConfigString(pCfg, "AudioDriver", "PulseAudio");2747 #else2748 InsertConfigString(pCfg, "AudioDriver", "pulse");2749 #endif2750 break;2751 }2752 # endif2753 2752 #endif 2754 2753 #ifdef RT_OS_DARWIN 2755 2754 case AudioDriverType_CoreAudio: 2756 2755 { 2756 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2757 InsertConfigString(pLunL1, "Driver", "CoreAudio"); 2758 # else 2757 2759 InsertConfigString(pCfg, "AudioDriver", "coreaudio"); 2760 # endif 2758 2761 break; 2759 2762 } 2760 2763 #endif 2761 2764 } 2765 2762 2766 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H(); 2763 InsertConfigString(pCfg, "StreamName", bstr); 2767 2764 2768 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2765 /* the Audio driver */ 2766 InsertConfigNode(pInst, "LUN#1", &pLunL0); 2767 InsertConfigString(pLunL0, "Driver", "AUDIO"); 2768 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 2769 /* 2770 * The VRDE audio backend driver. This one always is there 2771 * and therefore is hardcoded here. 2772 */ 2773 InsertConfigNode(pInst, "LUN#1", &pLunL1); 2774 InsertConfigString(pLunL1, "Driver", "AUDIO"); 2775 2776 InsertConfigNode(pLunL1, "AttachedDriver", &pLunL1); 2769 2777 InsertConfigString(pLunL1, "Driver", "AudioVRDE"); 2770 InsertConfigNode(pLunL0, "Config", &pCfg); 2778 2779 InsertConfigNode(pLunL1, "Config", &pCfg); 2771 2780 InsertConfigString(pCfg, "AudioDriver", "AudioVRDE"); 2772 2781 InsertConfigString(pCfg, "StreamName", bstr); 2773 InsertConfig Node(pLunL1, "Config", &pCfg);2774 InsertConfigInteger(pCfg, "Object", (uintptr_t)mAudioVRDE);2775 InsertConfigInteger(pCfg, "ObjectVRDPServer", (uintptr_t)mConsoleVRDPServer); 2776 2782 InsertConfigInteger(pCfg, "Object", (uintptr_t)mAudioVRDE); 2783 InsertConfigInteger(pCfg, "ObjectVRDPServer", (uintptr_t)mConsoleVRDPServer); 2784 2785 /** @todo Add audio video recording driver here. */ 2777 2786 #endif 2778 2787 } -
trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp
r52978 r53442 946 946 uint32_t fu32Intercepted) 947 947 { 948 ConsoleVRDPServer *server = static_cast<ConsoleVRDPServer*>(pvCallback); 949 950 server->mConsole->i_VRDPClientDisconnect(u32ClientId, fu32Intercepted); 951 952 if (ASMAtomicReadU32(&server->mu32AudioInputClientId) == u32ClientId) 953 { 954 Log(("AUDIOIN: disconnected client %u\n", u32ClientId)); 955 ASMAtomicWriteU32(&server->mu32AudioInputClientId, 0); 948 ConsoleVRDPServer *pServer = static_cast<ConsoleVRDPServer*>(pvCallback); 949 AssertPtrReturnVoid(pServer); 950 951 pServer->mConsole->i_VRDPClientDisconnect(u32ClientId, fu32Intercepted); 952 953 if (ASMAtomicReadU32(&pServer->mu32AudioInputClientId) == u32ClientId) 954 { 955 LogFunc(("Disconnected client %u\n", u32ClientId)); 956 ASMAtomicWriteU32(&pServer->mu32AudioInputClientId, 0); 956 957 957 958 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 958 server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputIntercept(false);959 pServer->mConsole->i_getAudioVRDE()->onVRDEInputIntercept(false); 959 960 #else 960 PPDMIAUDIOSNIFFERPORT pPort = server->mConsole->i_getAudioSniffer()->getAudioSnifferPort();961 PPDMIAUDIOSNIFFERPORT pPort = pServer->mConsole->i_getAudioSniffer()->getAudioSnifferPort(); 961 962 if (pPort) 962 963 { … … 970 971 } 971 972 972 int c = ASMAtomicDecS32(&server->mcClients);973 if (c == 0)973 int32_t cClients = ASMAtomicDecS32(&pServer->mcClients); 974 if (cClients == 0) 974 975 { 975 976 /* Features which should be enabled only if there is a client. */ 976 server->remote3DRedirect(false);977 pServer->remote3DRedirect(false); 977 978 } 978 979 } … … 981 982 void **ppvIntercept) 982 983 { 983 ConsoleVRDPServer * server = static_cast<ConsoleVRDPServer*>(pvCallback);984 ConsoleVRDPServer *pServer = static_cast<ConsoleVRDPServer*>(pvCallback); 984 985 985 986 LogFlowFunc(("%x\n", fu32Intercept)); … … 991 992 case VRDE_CLIENT_INTERCEPT_AUDIO: 992 993 { 993 server->mConsole->i_VRDPInterceptAudio(u32ClientId);994 pServer->mConsole->i_VRDPInterceptAudio(u32ClientId); 994 995 if (ppvIntercept) 995 996 { 996 *ppvIntercept = server;997 *ppvIntercept = pServer; 997 998 } 998 999 rc = VINF_SUCCESS; … … 1001 1002 case VRDE_CLIENT_INTERCEPT_USB: 1002 1003 { 1003 server->mConsole->i_VRDPInterceptUSB(u32ClientId, ppvIntercept);1004 pServer->mConsole->i_VRDPInterceptUSB(u32ClientId, ppvIntercept); 1004 1005 rc = VINF_SUCCESS; 1005 1006 } break; … … 1007 1008 case VRDE_CLIENT_INTERCEPT_CLIPBOARD: 1008 1009 { 1009 server->mConsole->i_VRDPInterceptClipboard(u32ClientId);1010 pServer->mConsole->i_VRDPInterceptClipboard(u32ClientId); 1010 1011 if (ppvIntercept) 1011 1012 { 1012 *ppvIntercept = server;1013 *ppvIntercept = pServer; 1013 1014 } 1014 1015 rc = VINF_SUCCESS; … … 1020 1021 * Only one client is allowed to intercept audio input. 1021 1022 */ 1022 if (ASMAtomicCmpXchgU32(& server->mu32AudioInputClientId, u32ClientId, 0) == true)1023 { 1024 Log (("AUDIOIN: connected client %u\n", u32ClientId));1023 if (ASMAtomicCmpXchgU32(&pServer->mu32AudioInputClientId, u32ClientId, 0) == true) 1024 { 1025 LogFunc(("Connected client %u\n", u32ClientId)); 1025 1026 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1026 server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputIntercept(true);1027 pServer->mConsole->i_getAudioVRDE()->onVRDEInputIntercept(true); 1027 1028 #else 1028 PPDMIAUDIOSNIFFERPORT pPort = server->mConsole->i_getAudioSniffer()->getAudioSnifferPort();1029 PPDMIAUDIOSNIFFERPORT pPort = pServer->mConsole->i_getAudioSniffer()->getAudioSnifferPort(); 1029 1030 if (pPort) 1030 1031 { 1031 1032 pPort->pfnAudioInputIntercept(pPort, true); 1032 1033 if (ppvIntercept) 1033 { 1034 *ppvIntercept = server; 1035 } 1034 *ppvIntercept = pServer; 1036 1035 } 1037 1036 else 1038 1037 { 1039 1038 AssertFailed(); 1040 ASMAtomicWriteU32(& server->mu32AudioInputClientId, 0);1039 ASMAtomicWriteU32(&pServer->mu32AudioInputClientId, 0); 1041 1040 rc = VERR_NOT_SUPPORTED; 1042 1041 } … … 1045 1044 else 1046 1045 { 1047 Log(("AUDIOIN: ignored client %u, active client %u\n", u32ClientId, server->mu32AudioInputClientId));1046 Log(("AUDIOIN: ignored client %u, active client %u\n", u32ClientId, pServer->mu32AudioInputClientId)); 1048 1047 rc = VERR_NOT_SUPPORTED; 1049 1048 } … … 1306 1305 uint32_t cbData) 1307 1306 { 1308 ConsoleVRDPServer *server = static_cast<ConsoleVRDPServer*>(pvCallback); 1307 ConsoleVRDPServer *pServer = static_cast<ConsoleVRDPServer*>(pvCallback); 1308 AssertPtrReturnVoid(pServer); 1309 1309 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER 1310 PPDMIAUDIOSNIFFERPORT pPort = server->mConsole->i_getAudioSniffer()->getAudioSnifferPort();1310 PPDMIAUDIOSNIFFERPORT pPort = pServer->mConsole->i_getAudioSniffer()->getAudioSnifferPort(); 1311 1311 #endif 1312 1312 … … 1315 1315 case VRDE_AUDIOIN_BEGIN: 1316 1316 { 1317 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1318 pServer->mConsole->i_getAudioVRDE()->onVRDEInputBegin(pvCtx, (PVRDEAUDIOINBEGIN)pvData); 1319 #else 1317 1320 const VRDEAUDIOINBEGIN *pParms = (const VRDEAUDIOINBEGIN *)pvData; 1318 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER1319 server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputEventBegin(pvCtx,1320 VRDE_AUDIO_FMT_SAMPLE_FREQ(pParms->fmt),1321 VRDE_AUDIO_FMT_CHANNELS(pParms->fmt),1322 VRDE_AUDIO_FMT_BITS_PER_SAMPLE(pParms->fmt),1323 VRDE_AUDIO_FMT_SIGNED(pParms->fmt)1324 );1325 #else1326 1321 pPort->pfnAudioInputEventBegin (pPort, pvCtx, 1327 1322 VRDE_AUDIO_FMT_SAMPLE_FREQ(pParms->fmt), … … 1331 1326 ); 1332 1327 #endif 1333 } break; 1328 break; 1329 } 1334 1330 1335 1331 case VRDE_AUDIOIN_DATA: 1336 {1337 1332 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1338 server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputEventData(pvCtx, pvData, cbData);1333 pServer->mConsole->i_getAudioVRDE()->onVRDEInputData(pvCtx, pvData, cbData); 1339 1334 #else 1340 1335 pPort->pfnAudioInputEventData (pPort, pvCtx, pvData, cbData); 1341 1336 #endif 1342 }break;1337 break; 1343 1338 1344 1339 case VRDE_AUDIOIN_END: 1345 {1346 1340 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1347 server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputEventEnd(pvCtx);1341 pServer->mConsole->i_getAudioVRDE()->onVRDEInputEnd(pvCtx); 1348 1342 #else 1349 1343 pPort->pfnAudioInputEventEnd (pPort, pvCtx); 1350 1344 #endif 1351 }break;1345 break; 1352 1346 1353 1347 default: 1354 return; 1355 } 1356 } 1357 1348 break; 1349 } 1350 } 1358 1351 1359 1352 ConsoleVRDPServer::ConsoleVRDPServer(Console *console) … … 3906 3899 } 3907 3900 3908 /* @todo rc not needed? */3909 3901 int ConsoleVRDPServer::SendAudioInputBegin(void **ppvUserCtx, 3910 3902 void *pvContext, … … 3914 3906 uint32_t cBits) 3915 3907 { 3916 if (mpEntryPoints && mhServer && mpEntryPoints->VRDEAudioInOpen) 3908 if ( mhServer 3909 && mpEntryPoints && mpEntryPoints->VRDEAudioInOpen) 3917 3910 { 3918 3911 uint32_t u32ClientId = ASMAtomicReadU32(&mu32AudioInputClientId); … … 3920 3913 { 3921 3914 VRDEAUDIOFORMAT audioFormat = VRDE_AUDIO_FMT_MAKE(iSampleHz, cChannels, cBits, 0); 3922 mpEntryPoints->VRDEAudioInOpen (mhServer, 3923 pvContext, 3924 u32ClientId, 3925 audioFormat, 3926 cSamples); 3927 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 3928 //*ppvUserCtx = NULL; 3929 #else 3930 *ppvUserCtx = NULL; /* This is the ConsoleVRDPServer context. 3931 - * Currently not used because only one client is allowed to 3932 - * do audio input and the client id is saved by the ConsoleVRDPServer. 3933 - */ 3934 #endif 3935 3915 mpEntryPoints->VRDEAudioInOpen(mhServer, 3916 pvContext, 3917 u32ClientId, 3918 audioFormat, 3919 cSamples); 3920 if (ppvUserCtx) 3921 *ppvUserCtx = NULL; /* This is the ConsoleVRDPServer context. 3922 * Currently not used because only one client is allowed to 3923 * do audio input and the client ID is saved by the ConsoleVRDPServer. 3924 */ 3936 3925 return VINF_SUCCESS; 3937 3926 } 3938 3927 } 3928 3929 /* 3930 * Not supported or no client connected. 3931 */ 3939 3932 return VERR_NOT_SUPPORTED; 3940 3933 } … … 3951 3944 } 3952 3945 } 3953 3954 3946 3955 3947 void ConsoleVRDPServer::QueryInfo(uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut) const -
trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp
r51096 r53442 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * VBox Audio VRDE backend 3 * VRDE audio backend for Main. 5 4 */ 6 5 7 6 /* 8 * Copyright (C) 20 06-2010Oracle Corporation7 * Copyright (C) 2013-2014 Oracle Corporation 9 8 * 10 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 21 #include "Logging.h" 23 22 23 #include "../../Devices/Audio/DrvAudio.h" 24 #include "../../Devices/Audio/AudioMixBuffer.h" 25 26 #include <iprt/mem.h> 27 #include <iprt/cdefs.h> 28 #include <iprt/circbuf.h> 29 24 30 #include <VBox/vmm/pdmaudioifs.h> 25 31 #include <VBox/vmm/pdmdrv.h> … … 27 33 #include <VBox/vmm/cfgm.h> 28 34 #include <VBox/err.h> 29 #include <iprt/mem.h> 30 #include <iprt/cdefs.h> 31 32 33 /******************************************************************************* 34 * 35 * IO Ring Buffer section 36 * 37 ******************************************************************************/ 38 39 /* Implementation of a lock free ring buffer which could be used in a multi 40 * threaded environment. Note that only the acquire, release and getter 41 * functions are threading aware. So don't use reset if the ring buffer is 42 * still in use. */ 43 typedef struct IORINGBUFFER 44 { 45 /* The current read position in the buffer */ 46 uint32_t uReadPos; 47 /* The current write position in the buffer */ 48 uint32_t uWritePos; 49 /* How much space of the buffer is currently in use */ 50 volatile uint32_t cBufferUsed; 51 /* How big is the buffer */ 52 uint32_t cBufSize; 53 /* The buffer itself */ 54 char *pBuffer; 55 } IORINGBUFFER; 56 /* Pointer to an ring buffer structure */ 57 typedef IORINGBUFFER* PIORINGBUFFER; 58 59 PPDMDRVINS gpDrvIns; //@todo handle this bad programming; 60 61 static void IORingBufferCreate(PIORINGBUFFER *ppBuffer, uint32_t cSize) 62 { 63 PIORINGBUFFER pTmpBuffer; 64 65 AssertPtr(ppBuffer); 66 67 *ppBuffer = NULL; 68 pTmpBuffer = RTMemAllocZ(sizeof(IORINGBUFFER)); 69 if (pTmpBuffer) 70 { 71 pTmpBuffer->pBuffer = RTMemAlloc(cSize); 72 if(pTmpBuffer->pBuffer) 73 { 74 pTmpBuffer->cBufSize = cSize; 75 *ppBuffer = pTmpBuffer; 76 } 77 else 78 RTMemFree(pTmpBuffer); 79 } 80 } 81 82 static void IORingBufferDestroy(PIORINGBUFFER pBuffer) 83 { 84 if (pBuffer) 85 { 86 if (pBuffer->pBuffer) 87 RTMemFree(pBuffer->pBuffer); 88 RTMemFree(pBuffer); 89 } 90 } 91 92 DECL_FORCE_INLINE(void) IORingBufferReset(PIORINGBUFFER pBuffer) 93 { 94 AssertPtr(pBuffer); 95 96 pBuffer->uReadPos = 0; 97 pBuffer->uWritePos = 0; 98 pBuffer->cBufferUsed = 0; 99 } 100 101 DECL_FORCE_INLINE(uint32_t) IORingBufferFree(PIORINGBUFFER pBuffer) 102 { 103 AssertPtr(pBuffer); 104 return pBuffer->cBufSize - ASMAtomicReadU32(&pBuffer->cBufferUsed); 105 } 106 107 DECL_FORCE_INLINE(uint32_t) IORingBufferUsed(PIORINGBUFFER pBuffer) 108 { 109 AssertPtr(pBuffer); 110 return ASMAtomicReadU32(&pBuffer->cBufferUsed); 111 } 112 113 DECL_FORCE_INLINE(uint32_t) IORingBufferSize(PIORINGBUFFER pBuffer) 114 { 115 AssertPtr(pBuffer); 116 return pBuffer->cBufSize; 117 } 118 119 static void IORingBufferAquireReadBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize) 120 { 121 uint32_t uUsed = 0; 122 uint32_t uSize = 0; 123 124 AssertPtr(pBuffer); 125 126 *ppStart = 0; 127 *pcSize = 0; 128 129 /* How much is in use? */ 130 uUsed = ASMAtomicReadU32(&pBuffer->cBufferUsed); 131 if (uUsed > 0) 132 { 133 /* Get the size out of the requested size, the read block till the end 134 * of the buffer & the currently used size. */ 135 uSize = RT_MIN(cReqSize, RT_MIN(pBuffer->cBufSize - pBuffer->uReadPos, uUsed)); 136 if (uSize > 0) 137 { 138 /* Return the pointer address which point to the current read 139 * position. */ 140 *ppStart = pBuffer->pBuffer + pBuffer->uReadPos; 141 *pcSize = uSize; 142 } 143 } 144 } 145 146 DECL_FORCE_INLINE(void) IORingBufferReleaseReadBlock(PIORINGBUFFER pBuffer, uint32_t cSize) 147 { 148 AssertPtr(pBuffer); 149 150 /* Split at the end of the buffer. */ 151 pBuffer->uReadPos = (pBuffer->uReadPos + cSize) % pBuffer->cBufSize; 152 ASMAtomicSubU32(&pBuffer->cBufferUsed, cSize); 153 } 154 155 static void IORingBufferAquireWriteBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize) 156 { 157 uint32_t uFree; 158 uint32_t uSize; 159 160 AssertPtr(pBuffer); 161 162 *ppStart = 0; 163 *pcSize = 0; 164 165 /* How much is free? */ 166 uFree = pBuffer->cBufSize - ASMAtomicReadU32(&pBuffer->cBufferUsed); 167 if (uFree > 0) 168 { 169 /* Get the size out of the requested size, the write block till the end 170 * of the buffer & the currently free size. */ 171 uSize = RT_MIN(cReqSize, RT_MIN(pBuffer->cBufSize - pBuffer->uWritePos, uFree)); 172 if (uSize > 0) 173 { 174 /* Return the pointer address which point to the current write 175 * position. */ 176 *ppStart = pBuffer->pBuffer + pBuffer->uWritePos; 177 *pcSize = uSize; 178 } 179 } 180 } 181 182 DECL_FORCE_INLINE(void) IORingBufferReleaseWriteBlock(PIORINGBUFFER pBuffer, uint32_t cSize) 183 { 184 AssertPtr(pBuffer); 185 186 /* Split at the end of the buffer. */ 187 pBuffer->uWritePos = (pBuffer->uWritePos + cSize) % pBuffer->cBufSize; 188 189 ASMAtomicAddU32(&pBuffer->cBufferUsed, cSize); 190 } 191 192 /****************** Ring Buffer Function Ends *****************/ 193 194 //@todo need to see if they need to move to pdmifs.h 195 #define AUDIO_HOST_ENDIANNESS 0 196 #define VOICE_ENABLE 1 197 #define VOICE_DISABLE 2 198 199 200 /* Initialization status indicator used for the recreation of the AudioUnits. */ 201 #define CA_STATUS_UNINIT UINT32_C(0) /* The device is uninitialized */ 202 #define CA_STATUS_IN_INIT UINT32_C(1) /* The device is currently initializing */ 203 #define CA_STATUS_INIT UINT32_C(2) /* The device is initialized */ 204 #define CA_STATUS_IN_UNINIT UINT32_C(3) /* The device is currently uninitializing */ 205 206 //@todo move t_sample as a PDM interface 207 //typedef struct { int mute; uint32_t r; uint32_t l; } volume_t; 208 209 #define INT_MAX 0x7fffffff 210 volume_t nominal_volume = { 211 0, 212 INT_MAX, 213 INT_MAX 214 }; 215 216 /* The desired buffer length in milliseconds. Will be the target total stream 217 * latency on newer version of pulse. Apparent latency can be less (or more.) 218 * In case its need to be used. Currently its not used. 219 */ 220 #if 0 221 static struct 222 { 223 int buffer_msecs_out; 224 int buffer_msecs_in; 225 } confAudioVRDE 226 = 227 { 228 INIT_FIELD (.buffer_msecs_out = ) 100, 229 INIT_FIELD (.buffer_msecs_in = ) 100, 230 }; 35 36 #ifdef LOG_GROUP 37 #undef LOG_GROUP 231 38 #endif 39 #define LOG_GROUP LOG_GROUP_DEV_AUDIO 40 #include <VBox/log.h> 41 232 42 /** 233 43 * Audio VRDE driver instance data. 234 *235 * @extends PDMIAUDIOSNIFFERCONNECTOR236 44 */ 237 45 typedef struct DRVAUDIOVRDE 238 46 { 239 /** Pointer to audio VRDE object */47 /** Pointer to audio VRDE object. */ 240 48 AudioVRDE *pAudioVRDE; 241 PPDMDRVINS pDrvIns;49 PPDMDRVINS pDrvIns; 242 50 /** Pointer to the driver instance structure. */ 243 PDMIHOSTAUDIO IHostAudioR3;244 ConsoleVRDPServer *pConsoleVRDPServer;51 PDMIHOSTAUDIO IHostAudioR3; 52 ConsoleVRDPServer *pConsoleVRDPServer; 245 53 /** Pointer to the DrvAudio port interface that is above it. */ 246 PPDMIAUDIOCONNECTOR pUpPort;54 PPDMIAUDIOCONNECTOR pDrvAudio; 247 55 } DRVAUDIOVRDE, *PDRVAUDIOVRDE; 248 typedef struct PDMHOSTVOICEOUT PDMHOSTVOICEOUT; 249 typedef PDMHOSTVOICEOUT *PPDMHOSTVOICEOUT; 250 251 typedef struct VRDEVoice 252 { 253 /* Audio and audio details for recording */ 254 PDMHOSTVOICEIN pHostVoiceIn; 255 void * pvUserCtx; 256 /* Number of bytes per frame (bitsPerSample * channels) of the actual input format. */ 257 uint32_t cBytesPerFrame; 258 /* Frequency of the actual audio format. */ 259 uint32_t uFrequency; 260 /* If the actual format frequence differs from the requested format, this is not NULL. */ 261 void *rate; 262 /* Temporary buffer for st_sample_t representation of the input audio data. */ 263 void *pvSamplesBuffer; 264 /* buffer for bytes of samples (not rate converted) */ 265 uint32_t cbSamplesBufferAllocated; 266 /* Temporary buffer for frequency conversion. */ 267 void *pvRateBuffer; 268 /* buffer for bytes rate converted samples */ 269 uint32_t cbRateBufferAllocated; 270 /* A ring buffer for transferring data to the playback thread */ 271 PIORINGBUFFER pRecordedVoiceBuf; 272 t_sample * convAudioDevFmtToStSampl; 273 uint32_t fIsInit; 274 uint32_t status; 275 }; 276 typedef VRDEVoice *PVRDEVoice; 277 278 typedef struct VRDEVoiceOut 279 { 280 PDMHOSTVOICEOUT pHostVoiceOut; 56 57 typedef struct VRDESTREAMIN 58 { 59 /** Associated host input stream. */ 60 PDMAUDIOHSTSTRMIN HstStrmIn; 61 /** Number of samples captured asynchronously in the 62 * onVRDEInputXXX callbacks. */ 63 uint32_t cSamplesCaptured; 64 /** Critical section. */ 65 RTCRITSECT CritSect; 66 67 } VRDESTREAMIN, *PVRDESTREAMIN; 68 69 typedef struct VRDESTREAMOUT 70 { 71 /** Associated host output stream. */ 72 PDMAUDIOHSTSTRMOUT HstStrmOut; 281 73 uint64_t old_ticks; 282 74 uint64_t cSamplesSentPerSec; 283 }; 284 typedef VRDEVoiceOut * PVRDEVoiceOut; 285 286 AudioVRDE::AudioVRDE(Console *console) 287 : mpDrv(NULL), 288 mParent(console) 289 { 290 } 291 292 AudioVRDE::~AudioVRDE() 293 { 294 if (mpDrv) 295 { 296 mpDrv->pAudioVRDE = NULL; 297 mpDrv = NULL; 298 } 299 } 300 301 PPDMIAUDIOCONNECTOR AudioVRDE::getDrvAudioPort() 302 { 303 Assert(mpDrv); 304 return mpDrv->pUpPort; 305 } 306 307 void AudioVRDE::handleVRDESvrCmdAudioInputIntercept(bool fIntercept) 308 { 309 LogFlow(("AudioVRDE: handleVRDPCmdInputIntercept\n")); 310 } 311 312 static DECLCALLBACK(void *) drvAudioVRDEInit(PPDMIHOSTAUDIO pInterface) 313 { 314 LogFlow(("drvAudioVRDEInit \n")); 315 return 1; 316 } 317 318 static void drvAudioVRDEPcmInitInfo(PDMPCMPROPERTIES * pProps, audsettings_t *as) 319 { 320 int bits = 8, sign = 0, shift = 0; 321 LogFlow(("AudioVRDE: PcmInitInfo \n")); 322 323 switch (as->fmt) { 324 case AUD_FMT_S8: 325 sign = 1; 326 case AUD_FMT_U8: 327 break; 328 329 case AUD_FMT_S16: 330 sign = 1; 331 case AUD_FMT_U16: 332 bits = 16; 333 shift = 1; 334 break; 335 336 case AUD_FMT_S32: 337 sign = 1; 338 case AUD_FMT_U32: 339 bits = 32; 340 shift = 2; 341 break; 342 } 343 344 pProps->uFrequency = as->freq; 345 pProps->cBits = bits; 346 pProps->fSigned = sign; 347 pProps->cChannels = as->nchannels; 348 pProps->cShift = (as->nchannels == 2) + shift; 349 pProps->fAlign = (1 << pProps->cShift) - 1; 350 pProps->cbPerSec = pProps->uFrequency << pProps->cShift; 351 pProps->fSwapEndian = (as->endianness != AUDIO_HOST_ENDIANNESS); 352 } 353 354 /* 355 * Hard voice (playback) 356 */ 357 static int audio_pcm_hw_find_min_out (PPDMHOSTVOICEOUT hw, int *nb_livep) 358 { 359 PPDMGSTVOICEOUT sw; 360 PPDMGSTVOICEOUT pIter; 361 int m = INT_MAX; 362 int nb_live = 0; 363 LogFlow(("Hard Voice Playback \n")); 364 365 RTListForEach(&hw->HeadGstVoiceOut, pIter, PDMGSTVOICEOUT, ListGstVoiceOut) 366 { 367 sw = pIter; 368 if (sw->State.fActive || !sw->State.fEmpty) 369 { 370 m = audio_MIN (m, sw->cSamplesMixed); 371 nb_live += 1; 372 } 373 } 374 375 *nb_livep = nb_live; 376 return m; 377 } 378 379 int audio_pcm_hw_get_live_out2 (PPDMHOSTVOICEOUT hw, int *nb_live) 380 { 381 int smin; 382 383 smin = audio_pcm_hw_find_min_out (hw, nb_live); 384 385 if (!*nb_live) { 386 return 0; 75 } VRDESTREAMOUT, *PVRDESTREAMOUT; 76 77 static DECLCALLBACK(int) drvAudioVRDEInit(PPDMIHOSTAUDIO pInterface) 78 { 79 LogFlowFuncEnter(); 80 81 return VINF_SUCCESS; 82 } 83 84 static DECLCALLBACK(int) drvAudioVRDEInitOut(PPDMIHOSTAUDIO pInterface, 85 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg, 86 uint32_t *pcSamples) 87 { 88 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 89 AssertPtrReturn(pDrv, VERR_INVALID_POINTER); 90 91 LogFlowFunc(("pHstStrmOut=%p, pCfg=%p\n", pHstStrmOut, pCfg)); 92 93 PVRDESTREAMOUT pVRDEStrmOut = (PVRDESTREAMOUT)pHstStrmOut; 94 AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER); 95 96 if (pcSamples) 97 *pcSamples = _4K; /** @todo Make this configurable. */ 98 99 return drvAudioStreamCfgToProps(pCfg, &pVRDEStrmOut->HstStrmOut.Props); 100 } 101 102 static DECLCALLBACK(int) drvAudioVRDEInitIn(PPDMIHOSTAUDIO pInterface, 103 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg, 104 PDMAUDIORECSOURCE enmRecSource, 105 uint32_t *pcSamples) 106 { 107 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 108 AssertPtrReturn(pDrv, VERR_INVALID_POINTER); 109 110 PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn; 111 AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER); 112 113 if (pcSamples) 114 *pcSamples = _4K; /** @todo Make this configurable. */ 115 116 return drvAudioStreamCfgToProps(pCfg, &pVRDEStrmIn->HstStrmIn.Props); 117 } 118 119 /** 120 * Transfers audio input formerly sent by a connected RDP client / VRDE backend 121 * (using the onVRDEInputXXX methods) over to the VRDE host (VM). The audio device 122 * emulation then will read and send the data to the guest. 123 * 124 * @return IPRT status code. 125 * @param pInterface 126 * @param pHstStrmIn 127 * @param pcSamplesCaptured 128 */ 129 static DECLCALLBACK(int) drvAudioVRDECaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, 130 uint32_t *pcSamplesCaptured) 131 { 132 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 133 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 134 AssertPtrReturn(pcSamplesCaptured, VERR_INVALID_POINTER); 135 136 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 137 AssertPtrReturn(pDrv, VERR_INVALID_POINTER); 138 139 PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn; 140 AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER); 141 142 /** @todo Use CritSect! */ 143 144 int rc; 145 146 uint32_t cProcessed = 0; 147 if (pVRDEStrmIn->cSamplesCaptured) 148 { 149 rc = audioMixBufMixToParent(&pVRDEStrmIn->HstStrmIn.MixBuf, pVRDEStrmIn->cSamplesCaptured, 150 &cProcessed); 387 151 } 388 152 else 389 { 390 int live = smin; 391 392 if (live < 0 || live > hw->cSamples) 393 { 394 LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples)); 395 return 0; 396 } 397 return live; 398 } 399 } 400 401 402 int audio_pcm_hw_get_live_out (PPDMHOSTVOICEOUT hw) 403 { 404 int nb_live; 405 int live; 406 407 live = audio_pcm_hw_get_live_out2 (hw, &nb_live); 408 if (live < 0 || live > hw->cSamples) 409 { 410 LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples)); 411 return 0; 412 } 413 return live; 414 } 415 416 /* 417 * Hard voice (capture) 418 */ 419 static int audio_pcm_hw_find_min_in (PPDMHOSTVOICEIN hw) 420 { 421 PPDMGSTVOICEIN pIter; 422 int m = hw->cSamplesCaptured; 423 424 RTListForEach(&hw->HeadGstVoiceIn, pIter, PDMGSTVOICEIN, ListGstVoiceIn) 425 { 426 if (pIter->State.fActive) 427 { 428 m = audio_MIN (m, pIter->cHostSamplesAcquired); 429 } 430 } 431 return m; 432 } 433 434 int audio_pcm_hw_get_live_in (PPDMHOSTVOICEIN hw) 435 { 436 int live = hw->cSamplesCaptured - audio_pcm_hw_find_min_in (hw); 437 if (live < 0 || live > hw->cSamples) 438 { 439 LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples)); 440 return 0; 441 } 442 return live; 443 } 444 445 static inline void *advance (void *p, int incr) 446 { 447 uint8_t *d = (uint8_t*)p; 448 return (d + incr); 449 } 450 451 uint64_t audio_get_ticks_per_sec (void) 452 { 453 return PDMDrvHlpTMGetVirtualFreq (gpDrvIns); 454 } 455 456 uint64_t audio_get_clock (void) 457 { 458 return PDMDrvHlpTMGetVirtualTime (gpDrvIns); 459 } 460 461 void VRDEReallocSampleBuf(PVRDEVoice pVRDEVoice, uint32_t cSamples) 462 { 463 uint32_t cbBuffer = cSamples * sizeof(PDMHOSTSTEREOSAMPLE); 464 if (cbBuffer > pVRDEVoice->cbSamplesBufferAllocated) 465 { 466 if (pVRDEVoice->pvSamplesBuffer) 467 { 468 RTMemFree(pVRDEVoice->pvSamplesBuffer); 469 pVRDEVoice->pvSamplesBuffer = NULL; 470 } 471 pVRDEVoice->pvSamplesBuffer = RTMemAlloc(cbBuffer); 472 if (pVRDEVoice->pvSamplesBuffer) 473 pVRDEVoice->cbSamplesBufferAllocated = cbBuffer; 474 else 475 pVRDEVoice->cbSamplesBufferAllocated = 0; 476 } 477 478 } 479 480 void VRDEReallocRateAdjSampleBuf(PVRDEVoice pVRDEVoice, uint32_t cSamples) 481 { 482 uint32_t cbBuffer = cSamples * sizeof(PDMHOSTSTEREOSAMPLE); 483 if (cbBuffer > pVRDEVoice->cbRateBufferAllocated) 484 { 485 RTMemFree(pVRDEVoice->pvRateBuffer); 486 pVRDEVoice->pvRateBuffer = RTMemAlloc(cbBuffer); 487 if (pVRDEVoice->pvRateBuffer) 488 pVRDEVoice->cbRateBufferAllocated = cbBuffer; 489 else 490 pVRDEVoice->cbRateBufferAllocated = 0; 491 } 492 } 493 494 /******************************************************************************* 153 rc = VINF_SUCCESS; 154 155 if (RT_SUCCESS(rc)) 156 { 157 *pcSamplesCaptured = cProcessed; 158 159 Assert(pVRDEStrmIn->cSamplesCaptured >= cProcessed); 160 pVRDEStrmIn->cSamplesCaptured -= cProcessed; 161 } 162 163 LogFlowFunc(("cSamplesCaptured=%RU32, cProcessed=%RU32\n", 164 pVRDEStrmIn->cSamplesCaptured, cProcessed, rc)); 165 return rc; 166 } 167 168 /** 169 * Transfers VM audio output over to the VRDE instance for playing remotely 170 * on the client. 495 171 * 496 * AudioVRDE input section 497 * 498 ******************************************************************************/ 499 500 /* 501 * Callback to feed audio input buffer. Samples format is be the same as 502 * in the voice. The caller prepares st_sample_t. 503 * 504 * @param cbSamples Size of pvSamples array in bytes. 505 * @param pvSamples Points to an array of samples. 506 * 507 * @return IPRT status code. 508 */ 509 static int fltRecordingCallback(PVRDEVoice pVRDEVoice, uint32_t cbSamples, const void *pvSamples) 510 { 511 int rc = VINF_SUCCESS; 512 uint32_t csAvail = 0; 513 uint32_t csToWrite = 0; 514 uint32_t cbToWrite = 0; 515 uint32_t csWritten = 0; 516 char *pcDst = NULL; 517 518 LogFlow(("audio-filter: fltRecordingCallback\n")); 519 520 Assert((cbSamples % sizeof(PDMHOSTSTEREOSAMPLE)) == 0); 521 522 if (!pVRDEVoice->fIsInit) 523 return VINF_SUCCESS; 524 525 /* If nothing is pending return immediately. */ 526 if (cbSamples == 0) 527 return VINF_SUCCESS; 528 529 /* How much space is free in the ring buffer? */ 530 PPDMHOSTSTEREOSAMPLE psSrc; 531 csAvail = IORingBufferFree(pVRDEVoice->pRecordedVoiceBuf) / sizeof(PDMHOSTSTEREOSAMPLE); /* bytes -> samples */ 532 533 /* How much space is used in the audio buffer. Use the smaller size of the too. */ 534 csAvail = RT_MIN(csAvail, cbSamples / sizeof(PDMHOSTSTEREOSAMPLE)); 535 536 /* Iterate as long as data is available */ 537 while(csWritten < csAvail) 538 { 539 /* How much is left? */ 540 csToWrite = csAvail - csWritten; 541 cbToWrite = csToWrite * sizeof(PDMHOSTSTEREOSAMPLE); 542 543 /* Try to acquire the necessary space from the ring buffer. */ 544 IORingBufferAquireWriteBlock(pVRDEVoice->pRecordedVoiceBuf, cbToWrite, &pcDst, &cbToWrite); 545 546 /* How much do we get? */ 547 csToWrite = cbToWrite / sizeof(PDMHOSTSTEREOSAMPLE); 548 549 /* Break if nothing is free anymore. */ 550 if (RT_UNLIKELY(csToWrite == 0)) 551 break; 552 553 /* Copy the data from the audio buffer to the ring buffer in PVRDEVoice. */ 554 memcpy(pcDst, (uint8_t *)pvSamples + (csWritten * sizeof(PDMHOSTSTEREOSAMPLE)), cbToWrite); 555 556 /* Release the ring buffer, so the main thread could start reading this data. */ 557 IORingBufferReleaseWriteBlock(pVRDEVoice->pRecordedVoiceBuf, cbToWrite); 558 559 csWritten += csToWrite; 560 } 561 562 LogFlow(("AudioVRDE: [Input] Finished writing buffer with %RU32 samples (%RU32 bytes)\n", 563 csWritten, csWritten * sizeof(PDMHOSTSTEREOSAMPLE))); 564 565 return rc; 566 } 567 568 569 STDMETHODIMP AudioVRDE::handleVRDESvrCmdAudioInputEventBegin(void *pvContext, int iSampleHz, int cChannels, 570 int cBits, bool fUnsigned) 571 { 572 int bitIdx; 573 PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext; 574 LogFlow(("AudioVRDE: handleVRDPCmdInputEventBegin\n")); 575 /* Prepare a format convertion for the actually used format. */ 576 pVRDEVoice->cBytesPerFrame = ((cBits + 7) / 8) * cChannels; 577 if (cBits == 16) 578 { 579 bitIdx = 1; 580 } 581 else if (cBits == 32) 582 { 583 bitIdx = 2; 584 } 585 else 586 { 587 bitIdx = 0; 588 } 589 //PPDMIAUDIOCONNECTOR pPort = server->mConsole->getAudioVRDE()->getDrvAudioPort(); 590 /* Call DrvAudio interface to get the t_sample type conversion function */ 591 pVRDEVoice->convAudioDevFmtToStSampl = mpDrv->pUpPort->pfnConvDevFmtToStSample(mpDrv->pUpPort, 592 (cChannels == 2) ? 1 : 0, 593 !fUnsigned, 0, bitIdx 594 ); 595 if (pVRDEVoice->convAudioDevFmtToStSampl) 596 { 597 LogFlow(("AudioVRDE: Failed to get the conversion function \n")); 598 } 599 LogFlow(("AudioVRDE: Required freq as requested by VRDP Server = %d\n", iSampleHz)); 600 //if (iSampleHz && iSampleHz != pVRDEVoice->pHostVoiceIn.Props.uFrequency) 601 { 602 /* @todo if the above condition is false then pVRDEVoice->uFrequency will remain 0 */ 603 pVRDEVoice->rate = mpDrv->pUpPort->pfnPrepareAudioConversion(mpDrv->pUpPort, iSampleHz, 604 pVRDEVoice->pHostVoiceIn.Props.uFrequency); 605 pVRDEVoice->uFrequency = iSampleHz; 606 LogFlow(("AudioVRDE: pVRDEVoice assigned requested freq =%d\n", pVRDEVoice->uFrequency)); 607 } 608 return VINF_SUCCESS; 609 } 610 611 /* 612 * pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in 613 * drvAudioVRDEDisableEnableIn VOICE_ENABLE case. 614 */ 615 void AudioVRDE::handleVRDESvrCmdAudioInputEventData(void *pvContext, const void *pvData, uint32_t cbData) 616 { 617 PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext; 618 PPDMHOSTSTEREOSAMPLE pHostStereoSampleBuf; /* target sample buffer */ 619 PPDMHOSTSTEREOSAMPLE pConvertedSampleBuf; /* samples adjusted for rate */ 620 uint32_t cSamples = cbData / pVRDEVoice->cBytesPerFrame; /* Count of samples */ 621 void * pTmpSampleBuf = NULL; 622 uint32_t cConvertedSamples; /* samples adjusted for rate */ 623 uint32_t cbSamples; /* count of bytes occupied by samples */ 624 uint32_t rc; 625 LogFlow(("AudioVRDE: handleVRDPCmdInputEventData cbData = %d, bytesperfram=%d\n", 626 cbData, pVRDEVoice->cBytesPerFrame)); 627 628 VRDEReallocSampleBuf(pVRDEVoice, cSamples); 629 pHostStereoSampleBuf = (PPDMHOSTSTEREOSAMPLE)pVRDEVoice->pvSamplesBuffer; 630 pVRDEVoice->convAudioDevFmtToStSampl(pHostStereoSampleBuf, pvData, cSamples, &nominal_volume); 631 632 /* count of rate adjusted samples */ 633 pVRDEVoice->uFrequency = 22100; /* @todo handle this. How pVRDEVoice will get proper value */ 634 cConvertedSamples = (cSamples * pVRDEVoice->pHostVoiceIn.Props.uFrequency) / pVRDEVoice->uFrequency; 635 VRDEReallocRateAdjSampleBuf(pVRDEVoice, cConvertedSamples); 636 637 pConvertedSampleBuf = (PPDMHOSTSTEREOSAMPLE)pVRDEVoice->pvRateBuffer; 638 639 if (pConvertedSampleBuf) 640 { 641 uint32_t cSampleSrc = cSamples; 642 uint32_t cSampleDst = cConvertedSamples; 643 mpDrv->pUpPort->pfnDoRateConversion(mpDrv->pUpPort, pVRDEVoice->rate, pHostStereoSampleBuf, 644 pConvertedSampleBuf, &cSampleSrc, &cConvertedSamples); 645 pTmpSampleBuf = pConvertedSampleBuf; 646 cbSamples = cConvertedSamples * sizeof(PDMHOSTSTEREOSAMPLE); 647 } 648 649 if (cbSamples) 650 { 651 rc = fltRecordingCallback(pVRDEVoice, cbSamples, pTmpSampleBuf); 652 } 653 } 654 655 /* 656 * pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in 657 * drvAudioVRDEDisableEnableIn VOICE_ENABLE case. 658 */ 659 void AudioVRDE::handleVRDESvrCmdAudioInputEventEnd(void *pvContext) 660 { 661 PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext; 662 LogFlow(("AudioVRDE: handleVRDPCmdInputEventEnd\n")); 663 /* The caller will not use this context anymore. */ 664 if (pVRDEVoice->rate) 665 { 666 mpDrv->pUpPort->pfnEndAudioConversion(mpDrv->pUpPort, pVRDEVoice->rate); 667 } 668 669 if (pVRDEVoice->pvSamplesBuffer) 670 { 671 RTMemFree(pVRDEVoice->pvSamplesBuffer); 672 pVRDEVoice->pvSamplesBuffer = NULL; 673 } 674 if(pVRDEVoice->pvRateBuffer) 675 { 676 RTMemFree(pVRDEVoice->pvRateBuffer); 677 pVRDEVoice->pvRateBuffer = NULL; 678 } 679 } 680 681 static DECLCALLBACK(int) drvAudioVRDEInitOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut, audsettings_t *as) 682 { 683 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 684 685 PVRDEVoiceOut pVRDEVoiceOut = (PVRDEVoiceOut)pHostVoiceOut; 686 LogFlow(("DrvAudioVRDEInitOut: audio input begin cShift=%d\n", pHostVoiceOut->Props.cShift)); 687 pHostVoiceOut->cSamples = 6174; 688 drvAudioVRDEPcmInitInfo(&pVRDEVoiceOut->pHostVoiceOut.Props, as); 689 return VINF_SUCCESS; 690 691 } 692 693 static DECLCALLBACK(int) drvAudioVRDEInitIn (PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, audsettings_t *as) 694 { 695 LogFlow(("DrvAudioVRDE: drvAudioVRDEInitIn \n")); 696 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 697 PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn; 698 pHostVoiceIn->cSamples = 6174; 699 drvAudioVRDEPcmInitInfo(&pVRDEVoice->pHostVoiceIn.Props, as); 700 return VINF_SUCCESS; 701 } 702 703 static DECLCALLBACK(int) drvAudioVRDEPlayIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn) 704 { 705 uint32_t cbAvlblRingBuffer = 0; 706 uint32_t cSamplesRingBuffer = 0; 707 uint32_t cSamplesToRead = 0; 708 uint32_t cSamplesRead = 0; 709 uint32_t cbToRead; 710 char *pcSrc; 711 PDMHOSTSTEREOSAMPLE * psDst; 712 //@todo take care of the size of the buffer allocated to pHostVoiceIn 713 PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn; 714 LogFlow(("DrvAudioVRDE: drvAudioVRDEPlayIn \n")); 715 716 /* use this from DrvHostCoreAudio.c */ 717 if (ASMAtomicReadU32(&pVRDEVoice->status) != CA_STATUS_INIT) 718 { 719 LogFlow(("AudioVRDE: VRDE voice not initialized \n")); 720 return 0; 721 } 722 723 /* how much space is used in the ring buffer in pRecordedVocieBuf with pAudioVRDE . Bytes-> samples*/ 724 cSamplesRingBuffer = IORingBufferUsed(pVRDEVoice->pRecordedVoiceBuf) / sizeof(PDMHOSTSTEREOSAMPLE); 725 726 /* How much space is available in the mix buffer. Use the smaller size of the too. */ 727 cSamplesRingBuffer = RT_MIN(cSamplesRingBuffer, (uint32_t)(pVRDEVoice->pHostVoiceIn.cSamples - 728 audio_pcm_hw_get_live_in (&pVRDEVoice->pHostVoiceIn))); 729 LogFlow(("AudioVRDE: [Input] Start reading buffer with %d samples (%d bytes)\n", cSamplesRingBuffer, 730 cSamplesRingBuffer * sizeof(PDMHOSTSTEREOSAMPLE))); 731 732 /* Iterate as long as data is available */ 733 while (cSamplesRead < cSamplesRingBuffer) 734 { 735 /* How much is left? Split request at the end of our samples buffer. */ 736 cSamplesToRead = RT_MIN(cSamplesRingBuffer - cSamplesRead, 737 (uint32_t)(pVRDEVoice->pHostVoiceIn.cSamples - pVRDEVoice->pHostVoiceIn.offWrite)); 738 cbToRead = cSamplesToRead * sizeof(PDMHOSTSTEREOSAMPLE); 739 LogFlow(("AudioVRDE: [Input] Try reading %RU32 samples (%RU32 bytes)\n", cSamplesToRead, cbToRead)); 740 741 /* Try to acquire the necessary block from the ring buffer. Remeber in fltRecrodCallback we 742 * we are filling this buffer with the audio data available from VRDP. Here we are reading it 743 */ 744 /*todo do I need to introduce a thread to fill the buffer in fltRecordcallback. So that 745 * filling is in separate thread and the reading of that buffer is in separate thread 746 */ 747 IORingBufferAquireReadBlock(pVRDEVoice->pRecordedVoiceBuf, cbToRead, &pcSrc, &cbToRead); 748 749 /* How much to we get? */ 750 cSamplesToRead = cbToRead / sizeof(PDMHOSTSTEREOSAMPLE); 751 LogFlow(("AuderVRDE: [Input] There are %d samples (%d bytes) available\n", cSamplesToRead, cbToRead)); 752 753 /* Break if nothing is used anymore. */ 754 if (cSamplesToRead == 0) 755 { 756 LogFlow(("AudioVRDE: Nothing to read \n")); 757 break; 758 } 759 760 /* Copy the data from our ring buffer to the mix buffer. */ 761 psDst = pVRDEVoice->pHostVoiceIn.pConversionBuf + pVRDEVoice->pHostVoiceIn.offWrite; 762 memcpy(psDst, pcSrc, cbToRead); 763 764 /* Release the read buffer, so it could be used for new data. */ 765 IORingBufferReleaseReadBlock(pVRDEVoice->pRecordedVoiceBuf, cbToRead); 766 767 pVRDEVoice->pHostVoiceIn.offWrite = (pVRDEVoice->pHostVoiceIn.offWrite + cSamplesToRead) 768 % pVRDEVoice->pHostVoiceIn.cSamples; 769 770 /* How much have we reads so far. */ 771 cSamplesRead += cSamplesToRead; 772 } 773 LogFlow(("AudioVRDE: [Input] Finished reading buffer with %d samples (%d bytes)\n", 774 cSamplesRead, cSamplesRead * sizeof(PDMHOSTSTEREOSAMPLE))); 775 776 return cSamplesRead; 777 } 778 779 static DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut) 780 { 781 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 782 PVRDEVoiceOut pVRDEVoiceOut = (PVRDEVoiceOut)pHostVoiceOut; 783 int live; 784 uint8_t *pu8Dst; 785 int cSamplesPlayed; 786 int cSamplesToSend = 0; 172 * @return IPRT status code. 173 * @param pInterface 174 * @param pHstStrmOut 175 * @param pcSamplesPlayed 176 */ 177 static DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, 178 uint32_t *pcSamplesPlayed) 179 { 180 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 181 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 182 /* pcSamplesPlayed is optional. */ 183 184 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 185 AssertPtrReturn(pDrv, VERR_INVALID_POINTER); 186 PVRDESTREAMOUT pVRDEStrmOut = (PVRDESTREAMOUT)pHstStrmOut; 187 AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER); 188 787 189 /* 788 190 * Just call the VRDP server with the data. 789 191 */ 790 live = audio_pcm_hw_get_live_out (pHostVoiceOut); 791 uint64_t now = audio_get_clock(); 792 uint64_t ticks = now - pVRDEVoiceOut->old_ticks; 793 uint64_t ticks_per_second = audio_get_ticks_per_sec(); 794 cSamplesPlayed = (int)((2 * ticks * pHostVoiceOut->Props.uFrequency + ticks_per_second) / ticks_per_second / 2); 795 if (cSamplesPlayed < 0) 192 uint32_t live = drvAudioHstOutSamplesLive(pHstStrmOut, NULL /* pcStreamsLive */); 193 uint64_t now = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns); 194 uint64_t ticks = now - pVRDEStrmOut->old_ticks; 195 uint64_t ticks_per_second = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns); 196 197 uint32_t cSamplesPlayed = (int)((2 * ticks * pHstStrmOut->Props.uHz + ticks_per_second) / ticks_per_second / 2); 198 if (!cSamplesPlayed) 796 199 cSamplesPlayed = live; 797 pHostVoiceOut->Props.cBits = 128; 798 VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pHostVoiceOut->Props.uFrequency, 799 pHostVoiceOut->Props.cChannels, 800 pHostVoiceOut->Props.cBits, /* bits per sample */ 801 !pHostVoiceOut->Props.fSigned); 802 LogFlow(("DrvAudioVRDE: send audio sample freq=%d, chan=%d, cBits = %d, fsigned = %d, cSamples=%d format=%d \n", 803 pHostVoiceOut->Props.uFrequency, pHostVoiceOut->Props.cChannels, 804 pHostVoiceOut->Props.cBits, pHostVoiceOut->Props.fSigned, 805 pHostVoiceOut->cSamples, format) 806 ); 807 pVRDEVoiceOut->old_ticks = now; 808 cSamplesToSend = RT_MIN(live, cSamplesPlayed); 809 if (pHostVoiceOut->offRead + cSamplesToSend > pHostVoiceOut->cSamples) 810 { 811 /* send the samples till the end of pHostStereoSampleBuf */ 812 pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead], 813 (pHostVoiceOut->cSamples - pHostVoiceOut->offRead), format); 814 /*pHostStereoSampleBuff already has the samples which exceeded its space. They have overwriten the old 815 * played sampled starting from offset 0. So based on the number of samples that we had to play, 816 * read the number of samples from offset 0 . 817 */ 818 pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[0], 819 (cSamplesToSend - (pHostVoiceOut->cSamples - 820 pHostVoiceOut->offRead)), 821 format); 822 } 823 else 824 { 825 pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead], 826 cSamplesToSend, format); 827 } 828 pHostVoiceOut->offRead = (pHostVoiceOut->offRead + cSamplesToSend) % pHostVoiceOut->cSamples; 829 return cSamplesToSend; 830 } 831 832 static DECLCALLBACK(void) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN hw) 833 { 834 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 835 LogFlow(("DrvAudioVRDE: drvAudioVRDEFiniIn \n")); 836 pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL); 837 } 838 839 static DECLCALLBACK(void) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut) 840 { 841 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 842 LogFlow(("DrvAudioVRDE: audio input end\n")); 843 } 844 845 static DECLCALLBACK(int) drvAudioVRDEDisableEnableOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT hw, int cmd) 846 { 847 LogFlow(("DrvAudioVRDE: drvAudioVRDEDisableEnableOut \n")); 848 return VINF_SUCCESS; 849 } 850 851 static DECLCALLBACK(int) drvAudioVRDEDisableEnableIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, int cmd) 852 { 853 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 854 855 /* Initialize VRDEVoice and return to VRDP server which returns this struct back to us 856 * in the form void * pvContext 857 */ 858 PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn; 859 LogFlow(("DrvAudioVRDE: drvAudioVRDEDisableEnableIn \n")); 860 /* initialize only if not already done */ 861 if (cmd == VOICE_ENABLE) 862 { 863 //@todo if (!pVRDEVoice->fIsInit) 864 // IORingBufferReset(pVRDEVoice->pRecordedVoiceBuf); 865 LogFlow(("DrvAudioVRDE: Intializing the VRDE params and buffer \n")); 866 pVRDEVoice->fIsInit = 1; 867 pVRDEVoice->pHostVoiceIn = *pHostVoiceIn; 868 pVRDEVoice->cBytesPerFrame =1 ; 869 pVRDEVoice->uFrequency = 0; 870 pVRDEVoice->rate = NULL; 871 pVRDEVoice->cbSamplesBufferAllocated = 0; 872 pVRDEVoice->pvRateBuffer = NULL; 873 pVRDEVoice->cbRateBufferAllocated = 0; 874 875 pVRDEVoice->pHostVoiceIn.cSamples = 2048; 876 /* Initialize the hardware info section with the audio settings */ 877 878 ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_IN_INIT); 879 880 /* Create the internal ring buffer. */ 881 IORingBufferCreate(&pVRDEVoice->pRecordedVoiceBuf, 882 pVRDEVoice->pHostVoiceIn.cSamples * sizeof(PDMHOSTSTEREOSAMPLE)); 883 884 if (!RT_VALID_PTR(pVRDEVoice->pRecordedVoiceBuf)) 200 201 VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pHstStrmOut->Props.uHz, 202 pHstStrmOut->Props.cChannels, 203 pHstStrmOut->Props.cBits, 204 pHstStrmOut->Props.fSigned); 205 206 LogFlowFunc(("hz=%d, chan=%d, cBits=%d, fSigned=%RTbool, format=%ld\n", 207 pHstStrmOut->Props.uHz, pHstStrmOut->Props.cChannels, 208 pHstStrmOut->Props.cBits, pHstStrmOut->Props.fSigned, 209 format)); 210 211 pVRDEStrmOut->old_ticks = now; 212 int cSamplesToSend = RT_MIN(live, cSamplesPlayed); 213 214 uint32_t cReadTotal = 0; 215 216 PPDMAUDIOSAMPLE pSamples; 217 uint32_t cRead; 218 int rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend, 219 &pSamples, &cRead); 220 if (RT_SUCCESS(rc)) 221 { 222 cReadTotal = cRead; 223 pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format); 224 225 if (rc == VINF_TRY_AGAIN) 885 226 { 886 LogRel(("AudioVRDE: [Input] Failed to create internal ring buffer\n")); 887 return VERR_NO_MEMORY; 227 rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend - cRead, 228 &pSamples, &cRead); 229 if (RT_SUCCESS(rc)) 230 { 231 cReadTotal += cRead; 232 pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format); 233 } 888 234 } 889 890 ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_INIT); 891 return pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEVoice, pHostVoiceIn->cSamples, 892 pHostVoiceIn->Props.uFrequency, 893 pHostVoiceIn->Props.cChannels, pHostVoiceIn->Props.cBits); 894 } 895 else if (cmd == VOICE_DISABLE) 896 { 897 LogFlow(("DrvAudioVRDE: Cmd to disable VRDE \n")); 898 pVRDEVoice->fIsInit = 0; 899 ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_IN_UNINIT); 900 IORingBufferDestroy(pVRDEVoice->pRecordedVoiceBuf); 901 pVRDEVoice->pRecordedVoiceBuf = NULL; 902 ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_UNINIT); 235 } 236 237 audioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal); 238 239 if (pcSamplesPlayed) 240 *pcSamplesPlayed = cReadTotal; 241 242 LogFlowFunc(("cSamplesToSend=%RU32, rc=%Rrc\n", cSamplesToSend, rc)); 243 return rc; 244 } 245 246 static DECLCALLBACK(int) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn) 247 { 248 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 249 AssertPtrReturn(pDrv, VERR_INVALID_POINTER); 250 251 if (pDrv->pConsoleVRDPServer) 903 252 pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL); 904 } 905 return VINF_SUCCESS; 906 } 907 908 static DECLCALLBACK(void) drvAudioVRDEGetConf(PPDMIBASE pInterface, PPDMAUDIOCONF pAudioConf) 909 { 910 LogFlow(("drvAudioVRDE: drvAudioVRDEGetConf \n")); 911 /* @todo check if szHostVoiceOut = sizeof VRDEVoice works. VRDEVoice doesn't contain HOSTVOICEOUT. */ 912 pAudioConf->szHostVoiceOut = sizeof(VRDEVoice); 913 pAudioConf->szHostVoiceIn = sizeof(VRDEVoice); 914 pAudioConf->MaxHostVoicesOut = 1; 915 pAudioConf->MaxHostVoicesIn = 1; 253 254 return VINF_SUCCESS; 255 } 256 257 static DECLCALLBACK(int) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut) 258 { 259 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 260 AssertPtrReturn(pDrv, VERR_INVALID_POINTER); 261 262 return VINF_SUCCESS; 263 } 264 265 static DECLCALLBACK(int) drvAudioVRDEControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, 266 PDMAUDIOSTREAMCMD enmStreamCmd) 267 { 268 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 269 AssertPtrReturn(pDrv, VERR_INVALID_POINTER); 270 271 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); 272 273 return VINF_SUCCESS; 274 } 275 276 static DECLCALLBACK(int) drvAudioVRDEControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn2, /** @todo Fix param types! */ 277 PDMAUDIOSTREAMCMD enmStreamCmd) 278 { 279 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3); 280 AssertPtrReturn(pDrv, VERR_INVALID_POINTER); 281 282 PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn2; 283 AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER); 284 285 PPDMAUDIOHSTSTRMIN pHstStrmIn = &pVRDEStrmIn->HstStrmIn; 286 287 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); 288 289 /* Initialize only if not already done. */ 290 if (enmStreamCmd == PDMAUDIOSTREAMCMD_ENABLE) 291 { 292 int rc2 = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEStrmIn, audioMixBufSize(&pHstStrmIn->MixBuf), 293 pHstStrmIn->Props.uHz, 294 pHstStrmIn->Props.cChannels, pHstStrmIn->Props.cBits); 295 #ifdef DEBUG 296 if (rc2 == VERR_NOT_SUPPORTED) 297 LogFlowFunc(("No RDP client connected, so no input recording supported\n")); 298 #endif 299 } 300 else if (enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE) 301 pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL /* pvUserCtx */); 302 303 return VINF_SUCCESS; 304 } 305 306 static DECLCALLBACK(int) drvAudioVRDEGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 307 { 308 pCfg->cbStreamOut = sizeof(VRDESTREAMOUT); 309 pCfg->cbStreamIn = sizeof(VRDESTREAMIN); 310 pCfg->cMaxHstStrmsOut = 1; 311 pCfg->cMaxHstStrmsIn = 2; /* Microphone in + line in. */ 312 313 return VINF_SUCCESS; 916 314 } 917 315 … … 922 320 { 923 321 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 924 PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE); 322 PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE); 323 925 324 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase); 926 325 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudioR3); … … 928 327 } 929 328 930 931 static DECLCALLBACK(void) drvAudioVRDEDestruct(PPDMDRVINS pDrvIns) 932 { 933 } 934 935 /** 936 * Construct a DirectSound Audio driver instance. 329 AudioVRDE::AudioVRDE(Console *pConsole) 330 : mpDrv(NULL), 331 mParent(pConsole) 332 { 333 } 334 335 AudioVRDE::~AudioVRDE(void) 336 { 337 if (mpDrv) 338 { 339 mpDrv->pAudioVRDE = NULL; 340 mpDrv = NULL; 341 } 342 } 343 344 int AudioVRDE::onVRDEInputIntercept(bool fIntercept) 345 { 346 LogFlowThisFunc(("fIntercept=%RTbool\n", fIntercept)); 347 return VINF_SUCCESS; /* Never veto. */ 348 } 349 350 /** 351 * Marks the beginning of sending captured audio data from a connected 352 * RDP client. 353 * 354 * @return IPRT status code. 355 * @param pvContext The context; in this case a pointer to a 356 * VRDESTREAMIN structure. 357 * @param pVRDEAudioBegin Pointer to a VRDEAUDIOINBEGIN structure. 358 */ 359 int AudioVRDE::onVRDEInputBegin(void *pvContext, PVRDEAUDIOINBEGIN pVRDEAudioBegin) 360 { 361 AssertPtrReturn(pvContext, VERR_INVALID_POINTER); 362 AssertPtrReturn(pVRDEAudioBegin, VERR_INVALID_POINTER); 363 364 PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext; 365 AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER); 366 367 VRDEAUDIOFORMAT audioFmt = pVRDEAudioBegin->fmt; 368 369 int iSampleHz = VRDE_AUDIO_FMT_SAMPLE_FREQ(audioFmt); 370 int cChannels = VRDE_AUDIO_FMT_CHANNELS(audioFmt); 371 int cBits = VRDE_AUDIO_FMT_BITS_PER_SAMPLE(audioFmt); 372 bool fUnsigned = VRDE_AUDIO_FMT_SIGNED(audioFmt); 373 374 /*pVRDEStrmIn->cbSample = VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt); 375 pVRDEStrmIn->uHz = iSampleHz;*/ 376 377 LogFlowFunc(("cbSample=%RU32, iSampleHz=%d, cChannels=%d, cBits=%d, fUnsigned=%RTbool\n", 378 VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt), iSampleHz, cChannels, cBits, fUnsigned)); 379 380 return VINF_SUCCESS; 381 } 382 383 int AudioVRDE::onVRDEInputData(void *pvContext, const void *pvData, uint32_t cbData) 384 { 385 PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext; 386 AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER); 387 388 PPDMAUDIOHSTSTRMIN pHstStrmIn = &pVRDEStrmIn->HstStrmIn; 389 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 390 391 /** @todo Use CritSect! */ 392 393 uint32_t cWritten; 394 int rc = audioMixBufWriteCirc(&pHstStrmIn->MixBuf, pvData, cbData, &cWritten); 395 if (RT_SUCCESS(rc)) 396 pVRDEStrmIn->cSamplesCaptured += cWritten; 397 398 LogFlowFunc(("cbData=%RU32, cWritten=%RU32, cSamplesCaptured=%RU32, rc=%Rrc\n", 399 cbData, cWritten, pVRDEStrmIn->cSamplesCaptured, rc)); 400 return rc; 401 } 402 403 int AudioVRDE::onVRDEInputEnd(void *pvContext) 404 { 405 NOREF(pvContext); 406 407 return VINF_SUCCESS; 408 } 409 410 /** 411 * Construct a VRDE audio driver instance. 937 412 * 938 413 * @copydoc FNPDMDRVCONSTRUCT 939 414 */ 940 DECLCALLBACK(int) AudioVRDE::drvAudioVRDEConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) 415 /* static */ 416 DECLCALLBACK(int) AudioVRDE::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) 941 417 { 942 418 PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE); 943 LogRel(("drvAudioVRDEConstruct\n")); 944 945 /* we save the address of AudioVRDE in Object node in CFGM tree and address of VRDP server in 946 * ObjectVRDPServer node. So presence of both is necessary. 947 */ 948 //if (!CFGMR3AreValuesValid(pCfg, "Object\0") || !CFGMR3AreValuesValid(pCfg, "ObjectVRDPServer\0")) 949 // return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; 419 LogRel(("Audio: Initializing VRDE driver\n")); 420 LogFlowFunc(("fFlags=0x%x\n", fFlags)); 421 950 422 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER, 951 423 ("Configuration error: Not possible to attach anything to this driver!\n"), … … 955 427 * Init the static parts. 956 428 */ 957 pThis->pDrvIns = pDrvIns; 958 gpDrvIns = pDrvIns; 429 pThis->pDrvIns = pDrvIns; 959 430 /* IBase */ 960 pDrvIns->IBase.pfnQueryInterface 961 pThis->IHostAudioR3.pfnInitIn 962 pThis->IHostAudioR3.pfnInitOut 963 pThis->IHostAudioR3.pfn DisableEnableOut = drvAudioVRDEDisableEnableOut;964 pThis->IHostAudioR3.pfn DisableEnableIn = drvAudioVRDEDisableEnableIn;965 pThis->IHostAudioR3.pfnFiniIn 966 pThis->IHostAudioR3.pfnFiniOut 967 pThis->IHostAudioR3.pfn PlayIn = drvAudioVRDEPlayIn;968 pThis->IHostAudioR3.pfnPlayOut 969 pThis->IHostAudioR3.pfnGetConf 970 pThis->IHostAudioR3.pfnInit 971 972 /* Get VRDPServer pointer */973 void *pv ;974 int rc = CFGMR3QueryPtr(pCfg, "ObjectVRDPServer", &pv );431 pDrvIns->IBase.pfnQueryInterface = drvAudioVRDEQueryInterface; 432 pThis->IHostAudioR3.pfnInitIn = drvAudioVRDEInitIn; 433 pThis->IHostAudioR3.pfnInitOut = drvAudioVRDEInitOut; 434 pThis->IHostAudioR3.pfnControlOut = drvAudioVRDEControlOut; 435 pThis->IHostAudioR3.pfnControlIn = drvAudioVRDEControlIn; 436 pThis->IHostAudioR3.pfnFiniIn = drvAudioVRDEFiniIn; 437 pThis->IHostAudioR3.pfnFiniOut = drvAudioVRDEFiniOut; 438 pThis->IHostAudioR3.pfnCaptureIn = drvAudioVRDECaptureIn; 439 pThis->IHostAudioR3.pfnPlayOut = drvAudioVRDEPlayOut; 440 pThis->IHostAudioR3.pfnGetConf = drvAudioVRDEGetConf; 441 pThis->IHostAudioR3.pfnInit = drvAudioVRDEInit; 442 443 /* Get VRDPServer pointer. */ 444 void *pvUser; 445 int rc = CFGMR3QueryPtr(pCfg, "ObjectVRDPServer", &pvUser); 975 446 if (RT_FAILURE(rc)) 976 447 { 977 AssertMsgFailed((" DrvAudioVRDE Confguration error: No/bad \"Object\" value!rc=%Rrc\n", rc));448 AssertMsgFailed(("Confguration error: No/bad \"ObjectVRDPServer\" value, rc=%Rrc\n", rc)); 978 449 return rc; 979 450 } 980 /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE */ 981 pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pv; 982 pv = NULL; 983 984 rc = CFGMR3QueryPtr(pCfg, "Object", &pv); 451 452 /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE. */ 453 pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pvUser; 454 455 pvUser = NULL; 456 rc = CFGMR3QueryPtr(pCfg, "Object", &pvUser); 985 457 if (RT_FAILURE(rc)) 986 458 { 987 AssertMsgFailed((" DrvAudioVRDE Confguration error: No/bad \"Object\" value!rc=%Rrc\n", rc));459 AssertMsgFailed(("Confguration error: No/bad \"Object\" value, rc=%Rrc\n", rc)); 988 460 return rc; 989 461 } 990 pThis->pAudioVRDE = (AudioVRDE *)pv; 462 463 pThis->pAudioVRDE = (AudioVRDE *)pvUser; 991 464 pThis->pAudioVRDE->mpDrv = pThis; 465 992 466 /* 993 * Get the interface for the above driver (DrvAudio) to make mixer/conversion calls 467 * Get the interface for the above driver (DrvAudio) to make mixer/conversion calls. 994 468 * Described in CFGM tree. 995 469 */ 996 pThis->p UpPort= PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR);997 if (!pThis->p UpPort)998 { 999 AssertMsgFailed(("Configuration error: No Audio Sniffer port interface above!\n"));470 pThis->pDrvAudio = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR); 471 if (!pThis->pDrvAudio) 472 { 473 AssertMsgFailed(("Configuration error: No upper interface specified!\n")); 1000 474 return VERR_PDM_MISSING_INTERFACE_ABOVE; 1001 475 } … … 1004 478 } 1005 479 1006 1007 /** 1008 * Char driver registration record. 1009 */ 1010 const PDMDRVREG g_DrvAudioVRDE = 1011 { 1012 PDM_DRVREG_VERSION, 1013 /* szName */ 480 /* static */ 481 DECLCALLBACK(void) AudioVRDE::drvDestruct(PPDMDRVINS pDrvIns) 482 { 483 LogFlowFuncEnter(); 484 } 485 486 /** 487 * VRDE audio driver registration record. 488 */ 489 const PDMDRVREG AudioVRDE::DrvReg = 490 { 491 PDM_DRVREG_VERSION, 492 /* szName */ 1014 493 "AudioVRDE", 1015 494 /* szRCMod */ … … 1018 497 "", 1019 498 /* pszDescription */ 1020 "Audio VRDE",499 "Audio driver for VRDE backend", 1021 500 /* fFlags */ 1022 501 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT, … … 1028 507 sizeof(DRVAUDIOVRDE), 1029 508 /* pfnConstruct */ 1030 AudioVRDE::drv AudioVRDEConstruct,509 AudioVRDE::drvConstruct, 1031 510 /* pfnDestruct */ 1032 drvAudioVRDEDestruct,511 AudioVRDE::drvDestruct, 1033 512 /* pfnRelocate */ 1034 513 NULL, … … 1055 534 }; 1056 535 1057 1058 -
trunk/src/VBox/Main/src-client/VBoxDriversRegister.cpp
r50686 r53442 71 71 if (RT_FAILURE(rc)) 72 72 return rc; 73 73 74 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 74 rc = pCallbacks->pfnRegister(pCallbacks, & g_DrvAudioVRDE);75 rc = pCallbacks->pfnRegister(pCallbacks, &AudioVRDE::DrvReg); 75 76 #else 76 77 rc = pCallbacks->pfnRegister(pCallbacks, &AudioSniffer::DrvReg);
Note:
See TracChangeset
for help on using the changeset viewer.