Skip to content

Instantly share code, notes, and snippets.

@Maxdamantus
Last active Jul 29, 2016
Embed
What would you like to do?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
static void failp(char *s){
perror(s);
exit(EXIT_FAILURE);
}
static void writestr(int fd, char *s){
size_t sz = strlen(s);
if(write(fd, s, sz) != sz)
failp("write");
}
struct pollstate {
int nfds;
};
struct proc {
struct self *self;
struct pollstate (*poll_pre)(struct self *, long long time, struct pollfd *fds, int sz);
void (*poll_post)(struct self *, long long time);
};
struct s_watchkey {
int fd;
int ispressed;
struct pollfd *pollfd;
};
static struct s_watchkey watchkey(char *fn){
int fd = open(fn, O_RDONLY);
if(fd < 0)
failp("open");
return (struct s_watchkey){ fd };
}
static struct pollstate watchkey_poll_pre(struct s_watchkey *s, long long time, struct pollfd *fds, int sz){
if(sz < 1){
fprintf(stderr, "sz < 1");
exit(EXIT_FAILURE);
}
*fds = (struct pollfd){
.fd = s->fd,
.events = POLLPRI
};
s->pollfd = fds;
return (struct pollstate){ 1 };
}
static void watchkey_poll_post(struct s_watchkey *s, long long time){
if(!(s->pollfd->revents & POLLPRI))
return;
if(lseek(s->fd, 0, SEEK_SET))
failp("lseek");
char rb = 0;
if(read(s->fd, &rb, 1) < 0)
failp("read");
s->ispressed = rb == 'a';
}
struct s_watchmpd {
int fd;
int linelen;
struct pollfd *pollfd;
char linebuf[128];
unsigned int playing:1, got_state:1, idle:1;
int queue;
};
static struct s_watchmpd watchmpd(void){
int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd < 0)
failp("socket");
struct addrinfo *addr;
if(getaddrinfo("127.1", "6600", NULL, &addr))
failp("getaddrinfo");
if(connect(fd, addr->ai_addr, addr->ai_addrlen))
failp("connect");
return (struct s_watchmpd){ fd, .queue = 1 };
}
static struct pollstate watchmpd_poll_pre(struct s_watchmpd *s, long long time, struct pollfd *fds, int sz){
if(sz < 1){
fprintf(stderr, "sz < 1");
exit(EXIT_FAILURE);
}
*fds = (struct pollfd){
.fd = s->fd,
.events = POLLIN
};
s->pollfd = fds;
return (struct pollstate){ 1 };
}
static void watchmpd_line(struct s_watchmpd *s){
static char ok_pre[] = "OK";
if(!strncmp(s->linebuf, ok_pre, sizeof ok_pre - 1) && (!s->linebuf[sizeof ok_pre - 1] || s->linebuf[sizeof ok_pre - 1] == ' ')){
if(--s->queue > 0)
return;
s->idle = 0;
if(!s->got_state){
s->queue++;
writestr(s->fd, "status\n");
}else{
s->got_state = 0;
s->idle = 1;
s->queue++;
writestr(s->fd, "idle player\n");
}
}
static char state_pre[] = "state: ";
if(!strncmp(s->linebuf, state_pre, sizeof state_pre - 1)){
s->playing = !strcmp(s->linebuf + (sizeof state_pre - 1), "play");
s->got_state = 1;
}
}
static void watchmpd_poll_post(struct s_watchmpd *s, long long time){
if(!(s->pollfd->revents & POLLIN))
return;
char buf[1024];
int rs = read(s->fd, &buf, sizeof buf);
if(rs == 0){
close(s->fd);
sleep(1);
*s = watchmpd();
return;
}
if(rs < 0)
failp("read");
for(int x = 0; x < rs; x++){
int c = buf[x];
if(c == '\n')
c = 0;
if(s->linelen < sizeof s->linebuf - 1)
s->linebuf[s->linelen++] = c;
if(c == 0){
watchmpd_line(s);
s->linelen = 0;
}
}
}
int main(void){
struct s_watchkey s_watchkey = watchkey("/sys/devices/platform/gpio-switch/cam_launch/state");
struct s_watchmpd s_watchmpd = watchmpd();
struct pollfd pollfds[10];
struct proc procs[] = {
{ &s_watchkey, watchkey_poll_pre, watchkey_poll_post },
{ &s_watchmpd, watchmpd_poll_pre, watchmpd_poll_post }
};
long long time;
for(;;){
int waspressed = s_watchkey.ispressed;
int nfds = 0;
int timer = -1;
for(int x = 0; x < sizeof procs/sizeof *procs; x++){
struct pollstate ps = procs[x].poll_pre(procs[x].self, 0, pollfds + nfds, sizeof pollfds/sizeof *pollfds - nfds).nfds;
nfds += ps.nfds;
if(ps.timer >= 0 && (timer < 0 || timer > ps.timer))
timer = ps.timer;
}
int pollr = poll(pollfds, nfds, timer);
if(pollr < 0)
failp("poll");
else if(pollr == 0)
time += timer;
for(int x = 0; x < sizeof procs/sizeof *procs; x++)
procs[x].poll_post(procs[x].self, 0);
if(s_watchmpd.playing && !waspressed && s_watchkey.ispressed){
if(s_watchmpd.idle){
s_watchmpd.idle = 0;
writestr(s_watchmpd.fd, "noidle\n");
}
s_watchmpd.queue++;
writestr(s_watchmpd.fd, "next\n");
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment