doorbell

view doorbell-client/src/main.c @ 5:f21ae31ef0e7

craptacular
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 15 Mar 2016 08:35:21 +0200
parents
children dc4018af3a40
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/select.h>
8 #include <sys/socket.h>
9 #include <arpa/inet.h>
10 #include <netdb.h>
11 #include <GL/glut.h>
12 #include <GL/freeglut_ext.h>
13 #include <GL/glx.h>
15 struct video_block_header {
16 unsigned int magic;
17 int frame;
18 int x, y;
19 int width, height;
20 int frame_width, frame_height;
21 };
23 int conn(const char *host, int port);
24 void display(void);
25 void reshape(int x, int y);
26 void keyb(unsigned char key, int x, int y);
27 int handle_conn(int s);
28 void post_redisplay(void);
30 int quit;
31 int srvsock;
32 const char *address = "localhost";
33 int port = 2828;
34 unsigned int tex, tex_width, tex_height;
35 int redraw_pending;
37 int main(int argc, char **argv)
38 {
39 Display *dpy;
40 int xsock;
42 glutInit(&argc, argv);
43 glutInitWindowSize(800, 600);
44 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
45 glutCreateWindow("doorbell");
47 glutDisplayFunc(display);
48 glutReshapeFunc(reshape);
49 glutKeyboardFunc(keyb);
51 dpy = glXGetCurrentDisplay();
52 xsock = ConnectionNumber(dpy);
54 if((srvsock = conn(address, port)) == -1) {
55 return 1;
56 }
57 write(srvsock, "hello", 5);
59 glGenTextures(1, &tex);
60 glBindTexture(GL_TEXTURE_2D, tex);
61 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
62 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
64 for(;;) {
65 int res;
66 int maxfd = srvsock > xsock ? srvsock : xsock;
67 struct timeval tv0 = {0, 0};
68 fd_set rdset;
70 FD_ZERO(&rdset);
71 FD_SET(xsock, &rdset);
72 FD_SET(srvsock, &rdset);
74 while((res = select(maxfd + 1, &rdset, 0, 0, redraw_pending ? &tv0 : 0) == -1) && errno == EINTR);
75 if(res == -1) break;
77 if(redraw_pending || FD_ISSET(xsock, &rdset)) {
78 glutMainLoopEvent();
79 if(quit) {
80 break;
81 }
82 }
83 if(FD_ISSET(srvsock, &rdset)) {
84 if(handle_conn(srvsock) == -1) {
85 break;
86 }
87 }
88 }
90 close(srvsock);
91 return 0;
92 }
95 int conn(const char *hostname, int port)
96 {
97 int s;
98 struct sockaddr_in addr;
99 struct hostent *host;
101 if((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
102 fprintf(stderr, "failed to create socket\n");
103 return -1;
104 }
106 if(!(host = gethostbyname(hostname))) {
107 fprintf(stderr, "failed to resolve hostname: %s\n", hostname);
108 return -1;
109 }
111 memset(&addr, 0, sizeof addr);
112 addr.sin_family = AF_INET;
113 addr.sin_port = htons(port);
114 addr.sin_addr = *(struct in_addr*)host->h_addr;
116 printf("connecting to %s (%s), port %d\n", hostname, inet_ntoa(addr.sin_addr), port);
117 if(connect(s, (struct sockaddr*)&addr, sizeof addr) == -1) {
118 fprintf(stderr, "failed to connect\n");
119 return -1;
120 }
122 fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK);
123 return s;
124 }
126 void display(void)
127 {
128 redraw_pending = 0;
130 glClear(GL_COLOR_BUFFER_BIT);
132 glMatrixMode(GL_MODELVIEW);
133 glLoadIdentity();
135 glPushMatrix();
136 glScalef(0.75, 0.75, 0.75);
138 glBindTexture(GL_TEXTURE_2D, tex);
139 glEnable(GL_TEXTURE_2D);
141 glBegin(GL_QUADS);
142 glTexCoord2f(0, 0); glVertex2f(-1, -1);
143 glTexCoord2f(1, 0); glVertex2f(1, -1);
144 glTexCoord2f(1, 1); glVertex2f(1, 1);
145 glTexCoord2f(0, 1); glVertex2f(-1, 1);
146 glEnd();
148 glDisable(GL_TEXTURE_2D);
149 glPopMatrix();
151 glutSwapBuffers();
152 }
154 void reshape(int x, int y)
155 {
156 glViewport(0, 0, x, y);
157 glMatrixMode(GL_PROJECTION);
158 glLoadIdentity();
159 }
161 void keyb(unsigned char key, int x, int y)
162 {
163 switch(key) {
164 case 27:
165 quit = 1;
166 break;
167 }
168 }
170 int handle_conn(int s)
171 {
172 static int cur_frame;
173 struct video_block_header hdr;
174 int size;
175 unsigned char *pixels;
177 if(read(s, &hdr, sizeof hdr) != sizeof hdr) {
178 fprintf(stderr, "failed to read video block header\n");
179 return -1;
180 }
181 if(hdr.frame < cur_frame) {
182 printf("skipping old frame %d\n", hdr.frame);
183 }
184 cur_frame = hdr.frame;
185 printf("updating block %dx%d%+d%+d in frame %d\n", hdr.width, hdr.height, hdr.x, hdr.y, hdr.frame);
187 size = hdr.width * hdr.height * 2;
188 if(!(pixels = malloc(size))) {
189 fprintf(stderr, "failed to allocate pixel block %dx%d\n", hdr.width, hdr.height);
190 return -1;
191 }
192 if(read(s, pixels, size) != size) {
193 fprintf(stderr, "failed to read pixel block\n");
194 return -1;
195 }
197 glBindTexture(GL_TEXTURE_2D, tex);
199 if(tex_width < hdr.frame_width || tex_height < hdr.frame_height) {
200 tex_width = hdr.frame_width;
201 tex_height = hdr.frame_height;
202 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0,
203 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
204 }
205 glTexSubImage2D(GL_TEXTURE_2D, 0, hdr.x, hdr.y, hdr.width, hdr.height,
206 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
208 post_redisplay();
209 return 0;
210 }
212 void post_redisplay(void)
213 {
214 glutPostRedisplay();
215 redraw_pending = 1;
216 }