| /** |
| * @example ppmtest.c |
| * A simple example of an RFB client |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <time.h> |
| #include <errno.h> |
| #include <rfb/rfbclient.h> |
| |
| static void PrintRect(rfbClient* client, int x, int y, int w, int h) { |
| rfbClientLog("Received an update for %d,%d,%d,%d.\n",x,y,w,h); |
| } |
| |
| static void SaveFramebufferAsPPM(rfbClient* client, int x, int y, int w, int h) { |
| static time_t t=0,t1; |
| FILE* f; |
| int i,j; |
| rfbPixelFormat* pf=&client->format; |
| int bpp=pf->bitsPerPixel/8; |
| int row_stride=client->width*bpp; |
| |
| /* save one picture only if the last is older than 2 seconds */ |
| t1=time(NULL); |
| if(t1-t>2) |
| t=t1; |
| else |
| return; |
| |
| /* assert bpp=4 */ |
| if(bpp!=4 && bpp!=2) { |
| rfbClientLog("bpp = %d (!=4)\n",bpp); |
| return; |
| } |
| |
| f=fopen("framebuffer.ppm","wb"); |
| if(!f) { |
| rfbClientErr("Could not open framebuffer.ppm\n"); |
| return; |
| } |
| |
| fprintf(f,"P6\n# %s\n%d %d\n255\n",client->desktopName,client->width,client->height); |
| for(j=0;j<client->height*row_stride;j+=row_stride) |
| for(i=0;i<client->width*bpp;i+=bpp) { |
| unsigned char* p=client->frameBuffer+j+i; |
| unsigned int v; |
| if(bpp==4) |
| v=*(unsigned int*)p; |
| else if(bpp==2) |
| v=*(unsigned short*)p; |
| else |
| v=*(unsigned char*)p; |
| fputc((v>>pf->redShift)*256/(pf->redMax+1),f); |
| fputc((v>>pf->greenShift)*256/(pf->greenMax+1),f); |
| fputc((v>>pf->blueShift)*256/(pf->blueMax+1),f); |
| } |
| fclose(f); |
| } |
| |
| int |
| main(int argc, char **argv) |
| { |
| rfbClient* client = rfbGetClient(8,3,4); |
| time_t t=time(NULL); |
| |
| if(argc>1 && !strcmp("-print",argv[1])) { |
| client->GotFrameBufferUpdate = PrintRect; |
| argv[1]=argv[0]; argv++; argc--; |
| } else |
| client->GotFrameBufferUpdate = SaveFramebufferAsPPM; |
| |
| /* The -listen option is used to make us a daemon process which listens for |
| incoming connections from servers, rather than actively connecting to a |
| given server. The -tunnel and -via options are useful to create |
| connections tunneled via SSH port forwarding. We must test for the |
| -listen option before invoking any Xt functions - this is because we use |
| forking, and Xt doesn't seem to cope with forking very well. For -listen |
| option, when a successful incoming connection has been accepted, |
| listenForIncomingConnections() returns, setting the listenSpecified |
| flag. */ |
| |
| if (!rfbInitClient(client,&argc,argv)) |
| return 1; |
| |
| /* TODO: better wait for update completion */ |
| while (time(NULL)-t<5) { |
| static int i=0; |
| fprintf(stderr,"\r%d",i++); |
| if(WaitForMessage(client,50)<0) |
| break; |
| if(!HandleRFBServerMessage(client)) |
| break; |
| } |
| |
| rfbClientCleanup(client); |
| |
| return 0; |
| } |
| |