Merge pull request #942 from C-o-r-E/master

mfreerdp-server: Added output sound redirection
This commit is contained in:
Marc-André Moreau 2013-01-30 17:10:21 -08:00
commit 2efb4637d4
13 changed files with 277 additions and 66 deletions

View File

@ -410,13 +410,28 @@ endif()
# Packaging
SET(CPACK_BINARY_ZIP "ON")
set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;/\\\\.gitignore;/CMakeCache.txt")
if(NOT WIN32)
set(CPACK_PACKAGE_EXECUTABLES "xfreerdp")
if(WITH_SERVER)
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "xfreerdp-server")
if(APPLE AND (NOT IOS))
#set(CPACK_PACKAGE_EXECUTABLES "mfreerdp")
if(WITH_SERVER)
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "mfreerdp-server")
endif()
endif()
if(WITH_X11)
set(CPACK_PACKAGE_EXECUTABLES "xfreerdp")
if(WITH_SERVER)
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "xfreerdp-server")
endif()
endif()
endif()
set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
@ -447,6 +462,8 @@ set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Install.bmp")
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Icon_96px.ico")
set(CPACK_NSIS_MUI_UNICON "${CMAKE_SOURCE_DIR}/resource\\\\FreeRDP_Icon_96px.ico")
set(CPACK_COMPONENTS_ALL client server libraries headers)
if(MSVC)
if(MSVC_RUNTIME STREQUAL "dynamic")
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
@ -454,26 +471,24 @@ if(MSVC)
install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT libraries)
endif()
set(EXTRA_DATA_DIR "extra/")
file(GLOB EXTRA_FILES "${CMAKE_SOURCE_DIR}/extra/*")
install(FILES ${EXTRA_FILES}
DESTINATION ${EXTRA_DATA_DIR}
COMPONENT extra)
set(EXTRA_DATA_DIR "pre-requisites/")
file(GLOB EXTRA_FILES "${CMAKE_SOURCE_DIR}/extra/*")
install(FILES ${EXTRA_FILES}
DESTINATION ${EXTRA_DATA_DIR}
COMPONENT extra)
set(REV_DATA_DIR "REV/")
file(GLOB REV_FILES "${CMAKE_SOURCE_DIR}/REV/*")
install(FILES ${REV_FILES}
DESTINATION ${REV_DATA_DIR}
COMPONENT rev)
endif()
set(REV_DATA_DIR "REV/")
file(GLOB REV_FILES "${CMAKE_SOURCE_DIR}/REV/*")
install(FILES ${REV_FILES}
DESTINATION ${REV_DATA_DIR}
COMPONENT rev)
set(CPACK_COMPONENTS_AL ${CPACK_COMPONENTS_ALL} extra rev)
endif()
set(CPACK_COMPONENTS_ALL client server libraries headers extra rev)
set(CPACK_COMPONENT_CLIENT_DISPLAY_NAME "Client")
set(CPACK_COMPONENT_CLIENT_GROUP "Applications")

View File

@ -33,6 +33,7 @@
#include <winpr/tchar.h>
#include <winpr/sysinfo.h>
#include <winpr/registry.h>
#include <winpr/tchar.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/constants.h>

View File

@ -189,7 +189,7 @@ int rpc_client_on_fragment_received_event(rdpRpc* rpc)
* combined stub data length of all remaining fragment PDUs.
*/
if ((header->response.alloc_hint == StubLength))
if (header->response.alloc_hint == StubLength)
{
rpc->StubCallId = 0;
rpc->StubFragCount = 0;

View File

@ -18,6 +18,8 @@
set(MODULE_NAME "mfreerdp-server")
set(MODULE_PREFIX "FREERDP_SERVER_MAC")
FIND_LIBRARY(AUDIO_TOOL AudioToolbox)
FIND_LIBRARY(CORE_AUDIO CoreAudio)
FIND_LIBRARY(CORE_VIDEO CoreVideo)
FIND_LIBRARY(CORE_GRAPHICS CoreGraphics)
FIND_LIBRARY(APP_SERVICES ApplicationServices)
@ -55,7 +57,9 @@ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
freerdp-server
${CORE_VIDEO}
${AUDIO_TOOL}
${CORE_AUDIO}
${CORE_VIDEO}
${CORE_GRAPHICS}
${APP_SERVICES}
${IOKIT}

View File

@ -3,6 +3,7 @@
* FreeRDP Mac OS X Server (Audio Input)
*
* 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.
@ -22,10 +23,11 @@
#include <freerdp/freerdp.h>
#include <freerdp/listener.h>
#include <freerdp/server/audin.h>
#include "mf_interface.h"
#include "mfreerdp.h"
void mf_peer_audin_init(mfPeerContext* context);
#endif /* MF_AUDIN_H */

View File

@ -26,7 +26,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <freerdp/utils/memory.h>
//#include <util.h>
#include "mf_event.h"
@ -144,7 +144,7 @@ mfEvent* mf_event_pop(mfEventQueue* event_queue)
mfEventRegion* mf_event_region_new(int x, int y, int width, int height)
{
mfEventRegion* event_region = xnew(mfEventRegion);
mfEventRegion* event_region = malloc(sizeof(mfEventRegion));
if (event_region != NULL)
{
@ -164,7 +164,7 @@ void mf_event_region_free(mfEventRegion* event_region)
mfEvent* mf_event_new(int type)
{
mfEvent* event = xnew(mfEvent);
mfEvent* event = malloc(sizeof(mfEvent));
event->type = type;
return event;
}
@ -176,7 +176,7 @@ void mf_event_free(mfEvent* event)
mfEventQueue* mf_event_queue_new()
{
mfEventQueue* event_queue = xnew(mfEventQueue);
mfEventQueue* event_queue = malloc(sizeof(mfEventQueue));
if (event_queue != NULL)
{
@ -185,7 +185,7 @@ mfEventQueue* mf_event_queue_new()
event_queue->size = 16;
event_queue->count = 0;
event_queue->events = (mfEvent**) xzalloc(sizeof(mfEvent*) * event_queue->size);
event_queue->events = (mfEvent**) malloc(sizeof(mfEvent*) * event_queue->size);
if (pipe(event_queue->pipe_fd) < 0)
printf("mf_event_queue_new: pipe failed\n");

View File

@ -23,22 +23,24 @@
#include <pthread.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/codec/nsc.h>
#include <freerdp/listener.h>
#include <freerdp/utils/stream.h>
#ifdef WITH_SERVER_CHANNELS
//#ifdef WITH_SERVER_CHANNELS
#include <freerdp/channels/wtsvc.h>
#endif
//#endif
#ifdef CHANNEL_RDPSND_SERVER
//#ifdef CHANNEL_RDPSND_SERVER
#include <freerdp/server/rdpsnd.h>
#include "mf_rdpsnd.h"
#endif
//#include "mf_rdpsnd.h"
//#endif
#ifdef CHANNEL_AUDIN_SERVER
#include "mf_audin.h"
#endif
//#ifdef CHANNEL_AUDIN_SERVER
#include <freerdp/server/audin.h>
//#include "mf_audin.h"
//#endif
typedef struct mf_info mfInfo;
typedef struct mf_peer_context mfPeerContext;
@ -55,16 +57,16 @@ struct mf_peer_context
RFX_CONTEXT* rfx_context;
NSC_CONTEXT* nsc_context;
#ifdef WITH_SERVER_CHANNELS
//#ifdef WITH_SERVER_CHANNELS
WTSVirtualChannelManager* vcm;
#endif
#ifdef CHANNEL_AUDIN_SERVER
//#endif
//#ifdef CHANNEL_AUDIN_SERVER
audin_server_context* audin;
#endif
//#endif
#ifdef CHANNEL_RDPSND_SERVER
//#ifdef CHANNEL_RDPSND_SERVER
rdpsnd_server_context* rdpsnd;
#endif
//#endif
};

View File

@ -22,7 +22,6 @@
#endif
#include <freerdp/listener.h>
#include <freerdp/utils/sleep.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/utils/stream.h>
@ -31,6 +30,7 @@
#include "mf_peer.h"
#include "mf_info.h"
#include "mf_event.h"
#include "mf_rdpsnd.h"
#include <mach/clock.h>
#include <mach/mach.h>
@ -147,6 +147,9 @@ void mf_peer_rfx_update(freerdp_peer* client)
rect.width = width;
rect.height = height;
mfp->rfx_context->width = mfi->servscreen_width;
mfp->rfx_context->height = mfi->servscreen_height;
rfx_compose_message(mfp->rfx_context, s, &rect, 1,
(BYTE*) dataBits, rect.width, rect.height, pitch);
@ -165,7 +168,7 @@ void mf_peer_rfx_update(freerdp_peer* client)
//send
update->SurfaceBits(update->context, cmd);
update->SurfaceBits(update->context, cmd);
//clean up
@ -198,9 +201,9 @@ void mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
context->s = stream_new(0xFFFF);
#ifdef WITH_SERVER_CHANNELS
//#ifdef WITH_SERVER_CHANNELS
context->vcm = WTSCreateVirtualChannelManager(client);
#endif
//#endif
mf_info_peer_register(context->info, context);
}
@ -225,14 +228,15 @@ void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context)
audin_server_context_free(context->audin);
#endif
#ifdef CHANNEL_RDPSND_SERVER
//#ifdef CHANNEL_RDPSND_SERVER
mf_peer_rdpsnd_stop();
if (context->rdpsnd)
rdpsnd_server_context_free(context->rdpsnd);
#endif
//#endif
#ifdef WITH_SERVER_CHANNELS
//#ifdef WITH_SERVER_CHANNELS
WTSDestroyVirtualChannelManager(context->vcm);
#endif
//#endif
}
}
@ -252,7 +256,7 @@ void mf_peer_init(freerdp_peer* client)
if(info_timer)
{
//printf("created timer\n");
dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 33ull * NSEC_PER_MSEC, 100ull * NSEC_PER_MSEC);
dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 42ull * NSEC_PER_MSEC, 100ull * NSEC_PER_MSEC);
dispatch_source_set_event_handler(info_timer, ^{
//printf("dispatch\n");
mfEvent* event = mf_event_new(MF_EVENT_TYPE_FRAME_TICK);
@ -265,10 +269,10 @@ void mf_peer_init(freerdp_peer* client)
BOOL mf_peer_post_connect(freerdp_peer* client)
{
//mfPeerContext* context = (mfPeerContext*) client->context;
mfPeerContext* context = (mfPeerContext*) client->context;
rdpSettings* settings = client->settings;
printf("Client %s is activated\n", client->hostname);
printf("Client %s post connect\n", client->hostname);
if (client->settings->AutoLogonEnabled)
{
@ -300,27 +304,24 @@ BOOL mf_peer_post_connect(freerdp_peer* client)
client->update->DesktopResize(client->update->context);
/*printf("Client requested desktop: %dx%dx%d\n",
client->settings->DesktopWidth, client->settings->DesktopHeight, client->settings->ColorDepth);
*/
#ifdef WITH_SERVER_CHANNELS
//#ifdef WITH_SERVER_CHANNELS
/* Iterate all channel names requested by the client and activate those supported by the server */
int i;
for (i = 0; i < client->settings->ChannelCount; i++)
{
if (client->settings->ChannelDefArray[i].joined)
{
#ifdef CHANNEL_RDPSND_SERVER
//#ifdef CHANNEL_RDPSND_SERVER
if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpsnd", 6) == 0)
{
mf_peer_rdpsnd_init(context); /* Audio Output */
}
#endif
//#endif
}
}
/* Dynamic Virtual Channels */
#endif
//#endif
#ifdef CHANNEL_AUDIN_SERVER
mf_peer_audin_init(context); /* Audio Input */
@ -333,7 +334,7 @@ BOOL mf_peer_post_connect(freerdp_peer* client)
BOOL mf_peer_activate(freerdp_peer* client)
{
mfPeerContext* context = (mfPeerContext*) client->context;
rfx_context_reset(context->rfx_context);
context->activated = TRUE;
@ -374,10 +375,12 @@ void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
state_down = TRUE;
}
/*
CGEventRef event;
event = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, state_down);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
*/
}
void mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
@ -511,6 +514,7 @@ void* mf_peer_main_loop(void* arg)
client->settings->PrivateKeyFile = _strdup("server.key");
client->settings->NlaSecurity = FALSE;
client->settings->RemoteFxCodec = TRUE;
client->settings->ColorDepth = 32;
client->settings->SuppressOutput = TRUE;
client->settings->RefreshRect = FALSE;
@ -546,9 +550,9 @@ void* mf_peer_main_loop(void* arg)
break;
}
#ifdef WITH_SERVER_CHANNELS
//#ifdef WITH_SERVER_CHANNELS
WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount);
#endif
//#endif
max_fds = 0;
FD_ZERO(&rfds_set);
@ -591,10 +595,10 @@ void* mf_peer_main_loop(void* arg)
}
#ifdef WITH_SERVER_CHANNELS
//#ifdef WITH_SERVER_CHANNELS
if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
break;
#endif
//#endif
}

View File

@ -23,8 +23,11 @@
#include <freerdp/server/audin.h>
#include "mf_info.h"
#include "mf_rdpsnd.h"
AQRecorderState recorderState;
static const rdpsndFormat audio_formats[] =
{
{ 0x11, 2, 22050, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */
@ -42,10 +45,82 @@ static const rdpsndFormat audio_formats[] =
static void mf_peer_rdpsnd_activated(rdpsnd_server_context* context)
{
printf("RDPSND Activated\n");
printf("Let's create an audio queue for input!\n");
OSStatus status;
recorderState.dataFormat.mSampleRate = 44100.0;
recorderState.dataFormat.mFormatID = kAudioFormatLinearPCM;
recorderState.dataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
recorderState.dataFormat.mBytesPerPacket = 4;
recorderState.dataFormat.mFramesPerPacket = 1;
recorderState.dataFormat.mBytesPerFrame = 4;
recorderState.dataFormat.mChannelsPerFrame = 2;
recorderState.dataFormat.mBitsPerChannel = 16;
recorderState.snd_context = context;
status = AudioQueueNewInput(&recorderState.dataFormat,
mf_peer_rdpsnd_input_callback,
&recorderState,
NULL,
kCFRunLoopCommonModes,
0,
&recorderState.queue);
if (status != noErr)
{
printf("Failed to create a new Audio Queue. Status code: %d\n", status);
}
UInt32 dataFormatSize = sizeof (recorderState.dataFormat);
AudioQueueGetProperty(recorderState.queue,
kAudioConverterCurrentInputStreamDescription,
&recorderState.dataFormat,
&dataFormatSize);
mf_rdpsnd_derive_buffer_size(recorderState.queue, &recorderState.dataFormat, 0.05, &recorderState.bufferByteSize);
printf("Preparing a set of buffers...");
for (int i = 0; i < snd_numBuffers; ++i)
{
AudioQueueAllocateBuffer(recorderState.queue,
recorderState.bufferByteSize,
&recorderState.buffers[i]);
AudioQueueEnqueueBuffer(recorderState.queue,
recorderState.buffers[i],
0,
NULL);
}
printf("done\n");
printf("recording...\n");
recorderState.currentPacket = 0;
recorderState.isRunning = true;
context->SelectFormat(context, 4);
context->SetVolume(context, 0x7FFF, 0x7FFF);
AudioQueueStart (recorderState.queue, NULL);
}
BOOL mf_peer_rdpsnd_init(mfPeerContext* context)
{
//printf("RDPSND INIT\n");
context->rdpsnd = rdpsnd_server_context_new(context->vcm);
context->rdpsnd->data = context;
@ -63,3 +138,75 @@ BOOL mf_peer_rdpsnd_init(mfPeerContext* context)
return TRUE;
}
BOOL mf_peer_rdpsnd_stop()
{
recorderState.isRunning = false;
AudioQueueStop(recorderState.queue, true);
return TRUE;
}
void mf_peer_rdpsnd_input_callback (void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumberPacketDescriptions,
const AudioStreamPacketDescription *inPacketDescs)
{
OSStatus status;
AQRecorderState * rState;
rState = inUserData;
if (inNumberPacketDescriptions == 0 && rState->dataFormat.mBytesPerPacket != 0)
{
inNumberPacketDescriptions = inBuffer->mAudioDataByteSize / rState->dataFormat.mBytesPerPacket;
}
if (rState->isRunning == 0)
{
return ;
}
rState->snd_context->SendSamples(rState->snd_context, inBuffer->mAudioData, inBuffer->mAudioDataByteSize/4);
status = AudioQueueEnqueueBuffer(
rState->queue,
inBuffer,
0,
NULL);
if (status != noErr)
{
printf("AudioQueueEnqueueBuffer() returned status = %d\n", status);
}
}
void mf_rdpsnd_derive_buffer_size (AudioQueueRef audioQueue,
AudioStreamBasicDescription *ASBDescription,
Float64 seconds,
UInt32 *outBufferSize)
{
static const int maxBufferSize = 0x50000;
int maxPacketSize = ASBDescription->mBytesPerPacket;
if (maxPacketSize == 0)
{
UInt32 maxVBRPacketSize = sizeof(maxPacketSize);
AudioQueueGetProperty (audioQueue,
kAudioQueueProperty_MaximumOutputPacketSize,
// in Mac OS X v10.5, instead use
// kAudioConverterPropertyMaximumOutputPacketSize
&maxPacketSize,
&maxVBRPacketSize
);
}
Float64 numBytesForTime =
ASBDescription->mSampleRate * maxPacketSize * seconds;
*outBufferSize = (UInt32) (numBytesForTime < maxBufferSize ? numBytesForTime : maxBufferSize);
}

View File

@ -20,13 +20,47 @@
#ifndef MF_RDPSND_H
#define MF_RDPSND_H
#include <CoreAudio/CoreAudio.h>
#include <AudioToolbox/AudioToolbox.h>
#include <freerdp/freerdp.h>
#include <freerdp/listener.h>
#include <freerdp/server/rdpsnd.h>
#include "mf_interface.h"
#include "mfreerdp.h"
void mf_rdpsnd_derive_buffer_size (AudioQueueRef audioQueue,
AudioStreamBasicDescription *ASBDescription,
Float64 seconds,
UInt32 *outBufferSize);
void mf_peer_rdpsnd_input_callback (void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumberPacketDescriptions,
const AudioStreamPacketDescription *inPacketDescs);
static const int snd_numBuffers = 3;
struct _AQRecorderState
{
AudioStreamBasicDescription dataFormat;
AudioQueueRef queue;
AudioQueueBufferRef buffers[snd_numBuffers];
AudioFileID audioFile;
UInt32 bufferByteSize;
SInt64 currentPacket;
bool isRunning;
rdpsnd_server_context* snd_context;
};
typedef struct _AQRecorderState AQRecorderState;
BOOL mf_peer_rdpsnd_init(mfPeerContext* context);
BOOL mf_peer_rdpsnd_stop();
#endif /* MF_RDPSND_H */

View File

@ -35,8 +35,8 @@
#include <winpr/crt.h>
#include <freerdp/constants.h>
#include <freerdp/utils/sleep.h>
#include <freerdp/utils/memory.h>
//#include <freerdp/utils/sleep.h>
//#include <freerdp/utils/memory.h>
#include "mfreerdp.h"
#include "mf_peer.h"

View File

@ -202,6 +202,7 @@ void wf_update_encoder_reset(wfInfo* wfi)
wfi->rfx_context->width = wfi->servscreen_width;
wfi->rfx_context->height = wfi->servscreen_height;
rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
rfx_context_set_cpu_opt(wfi->rfx_context, CPU_SSE2);
wfi->s = stream_new(0xFFFF);
}

View File

@ -29,7 +29,8 @@
#include <winpr/synch.h>
#include "synch.h"
#include "thread.h"
#include "../thread/thread.h"
#include <winpr/thread.h>
/**
* WaitForSingleObject