vrmodel
changeset 4:a32b151fb3c6
moving along slowly
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 11 Sep 2014 00:08:23 +0300 |
parents | a1784a4290c2 |
children | 9e260c091f75 |
files | .clang_complete Makefile include/proto.h inptools/test/.clang_complete inptools/test/src/main.c src/inpclient.cc src/inpclient.h src/main.cc |
diffstat | 8 files changed, 269 insertions(+), 12 deletions(-) [+] |
line diff
1.1 --- a/.clang_complete Mon Sep 01 05:59:31 2014 +0300 1.2 +++ b/.clang_complete Thu Sep 11 00:08:23 2014 +0300 1.3 @@ -1,1 +1,2 @@ 1.4 +-std=c++11 1.5 -Iinclude
2.1 --- a/Makefile Mon Sep 01 05:59:31 2014 +0300 2.2 +++ b/Makefile Thu Sep 11 00:08:23 2014 +0300 2.3 @@ -6,7 +6,7 @@ 2.4 inc = -Iinclude 2.5 2.6 CFLAGS = -pedantic -Wall -g $(inc) `pkg-config --cflags sdl2` 2.7 -CXXFLAGS = $(CFLAGS) 2.8 +CXXFLAGS = -std=c++11 $(CFLAGS) 2.9 LDFLAGS = $(libgl) `pkg-config --libs sdl2` 2.10 2.11 ifeq ($(shell uname -s), Darwin)
3.1 --- a/include/proto.h Mon Sep 01 05:59:31 2014 +0300 3.2 +++ b/include/proto.h Thu Sep 11 00:08:23 2014 +0300 3.3 @@ -11,12 +11,24 @@ 3.4 /* responses */ 3.5 #define RSP_OK 0 3.6 #define RSP_ERR 255 3.7 +/* events */ 3.8 +#define EV_STATE MAGIC 3.9 +#define EV_MOTION 16 3.10 +#define EV_BUTTON 17 3.11 3.12 +struct msg_ev_data { 3.13 + float x, y, z; 3.14 + unsigned int bnmask; 3.15 +}; 3.16 3.17 struct message { 3.18 int magic; 3.19 int type; 3.20 - char data[24]; 3.21 + 3.22 + union { 3.23 + char raw[24]; 3.24 + struct msg_ev_data event; 3.25 + } data; 3.26 }; 3.27 3.28
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/inptools/test/.clang_complete Thu Sep 11 00:08:23 2014 +0300 4.3 @@ -0,0 +1,1 @@ 4.4 +-I../../include
5.1 --- a/inptools/test/src/main.c Mon Sep 01 05:59:31 2014 +0300 5.2 +++ b/inptools/test/src/main.c Thu Sep 11 00:08:23 2014 +0300 5.3 @@ -1,5 +1,174 @@ 5.4 #include <stdio.h> 5.5 +#include <stdlib.h> 5.6 +#include <string.h> 5.7 +#include <limits.h> 5.8 +#include <errno.h> 5.9 +#include <assert.h> 5.10 +#include <unistd.h> 5.11 +#include <fcntl.h> 5.12 +#include <sys/socket.h> 5.13 +#include <arpa/inet.h> 5.14 +#include <sys/select.h> 5.15 +#include <sys/time.h> 5.16 +#include <sys/types.h> 5.17 +#include <linux/joystick.h> 5.18 +#include "proto.h" 5.19 + 5.20 +struct client { 5.21 + int s; 5.22 + struct sockaddr_in addr; 5.23 + struct client *next; 5.24 +}; 5.25 + 5.26 +int open_js(const char *jspath); 5.27 +int handle_js(int fd); 5.28 +int start_srv(int port); 5.29 +int handle_net(int s); 5.30 + 5.31 +static int opt_dport = DEF_PORT; 5.32 +static const char *opt_jspath = "/dev/input/js0"; 5.33 + 5.34 +static struct client *clients; 5.35 + 5.36 +static int js_num_axes; 5.37 +static float *js_axis_state; 5.38 +static unsigned int js_bn_state; 5.39 + 5.40 5.41 int main(int argc, char **argv) 5.42 { 5.43 + int js, sock; 5.44 + int maxfd; 5.45 + 5.46 + if((js = open_js(opt_jspath)) == -1) { 5.47 + return 1; 5.48 + } 5.49 + if((sock = start_srv(opt_dport)) == -1) { 5.50 + return 1; 5.51 + } 5.52 + maxfd = js > sock ? js : sock; 5.53 + 5.54 + for(;;) { 5.55 + fd_set rdset; 5.56 + 5.57 + FD_ZERO(&rdset); 5.58 + FD_SET(js, &rdset); 5.59 + FD_SET(sock, &rdset); 5.60 + 5.61 + while(select(maxfd + 1, &rdset, 0, 0, 0) == -1 && errno == EINTR); 5.62 + 5.63 + if(FD_ISSET(js, &rdset)) { 5.64 + handle_js(js); 5.65 + } 5.66 + if(FD_ISSET(sock, &rdset)) { 5.67 + handle_net(sock); 5.68 + } 5.69 + } 5.70 + 5.71 + close(js); 5.72 + close(sock); 5.73 + return 0; 5.74 } 5.75 + 5.76 +int open_js(const char *jspath) 5.77 +{ 5.78 + int fd; 5.79 + char buf[256]; 5.80 + int axes; 5.81 + 5.82 + if((fd = open(jspath, O_RDONLY)) == -1) { 5.83 + fprintf(stderr, "failed to open js device: %s: %s\n", jspath, strerror(errno)); 5.84 + return -1; 5.85 + } 5.86 + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 5.87 + 5.88 + if(ioctl(fd, JSIOCGAXES, &axes) == -1) { 5.89 + fprintf(stderr, "failed to get number of joystick axes\n"); 5.90 + return -1; 5.91 + } 5.92 + if(ioctl(fd, JSIOCGNAME(sizeof buf), buf) == -1) { 5.93 + strcpy(buf, "unknown"); 5.94 + } 5.95 + printf("opened joystick: %s: %s (%d axes)\n", jspath, buf, axes); 5.96 + 5.97 + js_axis_state = malloc(axes * sizeof *js_axis_state); 5.98 + assert(js_axis_state); 5.99 + js_num_axes = axes; 5.100 + 5.101 + return fd; 5.102 +} 5.103 + 5.104 +int handle_js(int fd) 5.105 +{ 5.106 + int evtype; 5.107 + struct js_event ev; 5.108 + struct client *c; 5.109 + 5.110 + if(read(fd, &ev, sizeof ev) <= 0) { 5.111 + return -1; 5.112 + } 5.113 + 5.114 + switch(ev.type) { 5.115 + case JS_EVENT_AXIS: 5.116 + js_axis_state[ev.number] = (float)ev.value / (float)SHRT_MAX; 5.117 + evtype = EV_MOTION; 5.118 + break; 5.119 + 5.120 + case JS_EVENT_BUTTON: 5.121 + if(ev.value) { 5.122 + js_bn_state |= 1 << ev.number; 5.123 + } else { 5.124 + js_bn_state &= ~(1 << ev.number); 5.125 + } 5.126 + evtype = EV_BUTTON; 5.127 + break; 5.128 + 5.129 + default: 5.130 + break; 5.131 + } 5.132 + 5.133 + /* send client events */ 5.134 + c = clients; 5.135 + while(c) { 5.136 + struct message m; 5.137 + 5.138 + m.magic = MAGIC; 5.139 + m.type = evtype; 5.140 + m.data.event.x = js_axis_state[0]; 5.141 + m.data.event.y = js_num_axes > 1 ? js_axis_state[1] : 0; 5.142 + m.data.event.z = js_num_axes > 2 ? js_axis_state[2] : 0; 5.143 + 5.144 + sendto(c->s, &m, sizeof m, 0, (struct sockaddr*)&c->addr, sizeof c->addr); 5.145 + c = c->next; 5.146 + } 5.147 + return 0; 5.148 +} 5.149 + 5.150 +int start_srv(int port) 5.151 +{ 5.152 + int s; 5.153 + struct sockaddr_in sa; 5.154 + 5.155 + if((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { 5.156 + perror("failed to create socket"); 5.157 + return -1; 5.158 + } 5.159 + 5.160 + memset(&sa, 0, sizeof sa); 5.161 + sa.sin_family = AF_INET; 5.162 + sa.sin_addr.s_addr = htonl(INADDR_ANY); 5.163 + sa.sin_port = htons(opt_dport); 5.164 + 5.165 + if(bind(s, (struct sockaddr*)&sa, sizeof sa) == -1) { 5.166 + perror("failed to bind socket"); 5.167 + close(s); 5.168 + return -1; 5.169 + } 5.170 + 5.171 + return s; 5.172 +} 5.173 + 5.174 +int handle_net(int s) 5.175 +{ 5.176 + return 0; 5.177 +}
6.1 --- a/src/inpclient.cc Mon Sep 01 05:59:31 2014 +0300 6.2 +++ b/src/inpclient.cc Thu Sep 11 00:08:23 2014 +0300 6.3 @@ -15,7 +15,7 @@ 6.4 static int send_request(int s, struct message *msg, long timeout); 6.5 6.6 static int opt_dport = DEF_PORT; /* discover broadcast port */ 6.7 -static long opt_timeout = 5000; /* 10 sec discovery timeout */ 6.8 +static long opt_timeout = 5000; /* 10 sec discovery timeout */ 6.9 6.10 static int sock = -1; 6.11 6.12 @@ -40,7 +40,10 @@ 6.13 memset(&msg, 0, sizeof msg); 6.14 msg.magic = MAGIC; 6.15 msg.type = REQ_START; 6.16 - return send_request(sock, &msg, opt_timeout); 6.17 + if(send_request(sock, &msg, opt_timeout) == -1) { 6.18 + return -1; 6.19 + } 6.20 + return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1; 6.21 } 6.22 6.23 int netinp_stop() 6.24 @@ -54,10 +57,14 @@ 6.25 memset(&msg, 0, sizeof msg); 6.26 msg.magic = MAGIC; 6.27 msg.type = REQ_STOP; 6.28 - return send_request(sock, &msg, opt_timeout); 6.29 + 6.30 + if(send_request(sock, &msg, opt_timeout) == -1) { 6.31 + return -1; 6.32 + } 6.33 + return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1; 6.34 } 6.35 6.36 -int netinp_read(float *pos) 6.37 +int netinp_read(float *pos, unsigned int *bnmask) 6.38 { 6.39 struct message msg; 6.40 6.41 @@ -70,15 +77,34 @@ 6.42 return -1; 6.43 } 6.44 6.45 - pos[0] = ((float*)msg.data)[0]; 6.46 - pos[1] = ((float*)msg.data)[1]; 6.47 - pos[2] = ((float*)msg.data)[3]; 6.48 + if(msg.magic != MAGIC || msg.type != MAGIC) { 6.49 + fprintf(stderr, "not enough magic in the message\n"); 6.50 + return -1; 6.51 + } 6.52 + 6.53 + pos[0] = msg.data.event.x; 6.54 + pos[1] = msg.data.event.y; 6.55 + pos[2] = msg.data.event.z; 6.56 + *bnmask = msg.data.event.bnmask; 6.57 return 0; 6.58 } 6.59 6.60 int netinp_reset() 6.61 { 6.62 - return -1; // TODO 6.63 + struct message msg; 6.64 + 6.65 + if(sock == -1) { 6.66 + return -1; 6.67 + } 6.68 + 6.69 + memset(&msg, 0, sizeof msg); 6.70 + msg.magic = MAGIC; 6.71 + msg.type = REQ_STOP; 6.72 + 6.73 + if(send_request(sock, &msg, opt_timeout) == -1) { 6.74 + return -1; 6.75 + } 6.76 + return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1; 6.77 } 6.78 6.79 static int discover(struct sockaddr_in *srv_sa) 6.80 @@ -142,7 +168,7 @@ 6.81 perror("failed to receive datagram\n"); 6.82 } 6.83 if(msg.magic == MAGIC && msg.type == RSP_OK) { 6.84 - printf("found input server \"%s\" at: %s:%d\n", msg.data, 6.85 + printf("found input server \"%s\" at: %s:%d\n", msg.data.raw, 6.86 inet_ntoa(srv_sa->sin_addr), ntohs(srv_sa->sin_port)); 6.87 return s; 6.88 }
7.1 --- a/src/inpclient.h Mon Sep 01 05:59:31 2014 +0300 7.2 +++ b/src/inpclient.h Thu Sep 11 00:08:23 2014 +0300 7.3 @@ -4,7 +4,7 @@ 7.4 int netinp_start(); 7.5 int netinp_stop(); 7.6 7.7 -int netinp_read(float *pos); 7.8 +int netinp_read(float *pos, unsigned int *bnmask); 7.9 int netinp_reset(); 7.10 7.11 #endif // INPCLIENT_H_
8.1 --- a/src/main.cc Mon Sep 01 05:59:31 2014 +0300 8.2 +++ b/src/main.cc Thu Sep 11 00:08:23 2014 +0300 8.3 @@ -1,8 +1,16 @@ 8.4 #include <stdio.h> 8.5 #include <stdlib.h> 8.6 +#include <errno.h> 8.7 +#include <thread> 8.8 +#include <mutex> 8.9 #include <SDL2/SDL.h> 8.10 +#include <unistd.h> 8.11 +#include <sys/select.h> 8.12 +#include <sys/types.h> 8.13 +#include <sys/time.h> 8.14 #include "opengl.h" 8.15 #include "vport.h" 8.16 +#include "inpclient.h" 8.17 8.18 #define ANYPOS SDL_WINDOWPOS_UNDEFINED 8.19 8.20 @@ -10,10 +18,17 @@ 8.21 bool handle_event(SDL_Event *ev); 8.22 bool handle_key(int key, bool pressed); 8.23 void reshape(int x, int y); 8.24 +void inp_thread_func(); 8.25 8.26 static SDL_Window *win; 8.27 static SDL_GLContext ctx; 8.28 8.29 +// network input stuff 8.30 +static std::thread inp_thread; 8.31 +static std::mutex inp_mutex; 8.32 +static float inp_pos[3]; 8.33 +static unsigned int inp_bn; 8.34 + 8.35 int main(int argc, char **argv) 8.36 { 8.37 if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) { 8.38 @@ -32,6 +47,8 @@ 8.39 return 1; 8.40 } 8.41 8.42 + inp_thread = std::thread(inp_thread_func); 8.43 + 8.44 for(;;) { 8.45 SDL_Event ev; 8.46 SDL_WaitEvent(&ev); 8.47 @@ -46,6 +63,7 @@ 8.48 } 8.49 8.50 done: 8.51 + inp_thread.join(); 8.52 SDL_Quit(); 8.53 return 0; 8.54 } 8.55 @@ -99,3 +117,33 @@ 8.56 } 8.57 return true; 8.58 } 8.59 + 8.60 +void inp_thread_func() 8.61 +{ 8.62 + int s = netinp_start(); 8.63 + if(s == -1) { 8.64 + return; 8.65 + } 8.66 + 8.67 + for(;;) { 8.68 + fd_set rdset; 8.69 + 8.70 + FD_ZERO(&rdset); 8.71 + FD_SET(s, &rdset); 8.72 + 8.73 + struct timeval tv; 8.74 + tv.tv_sec = 5; 8.75 + tv.tv_usec = 0; 8.76 + 8.77 + while(select(s + 1, &rdset, 0, 0, &tv) == -1 && errno == EINTR); 8.78 + 8.79 + if(FD_ISSET(s, &rdset)) { 8.80 + inp_mutex.lock(); 8.81 + netinp_read(inp_pos, &inp_bn); 8.82 + inp_mutex.unlock(); 8.83 + } 8.84 + } 8.85 + 8.86 + netinp_stop(); 8.87 + close(s); 8.88 +}