diff --git a/.gitignore b/.gitignore index 5d23fe8dd..bbc60f936 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ docs/api *.dylib cunit/test_freerdp client/test/freerdp-test +client/DirectFB/dfreerdp diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index f699877f0..cfc941c78 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -19,3 +19,9 @@ # User Interfaces add_subdirectory(test) + +# Build DirectFB Client +find_package(DirectFB) +if(DIRECTFB_FOUND) + add_subdirectory(DirectFB) +endif() diff --git a/client/DirectFB/CMakeLists.txt b/client/DirectFB/CMakeLists.txt new file mode 100644 index 000000000..8a871402a --- /dev/null +++ b/client/DirectFB/CMakeLists.txt @@ -0,0 +1,31 @@ +# FreeRDP: A Remote Desktop Protocol Client +# FreeRDP DirectFB Client +# +# Copyright 2011 O.S. Systems Software Ltda. +# Copyright 2011 Otavio Salvador +# Copyright 2011 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. + +include_directories(../../libfreerdp-gdi) +include_directories(../../libfreerdp-core) +include_directories(${DIRECTFB_INCLUDE_DIRS}) + +add_executable(dfreerdp + dfreerdp.c + dfreerdp.h) + +target_link_libraries(dfreerdp freerdp-core) +target_link_libraries(dfreerdp freerdp-gdi) +target_link_libraries(dfreerdp freerdp-utils) +target_link_libraries(dfreerdp ${DIRECTFB_LIBRARIES}) diff --git a/client/DirectFB/dfreerdp.c b/client/DirectFB/dfreerdp.c new file mode 100644 index 000000000..cd918b919 --- /dev/null +++ b/client/DirectFB/dfreerdp.c @@ -0,0 +1,203 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * DirectFB Client + * + * Copyright 2011 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. + */ + +#include "gdi.h" +#include +#include +#include +#include +#include + +#include "dfreerdp.h" + +freerdp_sem g_sem; +static int g_thread_count = 0; + +struct thread_data +{ + freerdp* instance; +}; + +int df_begin_paint(rdpUpdate* update) +{ + GDI* gdi; + + gdi = GET_GDI(update); + gdi->primary->hdc->hwnd->invalid->null = 1; + + return 0; +} + +int df_end_paint(rdpUpdate* update) +{ + GDI* gdi; + dfInfo* dfi; + + gdi = GET_GDI(update); + dfi = GET_DFI(update); + + if (gdi->primary->hdc->hwnd->invalid->null) + return 0; + + dfi->update_rect.x = gdi->primary->hdc->hwnd->invalid->x; + dfi->update_rect.y = gdi->primary->hdc->hwnd->invalid->y; + dfi->update_rect.w = gdi->primary->hdc->hwnd->invalid->w; + dfi->update_rect.h = gdi->primary->hdc->hwnd->invalid->h; + + dfi->primary->Blit(dfi->primary, dfi->surface, &(dfi->update_rect), dfi->update_rect.x, dfi->update_rect.y); + + return 0; +} + +boolean df_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) +{ + return True; +} + +boolean df_check_fds(freerdp* instance) +{ + return True; +} + +boolean df_pre_connect(freerdp* instance) +{ + dfInfo* dfi; + + dfi = (dfInfo*) xzalloc(sizeof(dfInfo)); + SET_DFI(instance, dfi); + + return True; +} + +boolean df_post_connect(freerdp* instance) +{ + GDI* gdi; + dfInfo* dfi; + + dfi = GET_DFI(instance); + SET_DFI(instance->update, dfi); + + gdi_init(instance, CLRCONV_ALPHA | CLRBUF_16BPP | CLRBUF_32BPP); + gdi = GET_GDI(instance->update); + + dfi->err = DirectFBCreate(&(dfi->dfb)); + + dfi->dsc.flags = DSDESC_CAPS; + dfi->dsc.caps = DSCAPS_PRIMARY; + dfi->err = dfi->dfb->CreateSurface(dfi->dfb, &(dfi->dsc), &(dfi->primary)); + dfi->err = dfi->primary->GetSize(dfi->primary, &(gdi->width), &(gdi->height)); + dfi->dfb->SetVideoMode(dfi->dfb, gdi->width, gdi->height, gdi->dstBpp); + dfi->dfb->CreateInputEventBuffer(dfi->dfb, DICAPS_ALL, DFB_TRUE, &(dfi->event_buffer)); + dfi->event_buffer->CreateFileDescriptor(dfi->event_buffer, &(dfi->read_fds)); + + dfi->dfb->GetDisplayLayer(dfi->dfb, 0, &(dfi->layer)); + dfi->layer->EnableCursor(dfi->layer, 1); + + dfi->dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PREALLOCATED | DSDESC_PIXELFORMAT; + dfi->dsc.caps = DSCAPS_SYSTEMONLY; + dfi->dsc.width = gdi->width; + dfi->dsc.height = gdi->height; + + if (gdi->dstBpp == 32 || gdi->dstBpp == 24) + dfi->dsc.pixelformat = DSPF_AiRGB; + else if (gdi->dstBpp == 16 || gdi->dstBpp == 15) + dfi->dsc.pixelformat = DSPF_RGB16; + else if (gdi->dstBpp == 8) + dfi->dsc.pixelformat = DSPF_RGB332; + else + dfi->dsc.pixelformat = DSPF_AiRGB; + + dfi->dsc.preallocated[0].data = gdi->primary_buffer; + dfi->dsc.preallocated[0].pitch = gdi->width * gdi->bytesPerPixel; + dfi->dfb->CreateSurface(dfi->dfb, &(dfi->dsc), &(dfi->surface)); + + instance->update->BeginPaint = df_begin_paint; + instance->update->EndPaint = df_end_paint; + + return True; +} + +int dfreerdp_run(freerdp* instance) +{ + int rcount; + int wcount; + void* rfds[32]; + void* wfds[32]; + fd_set rfds_set; + fd_set wfds_set; + + memset(rfds, 0, sizeof(rfds)); + memset(wfds, 0, sizeof(wfds)); + + printf("DirectFB Run\n"); + + instance->Connect(instance); + + freerdp_free(instance); + + return 0; +} + +void* thread_func(void* param) +{ + struct thread_data* data; + data = (struct thread_data*) param; + + dfreerdp_run(data->instance); + + xfree(data); + + pthread_detach(pthread_self()); + + g_thread_count--; + + if (g_thread_count < 1) + freerdp_sem_signal(&g_sem); + + return NULL; +} + +int main(int argc, char* argv[]) +{ + pthread_t thread; + freerdp* instance; + struct thread_data* data; + + g_sem = freerdp_sem_new(1); + + instance = freerdp_new(); + instance->PreConnect = df_pre_connect; + instance->PostConnect = df_post_connect; + + DirectFBInit(&argc, &argv); + freerdp_parse_args(instance->settings, argc, argv, NULL, NULL, NULL, NULL); + + data = (struct thread_data*) xzalloc(sizeof(struct thread_data)); + data->instance = instance; + + g_thread_count++; + pthread_create(&thread, 0, thread_func, data); + + while (g_thread_count > 0) + { + freerdp_sem_wait(g_sem); + } + + return 0; +} diff --git a/client/DirectFB/dfreerdp.h b/client/DirectFB/dfreerdp.h new file mode 100644 index 000000000..3a3944fea --- /dev/null +++ b/client/DirectFB/dfreerdp.h @@ -0,0 +1,45 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * DirectFB Client + * + * Copyright 2011 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. + */ + +#ifndef __DFREERDP_H +#define __DFREERDP_H + +#include +#include +#include + +#define SET_DFI(_instance, _dfi) (_instance)->param1 = _dfi +#define GET_DFI(_instance) ((dfInfo *) ((_instance)->param1)) + +struct df_info +{ + int read_fds; + DFBResult err; + IDirectFB* dfb; + DFBEvent event; + DFBRectangle update_rect; + DFBSurfaceDescription dsc; + IDirectFBSurface* primary; + IDirectFBSurface* surface; + IDirectFBDisplayLayer* layer; + IDirectFBEventBuffer* event_buffer; +}; +typedef struct df_info dfInfo; + +#endif /* __DFREERDP_H */ diff --git a/cmake/FindDirectFB.cmake b/cmake/FindDirectFB.cmake new file mode 100644 index 000000000..9e226341f --- /dev/null +++ b/cmake/FindDirectFB.cmake @@ -0,0 +1,49 @@ +# - Find DirectFB +# Find the DirectFB libraries +# +# This module defines the following variables: +# DIRECTFB_FOUND - True if DIRECTFB_INCLUDE_DIR & DIRECTFB_LIBRARY are found +# DIRECTFB_LIBRARIES - Set when DIRECTFB_LIBRARY is found +# DIRECTFB_INCLUDE_DIRS - Set when DIRECTFB_INCLUDE_DIR is found +# +# DIRECTFB_INCLUDE_DIR - where to find CUnit.h, etc. +# DIRECTFB_LIBRARY - the cunit library +# + +#============================================================================= +# Copyright 2011 O.S. Systems Software Ltda. +# Copyright 2011 Otavio Salvador +# Copyright 2011 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. +#============================================================================= + +find_path(DIRECTFB_INCLUDE_DIR NAMES directfb.h + PATH_SUFFIXES directfb + DOC "The directfb include directory" +) + +find_library(DIRECTFB_LIBRARY NAMES directfb + DOC "The DirectFB library" +) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(DIRECTFB DEFAULT_MSG DIRECTFB_LIBRARY DIRECTFB_INCLUDE_DIR) + +if(DIRECTFB_FOUND) + set( DIRECTFB_LIBRARIES ${DIRECTFB_LIBRARY} ) + set( DIRECTFB_INCLUDE_DIRS ${DIRECTFB_INCLUDE_DIR} ) +endif() + +mark_as_advanced(DIRECTFB_INCLUDE_DIR DIRECTFB_LIBRARY) + diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index e3dccc940..08578f371 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -38,6 +38,10 @@ FREERDP_API void freerdp_global_finish(); typedef struct rdp_freerdp freerdp; typedef boolean (*pcConnect)(freerdp* freerdp); +typedef boolean (*pcPreConnect)(freerdp* freerdp); +typedef boolean (*pcPostConnect)(freerdp* freerdp); +typedef boolean (*pcGetFileDescriptor)(freerdp* freerdp, void** rfds, int* rcount, void** wfds, int* wcount); +typedef boolean (*pcCheckFileDescriptor)(freerdp* freerdp); typedef int (*pcChannelDataInput)(freerdp* freerdp, int channelId, uint8* data, int size); struct rdp_freerdp @@ -53,6 +57,10 @@ struct rdp_freerdp rdpSettings* settings; pcConnect Connect; + pcPreConnect PreConnect; + pcPostConnect PostConnect; + pcGetFileDescriptor GetFileDescriptor; + pcCheckFileDescriptor CheckFileDescriptor; pcChannelDataInput ChannelDataInput; }; diff --git a/include/freerdp/update.h b/include/freerdp/update.h index e6fc08809..ba5f50355 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -378,6 +378,8 @@ typedef struct typedef struct rdp_update rdpUpdate; +typedef int (*pcBeginPaint)(rdpUpdate* update); +typedef int (*pcEndPaint)(rdpUpdate* update); typedef int (*pcSynchronize)(rdpUpdate* update); typedef int (*pcBitmap)(rdpUpdate* update, BITMAP_UPDATE* bitmap); typedef int (*pcPalette)(rdpUpdate* update, PALETTE_UPDATE* palette); @@ -407,9 +409,12 @@ typedef int (*pcGlyphIndex)(rdpUpdate* update, GLYPH_INDEX_ORDER* glyph_index); struct rdp_update { void* rdp; + void* gdi; void* param1; void* param2; + pcBeginPaint BeginPaint; + pcEndPaint EndPaint; pcSynchronize Synchronize; pcBitmap Bitmap; pcPalette Palette; diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index c9b3ff6e9..5b027af9e 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -96,11 +96,6 @@ boolean rdp_client_connect(rdpRdp* rdp) rdp_client_activate(rdp); - while(1) - { - rdp_recv(rdp); - } - return True; } diff --git a/libfreerdp-core/freerdp.c b/libfreerdp-core/freerdp.c index 4469973bd..5f33a185d 100644 --- a/libfreerdp-core/freerdp.c +++ b/libfreerdp-core/freerdp.c @@ -20,6 +20,7 @@ #include "rdp.h" #include "input.h" #include "update.h" +#include "transport.h" #include "connection.h" #include @@ -27,7 +28,41 @@ boolean freerdp_connect(freerdp* instance) { - return rdp_client_connect((rdpRdp*) instance->rdp); + rdpRdp* rdp; + boolean status; + + rdp = (rdpRdp*) instance->rdp; + + IFCALL(instance->PreConnect, instance); + status = rdp_client_connect((rdpRdp*) instance->rdp); + IFCALL(instance->PostConnect, instance); + + while(1) + { + rdp_recv(rdp); + } + + return status; +} + +boolean freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) +{ + rdpRdp* rdp; + + rdp = (rdpRdp*) instance->rdp; + rfds[*rcount] = (void*)(long)(rdp->transport->tcp->sockfd); + (*rcount)++; + + return True; +} + +boolean freerdp_check_fds(freerdp* instance) +{ + rdpRdp* rdp; + + rdp = (rdpRdp*) instance->rdp; + + return True; } freerdp* freerdp_new() @@ -45,6 +80,8 @@ freerdp* freerdp_new() instance->settings = rdp->settings; instance->Connect = freerdp_connect; + instance->GetFileDescriptor = freerdp_get_fds; + instance->CheckFileDescriptor = freerdp_check_fds; } return instance; diff --git a/libfreerdp-core/update.c b/libfreerdp-core/update.c index 891281c66..10caeea0a 100644 --- a/libfreerdp-core/update.c +++ b/libfreerdp-core/update.c @@ -153,6 +153,8 @@ void update_recv(rdpUpdate* update, STREAM* s) //printf("%s Update Data PDU\n", UPDATE_TYPE_STRINGS[updateType]); + IFCALL(update->BeginPaint, update); + switch (updateType) { case UPDATE_TYPE_ORDERS: @@ -174,6 +176,8 @@ void update_recv(rdpUpdate* update, STREAM* s) IFCALL(update->Synchronize, update); break; } + + IFCALL(update->EndPaint, update); } rdpUpdate* update_new(rdpRdp* rdp) diff --git a/libfreerdp-gdi/gdi.c b/libfreerdp-gdi/gdi.c index 3b93ae682..e994b7659 100644 --- a/libfreerdp-gdi/gdi.c +++ b/libfreerdp-gdi/gdi.c @@ -1195,7 +1195,7 @@ int gdi_init(freerdp* instance, uint32 flags) void gdi_free(freerdp* instance) { - GDI *gdi = GET_GDI(instance); + GDI *gdi = GET_GDI(instance->update); if (gdi) { @@ -1205,6 +1205,6 @@ void gdi_free(freerdp* instance) free(gdi); } - SET_GDI(instance, NULL); + SET_GDI(instance->update, NULL); } diff --git a/libfreerdp-gdi/gdi.h b/libfreerdp-gdi/gdi.h index 4745bb509..05398c23e 100644 --- a/libfreerdp-gdi/gdi.h +++ b/libfreerdp-gdi/gdi.h @@ -256,8 +256,8 @@ void gdi_bitmap_free(GDI_IMAGE *gdi_bmp); int gdi_init(freerdp* instance, uint32 flags); void gdi_free(freerdp* instance); -#define SET_GDI(_instance, _gdi) (_instance)->param1 = _gdi -#define GET_GDI(_instance) ((GDI*) ((_instance)->param1)) +#define SET_GDI(_instance, _gdi) (_instance)->gdi = _gdi +#define GET_GDI(_instance) ((GDI*) ((_instance)->gdi)) #ifdef WITH_DEBUG_GDI #define DEBUG_GDI(fmt, ...) DEBUG_CLASS(GDI, fmt, ## __VA_ARGS__)