From c4960d55f1b375d16b16e668a2f9dad66388e5e3 Mon Sep 17 00:00:00 2001 From: Corey C Date: Fri, 12 Oct 2012 10:37:19 -0400 Subject: [PATCH] wfreerdp-server: initial rdpsnd support --- server/Windows/CMakeLists.txt | 2 +- server/Windows/wf_rdpsnd.c | 158 ++++++++++++++++++++++++++++++++++ server/Windows/wf_rdpsnd.h | 2 + 3 files changed, 161 insertions(+), 1 deletion(-) diff --git a/server/Windows/CMakeLists.txt b/server/Windows/CMakeLists.txt index 33a5e4650..5f27d4364 100644 --- a/server/Windows/CMakeLists.txt +++ b/server/Windows/CMakeLists.txt @@ -54,7 +54,7 @@ if(WITH_WIN8) endif() -set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-channels-server) +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-channels-server dsound) if(MONOLITHIC_BUILD) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp) diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 54ea83c64..da063f50f 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -24,10 +24,27 @@ #include #include +#include +#define CINTERFACE +#include +#include + #include #include "wf_rdpsnd.h" + +/* + * Here are some temp things that shall be moved + * + */ +IDirectSoundCapture8 * cap; +IDirectSoundCaptureBuffer8* capBuf; +DSCBUFFERDESC dscbd; +DWORD capturePos; + +#define BYTESPERSEC 176400 + static const rdpsndFormat test_audio_formats[] = { { 0x11, 2, 22050, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */ @@ -44,7 +61,54 @@ static const rdpsndFormat test_audio_formats[] = static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context) { + HRESULT hr; + + LPDIRECTSOUNDCAPTUREBUFFER pDSCB; + WAVEFORMATEX wfx = {WAVE_FORMAT_PCM, 2, 44100, BYTESPERSEC, 4, 16, 0}; + + printf("RDPSND Activated\n"); + + hr = DirectSoundCaptureCreate8(NULL, &cap, NULL); + + if (FAILED(hr)) + { + _tprintf(_T("Failed to create sound capture device\n")); + return; + } + _tprintf(_T("Created sound capture device\n")); + + dscbd.dwSize = sizeof(DSCBUFFERDESC); + dscbd.dwFlags = 0; + dscbd.dwBufferBytes = BYTESPERSEC; + dscbd.dwReserved = 0; + dscbd.lpwfxFormat = &wfx; + dscbd.dwFXCount = 0; + dscbd.lpDSCFXDesc = NULL; + + hr = cap->lpVtbl->CreateCaptureBuffer(cap, &dscbd, &pDSCB, NULL); + + if (FAILED(hr)) + { + _tprintf(_T("Failed to create capture buffer\n")); + } + _tprintf(_T("Created capture buffer")); + + hr = pDSCB->lpVtbl->QueryInterface(pDSCB, &IID_IDirectSoundCaptureBuffer8, (LPVOID*)&capBuf); + if (FAILED(hr)) + { + _tprintf(_T("Failed to QI capture buffer\n")); + } + _tprintf(_T("Created IDirectSoundCaptureBuffer8\n")); + pDSCB->lpVtbl->Release(pDSCB); + + context->SelectFormat(context, 4); + context->SetVolume(context, 0x7FFF, 0x7FFF); + capturePos = 0; + + CreateThread(NULL, 0, wf_rdpsnd_thread, context, 0, NULL); + + } BOOL wf_peer_rdpsnd_init(wfPeerContext* context) @@ -67,3 +131,97 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context) return TRUE; } + +DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) +{ + HRESULT hr; + DWORD beg, end; + DWORD diff, rate; + rdpsnd_server_context* context; + + context = (rdpsnd_server_context*)lpParam; + + rate = 1000 / 5; + + _tprintf(_T("Trying to start capture\n")); + hr = capBuf->lpVtbl->Start(capBuf, DSCBSTART_LOOPING); + if (FAILED(hr)) + { + _tprintf(_T("Failed to start capture\n")); + } + _tprintf(_T("Capture started\n")); + + while (1) + { + VOID* pbCaptureData = NULL; + DWORD dwCaptureLength; + VOID* pbCaptureData2 = NULL; + DWORD dwCaptureLength2; + VOID* pbPlayData = NULL; + DWORD dwReadPos; + LONG lLockSize; + beg = GetTickCount(); + + + + hr = capBuf->lpVtbl->GetCurrentPosition(capBuf, NULL, &dwReadPos); + if (FAILED(hr)) + { + _tprintf(_T("Failed to get read pos\n")); + break; + } + + lLockSize = dwReadPos - capturePos;//dscbd.dwBufferBytes; + if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes; + + if (lLockSize == 0) continue; + + hr = capBuf->lpVtbl->Lock(capBuf, capturePos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); + if (FAILED(hr)) + { + _tprintf(_T("Failed to lock sound capture buffer\n")); + break; + } + + //fwrite(pbCaptureData, 1, dwCaptureLength, pFile); + //fwrite(pbCaptureData2, 1, dwCaptureLength2, pFile); + + //FIXME: frames = bytes/(bytespersample * channels) + + context->SendSamples(context, pbCaptureData, dwCaptureLength/4); + context->SendSamples(context, pbCaptureData2, dwCaptureLength2/4); + + + hr = capBuf->lpVtbl->Unlock(capBuf, pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2); + if (FAILED(hr)) + { + _tprintf(_T("Failed to unlock sound capture buffer\n")); + return 0; + } + + //TODO keep track of location in buffer + capturePos += dwCaptureLength; + capturePos %= dscbd.dwBufferBytes; + capturePos += dwCaptureLength2; + capturePos %= dscbd.dwBufferBytes; + + end = GetTickCount(); + diff = end - beg; + + if (diff < rate) + { + Sleep(rate - diff); + } + } + + _tprintf(_T("Trying to stop sound capture\n")); + hr = capBuf->lpVtbl->Stop(capBuf); + if (FAILED(hr)) + { + _tprintf(_T("Failed to stop capture\n")); + } + _tprintf(_T("Capture stopped\n")); + + + return 0; +} diff --git a/server/Windows/wf_rdpsnd.h b/server/Windows/wf_rdpsnd.h index 0289cd245..482cdcfd8 100644 --- a/server/Windows/wf_rdpsnd.h +++ b/server/Windows/wf_rdpsnd.h @@ -28,5 +28,7 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context); +DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam); + #endif /* WF_RDPSND_H */