source: trunk/third/xscreensaver/hacks/xteevee.c @ 20148

Revision 20148, 13.6 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/*****************************************************************************
2 *                                                                           *
3 * xteevee -- TV good... TV good...                                          *
4 *                                                                           *
5 * Copyright (c) 1999 Greg Knauss (greg@eod.com)                             *
6 *                                                                           *
7 * Permission to use, copy, modify, distribute, and sell this software and   *
8 * its documentation for any purpose is hereby granted without fee, provided *
9 * that the above copyright notice appear in all copies and that both that   *
10 * copyright notice and this permission notice appear in supporting          *
11 * documentation.  No representations are made about the suitability of this *
12 * software for any purpose.  It is provided "as is" without express or      *
13 * implied warranty.                                                         *
14 *                                                                           *
15 *****************************************************************************/
16
17
18/* Changelog *****************************************************************
19
20        1.0.0   19991119        Initial release
21
22*/
23
24
25/* Includes ******************************************************************/
26#include "screenhack.h"
27#include "colorbars.h"
28#include <X11/Xutil.h>
29#include <time.h>
30#include <sys/time.h>
31
32
33/* Defines *******************************************************************/
34#define XTEEVEE_NAME                    "XTeeVee"
35#define XTEEVEE_MODE_EXCLUDE            0
36#define XTEEVEE_MODE_INCLUDE_IMPLICIT   1
37#define XTEEVEE_MODE_INCLUDE_EXPLICIT   2
38#define XTEEVEE_ARG_STATIC              "static"
39#define XTEEVEE_ARG_STATIC_SIGNAL       "staticSignal"
40#define XTEEVEE_ARG_ROLL                "roll"
41#define XTEEVEE_ARG_BARS                "bars"
42#define XTEEVEE_ARG_CYCLE               "cycle"
43#define XTEEVEE_ARG_DELAY_MODE          "delayMode"
44#define XTEEVEE_ARG_DELAY_BETWEEN       "delayBetween"
45#define XTEEVEE_STATIC_COLOR_COUNT      6
46#define XTEEVEE_STATIC_TILE_COUNT       16
47
48
49/* Globals *******************************************************************/
50char *progclass  = XTEEVEE_NAME;
51char *defaults[] =
52{
53        "*" XTEEVEE_ARG_STATIC        ": true",
54        "*" XTEEVEE_ARG_STATIC_SIGNAL ": 50",
55        "*" XTEEVEE_ARG_ROLL          ": true",
56        "*" XTEEVEE_ARG_BARS          ": true",
57        "*" XTEEVEE_ARG_CYCLE         ": true",
58        "*" XTEEVEE_ARG_DELAY_MODE    ": 30",
59        "*" XTEEVEE_ARG_DELAY_BETWEEN ": 3",
60        NULL
61};
62XrmOptionDescRec options[] =
63{
64 { "-"    XTEEVEE_ARG_STATIC,"._" XTEEVEE_ARG_STATIC,XrmoptionNoArg,"true" },
65 { "-no-" XTEEVEE_ARG_STATIC,"."  XTEEVEE_ARG_STATIC,XrmoptionNoArg,"false" },
66 { "-"    XTEEVEE_ARG_ROLL  ,"._" XTEEVEE_ARG_ROLL  ,XrmoptionNoArg,"true" },
67 { "-no-" XTEEVEE_ARG_ROLL  ,"."  XTEEVEE_ARG_ROLL  ,XrmoptionNoArg,"false" },
68 { "-"    XTEEVEE_ARG_BARS  ,"._" XTEEVEE_ARG_BARS  ,XrmoptionNoArg,"true" },
69 { "-no-" XTEEVEE_ARG_BARS  ,"."  XTEEVEE_ARG_BARS  ,XrmoptionNoArg,"false" },
70 { "-"    XTEEVEE_ARG_CYCLE ,"."  XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"true" },
71 { "-no-" XTEEVEE_ARG_CYCLE ,"."  XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"false" },
72 { NULL                     ,NULL                   ,0             ,NULL }
73};
74
75
76/* Functions *****************************************************************/
77
78/* Get the forground pixel ================================================= */
79void xteevee_FreeColorForeground(Display* x_Disp,XWindowAttributes* x_WinAttr,
80      GC x_Gc)
81{
82        XGCValues x_GcVal;
83
84        if (XGetGCValues(x_Disp,x_Gc,GCForeground,&x_GcVal) != 0)
85        {
86                XFreeColors(x_Disp,x_WinAttr->colormap,&x_GcVal.foreground,1,
87                 0);
88        }
89}
90
91/* Static ================================================================== */
92void xteevee_Static(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
93      time_t hack_Time,Pixmap hack_Pm)
94{
95        GC        x_Gc[XTEEVEE_STATIC_COLOR_COUNT];
96        unsigned long pixels[XTEEVEE_STATIC_COLOR_COUNT];
97        XImage   *xim = 0;
98        char     *orig_bits = 0;
99        XGCValues x_GcVal;
100        int       signal_Strength;
101        XColor    color_Color;
102        int       color_Index;
103        int       tile_Index;
104        Pixmap    tile_Tile[XTEEVEE_STATIC_TILE_COUNT];
105        int       tile_X;
106        int       tile_Y;
107        int       tile_Width;
108        int       tile_Height;
109        char      tile_Used[XTEEVEE_STATIC_TILE_COUNT/2+1];
110        int       tile_Selected;
111
112        /* Get any extra arguments */
113        signal_Strength = get_integer_resource(XTEEVEE_ARG_STATIC_SIGNAL,
114         "Integer");
115
116        /* Build the GCs */
117        color_Color.flags = DoRed|DoGreen|DoBlue;
118        for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
119         color_Index++)
120        {
121                color_Color.red = color_Color.green = color_Color.blue =
122                 (((double)color_Index+1)/XTEEVEE_STATIC_COLOR_COUNT)*65535;
123                if (!x_WinAttr->colormap ||
124                    !XAllocColor(x_Disp,x_WinAttr->colormap,&color_Color))
125                {
126                        /* NOTE: I have no idea what to do here.  Why would
127                                 this fail? */
128                }
129                pixels[color_Index] = color_Color.pixel;
130                x_GcVal.foreground = color_Color.pixel;
131                x_Gc[color_Index] = XCreateGC(x_Disp,x_Win,GCForeground,
132                 &x_GcVal);
133        }
134
135        /* Build the tiles */
136        for (tile_Index = 0;tile_Index < XTEEVEE_STATIC_TILE_COUNT;
137         tile_Index++)
138        {
139                if (signal_Strength == 0)
140                {
141                        /* NOTE: Checking XQueryBestTile() returns tiles that
142                                 are too regular -- you can see patterns
143                                 emerge. */
144                        tile_Width = (random()%128)+64;
145                        tile_Height = (random()%128)+64;
146                }
147                else
148                {
149                        tile_Width = x_WinAttr->width;
150                        tile_Height = x_WinAttr->height;
151                }
152                tile_Tile[tile_Index] = XCreatePixmap(x_Disp,x_Win,tile_Width,
153                 tile_Height,x_WinAttr->depth);
154                XCopyArea(x_Disp,hack_Pm,tile_Tile[tile_Index],x_Gc[0],0,0,
155                 x_WinAttr->width,x_WinAttr->height,0,0);
156
157                if (signal_Strength == 0)
158                  {
159                    if (!xim)
160                      {
161                        xim = XCreateImage (x_Disp, x_WinAttr->visual,
162                                            x_WinAttr->depth,
163                                            (x_WinAttr->depth == 1
164                                             ? XYPixmap : ZPixmap),
165                                            0, 0,
166                                            x_WinAttr->width,
167                                            x_WinAttr->height,
168                                            8, 0);
169                       
170                        xim->data = (char *) malloc (xim->bytes_per_line *
171                                                     xim->height);
172                      }
173                  }
174                else if (xim)
175                  {
176                    memcpy (xim->data, orig_bits,
177                            xim->bytes_per_line * xim->height);
178                  }
179                else
180                  {
181                    xim = XGetImage (x_Disp, tile_Tile[tile_Index], 0, 0,
182                                     x_WinAttr->width, x_WinAttr->height, ~0L,
183                                     (x_WinAttr->depth == 1
184                                      ? XYPixmap : ZPixmap));
185                    orig_bits = (char *) malloc (xim->bytes_per_line *
186                                                 xim->height);
187                    memcpy (orig_bits, xim->data,
188                            xim->bytes_per_line * xim->height);
189                  }
190
191                for (tile_Y = tile_Height-1;tile_Y >= 0;tile_Y--)
192                  for (tile_X = tile_Width-1;tile_X >= 0;tile_X--)
193                    if (random()%100 > signal_Strength)
194                      XPutPixel(xim,tile_X,tile_Y,
195                                pixels[random()%XTEEVEE_STATIC_COLOR_COUNT]);
196                XPutImage(x_Disp,tile_Tile[tile_Index],x_Gc[0],xim,
197                          0,0,0,0,x_WinAttr->width,x_WinAttr->height);
198        }
199
200        if (xim) XDestroyImage (xim);
201        if (orig_bits) free (orig_bits);
202
203        /* Go! */
204        memset(tile_Used,-1,sizeof(tile_Used));
205        if (hack_Time > 0)
206        {
207                hack_Time += time(NULL);
208        }
209        while ((time(NULL) < hack_Time) || (hack_Time == 0))
210        {
211                /* Pick a tile */
212                do
213                {
214                        tile_Selected = random()%XTEEVEE_STATIC_TILE_COUNT;
215                        for (tile_Index = 0;tile_Index < sizeof(tile_Used);
216                         tile_Index++)
217                        {
218                                if (tile_Used[tile_Index] == tile_Selected)
219                                {
220                                        tile_Selected = -1;
221                                        break;
222                                }
223                        }
224                } while (tile_Selected == -1);
225                memmove(tile_Used,tile_Used+1,sizeof(tile_Used)-1);
226                tile_Used[sizeof(tile_Used)-1] = tile_Selected;
227
228                /* Set it */
229                XSetWindowBackgroundPixmap(x_Disp,x_Win,
230                 tile_Tile[tile_Selected]);
231                XClearWindow(x_Disp,x_Win);
232
233                XSync(x_Disp,0);
234                screenhack_handle_events(x_Disp);
235                usleep(25000);
236        }
237
238        /* Free everything */
239        for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
240         color_Index++)
241        {
242                xteevee_FreeColorForeground(x_Disp,x_WinAttr,
243                 x_Gc[color_Index]);
244                XFreeGC(x_Disp,x_Gc[color_Index]);
245        }
246
247        for (tile_Index = 0;tile_Index < XTEEVEE_STATIC_TILE_COUNT;
248         tile_Index++)
249        {
250                XFreePixmap(x_Disp, tile_Tile[tile_Index]);
251        }
252}
253
254/* Vertical Roll =========================================================== */
255void xteevee_Roll(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
256      time_t hack_Time,Pixmap hack_Pm)
257{
258        GC        x_Gc;
259        XGCValues x_GcVal;
260        int       roll_Y = 0;
261        int       roll_Speed = 0;
262        int       blank_Height = x_WinAttr->height/10;
263
264        /* Build the GC */
265        x_GcVal.foreground = BlackPixel(x_Disp,0);
266        x_GcVal.subwindow_mode = IncludeInferiors;
267        x_Gc = XCreateGC(x_Disp,x_Win,GCForeground|GCSubwindowMode,&x_GcVal);
268
269        /* Go! */
270        if (hack_Time > 0)
271        {
272                hack_Time += time(NULL);
273        }
274        while ((roll_Y > 0) || ((time(NULL) < hack_Time) || (hack_Time == 0)))
275        {
276                if (roll_Y > blank_Height)
277                {
278                        XCopyArea(x_Disp,hack_Pm,x_Win,x_Gc,
279                         0,x_WinAttr->height-(roll_Y-blank_Height)-1,
280                         x_WinAttr->width,roll_Y-blank_Height,
281                         0,0);
282                }
283                XFillRectangle(x_Disp,x_Win,x_Gc,
284                 0,roll_Y-blank_Height,
285                 x_WinAttr->width,blank_Height);
286                if (roll_Y < x_WinAttr->height)
287                {
288                        XCopyArea(x_Disp,hack_Pm,x_Win,x_Gc,
289                         0,0,
290                         x_WinAttr->width,x_WinAttr->height-roll_Y,
291                         0,roll_Y);
292                }
293
294                roll_Y += roll_Speed/2;
295                if (roll_Speed < 50)
296                {
297                        roll_Speed++;
298                }
299                if (roll_Y > x_WinAttr->height+blank_Height)
300                {
301                        roll_Y = 0;
302                        roll_Speed = 0;
303                }
304
305                XSync(x_Disp,0);
306                usleep(50000);
307                screenhack_handle_events(x_Disp);
308        }
309
310        /* Free everything */
311        XFreeGC(x_Disp,x_Gc);
312}
313
314/* Color-Bars Test Pattern ================================================= */
315void xteevee_Bars(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
316      time_t hack_Time,Pixmap hack_Pm)
317{
318  draw_colorbars (x_WinAttr->screen, x_WinAttr->visual, x_Win,
319                  x_WinAttr->colormap,
320                  0, 0, x_WinAttr->width, x_WinAttr->height);
321
322  /* Go! */
323  if (hack_Time > 0)
324    {
325      hack_Time += time(NULL);
326    }
327  while ((time(NULL) < hack_Time) || (hack_Time == 0))
328    {
329      screenhack_handle_events(x_Disp);
330      usleep(100000);
331    }
332}
333
334
335/* Standard XScreenSaver entry point ======================================= */
336void screenhack(Display* x_Disp,Window x_Win)
337{
338        XWindowAttributes x_WinAttr;
339        GC                x_Gc;
340        XGCValues         x_GcVal;
341        Pixmap            screen_Pm;
342        time_t            delay_Time;
343        int               delay_Mode;
344        int               delay_Between;
345        int               mode_Index;
346        int               mode_Count = 0;
347        int               mode_Total = 0;
348        char              mode_Arg[64+1];
349        int               mode_Min = XTEEVEE_MODE_INCLUDE_IMPLICIT;
350        struct
351        {
352                char* mode_Arg;
353                void  (*mode_Func)(Display* x_Disp,Window x_Win,
354                      XWindowAttributes* x_WinAttr,time_t hack_Time,
355                      Pixmap hack_Pm);
356                int   mode_Flag;
357        } mode_Mode[] =
358        {
359                { XTEEVEE_ARG_STATIC,xteevee_Static,XTEEVEE_MODE_EXCLUDE },
360                { XTEEVEE_ARG_ROLL,  xteevee_Roll,  XTEEVEE_MODE_EXCLUDE },
361                { XTEEVEE_ARG_BARS,  xteevee_Bars,  XTEEVEE_MODE_EXCLUDE },
362                { NULL,              NULL,          -1 }
363        };
364
365        /* Grab the screen to give us time to do whatever we want */
366        XGetWindowAttributes(x_Disp,x_Win,&x_WinAttr);
367        load_random_image (x_WinAttr.screen, x_Win, x_Win, NULL);
368
369        x_GcVal.subwindow_mode = IncludeInferiors;
370        x_Gc = XCreateGC(x_Disp,x_Win,GCSubwindowMode,&x_GcVal);
371        screen_Pm = XCreatePixmap(x_Disp,x_Win,x_WinAttr.width,
372         x_WinAttr.height,x_WinAttr.depth);
373        XCopyArea(x_Disp,x_Win,screen_Pm,x_Gc,0,0,x_WinAttr.width,
374         x_WinAttr.height,0,0);
375
376        /* Read the arguments */
377        delay_Mode = get_integer_resource(XTEEVEE_ARG_DELAY_MODE,"Integer");
378        delay_Between = get_integer_resource(XTEEVEE_ARG_DELAY_BETWEEN,
379         "Integer");
380        if (!get_boolean_resource(XTEEVEE_ARG_CYCLE,"Boolean"))
381        {
382                delay_Mode = 0;
383        }
384        for (mode_Index = 0;mode_Mode[mode_Index].mode_Arg != NULL;
385         mode_Index++)
386        {
387                if (get_boolean_resource(mode_Mode[mode_Index].mode_Arg,
388                 "Boolean") != 0)
389                {
390                        mode_Mode[mode_Index].mode_Flag =
391                         XTEEVEE_MODE_INCLUDE_IMPLICIT;
392                        mode_Count++;
393                }
394                sprintf(mode_Arg,"_%s",mode_Mode[mode_Index].mode_Arg);
395                if (get_boolean_resource(mode_Arg,"Boolean") != 0)
396                {
397                        mode_Mode[mode_Index].mode_Flag =
398                         XTEEVEE_MODE_INCLUDE_EXPLICIT;
399                        mode_Min = XTEEVEE_MODE_INCLUDE_EXPLICIT;
400                        mode_Count++;
401                }
402                mode_Total++;
403        }
404        if (mode_Count == 0)
405        {
406                fprintf(stderr,"%s: No modes selected!\n",XTEEVEE_NAME);
407                return;
408        }
409
410        /* Cycle through various modes */
411        for (;;)
412        {
413                /* Find a mode */
414                do
415                {
416                        mode_Index = random()%mode_Total;
417                } while (mode_Mode[mode_Index].mode_Flag < mode_Min);
418
419                /* Run the hack */
420                mode_Mode[mode_Index].mode_Func(x_Disp,x_Win,&x_WinAttr,
421                 delay_Mode,screen_Pm);
422
423                /* Restore the screen and wait */
424                XCopyArea(x_Disp,screen_Pm,x_Win,x_Gc,0,0,x_WinAttr.width,
425                 x_WinAttr.height,0,0);
426                delay_Time = time(NULL)+delay_Between;
427                while (time(NULL) < delay_Time)
428                {
429                        screenhack_handle_events(x_Disp);
430                        usleep(100000);
431                }
432        }
433}
Note: See TracBrowser for help on using the repository browser.