Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | /* |
2 | * Copyright (c) 1995 The Regents of the University of California. |
||
3 | * All rights reserved. |
||
4 | * |
||
5 | * Permission to use, copy, modify, and distribute this software and its |
||
6 | * documentation for any purpose, without fee, and without written agreement is |
||
7 | * hereby granted, provided that the above copyright notice and the following |
||
8 | * two paragraphs appear in all copies of this software. |
||
9 | * |
||
10 | * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
||
11 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
||
12 | * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF |
||
13 | * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
14 | * |
||
15 | * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
||
16 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
||
17 | * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
||
18 | * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO |
||
19 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||
20 | |||
21 | contributed by (but no rights held by): |
||
22 | |||
23 | Michael J. Donahue |
||
24 | National Institute of Standards and Technology |
||
25 | Gaithersburg MD USA |
||
26 | donahue@ulexite.nist.gov |
||
27 | |||
28 | */ |
||
29 | |||
30 | /* |
||
31 | * Portions of this software Copyright (c) 1995 Brown University. |
||
32 | * All rights reserved. |
||
33 | * |
||
34 | * Permission to use, copy, modify, and distribute this software and its |
||
35 | * documentation for any purpose, without fee, and without written agreement |
||
36 | * is hereby granted, provided that the above copyright notice and the |
||
37 | * following two paragraphs appear in all copies of this software. |
||
38 | * |
||
39 | * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR |
||
40 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
||
41 | * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN |
||
42 | * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
43 | * |
||
44 | * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||
46 | * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||
47 | * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||
48 | * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||
49 | */ |
||
50 | |||
51 | /* |
||
52 | Changes to make the code reentrant: |
||
53 | If using ANSI C, do prototyping for static functions |
||
54 | display not a global, must be passed to functions |
||
55 | display window now not a global, must be passed to functions via xinfo |
||
56 | struct |
||
57 | FILMState removed - now uses vid_stream->film_has_ended instead |
||
58 | use totNumFrames from vid_stream, not global |
||
59 | must pass vid_stream (EOF_flag, seekValue, etc. no longer global) |
||
60 | CONTROLS version now can deal with >1 movie |
||
61 | Additional changes: |
||
62 | Do prototyping for static functions |
||
63 | - lsh@cs.brown.edu (Loring Holden) |
||
64 | */ |
||
65 | |||
66 | #ifndef NOCONTROLS |
||
67 | #include <stdio.h> |
||
68 | #include <stdlib.h> |
||
69 | #include <string.h> |
||
70 | #include "dither.h" |
||
71 | #include "video.h" |
||
72 | #include "ctrlbar.h" |
||
73 | #include "proto.h" |
||
74 | |||
75 | #ifndef MIPS |
||
76 | #include <sys/time.h> |
||
77 | #else |
||
78 | #include <sys/types.h> |
||
79 | #include <sys/system.h> |
||
80 | #endif |
||
81 | |||
82 | /* Default is to play asap. If you want it to start paused, change to |
||
83 | CTRL_PAUSE |
||
84 | */ |
||
85 | #define INITIAL_STATE CTRL_PLAY |
||
86 | |||
87 | /* Global variable definitions */ |
||
88 | int ControlShow = CTRLBAR_ON; /* ON => Show (display) control bar */ |
||
89 | int ControlState = CTRL_UNDEFINED; /* Current control state */ |
||
90 | int ControlMotion = CTRLMOTION_OFF; /* Pause mode */ |
||
91 | long TotalFrameCount= 0; /* Total number of frames processed, including loops */ |
||
92 | |||
93 | /* File statics */ |
||
94 | static int CtrlBarWidth; |
||
95 | static int CtrlBarHeight = 31; |
||
96 | static int CtrlBarBorder = 4; |
||
97 | static int ChildBorder = 2; |
||
98 | static int ChildMargin = 6; |
||
99 | |||
100 | static Window ctrlwindow = 0; |
||
101 | static int screen = -1; |
||
102 | static XFontStruct* ctrlfont = NULL; |
||
103 | static int fontheight, fontwidth; |
||
104 | static unsigned long fgcolor, bgcolor; |
||
105 | |||
106 | static int ctrl_init = 0; /* 1 => Control windows have been initialized */ |
||
107 | |||
108 | /* Support for WM_DELETE_WINDOW */ |
||
109 | static Atom protocol_atom = (Atom)None; |
||
110 | static Atom delete_atom = (Atom)None; |
||
111 | |||
112 | /* Child windows */ |
||
113 | static int ChildCount = 7; |
||
114 | static Window frametotalwin; |
||
115 | static int ftw_width, ftw_height; |
||
116 | static Window rewindwin; |
||
117 | static int rww_width, rww_height; |
||
118 | static Window pausewin; |
||
119 | static int psw_width, psw_height; |
||
120 | static Window playwin; |
||
121 | static int plw_width, plw_height; |
||
122 | static Window stepwin; |
||
123 | static int stw_width, stw_height; |
||
124 | static Window exitwin; |
||
125 | static int exw_width, exw_height; |
||
126 | static Window loopwin; |
||
127 | static int lpw_width, lpw_height; |
||
128 | |||
129 | |||
130 | /* |
||
131 | *-------------------------------------------------------------- |
||
132 | * |
||
133 | * StopWatch -- |
||
134 | * |
||
135 | * On/off timing routine (in real elapsed time). |
||
136 | * |
||
137 | * Results: |
||
138 | * If import is: |
||
139 | * STOPWATCH_START ---- Starts timing, returns 0.0. |
||
140 | * STOPWATCH_STOP ---- Stops timing, returns elapsed |
||
141 | * time in seconds. |
||
142 | * STOPWATCH_RESET ---- Resets timing, returns 0.0. |
||
143 | * STOPWATCH_READ ---- Returns elapsed time in seconds. |
||
144 | * |
||
145 | * Side effects: |
||
146 | * None. |
||
147 | * |
||
148 | *-------------------------------------------------------------- |
||
149 | */ |
||
150 | |||
151 | double |
||
152 | StopWatch(action) |
||
153 | int action; |
||
154 | { |
||
155 | static struct timeval start,current; /* Working times */ |
||
156 | static struct timeval elapsed; /* Previously accumulated time */ |
||
157 | static int state = STOPWATCH_STOP; |
||
158 | double dtemp = 0.0; |
||
159 | long ltemp; |
||
160 | |||
161 | if (action == state) { |
||
162 | if (state == STOPWATCH_START) { |
||
163 | return 0.0; |
||
164 | } |
||
165 | else return elapsed.tv_sec + elapsed.tv_usec/1000000.0; |
||
166 | } |
||
167 | switch(action) { |
||
168 | case STOPWATCH_START: |
||
169 | state = STOPWATCH_START; |
||
170 | gettimeofday(&start, (struct timezone *)NULL); |
||
171 | break; |
||
172 | case STOPWATCH_STOP: |
||
173 | gettimeofday(¤t, (struct timezone *)NULL); |
||
174 | state = STOPWATCH_STOP; |
||
175 | ltemp = elapsed.tv_usec + current.tv_usec - start.tv_usec; |
||
176 | elapsed.tv_sec += current.tv_sec-start.tv_sec + ltemp/1000000; |
||
177 | elapsed.tv_usec = ltemp % 1000000; |
||
178 | /* And fall through to STOPWATCH_READ */ |
||
179 | case STOPWATCH_READ: |
||
180 | if (state == STOPWATCH_START) { /* Stopwatch is running */ |
||
181 | gettimeofday(¤t,(struct timezone *)NULL); |
||
182 | dtemp = (current.tv_sec-start.tv_sec + elapsed.tv_sec) |
||
183 | + (current.tv_usec-start.tv_usec + elapsed.tv_usec) / 1000000.0; |
||
184 | } |
||
185 | else dtemp = elapsed.tv_sec + elapsed.tv_usec/1000000.0; |
||
186 | break; |
||
187 | case STOPWATCH_RESET: |
||
188 | state = STOPWATCH_STOP; |
||
189 | elapsed.tv_sec = elapsed.tv_usec = 0; |
||
190 | break; |
||
191 | default: |
||
192 | fprintf(stderr,"Illegal action (%d) requested of StopWatch()",action); |
||
193 | exit(1); |
||
194 | } |
||
195 | return dtemp; |
||
196 | } |
||
197 | |||
198 | |||
199 | /* |
||
200 | *-------------------------------------------------------------- |
||
201 | * |
||
202 | * GetWindowOrigins -- |
||
203 | * |
||
204 | * Determines window coordinates with respect to root window. |
||
205 | * |
||
206 | * Results: |
||
207 | * Sets (xwhole,ywhole) to root coordinates of upper lefthand corner |
||
208 | * of the specified window (including decorations), and (xclient,yclient) |
||
209 | * to the root coordinates of the client region. |
||
210 | * |
||
211 | * Side effects: |
||
212 | * None. |
||
213 | * |
||
214 | *-------------------------------------------------------------- |
||
215 | */ |
||
216 | |||
217 | #ifdef __STDC__ |
||
218 | static void GetWindowOrigins(XInfo *xinfo, int *xclient, |
||
219 | int *yclient, int *xwhole, int *ywhole) |
||
220 | #else |
||
221 | static void GetWindowOrigins(xinfo,xclient,yclient,xwhole,ywhole) |
||
222 | XInfo *xinfo; |
||
223 | int *xclient; |
||
224 | int *yclient; |
||
225 | int *xwhole; |
||
226 | int *ywhole; |
||
227 | #endif |
||
228 | { |
||
229 | Window dummy_window; |
||
230 | Window win=xinfo->window; |
||
231 | Display *display=xinfo->display; |
||
232 | |||
233 | /* First get coordinates for client "sub"-window */ |
||
234 | XTranslateCoordinates(display,win,DefaultRootWindow(display), |
||
235 | 0,0,xclient,yclient,&dummy_window); |
||
236 | if (dummy_window == None) { /* Shouldn't happen, but if so, then punt */ |
||
237 | *xwhole = *xclient; |
||
238 | *ywhole = *yclient; |
||
239 | return; |
||
240 | } |
||
241 | |||
242 | /* Now dummy_window should be a direct child of root, so find */ |
||
243 | /* its base coordinates. */ |
||
244 | XTranslateCoordinates(display,dummy_window,DefaultRootWindow(display), |
||
245 | 0,0,xwhole,ywhole,&dummy_window); |
||
246 | |||
247 | /* And finally, subtract 1 for good luck ;-) */ |
||
248 | if ((*xwhole) > 0) { |
||
249 | (*xwhole)--; |
||
250 | } |
||
251 | if ((*ywhole) > 0) { |
||
252 | (*ywhole)--; |
||
253 | } |
||
254 | } |
||
255 | |||
256 | |||
257 | |||
258 | /* |
||
259 | *-------------------------------------------------------------- |
||
260 | * |
||
261 | * WindowMapped -- |
||
262 | * |
||
263 | * Check event to see if window is mapped. A procedure |
||
264 | * intended to be passed to XIfEvent(). |
||
265 | * |
||
266 | * Results: |
||
267 | * Read the code. |
||
268 | * |
||
269 | * Side effects: |
||
270 | * None. |
||
271 | * |
||
272 | *-------------------------------------------------------------- |
||
273 | */ |
||
274 | |||
275 | Bool WindowMapped(dsp,xev,window) |
||
276 | Display *dsp; |
||
277 | XEvent *xev; |
||
278 | char *window; |
||
279 | { |
||
280 | if (xev->type == MapNotify && xev->xmap.event == *((Window *)window)) |
||
281 | return TRUE; |
||
282 | return FALSE; |
||
283 | } |
||
284 | |||
285 | /* |
||
286 | *-------------------------------------------------------------- |
||
287 | * |
||
288 | * IfEventType -- |
||
289 | * |
||
290 | * Check event type. A procedure intended to be passed to XIfEvent(). |
||
291 | * |
||
292 | * Results: |
||
293 | * Read the code. |
||
294 | * |
||
295 | * Side effects: |
||
296 | * None. |
||
297 | * |
||
298 | *-------------------------------------------------------------- |
||
299 | */ |
||
300 | |||
301 | Bool IfEventType(dsp,xev,type) |
||
302 | Display *dsp; |
||
303 | XEvent *xev; |
||
304 | char *type; |
||
305 | { |
||
306 | if (xev->type == *((int *)type)) { |
||
307 | return TRUE; |
||
308 | } |
||
309 | return FALSE; |
||
310 | } |
||
311 | |||
312 | |||
313 | |||
314 | /* |
||
315 | *-------------------------------------------------------------- |
||
316 | * ShowHideControls--- |
||
317 | * |
||
318 | * Maps or unmaps control bar as dictated by the value of the |
||
319 | * global variable ControlShow. |
||
320 | * |
||
321 | * Results: |
||
322 | * None. |
||
323 | * |
||
324 | * Side effects: |
||
325 | * None. |
||
326 | * |
||
327 | *-------------------------------------------------------------- |
||
328 | */ |
||
329 | #ifdef __STDC__ |
||
330 | static void ShowHideControls(XInfo *xinfo) |
||
331 | #else |
||
332 | static void ShowHideControls(xinfo) |
||
333 | XInfo *xinfo; |
||
334 | #endif |
||
335 | { |
||
336 | if (ControlShow == CTRLBAR_ON) { |
||
337 | XEvent event; |
||
338 | XMapRaised(xinfo->display, ctrlwindow); |
||
339 | XIfEvent(xinfo->display, &event, WindowMapped, (char *)(&ctrlwindow)); |
||
340 | /* Wait for map. */ |
||
341 | } |
||
342 | else { |
||
343 | XUnmapWindow(xinfo->display, ctrlwindow); |
||
344 | } |
||
345 | } |
||
346 | |||
347 | |||
348 | |||
349 | /* |
||
350 | *-------------------------------------------------------------- |
||
351 | * |
||
352 | * MakeControlBar -- |
||
353 | * |
||
354 | * Creates and (possibly) displays Control Bar in root window |
||
355 | * at position (x,y) relative to video output window. |
||
356 | * |
||
357 | * Results: |
||
358 | * Sets ctrlwindow. |
||
359 | * |
||
360 | * Side effects: |
||
361 | * Sets ctrl_init to 1 if successful. |
||
362 | * |
||
363 | *-------------------------------------------------------------- |
||
364 | */ |
||
365 | void MakeControlBar(xinfo) |
||
366 | XInfo *xinfo; |
||
367 | { |
||
368 | char *ctrlname = "MPEG Player Controls"; |
||
369 | XSizeHints hint; |
||
370 | int xpos, ypos; |
||
371 | Display *display=xinfo->display; |
||
372 | |||
373 | if (ctrl_init) { |
||
374 | fprintf(stderr, |
||
375 | "Warning from MakeControlBar(): Controls already initialized\n"); |
||
376 | return; |
||
377 | } |
||
378 | if (xinfo->ditherType == NO_DITHER) return; |
||
379 | if (display == (Display*)NULL) { |
||
380 | fprintf(stderr, |
||
381 | "Fatal error in MakeControlBar(): Display pointer not initialized\n"); |
||
382 | exit(1); |
||
383 | } |
||
384 | |||
385 | /* Get font (used in window sizing) */ |
||
386 | if ((ctrlfont = XLoadQueryFont(display, "fixed")) == NULL) { |
||
387 | fprintf(stderr,"Error: Unable to load font \"fixed\" for Control Bar\n"); |
||
388 | exit(1); |
||
389 | } |
||
390 | fontheight = ctrlfont->ascent + ctrlfont->descent; |
||
391 | fontwidth = ctrlfont->max_bounds.width; |
||
392 | |||
393 | if (fontheight < 4 || fontheight > 75 || fontwidth < 2 || fontwidth > 30) { |
||
394 | fprintf(stderr,"Warning: Font size seems suspect...guessing\n"); |
||
395 | fontheight = 20; |
||
396 | fontwidth = 10; /* Maybe 13 and 6 are better */ |
||
397 | } |
||
398 | |||
399 | /* Set window sizes */ |
||
400 | ftw_height = CtrlBarHeight-2*(ChildBorder+ChildMargin); |
||
401 | ftw_width = fontwidth * 21; |
||
402 | rww_height = ftw_height; rww_width = fontwidth * 8; |
||
403 | psw_height = rww_height; psw_width = fontwidth * 7; |
||
404 | stw_height = psw_height; stw_width = fontwidth * 6; |
||
405 | plw_height = stw_height; plw_width = fontwidth * 6; |
||
406 | lpw_height = plw_height; lpw_width = fontwidth * 10; |
||
407 | exw_height = lpw_height; exw_width = fontwidth * 6; |
||
408 | CtrlBarWidth = rww_width + psw_width + stw_width + plw_width + lpw_width |
||
409 | + exw_width + ftw_width + ChildMargin |
||
410 | + ChildCount*(ChildMargin + 2*ChildBorder); |
||
411 | |||
412 | /* Figure out how to place control bar just above display window */ |
||
413 | GetWindowOrigins(xinfo,&xpos,&ypos,&hint.x,&hint.y); |
||
414 | |||
415 | /* Leave room for title bar decorations. Note this assumes */ |
||
416 | /* control bar dec. same height as for display window */ |
||
417 | hint.y = 2*hint.y - ypos; |
||
418 | |||
419 | hint.y -= (CtrlBarHeight + 2*CtrlBarBorder + 1); /* +1 for luck ;-) */ |
||
420 | if (hint.y < 0) { |
||
421 | hint.y = 0; |
||
422 | } |
||
423 | hint.max_width = hint.base_width = hint.width = CtrlBarWidth; |
||
424 | hint.max_height = hint.base_height = hint.height = CtrlBarHeight; |
||
425 | hint.min_width = hint.min_height = 0; |
||
426 | hint.flags = PMinSize | PMaxSize | PBaseSize | |
||
427 | PPosition | PSize | USPosition; |
||
428 | |||
429 | screen = DefaultScreen (display); |
||
430 | fgcolor = BlackPixel(display, screen); |
||
431 | bgcolor = WhitePixel(display, screen); |
||
432 | |||
433 | /* Create main control window */ |
||
434 | ctrlwindow = XCreateSimpleWindow (display, |
||
435 | DefaultRootWindow(display), |
||
436 | hint.x, hint.y, |
||
437 | hint.base_width, hint.base_height, |
||
438 | CtrlBarBorder, fgcolor, bgcolor); |
||
439 | |||
440 | /* Create child windows */ |
||
441 | xpos = ChildMargin; |
||
442 | ypos = ChildMargin; |
||
443 | frametotalwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos, |
||
444 | ftw_width, ftw_height, ChildBorder, fgcolor, bgcolor); |
||
445 | xpos += ftw_width + 2*ChildBorder + ChildMargin; |
||
446 | rewindwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos, |
||
447 | rww_width, rww_height, ChildBorder, fgcolor, bgcolor); |
||
448 | xpos += rww_width + 2*ChildBorder + ChildMargin; |
||
449 | pausewin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos, |
||
450 | psw_width, psw_height, ChildBorder, fgcolor, bgcolor); |
||
451 | xpos += psw_width + 2*ChildBorder + ChildMargin; |
||
452 | stepwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos, |
||
453 | stw_width, stw_height, ChildBorder, fgcolor, bgcolor); |
||
454 | xpos += stw_width + 2*ChildBorder + ChildMargin; |
||
455 | playwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos, |
||
456 | plw_width, plw_height, ChildBorder, fgcolor, bgcolor); |
||
457 | xpos += plw_width + 2*ChildBorder + ChildMargin; |
||
458 | loopwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos, |
||
459 | lpw_width, lpw_height, ChildBorder, fgcolor, bgcolor); |
||
460 | xpos += lpw_width + 2*ChildBorder + ChildMargin; |
||
461 | exitwin = XCreateSimpleWindow (display, ctrlwindow, xpos, ypos, |
||
462 | exw_width, exw_height, ChildBorder, fgcolor, bgcolor); |
||
463 | |||
464 | /* Set up windows */ |
||
465 | XSelectInput(display, ctrlwindow, StructureNotifyMask); |
||
466 | XSetStandardProperties(display, ctrlwindow, ctrlname, ctrlname, None, |
||
467 | NULL, 0, &hint); |
||
468 | /*Safety*/ |
||
469 | XResizeWindow(display,ctrlwindow, hint. base_width, hint. base_height); |
||
470 | |||
471 | XSelectInput(display, rewindwin, ExposureMask | ButtonPressMask); |
||
472 | XSelectInput(display, pausewin, ExposureMask | ButtonPressMask); |
||
473 | XSelectInput(display, stepwin, ExposureMask | ButtonPressMask); |
||
474 | XSelectInput(display, playwin, ExposureMask | ButtonPressMask); |
||
475 | XSelectInput(display, loopwin, ExposureMask | ButtonPressMask); |
||
476 | XSelectInput(display, exitwin, ExposureMask | ButtonPressMask); |
||
477 | XSelectInput(display, frametotalwin, ExposureMask ); |
||
478 | |||
479 | /* Add "Delete" option to system menus */ |
||
480 | protocol_atom = XInternAtom(display,"WM_PROTOCOLS",False); |
||
481 | delete_atom = XInternAtom(display,"WM_DELETE_WINDOW",False); |
||
482 | if ( protocol_atom != (Atom)None && delete_atom != (Atom)None) { |
||
483 | XSetWMProtocols(display, xinfo->window, &delete_atom, 1);/* Video window */ |
||
484 | XSetWMProtocols(display, ctrlwindow, &delete_atom, 1); /* Control bar */ |
||
485 | } |
||
486 | |||
487 | /* Map windows (or not ;-) */ |
||
488 | XMapSubwindows(display, ctrlwindow); |
||
489 | ShowHideControls(xinfo); |
||
490 | |||
491 | ctrl_init = 1; /* Control Bar successfully initialized */ |
||
492 | } |
||
493 | |||
494 | |||
495 | |||
496 | /* |
||
497 | *-------------------------------------------------------------- |
||
498 | * |
||
499 | * Child window draw functions -- |
||
500 | * |
||
501 | * (Re)draws child window |
||
502 | * |
||
503 | * Results: |
||
504 | * None. |
||
505 | * |
||
506 | * Side effects: |
||
507 | * None. |
||
508 | * |
||
509 | *-------------------------------------------------------------- |
||
510 | */ |
||
511 | |||
512 | #if __STDC__ |
||
513 | static void WriteCenteredText(Window win, |
||
514 | GC gc, |
||
515 | int winwidth, |
||
516 | int winheight, |
||
517 | char *str, |
||
518 | Display *display) |
||
519 | #else |
||
520 | static void WriteCenteredText(win,gc,winwidth,winheight,str,display) |
||
521 | Window win; |
||
522 | GC gc; |
||
523 | int winwidth, winheight; |
||
524 | char *str; |
||
525 | Display *display; |
||
526 | #endif |
||
527 | { |
||
528 | int xpos, ypos, len; |
||
529 | len = strlen(str); |
||
530 | ypos = (winheight + ctrlfont->ascent)/2 - 1; /* Ignore descenders */ |
||
531 | xpos = (winwidth - len*fontwidth)/2; |
||
532 | XDrawImageString(display, win, gc, xpos, ypos, str, len); |
||
533 | } |
||
534 | |||
535 | #if __STDC__ |
||
536 | static void ExposeWindow(Window win, Display *display) |
||
537 | #else |
||
538 | static void ExposeWindow(win,display) |
||
539 | Window win; |
||
540 | Display *display; |
||
541 | #endif |
||
542 | { |
||
543 | static XEvent event; |
||
544 | event.xexpose.type = Expose; |
||
545 | event.xexpose.serial = 0; |
||
546 | event.xexpose.send_event = TRUE; |
||
547 | event.xexpose.display = display; |
||
548 | event.xexpose.window = win; |
||
549 | event.xexpose.x = 0; |
||
550 | event.xexpose.y = 0; |
||
551 | event.xexpose.width = 0; |
||
552 | event.xexpose.height = 0; |
||
553 | event.xexpose.count = 0; |
||
554 | XSendEvent(display, win, FALSE, ExposureMask, &event); |
||
555 | } |
||
556 | |||
557 | #if __STDC__ |
||
558 | static void NormalColors(GC gc, Display *display) |
||
559 | #else |
||
560 | static void NormalColors(gc,display) |
||
561 | GC gc; |
||
562 | Display *display; |
||
563 | #endif |
||
564 | { |
||
565 | XSetForeground(display, gc, fgcolor); |
||
566 | XSetBackground(display, gc, bgcolor); |
||
567 | } |
||
568 | |||
569 | #if __STDC__ |
||
570 | static void InvertColors(GC gc, Display *display) |
||
571 | #else |
||
572 | static void InvertColors(gc,display) |
||
573 | GC gc; |
||
574 | Display *display; |
||
575 | #endif |
||
576 | { |
||
577 | XSetForeground(display, gc, bgcolor); |
||
578 | XSetBackground(display, gc, fgcolor); |
||
579 | } |
||
580 | |||
581 | #if __STDC__ |
||
582 | static void DrawRewind(GC gc, Display *display) |
||
583 | #else |
||
584 | static void DrawRewind(gc,display) |
||
585 | GC gc; |
||
586 | Display *display; |
||
587 | #endif |
||
588 | { |
||
589 | if (ControlState == CTRL_REWIND) { |
||
590 | XFillRectangle(display, rewindwin, gc, 0, 0, rww_width, rww_height); |
||
591 | InvertColors(gc,display); |
||
592 | WriteCenteredText(rewindwin, gc, rww_width, rww_height, "Rewind",display); |
||
593 | NormalColors(gc,display); |
||
594 | } |
||
595 | else { |
||
596 | WriteCenteredText(rewindwin, gc, rww_width, rww_height, "Rewind",display); |
||
597 | } |
||
598 | } |
||
599 | |||
600 | #if __STDC__ |
||
601 | static void DrawPause(GC gc, Display *display) |
||
602 | #else |
||
603 | static void DrawPause(gc,display) |
||
604 | GC gc; |
||
605 | Display *display; |
||
606 | #endif |
||
607 | { |
||
608 | if (ControlState == CTRL_EOF || ControlState == CTRL_FFWD |
||
609 | || ControlState == CTRL_PAUSE) { |
||
610 | XFillRectangle(display,pausewin,gc,0,0,psw_width,psw_height); |
||
611 | InvertColors(gc,display); |
||
612 | switch(ControlState) { |
||
613 | case CTRL_EOF: |
||
614 | WriteCenteredText(pausewin,gc,psw_width,psw_height,"End",display); |
||
615 | break; |
||
616 | case CTRL_FFWD: |
||
617 | WriteCenteredText(pausewin,gc,psw_width,psw_height,"Wait",display); |
||
618 | break; |
||
619 | default: |
||
620 | WriteCenteredText(pausewin,gc,psw_width,psw_height,"Pause",display); |
||
621 | break; |
||
622 | } |
||
623 | NormalColors(gc,display); |
||
624 | } |
||
625 | else { |
||
626 | WriteCenteredText(pausewin,gc,psw_width,psw_height,"Pause",display); |
||
627 | } |
||
628 | } |
||
629 | |||
630 | #if __STDC__ |
||
631 | static void DrawStep(GC gc, Display *display) |
||
632 | #else |
||
633 | static void DrawStep(gc,display) |
||
634 | GC gc; |
||
635 | Display *display; |
||
636 | #endif |
||
637 | { |
||
638 | if (ControlState == CTRL_STEP) { |
||
639 | XFillRectangle(display, stepwin, gc, 0, 0, stw_width, stw_height); |
||
640 | InvertColors(gc,display); |
||
641 | } |
||
642 | WriteCenteredText(stepwin, gc, stw_width, stw_height, "Step",display); |
||
643 | if (ControlState == CTRL_STEP) { |
||
644 | NormalColors(gc,display); |
||
645 | } |
||
646 | } |
||
647 | |||
648 | #if __STDC__ |
||
649 | static void DrawPlay(GC gc, Display *display) |
||
650 | #else |
||
651 | static void DrawPlay(gc,display) |
||
652 | GC gc; |
||
653 | Display *display; |
||
654 | #endif |
||
655 | { |
||
656 | if (ControlState == CTRL_PLAY || |
||
657 | (ControlState == CTRL_EOF && ControlMotion == CTRLMOTION_ON)) { |
||
658 | XFillRectangle(display, playwin, gc, 0, 0, plw_width, plw_height); |
||
659 | InvertColors(gc,display); |
||
660 | WriteCenteredText(playwin, gc, plw_width, plw_height, "Play",display); |
||
661 | NormalColors(gc,display); |
||
662 | } |
||
663 | else { |
||
664 | WriteCenteredText(playwin, gc, plw_width, plw_height, "Play",display); |
||
665 | } |
||
666 | } |
||
667 | |||
668 | #if __STDC__ |
||
669 | static void DrawLoop(GC gc, Display *display) |
||
670 | #else |
||
671 | static void DrawLoop(gc,display) |
||
672 | GC gc; |
||
673 | Display *display; |
||
674 | #endif |
||
675 | { |
||
676 | if (loopFlag) { |
||
677 | XFillRectangle(display, loopwin, gc, 0, 0, lpw_width, lpw_height); |
||
678 | InvertColors(gc,display); |
||
679 | WriteCenteredText(loopwin, gc, lpw_width, lpw_height, "Loop ON",display); |
||
680 | NormalColors(gc,display); |
||
681 | } |
||
682 | else WriteCenteredText(loopwin, gc, lpw_width, lpw_height, "Loop OFF", |
||
683 | display); |
||
684 | } |
||
685 | |||
686 | #if __STDC__ |
||
687 | static void DrawExit(GC gc, Display *display) |
||
688 | #else |
||
689 | static void DrawExit(gc,display) |
||
690 | GC gc; |
||
691 | Display *display; |
||
692 | #endif |
||
693 | { |
||
694 | if (ControlState == CTRL_EXIT) { |
||
695 | XFillRectangle(display,exitwin, gc, 0, 0, exw_width, exw_height); |
||
696 | InvertColors(gc,display); |
||
697 | } |
||
698 | WriteCenteredText(exitwin, gc, exw_width, exw_height, "Exit",display); |
||
699 | if (ControlState == CTRL_EXIT) { |
||
700 | NormalColors(gc,display); |
||
701 | } |
||
702 | } |
||
703 | |||
704 | void UpdateFrameTotal(display) |
||
705 | Display *display; |
||
706 | { |
||
707 | if (!ctrl_init) { |
||
708 | return; |
||
709 | } |
||
710 | ExposeWindow(frametotalwin,display); |
||
711 | } |
||
712 | |||
713 | void UpdateControlDisplay(display) |
||
714 | Display *display; |
||
715 | { |
||
716 | if (!ctrl_init) { |
||
717 | return; |
||
718 | } |
||
719 | ExposeWindow(rewindwin,display); |
||
720 | ExposeWindow(pausewin,display); |
||
721 | ExposeWindow(stepwin,display); |
||
722 | ExposeWindow(playwin,display); |
||
723 | ExposeWindow(loopwin,display); |
||
724 | ExposeWindow(exitwin,display); |
||
725 | ExposeWindow(frametotalwin,display); |
||
726 | } |
||
727 | |||
728 | #if __STDC__ |
||
729 | static void DrawFrameTotal(GC gc, VidStream **vid_stream, Display *display, |
||
730 | int numMovies) |
||
731 | #else |
||
732 | static void DrawFrameTotal(gc, vid_stream, display, numMovies) |
||
733 | GC gc; |
||
734 | VidStream **vid_stream; |
||
735 | Display *display; |
||
736 | int numMovies; |
||
737 | #endif |
||
738 | { |
||
739 | char str[32]; |
||
740 | double dtemp; |
||
741 | int totNumFrames=0, i; |
||
742 | |||
743 | dtemp = StopWatch(STOPWATCH_READ); |
||
744 | |||
745 | |||
746 | for (i=0;i<numMovies;i++) { |
||
747 | if ((vid_stream[i]!=NULL) && |
||
748 | (vid_stream[i]->totNumFrames > totNumFrames)) { |
||
749 | totNumFrames= vid_stream[i]->totNumFrames; |
||
750 | } |
||
751 | } |
||
752 | |||
753 | if (dtemp > 0.0) { |
||
754 | sprintf(str, "Frame/Rate%4d/%4.1f", |
||
755 | totNumFrames, TotalFrameCount/dtemp); |
||
756 | } |
||
757 | else { |
||
758 | sprintf(str, "Frame/Rate%4d/----", totNumFrames); |
||
759 | } |
||
760 | WriteCenteredText(frametotalwin, gc, ftw_width, ftw_height, str, display); |
||
761 | } |
||
762 | |||
763 | #if __STDC__ |
||
764 | static GC CreateCtrlGC(Display *display) |
||
765 | #else |
||
766 | static GC CreateCtrlGC(display) |
||
767 | Display *display; |
||
768 | #endif |
||
769 | { |
||
770 | XGCValues gcv; |
||
771 | GC gc; |
||
772 | gcv.foreground = BlackPixel(display, screen); |
||
773 | gcv.background = WhitePixel(display, screen); |
||
774 | gcv.font = ctrlfont->fid; |
||
775 | gcv.subwindow_mode = ClipByChildren; |
||
776 | /* gcv.subwindow_mode = IncludeInferiors; */ |
||
777 | gc=XCreateGC(display, ctrlwindow, |
||
778 | GCForeground|GCBackground|GCFont|GCSubwindowMode, &gcv); |
||
779 | return gc; |
||
780 | } |
||
781 | |||
782 | |||
783 | /* |
||
784 | *-------------------------------------------------------------- |
||
785 | * |
||
786 | * GetStateButton -- |
||
787 | * |
||
788 | * Determines the window of the button associated with the |
||
789 | * import ctrlstate. |
||
790 | * |
||
791 | * Results: |
||
792 | * The associated window, if any; Otherwise 0. |
||
793 | * |
||
794 | * Side effects: |
||
795 | * None. |
||
796 | * |
||
797 | *-------------------------------------------------------------- |
||
798 | */ |
||
799 | |||
800 | #if __STDC__ |
||
801 | static Window GetStateButton(int ctrlstate) |
||
802 | #else |
||
803 | static Window GetStateButton(ctrlstate) |
||
804 | int ctrlstate; |
||
805 | #endif |
||
806 | { |
||
807 | switch(ctrlstate) { |
||
808 | case CTRL_REWIND: |
||
809 | return rewindwin; |
||
810 | case CTRL_PAUSE: |
||
811 | case CTRL_FFWD: |
||
812 | case CTRL_EOF: |
||
813 | return pausewin; |
||
814 | case CTRL_STEP: |
||
815 | return stepwin; |
||
816 | case CTRL_PLAY: |
||
817 | return playwin; |
||
818 | case CTRL_EXIT: |
||
819 | return exitwin; |
||
820 | default: |
||
821 | break; |
||
822 | } |
||
823 | return (Window)0; |
||
824 | } |
||
825 | |||
826 | |||
827 | /* |
||
828 | *-------------------------------------------------------------- |
||
829 | * |
||
830 | * DrawButton -- |
||
831 | * |
||
832 | * Calls the draw button function associated with the import |
||
833 | * window button. |
||
834 | * |
||
835 | * Results: |
||
836 | * None. |
||
837 | * |
||
838 | * Side effects: |
||
839 | * None. |
||
840 | * |
||
841 | *-------------------------------------------------------------- |
||
842 | */ |
||
843 | |||
844 | #if __STDC__ |
||
845 | static void DrawButton(Window button, GC gc, |
||
846 | Display *display, |
||
847 | VidStream **vid_stream, |
||
848 | int num) |
||
849 | #else |
||
850 | static void DrawButton(button,gc,display,vid_stream, num) |
||
851 | Window button; |
||
852 | GC gc; |
||
853 | Display *display; |
||
854 | VidStream **vid_stream; |
||
855 | int num; |
||
856 | #endif |
||
857 | { |
||
858 | if (button == frametotalwin) DrawFrameTotal(gc,vid_stream,display,num); |
||
859 | else if (button == rewindwin) DrawRewind(gc,display); |
||
860 | else if (button == pausewin) DrawPause(gc,display); |
||
861 | else if (button == stepwin) DrawStep(gc,display); |
||
862 | else if (button == playwin) DrawPlay(gc,display); |
||
863 | else if (button == loopwin) DrawLoop(gc,display); |
||
864 | else if (button == exitwin) DrawExit(gc,display); |
||
865 | else fprintf(stderr, "DrawButton called with unknown button\n"); |
||
866 | } |
||
867 | |||
868 | |||
869 | /* |
||
870 | * |
||
871 | * WindowSearch -- |
||
872 | * |
||
873 | * Search window id's to see if an expose event is on a display window |
||
874 | * |
||
875 | */ |
||
876 | #if __STDC__ |
||
877 | static int WindowSearch(XInfo *xinfo, Window win, int num) |
||
878 | #else |
||
879 | static int WindowSearch(xinfo, win, num) |
||
880 | XInfo *xinfo; |
||
881 | Window win; |
||
882 | int num; |
||
883 | #endif |
||
884 | { |
||
885 | int i; |
||
886 | |||
887 | for (i=0;(i<num) && (xinfo[i].window!=win);i++) { |
||
888 | } |
||
889 | if (i==num) return -1; |
||
890 | else return i; |
||
891 | } |
||
892 | |||
893 | |||
894 | /* |
||
895 | *-------------------------------------------------------------- |
||
896 | * |
||
897 | * ControlBar -- |
||
898 | * |
||
899 | * Checks XEvent queue for control commands. |
||
900 | * |
||
901 | * Results: |
||
902 | * Adjusts global variables ControlState, loopFlag as appropriate. |
||
903 | * |
||
904 | * Side effects: |
||
905 | * May adjust StopWatch state. |
||
906 | * |
||
907 | *-------------------------------------------------------------- |
||
908 | */ |
||
909 | |||
910 | void ControlBar(vid_stream,xinfo,numMovies) |
||
911 | VidStream **vid_stream; |
||
912 | XInfo *xinfo; |
||
913 | int numMovies; |
||
914 | { |
||
915 | GC gc; |
||
916 | int gcflag, winNum; |
||
917 | Window oldbutton, newbutton; |
||
918 | XEvent event; |
||
919 | static int LastState = CTRL_UNDEFINED; |
||
920 | Display *display=xinfo[0].display; |
||
921 | |||
922 | gcflag = 0; |
||
923 | |||
924 | /* Check to see if ControlState was modified outside this function, */ |
||
925 | /* and update control displays if it was. */ |
||
926 | if (LastState != ControlState) { |
||
927 | if (!gcflag) { |
||
928 | gc = CreateCtrlGC(display); |
||
929 | gcflag = 1; |
||
930 | } |
||
931 | if ((oldbutton = GetStateButton(LastState)) != (Window)NULL) { |
||
932 | XClearWindow(display, oldbutton); |
||
933 | DrawButton(oldbutton, gc, display, vid_stream, numMovies); |
||
934 | if (LastState == CTRL_EOF) { |
||
935 | XClearWindow(display, playwin); |
||
936 | DrawButton(playwin, gc, display, vid_stream, numMovies); |
||
937 | } |
||
938 | } |
||
939 | DrawButton(GetStateButton(LastState = ControlState), gc, |
||
940 | display, vid_stream, numMovies); |
||
941 | } |
||
942 | |||
943 | /* Process events, if any */ |
||
944 | if (XPending(display) < 1) { /* No events */ |
||
945 | if (gcflag) { |
||
946 | XFreeGC(display, gc); |
||
947 | } |
||
948 | LastState = ControlState; |
||
949 | return; |
||
950 | } |
||
951 | |||
952 | if (!gcflag) { |
||
953 | gc=CreateCtrlGC(display); |
||
954 | gcflag=1; |
||
955 | } |
||
956 | do { |
||
957 | XNextEvent(display, &event); |
||
958 | #ifdef HAVE_XFILTEREVENT /* Define if needed; Some older X's don't have this */ |
||
959 | if (XFilterEvent(&event, ctrlwindow)) continue; |
||
960 | #endif |
||
961 | switch(event.type) { |
||
962 | case ButtonPress: |
||
963 | /* Toggle Buttons */ |
||
964 | if (event.xbutton.window == loopwin) { |
||
965 | if (loopFlag) { |
||
966 | XClearWindow(display,loopwin); |
||
967 | loopFlag = 0; |
||
968 | } |
||
969 | else { |
||
970 | loopFlag = 1; |
||
971 | if (ControlState == CTRL_EOF && ControlMotion == CTRLMOTION_ON) { |
||
972 | ControlState = CTRL_REWIND; |
||
973 | DrawRewind(gc,display); |
||
974 | XClearWindow(display, playwin); |
||
975 | DrawPlay(gc,display); |
||
976 | XClearWindow(display, pausewin); |
||
977 | DrawPause(gc,display); |
||
978 | } |
||
979 | } |
||
980 | DrawLoop(gc,display); |
||
981 | break; |
||
982 | } |
||
983 | /* Click in display window */ |
||
984 | else if (WindowSearch(xinfo,event.xbutton.window,numMovies) != -1) { |
||
985 | if (ControlShow) { |
||
986 | ControlShow = CTRLBAR_OFF; |
||
987 | } else { |
||
988 | ControlShow = CTRLBAR_ON; |
||
989 | } |
||
990 | ShowHideControls(&xinfo[0]); |
||
991 | break; |
||
992 | } |
||
993 | /* ControlState buttons --- */ |
||
994 | /* Get currently selected button */ |
||
995 | oldbutton = GetStateButton(ControlState); |
||
996 | /* Update state */ |
||
997 | if (event.xbutton.window == pausewin) { |
||
998 | if ((ControlState == CTRL_EOF || ControlState == CTRL_FFWD) |
||
999 | && ControlMotion == CTRLMOTION_ON) { |
||
1000 | ControlMotion = CTRLMOTION_OFF; |
||
1001 | XClearWindow(display, playwin); |
||
1002 | DrawPlay(gc,display); |
||
1003 | } |
||
1004 | else if (ControlState == CTRL_PLAY) { |
||
1005 | ControlMotion = CTRLMOTION_OFF; |
||
1006 | ControlState = CTRL_PAUSE; |
||
1007 | } |
||
1008 | else if (ControlState == CTRL_PAUSE) { |
||
1009 | ControlMotion = CTRLMOTION_ON; |
||
1010 | ControlState = CTRL_PLAY; |
||
1011 | } |
||
1012 | } |
||
1013 | else if (event.xbutton.window == stepwin) { |
||
1014 | if (ControlState == CTRL_PAUSE || ControlState == CTRL_PLAY) |
||
1015 | ControlState = CTRL_STEP; |
||
1016 | else if (ControlState == CTRL_EOF && loopFlag) |
||
1017 | ControlState = CTRL_REWIND; |
||
1018 | ControlMotion = CTRLMOTION_OFF; |
||
1019 | } |
||
1020 | else if (event.xbutton.window == playwin) { |
||
1021 | ControlMotion = CTRLMOTION_ON; |
||
1022 | if (ControlState == CTRL_EOF) { |
||
1023 | if (loopFlag) { |
||
1024 | ControlState = CTRL_REWIND; |
||
1025 | } |
||
1026 | DrawButton(playwin, gc, display, vid_stream, numMovies); |
||
1027 | } |
||
1028 | else if (ControlState == CTRL_PAUSE) { |
||
1029 | ControlState = CTRL_PLAY; |
||
1030 | } |
||
1031 | } |
||
1032 | else if (event.xbutton.window == rewindwin) { |
||
1033 | ControlState = CTRL_REWIND; |
||
1034 | } |
||
1035 | else if (event.xbutton.window == exitwin) { |
||
1036 | ControlState = CTRL_EXIT; |
||
1037 | } |
||
1038 | /* Get newly selected button */ |
||
1039 | newbutton = GetStateButton(ControlState); |
||
1040 | if (LastState == ControlState) break; |
||
1041 | /* Adjust stopwatch */ |
||
1042 | if (LastState == CTRL_PLAY) |
||
1043 | StopWatch(STOPWATCH_STOP); /* Stop playing */ |
||
1044 | else if (ControlState == CTRL_PLAY) |
||
1045 | StopWatch(STOPWATCH_START); /* Start playing */ |
||
1046 | /* Update button display */ |
||
1047 | if (oldbutton != (Window)NULL) { |
||
1048 | XClearWindow(display,oldbutton); |
||
1049 | DrawButton(oldbutton,gc,display,vid_stream,numMovies); |
||
1050 | } |
||
1051 | DrawButton(newbutton,gc,display,vid_stream,numMovies); |
||
1052 | break; |
||
1053 | case ClientMessage: |
||
1054 | if (event.xclient.message_type != protocol_atom || |
||
1055 | event.xclient.data.l[0] != delete_atom || |
||
1056 | event.xclient.format != 32) break; /* Not WM_DELETE_WINDOW */ |
||
1057 | /* Otherwise drop through to DestroyNotify */ |
||
1058 | case DestroyNotify: |
||
1059 | ControlState=CTRL_EXIT; |
||
1060 | break; |
||
1061 | case Expose: |
||
1062 | if (event.xexpose.count > 0) { |
||
1063 | break; /* Wait for last expose event */ |
||
1064 | } |
||
1065 | if ((winNum= |
||
1066 | WindowSearch(xinfo,event.xexpose.window, numMovies)) != -1) { |
||
1067 | if ( vid_stream[winNum]->current != NULL) { |
||
1068 | ExecuteDisplay(vid_stream[winNum],0,&xinfo[winNum]); |
||
1069 | } |
||
1070 | } |
||
1071 | else { |
||
1072 | DrawButton(event.xexpose.window,gc,display,vid_stream,numMovies); |
||
1073 | } |
||
1074 | break; |
||
1075 | default: |
||
1076 | break; |
||
1077 | } |
||
1078 | } while (XPending(display) > 0); |
||
1079 | if (gcflag) { |
||
1080 | XFreeGC(display, gc); |
||
1081 | } |
||
1082 | LastState = ControlState; |
||
1083 | } |
||
1084 | |||
1085 | |||
1086 | /* |
||
1087 | *-------------------------------------------------------------- |
||
1088 | * |
||
1089 | * ControlLoop -- |
||
1090 | * |
||
1091 | * Main control loop. Intermixes video processing (as |
||
1092 | * determined by ControlState) with user input. |
||
1093 | * |
||
1094 | * Results: |
||
1095 | * None. |
||
1096 | * |
||
1097 | * Side effects: |
||
1098 | * Adjusts StopWatch state, totNumFrames, ControlState. |
||
1099 | * May also reset video state. |
||
1100 | * |
||
1101 | *-------------------------------------------------------------- |
||
1102 | */ |
||
1103 | |||
1104 | void ControlLoop(vid_stream,xinfo,numStreams) |
||
1105 | VidStream **vid_stream; |
||
1106 | XInfo *xinfo; |
||
1107 | int numStreams; |
||
1108 | { |
||
1109 | int itemp, i, allMovies; |
||
1110 | XEvent event; |
||
1111 | Display *display=xinfo[0].display; |
||
1112 | |||
1113 | for (i=0;(display==NULL) && (i<numStreams); i++) { |
||
1114 | display=xinfo[i].display; |
||
1115 | } |
||
1116 | |||
1117 | if (!ctrl_init) { |
||
1118 | fprintf(stderr,"ControlLoop() accessed without initialization\n"); |
||
1119 | exit(1); |
||
1120 | } |
||
1121 | StopWatch(STOPWATCH_RESET); |
||
1122 | TotalFrameCount = 0; |
||
1123 | StopWatch(STOPWATCH_START); |
||
1124 | |||
1125 | for (i=0;i<numStreams;i++) { |
||
1126 | itemp = vid_stream[i]->totNumFrames; |
||
1127 | while (vid_stream[i]->totNumFrames == itemp) |
||
1128 | mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]); /* Advance to 1st frame */ |
||
1129 | } |
||
1130 | if (startFrame > vid_stream[0]->totNumFrames) { |
||
1131 | ControlState = CTRL_FFWD; |
||
1132 | ControlMotion = CTRLMOTION_OFF; |
||
1133 | StopWatch(STOPWATCH_STOP); |
||
1134 | } |
||
1135 | else if (ControlShow != CTRLBAR_ON || noDisplayFlag) { |
||
1136 | ControlState = CTRL_PLAY; |
||
1137 | ControlMotion = CTRLMOTION_ON; |
||
1138 | } |
||
1139 | else { |
||
1140 | ControlState = INITIAL_STATE; |
||
1141 | ControlMotion = CTRLMOTION_OFF; |
||
1142 | if (ControlState == CTRL_PAUSE) { |
||
1143 | StopWatch(STOPWATCH_STOP); |
||
1144 | } else { |
||
1145 | StopWatch(STOPWATCH_START); |
||
1146 | } |
||
1147 | } |
||
1148 | |||
1149 | while (1) { |
||
1150 | ControlBar(vid_stream,&xinfo[0],numStreams); |
||
1151 | if (ControlState == CTRL_PAUSE || ControlState == CTRL_EOF) { |
||
1152 | XPeekEvent(display, &event); /* Block until user input */ |
||
1153 | } |
||
1154 | else { |
||
1155 | switch(ControlState) { |
||
1156 | case CTRL_PLAY: |
||
1157 | allMovies=1; |
||
1158 | for (i=0;i<numStreams;i++) { |
||
1159 | /* If Film end reached, don't play frames */ |
||
1160 | if ((vid_stream[i]!=NULL) && (!vid_stream[i]->film_has_ended)) { |
||
1161 | itemp = vid_stream[i]->totNumFrames; /* Advance 1 frame */ |
||
1162 | while (vid_stream[i]->totNumFrames == itemp) { |
||
1163 | mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]); |
||
1164 | } |
||
1165 | allMovies=allMovies && (vid_stream[i]->film_has_ended); |
||
1166 | } |
||
1167 | } |
||
1168 | if (allMovies) { /* Film end reached for all movies*/ |
||
1169 | StopWatch(STOPWATCH_STOP); |
||
1170 | XSync(display, FALSE); /* Kludge to update frametotalwin */ |
||
1171 | if (loopFlag) { |
||
1172 | ControlState = CTRL_REWIND; |
||
1173 | } |
||
1174 | else { |
||
1175 | ControlState = CTRL_EOF; |
||
1176 | } |
||
1177 | } |
||
1178 | break; |
||
1179 | case CTRL_FFWD: |
||
1180 | allMovies=1; |
||
1181 | for (i=0;i<numStreams;i++) { |
||
1182 | if (vid_stream[i]!=NULL) { |
||
1183 | mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]); |
||
1184 | allMovies=allMovies && vid_stream[i]->film_has_ended; |
||
1185 | } |
||
1186 | } |
||
1187 | for (i=0;(i<numStreams) && ((vid_stream[i]==NULL) |
||
1188 | || (startFrame <= vid_stream[i]->totNumFrames));i++) { |
||
1189 | ; |
||
1190 | } |
||
1191 | if (i==numStreams) { |
||
1192 | if (ControlMotion == CTRLMOTION_ON) { |
||
1193 | ControlState = CTRL_PLAY; |
||
1194 | StopWatch(STOPWATCH_START); |
||
1195 | } else { |
||
1196 | ControlState = CTRL_PAUSE; |
||
1197 | } |
||
1198 | } |
||
1199 | |||
1200 | /* Film end just reached---Degenerate case */ |
||
1201 | if (allMovies) { |
||
1202 | StopWatch(STOPWATCH_STOP); |
||
1203 | if (loopFlag) { |
||
1204 | ControlState = CTRL_REWIND; |
||
1205 | } |
||
1206 | else { |
||
1207 | ControlState = CTRL_EOF; |
||
1208 | } |
||
1209 | } |
||
1210 | break; |
||
1211 | case CTRL_EOF: |
||
1212 | if (loopFlag) { |
||
1213 | ControlState = CTRL_REWIND; |
||
1214 | } |
||
1215 | break; |
||
1216 | case CTRL_STEP: |
||
1217 | StopWatch(STOPWATCH_START); |
||
1218 | allMovies=1; |
||
1219 | for (i=0;i<numStreams;i++) { |
||
1220 | if ((vid_stream[i]!=NULL) && !vid_stream[i]->film_has_ended) { |
||
1221 | itemp = vid_stream[i]->totNumFrames; /* Advance 1 frame */ |
||
1222 | while (vid_stream[i]->totNumFrames == itemp) { |
||
1223 | mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]); |
||
1224 | } |
||
1225 | allMovies=allMovies && vid_stream[i]->film_has_ended; |
||
1226 | } |
||
1227 | } |
||
1228 | StopWatch(STOPWATCH_STOP); |
||
1229 | ControlState = CTRLMOTION_OFF; |
||
1230 | /* Film end just reached for last ending movie */ |
||
1231 | if (allMovies) |
||
1232 | ControlState = CTRL_EOF; |
||
1233 | else |
||
1234 | ControlState = CTRL_PAUSE; |
||
1235 | break; |
||
1236 | case CTRL_REWIND: |
||
1237 | StopWatch(STOPWATCH_STOP); |
||
1238 | for (i=0;i<numStreams;i++) { |
||
1239 | rewind(vid_stream[i]->input); |
||
1240 | } |
||
1241 | ControlBar(vid_stream, &xinfo[0], numStreams); |
||
1242 | for (i=0;i<numStreams;i++) { |
||
1243 | if (vid_stream[i]!=NULL) { |
||
1244 | ResetVidStream(vid_stream[i]);/* Reinitialize vid_stream pointers */ |
||
1245 | if (vid_stream[i]->seekValue < 0) { |
||
1246 | vid_stream[i]->seekValue = 0 - vid_stream[i]->seekValue; |
||
1247 | } |
||
1248 | } |
||
1249 | } |
||
1250 | for (i=0; i<numStreams; i++) { |
||
1251 | if (vid_stream[i] != NULL) { |
||
1252 | /* Process start codes */ |
||
1253 | mpegVidRsrc(0, vid_stream[i], 1, &xinfo[i]); |
||
1254 | } |
||
1255 | } |
||
1256 | if (startFrame > 0) { |
||
1257 | ControlState = CTRL_FFWD; |
||
1258 | } |
||
1259 | else { |
||
1260 | /* Do 1st frame */ |
||
1261 | for (i=0;i<numStreams;i++) { |
||
1262 | if (vid_stream[i] != NULL) { |
||
1263 | vid_stream[i]->realTimeStart = ReadSysClock(); |
||
1264 | while (vid_stream[i]->totNumFrames == 0) { |
||
1265 | mpegVidRsrc(0, vid_stream[i], 0, &xinfo[i]); |
||
1266 | } |
||
1267 | } |
||
1268 | } |
||
1269 | /* Time like original pass */ |
||
1270 | StopWatch(STOPWATCH_START); |
||
1271 | |||
1272 | if (ControlMotion == CTRLMOTION_ON) { |
||
1273 | ControlState = CTRL_PLAY; |
||
1274 | } else { |
||
1275 | ControlState = CTRL_PAUSE; |
||
1276 | StopWatch(STOPWATCH_STOP); |
||
1277 | } |
||
1278 | } |
||
1279 | break; |
||
1280 | case CTRL_EXIT: |
||
1281 | if (ctrlfont != NULL) { |
||
1282 | XFreeFont(display, ctrlfont); |
||
1283 | } |
||
1284 | XDestroyWindow(display, ctrlwindow); |
||
1285 | return; |
||
1286 | default: |
||
1287 | fprintf(stderr,"Code error: Illegal control state: %d (main())", |
||
1288 | ControlState); |
||
1289 | exit(1); |
||
1290 | break; |
||
1291 | } |
||
1292 | } |
||
1293 | } |
||
1294 | } |
||
1295 | #endif /* !NOCONTROLS */ |