doorbell

view doorbell-client/src/main.c @ 7:dc4018af3a40

video broadcast with UDP. retarded amount of data, unusable.
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 16 Mar 2016 02:50:30 +0200
parents f21ae31ef0e7
children
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <errno.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/select.h>
9 #include <sys/socket.h>
10 #include <arpa/inet.h>
11 #include <netdb.h>
12 #include <GL/glut.h>
13 #include <GL/freeglut_ext.h>
14 #include <GL/glx.h>
16 struct video_block {
17 int frame;
18 uint16_t x, y;
19 uint16_t width, height;
20 uint16_t frame_width, frame_height;
21 uint16_t pixels[1];
22 };
24 int conn(const char *host, int port);
25 void display(void);
26 void reshape(int x, int y);
27 void keyb(unsigned char key, int x, int y);
28 int handle_conn(int s);
29 int handle_video(int s);
30 void post_redisplay(void);
32 int quit;
33 int ctlsock, vidsock;
34 const char *address = "localhost";
35 int port = 2828;
36 unsigned int tex, tex_width, tex_height;
37 int redraw_pending;
39 #define MAX(a, b) ((a) > (b) ? (a) : (b))
41 int main(int argc, char **argv)
42 {
43 Display *dpy;
44 int xsock;
46 glutInit(&argc, argv);
47 glutInitWindowSize(800, 600);
48 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
49 glutCreateWindow("doorbell");
51 glutDisplayFunc(display);
52 glutReshapeFunc(reshape);
53 glutKeyboardFunc(keyb);
55 dpy = glXGetCurrentDisplay();
56 xsock = ConnectionNumber(dpy);
58 if(conn(address, port) == -1) {
59 return 1;
60 }
61 write(ctlsock, "hello", 5);
63 glGenTextures(1, &tex);
64 glBindTexture(GL_TEXTURE_2D, tex);
65 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
66 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
68 for(;;) {
69 int res, maxfd;
70 struct timeval tv0 = {0, 0};
71 fd_set rdset;
73 FD_ZERO(&rdset);
74 FD_SET(xsock, &rdset);
75 FD_SET(ctlsock, &rdset);
76 FD_SET(vidsock, &rdset);
78 maxfd = MAX(MAX(xsock, ctlsock), vidsock);
79 while((res = select(maxfd + 1, &rdset, 0, 0, redraw_pending ? &tv0 : 0) == -1) && errno == EINTR);
80 if(res == -1) break;
82 if(redraw_pending || FD_ISSET(xsock, &rdset)) {
83 glutMainLoopEvent();
84 if(quit) {
85 break;
86 }
87 }
88 if(FD_ISSET(ctlsock, &rdset)) {
89 if(handle_conn(ctlsock) == -1) {
90 break;
91 }
92 }
93 if(FD_ISSET(vidsock, &rdset)) {
94 if(handle_video(vidsock) == -1) {
95 break;
96 }
97 }
98 }
100 close(ctlsock);
101 return 0;
102 }
105 int conn(const char *hostname, int port)
106 {
107 struct sockaddr_in addr;
108 struct hostent *host;
110 if((ctlsock = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
111 fprintf(stderr, "failed to create socket\n");
112 return -1;
113 }
115 if(!(host = gethostbyname(hostname))) {
116 fprintf(stderr, "failed to resolve hostname: %s\n", hostname);
117 return -1;
118 }
120 memset(&addr, 0, sizeof addr);
121 addr.sin_family = AF_INET;
122 addr.sin_port = htons(port);
123 addr.sin_addr = *(struct in_addr*)host->h_addr;
125 printf("connecting to %s (%s), port %d\n", hostname, inet_ntoa(addr.sin_addr), port);
126 if(connect(ctlsock, (struct sockaddr*)&addr, sizeof addr) == -1) {
127 fprintf(stderr, "failed to connect\n");
128 return -1;
129 }
130 fcntl(ctlsock, F_SETFL, fcntl(ctlsock, F_GETFL) | O_NONBLOCK);
132 /* prepare the video socket */
133 if((vidsock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
134 fprintf(stderr, "failed to create video socket\n");
135 return 1;
136 }
138 memset(&addr, 0, sizeof addr);
139 addr.sin_family = AF_INET;
140 addr.sin_port = htons(port + 1);
141 addr.sin_addr.s_addr = htonl(INADDR_ANY);
142 if(bind(vidsock, (struct sockaddr*)&addr, sizeof addr) == -1) {
143 fprintf(stderr, "failed to bind video socket to port %d\n", port + 1);
144 return 1;
145 }
147 return 0;
148 }
150 void display(void)
151 {
152 redraw_pending = 0;
154 glClear(GL_COLOR_BUFFER_BIT);
156 glMatrixMode(GL_MODELVIEW);
157 glLoadIdentity();
159 glPushMatrix();
160 glScalef(0.75, 0.75, 0.75);
162 glBindTexture(GL_TEXTURE_2D, tex);
163 glEnable(GL_TEXTURE_2D);
165 glBegin(GL_QUADS);
166 glTexCoord2f(0, 1); glVertex2f(-1, -1);
167 glTexCoord2f(1, 1); glVertex2f(1, -1);
168 glTexCoord2f(1, 0); glVertex2f(1, 1);
169 glTexCoord2f(0, 0); glVertex2f(-1, 1);
170 glEnd();
172 glDisable(GL_TEXTURE_2D);
173 glPopMatrix();
175 glutSwapBuffers();
176 }
178 void reshape(int x, int y)
179 {
180 glViewport(0, 0, x, y);
181 glMatrixMode(GL_PROJECTION);
182 glLoadIdentity();
183 }
185 void keyb(unsigned char key, int x, int y)
186 {
187 switch(key) {
188 case 27:
189 quit = 1;
190 break;
191 }
192 }
194 int handle_conn(int s)
195 {
196 fprintf(stderr, "whaaaa!\n");
197 return -1;
198 }
200 int handle_video(int s)
201 {
202 static int cur_frame;
203 static char buffer[2048];
204 struct video_block *vblock;
205 struct sockaddr_in addr;
206 socklen_t addr_size;
208 addr_size = sizeof addr;
209 if(recvfrom(vidsock, buffer, sizeof buffer, 0, (struct sockaddr*)&addr, &addr_size) == -1) {
210 perror("failed to receive video block");
211 return -1;
212 }
214 vblock = (struct video_block*)buffer;
216 if(vblock->frame < cur_frame) {
217 printf("skipping old frame %d\n", vblock->frame);
218 return 0;
219 }
220 cur_frame = vblock->frame;
221 printf("updating block %dx%d%+d%+d in frame %d\n", vblock->width, vblock->height,
222 vblock->x, vblock->y, vblock->frame);
224 glBindTexture(GL_TEXTURE_2D, tex);
226 if(tex_width < vblock->frame_width || tex_height < vblock->frame_height) {
227 tex_width = vblock->frame_width;
228 tex_height = vblock->frame_height;
229 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0,
230 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
231 }
232 glTexSubImage2D(GL_TEXTURE_2D, 0, vblock->x, vblock->y, vblock->width, vblock->height,
233 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, vblock->pixels);
235 post_redisplay();
236 return 0;
237 }
239 void post_redisplay(void)
240 {
241 glutPostRedisplay();
242 redraw_pending = 1;
243 }