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 +}