about summary refs log tree commit diff
path: root/converter/other/fiasco/buttons.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/other/fiasco/buttons.c')
-rw-r--r--converter/other/fiasco/buttons.c510
1 files changed, 510 insertions, 0 deletions
diff --git a/converter/other/fiasco/buttons.c b/converter/other/fiasco/buttons.c
new file mode 100644
index 00000000..82ed18cd
--- /dev/null
+++ b/converter/other/fiasco/buttons.c
@@ -0,0 +1,510 @@
+/*
+ *  buttons.c:		Draw MWFA player buttons in X11 window	
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/15 17:23:11 $
+ *  $Author: hafner $
+ *  $Revision: 5.2 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#ifndef X_DISPLAY_MISSING
+
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+
+#if STDC_HEADERS
+#	include <stdlib.h>
+#endif /* not STDC_HEADERS */
+
+#include "types.h"
+#include "macros.h"
+
+#include "display.h"
+#include "binerror.h"
+#include "buttons.h"
+
+/*****************************************************************************
+
+			     local variables
+  
+*****************************************************************************/
+
+static const int EVENT_MASK = (KeyPressMask | ButtonPressMask |
+			       ButtonReleaseMask | ExposureMask);
+
+/*****************************************************************************
+
+				prototypes
+  
+*****************************************************************************/
+
+static void
+draw_progress_bar (x11_info_t *xinfo, binfo_t *binfo, unsigned n,
+		   unsigned n_frames);
+static void
+draw_button (x11_info_t *xinfo, binfo_t *binfo,
+	     buttons_t button, bool_t pressed);
+static void
+draw_control_panel (x11_info_t *xinfo, binfo_t *binfo,
+		    unsigned n, unsigned n_frames);
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+binfo_t * 
+init_buttons (x11_info_t *xinfo, unsigned n, unsigned n_frames,
+	      unsigned buttons_height, unsigned progbar_height)
+/*
+ *  Initialize a toolbar with the typical collection of video player
+ *  buttons (pause, play, record, next, etc.) in the window given by 'xinfo'.
+ *  'n' gives the current frame, 'whereas' n_frames is the total number of
+ *  frames of the video stream.
+ *  The size of the button toolbar is given by 'buttons_height',
+ *  the size of the progressbar is given by 'progbar_height'.
+ *
+ *  Return value:
+ *	struct managing the toolbar and progressbar information
+ */
+{
+   XGCValues  values;
+   XEvent     event;
+   Colormap   cmap;
+   XColor     gray, dgray, lgray, red;
+   XColor     graye, dgraye, lgraye, rede;
+   buttons_t  button;			/* counter */
+   binfo_t   *binfo = calloc (1, sizeof (binfo_t));
+
+   if (!binfo)
+      error ("Out of memory.");
+   
+   binfo->width            = xinfo->ximage->width;
+   binfo->height           = buttons_height;
+   binfo->progbar_height   = progbar_height;
+   binfo->record_is_rewind = NO;
+
+   /*
+    *  Generate sub-window for control panel
+    */
+   binfo->window = XCreateSimpleWindow (xinfo->display, xinfo->window,
+					0, xinfo->ximage->height,
+					binfo->width, binfo->height, 0,
+					BlackPixel (xinfo->display,
+						    xinfo->screen),
+					WhitePixel (xinfo->display,
+						    xinfo->screen));
+   XSelectInput(xinfo->display, binfo->window, StructureNotifyMask);
+   XMapWindow (xinfo->display, binfo->window);
+   do
+   {
+      XNextEvent (xinfo->display, &event);
+   }
+   while (event.type != MapNotify || event.xmap.event != binfo->window);
+   XSelectInput (xinfo->display, binfo->window, EVENT_MASK);
+
+   /*
+    *  Generate graphic contexts for different colors.
+    */
+   cmap = DefaultColormap (xinfo->display, xinfo->screen);
+   XAllocNamedColor (xinfo->display, cmap, "#404040", &dgray, &dgraye);
+   XAllocNamedColor (xinfo->display, cmap, "white", &lgray, &lgraye);
+   XAllocNamedColor (xinfo->display, cmap, "#a8a8a8", &gray, &graye);
+   XAllocNamedColor (xinfo->display, cmap, "red", &red, &rede);
+   
+   values.foreground = BlackPixel (xinfo->display, xinfo->screen);
+   values.background = WhitePixel (xinfo->display, xinfo->screen);
+   binfo->gc [BLACK] = XCreateGC (xinfo->display,
+				  RootWindow (xinfo->display, xinfo->screen),
+				  (GCForeground | GCBackground), &values);
+   values.foreground = BlackPixel (xinfo->display, xinfo->screen);
+   values.background = WhitePixel (xinfo->display, xinfo->screen);
+   values.line_width = 3;
+   values.join_style = JoinRound;
+   binfo->gc [THICKBLACK] = XCreateGC (xinfo->display,
+				       RootWindow (xinfo->display,
+						   xinfo->screen),
+				       (GCForeground | GCBackground
+					| GCLineWidth | GCJoinStyle), &values);
+   values.foreground = gray.pixel;
+   values.background = WhitePixel (xinfo->display, xinfo->screen);
+   binfo->gc [NGRAY] = XCreateGC (xinfo->display,
+				  RootWindow (xinfo->display, xinfo->screen),
+				  (GCForeground | GCBackground), &values);
+   values.foreground = lgray.pixel;
+   values.background = WhitePixel (xinfo->display, xinfo->screen);
+   binfo->gc [LGRAY] = XCreateGC (xinfo->display,
+				  RootWindow (xinfo->display, xinfo->screen),
+				  (GCForeground | GCBackground), &values);
+   values.foreground = dgray.pixel;
+   values.background = WhitePixel (xinfo->display, xinfo->screen);
+   binfo->gc [DGRAY] = XCreateGC (xinfo->display,
+				  RootWindow (xinfo->display, xinfo->screen),
+				  (GCForeground | GCBackground), &values);
+   values.foreground = red.pixel;
+   values.background = WhitePixel (xinfo->display, xinfo->screen);
+   binfo->gc [RED]   = XCreateGC (xinfo->display,
+				  RootWindow (xinfo->display, xinfo->screen),
+				  (GCForeground | GCBackground), &values);
+
+   for (button = 0; button < NO_BUTTON; button++)
+      binfo->pressed [button] = NO;
+
+   draw_control_panel (xinfo, binfo, n, n_frames); 
+   
+   return binfo;
+}
+
+void
+wait_for_input (x11_info_t *xinfo)
+/*
+ *  Wait for key press or mouse click in window 'xinfo'.
+ *  Redraw 'image' if event other then ButtonPress or KeyPress occurs.
+ *  Enlarge or reduce size of image by factor 2^'enlarge_factor'.
+ *
+ *  No return value.
+ *
+ *  Side effect:
+ *	program is terminated after key press or mouse click.
+ */
+{
+   bool_t leave_loop = NO;
+   
+   XSelectInput (xinfo->display, xinfo->window, EVENT_MASK);
+
+   while (!leave_loop)
+   {
+      XEvent event;
+
+      XMaskEvent (xinfo->display, EVENT_MASK, &event);
+      switch (event.type)
+      {
+	 case ButtonPress:
+	 case KeyPress:
+	    leave_loop = YES;
+	    break;
+	 default:
+	    display_image (0, 0, xinfo);
+	    break;
+      }
+   }
+}
+
+void
+check_events (x11_info_t *xinfo, binfo_t *binfo, unsigned n, unsigned n_frames)
+/*
+ *  Check the X11 event loop. If the PAUSE buttonin the of panel 'binfo'
+ *  is activated wait until next event occurs.
+ *  Redraw 'image' if event other then ButtonPress or ButtonRelease occurs.
+ *  Enlarge or reduce size of image by factor 2^'enlarge_factor'.
+ *  'n' gives the current frame, 'whereas' n_frames is the total number of
+ *  frames of the video stream.
+ *
+ *  No return values.
+ *
+ *  Side effects:
+ *	status of buttons (binfo->pressed [button]) is changed accordingly.
+ */
+{
+   bool_t leave_eventloop;
+
+   leave_eventloop = (!binfo->pressed [PAUSE_BUTTON]
+		      && binfo->pressed [PLAY_BUTTON])
+		     || (!binfo->pressed [PAUSE_BUTTON]
+			 && binfo->record_is_rewind
+			 && binfo->pressed [RECORD_BUTTON])
+		     || binfo->pressed [RECORD_BUTTON];
+   draw_progress_bar (xinfo, binfo, n, n_frames);
+
+   if (binfo->pressed [PAUSE_BUTTON] && binfo->pressed [PLAY_BUTTON])
+   {
+      XFlush (xinfo->display);
+      draw_button (xinfo, binfo, PLAY_BUTTON, NO); /* clear PLAY mode */
+      XFlush (xinfo->display);
+   }
+   if (binfo->pressed [PAUSE_BUTTON]
+       && binfo->record_is_rewind && binfo->pressed [RECORD_BUTTON])
+   {
+      XFlush (xinfo->display);
+      draw_button (xinfo, binfo, RECORD_BUTTON, NO); /* clear PLAY mode */
+      XFlush (xinfo->display);
+   }
+
+   if (binfo->pressed [STOP_BUTTON])
+   {
+      XFlush (xinfo->display);
+      draw_button (xinfo, binfo, STOP_BUTTON, NO); /* clear STOP button */
+      XFlush (xinfo->display);
+   }
+
+   do
+   {
+      XEvent event;
+      int    button;
+      bool_t wait_release = NO;
+	 
+      
+      if (XCheckMaskEvent (xinfo->display, EVENT_MASK, &event))
+      {
+	 switch (event.type)
+	 {
+	    case ButtonPress:
+	       wait_release = NO;
+	       if (!(binfo->pressed [RECORD_BUTTON] &&
+		     !binfo->record_is_rewind))
+		  for (button = 0; button < NO_BUTTON; button++)
+		  {
+		     int x0, y0, x1, y1; /* button coordinates */
+		  
+		     x0 = button * (binfo->width / NO_BUTTON);
+		     y0 = binfo->progbar_height;
+		     x1 = x0 + binfo->width / NO_BUTTON;
+		     y1 = y0 + binfo->height - binfo->progbar_height - 1;
+		     if (event.xbutton.x > x0 && event.xbutton.x < x1
+			 && event.xbutton.y > y0 && event.xbutton.y < y1) 
+		     {
+			draw_button (xinfo, binfo, button,
+				     !binfo->pressed [button]);
+			wait_release = YES;
+			break;
+		     }
+		  }
+	       break;
+	    case ButtonRelease:
+	       wait_release = NO;
+	       break;
+	    default:
+	       wait_release = NO;
+	       draw_control_panel (xinfo, binfo, n, n_frames);
+	       display_image (0, 0, xinfo);
+	       break;
+	 }
+	 leave_eventloop = !wait_release
+			   && (binfo->pressed [PLAY_BUTTON]
+			       || binfo->pressed [STOP_BUTTON]
+			       || binfo->pressed [RECORD_BUTTON]
+			       || binfo->pressed [QUIT_BUTTON]);
+      }
+   } while (!leave_eventloop);
+
+   if ((binfo->pressed [RECORD_BUTTON] && !binfo->record_is_rewind)
+       && n == n_frames - 1)
+   {
+      binfo->record_is_rewind = YES;
+      draw_button (xinfo, binfo, RECORD_BUTTON, NO);
+   }
+}
+
+/*****************************************************************************
+
+				private code
+  
+*****************************************************************************/
+
+static void
+draw_control_panel (x11_info_t *xinfo, binfo_t *binfo,
+		    unsigned n, unsigned n_frames)
+/*
+ *  Draw control panel 'binfo' with all buttons and progressbar in
+ *  the given 'window'.
+ *  'n' gives the current frame, 'whereas' n_frames is the total number of
+ *  frames of the video stream.
+ *
+ *  No return value.
+ */
+{
+   buttons_t button;
+   
+   XFillRectangle (xinfo->display, binfo->window, binfo->gc [NGRAY],
+		   0, 0, binfo->width, binfo->height);
+   draw_progress_bar (xinfo, binfo, n, n_frames);
+   for (button = 0; button < NO_BUTTON; button++)
+      draw_button (xinfo, binfo, button, binfo->pressed [button]);
+}
+
+static void
+draw_progress_bar (x11_info_t *xinfo, binfo_t *binfo, unsigned n,
+		   unsigned n_frames)
+/*
+ *  Draw progressbar of control panel 'binfo' in the given 'window'.
+ *  'n' gives the current frame, whereas 'n_frames' is the total number of
+ *  frames of the video stream.
+ *
+ *  No return value.
+ */
+{
+   unsigned x, y, width, height;
+
+   x 	  = 2;
+   y 	  = 1;
+   width  = binfo->width - 5;
+   height = binfo->progbar_height - 3;
+   
+   XDrawLine (xinfo->display, binfo->window, binfo->gc [DGRAY],
+	      x, y, x + width, y);
+   XDrawLine (xinfo->display, binfo->window, binfo->gc [DGRAY],
+	      x, y, x, y + height - 1);
+   XDrawLine (xinfo->display, binfo->window, binfo->gc [LGRAY],
+	      x + width, y + 1, x + width, y + height);
+   XDrawLine (xinfo->display, binfo->window, binfo->gc [LGRAY],
+	      x, y + height, x + width, y + height);
+
+   x++; y++; width  -= 2; height -= 2;
+   XFillRectangle (xinfo->display, binfo->window, binfo->gc [NGRAY],
+		   x, y, width, height);
+
+   XFillRectangle (xinfo->display, binfo->window, binfo->gc [BLACK],
+		   x + n * max (1, width / n_frames), y,
+		   max (1, width / n_frames), height);
+}
+
+static void
+draw_button (x11_info_t *xinfo, binfo_t *binfo,
+	     buttons_t button, bool_t pressed)
+/*
+ *  Draw 'button' of control panel 'binfo' in the given 'window'.
+ *  'pressed' indicates whether the button is pressed or not.
+ *
+ *  No return value.
+ */
+{
+   grayscale_t top, bottom;		/* index of GC */
+   unsigned    x, y, width, height;	/* coordinates of button */
+   
+   x 	  = button * (binfo->width / NO_BUTTON);
+   y 	  = binfo->progbar_height;
+   width  = binfo->width / NO_BUTTON;
+   height = binfo->height - binfo->progbar_height - 1;
+   
+   if (width < 4 || height < 4)
+      return;
+   
+   if (pressed)
+   {
+      top    = DGRAY;
+      bottom = LGRAY;
+   }
+   else
+   {
+      top    = LGRAY;
+      bottom = DGRAY;
+   }
+
+   x 	 += 2;
+   width -= 4;
+   
+   XDrawLine (xinfo->display, binfo->window, binfo->gc [top],
+	      x, y, x + width, y);
+   XDrawLine (xinfo->display, binfo->window, binfo->gc [top],
+	      x, y, x, y + height - 1);
+   XDrawLine (xinfo->display, binfo->window, binfo->gc [bottom],
+	      x + width, y + 1, x + width, y + height);
+   XDrawLine (xinfo->display, binfo->window, binfo->gc [bottom],
+	      x, y + height, x + width, y + height);
+
+   x++; y++; width  -= 2; height -= 2;
+   XFillRectangle (xinfo->display, binfo->window, binfo->gc [NGRAY],
+		   x, y, width, height);
+
+   switch (button)
+   {
+      case STOP_BUTTON:
+	 XFillRectangle (xinfo->display, binfo->window, binfo->gc [BLACK],
+			 x + width / 2 - 6, y + height / 2 - 4, 11, 11);
+	 if (pressed && !binfo->pressed [STOP_BUTTON])
+	 {
+	    draw_button (xinfo, binfo, PLAY_BUTTON, NO);
+	    draw_button (xinfo, binfo, PAUSE_BUTTON, NO); 
+	    draw_button (xinfo, binfo, RECORD_BUTTON, NO); 
+	 }
+	 break;
+      case PAUSE_BUTTON:
+	 XFillRectangle (xinfo->display, binfo->window, binfo->gc [BLACK],
+			 x + width / 2 - 6, y + height / 2 - 4, 5, 11);
+	 XFillRectangle (xinfo->display, binfo->window, binfo->gc [BLACK],
+			 x + width / 2 + 1, y + height / 2 - 4, 5, 11);
+	 break;
+      case PLAY_BUTTON:
+	 {
+	    XPoint triangle [3];
+
+	    triangle [0].x = x + width / 2 - 5;
+	    triangle [0].y = y + height / 2 - 5;
+	    triangle [1].x = 10;
+	    triangle [1].y = 6;
+	    triangle [2].x = -10;
+	    triangle [2].y = 6;
+
+	    XFillPolygon (xinfo->display, binfo->window, binfo->gc [BLACK],
+			  triangle, 3, Convex, CoordModePrevious);
+	    if (pressed && !binfo->pressed [PLAY_BUTTON]
+		&& binfo->pressed [RECORD_BUTTON])
+	       draw_button (xinfo, binfo, RECORD_BUTTON, NO);
+	 }
+	 break;
+      case RECORD_BUTTON:
+	 if (!binfo->record_is_rewind)
+	 {
+	    XFillArc (xinfo->display, binfo->window, binfo->gc [RED],
+		      x + width / 2 - 5, y + height / 2 - 5, 11, 11, 0,
+		      360 * 64);
+	    if (pressed && !binfo->pressed [RECORD_BUTTON])
+	    {
+	       draw_button (xinfo, binfo, STOP_BUTTON, YES);
+	       draw_button (xinfo, binfo, PLAY_BUTTON, NO);
+	       draw_button (xinfo, binfo, PAUSE_BUTTON, NO); 
+	    }
+	 }
+	 else
+	 {
+	    XPoint triangle [3];
+
+	    triangle [0].x = x + width / 2 + 5;
+	    triangle [0].y = y + height / 2 - 5;
+	    triangle [1].x = -10;
+	    triangle [1].y = 6;
+	    triangle [2].x = 10;
+	    triangle [2].y = 6;
+
+	    XFillPolygon (xinfo->display, binfo->window, binfo->gc [BLACK],
+			  triangle, 3, Convex, CoordModePrevious);
+	    if (pressed && !binfo->pressed [RECORD_BUTTON]
+		&& binfo->pressed [PLAY_BUTTON])
+	       draw_button (xinfo, binfo, PLAY_BUTTON, NO);
+	 }
+	 break;
+      case QUIT_BUTTON:
+	 {
+	    XPoint triangle [3];
+
+	    triangle [0].x = x + width / 2 - 6;
+	    triangle [0].y = y + height / 2 + 2;
+	    triangle [1].x = 6;
+	    triangle [1].y = -7;
+	    triangle [2].x = 6;
+	    triangle [2].y = 7;
+
+	    XFillPolygon (xinfo->display, binfo->window, binfo->gc [BLACK],
+			  triangle, 3, Convex, CoordModePrevious);
+	    XFillRectangle (xinfo->display, binfo->window, binfo->gc [BLACK],
+			    x + width / 2 - 5, y + height / 2 + 4, 11, 3);
+	 }
+	 break;
+      default:
+	 break;
+   }
+   binfo->pressed [button] = pressed;
+}
+
+#endif /* not X_DISPLAY_MISSING */