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