ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp.c
Revision: 3.10
Committed: Mon Dec 8 18:51:15 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.9: +109 -8 lines
Log Message:
added command reading from server's stdin

File Contents

# Content
1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * Holodeck display process.
9 */
10
11 #include "rholo.h"
12 #include "rhdisp.h"
13 #include "rhdriver.h"
14 #include "selcall.h"
15 #include <ctype.h>
16
17 HOLO *hdlist[HDMAX+1]; /* global holodeck list */
18
19 char cmdlist[DC_NCMDS][8] = DC_INIT;
20
21 int imm_mode = 0; /* bundles are being delivered immediately */
22
23 char *progname; /* global argv[0] */
24
25 FILE *sstdin, *sstdout; /* server's standard input and output */
26
27 #define RDY_SRV 01
28 #define RDY_DEV 02
29 #define RDY_SIN 04
30
31
32 main(argc, argv)
33 int argc;
34 char *argv[];
35 {
36 extern int eputs();
37 int rdy, inp, res = 0, pause = 0;
38
39 progname = argv[0];
40 if (argc < 3)
41 error(USER, "bad command line arguments");
42 /* open our device */
43 dev_open(argv[1]);
44 /* open server process i/o */
45 sstdout = fdopen(atoi(argv[2]), "w");
46 if (argc < 4 || (inp = atoi(argv[3])) < 0)
47 sstdin = NULL;
48 else
49 sstdin = fdopen(inp, "r");
50 /* set command error vector */
51 erract[COMMAND].pf = eputs;
52 /* enter main loop */
53 do {
54 rdy = disp_wait();
55 if (rdy & RDY_DEV) { /* user input from driver */
56 inp = dev_input();
57 if (inp & DEV_PUTVIEW)
58 printview();
59 if (inp & DEV_NEWVIEW)
60 new_view(&odev.v);
61 if (inp & DEV_SHUTDOWN)
62 serv_request(DR_SHUTDOWN, 0, NULL);
63 if (inp & DEV_REDRAW) {
64 imm_mode = 1; /* preempt updates */
65 beam_sync();
66 }
67 if (inp & DEV_WAIT)
68 pause = 1;
69 if (inp & DEV_RESUME) {
70 serv_request(DR_NOOP, 0, NULL);
71 pause = 0;
72 }
73 }
74 if (rdy & RDY_SIN) /* user input from sstdin */
75 switch (usr_input()) {
76 case DC_PAUSE:
77 pause = 1;
78 break;
79 case DC_RESUME:
80 serv_request(DR_NOOP, 0, NULL);
81 pause = 0;
82 break;
83 }
84 if (rdy & RDY_SRV) { /* process server result */
85 res = serv_result();
86 if (pause && res != DS_SHUTDOWN) {
87 serv_request(DR_ATTEN, 0, NULL);
88 while ((res = serv_result()) != DS_ACKNOW &&
89 res != DS_SHUTDOWN)
90 ;
91 }
92 }
93 } while (res != DS_SHUTDOWN);
94 /* all done */
95 quit(0);
96 }
97
98
99 int
100 disp_wait() /* wait for more input */
101 {
102 fd_set readset, errset;
103 int flgs;
104 int n;
105 register int i;
106 /* see if we can avoid select call */
107 if (imm_mode || stdin->_cnt > 0)
108 return(RDY_SRV);
109 if (sstdin != NULL && sstdin->_cnt > 0)
110 return(RDY_SIN);
111 if (dev_flush())
112 return(RDY_DEV);
113 /* make the call */
114 FD_ZERO(&readset); FD_ZERO(&errset);
115 FD_SET(0, &readset);
116 FD_SET(0, &errset);
117 FD_SET(odev.ifd, &readset);
118 FD_SET(odev.ifd, &errset);
119 n = odev.ifd+1;
120 if (sstdin != NULL) {
121 FD_SET(fileno(sstdin), &readset);
122 if (fileno(sstdin) >= n)
123 n = fileno(sstdin) + 1;
124 }
125 n = select(n, &readset, NULL, &errset, NULL);
126 if (n < 0) {
127 if (errno == EINTR)
128 return(0);
129 error(SYSTEM, "select call failure in disp_wait");
130 }
131 flgs = 0; /* flag what's ready */
132 if (FD_ISSET(0, &readset) || FD_ISSET(0, &errset))
133 flgs |= RDY_SRV;
134 if (FD_ISSET(odev.ifd, &readset) || FD_ISSET(odev.ifd, &errset))
135 flgs |= RDY_DEV;
136 if (sstdin != NULL && FD_ISSET(fileno(sstdin), &readset))
137 flgs |= RDY_SIN;
138 return(flgs);
139 }
140
141
142 add_holo(hdg) /* register a new holodeck section */
143 HDGRID *hdg;
144 {
145 VIEW nv;
146 register int hd;
147
148 for (hd = 0; hd < HDMAX && hdlist[hd] != NULL; hd++)
149 ;
150 if (hd >= HDMAX)
151 error(INTERNAL, "too many holodeck sections in add_holo");
152 hdlist[hd] = (HOLO *)malloc(sizeof(HOLO));
153 if (hdlist[hd] == NULL)
154 error(SYSTEM, "out of memory in add_holo");
155 bcopy((char *)hdg, (char *)hdlist[hd], sizeof(HDGRID));
156 hdcompgrid(hdlist[hd]);
157 if (hd)
158 return;
159 /* set initial viewpoint */
160 copystruct(&nv, &odev.v);
161 VSUM(nv.vp, hdlist[0]->orig, hdlist[0]->xv[0], 0.5);
162 VSUM(nv.vp, nv.vp, hdlist[0]->xv[1], 0.5);
163 VSUM(nv.vp, nv.vp, hdlist[0]->xv[2], 0.5);
164 fcross(nv.vdir, hdlist[0]->xv[1], hdlist[0]->xv[2]);
165 VCOPY(nv.vup, hdlist[0]->xv[2]);
166 new_view(&nv);
167 }
168
169
170 disp_bundle(p) /* display a ray bundle */
171 register PACKHEAD *p;
172 {
173 GCOORD gc[2];
174 FVECT ro, rd, wp;
175 double d;
176 register int i;
177 /* get beam coordinates */
178 if (p->hd < 0 | p->hd >= HDMAX || hdlist[p->hd] == NULL)
179 error(INTERNAL, "bad holodeck number in disp_bundle");
180 if (!hdbcoord(gc, hdlist[p->hd], p->bi))
181 error(INTERNAL, "bad beam index in disp_bundle");
182 /* display each ray */
183 for (i = p->nr; i--; ) {
184 hdray(ro, rd, hdlist[p->hd], gc, packra(p)[i].r);
185 d = hddepth(hdlist[p->hd], packra(p)[i].d);
186 VSUM(wp, ro, rd, d); /* might be behind viewpoint */
187 dev_value(packra(p)[i].v, wp, rd);
188 }
189 }
190
191
192 new_view(v) /* change view parameters */
193 VIEW *v;
194 {
195 char *err;
196
197 do {
198 if ((err = setview(v)) != NULL) {
199 error(COMMAND, err);
200 return;
201 }
202 if (v->type == VT_PAR) {
203 error(COMMAND, "cannot handle parallel views");
204 return;
205 }
206 dev_view(v); /* update display driver */
207 dev_flush(); /* update screen */
208 } while (!beam_view(v)); /* update beam list */
209 }
210
211
212 int
213 usr_input() /* get user input and process it */
214 {
215 VIEW vparams;
216 char cmd[128];
217 register char *args;
218 register int cmdno;
219
220 if (fgets(cmd, sizeof(cmd), sstdin) == NULL)
221 return(DC_QUIT);
222 for (args = cmd; *args && !isspace(*args); args++)
223 ;
224 while (isspace(*args))
225 *args++ = '\0';
226 if (!*cmd)
227 return(DC_RESUME);
228 for (cmdno = 0; cmdno < DC_NCMDS; cmdno++)
229 if (!strcmp(cmd, cmdlist[cmdno]))
230 break;
231 if (cmdno >= DC_NCMDS) {
232 sprintf(errmsg, "unknown command: %s", cmd);
233 error(COMMAND, errmsg);
234 return(-1);
235 }
236 switch (cmdno) {
237 case DC_SETVIEW: /* set the view */
238 copystruct(&vparams, &odev.v);
239 if (!sscanview(&vparams, args))
240 error(COMMAND, "missing view options");
241 else
242 new_view(&vparams);
243 break;
244 case DC_GETVIEW: /* print the current view */
245 printview();
246 break;
247 case DC_PAUSE: /* pause the current calculation */
248 case DC_RESUME: /* resume the calculation */
249 /* handled in main() */
250 break;
251 case DC_QUIT: /* quit request */
252 serv_request(DR_SHUTDOWN, 0, NULL);
253 break;
254 default:
255 error(CONSISTENCY, "bad command id in usr_input");
256 }
257 return(cmdno);
258
259 }
260
261
262 printview() /* print our current view to server stdout */
263 {
264 fputs(VIEWSTR, sstdout);
265 fprintview(&odev.v, sstdout);
266 fputc('\n', sstdout);
267 fflush(sstdout);
268 }
269
270
271 int
272 serv_result() /* get next server result and process it */
273 {
274 static char *buf = NULL;
275 static int bufsiz = 0;
276 MSGHEAD msg;
277 int n;
278 /* read message header */
279 if (fread((char *)&msg, sizeof(MSGHEAD), 1, stdin) != 1)
280 goto readerr;
281 if (msg.nbytes > 0) { /* get the message body */
282 if (msg.nbytes > bufsiz) {
283 if (buf == NULL)
284 buf = (char *)malloc(bufsiz=msg.nbytes);
285 else
286 buf = (char *)realloc(buf, bufsiz=msg.nbytes);
287 if (buf == NULL)
288 error(SYSTEM, "out of memory in serv_result");
289 }
290 if (fread(buf, 1, msg.nbytes, stdin) != msg.nbytes)
291 goto readerr;
292 }
293 switch (msg.type) { /* process results */
294 case DS_BUNDLE:
295 if (msg.nbytes < sizeof(PACKHEAD) ||
296 msg.nbytes != packsiz(((PACKHEAD *)buf)->nr))
297 error(INTERNAL, "bad display packet from server");
298 disp_bundle((PACKHEAD *)buf);
299 break;
300 case DS_ADDHOLO:
301 if (msg.nbytes != sizeof(HDGRID))
302 error(INTERNAL, "bad holodeck record from server");
303 add_holo((HDGRID *)buf);
304 break;
305 case DS_STARTIMM:
306 case DS_ENDIMM:
307 imm_mode = msg.type==DS_STARTIMM;
308 if (msg.type == DS_ENDIMM)
309 dev_flush(); /* update display NOW */
310 /* fall through */
311 case DS_ACKNOW:
312 case DS_SHUTDOWN:
313 if (msg.nbytes) {
314 sprintf(errmsg,
315 "unexpected body with server message %d",
316 msg.type);
317 error(INTERNAL, errmsg);
318 }
319 break;
320 default:
321 error(INTERNAL, "unrecognized result from server process");
322 }
323 return(msg.type); /* return message type */
324 readerr:
325 if (feof(stdin))
326 error(SYSTEM, "server process died");
327 error(SYSTEM, "error reading from server process");
328 }
329
330
331 serv_request(type, nbytes, p) /* send a request to the server process */
332 int type, nbytes;
333 char *p;
334 {
335 MSGHEAD msg;
336 int m;
337 /* get server's attention for big request */
338 if (nbytes >= BIGREQSIZ-sizeof(MSGHEAD)) {
339 serv_request(DR_ATTEN, 0, NULL);
340 while ((m = serv_result()) != DS_ACKNOW)
341 if (m == DS_SHUTDOWN) /* the bugger quit on us */
342 quit(0);
343 }
344 msg.type = type; /* write and flush the message */
345 msg.nbytes = nbytes;
346 fwrite((char *)&msg, sizeof(MSGHEAD), 1, stdout);
347 if (nbytes > 0)
348 fwrite(p, 1, nbytes, stdout);
349 if (fflush(stdout) < 0)
350 error(SYSTEM, "write error in serv_request");
351 }
352
353
354 eputs(s) /* put error message to stderr */
355 register char *s;
356 {
357 static int midline = 0;
358
359 if (!*s)
360 return;
361 if (!midline++) { /* prepend line with program name */
362 fputs(progname, stderr);
363 fputs(": ", stderr);
364 }
365 fputs(s, stderr);
366 if (s[strlen(s)-1] == '\n') {
367 fflush(stderr);
368 midline = 0;
369 }
370 }
371
372
373 quit(code) /* clean up and exit */
374 int code;
375 {
376 if (odev.v.type)
377 dev_close();
378 exit(code);
379 }