1/** 2 * @example ppmtest.c 3 * A simple example of an RFB client 4 */ 5 6#include <stdio.h> 7#include <stdlib.h> 8#include <time.h> 9#include <errno.h> 10#include <rfb/rfbclient.h> 11 12static void PrintRect(rfbClient* client, int x, int y, int w, int h) { 13 rfbClientLog("Received an update for %d,%d,%d,%d.\n",x,y,w,h); 14} 15 16static void SaveFramebufferAsPPM(rfbClient* client, int x, int y, int w, int h) { 17 static time_t t=0,t1; 18 FILE* f; 19 int i,j; 20 rfbPixelFormat* pf=&client->format; 21 int bpp=pf->bitsPerPixel/8; 22 int row_stride=client->width*bpp; 23 24 /* save one picture only if the last is older than 2 seconds */ 25 t1=time(NULL); 26 if(t1-t>2) 27 t=t1; 28 else 29 return; 30 31 /* assert bpp=4 */ 32 if(bpp!=4 && bpp!=2) { 33 rfbClientLog("bpp = %d (!=4)\n",bpp); 34 return; 35 } 36 37 f=fopen("framebuffer.ppm","wb"); 38 if(!f) { 39 rfbClientErr("Could not open framebuffer.ppm\n"); 40 return; 41 } 42 43 fprintf(f,"P6\n# %s\n%d %d\n255\n",client->desktopName,client->width,client->height); 44 for(j=0;j<client->height*row_stride;j+=row_stride) 45 for(i=0;i<client->width*bpp;i+=bpp) { 46 unsigned char* p=client->frameBuffer+j+i; 47 unsigned int v; 48 if(bpp==4) 49 v=*(unsigned int*)p; 50 else if(bpp==2) 51 v=*(unsigned short*)p; 52 else 53 v=*(unsigned char*)p; 54 fputc((v>>pf->redShift)*256/(pf->redMax+1),f); 55 fputc((v>>pf->greenShift)*256/(pf->greenMax+1),f); 56 fputc((v>>pf->blueShift)*256/(pf->blueMax+1),f); 57 } 58 fclose(f); 59} 60 61int 62main(int argc, char **argv) 63{ 64 rfbClient* client = rfbGetClient(8,3,4); 65 time_t t=time(NULL); 66 67 if(argc>1 && !strcmp("-print",argv[1])) { 68 client->GotFrameBufferUpdate = PrintRect; 69 argv[1]=argv[0]; argv++; argc--; 70 } else 71 client->GotFrameBufferUpdate = SaveFramebufferAsPPM; 72 73 /* The -listen option is used to make us a daemon process which listens for 74 incoming connections from servers, rather than actively connecting to a 75 given server. The -tunnel and -via options are useful to create 76 connections tunneled via SSH port forwarding. We must test for the 77 -listen option before invoking any Xt functions - this is because we use 78 forking, and Xt doesn't seem to cope with forking very well. For -listen 79 option, when a successful incoming connection has been accepted, 80 listenForIncomingConnections() returns, setting the listenSpecified 81 flag. */ 82 83 if (!rfbInitClient(client,&argc,argv)) 84 return 1; 85 86 /* TODO: better wait for update completion */ 87 while (time(NULL)-t<5) { 88 static int i=0; 89 fprintf(stderr,"\r%d",i++); 90 if(WaitForMessage(client,50)<0) 91 break; 92 if(!HandleRFBServerMessage(client)) 93 break; 94 } 95 96 rfbClientCleanup(client); 97 98 return 0; 99} 100 101