chiark / gitweb /
wip gui-plan connect to multiplex - does not compile
authorian <ian>
Tue, 27 May 2008 18:40:43 +0000 (18:40 +0000)
committerian <ian>
Tue, 27 May 2008 18:40:43 +0000 (18:40 +0000)
hostside/gui-plan.c
hostside/utils.c

index 5596ba320d197f466accec5cde14e4238a6f229f..2725e2a3b94e061813fa78010f5f92fd38090600 100644 (file)
 #include <string.h>
 #include <errno.h>
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
 #include <X11/Xlib.h>
 #include <X11/xpm.h>
 
@@ -51,7 +55,7 @@ const char *progname= "gui-plan";
 static SegmovfeatState **state, *states_head;
 static Display *d;
 static oop_source_sys *sys_events;
-static Window w;
+static Window w=None;
 static int redraw_needed_count, expose_count;
 static Pixmap bg_pixmap;
 static unsigned long train_pixel, owned_pixel;
@@ -95,14 +99,6 @@ int vbadcmd(ParseState *ps, const char *fmt, va_list al) {
   exit(8);
 }
 
-static void *stdin_iferr(oop_source *evts, oop_read *stdin_read,
-                         oop_rd_event evt, const char *errmsg, int errnoval,
-                         const char *data, size_t recsz, void *cl_v) {
-  die("read stdin: %s", oop_rd_errmsg(stdin_read, evt,
-                                     errnoval, OOP_RD_STYLE_GETLINE));
-  return OOP_CONTINUE;
-}
-
 static int lstrpdbsearch(const char *str, int l,
                         const char *what,
                         const void *items, int n_items,
@@ -241,22 +237,67 @@ static int thiswordeatonechar(ParseState *ps, int c) {
   return 0;
 }
 
-static void *stdin_ifok(oop_source *evts, oop_read *cl_read,
+static void loadmask(MaskState *out, const PlanPixmapDataRef *ppd,
+                    XGCValues *gcv, long gcv_mask) {
+  static XpmColorSymbol coloursymbols[2]= {
+    { (char*)"space", 0, 0 },
+    { (char*)"mark",  0, 1 }
+  };
+  
+  XpmAttributes mattribs;
+  Pixmap pm;
+
+  out->x= ppd->x;
+  out->y= ppd->y;
+  mattribs.valuemask= XpmDepth | XpmColorSymbols;
+  mattribs.depth= 1;
+  mattribs.colorsymbols= coloursymbols;
+  mattribs.numsymbols= sizeof(coloursymbols) / sizeof(*coloursymbols);
+  XPMCALL( XpmCreatePixmapFromData, "mask",
+          (d,w, (char**)ppd->d, &pm,0, &mattribs) );
+  out->width= mattribs.width;
+  out->height= mattribs.height;
+
+  gcv->clip_x_origin= out->x;
+  gcv->clip_y_origin= out->y;
+  gcv->clip_mask= pm;
+  out->gc= XCreateGC(d,w,
+                    gcv_mask | GCClipXOrigin | GCClipYOrigin | GCClipMask,
+                    gcv);
+  XCALL( XFreePixmap, "mask", (d,pm) );
+}
+
+/*---------- input handling ----------*/
+
+typedef struct {
+  const char *name;
+  void (*on_eof)(void);
+  void (*on_input_line)(ParseState *ps);
+} InputStream;
+
+static void *input_iferr(oop_source *evts, oop_read *stdin_read,
+                         oop_rd_event evt, const char *errmsg, int errnoval,
+                         const char *data, size_t recsz, void *is_v) {
+  const InputStream *is= is_v;
+  const char *emsg;
+  emsg= oop_rd_errmsg(stdin_read, evt, errnoval, OOP_RD_STYLE_GETLINE)
+  die("%s: %s", is->name, emsg);
+}
+
+static void *input_ifok(oop_source *evts, oop_read *cl_read,
                        oop_rd_event evt, const char *errmsg, int errnoval,
                        const char *data, size_t recsz, void *cl_v) {
-  const char *slash, *movfeatname;
+  const InputStream *is= is_v;
   ParseState ps;
-  int invert, det, trainown, segment_ix, movfeat_ix, lmovfeatname;
-  long posn;
-  const PlanSegmentData *segment_d;
-  const PlanSegmovfeatData *movfeat_d;
-  SegmovfeatState *fs;
 
-  if (evt == OOP_RD_EOF)
-    exit(0);
-  
-  if (evt != OOP_RD_OK)
-    return stdin_iferr(evts,cl_read,evt,errmsg,errnoval,data,recsz,cl_v);
+  if (evt == OOP_RD_EOF) {
+    is->on_eof();
+    abort;
+  }
+  if (evt != OOP_RD_OK) {
+    input_iferr(evts,cl_read,evt,errmsg,errnoval,data,recsz,cl_v);
+    return OOP_CONTINUE;
+  }
 
   badcmdreport_data= data;
   badcmdreport_recsz= recsz;
@@ -264,20 +305,37 @@ static void *stdin_ifok(oop_source *evts, oop_read *cl_read,
   ps.remain= data;
   ps_needword(&ps);
 
-  if (!thiswordstrcmp(&ps,"off")) {
+  is->on_input_line(&ps);
+
+  return OOP_CONTINUE;
+}
+
+/*---------- stdin input handling ----------*/
+
+static void stdin_eof(void) { exit(0); }
+
+static void stdin_input_line() {
+  const char *slash, *movfeatname;
+  int invert, det, trainown, segment_ix, movfeat_ix, lmovfeatname;
+  long posn;
+  const PlanSegmentData *segment_d;
+  const PlanSegmovfeatData *movfeat_d;
+  SegmovfeatState *fs;
+
+  if (!thiswordstrcmp(ps,"off")) {
     invert= -1;
     trainown= 0;
     det= 0;
   } else {
     trainown=
-      thiswordeatonechar(&ps,'t') ? 2 :
-      thiswordeatonechar(&ps,'f') ? 1 : 0;
-    invert= thiswordeatonechar(&ps,'i');
-    det= (!thiswordstrcmp(&ps,"on") ? 0 :
-         !thiswordstrcmp(&ps,"det") ? 1 :
-         (badcmd(&ps,"unknown command"),-1));
+      thiswordeatonechar(ps,'t') ? 2 :
+      thiswordeatonechar(ps,'f') ? 1 : 0;
+    invert= thiswordeatonechar(ps,'i');
+    det= (!thiswordstrcmp(ps,"on") ? 0 :
+         !thiswordstrcmp(ps,"det") ? 1 :
+         (badcmd(ps,"unknown command"),-1));
   }
-  ps_needword(&ps);
+  ps_needword(ps);
   slash= memchr(ps.thisword, '/', ps.lthisword);
   if (slash) {
     movfeatname= slash + 1;
@@ -299,7 +357,7 @@ static void *stdin_ifok(oop_source *evts, oop_read *cl_read,
 
   if (ps.remain) {
     if (invert<0) badcmd(0,"off may not take movfeatpos");
-    ps_neednumber(&ps, &posn, 0, movfeat_d->n_posns-1, "movfeatpos");
+    ps_neednumber(ps, &posn, 0, movfeat_d->n_posns-1, "movfeatpos");
   } else {
     if (invert>=0 && movfeat_d->n_posns > 1) {
       posn= movfeat_d->n_posns;
@@ -308,7 +366,7 @@ static void *stdin_ifok(oop_source *evts, oop_read *cl_read,
     }
   }
 
-  ps_neednoargs(&ps);
+  ps_neednoargs(ps);
 
   fs= &state[segment_ix][movfeat_ix];
   fs->invert= invert;
@@ -322,64 +380,126 @@ static void *stdin_ifok(oop_source *evts, oop_read *cl_read,
   return OOP_CONTINUE;
 }
 
-static void loadmask(MaskState *out, const PlanPixmapDataRef *ppd,
-                    XGCValues *gcv, long gcv_mask) {
-  static XpmColorSymbol coloursymbols[2]= {
-    { (char*)"space", 0, 0 },
-    { (char*)"mark",  0, 1 }
-  };
+static const InputStream stdin_is= { "stdin", stdin_eof, stdin_input_line };
+
+/*---------- multiplexer client ----------*/
+
+static int sock_clientconnect(const char *node, const char *service) {
+  struct addrinfo *aires, *try, hints;
+  char niaddrbuf[256], niportbuf[64];
+  int r, sock;
   
-  XpmAttributes mattribs;
-  Pixmap pm;
+  memset(&hints,0,sizeof(hints));
+  hints.ai_family= PF_UNSPEC;
+  hints.ai_socktype= SOCK_STREAM;
+  r= getaddrinfo(node,service,&hints,&aires);
+  if (r) die("getaddrinfo node `%s' service `%s' failed: %s\n",
+            node,service,gai_strerror(r));
+
+  for (try=aires; try; try=try->ai_next) {
+    assert(try->ai_socktype == SOCK_STREAM);
+
+    r= getnameinfo(try->ai_addr, try->ai_addrlen,
+                  niaddrbuf, sizeof(niaddrbuf),
+                  niportbuf, sizeof(niportbuf),
+                  NI_NUMERICHOST|NI_NUMERICSERV);
+    assert(!r);
+
+    printf("trying %s,%s... ",niaddrbuf,niportbuf);
+    mflushstdout();
+
+    sock= socket(try->ai_family, SOCK_STREAM, try->ai_protocol);
+    if (sock<0) {
+      printf("couldn't create socket: %s\n",strerror(errno));
+      continue;
+    }
 
-  out->x= ppd->x;
-  out->y= ppd->y;
-  mattribs.valuemask= XpmDepth | XpmColorSymbols;
-  mattribs.depth= 1;
-  mattribs.colorsymbols= coloursymbols;
-  mattribs.numsymbols= sizeof(coloursymbols) / sizeof(*coloursymbols);
-  XPMCALL( XpmCreatePixmapFromData, "mask",
-          (d,w, (char**)ppd->d, &pm,0, &mattribs) );
-  out->width= mattribs.width;
-  out->height= mattribs.height;
+    r= connect(sock, try->ai_addr, try->ai_addrlen);
+    if (!r) {
+      printf("connected\n");
+      return sock;
+    }
 
-  gcv->clip_x_origin= out->x;
-  gcv->clip_y_origin= out->y;
-  gcv->clip_mask= pm;
-  out->gc= XCreateGC(d,w,
-                    gcv_mask | GCClipXOrigin | GCClipYOrigin | GCClipMask,
-                    gcv);
-  XCALL( XFreePixmap, "mask", (d,pm) );
+    printf("connect failed: %s\n",strerror(errno));
+    close(sock);
+  }
+  mflushstdout();
+  return -1;
 }
 
+static void sock_eof(void) { die("EOF on multiplexer connection"); }
+
+static void 
+
+static const char[]= {
+  { "?detect",             si_detect     },
+  { "?picio_out_polarity", si_polarity   },
+  { "?movpos_*_feat",      si_movpos     },
+  { "?stastate",           si_stastate   },
+  { "?picio_out_on",       si_pic_on     },
+  { "?picio_out_off",      si_pic_off    },
+  { "=connected",          si_connected  },
+  { "=permission",         0             },
+  { 0 }
+}  
+
+static void sock_input_line(ParseStatee *ps) {
+  if (thiswordstrcmp(ps,"=connected")) {
+    write sock ("select ?detect ?stastate ?picio_out_on ?picio_out_off"
+               " ?picio_out_polarity
+}
+
+static const InputStream sock_is= {
+  "multiplexer connection",
+  sock_eof,
+  sock_input_line
+};
+
+/*---------- main program including much of the initialisation ----------*/
+
 int main(int argc, const char *const *argv) {
   oop_read *rd;
   const char *arg;
   XpmAttributes mattribs;
   XWindowAttributes wattribs;
-  int segment_ix, movfeat_ix, posn, invert, det, oor;
+  int segment_ix, movfeat_ix, posn, invert, det, oor, sock=-1;
   XGCValues gcv;
   XColor colour;
   SegmovfeatState *fs;
   const PlanSegmentData *segment_d;
   const PlanSegmovfeatData *movfeat_d;
+  char *ep;
 
-  d= XOpenDisplay(0);  if (!d) die("XOpenDisplay failed");
-
-  if ((arg= *++argv)) {
-    char *ep;
-
+  while ((arg= *++argv)) {
     if (!strcmp(arg,"--sizes")) {
       printf("%d\n%d\n", ui_plan_data.xsz, ui_plan_data.ysz);
       if (ferror(stdout) || fflush(stdout)) diee("print stdout");
       exit(0);
+    } else if (arg[0]=='@') {
+      char *node, *comma;
+      const char *service;
+      node= (char*)arg+1;
+      comma= strchr(node,',');
+      if (comma) {
+       *comma= 0;
+       service= comma+1;
+      } else {
+       service= STR(TRAINMX_PORT);
+      }
+      sock= clientconnect(node,service);
+      if (sock<0) die("unable to connect to multiplexer");
+      if (comma) *comma= ',';
+    } else if (arg[0]=='-') {
+      die("invalid option(s)");
+    } else {
+      errno=0; w= strtoul(arg,&ep,0);
+      if (errno || ep==arg || *ep || w==None) die("bad windowid");
     }
+  }
 
-    if (arg[0]=='-') die("invalid option(s)");
+  d= XOpenDisplay(0);  if (!d) die("XOpenDisplay failed");
 
-    errno=0; w= strtoul(arg,&ep,0);
-    if (errno || ep==arg || *ep) die("bad windowid");
-  } else {
+  if (w==None) {
     w= XCreateSimpleWindow(d, DefaultRootWindow(d),
                           0,0, ui_plan_data.xsz, ui_plan_data.ysz,
                           0,0, 0);
@@ -458,9 +578,16 @@ int main(int argc, const char *const *argv) {
 
   rd= oop_rd_new_fd(events, 0, 0,0);
   if (!rd) diee("oop_rd_new_fd");
-  oor= oop_rd_read(rd, OOP_RD_STYLE_GETLINE, 1024,
-                  stdin_ifok, 0,
-                  stdin_iferr, 0);
+
+  if (sock==-1)
+    oor= oop_rd_read(rd, OOP_RD_STYLE_GETLINE, 1024,
+                    stdin_ifok, (void*)&stdin_is,
+                    stdin_iferr, (void*)&stdin_is);
+  else
+    oor= oop_rd_read(rd, OOP_RD_STYLE_GETLINE, 1024,
+                    sock_ifok, (void*)&sock_is,
+                    sock_iferr, (void*)&sock_is);
+
   if (oor) diee("oop_rd_read");
 
   events->on_fd(events, 0,                   OOP_EXCEPTION, some_exception, 0);
index a1f9d346e4c06f4fe547ddb141176cf37c545268..c7a37715d286a73f70117914f4ffd0c48763535e 100644 (file)
@@ -94,3 +94,7 @@ void mwaitpid(pid_t child, const char *what) {
     die("%s failed with unexpected wait status 0x%x", what, status);
   }
 }
+
+void mflushstdout(void) {
+  if (ferror(stdout) || fflush(stdout)) diee("write to stdout");
+}