doorbell
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/doorbell-client/src/main.c Tue Mar 15 08:35:21 2016 +0200 1.3 @@ -0,0 +1,216 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include <errno.h> 1.8 +#include <unistd.h> 1.9 +#include <fcntl.h> 1.10 +#include <sys/select.h> 1.11 +#include <sys/socket.h> 1.12 +#include <arpa/inet.h> 1.13 +#include <netdb.h> 1.14 +#include <GL/glut.h> 1.15 +#include <GL/freeglut_ext.h> 1.16 +#include <GL/glx.h> 1.17 + 1.18 +struct video_block_header { 1.19 + unsigned int magic; 1.20 + int frame; 1.21 + int x, y; 1.22 + int width, height; 1.23 + int frame_width, frame_height; 1.24 +}; 1.25 + 1.26 +int conn(const char *host, int port); 1.27 +void display(void); 1.28 +void reshape(int x, int y); 1.29 +void keyb(unsigned char key, int x, int y); 1.30 +int handle_conn(int s); 1.31 +void post_redisplay(void); 1.32 + 1.33 +int quit; 1.34 +int srvsock; 1.35 +const char *address = "localhost"; 1.36 +int port = 2828; 1.37 +unsigned int tex, tex_width, tex_height; 1.38 +int redraw_pending; 1.39 + 1.40 +int main(int argc, char **argv) 1.41 +{ 1.42 + Display *dpy; 1.43 + int xsock; 1.44 + 1.45 + glutInit(&argc, argv); 1.46 + glutInitWindowSize(800, 600); 1.47 + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 1.48 + glutCreateWindow("doorbell"); 1.49 + 1.50 + glutDisplayFunc(display); 1.51 + glutReshapeFunc(reshape); 1.52 + glutKeyboardFunc(keyb); 1.53 + 1.54 + dpy = glXGetCurrentDisplay(); 1.55 + xsock = ConnectionNumber(dpy); 1.56 + 1.57 + if((srvsock = conn(address, port)) == -1) { 1.58 + return 1; 1.59 + } 1.60 + write(srvsock, "hello", 5); 1.61 + 1.62 + glGenTextures(1, &tex); 1.63 + glBindTexture(GL_TEXTURE_2D, tex); 1.64 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1.65 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.66 + 1.67 + for(;;) { 1.68 + int res; 1.69 + int maxfd = srvsock > xsock ? srvsock : xsock; 1.70 + struct timeval tv0 = {0, 0}; 1.71 + fd_set rdset; 1.72 + 1.73 + FD_ZERO(&rdset); 1.74 + FD_SET(xsock, &rdset); 1.75 + FD_SET(srvsock, &rdset); 1.76 + 1.77 + while((res = select(maxfd + 1, &rdset, 0, 0, redraw_pending ? &tv0 : 0) == -1) && errno == EINTR); 1.78 + if(res == -1) break; 1.79 + 1.80 + if(redraw_pending || FD_ISSET(xsock, &rdset)) { 1.81 + glutMainLoopEvent(); 1.82 + if(quit) { 1.83 + break; 1.84 + } 1.85 + } 1.86 + if(FD_ISSET(srvsock, &rdset)) { 1.87 + if(handle_conn(srvsock) == -1) { 1.88 + break; 1.89 + } 1.90 + } 1.91 + } 1.92 + 1.93 + close(srvsock); 1.94 + return 0; 1.95 +} 1.96 + 1.97 + 1.98 +int conn(const char *hostname, int port) 1.99 +{ 1.100 + int s; 1.101 + struct sockaddr_in addr; 1.102 + struct hostent *host; 1.103 + 1.104 + if((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) { 1.105 + fprintf(stderr, "failed to create socket\n"); 1.106 + return -1; 1.107 + } 1.108 + 1.109 + if(!(host = gethostbyname(hostname))) { 1.110 + fprintf(stderr, "failed to resolve hostname: %s\n", hostname); 1.111 + return -1; 1.112 + } 1.113 + 1.114 + memset(&addr, 0, sizeof addr); 1.115 + addr.sin_family = AF_INET; 1.116 + addr.sin_port = htons(port); 1.117 + addr.sin_addr = *(struct in_addr*)host->h_addr; 1.118 + 1.119 + printf("connecting to %s (%s), port %d\n", hostname, inet_ntoa(addr.sin_addr), port); 1.120 + if(connect(s, (struct sockaddr*)&addr, sizeof addr) == -1) { 1.121 + fprintf(stderr, "failed to connect\n"); 1.122 + return -1; 1.123 + } 1.124 + 1.125 + fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK); 1.126 + return s; 1.127 +} 1.128 + 1.129 +void display(void) 1.130 +{ 1.131 + redraw_pending = 0; 1.132 + 1.133 + glClear(GL_COLOR_BUFFER_BIT); 1.134 + 1.135 + glMatrixMode(GL_MODELVIEW); 1.136 + glLoadIdentity(); 1.137 + 1.138 + glPushMatrix(); 1.139 + glScalef(0.75, 0.75, 0.75); 1.140 + 1.141 + glBindTexture(GL_TEXTURE_2D, tex); 1.142 + glEnable(GL_TEXTURE_2D); 1.143 + 1.144 + glBegin(GL_QUADS); 1.145 + glTexCoord2f(0, 0); glVertex2f(-1, -1); 1.146 + glTexCoord2f(1, 0); glVertex2f(1, -1); 1.147 + glTexCoord2f(1, 1); glVertex2f(1, 1); 1.148 + glTexCoord2f(0, 1); glVertex2f(-1, 1); 1.149 + glEnd(); 1.150 + 1.151 + glDisable(GL_TEXTURE_2D); 1.152 + glPopMatrix(); 1.153 + 1.154 + glutSwapBuffers(); 1.155 +} 1.156 + 1.157 +void reshape(int x, int y) 1.158 +{ 1.159 + glViewport(0, 0, x, y); 1.160 + glMatrixMode(GL_PROJECTION); 1.161 + glLoadIdentity(); 1.162 +} 1.163 + 1.164 +void keyb(unsigned char key, int x, int y) 1.165 +{ 1.166 + switch(key) { 1.167 + case 27: 1.168 + quit = 1; 1.169 + break; 1.170 + } 1.171 +} 1.172 + 1.173 +int handle_conn(int s) 1.174 +{ 1.175 + static int cur_frame; 1.176 + struct video_block_header hdr; 1.177 + int size; 1.178 + unsigned char *pixels; 1.179 + 1.180 + if(read(s, &hdr, sizeof hdr) != sizeof hdr) { 1.181 + fprintf(stderr, "failed to read video block header\n"); 1.182 + return -1; 1.183 + } 1.184 + if(hdr.frame < cur_frame) { 1.185 + printf("skipping old frame %d\n", hdr.frame); 1.186 + } 1.187 + cur_frame = hdr.frame; 1.188 + printf("updating block %dx%d%+d%+d in frame %d\n", hdr.width, hdr.height, hdr.x, hdr.y, hdr.frame); 1.189 + 1.190 + size = hdr.width * hdr.height * 2; 1.191 + if(!(pixels = malloc(size))) { 1.192 + fprintf(stderr, "failed to allocate pixel block %dx%d\n", hdr.width, hdr.height); 1.193 + return -1; 1.194 + } 1.195 + if(read(s, pixels, size) != size) { 1.196 + fprintf(stderr, "failed to read pixel block\n"); 1.197 + return -1; 1.198 + } 1.199 + 1.200 + glBindTexture(GL_TEXTURE_2D, tex); 1.201 + 1.202 + if(tex_width < hdr.frame_width || tex_height < hdr.frame_height) { 1.203 + tex_width = hdr.frame_width; 1.204 + tex_height = hdr.frame_height; 1.205 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0, 1.206 + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0); 1.207 + } 1.208 + glTexSubImage2D(GL_TEXTURE_2D, 0, hdr.x, hdr.y, hdr.width, hdr.height, 1.209 + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); 1.210 + 1.211 + post_redisplay(); 1.212 + return 0; 1.213 +} 1.214 + 1.215 +void post_redisplay(void) 1.216 +{ 1.217 + glutPostRedisplay(); 1.218 + redraw_pending = 1; 1.219 +}