BOOL wf_peer_rdpsnd_init(wfPeerContext* context) { wfInfo* wfi; wfi = wf_info_get_instance(); wfi->snd_mutex = CreateMutex(NULL, FALSE, NULL); context->rdpsnd = rdpsnd_server_context_new(context->vcm); context->rdpsnd->data = context; context->rdpsnd->server_formats = test_audio_formats; context->rdpsnd->num_server_formats = sizeof(test_audio_formats) / sizeof(test_audio_formats[0]); context->rdpsnd->src_format.wFormatTag = 1; context->rdpsnd->src_format.nChannels = 2; context->rdpsnd->src_format.nSamplesPerSec = 44100; context->rdpsnd->src_format.wBitsPerSample = 16; context->rdpsnd->Activated = wf_peer_rdpsnd_activated; context->rdpsnd->Initialize(context->rdpsnd); wf_rdpsnd_set_latest_peer(context); wfi->snd_stop = FALSE; return TRUE; }
FREERDP_API UINT32 wfreerdp_server_num_peers() { wfInfo* wfi; wfi = wf_info_get_instance(); return wfi->peerCount; }
int wf_rdpsnd_lock() { DWORD dRes; wfInfo* wfi; wfi = wf_info_get_instance(); dRes = WaitForSingleObject(wfi->snd_mutex, INFINITE); switch (dRes) { case WAIT_ABANDONED: case WAIT_OBJECT_0: return TRUE; break; case WAIT_TIMEOUT: return FALSE; break; case WAIT_FAILED: printf("wf_rdpsnd_lock failed with 0x%08X\n", GetLastError()); return -1; break; } return -1; }
DWORD WINAPI wf_server_main_loop(LPVOID lpParam) { int i, fds; int rcount; int max_fds; void* rfds[32]; fd_set rfds_set; freerdp_listener* instance; wfInfo* wfi; wfi = wf_info_get_instance(); wfi->force_all_disconnect = FALSE; ZeroMemory(rfds, sizeof(rfds)); instance = (freerdp_listener*) lpParam; while(wfi->force_all_disconnect == FALSE) { rcount = 0; if (instance->GetFileDescriptor(instance, rfds, &rcount) != TRUE) { printf("Failed to get FreeRDP file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; select(max_fds + 1, &rfds_set, NULL, NULL, NULL); if (instance->CheckFileDescriptor(instance) != TRUE) { printf("Failed to check FreeRDP file descriptor\n"); break; } } printf("wf_server_main_loop terminating\n"); instance->Close(instance); return 0; }
void set_screen_id(int id) { wfInfo* wfi; wfi = wf_info_get_instance(); wfi->screenID = id; return; }
BOOL wfreerdp_server_stop(wfServer* server) { wfInfo* wfi; wfi = wf_info_get_instance(); WLog_INFO(TAG, "Stopping server"); wfi->force_all_disconnect = TRUE; server->instance->Close(server->instance); return TRUE; }
int wf_directsound_activate(RdpsndServerContext* context) { HRESULT hr; wfInfo* wfi; LPDIRECTSOUNDCAPTUREBUFFER pDSCB; wfi = wf_info_get_instance(); if (!wfi) { WLog_ERR(TAG, "Failed to wfi instance"); return 1; } WLog_DBG(TAG, "RDPSND (direct sound) Activated"); hr = DirectSoundCaptureCreate8(NULL, &cap, NULL); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to create sound capture device"); return 1; } WLog_INFO(TAG, "Created sound capture device"); dscbd.dwSize = sizeof(DSCBUFFERDESC); dscbd.dwFlags = 0; dscbd.dwBufferBytes = wfi->agreed_format->nAvgBytesPerSec; dscbd.dwReserved = 0; dscbd.lpwfxFormat = wfi->agreed_format; dscbd.dwFXCount = 0; dscbd.lpDSCFXDesc = NULL; hr = cap->lpVtbl->CreateCaptureBuffer(cap, &dscbd, &pDSCB, NULL); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to create capture buffer"); } WLog_INFO(TAG, "Created capture buffer"); hr = pDSCB->lpVtbl->QueryInterface(pDSCB, &IID_IDirectSoundCaptureBuffer8, (LPVOID*)&capBuf); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to QI capture buffer"); } WLog_INFO(TAG, "Created IDirectSoundCaptureBuffer8"); pDSCB->lpVtbl->Release(pDSCB); lastPos = 0; CreateThread(NULL, 0, wf_rdpsnd_directsound_thread, latestPeer, 0, NULL); return 0; }
int wf_rdpsnd_unlock() { wfInfo* wfi; wfi = wf_info_get_instance(); if (ReleaseMutex(wfi->snd_mutex) == 0) { WLog_DBG(TAG, "wf_rdpsnd_unlock failed with 0x%08lX", GetLastError()); return -1; } return TRUE; }
static void wf_peer_rdpsnd_activated(RdpsndServerContext* context) { wfInfo* wfi; int i, j; wfi = wf_info_get_instance(); wfi->agreed_format = NULL; WLog_DBG(TAG, "Client supports the following %d formats:", context->num_client_formats); for (i = 0; i < context->num_client_formats; i++) { //TODO: improve the way we agree on a format for (j = 0; j < context->num_server_formats; j++) { if ((context->client_formats[i].wFormatTag == context->server_formats[j].wFormatTag) && (context->client_formats[i].nChannels == context->server_formats[j].nChannels) && (context->client_formats[i].nSamplesPerSec == context->server_formats[j].nSamplesPerSec)) { WLog_DBG(TAG, "agreed on format!"); wfi->agreed_format = (AUDIO_FORMAT*) &context->server_formats[j]; break; } } if (wfi->agreed_format != NULL) break; } if (wfi->agreed_format == NULL) { WLog_ERR(TAG, "Could not agree on a audio format with the server"); return; } context->SelectFormat(context, i); context->SetVolume(context, 0x7FFF, 0x7FFF); #ifdef WITH_RDPSND_DSOUND wf_directsound_activate(context); #else wf_wasapi_activate(context); #endif }
BOOL wf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { if ((flags & PTR_XFLAGS_BUTTON1) || (flags & PTR_XFLAGS_BUTTON2)) { INPUT mouse_event; ZeroMemory(&mouse_event, sizeof(INPUT)); mouse_event.type = INPUT_MOUSE; if (flags & PTR_FLAGS_MOVE) { float width, height; wfInfo* wfi; wfi = wf_info_get_instance(); if (!wfi) return FALSE; //width and height of primary screen (even in multimon setups width = (float) GetSystemMetrics(SM_CXSCREEN); height = (float) GetSystemMetrics(SM_CYSCREEN); x += wfi->servscreen_xoffset; y += wfi->servscreen_yoffset; mouse_event.mi.dx = (LONG)((float) x * (65535.0f / width)); mouse_event.mi.dy = (LONG)((float) y * (65535.0f / height)); mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; SendInput(1, &mouse_event, sizeof(INPUT)); } mouse_event.mi.dx = mouse_event.mi.dy = mouse_event.mi.dwFlags = 0; if (flags & PTR_XFLAGS_DOWN) mouse_event.mi.dwFlags |= MOUSEEVENTF_XDOWN; else mouse_event.mi.dwFlags |= MOUSEEVENTF_XUP; if (flags & PTR_XFLAGS_BUTTON1) mouse_event.mi.mouseData = XBUTTON1; else if (flags & PTR_XFLAGS_BUTTON2) mouse_event.mi.mouseData = XBUTTON2; SendInput(1, &mouse_event, sizeof(INPUT)); } else { wf_peer_mouse_event(input, flags, x, y); } return TRUE; }
BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { wfInfo * wfi; wfi = wf_info_get_instance(); if(_IDcount == wfi->screenID) { wfi->servscreen_xoffset = lprcMonitor->left; wfi->servscreen_yoffset = lprcMonitor->top; } _IDcount++; return TRUE; }
FREERDP_API BOOL wfreerdp_server_peer_is_authenticated(int pId) { wfInfo* wfi; freerdp_peer* peer; wfi = wf_info_get_instance(); peer = wfi->peers[pId]; if (peer) { return peer->authenticated; } else { return FALSE; } }
BOOL wf_peer_context_new(freerdp_peer* client, wfPeerContext* context) { if (!(context->info = wf_info_get_instance())) return FALSE; context->vcm = WTSOpenServerA((LPSTR) client->context); if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE) return FALSE; if (!wf_info_peer_register(context->info, context)) { WTSCloseServer(context->vcm); context->vcm = NULL; return FALSE; } return TRUE; }
FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId) { wfInfo* wfi; freerdp_peer* peer; wfi = wf_info_get_instance(); if (!wfi) return FALSE; peer = wfi->peers[pId]; if (peer) { return peer->local; } else { return FALSE; } }
FREERDP_API UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) { wfInfo* wfi; freerdp_peer* peer; wfi = wf_info_get_instance(); peer = wfi->peers[pId]; if (peer) { UINT32 sLen; sLen = strnlen_s(peer->hostname, 50); swprintf(dstStr, 50, L"%hs", peer->hostname); return sLen; } else { printf("nonexistent peer id=%d\n", pId); return 0; } }
BOOL wf_peer_rdpsnd_init(wfPeerContext* context) { wfInfo* wfi = wf_info_get_instance(); if (!wfi) return FALSE; if (!(wfi->snd_mutex = CreateMutex(NULL, FALSE, NULL))) return FALSE; context->rdpsnd = rdpsnd_server_context_new(context->vcm); context->rdpsnd->rdpcontext = &context->_p; context->rdpsnd->data = context; context->rdpsnd->num_server_formats = server_rdpsnd_get_formats(&context->rdpsnd->server_formats); if (context->rdpsnd->num_server_formats > 0) context->rdpsnd->src_format = &context->rdpsnd->server_formats[0]; context->rdpsnd->Activated = wf_peer_rdpsnd_activated; context->rdpsnd->Initialize(context->rdpsnd, TRUE); wf_rdpsnd_set_latest_peer(context); wfi->snd_stop = FALSE; return TRUE; }
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context) { context->info = wf_info_get_instance(); context->vcm = WTSOpenServerA((LPSTR) client->context); wf_info_peer_register(context->info, context); }
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, (UINT16)(beg & 0xffff)); context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData2, dwCaptureLength2/4, (UINT16)(beg & 0xffff)); 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; }
DWORD WINAPI wf_rdpsnd_wasapi_thread(LPVOID lpParam) { IMMDeviceEnumerator *pEnumerator = NULL; IMMDevice *pDevice = NULL; IAudioClient *pAudioClient = NULL; IAudioCaptureClient *pCaptureClient = NULL; WAVEFORMATEX *pwfx = NULL; HRESULT hr; REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC; REFERENCE_TIME hnsActualDuration; UINT32 bufferFrameCount; UINT32 numFramesAvailable; UINT32 packetLength = 0; UINT32 dCount = 0; BYTE *pData; wfPeerContext* context; wfInfo* wfi; wfi = wf_info_get_instance(); context = (wfPeerContext*)lpParam; CoInitialize(NULL); hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void **) &pEnumerator); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to cocreate device enumerator"); exit(1); } hr = pEnumerator->lpVtbl->GetDevice(pEnumerator, devStr, &pDevice); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to cocreate get device"); exit(1); } hr = pDevice->lpVtbl->Activate(pDevice, &IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&pAudioClient); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to activate audio client"); exit(1); } hr = pAudioClient->lpVtbl->GetMixFormat(pAudioClient, &pwfx); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to get mix format"); exit(1); } pwfx->wFormatTag = wfi->agreed_format->wFormatTag; pwfx->nChannels = wfi->agreed_format->nChannels; pwfx->nSamplesPerSec = wfi->agreed_format->nSamplesPerSec; pwfx->nAvgBytesPerSec = wfi->agreed_format->nAvgBytesPerSec; pwfx->nBlockAlign = wfi->agreed_format->nBlockAlign; pwfx->wBitsPerSample = wfi->agreed_format->wBitsPerSample; pwfx->cbSize = wfi->agreed_format->cbSize; hr = pAudioClient->lpVtbl->Initialize( pAudioClient, AUDCLNT_SHAREMODE_SHARED, 0, hnsRequestedDuration, 0, pwfx, NULL); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to initialize the audio client"); exit(1); } hr = pAudioClient->lpVtbl->GetBufferSize(pAudioClient, &bufferFrameCount); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to get buffer size"); exit(1); } hr = pAudioClient->lpVtbl->GetService(pAudioClient, &IID_IAudioCaptureClient, (void **) &pCaptureClient); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to get the capture client"); exit(1); } hnsActualDuration = (UINT32)REFTIMES_PER_SEC * bufferFrameCount / pwfx->nSamplesPerSec; hr = pAudioClient->lpVtbl->Start(pAudioClient); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to start capture"); exit(1); } dCount = 0; while (wfi->snd_stop == FALSE) { DWORD flags; Sleep(hnsActualDuration/REFTIMES_PER_MILLISEC/2); hr = pCaptureClient->lpVtbl->GetNextPacketSize(pCaptureClient, &packetLength); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to get packet length"); exit(1); } while (packetLength != 0) { hr = pCaptureClient->lpVtbl->GetBuffer(pCaptureClient, &pData, &numFramesAvailable, &flags, NULL, NULL); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to get buffer"); exit(1); } //Here we are writing the audio data //not sure if this flag is ever set by the system; msdn is not clear about it if (!(flags & AUDCLNT_BUFFERFLAGS_SILENT)) context->rdpsnd->SendSamples(context->rdpsnd, pData, packetLength, (UINT16)(GetTickCount() & 0xffff)); hr = pCaptureClient->lpVtbl->ReleaseBuffer(pCaptureClient, numFramesAvailable); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to release buffer"); exit(1); } hr = pCaptureClient->lpVtbl->GetNextPacketSize(pCaptureClient, &packetLength); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to get packet length"); exit(1); } } } pAudioClient->lpVtbl->Stop(pAudioClient); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to stop audio client"); exit(1); } CoTaskMemFree(pwfx); if (pEnumerator != NULL) pEnumerator->lpVtbl->Release(pEnumerator); if (pDevice != NULL) pDevice->lpVtbl->Release(pDevice); if (pAudioClient != NULL) pAudioClient->lpVtbl->Release(pAudioClient); if (pCaptureClient != NULL) pCaptureClient->lpVtbl->Release(pCaptureClient); CoUninitialize(); return 0; }
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context) { context->info = wf_info_get_instance(); wf_info_peer_register(context->info, context); }
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context) { context->info = wf_info_get_instance(); context->vcm = WTSCreateVirtualChannelManager(client); wf_info_peer_register(context->info, context); }
void wf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) { INPUT mouse_event; float width, height; ZeroMemory(&mouse_event, sizeof(INPUT)); mouse_event.type = INPUT_MOUSE; if (flags & PTR_FLAGS_WHEEL) { mouse_event.mi.dwFlags = MOUSEEVENTF_WHEEL; mouse_event.mi.mouseData = flags & WheelRotationMask; if (flags & PTR_FLAGS_WHEEL_NEGATIVE) mouse_event.mi.mouseData *= -1; SendInput(1, &mouse_event, sizeof(INPUT)); } else { wfInfo * wfi; wfi = wf_info_get_instance(); //width and height of primary screen (even in multimon setups width = (float) GetSystemMetrics(SM_CXSCREEN); height = (float) GetSystemMetrics(SM_CYSCREEN); x += wfi->servscreen_xoffset; y += wfi->servscreen_yoffset; mouse_event.mi.dx = (LONG) ((float) x * (65535.0f / width)); mouse_event.mi.dy = (LONG) ((float) y * (65535.0f / height)); mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE; if (flags & PTR_FLAGS_MOVE) { mouse_event.mi.dwFlags |= MOUSEEVENTF_MOVE; SendInput(1, &mouse_event, sizeof(INPUT)); } mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE; if (flags & PTR_FLAGS_BUTTON1) { if (flags & PTR_FLAGS_DOWN) mouse_event.mi.dwFlags |= MOUSEEVENTF_LEFTDOWN; else mouse_event.mi.dwFlags |= MOUSEEVENTF_LEFTUP; SendInput(1, &mouse_event, sizeof(INPUT)); } else if (flags & PTR_FLAGS_BUTTON2) { if (flags & PTR_FLAGS_DOWN) mouse_event.mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN; else mouse_event.mi.dwFlags |= MOUSEEVENTF_RIGHTUP; SendInput(1, &mouse_event, sizeof(INPUT)); } else if (flags & PTR_FLAGS_BUTTON3) { if (flags & PTR_FLAGS_DOWN) mouse_event.mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN; else mouse_event.mi.dwFlags |= MOUSEEVENTF_MIDDLEUP; SendInput(1, &mouse_event, sizeof(INPUT)); } } }