wfreerdp-server: refactored rdpsnd for multiple subsystems
This commit is contained in:
parent
29b94e6787
commit
ad16c31723
@ -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
|
||||
|
203
server/Windows/wf_directsound.c
Normal file
203
server/Windows/wf_directsound.c
Normal file
@ -0,0 +1,203 @@
|
||||
#include "wf_directsound.h"
|
||||
#include "wf_interface.h"
|
||||
#include "wf_info.h"
|
||||
#include "wf_rdpsnd.h"
|
||||
|
||||
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#define INITGUID
|
||||
#include <initguid.h>
|
||||
#include <objbase.h>
|
||||
|
||||
#define CINTERFACE 1
|
||||
#include <mmsystem.h>
|
||||
#include <dsound.h>
|
||||
|
||||
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;
|
||||
}
|
13
server/Windows/wf_directsound.h
Normal file
13
server/Windows/wf_directsound.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef WF_DSOUND_H
|
||||
#define WF_DSOUND_H
|
||||
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
#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
|
@ -3,6 +3,7 @@
|
||||
* FreeRDP Windows Server (Audio Output)
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2013 Corey Clayton <can.of.tuna@gmail.com>
|
||||
*
|
||||
* 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 <freerdp/server/rdpsnd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
0
server/Windows/wf_wasapi.c
Normal file
0
server/Windows/wf_wasapi.c
Normal file
6
server/Windows/wf_wasapi.h
Normal file
6
server/Windows/wf_wasapi.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef WF_WASAPI_H
|
||||
#define WF_WASAPI_H
|
||||
|
||||
//..
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user