diff --git a/.gitignore b/.gitignore index 10fe97360..cafaa421d 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ client/X11/xfreerdp.1 # Mac OS X .DS_Store *.xcodeproj/ +DerivedData/ # Windows *.vcxproj diff --git a/CMakeLists.txt b/CMakeLists.txt index 290b7d6c3..0f9d6697c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,7 +209,7 @@ if(ANDROID) message(STATUS "FREERDP_ANDROID_EXTERNAL_SSL_PATH not set! - Needs to be set if openssl is not found in the android NDK (which usually isn't)") endif() set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_ANDROID_EXTERNAL_SSL_PATH}) - set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/libs/${ANDROID_ABI}) + set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/FreeRDPCore/libs/${ANDROID_ABI}) endif() set(CMAKE_THREAD_PREFER_PTHREAD TRUE) diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c index 33c852057..11f31e420 100644 --- a/channels/audin/client/alsa/audin_alsa.c +++ b/channels/audin/client/alsa/audin_alsa.c @@ -31,8 +31,9 @@ #include #include -#include +#include #include +#include #include "audin_main.h" @@ -73,15 +74,12 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand snd_strerror(error)); return FALSE; } + snd_pcm_hw_params_any(capture_handle, hw_params); - snd_pcm_hw_params_set_access(capture_handle, hw_params, - SND_PCM_ACCESS_RW_INTERLEAVED); - snd_pcm_hw_params_set_format(capture_handle, hw_params, - alsa->format); - snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, - &alsa->actual_rate, NULL); - snd_pcm_hw_params_set_channels_near(capture_handle, hw_params, - &alsa->actual_channels); + snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_format(capture_handle, hw_params, alsa->format); + snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &alsa->actual_rate, NULL); + snd_pcm_hw_params_set_channels_near(capture_handle, hw_params, &alsa->actual_channels); snd_pcm_hw_params(capture_handle, hw_params); snd_pcm_hw_params_free(hw_params); snd_pcm_prepare(capture_handle); @@ -94,6 +92,7 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand alsa->actual_rate, alsa->actual_channels, alsa->target_rate, alsa->target_channels); } + return TRUE; } @@ -133,20 +132,25 @@ static BOOL audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size break; cframes = alsa->frames_per_packet - alsa->buffer_frames; + if (cframes > frames) cframes = frames; - memcpy(alsa->buffer + alsa->buffer_frames * tbytes_per_frame, - src, cframes * tbytes_per_frame); + + CopyMemory(alsa->buffer + alsa->buffer_frames * tbytes_per_frame, src, cframes * tbytes_per_frame); + alsa->buffer_frames += cframes; + if (alsa->buffer_frames >= alsa->frames_per_packet) { - if (alsa->wformat == 0x11) + if (alsa->wformat == WAVE_FORMAT_DVI_ADPCM) { alsa->dsp_context->encode_ima_adpcm(alsa->dsp_context, alsa->buffer, alsa->buffer_frames * tbytes_per_frame, alsa->target_channels, alsa->block_size); + encoded_data = alsa->dsp_context->adpcm_buffer; encoded_size = alsa->dsp_context->adpcm_size; + DEBUG_DVC("encoded %d to %d", alsa->buffer_frames * tbytes_per_frame, encoded_size); } @@ -162,11 +166,16 @@ static BOOL audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size frames = 0; } else + { ret = alsa->receive(encoded_data, encoded_size, alsa->user_data); + } + alsa->buffer_frames = 0; + if (!ret) break; } + src += cframes * tbytes_per_frame; frames -= cframes; } @@ -225,8 +234,10 @@ static void* audin_alsa_thread_func(void* arg) } while (0); free(buffer); + free(alsa->buffer); alsa->buffer = NULL; + if (capture_handle) snd_pcm_close(capture_handle); @@ -253,7 +264,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma { switch (format->wFormatTag) { - case 1: /* PCM */ + case WAVE_FORMAT_PCM: if (format->cbSize == 0 && (format->nSamplesPerSec <= 48000) && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && @@ -263,7 +274,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma } break; - case 0x11: /* IMA ADPCM */ + case WAVE_FORMAT_DVI_ADPCM: if ((format->nSamplesPerSec <= 48000) && (format->wBitsPerSample == 4) && (format->nChannels == 1 || format->nChannels == 2)) @@ -272,6 +283,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma } break; } + return FALSE; } @@ -284,9 +296,10 @@ static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN alsa->actual_rate = format->nSamplesPerSec; alsa->target_channels = format->nChannels; alsa->actual_channels = format->nChannels; + switch (format->wFormatTag) { - case 1: /* PCM */ + case WAVE_FORMAT_PCM: switch (format->wBitsPerSample) { case 8: @@ -300,7 +313,7 @@ static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN } break; - case 0x11: /* IMA ADPCM */ + case WAVE_FORMAT_DVI_ADPCM: alsa->format = SND_PCM_FORMAT_S16_LE; alsa->bytes_per_channel = 2; bs = (format->nBlockAlign - 4 * format->nChannels) * 4; @@ -310,6 +323,7 @@ static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN alsa->frames_per_packet); break; } + alsa->wformat = format->wFormatTag; alsa->block_size = format->nBlockAlign; } diff --git a/channels/audin/client/pulse/audin_pulse.c b/channels/audin/client/pulse/audin_pulse.c index 75b1e4cdf..2d4906ea2 100644 --- a/channels/audin/client/pulse/audin_pulse.c +++ b/channels/audin/client/pulse/audin_pulse.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include "audin_main.h" diff --git a/channels/audin/server/CMakeLists.txt b/channels/audin/server/CMakeLists.txt index 6afda4d4a..7da71e81c 100644 --- a/channels/audin/server/CMakeLists.txt +++ b/channels/audin/server/CMakeLists.txt @@ -27,6 +27,6 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-utils) + MODULES freerdp-codec freerdp-utils) set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server") diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c index 06d135b02..b93476a74 100644 --- a/channels/audin/server/audin.c +++ b/channels/audin/server/audin.c @@ -27,7 +27,7 @@ #include -#include +#include #include #include #include @@ -134,8 +134,8 @@ static BOOL audin_server_recv_formats(audin_server* audin, STREAM* s, UINT32 len if (audin->context.num_client_formats <= 0) return FALSE; - audin->context.client_formats = malloc(audin->context.num_client_formats * sizeof(rdpsndFormat)); - ZeroMemory(audin->context.client_formats, audin->context.num_client_formats * sizeof(rdpsndFormat)); + audin->context.client_formats = malloc(audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); + ZeroMemory(audin->context.client_formats, audin->context.num_client_formats * sizeof(AUDIO_FORMAT)); for (i = 0; i < audin->context.num_client_formats; i++) { @@ -206,7 +206,7 @@ static BOOL audin_server_recv_open_reply(audin_server* audin, STREAM* s, UINT32 static BOOL audin_server_recv_data(audin_server* audin, STREAM* s, UINT32 length) { - rdpsndFormat* format; + AUDIO_FORMAT* format; int sbytes_per_sample; int sbytes_per_frame; BYTE* src; @@ -284,7 +284,8 @@ static void* audin_server_thread_func(void* arg) /* Wait for the client to confirm that the Audio Input dynamic channel is ready */ while (1) { - freerdp_thread_wait(thread); + if (freerdp_thread_wait(thread) < 0) + break; if (freerdp_thread_is_stopped(thread)) break; @@ -309,7 +310,8 @@ static void* audin_server_thread_func(void* arg) while (ready) { - freerdp_thread_wait(thread); + if (freerdp_thread_wait(thread) < 0) + break; if (freerdp_thread_is_stopped(thread)) break; diff --git a/channels/client/channels.c b/channels/client/channels.c index e6038cf47..c7d617a0c 100644 --- a/channels/client/channels.c +++ b/channels/client/channels.c @@ -44,7 +44,7 @@ #include #include #include -#include +#include #ifdef WITH_DEBUG_CHANNELS #define DEBUG_CHANNELS(fmt, ...) DEBUG_CLASS(CHANNELS, fmt, ## __VA_ARGS__) @@ -383,15 +383,14 @@ struct channel_data PCHANNEL_OPEN_EVENT_FN open_event_proc; }; -struct _SYNC_DATA +struct _CHANNEL_OPEN_EVENT { - SLIST_ENTRY ItemEntry; void* Data; UINT32 DataLength; void* UserData; int Index; }; -typedef struct _SYNC_DATA SYNC_DATA; +typedef struct _CHANNEL_OPEN_EVENT CHANNEL_OPEN_EVENT; typedef struct rdp_init_handle rdpInitHandle; @@ -430,15 +429,7 @@ struct rdp_channels /* used for locating the channels for a given instance */ freerdp* instance; - /* signal for incoming data or event */ - HANDLE signal; - - /* used for sync write */ - PSLIST_HEADER pSyncDataList; - - /* used for sync event */ - HANDLE event_sem; - RDP_EVENT* event; + wMessagePipe* MsgPipe; }; /** @@ -505,6 +496,7 @@ static rdpChannels* freerdp_channels_find_by_instance(freerdp* instance) for (channels_list = g_channels_list; channels_list; channels_list = channels_list->next) { channels = channels_list->channels; + if (channels->instance == instance) { ReleaseMutex(g_mutex_list); @@ -605,7 +597,7 @@ static UINT32 FREERDP_CC MyVirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF PCHANNEL_DEF lchannel_def; struct channel_data* lchannel_data; - if (ppInitHandle == NULL) + if (!ppInitHandle) { DEBUG_CHANNELS("error bad init handle"); return CHANNEL_RC_BAD_INIT_HANDLE; @@ -630,7 +622,7 @@ static UINT32 FREERDP_CC MyVirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF return CHANNEL_RC_TOO_MANY_CHANNELS; } - if (pChannel == 0) + if (!pChannel) { DEBUG_CHANNELS("error bad channel"); return CHANNEL_RC_BAD_CHANNEL; @@ -709,13 +701,13 @@ static UINT32 FREERDP_CC MyVirtualChannelOpen(void* pInitHandle, UINT32* pOpenHa channels = ((rdpInitHandle*) pInitHandle)->channels; - if (pOpenHandle == 0) + if (!pOpenHandle) { DEBUG_CHANNELS("error bad channel handle"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } - if (pChannelOpenEventProc == 0) + if (!pChannelOpenEventProc) { DEBUG_CHANNELS("error bad proc"); return CHANNEL_RC_BAD_PROC; @@ -729,7 +721,7 @@ static UINT32 FREERDP_CC MyVirtualChannelOpen(void* pInitHandle, UINT32* pOpenHa lchannel_data = freerdp_channels_find_channel_data_by_name(channels, pChannelName, &index); - if (lchannel_data == 0) + if (!lchannel_data) { DEBUG_CHANNELS("error channel name"); return CHANNEL_RC_UNKNOWN_CHANNEL_NAME; @@ -785,13 +777,13 @@ static UINT32 FREERDP_CC MyVirtualChannelClose(UINT32 openHandle) static UINT32 FREERDP_CC MyVirtualChannelWrite(UINT32 openHandle, void* pData, UINT32 dataLength, void* pUserData) { int index; - SYNC_DATA* item; + CHANNEL_OPEN_EVENT* item; rdpChannels* channels; struct channel_data* lchannel_data; channels = freerdp_channels_find_by_open_handle(openHandle, &index); - if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) + if ((!channels) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) { DEBUG_CHANNELS("error bad channel handle"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; @@ -803,13 +795,13 @@ static UINT32 FREERDP_CC MyVirtualChannelWrite(UINT32 openHandle, void* pData, U return CHANNEL_RC_NOT_CONNECTED; } - if (pData == 0) + if (!pData) { DEBUG_CHANNELS("error bad pData"); return CHANNEL_RC_NULL_DATA; } - if (dataLength == 0) + if (!dataLength) { DEBUG_CHANNELS("error bad dataLength"); return CHANNEL_RC_ZERO_LENGTH; @@ -829,16 +821,13 @@ static UINT32 FREERDP_CC MyVirtualChannelWrite(UINT32 openHandle, void* pData, U return CHANNEL_RC_NOT_CONNECTED; } - item = (SYNC_DATA*) _aligned_malloc(sizeof(SYNC_DATA), MEMORY_ALLOCATION_ALIGNMENT); + item = (CHANNEL_OPEN_EVENT*) malloc(sizeof(CHANNEL_OPEN_EVENT)); item->Data = pData; item->DataLength = dataLength; item->UserData = pUserData; item->Index = index; - InterlockedPushEntrySList(channels->pSyncDataList, &(item->ItemEntry)); - - /* set the event */ - SetEvent(channels->signal); + MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 0, (void*) item, NULL); return CHANNEL_RC_OK; } @@ -851,7 +840,7 @@ static UINT32 FREERDP_CC MyVirtualChannelEventPush(UINT32 openHandle, RDP_EVENT* channels = freerdp_channels_find_by_open_handle(openHandle, &index); - if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) + if ((!channels) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) { DEBUG_CHANNELS("error bad channels handle"); return CHANNEL_RC_BAD_CHANNEL_HANDLE; @@ -863,7 +852,7 @@ static UINT32 FREERDP_CC MyVirtualChannelEventPush(UINT32 openHandle, RDP_EVENT* return CHANNEL_RC_NOT_CONNECTED; } - if (event == NULL) + if (!event) { DEBUG_CHANNELS("error bad event"); return CHANNEL_RC_NULL_DATA; @@ -877,19 +866,20 @@ static UINT32 FREERDP_CC MyVirtualChannelEventPush(UINT32 openHandle, RDP_EVENT* return CHANNEL_RC_NOT_OPEN; } - /* lock channels->event */ - WaitForSingleObject(channels->event_sem, INFINITE); - if (!channels->is_connected) { - ReleaseSemaphore(channels->event_sem, 1, NULL); DEBUG_CHANNELS("error not connected"); return CHANNEL_RC_NOT_CONNECTED; } - channels->event = event; - /* set the event */ - SetEvent(channels->signal); + /** + * We really intend to use the In queue for events, but we're pushing on both + * to wake up threads waiting on the out queue. Doing this cleanly would require + * breaking freerdp_pop_event() a bit too early in this refactoring. + */ + + MessageQueue_Post(channels->MsgPipe->In, (void*) channels, 1, (void*) event, NULL); + MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 1, (void*) event, NULL); return CHANNEL_RC_OK; } @@ -929,11 +919,7 @@ rdpChannels* freerdp_channels_new(void) channels = (rdpChannels*) malloc(sizeof(rdpChannels)); ZeroMemory(channels, sizeof(rdpChannels)); - channels->pSyncDataList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT); - InitializeSListHead(channels->pSyncDataList); - - channels->event_sem = CreateSemaphore(NULL, 1, 16, NULL); - channels->signal = CreateEvent(NULL, TRUE, FALSE, NULL); + channels->MsgPipe = MessagePipe_New(); /* Add it to the global list */ channels_list = (rdpChannelsList*) malloc(sizeof(rdpChannelsList)); @@ -953,11 +939,7 @@ void freerdp_channels_free(rdpChannels* channels) rdpChannelsList* list; rdpChannelsList* prev; - InterlockedFlushSList(channels->pSyncDataList); - _aligned_free(channels->pSyncDataList); - - CloseHandle(channels->event_sem); - CloseHandle(channels->signal); + MessagePipe_Free(channels->MsgPipe); /* Remove from global list */ @@ -1144,15 +1126,15 @@ int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int dat channels = freerdp_channels_find_by_instance(instance); - if (channels == 0) + if (!channels) { DEBUG_CHANNELS("could not find channel manager"); return 1; } - lrdp_channel = freerdp_channels_find_channel_by_id(channels, instance->settings, - channel_id, &index); - if (lrdp_channel == 0) + lrdp_channel = freerdp_channels_find_channel_by_id(channels, instance->settings, channel_id, &index); + + if (!lrdp_channel) { DEBUG_CHANNELS("could not find channel id"); return 1; @@ -1160,7 +1142,7 @@ int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int dat lchannel_data = freerdp_channels_find_channel_data_by_name(channels, lrdp_channel->Name, &index); - if (lchannel_data == 0) + if (!lchannel_data) { DEBUG_CHANNELS("could not find channel name"); return 1; @@ -1198,7 +1180,7 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, RDP_EVENT* ev name = event_class_to_name_table[event->event_class]; - if (name == NULL) + if (!name) { DEBUG_CHANNELS("unknown event_class %d", event->event_class); freerdp_event_free(event); @@ -1207,17 +1189,16 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, RDP_EVENT* ev lchannel_data = freerdp_channels_find_channel_data_by_name(channels, name, &index); - if (lchannel_data == NULL) + if (!lchannel_data) { DEBUG_CHANNELS("could not find channel name %s", name); freerdp_event_free(event); return 1; } - if (lchannel_data->open_event_proc != NULL) + if (lchannel_data->open_event_proc) { - lchannel_data->open_event_proc(lchannel_data->open_handle, - CHANNEL_EVENT_USER, + lchannel_data->open_event_proc(lchannel_data->open_handle, CHANNEL_EVENT_USER, event, sizeof(RDP_EVENT), sizeof(RDP_EVENT), 0); } @@ -1229,32 +1210,49 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, RDP_EVENT* ev */ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance) { - SYNC_DATA* item; + wMessage message; + RDP_EVENT* event; + CHANNEL_OPEN_EVENT* item; rdpChannel* lrdp_channel; struct channel_data* lchannel_data; - while (QueryDepthSList(channels->pSyncDataList) > 0) + while (MessageQueue_Peek(channels->MsgPipe->Out, &message, TRUE)) { - item = (SYNC_DATA*) InterlockedPopEntrySList(channels->pSyncDataList); - - if (!item) + if (message.id == WMQ_QUIT) break; - lchannel_data = channels->channels_data + item->Index; - - lrdp_channel = freerdp_channels_find_channel_by_name(channels, instance->settings, - lchannel_data->name, &item->Index); - - if (lrdp_channel != NULL) - instance->SendChannelData(instance, lrdp_channel->ChannelId, item->Data, item->DataLength); - - if (lchannel_data->open_event_proc != 0) + if (message.id == 0) { - lchannel_data->open_event_proc(lchannel_data->open_handle, - CHANNEL_EVENT_WRITE_COMPLETE, item->UserData, sizeof(void*), sizeof(void*), 0); - } + item = (CHANNEL_OPEN_EVENT*) message.wParam; - _aligned_free(item); + if (!item) + break; + + lchannel_data = channels->channels_data + item->Index; + + lrdp_channel = freerdp_channels_find_channel_by_name(channels, instance->settings, + lchannel_data->name, &item->Index); + + if (lrdp_channel) + instance->SendChannelData(instance, lrdp_channel->ChannelId, item->Data, item->DataLength); + + if (lchannel_data->open_event_proc) + { + lchannel_data->open_event_proc(lchannel_data->open_handle, + CHANNEL_EVENT_WRITE_COMPLETE, item->UserData, item->DataLength, item->DataLength, 0); + } + + free(item); + } + else if (message.id == 1) + { + event = (RDP_EVENT*) message.wParam; + + /** + * Ignore for now, the same event is being pushed on the In queue, + * and we're pushing it on the Out queue just to wake other threads + */ + } } } @@ -1266,7 +1264,7 @@ BOOL freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** r { void* pfd; - pfd = GetEventWaitObject(channels->signal); + pfd = GetEventWaitObject(MessageQueue_Event(channels->MsgPipe->Out)); if (pfd) { @@ -1283,7 +1281,7 @@ HANDLE freerdp_channels_get_event_handle(freerdp* instance) rdpChannels* channels; channels = instance->context->channels; - event = channels->signal; + event = MessageQueue_Event(channels->MsgPipe->Out); return event; } @@ -1294,9 +1292,8 @@ int freerdp_channels_process_pending_messages(freerdp* instance) channels = instance->context->channels; - if (WaitForSingleObject(channels->signal, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(MessageQueue_Event(channels->MsgPipe->Out), 0) == WAIT_OBJECT_0) { - ResetEvent(channels->signal); freerdp_channels_process_sync(channels, instance); } @@ -1308,9 +1305,8 @@ int freerdp_channels_process_pending_messages(freerdp* instance) */ BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance) { - if (WaitForSingleObject(channels->signal, 0) == WAIT_OBJECT_0) + if (WaitForSingleObject(MessageQueue_Event(channels->MsgPipe->Out), 0) == WAIT_OBJECT_0) { - ResetEvent(channels->signal); freerdp_channels_process_sync(channels, instance); } @@ -1319,16 +1315,16 @@ BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance) RDP_EVENT* freerdp_channels_pop_event(rdpChannels* channels) { - RDP_EVENT* event; + wMessage message; + RDP_EVENT* event = NULL; - if (channels->event == NULL) - return NULL; - - event = channels->event; - channels->event = NULL; - - /* release channels->event */ - ReleaseSemaphore(channels->event_sem, 1, NULL); + if (MessageQueue_Peek(channels->MsgPipe->In, &message, TRUE)) + { + if (message.id == 1) + { + event = (RDP_EVENT*) message.wParam; + } + } return event; } diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index 1d6040245..35fd94f6c 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -470,14 +470,11 @@ static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP* } /* http://msdn.microsoft.com/en-us/library/cc241518.aspx */ + static void drive_process_irp_silent_ignore(DRIVE_DEVICE* disk, IRP* irp) { UINT32 FsInformationClass; - UINT32 pad; STREAM* output = irp->output; - char* volumeLabel; - int length; - int status; stream_read_UINT32(irp->input, FsInformationClass); diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index 9ac56a8ca..5b3d1d7c2 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -268,7 +268,8 @@ static void* parallel_thread_func(void* arg) while (1) { - freerdp_thread_wait(parallel->thread); + if (freerdp_thread_wait(parallel->thread) < 0) + break; if (freerdp_thread_is_stopped(parallel->thread)) break; diff --git a/channels/rdpsnd/client/CMakeLists.txt b/channels/rdpsnd/client/CMakeLists.txt index bdf84756a..63c439548 100644 --- a/channels/rdpsnd/client/CMakeLists.txt +++ b/channels/rdpsnd/client/CMakeLists.txt @@ -33,7 +33,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE winpr - MODULES winpr-utils) + MODULES winpr-sysinfo winpr-utils) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c index 05a8dea6d..6784e518a 100644 --- a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c +++ b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c @@ -28,12 +28,14 @@ #include #include +#include +#include #include #include -#include -#include +#include +#include #include "rdpsnd_main.h" @@ -43,94 +45,175 @@ struct rdpsnd_alsa_plugin { rdpsndDevicePlugin device; + int latency; + int wformat; + int block_size; char* device_name; - snd_pcm_t* out_handle; + snd_pcm_t* pcm_handle; snd_mixer_t* mixer_handle; UINT32 source_rate; UINT32 actual_rate; + UINT32 wLocalTimeClose; snd_pcm_format_t format; UINT32 source_channels; UINT32 actual_channels; int bytes_per_channel; - int wformat; - int block_size; - int latency; - + snd_pcm_uframes_t buffer_size; + snd_pcm_uframes_t period_size; + snd_pcm_uframes_t start_threshold; + snd_async_handler_t* pcm_callback; FREERDP_DSP_CONTEXT* dsp_context; }; -static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa) +#define SND_PCM_CHECK(_func, _status) \ + if (_status < 0) \ + { \ + printf("%s: %d\n", _func, _status); \ + return -1; \ + } + +int rdpsnd_alsa_set_hw_params(rdpsndAlsaPlugin* alsa) { int status; snd_pcm_hw_params_t* hw_params; - snd_pcm_sw_params_t* sw_params; - snd_pcm_uframes_t frames; - snd_pcm_uframes_t start_threshold; - - snd_pcm_drop(alsa->out_handle); + snd_pcm_uframes_t buffer_size_max; status = snd_pcm_hw_params_malloc(&hw_params); + SND_PCM_CHECK("snd_pcm_hw_params_malloc", status); - if (status < 0) + status = snd_pcm_hw_params_any(alsa->pcm_handle, hw_params); + SND_PCM_CHECK("snd_pcm_hw_params_any", status); + + /* Set interleaved read/write access */ + status = snd_pcm_hw_params_set_access(alsa->pcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); + SND_PCM_CHECK("snd_pcm_hw_params_set_access", status); + + /* Set sample format */ + status = snd_pcm_hw_params_set_format(alsa->pcm_handle, hw_params, alsa->format); + SND_PCM_CHECK("snd_pcm_hw_params_set_format", status); + + /* Set sample rate */ + status = snd_pcm_hw_params_set_rate_near(alsa->pcm_handle, hw_params, &alsa->actual_rate, NULL); + SND_PCM_CHECK("snd_pcm_hw_params_set_rate_near", status); + + /* Set number of channels */ + status = snd_pcm_hw_params_set_channels(alsa->pcm_handle, hw_params, alsa->actual_channels); + SND_PCM_CHECK("snd_pcm_hw_params_set_channels", status); + + /* Get maximum buffer size */ + status = snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size_max); + SND_PCM_CHECK("snd_pcm_hw_params_get_buffer_size_max", status); + + if (alsa->buffer_size > buffer_size_max) { - DEBUG_WARN("snd_pcm_hw_params_malloc failed"); - return; + printf("Warning: requested sound buffer size %d, got %d instead\n", + (int) alsa->buffer_size, (int) buffer_size_max); + alsa->buffer_size = buffer_size_max; } - snd_pcm_hw_params_any(alsa->out_handle, hw_params); - snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); - snd_pcm_hw_params_set_format(alsa->out_handle, hw_params, alsa->format); - snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params, &alsa->actual_rate, NULL); - snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params, &alsa->actual_channels); + /* Set buffer size */ + status = snd_pcm_hw_params_set_buffer_size_near(alsa->pcm_handle, hw_params, &alsa->buffer_size); + SND_PCM_CHECK("snd_pcm_hw_params_set_buffer_size_near", status); - if (alsa->latency < 0) - frames = alsa->actual_rate * 4 / 10; /* Default to 400ms buffer */ - else - frames = alsa->latency * alsa->actual_rate * 2 / 1000; /* Double of the latency */ + /* Get period size */ + status = snd_pcm_hw_params_get_period_size_min(hw_params, &alsa->period_size, NULL); + SND_PCM_CHECK("snd_pcm_hw_params_get_period_size_min", status); - if (frames < alsa->actual_rate / 2) - frames = alsa->actual_rate / 2; /* Minimum 0.5-second buffer */ + /* Set period size */ + status = snd_pcm_hw_params_set_period_size_near(alsa->pcm_handle, hw_params, &alsa->period_size, NULL); + SND_PCM_CHECK("snd_pcm_hw_params_set_period_size_near", status); + + status = snd_pcm_hw_params(alsa->pcm_handle, hw_params); + SND_PCM_CHECK("snd_pcm_hw_params", status); - snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params, &frames); - snd_pcm_hw_params(alsa->out_handle, hw_params); snd_pcm_hw_params_free(hw_params); - status = snd_pcm_sw_params_malloc(&sw_params); - - if (status < 0) - { - DEBUG_WARN("snd_pcm_sw_params_malloc failed"); - return; - } - - snd_pcm_sw_params_current(alsa->out_handle, sw_params); - - if (alsa->latency == 0) - start_threshold = 0; - else - start_threshold = frames / 2; - - snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, start_threshold); - snd_pcm_sw_params(alsa->out_handle, sw_params); - snd_pcm_sw_params_free(sw_params); - - snd_pcm_prepare(alsa->out_handle); - - DEBUG_SVC("hardware buffer %d frames, playback buffer %.2g seconds", - (int) frames, (double) frames / 2.0 / (double) alsa->actual_rate); - - if ((alsa->actual_rate != alsa->source_rate) || (alsa->actual_channels != alsa->source_channels)) - { - DEBUG_SVC("actual rate %d / channel %d is different from source rate %d / channel %d, resampling required.", - alsa->actual_rate, alsa->actual_channels, alsa->source_rate, alsa->source_channels); - } + return 0; } -static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) +int rdpsnd_alsa_set_sw_params(rdpsndAlsaPlugin* alsa) { - rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; + int status; + snd_pcm_sw_params_t* sw_params; - if (format != NULL) + alsa->start_threshold = alsa->buffer_size; + + status = snd_pcm_sw_params_malloc(&sw_params); + SND_PCM_CHECK("snd_pcm_sw_params_malloc", status); + + status = snd_pcm_sw_params_current(alsa->pcm_handle, sw_params); + SND_PCM_CHECK("snd_pcm_sw_params_current", status); + + status = snd_pcm_sw_params_set_start_threshold(alsa->pcm_handle, sw_params, alsa->start_threshold); + SND_PCM_CHECK("snd_pcm_sw_params_set_start_threshold", status); + + status = snd_pcm_sw_params(alsa->pcm_handle, sw_params); + SND_PCM_CHECK("snd_pcm_sw_params", status); + + snd_pcm_sw_params_free(sw_params); + + status = snd_pcm_prepare(alsa->pcm_handle); + SND_PCM_CHECK("snd_pcm_prepare", status); + + return 0; +} + +int rdpsnd_alsa_validate_params(rdpsndAlsaPlugin* alsa) +{ + int status; + snd_pcm_uframes_t buffer_size; + snd_pcm_uframes_t period_size; + + status = snd_pcm_get_params(alsa->pcm_handle, &buffer_size, &period_size); + SND_PCM_CHECK("snd_pcm_get_params", status); + + return 0; +} + +static int rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa) +{ + /** + * ALSA Parameters + * + * http://www.alsa-project.org/main/index.php/FramesPeriods + * + * buffer_size = period_size * periods + * period_bytes = period_size * bytes_per_frame + * bytes_per_frame = channels * bytes_per_sample + * + * A frame is equivalent of one sample being played, + * irrespective of the number of channels or the number of bits + * + * A period is the number of frames in between each hardware interrupt. + * + * The buffer size always has to be greater than one period size. + * Commonly this is (2 * period_size), but some hardware can do 8 periods per buffer. + * It is also possible for the buffer size to not be an integer multiple of the period size. + */ + + snd_pcm_drop(alsa->pcm_handle); + + if (alsa->latency < 0) + alsa->latency = 400; + + alsa->buffer_size = alsa->latency * (alsa->actual_rate / 1000); + + if (rdpsnd_alsa_set_hw_params(alsa) < 0) + return -1; + + if (rdpsnd_alsa_set_sw_params(alsa) < 0) + return -1; + + rdpsnd_alsa_validate_params(alsa); + + return 0; +} + +static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) +{ + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; + + if (format) { alsa->source_rate = format->nSamplesPerSec; alsa->actual_rate = format->nSamplesPerSec; @@ -139,13 +222,19 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* for switch (format->wFormatTag) { - case 1: /* PCM */ + case WAVE_FORMAT_PCM: switch (format->wBitsPerSample) { + case 4: + alsa->format = SND_PCM_FORMAT_S16_LE; + alsa->bytes_per_channel = 2; + break; + case 8: alsa->format = SND_PCM_FORMAT_S8; alsa->bytes_per_channel = 1; break; + case 16: alsa->format = SND_PCM_FORMAT_S16_LE; alsa->bytes_per_channel = 2; @@ -153,8 +242,8 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* for } break; - case 2: /* MS ADPCM */ - case 0x11: /* IMA ADPCM */ + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: alsa->format = SND_PCM_FORMAT_S16_LE; alsa->bytes_per_channel = 2; break; @@ -172,9 +261,11 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* for static void rdpsnd_alsa_open_mixer(rdpsndAlsaPlugin* alsa) { int status; - snd_mixer_t* handle; - status = snd_mixer_open(&handle, 0); + if (alsa->mixer_handle) + return; + + status = snd_mixer_open(&alsa->mixer_handle, 0); if (status < 0) { @@ -182,47 +273,47 @@ static void rdpsnd_alsa_open_mixer(rdpsndAlsaPlugin* alsa) return; } - status = snd_mixer_attach(handle, alsa->device_name); + status = snd_mixer_attach(alsa->mixer_handle, alsa->device_name); if (status < 0) { DEBUG_WARN("snd_mixer_attach failed"); - snd_mixer_close(handle); + snd_mixer_close(alsa->mixer_handle); return; } - status = snd_mixer_selem_register(handle, NULL, NULL); + status = snd_mixer_selem_register(alsa->mixer_handle, NULL, NULL); if (status < 0) { DEBUG_WARN("snd_mixer_selem_register failed"); - snd_mixer_close(handle); + snd_mixer_close(alsa->mixer_handle); return; } - status = snd_mixer_load(handle); + status = snd_mixer_load(alsa->mixer_handle); if (status < 0) { DEBUG_WARN("snd_mixer_load failed"); - snd_mixer_close(handle); + snd_mixer_close(alsa->mixer_handle); return; } - - alsa->mixer_handle = handle; } -static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) +static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) { + int mode; int status; rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; - if (alsa->out_handle != 0) + if (alsa->pcm_handle) return; - DEBUG_SVC("opening"); + mode = 0; + //mode |= SND_PCM_NONBLOCK; - status = snd_pcm_open(&alsa->out_handle, alsa->device_name, SND_PCM_STREAM_PLAYBACK, 0); + status = snd_pcm_open(&alsa->pcm_handle, alsa->device_name, SND_PCM_STREAM_PLAYBACK, mode); if (status < 0) { @@ -238,14 +329,32 @@ static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, rdpsndFormat* format, i static void rdpsnd_alsa_close(rdpsndDevicePlugin* device) { - rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; + int status; + snd_htimestamp_t tstamp; + snd_pcm_uframes_t frames; + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; - if (alsa->out_handle != 0) + if (!alsa->pcm_handle) + return; + + status = snd_pcm_htimestamp(alsa->pcm_handle, &frames, &tstamp); + + if (status != 0) + frames = 0; + + alsa->wLocalTimeClose = GetTickCount(); + alsa->wLocalTimeClose += (((frames * 1000) / alsa->actual_rate) / alsa->actual_channels); +} + +static void rdpsnd_alsa_free(rdpsndDevicePlugin* device) +{ + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; + + if (alsa->pcm_handle) { - DEBUG_SVC("close"); - snd_pcm_drain(alsa->out_handle); - snd_pcm_close(alsa->out_handle); - alsa->out_handle = 0; + snd_pcm_drain(alsa->pcm_handle); + snd_pcm_close(alsa->pcm_handle); + alsa->pcm_handle = 0; } if (alsa->mixer_handle) @@ -253,23 +362,19 @@ static void rdpsnd_alsa_close(rdpsndDevicePlugin* device) snd_mixer_close(alsa->mixer_handle); alsa->mixer_handle = NULL; } -} -static void rdpsnd_alsa_free(rdpsndDevicePlugin* device) -{ - rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; - - rdpsnd_alsa_close(device); free(alsa->device_name); + freerdp_dsp_context_free(alsa->dsp_context); + free(alsa); } -static BOOL rdpsnd_alsa_format_supported(rdpsndDevicePlugin* device, rdpsndFormat* format) +static BOOL rdpsnd_alsa_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format) { switch (format->wFormatTag) { - case 1: /* PCM */ + case WAVE_FORMAT_PCM: if (format->cbSize == 0 && format->nSamplesPerSec <= 48000 && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && @@ -279,8 +384,8 @@ static BOOL rdpsnd_alsa_format_supported(rdpsndDevicePlugin* device, rdpsndForma } break; - case 2: /* MS ADPCM */ - case 0x11: /* IMA ADPCM */ + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: if (format->nSamplesPerSec <= 48000 && format->wBitsPerSample == 4 && (format->nChannels == 1 || format->nChannels == 2)) @@ -288,10 +393,63 @@ static BOOL rdpsnd_alsa_format_supported(rdpsndDevicePlugin* device, rdpsndForma return TRUE; } break; + + case WAVE_FORMAT_ALAW: + break; + + case WAVE_FORMAT_MULAW: + break; + + case WAVE_FORMAT_GSM610: + break; } + return FALSE; } +static UINT32 rdpsnd_alsa_get_volume(rdpsndDevicePlugin* device) +{ + long volume_min; + long volume_max; + long volume_left; + long volume_right; + int percent_left; + int percent_right; + UINT32 dwVolume; + UINT16 dwVolumeLeft; + UINT16 dwVolumeRight; + snd_mixer_elem_t* elem; + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; + + dwVolumeLeft = ((50 * 0xFFFF) / 100); /* 50% */ + dwVolumeRight = ((50 * 0xFFFF) / 100); /* 50% */ + + if (!alsa->mixer_handle) + rdpsnd_alsa_open_mixer(alsa); + + for (elem = snd_mixer_first_elem(alsa->mixer_handle); elem; elem = snd_mixer_elem_next(elem)) + { + if (snd_mixer_selem_has_playback_volume(elem)) + { + snd_mixer_selem_get_playback_volume_range(elem, &volume_min, &volume_max); + snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &volume_left); + snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &volume_right); + + dwVolumeLeft = (UINT16) (((volume_left * 0xFFFF) - volume_min) / (volume_max - volume_min)); + dwVolumeRight = (UINT16) (((volume_right * 0xFFFF) - volume_min) / (volume_max - volume_min)); + + percent_left = (dwVolumeLeft * 100) / 0xFFFF; + percent_right = (dwVolumeRight * 100) / 0xFFFF; + + break; + } + } + + dwVolume = (dwVolumeLeft << 16) | dwVolumeRight; + + return dwVolume; +} + static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value) { long left; @@ -300,15 +458,20 @@ static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value) long volume_max; long volume_left; long volume_right; + int percent_left; + int percent_right; snd_mixer_elem_t* elem; rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; if (!alsa->mixer_handle) - return; + rdpsnd_alsa_open_mixer(alsa); left = (value & 0xFFFF); right = ((value >> 16) & 0xFFFF); + percent_left = (left * 100) / 0xFFFF; + percent_right = (right * 100) / 0xFFFF; + for (elem = snd_mixer_first_elem(alsa->mixer_handle); elem; elem = snd_mixer_elem_next(elem)) { if (snd_mixer_selem_has_playback_volume(elem)) @@ -322,99 +485,141 @@ static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value) } } -static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, BYTE* data, int size) +BYTE* rdpsnd_alsa_process_audio_sample(rdpsndDevicePlugin* device, BYTE* data, int* size) { - BYTE* src; - int len; - int status; int frames; - int rbytes_per_frame; - int sbytes_per_frame; - BYTE* pindex; - BYTE* end; + BYTE* srcData; + int srcFrameSize; + int dstFrameSize; rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; - if (alsa->out_handle == 0) - return; - - if (alsa->wformat == 2) + if (alsa->wformat == WAVE_FORMAT_ADPCM) { alsa->dsp_context->decode_ms_adpcm(alsa->dsp_context, - data, size, alsa->source_channels, alsa->block_size); - size = alsa->dsp_context->adpcm_size; - src = alsa->dsp_context->adpcm_buffer; + data, *size, alsa->source_channels, alsa->block_size); + + *size = alsa->dsp_context->adpcm_size; + srcData = alsa->dsp_context->adpcm_buffer; } - else if (alsa->wformat == 0x11) + else if (alsa->wformat == WAVE_FORMAT_DVI_ADPCM) { alsa->dsp_context->decode_ima_adpcm(alsa->dsp_context, - data, size, alsa->source_channels, alsa->block_size); - size = alsa->dsp_context->adpcm_size; - src = alsa->dsp_context->adpcm_buffer; + data, *size, alsa->source_channels, alsa->block_size); + + *size = alsa->dsp_context->adpcm_size; + srcData = alsa->dsp_context->adpcm_buffer; } else { - src = data; + srcData = data; } - sbytes_per_frame = alsa->source_channels * alsa->bytes_per_channel; - rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; + srcFrameSize = alsa->source_channels * alsa->bytes_per_channel; + dstFrameSize = alsa->actual_channels * alsa->bytes_per_channel; - if ((size % sbytes_per_frame) != 0) - { - DEBUG_WARN("error len mod"); - return; - } + if ((*size % srcFrameSize) != 0) + return NULL; - if ((alsa->source_rate == alsa->actual_rate) && (alsa->source_channels == alsa->actual_channels)) + if (!((alsa->source_rate == alsa->actual_rate) && (alsa->source_channels == alsa->actual_channels))) { - } - else - { - alsa->dsp_context->resample(alsa->dsp_context, src, alsa->bytes_per_channel, - alsa->source_channels, alsa->source_rate, size / sbytes_per_frame, + alsa->dsp_context->resample(alsa->dsp_context, srcData, alsa->bytes_per_channel, + alsa->source_channels, alsa->source_rate, *size / srcFrameSize, alsa->actual_channels, alsa->actual_rate); + frames = alsa->dsp_context->resampled_frames; - DEBUG_SVC("resampled %d frames at %d to %d frames at %d", - size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate); - size = frames * rbytes_per_frame; - src = alsa->dsp_context->resampled_buffer; + + *size = frames * dstFrameSize; + srcData = alsa->dsp_context->resampled_buffer; } - pindex = src; - end = pindex + size; + data = srcData; - while (pindex < end) + return data; +} + +static void rdpsnd_alsa_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) +{ + int size; + BYTE* data; + + size = wave->length; + data = rdpsnd_alsa_process_audio_sample(device, wave->data, &size); + + wave->data = (BYTE*) malloc(size); + CopyMemory(wave->data, data, size); + wave->length = size; +} + +static void rdpsnd_alsa_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) +{ + BYTE* data; + int offset; + int length; + int status; + int frame_size; + UINT32 wCurrentTime; + snd_htimestamp_t tstamp; + snd_pcm_uframes_t frames; + + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; + + offset = 0; + data = wave->data; + length = wave->length; + frame_size = alsa->actual_channels * alsa->bytes_per_channel; + + if (alsa->wLocalTimeClose) { - len = end - pindex; - frames = len / rbytes_per_frame; - status = snd_pcm_writei(alsa->out_handle, pindex, frames); + wCurrentTime = GetTickCount(); + + if (snd_pcm_htimestamp(alsa->pcm_handle, &frames, &tstamp) == -EPIPE) + { + if (wCurrentTime > alsa->wLocalTimeClose) + snd_pcm_recover(alsa->pcm_handle, -EPIPE, 1); + } + + alsa->wLocalTimeClose = 0; + } + + while (offset < length) + { + status = snd_pcm_writei(alsa->pcm_handle, &data[offset], (length - offset) / frame_size); if (status == -EPIPE) { - snd_pcm_recover(alsa->out_handle, status, 0); + snd_pcm_recover(alsa->pcm_handle, status, 0); + status = 0; + } + else if (status == -EAGAIN) + { status = 0; } else if (status < 0) { - DEBUG_WARN("status %d", status); - snd_pcm_close(alsa->out_handle); - alsa->out_handle = 0; - rdpsnd_alsa_open(device, NULL, alsa->latency); + printf("status: %d\n", status); + snd_pcm_close(alsa->pcm_handle); + alsa->pcm_handle = NULL; + rdpsnd_alsa_open((rdpsndDevicePlugin*) alsa, NULL, alsa->latency); break; } - pindex += status * rbytes_per_frame; + offset += status * frame_size; } -} -static void rdpsnd_alsa_start(rdpsndDevicePlugin* device) -{ - rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; + free(data); - if (alsa->out_handle == 0) - return; + snd_pcm_htimestamp(alsa->pcm_handle, &frames, &tstamp); - snd_pcm_start(alsa->out_handle); + wave->wPlaybackDelay = ((frames * 1000) / alsa->actual_rate); + + wave->wLocalTimeB = GetTickCount(); + wave->wLocalTimeB += wave->wPlaybackDelay; + wave->wLatency = (UINT16) (wave->wLocalTimeB - wave->wLocalTimeA); + wave->wTimeStampB = wave->wTimeStampA + wave->wLatency; + + //printf("wTimeStampA: %d wTimeStampB: %d wLatency: %d\n", wave->wTimeStampA, wave->wTimeStampB, wave->wLatency); + + device->WaveConfirm(device, wave); } COMMAND_LINE_ARGUMENT_A rdpsnd_alsa_args[] = @@ -468,9 +673,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE alsa->device.Open = rdpsnd_alsa_open; alsa->device.FormatSupported = rdpsnd_alsa_format_supported; alsa->device.SetFormat = rdpsnd_alsa_set_format; + alsa->device.GetVolume = rdpsnd_alsa_get_volume; alsa->device.SetVolume = rdpsnd_alsa_set_volume; - alsa->device.Play = rdpsnd_alsa_play; - alsa->device.Start = rdpsnd_alsa_start; + alsa->device.WaveDecode = rdpsnd_alsa_wave_decode; + alsa->device.WavePlay = rdpsnd_alsa_wave_play; alsa->device.Close = rdpsnd_alsa_close; alsa->device.Free = rdpsnd_alsa_free; @@ -480,7 +686,7 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE if (!alsa->device_name) alsa->device_name = _strdup("default"); - alsa->out_handle = 0; + alsa->pcm_handle = 0; alsa->source_rate = 22050; alsa->actual_rate = 22050; alsa->format = SND_PCM_FORMAT_S16_LE; diff --git a/channels/rdpsnd/client/mac/rdpsnd_mac.c b/channels/rdpsnd/client/mac/rdpsnd_mac.c index c9fd63c82..90a3ace0e 100644 --- a/channels/rdpsnd/client/mac/rdpsnd_mac.c +++ b/channels/rdpsnd/client/mac/rdpsnd_mac.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include @@ -72,7 +72,7 @@ static void rdpsnd_audio_close(rdpsndDevicePlugin* device) aq_plugin_p->is_open = 0; } -static void rdpsnd_audio_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) +static void rdpsnd_audio_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) { int rv; int i; @@ -127,7 +127,7 @@ static void rdpsnd_audio_free(rdpsndDevicePlugin* device) { } -static BOOL rdpsnd_audio_format_supported(rdpsndDevicePlugin* device, rdpsndFormat* format) +static BOOL rdpsnd_audio_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format) { switch (format->wFormatTag) { @@ -144,7 +144,7 @@ static BOOL rdpsnd_audio_format_supported(rdpsndDevicePlugin* device, rdpsndForm return 0; } -static void rdpsnd_audio_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) +static void rdpsnd_audio_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) { } diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index d0bb11f8e..607645d1e 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include "rdpsnd_main.h" @@ -43,10 +43,10 @@ struct rdpsnd_pulse_plugin rdpsndDevicePlugin device; char* device_name; - pa_threaded_mainloop *mainloop; - pa_context *context; + pa_threaded_mainloop* mainloop; + pa_context* context; pa_sample_spec sample_spec; - pa_stream *stream; + pa_stream* stream; int format; int block_size; int latency; @@ -106,13 +106,16 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) for (;;) { state = pa_context_get_state(pulse->context); + if (state == PA_CONTEXT_READY) break; + if (!PA_CONTEXT_IS_GOOD(state)) { DEBUG_WARN("bad context state (%d)", pa_context_errno(pulse->context)); break; } + pa_threaded_mainloop_wait(pulse->mainloop); } @@ -139,7 +142,7 @@ static void rdpsnd_pulse_stream_success_callback(pa_stream* stream, int success, static void rdpsnd_pulse_wait_for_operation(rdpsndPulsePlugin* pulse, pa_operation* operation) { - if (operation == NULL) + if (!operation) return; while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) @@ -200,7 +203,7 @@ static void rdpsnd_pulse_close(rdpsndDevicePlugin* device) pa_threaded_mainloop_unlock(pulse->mainloop); } -static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, rdpsndFormat* format) +static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, AUDIO_FORMAT* format) { pa_sample_spec sample_spec = { 0 }; @@ -212,7 +215,7 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, rdpsndFormat* switch (format->wFormatTag) { - case 1: /* PCM */ + case WAVE_FORMAT_PCM: switch (format->wBitsPerSample) { case 8: @@ -224,17 +227,20 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, rdpsndFormat* } break; - case 6: /* A-LAW */ + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: + sample_spec.format = PA_SAMPLE_S16LE; + break; + + case WAVE_FORMAT_ALAW: sample_spec.format = PA_SAMPLE_ALAW; break; - case 7: /* U-LAW */ + case WAVE_FORMAT_MULAW: sample_spec.format = PA_SAMPLE_ULAW; break; - case 2: /* MS ADPCM */ - case 0x11: /* IMA ADPCM */ - sample_spec.format = PA_SAMPLE_S16LE; + case WAVE_FORMAT_GSM610: break; } @@ -243,7 +249,7 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, rdpsndFormat* pulse->block_size = format->nBlockAlign; } -static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) +static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) { pa_stream_state_t state; pa_stream_flags_t flags; @@ -278,7 +284,7 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, return; } - /* install essential callbacks */ + /* register essential callbacks */ pa_stream_set_state_callback(pulse->stream, rdpsnd_pulse_stream_state_callback, pulse); pa_stream_set_write_callback(pulse->stream, rdpsnd_pulse_stream_request_callback, pulse); @@ -365,7 +371,7 @@ static void rdpsnd_pulse_free(rdpsndDevicePlugin* device) free(pulse); } -static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndFormat* format) +static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; @@ -374,7 +380,7 @@ static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndForm switch (format->wFormatTag) { - case 1: /* PCM */ + case WAVE_FORMAT_PCM: if (format->cbSize == 0 && (format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && @@ -384,8 +390,8 @@ static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndForm } break; - case 6: /* A-LAW */ - case 7: /* U-LAW */ + case WAVE_FORMAT_ALAW: + case WAVE_FORMAT_MULAW: if (format->cbSize == 0 && (format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 8) && @@ -395,8 +401,8 @@ static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndForm } break; - case 2: /* MS ADPCM */ - case 0x11: /* IMA ADPCM */ + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: if ((format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 4) && (format->nChannels == 1 || format->nChannels == 2)) @@ -408,7 +414,7 @@ static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndForm return FALSE; } -static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) +static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; @@ -463,17 +469,19 @@ static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, BYTE* data, int size) if (!pulse->stream) return; - if (pulse->format == 2) + if (pulse->format == WAVE_FORMAT_ADPCM) { pulse->dsp_context->decode_ms_adpcm(pulse->dsp_context, data, size, pulse->sample_spec.channels, pulse->block_size); + size = pulse->dsp_context->adpcm_size; src = pulse->dsp_context->adpcm_buffer; } - else if (pulse->format == 0x11) + else if (pulse->format == WAVE_FORMAT_DVI_ADPCM) { pulse->dsp_context->decode_ima_adpcm(pulse->dsp_context, data, size, pulse->sample_spec.channels, pulse->block_size); + size = pulse->dsp_context->adpcm_size; src = pulse->dsp_context->adpcm_buffer; } diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 1005303f3..420626160 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -24,6 +24,7 @@ #ifndef _WIN32 #include +#include #endif #include @@ -31,41 +32,49 @@ #include #include +#include +#include #include +#include +#include #include #include #include #include -#include +#include #include #include "rdpsnd_main.h" +#define TIME_DELAY_MS 65 + struct rdpsnd_plugin { rdpSvcPlugin plugin; - LIST* data_out_list; + HANDLE thread; + wMessageQueue* queue; BYTE cBlockNo; - rdpsndFormat* supported_formats; - int n_supported_formats; - int current_format; + int wCurrentFormatNo; + + AUDIO_FORMAT* ServerFormats; + UINT16 NumberOfServerFormats; + + AUDIO_FORMAT* ClientFormats; + UINT16 NumberOfClientFormats; BOOL expectingWave; BYTE waveData[4]; UINT16 waveDataSize; - UINT32 wTimeStamp; /* server timestamp */ - UINT32 wave_timestamp; /* client timestamp */ + UINT32 wTimeStamp; - BOOL is_open; - UINT32 close_timestamp; - - UINT16 fixed_format; - UINT16 fixed_channel; - UINT32 fixed_rate; int latency; + BOOL isOpen; + UINT16 fixedFormat; + UINT16 fixedChannel; + UINT32 fixedRate; char* subsystem; char* device_name; @@ -74,339 +83,484 @@ struct rdpsnd_plugin rdpsndDevicePlugin* device; }; -struct data_out_item +void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE cConfirmedBlockNo); + +static void* rdpsnd_schedule_thread(void* arg) { - STREAM* data_out; - UINT32 out_timestamp; -}; + wMessage message; + UINT16 wTimeDiff; + UINT16 wTimeStamp; + UINT16 wCurrentTime; + RDPSND_WAVE* wave; + rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg; -/* get time in milliseconds */ -static UINT32 get_mstime(void) + while (1) + { + if (!MessageQueue_Wait(rdpsnd->queue)) + break; + + if (!MessageQueue_Peek(rdpsnd->queue, &message, TRUE)) + break; + + if (message.id == WMQ_QUIT) + break; + + wave = (RDPSND_WAVE*) message.wParam; + wCurrentTime = (UINT16) GetTickCount(); + wTimeStamp = wave->wLocalTimeB; + + if (wCurrentTime <= wTimeStamp) + { + wTimeDiff = wTimeStamp - wCurrentTime; + Sleep(wTimeDiff); + } + + rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo); + free(wave); + } + + return NULL; +} + +void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd) { -#ifndef _WIN32 - struct timeval tp; - gettimeofday(&tp, 0); - return (tp.tv_sec * 1000) + (tp.tv_usec / 1000); -#else - FILETIME ft; - UINT64 time64 = 0; + STREAM* pdu; - GetSystemTimeAsFileTime(&ft); - - time64 |= ft.dwHighDateTime; - time64 <<= 32; - time64 |= ft.dwLowDateTime; - time64 /= 10000; - - /* fix epoch? */ + pdu = stream_new(8); + stream_write_BYTE(pdu, SNDC_QUALITYMODE); /* msgType */ + stream_write_BYTE(pdu, 0); /* bPad */ + stream_write_UINT16(pdu, 4); /* BodySize */ + stream_write_UINT16(pdu, HIGH_QUALITY); /* wQualityMode */ + stream_write_UINT16(pdu, 0); /* Reserved */ - return (UINT32) time64; + svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu); +} + +void rdpsnd_free_audio_formats(AUDIO_FORMAT* formats, UINT16 count) +{ + int index; + AUDIO_FORMAT* format; + + if (formats) + { + for (index = 0; index < (int) count; index++) + { + format = &formats[index]; + + if (format->cbSize) + free(format->data); + } + + free(formats); + } +} + +char* rdpsnd_get_audio_tag_string(UINT16 wFormatTag) +{ + switch (wFormatTag) + { + case WAVE_FORMAT_PCM: + return "WAVE_FORMAT_PCM"; + + case WAVE_FORMAT_ADPCM: + return "WAVE_FORMAT_ADPCM"; + + case WAVE_FORMAT_ALAW: + return "WAVE_FORMAT_ALAW"; + + case WAVE_FORMAT_MULAW: + return "WAVE_FORMAT_MULAW"; + + case WAVE_FORMAT_DVI_ADPCM: + return "WAVE_FORMAT_DVI_ADPCM"; + + case WAVE_FORMAT_GSM610: + return "WAVE_FORMAT_GSM610"; + + case WAVE_FORMAT_MSG723: + return "WAVE_FORMAT_MSG723"; + + case WAVE_FORMAT_DSPGROUP_TRUESPEECH: + return "WAVE_FORMAT_DSPGROUP_TRUESPEECH "; + + case WAVE_FORMAT_MPEGLAYER3: + return "WAVE_FORMAT_MPEGLAYER3"; + + case WAVE_FORMAT_WMAUDIO2: + return "WAVE_FORMAT_WMAUDIO2"; + } + + return "WAVE_FORMAT_UNKNOWN"; +} + +void rdpsnd_print_audio_format(AUDIO_FORMAT* format) +{ + printf("%s:\t wFormatTag: 0x%04X nChannels: %d nSamplesPerSec: %d nAvgBytesPerSec: %d nBlockAlign: %d wBitsPerSample: %d cbSize: %d\n", + rdpsnd_get_audio_tag_string(format->wFormatTag), format->wFormatTag, + format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec, + format->nBlockAlign, format->wBitsPerSample, format->cbSize); +} + +void rdpsnd_print_audio_formats(AUDIO_FORMAT* formats, UINT16 count) +{ + int index; + AUDIO_FORMAT* format; + + if (formats) + { + printf("AUDIO_FORMATS (%d) =\n{\n", count); + + for (index = 0; index < (int) count; index++) + { + format = &formats[index]; + + printf("\t"); + rdpsnd_print_audio_format(format); + } + + printf("}\n"); + } +} + +UINT32 rdpsnd_compute_audio_time_length(AUDIO_FORMAT* format, int size) +{ + UINT32 mstime; + UINT32 wSamples; + + /** + * [MSDN-AUDIOFORMAT]: + * http://msdn.microsoft.com/en-us/library/ms713497.aspx + */ + + wSamples = (size * 8) / format->wBitsPerSample; + mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels); + + return mstime; +} + +void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd) +{ + int index; + AUDIO_FORMAT* serverFormat; + AUDIO_FORMAT* clientFormat; + + rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); + rdpsnd->NumberOfClientFormats = 0; + rdpsnd->ClientFormats = NULL; + + rdpsnd->ClientFormats = (AUDIO_FORMAT*) malloc(sizeof(AUDIO_FORMAT) * rdpsnd->NumberOfServerFormats); + + for (index = 0; index < (int) rdpsnd->NumberOfServerFormats; index++) + { + serverFormat = &rdpsnd->ServerFormats[index]; + + if (rdpsnd->fixedFormat > 0 && (rdpsnd->fixedFormat != serverFormat->wFormatTag)) + continue; + + if (rdpsnd->fixedChannel > 0 && (rdpsnd->fixedChannel != serverFormat->nChannels)) + continue; + + if (rdpsnd->fixedRate > 0 && (rdpsnd->fixedRate != serverFormat->nSamplesPerSec)) + continue; + + if (rdpsnd->device && rdpsnd->device->FormatSupported(rdpsnd->device, serverFormat)) + { + clientFormat = &rdpsnd->ClientFormats[rdpsnd->NumberOfClientFormats++]; + + CopyMemory(clientFormat, serverFormat, sizeof(AUDIO_FORMAT)); + clientFormat->cbSize = 0; + + if (serverFormat->cbSize > 0) + { + clientFormat->data = (BYTE*) malloc(serverFormat->cbSize); + CopyMemory(clientFormat->data, serverFormat->data, serverFormat->cbSize); + clientFormat->cbSize = serverFormat->cbSize; + } + } + } + +#if 0 + printf("Server "); + rdpsnd_print_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); + printf("\n"); + + printf("Client "); + rdpsnd_print_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); + printf("\n"); #endif } -/* process the linked list of data that has queued to be sent */ -static void rdpsnd_process_interval(rdpSvcPlugin* plugin) -{ - rdpsndPlugin* rdpsnd = (rdpsndPlugin*)plugin; - struct data_out_item* item; - UINT32 cur_time; - - while (list_size(rdpsnd->data_out_list) > 0) - { - item = (struct data_out_item*) list_peek(rdpsnd->data_out_list); - - cur_time = get_mstime(); - - if (!item || cur_time <= item->out_timestamp) - break; - - item = (struct data_out_item*) list_dequeue(rdpsnd->data_out_list); - svc_plugin_send(plugin, item->data_out); - free(item); - - DEBUG_SVC("processed data_out"); - } - - if (rdpsnd->is_open && rdpsnd->close_timestamp > 0) - { - cur_time = get_mstime(); - - if (cur_time > rdpsnd->close_timestamp) - { - if (rdpsnd->device) - IFCALL(rdpsnd->device->Close, rdpsnd->device); - rdpsnd->is_open = FALSE; - rdpsnd->close_timestamp = 0; - - DEBUG_SVC("processed close"); - } - } - - if (list_size(rdpsnd->data_out_list) == 0 && !rdpsnd->is_open) - { - rdpsnd->plugin.interval_ms = 0; - } -} - -static void rdpsnd_free_supported_formats(rdpsndPlugin* rdpsnd) -{ - UINT16 i; - - for (i = 0; i < rdpsnd->n_supported_formats; i++) - free(rdpsnd->supported_formats[i].data); - free(rdpsnd->supported_formats); - - rdpsnd->supported_formats = NULL; - rdpsnd->n_supported_formats = 0; -} - -/* receives a list of server supported formats and returns a list - of client supported formats */ -static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in) +void rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd) { + int index; + STREAM* pdu; + UINT16 length; + UINT32 dwVolume; + UINT16 dwVolumeLeft; + UINT16 dwVolumeRight; UINT16 wNumberOfFormats; - UINT16 nFormat; - UINT16 wVersion; - STREAM* data_out; - rdpsndFormat* out_formats; - UINT16 n_out_formats; - rdpsndFormat* format; - BYTE* format_mark; - BYTE* data_mark; - int pos; + AUDIO_FORMAT* clientFormat; - rdpsnd_free_supported_formats(rdpsnd); - - stream_seek_UINT32(data_in); /* dwFlags */ - stream_seek_UINT32(data_in); /* dwVolume */ - stream_seek_UINT32(data_in); /* dwPitch */ - stream_seek_UINT16(data_in); /* wDGramPort */ - stream_read_UINT16(data_in, wNumberOfFormats); - stream_read_BYTE(data_in, rdpsnd->cBlockNo); /* cLastBlockConfirmed */ - stream_read_UINT16(data_in, wVersion); - stream_seek_BYTE(data_in); /* bPad */ - - DEBUG_SVC("wNumberOfFormats %d wVersion %d", wNumberOfFormats, wVersion); - if (wNumberOfFormats < 1) + if (rdpsnd->device->GetVolume) { - DEBUG_WARN("wNumberOfFormats is 0"); - return; - } - - out_formats = (rdpsndFormat*) malloc(wNumberOfFormats * sizeof(rdpsndFormat)); - ZeroMemory(out_formats, wNumberOfFormats * sizeof(rdpsndFormat)); - n_out_formats = 0; - - data_out = stream_new(24); - stream_write_BYTE(data_out, SNDC_FORMATS); /* msgType */ - stream_write_BYTE(data_out, 0); /* bPad */ - stream_seek_UINT16(data_out); /* BodySize */ - stream_write_UINT32(data_out, TSSNDCAPS_ALIVE | TSSNDCAPS_VOLUME); /* dwFlags */ - stream_write_UINT32(data_out, 0xFFFFFFFF); /* dwVolume */ - stream_write_UINT32(data_out, 0); /* dwPitch */ - stream_write_UINT16_be(data_out, 0); /* wDGramPort */ - stream_seek_UINT16(data_out); /* wNumberOfFormats */ - stream_write_BYTE(data_out, 0); /* cLastBlockConfirmed */ - stream_write_UINT16(data_out, 6); /* wVersion */ - stream_write_BYTE(data_out, 0); /* bPad */ - - for (nFormat = 0; nFormat < wNumberOfFormats; nFormat++) - { - stream_get_mark(data_in, format_mark); - format = &out_formats[n_out_formats]; - stream_read_UINT16(data_in, format->wFormatTag); - stream_read_UINT16(data_in, format->nChannels); - stream_read_UINT32(data_in, format->nSamplesPerSec); - stream_seek_UINT32(data_in); /* nAvgBytesPerSec */ - stream_read_UINT16(data_in, format->nBlockAlign); - stream_read_UINT16(data_in, format->wBitsPerSample); - stream_read_UINT16(data_in, format->cbSize); - stream_get_mark(data_in, data_mark); - stream_seek(data_in, format->cbSize); - format->data = NULL; - - DEBUG_SVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d nBlockAlign=%d wBitsPerSample=%d", - format->wFormatTag, format->nChannels, format->nSamplesPerSec, - format->nBlockAlign, format->wBitsPerSample); - - if (rdpsnd->fixed_format > 0 && rdpsnd->fixed_format != format->wFormatTag) - continue; - if (rdpsnd->fixed_channel > 0 && rdpsnd->fixed_channel != format->nChannels) - continue; - if (rdpsnd->fixed_rate > 0 && rdpsnd->fixed_rate != format->nSamplesPerSec) - continue; - if (rdpsnd->device && rdpsnd->device->FormatSupported(rdpsnd->device, format)) - { - DEBUG_SVC("format supported."); - - stream_check_size(data_out, 18 + format->cbSize); - stream_write(data_out, format_mark, 18 + format->cbSize); - if (format->cbSize > 0) - { - format->data = malloc(format->cbSize); - memcpy(format->data, data_mark, format->cbSize); - } - n_out_formats++; - } - } - - rdpsnd->n_supported_formats = n_out_formats; - if (n_out_formats > 0) - { - rdpsnd->supported_formats = out_formats; + dwVolume = rdpsnd->device->GetVolume(rdpsnd->device); } else { - free(out_formats); - DEBUG_WARN("no formats supported"); + dwVolumeLeft = ((50 * 0xFFFF) / 100); /* 50% */ + dwVolumeRight = ((50 * 0xFFFF) / 100); /* 50% */ + dwVolume = (dwVolumeLeft << 16) | dwVolumeRight; } - pos = stream_get_pos(data_out); - stream_set_pos(data_out, 2); - stream_write_UINT16(data_out, pos - 4); - stream_set_pos(data_out, 18); - stream_write_UINT16(data_out, n_out_formats); - stream_set_pos(data_out, pos); + wNumberOfFormats = rdpsnd->NumberOfClientFormats; - svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); + length = 4 + 20; - if (wVersion >= 6) + for (index = 0; index < (int) wNumberOfFormats; index++) + length += (18 + rdpsnd->ClientFormats[index].cbSize); + + pdu = stream_new(length); + + stream_write_BYTE(pdu, SNDC_FORMATS); /* msgType */ + stream_write_BYTE(pdu, 0); /* bPad */ + stream_write_UINT16(pdu, length - 4); /* BodySize */ + + stream_write_UINT32(pdu, TSSNDCAPS_ALIVE | TSSNDCAPS_VOLUME); /* dwFlags */ + stream_write_UINT32(pdu, dwVolume); /* dwVolume */ + stream_write_UINT32(pdu, 0); /* dwPitch */ + stream_write_UINT16(pdu, 0); /* wDGramPort */ + stream_write_UINT16(pdu, wNumberOfFormats); /* wNumberOfFormats */ + stream_write_BYTE(pdu, 0); /* cLastBlockConfirmed */ + stream_write_UINT16(pdu, 6); /* wVersion */ + stream_write_BYTE(pdu, 0); /* bPad */ + + for (index = 0; index < (int) wNumberOfFormats; index++) { - data_out = stream_new(8); - stream_write_BYTE(data_out, SNDC_QUALITYMODE); /* msgType */ - stream_write_BYTE(data_out, 0); /* bPad */ - stream_write_UINT16(data_out, 4); /* BodySize */ - stream_write_UINT16(data_out, HIGH_QUALITY); /* wQualityMode */ - stream_write_UINT16(data_out, 0); /* Reserved */ + clientFormat = &rdpsnd->ClientFormats[index]; - svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); + stream_write_UINT16(pdu, clientFormat->wFormatTag); + stream_write_UINT16(pdu, clientFormat->nChannels); + stream_write_UINT32(pdu, clientFormat->nSamplesPerSec); + stream_write_UINT32(pdu, clientFormat->nAvgBytesPerSec); + stream_write_UINT16(pdu, clientFormat->nBlockAlign); + stream_write_UINT16(pdu, clientFormat->wBitsPerSample); + stream_write_UINT16(pdu, clientFormat->cbSize); + + if (clientFormat->cbSize > 0) + stream_write(pdu, clientFormat->data, clientFormat->cbSize); } + + svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu); } -/* server is getting a feel of the round trip time */ -static void rdpsnd_process_message_training(rdpsndPlugin* rdpsnd, STREAM* data_in) +void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, STREAM* s) +{ + int index; + UINT16 wVersion; + AUDIO_FORMAT* format; + UINT16 wNumberOfFormats; + + rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); + rdpsnd->NumberOfServerFormats = 0; + rdpsnd->ServerFormats = NULL; + + stream_seek_UINT32(s); /* dwFlags */ + stream_seek_UINT32(s); /* dwVolume */ + stream_seek_UINT32(s); /* dwPitch */ + stream_seek_UINT16(s); /* wDGramPort */ + stream_read_UINT16(s, wNumberOfFormats); + stream_read_BYTE(s, rdpsnd->cBlockNo); /* cLastBlockConfirmed */ + stream_read_UINT16(s, wVersion); /* wVersion */ + stream_seek_BYTE(s); /* bPad */ + + rdpsnd->NumberOfServerFormats = wNumberOfFormats; + rdpsnd->ServerFormats = (AUDIO_FORMAT*) malloc(sizeof(AUDIO_FORMAT) * wNumberOfFormats); + + for (index = 0; index < (int) wNumberOfFormats; index++) + { + format = &rdpsnd->ServerFormats[index]; + + stream_read_UINT16(s, format->wFormatTag); /* wFormatTag */ + stream_read_UINT16(s, format->nChannels); /* nChannels */ + stream_read_UINT32(s, format->nSamplesPerSec); /* nSamplesPerSec */ + stream_read_UINT32(s, format->nAvgBytesPerSec); /* nAvgBytesPerSec */ + stream_read_UINT16(s, format->nBlockAlign); /* nBlockAlign */ + stream_read_UINT16(s, format->wBitsPerSample); /* wBitsPerSample */ + stream_read_UINT16(s, format->cbSize); /* cbSize */ + + format->data = (BYTE*) malloc(format->cbSize); + stream_read(s, format->data, format->cbSize); + } + + rdpsnd_select_supported_audio_formats(rdpsnd); + + rdpsnd_send_client_audio_formats(rdpsnd); + + if (wVersion >= 6) + rdpsnd_send_quality_mode_pdu(rdpsnd); +} + +void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, UINT16 wPackSize) +{ + STREAM* pdu; + + pdu = stream_new(8); + stream_write_BYTE(pdu, SNDC_TRAINING); /* msgType */ + stream_write_BYTE(pdu, 0); /* bPad */ + stream_write_UINT16(pdu, 4); /* BodySize */ + stream_write_UINT16(pdu, wTimeStamp); + stream_write_UINT16(pdu, wPackSize); + + svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu); +} + +static void rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, STREAM* s) { UINT16 wTimeStamp; UINT16 wPackSize; - STREAM* data_out; - stream_read_UINT16(data_in, wTimeStamp); - stream_read_UINT16(data_in, wPackSize); + stream_read_UINT16(s, wTimeStamp); + stream_read_UINT16(s, wPackSize); - data_out = stream_new(8); - stream_write_BYTE(data_out, SNDC_TRAINING); /* msgType */ - stream_write_BYTE(data_out, 0); /* bPad */ - stream_write_UINT16(data_out, 4); /* BodySize */ - stream_write_UINT16(data_out, wTimeStamp); - stream_write_UINT16(data_out, wPackSize); - - svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); + rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize); } -static void rdpsnd_process_message_wave_info(rdpsndPlugin* rdpsnd, STREAM* data_in, UINT16 BodySize) +static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, STREAM* s, UINT16 BodySize) { UINT16 wFormatNo; + AUDIO_FORMAT* format; - stream_read_UINT16(data_in, rdpsnd->wTimeStamp); - stream_read_UINT16(data_in, wFormatNo); - stream_read_BYTE(data_in, rdpsnd->cBlockNo); - stream_seek(data_in, 3); /* bPad */ - stream_read(data_in, rdpsnd->waveData, 4); - rdpsnd->waveDataSize = BodySize - 8; - rdpsnd->wave_timestamp = get_mstime(); rdpsnd->expectingWave = TRUE; - DEBUG_SVC("waveDataSize %d wFormatNo %d", rdpsnd->waveDataSize, wFormatNo); + stream_read_UINT16(s, rdpsnd->wTimeStamp); + stream_read_UINT16(s, wFormatNo); + stream_read_BYTE(s, rdpsnd->cBlockNo); + stream_seek(s, 3); /* bPad */ + stream_read(s, rdpsnd->waveData, 4); - rdpsnd->close_timestamp = 0; + rdpsnd->waveDataSize = BodySize - 8; - if (!rdpsnd->is_open) + format = &rdpsnd->ClientFormats[wFormatNo]; + + if (!rdpsnd->isOpen) { - rdpsnd->current_format = wFormatNo; - rdpsnd->is_open = TRUE; + rdpsnd->isOpen = TRUE; + rdpsnd->wCurrentFormatNo = wFormatNo; + + //rdpsnd_print_audio_format(format); if (rdpsnd->device) { - IFCALL(rdpsnd->device->Open, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo], - rdpsnd->latency); + IFCALL(rdpsnd->device->Open, rdpsnd->device, format, rdpsnd->latency); } } - else if (wFormatNo != rdpsnd->current_format) + else if (wFormatNo != rdpsnd->wCurrentFormatNo) { - rdpsnd->current_format = wFormatNo; + rdpsnd->wCurrentFormatNo = wFormatNo; if (rdpsnd->device) { - IFCALL(rdpsnd->device->SetFormat, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo], - rdpsnd->latency); + IFCALL(rdpsnd->device->SetFormat, rdpsnd->device, format, rdpsnd->latency); } } } -/* header is not removed from data in this function */ -static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in) +void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE cConfirmedBlockNo) { - UINT16 wTimeStamp; - UINT32 delay_ms; - UINT32 process_ms; - struct data_out_item* item; + STREAM* pdu; - rdpsnd->expectingWave = 0; + pdu = stream_new(8); + stream_write_BYTE(pdu, SNDC_WAVECONFIRM); + stream_write_BYTE(pdu, 0); + stream_write_UINT16(pdu, 4); + stream_write_UINT16(pdu, wTimeStamp); + stream_write_BYTE(pdu, cConfirmedBlockNo); /* cConfirmedBlockNo */ + stream_write_BYTE(pdu, 0); /* bPad */ - memcpy(stream_get_head(data_in), rdpsnd->waveData, 4); - - if (stream_get_size(data_in) != rdpsnd->waveDataSize) - { - DEBUG_WARN("size error"); - return; - } - - if (rdpsnd->device) - { - IFCALL(rdpsnd->device->Play, rdpsnd->device, stream_get_head(data_in), stream_get_size(data_in)); - } - - process_ms = get_mstime() - rdpsnd->wave_timestamp; - delay_ms = 250; - wTimeStamp = rdpsnd->wTimeStamp + delay_ms; - - DEBUG_SVC("data_size %d delay_ms %u process_ms %u", - stream_get_size(data_in), delay_ms, process_ms); - - item = (struct data_out_item*) malloc(sizeof(struct data_out_item)); - ZeroMemory(item, sizeof(struct data_out_item)); - - item->data_out = stream_new(8); - stream_write_BYTE(item->data_out, SNDC_WAVECONFIRM); - stream_write_BYTE(item->data_out, 0); - stream_write_UINT16(item->data_out, 4); - stream_write_UINT16(item->data_out, wTimeStamp); - stream_write_BYTE(item->data_out, rdpsnd->cBlockNo); /* cConfirmedBlockNo */ - stream_write_BYTE(item->data_out, 0); /* bPad */ - item->out_timestamp = rdpsnd->wave_timestamp + delay_ms; - - list_enqueue(rdpsnd->data_out_list, item); - rdpsnd->plugin.interval_ms = 10; + svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu); } -static void rdpsnd_process_message_close(rdpsndPlugin* rdpsnd) +void rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) +{ + MessageQueue_Post(device->rdpsnd->queue, NULL, 0, (void*) wave, NULL); +} + +static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, STREAM* s) +{ + int size; + BYTE* data; + RDPSND_WAVE* wave; + AUDIO_FORMAT* format; + + rdpsnd->expectingWave = FALSE; + + /** + * The Wave PDU is a special case: it is always sent after a Wave Info PDU, + * and we do not process its header. Instead, the header is pad that needs + * to be filled with the first four bytes of the audio sample data sent as + * part of the preceding Wave Info PDU. + */ + + CopyMemory(stream_get_head(s), rdpsnd->waveData, 4); + + data = stream_get_head(s); + size = stream_get_size(s); + + wave = (RDPSND_WAVE*) malloc(sizeof(RDPSND_WAVE)); + + wave->wLocalTimeA = GetTickCount(); + wave->wTimeStampA = rdpsnd->wTimeStamp; + wave->wFormatNo = rdpsnd->wCurrentFormatNo; + wave->cBlockNo = rdpsnd->cBlockNo; + + wave->data = data; + wave->length = size; + + format = &rdpsnd->ClientFormats[rdpsnd->wCurrentFormatNo]; + wave->wAudioLength = rdpsnd_compute_audio_time_length(format, size); + + if (!rdpsnd->device) + return; + + if (rdpsnd->device->WaveDecode) + { + IFCALL(rdpsnd->device->WaveDecode, rdpsnd->device, wave); + } + + if (rdpsnd->device->WavePlay) + { + IFCALL(rdpsnd->device->WavePlay, rdpsnd->device, wave); + } + else + { + IFCALL(rdpsnd->device->Play, rdpsnd->device, data, size); + } + + if (!rdpsnd->device->WavePlay) + { + wave->wTimeStampB = rdpsnd->wTimeStamp + wave->wAudioLength + TIME_DELAY_MS; + wave->wLocalTimeB = wave->wLocalTimeA + wave->wAudioLength + TIME_DELAY_MS; + rdpsnd->device->WaveConfirm(rdpsnd->device, wave); + } +} + +static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd) { DEBUG_SVC("server closes."); if (rdpsnd->device) { - IFCALL(rdpsnd->device->Start, rdpsnd->device); + IFCALL(rdpsnd->device->Close, rdpsnd->device); } - rdpsnd->close_timestamp = get_mstime() + 2000; - rdpsnd->plugin.interval_ms = 10; + rdpsnd->isOpen = FALSE; } -static void rdpsnd_process_message_setvolume(rdpsndPlugin* rdpsnd, STREAM* data_in) +static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, STREAM* s) { UINT32 dwVolume; - stream_read_UINT32(data_in, dwVolume); + stream_read_UINT32(s, dwVolume); DEBUG_SVC("dwVolume 0x%X", dwVolume); if (rdpsnd->device) @@ -415,45 +569,45 @@ static void rdpsnd_process_message_setvolume(rdpsndPlugin* rdpsnd, STREAM* data_ } } -static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) +static void rdpsnd_recv_pdu(rdpSvcPlugin* plugin, STREAM* s) { - rdpsndPlugin* rdpsnd = (rdpsndPlugin*)plugin; BYTE msgType; UINT16 BodySize; + rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin; if (rdpsnd->expectingWave) { - rdpsnd_process_message_wave(rdpsnd, data_in); - stream_free(data_in); + rdpsnd_recv_wave_pdu(rdpsnd, s); + stream_free(s); return; } - stream_read_BYTE(data_in, msgType); /* msgType */ - stream_seek_BYTE(data_in); /* bPad */ - stream_read_UINT16(data_in, BodySize); + stream_read_BYTE(s, msgType); /* msgType */ + stream_seek_BYTE(s); /* bPad */ + stream_read_UINT16(s, BodySize); - DEBUG_SVC("msgType %d BodySize %d", msgType, BodySize); + //printf("msgType %d BodySize %d\n", msgType, BodySize); switch (msgType) { case SNDC_FORMATS: - rdpsnd_process_message_formats(rdpsnd, data_in); + rdpsnd_recv_server_audio_formats_pdu(rdpsnd, s); break; case SNDC_TRAINING: - rdpsnd_process_message_training(rdpsnd, data_in); + rdpsnd_recv_training_pdu(rdpsnd, s); break; case SNDC_WAVE: - rdpsnd_process_message_wave_info(rdpsnd, data_in, BodySize); + rdpsnd_recv_wave_info_pdu(rdpsnd, s, BodySize); break; case SNDC_CLOSE: - rdpsnd_process_message_close(rdpsnd); + rdpsnd_recv_close_pdu(rdpsnd); break; case SNDC_SETVOLUME: - rdpsnd_process_message_setvolume(rdpsnd, data_in); + rdpsnd_recv_volume_pdu(rdpsnd, s); break; default: @@ -461,7 +615,7 @@ static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) break; } - stream_free(data_in); + stream_free(s); } static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlugin* device) @@ -471,7 +625,11 @@ static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlug DEBUG_WARN("existing device, abort."); return; } + rdpsnd->device = device; + device->rdpsnd = rdpsnd; + + device->WaveConfirm = rdpsnd_device_send_wave_confirm_pdu; } static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, ADDIN_ARGV* args) @@ -481,7 +639,7 @@ static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, AD entry = (PFREERDP_RDPSND_DEVICE_ENTRY) freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0); - if (entry == NULL) + if (!entry) return FALSE; entryPoints.rdpsnd = rdpsnd; @@ -554,15 +712,15 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args) } CommandLineSwitchCase(arg, "format") { - rdpsnd->fixed_format = atoi(arg->Value); + rdpsnd->fixedFormat = atoi(arg->Value); } CommandLineSwitchCase(arg, "rate") { - rdpsnd->fixed_rate = atoi(arg->Value); + rdpsnd->fixedRate = atoi(arg->Value); } CommandLineSwitchCase(arg, "channel") { - rdpsnd->fixed_channel = atoi(arg->Value); + rdpsnd->fixedChannel = atoi(arg->Value); } CommandLineSwitchCase(arg, "latency") { @@ -585,10 +743,9 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin) DEBUG_SVC("connecting"); - plugin->interval_callback = rdpsnd_process_interval; - - rdpsnd->data_out_list = list_new(); rdpsnd->latency = -1; + rdpsnd->queue = MessageQueue_New(); + rdpsnd->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread, (void*) plugin, 0, NULL); args = (ADDIN_ARGV*) plugin->channel_entry_points.pExtendedData; @@ -631,9 +788,10 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin) rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args); } - if (rdpsnd->device == NULL) + if (!rdpsnd->device) { DEBUG_WARN("no sound device."); + return; } } @@ -644,21 +802,16 @@ static void rdpsnd_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) static void rdpsnd_process_terminate(rdpSvcPlugin* plugin) { - struct data_out_item* item; rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin; if (rdpsnd->device) IFCALL(rdpsnd->device->Free, rdpsnd->device); - if (rdpsnd->data_out_list) - { - while ((item = list_dequeue(rdpsnd->data_out_list)) != NULL) - { - stream_free(item->data_out); - free(item); - } - list_free(rdpsnd->data_out_list); - } + MessageQueue_PostQuit(rdpsnd->queue, 0); + WaitForSingleObject(rdpsnd->thread, INFINITE); + + MessageQueue_Free(rdpsnd->queue); + CloseHandle(rdpsnd->thread); if (rdpsnd->subsystem) free(rdpsnd->subsystem); @@ -666,9 +819,13 @@ static void rdpsnd_process_terminate(rdpSvcPlugin* plugin) if (rdpsnd->device_name) free(rdpsnd->device_name); - rdpsnd_free_supported_formats(rdpsnd); + rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); + rdpsnd->NumberOfServerFormats = 0; + rdpsnd->ServerFormats = NULL; - free(plugin); + rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); + rdpsnd->NumberOfClientFormats = 0; + rdpsnd->ClientFormats = NULL; } /* rdpsnd is always built-in */ @@ -688,10 +845,19 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) strcpy(_p->plugin.channel_def.name, "rdpsnd"); _p->plugin.connect_callback = rdpsnd_process_connect; - _p->plugin.receive_callback = rdpsnd_process_receive; + _p->plugin.receive_callback = rdpsnd_recv_pdu; _p->plugin.event_callback = rdpsnd_process_event; _p->plugin.terminate_callback = rdpsnd_process_terminate; +#if !defined(_WIN32) && !defined(ANDROID) + { + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGIO); + pthread_sigmask(SIG_BLOCK, &mask, NULL); + } +#endif + svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints); return 1; diff --git a/channels/rdpsnd/client/rdpsnd_main.h b/channels/rdpsnd/client/rdpsnd_main.h index 654dad27c..19352d0f3 100644 --- a/channels/rdpsnd/client/rdpsnd_main.h +++ b/channels/rdpsnd/client/rdpsnd_main.h @@ -22,29 +22,60 @@ #include +struct _RDPSND_WAVE +{ + BYTE* data; + int length; + + BYTE cBlockNo; + UINT16 wFormatNo; + UINT16 wTimeStampA; + UINT16 wTimeStampB; + + UINT16 wLatency; + UINT16 wAudioLength; + UINT16 wPlaybackDelay; + + UINT32 wLocalTimeA; + UINT32 wLocalTimeB; +}; +typedef struct _RDPSND_WAVE RDPSND_WAVE; + typedef struct rdpsnd_plugin rdpsndPlugin; typedef struct rdpsnd_device_plugin rdpsndDevicePlugin; -typedef BOOL (*pcFormatSupported) (rdpsndDevicePlugin* device, rdpsndFormat* format); -typedef void (*pcOpen) (rdpsndDevicePlugin* device, rdpsndFormat* format, int latency); -typedef void (*pcSetFormat) (rdpsndDevicePlugin* device, rdpsndFormat* format, int latency); +typedef BOOL (*pcFormatSupported) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format); +typedef void (*pcOpen) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency); +typedef void (*pcSetFormat) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency); +typedef UINT32 (*pcGetVolume) (rdpsndDevicePlugin* device); typedef void (*pcSetVolume) (rdpsndDevicePlugin* device, UINT32 value); typedef void (*pcPlay) (rdpsndDevicePlugin* device, BYTE* data, int size); typedef void (*pcStart) (rdpsndDevicePlugin* device); typedef void (*pcClose) (rdpsndDevicePlugin* device); typedef void (*pcFree) (rdpsndDevicePlugin* device); +typedef void (*pcWaveDecode) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave); +typedef void (*pcWavePlay) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave); +typedef void (*pcWaveConfirm) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave); + struct rdpsnd_device_plugin { + rdpsndPlugin* rdpsnd; + pcFormatSupported FormatSupported; pcOpen Open; pcSetFormat SetFormat; + pcGetVolume GetVolume; pcSetVolume SetVolume; pcPlay Play; pcStart Start; pcClose Close; pcFree Free; + + pcWaveDecode WaveDecode; + pcWavePlay WavePlay; + pcWaveConfirm WaveConfirm; }; #define RDPSND_DEVICE_EXPORT_FUNC_NAME "freerdp_rdpsnd_client_subsystem_entry" diff --git a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c index dc4bd7f14..564b2f63f 100644 --- a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c +++ b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include "rdpsnd_main.h" @@ -63,7 +63,7 @@ struct rdpsnd_winmm_plugin FREERDP_DSP_CONTEXT* dsp_context; }; -static BOOL rdpsnd_winmm_convert_format(const rdpsndFormat* in, WAVEFORMATEX* out) +static BOOL rdpsnd_winmm_convert_format(const AUDIO_FORMAT* in, WAVEFORMATEX* out) { BOOL result = FALSE; @@ -71,6 +71,7 @@ static BOOL rdpsnd_winmm_convert_format(const rdpsndFormat* in, WAVEFORMATEX* ou out->wFormatTag = WAVE_FORMAT_PCM; out->nChannels = in->nChannels; out->nSamplesPerSec = in->nSamplesPerSec; + switch (in->wFormatTag) { case WAVE_FORMAT_PCM: @@ -78,12 +79,13 @@ static BOOL rdpsnd_winmm_convert_format(const rdpsndFormat* in, WAVEFORMATEX* ou result = TRUE; break; - case 2: /* MS ADPCM */ - case 0x11: /* IMA ADPCM */ + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: out->wBitsPerSample = 16; result = TRUE; break; } + out->nBlockAlign = out->nChannels * out->wBitsPerSample / 8; out->nAvgBytesPerSec = out->nSamplesPerSec * out->nBlockAlign; @@ -98,19 +100,22 @@ static void rdpsnd_winmm_clear_datablocks(rdpsndWinmmPlugin* winmm, BOOL drain) { if (!drain && (datablock->header.dwFlags & WHDR_DONE) == 0) break; + while ((datablock->header.dwFlags & WHDR_DONE) == 0) WaitForSingleObject(winmm->event, INFINITE); + winmm->datablock_head = datablock->next; + free(datablock->header.lpData); free(datablock); } } -static void rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) +static void rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) { rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*)device; - if (format != NULL) + if (format) { rdpsnd_winmm_convert_format(format, &winmm->format); @@ -121,7 +126,7 @@ static void rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, rdpsndFormat* fo winmm->latency = latency; } -static void rdpsnd_winmm_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) +static void rdpsnd_winmm_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) { MMRESULT result; rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device; @@ -135,6 +140,7 @@ static void rdpsnd_winmm_open(rdpsndDevicePlugin* device, rdpsndFormat* format, freerdp_dsp_context_reset_adpcm(winmm->dsp_context); result = waveOutOpen(&winmm->out_handle, WAVE_MAPPER, &winmm->format, (DWORD_PTR) winmm->event, 0, CALLBACK_EVENT); + if (result != MMSYSERR_NOERROR) { DEBUG_WARN("waveOutOpen failed: %d", result); @@ -145,14 +151,16 @@ static void rdpsnd_winmm_close(rdpsndDevicePlugin* device) { rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*)device; - if (winmm->out_handle != NULL) + if (winmm->out_handle) { DEBUG_SVC("close"); rdpsnd_winmm_clear_datablocks(winmm, TRUE); + if (waveOutClose(winmm->out_handle) != MMSYSERR_NOERROR) { DEBUG_WARN("waveOutClose error"); } + winmm->out_handle = NULL; } } @@ -167,7 +175,7 @@ static void rdpsnd_winmm_free(rdpsndDevicePlugin* device) free(winmm); } -static BOOL rdpsnd_winmm_format_supported(rdpsndDevicePlugin* device, rdpsndFormat* format) +static BOOL rdpsnd_winmm_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format) { MMRESULT result; WAVEFORMATEX out; @@ -175,6 +183,7 @@ static BOOL rdpsnd_winmm_format_supported(rdpsndDevicePlugin* device, rdpsndForm if (rdpsnd_winmm_convert_format(format, &out)) { result = waveOutOpen(NULL, WAVE_MAPPER, &out, 0, 0, WAVE_FORMAT_QUERY); + if (result == MMSYSERR_NOERROR) return TRUE; } @@ -182,11 +191,31 @@ static BOOL rdpsnd_winmm_format_supported(rdpsndDevicePlugin* device, rdpsndForm return FALSE; } +static UINT32 rdpsnd_winmm_get_volume(rdpsndDevicePlugin* device) +{ + DWORD dwVolume; + UINT16 dwVolumeLeft; + UINT16 dwVolumeRight; + + rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device; + + dwVolumeLeft = ((50 * 0xFFFF) / 100); /* 50% */ + dwVolumeRight = ((50 * 0xFFFF) / 100); /* 50% */ + dwVolume = (dwVolumeLeft << 16) | dwVolumeRight; + + if (!winmm->out_handle) + return dwVolume; + + waveOutGetVolume(winmm->out_handle, &dwVolume); + + return dwVolume; +} + static void rdpsnd_winmm_set_volume(rdpsndDevicePlugin* device, UINT32 value) { rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device; - if (winmm->out_handle == NULL) + if (!winmm->out_handle) return; waveOutSetVolume(winmm->out_handle, value); @@ -200,17 +229,17 @@ static void rdpsnd_winmm_play(rdpsndDevicePlugin* device, BYTE* data, int size) rdpsndWinmmDatablock* datablock; rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device; - if (winmm->out_handle == NULL) + if (!winmm->out_handle) return; - if (winmm->wformat == 2) + if (winmm->wformat == WAVE_FORMAT_ADPCM) { winmm->dsp_context->decode_ms_adpcm(winmm->dsp_context, data, size, winmm->format.nChannels, winmm->block_size); size = winmm->dsp_context->adpcm_size; src = winmm->dsp_context->adpcm_buffer; } - else if (winmm->wformat == 0x11) + else if (winmm->wformat == WAVE_FORMAT_DVI_ADPCM) { winmm->dsp_context->decode_ima_adpcm(winmm->dsp_context, data, size, winmm->format.nChannels, winmm->block_size); @@ -223,25 +252,32 @@ static void rdpsnd_winmm_play(rdpsndDevicePlugin* device, BYTE* data, int size) } rdpsnd_winmm_clear_datablocks(winmm, FALSE); + for (last = winmm->datablock_head; last && last->next; last = last->next) { + } + datablock = (rdpsndWinmmDatablock*) malloc(sizeof(rdpsndWinmmDatablock)); ZeroMemory(datablock, sizeof(rdpsndWinmmDatablock)); + if (last) last->next = datablock; else winmm->datablock_head = datablock; + datablock->header.dwBufferLength = size; datablock->header.lpData = (LPSTR) malloc(size); CopyMemory(datablock->header.lpData, src, size); result = waveOutPrepareHeader(winmm->out_handle, &datablock->header, sizeof(datablock->header)); + if (result != MMSYSERR_NOERROR) { DEBUG_WARN("waveOutPrepareHeader: %d", result); return; } + ResetEvent(winmm->event); waveOutWrite(winmm->out_handle, &datablock->header, sizeof(datablock->header)); } @@ -272,6 +308,7 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE winmm->device.Open = rdpsnd_winmm_open; winmm->device.FormatSupported = rdpsnd_winmm_format_supported; winmm->device.SetFormat = rdpsnd_winmm_set_format; + winmm->device.GetVolume = rdpsnd_winmm_get_volume; winmm->device.SetVolume = rdpsnd_winmm_set_volume; winmm->device.Play = rdpsnd_winmm_play; winmm->device.Start = rdpsnd_winmm_start; diff --git a/channels/rdpsnd/server/rdpsnd.c b/channels/rdpsnd/server/rdpsnd.c index 0b499f929..801ea8938 100644 --- a/channels/rdpsnd/server/rdpsnd.c +++ b/channels/rdpsnd/server/rdpsnd.c @@ -27,7 +27,7 @@ #include -#include +#include #include #include #include @@ -129,8 +129,8 @@ static BOOL rdpsnd_server_recv_formats(rdpsnd_server* rdpsnd, STREAM* s) if (rdpsnd->context.num_client_formats > 0) { - rdpsnd->context.client_formats = (rdpsndFormat*) malloc(rdpsnd->context.num_client_formats * sizeof(rdpsndFormat)); - ZeroMemory(rdpsnd->context.client_formats, sizeof(rdpsndFormat)); + rdpsnd->context.client_formats = (AUDIO_FORMAT*) malloc(rdpsnd->context.num_client_formats * sizeof(AUDIO_FORMAT)); + ZeroMemory(rdpsnd->context.client_formats, sizeof(AUDIO_FORMAT)); for (i = 0; i < rdpsnd->context.num_client_formats; i++) { @@ -184,7 +184,8 @@ static void* rdpsnd_server_thread_func(void* arg) while (1) { - freerdp_thread_wait(thread); + if (freerdp_thread_wait(thread) < 0) + break; if (freerdp_thread_is_stopped(thread)) break; @@ -254,7 +255,7 @@ static void rdpsnd_server_select_format(rdpsnd_server_context* context, int clie { int bs; int out_buffer_size; - rdpsndFormat *format; + AUDIO_FORMAT *format; rdpsnd_server* rdpsnd = (rdpsnd_server*) context; if (client_format_index < 0 || client_format_index >= context->num_client_formats) @@ -308,7 +309,7 @@ static BOOL rdpsnd_server_send_audio_pdu(rdpsnd_server* rdpsnd) BYTE* src; int frames; int fill_size; - rdpsndFormat* format; + AUDIO_FORMAT* format; int tbytes_per_frame; STREAM* s = rdpsnd->rdpsnd_pdu; diff --git a/channels/sample/client/sample_main.c b/channels/sample/client/sample_main.c index 77f176ca0..0c8d3571d 100644 --- a/channels/sample/client/sample_main.c +++ b/channels/sample/client/sample_main.c @@ -45,14 +45,8 @@ struct sample_plugin rdpSvcPlugin plugin; /* put your private data here */ - }; -static void sample_process_interval(rdpSvcPlugin* plugin) -{ - printf("sample_process_interval:\n"); -} - static void sample_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) { int bytes; @@ -61,17 +55,18 @@ static void sample_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) printf("sample_process_receive:\n"); - if (sample == NULL) + if (!sample) { printf("sample_process_receive: sample is nil\n"); return; } - /* process data in(from server) here */ + /* process data in (from server) here */ /* here we just send the same data back */ bytes = stream_get_size(data_in); printf("sample_process_receive: got bytes %d\n", bytes); + if (bytes > 0) { data_out = stream_new(bytes); @@ -95,22 +90,15 @@ static void sample_process_connect(rdpSvcPlugin* plugin) printf("sample_process_connect:\n"); - if (sample == NULL) - { + if (!sample) return; - } - - /* if you want a call from channel thread once is a while do this */ - plugin->interval_ms = 1000; - plugin->interval_callback = sample_process_interval; - } static void sample_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { printf("sample_process_event:\n"); - /* events comming from main freerdp window to plugin */ + /* events coming from main freerdp window to plugin */ /* send them back with svc_plugin_send_event */ freerdp_event_free(event); @@ -118,14 +106,12 @@ static void sample_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) static void sample_process_terminate(rdpSvcPlugin* plugin) { - samplePlugin* sample = (samplePlugin*)plugin; + samplePlugin* sample = (samplePlugin*) plugin; printf("sample_process_terminate:\n"); - if (sample == NULL) - { + if (!sample) return; - } /* put your cleanup here */ diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index 043dedbac..bbcdbeba7 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -341,7 +341,8 @@ static void* serial_thread_func(void* arg) while (1) { - freerdp_thread_wait_timeout(serial->thread, 500); + if (freerdp_thread_wait_timeout(serial->thread, 500) < 0) + break; serial->nfds = 1; FD_ZERO(&serial->read_fds); diff --git a/channels/server/CMakeLists.txt b/channels/server/CMakeLists.txt index 5e248110d..fbe33d668 100644 --- a/channels/server/CMakeLists.txt +++ b/channels/server/CMakeLists.txt @@ -35,7 +35,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVER set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE freerdp - MODULES freerdp-utils) + MODULES freerdp-codec freerdp-utils) set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} diff --git a/channels/tsmf/client/alsa/tsmf_alsa.c b/channels/tsmf/client/alsa/tsmf_alsa.c index 393f62ea8..74c78a744 100644 --- a/channels/tsmf/client/alsa/tsmf_alsa.c +++ b/channels/tsmf/client/alsa/tsmf_alsa.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include "tsmf_audio.h" diff --git a/client/Android/AndroidManifest.xml.cmake b/client/Android/AndroidManifest.xml.cmake deleted file mode 100644 index 0fd9e9c1b..000000000 --- a/client/Android/AndroidManifest.xml.cmake +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/client/Android/CMakeLists.txt b/client/Android/CMakeLists.txt index bf543ed2e..9557f7e63 100644 --- a/client/Android/CMakeLists.txt +++ b/client/Android/CMakeLists.txt @@ -1,7 +1,6 @@ # FreeRDP: A Remote Desktop Protocol Implementation # Android Client # -# Copyright 2012 Marc-Andre Moreau # Copyright 2013 Bernhard Miklautz # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,23 +15,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -set(ANDROID_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(ANDROID_PACKAGE_NAME "aFreeRDP") - -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake ${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml @ONLY) - -if (ANDROID_SDK) - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/local.properties.cmake ${CMAKE_CURRENT_SOURCE_DIR}/local.properties @ONLY) -endif() - -add_subdirectory(jni) - - if(ANDROID_BUILD_JAVA) if (NOT ANDROID_SDK) message(FATAL_ERROR "ANDROID_SDK not set but required for building the java gui (ANDROID_BUILD_JAVA)") endif() - # And isn't shiped with the android ndk/sdk so # we need to find it on the local machine SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH) @@ -43,22 +29,12 @@ if(ANDROID_BUILD_JAVA) message(FATAL_ERROR "ant not found but required to build android java") endif() - if(ANDROID_BUILD_JAVA_DEBUG) + if(ANDROID_BUILD_JAVA_DEBUG) set(ANDROID_BUILD_TYPE "debug") - set(APK "${ANDROID_SOURCE_DIR}/bin/${ANDROID_PACKAGE_NAME}-release-unsigned.apk") else() set(ANDROID_BUILD_TYPE "release") - set(APK "${ANDROID_SOURCE_DIR}/bin/${ANDROID_PACKAGE_NAME}-debug.apk") endif() +endif(ANDROID_BUILD_JAVA) - # command to create the android package - add_custom_command( - OUTPUT "${APK}" - COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE} - WORKING_DIRECTORY "${ANDROID_SOURCE_DIR}" - MAIN_DEPENDENCY AndroidManifest.xml - DEPENDS freerdp-android local.properties - ) - add_custom_target(android-package ALL SOURCES "${APK}") - SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin") -endif() +add_subdirectory(FreeRDPCore) +add_subdirectory(aFreeRDP) diff --git a/client/Android/FreeRDPCore/.classpath b/client/Android/FreeRDPCore/.classpath new file mode 100644 index 000000000..a4763d1ee --- /dev/null +++ b/client/Android/FreeRDPCore/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/client/Android/FreeRDPCore/.project b/client/Android/FreeRDPCore/.project new file mode 100644 index 000000000..85408c31b --- /dev/null +++ b/client/Android/FreeRDPCore/.project @@ -0,0 +1,33 @@ + + + FreeRDPCore + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/client/Android/FreeRDPCore/AndroidManifest.xml.cmake b/client/Android/FreeRDPCore/AndroidManifest.xml.cmake new file mode 100644 index 000000000..03344d43f --- /dev/null +++ b/client/Android/FreeRDPCore/AndroidManifest.xml.cmake @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/Android/FreeRDPCore/CMakeLists.txt b/client/Android/FreeRDPCore/CMakeLists.txt new file mode 100644 index 000000000..005e90d45 --- /dev/null +++ b/client/Android/FreeRDPCore/CMakeLists.txt @@ -0,0 +1,44 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# Android Client +# +# Copyright 2012 Marc-Andre Moreau +# Copyright 2013 Bernhard Miklautz +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set(ANDROID_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(ANDROID_PACKAGE_NAME "aFreeRDPCore") + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake ${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml @ONLY) + +if (ANDROID_SDK) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/local.properties.cmake ${CMAKE_CURRENT_SOURCE_DIR}/local.properties @ONLY) +endif() + +add_subdirectory(jni) + + +if(ANDROID_BUILD_JAVA) + set(ANDROIDLIB "${ANDROID_SOURCE_DIR}/bin/classes.jar") + + # command to create the android package + add_custom_command( + OUTPUT "${ANDROIDLIB}" + COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE} + WORKING_DIRECTORY "${ANDROID_SOURCE_DIR}" + MAIN_DEPENDENCY AndroidManifest.xml + DEPENDS freerdp-android local.properties + ) + add_custom_target(android-lib ALL SOURCES "${ANDROIDLIB}") + SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin") +endif() diff --git a/client/Android/FreeRDPCore/ant.properties b/client/Android/FreeRDPCore/ant.properties new file mode 100644 index 000000000..73031c7a7 --- /dev/null +++ b/client/Android/FreeRDPCore/ant.properties @@ -0,0 +1,16 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked into Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. diff --git a/client/Android/FreeRDPCore/build.xml b/client/Android/FreeRDPCore/build.xml new file mode 100644 index 000000000..f07d7de42 --- /dev/null +++ b/client/Android/FreeRDPCore/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/Android/jni/CMakeLists.txt b/client/Android/FreeRDPCore/jni/CMakeLists.txt similarity index 100% rename from client/Android/jni/CMakeLists.txt rename to client/Android/FreeRDPCore/jni/CMakeLists.txt diff --git a/client/Android/jni/android_debug.h b/client/Android/FreeRDPCore/jni/android_debug.h similarity index 100% rename from client/Android/jni/android_debug.h rename to client/Android/FreeRDPCore/jni/android_debug.h diff --git a/client/Android/jni/android_event.c b/client/Android/FreeRDPCore/jni/android_event.c similarity index 100% rename from client/Android/jni/android_event.c rename to client/Android/FreeRDPCore/jni/android_event.c diff --git a/client/Android/jni/android_event.h b/client/Android/FreeRDPCore/jni/android_event.h similarity index 100% rename from client/Android/jni/android_event.h rename to client/Android/FreeRDPCore/jni/android_event.h diff --git a/client/Android/jni/android_freerdp.c b/client/Android/FreeRDPCore/jni/android_freerdp.c similarity index 99% rename from client/Android/jni/android_freerdp.c rename to client/Android/FreeRDPCore/jni/android_freerdp.c index 6a31ebc0e..7f84dea75 100644 --- a/client/Android/jni/android_freerdp.c +++ b/client/Android/FreeRDPCore/jni/android_freerdp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -536,7 +537,10 @@ JNIEXPORT void JNICALL jni_freerdp_set_data_directory(JNIEnv *env, jclass cls, j const jbyte *directory = (*env)->GetStringUTFChars(env, jdirectory, NULL); free(settings->HomePath); + free(settings->ConfigPath); settings->HomePath = strdup(directory); + settings->ConfigPath = NULL; + freerdp_detect_paths(settings); (*env)->ReleaseStringUTFChars(env, jdirectory, directory); } @@ -655,7 +659,6 @@ JNIEXPORT void JNICALL jni_freerdp_set_performance_flags( settings->FastPathOutput = TRUE; settings->ColorDepth = 32; settings->LargePointerFlag = TRUE; - settings->PerformanceFlags = PERF_FLAG_NONE; settings->FrameMarkerCommandEnabled = TRUE; } @@ -680,6 +683,7 @@ JNIEXPORT void JNICALL jni_freerdp_set_performance_flags( /* Create performance flags from settings */ + settings->PerformanceFlags = PERF_FLAG_NONE; if (settings->AllowFontSmoothing) settings->PerformanceFlags |= PERF_ENABLE_FONT_SMOOTHING; diff --git a/client/Android/jni/android_freerdp.h b/client/Android/FreeRDPCore/jni/android_freerdp.h similarity index 100% rename from client/Android/jni/android_freerdp.h rename to client/Android/FreeRDPCore/jni/android_freerdp.h diff --git a/client/Android/jni/android_jni_callback.c b/client/Android/FreeRDPCore/jni/android_jni_callback.c similarity index 100% rename from client/Android/jni/android_jni_callback.c rename to client/Android/FreeRDPCore/jni/android_jni_callback.c diff --git a/client/Android/jni/android_jni_callback.h b/client/Android/FreeRDPCore/jni/android_jni_callback.h similarity index 100% rename from client/Android/jni/android_jni_callback.h rename to client/Android/FreeRDPCore/jni/android_jni_callback.h diff --git a/client/Android/jni/generated/android_freerdp_jni.c b/client/Android/FreeRDPCore/jni/generated/android_freerdp_jni.c similarity index 59% rename from client/Android/jni/generated/android_freerdp_jni.c rename to client/Android/FreeRDPCore/jni/generated/android_freerdp_jni.c index 8d64e094c..308c146cb 100644 --- a/client/Android/jni/generated/android_freerdp_jni.c +++ b/client/Android/FreeRDPCore/jni/generated/android_freerdp_jni.c @@ -20,32 +20,32 @@ #include "android_freerdp.h" #include "android_freerdp_jni.h" -JNIEXPORT jint JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1new(JNIEnv *env, jclass cls) +JNIEXPORT jint JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1new(JNIEnv *env, jclass cls) { return jni_freerdp_new(env, cls); } -JNIEXPORT void JNICALL JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1free(JNIEnv *env, jclass cls, jint instance) +JNIEXPORT void JNICALL JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1free(JNIEnv *env, jclass cls, jint instance) { jni_freerdp_free(env, cls, instance); } -JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1connect(JNIEnv *env, jclass cls, jint instance) +JNIEXPORT jboolean JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1connect(JNIEnv *env, jclass cls, jint instance) { return jni_freerdp_connect(env, cls, instance); } -JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1disconnect(JNIEnv *env, jclass cls, jint instance) +JNIEXPORT jboolean JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1disconnect(JNIEnv *env, jclass cls, jint instance) { return jni_freerdp_disconnect(env, cls, instance); } -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1cancel_1connection(JNIEnv *env, jclass cls, jint instance) +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1cancel_1connection(JNIEnv *env, jclass cls, jint instance) { jni_freerdp_cancel_connection(env, cls, instance); } -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1connection_1info(JNIEnv *env, jclass cls, jint instance, +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1set_1connection_1info(JNIEnv *env, jclass cls, jint instance, jstring jhostname, jstring jusername, jstring jpassword, jstring jdomain, jint width, jint height, jint color_depth, jint port, jboolean console, jint security, jstring certname) { @@ -53,48 +53,48 @@ JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1se width, height, color_depth, port, console, security, certname); } -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1advanced_1settings(JNIEnv *env, jclass cls, jint instance, jstring remote_program, jstring work_dir) +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1set_1advanced_1settings(JNIEnv *env, jclass cls, jint instance, jstring remote_program, jstring work_dir) { jni_freerdp_set_advanced_settings(env, cls, instance, remote_program, work_dir); } -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1data_1directory(JNIEnv *env, jclass cls, jint instance, jstring directory) +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1set_1data_1directory(JNIEnv *env, jclass cls, jint instance, jstring directory) { jni_freerdp_set_data_directory(env, cls, instance, directory); } -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1performance_1flags( +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1set_1performance_1flags( JNIEnv *env, jclass cls, jint instance, jboolean remotefx, jboolean disableWallpaper, jboolean disableFullWindowDrag, jboolean disableMenuAnimations, jboolean disableTheming, jboolean enableFontSmoothing, jboolean enableDesktopComposition) { jni_freerdp_set_performance_flags(env, cls, instance, remotefx, disableWallpaper, disableFullWindowDrag, disableMenuAnimations, disableTheming, enableFontSmoothing, enableDesktopComposition); } -JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1update_1graphics( +JNIEXPORT jboolean JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1update_1graphics( JNIEnv *env, jclass cls, jint instance, jobject bitmap, jint x, jint y, jint width, jint height) { return jni_freerdp_update_graphics(env, cls, instance, bitmap, x, y, width, height); } -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1cursor_1event( +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1cursor_1event( JNIEnv *env, jclass cls, jint instance, jint x, jint y, jint flags) { jni_freerdp_send_cursor_event(env, cls, instance, x, y, flags); } -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1key_1event( +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1key_1event( JNIEnv *env, jclass cls, jint instance, jint keycode, jboolean down) { jni_freerdp_send_key_event(env, cls, instance, keycode, down); } -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1unicodekey_1event +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1unicodekey_1event (JNIEnv *env, jclass cls, jint instance, jint keycode) { jni_freerdp_send_unicodekey_event(env, cls, instance, keycode); } -JNIEXPORT jstring JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1get_1version(JNIEnv *env, jclass cls) +JNIEXPORT jstring JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1version(JNIEnv *env, jclass cls) { return jni_freerdp_get_version(env, cls); } diff --git a/client/Android/jni/generated/android_freerdp_jni.h b/client/Android/FreeRDPCore/jni/generated/android_freerdp_jni.h similarity index 85% rename from client/Android/jni/generated/android_freerdp_jni.h rename to client/Android/FreeRDPCore/jni/generated/android_freerdp_jni.h index a10d17cc6..fab4c7290 100644 --- a/client/Android/jni/generated/android_freerdp_jni.h +++ b/client/Android/FreeRDPCore/jni/generated/android_freerdp_jni.h @@ -20,9 +20,9 @@ #ifndef __ANDROID_FREERDP_JNI_H #define __ANDROID_FREERDP_JNI_H -#include "com_freerdp_afreerdp_services_LibFreeRDP.h" +#include "com_freerdp_freerdpcore_services_LibFreeRDP.h" -#define JAVA_LIBFREERDP_CLASS "com/freerdp/afreerdp/services/LibFreeRDP" +#define JAVA_LIBFREERDP_CLASS "com/freerdp/freerdpcore/services/LibFreeRDP" #endif /* __ANDROID_FREERDP_JNI_H */ diff --git a/client/Android/FreeRDPCore/jni/generated/com_freerdp_freerdpcore_services_LibFreeRDP.h b/client/Android/FreeRDPCore/jni/generated/com_freerdp_freerdpcore_services_LibFreeRDP.h new file mode 100644 index 000000000..17c62cd99 --- /dev/null +++ b/client/Android/FreeRDPCore/jni/generated/com_freerdp_freerdpcore_services_LibFreeRDP.h @@ -0,0 +1,125 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_freerdp_freerdpcore_services_LibFreeRDP */ + +#ifndef _Included_com_freerdp_freerdpcore_services_LibFreeRDP +#define _Included_com_freerdp_freerdpcore_services_LibFreeRDP +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_new + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1new + (JNIEnv *, jclass); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_free + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1free + (JNIEnv *, jclass, jint); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_connect + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1connect + (JNIEnv *, jclass, jint); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_disconnect + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1disconnect + (JNIEnv *, jclass, jint); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_cancel_connection + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1cancel_1connection + (JNIEnv *, jclass, jint); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_set_connection_info + * Signature: (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIZILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1set_1connection_1info + (JNIEnv *, jclass, jint, jstring, jstring, jstring, jstring, jint, jint, jint, jint, jboolean, jint, jstring); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_set_performance_flags + * Signature: (IZZZZZZZ)V + */ +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1set_1performance_1flags + (JNIEnv *, jclass, jint, jboolean, jboolean, jboolean, jboolean, jboolean, jboolean, jboolean); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_set_advanced_settings + * Signature: (ILjava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1set_1advanced_1settings + (JNIEnv *, jclass, jint, jstring, jstring); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_set_data_directory + * Signature: (ILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1set_1data_1directory + (JNIEnv *, jclass, jint, jstring); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_update_graphics + * Signature: (ILandroid/graphics/Bitmap;IIII)Z + */ +JNIEXPORT jboolean JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1update_1graphics + (JNIEnv *, jclass, jint, jobject, jint, jint, jint, jint); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_send_cursor_event + * Signature: (IIII)V + */ +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1cursor_1event + (JNIEnv *, jclass, jint, jint, jint, jint); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_send_key_event + * Signature: (IIZ)V + */ +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1key_1event + (JNIEnv *, jclass, jint, jint, jboolean); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_send_unicodekey_event + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1send_1unicodekey_1event + (JNIEnv *, jclass, jint, jint); + +/* + * Class: com_freerdp_freerdpcore_services_LibFreeRDP + * Method: freerdp_get_version + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_freerdp_freerdpcore_services_LibFreeRDP_freerdp_1get_1version + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/client/Android/local.properties.cmake b/client/Android/FreeRDPCore/local.properties.cmake similarity index 100% rename from client/Android/local.properties.cmake rename to client/Android/FreeRDPCore/local.properties.cmake diff --git a/client/Android/FreeRDPCore/project.properties b/client/Android/FreeRDPCore/project.properties new file mode 100644 index 000000000..db721fd89 --- /dev/null +++ b/client/Android/FreeRDPCore/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-8 +android.library=true diff --git a/client/Android/res/drawable-hdpi/icon_button_add.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_button_add.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_button_add.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_button_add.png diff --git a/client/Android/res/drawable-hdpi/icon_edittext_clear.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_edittext_clear.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_edittext_clear.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_edittext_clear.png diff --git a/client/Android/res/drawable-hdpi/icon_edittext_search.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_edittext_search.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_edittext_search.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_edittext_search.png diff --git a/client/Android/res/drawable-hdpi/icon_launcher_freerdp.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_launcher_freerdp.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_launcher_freerdp.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_launcher_freerdp.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_about.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_about.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_about.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_about.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_add.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_add.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_add.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_add.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_close.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_close.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_close.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_close.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_disconnect.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_disconnect.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_disconnect.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_disconnect.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_ext_keyboard.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_ext_keyboard.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_ext_keyboard.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_ext_keyboard.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_help.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_help.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_help.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_help.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_preferences.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_preferences.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_preferences.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_preferences.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_settings.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_settings.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_settings.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_settings.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_sys_keyboard.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_sys_keyboard.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_sys_keyboard.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_sys_keyboard.png diff --git a/client/Android/res/drawable-hdpi/icon_menu_touch_pointer.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_touch_pointer.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_menu_touch_pointer.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_menu_touch_pointer.png diff --git a/client/Android/res/drawable-hdpi/icon_star_off.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_star_off.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_star_off.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_star_off.png diff --git a/client/Android/res/drawable-hdpi/icon_star_on.png b/client/Android/FreeRDPCore/res/drawable-hdpi/icon_star_on.png similarity index 100% rename from client/Android/res/drawable-hdpi/icon_star_on.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/icon_star_on.png diff --git a/client/Android/res/drawable-hdpi/search_plate.9.png b/client/Android/FreeRDPCore/res/drawable-hdpi/search_plate.9.png similarity index 100% rename from client/Android/res/drawable-hdpi/search_plate.9.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/search_plate.9.png diff --git a/client/Android/res/drawable-hdpi/sym_keyboard_delete.png b/client/Android/FreeRDPCore/res/drawable-hdpi/sym_keyboard_delete.png similarity index 100% rename from client/Android/res/drawable-hdpi/sym_keyboard_delete.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/sym_keyboard_delete.png diff --git a/client/Android/res/drawable-hdpi/sym_keyboard_feedback_delete.png b/client/Android/FreeRDPCore/res/drawable-hdpi/sym_keyboard_feedback_delete.png similarity index 100% rename from client/Android/res/drawable-hdpi/sym_keyboard_feedback_delete.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/sym_keyboard_feedback_delete.png diff --git a/client/Android/res/drawable-hdpi/sym_keyboard_feedback_return.png b/client/Android/FreeRDPCore/res/drawable-hdpi/sym_keyboard_feedback_return.png similarity index 100% rename from client/Android/res/drawable-hdpi/sym_keyboard_feedback_return.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/sym_keyboard_feedback_return.png diff --git a/client/Android/res/drawable-hdpi/sym_keyboard_return.png b/client/Android/FreeRDPCore/res/drawable-hdpi/sym_keyboard_return.png similarity index 100% rename from client/Android/res/drawable-hdpi/sym_keyboard_return.png rename to client/Android/FreeRDPCore/res/drawable-hdpi/sym_keyboard_return.png diff --git a/client/Android/res/drawable-ldpi/icon_button_add.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_button_add.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_button_add.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_button_add.png diff --git a/client/Android/res/drawable-ldpi/icon_edittext_search.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_edittext_search.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_edittext_search.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_edittext_search.png diff --git a/client/Android/res/drawable-ldpi/icon_launcher_freerdp.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_launcher_freerdp.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_launcher_freerdp.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_launcher_freerdp.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_about.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_about.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_about.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_about.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_add.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_add.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_add.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_add.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_disconnect.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_disconnect.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_disconnect.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_disconnect.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_exit.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_exit.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_exit.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_exit.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_ext_keyboard.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_ext_keyboard.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_ext_keyboard.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_ext_keyboard.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_help.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_help.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_help.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_help.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_preferences.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_preferences.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_preferences.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_preferences.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_settings.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_settings.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_settings.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_settings.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_sys_keyboard.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_sys_keyboard.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_sys_keyboard.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_sys_keyboard.png diff --git a/client/Android/res/drawable-ldpi/icon_menu_touch_pointer.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_touch_pointer.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_menu_touch_pointer.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_menu_touch_pointer.png diff --git a/client/Android/res/drawable-ldpi/icon_star_off.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_star_off.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_star_off.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_star_off.png diff --git a/client/Android/res/drawable-ldpi/icon_star_on.png b/client/Android/FreeRDPCore/res/drawable-ldpi/icon_star_on.png similarity index 100% rename from client/Android/res/drawable-ldpi/icon_star_on.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/icon_star_on.png diff --git a/client/Android/res/drawable-ldpi/search_plate.9.png b/client/Android/FreeRDPCore/res/drawable-ldpi/search_plate.9.png similarity index 100% rename from client/Android/res/drawable-ldpi/search_plate.9.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/search_plate.9.png diff --git a/client/Android/res/drawable-ldpi/sym_keyboard_delete.png b/client/Android/FreeRDPCore/res/drawable-ldpi/sym_keyboard_delete.png similarity index 100% rename from client/Android/res/drawable-ldpi/sym_keyboard_delete.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/sym_keyboard_delete.png diff --git a/client/Android/res/drawable-ldpi/sym_keyboard_feedback_delete.png b/client/Android/FreeRDPCore/res/drawable-ldpi/sym_keyboard_feedback_delete.png similarity index 100% rename from client/Android/res/drawable-ldpi/sym_keyboard_feedback_delete.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/sym_keyboard_feedback_delete.png diff --git a/client/Android/res/drawable-ldpi/sym_keyboard_feedback_return.png b/client/Android/FreeRDPCore/res/drawable-ldpi/sym_keyboard_feedback_return.png similarity index 100% rename from client/Android/res/drawable-ldpi/sym_keyboard_feedback_return.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/sym_keyboard_feedback_return.png diff --git a/client/Android/res/drawable-ldpi/sym_keyboard_return.png b/client/Android/FreeRDPCore/res/drawable-ldpi/sym_keyboard_return.png similarity index 100% rename from client/Android/res/drawable-ldpi/sym_keyboard_return.png rename to client/Android/FreeRDPCore/res/drawable-ldpi/sym_keyboard_return.png diff --git a/client/Android/res/drawable-mdpi/icon_button_add.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_button_add.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_button_add.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_button_add.png diff --git a/client/Android/res/drawable-mdpi/icon_edittext_clear.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_edittext_clear.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_edittext_clear.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_edittext_clear.png diff --git a/client/Android/res/drawable-mdpi/icon_edittext_search.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_edittext_search.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_edittext_search.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_edittext_search.png diff --git a/client/Android/res/drawable-mdpi/icon_launcher_freerdp.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_launcher_freerdp.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_launcher_freerdp.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_launcher_freerdp.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_about.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_about.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_about.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_about.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_add.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_add.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_add.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_add.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_disconnect.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_disconnect.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_disconnect.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_disconnect.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_exit.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_exit.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_exit.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_exit.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_ext_keyboard.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_ext_keyboard.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_ext_keyboard.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_ext_keyboard.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_help.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_help.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_help.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_help.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_preferences.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_preferences.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_preferences.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_preferences.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_settings.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_settings.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_settings.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_settings.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_sys_keyboard.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_sys_keyboard.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_sys_keyboard.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_sys_keyboard.png diff --git a/client/Android/res/drawable-mdpi/icon_menu_touch_pointer.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_touch_pointer.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_menu_touch_pointer.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_menu_touch_pointer.png diff --git a/client/Android/res/drawable-mdpi/icon_star_off.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_star_off.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_star_off.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_star_off.png diff --git a/client/Android/res/drawable-mdpi/icon_star_on.png b/client/Android/FreeRDPCore/res/drawable-mdpi/icon_star_on.png similarity index 100% rename from client/Android/res/drawable-mdpi/icon_star_on.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/icon_star_on.png diff --git a/client/Android/res/drawable-mdpi/search_plate.9.png b/client/Android/FreeRDPCore/res/drawable-mdpi/search_plate.9.png similarity index 100% rename from client/Android/res/drawable-mdpi/search_plate.9.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/search_plate.9.png diff --git a/client/Android/res/drawable-mdpi/sym_keyboard_delete.png b/client/Android/FreeRDPCore/res/drawable-mdpi/sym_keyboard_delete.png similarity index 100% rename from client/Android/res/drawable-mdpi/sym_keyboard_delete.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/sym_keyboard_delete.png diff --git a/client/Android/res/drawable-mdpi/sym_keyboard_feedback_delete.png b/client/Android/FreeRDPCore/res/drawable-mdpi/sym_keyboard_feedback_delete.png similarity index 100% rename from client/Android/res/drawable-mdpi/sym_keyboard_feedback_delete.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/sym_keyboard_feedback_delete.png diff --git a/client/Android/res/drawable-mdpi/sym_keyboard_feedback_return.png b/client/Android/FreeRDPCore/res/drawable-mdpi/sym_keyboard_feedback_return.png similarity index 100% rename from client/Android/res/drawable-mdpi/sym_keyboard_feedback_return.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/sym_keyboard_feedback_return.png diff --git a/client/Android/res/drawable-mdpi/sym_keyboard_return.png b/client/Android/FreeRDPCore/res/drawable-mdpi/sym_keyboard_return.png similarity index 100% rename from client/Android/res/drawable-mdpi/sym_keyboard_return.png rename to client/Android/FreeRDPCore/res/drawable-mdpi/sym_keyboard_return.png diff --git a/client/Android/res/drawable/button_background.xml b/client/Android/FreeRDPCore/res/drawable/button_background.xml similarity index 100% rename from client/Android/res/drawable/button_background.xml rename to client/Android/FreeRDPCore/res/drawable/button_background.xml diff --git a/client/Android/res/drawable/icon_button_cancel.png b/client/Android/FreeRDPCore/res/drawable/icon_button_cancel.png similarity index 100% rename from client/Android/res/drawable/icon_button_cancel.png rename to client/Android/FreeRDPCore/res/drawable/icon_button_cancel.png diff --git a/client/Android/res/drawable/icon_launcher_freerdp.png b/client/Android/FreeRDPCore/res/drawable/icon_launcher_freerdp.png similarity index 100% rename from client/Android/res/drawable/icon_launcher_freerdp.png rename to client/Android/FreeRDPCore/res/drawable/icon_launcher_freerdp.png diff --git a/client/Android/res/drawable/separator_background.xml b/client/Android/FreeRDPCore/res/drawable/separator_background.xml similarity index 100% rename from client/Android/res/drawable/separator_background.xml rename to client/Android/FreeRDPCore/res/drawable/separator_background.xml diff --git a/client/Android/res/drawable/sym_keyboard_arrows.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_arrows.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_arrows.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_arrows.png diff --git a/client/Android/res/drawable/sym_keyboard_arrows_black.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_arrows_black.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_arrows_black.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_arrows_black.png diff --git a/client/Android/res/drawable/sym_keyboard_down_arrow.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_down_arrow.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_down_arrow.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_down_arrow.png diff --git a/client/Android/res/drawable/sym_keyboard_down_arrow_black.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_down_arrow_black.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_down_arrow_black.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_down_arrow_black.png diff --git a/client/Android/res/drawable/sym_keyboard_left_arrow.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_left_arrow.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_left_arrow.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_left_arrow.png diff --git a/client/Android/res/drawable/sym_keyboard_left_arrow_black.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_left_arrow_black.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_left_arrow_black.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_left_arrow_black.png diff --git a/client/Android/res/drawable/sym_keyboard_menu.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_menu.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_menu.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_menu.png diff --git a/client/Android/res/drawable/sym_keyboard_menu_black.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_menu_black.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_menu_black.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_menu_black.png diff --git a/client/Android/res/drawable/sym_keyboard_right_arrow.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_right_arrow.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_right_arrow.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_right_arrow.png diff --git a/client/Android/res/drawable/sym_keyboard_right_arrow_black.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_right_arrow_black.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_right_arrow_black.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_right_arrow_black.png diff --git a/client/Android/res/drawable/sym_keyboard_up_arrow.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_up_arrow.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_up_arrow.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_up_arrow.png diff --git a/client/Android/res/drawable/sym_keyboard_up_arrow_black.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_up_arrow_black.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_up_arrow_black.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_up_arrow_black.png diff --git a/client/Android/res/drawable/sym_keyboard_winkey.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_winkey.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_winkey.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_winkey.png diff --git a/client/Android/res/drawable/sym_keyboard_winkey_black.png b/client/Android/FreeRDPCore/res/drawable/sym_keyboard_winkey_black.png similarity index 100% rename from client/Android/res/drawable/sym_keyboard_winkey_black.png rename to client/Android/FreeRDPCore/res/drawable/sym_keyboard_winkey_black.png diff --git a/client/Android/res/drawable/touch_pointer_active.png b/client/Android/FreeRDPCore/res/drawable/touch_pointer_active.png similarity index 100% rename from client/Android/res/drawable/touch_pointer_active.png rename to client/Android/FreeRDPCore/res/drawable/touch_pointer_active.png diff --git a/client/Android/res/drawable/touch_pointer_default.png b/client/Android/FreeRDPCore/res/drawable/touch_pointer_default.png similarity index 100% rename from client/Android/res/drawable/touch_pointer_default.png rename to client/Android/FreeRDPCore/res/drawable/touch_pointer_default.png diff --git a/client/Android/res/drawable/touch_pointer_extkeyboard.png b/client/Android/FreeRDPCore/res/drawable/touch_pointer_extkeyboard.png similarity index 100% rename from client/Android/res/drawable/touch_pointer_extkeyboard.png rename to client/Android/FreeRDPCore/res/drawable/touch_pointer_extkeyboard.png diff --git a/client/Android/res/drawable/touch_pointer_keyboard.png b/client/Android/FreeRDPCore/res/drawable/touch_pointer_keyboard.png similarity index 100% rename from client/Android/res/drawable/touch_pointer_keyboard.png rename to client/Android/FreeRDPCore/res/drawable/touch_pointer_keyboard.png diff --git a/client/Android/res/drawable/touch_pointer_lclick.png b/client/Android/FreeRDPCore/res/drawable/touch_pointer_lclick.png similarity index 100% rename from client/Android/res/drawable/touch_pointer_lclick.png rename to client/Android/FreeRDPCore/res/drawable/touch_pointer_lclick.png diff --git a/client/Android/res/drawable/touch_pointer_rclick.png b/client/Android/FreeRDPCore/res/drawable/touch_pointer_rclick.png similarity index 100% rename from client/Android/res/drawable/touch_pointer_rclick.png rename to client/Android/FreeRDPCore/res/drawable/touch_pointer_rclick.png diff --git a/client/Android/res/drawable/touch_pointer_reset.png b/client/Android/FreeRDPCore/res/drawable/touch_pointer_reset.png similarity index 100% rename from client/Android/res/drawable/touch_pointer_reset.png rename to client/Android/FreeRDPCore/res/drawable/touch_pointer_reset.png diff --git a/client/Android/res/drawable/touch_pointer_scroll.png b/client/Android/FreeRDPCore/res/drawable/touch_pointer_scroll.png similarity index 100% rename from client/Android/res/drawable/touch_pointer_scroll.png rename to client/Android/FreeRDPCore/res/drawable/touch_pointer_scroll.png diff --git a/client/Android/res/layout/bookmark_list_item.xml b/client/Android/FreeRDPCore/res/layout/bookmark_list_item.xml similarity index 100% rename from client/Android/res/layout/bookmark_list_item.xml rename to client/Android/FreeRDPCore/res/layout/bookmark_list_item.xml diff --git a/client/Android/res/layout/button_preference.xml b/client/Android/FreeRDPCore/res/layout/button_preference.xml similarity index 100% rename from client/Android/res/layout/button_preference.xml rename to client/Android/FreeRDPCore/res/layout/button_preference.xml diff --git a/client/Android/res/layout/credentials.xml b/client/Android/FreeRDPCore/res/layout/credentials.xml similarity index 100% rename from client/Android/res/layout/credentials.xml rename to client/Android/FreeRDPCore/res/layout/credentials.xml diff --git a/client/Android/res/layout/dont_show_again_dialog.xml b/client/Android/FreeRDPCore/res/layout/dont_show_again_dialog.xml similarity index 100% rename from client/Android/res/layout/dont_show_again_dialog.xml rename to client/Android/FreeRDPCore/res/layout/dont_show_again_dialog.xml diff --git a/client/Android/res/layout/home.xml b/client/Android/FreeRDPCore/res/layout/home.xml similarity index 100% rename from client/Android/res/layout/home.xml rename to client/Android/FreeRDPCore/res/layout/home.xml diff --git a/client/Android/res/layout/list_header.xml b/client/Android/FreeRDPCore/res/layout/list_header.xml similarity index 100% rename from client/Android/res/layout/list_header.xml rename to client/Android/FreeRDPCore/res/layout/list_header.xml diff --git a/client/Android/res/layout/session.xml b/client/Android/FreeRDPCore/res/layout/session.xml similarity index 91% rename from client/Android/res/layout/session.xml rename to client/Android/FreeRDPCore/res/layout/session.xml index aa4db7296..925e73d95 100644 --- a/client/Android/res/layout/session.xml +++ b/client/Android/FreeRDPCore/res/layout/session.xml @@ -24,7 +24,7 @@ android:visibility="gone" /> - - - + - + /> diff --git a/client/Android/res/menu/session_menu.xml b/client/Android/FreeRDPCore/res/menu/session_menu.xml similarity index 100% rename from client/Android/res/menu/session_menu.xml rename to client/Android/FreeRDPCore/res/menu/session_menu.xml diff --git a/client/Android/res/values-land/dimens.xml b/client/Android/FreeRDPCore/res/values-land/dimens.xml similarity index 100% rename from client/Android/res/values-land/dimens.xml rename to client/Android/FreeRDPCore/res/values-land/dimens.xml diff --git a/client/Android/res/values/attrs.xml b/client/Android/FreeRDPCore/res/values/attrs.xml similarity index 100% rename from client/Android/res/values/attrs.xml rename to client/Android/FreeRDPCore/res/values/attrs.xml diff --git a/client/Android/res/values/dimens.xml b/client/Android/FreeRDPCore/res/values/dimens.xml similarity index 100% rename from client/Android/res/values/dimens.xml rename to client/Android/FreeRDPCore/res/values/dimens.xml diff --git a/client/Android/res/values/integers.xml b/client/Android/FreeRDPCore/res/values/integers.xml similarity index 100% rename from client/Android/res/values/integers.xml rename to client/Android/FreeRDPCore/res/values/integers.xml diff --git a/client/Android/res/values/strings.xml b/client/Android/FreeRDPCore/res/values/strings.xml similarity index 97% rename from client/Android/res/values/strings.xml rename to client/Android/FreeRDPCore/res/values/strings.xml index 780a7aa3e..810127219 100644 --- a/client/Android/res/values/strings.xml +++ b/client/Android/FreeRDPCore/res/values/strings.xml @@ -1,7 +1,5 @@ - aFreeRDP - Yes No @@ -29,6 +27,8 @@ Manual Connections Active Sessions + + Connect to Computer Login No Servers @@ -38,10 +38,6 @@ Wrong Password Invalid Username Add Connection - - aFreeRDP - Connect to Computer - Remote Computers Host Label diff --git a/client/Android/res/values/theme.xml b/client/Android/FreeRDPCore/res/values/theme.xml similarity index 100% rename from client/Android/res/values/theme.xml rename to client/Android/FreeRDPCore/res/values/theme.xml diff --git a/client/Android/res/xml/advanced_settings.xml b/client/Android/FreeRDPCore/res/xml/advanced_settings.xml similarity index 62% rename from client/Android/res/xml/advanced_settings.xml rename to client/Android/FreeRDPCore/res/xml/advanced_settings.xml index 657a0dd7c..9158acf16 100644 --- a/client/Android/res/xml/advanced_settings.xml +++ b/client/Android/FreeRDPCore/res/xml/advanced_settings.xml @@ -15,20 +15,20 @@ - + - + - + diff --git a/client/Android/res/xml/application_settings.xml b/client/Android/FreeRDPCore/res/xml/application_settings.xml similarity index 81% rename from client/Android/res/xml/application_settings.xml rename to client/Android/FreeRDPCore/res/xml/application_settings.xml index 314b2acb9..9d7cc0a67 100644 --- a/client/Android/res/xml/application_settings.xml +++ b/client/Android/FreeRDPCore/res/xml/application_settings.xml @@ -9,7 +9,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ --> - + @@ -21,7 +21,7 @@ - + diff --git a/client/Android/FreeRDPCore/res/xml/bookmark_settings.xml b/client/Android/FreeRDPCore/res/xml/bookmark_settings.xml new file mode 100644 index 000000000..c49d4272a --- /dev/null +++ b/client/Android/FreeRDPCore/res/xml/bookmark_settings.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/Android/res/xml/credentials_settings.xml b/client/Android/FreeRDPCore/res/xml/credentials_settings.xml similarity index 100% rename from client/Android/res/xml/credentials_settings.xml rename to client/Android/FreeRDPCore/res/xml/credentials_settings.xml diff --git a/client/Android/res/xml/cursor_keyboard.xml b/client/Android/FreeRDPCore/res/xml/cursor_keyboard.xml similarity index 100% rename from client/Android/res/xml/cursor_keyboard.xml rename to client/Android/FreeRDPCore/res/xml/cursor_keyboard.xml diff --git a/client/Android/res/xml/modifiers_keyboard.xml b/client/Android/FreeRDPCore/res/xml/modifiers_keyboard.xml similarity index 100% rename from client/Android/res/xml/modifiers_keyboard.xml rename to client/Android/FreeRDPCore/res/xml/modifiers_keyboard.xml diff --git a/client/Android/res/xml/numpad_keyboard.xml b/client/Android/FreeRDPCore/res/xml/numpad_keyboard.xml similarity index 100% rename from client/Android/res/xml/numpad_keyboard.xml rename to client/Android/FreeRDPCore/res/xml/numpad_keyboard.xml diff --git a/client/Android/res/xml/performance_flags.xml b/client/Android/FreeRDPCore/res/xml/performance_flags.xml similarity index 100% rename from client/Android/res/xml/performance_flags.xml rename to client/Android/FreeRDPCore/res/xml/performance_flags.xml diff --git a/client/Android/res/xml/performance_flags_3g.xml b/client/Android/FreeRDPCore/res/xml/performance_flags_3g.xml similarity index 100% rename from client/Android/res/xml/performance_flags_3g.xml rename to client/Android/FreeRDPCore/res/xml/performance_flags_3g.xml diff --git a/client/Android/res/xml/screen_settings_3g.xml b/client/Android/FreeRDPCore/res/xml/screen_settings.xml similarity index 51% rename from client/Android/res/xml/screen_settings_3g.xml rename to client/Android/FreeRDPCore/res/xml/screen_settings.xml index de750855c..265c1c9e9 100644 --- a/client/Android/res/xml/screen_settings_3g.xml +++ b/client/Android/FreeRDPCore/res/xml/screen_settings.xml @@ -1,7 +1,7 @@ - + - - - - + + + + diff --git a/client/Android/FreeRDPCore/res/xml/screen_settings_3g.xml b/client/Android/FreeRDPCore/res/xml/screen_settings_3g.xml new file mode 100644 index 000000000..0eb0a7925 --- /dev/null +++ b/client/Android/FreeRDPCore/res/xml/screen_settings_3g.xml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/client/Android/res/xml/specialkeys_keyboard.xml b/client/Android/FreeRDPCore/res/xml/specialkeys_keyboard.xml similarity index 100% rename from client/Android/res/xml/specialkeys_keyboard.xml rename to client/Android/FreeRDPCore/res/xml/specialkeys_keyboard.xml diff --git a/client/Android/src/com/freerdp/afreerdp/application/GlobalApp.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/GlobalApp.java similarity index 93% rename from client/Android/src/com/freerdp/afreerdp/application/GlobalApp.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/GlobalApp.java index 4fd849c21..c37f8df5a 100644 --- a/client/Android/src/com/freerdp/afreerdp/application/GlobalApp.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/GlobalApp.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.application; +package com.freerdp.freerdpcore.application; import android.app.Application; import android.content.Intent; @@ -16,13 +16,13 @@ import android.util.Log; import java.util.*; -import com.freerdp.afreerdp.application.SessionState; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.services.BookmarkDB; -import com.freerdp.afreerdp.services.HistoryDB; -import com.freerdp.afreerdp.services.LibFreeRDP; -import com.freerdp.afreerdp.services.ManualBookmarkGateway; -import com.freerdp.afreerdp.services.QuickConnectHistoryGateway; +import com.freerdp.freerdpcore.application.SessionState; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.services.BookmarkDB; +import com.freerdp.freerdpcore.services.HistoryDB; +import com.freerdp.freerdpcore.services.LibFreeRDP; +import com.freerdp.freerdpcore.services.ManualBookmarkGateway; +import com.freerdp.freerdpcore.services.QuickConnectHistoryGateway; public class GlobalApp extends Application implements LibFreeRDP.EventListener { diff --git a/client/Android/src/com/freerdp/afreerdp/application/GlobalSettings.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/GlobalSettings.java similarity index 98% rename from client/Android/src/com/freerdp/afreerdp/application/GlobalSettings.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/GlobalSettings.java index 48ef10fbb..5b876dd94 100644 --- a/client/Android/src/com/freerdp/afreerdp/application/GlobalSettings.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/GlobalSettings.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.application; +package com.freerdp.freerdpcore.application; import android.content.Context; import android.content.SharedPreferences; diff --git a/client/Android/src/com/freerdp/afreerdp/application/NetworkStateReceiver.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/NetworkStateReceiver.java similarity index 97% rename from client/Android/src/com/freerdp/afreerdp/application/NetworkStateReceiver.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/NetworkStateReceiver.java index 24a7ff990..86f9f075e 100644 --- a/client/Android/src/com/freerdp/afreerdp/application/NetworkStateReceiver.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/NetworkStateReceiver.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.application; +package com.freerdp.freerdpcore.application; import android.content.BroadcastReceiver; import android.content.Context; diff --git a/client/Android/src/com/freerdp/afreerdp/application/ScreenReceiver.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/ScreenReceiver.java similarity index 95% rename from client/Android/src/com/freerdp/afreerdp/application/ScreenReceiver.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/ScreenReceiver.java index d2d74286e..25c392c7e 100644 --- a/client/Android/src/com/freerdp/afreerdp/application/ScreenReceiver.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/ScreenReceiver.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.application; +package com.freerdp.freerdpcore.application; import android.content.BroadcastReceiver; import android.content.Context; diff --git a/client/Android/src/com/freerdp/afreerdp/application/SessionState.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/SessionState.java similarity index 93% rename from client/Android/src/com/freerdp/afreerdp/application/SessionState.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/SessionState.java index 18d19f232..fe213fb4f 100644 --- a/client/Android/src/com/freerdp/afreerdp/application/SessionState.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/application/SessionState.java @@ -7,15 +7,15 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.application; +package com.freerdp.freerdpcore.application; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.os.Parcel; import android.os.Parcelable; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.services.LibFreeRDP; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.services.LibFreeRDP; public class SessionState implements Parcelable { diff --git a/client/Android/src/com/freerdp/afreerdp/domain/BookmarkBase.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/BookmarkBase.java similarity index 99% rename from client/Android/src/com/freerdp/afreerdp/domain/BookmarkBase.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/BookmarkBase.java index dc73872e1..12828ffd4 100644 --- a/client/Android/src/com/freerdp/afreerdp/domain/BookmarkBase.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/BookmarkBase.java @@ -7,9 +7,9 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.domain; +package com.freerdp.freerdpcore.domain; -import com.freerdp.afreerdp.application.GlobalApp; +import com.freerdp.freerdpcore.application.GlobalApp; import android.content.SharedPreferences; import android.os.Parcel; diff --git a/client/Android/src/com/freerdp/afreerdp/domain/ConnectionReference.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ConnectionReference.java similarity index 97% rename from client/Android/src/com/freerdp/afreerdp/domain/ConnectionReference.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ConnectionReference.java index 7975f795e..270139c51 100644 --- a/client/Android/src/com/freerdp/afreerdp/domain/ConnectionReference.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ConnectionReference.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.domain; +package com.freerdp.freerdpcore.domain; public class ConnectionReference { diff --git a/client/Android/src/com/freerdp/afreerdp/domain/ManualBookmark.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ManualBookmark.java similarity index 98% rename from client/Android/src/com/freerdp/afreerdp/domain/ManualBookmark.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ManualBookmark.java index 4d749c5a1..81d9b717c 100644 --- a/client/Android/src/com/freerdp/afreerdp/domain/ManualBookmark.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ManualBookmark.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.domain; +package com.freerdp.freerdpcore.domain; import android.content.SharedPreferences; import android.os.Parcel; diff --git a/client/Android/src/com/freerdp/afreerdp/domain/PlaceholderBookmark.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/PlaceholderBookmark.java similarity index 97% rename from client/Android/src/com/freerdp/afreerdp/domain/PlaceholderBookmark.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/PlaceholderBookmark.java index 54b08d431..b6712ec02 100644 --- a/client/Android/src/com/freerdp/afreerdp/domain/PlaceholderBookmark.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/PlaceholderBookmark.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.domain; +package com.freerdp.freerdpcore.domain; import android.content.SharedPreferences; import android.os.Parcel; diff --git a/client/Android/src/com/freerdp/afreerdp/domain/QuickConnectBookmark.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/QuickConnectBookmark.java similarity index 97% rename from client/Android/src/com/freerdp/afreerdp/domain/QuickConnectBookmark.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/QuickConnectBookmark.java index 1f6780c26..396853989 100644 --- a/client/Android/src/com/freerdp/afreerdp/domain/QuickConnectBookmark.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/QuickConnectBookmark.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.domain; +package com.freerdp.freerdpcore.domain; import android.content.SharedPreferences; import android.os.Parcel; diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/AboutActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/AboutActivity.java similarity index 95% rename from client/Android/src/com/freerdp/afreerdp/presentation/AboutActivity.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/AboutActivity.java index f5a525b37..dc030c977 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/AboutActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/AboutActivity.java @@ -7,14 +7,14 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.IllegalFormatException; -import com.freerdp.afreerdp.services.LibFreeRDP; +import com.freerdp.freerdpcore.services.LibFreeRDP; import android.app.Activity; import android.content.pm.PackageManager.NameNotFoundException; diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/ApplicationSettingsActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/ApplicationSettingsActivity.java similarity index 97% rename from client/Android/src/com/freerdp/afreerdp/presentation/ApplicationSettingsActivity.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/ApplicationSettingsActivity.java index 6dd387de3..3b99ee240 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/ApplicationSettingsActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/ApplicationSettingsActivity.java @@ -7,11 +7,11 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; import java.io.File; -import com.freerdp.afreerdp.R; +import com.freerdp.freerdpcore.R; import android.app.AlertDialog; import android.content.DialogInterface; diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/BookmarkActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/BookmarkActivity.java similarity index 93% rename from client/Android/src/com/freerdp/afreerdp/presentation/BookmarkActivity.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/BookmarkActivity.java index 40ebeddfa..078852f3b 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/BookmarkActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/BookmarkActivity.java @@ -7,21 +7,23 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; -import com.freerdp.afreerdp.R; -import com.freerdp.afreerdp.application.GlobalApp; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.domain.ConnectionReference; -import com.freerdp.afreerdp.domain.ManualBookmark; -import com.freerdp.afreerdp.services.BookmarkBaseGateway; +import com.freerdp.freerdpcore.R; +import com.freerdp.freerdpcore.application.GlobalApp; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.domain.ConnectionReference; +import com.freerdp.freerdpcore.domain.ManualBookmark; +import com.freerdp.freerdpcore.services.BookmarkBaseGateway; import android.app.AlertDialog; +import android.content.ComponentName; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; import android.preference.ListPreference; +import android.preference.Preference; import android.preference.PreferenceActivity; public class BookmarkActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener @@ -137,8 +139,35 @@ public class BookmarkActivity extends PreferenceActivity implements OnSharedPref // register for preferences changed notification getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + + // set the correct component names in our preferencescreen settings + setIntentComponentNames(); } + private void setIntentComponentNames() + { + // we set the component name for our sub-activity calls here because we don't know the package + // name of the main app in our library project. + ComponentName compName = new ComponentName(getPackageName(), BookmarkActivity.class.getName()); + String[] prefKeys = { + "bookmark.credentials", + "bookmark.screen", + "bookmark.performance", + "bookmark.advanced", + "bookmark.screen_3g", + "bookmark.performance_3g" + }; + + for (int i = 0; i < prefKeys.length; ++i) + { + Preference pref = findPreference(prefKeys[i]); + if (pref != null) + pref.getIntent().setComponent(compName); + } + + + } + @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { settings_changed = true; diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/HelpActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HelpActivity.java similarity index 95% rename from client/Android/src/com/freerdp/afreerdp/presentation/HelpActivity.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HelpActivity.java index 07f6cc9d4..2b526faee 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/HelpActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HelpActivity.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; import android.app.Activity; import android.content.res.Configuration; diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/HomeActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HomeActivity.java similarity index 80% rename from client/Android/src/com/freerdp/afreerdp/presentation/HomeActivity.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HomeActivity.java index 62fff1d98..8abd471c9 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/HomeActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HomeActivity.java @@ -7,19 +7,19 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; import java.util.ArrayList; -import com.freerdp.afreerdp.R; -import com.freerdp.afreerdp.application.GlobalApp; -import com.freerdp.afreerdp.application.GlobalSettings; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.domain.ConnectionReference; -import com.freerdp.afreerdp.domain.PlaceholderBookmark; -import com.freerdp.afreerdp.domain.QuickConnectBookmark; -import com.freerdp.afreerdp.utils.BookmarkArrayAdapter; -import com.freerdp.afreerdp.utils.SeparatedListAdapter; +import com.freerdp.freerdpcore.R; +import com.freerdp.freerdpcore.application.GlobalApp; +import com.freerdp.freerdpcore.application.GlobalSettings; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.domain.ConnectionReference; +import com.freerdp.freerdpcore.domain.PlaceholderBookmark; +import com.freerdp.freerdpcore.domain.QuickConnectBookmark; +import com.freerdp.freerdpcore.utils.BookmarkArrayAdapter; +import com.freerdp.freerdpcore.utils.SeparatedListAdapter; import android.app.Activity; import android.app.AlertDialog; @@ -185,52 +185,49 @@ public class HomeActivity extends Activity // get connection reference AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo)aItem.getMenuInfo(); String refStr = menuInfo.targetView.getTag().toString(); - - switch(aItem.getItemId()) { - - case R.id.bookmark_connect: + + // refer to http://tools.android.com/tips/non-constant-fields why we can't use switch/case here .. + int itemId = aItem.getItemId(); + if (itemId == R.id.bookmark_connect) + { + Bundle bundle = new Bundle(); + bundle.putString(SessionActivity.PARAM_CONNECTION_REFERENCE, refStr); + Intent sessionIntent = new Intent(this, SessionActivity.class); + sessionIntent.putExtras(bundle); + + startActivity(sessionIntent); + return true; + } + else if (itemId == R.id.bookmark_edit) + { + Bundle bundle = new Bundle(); + bundle.putString(BookmarkActivity.PARAM_CONNECTION_REFERENCE, refStr); + + Intent bookmarkIntent = new Intent(this.getApplicationContext(), BookmarkActivity.class); + bookmarkIntent.putExtras(bundle); + startActivity(bookmarkIntent); + return true; + } + else if (itemId == R.id.bookmark_delete) + { + if(ConnectionReference.isManualBookmarkReference(refStr)) { - Bundle bundle = new Bundle(); - bundle.putString(SessionActivity.PARAM_CONNECTION_REFERENCE, refStr); - Intent sessionIntent = new Intent(this, SessionActivity.class); - sessionIntent.putExtras(bundle); - - startActivity(sessionIntent); - return true; + long id = ConnectionReference.getManualBookmarkId(refStr); + GlobalApp.getManualBookmarkGateway().delete(id); + manualBookmarkAdapter.remove(id); + separatedListAdapter.notifyDataSetChanged(); + } + else + { + assert false; } - case R.id.bookmark_edit: - { - Bundle bundle = new Bundle(); - bundle.putString(BookmarkActivity.PARAM_CONNECTION_REFERENCE, refStr); - - Intent bookmarkIntent = new Intent(this.getApplicationContext(), BookmarkActivity.class); - bookmarkIntent.putExtras(bundle); - startActivity(bookmarkIntent); - return true; - } - - case R.id.bookmark_delete: - { - if(ConnectionReference.isManualBookmarkReference(refStr)) - { - long id = ConnectionReference.getManualBookmarkId(refStr); - GlobalApp.getManualBookmarkGateway().delete(id); - manualBookmarkAdapter.remove(id); - separatedListAdapter.notifyDataSetChanged(); - } - else - { - assert false; - } - - showWelcomeScreenOrBookmarkList(); - - // clear super bar text - superBarEditText.setText(""); - return true; - } - } + showWelcomeScreenOrBookmarkList(); + + // clear super bar text + superBarEditText.setText(""); + return true; + } return false; } @@ -333,41 +330,31 @@ public class HomeActivity extends Activity @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - - case R.id.newBookmark: - { - Intent bookmarkIntent = new Intent(this, BookmarkActivity.class); - startActivity(bookmarkIntent); - break; - } - - case R.id.appSettings: - { - Intent settingsIntent = new Intent(this, ApplicationSettingsActivity.class); - startActivity(settingsIntent); - break; - } - - case R.id.help: - { - Intent helpIntent = new Intent(this, HelpActivity.class); - startActivity(helpIntent); - break; - } - - case R.id.exit: - { - finish(); - break; - } - - case R.id.about: - { - Intent aboutIntent = new Intent(this, AboutActivity.class); - startActivity(aboutIntent); - break; - } + // refer to http://tools.android.com/tips/non-constant-fields why we can't use switch/case here .. + int itemId = item.getItemId(); + if (itemId == R.id.newBookmark) + { + Intent bookmarkIntent = new Intent(this, BookmarkActivity.class); + startActivity(bookmarkIntent); + } + else if (itemId == R.id.appSettings) + { + Intent settingsIntent = new Intent(this, ApplicationSettingsActivity.class); + startActivity(settingsIntent); + } + else if (itemId == R.id.help) + { + Intent helpIntent = new Intent(this, HelpActivity.class); + startActivity(helpIntent); + } + else if (itemId == R.id.exit) + { + finish(); + } + else if (itemId == R.id.about) + { + Intent aboutIntent = new Intent(this, AboutActivity.class); + startActivity(aboutIntent); } return true; diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/ScrollView2D.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/ScrollView2D.java similarity index 99% rename from client/Android/src/com/freerdp/afreerdp/presentation/ScrollView2D.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/ScrollView2D.java index 9150e5ccc..332306abb 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/ScrollView2D.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/ScrollView2D.java @@ -19,7 +19,7 @@ * http://GORGES.us */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; import java.util.List; diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/SessionActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java similarity index 95% rename from client/Android/src/com/freerdp/afreerdp/presentation/SessionActivity.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java index eef2c3d65..5a637930c 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/SessionActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java @@ -7,21 +7,21 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; import java.util.Iterator; import java.util.List; -import com.freerdp.afreerdp.R; -import com.freerdp.afreerdp.application.GlobalApp; -import com.freerdp.afreerdp.application.GlobalSettings; -import com.freerdp.afreerdp.application.SessionState; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.domain.ConnectionReference; -import com.freerdp.afreerdp.domain.ManualBookmark; -import com.freerdp.afreerdp.services.LibFreeRDP; -import com.freerdp.afreerdp.utils.KeyboardMapper; -import com.freerdp.afreerdp.utils.Mouse; +import com.freerdp.freerdpcore.R; +import com.freerdp.freerdpcore.application.GlobalApp; +import com.freerdp.freerdpcore.application.GlobalSettings; +import com.freerdp.freerdpcore.application.SessionState; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.domain.ConnectionReference; +import com.freerdp.freerdpcore.domain.ManualBookmark; +import com.freerdp.freerdpcore.services.LibFreeRDP; +import com.freerdp.freerdpcore.utils.KeyboardMapper; +import com.freerdp.freerdpcore.utils.Mouse; import android.app.Activity; import android.app.Dialog; @@ -754,43 +754,36 @@ public class SessionActivity extends Activity @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) - { - case R.id.session_touch_pointer: - { - // toggle touch pointer - if(touchPointerView.getVisibility() == View.VISIBLE) - { - touchPointerView.setVisibility(View.INVISIBLE); - sessionView.setTouchPointerPadding(0, 0); - } - else - { - touchPointerView.setVisibility(View.VISIBLE); - sessionView.setTouchPointerPadding(touchPointerView.getPointerWidth(), touchPointerView.getPointerHeight()); - } - break; - } + // refer to http://tools.android.com/tips/non-constant-fields why we can't use switch/case here .. + int itemId = item.getItemId(); - case R.id.session_sys_keyboard: + if (itemId == R.id.session_touch_pointer) + { + // toggle touch pointer + if(touchPointerView.getVisibility() == View.VISIBLE) { - showKeyboard(!sysKeyboardVisible, false); - break; + touchPointerView.setVisibility(View.INVISIBLE); + sessionView.setTouchPointerPadding(0, 0); } - - case R.id.session_ext_keyboard: + else { - showKeyboard(false, !extKeyboardVisible); - break; - } - - case R.id.session_disconnect: - { - showKeyboard(false, false); - LibFreeRDP.disconnect(session.getInstance()); - break; + touchPointerView.setVisibility(View.VISIBLE); + sessionView.setTouchPointerPadding(touchPointerView.getPointerWidth(), touchPointerView.getPointerHeight()); } } + else if (itemId == R.id.session_sys_keyboard) + { + showKeyboard(!sysKeyboardVisible, false); + } + else if (itemId == R.id.session_ext_keyboard) + { + showKeyboard(false, !extKeyboardVisible); + } + else if (itemId == R.id.session_disconnect) + { + showKeyboard(false, false); + LibFreeRDP.disconnect(session.getInstance()); + } return true; } diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/SessionView.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionView.java similarity index 97% rename from client/Android/src/com/freerdp/afreerdp/presentation/SessionView.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionView.java index f1234567f..0074e2eb9 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/SessionView.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionView.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; import android.util.AttributeSet; import android.util.Log; @@ -21,9 +21,9 @@ import android.graphics.drawable.BitmapDrawable; import java.util.*; -import com.freerdp.afreerdp.application.SessionState; -import com.freerdp.afreerdp.utils.DoubleGestureDetector; -import com.freerdp.afreerdp.utils.GestureDetector; +import com.freerdp.freerdpcore.application.SessionState; +import com.freerdp.freerdpcore.utils.DoubleGestureDetector; +import com.freerdp.freerdpcore.utils.GestureDetector; public class SessionView extends View diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/ShortcutsActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/ShortcutsActivity.java similarity index 94% rename from client/Android/src/com/freerdp/afreerdp/presentation/ShortcutsActivity.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/ShortcutsActivity.java index 947cb05e2..3281774c5 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/ShortcutsActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/ShortcutsActivity.java @@ -7,15 +7,15 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; import java.util.ArrayList; -import com.freerdp.afreerdp.R; -import com.freerdp.afreerdp.application.GlobalApp; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.services.SessionRequestHandlerActivity; -import com.freerdp.afreerdp.utils.BookmarkArrayAdapter; +import com.freerdp.freerdpcore.R; +import com.freerdp.freerdpcore.application.GlobalApp; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.services.SessionRequestHandlerActivity; +import com.freerdp.freerdpcore.utils.BookmarkArrayAdapter; import android.app.AlertDialog; import android.app.ListActivity; diff --git a/client/Android/src/com/freerdp/afreerdp/presentation/TouchPointerView.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/TouchPointerView.java similarity index 98% rename from client/Android/src/com/freerdp/afreerdp/presentation/TouchPointerView.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/TouchPointerView.java index 7850f9fdf..f58b840bd 100644 --- a/client/Android/src/com/freerdp/afreerdp/presentation/TouchPointerView.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/TouchPointerView.java @@ -7,10 +7,10 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.presentation; +package com.freerdp.freerdpcore.presentation; -import com.freerdp.afreerdp.R; -import com.freerdp.afreerdp.utils.GestureDetector; +import com.freerdp.freerdpcore.R; +import com.freerdp.freerdpcore.utils.GestureDetector; import android.content.Context; import android.graphics.Matrix; diff --git a/client/Android/src/com/freerdp/afreerdp/services/BookmarkBaseGateway.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/BookmarkBaseGateway.java similarity index 99% rename from client/Android/src/com/freerdp/afreerdp/services/BookmarkBaseGateway.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/BookmarkBaseGateway.java index 97aefdde7..6abac51d2 100644 --- a/client/Android/src/com/freerdp/afreerdp/services/BookmarkBaseGateway.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/BookmarkBaseGateway.java @@ -7,12 +7,12 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.services; +package com.freerdp.freerdpcore.services; import java.util.ArrayList; -import com.freerdp.afreerdp.domain.BookmarkBase; +import com.freerdp.freerdpcore.domain.BookmarkBase; import android.content.ContentValues; import android.database.Cursor; diff --git a/client/Android/src/com/freerdp/afreerdp/services/BookmarkDB.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/BookmarkDB.java similarity index 92% rename from client/Android/src/com/freerdp/afreerdp/services/BookmarkDB.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/BookmarkDB.java index 02f74440b..5d10d7048 100644 --- a/client/Android/src/com/freerdp/afreerdp/services/BookmarkDB.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/BookmarkDB.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.services; +package com.freerdp.freerdpcore.services; import android.content.Context; import android.provider.BaseColumns; @@ -82,8 +82,7 @@ public class BookmarkDB extends SQLiteOpenHelper db.execSQL(sqlManualBookmarks); - // REMOVE - FOR DEBUGGING ONLY! -/* + // Insert a test entry String sqlInsertDefaultScreenEntry = "INSERT INTO tbl_screen_settings (" + "colors, " @@ -91,8 +90,8 @@ public class BookmarkDB extends SQLiteOpenHelper + "width, " + "height) " + "VALUES ( " - + "16, -1, 0, 0);"; - db.execSQL(sqlInsertDefaultScreenEntry); + + "32, 1, 1024, 768);"; + db.execSQL(sqlInsertDefaultScreenEntry); db.execSQL(sqlInsertDefaultScreenEntry); String sqlInsertDefaultPerfFlags = @@ -105,7 +104,7 @@ public class BookmarkDB extends SQLiteOpenHelper + "perf_font_smoothing, " + "perf_desktop_composition) " + "VALUES ( " - + "0, 0, 0, 0, 0, 0, 0);"; + + "1, 0, 0, 0, 0, 0, 0);"; db.execSQL(sqlInsertDefaultPerfFlags); db.execSQL(sqlInsertDefaultPerfFlags); @@ -126,14 +125,14 @@ public class BookmarkDB extends SQLiteOpenHelper + "work_dir, " + "console_mode) " + "VALUES ( " - + "'test', " - + "'192.168.50.125', " - + "'demo1', " - + "'qw', " + + "'Test Server', " + + "'testservice.afreerdp.com', " + + "'', " + + "'', " + "'', " + "3389, " + "1, 1, 2, 2, 0, '', '', 0);"; - db.execSQL(sqlInsertDefaultSessionEntry); */ + db.execSQL(sqlInsertDefaultSessionEntry); } @Override diff --git a/client/Android/src/com/freerdp/afreerdp/services/FreeRDPSuggestionProvider.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/FreeRDPSuggestionProvider.java similarity index 92% rename from client/Android/src/com/freerdp/afreerdp/services/FreeRDPSuggestionProvider.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/FreeRDPSuggestionProvider.java index 1fd06a7cf..ee242d5d4 100644 --- a/client/Android/src/com/freerdp/afreerdp/services/FreeRDPSuggestionProvider.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/FreeRDPSuggestionProvider.java @@ -7,15 +7,15 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.services; +package com.freerdp.freerdpcore.services; import java.util.ArrayList; -import com.freerdp.afreerdp.R; -import com.freerdp.afreerdp.application.GlobalApp; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.domain.ConnectionReference; -import com.freerdp.afreerdp.domain.ManualBookmark; +import com.freerdp.freerdpcore.R; +import com.freerdp.freerdpcore.application.GlobalApp; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.domain.ConnectionReference; +import com.freerdp.freerdpcore.domain.ManualBookmark; import android.app.SearchManager; import android.content.ContentProvider; diff --git a/client/Android/src/com/freerdp/afreerdp/services/HistoryDB.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/HistoryDB.java similarity index 96% rename from client/Android/src/com/freerdp/afreerdp/services/HistoryDB.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/HistoryDB.java index 900336f60..f12be6bb0 100644 --- a/client/Android/src/com/freerdp/afreerdp/services/HistoryDB.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/HistoryDB.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.services; +package com.freerdp.freerdpcore.services; import android.content.Context; import android.database.sqlite.SQLiteDatabase; diff --git a/client/Android/src/com/freerdp/afreerdp/services/LibFreeRDP.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/LibFreeRDP.java similarity index 96% rename from client/Android/src/com/freerdp/afreerdp/services/LibFreeRDP.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/LibFreeRDP.java index 8de2cc435..672dcd934 100644 --- a/client/Android/src/com/freerdp/afreerdp/services/LibFreeRDP.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/LibFreeRDP.java @@ -7,13 +7,13 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.services; +package com.freerdp.freerdpcore.services; -import com.freerdp.afreerdp.application.GlobalApp; -import com.freerdp.afreerdp.application.SessionState; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.domain.ManualBookmark; +import com.freerdp.freerdpcore.application.GlobalApp; +import com.freerdp.freerdpcore.application.SessionState; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.domain.ManualBookmark; import android.graphics.Bitmap; diff --git a/client/Android/src/com/freerdp/afreerdp/services/ManualBookmarkGateway.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/ManualBookmarkGateway.java similarity index 93% rename from client/Android/src/com/freerdp/afreerdp/services/ManualBookmarkGateway.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/ManualBookmarkGateway.java index a95f8e40d..6b07850ac 100644 --- a/client/Android/src/com/freerdp/afreerdp/services/ManualBookmarkGateway.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/ManualBookmarkGateway.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.services; +package com.freerdp.freerdpcore.services; import java.util.ArrayList; @@ -15,8 +15,8 @@ import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteOpenHelper; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.domain.ManualBookmark; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.domain.ManualBookmark; public class ManualBookmarkGateway extends BookmarkBaseGateway { diff --git a/client/Android/src/com/freerdp/afreerdp/services/QuickConnectHistoryGateway.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/QuickConnectHistoryGateway.java similarity index 95% rename from client/Android/src/com/freerdp/afreerdp/services/QuickConnectHistoryGateway.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/QuickConnectHistoryGateway.java index beb6a596f..df3cfb478 100644 --- a/client/Android/src/com/freerdp/afreerdp/services/QuickConnectHistoryGateway.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/QuickConnectHistoryGateway.java @@ -7,12 +7,12 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.services; +package com.freerdp.freerdpcore.services; import java.util.ArrayList; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.domain.QuickConnectBookmark; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.domain.QuickConnectBookmark; import android.database.Cursor; import android.database.SQLException; diff --git a/client/Android/src/com/freerdp/afreerdp/services/SessionRequestHandlerActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/SessionRequestHandlerActivity.java similarity index 90% rename from client/Android/src/com/freerdp/afreerdp/services/SessionRequestHandlerActivity.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/SessionRequestHandlerActivity.java index ac41df7c1..57a61bddc 100644 --- a/client/Android/src/com/freerdp/afreerdp/services/SessionRequestHandlerActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/services/SessionRequestHandlerActivity.java @@ -7,11 +7,11 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.services; +package com.freerdp.freerdpcore.services; -import com.freerdp.afreerdp.domain.ConnectionReference; -import com.freerdp.afreerdp.presentation.BookmarkActivity; -import com.freerdp.afreerdp.presentation.SessionActivity; +import com.freerdp.freerdpcore.domain.ConnectionReference; +import com.freerdp.freerdpcore.presentation.BookmarkActivity; +import com.freerdp.freerdpcore.presentation.SessionActivity; import android.app.Activity; import android.app.SearchManager; diff --git a/client/Android/src/com/freerdp/afreerdp/utils/BookmarkArrayAdapter.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/BookmarkArrayAdapter.java similarity index 91% rename from client/Android/src/com/freerdp/afreerdp/utils/BookmarkArrayAdapter.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/BookmarkArrayAdapter.java index 50d2cf66b..cdd4721a6 100644 --- a/client/Android/src/com/freerdp/afreerdp/utils/BookmarkArrayAdapter.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/BookmarkArrayAdapter.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.utils; +package com.freerdp.freerdpcore.utils; import java.util.List; @@ -22,12 +22,12 @@ import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; -import com.freerdp.afreerdp.R; -import com.freerdp.afreerdp.domain.BookmarkBase; -import com.freerdp.afreerdp.domain.ConnectionReference; -import com.freerdp.afreerdp.domain.ManualBookmark; -import com.freerdp.afreerdp.domain.PlaceholderBookmark; -import com.freerdp.afreerdp.presentation.BookmarkActivity; +import com.freerdp.freerdpcore.R; +import com.freerdp.freerdpcore.domain.BookmarkBase; +import com.freerdp.freerdpcore.domain.ConnectionReference; +import com.freerdp.freerdpcore.domain.ManualBookmark; +import com.freerdp.freerdpcore.domain.PlaceholderBookmark; +import com.freerdp.freerdpcore.presentation.BookmarkActivity; public class BookmarkArrayAdapter extends ArrayAdapter { diff --git a/client/Android/src/com/freerdp/afreerdp/utils/ButtonPreference.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ButtonPreference.java similarity index 96% rename from client/Android/src/com/freerdp/afreerdp/utils/ButtonPreference.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ButtonPreference.java index fb9cbe261..3f119fa15 100644 --- a/client/Android/src/com/freerdp/afreerdp/utils/ButtonPreference.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ButtonPreference.java @@ -7,9 +7,9 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.utils; +package com.freerdp.freerdpcore.utils; -import com.freerdp.afreerdp.R; +import com.freerdp.freerdpcore.R; import android.content.Context; import android.preference.Preference; diff --git a/client/Android/src/com/freerdp/afreerdp/utils/DoubleGestureDetector.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/DoubleGestureDetector.java similarity index 99% rename from client/Android/src/com/freerdp/afreerdp/utils/DoubleGestureDetector.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/DoubleGestureDetector.java index e837a6a2e..1146c4c92 100644 --- a/client/Android/src/com/freerdp/afreerdp/utils/DoubleGestureDetector.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/DoubleGestureDetector.java @@ -7,14 +7,14 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.utils; +package com.freerdp.freerdpcore.utils; import android.content.Context; import android.os.Handler; import android.view.MotionEvent; import android.view.ScaleGestureDetector; -import com.freerdp.afreerdp.utils.GestureDetector.OnGestureListener; +import com.freerdp.freerdpcore.utils.GestureDetector.OnGestureListener; public class DoubleGestureDetector { /** diff --git a/client/Android/src/com/freerdp/afreerdp/utils/GestureDetector.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/GestureDetector.java similarity index 99% rename from client/Android/src/com/freerdp/afreerdp/utils/GestureDetector.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/GestureDetector.java index e656bab77..c8773b930 100644 --- a/client/Android/src/com/freerdp/afreerdp/utils/GestureDetector.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/GestureDetector.java @@ -16,7 +16,7 @@ * Modified for aFreeRDP by Martin Fleisz (mfleisz@thinstuff.at) */ -package com.freerdp.afreerdp.utils; +package com.freerdp.freerdpcore.utils; import android.content.Context; import android.os.Build; diff --git a/client/Android/src/com/freerdp/afreerdp/utils/IntEditTextPreference.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/IntEditTextPreference.java similarity index 97% rename from client/Android/src/com/freerdp/afreerdp/utils/IntEditTextPreference.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/IntEditTextPreference.java index 4ce494467..1142bc4ae 100644 --- a/client/Android/src/com/freerdp/afreerdp/utils/IntEditTextPreference.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/IntEditTextPreference.java @@ -7,9 +7,9 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.utils; +package com.freerdp.freerdpcore.utils; -import com.freerdp.afreerdp.R; +import com.freerdp.freerdpcore.R; import android.content.Context; import android.content.res.TypedArray; diff --git a/client/Android/src/com/freerdp/afreerdp/utils/IntListPreference.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/IntListPreference.java similarity index 95% rename from client/Android/src/com/freerdp/afreerdp/utils/IntListPreference.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/IntListPreference.java index 718a69ae7..49b718a29 100644 --- a/client/Android/src/com/freerdp/afreerdp/utils/IntListPreference.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/IntListPreference.java @@ -7,7 +7,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.utils; +package com.freerdp.freerdpcore.utils; import android.content.Context; import android.preference.ListPreference; diff --git a/client/Android/src/com/freerdp/afreerdp/utils/KeyboardMapper.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/KeyboardMapper.java similarity index 99% rename from client/Android/src/com/freerdp/afreerdp/utils/KeyboardMapper.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/KeyboardMapper.java index ae72de873..e9bbb2cd6 100644 --- a/client/Android/src/com/freerdp/afreerdp/utils/KeyboardMapper.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/KeyboardMapper.java @@ -8,9 +8,9 @@ */ -package com.freerdp.afreerdp.utils; +package com.freerdp.freerdpcore.utils; -import com.freerdp.afreerdp.R; +import com.freerdp.freerdpcore.R; import android.content.Context; import android.view.KeyEvent; diff --git a/client/Android/src/com/freerdp/afreerdp/utils/Mouse.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/Mouse.java similarity index 93% rename from client/Android/src/com/freerdp/afreerdp/utils/Mouse.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/Mouse.java index 202c4d5de..38743be93 100644 --- a/client/Android/src/com/freerdp/afreerdp/utils/Mouse.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/Mouse.java @@ -7,9 +7,9 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.utils; +package com.freerdp.freerdpcore.utils; -import com.freerdp.afreerdp.application.GlobalSettings; +import com.freerdp.freerdpcore.application.GlobalSettings; public class Mouse { diff --git a/client/Android/src/com/freerdp/afreerdp/utils/SeparatedListAdapter.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/SeparatedListAdapter.java similarity index 98% rename from client/Android/src/com/freerdp/afreerdp/utils/SeparatedListAdapter.java rename to client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/SeparatedListAdapter.java index 9ee8894c1..1528b78b4 100644 --- a/client/Android/src/com/freerdp/afreerdp/utils/SeparatedListAdapter.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/SeparatedListAdapter.java @@ -8,12 +8,12 @@ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package com.freerdp.afreerdp.utils; +package com.freerdp.freerdpcore.utils; import java.util.LinkedHashMap; import java.util.Map; -import com.freerdp.afreerdp.R; +import com.freerdp.freerdpcore.R; import android.content.Context; import android.view.View; diff --git a/client/Android/aFreeRDP/.classpath b/client/Android/aFreeRDP/.classpath new file mode 100644 index 000000000..a4763d1ee --- /dev/null +++ b/client/Android/aFreeRDP/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/client/Android/aFreeRDP/.project b/client/Android/aFreeRDP/.project new file mode 100644 index 000000000..335291e03 --- /dev/null +++ b/client/Android/aFreeRDP/.project @@ -0,0 +1,33 @@ + + + aFreeRDP + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/client/Android/aFreeRDP/AndroidManifest.xml.cmake b/client/Android/aFreeRDP/AndroidManifest.xml.cmake new file mode 100644 index 000000000..e0d01c824 --- /dev/null +++ b/client/Android/aFreeRDP/AndroidManifest.xml.cmake @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/Android/aFreeRDP/CMakeLists.txt b/client/Android/aFreeRDP/CMakeLists.txt new file mode 100644 index 000000000..9dd3b6179 --- /dev/null +++ b/client/Android/aFreeRDP/CMakeLists.txt @@ -0,0 +1,45 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# Android Client +# +# Copyright 2012 Marc-Andre Moreau +# Copyright 2013 Bernhard Miklautz +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set(ANDROID_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(ANDROID_PACKAGE_NAME "aFreeRDP") + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake ${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml @ONLY) + +if (ANDROID_SDK) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/local.properties.cmake ${CMAKE_CURRENT_SOURCE_DIR}/local.properties @ONLY) +endif() + +if(ANDROID_BUILD_JAVA) + if(ANDROID_BUILD_JAVA_DEBUG) + set(APK "${ANDROID_SOURCE_DIR}/bin/${ANDROID_PACKAGE_NAME}-release-unsigned.apk") + else() + set(APK "${ANDROID_SOURCE_DIR}/bin/${ANDROID_PACKAGE_NAME}-debug.apk") + endif() + + # command to create the android package + add_custom_command( + OUTPUT "${APK}" + COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE} + WORKING_DIRECTORY "${ANDROID_SOURCE_DIR}" + MAIN_DEPENDENCY AndroidManifest.xml + DEPENDS freerdp-android local.properties android-lib + ) + add_custom_target(android-package ALL SOURCES "${APK}") + SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin") +endif() diff --git a/client/Android/assets/about_page/FreeRDP_Logo.png b/client/Android/aFreeRDP/assets/about_page/FreeRDP_Logo.png similarity index 100% rename from client/Android/assets/about_page/FreeRDP_Logo.png rename to client/Android/aFreeRDP/assets/about_page/FreeRDP_Logo.png diff --git a/client/Android/assets/about_page/about.html b/client/Android/aFreeRDP/assets/about_page/about.html similarity index 100% rename from client/Android/assets/about_page/about.html rename to client/Android/aFreeRDP/assets/about_page/about.html diff --git a/client/Android/assets/about_page/about_phone.html b/client/Android/aFreeRDP/assets/about_page/about_phone.html similarity index 100% rename from client/Android/assets/about_page/about_phone.html rename to client/Android/aFreeRDP/assets/about_page/about_phone.html diff --git a/client/Android/assets/about_page/back.jpg b/client/Android/aFreeRDP/assets/about_page/back.jpg similarity index 100% rename from client/Android/assets/about_page/back.jpg rename to client/Android/aFreeRDP/assets/about_page/back.jpg diff --git a/client/Android/assets/about_page/background_transparent.png b/client/Android/aFreeRDP/assets/about_page/background_transparent.png similarity index 100% rename from client/Android/assets/about_page/background_transparent.png rename to client/Android/aFreeRDP/assets/about_page/background_transparent.png diff --git a/client/Android/assets/help_page/back.jpg b/client/Android/aFreeRDP/assets/help_page/back.jpg similarity index 100% rename from client/Android/assets/help_page/back.jpg rename to client/Android/aFreeRDP/assets/help_page/back.jpg diff --git a/client/Android/assets/help_page/gestures.html b/client/Android/aFreeRDP/assets/help_page/gestures.html similarity index 100% rename from client/Android/assets/help_page/gestures.html rename to client/Android/aFreeRDP/assets/help_page/gestures.html diff --git a/client/Android/assets/help_page/gestures.png b/client/Android/aFreeRDP/assets/help_page/gestures.png similarity index 100% rename from client/Android/assets/help_page/gestures.png rename to client/Android/aFreeRDP/assets/help_page/gestures.png diff --git a/client/Android/assets/help_page/gestures_phone.html b/client/Android/aFreeRDP/assets/help_page/gestures_phone.html similarity index 100% rename from client/Android/assets/help_page/gestures_phone.html rename to client/Android/aFreeRDP/assets/help_page/gestures_phone.html diff --git a/client/Android/assets/help_page/gestures_phone.png b/client/Android/aFreeRDP/assets/help_page/gestures_phone.png similarity index 100% rename from client/Android/assets/help_page/gestures_phone.png rename to client/Android/aFreeRDP/assets/help_page/gestures_phone.png diff --git a/client/Android/assets/help_page/nav_gestures.png b/client/Android/aFreeRDP/assets/help_page/nav_gestures.png similarity index 100% rename from client/Android/assets/help_page/nav_gestures.png rename to client/Android/aFreeRDP/assets/help_page/nav_gestures.png diff --git a/client/Android/assets/help_page/nav_toolbar.png b/client/Android/aFreeRDP/assets/help_page/nav_toolbar.png similarity index 100% rename from client/Android/assets/help_page/nav_toolbar.png rename to client/Android/aFreeRDP/assets/help_page/nav_toolbar.png diff --git a/client/Android/assets/help_page/nav_touch_pointer.png b/client/Android/aFreeRDP/assets/help_page/nav_touch_pointer.png similarity index 100% rename from client/Android/assets/help_page/nav_touch_pointer.png rename to client/Android/aFreeRDP/assets/help_page/nav_touch_pointer.png diff --git a/client/Android/assets/help_page/toolbar.html b/client/Android/aFreeRDP/assets/help_page/toolbar.html similarity index 100% rename from client/Android/assets/help_page/toolbar.html rename to client/Android/aFreeRDP/assets/help_page/toolbar.html diff --git a/client/Android/assets/help_page/toolbar.png b/client/Android/aFreeRDP/assets/help_page/toolbar.png similarity index 100% rename from client/Android/assets/help_page/toolbar.png rename to client/Android/aFreeRDP/assets/help_page/toolbar.png diff --git a/client/Android/assets/help_page/toolbar_phone.html b/client/Android/aFreeRDP/assets/help_page/toolbar_phone.html similarity index 100% rename from client/Android/assets/help_page/toolbar_phone.html rename to client/Android/aFreeRDP/assets/help_page/toolbar_phone.html diff --git a/client/Android/assets/help_page/toolbar_phone.png b/client/Android/aFreeRDP/assets/help_page/toolbar_phone.png similarity index 100% rename from client/Android/assets/help_page/toolbar_phone.png rename to client/Android/aFreeRDP/assets/help_page/toolbar_phone.png diff --git a/client/Android/assets/help_page/touch_pointer.html b/client/Android/aFreeRDP/assets/help_page/touch_pointer.html similarity index 100% rename from client/Android/assets/help_page/touch_pointer.html rename to client/Android/aFreeRDP/assets/help_page/touch_pointer.html diff --git a/client/Android/assets/help_page/touch_pointer.png b/client/Android/aFreeRDP/assets/help_page/touch_pointer.png similarity index 100% rename from client/Android/assets/help_page/touch_pointer.png rename to client/Android/aFreeRDP/assets/help_page/touch_pointer.png diff --git a/client/Android/assets/help_page/touch_pointer_phone.html b/client/Android/aFreeRDP/assets/help_page/touch_pointer_phone.html similarity index 100% rename from client/Android/assets/help_page/touch_pointer_phone.html rename to client/Android/aFreeRDP/assets/help_page/touch_pointer_phone.html diff --git a/client/Android/assets/help_page/touch_pointer_phone.png b/client/Android/aFreeRDP/assets/help_page/touch_pointer_phone.png similarity index 100% rename from client/Android/assets/help_page/touch_pointer_phone.png rename to client/Android/aFreeRDP/assets/help_page/touch_pointer_phone.png diff --git a/client/Android/assets/welcome_page/1.png b/client/Android/aFreeRDP/assets/welcome_page/1.png similarity index 100% rename from client/Android/assets/welcome_page/1.png rename to client/Android/aFreeRDP/assets/welcome_page/1.png diff --git a/client/Android/assets/welcome_page/2.png b/client/Android/aFreeRDP/assets/welcome_page/2.png similarity index 100% rename from client/Android/assets/welcome_page/2.png rename to client/Android/aFreeRDP/assets/welcome_page/2.png diff --git a/client/Android/assets/welcome_page/back.jpg b/client/Android/aFreeRDP/assets/welcome_page/back.jpg similarity index 100% rename from client/Android/assets/welcome_page/back.jpg rename to client/Android/aFreeRDP/assets/welcome_page/back.jpg diff --git a/client/Android/assets/welcome_page/new_connection.png b/client/Android/aFreeRDP/assets/welcome_page/new_connection.png similarity index 100% rename from client/Android/assets/welcome_page/new_connection.png rename to client/Android/aFreeRDP/assets/welcome_page/new_connection.png diff --git a/client/Android/assets/welcome_page/welcome.html b/client/Android/aFreeRDP/assets/welcome_page/welcome.html similarity index 100% rename from client/Android/assets/welcome_page/welcome.html rename to client/Android/aFreeRDP/assets/welcome_page/welcome.html diff --git a/client/Android/assets/welcome_page/welcome_phone.html b/client/Android/aFreeRDP/assets/welcome_page/welcome_phone.html similarity index 100% rename from client/Android/assets/welcome_page/welcome_phone.html rename to client/Android/aFreeRDP/assets/welcome_page/welcome_phone.html diff --git a/client/Android/build.xml b/client/Android/aFreeRDP/build.xml similarity index 100% rename from client/Android/build.xml rename to client/Android/aFreeRDP/build.xml diff --git a/client/Android/aFreeRDP/local.properties.cmake b/client/Android/aFreeRDP/local.properties.cmake new file mode 100644 index 000000000..159126370 --- /dev/null +++ b/client/Android/aFreeRDP/local.properties.cmake @@ -0,0 +1,2 @@ +# This file is automatically generated by cmake. +sdk.dir=@ANDROID_SDK@ diff --git a/client/Android/project.properties b/client/Android/aFreeRDP/project.properties similarity index 83% rename from client/Android/project.properties rename to client/Android/aFreeRDP/project.properties index ea89160e0..857d31de6 100644 --- a/client/Android/project.properties +++ b/client/Android/aFreeRDP/project.properties @@ -9,3 +9,5 @@ # Project target. target=android-8 +android.library.reference.1=../FreeRDPCore +manifestmerger.enabled=true diff --git a/client/Android/aFreeRDP/res/drawable-hdpi/icon_launcher_freerdp.png b/client/Android/aFreeRDP/res/drawable-hdpi/icon_launcher_freerdp.png new file mode 100644 index 000000000..45ed86123 Binary files /dev/null and b/client/Android/aFreeRDP/res/drawable-hdpi/icon_launcher_freerdp.png differ diff --git a/client/Android/aFreeRDP/res/drawable-ldpi/icon_launcher_freerdp.png b/client/Android/aFreeRDP/res/drawable-ldpi/icon_launcher_freerdp.png new file mode 100644 index 000000000..b57651bed Binary files /dev/null and b/client/Android/aFreeRDP/res/drawable-ldpi/icon_launcher_freerdp.png differ diff --git a/client/Android/aFreeRDP/res/drawable-mdpi/icon_launcher_freerdp.png b/client/Android/aFreeRDP/res/drawable-mdpi/icon_launcher_freerdp.png new file mode 100644 index 000000000..55335c869 Binary files /dev/null and b/client/Android/aFreeRDP/res/drawable-mdpi/icon_launcher_freerdp.png differ diff --git a/client/Android/aFreeRDP/res/drawable/button_background.xml b/client/Android/aFreeRDP/res/drawable/button_background.xml new file mode 100644 index 000000000..9fdf3096d --- /dev/null +++ b/client/Android/aFreeRDP/res/drawable/button_background.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/Android/aFreeRDP/res/drawable/icon_launcher_freerdp.png b/client/Android/aFreeRDP/res/drawable/icon_launcher_freerdp.png new file mode 100644 index 000000000..ad325d46e Binary files /dev/null and b/client/Android/aFreeRDP/res/drawable/icon_launcher_freerdp.png differ diff --git a/client/Android/aFreeRDP/res/drawable/separator_background.xml b/client/Android/aFreeRDP/res/drawable/separator_background.xml new file mode 100644 index 000000000..61c7b8925 --- /dev/null +++ b/client/Android/aFreeRDP/res/drawable/separator_background.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/client/Android/aFreeRDP/res/values/strings.xml b/client/Android/aFreeRDP/res/values/strings.xml new file mode 100644 index 000000000..f0aa7c6af --- /dev/null +++ b/client/Android/aFreeRDP/res/values/strings.xml @@ -0,0 +1,7 @@ + + + aFreeRDP + + aFreeRDP + Remote Computers + diff --git a/client/Android/res/xml/searchable.xml b/client/Android/aFreeRDP/res/xml/searchable.xml similarity index 100% rename from client/Android/res/xml/searchable.xml rename to client/Android/aFreeRDP/res/xml/searchable.xml diff --git a/client/Android/aFreeRDP/src/com/freerdp/afreerdp/application/GlobalApp.java b/client/Android/aFreeRDP/src/com/freerdp/afreerdp/application/GlobalApp.java new file mode 100644 index 000000000..c0b36f020 --- /dev/null +++ b/client/Android/aFreeRDP/src/com/freerdp/afreerdp/application/GlobalApp.java @@ -0,0 +1,6 @@ +package com.freerdp.afreerdp.application; + + +public class GlobalApp extends com.freerdp.freerdpcore.application.GlobalApp { + +} diff --git a/client/Android/jni/generated/com_freerdp_afreerdp_services_LibFreeRDP.h b/client/Android/jni/generated/com_freerdp_afreerdp_services_LibFreeRDP.h deleted file mode 100644 index cfe8d65f5..000000000 --- a/client/Android/jni/generated/com_freerdp_afreerdp_services_LibFreeRDP.h +++ /dev/null @@ -1,125 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class com_freerdp_afreerdp_services_LibFreeRDP */ - -#ifndef _Included_com_freerdp_afreerdp_services_LibFreeRDP -#define _Included_com_freerdp_afreerdp_services_LibFreeRDP -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_new - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1new - (JNIEnv *, jclass); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_free - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1free - (JNIEnv *, jclass, jint); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_connect - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1connect - (JNIEnv *, jclass, jint); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_disconnect - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1disconnect - (JNIEnv *, jclass, jint); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_cancel_connection - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1cancel_1connection - (JNIEnv *, jclass, jint); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_set_connection_info - * Signature: (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIZILjava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1connection_1info - (JNIEnv *, jclass, jint, jstring, jstring, jstring, jstring, jint, jint, jint, jint, jboolean, jint, jstring); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_set_performance_flags - * Signature: (IZZZZZZZ)V - */ -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1performance_1flags - (JNIEnv *, jclass, jint, jboolean, jboolean, jboolean, jboolean, jboolean, jboolean, jboolean); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_set_advanced_settings - * Signature: (ILjava/lang/String;Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1advanced_1settings - (JNIEnv *, jclass, jint, jstring, jstring); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_set_data_directory - * Signature: (ILjava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1data_1directory - (JNIEnv *, jclass, jint, jstring); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_update_graphics - * Signature: (ILandroid/graphics/Bitmap;IIII)Z - */ -JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1update_1graphics - (JNIEnv *, jclass, jint, jobject, jint, jint, jint, jint); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_send_cursor_event - * Signature: (IIII)V - */ -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1cursor_1event - (JNIEnv *, jclass, jint, jint, jint, jint); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_send_key_event - * Signature: (IIZ)V - */ -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1key_1event - (JNIEnv *, jclass, jint, jint, jboolean); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_send_unicodekey_event - * Signature: (II)V - */ -JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1unicodekey_1event - (JNIEnv *, jclass, jint, jint); - -/* - * Class: com_freerdp_afreerdp_services_LibFreeRDP - * Method: freerdp_get_version - * Signature: ()Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1get_1version - (JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/client/Android/res/xml/bookmark_settings.xml b/client/Android/res/xml/bookmark_settings.xml deleted file mode 100644 index 86df480ad..000000000 --- a/client/Android/res/xml/bookmark_settings.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/client/Android/res/xml/screen_settings.xml b/client/Android/res/xml/screen_settings.xml deleted file mode 100644 index 589a35a8d..000000000 --- a/client/Android/res/xml/screen_settings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 68aefcbb9..25b639caf 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -47,9 +47,7 @@ if(APPLE) endif() if(ANDROID) - if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/Android") - message(STATUS "Adding Android client") - add_subdirectory(Android) - endif() + message(STATUS "Adding Android client") + add_subdirectory(Android) endif() diff --git a/client/Mac/AppDelegate.h b/client/Mac/AppDelegate.h index d868d1564..a050c8d6c 100644 --- a/client/Mac/AppDelegate.h +++ b/client/Mac/AppDelegate.h @@ -1,10 +1,21 @@ -// -// AppDelegate.h -// MacFreeRDP -// -// Created by Thomas Goddard on 5/8/12. -// Copyright (c) 2012 __MyCompanyName__. All rights reserved. -// +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #import #import "MRDPView.h" @@ -14,6 +25,5 @@ @property (assign) IBOutlet MRDPView *mrdpView; @property (assign) IBOutlet NSWindow *window; - int rdp_connect(void); @end diff --git a/client/Mac/AppDelegate.m b/client/Mac/AppDelegate.m index 755f02de6..029d055d1 100644 --- a/client/Mac/AppDelegate.m +++ b/client/Mac/AppDelegate.m @@ -1,10 +1,21 @@ -// -// AppDelegate.m -// MacFreeRDP -// -// Created by Thomas Goddard on 5/8/12. -// Copyright (c) 2012 __MyCompanyName__. All rights reserved. -// +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #import "AppDelegate.h" @@ -14,14 +25,14 @@ @synthesize mrdpView; -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +- (void)applicationDidFinishLaunching:(NSNotification*)aNotification { rdp_connect(); } -- (void) applicationWillTerminate:(NSNotification *)notification +- (void) applicationWillTerminate:(NSNotification*)notification { - //[mrdpView releaseResources]; + //[mrdpView releaseResources]; } @end diff --git a/client/Mac/MRDPCursor.h b/client/Mac/MRDPCursor.h index 6fd2cd580..7c193e684 100644 --- a/client/Mac/MRDPCursor.h +++ b/client/Mac/MRDPCursor.h @@ -1,10 +1,21 @@ -// -// MRDPCursor.h -// MacFreeRDP -// -// Created by Laxmikant Rashinkar -// Copyright (c) 2012 FreeRDP.org All rights reserved. -// +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #import @@ -13,11 +24,11 @@ @interface MRDPCursor : NSObject { @public - rdpPointer *pointer; - BYTE *cursor_data; // bitmapped pixel data - NSBitmapImageRep *bmiRep; - NSCursor *nsCursor; - NSImage *nsImage; + rdpPointer *pointer; + BYTE *cursor_data; // bitmapped pixel data + NSBitmapImageRep *bmiRep; + NSCursor *nsCursor; + NSImage *nsImage; } @end diff --git a/client/Mac/MRDPCursor.m b/client/Mac/MRDPCursor.m index 29a93c808..86e1c2d9b 100644 --- a/client/Mac/MRDPCursor.m +++ b/client/Mac/MRDPCursor.m @@ -1,10 +1,21 @@ -// -// MRDPCursor.m -// MacFreeRDP -// -// Created by Laxmikant Rashinkar -// Copyright (c) 2012 FreeRDP.org All rights reserved. -// +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #import "MRDPCursor.h" diff --git a/client/Mac/MRDPRailView.h b/client/Mac/MRDPRailView.h index 0a6c56218..84d4c55ee 100644 --- a/client/Mac/MRDPRailView.h +++ b/client/Mac/MRDPRailView.h @@ -1,3 +1,22 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #import #import "freerdp/gdi/gdi.h" @@ -7,35 +26,34 @@ @interface MRDPRailView : NSView { - freerdp* rdp_instance; - rdpContext* context; - NSBitmapImageRep* bmiRep; - NSPoint savedDragLocation; - char* pixelData; - BOOL mouseInClientArea; - BOOL titleBarClicked; - BOOL gestureEventInProgress; - int width; - int height; - int savedWindowId; - int scrollWheelCount; - - /* store state info for some keys */ - int kdlshift; - int kdrshift; - int kdlctrl; - int kdrctrl; - int kdlalt; - int kdralt; - int kdlmeta; - int kdrmeta; - int kdcapslock; - - @public - BOOL isMoveSizeInProgress; - BOOL saveInitialDragLoc; - BOOL skipMoveWindowOnce; - int localMoveType; + freerdp* rdp_instance; + rdpContext* context; + NSBitmapImageRep* bmiRep; + NSPoint savedDragLocation; + char* pixelData; + BOOL mouseInClientArea; + BOOL titleBarClicked; + BOOL gestureEventInProgress; + int width; + int height; + int savedWindowId; + int scrollWheelCount; + + int kdlshift; + int kdrshift; + int kdlctrl; + int kdrctrl; + int kdlalt; + int kdralt; + int kdlmeta; + int kdrmeta; + int kdcapslock; + +@public + BOOL isMoveSizeInProgress; + BOOL saveInitialDragLoc; + BOOL skipMoveWindowOnce; + int localMoveType; } @property (assign) MRDPRailWindow* mrdpRailWindow; diff --git a/client/Mac/MRDPRailView.m b/client/Mac/MRDPRailView.m index c8510cc5e..f9e0e0655 100644 --- a/client/Mac/MRDPRailView.m +++ b/client/Mac/MRDPRailView.m @@ -1,3 +1,22 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "MRDPRailView.h" #define USE_RAIL_CVT @@ -6,74 +25,78 @@ @synthesize mrdpRailWindow, windowIndex, activateWindow; -MRDPRailView * g_mrdpRailView; +MRDPRailView* g_mrdpRailView; struct kkey { - int key_code; - int flags; + int key_code; + int flags; }; extern struct kkey g_keys[]; - (void) updateDisplay { - BOOL moveWindow = NO; - NSRect srcRectOuter; - NSRect destRectOuter; - - rdpGdi * gdi; - - if ((context == 0) || (context->gdi == 0)) - return; - - if (context->gdi->primary->hdc->hwnd->invalid->null) - return; - - if (context->gdi->drawing != context->gdi->primary) - return; - - gdi = context->gdi; - - srcRectOuter = NSMakeRect(0, 0, self->width, self->height); - destRectOuter = [[self window] frame]; - - // cannot be bigger than our current screen size - NSRect screenSize = [[NSScreen mainScreen] frame]; - if (destRectOuter.size.width > screenSize.size.width) { - destRectOuter.size.width = screenSize.size.width; - moveWindow = YES; - } - - if (destRectOuter.size.height > screenSize.size.height) { - destRectOuter.size.height = screenSize.size.height; - moveWindow = YES; - } - - if (destRectOuter.origin.x + destRectOuter.size.width > width) - destRectOuter.size.width = width - destRectOuter.origin.x; - - [self setupBmiRep:destRectOuter.size.width :destRectOuter.size.height]; - - if (moveWindow) { - moveWindow = NO; - RAIL_WINDOW_MOVE_ORDER newWndLoc; - apple_to_windowMove(&destRectOuter, &newWndLoc); - newWndLoc.windowId = savedWindowId; - //skipMoveWindowOnce = TRUE; - //mac_send_rail_client_event(g_mrdpRailView->rdp_instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &newWndLoc); - } - - destRectOuter.origin.y = height - destRectOuter.origin.y - destRectOuter.size.height; - rail_convert_color_space(pixelData, (char *) gdi->primary_buffer, - &destRectOuter, self->width, self->height); - - if (moveWindow) - [self setNeedsDisplayInRect:destRectOuter]; - else - [self setNeedsDisplayInRect:[self frame]]; - - gdi->primary->hdc->hwnd->ninvalid = 0; + BOOL moveWindow = NO; + NSRect srcRectOuter; + NSRect destRectOuter; + + rdpGdi* gdi; + + if ((context == 0) || (context->gdi == 0)) + return; + + if (context->gdi->primary->hdc->hwnd->invalid->null) + return; + + if (context->gdi->drawing != context->gdi->primary) + return; + + gdi = context->gdi; + + srcRectOuter = NSMakeRect(0, 0, self->width, self->height); + destRectOuter = [[self window] frame]; + + // cannot be bigger than our current screen size + NSRect screenSize = [[NSScreen mainScreen] frame]; + + if (destRectOuter.size.width > screenSize.size.width) + { + destRectOuter.size.width = screenSize.size.width; + moveWindow = YES; + } + + if (destRectOuter.size.height > screenSize.size.height) + { + destRectOuter.size.height = screenSize.size.height; + moveWindow = YES; + } + + if (destRectOuter.origin.x + destRectOuter.size.width > width) + destRectOuter.size.width = width - destRectOuter.origin.x; + + [self setupBmiRep:destRectOuter.size.width :destRectOuter.size.height]; + + if (moveWindow) + { + moveWindow = NO; + RAIL_WINDOW_MOVE_ORDER newWndLoc; + apple_to_windowMove(&destRectOuter, &newWndLoc); + newWndLoc.windowId = savedWindowId; + //skipMoveWindowOnce = TRUE; + //mac_send_rail_client_event(g_mrdpRailView->rdp_instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &newWndLoc); + } + + destRectOuter.origin.y = height - destRectOuter.origin.y - destRectOuter.size.height; + rail_convert_color_space(pixelData, (char *) gdi->primary_buffer, + &destRectOuter, self->width, self->height); + + if (moveWindow) + [self setNeedsDisplayInRect:destRectOuter]; + else + [self setNeedsDisplayInRect:[self frame]]; + + gdi->primary->hdc->hwnd->ninvalid = 0; } /** ********************************************************************* @@ -82,37 +105,39 @@ extern struct kkey g_keys[]; - (void) drawRect:(NSRect)dirtyRect { - [bmiRep drawInRect:dirtyRect fromRect:dirtyRect operation:NSCompositeCopy fraction:1.0 respectFlipped:NO hints:nil]; - - if (pixelData) { - free(pixelData); - pixelData = NULL; - } - bmiRep = nil; + [bmiRep drawInRect:dirtyRect fromRect:dirtyRect operation:NSCompositeCopy fraction:1.0 respectFlipped:NO hints:nil]; + + if (pixelData) + { + free(pixelData); + pixelData = NULL; + } + + bmiRep = nil; } /** ********************************************************************* * become first responder so we can get keyboard and mouse events ***********************************************************************/ -- (BOOL)acceptsFirstResponder -{ - return YES; +- (BOOL)acceptsFirstResponder +{ + return YES; } - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { - return NO; + return NO; } /** ********************************************************************* * called when a mouse move event occurs - * + * * ideally we want to be called when the mouse moves over NSView client area, * but in reality we get called any time the mouse moves anywhere on the screen; * we could use NSTrackingArea class to handle this but this class is available * on Mac OS X v10.5 and higher; since we want to be compatible with older - * versions, we do this manually. + * versions, we do this manually. * * TODO: here is how it can be done using legacy methods * http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/MouseTrackingEvents/MouseTrackingEvents.html#//apple_ref/doc/uid/10000060i-CH11-SW1 @@ -120,18 +145,18 @@ extern struct kkey g_keys[]; - (void) mouseMoved:(NSEvent *)event { - [super mouseMoved:event]; - - NSRect winFrame = [[self window] frame]; - NSPoint loc = [event locationInWindow]; - - int x = (int) (winFrame.origin.x + loc.x); - int y = (int) (winFrame.origin.y + loc.y); - - y = height - y; - - /* send mouse motion event to RDP server */ - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y); + [super mouseMoved:event]; + + NSRect winFrame = [[self window] frame]; + NSPoint loc = [event locationInWindow]; + + int x = (int) (winFrame.origin.x + loc.x); + int y = (int) (winFrame.origin.y + loc.y); + + y = height - y; + + /* send mouse motion event to RDP server */ + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y); } /** ********************************************************************* @@ -140,25 +165,25 @@ extern struct kkey g_keys[]; - (void)mouseDown:(NSEvent *) event { - [super mouseDown:event]; - - NSRect winFrame = [[self window] frame]; - NSPoint loc = [event locationInWindow]; - int x = (int) (winFrame.origin.x + loc.x); - int y = (int) (winFrame.origin.y + loc.y); - int yPos = (int) (winFrame.size.height - loc.y); - - y = height - y; - - if ((yPos >= 4) && (yPos <= 20)) - titleBarClicked = YES; - else - titleBarClicked = NO; - - savedDragLocation.x = loc.x; - savedDragLocation.y = loc.y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, x, y); + [super mouseDown:event]; + + NSRect winFrame = [[self window] frame]; + NSPoint loc = [event locationInWindow]; + int x = (int) (winFrame.origin.x + loc.x); + int y = (int) (winFrame.origin.y + loc.y); + int yPos = (int) (winFrame.size.height - loc.y); + + y = height - y; + + if ((yPos >= 4) && (yPos <= 20)) + titleBarClicked = YES; + else + titleBarClicked = NO; + + savedDragLocation.x = loc.x; + savedDragLocation.y = loc.y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, x, y); } /** ********************************************************************* @@ -167,16 +192,16 @@ extern struct kkey g_keys[]; - (void) mouseUp:(NSEvent *) event { - [super mouseUp:event]; - - NSRect winFrame = [[self window] frame]; - NSPoint loc = [event locationInWindow]; - int x = (int) (winFrame.origin.x + loc.x); - int y = (int) (winFrame.origin.y + loc.y); - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON1, x, y); - titleBarClicked = NO; + [super mouseUp:event]; + + NSRect winFrame = [[self window] frame]; + NSPoint loc = [event locationInWindow]; + int x = (int) (winFrame.origin.x + loc.x); + int y = (int) (winFrame.origin.y + loc.y); + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON1, x, y); + titleBarClicked = NO; } /** ********************************************************************* @@ -185,15 +210,15 @@ extern struct kkey g_keys[]; - (void) rightMouseDown:(NSEvent *)event { - [super rightMouseDown:event]; - - NSRect winFrame = [[self window] frame]; - NSPoint loc = [event locationInWindow]; - int x = (int) (winFrame.origin.x + loc.x); - int y = (int) (winFrame.origin.y + loc.y); - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, x, y); + [super rightMouseDown:event]; + + NSRect winFrame = [[self window] frame]; + NSPoint loc = [event locationInWindow]; + int x = (int) (winFrame.origin.x + loc.x); + int y = (int) (winFrame.origin.y + loc.y); + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, x, y); } /** ********************************************************************* @@ -202,15 +227,15 @@ extern struct kkey g_keys[]; - (void) rightMouseUp:(NSEvent *)event { - [super rightMouseUp:event]; - - NSRect winFrame = [[self window] frame]; - NSPoint loc = [event locationInWindow]; - int x = (int) (winFrame.origin.x + loc.x); - int y = (int) (winFrame.origin.y + loc.y); - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON2, x, y); + [super rightMouseUp:event]; + + NSRect winFrame = [[self window] frame]; + NSPoint loc = [event locationInWindow]; + int x = (int) (winFrame.origin.x + loc.x); + int y = (int) (winFrame.origin.y + loc.y); + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON2, x, y); } /** ********************************************************************* @@ -219,15 +244,15 @@ extern struct kkey g_keys[]; - (void) otherMouseDown:(NSEvent *)event { - [super otherMouseDown:event]; - - NSRect winFrame = [[self window] frame]; - NSPoint loc = [event locationInWindow]; - int x = (int) (winFrame.origin.x + loc.x); - int y = (int) (winFrame.origin.y + loc.y); - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3, x, y); + [super otherMouseDown:event]; + + NSRect winFrame = [[self window] frame]; + NSPoint loc = [event locationInWindow]; + int x = (int) (winFrame.origin.x + loc.x); + int y = (int) (winFrame.origin.y + loc.y); + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3, x, y); } /** ********************************************************************* @@ -236,40 +261,44 @@ extern struct kkey g_keys[]; - (void) otherMouseUp:(NSEvent *)event { - [super otherMouseUp:event]; - - NSRect winFrame = [[self window] frame]; - NSPoint loc = [event locationInWindow]; - int x = (int) (winFrame.origin.x + loc.x); - int y = (int) (winFrame.origin.y + loc.y); - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON3, x, y); + [super otherMouseUp:event]; + + NSRect winFrame = [[self window] frame]; + NSPoint loc = [event locationInWindow]; + int x = (int) (winFrame.origin.x + loc.x); + int y = (int) (winFrame.origin.y + loc.y); + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON3, x, y); } - (void) scrollWheel:(NSEvent *)event { - uint16 flags; - - [super scrollWheel:event]; - - // we get more two finger trackpad scroll events - // than scrollWheel events, so we drop some - - if (gestureEventInProgress) { - scrollWheelCount++; - if (scrollWheelCount % 8 != 0) - return; - } - - if ([event scrollingDeltaY] < 0) { - flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; - } - else { - flags = PTR_FLAGS_WHEEL | 0x78; - } - - rdp_instance->input->MouseEvent(rdp_instance->input, flags, 0, 0); + uint16 flags; + + [super scrollWheel:event]; + + // we get more two finger trackpad scroll events + // than scrollWheel events, so we drop some + + if (gestureEventInProgress) + { + scrollWheelCount++; + + if (scrollWheelCount % 8 != 0) + return; + } + + if ([event scrollingDeltaY] < 0) + { + flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; + } + else + { + flags = PTR_FLAGS_WHEEL | 0x78; + } + + rdp_instance->input->MouseEvent(rdp_instance->input, flags, 0, 0); } /** ********************************************************************* @@ -278,204 +307,243 @@ extern struct kkey g_keys[]; ***********************************************************************/ - (void) mouseDragged:(NSEvent *)event { - [super mouseDragged:event]; - - NSRect winFrame = [[self window] frame]; - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - if (titleBarClicked) { - // window is being dragged to a new location - int newX = x - savedDragLocation.x; - int newY = y - savedDragLocation.y; - - if ((newX == 0) && (newY == 0)) - return; - - winFrame.origin.x += newX; - winFrame.origin.y += newY; - - [[self window] setFrame:winFrame display:YES]; - return; - } - - if (localMoveType == RAIL_WMSZ_LEFT) { - // left border resize taking place - int diff = (int) (loc.x - savedDragLocation.x); - if (diff == 0) - return; - - if (diff < 0) { - diff = abs(diff); - winFrame.origin.x -= diff; - winFrame.size.width += diff; - } - else { - winFrame.origin.x += diff; - winFrame.size.width -= diff; - } - - [[self window] setFrame:winFrame display:YES]; - return; - } - - if (localMoveType == RAIL_WMSZ_RIGHT) { - // right border resize taking place - int diff = (int) (loc.x - savedDragLocation.x); - if (diff == 0) - return; - - savedDragLocation.x = loc.x; - savedDragLocation.y = loc.y; - - winFrame.size.width += diff; - [[self window] setFrame:winFrame display:YES]; - return; - } - - if (localMoveType == RAIL_WMSZ_TOP) { - // top border resize taking place - int diff = (int) (loc.y - savedDragLocation.y); - if (diff == 0) - return; - - savedDragLocation.x = loc.x; - savedDragLocation.y = loc.y; - - winFrame.size.height += diff; - [[self window] setFrame:winFrame display:YES]; - return; - } - - if (localMoveType == RAIL_WMSZ_BOTTOM) { - // bottom border resize taking place - int diff = (int) (loc.y - savedDragLocation.y); - if (diff == 0) - return; - - if (diff < 0) { - diff = abs(diff); - winFrame.origin.y -= diff; - winFrame.size.height += diff; - } - else { - winFrame.origin.y += diff; - winFrame.size.height -= diff; - } - - [[self window] setFrame:winFrame display:YES]; - return; - } - - if (localMoveType == RAIL_WMSZ_TOPLEFT) { - // top left border resize taking place - int diff = (int) (loc.x - savedDragLocation.x); - if (diff != 0) { - if (diff < 0) { - diff = abs(diff); - winFrame.origin.x -= diff; - winFrame.size.width += diff; - } - else { - winFrame.origin.x += diff; - winFrame.size.width -= diff; - } - } - - diff = (int) (loc.y - savedDragLocation.y); - if (diff != 0) { - savedDragLocation.y = loc.y; - winFrame.size.height += diff; - } - - [[self window] setFrame:winFrame display:YES]; - return; - } - - if (localMoveType == RAIL_WMSZ_TOPRIGHT) { - // top right border resize taking place - int diff = (int) (loc.x - savedDragLocation.x); - if (diff != 0) { - winFrame.size.width += diff; - } - - diff = (int) (loc.y - savedDragLocation.y); - if (diff != 0) { - winFrame.size.height += diff; - } - - savedDragLocation.x = loc.x; - savedDragLocation.y = loc.y; - - [[self window] setFrame:winFrame display:YES]; - return; - } - - if (localMoveType == RAIL_WMSZ_BOTTOMLEFT) { - // bottom left border resize taking place - int diff = (int) (loc.x - savedDragLocation.x); - if (diff != 0) { - if (diff < 0) { - diff = abs(diff); - winFrame.origin.x -= diff; - winFrame.size.width += diff; - } - else { - winFrame.origin.x += diff; - winFrame.size.width -= diff; - } - } - - diff = (int) (loc.y - savedDragLocation.y); - if (diff != 0) { - if (diff < 0) { - diff = abs(diff); - winFrame.origin.y -= diff; - winFrame.size.height += diff; - } - else { - winFrame.origin.y += diff; - winFrame.size.height -= diff; - } - } - - [[self window] setFrame:winFrame display:YES]; - return; - } - - if (localMoveType == RAIL_WMSZ_BOTTOMRIGHT) { - // bottom right border resize taking place - int diff = (int) (loc.x - savedDragLocation.x); - if (diff != 0) { - savedDragLocation.x = loc.x; - //savedDragLocation.y = loc.y; - winFrame.size.width += diff; - } - - diff = (int) (loc.y - savedDragLocation.y); - if (diff != 0) { - if (diff < 0) { - diff = abs(diff); - winFrame.origin.y -= diff; - winFrame.size.height += diff; - } - else { - winFrame.origin.y += diff; - winFrame.size.height -= diff; - } - } - - [[self window] setFrame:winFrame display:YES]; - return; - } - - x = (int) (winFrame.origin.x + loc.x); - y = (int) (winFrame.origin.y + loc.y); - y = height - y; - - // send mouse motion event to RDP server - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y); + [super mouseDragged:event]; + + NSRect winFrame = [[self window] frame]; + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + if (titleBarClicked) + { + // window is being dragged to a new location + int newX = x - savedDragLocation.x; + int newY = y - savedDragLocation.y; + + if ((newX == 0) && (newY == 0)) + return; + + winFrame.origin.x += newX; + winFrame.origin.y += newY; + + [[self window] setFrame:winFrame display:YES]; + return; + } + + if (localMoveType == RAIL_WMSZ_LEFT) + { + // left border resize taking place + int diff = (int) (loc.x - savedDragLocation.x); + + if (diff == 0) + return; + + if (diff < 0) + { + diff = abs(diff); + winFrame.origin.x -= diff; + winFrame.size.width += diff; + } + else + { + winFrame.origin.x += diff; + winFrame.size.width -= diff; + } + + [[self window] setFrame:winFrame display:YES]; + return; + } + + if (localMoveType == RAIL_WMSZ_RIGHT) + { + // right border resize taking place + int diff = (int) (loc.x - savedDragLocation.x); + + if (diff == 0) + return; + + savedDragLocation.x = loc.x; + savedDragLocation.y = loc.y; + + winFrame.size.width += diff; + [[self window] setFrame:winFrame display:YES]; + + return; + } + + if (localMoveType == RAIL_WMSZ_TOP) + { + // top border resize taking place + int diff = (int) (loc.y - savedDragLocation.y); + + if (diff == 0) + return; + + savedDragLocation.x = loc.x; + savedDragLocation.y = loc.y; + + winFrame.size.height += diff; + [[self window] setFrame:winFrame display:YES]; + + return; + } + + if (localMoveType == RAIL_WMSZ_BOTTOM) + { + // bottom border resize taking place + int diff = (int) (loc.y - savedDragLocation.y); + + if (diff == 0) + return; + + if (diff < 0) + { + diff = abs(diff); + winFrame.origin.y -= diff; + winFrame.size.height += diff; + } + else + { + winFrame.origin.y += diff; + winFrame.size.height -= diff; + } + + [[self window] setFrame:winFrame display:YES]; + return; + } + + if (localMoveType == RAIL_WMSZ_TOPLEFT) + { + // top left border resize taking place + int diff = (int) (loc.x - savedDragLocation.x); + + if (diff != 0) + { + if (diff < 0) + { + diff = abs(diff); + winFrame.origin.x -= diff; + winFrame.size.width += diff; + } + else + { + winFrame.origin.x += diff; + winFrame.size.width -= diff; + } + } + + diff = (int) (loc.y - savedDragLocation.y); + + if (diff != 0) + { + savedDragLocation.y = loc.y; + winFrame.size.height += diff; + } + + [[self window] setFrame:winFrame display:YES]; + return; + } + + if (localMoveType == RAIL_WMSZ_TOPRIGHT) + { + // top right border resize taking place + int diff = (int) (loc.x - savedDragLocation.x); + + if (diff != 0) + winFrame.size.width += diff; + + diff = (int) (loc.y - savedDragLocation.y); + + if (diff != 0) + winFrame.size.height += diff; + + savedDragLocation.x = loc.x; + savedDragLocation.y = loc.y; + + [[self window] setFrame:winFrame display:YES]; + return; + } + + if (localMoveType == RAIL_WMSZ_BOTTOMLEFT) + { + // bottom left border resize taking place + int diff = (int) (loc.x - savedDragLocation.x); + + if (diff != 0) + { + if (diff < 0) + { + diff = abs(diff); + winFrame.origin.x -= diff; + winFrame.size.width += diff; + } + else + { + winFrame.origin.x += diff; + winFrame.size.width -= diff; + } + } + + diff = (int) (loc.y - savedDragLocation.y); + + if (diff != 0) + { + if (diff < 0) + { + diff = abs(diff); + winFrame.origin.y -= diff; + winFrame.size.height += diff; + } + else + { + winFrame.origin.y += diff; + winFrame.size.height -= diff; + } + } + + [[self window] setFrame:winFrame display:YES]; + return; + } + + if (localMoveType == RAIL_WMSZ_BOTTOMRIGHT) + { + // bottom right border resize taking place + int diff = (int) (loc.x - savedDragLocation.x); + + if (diff != 0) + { + savedDragLocation.x = loc.x; + //savedDragLocation.y = loc.y; + winFrame.size.width += diff; + } + + diff = (int) (loc.y - savedDragLocation.y); + + if (diff != 0) + { + if (diff < 0) + { + diff = abs(diff); + winFrame.origin.y -= diff; + winFrame.size.height += diff; + } + else + { + winFrame.origin.y += diff; + winFrame.size.height -= diff; + } + } + + [[self window] setFrame:winFrame display:YES]; + return; + } + + x = (int) (winFrame.origin.x + loc.x); + y = (int) (winFrame.origin.y + loc.y); + y = height - y; + + // send mouse motion event to RDP server + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y); } /** ********************************************************************* @@ -484,10 +552,10 @@ extern struct kkey g_keys[]; - (void) keyDown:(NSEvent *) event { - int key; - - key = [event keyCode]; - rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_DOWN, g_keys[key].key_code); + int key; + + key = [event keyCode]; + rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_DOWN, g_keys[key].key_code); } /** ********************************************************************* @@ -496,10 +564,10 @@ extern struct kkey g_keys[]; - (void) keyUp:(NSEvent *) event { - int key; - - key = [event keyCode]; - rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_RELEASE, g_keys[key].key_code); + int key; + + key = [event keyCode]; + rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_RELEASE, g_keys[key].key_code); } /** ********************************************************************* @@ -508,179 +576,179 @@ extern struct kkey g_keys[]; - (void) flagsChanged:(NSEvent *) event { - NSUInteger mf = [event modifierFlags]; - - // caps lock - if (mf == 0x10100) { - printf("TODO: caps lock is on\n"); - kdcapslock = 1; - } - if (kdcapslock && (mf == 0x100)) { - kdcapslock = 0; - printf("TODO: caps lock is off\n"); - } - // left shift - if ((kdlshift == 0) && ((mf & 2) != 0)) { - // left shift went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x2a); - kdlshift = 1; - } - if ((kdlshift != 0) && ((mf & 2) == 0)) { - // left shift went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x2a); - kdlshift = 0; - } - - // right shift - if ((kdrshift == 0) && ((mf & 4) != 0)) { - // right shift went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x36); - kdrshift = 1; - } - if ((kdrshift != 0) && ((mf & 4) == 0)) { - // right shift went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x36); - kdrshift = 0; - } - - // left ctrl - if ((kdlctrl == 0) && ((mf & 1) != 0)) { - // left ctrl went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x1d); - kdlctrl = 1; - } - if ((kdlctrl != 0) && ((mf & 1) == 0)) { - // left ctrl went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x1d); - kdlctrl = 0; - } - - // right ctrl - if ((kdrctrl == 0) && ((mf & 0x2000) != 0)) { - // right ctrl went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x1d); - kdrctrl = 1; - } - if ((kdrctrl != 0) && ((mf & 0x2000) == 0)) { - // right ctrl went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x1d); - kdrctrl = 0; - } - - // left alt - if ((kdlalt == 0) && ((mf & 0x20) != 0)) { - // left alt went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x38); - kdlalt = 1; - } - if ((kdlalt != 0) && ((mf & 0x20) == 0)) { - // left alt went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x38); - kdlalt = 0; - } - - // right alt - if ((kdralt == 0) && ((mf & 0x40) != 0)) { - // right alt went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x38); - kdralt = 1; - } - if ((kdralt != 0) && ((mf & 0x40) == 0)) { - // right alt went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x38); - kdralt = 0; - } - - // left meta - if ((kdlmeta == 0) && ((mf & 0x08) != 0)) { - // left meta went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5b); - kdlmeta = 1; - } - if ((kdlmeta != 0) && ((mf & 0x08) == 0)) { - // left meta went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5b); - kdlmeta = 0; - } - - // right meta - if ((kdrmeta == 0) && ((mf & 0x10) != 0)) { - // right meta went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5c); - kdrmeta = 1; - } - if ((kdrmeta != 0) && ((mf & 0x10) == 0)) { - // right meta went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5c); - kdrmeta = 0; - } + NSUInteger mf = [event modifierFlags]; + + // caps lock + if (mf == 0x10100) { + printf("TODO: caps lock is on\n"); + kdcapslock = 1; + } + if (kdcapslock && (mf == 0x100)) { + kdcapslock = 0; + printf("TODO: caps lock is off\n"); + } + // left shift + if ((kdlshift == 0) && ((mf & 2) != 0)) { + // left shift went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x2a); + kdlshift = 1; + } + if ((kdlshift != 0) && ((mf & 2) == 0)) { + // left shift went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x2a); + kdlshift = 0; + } + + // right shift + if ((kdrshift == 0) && ((mf & 4) != 0)) { + // right shift went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x36); + kdrshift = 1; + } + if ((kdrshift != 0) && ((mf & 4) == 0)) { + // right shift went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x36); + kdrshift = 0; + } + + // left ctrl + if ((kdlctrl == 0) && ((mf & 1) != 0)) { + // left ctrl went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x1d); + kdlctrl = 1; + } + if ((kdlctrl != 0) && ((mf & 1) == 0)) { + // left ctrl went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x1d); + kdlctrl = 0; + } + + // right ctrl + if ((kdrctrl == 0) && ((mf & 0x2000) != 0)) { + // right ctrl went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x1d); + kdrctrl = 1; + } + if ((kdrctrl != 0) && ((mf & 0x2000) == 0)) { + // right ctrl went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x1d); + kdrctrl = 0; + } + + // left alt + if ((kdlalt == 0) && ((mf & 0x20) != 0)) { + // left alt went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x38); + kdlalt = 1; + } + if ((kdlalt != 0) && ((mf & 0x20) == 0)) { + // left alt went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x38); + kdlalt = 0; + } + + // right alt + if ((kdralt == 0) && ((mf & 0x40) != 0)) { + // right alt went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x38); + kdralt = 1; + } + if ((kdralt != 0) && ((mf & 0x40) == 0)) { + // right alt went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x38); + kdralt = 0; + } + + // left meta + if ((kdlmeta == 0) && ((mf & 0x08) != 0)) { + // left meta went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5b); + kdlmeta = 1; + } + if ((kdlmeta != 0) && ((mf & 0x08) == 0)) { + // left meta went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5b); + kdlmeta = 0; + } + + // right meta + if ((kdrmeta == 0) && ((mf & 0x10) != 0)) { + // right meta went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5c); + kdrmeta = 1; + } + if ((kdrmeta != 0) && ((mf & 0x10) == 0)) { + // right meta went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5c); + kdrmeta = 0; + } } - (void) setRdpInstance:(freerdp *) instance width:(int) w andHeight:(int) h windowID:(int) windowID { - rdp_instance = instance; - context = instance->context; - width = w; - height = h; - savedWindowId = windowID; - - NSRect tr = NSMakeRect(0, 0, - [[NSScreen mainScreen] frame].size.width, - [[NSScreen mainScreen] frame].size.height); - - NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:tr options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveAlways owner:self userInfo:nil]; - - [self addTrackingArea:trackingArea]; - - g_mrdpRailView = self; - - [self becomeFirstResponder]; - [self setAcceptsTouchEvents:YES]; - - // we want to be notified when window resizes.... - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:nil]; - - // ...moves - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:nil]; - - // ...and becomes the key window - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:nil]; + rdp_instance = instance; + context = instance->context; + width = w; + height = h; + savedWindowId = windowID; + + NSRect tr = NSMakeRect(0, 0, + [[NSScreen mainScreen] frame].size.width, + [[NSScreen mainScreen] frame].size.height); + + NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:tr options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveAlways owner:self userInfo:nil]; + + [self addTrackingArea:trackingArea]; + + g_mrdpRailView = self; + + [self becomeFirstResponder]; + [self setAcceptsTouchEvents:YES]; + + // we want to be notified when window resizes.... + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:nil]; + + // ...moves + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:nil]; + + // ...and becomes the key window + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:nil]; } - (void) setupBmiRep:(int) frameWidth :(int) frameHeight { - struct rgba_data - { - char red; - char green; - char blue; - char alpha; - }; - - if (pixelData) - free(pixelData); - - pixelData = (char *) malloc(frameWidth * frameHeight * sizeof(struct rgba_data)); - bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &pixelData - pixelsWide:frameWidth - pixelsHigh:frameHeight - bitsPerSample:8 - samplesPerPixel:sizeof(struct rgba_data) - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bitmapFormat:0 - bytesPerRow:frameWidth * sizeof(struct rgba_data) - bitsPerPixel:0]; + struct rgba_data + { + char red; + char green; + char blue; + char alpha; + }; + + if (pixelData) + free(pixelData); + + pixelData = (char *) malloc(frameWidth * frameHeight * sizeof(struct rgba_data)); + bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &pixelData + pixelsWide:frameWidth + pixelsHigh:frameHeight + bitsPerSample:8 + samplesPerPixel:sizeof(struct rgba_data) + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bitmapFormat:0 + bytesPerRow:frameWidth * sizeof(struct rgba_data) + bitsPerPixel:0]; } - (void) beginGestureWithEvent:(NSEvent *)event { - gestureEventInProgress = YES; + gestureEventInProgress = YES; } - (void) endGestureWithEvent:(NSEvent *)event { - gestureEventInProgress = NO; + gestureEventInProgress = NO; } /** @@ -689,20 +757,20 @@ extern struct kkey g_keys[]; - (void) windowDidResize:(NSNotification *) notification { - // if we are not the source of this notification, just return - if ([notification object] != [self mrdpRailWindow]) - return; - - // let RDP server know that window has moved - RAIL_WINDOW_MOVE_ORDER windowMove; - NSRect r = [[self window] frame]; - - int diffInHeight = [[self window] frame].size.height - [self frame].size.height; - r.size.height -= diffInHeight; - - apple_to_windowMove(&r, &windowMove); - windowMove.windowId = self->savedWindowId; - mac_send_rail_client_event(self->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); + // if we are not the source of this notification, just return + if ([notification object] != [self mrdpRailWindow]) + return; + + // let RDP server know that window has moved + RAIL_WINDOW_MOVE_ORDER windowMove; + NSRect r = [[self window] frame]; + + int diffInHeight = [[self window] frame].size.height - [self frame].size.height; + r.size.height -= diffInHeight; + + apple_to_windowMove(&r, &windowMove); + windowMove.windowId = self->savedWindowId; + mac_send_rail_client_event(self->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); } /** @@ -711,20 +779,20 @@ extern struct kkey g_keys[]; - (void) windowDidMove:(NSNotification *) notification { - // if we are not the source of this notification, just return - if ([notification object] != [self mrdpRailWindow]) - return; - - // let RDP server know that window has moved - RAIL_WINDOW_MOVE_ORDER windowMove; - NSRect r = [[self window] frame]; - - int diffInHeight = [[self window] frame].size.height - [self frame].size.height; - r.size.height -= diffInHeight; - - apple_to_windowMove(&r, &windowMove); - windowMove.windowId = self->savedWindowId; - mac_send_rail_client_event(self->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); + // if we are not the source of this notification, just return + if ([notification object] != [self mrdpRailWindow]) + return; + + // let RDP server know that window has moved + RAIL_WINDOW_MOVE_ORDER windowMove; + NSRect r = [[self window] frame]; + + int diffInHeight = [[self window] frame].size.height - [self frame].size.height; + r.size.height -= diffInHeight; + + apple_to_windowMove(&r, &windowMove); + windowMove.windowId = self->savedWindowId; + mac_send_rail_client_event(self->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); } /** @@ -733,86 +801,84 @@ extern struct kkey g_keys[]; - (void) windowDidBecomeKey:(NSNotification *) notification { - // if we are not the source of this notification, just return - if ([notification object] != [self mrdpRailWindow]) - return; - - if (![self activateWindow]) - return; - - [[self window] setAcceptsMouseMovedEvents: YES]; - - //if ([self activateWindow]) + // if we are not the source of this notification, just return + if ([notification object] != [self mrdpRailWindow]) + return; + + if (![self activateWindow]) + return; + + [[self window] setAcceptsMouseMovedEvents: YES]; + + //if ([self activateWindow]) mac_rail_send_activate(savedWindowId); - - // set_current_window(windowIndex); // ? code mis-merge? + + // set_current_window(windowIndex); // ? code mis-merge? } - (void) releaseResources { - [[NSNotificationCenter defaultCenter] removeObserver:self]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; } -void rail_cvt_from_rect(char *dest, char *src, NSRect destRect, int destWidth, int destHeight, NSRect srcRect) +void rail_cvt_from_rect(char* dest, char* src, NSRect destRect, int destWidth, int destHeight, NSRect srcRect) { } /** ********************************************************************* * color space conversion used specifically in RAIL ***********************************************************************/ -void rail_convert_color_space(char *destBuf, char * srcBuf, - NSRect * destRect, int width, int height) +void rail_convert_color_space(char* destBuf, char* srcBuf, NSRect* destRect, int width, int height) { - int i; - int j; - int numRows; - int srcX; - int srcY; - int destX; - int destY; - int pixelsPerRow; - int pixel; - int pixel1; - int pixel2; - int * src32; - int * dest32; - - int destWidth = destRect->size.width; - int destHeight = destRect->size.height; - - if ((!destBuf) || (!srcBuf)) { - return; - } - - numRows = (destRect->origin.y + destHeight > height) ? height - destRect->origin.y : destHeight; - pixelsPerRow = destWidth; - - srcX = destRect->origin.x; - srcY = destRect->origin.y; - destX = 0; - destY = 0; - - for (i = 0; i < numRows; i++) - { - src32 = (int *) (srcBuf + ((srcY + i) * width + srcX) * 4); - dest32 = (int *) (destBuf + ((destY + i) * destWidth + destX) * 4); - - for (j = 0; j < pixelsPerRow; j++) - { - pixel = *src32; - pixel1 = (pixel & 0x00ff0000) >> 16; - pixel2 = (pixel & 0x000000ff) << 16; - pixel = (pixel & 0xff00ff00) | pixel1 | pixel2; - - *dest32 = pixel; - - src32++; - dest32++; - } - } - - destRect->origin.y = destHeight - destRect->origin.y - destRect->size.height; - return; + int i; + int j; + int numRows; + int srcX; + int srcY; + int destX; + int destY; + int pixelsPerRow; + int pixel; + int pixel1; + int pixel2; + int * src32; + int * dest32; + + int destWidth = destRect->size.width; + int destHeight = destRect->size.height; + + if ((!destBuf) || (!srcBuf)) + return; + + numRows = (destRect->origin.y + destHeight > height) ? height - destRect->origin.y : destHeight; + pixelsPerRow = destWidth; + + srcX = destRect->origin.x; + srcY = destRect->origin.y; + destX = 0; + destY = 0; + + for (i = 0; i < numRows; i++) + { + src32 = (int *) (srcBuf + ((srcY + i) * width + srcX) * 4); + dest32 = (int *) (destBuf + ((destY + i) * destWidth + destX) * 4); + + for (j = 0; j < pixelsPerRow; j++) + { + pixel = *src32; + pixel1 = (pixel & 0x00ff0000) >> 16; + pixel2 = (pixel & 0x000000ff) << 16; + pixel = (pixel & 0xff00ff00) | pixel1 | pixel2; + + *dest32 = pixel; + + src32++; + dest32++; + } + } + + destRect->origin.y = destHeight - destRect->origin.y - destRect->size.height; + return; } /** @@ -821,35 +887,35 @@ void rail_convert_color_space(char *destBuf, char * srcBuf, void rail_MoveWindow(rdpRail * rail, rdpWindow * window) { - if (g_mrdpRailView->isMoveSizeInProgress) { - return; - } - - if (g_mrdpRailView->skipMoveWindowOnce) { - g_mrdpRailView->skipMoveWindowOnce = NO; - return; - } - - // this rect is based on Windows co-ordinates... - NSRect r; - r.origin.x = window->windowOffsetX; - r.origin.y = window->windowOffsetY; - r.size.width = window->windowWidth; - r.size.height = window->windowHeight; - - windows_to_apple_cords(&r); - [[g_mrdpRailView window] setFrame:r display:YES]; + if (g_mrdpRailView->isMoveSizeInProgress) + return; + + if (g_mrdpRailView->skipMoveWindowOnce) + { + g_mrdpRailView->skipMoveWindowOnce = NO; + return; + } + + // this rect is based on Windows co-ordinates... + NSRect r; + r.origin.x = window->windowOffsetX; + r.origin.y = window->windowOffsetY; + r.size.width = window->windowWidth; + r.size.height = window->windowHeight; + + windows_to_apple_cords(&r); + [[g_mrdpRailView window] setFrame:r display:YES]; } void mac_rail_send_activate(int window_id) { - RAIL_ACTIVATE_ORDER activate; - - activate.windowId = window_id; - activate.enabled = 1; - - mac_send_rail_client_event(g_mrdpRailView->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE, &activate); + RAIL_ACTIVATE_ORDER activate; + + activate.windowId = window_id; + activate.enabled = 1; + + mac_send_rail_client_event(g_mrdpRailView->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE, &activate); } @end diff --git a/client/Mac/MRDPRailWindow.h b/client/Mac/MRDPRailWindow.h index 629dc819c..52f1c045a 100644 --- a/client/Mac/MRDPRailWindow.h +++ b/client/Mac/MRDPRailWindow.h @@ -1,10 +1,21 @@ -// -// MRDPRailWindow.h -// Mac -// -// Created by Laxmikant Rashinkar -// Copyright (c) 2012 __MyCompanyName__. All rights reserved. -// +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #import diff --git a/client/Mac/MRDPRailWindow.m b/client/Mac/MRDPRailWindow.m index 9cab180f4..f714d610e 100644 --- a/client/Mac/MRDPRailWindow.m +++ b/client/Mac/MRDPRailWindow.m @@ -1,10 +1,21 @@ -// -// MRDPRailWindow.m -// Mac -// -// Created by Laxmikant Rashinkar -// Copyright (c) 2012 __MyCompanyName__. All rights reserved. -// +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #import "MRDPRailWindow.h" @@ -12,7 +23,7 @@ - (BOOL) canBecomeKeyWindow { - return YES; + return YES; } @end diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index 4efdb970f..e8bb0f153 100644 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -1,10 +1,21 @@ -// -// MRDPView.h -// MacFreeRDP -// -// Created by Laxmikant Rashinkar -// Copyright (c) 2012 FreeRDP.org All rights reserved. -// +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #import @@ -24,52 +35,52 @@ @interface MRDPView : NSView { - CFRunLoopSourceRef run_loop_src; - CFRunLoopSourceRef run_loop_src_channels; - NSBitmapImageRep *bmiRep; - NSMutableArray *cursors; - NSMutableArray *windows; - NSTimer *pasteboard_timer; - NSRect rect; - NSRect prevWinPosition; - freerdp *rdp_instance; - rdpContext *rdp_context; - char *pixel_data; - int width; - int height; - int argc; - int titleBarHeight; - char **argv; - - // RAIL stuff - MRDPWindow *currentWindow; - NSPoint savedDragLocation; - BOOL mouseInClientArea; - BOOL isRemoteApp; - BOOL firstCreateWindow; - BOOL isMoveSizeInProgress; - BOOL skipResizeOnce; - BOOL saveInitialDragLoc; - BOOL skipMoveWindowOnce; - - // store state info for some keys - int kdlshift; - int kdrshift; - int kdlctrl; - int kdrctrl; - int kdlalt; - int kdralt; - int kdlmeta; - int kdrmeta; - int kdcapslock; - + CFRunLoopSourceRef run_loop_src; + CFRunLoopSourceRef run_loop_src_channels; + NSBitmapImageRep* bmiRep; + NSMutableArray* cursors; + NSMutableArray* windows; + NSTimer* pasteboard_timer; + NSRect rect; + NSRect prevWinPosition; + int titleBarHeight; + freerdp* rdp_instance; + rdpContext* rdp_context; + char* pixel_data; + int width; + int height; + int argc; + char** argv; + + // RAIL stuff + MRDPWindow* currentWindow; + NSPoint savedDragLocation; + BOOL mouseInClientArea; + BOOL isRemoteApp; + BOOL firstCreateWindow; + BOOL isMoveSizeInProgress; + BOOL skipResizeOnce; + BOOL saveInitialDragLoc; + BOOL skipMoveWindowOnce; + + // store state info for some keys + int kdlshift; + int kdrshift; + int kdlctrl; + int kdrctrl; + int kdlalt; + int kdralt; + int kdlmeta; + int kdrmeta; + int kdcapslock; + @public - NSWindow *ourMainWindow; - NSPasteboard *pasteboard_rd; // for reading from clipboard - NSPasteboard *pasteboard_wr; // for writing to clipboard - int pasteboard_changecount; - int pasteboard_format; - int is_connected; // true when connected to RDP server + NSWindow* ourMainWindow; + NSPasteboard* pasteboard_rd; // for reading from clipboard + NSPasteboard* pasteboard_wr; // for writing to clipboard + int pasteboard_changecount; + int pasteboard_format; + int is_connected; // true when connected to RDP server } - (void) rdpConnectError; @@ -100,77 +111,77 @@ void pointer_set(rdpContext* context, rdpPointer* pointer); void pointer_setNull(rdpContext* context); void pointer_setDefault(rdpContext* context); int rdp_connect(void); -BOOL mac_pre_connect(freerdp *inst); -BOOL mac_post_connect(freerdp *inst); -void mac_context_new(freerdp *inst, rdpContext *context); -void mac_context_free(freerdp *inst, rdpContext *context); -void mac_set_bounds(rdpContext *context, rdpBounds *bounds); -void mac_bitmap_update(rdpContext *context, BITMAP_UPDATE *bitmap); -void mac_begin_paint(rdpContext *context); +BOOL mac_pre_connect(freerdp* instance); +BOOL mac_post_connect(freerdp* instance); +void mac_context_new(freerdp* instance, rdpContext* context); +void mac_context_free(freerdp* instance, rdpContext* context); +void mac_set_bounds(rdpContext* context, rdpBounds* bounds); +void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap); +void mac_begin_paint(rdpContext* context); void mac_end_paint(rdpContext* context); -void mac_save_state_info(freerdp *inst, rdpContext *context); -void skt_activity_cb(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info); -void channel_activity_cb(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info); -int register_fds(int *fds, int count, void *inst); -int invoke_draw_rect(rdpContext *context); +void mac_save_state_info(freerdp* instance, rdpContext* context); +void skt_activity_cb(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void* data, void* info); +void channel_activity_cb(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void* data, void* info); +int register_fds(int* fds, int count, void* instance); +int invoke_draw_rect(rdpContext* context); int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data); -int receive_channel_data(freerdp *inst, int chan_id, BYTE *data, int size, int flags, int total_size); -void process_cliprdr_event(freerdp *inst, RDP_EVENT *event); -void cliprdr_process_cb_format_list_event(freerdp *inst, RDP_CB_FORMAT_LIST_EVENT* event); -void cliprdr_send_data_request(freerdp *inst, UINT32 format); +int receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size); +void process_cliprdr_event(freerdp* instance, RDP_EVENT* event); +void cliprdr_process_cb_format_list_event(freerdp* instance, RDP_CB_FORMAT_LIST_EVENT* event); +void cliprdr_send_data_request(freerdp* instance, UINT32 format); void cliprdr_process_cb_monitor_ready_event(freerdp* inst); -void cliprdr_process_cb_data_response_event(freerdp *inst, RDP_CB_DATA_RESPONSE_EVENT *event); -void cliprdr_process_text(freerdp *inst, BYTE *data, int len); -void cliprdr_send_supported_format_list(freerdp *inst); -int register_channel_fds(int *fds, int count, void *inst); +void cliprdr_process_cb_data_response_event(freerdp* instance, RDP_CB_DATA_RESPONSE_EVENT* event); +void cliprdr_process_text(freerdp* instance, BYTE* data, int len); +void cliprdr_send_supported_format_list(freerdp* instance); +int register_channel_fds(int* fds, int count, void* instance); -void mac_process_rail_event(freerdp *inst, RDP_EVENT *event); -void mac_rail_register_callbacks(freerdp *inst, rdpRail *rail); -void mac_rail_CreateWindow(rdpRail *rail, rdpWindow *window); -void mac_rail_MoveWindow(rdpRail *rail, rdpWindow *window); -void mac_rail_ShowWindow(rdpRail *rail, rdpWindow *window, BYTE state); -void mac_rail_SetWindowText(rdpRail *rail, rdpWindow *window); -void mac_rail_SetWindowIcon(rdpRail *rail, rdpWindow *window, rdpIcon *icon); -void mac_rail_SetWindowRects(rdpRail *rail, rdpWindow *window); -void mac_rail_SetWindowVisibilityRects(rdpRail *rail, rdpWindow *window); -void mac_rail_DestroyWindow(rdpRail *rail, rdpWindow *window); -void mac_process_rail_get_sysparams_event(rdpChannels *channels, RDP_EVENT *event); -void mac_send_rail_client_event(rdpChannels *channels, UINT16 event_type, void *param); +void mac_process_rail_event(freerdp* instance, RDP_EVENT* event); +void mac_rail_register_callbacks(freerdp* instance, rdpRail* rail); +void mac_rail_CreateWindow(rdpRail* rail, rdpWindow* window); +void mac_rail_MoveWindow(rdpRail* rail, rdpWindow* window); +void mac_rail_ShowWindow(rdpRail* rail, rdpWindow* window, BYTE state); +void mac_rail_SetWindowText(rdpRail* rail, rdpWindow* window); +void mac_rail_SetWindowIcon(rdpRail* rail, rdpWindow* window, rdpIcon* icon); +void mac_rail_SetWindowRects(rdpRail* rail, rdpWindow* window); +void mac_rail_SetWindowVisibilityRects(rdpRail* rail, rdpWindow* window); +void mac_rail_DestroyWindow(rdpRail* rail, rdpWindow* window); +void mac_process_rail_get_sysparams_event(rdpChannels* channels, RDP_EVENT* event); +void mac_send_rail_client_event(rdpChannels* channels, UINT16 event_type, void* param); void mac_on_free_rail_client_event(RDP_EVENT* event); void mac_process_rail_server_sysparam_event(rdpChannels* channels, RDP_EVENT* event); void mac_process_rail_exec_result_event(rdpChannels* channels, RDP_EVENT* event); void mac_rail_enable_remoteapp_mode(void); void mac_process_rail_server_minmaxinfo_event(rdpChannels* channels, RDP_EVENT* event); -void mac_process_rail_server_localmovesize_event(freerdp *inst, RDP_EVENT *event); -void apple_center_window(NSRect * r); -void apple_to_windowMove(NSRect * r, RAIL_WINDOW_MOVE_ORDER * windowMove); +void mac_process_rail_server_localmovesize_event(freerdp* instance, RDP_EVENT* event); +void apple_center_window(NSRect* r); +void apple_to_windowMove(NSRect* r, RAIL_WINDOW_MOVE_ORDER * windowMove); struct mac_context { - // *must* have this - do not delete - rdpContext _p; + // *must* have this - do not delete + rdpContext _p; }; struct cursor { - rdpPointer *pointer; - BYTE *cursor_data; // bitmapped pixel data - void *bmiRep; // NSBitmapImageRep - void *nsCursor; // NSCursor - void *nsImage; // NSImage + rdpPointer* pointer; + BYTE* cursor_data; // bitmapped pixel data + void* bmiRep; // NSBitmapImageRep + void* nsCursor; // NSCursor + void* nsImage; // NSImage }; struct rgba_data { - char red; - char green; - char blue; - char alpha; + char red; + char green; + char blue; + char alpha; }; struct kkey { - int key_code; - int flags; + int key_code; + int flags; }; diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index dcc36e93e..d4f79c1ff 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -1,10 +1,21 @@ -// -// MRDPView.m -// MacFreeRDP -// -// Created by Laxmikant Rashinkar -// Copyright (c) 2012 FreeRDP.org All rights reserved. -// +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /* * TODO @@ -18,27 +29,22 @@ * - all funcs same as above * - PolygonSc seems to create a transparent rect * - ensure mouse cursor changes are working ok after moving to NSTracking area - * - RAIL: - * - - * - + * - RAIL: + * - + * - * - tool tips to be correctly positioned * - dragging is slightly of * - resize after dragging not working * - dragging app from macbook to monitor gives exec/access err * - unable to drag rect out of monitor boundaries - * - - * - - * - + * - + * - + * - */ - + #import "MRDPView.h" #import "MRDPCursor.h" -#define RUN_IN_XCODE - -// LK_TODO -#define GOT_HERE //printf("### got here: %s : %s() : %d\n", __FILE__, __func__, __LINE__) - // RAIL_TODO DELETE WHEN DONE TESTING #define MRDP_DRAW_INDIVIDUAL_RECTS @@ -49,182 +55,183 @@ MRDPView *g_mrdpview; @synthesize is_connected; struct kkey g_keys[]; + void convert_color_space(char *dest, char *src, NSRect* drawRect, int width, int height); const char* error_code_names[] = { - "RAIL_EXEC_S_OK", - "RAIL_EXEC_E_HOOK_NOT_LOADED", - "RAIL_EXEC_E_DECODE_FAILED", - "RAIL_EXEC_E_NOT_IN_ALLOWLIST", - "RAIL_EXEC_E_FILE_NOT_FOUND", - "RAIL_EXEC_E_FAIL", - "RAIL_EXEC_E_SESSION_LOCKED" + "RAIL_EXEC_S_OK", + "RAIL_EXEC_E_HOOK_NOT_LOADED", + "RAIL_EXEC_E_DECODE_FAILED", + "RAIL_EXEC_E_NOT_IN_ALLOWLIST", + "RAIL_EXEC_E_FILE_NOT_FOUND", + "RAIL_EXEC_E_FAIL", + "RAIL_EXEC_E_SESSION_LOCKED" }; struct kkey g_keys[256] = { - { 0x1e, 0 }, // a 0 - { 0x1f, 0 }, // s - { 0x20, 0 }, // d - { 0x21, 0 }, // f - { 0x23, 0 }, // h - { 0x22, 0 }, // g - { 0x2c, 0 }, // z - { 0x2d, 0 }, // x - { 0x2e, 0 }, // c - { 0x2f, 0 }, // v - { 0x00, 0 }, // 10 - { 0x30, 0 }, // b - { 0x10, 0 }, // q - { 0x11, 0 }, // w - { 0x12, 0 }, // e - { 0x13, 0 }, // r - { 0x15, 0 }, // y - { 0x14, 0 }, // t - { 0x02, 0 }, // 1 - { 0x03, 0 }, // 2 - { 0x04, 0 }, // 3 20 - { 0x05, 0 }, // 4 - { 0x07, 0 }, // 6 - { 0x06, 0 }, // 5 - { 0x0d, 0 }, // = or + - { 0x0a, 0 }, // 9 - { 0x08, 0 }, // 7 - { 0x0c, 0 }, // - or _ - { 0x09, 0 }, // 8 - { 0x0b, 0 }, // 0 - { 0x1b, 0 }, // ] or } 30 - { 0x18, 0 }, // o - { 0x16, 0 }, // u - { 0x1a, 0 }, // [ or { - { 0x17, 0 }, // i - { 0x19, 0 }, // p - { 0x1c, 0 }, // enter - { 0x26, 0 }, // l - { 0x24, 0 }, // j - { 0x28, 0 }, // ' or " - { 0x25, 0 }, // k 40 - { 0x27, 0 }, // ; or : - { 0x2b, 0 }, // \ or | - { 0x33, 0 }, // , or < - { 0x35, 0 }, // / or ? - { 0x31, 0 }, // n - { 0x32, 0 }, // m - { 0x34, 0 }, // . or > - { 0x0f, 0 }, // tab - { 0x39, 0 }, // space - { 0x29, 0 }, // ` or ~ 50 - { 0x0e, 0 }, // backspace - { 0x00, 0 }, // - { 0x01, 0 }, // esc - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, // 60 - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x53, 0 }, // KP. - { 0x00, 0 }, - { 0x37, 0 }, // KP* - { 0x00, 0 }, - { 0x4e, 0 }, // KP+ - { 0x00, 0 }, // 70 - { 0x45, 0 }, // num lock - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x35, 1 }, // KP/ - { 0x1c, 1 }, // KPEnter - { 0x00, 0 }, - { 0x4a, 0 }, // KP- - { 0x00, 0 }, - { 0x00, 0 }, // 80 - { 0x00, 0 }, - { 0x52, 0 }, // KP0 - { 0x4f, 0 }, // KP1 - { 0x50, 0 }, // KP2 - { 0x51, 0 }, // KP3 - { 0x4b, 0 }, // KP4 - { 0x4c, 0 }, // KP5 - { 0x4d, 0 }, // KP6 - { 0x47, 0 }, // KP7 - { 0x00, 0 }, // 90 - { 0x48, 0 }, // KP8 - { 0x49, 0 }, // KP9 - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, // 100 - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x5d, 1 }, // menu 110 - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x52, 1 }, // Insert - { 0x47, 1 }, // Home - { 0x49, 1 }, // PgUp - { 0x53, 1 }, // Delete - { 0x00, 0 }, - { 0x4f, 1 }, // End - { 0x00, 0 }, // 120 - { 0x51, 1 }, // PgDown - { 0x3b, 0 }, // f1 - { 0x4b, 1 }, // left - { 0x4d, 1 }, // right - { 0x50, 1 }, // down - { 0x48, 1 }, // up - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, + { 0x1e, 0 }, // a 0 + { 0x1f, 0 }, // s + { 0x20, 0 }, // d + { 0x21, 0 }, // f + { 0x23, 0 }, // h + { 0x22, 0 }, // g + { 0x2c, 0 }, // z + { 0x2d, 0 }, // x + { 0x2e, 0 }, // c + { 0x2f, 0 }, // v + { 0x00, 0 }, // 10 + { 0x30, 0 }, // b + { 0x10, 0 }, // q + { 0x11, 0 }, // w + { 0x12, 0 }, // e + { 0x13, 0 }, // r + { 0x15, 0 }, // y + { 0x14, 0 }, // t + { 0x02, 0 }, // 1 + { 0x03, 0 }, // 2 + { 0x04, 0 }, // 3 20 + { 0x05, 0 }, // 4 + { 0x07, 0 }, // 6 + { 0x06, 0 }, // 5 + { 0x0d, 0 }, // = or + + { 0x0a, 0 }, // 9 + { 0x08, 0 }, // 7 + { 0x0c, 0 }, // - or _ + { 0x09, 0 }, // 8 + { 0x0b, 0 }, // 0 + { 0x1b, 0 }, // ] or } 30 + { 0x18, 0 }, // o + { 0x16, 0 }, // u + { 0x1a, 0 }, // [ or { + { 0x17, 0 }, // i + { 0x19, 0 }, // p + { 0x1c, 0 }, // enter + { 0x26, 0 }, // l + { 0x24, 0 }, // j + { 0x28, 0 }, // ' or " + { 0x25, 0 }, // k 40 + { 0x27, 0 }, // ; or : + { 0x2b, 0 }, // \ or | + { 0x33, 0 }, // , or < + { 0x35, 0 }, // / or ? + { 0x31, 0 }, // n + { 0x32, 0 }, // m + { 0x34, 0 }, // . or > + { 0x0f, 0 }, // tab + { 0x39, 0 }, // space + { 0x29, 0 }, // ` or ~ 50 + { 0x0e, 0 }, // backspace + { 0x00, 0 }, // + { 0x01, 0 }, // esc + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, // 60 + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x53, 0 }, // KP. + { 0x00, 0 }, + { 0x37, 0 }, // KP* + { 0x00, 0 }, + { 0x4e, 0 }, // KP+ + { 0x00, 0 }, // 70 + { 0x45, 0 }, // num lock + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x35, 1 }, // KP/ + { 0x1c, 1 }, // KPEnter + { 0x00, 0 }, + { 0x4a, 0 }, // KP- + { 0x00, 0 }, + { 0x00, 0 }, // 80 + { 0x00, 0 }, + { 0x52, 0 }, // KP0 + { 0x4f, 0 }, // KP1 + { 0x50, 0 }, // KP2 + { 0x51, 0 }, // KP3 + { 0x4b, 0 }, // KP4 + { 0x4c, 0 }, // KP5 + { 0x4d, 0 }, // KP6 + { 0x47, 0 }, // KP7 + { 0x00, 0 }, // 90 + { 0x48, 0 }, // KP8 + { 0x49, 0 }, // KP9 + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, // 100 + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x5d, 1 }, // menu 110 + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x52, 1 }, // Insert + { 0x47, 1 }, // Home + { 0x49, 1 }, // PgUp + { 0x53, 1 }, // Delete + { 0x00, 0 }, + { 0x4f, 1 }, // End + { 0x00, 0 }, // 120 + { 0x51, 1 }, // PgDown + { 0x3b, 0 }, // f1 + { 0x4b, 1 }, // left + { 0x4d, 1 }, // right + { 0x50, 1 }, // down + { 0x48, 1 }, // up + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, + { 0x00, 0 }, }; /************************************************************************ - methods we override -************************************************************************/ + methods we override + ************************************************************************/ /** ********************************************************************* * create MRDPView with specified rectangle @@ -232,12 +239,14 @@ struct kkey g_keys[256] = - (id)initWithFrame:(NSRect)frame { - self = [super initWithFrame:frame]; - if (self) { - // Initialization code here. - } - - return self; + self = [super initWithFrame:frame]; + + if (self) + { + // Initialization code here. + } + + return self; } /** ********************************************************************* @@ -246,80 +255,80 @@ struct kkey g_keys[256] = - (void) awakeFromNib { - g_mrdpview = self; - - // store our window dimensions - width = [self frame].size.width; - height = [self frame].size.height; - titleBarHeight = 22; - - [[self window] becomeFirstResponder]; - [[self window] setAcceptsMouseMovedEvents:YES]; - - cursors = [[NSMutableArray alloc] initWithCapacity:10]; - - firstCreateWindow = TRUE; - skipResizeOnce = YES; - windows = [[NSMutableArray alloc] initWithCapacity:10]; - - // setup a mouse tracking area - NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil]; - - //[self addTrackingArea:trackingArea]; - - // windows in RemoteApp (RAIL) mode cannot have title bars - NSArray * args = [[NSProcessInfo processInfo] arguments]; - for (NSString * str in args) - { - if ([str compare:@"--app"] == NSOrderedSame) { - isRemoteApp = TRUE; - break; - } - } - - if (!isRemoteApp) - [self addTrackingArea:trackingArea]; - - mouseInClientArea = YES; + g_mrdpview = self; + + // store our window dimensions + width = [self frame].size.width; + height = [self frame].size.height; + titleBarHeight = 22; + + [[self window] becomeFirstResponder]; + [[self window] setAcceptsMouseMovedEvents:YES]; + + cursors = [[NSMutableArray alloc] initWithCapacity:10]; + + firstCreateWindow = TRUE; + skipResizeOnce = YES; + windows = [[NSMutableArray alloc] initWithCapacity:10]; + + // setup a mouse tracking area + NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil]; + + //[self addTrackingArea:trackingArea]; + + // windows in RemoteApp (RAIL) mode cannot have title bars + NSArray * args = [[NSProcessInfo processInfo] arguments]; + for (NSString * str in args) + { + if ([str compare:@"--app"] == NSOrderedSame) { + isRemoteApp = TRUE; + break; + } + } + + if (!isRemoteApp) + [self addTrackingArea:trackingArea]; + + mouseInClientArea = YES; } /** ********************************************************************* * become first responder so we can get keyboard and mouse events ***********************************************************************/ -- (BOOL)acceptsFirstResponder -{ - return YES; +- (BOOL)acceptsFirstResponder +{ + return YES; } /** ********************************************************************* * called when a mouse move event occurrs - * + * * ideally we want to be called when the mouse moves over NSView client area, * but in reality we get called any time the mouse moves anywhere on the screen; * we could use NSTrackingArea class to handle this but this class is available * on Mac OS X v10.5 and higher; since we want to be compatible with older - * versions, we do this manually. + * versions, we do this manually. * * TODO: here is how it can be done using legacy methods * http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/MouseTrackingEvents/MouseTrackingEvents.html#//apple_ref/doc/uid/10000060i-CH11-SW1 ***********************************************************************/ - - - (void) mouseMoved:(NSEvent *)event + +- (void) mouseMoved:(NSEvent *)event { - [super mouseMoved:event]; - - if (!is_connected) - return; - - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - y = height - y; - - // send mouse motion event to RDP server - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y); + [super mouseMoved:event]; + + if (!is_connected) + return; + + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + y = height - y; + + // send mouse motion event to RDP server + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y); } /** ********************************************************************* @@ -328,18 +337,18 @@ struct kkey g_keys[256] = - (void)mouseDown:(NSEvent *) event { - [super mouseDown:event]; - - if (!is_connected) - return; - - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, x, y); + [super mouseDown:event]; + + if (!is_connected) + return; + + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, x, y); } /** ********************************************************************* @@ -348,18 +357,18 @@ struct kkey g_keys[256] = - (void) mouseUp:(NSEvent *) event { - [super mouseUp:event]; - - if (!is_connected) - return; - - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON1, x, y); + [super mouseUp:event]; + + if (!is_connected) + return; + + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON1, x, y); } /** ********************************************************************* @@ -368,18 +377,18 @@ struct kkey g_keys[256] = - (void) rightMouseDown:(NSEvent *)event { - [super rightMouseDown:event]; - - if (!is_connected) - return; - - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, x, y); + [super rightMouseDown:event]; + + if (!is_connected) + return; + + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, x, y); } /** ********************************************************************* @@ -388,18 +397,18 @@ struct kkey g_keys[256] = - (void) rightMouseUp:(NSEvent *)event { - [super rightMouseUp:event]; - - if (!is_connected) - return; - - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON2, x, y); + [super rightMouseUp:event]; + + if (!is_connected) + return; + + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON2, x, y); } /** ********************************************************************* @@ -408,18 +417,18 @@ struct kkey g_keys[256] = - (void) otherMouseDown:(NSEvent *)event { - [super otherMouseDown:event]; - - if (!is_connected) - return; - - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3, x, y); + [super otherMouseDown:event]; + + if (!is_connected) + return; + + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3, x, y); } /** ********************************************************************* @@ -428,45 +437,46 @@ struct kkey g_keys[256] = - (void) otherMouseUp:(NSEvent *)event { - [super otherMouseUp:event]; - - if (!is_connected) - return; - - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - y = height - y; - - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON3, x, y); + [super otherMouseUp:event]; + + if (!is_connected) + return; + + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + y = height - y; + + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON3, x, y); } - (void) scrollWheel:(NSEvent *)event { - uint16 flags; - - [super scrollWheel:event]; - - if (!is_connected) - return; - - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - y = height - y; - - flags = PTR_FLAGS_WHEEL; - if ([event deltaY] < 0) { - flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; - } - else { - flags |= 0x0078; - } - x += (int) [event deltaX]; - y += (int) [event deltaY]; - rdp_instance->input->MouseEvent(rdp_instance->input, flags, x, y); + UINT16 flags; + + [super scrollWheel:event]; + + if (!is_connected) + return; + + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + y = height - y; + + flags = PTR_FLAGS_WHEEL; + + if ([event deltaY] < 0) + flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; + else + flags |= 0x0078; + + x += (int) [event deltaX]; + y += (int) [event deltaY]; + + rdp_instance->input->MouseEvent(rdp_instance->input, flags, x, y); } /** ********************************************************************* @@ -476,37 +486,39 @@ struct kkey g_keys[256] = - (void) mouseDragged:(NSEvent *)event { - [super mouseDragged:event]; - - if (!is_connected) - return; - - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - // RAIL_TODO delete this if not reqd - if ((isRemoteApp) && (isMoveSizeInProgress)) { - if (saveInitialDragLoc) { - saveInitialDragLoc = NO; - savedDragLocation.x = x; - savedDragLocation.y = y; - return; - } - - int newX = x - savedDragLocation.x; - int newY = y - savedDragLocation.y; - - NSRect r = [[self window] frame]; - r.origin.x += newX; - r.origin.y += newY; - [[g_mrdpview window] setFrame:r display:YES]; - } - - y = height - y; - - // send mouse motion event to RDP server - rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y); + [super mouseDragged:event]; + + if (!is_connected) + return; + + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + // RAIL_TODO delete this if not reqd + if ((isRemoteApp) && (isMoveSizeInProgress)) + { + if (saveInitialDragLoc) + { + saveInitialDragLoc = NO; + savedDragLocation.x = x; + savedDragLocation.y = y; + return; + } + + int newX = x - savedDragLocation.x; + int newY = y - savedDragLocation.y; + + NSRect r = [[self window] frame]; + r.origin.x += newX; + r.origin.y += newY; + [[g_mrdpview window] setFrame:r display:YES]; + } + + y = height - y; + + // send mouse motion event to RDP server + rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y); } /** ********************************************************************* @@ -515,14 +527,13 @@ struct kkey g_keys[256] = - (void) keyDown:(NSEvent *) event { - int key; - - if (!is_connected) { - return; - } - - key = [event keyCode]; - rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_DOWN, g_keys[key].key_code); + int key; + + if (!is_connected) + return; + + key = [event keyCode]; + rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_DOWN, g_keys[key].key_code); } /** ********************************************************************* @@ -531,163 +542,161 @@ struct kkey g_keys[256] = - (void) keyUp:(NSEvent *) event { - int key; - - if (!is_connected) { - return; - } - - key = [event keyCode]; - rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_RELEASE, g_keys[key].key_code); + int key; + + if (!is_connected) + return; + + key = [event keyCode]; + rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_RELEASE, g_keys[key].key_code); } /** ********************************************************************* * called when shift, control, alt and meta keys are pressed/released ***********************************************************************/ -- (void) flagsChanged:(NSEvent *) event +- (void) flagsChanged:(NSEvent*) event { - NSUInteger mf = [event modifierFlags]; - - if (!is_connected) { - return; - } - - // caps lock - if (mf == 0x10100) { - printf("TODO: caps lock is on\n"); - kdcapslock = 1; - } - if (kdcapslock && (mf == 0x100)) { - kdcapslock = 0; - printf("TODO: caps lock is off\n"); - } - // left shift - if ((kdlshift == 0) && ((mf & 2) != 0)) { - // left shift went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x2a); - kdlshift = 1; - } - if ((kdlshift != 0) && ((mf & 2) == 0)) { - // left shift went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x2a); - kdlshift = 0; - } - - // right shift - if ((kdrshift == 0) && ((mf & 4) != 0)) { - // right shift went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x36); - kdrshift = 1; - } - if ((kdrshift != 0) && ((mf & 4) == 0)) { - // right shift went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x36); - kdrshift = 0; - } - - // left ctrl - if ((kdlctrl == 0) && ((mf & 1) != 0)) { - // left ctrl went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x1d); - kdlctrl = 1; - } - if ((kdlctrl != 0) && ((mf & 1) == 0)) { - // left ctrl went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x1d); - kdlctrl = 0; - } - - // right ctrl - if ((kdrctrl == 0) && ((mf & 0x2000) != 0)) { - // right ctrl went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x1d); - kdrctrl = 1; - } - if ((kdrctrl != 0) && ((mf & 0x2000) == 0)) { - // right ctrl went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x1d); - kdrctrl = 0; - } - - // left alt - if ((kdlalt == 0) && ((mf & 0x20) != 0)) { - // left alt went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x38); - kdlalt = 1; - } - if ((kdlalt != 0) && ((mf & 0x20) == 0)) { - // left alt went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x38); - kdlalt = 0; - } - - // right alt - if ((kdralt == 0) && ((mf & 0x40) != 0)) { - // right alt went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x38); - kdralt = 1; - } - if ((kdralt != 0) && ((mf & 0x40) == 0)) { - // right alt went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x38); - kdralt = 0; - } - - // left meta - if ((kdlmeta == 0) && ((mf & 0x08) != 0)) { - // left meta went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5b); - kdlmeta = 1; - } - if ((kdlmeta != 0) && ((mf & 0x08) == 0)) { - // left meta went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5b); - kdlmeta = 0; - } - - // right meta - if ((kdrmeta == 0) && ((mf & 0x10) != 0)) { - // right meta went down - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5c); - kdrmeta = 1; - } - if ((kdrmeta != 0) && ((mf & 0x10) == 0)) { - // right meta went up - rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5c); - kdrmeta = 0; - } + NSUInteger mf = [event modifierFlags]; + + if (!is_connected) + return; + + // caps lock + if (mf == 0x10100) { + printf("TODO: caps lock is on\n"); + kdcapslock = 1; + } + if (kdcapslock && (mf == 0x100)) { + kdcapslock = 0; + printf("TODO: caps lock is off\n"); + } + // left shift + if ((kdlshift == 0) && ((mf & 2) != 0)) { + // left shift went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x2a); + kdlshift = 1; + } + if ((kdlshift != 0) && ((mf & 2) == 0)) { + // left shift went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x2a); + kdlshift = 0; + } + + // right shift + if ((kdrshift == 0) && ((mf & 4) != 0)) { + // right shift went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x36); + kdrshift = 1; + } + if ((kdrshift != 0) && ((mf & 4) == 0)) { + // right shift went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x36); + kdrshift = 0; + } + + // left ctrl + if ((kdlctrl == 0) && ((mf & 1) != 0)) { + // left ctrl went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x1d); + kdlctrl = 1; + } + if ((kdlctrl != 0) && ((mf & 1) == 0)) { + // left ctrl went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x1d); + kdlctrl = 0; + } + + // right ctrl + if ((kdrctrl == 0) && ((mf & 0x2000) != 0)) { + // right ctrl went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x1d); + kdrctrl = 1; + } + if ((kdrctrl != 0) && ((mf & 0x2000) == 0)) { + // right ctrl went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x1d); + kdrctrl = 0; + } + + // left alt + if ((kdlalt == 0) && ((mf & 0x20) != 0)) { + // left alt went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x38); + kdlalt = 1; + } + if ((kdlalt != 0) && ((mf & 0x20) == 0)) { + // left alt went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x38); + kdlalt = 0; + } + + // right alt + if ((kdralt == 0) && ((mf & 0x40) != 0)) { + // right alt went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x38); + kdralt = 1; + } + if ((kdralt != 0) && ((mf & 0x40) == 0)) { + // right alt went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x38); + kdralt = 0; + } + + // left meta + if ((kdlmeta == 0) && ((mf & 0x08) != 0)) { + // left meta went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5b); + kdlmeta = 1; + } + if ((kdlmeta != 0) && ((mf & 0x08) == 0)) { + // left meta went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5b); + kdlmeta = 0; + } + + // right meta + if ((kdrmeta == 0) && ((mf & 0x10) != 0)) { + // right meta went down + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5c); + kdrmeta = 1; + } + if ((kdrmeta != 0) && ((mf & 0x10) == 0)) { + // right meta went up + rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5c); + kdrmeta = 0; + } } - (void) releaseResources { - int i; - - for (i = 0; i < argc; i++) - { - if (argv[i]) - free(argv[i]); - } - - for (MRDPWindow * w in windows) - { - [w setWindow:nil]; - [w setView:nil]; - } - - if (!is_connected) - return; - - freerdp_channels_global_uninit(); - - if (pixel_data) - free(pixel_data); - - if (run_loop_src != 0) - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_channels, kCFRunLoopDefaultMode); - - if (run_loop_src != 0) - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src, kCFRunLoopDefaultMode); + int i; + + for (i = 0; i < argc; i++) + { + if (argv[i]) + free(argv[i]); + } + + for (MRDPWindow * w in windows) + { + [w setWindow:nil]; + [w setView:nil]; + } + + if (!is_connected) + return; + + freerdp_channels_global_uninit(); + + if (pixel_data) + free(pixel_data); + + if (run_loop_src != 0) + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_channels, kCFRunLoopDefaultMode); + + if (run_loop_src != 0) + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src, kCFRunLoopDefaultMode); } /** ********************************************************************* @@ -696,90 +705,92 @@ struct kkey g_keys[256] = - (void) drawRect:(NSRect)dirtyRect { - if (!rdp_context) - return; - - if (g_mrdpview->isRemoteApp && g_mrdpview->currentWindow) { - return; - } - - if (!bmiRep) { - pixel_data = (char *) malloc(width * height * sizeof(struct rgba_data)); - bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &pixel_data - pixelsWide:width - pixelsHigh:height - bitsPerSample:8 - samplesPerPixel:sizeof(struct rgba_data) - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bitmapFormat:0 //NSAlphaFirstBitmapFormat - bytesPerRow:width * sizeof(struct rgba_data) - bitsPerPixel:0]; - } - - [bmiRep drawInRect:dirtyRect fromRect:dirtyRect operation:NSCompositeCopy fraction:1.0 respectFlipped:NO hints:nil]; + if (!rdp_context) + return; + + if (g_mrdpview->isRemoteApp && g_mrdpview->currentWindow) + return; + + if (!bmiRep) + { + pixel_data = (char *) malloc(width * height * sizeof(struct rgba_data)); + bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &pixel_data + pixelsWide:width + pixelsHigh:height + bitsPerSample:8 + samplesPerPixel:sizeof(struct rgba_data) + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bitmapFormat:0 //NSAlphaFirstBitmapFormat + bytesPerRow:width * sizeof(struct rgba_data) + bitsPerPixel:0]; + } + + [bmiRep drawInRect:dirtyRect fromRect:dirtyRect operation:NSCompositeCopy fraction:1.0 respectFlipped:NO hints:nil]; } /************************************************************************ - instance methods -************************************************************************/ + instance methods + ************************************************************************/ /** ********************************************************************* * called when RDP server wants us to update a rect with new data ***********************************************************************/ -- (void) my_draw_rect:(void *)context +- (void) my_draw_rect:(void*)context { - int w; - int h; - - rdpContext * ctx = (rdpContext *) context; - - struct rgba_data - { - char red; - char green; - char blue; - char alpha; - }; - - if (isRemoteApp && currentWindow) { - NSRect vrect = [ [currentWindow view] frame]; - [[currentWindow view] setNeedsDisplayInRect:vrect]; - // actual drawing will be done in MRDPRailView:drawRect() - return; - } - - w = width; - h = height; - rect.origin.x = 0; - rect.origin.y = 0; - rect.size.width = w; - rect.size.height = h; - - if (!bmiRep) { - pixel_data = (char *) malloc(w * h * sizeof(struct rgba_data)); - bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &pixel_data - pixelsWide:w - pixelsHigh:h - bitsPerSample:8 - samplesPerPixel:sizeof(struct rgba_data) - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bitmapFormat:0 //NSAlphaFirstBitmapFormat - bytesPerRow:w * sizeof(struct rgba_data) - bitsPerPixel:0]; - } - + int w; + int h; + + rdpContext* ctx = (rdpContext*) context; + + struct rgba_data + { + char red; + char green; + char blue; + char alpha; + }; + + if (isRemoteApp && currentWindow) + { + NSRect vrect = [ [currentWindow view] frame]; + [[currentWindow view] setNeedsDisplayInRect:vrect]; + // actual drawing will be done in MRDPRailView:drawRect() + return; + } + + w = width; + h = height; + rect.origin.x = 0; + rect.origin.y = 0; + rect.size.width = w; + rect.size.height = h; + + if (!bmiRep) + { + pixel_data = (char *) malloc(w * h * sizeof(struct rgba_data)); + bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &pixel_data + pixelsWide:w + pixelsHigh:h + bitsPerSample:8 + samplesPerPixel:sizeof(struct rgba_data) + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bitmapFormat:0 //NSAlphaFirstBitmapFormat + bytesPerRow:w * sizeof(struct rgba_data) + bitsPerPixel:0]; + } + #ifdef MRDP_DRAW_INDIVIDUAL_RECTS - [self setNeedsDisplayInRect:rect]; - return; + [self setNeedsDisplayInRect:rect]; + return; #endif - - convert_color_space(pixel_data, (char *) ctx->gdi->primary_buffer, &rect, w, h); - [self setNeedsDisplayInRect:rect]; + + convert_color_space(pixel_data, (char *) ctx->gdi->primary_buffer, &rect, w, h); + [self setNeedsDisplayInRect:rect]; } /** ********************************************************************* @@ -788,8 +799,8 @@ struct kkey g_keys[256] = - (void) saveStateInfo:(freerdp *) instance:(rdpContext *) context { - rdp_instance = instance; - rdp_context = context; + rdp_instance = instance; + rdp_context = context; } /** ********************************************************************* @@ -798,36 +809,43 @@ struct kkey g_keys[256] = - (BOOL) eventIsInClientArea :(NSEvent *) event :(int *) xptr :(int *) yptr { - NSPoint loc = [event locationInWindow]; - int x = (int) loc.x; - int y = (int) loc.y; - - if ((x < 0) || (y < 0)) { - if (mouseInClientArea) { - // set default cursor before leaving client area - mouseInClientArea = NO; - NSCursor *cur = [NSCursor arrowCursor]; - [cur set]; - } - return NO; - } - if ((x > width) || (y > height)) { - if (mouseInClientArea) { - // set default cursor before leaving client area - mouseInClientArea = NO; - NSCursor *cur = [NSCursor arrowCursor]; - [cur set]; - } - return NO; - } - - // on Mac origin is at lower left, but we want it on upper left - y = height - y; - - *xptr = x; - *yptr = y; - mouseInClientArea = YES; - return YES; + NSPoint loc = [event locationInWindow]; + int x = (int) loc.x; + int y = (int) loc.y; + + if ((x < 0) || (y < 0)) + { + if (mouseInClientArea) + { + // set default cursor before leaving client area + mouseInClientArea = NO; + NSCursor *cur = [NSCursor arrowCursor]; + [cur set]; + } + + return NO; + } + + if ((x > width) || (y > height)) + { + if (mouseInClientArea) + { + // set default cursor before leaving client area + mouseInClientArea = NO; + NSCursor *cur = [NSCursor arrowCursor]; + [cur set]; + } + + return NO; + } + + // on Mac origin is at lower left, but we want it on upper left + y = height - y; + + *xptr = x; + *yptr = y; + mouseInClientArea = YES; + return YES; } /** ********************************************************************* @@ -836,13 +854,13 @@ struct kkey g_keys[256] = - (void) rdpConnectError { - - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:@"Error connecting to server"]; - [alert beginSheetModalForWindow:[g_mrdpview window] - modalDelegate:g_mrdpview - didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) - contextInfo:nil]; + + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Error connecting to server"]; + [alert beginSheetModalForWindow:[g_mrdpview window] + modalDelegate:g_mrdpview + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:nil]; } /** ********************************************************************* @@ -851,119 +869,121 @@ struct kkey g_keys[256] = - (void) rdpRemoteAppError { - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:@"Error starting remote app on specified server"]; - [alert beginSheetModalForWindow:[g_mrdpview window] - modalDelegate:g_mrdpview - didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) - contextInfo:nil]; + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Error starting remote app on specified server"]; + [alert beginSheetModalForWindow:[g_mrdpview window] + modalDelegate:g_mrdpview + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:nil]; } /** ********************************************************************* * just a terminate selector for above call ***********************************************************************/ -- (void) alertDidEnd:(NSAlert *)a returnCode:(NSInteger)rc contextInfo:(void *)ci +- (void) alertDidEnd:(NSAlert *)a returnCode:(NSInteger)rc contextInfo:(void *)ci { - [NSApp terminate:nil]; + [NSApp terminate:nil]; } -- (void) onPasteboardTimerFired :(NSTimer *) timer +- (void) onPasteboardTimerFired :(NSTimer*) timer { - NSArray *types; - int i; - - i = (int) [pasteboard_rd changeCount]; - if (i != pasteboard_changecount) - { - pasteboard_changecount = i; - types = [NSArray arrayWithObject:NSStringPboardType]; - NSString *str = [pasteboard_rd availableTypeFromArray:types]; - if (str != nil) - { - cliprdr_send_supported_format_list(rdp_instance); - } - } + int i; + NSArray* types; + + i = (int) [pasteboard_rd changeCount]; + + if (i != pasteboard_changecount) + { + pasteboard_changecount = i; + types = [NSArray arrayWithObject:NSStringPboardType]; + NSString *str = [pasteboard_rd availableTypeFromArray:types]; + if (str != nil) + { + cliprdr_send_supported_format_list(rdp_instance); + } + } } - (void) setViewSize : (int) w : (int) h { - // store current dimensions - width = w; - height = h; - - // compute difference between window and client area - NSRect outerRect = [[g_mrdpview window] frame]; - NSRect innerRect = [g_mrdpview frame]; - - int widthDiff = outerRect.size.width - innerRect.size.width; - int heightDiff = outerRect.size.height - innerRect.size.height; - - if (!g_mrdpview->isRemoteApp) { - // we are not in RemoteApp mode, disable resizing - outerRect.size.width = w + widthDiff; - outerRect.size.height = h + heightDiff; - [[g_mrdpview window] setMaxSize:outerRect.size]; - [[g_mrdpview window] setMinSize:outerRect.size]; - [[g_mrdpview window] setFrame:outerRect display:YES]; - - // set client area to specified dimensions - innerRect.size.width = w; - innerRect.size.height = h; - [g_mrdpview setFrame:innerRect]; - - return; - } - - // we are in RemoteApp mode - - outerRect.origin.x = 0; - outerRect.origin.y = 0; - outerRect.size.width = width + widthDiff; - outerRect.size.height = height + heightDiff; - [[g_mrdpview window] setFrame:outerRect display:YES]; + // store current dimensions + width = w; + height = h; + + // compute difference between window and client area + NSRect outerRect = [[g_mrdpview window] frame]; + NSRect innerRect = [g_mrdpview frame]; + + int widthDiff = outerRect.size.width - innerRect.size.width; + int heightDiff = outerRect.size.height - innerRect.size.height; + + if (!g_mrdpview->isRemoteApp) + { + // we are not in RemoteApp mode, disable resizing + outerRect.size.width = w + widthDiff; + outerRect.size.height = h + heightDiff; + [[g_mrdpview window] setMaxSize:outerRect.size]; + [[g_mrdpview window] setMinSize:outerRect.size]; + [[g_mrdpview window] setFrame:outerRect display:YES]; + + // set client area to specified dimensions + innerRect.size.width = w; + innerRect.size.height = h; + [g_mrdpview setFrame:innerRect]; + + return; + } + + // we are in RemoteApp mode + + outerRect.origin.x = 0; + outerRect.origin.y = 0; + outerRect.size.width = width + widthDiff; + outerRect.size.height = height + heightDiff; + [[g_mrdpview window] setFrame:outerRect display:YES]; - // set client area to specified dimensions - innerRect.size.width = width; - innerRect.size.height = height; - [g_mrdpview setFrame:innerRect]; - - // main window displays desktop background - hide it - [[g_mrdpview window] orderOut:g_mrdpview]; + // set client area to specified dimensions + innerRect.size.width = width; + innerRect.size.height = height; + [g_mrdpview setFrame:innerRect]; + + // main window displays desktop background - hide it + [[g_mrdpview window] orderOut:g_mrdpview]; } // RAIL_TODO is this func required -- (void) windowDidResize:(NSNotification *) notification +- (void) windowDidResize:(NSNotification*) notification { - RAIL_WINDOW_MOVE_ORDER windowMove; - - printf("RAIL_TODO: MRDPView: windowDidResize() - not yet implemented\n"); - - return; - - // window resize valid only in RemoteApp mode - if (!g_mrdpview->isRemoteApp) - return; - - // window has resized, let server know - - NSRect r = [[g_mrdpview window] frame]; - printf("----- LK_TODO: MRDPView:windowDidResize (%d,%d %dx%d)\n", - (int) r.origin.x, (int) r.origin.y, - (int) r.size.width, (int) r.size.height); - - - windowMove.windowId = [currentWindow windowID]; - - windowMove.left = (uint16) r.origin.x; // x-cordinate of top left corner - windowMove.right = (uint16) (windowMove.left + r.size.width); // x-cordinate of bottom right corner - windowMove.top = (uint16) r.origin.y; // y-cordinate of top left corner - windowMove.bottom = (uint16) (windowMove.top + r.size.height); // y-cordinate of bottom right corner - - printf("----- LK_TODO: MRDPView:windowDidResize windowID=%d left=%d top=%d right=%d bottom=x%d width=%f height=%f\n", - [currentWindow windowID], windowMove.left, windowMove.top, windowMove.right, windowMove.bottom, r.size.width, r.size.height); - - //mac_send_rail_client_event(g_mrdpview->rdp_instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); + RAIL_WINDOW_MOVE_ORDER windowMove; + + printf("RAIL_TODO: MRDPView: windowDidResize() - not yet implemented\n"); + + return; + + // window resize valid only in RemoteApp mode + if (!g_mrdpview->isRemoteApp) + return; + + // window has resized, let server know + + NSRect r = [[g_mrdpview window] frame]; + printf("----- LK_TODO: MRDPView:windowDidResize (%d,%d %dx%d)\n", + (int) r.origin.x, (int) r.origin.y, + (int) r.size.width, (int) r.size.height); + + + windowMove.windowId = [currentWindow windowID]; + + windowMove.left = (UINT16) r.origin.x; // x-cordinate of top left corner + windowMove.right = (UINT16) (windowMove.left + r.size.width); // x-cordinate of bottom right corner + windowMove.top = (UINT16) r.origin.y; // y-cordinate of top left corner + windowMove.bottom = (UINT16) (windowMove.top + r.size.height); // y-cordinate of bottom right corner + + printf("----- LK_TODO: MRDPView:windowDidResize windowID=%d left=%d top=%d right=%d bottom=x%d width=%f height=%f\n", + [currentWindow windowID], windowMove.left, windowMove.top, windowMove.right, windowMove.bottom, r.size.width, r.size.height); + + //mac_send_rail_client_event(g_mrdpview->rdp_instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); } /************************************************************************ @@ -980,245 +1000,153 @@ struct kkey g_keys[256] = int rdp_connect() { - freerdp *inst; - int status; - - freerdp_channels_global_init(); - - inst = freerdp_new(); - inst->PreConnect = mac_pre_connect; - inst->PostConnect = mac_post_connect; - inst->context_size = sizeof(struct mac_context); - inst->ContextNew = mac_context_new; - inst->ContextFree = mac_context_free; - inst->ReceiveChannelData = receive_channel_data; - freerdp_context_new(inst); - - status = freerdp_connect(inst); - if(status) { - freerdp_check_fds(inst); - [g_mrdpview setIs_connected:1]; - return 0; - } - [g_mrdpview setIs_connected:0]; - [g_mrdpview rdpConnectError]; - return -1; + int status; + freerdp* instance; + + freerdp_channels_global_init(); + + instance = freerdp_new(); + instance->PreConnect = mac_pre_connect; + instance->PostConnect = mac_post_connect; + instance->context_size = sizeof(struct mac_context); + instance->ContextNew = mac_context_new; + instance->ContextFree = mac_context_free; + instance->ReceiveChannelData = receive_channel_data; + freerdp_context_new(instance); + + status = freerdp_connect(instance); + + if (status) + { + freerdp_check_fds(instance); + [g_mrdpview setIs_connected:1]; + return 0; + } + + [g_mrdpview setIs_connected:0]; + [g_mrdpview rdpConnectError]; + + return -1; } /** ********************************************************************* * a callback given to freerdp_connect() to process the pre-connect operations. * - * @param inst - pointer to a rdp_freerdp struct that contains the connection's parameters, and + * @param inst - pointer to a rdp_freerdp struct that contains the connection's parameters, and * will be filled with the appropriate informations. * * @return true if successful. false otherwise. ************************************************************************/ -BOOL mac_pre_connect(freerdp *inst) +BOOL mac_pre_connect(freerdp* instance) { + int i; + int len; int status; - char *cptr; - int len; - int i; - - inst->settings->OffscreenSupportLevel = FALSE; - inst->settings->GlyphSupportLevel = GLYPH_SUPPORT_FULL; - inst->settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; - inst->settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE; - inst->settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE; - inst->settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; - inst->settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; - - inst->settings->BitmapCacheEnabled = TRUE; - inst->settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE; - inst->settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = TRUE; - inst->settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE; - inst->settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE; - inst->settings->BitmapCacheV2NumCells = 3; // 5; - inst->settings->BitmapCacheV2CellInfo[0].numEntries = 0x78; // 600; - inst->settings->BitmapCacheV2CellInfo[0].persistent = FALSE; - inst->settings->BitmapCacheV2CellInfo[1].numEntries = 0x78; // 600; - inst->settings->BitmapCacheV2CellInfo[1].persistent = FALSE; - inst->settings->BitmapCacheV2CellInfo[2].numEntries = 0x150; // 2048; - inst->settings->BitmapCacheV2CellInfo[2].persistent = FALSE; - inst->settings->BitmapCacheV2CellInfo[3].numEntries = 0; // 4096; - inst->settings->BitmapCacheV2CellInfo[3].persistent = FALSE; - inst->settings->BitmapCacheV2CellInfo[4].numEntries = 0; // 2048; - inst->settings->BitmapCacheV2CellInfo[4].persistent = FALSE; - - inst->settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; - inst->settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; - inst->settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; - inst->settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = FALSE; - inst->settings->OrderSupport[NEG_POLYLINE_INDEX] = FALSE; - inst->settings->ColorDepth = 24; - inst->settings->SoftwareGdi = 1; - - // setup callbacks - inst->update->BeginPaint = mac_begin_paint; - inst->update->EndPaint = mac_end_paint; - inst->update->SetBounds = mac_set_bounds; - inst->update->BitmapUpdate = mac_bitmap_update; - - NSArray *args = [[NSProcessInfo processInfo] arguments]; - -#ifdef RUN_IN_XCODE - g_mrdpview->argc = 30; -#else - g_mrdpview->argc = (int) [args count]; -#endif - - g_mrdpview->argv = malloc(sizeof(char *) * g_mrdpview->argc); - if (g_mrdpview->argv == NULL) { - return FALSE; - } - -#ifdef RUN_IN_XCODE - - // create our own cmd line args - i = 0; - - NSString *sptr = [args objectAtIndex:0]; - len = [sptr length] + 1; - cptr = (char *) malloc(len); - strcpy(cptr, [sptr UTF8String]); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "-g"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "1280x800"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "--sec"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "rdp"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "--plugin"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "cliprdr"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "--plugin"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "rdpsnd"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "-u"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "lk"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "-p"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "abc@@@123"); - g_mrdpview->argv[i++] = cptr; - -#if 1 - // for RemoteApp (RAIL) testing - cptr = (char *)malloc(80); - strcpy(cptr, "--app"); - g_mrdpview->argv[i++] = cptr; - g_mrdpview->isRemoteApp = TRUE; - - cptr = (char *)malloc(80); - strcpy(cptr, "--plugin"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "rail"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "--data"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "||WordPad"); - g_mrdpview->argv[i++] = cptr; - - cptr = (char *)malloc(80); - strcpy(cptr, "--"); - g_mrdpview->argv[i++] = cptr; -#endif - - cptr = (char *)malloc(80); - strcpy(cptr, "192.168.1.69:45990"); - g_mrdpview->argv[i++] = cptr; - - g_mrdpview->argc = i; - -#else - // MacFreeRDP was not run in Xcode - i = 0; - - // in RemoteApp (RAIL) mode, we connect to RDP server at max screen resolution; - // in order to achieve this, we need to modify the cmd line args entered by the user; - - if (g_mrdpview->isRemoteApp) { - BOOL gotGeometry = NO; - - // get dimensions of screen that has keyboard focus; - // we use these dimensions when connecting to RDP server - inst->settings->DesktopWidth = [[NSScreen mainScreen] frame].size.width; - inst->settings->DesktopHeight = [[NSScreen mainScreen] frame].size.height - g_mrdpview->titleBarHeight; - g_mrdpview->width = inst->settings->DesktopWidth; - g_mrdpview->height = inst->settings->DesktopHeight; - - for (NSString * str in args) - { - if (gotGeometry) { - gotGeometry = NO; - cptr = (char *) malloc(20); - sprintf(cptr, "%dx%d", g_mrdpview->width, g_mrdpview->height); - g_mrdpview->argv[i++] = cptr; - continue; - } - - len = (int) ([str length] + 1); - cptr = (char *) malloc(len); - strcpy(cptr, [str UTF8String]); - g_mrdpview->argv[i++] = cptr; - - // -g is the cmd line arg to specify screen resolution/geometry - if ([str compare:@"-g"] == NSOrderedSame) { - gotGeometry = YES; - } - } - } - else { - for (NSString * str in args) - { - len = (int) ([str length] + 1); - cptr = (char *) malloc(len); - strcpy(cptr, [str UTF8String]); - g_mrdpview->argv[i++] = cptr; - } - } -#endif + char* cptr; - inst->context->argc = g_mrdpview->argc; - inst->context->argv = g_mrdpview->argv; + instance->settings->OffscreenSupportLevel = FALSE; + instance->settings->GlyphSupportLevel = GLYPH_SUPPORT_FULL; + instance->settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; + instance->settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE; + instance->settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE; + instance->settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; + instance->settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; - status = freerdp_client_parse_command_line_arguments(inst->context->argc, inst->context->argv, inst->settings); + instance->settings->BitmapCacheEnabled = TRUE; + instance->settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE; + instance->settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = TRUE; + instance->settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE; + instance->settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE; + instance->settings->BitmapCacheV2NumCells = 3; // 5; + instance->settings->BitmapCacheV2CellInfo[0].numEntries = 0x78; // 600; + instance->settings->BitmapCacheV2CellInfo[0].persistent = FALSE; + instance->settings->BitmapCacheV2CellInfo[1].numEntries = 0x78; // 600; + instance->settings->BitmapCacheV2CellInfo[1].persistent = FALSE; + instance->settings->BitmapCacheV2CellInfo[2].numEntries = 0x150; // 2048; + instance->settings->BitmapCacheV2CellInfo[2].persistent = FALSE; + instance->settings->BitmapCacheV2CellInfo[3].numEntries = 0; // 4096; + instance->settings->BitmapCacheV2CellInfo[3].persistent = FALSE; + instance->settings->BitmapCacheV2CellInfo[4].numEntries = 0; // 2048; + instance->settings->BitmapCacheV2CellInfo[4].persistent = FALSE; + + instance->settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; + instance->settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; + instance->settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; + instance->settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = FALSE; + instance->settings->OrderSupport[NEG_POLYLINE_INDEX] = FALSE; + instance->settings->ColorDepth = 24; + instance->settings->SoftwareGdi = 1; + + // setup callbacks + instance->update->BeginPaint = mac_begin_paint; + instance->update->EndPaint = mac_end_paint; + instance->update->SetBounds = mac_set_bounds; + instance->update->BitmapUpdate = mac_bitmap_update; + + NSArray *args = [[NSProcessInfo processInfo] arguments]; + + g_mrdpview->argc = (int) [args count]; + + g_mrdpview->argv = malloc(sizeof(char *) * g_mrdpview->argc); + + if (g_mrdpview->argv == NULL) + return FALSE; + + i = 0; + + // in RemoteApp (RAIL) mode, we connect to RDP server at max screen resolution; + // in order to achieve this, we need to modify the cmd line args entered by the user; + + if (g_mrdpview->isRemoteApp) + { + BOOL gotGeometry = NO; + + // get dimensions of screen that has keyboard focus; + // we use these dimensions when connecting to RDP server + instance->settings->DesktopWidth = [[NSScreen mainScreen] frame].size.width; + instance->settings->DesktopHeight = [[NSScreen mainScreen] frame].size.height - g_mrdpview->titleBarHeight; + g_mrdpview->width = instance->settings->DesktopWidth; + g_mrdpview->height = instance->settings->DesktopHeight; + + for (NSString * str in args) + { + if (gotGeometry) + { + gotGeometry = NO; + cptr = (char *) malloc(20); + sprintf(cptr, "%dx%d", g_mrdpview->width, g_mrdpview->height); + g_mrdpview->argv[i++] = cptr; + continue; + } + + len = (int) ([str length] + 1); + cptr = (char *) malloc(len); + strcpy(cptr, [str UTF8String]); + g_mrdpview->argv[i++] = cptr; + + // -g is the cmd line arg to specify screen resolution/geometry + if ([str compare:@"-g"] == NSOrderedSame) + { + gotGeometry = YES; + } + } + } + else + { + for (NSString * str in args) + { + len = (int) ([str length] + 1); + cptr = (char *) malloc(len); + strcpy(cptr, [str UTF8String]); + g_mrdpview->argv[i++] = cptr; + } + } + + instance->context->argc = g_mrdpview->argc; + instance->context->argv = g_mrdpview->argv; + + status = freerdp_client_parse_command_line_arguments(instance->context->argc, instance->context->argv, instance->settings); if (status < 0) { @@ -1226,17 +1154,17 @@ BOOL mac_pre_connect(freerdp *inst) return TRUE; } - freerdp_client_load_addins(inst->context->channels, inst->settings); - - [g_mrdpview setViewSize:inst->settings->DesktopWidth :inst->settings->DesktopHeight]; - - freerdp_channels_pre_connect(inst->context->channels, inst); - return TRUE; + freerdp_client_load_addins(instance->context->channels, instance->settings); + + [g_mrdpview setViewSize:instance->settings->DesktopWidth :instance->settings->DesktopHeight]; + + freerdp_channels_pre_connect(instance->context->channels, instance); + return TRUE; } /** ********************************************************************* * a callback registered with freerdp_connect() to perform post-connection operations. - * we get called only if the connection was initialized properly, and will continue + * we get called only if the connection was initialized properly, and will continue * the initialization based on the newly created connection. * * @param inst - pointer to a rdp_freerdp struct @@ -1245,73 +1173,74 @@ BOOL mac_pre_connect(freerdp *inst) * ************************************************************************/ -BOOL mac_post_connect(freerdp *inst) +BOOL mac_post_connect(freerdp* instance) { - uint32 flags; - rdpPointer rdp_pointer; - void *rd_fds[32]; - void *wr_fds[32]; - int rd_count = 0; - int wr_count = 0; - int index; - int fds[32]; - - memset(&rdp_pointer, 0, sizeof(rdpPointer)); - rdp_pointer.size = sizeof(rdpPointer); - rdp_pointer.New = pointer_new; - rdp_pointer.Free = pointer_free; - rdp_pointer.Set = pointer_set; - rdp_pointer.SetNull = pointer_setNull; - rdp_pointer.SetDefault = pointer_setDefault; - - flags = CLRCONV_ALPHA; - flags |= CLRBUF_32BPP; - - gdi_init(inst, flags, NULL); - pointer_cache_register_callbacks(inst->update); - graphics_register_pointer(inst->context->graphics, &rdp_pointer); - - // register file descriptors with the RunLoop - if (!freerdp_get_fds(inst, rd_fds, &rd_count, 0, 0)) - { - printf("mac_post_connect: freerdp_get_fds() failed!\n"); - } - - for (index = 0; index < rd_count; index++) - { - fds[index] = (int)(long)rd_fds[index]; - } - register_fds(fds, rd_count, inst); - - // register channel manager file descriptors with the RunLoop - if (!freerdp_channels_get_fds(inst->context->channels, inst, rd_fds, &rd_count, wr_fds, &wr_count)) - { - printf("ERROR: freerdp_channels_get_fds() failed\n"); - } - for (index = 0; index < rd_count; index++) - { - fds[index] = (int)(long)rd_fds[index]; - } - register_channel_fds(fds, rd_count, inst); - freerdp_channels_post_connect(inst->context->channels, inst); - - // setup RAIL (remote app) - inst->context->rail = rail_new(inst->settings); - rail_register_update_callbacks(inst->context->rail, inst->update); - mac_rail_register_callbacks(inst, inst->context->rail); - - // setup pasteboard (aka clipboard) for copy operations (write only) - g_mrdpview->pasteboard_wr = [NSPasteboard generalPasteboard]; - - // setup pasteboard for read operations - g_mrdpview->pasteboard_rd = [NSPasteboard generalPasteboard]; - g_mrdpview->pasteboard_changecount = (int) [g_mrdpview->pasteboard_rd changeCount]; - g_mrdpview->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:g_mrdpview selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES]; - - // we want to be notified when window resizes - [[NSNotificationCenter defaultCenter] addObserver:g_mrdpview selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:nil]; - - return TRUE; + int index; + int fds[32]; + UINT32 flags; + int rd_count = 0; + int wr_count = 0; + void* rd_fds[32]; + void* wr_fds[32]; + rdpPointer rdp_pointer; + + memset(&rdp_pointer, 0, sizeof(rdpPointer)); + rdp_pointer.size = sizeof(rdpPointer); + rdp_pointer.New = pointer_new; + rdp_pointer.Free = pointer_free; + rdp_pointer.Set = pointer_set; + rdp_pointer.SetNull = pointer_setNull; + rdp_pointer.SetDefault = pointer_setDefault; + + flags = CLRCONV_ALPHA; + flags |= CLRBUF_32BPP; + + gdi_init(instance, flags, NULL); + pointer_cache_register_callbacks(instance->update); + graphics_register_pointer(instance->context->graphics, &rdp_pointer); + + // register file descriptors with the RunLoop + if (!freerdp_get_fds(instance, rd_fds, &rd_count, 0, 0)) + { + printf("mac_post_connect: freerdp_get_fds() failed!\n"); + } + + for (index = 0; index < rd_count; index++) + { + fds[index] = (int)(long)rd_fds[index]; + } + register_fds(fds, rd_count, instance); + + // register channel manager file descriptors with the RunLoop + if (!freerdp_channels_get_fds(instance->context->channels, instance, rd_fds, &rd_count, wr_fds, &wr_count)) + { + printf("ERROR: freerdp_channels_get_fds() failed\n"); + } + for (index = 0; index < rd_count; index++) + { + fds[index] = (int)(long)rd_fds[index]; + } + + register_channel_fds(fds, rd_count, instance); + freerdp_channels_post_connect(instance->context->channels, instance); + + // setup RAIL (remote app) + instance->context->rail = rail_new(instance->settings); + rail_register_update_callbacks(instance->context->rail, instance->update); + mac_rail_register_callbacks(instance, instance->context->rail); + + // setup pasteboard (aka clipboard) for copy operations (write only) + g_mrdpview->pasteboard_wr = [NSPasteboard generalPasteboard]; + + // setup pasteboard for read operations + g_mrdpview->pasteboard_rd = [NSPasteboard generalPasteboard]; + g_mrdpview->pasteboard_changecount = (int) [g_mrdpview->pasteboard_rd changeCount]; + g_mrdpview->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:g_mrdpview selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES]; + + // we want to be notified when window resizes + [[NSNotificationCenter defaultCenter] addObserver:g_mrdpview selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:nil]; + + return TRUE; } /** ********************************************************************* @@ -1324,58 +1253,58 @@ BOOL mac_post_connect(freerdp *inst) void pointer_new(rdpContext* context, rdpPointer* pointer) { - MRDPCursor *mrdpCursor = [[MRDPCursor alloc] init]; - uint8 *cursor_data; - - NSRect rect; - rect.size.width = pointer->width; - rect.size.height = pointer->height; - rect.origin.x = pointer->xPos; - rect.origin.y = pointer->yPos; - - cursor_data = (uint8 *) malloc(rect.size.width * rect.size.height * 4); - mrdpCursor->cursor_data = cursor_data; - - freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData, - pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv); - - // TODO if xorBpp is > 24 need to call freerdp_image_swap_color_order - // see file df_graphics.c - - // store cursor bitmap image in representation - required by NSImage - NSBitmapImageRep *bmiRep; - bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &cursor_data - pixelsWide:rect.size.width - pixelsHigh:rect.size.height - bitsPerSample:8 - samplesPerPixel:sizeof(struct rgba_data) - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bitmapFormat:0 - bytesPerRow:rect.size.width * 4 - bitsPerPixel:0]; - mrdpCursor->bmiRep = bmiRep; - - // create an image using above representation - NSImage *image = [[NSImage alloc] initWithSize:[bmiRep size]]; - [image addRepresentation: bmiRep]; - [image setFlipped:NO]; - mrdpCursor->nsImage = image; - - // need hotspot to create cursor - NSPoint hotSpot; - hotSpot.x = pointer->xPos; - hotSpot.y = pointer->yPos; - - NSCursor *cursor = [[NSCursor alloc] initWithImage: image hotSpot:hotSpot]; - mrdpCursor->nsCursor = cursor; - mrdpCursor->pointer = pointer; - - // save cursor for later use in pointer_set() - NSMutableArray *ma = g_mrdpview->cursors; - [ma addObject:mrdpCursor]; -} + BYTE* cursor_data; + MRDPCursor *mrdpCursor = [[MRDPCursor alloc] init]; + + NSRect rect; + rect.size.width = pointer->width; + rect.size.height = pointer->height; + rect.origin.x = pointer->xPos; + rect.origin.y = pointer->yPos; + + cursor_data = (BYTE *) malloc(rect.size.width * rect.size.height * 4); + mrdpCursor->cursor_data = cursor_data; + + freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData, + pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv); + + // TODO if xorBpp is > 24 need to call freerdp_image_swap_color_order + // see file df_graphics.c + + // store cursor bitmap image in representation - required by NSImage + NSBitmapImageRep *bmiRep; + bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &cursor_data + pixelsWide:rect.size.width + pixelsHigh:rect.size.height + bitsPerSample:8 + samplesPerPixel:sizeof(struct rgba_data) + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bitmapFormat:0 + bytesPerRow:rect.size.width * 4 + bitsPerPixel:0]; + mrdpCursor->bmiRep = bmiRep; + + // create an image using above representation + NSImage *image = [[NSImage alloc] initWithSize:[bmiRep size]]; + [image addRepresentation: bmiRep]; + [image setFlipped:NO]; + mrdpCursor->nsImage = image; + + // need hotspot to create cursor + NSPoint hotSpot; + hotSpot.x = pointer->xPos; + hotSpot.y = pointer->yPos; + + NSCursor *cursor = [[NSCursor alloc] initWithImage: image hotSpot:hotSpot]; + mrdpCursor->nsCursor = cursor; + mrdpCursor->pointer = pointer; + + // save cursor for later use in pointer_set() + NSMutableArray *ma = g_mrdpview->cursors; + [ma addObject:mrdpCursor]; +} /** ********************************************************************* * release resources on specified cursor @@ -1383,19 +1312,20 @@ void pointer_new(rdpContext* context, rdpPointer* pointer) void pointer_free(rdpContext* context, rdpPointer* pointer) { - NSMutableArray *ma = g_mrdpview->cursors; - - for (MRDPCursor *cursor in ma) - { - if (cursor->pointer == pointer) { - cursor->nsImage = nil; - cursor->nsCursor = nil; - cursor->bmiRep = nil; - free(cursor->cursor_data); - [ma removeObject:cursor]; - return; - } - } + NSMutableArray* ma = g_mrdpview->cursors; + + for (MRDPCursor* cursor in ma) + { + if (cursor->pointer == pointer) + { + cursor->nsImage = nil; + cursor->nsCursor = nil; + cursor->bmiRep = nil; + free(cursor->cursor_data); + [ma removeObject:cursor]; + return; + } + } } /** ********************************************************************* @@ -1404,20 +1334,19 @@ void pointer_free(rdpContext* context, rdpPointer* pointer) void pointer_set(rdpContext* context, rdpPointer* pointer) { - NSMutableArray *ma = g_mrdpview->cursors; - - if (!g_mrdpview->mouseInClientArea) - { - return; // not in client area - } - - for (MRDPCursor *cursor in ma) - { - if (cursor->pointer == pointer) { - [cursor->nsCursor set]; - return; - } - } + NSMutableArray* ma = g_mrdpview->cursors; + + if (!g_mrdpview->mouseInClientArea) + return; + + for (MRDPCursor* cursor in ma) + { + if (cursor->pointer == pointer) + { + [cursor->nsCursor set]; + return; + } + } } /** ********************************************************************* @@ -1440,17 +1369,17 @@ void pointer_setDefault(rdpContext* context) * create a new context - but all we really need to do is save state info ***********************************************************************/ -void mac_context_new(freerdp *inst, rdpContext *context) +void mac_context_new(freerdp* instance, rdpContext* context) { - [g_mrdpview saveStateInfo:inst :context]; - context->channels = freerdp_channels_new(); + [g_mrdpview saveStateInfo:instance :context]; + context->channels = freerdp_channels_new(); } /** ********************************************************************* * we don't do much over here ***********************************************************************/ -void mac_context_free(freerdp *inst, rdpContext *context) +void mac_context_free(freerdp* instance, rdpContext* context) { } @@ -1458,7 +1387,7 @@ void mac_context_free(freerdp *inst, rdpContext *context) * clip drawing surface so nothing is drawn outside specified bounds ***********************************************************************/ -void mac_set_bounds(rdpContext *context, rdpBounds *bounds) +void mac_set_bounds(rdpContext* context, rdpBounds* bounds) { } @@ -1466,7 +1395,7 @@ void mac_set_bounds(rdpContext *context, rdpBounds *bounds) * we don't do much over here ***********************************************************************/ -void mac_bitmap_update(rdpContext *context, BITMAP_UPDATE *bitmap) +void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap) { } @@ -1474,10 +1403,10 @@ void mac_bitmap_update(rdpContext *context, BITMAP_UPDATE *bitmap) * we don't do much over here ***********************************************************************/ -void mac_begin_paint(rdpContext *context) +void mac_begin_paint(rdpContext* context) { - rdpGdi* gdi = context->gdi; - gdi->primary->hdc->hwnd->invalid->null = 1; + rdpGdi* gdi = context->gdi; + gdi->primary->hdc->hwnd->invalid->null = 1; } /** ********************************************************************* @@ -1486,206 +1415,202 @@ void mac_begin_paint(rdpContext *context) void mac_end_paint(rdpContext* context) { - int i; - NSRect drawRect; - rdpGdi * gdi; - - if ((context == 0) || (context->gdi == 0)) - return; - - if (context->gdi->primary->hdc->hwnd->invalid->null) - return; - - if (context->gdi->drawing != context->gdi->primary) - return; - - gdi = g_mrdpview->rdp_context->gdi; - - if (g_mrdpview->isRemoteApp && g_mrdpview->currentWindow) { - [[g_mrdpview->currentWindow view] updateDisplay]; - return; - } - - for (i = 0; i < gdi->primary->hdc->hwnd->ninvalid; i++) - { - drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x; - drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y; - drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w; - drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h; - - convert_color_space(g_mrdpview->pixel_data, (char *) gdi->primary_buffer, &drawRect, g_mrdpview->width, g_mrdpview->height); - - [g_mrdpview setNeedsDisplayInRect:drawRect]; - } - gdi->primary->hdc->hwnd->ninvalid = 0; + int i; + rdpGdi* gdi; + NSRect drawRect; + + if ((context == 0) || (context->gdi == 0)) + return; + + if (context->gdi->primary->hdc->hwnd->invalid->null) + return; + + if (context->gdi->drawing != context->gdi->primary) + return; + + gdi = g_mrdpview->rdp_context->gdi; + + if (g_mrdpview->isRemoteApp && g_mrdpview->currentWindow) + { + [[g_mrdpview->currentWindow view] updateDisplay]; + return; + } + + for (i = 0; i < gdi->primary->hdc->hwnd->ninvalid; i++) + { + drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x; + drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y; + drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w; + drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h; + + convert_color_space(g_mrdpview->pixel_data, (char *) gdi->primary_buffer, &drawRect, g_mrdpview->width, g_mrdpview->height); + + [g_mrdpview setNeedsDisplayInRect:drawRect]; + } + + gdi->primary->hdc->hwnd->ninvalid = 0; } /** ********************************************************************* * called when data is available on a socket ***********************************************************************/ -void skt_activity_cb( - CFSocketRef s, - CFSocketCallBackType callbackType, - CFDataRef address, - const void *data, - void *info - ) +void skt_activity_cb(CFSocketRef s, CFSocketCallBackType callbackType, + CFDataRef address, const void* data, void* info) { - if (!freerdp_check_fds(info)) { - // lost connection or did not connect - [NSApp terminate:nil]; - } + if (!freerdp_check_fds(info)) + { + // lost connection or did not connect + [NSApp terminate:nil]; + } } /** ********************************************************************* * called when data is available on a virtual channel ***********************************************************************/ -void channel_activity_cb( - CFSocketRef s, - CFSocketCallBackType callbackType, - CFDataRef address, - const void *data, - void *info - ) +void channel_activity_cb(CFSocketRef s, CFSocketCallBackType callbackType, + CFDataRef address, const void* data, void* info) { - freerdp *inst = (freerdp *) info; - RDP_EVENT* event; - - GOT_HERE; - - freerdp_channels_check_fds(inst->context->channels, inst); - event = freerdp_channels_pop_event(inst->context->channels); - if (event) { - switch (event->event_class) - { - case RDP_EVENT_CLASS_RAIL: - mac_process_rail_event(inst, event); - break; - - case RDP_EVENT_CLASS_CLIPRDR: - process_cliprdr_event(inst, event); - break; - } - } + RDP_EVENT* event; + freerdp* instance = (freerdp*) info; + + freerdp_channels_check_fds(instance->context->channels, instance); + event = freerdp_channels_pop_event(instance->context->channels); + + if (event) + { + switch (event->event_class) + { + case RDP_EVENT_CLASS_RAIL: + mac_process_rail_event(instance, event); + break; + + case RDP_EVENT_CLASS_CLIPRDR: + process_cliprdr_event(instance, event); + break; + } + } } /** ********************************************************************* * setup callbacks for data availability on sockets ***********************************************************************/ -int register_fds(int *fds, int count, void *inst) +int register_fds(int* fds, int count, void* instance) { - int i; - CFSocketRef skt_ref; - CFSocketContext skt_context = { 0, inst, NULL, NULL, NULL }; - - for (i = 0; i < count; i++) - { - skt_ref = CFSocketCreateWithNative(NULL, fds[i], kCFSocketReadCallBack, skt_activity_cb, &skt_context); - g_mrdpview->run_loop_src = CFSocketCreateRunLoopSource(NULL, skt_ref, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), g_mrdpview->run_loop_src, kCFRunLoopDefaultMode); - CFRelease(skt_ref); - } - return 0; + int i; + CFSocketRef skt_ref; + CFSocketContext skt_context = { 0, instance, NULL, NULL, NULL }; + + for (i = 0; i < count; i++) + { + skt_ref = CFSocketCreateWithNative(NULL, fds[i], kCFSocketReadCallBack, skt_activity_cb, &skt_context); + g_mrdpview->run_loop_src = CFSocketCreateRunLoopSource(NULL, skt_ref, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), g_mrdpview->run_loop_src, kCFRunLoopDefaultMode); + CFRelease(skt_ref); + } + + return 0; } /** ********************************************************************* - * setup callbacks for data availability on channels + * setup callbacks for data availability on channels ***********************************************************************/ -int register_channel_fds(int *fds, int count, void *inst) +int register_channel_fds(int* fds, int count, void* instance) { - int i; - CFSocketRef skt_ref; - CFSocketContext skt_context = { 0, inst, NULL, NULL, NULL }; - - for (i = 0; i < count; i++) - { - skt_ref = CFSocketCreateWithNative(NULL, fds[i], kCFSocketReadCallBack, channel_activity_cb, &skt_context); - g_mrdpview->run_loop_src_channels = CFSocketCreateRunLoopSource(NULL, skt_ref, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), g_mrdpview->run_loop_src_channels, kCFRunLoopDefaultMode); - CFRelease(skt_ref); - } - return 0; + int i; + CFSocketRef skt_ref; + CFSocketContext skt_context = { 0, instance, NULL, NULL, NULL }; + + for (i = 0; i < count; i++) + { + skt_ref = CFSocketCreateWithNative(NULL, fds[i], kCFSocketReadCallBack, channel_activity_cb, &skt_context); + g_mrdpview->run_loop_src_channels = CFSocketCreateRunLoopSource(NULL, skt_ref, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), g_mrdpview->run_loop_src_channels, kCFRunLoopDefaultMode); + CFRelease(skt_ref); + } + + return 0; } /** ********************************************************************* * called when channel data is available ***********************************************************************/ -int receive_channel_data(freerdp *inst, int chan_id, uint8 *data, int size, int flags, int total_size) +int receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size) { - return freerdp_channels_data(inst, chan_id, data, size, flags, total_size); + return freerdp_channels_data(instance, chan_id, data, size, flags, total_size); } /** ********************************************************************* * convert an array containing ARGB data to RGBA ***********************************************************************/ -void convert_color_space(char *dest, char *src, NSRect* drawRect, int width, int height) +void convert_color_space(char* dest, char* src, NSRect* drawRect, int width, int height) { - int i; - int j; - int x; - int y; - int cx; - int cy; - int pixel; - int pixel1; - int pixel2; - int* src32; - int* dst32; - - if ((!dest) || (!src)) { - return; - } - - x = drawRect->origin.x; - y = drawRect->origin.y; - cx = drawRect->size.width; - cy = drawRect->size.height; - - for (j = 0; j < cy; j++) - { - src32 = (int*)(src + ((y + j) * width + x) * 4); - dst32 = (int*)(dest + ((y + j) * width + x) * 4); - for (i = 0; i < cx; i++) - { - pixel = *src32; - pixel1 = (pixel & 0x00ff0000) >> 16; - pixel2 = (pixel & 0x000000ff) << 16; - pixel = (pixel & 0xff00ff00) | pixel1 | pixel2; - *dst32 = pixel; - src32++; - dst32++; - } - } - - drawRect->origin.y = height - drawRect->origin.y - drawRect->size.height; + int i; + int j; + int x; + int y; + int cx; + int cy; + int pixel; + int pixel1; + int pixel2; + int* src32; + int* dst32; + + if ((!dest) || (!src)) + return; + + x = drawRect->origin.x; + y = drawRect->origin.y; + cx = drawRect->size.width; + cy = drawRect->size.height; + + for (j = 0; j < cy; j++) + { + src32 = (int*)(src + ((y + j) * width + x) * 4); + dst32 = (int*)(dest + ((y + j) * width + x) * 4); + + for (i = 0; i < cx; i++) + { + pixel = *src32; + pixel1 = (pixel & 0x00ff0000) >> 16; + pixel2 = (pixel & 0x000000ff) << 16; + pixel = (pixel & 0xff00ff00) | pixel1 | pixel2; + *dst32 = pixel; + src32++; + dst32++; + } + } + + drawRect->origin.y = height - drawRect->origin.y - drawRect->size.height; } -/** +/** * Used to load plugins based on the commandline parameters. * This function is provided as a parameter to freerdp_parse_args(), that will call it * each time a plugin name is found on the command line. * This function just calls freerdp_channels_load_plugin() for the given plugin, and always returns 1. - * + * * @param settings * @param name * @param plugin_data * @param user_data - * + * * @return 1 */ int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) { - rdpChannels* channels = (rdpChannels*) user_data; - - freerdp_channels_load_plugin(channels, settings, name, plugin_data); - return 1; + rdpChannels* channels = (rdpChannels*) user_data; + + freerdp_channels_load_plugin(channels, settings, name, plugin_data); + + return 1; } /* @@ -1696,40 +1621,42 @@ int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA * remote system has requested clipboard data from local system */ -void cliprdr_process_cb_data_request_event(freerdp *inst) +void cliprdr_process_cb_data_request_event(freerdp* instance) { - RDP_CB_DATA_RESPONSE_EVENT *event; - NSArray *types; - int len; - - event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, - RDP_EVENT_TYPE_CB_DATA_RESPONSE, NULL, NULL); - types = [NSArray arrayWithObject:NSStringPboardType]; - NSString *str = [g_mrdpview->pasteboard_rd availableTypeFromArray:types]; - if (str == nil) - { - event->data = NULL; - event->size = 0; - } - else - { - NSString *data = [g_mrdpview->pasteboard_rd stringForType:NSStringPboardType]; - len = (int) ([data length] * 2 + 2); - event->data = malloc(len); - [data getCString:(char *) event->data maxLength:len encoding:NSUnicodeStringEncoding]; - event->size = len; - } - freerdp_channels_send_event(inst->context->channels, (RDP_EVENT*) event); + int len; + NSArray* types; + RDP_CB_DATA_RESPONSE_EVENT* event; + + event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_RESPONSE, NULL, NULL); + + types = [NSArray arrayWithObject:NSStringPboardType]; + NSString* str = [g_mrdpview->pasteboard_rd availableTypeFromArray:types]; + + if (str == nil) + { + event->data = NULL; + event->size = 0; + } + else + { + NSString* data = [g_mrdpview->pasteboard_rd stringForType:NSStringPboardType]; + len = (int) ([data length] * 2 + 2); + event->data = malloc(len); + [data getCString:(char *) event->data maxLength:len encoding:NSUnicodeStringEncoding]; + event->size = len; + } + + freerdp_channels_send_event(instance->context->channels, (RDP_EVENT*) event); } -void cliprdr_send_data_request(freerdp *inst, uint32 format) +void cliprdr_send_data_request(freerdp* instance, UINT32 format) { - RDP_CB_DATA_REQUEST_EVENT* event; - - event = (RDP_CB_DATA_REQUEST_EVENT *) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, - RDP_EVENT_TYPE_CB_DATA_REQUEST, NULL, NULL); - event->format = format; - freerdp_channels_send_event(inst->context->channels, (RDP_EVENT*) event); + RDP_CB_DATA_REQUEST_EVENT* event; + + event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_REQUEST, NULL, NULL); + + event->format = format; + freerdp_channels_send_event(instance->context->channels, (RDP_EVENT*) event); } /** @@ -1738,34 +1665,34 @@ void cliprdr_send_data_request(freerdp *inst, uint32 format) * CB_FORMAT_UNICODETEXT */ -void cliprdr_process_cb_data_response_event(freerdp *inst, RDP_CB_DATA_RESPONSE_EVENT *event) +void cliprdr_process_cb_data_response_event(freerdp* instance, RDP_CB_DATA_RESPONSE_EVENT* event) { - NSString *str; - NSArray *types; - - if (event->size == 0) { - return; - } - - if (g_mrdpview->pasteboard_format == CB_FORMAT_TEXT || g_mrdpview->pasteboard_format == CB_FORMAT_UNICODETEXT) { - str = [[NSString alloc] initWithCharacters:(unichar *) event->data length:event->size / 2]; - types = [[NSArray alloc] initWithObjects:NSStringPboardType, nil]; - [g_mrdpview->pasteboard_wr declareTypes:types owner:g_mrdpview]; - [g_mrdpview->pasteboard_wr setString:str forType:NSStringPboardType]; - } + NSString* str; + NSArray* types; + + if (event->size == 0) + return; + + if (g_mrdpview->pasteboard_format == CB_FORMAT_TEXT || g_mrdpview->pasteboard_format == CB_FORMAT_UNICODETEXT) + { + str = [[NSString alloc] initWithCharacters:(unichar *) event->data length:event->size / 2]; + types = [[NSArray alloc] initWithObjects:NSStringPboardType, nil]; + [g_mrdpview->pasteboard_wr declareTypes:types owner:g_mrdpview]; + [g_mrdpview->pasteboard_wr setString:str forType:NSStringPboardType]; + } } -void cliprdr_process_cb_monitor_ready_event(freerdp* inst) +void cliprdr_process_cb_monitor_ready_event(freerdp* instance) { - RDP_EVENT* event; - RDP_CB_FORMAT_LIST_EVENT* format_list_event; - - event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); - - format_list_event = (RDP_CB_FORMAT_LIST_EVENT*)event; - format_list_event->num_formats = 0; - - freerdp_channels_send_event(inst->context->channels, event); + RDP_EVENT* event; + RDP_CB_FORMAT_LIST_EVENT* format_list_event; + + event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); + + format_list_event = (RDP_CB_FORMAT_LIST_EVENT*)event; + format_list_event->num_formats = 0; + + freerdp_channels_send_event(instance->context->channels, event); } /** @@ -1774,106 +1701,107 @@ void cliprdr_process_cb_monitor_ready_event(freerdp* inst) * CB_FORMAT_UNICODETEXT */ -void cliprdr_process_cb_format_list_event(freerdp *inst, RDP_CB_FORMAT_LIST_EVENT* event) +void cliprdr_process_cb_format_list_event(freerdp* instance, RDP_CB_FORMAT_LIST_EVENT* event) { - int i; - - if (event->num_formats == 0) { - return; - } - - for (i = 0; i < event->num_formats; i++) - { - switch (event->formats[i]) - { - case CB_FORMAT_RAW: - printf("CB_FORMAT_RAW: not yet supported\n"); - break; - - case CB_FORMAT_TEXT: - case CB_FORMAT_UNICODETEXT: - g_mrdpview->pasteboard_format = CB_FORMAT_UNICODETEXT; - cliprdr_send_data_request(inst, CB_FORMAT_UNICODETEXT); - return; - break; - - case CB_FORMAT_DIB: - printf("CB_FORMAT_DIB: not yet supported\n"); - break; - - case CB_FORMAT_HTML: - printf("CB_FORMAT_HTML\n"); - break; - - case CB_FORMAT_PNG: - printf("CB_FORMAT_PNG: not yet supported\n"); - break; - - case CB_FORMAT_JPEG: - printf("CB_FORMAT_JPEG: not yet supported\n"); - break; - - case CB_FORMAT_GIF: - printf("CB_FORMAT_GIF: not yet supported\n"); - break; - } - } + int i; + + if (event->num_formats == 0) + return; + + for (i = 0; i < event->num_formats; i++) + { + switch (event->formats[i]) + { + case CB_FORMAT_RAW: + printf("CB_FORMAT_RAW: not yet supported\n"); + break; + + case CB_FORMAT_TEXT: + case CB_FORMAT_UNICODETEXT: + g_mrdpview->pasteboard_format = CB_FORMAT_UNICODETEXT; + cliprdr_send_data_request(instance, CB_FORMAT_UNICODETEXT); + return; + break; + + case CB_FORMAT_DIB: + printf("CB_FORMAT_DIB: not yet supported\n"); + break; + + case CB_FORMAT_HTML: + printf("CB_FORMAT_HTML\n"); + break; + + case CB_FORMAT_PNG: + printf("CB_FORMAT_PNG: not yet supported\n"); + break; + + case CB_FORMAT_JPEG: + printf("CB_FORMAT_JPEG: not yet supported\n"); + break; + + case CB_FORMAT_GIF: + printf("CB_FORMAT_GIF: not yet supported\n"); + break; + } + } } -void process_cliprdr_event(freerdp *inst, RDP_EVENT *event) +void process_cliprdr_event(freerdp* instance, RDP_EVENT* event) { - if (event) { - switch (event->event_type) - { - // Monitor Ready PDU is sent by server to indicate that it has been - // inited and is ready. This PDU is transmitted by the server after it has sent - // Clipboard Capabilities PDU - case RDP_EVENT_TYPE_CB_MONITOR_READY: - cliprdr_process_cb_monitor_ready_event(inst); - break; - - // The Format List PDU is sent either by the client or the server when its - // local system clipboard is updated with new clipboard data. This PDU - // contains the Clipboard Format ID and name pairs of the new Clipboard - // Formats on the clipboard - case RDP_EVENT_TYPE_CB_FORMAT_LIST: - cliprdr_process_cb_format_list_event(inst, (RDP_CB_FORMAT_LIST_EVENT*) event); - break; - - // The Format Data Request PDU is sent by the receipient of the Format List PDU. - // It is used to request the data for one of the formats that was listed in the - // Format List PDU - case RDP_EVENT_TYPE_CB_DATA_REQUEST: - cliprdr_process_cb_data_request_event(inst); - break; - - // The Format Data Response PDU is sent as a reply to the Format Data Request PDU. - // It is used to indicate whether processing of the Format Data Request PDU - // was successful. If the processing was successful, the Format Data Response PDU - // includes the contents of the requested clipboard data - case RDP_EVENT_TYPE_CB_DATA_RESPONSE: - cliprdr_process_cb_data_response_event(inst, (RDP_CB_DATA_RESPONSE_EVENT*) event); - break; - - default: - printf("process_cliprdr_event: unknown event type %d\n", event->event_type); - break; - } - freerdp_event_free(event); - } + if (event) + { + switch (event->event_type) + { + // Monitor Ready PDU is sent by server to indicate that it has been + // inited and is ready. This PDU is transmitted by the server after it has sent + // Clipboard Capabilities PDU + case RDP_EVENT_TYPE_CB_MONITOR_READY: + cliprdr_process_cb_monitor_ready_event(instance); + break; + + // The Format List PDU is sent either by the client or the server when its + // local system clipboard is updated with new clipboard data. This PDU + // contains the Clipboard Format ID and name pairs of the new Clipboard + // Formats on the clipboard + case RDP_EVENT_TYPE_CB_FORMAT_LIST: + cliprdr_process_cb_format_list_event(instance, (RDP_CB_FORMAT_LIST_EVENT*) event); + break; + + // The Format Data Request PDU is sent by the receipient of the Format List PDU. + // It is used to request the data for one of the formats that was listed in the + // Format List PDU + case RDP_EVENT_TYPE_CB_DATA_REQUEST: + cliprdr_process_cb_data_request_event(instance); + break; + + // The Format Data Response PDU is sent as a reply to the Format Data Request PDU. + // It is used to indicate whether processing of the Format Data Request PDU + // was successful. If the processing was successful, the Format Data Response PDU + // includes the contents of the requested clipboard data + case RDP_EVENT_TYPE_CB_DATA_RESPONSE: + cliprdr_process_cb_data_response_event(instance, (RDP_CB_DATA_RESPONSE_EVENT*) event); + break; + + default: + printf("process_cliprdr_event: unknown event type %d\n", event->event_type); + break; + } + + freerdp_event_free(event); + } } -void cliprdr_send_supported_format_list(freerdp *inst) +void cliprdr_send_supported_format_list(freerdp* instance) { - RDP_CB_FORMAT_LIST_EVENT* event; - - event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, - RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); - - event->formats = (uint32 *) malloc(sizeof(uint32) * 1); - event->num_formats = 1; - event->formats[0] = CB_FORMAT_UNICODETEXT; - freerdp_channels_send_event(inst->context->channels, (RDP_EVENT*) event); + RDP_CB_FORMAT_LIST_EVENT* event; + + event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); + + event->formats = (UINT32*) malloc(sizeof(UINT32) * 1); + event->num_formats = 1; + event->formats[0] = CB_FORMAT_UNICODETEXT; + + freerdp_channels_send_event(instance->context->channels, (RDP_EVENT*) event); } /**************************************************************************************** @@ -1882,162 +1810,167 @@ void cliprdr_send_supported_format_list(freerdp *inst) * RemoteApp (RAIL) related stuff goes here * * * * * - ****************************************************************************************/ + ****************************************************************************************/ -void mac_process_rail_event(freerdp *inst, RDP_EVENT *event) +void mac_process_rail_event(freerdp* instance, RDP_EVENT* event) { - switch (event->event_type) - { - case RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS: - mac_process_rail_get_sysparams_event(inst->context->channels, event); - break; - - case RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS: - mac_process_rail_exec_result_event(inst->context->channels, event); - break; - - case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM: - mac_process_rail_server_sysparam_event(inst->context->channels, event); - break; - - case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO: - mac_process_rail_server_minmaxinfo_event(inst->context->channels, event); - break; - - case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE: - mac_process_rail_server_localmovesize_event(inst, event); - break; - - case RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP: - GOT_HERE; - //xf_process_rail_appid_resp_event(xfi, channels, event); - break; - - case RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO: - GOT_HERE; - //xf_process_rail_langbarinfo_event(xfi, channels, event); - break; - } + switch (event->event_type) + { + case RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS: + mac_process_rail_get_sysparams_event(instance->context->channels, event); + break; + + case RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS: + mac_process_rail_exec_result_event(instance->context->channels, event); + break; + + case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM: + mac_process_rail_server_sysparam_event(instance->context->channels, event); + break; + + case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO: + mac_process_rail_server_minmaxinfo_event(instance->context->channels, event); + break; + + case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE: + mac_process_rail_server_localmovesize_event(instance, event); + break; + + case RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP: + //xf_process_rail_appid_resp_event(xfi, channels, event); + break; + + case RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO: + //xf_process_rail_langbarinfo_event(xfi, channels, event); + break; + } } -void mac_rail_CreateWindow(rdpRail *rail, rdpWindow *window) +void mac_rail_CreateWindow(rdpRail* rail, rdpWindow* window) { - BOOL centerWindow = NO; - BOOL moveWindow = NO; - BOOL displayAsModal = NO; - NSMutableArray * ma = g_mrdpview->windows; - - // make sure window fits resolution - if (window->windowWidth > g_mrdpview->width) - window->windowWidth = g_mrdpview->width; - - if (window->windowHeight > g_mrdpview->height) - window->windowHeight = g_mrdpview->height; - - // center main window, which is the first to be created - if ([ma count] == 0) { - centerWindow = YES; - moveWindow = YES; - } - - if ((window->extendedStyle & WS_EX_TOPMOST) || (window->extendedStyle & WS_EX_TOOLWINDOW)) { - [g_mrdpview->currentWindow view]->skipMoveWindowOnce = TRUE; - moveWindow = YES; - } - else if (window->style & WS_POPUP) { - centerWindow = YES; - moveWindow = YES; - } - else { - } - - // create NSWindow - NSRect winFrame = NSMakeRect(window->windowOffsetX, window->windowOffsetY, - window->windowWidth, window->windowHeight); - if (centerWindow) - apple_center_window(&winFrame); - - MRDPRailWindow * newWindow = [[MRDPRailWindow alloc] initWithContentRect:winFrame - styleMask:NSTitledWindowMask | NSResizableWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - - // this does not work if specified during window creation in above code - [newWindow setStyleMask:NSBorderlessWindowMask]; - - if (moveWindow) { - // let RDP server know that window has moved - RAIL_WINDOW_MOVE_ORDER windowMove; - apple_to_windowMove(&winFrame, &windowMove); - windowMove.windowId = window->windowId; - mac_send_rail_client_event(g_mrdpview->rdp_instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); - } - - // create MRDPRailView and add to above window - NSRect viewFrame = NSMakeRect(window->clientOffsetX, window->clientOffsetY, - window->clientAreaWidth, window->clientAreaHeight); - - MRDPRailView * newView = [[MRDPRailView alloc] initWithFrame:viewFrame]; - [newView setRdpInstance:g_mrdpview->rdp_instance width:g_mrdpview->width andHeight:g_mrdpview->height windowID: window->windowId]; - [newWindow setContentView:newView]; - - // save new window - MRDPWindow * mrdpWindow = [[MRDPWindow alloc] init]; - [mrdpWindow setWindowID:window->windowId]; - [mrdpWindow setWindow:newWindow]; - [mrdpWindow setView:newView]; - - // add to list of windows - [ma addObject:mrdpWindow]; - - // make new window current - g_mrdpview->currentWindow = mrdpWindow; - - if (displayAsModal) { - // display as modal window - NSModalSession session = [NSApp beginModalSessionForWindow:newWindow]; - while (1) - { - if ([NSApp runModalSession:session] != NSRunContinuesResponse) - break; - } - [NSApp endModalSession:session]; - } - else { - [newWindow makeKeyAndOrderFront:NSApp]; - [[g_mrdpview window] resignFirstResponder]; - [g_mrdpview resignFirstResponder]; - [[g_mrdpview window] setNextResponder:newWindow]; - } - - return; + BOOL centerWindow = NO; + BOOL moveWindow = NO; + BOOL displayAsModal = NO; + NSMutableArray * ma = g_mrdpview->windows; + + // make sure window fits resolution + if (window->windowWidth > g_mrdpview->width) + window->windowWidth = g_mrdpview->width; + + if (window->windowHeight > g_mrdpview->height) + window->windowHeight = g_mrdpview->height; + + // center main window, which is the first to be created + if ([ma count] == 0) + { + centerWindow = YES; + moveWindow = YES; + } + + if ((window->extendedStyle & WS_EX_TOPMOST) || (window->extendedStyle & WS_EX_TOOLWINDOW)) + { + [g_mrdpview->currentWindow view]->skipMoveWindowOnce = TRUE; + moveWindow = YES; + } + else if (window->style & WS_POPUP) + { + centerWindow = YES; + moveWindow = YES; + } + else + { + + } + + // create NSWindow + NSRect winFrame = NSMakeRect(window->windowOffsetX, window->windowOffsetY, + window->windowWidth, window->windowHeight); + if (centerWindow) + apple_center_window(&winFrame); + + MRDPRailWindow * newWindow = [[MRDPRailWindow alloc] initWithContentRect:winFrame + styleMask:NSTitledWindowMask | NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + + // this does not work if specified during window creation in above code + [newWindow setStyleMask:NSBorderlessWindowMask]; + + if (moveWindow) { + // let RDP server know that window has moved + RAIL_WINDOW_MOVE_ORDER windowMove; + apple_to_windowMove(&winFrame, &windowMove); + windowMove.windowId = window->windowId; + mac_send_rail_client_event(g_mrdpview->rdp_instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); + } + + // create MRDPRailView and add to above window + NSRect viewFrame = NSMakeRect(window->clientOffsetX, window->clientOffsetY, + window->clientAreaWidth, window->clientAreaHeight); + + MRDPRailView * newView = [[MRDPRailView alloc] initWithFrame:viewFrame]; + [newView setRdpInstance:g_mrdpview->rdp_instance width:g_mrdpview->width andHeight:g_mrdpview->height windowID: window->windowId]; + [newWindow setContentView:newView]; + + // save new window + MRDPWindow * mrdpWindow = [[MRDPWindow alloc] init]; + [mrdpWindow setWindowID:window->windowId]; + [mrdpWindow setWindow:newWindow]; + [mrdpWindow setView:newView]; + + // add to list of windows + [ma addObject:mrdpWindow]; + + // make new window current + g_mrdpview->currentWindow = mrdpWindow; + + if (displayAsModal) + { + // display as modal window + NSModalSession session = [NSApp beginModalSessionForWindow:newWindow]; + while (1) + { + if ([NSApp runModalSession:session] != NSRunContinuesResponse) + break; + } + [NSApp endModalSession:session]; + } + else { + [newWindow makeKeyAndOrderFront:NSApp]; + [[g_mrdpview window] resignFirstResponder]; + [g_mrdpview resignFirstResponder]; + [[g_mrdpview window] setNextResponder:newWindow]; + } + + return; } -void mac_rail_MoveWindow(rdpRail *rail, rdpWindow *window) +void mac_rail_MoveWindow(rdpRail* rail, rdpWindow* window) { - if (g_mrdpview->currentWindow) { - rail_MoveWindow(rail, window); - return; - } + if (g_mrdpview->currentWindow) + { + rail_MoveWindow(rail, window); + return; + } } -void mac_rail_ShowWindow(rdpRail *rail, rdpWindow *window, uint8 state) +void mac_rail_ShowWindow(rdpRail* rail, rdpWindow* window, BYTE state) { } -void mac_rail_SetWindowText(rdpRail *rail, rdpWindow *window) +void mac_rail_SetWindowText(rdpRail* rail, rdpWindow* window) { } -void mac_rail_SetWindowIcon(rdpRail *rail, rdpWindow *window, rdpIcon *icon) +void mac_rail_SetWindowIcon(rdpRail* rail, rdpWindow* window, rdpIcon* icon) { } -void mac_rail_SetWindowRects(rdpRail *rail, rdpWindow *window) +void mac_rail_SetWindowRects(rdpRail* rail, rdpWindow* window) { } -void mac_rail_SetWindowVisibilityRects(rdpRail *rail, rdpWindow *window) +void mac_rail_SetWindowVisibilityRects(rdpRail* rail, rdpWindow* window) { } @@ -2045,46 +1978,49 @@ void mac_rail_SetWindowVisibilityRects(rdpRail *rail, rdpWindow *window) * destroy window created in mac_rail_CreateWindow() ***********************************************************************/ -void mac_rail_DestroyWindow(rdpRail *rail, rdpWindow *window) +void mac_rail_DestroyWindow(rdpRail* rail, rdpWindow* window) { - int count = 0; - - for (MRDPWindow * win in g_mrdpview->windows) - { - if ([win windowID] == window->windowId) { - //[[win window] close]; - [win setView:nil]; - [win setWindow:nil]; - [g_mrdpview->windows removeObject:win]; - count = [g_mrdpview->windows count]; - if (count) { - g_mrdpview->currentWindow = [g_mrdpview->windows objectAtIndex:count - 1]; - //[[g_mrdpview window] makeKeyAndOrderFront:[g_mrdpview->currentWindow window]]; - [[g_mrdpview->currentWindow window] makeKeyAndOrderFront:NSApp]; - } - else { - g_mrdpview->currentWindow = nil; - // RAIL_TODO [[g_mrdpview window] makeKeyAndOrderFront:[g_mrdpview window]]; - [NSApp terminate:nil]; - } - return; - } - } + int count = 0; + + for (MRDPWindow * win in g_mrdpview->windows) + { + if ([win windowID] == window->windowId) + { + //[[win window] close]; + [win setView:nil]; + [win setWindow:nil]; + [g_mrdpview->windows removeObject:win]; + count = [g_mrdpview->windows count]; + + if (count) + { + g_mrdpview->currentWindow = [g_mrdpview->windows objectAtIndex:count - 1]; + //[[g_mrdpview window] makeKeyAndOrderFront:[g_mrdpview->currentWindow window]]; + [[g_mrdpview->currentWindow window] makeKeyAndOrderFront:NSApp]; + } + else + { + g_mrdpview->currentWindow = nil; + // RAIL_TODO [[g_mrdpview window] makeKeyAndOrderFront:[g_mrdpview window]]; + [NSApp terminate:nil]; + } + + return; + } + } } -void mac_rail_register_callbacks(freerdp *inst, rdpRail *rail) -{ - GOT_HERE; - - rail->extra = (void *) inst; - rail->rail_CreateWindow = mac_rail_CreateWindow; - rail->rail_MoveWindow = mac_rail_MoveWindow; - rail->rail_ShowWindow = mac_rail_ShowWindow; - rail->rail_SetWindowText = mac_rail_SetWindowText; - rail->rail_SetWindowIcon = mac_rail_SetWindowIcon; - rail->rail_SetWindowRects = mac_rail_SetWindowRects; - rail->rail_SetWindowVisibilityRects = mac_rail_SetWindowVisibilityRects; - rail->rail_DestroyWindow = mac_rail_DestroyWindow; +void mac_rail_register_callbacks(freerdp* instance, rdpRail* rail) +{ + rail->extra = (void*) instance; + rail->rail_CreateWindow = mac_rail_CreateWindow; + rail->rail_MoveWindow = mac_rail_MoveWindow; + rail->rail_ShowWindow = mac_rail_ShowWindow; + rail->rail_SetWindowText = mac_rail_SetWindowText; + rail->rail_SetWindowIcon = mac_rail_SetWindowIcon; + rail->rail_SetWindowRects = mac_rail_SetWindowRects; + rail->rail_SetWindowVisibilityRects = mac_rail_SetWindowVisibilityRects; + rail->rail_DestroyWindow = mac_rail_DestroyWindow; } /** ********************************************************************* @@ -2092,40 +2028,38 @@ void mac_rail_register_callbacks(freerdp *inst, rdpRail *rail) * by the system taskbar or by application desktop toolbars ************************************************************************/ -void mac_process_rail_get_sysparams_event(rdpChannels *channels, RDP_EVENT *event) +void mac_process_rail_get_sysparams_event(rdpChannels* channels, RDP_EVENT* event) { - RAIL_SYSPARAM_ORDER * sysparam; - sysparam = (RAIL_SYSPARAM_ORDER *) event->user_data; - - sysparam->workArea.left = 0; - sysparam->workArea.top = 22; - sysparam->workArea.right = g_mrdpview->width; - sysparam->workArea.bottom = g_mrdpview->height - 22; - - sysparam->taskbarPos.left = 0; - sysparam->taskbarPos.top = 0; - sysparam->taskbarPos.right = 0; - sysparam->taskbarPos.bottom = 0; - - sysparam->dragFullWindows = FALSE; - - mac_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS, sysparam); + RAIL_SYSPARAM_ORDER * sysparam; + sysparam = (RAIL_SYSPARAM_ORDER*) event->user_data; + + sysparam->workArea.left = 0; + sysparam->workArea.top = 22; + sysparam->workArea.right = g_mrdpview->width; + sysparam->workArea.bottom = g_mrdpview->height - 22; + + sysparam->taskbarPos.left = 0; + sysparam->taskbarPos.top = 0; + sysparam->taskbarPos.right = 0; + sysparam->taskbarPos.bottom = 0; + + sysparam->dragFullWindows = FALSE; + + mac_send_rail_client_event(channels, RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS, sysparam); } void mac_process_rail_server_sysparam_event(rdpChannels* channels, RDP_EVENT* event) { - RAIL_SYSPARAM_ORDER* sysparam = (RAIL_SYSPARAM_ORDER*) event->user_data; - - GOT_HERE; - - switch (sysparam->param) - { - case SPI_SET_SCREEN_SAVE_ACTIVE: - break; - - case SPI_SET_SCREEN_SAVE_SECURE: - break; - } + RAIL_SYSPARAM_ORDER* sysparam = (RAIL_SYSPARAM_ORDER*) event->user_data; + + switch (sysparam->param) + { + case SPI_SET_SCREEN_SAVE_ACTIVE: + break; + + case SPI_SET_SCREEN_SAVE_SECURE: + break; + } } /** ********************************************************************* @@ -2134,21 +2068,21 @@ void mac_process_rail_server_sysparam_event(rdpChannels* channels, RDP_EVENT* ev void mac_process_rail_exec_result_event(rdpChannels* channels, RDP_EVENT* event) { - RAIL_EXEC_RESULT_ORDER* exec_result; - - GOT_HERE; - - exec_result = (RAIL_EXEC_RESULT_ORDER*) event->user_data; - - if (exec_result->execResult != RAIL_EXEC_S_OK) { - printf("RAIL exec error: execResult=%s NtError=0x%X\n", - error_code_names[exec_result->execResult], exec_result->rawResult); - g_mrdpview->is_connected = FALSE; - [g_mrdpview rdpRemoteAppError]; - } - else { - mac_rail_enable_remoteapp_mode(); - } + RAIL_EXEC_RESULT_ORDER* exec_result; + + exec_result = (RAIL_EXEC_RESULT_ORDER*) event->user_data; + + if (exec_result->execResult != RAIL_EXEC_S_OK) + { + printf("RAIL exec error: execResult=%s NtError=0x%X\n", + error_code_names[exec_result->execResult], exec_result->rawResult); + g_mrdpview->is_connected = FALSE; + [g_mrdpview rdpRemoteAppError]; + } + else + { + mac_rail_enable_remoteapp_mode(); + } } /** ********************************************************************* @@ -2159,12 +2093,11 @@ void mac_process_rail_exec_result_event(rdpChannels* channels, RDP_EVENT* event) void mac_process_rail_server_minmaxinfo_event(rdpChannels* channels, RDP_EVENT* event) { - RAIL_MINMAXINFO_ORDER * minmax = (RAIL_MINMAXINFO_ORDER*) event->user_data; - #if 0 - printf("minmax_info: maxPosX=%d maxPosY=%d maxWidth=%d maxHeight=%d minTrackWidth=%d minTrackHeight=%d maxTrackWidth=%d maxTrackHeight=%d\n", - minmax->maxPosX, minmax->maxPosY, minmax->maxWidth, minmax->maxHeight, - minmax->minTrackWidth, minmax->minTrackHeight, minmax->maxTrackWidth, minmax->maxTrackHeight); + RAIL_MINMAXINFO_ORDER * minmax = (RAIL_MINMAXINFO_ORDER*) event->user_data; + printf("minmax_info: maxPosX=%d maxPosY=%d maxWidth=%d maxHeight=%d minTrackWidth=%d minTrackHeight=%d maxTrackWidth=%d maxTrackHeight=%d\n", + minmax->maxPosX, minmax->maxPosY, minmax->maxWidth, minmax->maxHeight, + minmax->minTrackWidth, minmax->minTrackHeight, minmax->maxTrackWidth, minmax->maxTrackHeight); #endif } @@ -2174,113 +2107,108 @@ void mac_process_rail_server_minmaxinfo_event(rdpChannels* channels, RDP_EVENT* * corresponding local window ************************************************************************/ -void mac_process_rail_server_localmovesize_event(freerdp *inst, RDP_EVENT *event) +void mac_process_rail_server_localmovesize_event(freerdp* instance, RDP_EVENT *event) { - RAIL_LOCALMOVESIZE_ORDER * moveSize = (RAIL_LOCALMOVESIZE_ORDER *) event->user_data; - RAIL_WINDOW_MOVE_ORDER windowMove; - - switch (moveSize->moveSizeType) { - case RAIL_WMSZ_LEFT: - printf("!!!! RAIL_WMSZ_LEFT\n"); - break; - - case RAIL_WMSZ_RIGHT: - printf("!!!! RAIL_WMSZ_RIGHT\n"); - break; - - case RAIL_WMSZ_TOP: - printf("!!!! RAIL_WMSZ_TOP\n"); - break; - - case RAIL_WMSZ_TOPLEFT: - printf("!!!! RAIL_WMSZ_TOPLEFT\n"); - break; - - case RAIL_WMSZ_TOPRIGHT: - printf("!!!! RAIL_WMSZ_TOPRIGHT\n"); - break; - - case RAIL_WMSZ_BOTTOM: - printf("!!!! RAIL_WMSZ_BOTTOM\n"); - break; - - case RAIL_WMSZ_BOTTOMLEFT: - printf("!!!! RAIL_WMSZ_BOTTOMLEFT\n"); - break; - - case RAIL_WMSZ_BOTTOMRIGHT: - printf("!!!! RAIL_WMSZ_BOTTOMRIGHT\n"); - break; - - case RAIL_WMSZ_MOVE: - if (moveSize->isMoveSizeStart) { - // local window move in progress - [g_mrdpview->currentWindow view]->isMoveSizeInProgress = YES; - [g_mrdpview->currentWindow view]->saveInitialDragLoc = YES; - - return; - } - - // local move has completed - [g_mrdpview->currentWindow view]->isMoveSizeInProgress = NO; - [g_mrdpview->currentWindow view]->saveInitialDragLoc = NO; - - //NSRect rect = [[g_mrdpview->currentWindow view] frame]; - NSRect rect = [[[g_mrdpview->currentWindow view] window] frame]; - - // let RDP server know where this window is located - mac_send_rail_client_event(inst->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); - - // the event we just sent will cause an extra MoveWindow() to be invoked which we need to ignore - [g_mrdpview->currentWindow view]->skipMoveWindowOnce = YES; - - break; - - case RAIL_WMSZ_KEYMOVE: - printf("!!!! RAIL_WMSZ_KEYMOVE\n"); - break; - - case RAIL_WMSZ_KEYSIZE: - printf("!!!! RAIL_WMSZ_KEYSIZE\n"); - break; - - default: - break; - } - return; + RAIL_LOCALMOVESIZE_ORDER* moveSize = (RAIL_LOCALMOVESIZE_ORDER*) event->user_data; + RAIL_WINDOW_MOVE_ORDER windowMove; + + switch (moveSize->moveSizeType) + { + case RAIL_WMSZ_LEFT: + printf("RAIL_WMSZ_LEFT\n"); + break; + + case RAIL_WMSZ_RIGHT: + printf("RAIL_WMSZ_RIGHT\n"); + break; + + case RAIL_WMSZ_TOP: + printf("RAIL_WMSZ_TOP\n"); + break; + + case RAIL_WMSZ_TOPLEFT: + printf("RAIL_WMSZ_TOPLEFT\n"); + break; + + case RAIL_WMSZ_TOPRIGHT: + printf("RAIL_WMSZ_TOPRIGHT\n"); + break; + + case RAIL_WMSZ_BOTTOM: + printf("RAIL_WMSZ_BOTTOM\n"); + break; + + case RAIL_WMSZ_BOTTOMLEFT: + printf("RAIL_WMSZ_BOTTOMLEFT\n"); + break; + + case RAIL_WMSZ_BOTTOMRIGHT: + printf("RAIL_WMSZ_BOTTOMRIGHT\n"); + break; + + case RAIL_WMSZ_MOVE: + if (moveSize->isMoveSizeStart) + { + // local window move in progress + [g_mrdpview->currentWindow view]->isMoveSizeInProgress = YES; + [g_mrdpview->currentWindow view]->saveInitialDragLoc = YES; + + return; + } + + // local move has completed + [g_mrdpview->currentWindow view]->isMoveSizeInProgress = NO; + [g_mrdpview->currentWindow view]->saveInitialDragLoc = NO; + + // let RDP server know where this window is located + mac_send_rail_client_event(instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); + + // the event we just sent will cause an extra MoveWindow() to be invoked which we need to ignore + [g_mrdpview->currentWindow view]->skipMoveWindowOnce = YES; + + break; + + case RAIL_WMSZ_KEYMOVE: + printf("RAIL_WMSZ_KEYMOVE\n"); + break; + + case RAIL_WMSZ_KEYSIZE: + printf("RAIL_WMSZ_KEYSIZE\n"); + break; + + default: + break; + } + + return; } -void mac_send_rail_client_event(rdpChannels *channels, uint16 event_type, void *param) +void mac_send_rail_client_event(rdpChannels* channels, UINT16 event_type, void* param) { - RDP_EVENT *out_event = NULL; - void *payload = NULL; - - GOT_HERE; - - payload = rail_clone_order(event_type, param); - if (payload != NULL) { - out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, - mac_on_free_rail_client_event, payload); - freerdp_channels_send_event(channels, out_event); - } + void* payload = NULL; + RDP_EVENT* out_event = NULL; + + payload = rail_clone_order(event_type, param); + + if (payload) + { + out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, mac_on_free_rail_client_event, payload); + freerdp_channels_send_event(channels, out_event); + } } void mac_on_free_rail_client_event(RDP_EVENT* event) -{ - GOT_HERE; - - if (event->event_class == RDP_EVENT_CLASS_RAIL) - { - rail_free_cloned_order(event->event_type, event->user_data); - } +{ + if (event->event_class == RDP_EVENT_CLASS_RAIL) + { + rail_free_cloned_order(event->event_type, event->user_data); + } } void mac_rail_enable_remoteapp_mode() -{ - GOT_HERE; - - if (!g_mrdpview->isRemoteApp) - g_mrdpview->isRemoteApp = TRUE; +{ + if (!g_mrdpview->isRemoteApp) + g_mrdpview->isRemoteApp = TRUE; } /** @@ -2288,9 +2216,9 @@ void mac_rail_enable_remoteapp_mode() * convert it to a rect with 0,0 at the top left (windows cords) */ -void apple_to_windows_cords(NSRect * r) +void apple_to_windows_cords(NSRect* r) { - r->origin.y = g_mrdpview->height - (r->origin.y + r->size.height); + r->origin.y = g_mrdpview->height - (r->origin.y + r->size.height); } /** @@ -2298,23 +2226,23 @@ void apple_to_windows_cords(NSRect * r) * convert it to a rect with 0,0 at the bottom left (apple cords) */ -void windows_to_apple_cords(NSRect * r) +void windows_to_apple_cords(NSRect* r) { - r->origin.y = g_mrdpview->height - (r->origin.y + r->size.height); + r->origin.y = g_mrdpview->height - (r->origin.y + r->size.height); } -void apple_center_window(NSRect * r) +void apple_center_window(NSRect* r) { - r->origin.x = (g_mrdpview->width - r->size.width) / 2; - r->origin.y = (g_mrdpview->height - r->size.height) / 2; + r->origin.x = (g_mrdpview->width - r->size.width) / 2; + r->origin.y = (g_mrdpview->height - r->size.height) / 2; } -void apple_to_windowMove(NSRect * r, RAIL_WINDOW_MOVE_ORDER * windowMove) +void apple_to_windowMove(NSRect* r, RAIL_WINDOW_MOVE_ORDER* windowMove) { - windowMove->left = (uint16) r->origin.x; // x-cord of top left corner - windowMove->top = (uint16) g_mrdpview->height - (r->origin.y + r->size.height); // y-cord of top left corner - windowMove->right = (uint16) (windowMove->left + r->size.width); // x-cord of bottom right corner - windowMove->bottom = (uint16) (windowMove->top + r->size.height); // y-cord of bottom right corner + windowMove->left = (UINT16) r->origin.x; // x-cord of top left corner + windowMove->top = (UINT16) g_mrdpview->height - (r->origin.y + r->size.height); // y-cord of top left corner + windowMove->right = (UINT16) (windowMove->left + r->size.width); // x-cord of bottom right corner + windowMove->bottom = (UINT16) (windowMove->top + r->size.height); // y-cord of bottom right corner } @end diff --git a/client/Mac/MRDPWindow.h b/client/Mac/MRDPWindow.h index cef1ab09e..0e7e26b97 100644 --- a/client/Mac/MRDPWindow.h +++ b/client/Mac/MRDPWindow.h @@ -1,3 +1,21 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #import #import "MRDPRailView.h" @@ -8,8 +26,8 @@ } @property (assign) int windowID; -@property (retain) MRDPRailWindow * window; -@property (retain) MRDPRailView * view; +@property (retain) MRDPRailWindow* window; +@property (retain) MRDPRailView* view; @end diff --git a/client/Mac/MRDPWindow.m b/client/Mac/MRDPWindow.m index 77b99728c..e5e5e402f 100644 --- a/client/Mac/MRDPWindow.m +++ b/client/Mac/MRDPWindow.m @@ -1,3 +1,21 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include "MRDPWindow.h" diff --git a/client/Mac/main.m b/client/Mac/main.m index a7ee86852..4cba6cfc1 100644 --- a/client/Mac/main.m +++ b/client/Mac/main.m @@ -1,10 +1,21 @@ -// -// main.m -// MacFreeRDP -// -// Created by Thomas Goddard on 5/8/12. -// Copyright (c) 2012 __MyCompanyName__. All rights reserved. -// +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * MacFreeRDP + * + * Copyright 2012 Thomas Goddard + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #import diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index 3c8f86c85..13ae748b1 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -34,6 +34,7 @@ #include "xf_cliprdr.h" typedef struct clipboard_format_mapping clipboardFormatMapping; + struct clipboard_format_mapping { Atom target_format; @@ -41,6 +42,7 @@ struct clipboard_format_mapping }; typedef struct clipboard_context clipboardContext; + struct clipboard_context { rdpChannels* channels; diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index d93abacc9..dc7aba819 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -1017,21 +1017,21 @@ int xf_receive_channel_data(freerdp* instance, int channelId, BYTE* data, int si return freerdp_channels_data(instance, channelId, data, size, flags, total_size); } -void xf_process_channel_event(rdpChannels* chanman, freerdp* instance) +void xf_process_channel_event(rdpChannels* channels, freerdp* instance) { xfInfo* xfi; RDP_EVENT* event; xfi = ((xfContext*) instance->context)->xfi; - event = freerdp_channels_pop_event(chanman); + event = freerdp_channels_pop_event(channels); if (event) { switch (event->event_class) { case RDP_EVENT_CLASS_RAIL: - xf_process_rail_event(xfi, chanman, event); + xf_process_rail_event(xfi, channels, event); break; case RDP_EVENT_CLASS_TSMF: @@ -1295,6 +1295,7 @@ int xfreerdp_run(freerdp* instance) async_update = settings->AsyncUpdate; async_input = settings->AsyncInput; + async_channels = settings->AsyncChannels; if (async_update) { @@ -1306,8 +1307,6 @@ int xfreerdp_run(freerdp* instance) input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_input_thread, instance, 0, NULL); } - async_channels = FALSE; - if (async_channels) { channels_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_channels_thread, instance, 0, NULL); diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 8ea572320..8233204fb 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -121,6 +121,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "fast-path", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "fast-path input/output" }, { "async-input", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous input" }, { "async-update", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous update" }, + { "async-channels", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "asynchronous channels (unstable)" }, { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "print version" }, { "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "print help" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } @@ -290,7 +291,7 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p printer->Type = RDPDR_DTYP_PRINT; printer->Name = _strdup(params[1]); - if (params[2]) + if (count > 2) printer->DriverName = _strdup(params[2]); freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer); @@ -1490,6 +1491,10 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin { settings->AsyncUpdate = arg->Value ? TRUE : FALSE; } + CommandLineSwitchCase(arg, "async-channels") + { + settings->AsyncChannels = arg->Value ? TRUE : FALSE; + } CommandLineSwitchDefault(arg) { diff --git a/client/iOS/Controllers/BookmarkListController.m b/client/iOS/Controllers/BookmarkListController.m index 27a508134..301bd5f5d 100644 --- a/client/iOS/Controllers/BookmarkListController.m +++ b/client/iOS/Controllers/BookmarkListController.m @@ -13,6 +13,7 @@ #import "RDPSessionViewController.h" #import "Toast+UIView.h" #import "Reachability.h" +#import "GlobalDefaults.h" #define SECTION_SESSIONS 0 #define SECTION_BOOKMARKS 1 @@ -803,7 +804,10 @@ _manual_bookmarks = [self arrayFromDataStoreURL:[self manualBookmarksDataStoreURL]]; if(_manual_bookmarks == nil) + { _manual_bookmarks = [[NSMutableArray alloc] init]; + [_manual_bookmarks addObject:[[[GlobalDefaults sharedGlobalDefaults] newTestServerBookmark] autorelease]]; + } } - (void)readConnectionHistoryFromDataStore diff --git a/client/iOS/Defaults.plist b/client/iOS/Defaults.plist index 88e2113b1..a60e3be19 100644 --- a/client/iOS/Defaults.plist +++ b/client/iOS/Defaults.plist @@ -9,11 +9,11 @@ port 3389 screen_resolution_type - 0 + 1 width - 1024 + 0 height - 768 + 0 colors 16 perf_font_smoothing diff --git a/client/iOS/Models/GlobalDefaults.h b/client/iOS/Models/GlobalDefaults.h index ecbee2c38..d522991bd 100644 --- a/client/iOS/Models/GlobalDefaults.h +++ b/client/iOS/Models/GlobalDefaults.h @@ -24,5 +24,6 @@ - (ConnectionParams*)newParams; - (ComputerBookmark*)newBookmark; +- (ComputerBookmark*)newTestServerBookmark; @end diff --git a/client/iOS/Models/GlobalDefaults.m b/client/iOS/Models/GlobalDefaults.m index 1a0619a22..2b2ab293f 100644 --- a/client/iOS/Models/GlobalDefaults.m +++ b/client/iOS/Models/GlobalDefaults.m @@ -68,4 +68,17 @@ return param_copy; } +- (ComputerBookmark*)newTestServerBookmark +{ + ComputerBookmark* bm = [self newBookmark]; + [bm setLabel:@"Test Server"]; + [[bm params] setValue:@"testservice.ifreerdp.com" forKey:@"hostname"]; + [[bm params] setInt:0 forKey:@"screen_resolution_type"]; + [[bm params] setInt:1024 forKey:@"width"]; + [[bm params] setInt:768 forKey:@"height"]; + [[bm params] setInt:32 forKey:@"colors"]; + [[bm params] setBool:YES forKey:@"perf_remotefx"]; + return bm; +} + @end diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake index 0f63c742c..c922d2f78 100644 --- a/cmake/ConfigOptions.cmake +++ b/cmake/ConfigOptions.cmake @@ -17,10 +17,18 @@ else() option(WITH_SSE2 "Enable SSE2 optimization." OFF) endif() -if((TARGET_ARCH MATCHES "ARM") AND (NOT DEFINED WITH_NEON)) - option(WITH_NEON "Enable NEON optimization." ON) -else() - option(WITH_NEON "Enable NEON optimization." OFF) +if(TARGET_ARCH MATCHES "ARM") + if (NOT DEFINED WITH_NEON) + option(WITH_NEON "Enable NEON optimization." ON) + else() + option(WITH_NEON "Enable NEON optimization." OFF) + endif() + if (NOT DEFINED ARM_FP_ABI) + set(ARM_FP_ABI "softfp" CACHE STRING "Floating point ABI to use on arm") + else() + set(ARM_FP_ABI ${ARM_FP_API} CACHE STRING "Floating point ABI to use on arm") + endif() + mark_as_advanced(ARM_FP_ABI) endif() option(WITH_JPEG "Use JPEG decoding." OFF) diff --git a/cmake/FindFeature.cmake b/cmake/FindFeature.cmake index 86362959e..783971b94 100644 --- a/cmake/FindFeature.cmake +++ b/cmake/FindFeature.cmake @@ -32,7 +32,7 @@ macro(find_feature _feature _type _purpose _description) else() set(_feature_default "OFF") message(STATUS "Skipping ${_type_lower} feature ${_feature} for ${_purpose} (${_description})") - message(STATUS " Enable feature ${_feature} using \"-DWITH_${_feature_upper}=OFF\"") + message(STATUS " Enable feature ${_feature} using \"-DWITH_${_feature_upper}=ON\"") endif() else() set(_feature_default "ON") diff --git a/include/freerdp/channels/rdpsnd.h b/include/freerdp/channels/rdpsnd.h index da59c5e07..b2c4eea80 100644 --- a/include/freerdp/channels/rdpsnd.h +++ b/include/freerdp/channels/rdpsnd.h @@ -23,39 +23,164 @@ #include #include -typedef struct rdpsnd_format rdpsndFormat; +#ifdef _WIN32 +#include +#endif -struct rdpsnd_format +struct AUDIO_FORMAT { UINT16 wFormatTag; UINT16 nChannels; UINT32 nSamplesPerSec; + UINT32 nAvgBytesPerSec; UINT16 nBlockAlign; UINT16 wBitsPerSample; UINT16 cbSize; BYTE* data; }; +typedef struct AUDIO_FORMAT AUDIO_FORMAT; -#define SNDC_CLOSE 1 -#define SNDC_WAVE 2 -#define SNDC_SETVOLUME 3 -#define SNDC_SETPITCH 4 -#define SNDC_WAVECONFIRM 5 -#define SNDC_TRAINING 6 -#define SNDC_FORMATS 7 -#define SNDC_CRYPTKEY 8 -#define SNDC_WAVEENCRYPT 9 -#define SNDC_UDPWAVE 10 -#define SNDC_UDPWAVELAST 11 -#define SNDC_QUALITYMODE 12 +#define SNDC_CLOSE 1 +#define SNDC_WAVE 2 +#define SNDC_SETVOLUME 3 +#define SNDC_SETPITCH 4 +#define SNDC_WAVECONFIRM 5 +#define SNDC_TRAINING 6 +#define SNDC_FORMATS 7 +#define SNDC_CRYPTKEY 8 +#define SNDC_WAVEENCRYPT 9 +#define SNDC_UDPWAVE 10 +#define SNDC_UDPWAVELAST 11 +#define SNDC_QUALITYMODE 12 +#define SNDC_WAVE2 13 -#define TSSNDCAPS_ALIVE 1 -#define TSSNDCAPS_VOLUME 2 -#define TSSNDCAPS_PITCH 4 +#define TSSNDCAPS_ALIVE 1 +#define TSSNDCAPS_VOLUME 2 +#define TSSNDCAPS_PITCH 4 -#define DYNAMIC_QUALITY 0x0000 -#define MEDIUM_QUALITY 0x0001 -#define HIGH_QUALITY 0x0002 +#define DYNAMIC_QUALITY 0x0000 +#define MEDIUM_QUALITY 0x0001 +#define HIGH_QUALITY 0x0002 + +/* + * Format Tags: + * http://tools.ietf.org/html/rfc2361 + */ + +#define WAVE_FORMAT_UNKNOWN 0x0000 + +#ifndef WAVE_FORMAT_PCM +#define WAVE_FORMAT_PCM 0x0001 +#endif + +#define WAVE_FORMAT_ADPCM 0x0002 +#define WAVE_FORMAT_IEEE_FLOAT 0x0003 +#define WAVE_FORMAT_VSELP 0x0004 +#define WAVE_FORMAT_IBM_CVSD 0x0005 +#define WAVE_FORMAT_ALAW 0x0006 +#define WAVE_FORMAT_MULAW 0x0007 +#define WAVE_FORMAT_OKI_ADPCM 0x0010 +#define WAVE_FORMAT_DVI_ADPCM 0x0011 +#define WAVE_FORMAT_MEDIASPACE_ADPCM 0x0012 +#define WAVE_FORMAT_SIERRA_ADPCM 0x0013 +#define WAVE_FORMAT_G723_ADPCM 0x0014 +#define WAVE_FORMAT_DIGISTD 0x0015 +#define WAVE_FORMAT_DIGIFIX 0x0016 +#define WAVE_FORMAT_DIALOGIC_OKI_ADPCM 0x0017 +#define WAVE_FORMAT_MEDIAVISION_ADPCM 0x0018 +#define WAVE_FORMAT_CU_CODEC 0x0019 +#define WAVE_FORMAT_YAMAHA_ADPCM 0x0020 +#define WAVE_FORMAT_SONARC 0x0021 +#define WAVE_FORMAT_DSPGROUP_TRUESPEECH 0x0022 +#define WAVE_FORMAT_ECHOSC1 0x0023 +#define WAVE_FORMAT_AUDIOFILE_AF36 0x0024 +#define WAVE_FORMAT_APTX 0x0025 +#define WAVE_FORMAT_AUDIOFILE_AF10 0x0026 +#define WAVE_FORMAT_PROSODY_1612 0x0027 +#define WAVE_FORMAT_LRC 0x0028 +#define WAVE_FORMAT_DOLBY_AC2 0x0030 +#define WAVE_FORMAT_GSM610 0x0031 +#define WAVE_FORMAT_MSNAUDIO 0x0032 +#define WAVE_FORMAT_ANTEX_ADPCME 0x0033 +#define WAVE_FORMAT_CONTROL_RES_VQLPC 0x0034 +#define WAVE_FORMAT_DIGIREAL 0x0035 +#define WAVE_FORMAT_DIGIADPCM 0x0036 +#define WAVE_FORMAT_CONTROL_RES_CR10 0x0037 +#define WAVE_FORMAT_NMS_VBXADPCM 0x0038 +#define WAVE_FORMAT_ROLAND_RDAC 0x0039 +#define WAVE_FORMAT_ECHOSC3 0x003A +#define WAVE_FORMAT_ROCKWELL_ADPCM 0x003B +#define WAVE_FORMAT_ROCKWELL_DIGITALK 0x003C +#define WAVE_FORMAT_XEBEC 0x003D +#define WAVE_FORMAT_G721_ADPCM 0x0040 +#define WAVE_FORMAT_G728_CELP 0x0041 +#define WAVE_FORMAT_MSG723 0x0042 +#define WAVE_FORMAT_MPEG 0x0050 +#define WAVE_FORMAT_RT24 0x0052 +#define WAVE_FORMAT_PAC 0x0053 + +#ifndef WAVE_FORMAT_MPEGLAYER3 +#define WAVE_FORMAT_MPEGLAYER3 0x0055 +#endif + +#define WAVE_FORMAT_LUCENT_G723 0x0059 +#define WAVE_FORMAT_CIRRUS 0x0060 +#define WAVE_FORMAT_ESPCM 0x0061 +#define WAVE_FORMAT_VOXWARE 0x0062 +#define WAVE_FORMAT_CANOPUS_ATRAC 0x0063 +#define WAVE_FORMAT_G726_ADPCM 0x0064 +#define WAVE_FORMAT_G722_ADPCM 0x0065 +#define WAVE_FORMAT_DSAT 0x0066 +#define WAVE_FORMAT_DSAT_DISPLAY 0x0067 +#define WAVE_FORMAT_VOXWARE_BYTE_ALIGNED 0x0069 +#define WAVE_FORMAT_VOXWARE_AC8 0x0070 +#define WAVE_FORMAT_VOXWARE_AC10 0x0071 +#define WAVE_FORMAT_VOXWARE_AC16 0x0072 +#define WAVE_FORMAT_VOXWARE_AC20 0x0073 +#define WAVE_FORMAT_VOXWARE_RT24 0x0074 +#define WAVE_FORMAT_VOXWARE_RT29 0x0075 +#define WAVE_FORMAT_VOXWARE_RT29HW 0x0076 +#define WAVE_FORMAT_VOXWARE_VR12 0x0077 +#define WAVE_FORMAT_VOXWARE_VR18 0x0078 +#define WAVE_FORMAT_VOXWARE_TQ40 0x0079 +#define WAVE_FORMAT_SOFTSOUND 0x0080 +#define WAVE_FORMAT_VOXWARE_TQ60 0x0081 +#define WAVE_FORMAT_MSRT24 0x0082 +#define WAVE_FORMAT_G729A 0x0083 +#define WAVE_FORMAT_MVI_MV12 0x0084 +#define WAVE_FORMAT_DF_G726 0x0085 +#define WAVE_FORMAT_DF_GSM610 0x0086 +#define WAVE_FORMAT_ISIAUDIO 0x0088 +#define WAVE_FORMAT_ONLIVE 0x0089 +#define WAVE_FORMAT_SBC24 0x0091 +#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 +#define WAVE_FORMAT_ZYXEL_ADPCM 0x0097 +#define WAVE_FORMAT_PHILIPS_LPCBB 0x0098 +#define WAVE_FORMAT_PACKED 0x0099 +#define WAVE_FORMAT_RHETOREX_ADPCM 0x0100 +#define WAVE_FORMAT_IRAT 0x0101 +#define WAVE_FORMAT_VIVO_G723 0x0111 +#define WAVE_FORMAT_VIVO_SIREN 0x0112 +#define WAVE_FORMAT_DIGITAL_G723 0x0123 +#define WAVE_FORMAT_WMAUDIO2 0x0161 +#define WAVE_FORMAT_WMAUDIO3 0x0162 +#define WAVE_FORMAT_WMAUDIO_LOSSLESS 0x0163 +#define WAVE_FORMAT_CREATIVE_ADPCM 0x0200 +#define WAVE_FORMAT_CREATIVE_FASTSPEECH8 0x0202 +#define WAVE_FORMAT_CREATIVE_FASTSPEECH10 0x0203 +#define WAVE_FORMAT_QUARTERDECK 0x0220 +#define WAVE_FORMAT_FM_TOWNS_SND 0x0300 +#define WAVE_FORMAT_BTV_DIGITAL 0x0400 +#define WAVE_FORMAT_VME_VMPCM 0x0680 +#define WAVE_FORMAT_OLIGSM 0x1000 +#define WAVE_FORMAT_OLIADPCM 0x1001 +#define WAVE_FORMAT_OLICELP 0x1002 +#define WAVE_FORMAT_OLISBC 0x1003 +#define WAVE_FORMAT_OLIOPR 0x1004 +#define WAVE_FORMAT_LH_CODEC 0x1100 +#define WAVE_FORMAT_NORRIS 0x1400 +#define WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS 0x1500 +#define WAVE_FORMAT_DVM 0x2000 #endif /* FREERDP_CHANNEL_RDPSND_H */ diff --git a/include/freerdp/utils/dsp.h b/include/freerdp/codec/dsp.h similarity index 95% rename from include/freerdp/utils/dsp.h rename to include/freerdp/codec/dsp.h index e2e209059..301eb2651 100644 --- a/include/freerdp/utils/dsp.h +++ b/include/freerdp/codec/dsp.h @@ -17,8 +17,8 @@ * limitations under the License. */ -#ifndef FREERDP_UTILS_DSP_H -#define FREERDP_UTILS_DSP_H +#ifndef FREERDP_CODEC_DSP_H +#define FREERDP_CODEC_DSP_H #include @@ -40,6 +40,7 @@ union _ADPCM typedef union _ADPCM ADPCM; typedef struct _FREERDP_DSP_CONTEXT FREERDP_DSP_CONTEXT; + struct _FREERDP_DSP_CONTEXT { BYTE* resampled_buffer; @@ -81,5 +82,5 @@ FREERDP_API void freerdp_dsp_context_free(FREERDP_DSP_CONTEXT* context); } #endif -#endif /* FREERDP_UTILS_DSP_H */ +#endif /* FREERDP_CODEC_DSP_H */ diff --git a/include/freerdp/server/audin.h b/include/freerdp/server/audin.h index 42bf075b1..9be2a4d67 100644 --- a/include/freerdp/server/audin.h +++ b/include/freerdp/server/audin.h @@ -41,17 +41,17 @@ struct _audin_server_context void* data; /* Server supported formats. Set by server. */ - const rdpsndFormat* server_formats; + const AUDIO_FORMAT* server_formats; int num_server_formats; /* Server destination PCM audio format. Set by server. */ - rdpsndFormat dst_format; + AUDIO_FORMAT dst_format; /* Server preferred frames per packet. */ int frames_per_packet; /* Client supported formats. */ - rdpsndFormat* client_formats; + AUDIO_FORMAT* client_formats; int num_client_formats; int selected_client_format; diff --git a/include/freerdp/server/rdpsnd.h b/include/freerdp/server/rdpsnd.h index c0973cf42..6349874fe 100644 --- a/include/freerdp/server/rdpsnd.h +++ b/include/freerdp/server/rdpsnd.h @@ -41,14 +41,14 @@ struct _rdpsnd_server_context void* data; /* Server supported formats. Set by server. */ - const rdpsndFormat* server_formats; + const AUDIO_FORMAT* server_formats; int num_server_formats; /* Server source PCM audio format. Set by server. */ - rdpsndFormat src_format; + AUDIO_FORMAT src_format; /* Client supported formats. */ - rdpsndFormat* client_formats; + AUDIO_FORMAT* client_formats; int num_client_formats; int selected_client_format; diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index f46d13b88..39c9bcb5f 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -680,7 +680,8 @@ struct rdp_settings ALIGN64 UINT64 ParentWindowId; /* 1543 */ ALIGN64 BOOL AsyncInput; /* 1544 */ ALIGN64 BOOL AsyncUpdate; /* 1545 */ - UINT64 padding1600[1600 - 1546]; /* 1546 */ + ALIGN64 BOOL AsyncChannels; /* 1546 */ + UINT64 padding1600[1600 - 1547]; /* 1547 */ /* Miscellaneous */ ALIGN64 BOOL SoftwareGdi; /* 1601 */ diff --git a/include/freerdp/utils/svc_plugin.h b/include/freerdp/utils/svc_plugin.h index 81060a7f3..ca792f8e7 100644 --- a/include/freerdp/utils/svc_plugin.h +++ b/include/freerdp/utils/svc_plugin.h @@ -27,11 +27,15 @@ #include #include -#include -#include -#include +#include +#include +#include +#include + +#include +#include +#include -typedef struct rdp_svc_plugin_private rdpSvcPluginPrivate; typedef struct rdp_svc_plugin rdpSvcPlugin; struct rdp_svc_plugin @@ -39,15 +43,16 @@ struct rdp_svc_plugin CHANNEL_ENTRY_POINTS_EX channel_entry_points; CHANNEL_DEF channel_def; - int interval_ms; - void (*connect_callback)(rdpSvcPlugin* plugin); void (*receive_callback)(rdpSvcPlugin* plugin, STREAM* data_in); void (*event_callback)(rdpSvcPlugin* plugin, RDP_EVENT* event); - void (*interval_callback)(rdpSvcPlugin* plugin); void (*terminate_callback)(rdpSvcPlugin* plugin); - rdpSvcPluginPrivate* priv; + HANDLE thread; + STREAM* data_in; + void* init_handle; + UINT32 open_handle; + wMessagePipe* MsgPipe; }; #ifdef __cplusplus diff --git a/keymaps/macosx b/keymaps/macosx index 8363f81cc..4f55dd72e 100644 --- a/keymaps/macosx +++ b/keymaps/macosx @@ -57,6 +57,8 @@ keyboard "macosx" VK_OEM_PERIOD <55> VK_OEM_2 <52> VK_SPACE <57> + VK_LWIN <63> + VK_RWIN <71> VK_LCONTROL <67> VK_LMENU <66> VK_LSHIFT <64> diff --git a/libfreerdp/codec/CMakeLists.txt b/libfreerdp/codec/CMakeLists.txt index 3e7717977..f69801897 100644 --- a/libfreerdp/codec/CMakeLists.txt +++ b/libfreerdp/codec/CMakeLists.txt @@ -19,6 +19,7 @@ set(MODULE_NAME "freerdp-codec") set(MODULE_PREFIX "FREERDP_CODEC") set(${MODULE_PREFIX}_SRCS + dsp.c bitmap.c color.c rfx_bitstream.h @@ -71,12 +72,12 @@ if(WITH_NEON) if(ANDROID) set(ANDROID_CPU_FEATURES_PATH "${ANDROID_NDK}/sources/android/cpufeatures") include_directories(${ANDROID_CPU_FEATURES_PATH}) - set(${MODULE_PREFIX}_NEON_SRCS ${${MODULE_PREFIX}_NEON_SRCS} + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${ANDROID_CPU_FEATURES_PATH}/cpu-features.c ${ANDROID_CPU_FEATURES_PATH}/cpu-features.h) endif() set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${${MODULE_PREFIX}_NEON_SRCS}) - set_source_files_properties(${${MODULE_PREFIX}_NEON_SRCS} PROPERTIES COMPILE_FLAGS "-mfpu=neon -mfloat-abi=softfp -Wno-unused-variable") + set_source_files_properties(${${MODULE_PREFIX}_NEON_SRCS} PROPERTIES COMPILE_FLAGS "-mfpu=neon -mfloat-abi=${ARM_FP_ABI} -Wno-unused-variable") endif() if(WITH_JPEG) diff --git a/libfreerdp/utils/dsp.c b/libfreerdp/codec/dsp.c similarity index 81% rename from libfreerdp/utils/dsp.c rename to libfreerdp/codec/dsp.c index 881d969a8..868af3e71 100644 --- a/libfreerdp/utils/dsp.c +++ b/libfreerdp/codec/dsp.c @@ -28,7 +28,13 @@ #include #include -#include + +#include + +/** + * Microsoft Multimedia Standards Update + * http://download.microsoft.com/download/9/8/6/9863C72A-A3AA-4DDB-B1BA-CA8D17EFD2D4/RIFFNEW.pdf + */ static void freerdp_dsp_resample(FREERDP_DSP_CONTEXT* context, const BYTE* src, int bytes_per_sample, @@ -56,12 +62,16 @@ static void freerdp_dsp_resample(FREERDP_DSP_CONTEXT* context, dst = context->resampled_buffer; p = dst; + for (i = 0; i < rframes; i++) { n1 = i * srate / rrate; + if (n1 >= sframes) n1 = sframes - 1; + n2 = (n1 * rrate == i * srate || n1 == sframes - 1 ? n1 : n1 + 1); + for (j = 0; j < rbytes; j++) { /* Nearest Interpolation, probably the easiest, but works */ @@ -108,7 +118,9 @@ static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* adpcm, INT32 d; ss = ima_step_size_table[adpcm->ima.last_step[channel]]; + d = (ss >> 3); + if (sample & 1) d += (ss >> 2); if (sample & 2) @@ -117,6 +129,7 @@ static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* adpcm, d += ss; if (sample & 8) d = -d; + d += adpcm->ima.last_sample[channel]; if (d < -32768) @@ -127,6 +140,7 @@ static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* adpcm, adpcm->ima.last_sample[channel] = (INT16) d; adpcm->ima.last_step[channel] += ima_step_index_table[sample]; + if (adpcm->ima.last_step[channel] < 0) adpcm->ima.last_step[channel] = 0; else if (adpcm->ima.last_step[channel] > 88) @@ -146,12 +160,15 @@ static void freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* context, int i; out_size = size * 4; + if (out_size > context->adpcm_maxlength) { context->adpcm_maxlength = out_size + 1024; context->adpcm_buffer = realloc(context->adpcm_buffer, context->adpcm_maxlength); } + dst = context->adpcm_buffer; + while (size > 0) { if (size % block_size == 0) @@ -161,6 +178,7 @@ static void freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* context, src += 4; size -= 4; out_size -= 16; + if (channels > 1) { context->adpcm.ima.last_sample[1] = (INT16) (((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8)); @@ -177,27 +195,32 @@ static void freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* context, { channel = (i < 4 ? 0 : 1); sample = ((*src) & 0x0f); + decoded = dsp_decode_ima_adpcm_sample(&context->adpcm, channel, sample); - dst[((i & 3) << 3) + (channel << 1)] = (decoded & 0xff); + dst[((i & 3) << 3) + (channel << 1)] = (decoded & 0xFF); dst[((i & 3) << 3) + (channel << 1) + 1] = (decoded >> 8); sample = ((*src) >> 4); + decoded = dsp_decode_ima_adpcm_sample(&context->adpcm, channel, sample); - dst[((i & 3) << 3) + (channel << 1) + 4] = (decoded & 0xff); + dst[((i & 3) << 3) + (channel << 1) + 4] = (decoded & 0xFF); dst[((i & 3) << 3) + (channel << 1) + 5] = (decoded >> 8); src++; } + dst += 32; size -= 8; } else { sample = ((*src) & 0x0f); + decoded = dsp_decode_ima_adpcm_sample(&context->adpcm, 0, sample); - *dst++ = (decoded & 0xff); + *dst++ = (decoded & 0xFF); *dst++ = (decoded >> 8); sample = ((*src) >> 4); + decoded = dsp_decode_ima_adpcm_sample(&context->adpcm, 0, sample); - *dst++ = (decoded & 0xff); + *dst++ = (decoded & 0xFF); *dst++ = (decoded >> 8); src++; size--; @@ -238,8 +261,7 @@ static const struct { 7, 4 } }; -static BYTE dsp_encode_ima_adpcm_sample(ADPCM* adpcm, - int channel, INT16 sample) +static BYTE dsp_encode_ima_adpcm_sample(ADPCM* adpcm, int channel, INT16 sample) { INT32 e; INT32 d; @@ -251,23 +273,29 @@ static BYTE dsp_encode_ima_adpcm_sample(ADPCM* adpcm, d = e = sample - adpcm->ima.last_sample[channel]; diff = ss >> 3; enc = 0; + if (e < 0) { enc = 8; e = -e; } + if (e >= ss) { enc |= 4; e -= ss; } + ss >>= 1; + if (e >= ss) { enc |= 2; e -= ss; } + ss >>= 1; + if (e >= ss) { enc |= 1; @@ -280,13 +308,16 @@ static BYTE dsp_encode_ima_adpcm_sample(ADPCM* adpcm, diff = d - e + diff; diff += adpcm->ima.last_sample[channel]; + if (diff < -32768) diff = -32768; else if (diff > 32767) diff = 32767; + adpcm->ima.last_sample[channel] = (INT16) diff; adpcm->ima.last_step[channel] += ima_step_index_table[enc]; + if (adpcm->ima.last_step[channel] < 0) adpcm->ima.last_step[channel] = 0; else if (adpcm->ima.last_step[channel] > 88) @@ -298,31 +329,35 @@ static BYTE dsp_encode_ima_adpcm_sample(ADPCM* adpcm, static void freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* context, const BYTE* src, int size, int channels, int block_size) { + int i; BYTE* dst; INT16 sample; BYTE encoded; UINT32 out_size; - int i; out_size = size / 2; + if (out_size > context->adpcm_maxlength) { context->adpcm_maxlength = out_size + 1024; context->adpcm_buffer = realloc(context->adpcm_buffer, context->adpcm_maxlength); } + dst = context->adpcm_buffer; + while (size > 0) { if ((dst - context->adpcm_buffer) % block_size == 0) { - *dst++ = context->adpcm.ima.last_sample[0] & 0xff; - *dst++ = (context->adpcm.ima.last_sample[0] >> 8) & 0xff; + *dst++ = context->adpcm.ima.last_sample[0] & 0xFF; + *dst++ = (context->adpcm.ima.last_sample[0] >> 8) & 0xFF; *dst++ = (BYTE) context->adpcm.ima.last_step[0]; *dst++ = 0; + if (channels > 1) { - *dst++ = context->adpcm.ima.last_sample[1] & 0xff; - *dst++ = (context->adpcm.ima.last_sample[1] >> 8) & 0xff; + *dst++ = context->adpcm.ima.last_sample[1] & 0xFF; + *dst++ = (context->adpcm.ima.last_sample[1] >> 8) & 0xFF; *dst++ = (BYTE) context->adpcm.ima.last_step[1]; *dst++ = 0; } @@ -330,7 +365,8 @@ static void freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* context, if (channels > 1) { - memset(dst, 0, 8); + ZeroMemory(dst, 8); + for (i = 0; i < 16; i++) { sample = (INT16) (((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8)); @@ -338,6 +374,7 @@ static void freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* context, encoded = dsp_encode_ima_adpcm_sample(&context->adpcm, i % 2, sample); dst[ima_stereo_encode_map[i].byte_num] |= encoded << ima_stereo_encode_map[i].byte_shift; } + dst += 8; size -= 32; } @@ -363,40 +400,46 @@ static void freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* context, * http://wiki.multimedia.cx/index.php?title=Microsoft_ADPCM */ -static const INT16 ms_adpcm_adaptation_table[] = +static const INT32 ms_adpcm_adaptation_table[] = { 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230 }; -static const INT16 ms_adpcm_coeff1_table[] = +static const INT32 ms_adpcm_coeffs1[7] = { 256, 512, 0, 192, 240, 460, 392 }; -static const INT16 ms_adpcm_coeff2_table[] = +static const INT32 ms_adpcm_coeffs2[7] = { 0, -256, 0, 64, 0, -208, -232 }; -static INT16 freerdp_dsp_decode_ms_adpcm_sample(ADPCM* adpcm, BYTE sample, int channel) +static INLINE INT16 freerdp_dsp_decode_ms_adpcm_sample(ADPCM* adpcm, BYTE sample, int channel) { INT8 nibble; INT32 presample; - nibble = (sample & 0x08 ? (INT8)sample - 16 : sample); - presample = ((adpcm->ms.sample1[channel] * ms_adpcm_coeff1_table[adpcm->ms.predictor[channel]]) + - (adpcm->ms.sample2[channel] * ms_adpcm_coeff2_table[adpcm->ms.predictor[channel]])) / 256; + nibble = (sample & 0x08 ? (INT8) sample - 16 : sample); + + presample = ((adpcm->ms.sample1[channel] * ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) + + (adpcm->ms.sample2[channel] * ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) / 256; + presample += nibble * adpcm->ms.delta[channel]; + if (presample > 32767) presample = 32767; else if (presample < -32768) presample = -32768; + adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel]; adpcm->ms.sample1[channel] = presample; adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[sample] / 256; + if (adpcm->ms.delta[channel] < 16) adpcm->ms.delta[channel] = 16; + return (INT16) presample; } @@ -408,12 +451,15 @@ static void freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* context, UINT32 out_size; out_size = size * 4; + if (out_size > context->adpcm_maxlength) { context->adpcm_maxlength = out_size + 1024; context->adpcm_buffer = realloc(context->adpcm_buffer, context->adpcm_maxlength); } + dst = context->adpcm_buffer; + while (size > 0) { if (size % block_size == 0) @@ -422,43 +468,43 @@ static void freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* context, { context->adpcm.ms.predictor[0] = *src++; context->adpcm.ms.predictor[1] = *src++; - context->adpcm.ms.delta[0] = *((INT16*)src); + context->adpcm.ms.delta[0] = *((INT16*) src); src += 2; - context->adpcm.ms.delta[1] = *((INT16*)src); + context->adpcm.ms.delta[1] = *((INT16*) src); src += 2; - context->adpcm.ms.sample1[0] = *((INT16*)src); + context->adpcm.ms.sample1[0] = *((INT16*) src); src += 2; - context->adpcm.ms.sample1[1] = *((INT16*)src); + context->adpcm.ms.sample1[1] = *((INT16*) src); src += 2; - context->adpcm.ms.sample2[0] = *((INT16*)src); + context->adpcm.ms.sample2[0] = *((INT16*) src); src += 2; - context->adpcm.ms.sample2[1] = *((INT16*)src); + context->adpcm.ms.sample2[1] = *((INT16*) src); src += 2; size -= 14; - *((INT16*)dst) = context->adpcm.ms.sample2[0]; + *((INT16*) dst) = context->adpcm.ms.sample2[0]; dst += 2; - *((INT16*)dst) = context->adpcm.ms.sample2[1]; + *((INT16*) dst) = context->adpcm.ms.sample2[1]; dst += 2; - *((INT16*)dst) = context->adpcm.ms.sample1[0]; + *((INT16*) dst) = context->adpcm.ms.sample1[0]; dst += 2; - *((INT16*)dst) = context->adpcm.ms.sample1[1]; + *((INT16*) dst) = context->adpcm.ms.sample1[1]; dst += 2; } else { context->adpcm.ms.predictor[0] = *src++; - context->adpcm.ms.delta[0] = *((INT16*)src); + context->adpcm.ms.delta[0] = *((INT16*) src); src += 2; - context->adpcm.ms.sample1[0] = *((INT16*)src); + context->adpcm.ms.sample1[0] = *((INT16*) src); src += 2; - context->adpcm.ms.sample2[0] = *((INT16*)src); + context->adpcm.ms.sample2[0] = *((INT16*) src); src += 2; size -= 7; - *((INT16*)dst) = context->adpcm.ms.sample2[0]; + *((INT16*) dst) = context->adpcm.ms.sample2[0]; dst += 2; - *((INT16*)dst) = context->adpcm.ms.sample1[0]; + *((INT16*) dst) = context->adpcm.ms.sample1[0]; dst += 2; } } @@ -467,25 +513,25 @@ static void freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* context, { sample = *src++; size--; - *((INT16*)dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0); + *((INT16*) dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0); dst += 2; - *((INT16*)dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1); + *((INT16*) dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1); dst += 2; sample = *src++; size--; - *((INT16*)dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0); + *((INT16*) dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0); dst += 2; - *((INT16*)dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1); + *((INT16*) dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1); dst += 2; } else { sample = *src++; size--; - *((INT16*)dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0); + *((INT16*) dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0); dst += 2; - *((INT16*)dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 0); + *((INT16*) dst) = freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 0); dst += 2; } } @@ -498,26 +544,33 @@ static BYTE freerdp_dsp_encode_ms_adpcm_sample(ADPCM* adpcm, INT32 sample, int c INT32 presample; INT32 errordelta; - presample = ((adpcm->ms.sample1[channel] * ms_adpcm_coeff1_table[adpcm->ms.predictor[channel]]) + - (adpcm->ms.sample2[channel] * ms_adpcm_coeff2_table[adpcm->ms.predictor[channel]])) / 256; + presample = ((adpcm->ms.sample1[channel] * ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) + + (adpcm->ms.sample2[channel] * ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) / 256; errordelta = (sample - presample) / adpcm->ms.delta[channel]; + if ((sample - presample) % adpcm->ms.delta[channel] > adpcm->ms.delta[channel] / 2) errordelta++; + if (errordelta > 7) errordelta = 7; else if (errordelta < -8) errordelta = -8; + presample += adpcm->ms.delta[channel] * errordelta; + if (presample > 32767) presample = 32767; else if (presample < -32768) presample = -32768; + adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel]; adpcm->ms.sample1[channel] = presample; - adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[(((BYTE)errordelta) & 0x0F)] / 256; + adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[(((BYTE) errordelta) & 0x0F)] / 256; + if (adpcm->ms.delta[channel] < 16) adpcm->ms.delta[channel] = 16; - return ((BYTE)errordelta) & 0x0F; + + return ((BYTE) errordelta) & 0x0F; } static void freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* context, @@ -528,15 +581,18 @@ static void freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* context, UINT32 out_size; out_size = size / 2; + if (out_size > context->adpcm_maxlength) { context->adpcm_maxlength = out_size + 1024; context->adpcm_buffer = realloc(context->adpcm_buffer, context->adpcm_maxlength); } + dst = context->adpcm_buffer; if (context->adpcm.ms.delta[0] < 16) context->adpcm.ms.delta[0] = 16; + if (context->adpcm.ms.delta[1] < 16) context->adpcm.ms.delta[1] = 16; @@ -548,10 +604,10 @@ static void freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* context, { *dst++ = context->adpcm.ms.predictor[0]; *dst++ = context->adpcm.ms.predictor[1]; - *dst++ = (BYTE) (context->adpcm.ms.delta[0] & 0xff); - *dst++ = (BYTE) ((context->adpcm.ms.delta[0] >> 8) & 0xff); - *dst++ = (BYTE) (context->adpcm.ms.delta[1] & 0xff); - *dst++ = (BYTE) ((context->adpcm.ms.delta[1] >> 8) & 0xff); + *dst++ = (BYTE) (context->adpcm.ms.delta[0] & 0xFF); + *dst++ = (BYTE) ((context->adpcm.ms.delta[0] >> 8) & 0xFF); + *dst++ = (BYTE) (context->adpcm.ms.delta[1] & 0xFF); + *dst++ = (BYTE) ((context->adpcm.ms.delta[1] >> 8) & 0xFF); context->adpcm.ms.sample1[0] = *((INT16*) (src + 4)); context->adpcm.ms.sample1[1] = *((INT16*) (src + 6)); context->adpcm.ms.sample2[0] = *((INT16*) (src + 0)); @@ -567,8 +623,8 @@ static void freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* context, else { *dst++ = context->adpcm.ms.predictor[0]; - *dst++ = (BYTE) (context->adpcm.ms.delta[0] & 0xff); - *dst++ = (BYTE) ((context->adpcm.ms.delta[0] >> 8) & 0xff); + *dst++ = (BYTE) (context->adpcm.ms.delta[0] & 0xFF); + *dst++ = (BYTE) ((context->adpcm.ms.delta[0] >> 8) & 0xFF); context->adpcm.ms.sample1[0] = *((INT16*) (src + 2)); context->adpcm.ms.sample2[0] = *((INT16*) (src + 0)); *((INT16*) (dst + 0)) = (INT16) context->adpcm.ms.sample1[0]; @@ -614,8 +670,10 @@ void freerdp_dsp_context_free(FREERDP_DSP_CONTEXT* context) { if (context->resampled_buffer) free(context->resampled_buffer); + if (context->adpcm_buffer) free(context->adpcm_buffer); + free(context); } } diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index d20e015c3..c405997d0 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -271,8 +271,8 @@ NSC_CONTEXT* nsc_context_new(void) NSC_CONTEXT* nsc_context; UINT8 i; - nsc_context = (NSC_CONTEXT*) malloc(sizeof(NSC_CONTEXT)); - nsc_context->priv = (NSC_CONTEXT_PRIV*) malloc(sizeof(NSC_CONTEXT_PRIV)); + nsc_context = (NSC_CONTEXT*) calloc(1, sizeof(NSC_CONTEXT)); + nsc_context->priv = (NSC_CONTEXT_PRIV*) calloc(1, sizeof(NSC_CONTEXT_PRIV)); for (i=0; i < 5; ++i) { nsc_context->priv->plane_buf[i] = NULL; diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index e29a095ca..3f30cbd22 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -37,6 +37,7 @@ #include #include +#include #include "rfx_constants.h" #include "rfx_types.h" @@ -45,13 +46,8 @@ #include "rfx_quantization.h" #include "rfx_dwt.h" -#ifdef WITH_SSE2 #include "rfx_sse2.h" -#endif - -#ifdef WITH_NEON #include "rfx_neon.h" -#endif #ifndef RFX_INIT_SIMD #define RFX_INIT_SIMD(_rfx_context) do { } while (0) @@ -209,6 +205,11 @@ RFX_CONTEXT* rfx_context_new(void) if (context->priv->UseThreads) { + /* Call primitives_get here in order to avoid race conditions when using primitives_get */ + /* from multiple threads. This call will initialize all function pointers correctly */ + /* before any decoding threads are started */ + primitives_get(); + context->priv->ThreadPool = CreateThreadpool(NULL); InitializeThreadpoolEnvironment(&context->priv->ThreadPoolEnv); SetThreadpoolCallbackPool(&context->priv->ThreadPoolEnv, context->priv->ThreadPool); @@ -232,6 +233,8 @@ RFX_CONTEXT* rfx_context_new(void) context->dwt_2d_decode = rfx_dwt_2d_decode; context->dwt_2d_encode = rfx_dwt_2d_encode; + RFX_INIT_SIMD(context); + return context; } diff --git a/libfreerdp/codec/rfx_neon.c b/libfreerdp/codec/rfx_neon.c index 7331ea18b..40683b91b 100644 --- a/libfreerdp/codec/rfx_neon.c +++ b/libfreerdp/codec/rfx_neon.c @@ -40,9 +40,7 @@ static __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) rfx_quantization_decode_block_NEON(INT16 * buffer, const int buffer_size, const UINT32 factor) { - if (factor <= 6) - return; - int16x8_t quantFactors = vdupq_n_s16(factor - 6); + int16x8_t quantFactors = vdupq_n_s16(factor); int16x8_t* buf = (int16x8_t*)buffer; int16x8_t* buf_end = (int16x8_t*)(buffer + buffer_size); @@ -59,16 +57,18 @@ rfx_quantization_decode_block_NEON(INT16 * buffer, const int buffer_size, const void rfx_quantization_decode_NEON(INT16 * buffer, const UINT32 * quantization_values) { - rfx_quantization_decode_block_NEON(buffer, 1024, quantization_values[8]); /* HL1 */ - rfx_quantization_decode_block_NEON(buffer + 1024, 1024, quantization_values[7]); /* LH1 */ - rfx_quantization_decode_block_NEON(buffer + 2048, 1024, quantization_values[9]); /* HH1 */ - rfx_quantization_decode_block_NEON(buffer + 3072, 256, quantization_values[5]); /* HL2 */ - rfx_quantization_decode_block_NEON(buffer + 3328, 256, quantization_values[4]); /* LH2 */ - rfx_quantization_decode_block_NEON(buffer + 3584, 256, quantization_values[6]); /* HH2 */ - rfx_quantization_decode_block_NEON(buffer + 3840, 64, quantization_values[2]); /* HL3 */ - rfx_quantization_decode_block_NEON(buffer + 3904, 64, quantization_values[1]); /* LH3 */ - rfx_quantization_decode_block_NEON(buffer + 3968, 64, quantization_values[3]); /* HH3 */ - rfx_quantization_decode_block_NEON(buffer + 4032, 64, quantization_values[0]); /* LL3 */ + rfx_quantization_decode_block_NEON(buffer, 4096, 5); + + rfx_quantization_decode_block_NEON(buffer, 1024, quantization_values[8] - 6); /* HL1 */ + rfx_quantization_decode_block_NEON(buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */ + rfx_quantization_decode_block_NEON(buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */ + rfx_quantization_decode_block_NEON(buffer + 3072, 256, quantization_values[5] - 6); /* HL2 */ + rfx_quantization_decode_block_NEON(buffer + 3328, 256, quantization_values[4] - 6); /* LH2 */ + rfx_quantization_decode_block_NEON(buffer + 3584, 256, quantization_values[6] - 6); /* HH2 */ + rfx_quantization_decode_block_NEON(buffer + 3840, 64, quantization_values[2] - 6); /* HL3 */ + rfx_quantization_decode_block_NEON(buffer + 3904, 64, quantization_values[1] - 6); /* LH3 */ + rfx_quantization_decode_block_NEON(buffer + 3968, 64, quantization_values[3] - 6); /* HH3 */ + rfx_quantization_decode_block_NEON(buffer + 4032, 64, quantization_values[0] - 6); /* LL3 */ } @@ -278,8 +278,11 @@ int isNeonSupported() } return FALSE; -#else +#elif defined(__APPLE) + /* assume NEON support on iOS devices */ return TRUE; +#else + return FALSE; #endif } diff --git a/libfreerdp/codec/rfx_neon.h b/libfreerdp/codec/rfx_neon.h index 4ec15b281..4a4edddf4 100644 --- a/libfreerdp/codec/rfx_neon.h +++ b/libfreerdp/codec/rfx_neon.h @@ -22,8 +22,6 @@ #include -#if defined(__ARM_NEON__) - void rfx_init_neon(RFX_CONTEXT * context); #ifndef RFX_INIT_SIMD @@ -32,7 +30,5 @@ void rfx_init_neon(RFX_CONTEXT * context); #endif #endif -#endif // __ARM_NEON__ - #endif /* __RFX_NEON_H */ diff --git a/libfreerdp/codec/rfx_sse2.h b/libfreerdp/codec/rfx_sse2.h index 2fc14fd47..f1ff20e6d 100644 --- a/libfreerdp/codec/rfx_sse2.h +++ b/libfreerdp/codec/rfx_sse2.h @@ -24,8 +24,10 @@ void rfx_init_sse2(RFX_CONTEXT* context); -#ifndef RFX_INIT_SIMD -#define RFX_INIT_SIMD(_rfx_context) rfx_init_sse2(_rfx_context) +#ifdef WITH_SSE2 + #ifndef RFX_INIT_SIMD + #define RFX_INIT_SIMD(_rfx_context) rfx_init_sse2(_rfx_context) + #endif #endif #endif /* __RFX_SSE2_H */ diff --git a/libfreerdp/core/channel.c b/libfreerdp/core/channel.c index b9bccc941..ba9240241 100644 --- a/libfreerdp/core/channel.c +++ b/libfreerdp/core/channel.c @@ -50,7 +50,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) } } - if (channel == NULL) + if (!channel) { printf("freerdp_channel_send: unknown channel_id %d\n", channel_id); return FALSE; @@ -58,6 +58,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) flags = CHANNEL_FLAG_FIRST; left = size; + while (left > 0) { s = rdp_send_stream_init(rdp); @@ -71,6 +72,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) chunk_size = left; flags |= CHANNEL_FLAG_LAST; } + if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL)) { flags |= CHANNEL_FLAG_SHOW_PROTOCOL; @@ -97,14 +99,16 @@ BOOL freerdp_channel_process(freerdp* instance, STREAM* s, UINT16 channel_id) UINT32 flags; int chunk_length; - if(stream_get_left(s) < 8) + if (stream_get_left(s) < 8) return FALSE; + stream_read_UINT32(s, length); stream_read_UINT32(s, flags); chunk_length = stream_get_left(s); IFCALL(instance->ReceiveChannelData, instance, channel_id, stream_get_tail(s), chunk_length, flags, length); + return TRUE; } diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index af727fd16..f2e67a96b 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -340,7 +340,11 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s) stream_check_size(fastpath->updateData, size); stream_copy(fastpath->updateData, comp_stream, size); - /* TODO: add a limit on the fragmentation buffer size */ + if (stream_get_size(fastpath->updateData) > rdp->settings->MultifragMaxRequestSize) + { + printf("fastpath PDU is bigger than MultifragMaxRequestSize\n"); + return -1; + } if (fragmentation == FASTPATH_FRAGMENT_LAST) { diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c index 5bf341fc0..441bf9680 100644 --- a/libfreerdp/core/nla.c +++ b/libfreerdp/core/nla.c @@ -1104,28 +1104,28 @@ void credssp_send(rdpCredssp* credssp) /* [1] negoTokens (NegoData) */ if (nego_tokens_length > 0) { - length = der_get_content_length(nego_tokens_length); - length -= der_write_contextual_tag(s, 1, length, TRUE); /* NegoData */ - length -= der_write_sequence_tag(s, length); /* SEQUENCE OF NegoDataItem */ - length -= der_write_sequence_tag(s, length); /* NegoDataItem */ - length -= der_write_contextual_tag(s, 0, length, TRUE); /* [0] negoToken */ - der_write_octet_string(s, (BYTE*) credssp->negoToken.pvBuffer, length); /* OCTET STRING */ + length = nego_tokens_length; + length -= der_write_contextual_tag(s, 1, der_get_content_length(length), TRUE); /* NegoData */ + length -= der_write_sequence_tag(s, der_get_content_length(length)); /* SEQUENCE OF NegoDataItem */ + length -= der_write_sequence_tag(s, der_get_content_length(length)); /* NegoDataItem */ + length -= der_write_contextual_tag(s, 0, der_get_content_length(length), TRUE); /* [0] negoToken */ + der_write_octet_string(s, (BYTE*) credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer); /* OCTET STRING */ } /* [2] authInfo (OCTET STRING) */ if (auth_info_length > 0) { - length = ber_get_content_length(auth_info_length); - length -= ber_write_contextual_tag(s, 2, length, TRUE); + length = auth_info_length; + length -= ber_write_contextual_tag(s, 2, ber_get_content_length(length), TRUE); ber_write_octet_string(s, credssp->authInfo.pvBuffer, credssp->authInfo.cbBuffer); } /* [3] pubKeyAuth (OCTET STRING) */ if (pub_key_auth_length > 0) { - length = ber_get_content_length(pub_key_auth_length); - length -= ber_write_contextual_tag(s, 3, length, TRUE); - ber_write_octet_string(s, credssp->pubKeyAuth.pvBuffer, length); + length = pub_key_auth_length; + length -= ber_write_contextual_tag(s, 3, ber_get_content_length(length), TRUE); + ber_write_octet_string(s, credssp->pubKeyAuth.pvBuffer, credssp->pubKeyAuth.cbBuffer); } transport_write(credssp->transport, s); diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index eb39d6a4c..544a9dd9e 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -420,6 +420,7 @@ BOOL rdp_send(rdpRdp* rdp, STREAM* s, UINT16 channel_id) length += rdp_security_stream_out(rdp, s, length); stream_set_pos(s, length); + if (transport_write(rdp->transport, s) < 0) return FALSE; diff --git a/libfreerdp/crypto/ber.c b/libfreerdp/crypto/ber.c index 344d5570d..963471dce 100644 --- a/libfreerdp/crypto/ber.c +++ b/libfreerdp/crypto/ber.c @@ -76,7 +76,7 @@ int ber_write_length(STREAM* s, int length) int _ber_skip_length(int length) { - if (length > 0x7F) + if (length > 0x80) return 3; else return 1; @@ -84,7 +84,7 @@ int _ber_skip_length(int length) int ber_get_content_length(int length) { - if (length - 1 > 0x7F) + if (length > 0x81) return length - 4; else return length - 2; diff --git a/libfreerdp/crypto/der.c b/libfreerdp/crypto/der.c index ef77b2a7f..888a00036 100644 --- a/libfreerdp/crypto/der.c +++ b/libfreerdp/crypto/der.c @@ -25,9 +25,9 @@ int _der_skip_length(int length) { - if (length > 0x7F && length <= 0xFF) + if (length > 0x81 && length <= 0x102) return 2; - else if (length > 0xFF) + else if (length > 0x102) return 3; else return 1; @@ -56,9 +56,9 @@ int der_write_length(STREAM* s, int length) int der_get_content_length(int length) { - if (length > 0x7F && length <= 0xFF) + if (length > 0x81 && length <= 0x102) return length - 3; - else if (length > 0xFF) + else if (length > 0x102) return length - 4; else return length - 2; diff --git a/libfreerdp/locale/keyboard_keymap.c b/libfreerdp/locale/keyboard_keymap.c index 4325b9a94..af4d6f294 100644 --- a/libfreerdp/locale/keyboard_keymap.c +++ b/libfreerdp/locale/keyboard_keymap.c @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -128,7 +130,7 @@ int freerdp_keyboard_load_map(UINT32 keycode_to_vkcode[256], char* name) keycode = atoi(keycode_string); /* Make sure it is a valid keycode */ - if (keycode < 0 || keycode > 255) //Corey: keycode cant be less than 0... + if (keycode > 255) break; /* Load this key mapping in the keyboard mapping */ @@ -185,7 +187,7 @@ void freerdp_keyboard_load_maps(UINT32 keycode_to_vkcode[256], char* names) char* names_end; int keymap_loaded = 0; - memset(keycode_to_vkcode, 0, sizeof(keycode_to_vkcode)); //Corey: should this be sizeof() * elements ??? + ZeroMemory(keycode_to_vkcode, sizeof(UINT32) * 256); kbd = names; names_end = names + strlen(names); diff --git a/libfreerdp/locale/keyboard_x11.c b/libfreerdp/locale/keyboard_x11.c index d432f31ff..2f938ae4d 100644 --- a/libfreerdp/locale/keyboard_x11.c +++ b/libfreerdp/locale/keyboard_x11.c @@ -277,7 +277,7 @@ const UINT32 KEYCODE_TO_VKCODE_MACOSX[256] = 0, /* 60 */ VK_ESCAPE, /* 61 */ 0, /* 62 */ - 0, /* 63 */ + VK_LWIN, /* 63 */ VK_LSHIFT, /* 64 */ VK_CAPITAL, /* 65 */ VK_LMENU, /* 66 */ @@ -285,7 +285,7 @@ const UINT32 KEYCODE_TO_VKCODE_MACOSX[256] = VK_RSHIFT, /* 68 */ VK_RMENU, /* 69 */ 0, /* 70 */ - 0, /* 71 */ + VK_RWIN, /* 71 */ 0, /* 72 */ VK_DECIMAL, /* 73 */ 0, /* 74 */ @@ -481,7 +481,7 @@ UINT32 freerdp_keyboard_init_x11(UINT32 keyboardLayoutId, RDP_SCANCODE x11_keyco UINT32 keycode_to_vkcode[256]; ZeroMemory(keycode_to_vkcode, sizeof(keycode_to_vkcode)); - ZeroMemory(x11_keycode_to_rdp_scancode, sizeof(x11_keycode_to_rdp_scancode)); + ZeroMemory(x11_keycode_to_rdp_scancode, sizeof(RDP_SCANCODE) * 256); #ifdef __APPLE__ /* Apple X11 breaks XKB detection */ diff --git a/libfreerdp/primitives/CMakeLists.txt b/libfreerdp/primitives/CMakeLists.txt index 4cbae2717..e8d1a7bfb 100644 --- a/libfreerdp/primitives/CMakeLists.txt +++ b/libfreerdp/primitives/CMakeLists.txt @@ -28,6 +28,15 @@ set(${MODULE_PREFIX}_SRCS primitives.c prim_internal.h) +set(${MODULE_PREFIX}_OPT_SRCS + prim_add_opt.c + prim_andor_opt.c + prim_alphaComp_opt.c + prim_colors_opt.c + prim_set_opt.c + prim_shift_opt.c + prim_sign_opt.c) + add_definitions(-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}) ### IPP Variable debugging @@ -49,7 +58,7 @@ if(WITH_SSE2) endif() elseif(WITH_NEON) if(CMAKE_COMPILER_IS_GNUCC) - set(OPTIMIZATION "${OPTIMIZATION} -mfpu=neon -mfloat-abi=softfp") + set(OPTIMIZATION "${OPTIMIZATION} -mfpu=neon -mfloat-abi=${ARM_FP_ABI}") endif() # TODO: Add MSVC equivalent endif() @@ -63,7 +72,9 @@ if(ANDROID) ${ANDROID_CPU_FEATURES_PATH}/cpu-features.h) endif() -set_property(SOURCE ${${MODULE_PREFIX}_SRCS} PROPERTY COMPILE_FLAGS ${OPTIMIZATION}) +set_property(SOURCE ${${MODULE_PREFIX}_OPT_SRCS} PROPERTY COMPILE_FLAGS ${OPTIMIZATION}) + +set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${${MODULE_PREFIX}_OPT_SRCS}) add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" MONOLITHIC ${MONOLITHIC_BUILD} diff --git a/libfreerdp/primitives/prim_add.c b/libfreerdp/primitives/prim_add.c index 17e504201..258bcc6ea 100644 --- a/libfreerdp/primitives/prim_add.c +++ b/libfreerdp/primitives/prim_add.c @@ -18,27 +18,16 @@ #include "config.h" #endif -#include - #include #include -#ifdef WITH_SSE2 -#include -#include -#endif /* WITH_SSE2 */ - -#ifdef WITH_IPP -#include -#endif /* WITH_IPP */ - #include "prim_internal.h" -#include "prim_templates.h" +#include "prim_add.h" /* ---------------------------------------------------------------------------- * 16-bit signed add with saturation (under and over). */ -PRIM_STATIC pstatus_t general_add_16s( +pstatus_t general_add_16s( const INT16 *pSrc1, const INT16 *pSrc2, INT16 *pDst, @@ -55,29 +44,14 @@ PRIM_STATIC pstatus_t general_add_16s( return PRIMITIVES_SUCCESS; } -#ifdef WITH_SSE2 -# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) -/* ------------------------------------------------------------------------- */ -SSE3_SSD_ROUTINE(sse3_add_16s, INT16, general_add_16s, - _mm_adds_epi16, general_add_16s(sptr1++, sptr2++, dptr++, 1)) -# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ -#endif - /* ------------------------------------------------------------------------- */ void primitives_init_add( const primitives_hints_t *hints, primitives_t *prims) { prims->add_16s = general_add_16s; -#ifdef WITH_IPP - prims->add_16s = (__add_16s_t) ippsAdd_16s; -#elif defined(WITH_SSE2) - if ((hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) - && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) /* for LDDQU */ - { - prims->add_16s = sse3_add_16s; - } -#endif + + primitives_init_add_opt(hints, prims); } /* ------------------------------------------------------------------------- */ diff --git a/libfreerdp/primitives/prim_add.h b/libfreerdp/primitives/prim_add.h new file mode 100644 index 000000000..4ad460279 --- /dev/null +++ b/libfreerdp/primitives/prim_add.h @@ -0,0 +1,30 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Add operations. + * vi:ts=4 sw=4 + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. Algorithms used by + * this code may be covered by patents by HP, Microsoft, or other parties. + * + */ + +#ifdef __GNUC__ +# pragma once +#endif + +#ifndef __PRIM_ADD_H_INCLUDED__ +#define __PRIM_ADD_H_INCLUDED__ + +pstatus_t general_add_16s(const INT16 *pSrc1, const INT16 *pSrc2, INT16 *pDst, INT32 len); + +void primitives_init_add_opt(const primitives_hints_t *hints, primitives_t *prims); + +#endif /* !__PRIM_ADD_H_INCLUDED__ */ + diff --git a/libfreerdp/primitives/prim_add_opt.c b/libfreerdp/primitives/prim_add_opt.c new file mode 100644 index 000000000..2de0b8fc6 --- /dev/null +++ b/libfreerdp/primitives/prim_add_opt.c @@ -0,0 +1,62 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Optimized add operations. + * vi:ts=4 sw=4: + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef WITH_SSE2 +#include +#include +#endif /* WITH_SSE2 */ + +#ifdef WITH_IPP +#include +#endif /* WITH_IPP */ + +#include "prim_internal.h" +#include "prim_templates.h" +#include "prim_add.h" + + +#ifdef WITH_SSE2 +# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) +/* ------------------------------------------------------------------------- */ +SSE3_SSD_ROUTINE(sse3_add_16s, INT16, general_add_16s, + _mm_adds_epi16, general_add_16s(sptr1++, sptr2++, dptr++, 1)) +# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ +#endif + +/* ------------------------------------------------------------------------- */ +void primitives_init_add_opt( + const primitives_hints_t *hints, + primitives_t *prims) +{ +#ifdef WITH_IPP + prims->add_16s = (__add_16s_t) ippsAdd_16s; +#elif defined(WITH_SSE2) + if ((hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) + && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) /* for LDDQU */ + { + prims->add_16s = sse3_add_16s; + } +#endif +} + + diff --git a/libfreerdp/primitives/prim_alphaComp.c b/libfreerdp/primitives/prim_alphaComp.c index 7f1a19093..24f916770 100644 --- a/libfreerdp/primitives/prim_alphaComp.c +++ b/libfreerdp/primitives/prim_alphaComp.c @@ -24,21 +24,11 @@ #include "config.h" #endif -#include - #include #include #include "prim_internal.h" - -#ifdef WITH_SSE2 -#include -#include -#endif /* WITH_SSE2 */ - -#ifdef WITH_IPP -#include -#endif /* WITH_IPP */ +#include "prim_alphaComp.h" #define ALPHA(_k_) (((_k_) & 0xFF000000U) >> 24) #define RED(_k_) (((_k_) & 0x00FF0000U) >> 16) @@ -46,7 +36,7 @@ #define BLU(_k_) (((_k_) & 0x000000FFU)) /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_alphaComp_argb( +pstatus_t general_alphaComp_argb( const BYTE *pSrc1, INT32 src1Step, const BYTE *pSrc2, INT32 src2Step, BYTE *pDst, INT32 dstStep, @@ -111,188 +101,12 @@ PRIM_STATIC pstatus_t general_alphaComp_argb( return PRIMITIVES_SUCCESS; } -/* ------------------------------------------------------------------------- */ -#ifdef WITH_SSE2 -#if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) - -PRIM_STATIC pstatus_t sse2_alphaComp_argb( - const BYTE *pSrc1, INT32 src1Step, - const BYTE *pSrc2, INT32 src2Step, - BYTE *pDst, INT32 dstStep, - INT32 width, INT32 height) -{ - const UINT32 *sptr1 = (const UINT32 *) pSrc1; - const UINT32 *sptr2 = (const UINT32 *) pSrc2; - UINT32 *dptr; - int linebytes, src1Jump, src2Jump, dstJump, y; - __m128i xmm0, xmm1; - - if ((width <= 0) || (height <= 0)) return PRIMITIVES_SUCCESS; - - if (width < 4) /* pointless if too small */ - { - return general_alphaComp_argb(pSrc1, src1Step, pSrc2, src2Step, - pDst, dstStep, width, height); - } - dptr = (UINT32 *) pDst; - linebytes = width * sizeof(UINT32); - src1Jump = (src1Step - linebytes) / sizeof(UINT32); - src2Jump = (src2Step - linebytes) / sizeof(UINT32); - dstJump = (dstStep - linebytes) / sizeof(UINT32); - - xmm0 = _mm_set1_epi32(0); - xmm1 = _mm_set1_epi16(1); - - for (y=0; y> 2; - pixels -= count << 2; - while (count--) - { - __m128i xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; - /* BdGdRdAdBcGcRcAcBbGbRbAbBaGaRaAa */ - xmm2 = LOAD_SI128(sptr1); sptr1 += 4; - /* BhGhRhAhBgGgRgAgBfGfRfAfBeGeReAe */ - xmm3 = LOAD_SI128(sptr2); sptr2 += 4; - /* 00Bb00Gb00Rb00Ab00Ba00Ga00Ra00Aa */ - xmm4 = _mm_unpackhi_epi8(xmm2, xmm0); - /* 00Bf00Gf00Bf00Af00Be00Ge00Re00Ae */ - xmm5 = _mm_unpackhi_epi8(xmm3, xmm0); - /* subtract */ - xmm6 = _mm_subs_epi16(xmm4, xmm5); - /* 00Bb00Gb00Rb00Ab00Aa00Aa00Aa00Aa */ - xmm4 = _mm_shufflelo_epi16(xmm4, 0xff); - /* 00Ab00Ab00Ab00Ab00Aa00Aa00Aa00Aa */ - xmm4 = _mm_shufflehi_epi16(xmm4, 0xff); - /* Add one to alphas */ - xmm4 = _mm_adds_epi16(xmm4, xmm1); - /* Multiply and take low word */ - xmm4 = _mm_mullo_epi16(xmm4, xmm6); - /* Shift 8 right */ - xmm4 = _mm_srai_epi16(xmm4, 8); - /* Add xmm5 */ - xmm4 = _mm_adds_epi16(xmm4, xmm5); - /* 00Bj00Gj00Rj00Aj00Bi00Gi00Ri00Ai */ - - /* 00Bd00Gd00Rd00Ad00Bc00Gc00Rc00Ac */ - xmm5 = _mm_unpacklo_epi8(xmm2, xmm0); - /* 00Bh00Gh00Rh00Ah00Bg00Gg00Rg00Ag */ - xmm6 = _mm_unpacklo_epi8(xmm3, xmm0); - /* subtract */ - xmm7 = _mm_subs_epi16(xmm5, xmm6); - /* 00Bd00Gd00Rd00Ad00Ac00Ac00Ac00Ac */ - xmm5 = _mm_shufflelo_epi16(xmm5, 0xff); - /* 00Ad00Ad00Ad00Ad00Ac00Ac00Ac00Ac */ - xmm5 = _mm_shufflehi_epi16(xmm5, 0xff); - /* Add one to alphas */ - xmm5 = _mm_adds_epi16(xmm5, xmm1); - /* Multiply and take low word */ - xmm5 = _mm_mullo_epi16(xmm5, xmm7); - /* Shift 8 right */ - xmm5 = _mm_srai_epi16(xmm5, 8); - /* Add xmm6 */ - xmm5 = _mm_adds_epi16(xmm5, xmm6); - /* 00Bl00Gl00Rl00Al00Bk00Gk00Rk0ABk */ - - /* Must mask off remainders or pack gets confused */ - xmm3 = _mm_set1_epi16(0x00ffU); - xmm4 = _mm_and_si128(xmm4, xmm3); - xmm5 = _mm_and_si128(xmm5, xmm3); - - /* BlGlRlAlBkGkRkAkBjGjRjAjBiGiRiAi */ - xmm5 = _mm_packus_epi16(xmm5, xmm4); - _mm_store_si128((__m128i *) dptr, xmm5); dptr += 4; - } - - /* Finish off the remainder. */ - if (pixels) - { - general_alphaComp_argb((const BYTE *) sptr1, src1Step, - (const BYTE *) sptr2, src2Step, - (BYTE *) dptr, dstStep, pixels, 1); - sptr1 += pixels; - sptr2 += pixels; - dptr += pixels; - } - - /* Jump to next row. */ - sptr1 += src1Jump; - sptr2 += src2Jump; - dptr += dstJump; - } - - return PRIMITIVES_SUCCESS; -} -#endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ -#endif - -#ifdef WITH_IPP -/* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t ipp_alphaComp_argb( - const BYTE *pSrc1, INT32 src1Step, - const BYTE *pSrc2, INT32 src2Step, - BYTE *pDst, INT32 dstStep, - INT32 width, INT32 height) -{ - IppiSize sz; - sz.width = width; - sz.height = height; - return ippiAlphaComp_8u_AC4R(pSrc1, src1Step, pSrc2, src2Step, - pDst, dstStep, sz, ippAlphaOver); -} -#endif - /* ------------------------------------------------------------------------- */ void primitives_init_alphaComp(const primitives_hints_t* hints, primitives_t* prims) { prims->alphaComp_argb = general_alphaComp_argb; -#ifdef WITH_IPP - prims->alphaComp_argb = ipp_alphaComp_argb; -#elif defined(WITH_SSE2) - if ((hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) - && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) /* for LDDQU */ - { - prims->alphaComp_argb = sse2_alphaComp_argb; - } -#endif + + primitives_init_alphaComp_opt(hints, prims); } /* ------------------------------------------------------------------------- */ @@ -300,3 +114,4 @@ void primitives_deinit_alphaComp(primitives_t *prims) { /* Nothing to do. */ } + diff --git a/libfreerdp/primitives/prim_alphaComp.h b/libfreerdp/primitives/prim_alphaComp.h new file mode 100644 index 000000000..50591162d --- /dev/null +++ b/libfreerdp/primitives/prim_alphaComp.h @@ -0,0 +1,30 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Alpha blending routines. + * vi:ts=4 sw=4 + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. Algorithms used by + * this code may be covered by patents by HP, Microsoft, or other parties. + * + */ + +#ifdef __GNUC__ +# pragma once +#endif + +#ifndef __PRIM_ALPHACOMP_H_INCLUDED__ +#define __PRIM_ALPHACOMP_H_INCLUDED__ + +pstatus_t general_alphaComp_argb(const BYTE *pSrc1, INT32 src1Step, const BYTE *pSrc2, INT32 src2Step, BYTE *pDst, INT32 dstStep, INT32 width, INT32 height); + +void primitives_init_alphaComp_opt(const primitives_hints_t* hints, primitives_t* prims); + +#endif /* !__PRIM_ALPHACOMP_H_INCLUDED__ */ + diff --git a/libfreerdp/primitives/prim_alphaComp_opt.c b/libfreerdp/primitives/prim_alphaComp_opt.c new file mode 100644 index 000000000..5550fcbc1 --- /dev/null +++ b/libfreerdp/primitives/prim_alphaComp_opt.c @@ -0,0 +1,225 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Optimized alpha blending routines. + * vi:ts=4 sw=4: + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + * + * Note: this code assumes the second operand is fully opaque, + * e.g. + * newval = alpha1*val1 + (1-alpha1)*val2 + * rather than + * newval = alpha1*val1 + (1-alpha1)*alpha2*val2 + * The IPP gives other options. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef WITH_SSE2 +#include +#include +#endif /* WITH_SSE2 */ + +#ifdef WITH_IPP +#include +#endif /* WITH_IPP */ + +#include "prim_internal.h" +#include "prim_alphaComp.h" + + +/* ------------------------------------------------------------------------- */ +#ifdef WITH_SSE2 +#if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) + +pstatus_t sse2_alphaComp_argb( + const BYTE *pSrc1, INT32 src1Step, + const BYTE *pSrc2, INT32 src2Step, + BYTE *pDst, INT32 dstStep, + INT32 width, INT32 height) +{ + const UINT32 *sptr1 = (const UINT32 *) pSrc1; + const UINT32 *sptr2 = (const UINT32 *) pSrc2; + UINT32 *dptr; + int linebytes, src1Jump, src2Jump, dstJump, y; + __m128i xmm0, xmm1; + + if ((width <= 0) || (height <= 0)) return PRIMITIVES_SUCCESS; + + if (width < 4) /* pointless if too small */ + { + return general_alphaComp_argb(pSrc1, src1Step, pSrc2, src2Step, + pDst, dstStep, width, height); + } + dptr = (UINT32 *) pDst; + linebytes = width * sizeof(UINT32); + src1Jump = (src1Step - linebytes) / sizeof(UINT32); + src2Jump = (src2Step - linebytes) / sizeof(UINT32); + dstJump = (dstStep - linebytes) / sizeof(UINT32); + + xmm0 = _mm_set1_epi32(0); + xmm1 = _mm_set1_epi16(1); + + for (y=0; y> 2; + pixels -= count << 2; + while (count--) + { + __m128i xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; + /* BdGdRdAdBcGcRcAcBbGbRbAbBaGaRaAa */ + xmm2 = LOAD_SI128(sptr1); sptr1 += 4; + /* BhGhRhAhBgGgRgAgBfGfRfAfBeGeReAe */ + xmm3 = LOAD_SI128(sptr2); sptr2 += 4; + /* 00Bb00Gb00Rb00Ab00Ba00Ga00Ra00Aa */ + xmm4 = _mm_unpackhi_epi8(xmm2, xmm0); + /* 00Bf00Gf00Bf00Af00Be00Ge00Re00Ae */ + xmm5 = _mm_unpackhi_epi8(xmm3, xmm0); + /* subtract */ + xmm6 = _mm_subs_epi16(xmm4, xmm5); + /* 00Bb00Gb00Rb00Ab00Aa00Aa00Aa00Aa */ + xmm4 = _mm_shufflelo_epi16(xmm4, 0xff); + /* 00Ab00Ab00Ab00Ab00Aa00Aa00Aa00Aa */ + xmm4 = _mm_shufflehi_epi16(xmm4, 0xff); + /* Add one to alphas */ + xmm4 = _mm_adds_epi16(xmm4, xmm1); + /* Multiply and take low word */ + xmm4 = _mm_mullo_epi16(xmm4, xmm6); + /* Shift 8 right */ + xmm4 = _mm_srai_epi16(xmm4, 8); + /* Add xmm5 */ + xmm4 = _mm_adds_epi16(xmm4, xmm5); + /* 00Bj00Gj00Rj00Aj00Bi00Gi00Ri00Ai */ + + /* 00Bd00Gd00Rd00Ad00Bc00Gc00Rc00Ac */ + xmm5 = _mm_unpacklo_epi8(xmm2, xmm0); + /* 00Bh00Gh00Rh00Ah00Bg00Gg00Rg00Ag */ + xmm6 = _mm_unpacklo_epi8(xmm3, xmm0); + /* subtract */ + xmm7 = _mm_subs_epi16(xmm5, xmm6); + /* 00Bd00Gd00Rd00Ad00Ac00Ac00Ac00Ac */ + xmm5 = _mm_shufflelo_epi16(xmm5, 0xff); + /* 00Ad00Ad00Ad00Ad00Ac00Ac00Ac00Ac */ + xmm5 = _mm_shufflehi_epi16(xmm5, 0xff); + /* Add one to alphas */ + xmm5 = _mm_adds_epi16(xmm5, xmm1); + /* Multiply and take low word */ + xmm5 = _mm_mullo_epi16(xmm5, xmm7); + /* Shift 8 right */ + xmm5 = _mm_srai_epi16(xmm5, 8); + /* Add xmm6 */ + xmm5 = _mm_adds_epi16(xmm5, xmm6); + /* 00Bl00Gl00Rl00Al00Bk00Gk00Rk0ABk */ + + /* Must mask off remainders or pack gets confused */ + xmm3 = _mm_set1_epi16(0x00ffU); + xmm4 = _mm_and_si128(xmm4, xmm3); + xmm5 = _mm_and_si128(xmm5, xmm3); + + /* BlGlRlAlBkGkRkAkBjGjRjAjBiGiRiAi */ + xmm5 = _mm_packus_epi16(xmm5, xmm4); + _mm_store_si128((__m128i *) dptr, xmm5); dptr += 4; + } + + /* Finish off the remainder. */ + if (pixels) + { + general_alphaComp_argb((const BYTE *) sptr1, src1Step, + (const BYTE *) sptr2, src2Step, + (BYTE *) dptr, dstStep, pixels, 1); + sptr1 += pixels; + sptr2 += pixels; + dptr += pixels; + } + + /* Jump to next row. */ + sptr1 += src1Jump; + sptr2 += src2Jump; + dptr += dstJump; + } + + return PRIMITIVES_SUCCESS; +} +#endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ +#endif + +#ifdef WITH_IPP +/* ------------------------------------------------------------------------- */ +pstatus_t ipp_alphaComp_argb( + const BYTE *pSrc1, INT32 src1Step, + const BYTE *pSrc2, INT32 src2Step, + BYTE *pDst, INT32 dstStep, + INT32 width, INT32 height) +{ + IppiSize sz; + sz.width = width; + sz.height = height; + return ippiAlphaComp_8u_AC4R(pSrc1, src1Step, pSrc2, src2Step, + pDst, dstStep, sz, ippAlphaOver); +} +#endif + +/* ------------------------------------------------------------------------- */ +void primitives_init_alphaComp_opt(const primitives_hints_t* hints, primitives_t* prims) +{ +#ifdef WITH_IPP + prims->alphaComp_argb = ipp_alphaComp_argb; +#elif defined(WITH_SSE2) + if ((hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) + && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) /* for LDDQU */ + { + prims->alphaComp_argb = sse2_alphaComp_argb; + } +#endif +} + diff --git a/libfreerdp/primitives/prim_andor.c b/libfreerdp/primitives/prim_andor.c index 358d6c823..0b8092ff2 100644 --- a/libfreerdp/primitives/prim_andor.c +++ b/libfreerdp/primitives/prim_andor.c @@ -17,27 +17,16 @@ #include "config.h" #endif -#include - #include #include -#ifdef WITH_SSE2 -#include -#include -#endif /* WITH_SSE2 */ - -#ifdef WITH_IPP -#include -#endif /* WITH_IPP */ - #include "prim_internal.h" -#include "prim_templates.h" +#include "prim_andor.h" /* ---------------------------------------------------------------------------- * 32-bit AND with a constant. */ -PRIM_STATIC pstatus_t general_andC_32u( +pstatus_t general_andC_32u( const UINT32 *pSrc, UINT32 val, UINT32 *pDst, @@ -55,7 +44,7 @@ PRIM_STATIC pstatus_t general_andC_32u( /* ---------------------------------------------------------------------------- * 32-bit OR with a constant. */ -PRIM_STATIC pstatus_t general_orC_32u( +pstatus_t general_orC_32u( const UINT32 *pSrc, UINT32 val, UINT32 *pDst, @@ -70,16 +59,6 @@ PRIM_STATIC pstatus_t general_orC_32u( return PRIMITIVES_SUCCESS; } -#ifdef WITH_SSE2 -# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) -/* ------------------------------------------------------------------------- */ -SSE3_SCD_PRE_ROUTINE(sse3_andC_32u, UINT32, general_andC_32u, - _mm_and_si128, *dptr++ = *sptr++ & val) -SSE3_SCD_PRE_ROUTINE(sse3_orC_32u, UINT32, general_orC_32u, - _mm_or_si128, *dptr++ = *sptr++ | val) -# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ -#endif - /* ------------------------------------------------------------------------- */ void primitives_init_andor( const primitives_hints_t *hints, @@ -89,17 +68,7 @@ void primitives_init_andor( prims->andC_32u = general_andC_32u; prims->orC_32u = general_orC_32u; -#if defined(WITH_IPP) - prims->andC_32u = (__andC_32u_t) ippsAndC_32u; - prims->orC_32u = (__orC_32u_t) ippsOrC_32u; -#elif defined(WITH_SSE2) - if ((hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) - && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) - { - prims->andC_32u = sse3_andC_32u; - prims->orC_32u = sse3_orC_32u; - } -#endif + primitives_init_andor_opt(hints, prims); } /* ------------------------------------------------------------------------- */ @@ -108,3 +77,4 @@ void primitives_deinit_andor( { /* Nothing to do. */ } + diff --git a/libfreerdp/primitives/prim_andor.h b/libfreerdp/primitives/prim_andor.h new file mode 100644 index 000000000..6a2e7ac46 --- /dev/null +++ b/libfreerdp/primitives/prim_andor.h @@ -0,0 +1,31 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Logical operations. + * vi:ts=4 sw=4 + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. Algorithms used by + * this code may be covered by patents by HP, Microsoft, or other parties. + * + */ + +#ifdef __GNUC__ +# pragma once +#endif + +#ifndef __PRIM_ANDOR_H_INCLUDED__ +#define __PRIM_ANDOR_H_INCLUDED__ + +pstatus_t general_andC_32u(const UINT32 *pSrc, UINT32 val, UINT32 *pDst, INT32 len); +pstatus_t general_orC_32u(const UINT32 *pSrc, UINT32 val, UINT32 *pDst, INT32 len); + +void primitives_init_andor_opt(const primitives_hints_t *hints, primitives_t *prims); + +#endif /* !__PRIM_ANDOR_H_INCLUDED__ */ + diff --git a/libfreerdp/primitives/prim_andor_opt.c b/libfreerdp/primitives/prim_andor_opt.c new file mode 100644 index 000000000..e0ce1ea5b --- /dev/null +++ b/libfreerdp/primitives/prim_andor_opt.c @@ -0,0 +1,62 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Optimized Logical operations. + * vi:ts=4 sw=4: + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef WITH_SSE2 +#include +#include +#endif /* WITH_SSE2 */ + +#ifdef WITH_IPP +#include +#endif /* WITH_IPP */ + +#include "prim_internal.h" +#include "prim_templates.h" +#include "prim_andor.h" + +#ifdef WITH_SSE2 +# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) +/* ------------------------------------------------------------------------- */ +SSE3_SCD_PRE_ROUTINE(sse3_andC_32u, UINT32, general_andC_32u, + _mm_and_si128, *dptr++ = *sptr++ & val) +SSE3_SCD_PRE_ROUTINE(sse3_orC_32u, UINT32, general_orC_32u, + _mm_or_si128, *dptr++ = *sptr++ | val) +# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ +#endif + + +/* ------------------------------------------------------------------------- */ +void primitives_init_andor_opt(const primitives_hints_t *hints, primitives_t *prims) +{ +#if defined(WITH_IPP) + prims->andC_32u = (__andC_32u_t) ippsAndC_32u; + prims->orC_32u = (__orC_32u_t) ippsOrC_32u; +#elif defined(WITH_SSE2) + if ((hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) + && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) + { + prims->andC_32u = sse3_andC_32u; + prims->orC_32u = sse3_orC_32u; + } +#endif +} + diff --git a/libfreerdp/primitives/prim_colors.c b/libfreerdp/primitives/prim_colors.c index e6e7a18bf..179e569b7 100644 --- a/libfreerdp/primitives/prim_colors.c +++ b/libfreerdp/primitives/prim_colors.c @@ -21,16 +21,11 @@ #include "config.h" #endif -#include #include #include -#ifdef WITH_SSE2 -#include -#elif defined(WITH_NEON) -#include -#endif /* WITH_SSE2 else WITH_NEON */ + #include "prim_internal.h" -#include "prim_templates.h" +#include "prim_colors.h" #ifndef MINMAX #define MINMAX(_v_, _l_, _h_) \ @@ -38,7 +33,7 @@ #endif /* !MINMAX */ /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_yCbCrToRGB_16s16s_P3P3( +pstatus_t general_yCbCrToRGB_16s16s_P3P3( const INT16 *pSrc[3], INT32 srcStep, INT16 *pDst[3], INT32 dstStep, const prim_size_t *roi) /* region of interest */ @@ -119,7 +114,7 @@ PRIM_STATIC pstatus_t general_yCbCrToRGB_16s16s_P3P3( } /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_RGBToYCbCr_16s16s_P3P3( +pstatus_t general_RGBToYCbCr_16s16s_P3P3( const INT16 *pSrc[3], INT32 srcStep, INT16 *pDst[3], INT32 dstStep, const prim_size_t *roi) /* region of interest */ @@ -187,7 +182,7 @@ PRIM_STATIC pstatus_t general_RGBToYCbCr_16s16s_P3P3( } /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_RGBToRGB_16s8u_P3AC4R( +pstatus_t general_RGBToRGB_16s8u_P3AC4R( const INT16 *pSrc[3], /* 16-bit R,G, and B arrays */ int srcStep, /* bytes between rows in source data */ BYTE *pDst, /* 32-bit interleaved ARGB (ABGR?) data */ @@ -219,500 +214,6 @@ PRIM_STATIC pstatus_t general_RGBToRGB_16s8u_P3AC4R( return PRIMITIVES_SUCCESS; } - -#ifdef WITH_SSE2 - -#ifdef __GNUC__ -# define GNU_INLINE \ - __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -#else -# define GNU_INLINE -#endif - -#define CACHE_LINE_BYTES 64 - -#define _mm_between_epi16(_val, _min, _max) \ - do { _val = _mm_min_epi16(_max, _mm_max_epi16(_val, _min)); } while (0) - -#ifdef DO_PREFETCH -/*---------------------------------------------------------------------------*/ -static inline void GNU_INLINE _mm_prefetch_buffer( - char * buffer, - int num_bytes) -{ - __m128i * buf = (__m128i*) buffer; - unsigned int i; - for (i = 0; i < (num_bytes / sizeof(__m128i)); - i+=(CACHE_LINE_BYTES / sizeof(__m128i))) - { - _mm_prefetch((char*)(&buf[i]), _MM_HINT_NTA); - } -} -#endif /* DO_PREFETCH */ - -/*---------------------------------------------------------------------------*/ -PRIM_STATIC pstatus_t sse2_yCbCrToRGB_16s16s_P3P3( - const INT16 *pSrc[3], - int srcStep, - INT16 *pDst[3], - int dstStep, - const prim_size_t *roi) /* region of interest */ -{ - __m128i zero, max, r_cr, g_cb, g_cr, b_cb, c4096; - __m128i *y_buf, *cb_buf, *cr_buf, *r_buf, *g_buf, *b_buf; - int srcbump, dstbump, yp, imax; - - if (((ULONG_PTR) (pSrc[0]) & 0x0f) - || ((ULONG_PTR) (pSrc[1]) & 0x0f) - || ((ULONG_PTR) (pSrc[2]) & 0x0f) - || ((ULONG_PTR) (pDst[0]) & 0x0f) - || ((ULONG_PTR) (pDst[1]) & 0x0f) - || ((ULONG_PTR) (pDst[2]) & 0x0f) - || (roi->width & 0x07) - || (srcStep & 127) - || (dstStep & 127)) - { - /* We can't maintain 16-byte alignment. */ - return general_yCbCrToRGB_16s16s_P3P3(pSrc, srcStep, - pDst, dstStep, roi); - } - - zero = _mm_setzero_si128(); - max = _mm_set1_epi16(255); - - y_buf = (__m128i*) (pSrc[0]); - cb_buf = (__m128i*) (pSrc[1]); - cr_buf = (__m128i*) (pSrc[2]); - r_buf = (__m128i*) (pDst[0]); - g_buf = (__m128i*) (pDst[1]); - b_buf = (__m128i*) (pDst[2]); - - r_cr = _mm_set1_epi16(22986); /* 1.403 << 14 */ - g_cb = _mm_set1_epi16(-5636); /* -0.344 << 14 */ - g_cr = _mm_set1_epi16(-11698); /* -0.714 << 14 */ - b_cb = _mm_set1_epi16(28999); /* 1.770 << 14 */ - c4096 = _mm_set1_epi16(4096); - srcbump = srcStep / sizeof(__m128i); - dstbump = dstStep / sizeof(__m128i); - -#ifdef DO_PREFETCH - /* Prefetch Y's, Cb's, and Cr's. */ - for (yp=0; ypheight; yp++) - { - int i; - for (i=0; iwidth * sizeof(INT16) / sizeof(__m128i); - i += (CACHE_LINE_BYTES / sizeof(__m128i))) - { - _mm_prefetch((char*)(&y_buf[i]), _MM_HINT_NTA); - _mm_prefetch((char*)(&cb_buf[i]), _MM_HINT_NTA); - _mm_prefetch((char*)(&cr_buf[i]), _MM_HINT_NTA); - } - y_buf += srcbump; - cb_buf += srcbump; - cr_buf += srcbump; - } - y_buf = (__m128i*) (pSrc[0]); - cb_buf = (__m128i*) (pSrc[1]); - cr_buf = (__m128i*) (pSrc[2]); -#endif /* DO_PREFETCH */ - - imax = roi->width * sizeof(INT16) / sizeof(__m128i); - for (yp=0; ypheight; ++yp) - { - int i; - for (i=0; i>5) + 128 + (cr*1.403)>>5 // our base formula - * r = (y>>5) + 128 + (HIWORD(cr*(1.403<<14)<<2))>>5 // see above - * r = (y+4096)>>5 + (HIWORD(cr*22986)<<2)>>5 // simplification - * r = ((y+4096)>>2 + HIWORD(cr*22986)) >> 3 - */ - - /* y = (y_r_buf[i] + 4096) >> 2 */ - __m128i y, cb, cr, r, g, b; - y = _mm_load_si128(y_buf + i); - y = _mm_add_epi16(y, c4096); - y = _mm_srai_epi16(y, 2); - /* cb = cb_g_buf[i]; */ - cb = _mm_load_si128(cb_buf + i); - /* cr = cr_b_buf[i]; */ - cr = _mm_load_si128(cr_buf + i); - - /* (y + HIWORD(cr*22986)) >> 3 */ - r = _mm_add_epi16(y, _mm_mulhi_epi16(cr, r_cr)); - r = _mm_srai_epi16(r, 3); - - /* r_buf[i] = MINMAX(r, 0, 255); */ - _mm_between_epi16(r, zero, max); - _mm_store_si128(r_buf + i, r); - - /* (y + HIWORD(cb*-5636) + HIWORD(cr*-11698)) >> 3 */ - g = _mm_add_epi16(y, _mm_mulhi_epi16(cb, g_cb)); - g = _mm_add_epi16(g, _mm_mulhi_epi16(cr, g_cr)); - g = _mm_srai_epi16(g, 3); - - /* g_buf[i] = MINMAX(g, 0, 255); */ - _mm_between_epi16(g, zero, max); - _mm_store_si128(g_buf + i, g); - - /* (y + HIWORD(cb*28999)) >> 3 */ - b = _mm_add_epi16(y, _mm_mulhi_epi16(cb, b_cb)); - b = _mm_srai_epi16(b, 3); - /* b_buf[i] = MINMAX(b, 0, 255); */ - _mm_between_epi16(b, zero, max); - _mm_store_si128(b_buf + i, b); - } - y_buf += srcbump; - cb_buf += srcbump; - cr_buf += srcbump; - r_buf += dstbump; - g_buf += dstbump; - b_buf += dstbump; - } - - return PRIMITIVES_SUCCESS; -} - -/*---------------------------------------------------------------------------*/ -/* The encodec YCbCr coeffectients are represented as 11.5 fixed-point - * numbers. See the general code above. - */ -PRIM_STATIC pstatus_t sse2_RGBToYCbCr_16s16s_P3P3( - const INT16 *pSrc[3], - int srcStep, - INT16 *pDst[3], - int dstStep, - const prim_size_t *roi) /* region of interest */ -{ - __m128i min, max, y_r, y_g, y_b, cb_r, cb_g, cb_b, cr_r, cr_g, cr_b; - __m128i *r_buf, *g_buf, *b_buf, *y_buf, *cb_buf, *cr_buf; - int srcbump, dstbump, yp, imax; - - if (((ULONG_PTR) (pSrc[0]) & 0x0f) - || ((ULONG_PTR) (pSrc[1]) & 0x0f) - || ((ULONG_PTR) (pSrc[2]) & 0x0f) - || ((ULONG_PTR) (pDst[0]) & 0x0f) - || ((ULONG_PTR) (pDst[1]) & 0x0f) - || ((ULONG_PTR) (pDst[2]) & 0x0f) - || (roi->width & 0x07) - || (srcStep & 127) - || (dstStep & 127)) - { - /* We can't maintain 16-byte alignment. */ - return general_RGBToYCbCr_16s16s_P3P3(pSrc, srcStep, - pDst, dstStep, roi); - } - - min = _mm_set1_epi16(-128 << 5); - max = _mm_set1_epi16(127 << 5); - - r_buf = (__m128i*) (pSrc[0]); - g_buf = (__m128i*) (pSrc[1]); - b_buf = (__m128i*) (pSrc[2]); - y_buf = (__m128i*) (pDst[0]); - cb_buf = (__m128i*) (pDst[1]); - cr_buf = (__m128i*) (pDst[2]); - - y_r = _mm_set1_epi16(9798); /* 0.299000 << 15 */ - y_g = _mm_set1_epi16(19235); /* 0.587000 << 15 */ - y_b = _mm_set1_epi16(3735); /* 0.114000 << 15 */ - cb_r = _mm_set1_epi16(-5535); /* -0.168935 << 15 */ - cb_g = _mm_set1_epi16(-10868); /* -0.331665 << 15 */ - cb_b = _mm_set1_epi16(16403); /* 0.500590 << 15 */ - cr_r = _mm_set1_epi16(16377); /* 0.499813 << 15 */ - cr_g = _mm_set1_epi16(-13714); /* -0.418531 << 15 */ - cr_b = _mm_set1_epi16(-2663); /* -0.081282 << 15 */ - - srcbump = srcStep / sizeof(__m128i); - dstbump = dstStep / sizeof(__m128i); - -#ifdef DO_PREFETCH - /* Prefetch RGB's. */ - for (yp=0; ypheight; yp++) - { - int i; - for (i=0; iwidth * sizeof(INT16) / sizeof(__m128i); - i += (CACHE_LINE_BYTES / sizeof(__m128i))) - { - _mm_prefetch((char*)(&r_buf[i]), _MM_HINT_NTA); - _mm_prefetch((char*)(&g_buf[i]), _MM_HINT_NTA); - _mm_prefetch((char*)(&b_buf[i]), _MM_HINT_NTA); - } - r_buf += srcbump; - g_buf += srcbump; - b_buf += srcbump; - } - r_buf = (__m128i*) (pSrc[0]); - g_buf = (__m128i*) (pSrc[1]); - b_buf = (__m128i*) (pSrc[2]); -#endif /* DO_PREFETCH */ - - imax = roi->width * sizeof(INT16) / sizeof(__m128i); - for (yp=0; ypheight; ++yp) - { - int i; - for (i=0; iwidth & 0x0f) - || (srcStep & 0x0f) - || (dstStep & 0x0f)) - { - return general_RGBToRGB_16s8u_P3AC4R(pSrc, srcStep, pDst, dstStep, roi); - } - - out = (BYTE *) pDst; - srcbump = (srcStep - (roi->width * sizeof(UINT16))) / sizeof(UINT16); - dstbump = (dstStep - (roi->width * sizeof(UINT32))); - - for (y=0; yheight; ++y) - { - int width = roi->width; - do { - __m128i R0, R1, R2, R3, R4; - /* The comments below pretend these are 8-byte registers - * rather than 16-byte, for readability. - */ - R0 = LOAD128(b); b += 8; /* R0 = 00B300B200B100B0 */ - R1 = LOAD128(b); b += 8; /* R1 = 00B700B600B500B4 */ - PACKUSWB(R0,R1); /* R0 = B7B6B5B4B3B2B1B0 */ - R1 = LOAD128(g); g += 8; /* R1 = 00G300G200G100G0 */ - R2 = LOAD128(g); g += 8; /* R2 = 00G700G600G500G4 */ - PACKUSWB(R1,R2); /* R1 = G7G6G5G4G3G2G1G0 */ - R2 = R1; /* R2 = G7G6G5G4G3G2G1G0 */ - PUNPCKLBW(R2,R0); /* R2 = G3B3G2B2G1B1G0B0 */ - PUNPCKHBW(R1,R0); /* R1 = G7B7G6B7G5B5G4B4 */ - R0 = LOAD128(r); r += 8; /* R0 = 00R300R200R100R0 */ - R3 = LOAD128(r); r += 8; /* R3 = 00R700R600R500R4 */ - PACKUSWB(R0,R3); /* R0 = R7R6R5R4R3R2R1R0 */ - R3 = XMM_ALL_ONES; /* R3 = FFFFFFFFFFFFFFFF */ - R4 = R3; /* R4 = FFFFFFFFFFFFFFFF */ - PUNPCKLBW(R4,R0); /* R4 = FFR3FFR2FFR1FFR0 */ - PUNPCKHBW(R3,R0); /* R3 = FFR7FFR6FFR5FFR4 */ - R0 = R4; /* R0 = R4 */ - PUNPCKLWD(R0,R2); /* R0 = FFR1G1B1FFR0G0B0 */ - PUNPCKHWD(R4,R2); /* R4 = FFR3G3B3FFR2G2B2 */ - R2 = R3; /* R2 = R3 */ - PUNPCKLWD(R2,R1); /* R2 = FFR5G5B5FFR4G4B4 */ - PUNPCKHWD(R3,R1); /* R3 = FFR7G7B7FFR6G6B6 */ - STORE128(out, R0); out += 16; /* FFR1G1B1FFR0G0B0 */ - STORE128(out, R4); out += 16; /* FFR3G3B3FFR2G2B2 */ - STORE128(out, R2); out += 16; /* FFR5G5B5FFR4G4B4 */ - STORE128(out, R3); out += 16; /* FFR7G7B7FFR6G6B6 */ - } while (width -= 16); - /* Jump to next row. */ - r += srcbump; - g += srcbump; - b += srcbump; - out += dstbump; - } - return PRIMITIVES_SUCCESS; -} -#endif /* WITH_SSE2 */ - -/*---------------------------------------------------------------------------*/ -#ifdef WITH_NEON -PRIM_STATIC pstatus_t neon_yCbCrToRGB_16s16s_P3P3( - const INT16 *pSrc[3], - int srcStep, - INT16 *pDst[3], - int dstStep, - const prim_size_t *roi) /* region of interest */ -{ - /* TODO: If necessary, check alignments and call the general version. */ - - int16x8_t zero = vdupq_n_s16(0); - int16x8_t max = vdupq_n_s16(255); - int16x8_t y_add = vdupq_n_s16(128); - - int16x8_t* y_buf = (int16x8_t*) pSrc[0]; - int16x8_t* cb_buf = (int16x8_t*) pSrc[1]; - int16x8_t* cr_buf = (int16x8_t*) pSrc[2]; - int16x8_t* r_buf = (int16x8_t*) pDst[0]; - int16x8_t* g_buf = (int16x8_t*) pDst[1]; - int16x8_t* b_buf = (int16x8_t*) pDst[2]; - - int srcbump = srcStep / sizeof(int16x8_t); - int dstbump = dstStep / sizeof(int16x8_t); - int yp; - - int imax = roi->width * sizeof(INT16) / sizeof(int16x8_t); - for (yp=0; ypheight; ++yp) - { - int i; - for (i=0; i> 2) + (cr >> 3) + (cr >> 5)), - * 0, 255); - */ - int16x8_t r = vaddq_s16(y, cr); - r = vaddq_s16(r, vshrq_n_s16(cr, 2)); - r = vaddq_s16(r, vshrq_n_s16(cr, 3)); - r = vaddq_s16(r, vshrq_n_s16(cr, 5)); - r = vminq_s16(vmaxq_s16(r, zero), max); - vst1q_s16((INT16*) (r_buf+i), r); - - /* cb = cb_g_buf[i]; */ - int16x8_t cb = vld1q_s16((INT16*) (cb_buf+i)); - - /* g = between(y - (cb >> 2) - (cb >> 4) - (cb >> 5) - (cr >> 1) - * - (cr >> 3) - (cr >> 4) - (cr >> 5), 0, 255); - */ - int16x8_t g = vsubq_s16(y, vshrq_n_s16(cb, 2)); - g = vsubq_s16(g, vshrq_n_s16(cb, 4)); - g = vsubq_s16(g, vshrq_n_s16(cb, 5)); - g = vsubq_s16(g, vshrq_n_s16(cr, 1)); - g = vsubq_s16(g, vshrq_n_s16(cr, 3)); - g = vsubq_s16(g, vshrq_n_s16(cr, 4)); - g = vsubq_s16(g, vshrq_n_s16(cr, 5)); - g = vminq_s16(vmaxq_s16(g, zero), max); - vst1q_s16((INT16*) (g_buf+i), g); - - /* b = between((y + cb + (cb >> 1) + (cb >> 2) + (cb >> 6)), - * 0, 255); - */ - int16x8_t b = vaddq_s16(y, cb); - b = vaddq_s16(b, vshrq_n_s16(cb, 1)); - b = vaddq_s16(b, vshrq_n_s16(cb, 2)); - b = vaddq_s16(b, vshrq_n_s16(cb, 6)); - b = vminq_s16(vmaxq_s16(b, zero), max); - vst1q_s16((INT16*) (b_buf+i), b); - } - y_buf += srcbump; - cb_buf += srcbump; - cr_buf += srcbump; - r_buf += dstbump; - g_buf += dstbump; - b_buf += dstbump; - } - return PRIMITIVES_SUCCESS; -} -#endif /* WITH_NEON */ - - -/* I don't see a direct IPP version of this, since the input is INT16 - * YCbCr. It may be possible via Deinterleave and then YCbCrToRGB_. - * But that would likely be slower. - */ - /* ------------------------------------------------------------------------- */ void primitives_init_colors(const primitives_hints_t* hints, primitives_t* prims) { @@ -720,19 +221,7 @@ void primitives_init_colors(const primitives_hints_t* hints, primitives_t* prims prims->yCbCrToRGB_16s16s_P3P3 = general_yCbCrToRGB_16s16s_P3P3; prims->RGBToYCbCr_16s16s_P3P3 = general_RGBToYCbCr_16s16s_P3P3; -#if defined(WITH_SSE2) - if (hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) - { - prims->RGBToRGB_16s8u_P3AC4R = sse2_RGBToRGB_16s8u_P3AC4R; - prims->yCbCrToRGB_16s16s_P3P3 = sse2_yCbCrToRGB_16s16s_P3P3; - prims->RGBToYCbCr_16s16s_P3P3 = sse2_RGBToYCbCr_16s16s_P3P3; - } -#elif defined(WITH_NEON) - if (hints->arm_flags & PRIM_ARM_NEON_AVAILABLE) - { - prims->yCbCrToRGB_16s16s_P3P3 = neon_yCbCrToRGB_16s16s_P3P3; - } -#endif /* WITH_SSE2 */ + primitives_init_colors_opt(hints, prims); } /* ------------------------------------------------------------------------- */ @@ -740,3 +229,4 @@ void primitives_deinit_colors(primitives_t* prims) { /* Nothing to do. */ } + diff --git a/libfreerdp/primitives/prim_colors.h b/libfreerdp/primitives/prim_colors.h new file mode 100644 index 000000000..70f478547 --- /dev/null +++ b/libfreerdp/primitives/prim_colors.h @@ -0,0 +1,32 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Color conversion operations. + * vi:ts=4 sw=4 + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. Algorithms used by + * this code may be covered by patents by HP, Microsoft, or other parties. + * + */ + +#ifdef __GNUC__ +# pragma once +#endif + +#ifndef __PRIM_COLORS_H_INCLUDED__ +#define __PRIM_COLORS_H_INCLUDED__ + +pstatus_t general_yCbCrToRGB_16s16s_P3P3(const INT16 *pSrc[3], INT32 srcStep, INT16 *pDst[3], INT32 dstStep, const prim_size_t *roi); +pstatus_t general_RGBToYCbCr_16s16s_P3P3(const INT16 *pSrc[3], INT32 srcStep, INT16 *pDst[3], INT32 dstStep, const prim_size_t *roi); +pstatus_t general_RGBToRGB_16s8u_P3AC4R(const INT16 *pSrc[3], int srcStep, BYTE *pDst, int dstStep, const prim_size_t *roi); + +void primitives_init_colors_opt(const primitives_hints_t* hints, primitives_t* prims); + +#endif /* !__PRIM_COLORS_H_INCLUDED__ */ + diff --git a/libfreerdp/primitives/prim_colors_opt.c b/libfreerdp/primitives/prim_colors_opt.c new file mode 100644 index 000000000..cfc87414e --- /dev/null +++ b/libfreerdp/primitives/prim_colors_opt.c @@ -0,0 +1,561 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Optimized Color conversion operations. + * vi:ts=4 sw=4: + * + * Copyright 2011 Stephen Erisman + * Copyright 2011 Norbert Federa + * Copyright 2011 Martin Fleisz + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef WITH_SSE2 +#include +#elif defined(WITH_NEON) +#include +#endif /* WITH_SSE2 else WITH_NEON */ + +#include "prim_internal.h" +#include "prim_templates.h" +#include "prim_colors.h" + +#ifdef WITH_SSE2 + +#ifdef __GNUC__ +# define GNU_INLINE \ + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +#else +# define GNU_INLINE +#endif + +#define CACHE_LINE_BYTES 64 + +#define _mm_between_epi16(_val, _min, _max) \ + do { _val = _mm_min_epi16(_max, _mm_max_epi16(_val, _min)); } while (0) + +#ifdef DO_PREFETCH +/*---------------------------------------------------------------------------*/ +static inline void GNU_INLINE _mm_prefetch_buffer( + char * buffer, + int num_bytes) +{ + __m128i * buf = (__m128i*) buffer; + unsigned int i; + for (i = 0; i < (num_bytes / sizeof(__m128i)); + i+=(CACHE_LINE_BYTES / sizeof(__m128i))) + { + _mm_prefetch((char*)(&buf[i]), _MM_HINT_NTA); + } +} +#endif /* DO_PREFETCH */ + +/*---------------------------------------------------------------------------*/ +pstatus_t sse2_yCbCrToRGB_16s16s_P3P3( + const INT16 *pSrc[3], + int srcStep, + INT16 *pDst[3], + int dstStep, + const prim_size_t *roi) /* region of interest */ +{ + __m128i zero, max, r_cr, g_cb, g_cr, b_cb, c4096; + __m128i *y_buf, *cb_buf, *cr_buf, *r_buf, *g_buf, *b_buf; + int srcbump, dstbump, yp, imax; + + if (((ULONG_PTR) (pSrc[0]) & 0x0f) + || ((ULONG_PTR) (pSrc[1]) & 0x0f) + || ((ULONG_PTR) (pSrc[2]) & 0x0f) + || ((ULONG_PTR) (pDst[0]) & 0x0f) + || ((ULONG_PTR) (pDst[1]) & 0x0f) + || ((ULONG_PTR) (pDst[2]) & 0x0f) + || (roi->width & 0x07) + || (srcStep & 127) + || (dstStep & 127)) + { + /* We can't maintain 16-byte alignment. */ + return general_yCbCrToRGB_16s16s_P3P3(pSrc, srcStep, + pDst, dstStep, roi); + } + + zero = _mm_setzero_si128(); + max = _mm_set1_epi16(255); + + y_buf = (__m128i*) (pSrc[0]); + cb_buf = (__m128i*) (pSrc[1]); + cr_buf = (__m128i*) (pSrc[2]); + r_buf = (__m128i*) (pDst[0]); + g_buf = (__m128i*) (pDst[1]); + b_buf = (__m128i*) (pDst[2]); + + r_cr = _mm_set1_epi16(22986); /* 1.403 << 14 */ + g_cb = _mm_set1_epi16(-5636); /* -0.344 << 14 */ + g_cr = _mm_set1_epi16(-11698); /* -0.714 << 14 */ + b_cb = _mm_set1_epi16(28999); /* 1.770 << 14 */ + c4096 = _mm_set1_epi16(4096); + srcbump = srcStep / sizeof(__m128i); + dstbump = dstStep / sizeof(__m128i); + +#ifdef DO_PREFETCH + /* Prefetch Y's, Cb's, and Cr's. */ + for (yp=0; ypheight; yp++) + { + int i; + for (i=0; iwidth * sizeof(INT16) / sizeof(__m128i); + i += (CACHE_LINE_BYTES / sizeof(__m128i))) + { + _mm_prefetch((char*)(&y_buf[i]), _MM_HINT_NTA); + _mm_prefetch((char*)(&cb_buf[i]), _MM_HINT_NTA); + _mm_prefetch((char*)(&cr_buf[i]), _MM_HINT_NTA); + } + y_buf += srcbump; + cb_buf += srcbump; + cr_buf += srcbump; + } + y_buf = (__m128i*) (pSrc[0]); + cb_buf = (__m128i*) (pSrc[1]); + cr_buf = (__m128i*) (pSrc[2]); +#endif /* DO_PREFETCH */ + + imax = roi->width * sizeof(INT16) / sizeof(__m128i); + for (yp=0; ypheight; ++yp) + { + int i; + for (i=0; i>5) + 128 + (cr*1.403)>>5 // our base formula + * r = (y>>5) + 128 + (HIWORD(cr*(1.403<<14)<<2))>>5 // see above + * r = (y+4096)>>5 + (HIWORD(cr*22986)<<2)>>5 // simplification + * r = ((y+4096)>>2 + HIWORD(cr*22986)) >> 3 + */ + + /* y = (y_r_buf[i] + 4096) >> 2 */ + __m128i y, cb, cr, r, g, b; + y = _mm_load_si128(y_buf + i); + y = _mm_add_epi16(y, c4096); + y = _mm_srai_epi16(y, 2); + /* cb = cb_g_buf[i]; */ + cb = _mm_load_si128(cb_buf + i); + /* cr = cr_b_buf[i]; */ + cr = _mm_load_si128(cr_buf + i); + + /* (y + HIWORD(cr*22986)) >> 3 */ + r = _mm_add_epi16(y, _mm_mulhi_epi16(cr, r_cr)); + r = _mm_srai_epi16(r, 3); + + /* r_buf[i] = MINMAX(r, 0, 255); */ + _mm_between_epi16(r, zero, max); + _mm_store_si128(r_buf + i, r); + + /* (y + HIWORD(cb*-5636) + HIWORD(cr*-11698)) >> 3 */ + g = _mm_add_epi16(y, _mm_mulhi_epi16(cb, g_cb)); + g = _mm_add_epi16(g, _mm_mulhi_epi16(cr, g_cr)); + g = _mm_srai_epi16(g, 3); + + /* g_buf[i] = MINMAX(g, 0, 255); */ + _mm_between_epi16(g, zero, max); + _mm_store_si128(g_buf + i, g); + + /* (y + HIWORD(cb*28999)) >> 3 */ + b = _mm_add_epi16(y, _mm_mulhi_epi16(cb, b_cb)); + b = _mm_srai_epi16(b, 3); + /* b_buf[i] = MINMAX(b, 0, 255); */ + _mm_between_epi16(b, zero, max); + _mm_store_si128(b_buf + i, b); + } + y_buf += srcbump; + cb_buf += srcbump; + cr_buf += srcbump; + r_buf += dstbump; + g_buf += dstbump; + b_buf += dstbump; + } + + return PRIMITIVES_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +/* The encodec YCbCr coeffectients are represented as 11.5 fixed-point + * numbers. See the general code above. + */ +pstatus_t sse2_RGBToYCbCr_16s16s_P3P3( + const INT16 *pSrc[3], + int srcStep, + INT16 *pDst[3], + int dstStep, + const prim_size_t *roi) /* region of interest */ +{ + __m128i min, max, y_r, y_g, y_b, cb_r, cb_g, cb_b, cr_r, cr_g, cr_b; + __m128i *r_buf, *g_buf, *b_buf, *y_buf, *cb_buf, *cr_buf; + int srcbump, dstbump, yp, imax; + + if (((ULONG_PTR) (pSrc[0]) & 0x0f) + || ((ULONG_PTR) (pSrc[1]) & 0x0f) + || ((ULONG_PTR) (pSrc[2]) & 0x0f) + || ((ULONG_PTR) (pDst[0]) & 0x0f) + || ((ULONG_PTR) (pDst[1]) & 0x0f) + || ((ULONG_PTR) (pDst[2]) & 0x0f) + || (roi->width & 0x07) + || (srcStep & 127) + || (dstStep & 127)) + { + /* We can't maintain 16-byte alignment. */ + return general_RGBToYCbCr_16s16s_P3P3(pSrc, srcStep, + pDst, dstStep, roi); + } + + min = _mm_set1_epi16(-128 << 5); + max = _mm_set1_epi16(127 << 5); + + r_buf = (__m128i*) (pSrc[0]); + g_buf = (__m128i*) (pSrc[1]); + b_buf = (__m128i*) (pSrc[2]); + y_buf = (__m128i*) (pDst[0]); + cb_buf = (__m128i*) (pDst[1]); + cr_buf = (__m128i*) (pDst[2]); + + y_r = _mm_set1_epi16(9798); /* 0.299000 << 15 */ + y_g = _mm_set1_epi16(19235); /* 0.587000 << 15 */ + y_b = _mm_set1_epi16(3735); /* 0.114000 << 15 */ + cb_r = _mm_set1_epi16(-5535); /* -0.168935 << 15 */ + cb_g = _mm_set1_epi16(-10868); /* -0.331665 << 15 */ + cb_b = _mm_set1_epi16(16403); /* 0.500590 << 15 */ + cr_r = _mm_set1_epi16(16377); /* 0.499813 << 15 */ + cr_g = _mm_set1_epi16(-13714); /* -0.418531 << 15 */ + cr_b = _mm_set1_epi16(-2663); /* -0.081282 << 15 */ + + srcbump = srcStep / sizeof(__m128i); + dstbump = dstStep / sizeof(__m128i); + +#ifdef DO_PREFETCH + /* Prefetch RGB's. */ + for (yp=0; ypheight; yp++) + { + int i; + for (i=0; iwidth * sizeof(INT16) / sizeof(__m128i); + i += (CACHE_LINE_BYTES / sizeof(__m128i))) + { + _mm_prefetch((char*)(&r_buf[i]), _MM_HINT_NTA); + _mm_prefetch((char*)(&g_buf[i]), _MM_HINT_NTA); + _mm_prefetch((char*)(&b_buf[i]), _MM_HINT_NTA); + } + r_buf += srcbump; + g_buf += srcbump; + b_buf += srcbump; + } + r_buf = (__m128i*) (pSrc[0]); + g_buf = (__m128i*) (pSrc[1]); + b_buf = (__m128i*) (pSrc[2]); +#endif /* DO_PREFETCH */ + + imax = roi->width * sizeof(INT16) / sizeof(__m128i); + for (yp=0; ypheight; ++yp) + { + int i; + for (i=0; iwidth & 0x0f) + || (srcStep & 0x0f) + || (dstStep & 0x0f)) + { + return general_RGBToRGB_16s8u_P3AC4R(pSrc, srcStep, pDst, dstStep, roi); + } + + out = (BYTE *) pDst; + srcbump = (srcStep - (roi->width * sizeof(UINT16))) / sizeof(UINT16); + dstbump = (dstStep - (roi->width * sizeof(UINT32))); + + for (y=0; yheight; ++y) + { + int width = roi->width; + do { + __m128i R0, R1, R2, R3, R4; + /* The comments below pretend these are 8-byte registers + * rather than 16-byte, for readability. + */ + R0 = LOAD128(b); b += 8; /* R0 = 00B300B200B100B0 */ + R1 = LOAD128(b); b += 8; /* R1 = 00B700B600B500B4 */ + PACKUSWB(R0,R1); /* R0 = B7B6B5B4B3B2B1B0 */ + R1 = LOAD128(g); g += 8; /* R1 = 00G300G200G100G0 */ + R2 = LOAD128(g); g += 8; /* R2 = 00G700G600G500G4 */ + PACKUSWB(R1,R2); /* R1 = G7G6G5G4G3G2G1G0 */ + R2 = R1; /* R2 = G7G6G5G4G3G2G1G0 */ + PUNPCKLBW(R2,R0); /* R2 = G3B3G2B2G1B1G0B0 */ + PUNPCKHBW(R1,R0); /* R1 = G7B7G6B7G5B5G4B4 */ + R0 = LOAD128(r); r += 8; /* R0 = 00R300R200R100R0 */ + R3 = LOAD128(r); r += 8; /* R3 = 00R700R600R500R4 */ + PACKUSWB(R0,R3); /* R0 = R7R6R5R4R3R2R1R0 */ + R3 = XMM_ALL_ONES; /* R3 = FFFFFFFFFFFFFFFF */ + R4 = R3; /* R4 = FFFFFFFFFFFFFFFF */ + PUNPCKLBW(R4,R0); /* R4 = FFR3FFR2FFR1FFR0 */ + PUNPCKHBW(R3,R0); /* R3 = FFR7FFR6FFR5FFR4 */ + R0 = R4; /* R0 = R4 */ + PUNPCKLWD(R0,R2); /* R0 = FFR1G1B1FFR0G0B0 */ + PUNPCKHWD(R4,R2); /* R4 = FFR3G3B3FFR2G2B2 */ + R2 = R3; /* R2 = R3 */ + PUNPCKLWD(R2,R1); /* R2 = FFR5G5B5FFR4G4B4 */ + PUNPCKHWD(R3,R1); /* R3 = FFR7G7B7FFR6G6B6 */ + STORE128(out, R0); out += 16; /* FFR1G1B1FFR0G0B0 */ + STORE128(out, R4); out += 16; /* FFR3G3B3FFR2G2B2 */ + STORE128(out, R2); out += 16; /* FFR5G5B5FFR4G4B4 */ + STORE128(out, R3); out += 16; /* FFR7G7B7FFR6G6B6 */ + } while (width -= 16); + /* Jump to next row. */ + r += srcbump; + g += srcbump; + b += srcbump; + out += dstbump; + } + return PRIMITIVES_SUCCESS; +} +#endif /* WITH_SSE2 */ + +/*---------------------------------------------------------------------------*/ +#ifdef WITH_NEON +pstatus_t neon_yCbCrToRGB_16s16s_P3P3( + const INT16 *pSrc[3], + int srcStep, + INT16 *pDst[3], + int dstStep, + const prim_size_t *roi) /* region of interest */ +{ + /* TODO: If necessary, check alignments and call the general version. */ + + int16x8_t zero = vdupq_n_s16(0); + int16x8_t max = vdupq_n_s16(255); + + int16x8_t r_cr = vdupq_n_s16(22986); // 1.403 << 14 + int16x8_t g_cb = vdupq_n_s16(-5636); // -0.344 << 14 + int16x8_t g_cr = vdupq_n_s16(-11698); // -0.714 << 14 + int16x8_t b_cb = vdupq_n_s16(28999); // 1.770 << 14 + int16x8_t c4096 = vdupq_n_s16(4096); + + int16x8_t* y_buf = (int16x8_t*) pSrc[0]; + int16x8_t* cb_buf = (int16x8_t*) pSrc[1]; + int16x8_t* cr_buf = (int16x8_t*) pSrc[2]; + int16x8_t* r_buf = (int16x8_t*) pDst[0]; + int16x8_t* g_buf = (int16x8_t*) pDst[1]; + int16x8_t* b_buf = (int16x8_t*) pDst[2]; + + int srcbump = srcStep / sizeof(int16x8_t); + int dstbump = dstStep / sizeof(int16x8_t); + int yp; + + int imax = roi->width * sizeof(INT16) / sizeof(int16x8_t); + for (yp=0; ypheight; ++yp) + { + int i; + for (i=0; i>5) + 128 + (cr*1.403)>>5 // our base formula + r = (y>>5) + 128 + (HIWORD(cr*(1.403<<14)<<2))>>5 // see above + r = (y+4096)>>5 + (HIWORD(cr*22986)<<2)>>5 // simplification + r = ((y+4096)>>2 + HIWORD(cr*22986)) >> 3 + */ + + /* y = (y_buf[i] + 4096) >> 2 */ + int16x8_t y = vld1q_s16((INT16*) &y_buf[i]); + y = vaddq_s16(y, c4096); + y = vshrq_n_s16(y, 2); + /* cb = cb_buf[i]; */ + int16x8_t cb = vld1q_s16((INT16*)&cb_buf[i]); + /* cr = cr_buf[i]; */ + int16x8_t cr = vld1q_s16((INT16*) &cr_buf[i]); + + /* (y + HIWORD(cr*22986)) >> 3 */ + int16x8_t r = vaddq_s16(y, vshrq_n_s16(vqdmulhq_s16(cr, r_cr), 1)); + r = vshrq_n_s16(r, 3); + /* r_buf[i] = MINMAX(r, 0, 255); */ + r = vminq_s16(vmaxq_s16(r, zero), max); + vst1q_s16((INT16*)&r_buf[i], r); + + /* (y + HIWORD(cb*-5636) + HIWORD(cr*-11698)) >> 3 */ + int16x8_t g = vaddq_s16(y, vshrq_n_s16(vqdmulhq_s16(cb, g_cb), 1)); + g = vaddq_s16(g, vshrq_n_s16(vqdmulhq_s16(cr, g_cr), 1)); + g = vshrq_n_s16(g, 3); + /* g_buf[i] = MINMAX(g, 0, 255); */ + g = vminq_s16(vmaxq_s16(g, zero), max); + vst1q_s16((INT16*)&g_buf[i], g); + + /* (y + HIWORD(cb*28999)) >> 3 */ + int16x8_t b = vaddq_s16(y, vshrq_n_s16(vqdmulhq_s16(cb, b_cb), 1)); + b = vshrq_n_s16(b, 3); + /* b_buf[i] = MINMAX(b, 0, 255); */ + b = vminq_s16(vmaxq_s16(b, zero), max); + vst1q_s16((INT16*)&b_buf[i], b); + } + + y_buf += srcbump; + cb_buf += srcbump; + cr_buf += srcbump; + r_buf += dstbump; + g_buf += dstbump; + b_buf += dstbump; + } + return PRIMITIVES_SUCCESS; +} +#endif /* WITH_NEON */ + + +/* I don't see a direct IPP version of this, since the input is INT16 + * YCbCr. It may be possible via Deinterleave and then YCbCrToRGB_. + * But that would likely be slower. + */ + +/* ------------------------------------------------------------------------- */ +void primitives_init_colors_opt(const primitives_hints_t* hints, primitives_t* prims) +{ +#if defined(WITH_SSE2) + if (hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) + { + prims->RGBToRGB_16s8u_P3AC4R = sse2_RGBToRGB_16s8u_P3AC4R; + prims->yCbCrToRGB_16s16s_P3P3 = sse2_yCbCrToRGB_16s16s_P3P3; + prims->RGBToYCbCr_16s16s_P3P3 = sse2_RGBToYCbCr_16s16s_P3P3; + } +#elif defined(WITH_NEON) + if (hints->arm_flags & PRIM_ARM_NEON_AVAILABLE) + { + prims->yCbCrToRGB_16s16s_P3P3 = neon_yCbCrToRGB_16s16s_P3P3; + } +#endif /* WITH_SSE2 */ +} + diff --git a/libfreerdp/primitives/prim_copy.c b/libfreerdp/primitives/prim_copy.c index 71303b1a6..4198f2d8f 100644 --- a/libfreerdp/primitives/prim_copy.c +++ b/libfreerdp/primitives/prim_copy.c @@ -72,7 +72,7 @@ static BOOL memory_regions_overlap_2d( } /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_copy_8u( +pstatus_t general_copy_8u( const BYTE *pSrc, BYTE *pDst, INT32 len) @@ -94,7 +94,7 @@ PRIM_STATIC pstatus_t general_copy_8u( * The addresses are assumed to have been already offset to the upper-left * corners of the source and destination region of interest. */ -PRIM_STATIC pstatus_t general_copy_8u_AC4r( +pstatus_t general_copy_8u_AC4r( const BYTE *pSrc, INT32 srcStep, BYTE *pDst, INT32 dstStep, INT32 width, INT32 height) diff --git a/libfreerdp/primitives/prim_internal.h b/libfreerdp/primitives/prim_internal.h index 21df8cae0..001ab8562 100644 --- a/libfreerdp/primitives/prim_internal.h +++ b/libfreerdp/primitives/prim_internal.h @@ -27,15 +27,6 @@ #include -/* Normally the internal entrypoints should be static, but a benchmark - * program may want to access them directly and turn this off. - */ -#ifndef PRIM_STATIC -# define PRIM_STATIC static -#else -# undef PRIM_STATIC -# define PRIM_STATIC -#endif /* !PRIM_STATIC */ /* Use lddqu for unaligned; load for 16-byte aligned. */ #define LOAD_SI128(_ptr_) \ diff --git a/libfreerdp/primitives/prim_set.c b/libfreerdp/primitives/prim_set.c index 5b40ce00c..9176c8722 100644 --- a/libfreerdp/primitives/prim_set.c +++ b/libfreerdp/primitives/prim_set.c @@ -19,18 +19,15 @@ #endif #include + #include #include -#ifdef WITH_SSE2 -# include -#endif /* WITH_SSE2 */ -#ifdef WITH_IPP -# include -#endif /* WITH_IPP */ + #include "prim_internal.h" +#include "prim_set.h" /* ========================================================================= */ -PRIM_STATIC pstatus_t general_set_8u( +pstatus_t general_set_8u( BYTE val, BYTE *pDst, INT32 len) @@ -40,7 +37,7 @@ PRIM_STATIC pstatus_t general_set_8u( } /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_zero( +pstatus_t general_zero( void *pDst, size_t len) { @@ -48,75 +45,8 @@ PRIM_STATIC pstatus_t general_zero( return PRIMITIVES_SUCCESS; } -/* ------------------------------------------------------------------------- */ -#ifdef WITH_SSE2 -# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) -PRIM_STATIC pstatus_t sse2_set_8u( - BYTE val, - BYTE *pDst, - INT32 len) -{ - BYTE byte, *dptr; - __m128i xmm0; - size_t count; - - if (len < 16) return general_set_8u(val, pDst, len); - - byte = val; - dptr = (BYTE *) pDst; - - /* Seek 16-byte alignment. */ - while ((ULONG_PTR) dptr & 0x0f) - { - *dptr++ = byte; - if (--len == 0) return PRIMITIVES_SUCCESS; - } - - xmm0 = _mm_set1_epi8(byte); - - /* Cover 256-byte chunks via SSE register stores. */ - count = len >> 8; - len -= count << 8; - /* Do 256-byte chunks using one XMM register. */ - while (count--) - { - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - } - - /* Cover 16-byte chunks via SSE register stores. */ - count = len >> 4; - len -= count << 4; - /* Do 16-byte chunks using one XMM register. */ - while (count--) - { - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; - } - - /* Do leftover bytes. */ - while (len--) *dptr++ = byte; - - return PRIMITIVES_SUCCESS; -} -# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ -#endif /* WITH_SSE2 */ - /* ========================================================================= */ -PRIM_STATIC pstatus_t general_set_32s( +pstatus_t general_set_32s( INT32 val, INT32 *pDst, INT32 len) @@ -148,7 +78,7 @@ PRIM_STATIC pstatus_t general_set_32s( } /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_set_32u( +pstatus_t general_set_32u( UINT32 val, UINT32 *pDst, INT32 len) @@ -179,104 +109,6 @@ PRIM_STATIC pstatus_t general_set_32u( return PRIMITIVES_SUCCESS; } -/* ------------------------------------------------------------------------- */ -#ifdef WITH_SSE2 -# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) -PRIM_STATIC pstatus_t sse2_set_32u( - UINT32 val, - UINT32 *pDst, - INT32 len) -{ - UINT32 *dptr = (UINT32 *) pDst; - __m128i xmm0; - size_t count; - - /* If really short, just do it here. */ - if (len < 32) - { - while (len--) *dptr++ = val; - return PRIMITIVES_SUCCESS; - } - - /* Assure we can reach 16-byte alignment. */ - if (((ULONG_PTR) dptr & 0x03) != 0) - { - return general_set_32u(val, pDst, len); - } - - /* Seek 16-byte alignment. */ - while ((ULONG_PTR) dptr & 0x0f) - { - *dptr++ = val; - if (--len == 0) return PRIMITIVES_SUCCESS; - } - - xmm0 = _mm_set1_epi32(val); - - /* Cover 256-byte chunks via SSE register stores. */ - count = len >> 6; - len -= count << 6; - /* Do 256-byte chunks using one XMM register. */ - while (count--) - { - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - } - - /* Cover 16-byte chunks via SSE register stores. */ - count = len >> 2; - len -= count << 2; - /* Do 16-byte chunks using one XMM register. */ - while (count--) - { - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; - } - - /* Do leftover bytes. */ - while (len--) *dptr++ = val; - - return PRIMITIVES_SUCCESS; -} - -/* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t sse2_set_32s( - INT32 val, - INT32 *pDst, - INT32 len) -{ - UINT32 uval = *((UINT32 *) &val); - return sse2_set_32u(uval, (UINT32 *) pDst, len); -} -# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ -#endif /* WITH_SSE2 */ - -#ifdef WITH_IPP -/* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t ipp_wrapper_set_32u( - UINT32 val, - UINT32 *pDst, - INT32 len) -{ - /* A little type conversion, then use the signed version. */ - INT32 sval = *((INT32 *) &val); - return ippsSet_32s(sval, (INT32 *) pDst, len); -} -#endif - /* ------------------------------------------------------------------------- */ void primitives_init_set( const primitives_hints_t *hints, @@ -288,20 +120,7 @@ void primitives_init_set( prims->set_32u = general_set_32u; prims->zero = general_zero; - /* Pick tuned versions if possible. */ -#ifdef WITH_IPP - prims->set_8u = (__set_8u_t) ippsSet_8u; - prims->set_32s = (__set_32s_t) ippsSet_32s; - prims->set_32u = (__set_32u_t) ipp_wrapper_set_32u; - prims->zero = (__zero_t) ippsZero_8u; -#elif defined(WITH_SSE2) - if (hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) - { - prims->set_8u = sse2_set_8u; - prims->set_32s = sse2_set_32s; - prims->set_32u = sse2_set_32u; - } -#endif + primitives_init_set_opt(hints, prims); } /* ------------------------------------------------------------------------- */ @@ -310,3 +129,4 @@ void primitives_deinit_set( { /* Nothing to do. */ } + diff --git a/libfreerdp/primitives/prim_set.h b/libfreerdp/primitives/prim_set.h new file mode 100644 index 000000000..e4504dc2c --- /dev/null +++ b/libfreerdp/primitives/prim_set.h @@ -0,0 +1,34 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Routines to set a chunk of memory to a constant. + * vi:ts=4 sw=4 + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. Algorithms used by + * this code may be covered by patents by HP, Microsoft, or other parties. + * + */ + +#ifdef __GNUC__ +# pragma once +#endif + +#ifndef __PRIM_SET_H_INCLUDED__ +#define __PRIM_SET_H_INCLUDED__ + +pstatus_t general_set_8u(BYTE val, BYTE *pDst, INT32 len); +pstatus_t general_zero(void *pDst, size_t len); +pstatus_t general_set_32s(INT32 val, INT32 *pDst, INT32 len); +pstatus_t general_set_32u(UINT32 val, UINT32 *pDst, INT32 len); + + +void primitives_init_set_opt(const primitives_hints_t *hints, primitives_t *prims); + +#endif /* !__PRIM_SET_H_INCLUDED__ */ + diff --git a/libfreerdp/primitives/prim_set_opt.c b/libfreerdp/primitives/prim_set_opt.c new file mode 100644 index 000000000..0523434ff --- /dev/null +++ b/libfreerdp/primitives/prim_set_opt.c @@ -0,0 +1,218 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Optimized routines to set a chunk of memory to a constant. + * vi:ts=4 sw=4: + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifdef WITH_SSE2 +# include +#endif /* WITH_SSE2 */ +#ifdef WITH_IPP +# include +#endif /* WITH_IPP */ + +#include "prim_internal.h" +#include "prim_set.h" + +/* ========================================================================= */ +#ifdef WITH_SSE2 +# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) +pstatus_t sse2_set_8u( + BYTE val, + BYTE *pDst, + INT32 len) +{ + BYTE byte, *dptr; + __m128i xmm0; + size_t count; + + if (len < 16) return general_set_8u(val, pDst, len); + + byte = val; + dptr = (BYTE *) pDst; + + /* Seek 16-byte alignment. */ + while ((ULONG_PTR) dptr & 0x0f) + { + *dptr++ = byte; + if (--len == 0) return PRIMITIVES_SUCCESS; + } + + xmm0 = _mm_set1_epi8(byte); + + /* Cover 256-byte chunks via SSE register stores. */ + count = len >> 8; + len -= count << 8; + /* Do 256-byte chunks using one XMM register. */ + while (count--) + { + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + } + + /* Cover 16-byte chunks via SSE register stores. */ + count = len >> 4; + len -= count << 4; + /* Do 16-byte chunks using one XMM register. */ + while (count--) + { + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 16; + } + + /* Do leftover bytes. */ + while (len--) *dptr++ = byte; + + return PRIMITIVES_SUCCESS; +} +# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ +#endif /* WITH_SSE2 */ + +/* ------------------------------------------------------------------------- */ +#ifdef WITH_SSE2 +# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) +pstatus_t sse2_set_32u( + UINT32 val, + UINT32 *pDst, + INT32 len) +{ + UINT32 *dptr = (UINT32 *) pDst; + __m128i xmm0; + size_t count; + + /* If really short, just do it here. */ + if (len < 32) + { + while (len--) *dptr++ = val; + return PRIMITIVES_SUCCESS; + } + + /* Assure we can reach 16-byte alignment. */ + if (((ULONG_PTR) dptr & 0x03) != 0) + { + return general_set_32u(val, pDst, len); + } + + /* Seek 16-byte alignment. */ + while ((ULONG_PTR) dptr & 0x0f) + { + *dptr++ = val; + if (--len == 0) return PRIMITIVES_SUCCESS; + } + + xmm0 = _mm_set1_epi32(val); + + /* Cover 256-byte chunks via SSE register stores. */ + count = len >> 6; + len -= count << 6; + /* Do 256-byte chunks using one XMM register. */ + while (count--) + { + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + } + + /* Cover 16-byte chunks via SSE register stores. */ + count = len >> 2; + len -= count << 2; + /* Do 16-byte chunks using one XMM register. */ + while (count--) + { + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 4; + } + + /* Do leftover bytes. */ + while (len--) *dptr++ = val; + + return PRIMITIVES_SUCCESS; +} + +/* ------------------------------------------------------------------------- */ +pstatus_t sse2_set_32s( + INT32 val, + INT32 *pDst, + INT32 len) +{ + UINT32 uval = *((UINT32 *) &val); + return sse2_set_32u(uval, (UINT32 *) pDst, len); +} +# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ +#endif /* WITH_SSE2 */ + +#ifdef WITH_IPP +/* ------------------------------------------------------------------------- */ +pstatus_t ipp_wrapper_set_32u( + UINT32 val, + UINT32 *pDst, + INT32 len) +{ + /* A little type conversion, then use the signed version. */ + INT32 sval = *((INT32 *) &val); + return ippsSet_32s(sval, (INT32 *) pDst, len); +} +#endif + +/* ------------------------------------------------------------------------- */ +void primitives_init_set_opt(const primitives_hints_t *hints, primitives_t *prims) +{ + /* Pick tuned versions if possible. */ +#ifdef WITH_IPP + prims->set_8u = (__set_8u_t) ippsSet_8u; + prims->set_32s = (__set_32s_t) ippsSet_32s; + prims->set_32u = (__set_32u_t) ipp_wrapper_set_32u; + prims->zero = (__zero_t) ippsZero_8u; +#elif defined(WITH_SSE2) + if (hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) + { + prims->set_8u = sse2_set_8u; + prims->set_32s = sse2_set_32s; + prims->set_32u = sse2_set_32u; + } +#endif +} + diff --git a/libfreerdp/primitives/prim_shift.c b/libfreerdp/primitives/prim_shift.c index 331c7216e..bd26dc0a0 100644 --- a/libfreerdp/primitives/prim_shift.c +++ b/libfreerdp/primitives/prim_shift.c @@ -17,25 +17,15 @@ #include "config.h" #endif -#include - #include #include -#ifdef WITH_SSE2 -#include -#include -#endif /* WITH_SSE2 */ - -#ifdef WITH_IPP -#include -#endif /* WITH_IPP */ - #include "prim_internal.h" -#include "prim_templates.h" +#include "prim_shift.h" + /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_lShiftC_16s( +pstatus_t general_lShiftC_16s( const INT16 *pSrc, INT32 val, INT16 *pDst, @@ -47,7 +37,7 @@ PRIM_STATIC pstatus_t general_lShiftC_16s( } /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_rShiftC_16s( +pstatus_t general_rShiftC_16s( const INT16 *pSrc, INT32 val, INT16 *pDst, @@ -59,7 +49,7 @@ PRIM_STATIC pstatus_t general_rShiftC_16s( } /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_lShiftC_16u( +pstatus_t general_lShiftC_16u( const UINT16 *pSrc, INT32 val, UINT16 *pDst, @@ -71,7 +61,7 @@ PRIM_STATIC pstatus_t general_lShiftC_16u( } /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_rShiftC_16u( +pstatus_t general_rShiftC_16u( const UINT16 *pSrc, INT32 val, UINT16 *pDst, @@ -82,25 +72,8 @@ PRIM_STATIC pstatus_t general_rShiftC_16u( return PRIMITIVES_SUCCESS; } -#ifdef WITH_SSE2 -# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) /* ------------------------------------------------------------------------- */ -SSE3_SCD_ROUTINE(sse2_lShiftC_16s, INT16, general_lShiftC_16s, - _mm_slli_epi16, *dptr++ = *sptr++ << val) -/* ------------------------------------------------------------------------- */ -SSE3_SCD_ROUTINE(sse2_rShiftC_16s, INT16, general_rShiftC_16s, - _mm_srai_epi16, *dptr++ = *sptr++ >> val) -/* ------------------------------------------------------------------------- */ -SSE3_SCD_ROUTINE(sse2_lShiftC_16u, UINT16, general_lShiftC_16u, - _mm_slli_epi16, *dptr++ = *sptr++ << val) -/* ------------------------------------------------------------------------- */ -SSE3_SCD_ROUTINE(sse2_rShiftC_16u, UINT16, general_rShiftC_16u, - _mm_srli_epi16, *dptr++ = *sptr++ >> val) -# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ -#endif - -/* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_shiftC_16s( +pstatus_t general_shiftC_16s( const INT16 *pSrc, INT32 val, INT16 *pDst, @@ -115,7 +88,7 @@ PRIM_STATIC pstatus_t general_shiftC_16s( } /* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t general_shiftC_16u( +pstatus_t general_shiftC_16u( const UINT16 *pSrc, INT32 val, UINT16 *pDst, @@ -129,11 +102,6 @@ PRIM_STATIC pstatus_t general_shiftC_16u( else return prims->lShiftC_16u(pSrc, val, pDst, len); } -/* Note: the IPP version will have to call ippLShiftC_16s or ippRShiftC_16s - * depending on the sign of val. To avoid using the deprecated inplace - * routines, a wrapper can use the src for the dest. - */ - /* ------------------------------------------------------------------------- */ void primitives_init_shift( const primitives_hints_t *hints, @@ -144,24 +112,12 @@ void primitives_init_shift( prims->rShiftC_16s = general_rShiftC_16s; prims->lShiftC_16u = general_lShiftC_16u; prims->rShiftC_16u = general_rShiftC_16u; -#if defined(WITH_IPP) - prims->lShiftC_16s = (__lShiftC_16s_t) ippsLShiftC_16s; - prims->rShiftC_16s = (__rShiftC_16s_t) ippsRShiftC_16s; - prims->lShiftC_16u = (__lShiftC_16u_t) ippsLShiftC_16u; - prims->rShiftC_16u = (__rShiftC_16u_t) ippsRShiftC_16u; -#elif defined(WITH_SSE2) - if ((hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) - && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) - { - prims->lShiftC_16s = sse2_lShiftC_16s; - prims->rShiftC_16s = sse2_rShiftC_16s; - prims->lShiftC_16u = sse2_lShiftC_16u; - prims->rShiftC_16u = sse2_rShiftC_16u; - } -#endif + /* Wrappers */ prims->shiftC_16s = general_shiftC_16s; prims->shiftC_16u = general_shiftC_16u; + + primitives_init_shift_opt(hints, prims); } /* ------------------------------------------------------------------------- */ diff --git a/libfreerdp/primitives/prim_shift.h b/libfreerdp/primitives/prim_shift.h new file mode 100644 index 000000000..cad054013 --- /dev/null +++ b/libfreerdp/primitives/prim_shift.h @@ -0,0 +1,35 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Shift operations. + * vi:ts=4 sw=4 + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. Algorithms used by + * this code may be covered by patents by HP, Microsoft, or other parties. + * + */ + +#ifdef __GNUC__ +# pragma once +#endif + +#ifndef __PRIM_SHIFT_H_INCLUDED__ +#define __PRIM_SHIFT_H_INCLUDED__ + +pstatus_t general_lShiftC_16s(const INT16 *pSrc, INT32 val, INT16 *pDst, INT32 len); +pstatus_t general_rShiftC_16s(const INT16 *pSrc, INT32 val, INT16 *pDst, INT32 len); +pstatus_t general_lShiftC_16u(const UINT16 *pSrc, INT32 val, UINT16 *pDst, INT32 len); +pstatus_t general_rShiftC_16u(const UINT16 *pSrc, INT32 val, UINT16 *pDst, INT32 len); +pstatus_t general_shiftC_16s(const INT16 *pSrc, INT32 val, INT16 *pDst, INT32 len); +pstatus_t general_shiftC_16u(const UINT16 *pSrc, INT32 val, UINT16 *pDst, INT32 len); + +void primitives_init_shift_opt(const primitives_hints_t *hints, primitives_t *prims); + +#endif /* !__PRIM_SHIFT_H_INCLUDED__ */ + diff --git a/libfreerdp/primitives/prim_shift_opt.c b/libfreerdp/primitives/prim_shift_opt.c new file mode 100644 index 000000000..0e57da269 --- /dev/null +++ b/libfreerdp/primitives/prim_shift_opt.c @@ -0,0 +1,79 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Shift operations. + * vi:ts=4 sw=4: + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef WITH_SSE2 +#include +#include +#endif /* WITH_SSE2 */ + +#ifdef WITH_IPP +#include +#endif /* WITH_IPP */ + +#include "prim_internal.h" +#include "prim_templates.h" +#include "prim_shift.h" + + +#ifdef WITH_SSE2 +# if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) +/* ------------------------------------------------------------------------- */ +SSE3_SCD_ROUTINE(sse2_lShiftC_16s, INT16, general_lShiftC_16s, + _mm_slli_epi16, *dptr++ = *sptr++ << val) +/* ------------------------------------------------------------------------- */ +SSE3_SCD_ROUTINE(sse2_rShiftC_16s, INT16, general_rShiftC_16s, + _mm_srai_epi16, *dptr++ = *sptr++ >> val) +/* ------------------------------------------------------------------------- */ +SSE3_SCD_ROUTINE(sse2_lShiftC_16u, UINT16, general_lShiftC_16u, + _mm_slli_epi16, *dptr++ = *sptr++ << val) +/* ------------------------------------------------------------------------- */ +SSE3_SCD_ROUTINE(sse2_rShiftC_16u, UINT16, general_rShiftC_16u, + _mm_srli_epi16, *dptr++ = *sptr++ >> val) +# endif /* !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) */ +#endif + + +/* Note: the IPP version will have to call ippLShiftC_16s or ippRShiftC_16s + * depending on the sign of val. To avoid using the deprecated inplace + * routines, a wrapper can use the src for the dest. + */ + +/* ------------------------------------------------------------------------- */ +void primitives_init_shift_opt(const primitives_hints_t *hints, primitives_t *prims) +{ +#if defined(WITH_IPP) + prims->lShiftC_16s = (__lShiftC_16s_t) ippsLShiftC_16s; + prims->rShiftC_16s = (__rShiftC_16s_t) ippsRShiftC_16s; + prims->lShiftC_16u = (__lShiftC_16u_t) ippsLShiftC_16u; + prims->rShiftC_16u = (__rShiftC_16u_t) ippsRShiftC_16u; +#elif defined(WITH_SSE2) + if ((hints->x86_flags & PRIM_X86_SSE2_AVAILABLE) + && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) + { + prims->lShiftC_16s = sse2_lShiftC_16s; + prims->rShiftC_16s = sse2_rShiftC_16s; + prims->lShiftC_16u = sse2_lShiftC_16u; + prims->rShiftC_16u = sse2_rShiftC_16u; + } +#endif +} + diff --git a/libfreerdp/primitives/prim_sign.c b/libfreerdp/primitives/prim_sign.c index a3b11ee14..d7d2eb018 100644 --- a/libfreerdp/primitives/prim_sign.c +++ b/libfreerdp/primitives/prim_sign.c @@ -17,22 +17,16 @@ #include "config.h" #endif -#include - #include #include -#ifdef WITH_SSE2 -#include -#include -#endif /* WITH_SSE2 */ - #include "prim_internal.h" +#include "prim_sign.h" /* ---------------------------------------------------------------------------- * Set pDst to the sign-value of the 16-bit values in pSrc (-1, 0, or 1). */ -PRIM_STATIC pstatus_t general_sign_16s( +pstatus_t general_sign_16s( const INT16 *pSrc, INT16 *pDst, INT32 len) @@ -46,110 +40,6 @@ PRIM_STATIC pstatus_t general_sign_16s( return PRIMITIVES_SUCCESS; } -#ifdef WITH_SSE2 -/* ------------------------------------------------------------------------- */ -PRIM_STATIC pstatus_t ssse3_sign_16s( - const INT16 *pSrc, - INT16 *pDst, - INT32 len) -{ - const INT16 *sptr = (const INT16 *) pSrc; - INT16 *dptr = (INT16 *) pDst; - size_t count; - - if (len < 16) - { - return general_sign_16s(pSrc, pDst, len); - } - - /* Check for 16-byte alignment (eventually). */ - if ((ULONG_PTR) pDst & 0x01) - { - return general_sign_16s(pSrc, pDst, len); - } - - /* Seek 16-byte alignment. */ - while ((ULONG_PTR) dptr & 0x0f) - { - INT16 src = *sptr++; - *dptr++ = (src < 0) ? (-1) : ((src > 0) ? 1 : 0); - if (--len == 0) return PRIMITIVES_SUCCESS; - } - - /* Do 32-short chunks using 8 XMM registers. */ - count = len >> 5; /* / 32 */ - len -= count << 5; /* * 32 */ - if ((ULONG_PTR) sptr & 0x0f) - { - /* Unaligned */ - while (count--) - { - __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; - xmm0 = _mm_set1_epi16(0x0001U); - xmm1 = _mm_set1_epi16(0x0001U); - xmm2 = _mm_set1_epi16(0x0001U); - xmm3 = _mm_set1_epi16(0x0001U); - xmm4 = _mm_lddqu_si128((__m128i *) sptr); sptr += 8; - xmm5 = _mm_lddqu_si128((__m128i *) sptr); sptr += 8; - xmm6 = _mm_lddqu_si128((__m128i *) sptr); sptr += 8; - xmm7 = _mm_lddqu_si128((__m128i *) sptr); sptr += 8; - xmm0 = _mm_sign_epi16(xmm0, xmm4); - xmm1 = _mm_sign_epi16(xmm1, xmm5); - xmm2 = _mm_sign_epi16(xmm2, xmm6); - xmm3 = _mm_sign_epi16(xmm3, xmm7); - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 8; - _mm_store_si128((__m128i *) dptr, xmm1); dptr += 8; - _mm_store_si128((__m128i *) dptr, xmm2); dptr += 8; - _mm_store_si128((__m128i *) dptr, xmm3); dptr += 8; - } - } - else - { - /* Aligned */ - while (count--) - { - __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; - xmm0 = _mm_set1_epi16(0x0001U); - xmm1 = _mm_set1_epi16(0x0001U); - xmm2 = _mm_set1_epi16(0x0001U); - xmm3 = _mm_set1_epi16(0x0001U); - xmm4 = _mm_load_si128((__m128i *) sptr); sptr += 8; - xmm5 = _mm_load_si128((__m128i *) sptr); sptr += 8; - xmm6 = _mm_load_si128((__m128i *) sptr); sptr += 8; - xmm7 = _mm_load_si128((__m128i *) sptr); sptr += 8; - xmm0 = _mm_sign_epi16(xmm0, xmm4); - xmm1 = _mm_sign_epi16(xmm1, xmm5); - xmm2 = _mm_sign_epi16(xmm2, xmm6); - xmm3 = _mm_sign_epi16(xmm3, xmm7); - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 8; - _mm_store_si128((__m128i *) dptr, xmm1); dptr += 8; - _mm_store_si128((__m128i *) dptr, xmm2); dptr += 8; - _mm_store_si128((__m128i *) dptr, xmm3); dptr += 8; - } - } - - /* Do 8-short chunks using two XMM registers. */ - count = len >> 3; - len -= count << 3; - while (count--) - { - __m128i xmm0 = _mm_set1_epi16(0x0001U); - __m128i xmm1 = LOAD_SI128(sptr); sptr += 8; - xmm0 = _mm_sign_epi16(xmm0, xmm1); - _mm_store_si128((__m128i *) dptr, xmm0); dptr += 8; - } - - /* Do leftovers. */ - while (len--) - { - INT16 src = *sptr++; - *dptr++ = (src < 0) ? -1 : ((src > 0) ? 1 : 0); - } - - return PRIMITIVES_SUCCESS; -} -#endif /* WITH_SSE2 */ - /* ------------------------------------------------------------------------- */ void primitives_init_sign( const primitives_hints_t *hints, @@ -157,15 +47,8 @@ void primitives_init_sign( { /* Start with the default. */ prims->sign_16s = general_sign_16s; - /* Pick tuned versions if possible. */ - /* I didn't spot an IPP version of this. */ -#if defined(WITH_SSE2) - if ((hints->x86_flags & PRIM_X86_SSSE3_AVAILABLE) - && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) - { - prims->sign_16s = ssse3_sign_16s; - } -#endif + + primitives_init_sign_opt(hints, prims); } /* ------------------------------------------------------------------------- */ @@ -174,3 +57,4 @@ void primitives_deinit_sign( { /* Nothing to do. */ } + diff --git a/libfreerdp/primitives/prim_sign.h b/libfreerdp/primitives/prim_sign.h new file mode 100644 index 000000000..3592990ec --- /dev/null +++ b/libfreerdp/primitives/prim_sign.h @@ -0,0 +1,30 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Sign operations. + * vi:ts=4 sw=4 + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. Algorithms used by + * this code may be covered by patents by HP, Microsoft, or other parties. + * + */ + +#ifdef __GNUC__ +# pragma once +#endif + +#ifndef __PRIM_SIGN_H_INCLUDED__ +#define __PRIM_SIGN_H_INCLUDED__ + +pstatus_t general_sign_16s(const INT16 *pSrc, INT16 *pDst, INT32 len); + +void primitives_init_sign_opt(const primitives_hints_t *hints, primitives_t *prims); + +#endif /* !__PRIM_SIGN_H_INCLUDED__ */ + diff --git a/libfreerdp/primitives/prim_sign_opt.c b/libfreerdp/primitives/prim_sign_opt.c new file mode 100644 index 000000000..81842b9bd --- /dev/null +++ b/libfreerdp/primitives/prim_sign_opt.c @@ -0,0 +1,149 @@ +/* FreeRDP: A Remote Desktop Protocol Client + * Optimized sign operations. + * vi:ts=4 sw=4: + * + * (c) Copyright 2012 Hewlett-Packard Development Company, L.P. + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef WITH_SSE2 +#include +#include +#endif /* WITH_SSE2 */ + +#include "prim_internal.h" +#include "prim_sign.h" + + +#ifdef WITH_SSE2 +/* ------------------------------------------------------------------------- */ +pstatus_t ssse3_sign_16s( + const INT16 *pSrc, + INT16 *pDst, + INT32 len) +{ + const INT16 *sptr = (const INT16 *) pSrc; + INT16 *dptr = (INT16 *) pDst; + size_t count; + + if (len < 16) + { + return general_sign_16s(pSrc, pDst, len); + } + + /* Check for 16-byte alignment (eventually). */ + if ((ULONG_PTR) pDst & 0x01) + { + return general_sign_16s(pSrc, pDst, len); + } + + /* Seek 16-byte alignment. */ + while ((ULONG_PTR) dptr & 0x0f) + { + INT16 src = *sptr++; + *dptr++ = (src < 0) ? (-1) : ((src > 0) ? 1 : 0); + if (--len == 0) return PRIMITIVES_SUCCESS; + } + + /* Do 32-short chunks using 8 XMM registers. */ + count = len >> 5; /* / 32 */ + len -= count << 5; /* * 32 */ + if ((ULONG_PTR) sptr & 0x0f) + { + /* Unaligned */ + while (count--) + { + __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; + xmm0 = _mm_set1_epi16(0x0001U); + xmm1 = _mm_set1_epi16(0x0001U); + xmm2 = _mm_set1_epi16(0x0001U); + xmm3 = _mm_set1_epi16(0x0001U); + xmm4 = _mm_lddqu_si128((__m128i *) sptr); sptr += 8; + xmm5 = _mm_lddqu_si128((__m128i *) sptr); sptr += 8; + xmm6 = _mm_lddqu_si128((__m128i *) sptr); sptr += 8; + xmm7 = _mm_lddqu_si128((__m128i *) sptr); sptr += 8; + xmm0 = _mm_sign_epi16(xmm0, xmm4); + xmm1 = _mm_sign_epi16(xmm1, xmm5); + xmm2 = _mm_sign_epi16(xmm2, xmm6); + xmm3 = _mm_sign_epi16(xmm3, xmm7); + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 8; + _mm_store_si128((__m128i *) dptr, xmm1); dptr += 8; + _mm_store_si128((__m128i *) dptr, xmm2); dptr += 8; + _mm_store_si128((__m128i *) dptr, xmm3); dptr += 8; + } + } + else + { + /* Aligned */ + while (count--) + { + __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; + xmm0 = _mm_set1_epi16(0x0001U); + xmm1 = _mm_set1_epi16(0x0001U); + xmm2 = _mm_set1_epi16(0x0001U); + xmm3 = _mm_set1_epi16(0x0001U); + xmm4 = _mm_load_si128((__m128i *) sptr); sptr += 8; + xmm5 = _mm_load_si128((__m128i *) sptr); sptr += 8; + xmm6 = _mm_load_si128((__m128i *) sptr); sptr += 8; + xmm7 = _mm_load_si128((__m128i *) sptr); sptr += 8; + xmm0 = _mm_sign_epi16(xmm0, xmm4); + xmm1 = _mm_sign_epi16(xmm1, xmm5); + xmm2 = _mm_sign_epi16(xmm2, xmm6); + xmm3 = _mm_sign_epi16(xmm3, xmm7); + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 8; + _mm_store_si128((__m128i *) dptr, xmm1); dptr += 8; + _mm_store_si128((__m128i *) dptr, xmm2); dptr += 8; + _mm_store_si128((__m128i *) dptr, xmm3); dptr += 8; + } + } + + /* Do 8-short chunks using two XMM registers. */ + count = len >> 3; + len -= count << 3; + while (count--) + { + __m128i xmm0 = _mm_set1_epi16(0x0001U); + __m128i xmm1 = LOAD_SI128(sptr); sptr += 8; + xmm0 = _mm_sign_epi16(xmm0, xmm1); + _mm_store_si128((__m128i *) dptr, xmm0); dptr += 8; + } + + /* Do leftovers. */ + while (len--) + { + INT16 src = *sptr++; + *dptr++ = (src < 0) ? -1 : ((src > 0) ? 1 : 0); + } + + return PRIMITIVES_SUCCESS; +} +#endif /* WITH_SSE2 */ + +/* ------------------------------------------------------------------------- */ +void primitives_init_sign_opt(const primitives_hints_t *hints, primitives_t *prims) +{ + /* Pick tuned versions if possible. */ + /* I didn't spot an IPP version of this. */ +#if defined(WITH_SSE2) + if ((hints->x86_flags & PRIM_X86_SSSE3_AVAILABLE) + && (hints->x86_flags & PRIM_X86_SSE3_AVAILABLE)) + { + prims->sign_16s = ssse3_sign_16s; + } +#endif +} + diff --git a/libfreerdp/primitives/prim_templates.h b/libfreerdp/primitives/prim_templates.h index c0b6ac10d..b530637b7 100644 --- a/libfreerdp/primitives/prim_templates.h +++ b/libfreerdp/primitives/prim_templates.h @@ -44,7 +44,7 @@ * SCD = Source, Constant, Destination */ #define SSE3_SCD_ROUTINE(_name_, _type_, _fallback_, _op_, _slowWay_) \ -PRIM_STATIC pstatus_t _name_(const _type_ *pSrc, INT32 val, _type_ *pDst, INT32 len) \ +pstatus_t _name_(const _type_ *pSrc, INT32 val, _type_ *pDst, INT32 len) \ { \ int shifts; \ UINT32 offBeatMask; \ @@ -188,7 +188,7 @@ PRIM_STATIC pstatus_t _name_(const _type_ *pSrc, INT32 val, _type_ *pDst, INT32 * PRE = preload xmm0 with the constant. */ #define SSE3_SCD_PRE_ROUTINE(_name_, _type_, _fallback_, _op_, _slowWay_) \ -PRIM_STATIC pstatus_t _name_(const _type_ *pSrc, _type_ val, _type_ *pDst, INT32 len) \ +pstatus_t _name_(const _type_ *pSrc, _type_ val, _type_ *pDst, INT32 len) \ { \ int shifts; \ UINT32 offBeatMask; \ @@ -293,7 +293,7 @@ PRIM_STATIC pstatus_t _name_(const _type_ *pSrc, _type_ val, _type_ *pDst, INT32 * SSD = Source1, Source2, Destination */ #define SSE3_SSD_ROUTINE(_name_, _type_, _fallback_, _op_, _slowWay_) \ -PRIM_STATIC pstatus_t _name_(const _type_ *pSrc1, const _type_ *pSrc2, _type_ *pDst, INT32 len) \ +pstatus_t _name_(const _type_ *pSrc1, const _type_ *pSrc2, _type_ *pDst, INT32 len) \ { \ int shifts; \ UINT32 offBeatMask; \ diff --git a/libfreerdp/primitives/primitives.c b/libfreerdp/primitives/primitives.c index ddafe7815..99c71e37f 100644 --- a/libfreerdp/primitives/primitives.c +++ b/libfreerdp/primitives/primitives.c @@ -150,7 +150,7 @@ static void set_hints(primitives_hints_t* hints) #elif defined(_M_ARM) -static UINT32 androidNeon(void) +static UINT32 getNeonSupport(void) { #ifdef __ANDROID__ if (android_getCpuFamily() != ANDROID_CPU_FAMILY_ARM) return 0; @@ -164,7 +164,9 @@ static UINT32 androidNeon(void) return PRIM_ARM_NEON_AVAILABLE; } } - /* else */ +#elif defined(__APPLE) + /* assume NEON support on iOS devices */ + return PRIM_ARM_NEON_AVAILABLE; #endif return 0; } @@ -172,7 +174,7 @@ static UINT32 androidNeon(void) static void set_hints(primitives_hints_t* hints) { /* ARM: TODO */ - hints->arm_flags |= androidNeon(); + hints->arm_flags |= getNeonSupport(); } #else diff --git a/libfreerdp/primitives/test/CMakeLists.txt b/libfreerdp/primitives/test/CMakeLists.txt index 49e1f2d3a..7030ac7f8 100644 --- a/libfreerdp/primitives/test/CMakeLists.txt +++ b/libfreerdp/primitives/test/CMakeLists.txt @@ -31,22 +31,29 @@ set(PRIMITIVE_TEST_CFILES test_set.c test_shift.c test_sign.c - ../prim_add.c - ../prim_andor.c - ../prim_alphaComp.c - ../prim_colors.c - ../prim_copy.c - ../prim_set.c - ../prim_shift.c - ../prim_sign.c + ../prim_add.c + ../prim_andor.c + ../prim_alphaComp.c + ../prim_colors.c + ../prim_copy.c + ../prim_set.c + ../prim_shift.c + ../prim_sign.c + ../prim_add_opt.c + ../prim_alphaComp_opt.c + ../prim_andor_opt.c + ../prim_colors_opt.c + ../prim_set_opt.c + ../prim_shift_opt.c + ../prim_sign_opt.c ../primitives.c ) set(PRIMITIVE_TEST_HEADERS measure.h prim_test.h - ../prim_internal.h - ) + ../prim_internal.h +) set(PRIMITIVE_TEST_SRCS ${PRIMITIVE_TEST_CFILES} @@ -85,7 +92,7 @@ if(WITH_SSE2) endif() elseif(WITH_NEON) if(CMAKE_COMPILER_IS_GNUCC) - set(OPTIMZATION "${OPTFLAGS} -mfpu=neon -mfloat-abi=softfp -O2") + set(OPTFLAGS "${OPTFLAGS} -mfpu=neon -mfloat-abi=${ARM_FP_ABI} -O2") endif() # TODO: Add MSVC equivalent endif() diff --git a/libfreerdp/utils/CMakeLists.txt b/libfreerdp/utils/CMakeLists.txt index ba14e9e42..55b3b7e46 100644 --- a/libfreerdp/utils/CMakeLists.txt +++ b/libfreerdp/utils/CMakeLists.txt @@ -19,7 +19,6 @@ set(MODULE_NAME "freerdp-utils") set(MODULE_PREFIX "FREERDP_UTILS") set(${MODULE_PREFIX}_SRCS - dsp.c event.c bitmap.c list.c @@ -63,7 +62,7 @@ endif() set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE winpr - MODULES winpr-crt winpr-synch winpr-thread) + MODULES winpr-crt winpr-synch winpr-thread winpr-utils) if(MONOLITHIC_BUILD) set(FREERDP_LIBS ${FREERDP_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) diff --git a/libfreerdp/utils/event.c b/libfreerdp/utils/event.c index 5f461a696..39e186e5b 100644 --- a/libfreerdp/utils/event.c +++ b/libfreerdp/utils/event.c @@ -117,7 +117,7 @@ RDP_EVENT* freerdp_event_new(UINT16 event_class, UINT16 event_type, break; } - if (event != NULL) + if (event) { event->event_class = event_class; event->event_type = event_type; @@ -168,9 +168,9 @@ static void freerdp_rail_event_free(RDP_EVENT* event) void freerdp_event_free(RDP_EVENT* event) { - if (event != NULL) + if (event) { - if (event->on_event_free_callback != NULL) + if (event->on_event_free_callback) event->on_event_free_callback(event); switch (event->event_class) @@ -185,6 +185,7 @@ void freerdp_event_free(RDP_EVENT* event) freerdp_rail_event_free(event); break; } + free(event); } } diff --git a/libfreerdp/utils/signal.c b/libfreerdp/utils/signal.c index 5e7ebce3e..82cdec9ad 100644 --- a/libfreerdp/utils/signal.c +++ b/libfreerdp/utils/signal.c @@ -64,46 +64,49 @@ static void fatal_handler(int signum) raise(signum); } -int freerdp_handle_signals(void) +const int fatal_signals[] = { - const int fatal_signals[] = { - SIGABRT, - SIGALRM, - SIGBUS, - SIGFPE, - SIGHUP, - SIGILL, - SIGINT, - SIGKILL, - SIGPIPE, - SIGQUIT, - SIGSEGV, - SIGSTOP, - SIGTERM, - SIGTSTP, - SIGTTIN, - SIGTTOU, - SIGUSR1, - SIGUSR2, + SIGABRT, + SIGALRM, + SIGBUS, + SIGFPE, + SIGHUP, + SIGILL, + SIGINT, + SIGKILL, + SIGPIPE, + SIGQUIT, + SIGSEGV, + SIGSTOP, + SIGTERM, + SIGTSTP, + SIGTTIN, + SIGTTOU, + SIGUSR1, + SIGUSR2, #ifdef SIGPOLL - SIGPOLL, + SIGPOLL, #endif #ifdef SIGPROF - SIGPROF, + SIGPROF, #endif #ifdef SIGSYS - SIGSYS, + SIGSYS, #endif - SIGTRAP, + SIGTRAP, #ifdef SIGVTALRM - SIGVTALRM, + SIGVTALRM, #endif - SIGXCPU, - SIGXFSZ - }; + SIGXCPU, + SIGXFSZ +}; + +int freerdp_handle_signals(void) +{ int signal_index; sigset_t orig_set; - struct sigaction orig_sigaction, fatal_sigaction; + struct sigaction orig_sigaction; + struct sigaction fatal_sigaction; sigfillset(&(fatal_sigaction.sa_mask)); sigdelset(&(fatal_sigaction.sa_mask), SIGCONT); @@ -112,16 +115,19 @@ int freerdp_handle_signals(void) fatal_sigaction.sa_handler = fatal_handler; fatal_sigaction.sa_flags = 0; - for (signal_index = 0; - signal_index < ARRAYSIZE(fatal_signals); - signal_index++) - if (sigaction(fatal_signals[signal_index], - NULL, &orig_sigaction) == 0) + for (signal_index = 0; signal_index < ARRAYSIZE(fatal_signals); signal_index++) + { + if (sigaction(fatal_signals[signal_index], NULL, &orig_sigaction) == 0) + { if (orig_sigaction.sa_handler != SIG_IGN) - sigaction(fatal_signals[signal_index], - &fatal_sigaction, NULL); + { + sigaction(fatal_signals[signal_index], &fatal_sigaction, NULL); + } + } + } pthread_sigmask(SIG_SETMASK, &orig_set, NULL); + return 0; } diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index bfe33bdb6..dc9b44d2e 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -27,141 +27,80 @@ #include #include +#include +#include #include #include #include -#include -#include #include #include -/* The list of all plugin instances. */ -typedef struct rdp_svc_plugin_list rdpSvcPluginList; - -struct rdp_svc_plugin_list -{ - rdpSvcPlugin* plugin; - rdpSvcPluginList* next; -}; - -static rdpSvcPluginList* g_svc_plugin_list = NULL; - -/* For locking the global resources */ -static HANDLE g_mutex = NULL; - -/* Queue for receiving packets */ -struct _svc_data_in_item -{ - STREAM* data_in; - RDP_EVENT* event_in; -}; -typedef struct _svc_data_in_item svc_data_in_item; - -static void svc_data_in_item_free(svc_data_in_item* item) -{ - if (item->data_in) - { - stream_free(item->data_in); - item->data_in = NULL; - } - - if (item->event_in) - { - freerdp_event_free(item->event_in); - item->event_in = NULL; - } - - free(item); -} - -struct rdp_svc_plugin_private -{ - void* init_handle; - UINT32 open_handle; - STREAM* data_in; - - LIST* data_in_list; - freerdp_thread* thread; -}; +static wArrayList* g_AddinList = NULL; static rdpSvcPlugin* svc_plugin_find_by_init_handle(void* init_handle) { - rdpSvcPluginList* list; + int index; + BOOL found = FALSE; rdpSvcPlugin* plugin; - WaitForSingleObject(g_mutex, INFINITE); + ArrayList_Lock(g_AddinList); - for (list = g_svc_plugin_list; list; list = list->next) + index = 0; + plugin = (rdpSvcPlugin*) ArrayList_GetItem(g_AddinList, index++); + + while (plugin) { - plugin = list->plugin; - - if (plugin->priv->init_handle == init_handle) + if (plugin->init_handle == init_handle) { - ReleaseMutex(g_mutex); - return plugin; + found = TRUE; + break; } + + plugin = (rdpSvcPlugin*) ArrayList_GetItem(g_AddinList, index++); } - ReleaseMutex(g_mutex); + ArrayList_Unlock(g_AddinList); - return NULL; + return (found) ? plugin : NULL; } static rdpSvcPlugin* svc_plugin_find_by_open_handle(UINT32 open_handle) { - rdpSvcPluginList* list; + int index; + BOOL found = FALSE; rdpSvcPlugin* plugin; - WaitForSingleObject(g_mutex, INFINITE); + ArrayList_Lock(g_AddinList); - for (list = g_svc_plugin_list; list; list = list->next) + index = 0; + plugin = (rdpSvcPlugin*) ArrayList_GetItem(g_AddinList, index++); + + while (plugin) { - plugin = list->plugin; - - if (plugin->priv->open_handle == open_handle) + if (plugin->open_handle == open_handle) { - ReleaseMutex(g_mutex); - return plugin; + found = TRUE; + break; } + + plugin = (rdpSvcPlugin*) ArrayList_GetItem(g_AddinList, index++); } - ReleaseMutex(g_mutex); + ArrayList_Unlock(g_AddinList); - return NULL; + return (found) ? plugin : NULL; } static void svc_plugin_remove(rdpSvcPlugin* plugin) { - rdpSvcPluginList* list; - rdpSvcPluginList* prev; - - /* Remove from global list */ - WaitForSingleObject(g_mutex, INFINITE); - - for (prev = NULL, list = g_svc_plugin_list; list; prev = list, list = list->next) - { - if (list->plugin == plugin) - break; - } - - if (list) - { - if (prev) - prev->next = list->next; - else - g_svc_plugin_list = list->next; - free(list); - } - - ReleaseMutex(g_mutex); + ArrayList_Remove(g_AddinList, (void*) plugin); } static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { STREAM* data_in; - svc_data_in_item* item; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { @@ -176,12 +115,13 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 if (dataFlags & CHANNEL_FLAG_FIRST) { - if (plugin->priv->data_in != NULL) - stream_free(plugin->priv->data_in); - plugin->priv->data_in = stream_new(totalLength); + if (plugin->data_in != NULL) + stream_free(plugin->data_in); + + plugin->data_in = stream_new(totalLength); } - data_in = plugin->priv->data_in; + data_in = plugin->data_in; stream_check_size(data_in, (int) dataLength); stream_write(data_in, pData, dataLength); @@ -192,35 +132,16 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 printf("svc_plugin_process_received: read error\n"); } - plugin->priv->data_in = NULL; + plugin->data_in = NULL; stream_set_pos(data_in, 0); - item = (svc_data_in_item*) malloc(sizeof(svc_data_in_item)); - ZeroMemory(item, sizeof(svc_data_in_item)); - - item->data_in = data_in; - - freerdp_thread_lock(plugin->priv->thread); - list_enqueue(plugin->priv->data_in_list, item); - freerdp_thread_unlock(plugin->priv->thread); - - freerdp_thread_signal(plugin->priv->thread); + MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) data_in, NULL); } } static void svc_plugin_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event_in) { - svc_data_in_item* item; - - item = (svc_data_in_item*) malloc(sizeof(svc_data_in_item)); - ZeroMemory(item, sizeof(svc_data_in_item)); - item->event_in = event_in; - - freerdp_thread_lock(plugin->priv->thread); - list_enqueue(plugin->priv->data_in_list, item); - freerdp_thread_unlock(plugin->priv->thread); - - freerdp_thread_signal(plugin->priv->thread); + MessageQueue_Post(plugin->MsgPipe->In, NULL, 1, (void*) event_in, NULL); } static void svc_plugin_open_event(UINT32 openHandle, UINT32 event, void* pData, UINT32 dataLength, @@ -233,7 +154,7 @@ static void svc_plugin_open_event(UINT32 openHandle, UINT32 event, void* pData, plugin = (rdpSvcPlugin*) svc_plugin_find_by_open_handle(openHandle); - if (plugin == NULL) + if (!plugin) { printf("svc_plugin_open_event: error no match\n"); return; @@ -255,36 +176,11 @@ static void svc_plugin_open_event(UINT32 openHandle, UINT32 event, void* pData, } } -static void svc_plugin_process_data_in(rdpSvcPlugin* plugin) -{ - svc_data_in_item* item; - - while (1) - { - /* terminate signal */ - if (freerdp_thread_is_stopped(plugin->priv->thread)) - break; - - freerdp_thread_lock(plugin->priv->thread); - item = list_dequeue(plugin->priv->data_in_list); - freerdp_thread_unlock(plugin->priv->thread); - - if (item != NULL) - { - /* the ownership of the data is passed to the callback */ - if (item->data_in) - IFCALL(plugin->receive_callback, plugin, item->data_in); - if (item->event_in) - IFCALL(plugin->event_callback, plugin, item->event_in); - free(item); - } - else - break; - } -} - static void* svc_plugin_thread_func(void* arg) { + STREAM* data; + RDP_EVENT* event; + wMessage message; rdpSvcPlugin* plugin = (rdpSvcPlugin*) arg; DEBUG_SVC("in"); @@ -293,23 +189,27 @@ static void* svc_plugin_thread_func(void* arg) while (1) { - if (plugin->interval_ms > 0) - freerdp_thread_wait_timeout(plugin->priv->thread, plugin->interval_ms); - else - freerdp_thread_wait(plugin->priv->thread); - - if (freerdp_thread_is_stopped(plugin->priv->thread)) + if (!MessageQueue_Wait(plugin->MsgPipe->In)) break; - freerdp_thread_reset(plugin->priv->thread); - svc_plugin_process_data_in(plugin); + if (MessageQueue_Peek(plugin->MsgPipe->In, &message, TRUE)) + { + if (message.id == WMQ_QUIT) + break; - if (plugin->interval_ms > 0) - IFCALL(plugin->interval_callback, plugin); + if (message.id == 0) + { + data = (STREAM*) message.wParam; + IFCALL(plugin->receive_callback, plugin, data); + } + else if (message.id == 1) + { + event = (RDP_EVENT*) message.wParam; + IFCALL(plugin->event_callback, plugin, event); + } + } } - freerdp_thread_quit(plugin->priv->thread); - DEBUG_SVC("out"); return 0; @@ -317,52 +217,40 @@ static void* svc_plugin_thread_func(void* arg) static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, UINT32 dataLength) { - UINT32 error; + UINT32 status; - error = plugin->channel_entry_points.pVirtualChannelOpen(plugin->priv->init_handle, - &plugin->priv->open_handle, plugin->channel_def.name, svc_plugin_open_event); + status = plugin->channel_entry_points.pVirtualChannelOpen(plugin->init_handle, + &plugin->open_handle, plugin->channel_def.name, svc_plugin_open_event); - if (error != CHANNEL_RC_OK) + if (status != CHANNEL_RC_OK) { printf("svc_plugin_process_connected: open failed\n"); return; } - plugin->priv->data_in_list = list_new(); - plugin->priv->thread = freerdp_thread_new(); + plugin->MsgPipe = MessagePipe_New(); - freerdp_thread_start(plugin->priv->thread, svc_plugin_thread_func, plugin); + plugin->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) svc_plugin_thread_func, (void*) plugin, 0, NULL); } static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) { - svc_data_in_item* item; + MessagePipe_PostQuit(plugin->MsgPipe, 0); + WaitForSingleObject(plugin->thread, INFINITE); - if (plugin->priv->thread) - { - freerdp_thread_stop(plugin->priv->thread); - freerdp_thread_free(plugin->priv->thread); - } + MessagePipe_Free(plugin->MsgPipe); + CloseHandle(plugin->thread); - plugin->channel_entry_points.pVirtualChannelClose(plugin->priv->open_handle); + plugin->channel_entry_points.pVirtualChannelClose(plugin->open_handle); svc_plugin_remove(plugin); - if (plugin->priv->data_in_list) + if (plugin->data_in) { - while ((item = list_dequeue(plugin->priv->data_in_list)) != NULL) - svc_data_in_item_free(item); - list_free(plugin->priv->data_in_list); + stream_free(plugin->data_in); + plugin->data_in = NULL; } - if (plugin->priv->data_in != NULL) - { - stream_free(plugin->priv->data_in); - plugin->priv->data_in = NULL; - } - free(plugin->priv); - plugin->priv = NULL; - IFCALL(plugin->terminate_callback, plugin); } @@ -397,65 +285,53 @@ static void svc_plugin_init_event(void* pInitHandle, UINT32 event, void* pData, void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) { - rdpSvcPluginList* list; - /** * The channel manager will guarantee only one thread can call * VirtualChannelInit at a time. So this should be safe. */ - if (g_mutex == NULL) - g_mutex = CreateMutex(NULL, FALSE, NULL); - memcpy(&plugin->channel_entry_points, pEntryPoints, pEntryPoints->cbSize); + CopyMemory(&plugin->channel_entry_points, pEntryPoints, pEntryPoints->cbSize); - plugin->priv = (rdpSvcPluginPrivate*) malloc(sizeof(rdpSvcPluginPrivate)); - ZeroMemory(plugin->priv, sizeof(rdpSvcPluginPrivate)); + if (!g_AddinList) + g_AddinList = ArrayList_New(TRUE); - /* Add it to the global list */ - list = (rdpSvcPluginList*) malloc(sizeof(rdpSvcPluginList)); - ZeroMemory(list, sizeof(rdpSvcPluginList)); - list->plugin = plugin; + ArrayList_Add(g_AddinList, (void*) plugin); - WaitForSingleObject(g_mutex, INFINITE); - list->next = g_svc_plugin_list; - g_svc_plugin_list = list; - ReleaseMutex(g_mutex); - - plugin->channel_entry_points.pVirtualChannelInit(&plugin->priv->init_handle, + plugin->channel_entry_points.pVirtualChannelInit(&plugin->init_handle, &plugin->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, svc_plugin_init_event); } int svc_plugin_send(rdpSvcPlugin* plugin, STREAM* data_out) { - UINT32 error = 0; + UINT32 status = 0; DEBUG_SVC("length %d", (int) stream_get_length(data_out)); - if (!plugin || !plugin->priv) - error = CHANNEL_RC_BAD_INIT_HANDLE; + if (!plugin) + status = CHANNEL_RC_BAD_INIT_HANDLE; else - error = plugin->channel_entry_points.pVirtualChannelWrite(plugin->priv->open_handle, + status = plugin->channel_entry_points.pVirtualChannelWrite(plugin->open_handle, stream_get_data(data_out), stream_get_length(data_out), data_out); - if (error != CHANNEL_RC_OK) + if (status != CHANNEL_RC_OK) { stream_free(data_out); - printf("svc_plugin_send: VirtualChannelWrite failed %d\n", error); + printf("svc_plugin_send: VirtualChannelWrite failed %d\n", status); } - return error; + return status; } int svc_plugin_send_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { - UINT32 error = 0; + UINT32 status = 0; DEBUG_SVC("event_type %d", event->event_type); - error = plugin->channel_entry_points.pVirtualChannelEventPush(plugin->priv->open_handle, event); + status = plugin->channel_entry_points.pVirtualChannelEventPush(plugin->open_handle, event); - if (error != CHANNEL_RC_OK) - printf("svc_plugin_send_event: VirtualChannelEventPush failed %d\n", error); + if (status != CHANNEL_RC_OK) + printf("svc_plugin_send_event: VirtualChannelEventPush failed %d\n", status); - return error; + return status; } diff --git a/server/Mac/mf_audin.c b/server/Mac/mf_audin.c index c90e252f8..fb5e54b45 100644 --- a/server/Mac/mf_audin.c +++ b/server/Mac/mf_audin.c @@ -25,7 +25,7 @@ #include "mf_audin.h" -static const rdpsndFormat audio_formats[] = +static const AUDIO_FORMAT audio_formats[] = { { 0x11, 2, 22050, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */ { 0x11, 1, 22050, 512, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 1 channels */ diff --git a/server/Mac/mf_rdpsnd.c b/server/Mac/mf_rdpsnd.c index 266805028..0bd40d7ef 100644 --- a/server/Mac/mf_rdpsnd.c +++ b/server/Mac/mf_rdpsnd.c @@ -28,7 +28,7 @@ AQRecorderState recorderState; -static const rdpsndFormat audio_formats[] = +static const AUDIO_FORMAT audio_formats[] = { { 0x11, 2, 22050, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */ { 0x11, 1, 22050, 512, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 1 channels */ diff --git a/server/Sample/sf_audin.c b/server/Sample/sf_audin.c index 9c19aaa7a..4baa6affc 100644 --- a/server/Sample/sf_audin.c +++ b/server/Sample/sf_audin.c @@ -25,7 +25,7 @@ #include "sf_audin.h" -static const rdpsndFormat test_audio_formats[] = +static const AUDIO_FORMAT test_audio_formats[] = { { 0x11, 2, 22050, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */ { 0x11, 1, 22050, 512, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 1 channels */ diff --git a/server/Sample/sf_rdpsnd.c b/server/Sample/sf_rdpsnd.c index ff901fef6..62845cb4c 100644 --- a/server/Sample/sf_rdpsnd.c +++ b/server/Sample/sf_rdpsnd.c @@ -25,7 +25,7 @@ #include "sf_rdpsnd.h" -static const rdpsndFormat test_audio_formats[] = +static const AUDIO_FORMAT test_audio_formats[] = { { 0x11, 2, 22050, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */ { 0x11, 1, 22050, 512, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 1 channels */ diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index 680be7d87..087d444cf 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -655,6 +655,7 @@ static void* test_peer_mainloop(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 = TRUE; diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index fa90456ac..cb24b95d1 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -40,19 +40,18 @@ #endif - -static const rdpsndFormat test_audio_formats[] = +static const AUDIO_FORMAT test_audio_formats[] = { - { 0x11, 2, 22050, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */ - { 0x11, 1, 22050, 512, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 1 channels */ - { 0x01, 2, 22050, 4, 16, 0, NULL }, /* PCM, 22050 Hz, 2 channels, 16 bits */ - { 0x01, 1, 22050, 2, 16, 0, NULL }, /* PCM, 22050 Hz, 1 channels, 16 bits */ - { 0x01, 2, 44100, 4, 16, 0, NULL }, /* PCM, 44100 Hz, 2 channels, 16 bits */ - { 0x01, 1, 44100, 2, 16, 0, NULL }, /* PCM, 44100 Hz, 1 channels, 16 bits */ - { 0x01, 2, 11025, 4, 16, 0, NULL }, /* PCM, 11025 Hz, 2 channels, 16 bits */ - { 0x01, 1, 11025, 2, 16, 0, NULL }, /* PCM, 11025 Hz, 1 channels, 16 bits */ - { 0x01, 2, 8000, 4, 16, 0, NULL }, /* PCM, 8000 Hz, 2 channels, 16 bits */ - { 0x01, 1, 8000, 2, 16, 0, NULL } /* PCM, 8000 Hz, 1 channels, 16 bits */ + { WAVE_FORMAT_DVI_ADPCM, 2, 22050, 0, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */ + { WAVE_FORMAT_DVI_ADPCM, 1, 22050, 0, 512, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 1 channels */ + { WAVE_FORMAT_PCM, 2, 22050, 0, 4, 16, 0, NULL }, /* PCM, 22050 Hz, 2 channels, 16 bits */ + { WAVE_FORMAT_PCM, 1, 22050, 0, 2, 16, 0, NULL }, /* PCM, 22050 Hz, 1 channels, 16 bits */ + { WAVE_FORMAT_PCM, 2, 44100, 0, 4, 16, 0, NULL }, /* PCM, 44100 Hz, 2 channels, 16 bits */ + { WAVE_FORMAT_PCM, 1, 44100, 0, 2, 16, 0, NULL }, /* PCM, 44100 Hz, 1 channels, 16 bits */ + { WAVE_FORMAT_PCM, 2, 11025, 0, 4, 16, 0, NULL }, /* PCM, 11025 Hz, 2 channels, 16 bits */ + { WAVE_FORMAT_PCM, 1, 11025, 0, 2, 16, 0, NULL }, /* PCM, 11025 Hz, 1 channels, 16 bits */ + { WAVE_FORMAT_PCM, 2, 8000, 0, 4, 16, 0, NULL }, /* PCM, 8000 Hz, 2 channels, 16 bits */ + { WAVE_FORMAT_PCM, 1, 8000, 0, 2, 16, 0, NULL } /* PCM, 8000 Hz, 1 channels, 16 bits */ }; static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context) diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index f6d087404..e70bf4fcc 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -282,6 +282,7 @@ struct _wMessage void* context; void* wParam; void* lParam; + UINT64 time; }; typedef struct _wMessage wMessage; @@ -313,4 +314,18 @@ WINPR_API int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL re WINPR_API wMessageQueue* MessageQueue_New(void); WINPR_API void MessageQueue_Free(wMessageQueue* queue); +/* Message Pipe */ + +struct _wMessagePipe +{ + wMessageQueue* In; + wMessageQueue* Out; +}; +typedef struct _wMessagePipe wMessagePipe; + +WINPR_API void MessagePipe_PostQuit(wMessagePipe* pipe, int nExitCode); + +WINPR_API wMessagePipe* MessagePipe_New(void); +WINPR_API void MessagePipe_Free(wMessagePipe* pipe); + #endif /* WINPR_COLLECTIONS_H */ diff --git a/winpr/include/winpr/sysinfo.h b/winpr/include/winpr/sysinfo.h index 79514c73a..2b37ab89d 100644 --- a/winpr/include/winpr/sysinfo.h +++ b/winpr/include/winpr/sysinfo.h @@ -241,6 +241,8 @@ WINPR_API BOOL GetVersionExW(LPOSVERSIONINFOW lpVersionInformation); WINPR_API VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime); +WINPR_API DWORD GetTickCount(void); + #endif #endif /* WINPR_SYSINFO_H */ diff --git a/winpr/libwinpr/sspi/Schannel/schannel.c b/winpr/libwinpr/sspi/Schannel/schannel.c index 8bb59f65d..d53f105ce 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel.c +++ b/winpr/libwinpr/sspi/Schannel/schannel.c @@ -314,12 +314,24 @@ SECURITY_STATUS SEC_ENTRY schannel_QueryContextAttributes(PCtxtHandle phContext, if (ulAttribute == SECPKG_ATTR_SIZES) { - SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer; + SecPkgContext_Sizes* Sizes = (SecPkgContext_Sizes*) pBuffer; - ContextSizes->cbMaxToken = 0x6000; - ContextSizes->cbMaxSignature = 16; - ContextSizes->cbBlockSize = 0; - ContextSizes->cbSecurityTrailer = 16; + Sizes->cbMaxToken = 0x6000; + Sizes->cbMaxSignature = 16; + Sizes->cbBlockSize = 0; + Sizes->cbSecurityTrailer = 16; + + return SEC_E_OK; + } + else if (ulAttribute == SECPKG_ATTR_STREAM_SIZES) + { + SecPkgContext_StreamSizes* StreamSizes = (SecPkgContext_StreamSizes*) pBuffer; + + StreamSizes->cbHeader = 5; + StreamSizes->cbTrailer = 36; + StreamSizes->cbMaximumMessage = 0x4000; + StreamSizes->cBuffers = 4; + StreamSizes->cbBlockSize = 16; return SEC_E_OK; } @@ -354,7 +366,17 @@ SECURITY_STATUS SEC_ENTRY schannel_EncryptMessage(PCtxtHandle phContext, ULONG f SECURITY_STATUS SEC_ENTRY schannel_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) { - return SEC_E_UNSUPPORTED_FUNCTION; + SECURITY_STATUS status; + SCHANNEL_CONTEXT* context; + + context = (SCHANNEL_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + return SEC_E_INVALID_HANDLE; + + status = schannel_openssl_decrypt_message(context->openssl, pMessage); + + return status; } const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA = diff --git a/winpr/libwinpr/sspi/Schannel/schannel_openssl.c b/winpr/libwinpr/sspi/Schannel/schannel_openssl.c index 02bf74017..7214ea0cb 100644 --- a/winpr/libwinpr/sspi/Schannel/schannel_openssl.c +++ b/winpr/libwinpr/sspi/Schannel/schannel_openssl.c @@ -265,6 +265,9 @@ SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context printf("SSL_connect error: %s\n", openssl_get_ssl_error_string(ssl_error)); } + if (status == 1) + context->connected = TRUE; + status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN); if (pOutput->cBuffers < 1) @@ -283,12 +286,12 @@ SECURITY_STATUS schannel_openssl_client_process_tokens(SCHANNEL_OPENSSL* context CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status); pBuffer->cbBuffer = status; - return SEC_I_CONTINUE_NEEDED; + return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED; } else { pBuffer->cbBuffer = 0; - return SEC_E_OK; + return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED; } } @@ -321,6 +324,9 @@ SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context printf("SSL_accept error: %s\n", openssl_get_ssl_error_string(ssl_error)); } + if (status == 1) + context->connected = TRUE; + status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN); if (pOutput->cBuffers < 1) @@ -339,12 +345,12 @@ SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context CopyMemory(pBuffer->pvBuffer, context->ReadBuffer, status); pBuffer->cbBuffer = status; - return SEC_I_CONTINUE_NEEDED; + return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED; } else { pBuffer->cbBuffer = 0; - return SEC_E_OK; + return (context->connected) ? SEC_E_OK : SEC_I_CONTINUE_NEEDED; } } @@ -354,6 +360,8 @@ SECURITY_STATUS schannel_openssl_server_process_tokens(SCHANNEL_OPENSSL* context SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage) { int status; + int length; + int offset; int ssl_error; PSecBuffer pStreamBodyBuffer; PSecBuffer pStreamHeaderBuffer; @@ -376,13 +384,33 @@ SECURITY_STATUS schannel_openssl_encrypt_message(SCHANNEL_OPENSSL* context, PSec status = BIO_read(context->bioWrite, context->ReadBuffer, SCHANNEL_CB_MAX_TOKEN); - return SEC_E_UNSUPPORTED_FUNCTION; + if (status > 0) + { + offset = 0; + length = (pStreamHeaderBuffer->cbBuffer > status) ? status : pStreamHeaderBuffer->cbBuffer; + CopyMemory(pStreamHeaderBuffer->pvBuffer, &context->ReadBuffer[offset], length); + status -= length; + + offset += length; + length = (pStreamBodyBuffer->cbBuffer > status) ? status : pStreamBodyBuffer->cbBuffer; + CopyMemory(pStreamBodyBuffer->pvBuffer, &context->ReadBuffer[offset], length); + status -= length; + + offset += length; + length = (pStreamTrailerBuffer->cbBuffer > status) ? status : pStreamTrailerBuffer->cbBuffer; + CopyMemory(pStreamTrailerBuffer->pvBuffer, &context->ReadBuffer[offset], length); + status -= length; + } + + return SEC_E_OK; } SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context, PSecBufferDesc pMessage) { - //int status; - //int ssl_error; + int status; + int length; + BYTE* buffer; + int ssl_error; PSecBuffer pBuffer; pBuffer = sspi_FindSecBuffer(pMessage, SECBUFFER_DATA); @@ -390,7 +418,33 @@ SECURITY_STATUS schannel_openssl_decrypt_message(SCHANNEL_OPENSSL* context, PSec if (!pBuffer) return SEC_E_INVALID_TOKEN; - return SEC_E_UNSUPPORTED_FUNCTION; + status = BIO_write(context->bioRead, pBuffer->pvBuffer, pBuffer->cbBuffer); + + status = SSL_read(context->ssl, pBuffer->pvBuffer, pBuffer->cbBuffer); + + if (status < 0) + { + ssl_error = SSL_get_error(context->ssl, status); + printf("SSL_read: %s\n", openssl_get_ssl_error_string(ssl_error)); + } + + length = status; + buffer = pBuffer->pvBuffer; + + pMessage->pBuffers[0].BufferType = SECBUFFER_STREAM_HEADER; + pMessage->pBuffers[0].cbBuffer = 5; + + pMessage->pBuffers[1].BufferType = SECBUFFER_DATA; + pMessage->pBuffers[1].pvBuffer = buffer; + pMessage->pBuffers[1].cbBuffer = length; + + pMessage->pBuffers[2].BufferType = SECBUFFER_STREAM_TRAILER; + pMessage->pBuffers[2].cbBuffer = 36; + + pMessage->pBuffers[3].BufferType = SECBUFFER_EMPTY; + pMessage->pBuffers[3].cbBuffer = 0; + + return SEC_E_OK; } SCHANNEL_OPENSSL* schannel_openssl_new() diff --git a/winpr/libwinpr/sspi/test/TestSchannel.c b/winpr/libwinpr/sspi/test/TestSchannel.c index 11678b059..740ad5c4f 100644 --- a/winpr/libwinpr/sspi/test/TestSchannel.c +++ b/winpr/libwinpr/sspi/test/TestSchannel.c @@ -332,8 +332,9 @@ static void* schannel_test_server_thread(void* arg) printf("Server cBuffers: %d pBuffers[0]: %d type: %d\n", SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType); - printf("Server Input cBuffers: %d pBuffers[1]: %d type: %d\n", - SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); + printf("Server Input cBuffers: %d pBuffers[0]: %d type: %d pBuffers[1]: %d type: %d\n", SecBufferDesc_in.cBuffers, + SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType, + SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); if (SecBufferDesc_in.pBuffers[1].BufferType == SECBUFFER_EXTRA) { @@ -544,7 +545,7 @@ int TestSchannel(int argc, char* argv[]) { NumberOfBytesRead = 0; } - + g_ClientWait = TRUE; printf("NumberOfBytesRead: %d\n", NumberOfBytesRead); @@ -588,8 +589,9 @@ int TestSchannel(int argc, char* argv[]) printf("Client Output cBuffers: %d pBuffers[0]: %d type: %d\n", SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType); - printf("Client Input cBuffers: %d pBuffers[1]: %d type: %d\n", - SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); + printf("Client Input cBuffers: %d pBuffers[0]: %d type: %d pBuffers[1]: %d type: %d\n", SecBufferDesc_in.cBuffers, + SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType, + SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); if (status != SEC_E_INCOMPLETE_MESSAGE) { diff --git a/winpr/libwinpr/sysinfo/CMakeLists.txt b/winpr/libwinpr/sysinfo/CMakeLists.txt index e0a65dd4b..769885818 100644 --- a/winpr/libwinpr/sysinfo/CMakeLists.txt +++ b/winpr/libwinpr/sysinfo/CMakeLists.txt @@ -31,9 +31,14 @@ add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT" set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib") -if(MONOLITHIC_BUILD) +if((NOT WIN32) AND (NOT APPLE) AND (NOT ANDROID)) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} rt) +endif() +if(MONOLITHIC_BUILD) + set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) else() + target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() diff --git a/winpr/libwinpr/sysinfo/sysinfo.c b/winpr/libwinpr/sysinfo/sysinfo.c index 29d6da306..6f574fe7e 100644 --- a/winpr/libwinpr/sysinfo/sysinfo.c +++ b/winpr/libwinpr/sysinfo/sysinfo.c @@ -299,4 +299,36 @@ VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) lpSystemTimeAsFileTime->dwHighDateTime = time64.HighPart; } +#ifndef CLOCK_MONOTONIC_RAW +#define CLOCK_MONOTONIC_RAW 4 +#endif + +DWORD GetTickCount(void) +{ + DWORD ticks = 0; + +#ifdef __linux__ + + struct timespec ts; + + if (!clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) + ticks = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); + +#else + + /** + * FIXME: this is relative to the Epoch time, and we + * need to return a value relative to the system uptime. + */ + + struct timeval tv; + + if (!gettimeofday(&tv, NULL)) + ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + +#endif + + return ticks; +} + #endif diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index bcc705040..54c88f286 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -29,7 +29,8 @@ set(${MODULE_PREFIX}_COLLECTIONS_SRCS collections/CountdownEvent.c collections/BufferPool.c collections/ObjectPool.c - collections/MessageQueue.c) + collections/MessageQueue.c + collections/MessagePipe.c) set(${MODULE_PREFIX}_SRCS sam.c @@ -57,7 +58,7 @@ set(${MODULE_PREFIX}_LIBS set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL MODULE winpr - MODULES winpr-crt winpr-synch) + MODULES winpr-crt winpr-synch winpr-sysinfo) if(MONOLITHIC_BUILD) set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE) diff --git a/winpr/libwinpr/utils/cmdline.c b/winpr/libwinpr/utils/cmdline.c index 431f34a4a..7ba1822c5 100644 --- a/winpr/libwinpr/utils/cmdline.c +++ b/winpr/libwinpr/utils/cmdline.c @@ -209,8 +209,27 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* if ((flags & COMMAND_LINE_SEPARATOR_SPACE) && ((i + 1) < argc)) { - if ((options[j].Flags & COMMAND_LINE_VALUE_REQUIRED) || - (options[j].Flags & COMMAND_LINE_VALUE_OPTIONAL)) + int value_present = 1; + + if (flags & COMMAND_LINE_SIGIL_DASH) + { + if (strncmp(argv[i + 1], "-", 1) == 0) + value_present = 0; + } + + if (flags & COMMAND_LINE_SIGIL_DOUBLE_DASH) + { + if (strncmp(argv[i + 1], "--", 2) == 0) + value_present = 0; + } + + if (flags & COMMAND_LINE_SIGIL_SLASH) + { + if (strncmp(argv[i + 1], "/", 1) == 0) + value_present = 0; + } + + if (value_present) { i++; value_index = 0; diff --git a/winpr/libwinpr/utils/collections/CountdownEvent.c b/winpr/libwinpr/utils/collections/CountdownEvent.c index 0e9df2b35..787c7e31b 100644 --- a/winpr/libwinpr/utils/collections/CountdownEvent.c +++ b/winpr/libwinpr/utils/collections/CountdownEvent.c @@ -116,13 +116,10 @@ BOOL CountdownEvent_Signal(wCountdownEvent* countdown, DWORD signalCount) if (WaitForSingleObject(countdown->event, 0) == WAIT_OBJECT_0) oldStatus = TRUE; - countdown->count -= signalCount; - - if (countdown->count < 0) - { - printf("CountdownEvent_Signal warning: count is less than zero\n"); + if (signalCount <= countdown->count) + countdown->count -= signalCount; + else countdown->count = 0; - } if (countdown->count == 0) newStatus = TRUE; diff --git a/winpr/libwinpr/utils/collections/MessagePipe.c b/winpr/libwinpr/utils/collections/MessagePipe.c new file mode 100644 index 000000000..6be37e7ed --- /dev/null +++ b/winpr/libwinpr/utils/collections/MessagePipe.c @@ -0,0 +1,73 @@ +/** + * WinPR: Windows Portable Runtime + * Message Pipe + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +/** + * Properties + */ + + + +/** + * Methods + */ + +void MessagePipe_PostQuit(wMessagePipe* pipe, int nExitCode) +{ + MessageQueue_PostQuit(pipe->In, nExitCode); + MessageQueue_PostQuit(pipe->Out, nExitCode); +} + +/** + * Construction, Destruction + */ + +wMessagePipe* MessagePipe_New() +{ + wMessagePipe* pipe = NULL; + + pipe = (wMessagePipe*) malloc(sizeof(wMessagePipe)); + + if (pipe) + { + pipe->In = MessageQueue_New(); + pipe->Out = MessageQueue_New(); + } + + return pipe; +} + +void MessagePipe_Free(wMessagePipe* pipe) +{ + if (pipe) + { + MessageQueue_Free(pipe->In); + MessageQueue_Free(pipe->Out); + + free(pipe); + } +} diff --git a/winpr/libwinpr/utils/collections/MessageQueue.c b/winpr/libwinpr/utils/collections/MessageQueue.c index a2b7e378a..d13916922 100644 --- a/winpr/libwinpr/utils/collections/MessageQueue.c +++ b/winpr/libwinpr/utils/collections/MessageQueue.c @@ -22,6 +22,7 @@ #endif #include +#include #include @@ -93,6 +94,9 @@ void MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message) queue->tail = (queue->tail + 1) % queue->capacity; queue->size++; + message = &(queue->array[queue->tail]); + message->time = (UINT64) GetTickCount(); + if (queue->size > 0) SetEvent(queue->event); diff --git a/winpr/libwinpr/utils/test/CMakeLists.txt b/winpr/libwinpr/utils/test/CMakeLists.txt index 97117735c..07f7e589e 100644 --- a/winpr/libwinpr/utils/test/CMakeLists.txt +++ b/winpr/libwinpr/utils/test/CMakeLists.txt @@ -8,7 +8,8 @@ set(${MODULE_PREFIX}_TESTS TestQueue.c TestArrayList.c TestCmdLine.c - TestMessageQueue.c) + TestMessageQueue.c + TestMessagePipe.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} diff --git a/winpr/libwinpr/utils/test/TestMessagePipe.c b/winpr/libwinpr/utils/test/TestMessagePipe.c new file mode 100644 index 000000000..6006e1b0d --- /dev/null +++ b/winpr/libwinpr/utils/test/TestMessagePipe.c @@ -0,0 +1,81 @@ + +#include +#include +#include + +static void* message_echo_pipe_client_thread(void* arg) +{ + int index; + int count; + wMessage message; + wMessagePipe* pipe; + + count = index = 0; + pipe = (wMessagePipe*) arg; + + while (index < 100) + { + MessageQueue_Post(pipe->In, NULL, 0, (void*) (size_t) index, NULL); + + if (!MessageQueue_Wait(pipe->Out)) + break; + + if (!MessageQueue_Peek(pipe->Out, &message, TRUE)) + break; + + if (message.id == WMQ_QUIT) + break; + + count = (int) (size_t) message.wParam; + + if (count != index) + printf("Echo count mismatch: Actual: %d, Expected: %d\n", count, index); + + index++; + } + + MessageQueue_PostQuit(pipe->In, 0); + + return NULL; +} + +static void* message_echo_pipe_server_thread(void* arg) +{ + int count; + wMessage message; + wMessagePipe* pipe; + + pipe = (wMessagePipe*) arg; + + while (MessageQueue_Wait(pipe->In)) + { + if (MessageQueue_Peek(pipe->In, &message, TRUE)) + { + if (message.id == WMQ_QUIT) + break; + + count = (int) (size_t) message.wParam; + + MessageQueue_Dispatch(pipe->Out, &message); + } + } + + return NULL; +} + +int TestMessagePipe(int argc, char* argv[]) +{ + HANDLE ClientThread; + HANDLE ServerThread; + wMessagePipe* EchoPipe; + + EchoPipe = MessagePipe_New(); + + ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) message_echo_pipe_client_thread, (void*) EchoPipe, 0, NULL); + ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) message_echo_pipe_server_thread, (void*) EchoPipe, 0, NULL); + + WaitForSingleObject(ClientThread, INFINITE); + WaitForSingleObject(ServerThread, INFINITE); + + return 0; +}