Subversion Repositories shark

Rev

Rev 2 | Details | Compare with Previous | 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(&current, (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(&current,(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 */