From: ian Date: Tue, 27 May 2008 18:40:43 +0000 (+0000) Subject: wip gui-plan connect to multiplex - does not compile X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=520c84ff1627bbdf5a91892cc90d034fe2383ce1;p=trains.git wip gui-plan connect to multiplex - does not compile --- diff --git a/hostside/gui-plan.c b/hostside/gui-plan.c index 5596ba3..2725e2a 100644 --- a/hostside/gui-plan.c +++ b/hostside/gui-plan.c @@ -12,6 +12,10 @@ #include #include +#include +#include +#include + #include #include @@ -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); diff --git a/hostside/utils.c b/hostside/utils.c index a1f9d34..c7a3771 100644 --- a/hostside/utils.c +++ b/hostside/utils.c @@ -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"); +}