Logo Search packages:      
Sourcecode: e16 version File versions  Download package

fx.c

/*
 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies of the Software, its documentation and marketing & publicity
 * materials, and acknowledgment shall be given in the documentation, materials
 * and software packages that this Software was used.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "E.h"
#include "desktops.h"
#include "dialog.h"
#include "eimage.h"
#include "emodule.h"
#include "settings.h"
#include "timers.h"
#include "xwin.h"
#include <math.h>

/* FIXME - Needs cleaning up */

#ifndef M_PI_2
#define M_PI_2 (3.141592654 / 2)
#endif

#define FX_OP_START  1
#define FX_OP_STOP   2
#define FX_OP_TOGGLE 3

typedef struct
{
   const char         *name;
   void                (*init_func) (const char *name);
   void                (*desk_func) (void);
   void                (*quit_func) (void);
   void                (*pause_func) (void);
   char                enabled;
   char                paused;
}
FXHandler;

/****************************** RIPPLES *************************************/

#define fx_ripple_waterh 64
static Pixmap       fx_ripple_above = None;
static Win          fx_ripple_win = NoWin;
static int          fx_ripple_count = 0;

static void
FX_ripple_timeout(int val __UNUSED__, void *data __UNUSED__)
{
   static double       incv = 0, inch = 0;
   static GC           gc1 = 0, gc = 0;
   int                 y;

   if (fx_ripple_above == None)
     {
      XGCValues           gcv;

      fx_ripple_win = DeskGetBackgroundWin(DesksGetCurrent());

      fx_ripple_above =
         ECreatePixmap(fx_ripple_win, VRoot.w, fx_ripple_waterh * 2, 0);
      if (gc)
         EXFreeGC(gc);
      if (gc1)
         EXFreeGC(gc1);
      gcv.subwindow_mode = IncludeInferiors;
      gc = EXCreateGC(WinGetXwin(fx_ripple_win), GCSubwindowMode, &gcv);
      gc1 = EXCreateGC(WinGetXwin(fx_ripple_win), 0L, &gcv);
     }

   if (fx_ripple_count == 0)
      XCopyArea(disp, EoGetXwin(DesksGetCurrent()), fx_ripple_above, gc, 0,
            VRoot.h - (fx_ripple_waterh * 3), VRoot.w, fx_ripple_waterh * 2,
            0, 0);

   fx_ripple_count++;
   if (fx_ripple_count > 32)
      fx_ripple_count = 0;
   incv += 0.40;
   if (incv > (M_PI_2 * 4))
     {
      incv = 0;
     }
   inch += 0.32;
   if (inch > (M_PI_2 * 4))
     {
      inch = 0;
     }
   for (y = 0; y < fx_ripple_waterh; y++)
     {
      double              aa, a, p;
      int                 yoff, off, yy;

      p = (((double)(fx_ripple_waterh - y)) / ((double)fx_ripple_waterh));
      a = p * p * 48 + incv;
      yoff = y + (int)(sin(a) * 7) + 1;
      yy = (fx_ripple_waterh * 2) - yoff;
      aa = p * p * 64 + inch;
      off = (int)(sin(aa) * 10 * (1 - p));
      XCopyArea(disp, fx_ripple_above, WinGetXwin(fx_ripple_win), gc1, 0, yy,
              VRoot.w, 1, off, VRoot.h - fx_ripple_waterh + y);
     }
   DoIn("FX_RIPPLE_TIMEOUT", 0.066, FX_ripple_timeout, 0, NULL);
}

static void
FX_Ripple_Init(const char *name __UNUSED__)
{
   fx_ripple_count = 0;
   DoIn("FX_RIPPLE_TIMEOUT", 0.066, FX_ripple_timeout, 0, NULL);
}

static void
FX_Ripple_Desk(void)
{
   if (fx_ripple_above != None)
      EFreePixmap(fx_ripple_above);
   fx_ripple_count = 0;
   fx_ripple_above = None;
}

static void
FX_Ripple_Quit(void)
{
   RemoveTimerEvent("FX_RIPPLE_TIMEOUT");
   EClearArea(fx_ripple_win, 0, VRoot.h - fx_ripple_waterh, VRoot.w,
            fx_ripple_waterh, False);
}

static void
FX_Ripple_Pause(void)
{
   static char         paused = 0;

   if (!paused)
     {
      FX_Ripple_Quit();
      paused = 1;
     }
   else
     {
      FX_Ripple_Init(NULL);
      paused = 0;
     }
}

#ifdef E_FX_RAINDROPS         /* FIXME - Requires eliminating use of PixImg */

/****************************** RAIN DROPS **********************************/

#define fx_raindrop_size 96
#define fx_raindrop_size2 (fx_raindrop_size / 2)
#define fx_raindrop_duration 32
#define fx_frequency 4
#define fx_amplitude 48
static Window       fx_raindrops_win = None;
static int          fx_raindrops_number = 4;
static PixImg      *fx_raindrops_draw = NULL;

typedef struct
{
   int                 x, y;
   int                 count;
   PixImg             *buf;
}
DropContext;

static DropContext  fx_raindrops[4];

static void
FX_raindrops_timeout(int val __UNUSED__, void *data __UNUSED__)
{
   static GC           gc1 = 0, gc = 0;
   int                 i, x, y, xx, yy;
   int                 percent_done;
   static char         first = 1;
   static char         sintab[256];
   static unsigned char disttab[fx_raindrop_size][fx_raindrop_size];

   if (fx_raindrops_win == None)
     {
      XGCValues           gcv;

      if (first)
        {
           int                 j;

           first = 0;
           for (i = 0; i < 256; i++)
            sintab[i] =
               (char)(sin(((double)i) * M_PI_2 * 4 / 256) * fx_amplitude);
           for (j = 0; j < fx_raindrop_size; j++)
             {
              for (i = 0; i < fx_raindrop_size; i++)
                {
                   xx = i - fx_raindrop_size2;
                   yy = j - fx_raindrop_size2;
                   disttab[i][j] =
                    (unsigned char)sqrt((double)((xx * xx) + (yy * yy)));
                }
             }
        }

      fx_raindrops_win = DeskGetBackgroundWin(DesksGetCurrent());

      if (gc)
         EXFreeGC(gc);
      if (gc1)
         EXFreeGC(gc1);

      gcv.subwindow_mode = IncludeInferiors;
      gc = EXCreateGC(fx_raindrops_win, GCSubwindowMode, &gcv);
      gc1 = EXCreateGC(fx_raindrops_win, 0L, &gcv);

      fx_raindrops_draw =
         ECreatePixImg(fx_raindrops_win, fx_raindrop_size, fx_raindrop_size);

      if (!fx_raindrops_draw)
         return;

      for (i = 0; i < fx_raindrops_number; i++)
        {
           fx_raindrops[i].buf =
            ECreatePixImg(fx_raindrops_win, fx_raindrop_size,
                        fx_raindrop_size);
           if (fx_raindrops[i].buf)
            XShmGetImage(disp, fx_raindrops_win, fx_raindrops[i].buf->xim,
                       fx_raindrops[i].x, fx_raindrops[i].y, 0xffffffff);
           if (!fx_raindrops[i].buf)
            return;
        }
     }

   for (i = 0; i < fx_raindrops_number; i++)
     {
      fx_raindrops[i].count++;
      if (fx_raindrops[i].count == fx_raindrop_duration)
        {
           int                 j, count = 0;
           char                intersect = 1;

           XClearArea(disp, fx_raindrops_win, fx_raindrops[i].x,
                  fx_raindrops[i].y, fx_raindrop_size, fx_raindrop_size,
                  False);
           fx_raindrops[i].count = 0;
           while (intersect)
             {
              count++;
              if (count > 10240)
                 break;
              intersect = 0;
              for (j = 0; j < fx_raindrops_number; j++)
                {
                   fx_raindrops[i].x =
                    rand() % (VRoot.w - fx_raindrop_size);
                   fx_raindrops[i].y =
                    rand() % (VRoot.h - fx_raindrop_size);
                   if (fx_raindrops[i].x < 0)
                    fx_raindrops[i].x = 0;
                   else if (fx_raindrops[i].x >
                        (VRoot.w - fx_raindrop_size))
                    fx_raindrops[i].x = VRoot.w - fx_raindrop_size;
                   if (fx_raindrops[i].y < 0)
                    fx_raindrops[i].y = 0;
                   else if (fx_raindrops[i].y >
                        (VRoot.h - fx_raindrop_size))
                    fx_raindrops[i].y = VRoot.h - fx_raindrop_size;
                   if (i != j)
                   {
                      if (((fx_raindrops[i].x >= fx_raindrops[j].x)
                         && (fx_raindrops[i].x <
                             fx_raindrops[j].x + fx_raindrop_size)
                         && (fx_raindrops[i].y >= fx_raindrops[j].y)
                         && (fx_raindrops[i].y <
                             fx_raindrops[j].y + fx_raindrop_size))
                        ||
                        ((fx_raindrops
                          [i].x + fx_raindrop_size >= fx_raindrops[j].x)
                         && (fx_raindrops[i].x + fx_raindrop_size <
                             fx_raindrops[j].x + fx_raindrop_size)
                         && (fx_raindrops[i].y >= fx_raindrops[j].y)
                         && (fx_raindrops[i].y <
                             fx_raindrops[j].y + fx_raindrop_size))
                        || ((fx_raindrops[i].x >= fx_raindrops[j].x)
                            && (fx_raindrops[i].x <
                              fx_raindrops[j].x + fx_raindrop_size)
                            && (fx_raindrops[i].y + fx_raindrop_size >=
                              fx_raindrops[j].y)
                            && (fx_raindrops[i].y + fx_raindrop_size <
                              fx_raindrops[j].y + fx_raindrop_size))
                        ||
                        ((fx_raindrops
                          [i].x + fx_raindrop_size >= fx_raindrops[j].x)
                         && (fx_raindrops[i].x + fx_raindrop_size <
                             fx_raindrops[j].x + fx_raindrop_size)
                         && (fx_raindrops[i].y + fx_raindrop_size >=
                             fx_raindrops[j].y)
                         && (fx_raindrops[i].y + fx_raindrop_size <
                             fx_raindrops[j].y + fx_raindrop_size)))
                         intersect = 1;
                   }
                }
             }
           XShmGetImage(disp, fx_raindrops_win, fx_raindrops[i].buf->xim,
                    fx_raindrops[i].x, fx_raindrops[i].y, 0xffffffff);
        }
      percent_done =
         1 + ((fx_raindrops[i].count << 8) / fx_raindrop_duration);
      for (y = 0; y < fx_raindrop_size; y++)
        {
           for (x = 0; x < fx_raindrop_size; x++)
             {
              int                 dist;

              dist = disttab[x][y];
              if (dist > fx_raindrop_size2)
                 XPutPixel(fx_raindrops_draw->xim, x, y,
                         XGetPixel(fx_raindrops[i].buf->xim, x, y));
              else
                {
                   int                 percent;

                   percent = 1 + ((dist << 8) / fx_raindrop_size2);
                   if (percent > percent_done)
                    XPutPixel(fx_raindrops_draw->xim, x, y,
                            XGetPixel(fx_raindrops[i].buf->xim, x, y));
                   else
                   {
                      int                 varx, vary;
                      int                 phase, divisor, multiplier;

                      phase =
                         ((percent - percent_done) * fx_frequency) & 0xff;
                      xx = x - fx_raindrop_size2;
                      yy = y - fx_raindrop_size2;
                      divisor = 1 + (dist << 8);
                      multiplier =
                         (int)sintab[phase] * (256 - percent_done);
                      varx = ((-xx) * multiplier) / divisor;
                      vary = ((-yy) * multiplier) / divisor;
                      xx = x + varx;
                      yy = y + vary;
                      if (xx < 0)
                         xx = 0;
                      else if (xx >= fx_raindrop_size)
                         xx = fx_raindrop_size - 1;
                      if (yy < 0)
                         yy = 0;
                      else if (yy >= fx_raindrop_size)
                         yy = fx_raindrop_size - 1;
                      XPutPixel(fx_raindrops_draw->xim, x, y,
                              XGetPixel(fx_raindrops[i].buf->xim, xx,
                                    yy));
                   }
                }
             }
        }
      XShmPutImage(disp, fx_raindrops_win, gc1, fx_raindrops_draw->xim, 0, 0,
                 fx_raindrops[i].x, fx_raindrops[i].y, fx_raindrop_size,
                 fx_raindrop_size, False);
      ESync();
     }

   DoIn("FX_RAINDROPS_TIMEOUT", (0.066 /*/ (float)fx_raindrops_number */ ),
      FX_raindrops_timeout, 0, NULL);
}

static void
FX_Raindrops_Init(const char *name __UNUSED__)
{
   int                 i;

   fx_raindrops_win = None;
   for (i = 0; i < fx_raindrops_number; i++)
     {
      fx_raindrops[i].count = rand() % fx_raindrop_duration;
      fx_raindrops[i].x = rand() % (VRoot.w - fx_raindrop_size);
      fx_raindrops[i].y = rand() % (VRoot.h - fx_raindrop_size);
     }
   DoIn("FX_RAINDROPS_TIMEOUT", 0.066, FX_raindrops_timeout, 0, NULL);
}

static void
FX_Raindrops_Desk(void)
{
   fx_raindrops_win = None;
}

static void
FX_Raindrops_Quit(void)
{
   int                 i;

   RemoveTimerEvent("FX_RAINDROPS_TIMEOUT");
   for (i = 0; i < fx_raindrops_number; i++)
     {
      XClearArea(disp, fx_raindrops_win, fx_raindrops[i].x, fx_raindrops[i].y,
               fx_raindrop_size, fx_raindrop_size, False);
      if (fx_raindrops[i].buf)
         EDestroyPixImg(fx_raindrops[i].buf);
      fx_raindrops[i].buf = NULL;
     }
   if (fx_raindrops_draw)
      EDestroyPixImg(fx_raindrops_draw);
   fx_raindrops_draw = NULL;
   fx_raindrops_win = None;
}

static void
FX_Raindrops_Pause(void)
{
   static char         paused = 0;

   if (!paused)
     {
      FX_Raindrops_Quit();
      paused = 1;
     }
   else
     {
      FX_Raindrops_Init(NULL);
      paused = 0;
     }
}

#endif /* E_FX_RAINDROPS */

/****************************** WAVES ***************************************/
/* by tsade :)                                                              */
/****************************************************************************/

#define FX_WAVE_WATERH 64
#define FX_WAVE_WATERW 64
#define FX_WAVE_DEPTH  10
#define FX_WAVE_GRABH  (FX_WAVE_WATERH + FX_WAVE_DEPTH)
#define FX_WAVE_CROSSPERIOD 0.42
static Pixmap       fx_wave_above = None;
static Win          fx_wave_win = NoWin;
static int          fx_wave_count = 0;

static void
FX_Wave_timeout(int val __UNUSED__, void *data __UNUSED__)
{
   /* Variables */
   static double       incv = 0, inch = 0;
   static double       incx = 0;
   double              incx2;
   static GC           gc1 = 0, gc = 0;
   int                 y;

   /* Check to see if we need to create stuff */
   if (!fx_wave_above)
     {
      XGCValues           gcv;

      fx_wave_win = DeskGetBackgroundWin(DesksGetCurrent());

      fx_wave_above =
         ECreatePixmap(fx_wave_win, VRoot.w, FX_WAVE_WATERH * 2, 0);
      if (gc)
         EXFreeGC(gc);
      if (gc1)
         EXFreeGC(gc1);
      gcv.subwindow_mode = IncludeInferiors;
      gc = EXCreateGC(WinGetXwin(fx_wave_win), GCSubwindowMode, &gcv);
      gc1 = EXCreateGC(WinGetXwin(fx_wave_win), 0L, &gcv);
     }

   /* On the zero, grab the desktop again. */
   if (fx_wave_count == 0)
     {
      XCopyArea(disp, EoGetXwin(DesksGetCurrent()), fx_wave_above, gc, 0,
              VRoot.h - (FX_WAVE_WATERH * 3), VRoot.w, FX_WAVE_WATERH * 2,
              0, 0);
     }

   /* Increment and roll the counter */
   fx_wave_count++;
   if (fx_wave_count > 32)
      fx_wave_count = 0;

   /* Increment and roll some other variables */
   incv += 0.40;
   if (incv > (M_PI_2 * 4))
      incv = 0;

   inch += 0.32;
   if (inch > (M_PI_2 * 4))
      inch = 0;

   incx += 0.32;
   if (incx > (M_PI_2 * 4))
      incx = 0;

   /* Copy the area to correct bugs */
   if (fx_wave_count == 0)
     {
      XCopyArea(disp, fx_wave_above, WinGetXwin(fx_wave_win), gc1, 0,
              VRoot.h - FX_WAVE_GRABH, VRoot.w, FX_WAVE_DEPTH * 2, 0,
              VRoot.h - FX_WAVE_GRABH);
     }

   /* Go through the bottom couple (FX_WAVE_WATERH) lines of the window */
   for (y = 0; y < FX_WAVE_WATERH; y++)
     {
      /* Variables */
      double              aa, a, p;
      int                 yoff, off, yy;
      int                 x;

      /* Figure out the side-to-side movement */
      p = (((double)(FX_WAVE_WATERH - y)) / ((double)FX_WAVE_WATERH));
      a = p * p * 48 + incv;
      yoff = y + (int)(sin(a) * 7) + 1;
      yy = (FX_WAVE_WATERH * 2) - yoff;
      aa = p * p * FX_WAVE_WATERH + inch;
      off = (int)(sin(aa) * 10 * (1 - p));

      /* Set up the next part */
      incx2 = incx;

      /* Go through the width of the screen, in block sizes */
      for (x = 0; x < VRoot.w; x += FX_WAVE_WATERW)
        {
           /* Variables */
           int                 sx;

           /* Add something to incx2 and roll it */
           incx2 += FX_WAVE_CROSSPERIOD;

           if (incx2 > (M_PI_2 * 4))
            incx2 = 0;

           /* Figure it out */
           sx = (int)(sin(incx2) * FX_WAVE_DEPTH);

           /* Display this block */
           XCopyArea(disp, fx_wave_above, WinGetXwin(fx_wave_win), gc1, x, yy,      /* x, y */
                   FX_WAVE_WATERW, 1,     /* w, h */
                   off + x, VRoot.h - FX_WAVE_WATERH + y + sx     /* dx, dy */
            );
        }
     }

   /* Make noise */
   DoIn("FX_WAVE_TIMEOUT", 0.066, FX_Wave_timeout, 0, NULL);
}

static void
FX_Waves_Init(const char *name __UNUSED__)
{
   fx_wave_count = 0;
   DoIn("FX_WAVE_TIMEOUT", 0.066, FX_Wave_timeout, 0, NULL);
}

static void
FX_Waves_Desk(void)
{
   EFreePixmap(fx_wave_above);
   fx_wave_count = 0;
   fx_wave_above = 0;
}

static void
FX_Waves_Quit(void)
{
   RemoveTimerEvent("FX_WAVE_TIMEOUT");
   EClearArea(fx_wave_win, 0, VRoot.h - FX_WAVE_WATERH, VRoot.w,
            FX_WAVE_WATERH, False);
}

static void
FX_Waves_Pause(void)
{
   static char         paused = 0;

   if (!paused)
     {
      FX_Waves_Quit();
      paused = 1;
     }
   else
     {
      FX_Waves_Init(NULL);
      paused = 0;
     }
}

#ifdef E_FX_IMAGESPINNER

/****************************** IMAGESPINNER ********************************/

static Window       fx_imagespinner_win = None;
static int          fx_imagespinner_count = 3;
static char        *fx_imagespinner_params = NULL;

static void
FX_imagespinner_timeout(int val __UNUSED__, void *data __UNUSED__)
{
   char               *string = NULL;

   if (fx_imagespinner_win == None)
     {
      fx_imagespinner_win = DeskGetBackgroundWin(DesksGetCurrent());
     }

#if 0                   /* Don't use getword */
/* do stuff here */
   string = getword(fx_imagespinner_params, fx_imagespinner_count);
   if (!string)
     {
      fx_imagespinner_count = 3;
      string = getword(fx_imagespinner_params, fx_imagespinner_count);
     }
#endif

   fx_imagespinner_count++;
   if (string)
     {
      EImage             *im;

      im = ThemeImageLoad(string);
      if (im)
        {
           int                 x, y, w, h;

           EImageGetSize(im, &w, &h);
           sscanf(fx_imagespinner_params, "%*s %i %i ", &x, &y);
           x = ((VRoot.w * x) >> 10) - ((w * x) >> 10);
           y = ((VRoot.h * y) >> 10) - ((h * y) >> 10);
           EImageRenderOnDrawable(im, fx_imagespinner_win, 0, x, y, w, h);
           EImageFree(im);
        }
      Efree(string);
     }

   DoIn("FX_IMAGESPINNER_TIMEOUT", 0.066, FX_imagespinner_timeout, 0, NULL);
}

static void
FX_ImageSpinner_Init(const char *name)
{
   fx_imagespinner_count = 3;
   DoIn("FX_IMAGESPINNER_TIMEOUT", 0.066, FX_imagespinner_timeout, 0, NULL);
   fx_imagespinner_params = Estrdup(name);
}

static void
FX_ImageSpinner_Desk(void)
{
   fx_imagespinner_win = DeskGetBackgroundWin(DesksGetCurrent());
}

static void
FX_ImageSpinner_Quit(void)
{
   RemoveTimerEvent("FX_IMAGESPINNER_TIMEOUT");
   XClearArea(disp, fx_imagespinner_win, 0, 0, VRoot.w, VRoot.h, False);
   if (fx_imagespinner_params)
      Efree(fx_imagespinner_params);
   fx_imagespinner_params = NULL;
   fx_imagespinner_win = None;
}

static void
FX_ImageSpinner_Pause(void)
{
   static char         paused = 0;

   if (!paused)
     {
      FX_ImageSpinner_Quit();
      paused = 1;
     }
   else
     {
      FX_ImageSpinner_Init(NULL);
      paused = 0;
     }
}

#endif /* E_FX_IMAGESPINNER */

/****************************************************************************/

static FXHandler    fx_handlers[] = {
   {"ripples",
    FX_Ripple_Init, FX_Ripple_Desk, FX_Ripple_Quit, FX_Ripple_Pause,
    0, 0},
   {"waves",
    FX_Waves_Init, FX_Waves_Desk, FX_Waves_Quit, FX_Waves_Pause,
    0, 0},
#ifdef E_FX_RAINDROPS         /* FIXME */
   {"raindrops",
    FX_Raindrops_Init, FX_Raindrops_Desk, FX_Raindrops_Quit,
    FX_Raindrops_Pause,
    0, 0},
#endif
#ifdef E_FX_IMAGESPINNER
   {"imagespinner",
    FX_ImageSpinner_Init, FX_ImageSpinner_Desk, FX_ImageSpinner_Quit,
    FX_ImageSpinner_Pause,
    0, 0},
#endif
};
#define N_FX_HANDLERS (sizeof(fx_handlers)/sizeof(FXHandler))

/****************************** Effect handlers *****************************/

static FXHandler   *
FX_Find(const char *name)
{
   unsigned int        i;

   for (i = 0; i < N_FX_HANDLERS; i++)
      if (!strcmp(fx_handlers[i].name, name))
       return &fx_handlers[i];

   return NULL;
}

static void
FX_Op(const char *name, int fx_op)
{
   FXHandler          *fxh;

   fxh = FX_Find(name);
   if (fxh == NULL)
      return;

   switch (fx_op)
     {
     case FX_OP_START:
      if (fxh->enabled)
         break;
      do_start:
      if (fxh->init_func)
         fxh->init_func(name);
      fxh->enabled = 1;
      break;

     case FX_OP_STOP:
      if (!fxh->enabled)
         break;
      do_stop:
      if (fxh->quit_func)
         fxh->quit_func();
      fxh->enabled = 0;
      break;

     case FX_OP_TOGGLE:
      if (fxh->enabled)
         goto do_stop;
      else
         goto do_start;
     }
}

static void
FX_DeskChange(void)
{
   unsigned int        i;

   for (i = 0; i < N_FX_HANDLERS; i++)
     {
      if (fx_handlers[i].enabled)
        {
           if (fx_handlers[i].desk_func)
            fx_handlers[i].desk_func();
        }
     }
}

static void
FX_Pause(void)
{
   unsigned int        i;

   for (i = 0; i < N_FX_HANDLERS; i++)
     {
      if (fx_handlers[i].enabled)
        {
           if (fx_handlers[i].paused)
             {
              if (fx_handlers[i].pause_func)
                 fx_handlers[i].pause_func();
              fx_handlers[i].paused = 1;
             }
           else
             {
              if (fx_handlers[i].pause_func)
                 fx_handlers[i].pause_func();
              fx_handlers[i].paused = 0;
             }
        }
     }
}

static void
FX_StartAll(void)
{
   unsigned int        i;
   FXHandler          *fxh;

   for (i = 0; i < N_FX_HANDLERS; i++)
     {
      fxh = &fx_handlers[i];
      if (fxh->enabled && fxh->init_func)
         fxh->init_func(fxh->name);
     }
}

static int
FX_IsOn(const char *effect)
{
   unsigned int        i;

   for (i = 0; i < N_FX_HANDLERS; i++)
     {
      if (!strcmp(fx_handlers[i].name, effect))
        {
           return fx_handlers[i].enabled;
        }
     }
   return 0;
}

/****************************************************************************/

/*
 * Fx Module
 */

static void
FxSighan(int sig, void *prm __UNUSED__)
{
   switch (sig)
     {
     case ESIGNAL_START:
      FX_StartAll();
      break;
     case ESIGNAL_AREA_SWITCH_START:
     case ESIGNAL_DESK_SWITCH_START:
      break;
     case ESIGNAL_AREA_SWITCH_DONE:
     case ESIGNAL_DESK_SWITCH_DONE:
      FX_DeskChange();
      break;
     case ESIGNAL_ANIMATION_SUSPEND:
     case ESIGNAL_ANIMATION_RESUME:
      FX_Pause();
      break;
     }
}

static char         tmp_effect_raindrops;
static char         tmp_effect_ripples;
static char         tmp_effect_waves;

static void
CB_ConfigureFX(Dialog * d __UNUSED__, int val, void *data __UNUSED__)
{
   if (val < 2)
     {
      FX_Op("raindrops", tmp_effect_raindrops ? FX_OP_START : FX_OP_STOP);
      FX_Op("ripples", tmp_effect_ripples ? FX_OP_START : FX_OP_STOP);
      FX_Op("waves", tmp_effect_waves ? FX_OP_START : FX_OP_STOP);
     }
   autosave();
}

static void
_DlgFillFx(Dialog * d __UNUSED__, DItem * table, void *data __UNUSED__)
{
   DItem              *di;

   tmp_effect_raindrops = FX_IsOn("raindrops");
   tmp_effect_ripples = FX_IsOn("ripples");
   tmp_effect_waves = FX_IsOn("waves");

   DialogItemTableSetOptions(table, 1, 0, 0, 0);

   /* Effects */
   di = DialogAddItem(table, DITEM_TEXT);
   DialogItemSetText(di, _("Effects"));
#if 0                   /* Disabled */
   di = DialogAddItem(table, DITEM_CHECKBUTTON);
   DialogItemSetText(di, _("Enable Effect: Raindrops"));
   DialogItemCheckButtonSetPtr(di, &tmp_effect_raindrops);
#endif
   di = DialogAddItem(table, DITEM_CHECKBUTTON);
   DialogItemSetText(di, _("Ripples"));
   DialogItemCheckButtonSetPtr(di, &tmp_effect_ripples);

   di = DialogAddItem(table, DITEM_CHECKBUTTON);
   DialogItemSetText(di, _("Waves"));
   DialogItemCheckButtonSetPtr(di, &tmp_effect_waves);
}

const DialogDef     DlgFx = {
   "CONFIGURE_FX",
   N_("FX"),
   N_("Special FX Settings"),
   "SOUND_SETTINGS_FX",
   "pix/fx.png",
   N_("Enlightenment Special Effects\n" "Settings Dialog\n"),
   _DlgFillFx,
   DLG_OAC, CB_ConfigureFX,
};

static void
FxIpc(const char *params)
{
   char                word1[1024];
   char                word2[1024];

   if (!params)
      return;

   word1[0] = word2[0] = '\0';
   sscanf(params, "%1000s %1000s", word1, word2);

   if (!strcmp(word1, "raindrops") || !strcmp(word1, "ripples") ||
       !strcmp(word1, "waves"))
     {
      if (!strcmp(word2, ""))
         FX_Op(word1, FX_OP_TOGGLE);
      else if (!strcmp(word2, "on"))
         FX_Op(word1, FX_OP_START);
      else if (!strcmp(word2, "off"))
         FX_Op(word1, FX_OP_STOP);
      else if (!strcmp(word2, "?"))
         IpcPrintf("%s: %s", word1, FX_IsOn(word1) ? "on" : "off");
      else
         IpcPrintf("Error: unknown mode specified");
     }
   else if (!strncmp(word1, "cfg", 2))
     {
      DialogShowSimple(&DlgFx, NULL);
     }
}

static const IpcItem FxIpcArray[] = {
   {
    FxIpc,
    "fx", "fx",
    "Toggle various effects on/off",
    "  fx cfg               Configure effects\n"
    "  fx <effect> <mode>   Set the mode of a particular effect\n"
    "  fx <effect> ?\"      Get the current mode\n"
    "the following effects are available\n"
    " ripples <on/off> (ripples that act as a water effect on the screen)\n"
    " waves <on/off> (waves that act as a water effect on the screen)\n"}
   ,
};
#define N_IPC_FUNCS (sizeof(FxIpcArray)/sizeof(IpcItem))

static const CfgItem FxCfgItems[] = {
   CFR_ITEM_BOOL(fx_handlers[0].enabled, ripples.enabled, 0),
   CFR_ITEM_BOOL(fx_handlers[1].enabled, waves.enabled, 0),
#ifdef E_FX_RAINDROPS         /* FIXME */
   CFR_ITEM_BOOL(fx_handlers[2].enabled, raindrops.enabled, 0),
#endif
};
#define N_CFG_ITEMS (sizeof(FxCfgItems)/sizeof(CfgItem))

/*
 * Module descriptor
 */
extern const EModule ModEffects;
const EModule       ModEffects = {
   "effects", "efx",
   FxSighan,
   {N_IPC_FUNCS, FxIpcArray},
   {N_CFG_ITEMS, FxCfgItems}
};

Generated by  Doxygen 1.6.0   Back to index