From ad16c317233595a6d7100ad278cd28eed180e857 Mon Sep 17 00:00:00 2001 From: Corey C Date: Fri, 15 Feb 2013 16:53:32 -0500 Subject: [PATCH] wfreerdp-server: refactored rdpsnd for multiple subsystems --- server/Windows/CMakeLists.txt | 4 + server/Windows/wf_directsound.c | 203 ++++++++++++++++++++++++++++++++ server/Windows/wf_directsound.h | 13 ++ server/Windows/wf_rdpsnd.c | 189 ++--------------------------- server/Windows/wf_rdpsnd.h | 1 - server/Windows/wf_wasapi.c | 0 server/Windows/wf_wasapi.h | 6 + 7 files changed, 235 insertions(+), 181 deletions(-) create mode 100644 server/Windows/wf_directsound.c create mode 100644 server/Windows/wf_directsound.h create mode 100644 server/Windows/wf_wasapi.c create mode 100644 server/Windows/wf_wasapi.h diff --git a/server/Windows/CMakeLists.txt b/server/Windows/CMakeLists.txt index 08ebb6563..83c606f99 100644 --- a/server/Windows/CMakeLists.txt +++ b/server/Windows/CMakeLists.txt @@ -35,6 +35,10 @@ set(${MODULE_PREFIX}_SRCS wf_peer.h wf_rdpsnd.c wf_rdpsnd.h + wf_directsound.c + wf_directsound.h + wf_wasapi.c + wf_wasapi.h wf_settings.c wf_settings.h wf_info.c diff --git a/server/Windows/wf_directsound.c b/server/Windows/wf_directsound.c new file mode 100644 index 000000000..45a576b3f --- /dev/null +++ b/server/Windows/wf_directsound.c @@ -0,0 +1,203 @@ +#include "wf_directsound.h" +#include "wf_interface.h" +#include "wf_info.h" +#include "wf_rdpsnd.h" + + +#include + +#define INITGUID +#include +#include + +#define CINTERFACE 1 +#include +#include + +IDirectSoundCapture8* cap; +IDirectSoundCaptureBuffer8* capBuf; +DSCBUFFERDESC dscbd; +DWORD lastPos; +wfPeerContext* latestPeer; + +int wf_directsound_set_latest_peer(wfPeerContext* peer) +{ + latestPeer = peer; + return 0; +} + +int wf_directsound_activate(rdpsnd_server_context* context) +{ + HRESULT hr; + + LPDIRECTSOUNDCAPTUREBUFFER pDSCB; + WAVEFORMATEX wfx = {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0}; + + + printf("RDPSND (direct sound) 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 = 176400; + 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); + lastPos = 0; + + CreateThread(NULL, 0, wf_rdpsnd_directsound_thread, latestPeer, 0, NULL); + + return 0; +} + +DWORD WINAPI wf_rdpsnd_directsound_thread(LPVOID lpParam) +{ + HRESULT hr; + DWORD beg = 0; + DWORD end = 0; + DWORD diff, rate; + wfPeerContext* context; + wfInfo* wfi; + + VOID* pbCaptureData = NULL; + DWORD dwCaptureLength = 0; + VOID* pbCaptureData2 = NULL; + DWORD dwCaptureLength2 = 0; + VOID* pbPlayData = NULL; + DWORD dwReadPos = 0; + LONG lLockSize = 0; + + wfi = wf_info_get_instance(); + + context = (wfPeerContext*)lpParam; + rate = 1000 / 24; + + _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) + { + + end = GetTickCount(); + diff = end - beg; + + if (diff < rate) + { + Sleep(rate - diff); + } + + beg = GetTickCount(); + + if (wf_rdpsnd_lock() > 0) + { + //check for main exit condition + if (wfi->snd_stop == TRUE) + { + wf_rdpsnd_unlock(); + break; + } + + hr = capBuf->lpVtbl->GetCurrentPosition(capBuf, NULL, &dwReadPos); + if (FAILED(hr)) + { + _tprintf(_T("Failed to get read pos\n")); + wf_rdpsnd_unlock(); + break; + } + + lLockSize = dwReadPos - lastPos;//dscbd.dwBufferBytes; + if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes; + + //printf("Last, read, lock = [%d, %d, %d]\n", lastPos, dwReadPos, lLockSize); + + if (lLockSize == 0) + { + wf_rdpsnd_unlock(); + continue; + } + + + hr = capBuf->lpVtbl->Lock(capBuf, lastPos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); + if (FAILED(hr)) + { + _tprintf(_T("Failed to lock sound capture buffer\n")); + wf_rdpsnd_unlock(); + break; + } + + //fwrite(pbCaptureData, 1, dwCaptureLength, pFile); + //fwrite(pbCaptureData2, 1, dwCaptureLength2, pFile); + + //FIXME: frames = bytes/(bytespersample * channels) + + context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData, dwCaptureLength/4); + context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData2, dwCaptureLength2/4); + + + hr = capBuf->lpVtbl->Unlock(capBuf, pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2); + if (FAILED(hr)) + { + _tprintf(_T("Failed to unlock sound capture buffer\n")); + wf_rdpsnd_unlock(); + return 0; + } + + //TODO keep track of location in buffer + lastPos += dwCaptureLength; + lastPos %= dscbd.dwBufferBytes; + lastPos += dwCaptureLength2; + lastPos %= dscbd.dwBufferBytes; + + wf_rdpsnd_unlock(); + } + + + } + + _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")); + capBuf->lpVtbl->Release(capBuf); + cap->lpVtbl->Release(cap); + + lastPos = 0; + + return 0; +} diff --git a/server/Windows/wf_directsound.h b/server/Windows/wf_directsound.h new file mode 100644 index 000000000..f4198f4b6 --- /dev/null +++ b/server/Windows/wf_directsound.h @@ -0,0 +1,13 @@ +#ifndef WF_DSOUND_H +#define WF_DSOUND_H + +#include +#include "wf_interface.h" + +int wf_directsound_set_latest_peer(wfPeerContext* peer); + +int wf_directsound_activate(rdpsnd_server_context* context); + +DWORD WINAPI wf_rdpsnd_directsound_thread(LPVOID lpParam); + +#endif \ No newline at end of file diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 8fffe76d5..de21e2c4b 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -3,6 +3,7 @@ * FreeRDP Windows Server (Audio Output) * * Copyright 2012 Marc-Andre Moreau + * Copyright 2013 Corey Clayton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,21 +38,16 @@ #include #include "wf_rdpsnd.h" +#include "wf_directsound.h" #include "wf_info.h" -/* - * Here are some temp things that shall be moved - * - */ -IDirectSoundCapture8* cap; -IDirectSoundCaptureBuffer8* capBuf; -DSCBUFFERDESC dscbd; -DWORD lastPos; -#define BYTESPERSEC 176400 + + +//#define BYTESPERSEC 176400 //FIXME support multiple clients -wfPeerContext* latestPeer; +//wfPeerContext* latestPeer; static const rdpsndFormat test_audio_formats[] = { @@ -69,53 +65,8 @@ 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); - lastPos = 0; - - CreateThread(NULL, 0, wf_rdpsnd_thread, latestPeer, 0, NULL); + wf_directsound_activate(context); } @@ -186,131 +137,9 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context) context->rdpsnd->Initialize(context->rdpsnd); - latestPeer = context; + wf_directsound_set_latest_peer(context); + wfi->snd_stop = FALSE; return TRUE; } -DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) -{ - HRESULT hr; - DWORD beg = 0; - DWORD end = 0; - DWORD diff, rate; - wfPeerContext* context; - wfInfo* wfi; - - VOID* pbCaptureData = NULL; - DWORD dwCaptureLength = 0; - VOID* pbCaptureData2 = NULL; - DWORD dwCaptureLength2 = 0; - VOID* pbPlayData = NULL; - DWORD dwReadPos = 0; - LONG lLockSize = 0; - - wfi = wf_info_get_instance(); - - context = (wfPeerContext*)lpParam; - rate = 1000 / 24; - - _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) - { - - end = GetTickCount(); - diff = end - beg; - - if (diff < rate) - { - Sleep(rate - diff); - } - - beg = GetTickCount(); - - if (wf_rdpsnd_lock() > 0) - { - //check for main exit condition - if (wfi->snd_stop == TRUE) - { - wf_rdpsnd_unlock(); - break; - } - - hr = capBuf->lpVtbl->GetCurrentPosition(capBuf, NULL, &dwReadPos); - if (FAILED(hr)) - { - _tprintf(_T("Failed to get read pos\n")); - wf_rdpsnd_unlock(); - break; - } - - lLockSize = dwReadPos - lastPos;//dscbd.dwBufferBytes; - if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes; - - //printf("Last, read, lock = [%d, %d, %d]\n", lastPos, dwReadPos, lLockSize); - - if (lLockSize == 0) - { - wf_rdpsnd_unlock(); - continue; - } - - - hr = capBuf->lpVtbl->Lock(capBuf, lastPos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); - if (FAILED(hr)) - { - _tprintf(_T("Failed to lock sound capture buffer\n")); - wf_rdpsnd_unlock(); - break; - } - - //fwrite(pbCaptureData, 1, dwCaptureLength, pFile); - //fwrite(pbCaptureData2, 1, dwCaptureLength2, pFile); - - //FIXME: frames = bytes/(bytespersample * channels) - - context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData, dwCaptureLength/4); - context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData2, dwCaptureLength2/4); - - - hr = capBuf->lpVtbl->Unlock(capBuf, pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2); - if (FAILED(hr)) - { - _tprintf(_T("Failed to unlock sound capture buffer\n")); - wf_rdpsnd_unlock(); - return 0; - } - - //TODO keep track of location in buffer - lastPos += dwCaptureLength; - lastPos %= dscbd.dwBufferBytes; - lastPos += dwCaptureLength2; - lastPos %= dscbd.dwBufferBytes; - - wf_rdpsnd_unlock(); - } - - - } - - _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")); - capBuf->lpVtbl->Release(capBuf); - cap->lpVtbl->Release(cap); - - lastPos = 0; - - return 0; -} diff --git a/server/Windows/wf_rdpsnd.h b/server/Windows/wf_rdpsnd.h index d54c4172d..34f952386 100644 --- a/server/Windows/wf_rdpsnd.h +++ b/server/Windows/wf_rdpsnd.h @@ -30,7 +30,6 @@ int wf_rdpsnd_lock(); int wf_rdpsnd_unlock(); BOOL wf_peer_rdpsnd_init(wfPeerContext* context); -DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam); #endif /* WF_RDPSND_H */ diff --git a/server/Windows/wf_wasapi.c b/server/Windows/wf_wasapi.c new file mode 100644 index 000000000..e69de29bb diff --git a/server/Windows/wf_wasapi.h b/server/Windows/wf_wasapi.h new file mode 100644 index 000000000..2dd709ceb --- /dev/null +++ b/server/Windows/wf_wasapi.h @@ -0,0 +1,6 @@ +#ifndef WF_WASAPI_H +#define WF_WASAPI_H + +//.. + +#endif \ No newline at end of file