diff --git a/uirdesktop/dfb.c b/uirdesktop/dfb.c new file mode 100644 index 00000000..cf51f801 --- /dev/null +++ b/uirdesktop/dfb.c @@ -0,0 +1,723 @@ +/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + directfb calls + Copyright (C) Jay Sorg 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "uimain.h" + +extern char g_username[]; +extern char g_hostname[]; +extern char g_servername[]; +extern char g_password[]; +extern char g_shell[]; +extern char g_directory[]; +extern char g_domain[]; +extern int g_width; +extern int g_height; +extern int g_tcp_sck; +extern int g_server_depth; +extern int g_tcp_port_rdp; /* in tcp.c */ +extern int pal_entries[]; + +extern char * g_bs; + +static pthread_mutex_t g_mutex1 = PTHREAD_MUTEX_INITIALIZER; + +/* direct frame buffer stuff */ +static IDirectFB * g_dfb = 0; +static IDirectFBSurface * g_primary = 0; +static int g_event_fd = 0; +static IDirectFBEventBuffer * g_event = 0; +static DFBRectangle g_rect = {0, 0, 0, 0}; + +struct cursor +{ + unsigned char andmask[32 * 32]; + unsigned char xormask[32 * 32]; + int x; + int y; + int w; + int h; +}; +static struct cursor g_mcursor; /* current mouse */ +static int g_mouse_x = 0; +static int g_mouse_y = 0; + +static IDirectFBSurface * g_s = 0; + +//static IDirectFBDataBuffer * g_buffer = 0; +//static IDirectFBImageProvider * g_provider = 0; + +/*****************************************************************************/ +void +mi_error(char * msg) +{ + printf(msg); +} + +/*****************************************************************************/ +void +mi_warning(char * msg) +{ + printf(msg); +} + +/*****************************************************************************/ +int +mi_read_keyboard_state(void) +{ + return 0; +} + +/*****************************************************************************/ +/* returns non zero if ok */ +int +mi_create_window(void) +{ + g_primary->SetColor(g_primary, 0, 0, 0, 0xff); + g_primary->FillRectangle(g_primary, 0, 0, g_width, g_height); + return 1; +} + +/*****************************************************************************/ +void +mi_update_screen(void) +{ + //g_provider->RenderTo(g_provider, g_primary, 0); + if (g_rect.w > 0 && g_rect.h > 0) + { + g_primary->Blit(g_primary, g_s, &g_rect, g_rect.x, g_rect.y); + + //g_primary->Blit(g_primary, g_s, 0, 0, 0); + + //g_primary->Blit(g_primary, g_primary, 0, 0, 0); + //g_primary->Blit(g_primary, g_s, &g_rect, g_rect.x, g_rect.y); + //g_primary->Flip(g_primary, 0, 0); + } + g_rect.x = 0; + g_rect.y = 0; + g_rect.w = 0; + g_rect.h = 0; +} + +/*****************************************************************************/ +void process_event(DFBEvent * event) +{ + DFBInputEvent * input_event; + int mouse_x; + int mouse_y; + + mouse_x = g_mouse_x + g_mcursor.x; + mouse_y = g_mouse_y + g_mcursor.y; + if (event->clazz == DFEC_INPUT) + { + input_event = (DFBInputEvent *) event; + if (input_event->type == DIET_AXISMOTION) + { + if (input_event->flags & DIEF_AXISABS) + { + if (input_event->axis == DIAI_X) + { + mouse_x = input_event->axisabs; + } + else if (input_event->axis == DIAI_Y) + { + mouse_y = input_event->axisabs; + } + } + if (input_event->flags & DIEF_AXISREL) + { + if (input_event->axis == DIAI_X) + { + mouse_x += input_event->axisrel; + } + else if (input_event->axis == DIAI_Y) + { + mouse_y += input_event->axisrel; + } + } + mouse_x = UI_MAX(mouse_x, 0); + mouse_x = UI_MIN(mouse_x, g_width - 1); + mouse_y = UI_MAX(mouse_y, 0); + mouse_y = UI_MIN(mouse_y, g_height - 1); + ui_mouse_move(mouse_x, mouse_y); + } + else if (input_event->type == DIET_BUTTONPRESS) + { + if (input_event->button == DIBI_LEFT) + { + ui_mouse_button(1, mouse_x, mouse_y, 1); + //rdp_send_input(0, RDP_INPUT_MOUSE, + // MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1, + // mouse_x, mouse_y); + } + else if (input_event->button == DIBI_RIGHT) + { + //mi_update_screen(); + ui_mouse_button(2, mouse_x, mouse_y, 1); +// invalidate(0, 0, g_width, g_height); + //rdp_send_input(0, RDP_INPUT_MOUSE, + // MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2, + // mouse_x, mouse_y); + } + else if (input_event->button == DIBI_MIDDLE) + { + ui_mouse_button(3, mouse_x, mouse_y, 1); + } + } + else if (input_event->type == DIET_BUTTONRELEASE) + { + if (input_event->button == DIBI_LEFT) + { + ui_mouse_button(1, mouse_x, mouse_y, 0); + //rdp_send_input(0, RDP_INPUT_MOUSE, + // MOUSE_FLAG_BUTTON1, + // mouse_x, mouse_y); + } + else if (input_event->button == DIBI_RIGHT) + { + ui_mouse_button(2, mouse_x, mouse_y, 0); + //rdp_send_input(0, RDP_INPUT_MOUSE, + // MOUSE_FLAG_BUTTON2, + // mouse_x, mouse_y); + } + else if (input_event->button == DIBI_MIDDLE) + { + ui_mouse_button(3, mouse_x, mouse_y, 0); + } + } + else if (input_event->type == DIET_KEYPRESS) + { + //printf("hi1 %d\n", input_event->key_id); + return; + } + else if (input_event->type == DIET_KEYRELEASE) + { + //printf("hi2 %d\n", input_event->key_id); + return; + } + } + g_mouse_x = mouse_x - g_mcursor.x; + g_mouse_y = mouse_y - g_mcursor.y; +// printf("%d %d\n", g_mouse_x, g_mouse_y); + g_primary->FillRectangle(g_primary, g_mouse_x, g_mouse_y, 5, 5); +// draw_mouse(); +} + +/*****************************************************************************/ +int +mi_main_loop(void) +{ + fd_set rfds; + int rv; + int fd; + int count; + DFBEvent event[10]; + struct timeval tv; + + fd = g_tcp_sck; + if (g_event_fd > fd) + { + fd = g_event_fd; + } + FD_ZERO(&rfds); + FD_SET(g_tcp_sck, &rfds); + FD_SET(g_event_fd, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 0; + rv = select(fd + 1, &rfds, 0, 0, &tv); + while (rv > -1) + { + if (rv > 0) + { + if (FD_ISSET(g_tcp_sck, &rfds)) + { + if (!ui_read_wire()) + { + return 0; + } + } + if (FD_ISSET(g_event_fd, &rfds)) + { + count = read(g_event_fd, &(event[0]), sizeof(DFBEvent)); + if (count == sizeof(DFBEvent)) + { + //printf("got event\n"); + //hexdump(&event, sizeof(DFBEvent)); + process_event(&(event[0])); + } + else + { + printf("error reading g_event_fd in main_loop\n"); + } + } + } + else + { + //usleep(1000000 / 60); + usleep(0); + } + FD_ZERO(&rfds); + FD_SET(g_tcp_sck, &rfds); + FD_SET(g_event_fd, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 0; + rv = select(fd + 1, &rfds, 0, 0, &tv); + } + return 0; +} + +/*****************************************************************************/ +void +mi_add_to(int x, int y, int cx, int cy) +{ + int right; + int bottom; + + if (g_rect.h == 0 && g_rect.w == 0) + { + g_rect.x = x; + g_rect.y = y; + g_rect.w = cx; + g_rect.h = cy; + } + else + { + right = g_rect.x + g_rect.w; + bottom = g_rect.y + g_rect.h; + if (x + cx > right) + { + right = x + cx; + } + if (y + cy > bottom) + { + bottom = y + cy; + } + if (x < g_rect.x) + { + g_rect.x = x; + } + if (y < g_rect.y) + { + g_rect.y = y; + } + g_rect.w = right - g_rect.x; + g_rect.h = bottom - g_rect.y; + } +} + +/*****************************************************************************/ +void +mi_invalidate(int x, int y, int cx, int cy) +{ + mi_add_to(x, y, cx, cy); +} + +/*****************************************************************************/ +static void +render_callback(DFBRectangle * rect, void * ctx) +{ + printf("hi11\n"); +/* int width; + int height; + IDirectFBSurface *image = (IDirectFBSurface*) ctx; + + image->GetSize( image, &width, &height ); + + primary->Blit( primary, image, rect, + (screen_width - width) / 2 + rect->x, + (screen_height - height) / 2 + rect->y); */ +} + +/*****************************************************************************/ +void * +update_thread(void * arg) +{ + while (g_bs != 0) + { + //usleep(1000000 / 24); /* 24 times per second */ + usleep(1000000 / 12); /* 12 times per second */ + pthread_mutex_lock(&g_mutex1); + mi_update_screen(); + + //g_primary->Blit(g_primary, g_s, &g_rect, g_rect.x, g_rect.y); + //g_primary->Flip(g_primary, 0, 0); + + pthread_mutex_unlock(&g_mutex1); + } + return 0; +} + +/*****************************************************************************/ +void +mi_begin_update(void) +{ +#if 0 + //DFBSurfaceDescription dsc; + DFBDataBufferDescription ddsc; + pthread_t thread; + //pthread_attr_t tt; + //struct sched_param param; + //char * priority; + //int policy; + void * data; + int fd; + IDirectFBDataBuffer * g_buffer1 = 0; + + pthread_mutex_lock(&g_mutex1); + + if (g_provider == 0) + { + + ddsc.flags = DBDESC_FILE; + ddsc.file = strdup("/media/xrdp256.bmp"); + g_dfb->CreateDataBuffer(g_dfb, &ddsc, &g_buffer1); + + //data = g_bs; + data = malloc(50230 * 2); + g_buffer1->GetData(g_buffer1, 50230 * 2, data, &fd); + printf("here %d\n", fd); + + //fd = open("/media/xrdp256.bmp", O_RDONLY); + //data = mmap( NULL, 50230, PROT_READ, MAP_SHARED, fd, 0 ); + //if (data == MAP_FAILED) + //{ + // printf("error\n"); + //} + //printf("%d\n", read(fd, data, 50231)); + //close(fd); + /*mmap(g_bs, g_width * g_height * 4, PROT_READ, MAP_SHARED, 0, 0); + if (data == MAP_FAILED) + { + printf("error calling mmap in mi_begin_update\n"); + data = 0; + }*/ + /* create a data buffer for memory */ + ddsc.flags = DBDESC_MEMORY; + //ddsc.flags = DBDESC_FILE; + ddsc.file = 0; + ddsc.memory.data = data; + //ddsc.file = strdup("/media/xrdp256.bmp"); + ddsc.memory.length = 50230; + //ddsc.memory.length = g_width * g_height * 4; + if (g_buffer == 0) + { + //if (g_dfb->CreateDataBuffer(g_dfb, &ddsc, &g_buffer) != 0) + if (g_dfb->CreateDataBuffer(g_dfb, 0, &g_buffer) != 0) + { + printf("error calling CreateDataBuffer in mi_begin_update\n"); + g_buffer = 0; + } + } + if (g_buffer != 0) + { + g_buffer->PutData(g_buffer, data, 50230); + usleep(1000000); + g_buffer->SeekTo(g_buffer, 0); + fd = g_buffer->CreateImageProvider(g_buffer, &g_provider); + printf("%d %d\n", fd, DFB_NOIMPL); + if (fd != 0) + { + printf("error calling CreateImageProvider in mi_begin_update\n"); + g_provider = 0; + } + } + if (g_provider != 0) + { + //g_provider->SetRenderCallback(g_provider, render_callback, 0); + pthread_create(&thread, 0, update_thread, 0); + pthread_detach(thread); + } + } +#endif + DFBSurfaceDescription dsc; + pthread_t thread; + + pthread_mutex_lock(&g_mutex1); + if (g_s == 0) + { + + dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | + DSDESC_PREALLOCATED | DSDESC_PIXELFORMAT; + dsc.caps = DSCAPS_SYSTEMONLY; + dsc.width = g_width; + dsc.height = g_height; + dsc.pixelformat = DSPF_AiRGB; + //dsc.pixelformat = DSPF_RGB32; + dsc.preallocated[0].data = g_bs; + dsc.preallocated[0].pitch = g_width * 4; + if (g_dfb->CreateSurface(g_dfb, &dsc, &g_s) == 0) + { + //policy = SCHED_RR; + //pthread_attr_init(&tt); + //pthread_attr_setschedpolicy(&tt, policy); + //param.sched_priority = 10; + //pthread_attr_setschedparam(&tt, ¶m); + //priority = strdup("Low"); + //pthread_create(&thread, &tt, update_thread, (void *) priority); + pthread_create(&thread, 0, update_thread, 0); + pthread_detach(thread); + } + else + { + g_s = 0; + } + } +} + +/*****************************************************************************/ +void +mi_end_update(void) +{ + pthread_mutex_unlock(&g_mutex1); +} + +/*****************************************************************************/ +void +mi_fill_rect(int x, int y, int cx, int cy, int red, int green, int blue) +{ + mi_add_to(x, y, cx, cy); +} + +/*****************************************************************************/ +void +mi_line(int x1, int y1, int x2, int y2, int red, int green, int blue) +{ + int x; + int y; + int cx; + int cy; + + x = UI_MIN(x1, x2); + y = UI_MIN(y1, y2); + cx = (UI_MAX(x1, x2) + 1) - x; + cy = (UI_MAX(y1, y2) + 1) - y; + mi_add_to(x, y, cx, cy); +} + +/*****************************************************************************/ +void +mi_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy) +{ + mi_add_to(x, y, cx, cy); +} + +/*****************************************************************************/ +void +mi_set_clip(int x, int y, int cx, int cy) +{ +} + +/*****************************************************************************/ +void +mi_reset_clip(void) +{ +} + +/*****************************************************************************/ +void * +mi_create_cursor(unsigned int x, unsigned int y, + int width, int height, + unsigned char * andmask, unsigned char * xormask) +{ + return (void *) 1; +} + +/*****************************************************************************/ +void +mi_destroy_cursor(void * cursor) +{ +} + +/*****************************************************************************/ +void +mi_set_cursor(void * cursor) +{ +} + +/*****************************************************************************/ +void +mi_set_null_cursor(void) +{ +} + +/*****************************************************************************/ +static void +out_params(void) +{ + fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n"); + fprintf(stderr, "Version 1.4.1. Copyright (C) 1999-2006 Matt Chapman.\n"); + fprintf(stderr, "direct framebuffer uiport by Jay Sorg\n"); + fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n"); + fprintf(stderr, "Usage: dfbrdesktop [options] server\n"); + fprintf(stderr, " -u: user name\n"); + fprintf(stderr, " -n: client hostname\n"); + fprintf(stderr, " -s: shell\n"); + fprintf(stderr, " -p: password\n"); + fprintf(stderr, " -d: domain\n"); + fprintf(stderr, " -c: working directory\n"); + fprintf(stderr, "\n"); +} + +/*****************************************************************************/ +static int +parse_parameters(int in_argc, char ** in_argv) +{ + int i; + + if (in_argc <= 1) + { + out_params(); + return 0; + } + for (i = 1; i < in_argc; i++) + { + strcpy(g_servername, in_argv[i]); + if (strcmp(in_argv[i], "-h") == 0) + { + out_params(); + return 0; + } + else if (strcmp(in_argv[i], "-u") == 0) + { + strcpy(g_username, in_argv[i + 1]); + } + else if (strcmp(in_argv[i], "-n") == 0) + { + strcpy(g_hostname, in_argv[i + 1]); + } + else if (strcmp(in_argv[i], "-s") == 0) + { + strcpy(g_shell, in_argv[i + 1]); + } + else if (strcmp(in_argv[i], "-p") == 0) + { + strcpy(g_password, in_argv[i + 1]); + } + else if (strcmp(in_argv[i], "-d") == 0) + { + strcpy(g_domain, in_argv[i + 1]); + } + else if (strcmp(in_argv[i], "-c") == 0) + { + strcpy(g_directory, in_argv[i + 1]); + } + } + return 1; +} + +/*****************************************************************************/ +int +main(int argc, char ** argv) +{ + int rv; + int i; + DFBSurfaceDescription dsc; + DFBResult err; + IDirectFBScreen * pScreen = NULL; + DFBScreenEncoderConfig encConfig; + DFBScreenEncoderConfigFlags encFlags; + IDirectFBDisplayLayer * layer; + + //strcpy(g_servername, "205.5.61.3"); + //strcpy(g_servername, "127.0.0.1"); + //strcpy(g_servername, "24.158.1.82"); + strcpy(g_hostname, "test"); + //strcpy(g_username, "d"); + //strcpy(g_password, "tucker"); + g_server_depth = 24; + + if (!parse_parameters(argc, argv)) + { + return 0; + } + + printf("DirectFBInit\n"); + err = DirectFBInit(&argc, &argv); + if (err == 0) + { + printf("DirectFBCreate\n"); + err = DirectFBCreate(&g_dfb); + } + if (err == 0) + { + printf("SetCooperativeLevel\n"); + err = g_dfb->SetCooperativeLevel(g_dfb, DFSCL_FULLSCREEN); + } + if (err == 0) + { + /*g_dfb->GetScreen(g_dfb, 0, &pScreen); + pScreen->GetEncoderConfiguration(pScreen, 0, &encConfig); + if (encConfig.tv_standard != DSETV_NTSC) + { + encConfig.tv_standard = DSETV_NTSC; + //encConfig.tv_standard = DSETV_SECAM; + encConfig.flags = DSECONF_TV_STANDARD; + g_dfb->SetVideoMode(g_dfb, 720, 480, 32); + if (pScreen->TestEncoderConfiguration(pScreen, 0, &encConfig, + &encFlags) == DFB_UNSUPPORTED) + { + printf("error\n"); + } + pScreen->SetEncoderConfiguration(pScreen, 0, &encConfig); + for (i = 0; i < 5; i++) + { + g_dfb->GetDisplayLayer(g_dfb, i, &layer); + layer->SetCooperativeLevel(layer, DLSCL_EXCLUSIVE); + } + } */ + err = g_dfb->GetScreen(g_dfb, 1, &pScreen); + } + if (err == 0) + { + dsc.flags = DSDESC_CAPS; + dsc.caps = DSCAPS_PRIMARY; // | DSCAPS_DOUBLE; + //dsc.caps = DSCAPS_PRIMARY | DSCAPS_DOUBLE; + err = g_dfb->CreateSurface(g_dfb, &dsc, &g_primary); + } + if (err == 0) + { + g_dfb->CreateInputEventBuffer(g_dfb, DICAPS_AXES | DICAPS_BUTTONS | + DICAPS_KEYS, 0, &g_event); + g_event->CreateFileDescriptor(g_event, &g_event_fd); + } + if (err == 0) + { + err = g_primary->GetSize(g_primary, &g_width, &g_height); + } + printf("%d %d\n", g_width, g_height); + if (err != 0) + { + printf("error in main\n"); + return 1; + } + rv = ui_main(); + g_primary->Release(g_primary); + g_dfb->Release(g_dfb); + return rv; +}