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