doorbell

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