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
PrintRect(rfbClient * client,int x,int y,int w,int h)12 static 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
SaveFramebufferAsPPM(rfbClient * client,int x,int y,int w,int h)16 static 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
61 int
main(int argc,char ** argv)62 main(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