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
StopWatch(action)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__
GetWindowOrigins(XInfo * xinfo,int * xclient,int * yclient,int * xwhole,int * ywhole)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
WindowMapped(dsp,xev,window)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
IfEventType(dsp,xev,type)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__
ShowHideControls(XInfo * xinfo)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 */
MakeControlBar(xinfo)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__
WriteCenteredText(Window win,GC gc,int winwidth,int winheight,char * str,Display * display)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__
ExposeWindow(Window win,Display * display)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__
NormalColors(GC gc,Display * display)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__
InvertColors(GC gc,Display * display)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__
DrawRewind(GC gc,Display * display)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__
DrawPause(GC gc,Display * display)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__
DrawStep(GC gc,Display * display)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__
DrawPlay(GC gc,Display * display)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__
DrawLoop(GC gc,Display * display)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__
DrawExit(GC gc,Display * display)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
UpdateFrameTotal(display)704 void UpdateFrameTotal(display)
705 Display *display;
706 {
707 if (!ctrl_init) {
708 return;
709 }
710 ExposeWindow(frametotalwin,display);
711 }
712
UpdateControlDisplay(display)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__
DrawFrameTotal(GC gc,VidStream ** vid_stream,Display * display,int numMovies)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__
CreateCtrlGC(Display * display)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__
GetStateButton(int ctrlstate)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__
DrawButton(Window button,GC gc,Display * display,VidStream ** vid_stream,int num)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__
WindowSearch(XInfo * xinfo,Window win,int num)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
ControlBar(vid_stream,xinfo,numMovies)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
ControlLoop(vid_stream,xinfo,numStreams)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 */
1296