8f1f57f99b6a5ba5d340940380cf8fb3ad2d23be
[shermanaquarium] / sherman-aquarium / shermans / screensaver.c
1
2 /* 
3
4    Sherman's aquarium - Screensaver part
5
6    Updated and partly rewritten for Sherman's aquarium v3.0.0 on
7    30th and 31st December 2003.
8
9    Jonas Aaberg <cja@gmx.net>
10
11 */
12
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <signal.h>
19 #include <time.h>
20 #include <glob.h>
21 #include <gdk-pixbuf/gdk-pixbuf.h>
22 #include <gdk/gdk.h>
23 #include <gdk/gdkx.h>
24 #include <SDL/SDL.h>
25 #include <X11/Xlib.h>
26
27
28
29 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
30 #define RMASK 0xff000000
31 #define GMASK 0x00ff0000
32 #define BMASK 0x0000ff00
33 #define AMASK 0x000000ff
34
35 #else
36
37 #define RMASK 0x000000ff
38 #define GMASK 0x0000ff00
39 #define BMASK 0x00ff0000
40 #define AMASK 0xff000000
41 #endif
42
43
44
45
46 typedef struct {
47     unsigned char r,g,b,alpha;
48 } GaiColor;
49
50
51 #include "aquarium.h"
52 #include "bottom.h"
53 #include "bubble.h"
54 #include "background.h"
55 #include "fish.h"
56 #include "draw.h"
57 #include "soundeffects.h"
58 #include "vroot.h"
59
60 #ifdef DARWIN
61 #include "getopt.h"
62 #else
63 #include <getopt.h>
64 #endif
65
66
67 #define ARG_SEAFLOOR 1
68 #define ARG_SOUND 2
69 #define ARG_PLANTS 3
70 #define ARG_PLANTSCALE 4
71 #define ARG_BOTTOMANIMALS 5
72 #define ARG_OGG 6
73 #define ARG_BG_SOLID 7
74 #define ARG_BG_SHADED 8
75 #define ARG_BG_WATERALIKE 9
76 #define ARG_BG_IMAGE 10
77 #define ARG_LCR 11
78 #define ARG_LCG 12
79 #define ARG_LCB 13
80 #define ARG_UCR 14
81 #define ARG_UCG 15
82 #define ARG_UCB 16
83 #define ARG_BG_IMAGE_FILE 17
84 #define ARG_RANDOM 18
85 #define ARG_SELECTED 19
86 #define ARG_RANDOM_POP 20
87 #define ARG_FISH1 21
88 #define ARG_FISH2 22
89 #define ARG_FISH3 23
90 #define ARG_FISH4 24
91 #define ARG_FISH5 25
92 #define ARG_FISH6 26
93 #define ARG_BLOWFISH 27
94 #define ARG_SWORDFISH 28
95 #define ARG_BDWELLER 29
96 #define ARG_FILLMORE 30
97 #define ARG_SHERMAN 31
98 #define ARG_MEGAN 32
99 #define ARG_HUNTER 33
100 #define ARG_PREY 34
101 #define ARG_LORI 35
102 #define ARG_ERNEST 36
103 #define ARG_SQUID 37
104 #define ARG_HAWTHORNE 38
105 #define ARG_EAT 39
106 #define ARG_EXPLODE 40
107 #define ARG_REBIRTH 41
108 #define ARG_SCALEDIFF 42
109 #define ARG_SPEED 43
110 #define ARG_SCALE 44
111 #define ARG_HUNTERA 45
112 #define ARG_SWORDA 46
113 #define ARG_SOUNDPRG 47
114 #define ARG_WINDOW_ID 48
115 #define ARG_FULLSCREEN 49
116 #define ARG_BUBBLE 50
117 #define ARG_DESKTOP 51
118 #define ARG_COMICS 52
119 #define ARG_COMICS_DIR 53
120 #define ARG_COMICS_DELAY 54
121 #define ARG_VIEW 55
122
123 #define DEPTH 24
124
125 static int screen_width;
126 static int screen_height;
127 static gboolean comics = FALSE;
128 static char *comic_dirs[1024]; /* No more than 1024 comic dirs :-) Ugly, but... */
129 static int num_comic_dirs = 0;
130
131 static GdkWindow *window;
132 static GdkGC *gc;
133 static SDL_Surface *screen=NULL, *screen_image, *background, **thisfish;
134 static SDL_Rect *fish_dest, *fish_src, *clean_dest;
135 static int curr_dest, clean_count,  no_sdl_quit = 0, comics_delay = 50;
136 int window_id = -1, fullscreen = 1;
137 int view = 1;
138 static unsigned char *original_bg;
139 static AquariumData ad;
140
141
142
143 void screensaver_draw_image(int x, int y, int idx, int rev, SA_Image *image)
144 {
145
146     fish_dest[curr_dest].x=x;
147     fish_dest[curr_dest].y=y;
148     fish_dest[curr_dest].w=image->width;
149     fish_dest[curr_dest].h=image->height;
150
151     fish_src[curr_dest].x=0;
152     fish_src[curr_dest].y=(int)((float)idx*(float)image->full_height/(float)image->frames+0.5);
153     fish_src[curr_dest].w=image->width;
154     fish_src[curr_dest].h=image->height;
155
156     if(!rev)
157         thisfish[curr_dest] = SDL_CreateRGBSurfaceFrom(image->image,
158                                                        image->width,
159                                                        (int)((float)image->full_height*(float)(idx+1) / 
160                                                              (float)image->frames + 0.5),
161                                                        32,image->rowstride,
162                                                        RMASK, GMASK, BMASK, AMASK);
163     else
164         thisfish[curr_dest] = SDL_CreateRGBSurfaceFrom(image->rev,
165                                                        image->width,
166                                                        (int)((float)image->full_height*(float)(idx+1) / 
167                                                              (float)image->frames + 0.5),
168                                                        32,image->rowstride,
169                                                        RMASK, GMASK, BMASK, AMASK);
170
171     curr_dest++;
172 }
173
174
175
176
177 void screensaver_clean(int x,int y,int w,int h)
178 {
179
180     clean_dest[clean_count].x=x-5;
181     clean_dest[clean_count].y=y-5;
182     clean_dest[clean_count].w=w+10;
183     clean_dest[clean_count].h=h+10;
184
185
186     SDL_BlitSurface(background,&clean_dest[clean_count],screen,&clean_dest[clean_count]);
187
188     clean_count++;
189 }
190
191
192 void screensaver_quit()
193 {
194     /* Resetting the term signal to the orignal so we can quit nicely.*/
195     signal(SIGTERM, SIG_DFL);
196
197     if(no_sdl_quit)
198         kill(getpid(),SIGTERM);
199     else
200         exit(0);
201
202     /* In case something is really weird */
203     kill(getpid(),SIGKILL);
204 }
205
206 void comics_clean(void)
207 {
208     int i;
209     for(i=0;i<num_comic_dirs;i++)
210         g_free(comic_dirs[i]);
211     num_comic_dirs = 0;
212     comic_dirs[0] = NULL;
213 }
214
215 void comics_prepare(char *dir)
216 {
217     comic_dirs[num_comic_dirs] = g_strdup_printf("%s/*", dir);
218     num_comic_dirs++;
219
220     /* Make sure the final one is always followed by a NULL */
221     comic_dirs[num_comic_dirs] = NULL;
222 }
223
224 char *comics_pick(void)
225 {
226     int i, flags = GLOB_NOSORT;
227     glob_t comic_files;
228     char *the_comic = NULL;
229
230
231     for(i=0;i<num_comic_dirs;i++){
232         if(i)
233             flags |= GLOB_APPEND;
234         glob(comic_dirs[i], flags, NULL, &comic_files);
235     }
236
237     if(comic_files.gl_pathc != 0)
238         the_comic = g_strdup(comic_files.gl_pathv[g_rand_int_range(ad.rnd, 0, comic_files.gl_pathc)]);
239
240     globfree(&comic_files);
241
242
243     return the_comic;
244
245 }
246
247
248 void comics_load(void)
249 {
250     int i,j, srs, ys, xs, alpha, sy, dy;
251     unsigned char *src;
252     char *comic_file = NULL;
253     GError *ferror = NULL;
254     GdkPixbuf *comic_pic, *tmp_pic;
255
256     memcpy(ad.rgb, original_bg, ad.xmax*3*ad.ymax);
257     memcpy(ad.bgr, original_bg, ad.xmax*3*ad.ymax);
258
259     comic_file = comics_pick();
260
261     if(comic_file == NULL)
262         return;
263
264     comic_pic = gdk_pixbuf_new_from_file(comic_file, &ferror);
265
266     g_free(comic_file);
267
268     if(comic_pic == NULL)
269         return;
270
271     if(screen_height < gdk_pixbuf_get_height(comic_pic) || screen_width < gdk_pixbuf_get_width(comic_pic)){
272
273         tmp_pic = gdk_pixbuf_scale_simple(comic_pic,screen_width, screen_height, GDK_INTERP_BILINEAR);
274         g_object_unref(comic_pic);
275         comic_pic = tmp_pic;
276     }
277
278
279     ys = (screen_height - gdk_pixbuf_get_height(comic_pic))/2;
280     xs = (screen_width - gdk_pixbuf_get_width(comic_pic))/2;
281
282
283     srs = gdk_pixbuf_get_rowstride(comic_pic);
284     alpha = gdk_pixbuf_get_has_alpha(comic_pic);
285     src = gdk_pixbuf_get_pixels(comic_pic);
286
287     for(i=0;i<gdk_pixbuf_get_height(comic_pic);i++){
288         sy = i * srs;
289         dy = (i+ys) * ad.xmax + xs;
290         
291         for(j=0;j<gdk_pixbuf_get_width(comic_pic);j++){
292             ad.bgr[(dy+j)*3+0] = ad.rgb[(dy+j)*3+0] = src[sy + j*(3+alpha)+0];
293             ad.bgr[(dy+j)*3+1] = ad.rgb[(dy+j)*3+1] = src[sy + j*(3+alpha)+1];
294             ad.bgr[(dy+j)*3+2] = ad.rgb[(dy+j)*3+2] = src[sy + j*(3+alpha)+2];
295         }
296     }
297     g_object_unref(comic_pic);
298
299 }
300
301
302
303 void screensaver_main_sdl(void)
304 {
305     SDL_Event event;
306     clock_t totaltime1;
307 #ifdef PERFORMACE_CHECK
308     clock_t totaltime2;
309 #endif
310     clock_t cali1, cali2;
311     int totalframes=0;
312     int num_events=0;
313     int main_loop=0;
314     int frames=0;
315     int i;
316     int delay=0;
317     int counter = 0;
318
319
320     totaltime1 = clock();
321     cali1 = clock();
322
323     while(!main_loop){
324
325
326         if(counter == 0 && comics){
327             comics_load();
328             SDL_BlitSurface(screen_image, NULL, screen, NULL);
329             SDL_UpdateRect(screen,0,0,0,0);
330             counter = 25*comics_delay;
331         }
332         counter --;
333
334
335         curr_dest=0;
336         clean_count=0;
337
338         fish_update();
339         bubble_update();
340
341         for(i=0;i<curr_dest;i++)
342             SDL_BlitSurface(thisfish[i],&fish_src[i],screen,&fish_dest[i]);
343         
344
345         /* If we get a SIGTERM from screensaver in this loop, and we later do a SDL_Quit()
346            X will get problems. So we have to avoid calling SDL_Quit if a sigterm is caught
347            in this loop.
348
349            Otherwise we get:
350            Xlib: unexpected async reply (sequence 0xf03)!
351            And sherman's starts eating processor power like mad!
352         */
353         no_sdl_quit = 1;
354         for(i=0;i<curr_dest;i++){
355             SDL_UpdateRects(screen,1,&clean_dest[i]);
356             SDL_FreeSurface(thisfish[i]);
357         }
358         no_sdl_quit = 0;
359
360         if(window_id!=-1)
361             SDL_Flip(screen);
362
363         totalframes++;
364         frames++;
365
366         if(frames==10){
367             cali2=clock();
368
369             /* Check if we're going too fast! */
370             if((float)(cali2-cali1) < (float)(0.2*CLOCKS_PER_SEC)){
371                 delay=(int)(((float)((0.2*CLOCKS_PER_SEC)-(cali2-cali1))/CLOCKS_PER_SEC)*100000);
372             }
373             else{
374                 if(delay!=0){
375                     if(delay<((int)(((float)((0.2*CLOCKS_PER_SEC)-(cali2-cali1))/CLOCKS_PER_SEC)*100000))){
376                         delay-=(int)(((float)((0.2*CLOCKS_PER_SEC)-(cali2-cali1))/CLOCKS_PER_SEC)*100000);
377                     }
378                     else
379                         delay=0;
380                 }
381             }
382             cali1=clock();
383             frames=0;
384         }
385         usleep(delay);
386         
387
388         while(SDL_PollEvent(&event)){
389             switch(event.type){
390             case SDL_QUIT:
391                 main_loop=1;
392                 break;
393             case SDL_KEYDOWN:
394                 num_events++;
395                 if(num_events==2)
396                     main_loop=1;
397                 break;
398             case SDL_MOUSEMOTION:
399                 num_events++;
400                 if(num_events==2)
401                     main_loop=1;
402                 break;
403             case  SDL_MOUSEBUTTONDOWN:
404                 num_events++;
405                 if(num_events==2)
406                     main_loop=1;
407                 break;
408             }
409         }    
410     }
411
412 #ifdef PERFORMACE_CHECK
413     totaltime2=clock();
414     printf("Frames: %d\n",totalframes);
415     printf("Seconds: %f\n",(float)(totaltime2-totaltime1)/CLOCKS_PER_SEC);
416     printf("FPS: %f\n",(float)totalframes/((float)(totaltime2-totaltime1)/CLOCKS_PER_SEC));
417 #endif
418
419 }
420
421 void screensaver_main_gdk(void)
422 {
423     GdkEvent *event;
424     int counter = 0;
425
426     while(1){
427         while(gdk_events_pending()){
428             event = gdk_event_get();
429             if(event){
430                 if(event->type == GDK_DESTROY)
431                     exit(0);
432             }
433         }
434
435         if(counter == 0 && comics){
436             comics_load();
437             counter = 25*comics_delay;
438         }
439         counter --;
440
441         memcpy(ad.rgb, ad.bgr, ad.ymax * ad.xmax * 3);
442         fish_update();
443         bubble_update();
444         gdk_draw_rgb_image(window, gc, ad.xmin, ad.ymin, ad.xmax, ad.ymax,
445                            GDK_RGB_DITHER_NONE, ad.rgb, ad.xmax * 3);
446         gdk_flush();
447         /* 25 fps */
448         usleep(1000000/25);
449     }
450
451 }
452
453 void init_sdl(int sdl_flags)
454 {
455
456     if (SDL_Init(SDL_INIT_VIDEO) < 0){
457         printf("Can't init SDL: %s\n",SDL_GetError());
458         exit(1);
459     }
460
461
462     signal(SIGTERM, screensaver_quit);
463     atexit(SDL_Quit);
464     
465
466     if(!SDL_VideoModeOK(screen_width,screen_height, DEPTH, sdl_flags)){
467         printf("Sorry, video mode %dx%d in %d bits isn't supported by hardware\n",
468                screen_width,screen_height, DEPTH);
469         exit(2);
470     }
471
472
473     screen = SDL_SetVideoMode(screen_width, screen_height, DEPTH, sdl_flags);
474
475     if(screen == NULL){
476         printf("Unable to set video mode %dx%d in %d bits.\n",
477                screen_width,screen_height,DEPTH);
478         exit(3);
479     }
480
481     SDL_WM_SetCaption("Sherman's aquarium",NULL);
482
483
484     /* Hide the mouse cursor */
485     SDL_ShowCursor(0);
486
487     /* Start with all black */
488     SDL_FillRect(screen,NULL,0x000000);
489
490     screen_image = SDL_CreateRGBSurfaceFrom(ad.rgb, ad.xmax, ad.ymax, DEPTH, ad.xmax*3, 
491                                             RMASK, GMASK, BMASK, 0);
492     background = SDL_CreateRGBSurfaceFrom(ad.bgr, ad.xmax, ad.ymax, DEPTH, ad.xmax*3, 
493                                           RMASK, GMASK, BMASK, 0);
494
495
496     SDL_BlitSurface(screen_image, NULL, screen, NULL);
497     SDL_UpdateRect(screen,0,0,0,0);
498
499 }
500
501
502 void screensaver_init()
503 {
504     char *sdl_command;
505     XWindowAttributes win_attr;
506     Display *display;
507     Fish_settings *fish_settings;
508     Bubble_settings *bubble_settings;
509     int sdl_flags = SDL_DOUBLEBUF|SDL_HWSURFACE|SDL_ANYFORMAT;
510
511     screen_height = 480;
512     screen_width = 800;
513     
514     if(window_id != -1){
515         display = XOpenDisplay(NULL);
516         XGetWindowAttributes(display, (Window)window_id, &win_attr);
517         screen_height = win_attr.height;
518         screen_width = win_attr.width;
519         fullscreen = 0;
520         ad.proximity = 1;                       /* No sound effects */
521         window = gdk_window_foreign_new((Window)window_id);
522         gdk_window_show(window);
523         gc = gdk_gc_new(window);
524     }
525
526     if(fullscreen){
527         screen_width = gdk_screen_width();
528         screen_height = gdk_screen_height();
529
530         display=XOpenDisplay(NULL);
531         sdl_command = g_strdup_printf("SDL_WINDOWID=%d",
532                                       (int)RootWindowOfScreen(ScreenOfDisplay(display, DefaultScreen(display))));
533         putenv(sdl_command);
534         ad.proximity = 0;
535         sdl_flags |= SDL_FULLSCREEN;
536     }
537
538     ad.xmax = screen_width;
539     ad.ymax = screen_height;
540   
541     ad.virtual_aquarium_x = ad.xmax + 2 * VIRTUAL_AQUARIUM_DX;
542     ad.virtual_aquarium_y = ad.ymax + 2 * VIRTUAL_AQUARIUM_DY;
543
544     ad.ymin = ad.xmin = ad.viewpoint_start_x = ad.viewpoint_start_y = 0;
545
546     ad.rgb = g_malloc0(ad.xmax*3*ad.ymax);
547     ad.bgr = g_malloc0(ad.xmax*3*ad.ymax);
548     original_bg = g_malloc0(ad.xmax*3*ad.ymax);
549
550     background_init();
551     fish_init();
552     fish_turn();
553     bottom_init();
554     bubble_init();
555
556     memcpy(ad.rgb, ad.bgr, ad.xmax*3*ad.ymax);
557     memcpy(original_bg, ad.bgr, ad.xmax*3*ad.ymax);
558
559
560     if(fullscreen || window_id == -1)
561         init_sdl(sdl_flags);
562
563
564     fish_settings = fish_get_settings_ptr();
565     bubble_settings = bubble_get_settings_ptr();
566
567     fish_dest = g_malloc0(sizeof(SDL_Rect)*(fish_settings->num_fish + 
568                                             bubble_settings->max_bubbles));
569     fish_src = g_malloc0(sizeof(SDL_Rect)*(fish_settings->num_fish +
570                                            bubble_settings->max_bubbles));
571     clean_dest = g_malloc0(sizeof(SDL_Rect)*(fish_settings->num_fish  + 
572                                              bubble_settings->max_bubbles));
573
574     thisfish = g_malloc0(sizeof(SDL_Surface*)*(fish_settings->num_fish + bubble_settings->max_bubbles));
575     
576 }
577
578 int htoi(char *str)
579 {
580   int i,sum=0,d;
581
582   if(str[0]!='0' || str[1]!='x') return -1;
583   for(i=2;i<strlen(str);i++){
584     d=0;
585     if(str[i]>='0' && str[i]<='9') d=(int)(str[i]-'0');
586     if(str[i]>='A' && str[i]<='F') d=(int)(str[i]-'A'+10);
587     if(str[i]>='a' && str[i]<='f') d=(int)(str[i]-'a'+10);
588
589     sum+=d;
590     sum=sum<<4;
591   }
592
593   return(sum>>4);
594 }
595
596 void screensaver_init_param(int argc, char **argv)
597 {
598     int i,c, numfish = 0, comic_start;
599     char *comic_buff;
600
601     Sound_settings *s, sound_settings = {0,TYPE_MP3, NULL};
602     Bubble_settings *bub, bubble_settings = {20};
603     Bottom_settings *b, bottom_settings = {1,5,1,75,3};
604     Background_settings *bg, background_settings = {NULL,NULL, 2,0, 
605                                                     (GaiColor){0, 100, 150, 0},
606                                                     (GaiColor){10,120, 250, 0},
607                                                     (GaiColor){0,0,0,0}};
608     Fish_settings *f, fish_settings = {1, 1, 75, 0, 100, 1, 15, 0, 75, 75,
609                                        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
610     struct option cmdline_options[] = {
611         {"sound", no_argument, NULL, ARG_SOUND},
612         {"soundprg", required_argument, NULL, ARG_SOUNDPRG},
613         {"ogg", no_argument, NULL, ARG_OGG},
614
615
616         {"seafloor", no_argument, NULL, ARG_SEAFLOOR},
617         {"plants", required_argument, NULL, ARG_PLANTS},
618         {"plantscale", required_argument, NULL, ARG_PLANTSCALE},
619         {"bottomanimals", required_argument, NULL, ARG_BOTTOMANIMALS},
620
621         {"bg_solid", no_argument, NULL, ARG_BG_SOLID},
622         {"bg_shaded", no_argument, NULL, ARG_BG_SHADED},
623         {"bg_wateralike", no_argument, NULL, ARG_BG_WATERALIKE},
624         {"bg_image", no_argument, NULL, ARG_BG_IMAGE},
625
626
627         {"lcr", required_argument, NULL, ARG_LCR},
628         {"lcg", required_argument, NULL, ARG_LCG},
629         {"lcb", required_argument, NULL, ARG_LCB},
630
631         {"ucr", required_argument, NULL, ARG_UCR},
632         {"ucg", required_argument, NULL, ARG_UCG},
633         {"ucb", required_argument, NULL, ARG_UCB},
634         
635         {"bg_image_file", required_argument, NULL, ARG_BG_IMAGE_FILE},
636
637         {"comics", no_argument, NULL, ARG_COMICS},
638         {"comics_dir", required_argument, NULL, ARG_COMICS_DIR},
639         {"comics_delay", required_argument, NULL, ARG_COMICS_DELAY},
640
641
642         {"random", no_argument, NULL, ARG_RANDOM},
643         {"selected", no_argument, NULL, ARG_SELECTED},
644         {"random_pop", required_argument, NULL, ARG_RANDOM_POP},
645
646         {"fish1", required_argument, NULL, ARG_FISH1},
647         {"fish2", required_argument, NULL, ARG_FISH2},
648         {"fish3", required_argument, NULL, ARG_FISH3},
649         {"fish4", required_argument, NULL, ARG_FISH4},
650         {"fish5", required_argument, NULL, ARG_FISH5},
651         {"fish6", required_argument, NULL, ARG_FISH6},
652         {"swordfish", required_argument, NULL, ARG_SWORDFISH},
653         {"blowfish", required_argument, NULL, ARG_BLOWFISH},
654         {"bdweller", required_argument, NULL, ARG_BDWELLER},
655         {"fillmore", required_argument, NULL, ARG_FILLMORE},
656         {"sherman", required_argument, NULL, ARG_SHERMAN},
657         {"megan", required_argument, NULL, ARG_MEGAN},
658         {"hunter", required_argument, NULL, ARG_HUNTER},
659         {"prey", required_argument, NULL, ARG_PREY},
660         {"lori", required_argument, NULL, ARG_LORI},
661         {"ernest", required_argument, NULL, ARG_ERNEST},
662         {"squid", required_argument, NULL, ARG_SQUID},
663         {"hawthorne", required_argument, NULL, ARG_HAWTHORNE},
664
665         {"eat", no_argument, NULL, ARG_EAT},
666         {"explode", no_argument, NULL, ARG_EXPLODE},
667         {"rebirth", no_argument, NULL, ARG_REBIRTH},
668         {"scalediff", no_argument, NULL, ARG_SCALEDIFF},
669         {"speed", required_argument, NULL, ARG_SPEED},
670         {"scale", required_argument, NULL, ARG_SCALE},
671         {"huntera", required_argument, NULL, ARG_HUNTERA},
672         {"sworda", required_argument, NULL, ARG_SWORDA},
673         {"window-id", required_argument, NULL, ARG_WINDOW_ID},
674         {"root", no_argument, NULL, ARG_FULLSCREEN},
675         {"bubble", required_argument, NULL, ARG_BUBBLE},
676         {"desktop", no_argument, NULL, ARG_DESKTOP},
677         {"view", required_argument, NULL, ARG_VIEW},
678         {0,0,0,0}};
679
680
681     b = bottom_get_settings_ptr();
682     bub = bubble_get_settings_ptr();
683     bg = background_get_settings_ptr();
684     f = fish_get_settings_ptr();
685     s = sound_get_settings_ptr();
686
687     memcpy(f,&fish_settings, sizeof(Fish_settings));
688     memcpy(bg,&background_settings, sizeof(Background_settings));
689     memcpy(b,&bottom_settings, sizeof(Bottom_settings));
690     memcpy(bub, &bubble_settings, sizeof(Bubble_settings));
691     memcpy(s, &sound_settings, sizeof(Sound_settings));
692 fprintf(stderr, "1BG %i\n",bg->desktop);
693
694     while ((c =
695             getopt_long_only(argc, argv, "", cmdline_options, NULL)) != -1){
696
697         switch(c){
698
699         case ARG_SEAFLOOR:
700             b->have_sea_floor = 1;
701             break;
702         case ARG_SOUND:
703             s->on = 1;
704             break;
705         case ARG_PLANTS:
706             b->max_plants = atoi(optarg);
707             break;
708         case ARG_PLANTSCALE:
709             b->scale = atoi(optarg);
710             break;
711         case ARG_BOTTOMANIMALS:
712             b->num_bottom_animals = atoi(optarg);
713             break;
714         case ARG_OGG:
715             s->type = TYPE_OGG;
716             break;
717         case ARG_BG_SOLID:
718             bg->type = BG_SOLID;
719             bg->desktop = 0;
720             break;
721         case ARG_BG_SHADED:
722             bg->type = BG_SHADED;
723             bg->desktop = 0;
724             break;
725         case ARG_BG_WATERALIKE:
726             bg->type = BG_WATER;
727             bg->desktop = 0;
728             break;
729         case ARG_BG_IMAGE:
730             bg->type = BG_IMAGE;
731             bg->desktop = 0;
732             break;
733         case ARG_LCR:
734             bg->solid_c.r = bg->shaded_bot_c.r = atoi(optarg);
735             break;
736         case ARG_LCG:
737             bg->solid_c.g = bg->shaded_bot_c.g = atoi(optarg);
738             break;
739         case ARG_LCB:
740             bg->solid_c.b = bg->shaded_bot_c.b = atoi(optarg);
741             break;
742         case ARG_UCR:
743             bg->shaded_top_c.r = atoi(optarg);
744             break;
745         case ARG_UCG:
746             bg->shaded_top_c.g = atoi(optarg);
747             break;
748         case ARG_UCB:
749             bg->shaded_top_c.b = atoi(optarg);
750             break;
751         case ARG_BG_IMAGE_FILE:
752             bg->imagename = g_strdup_printf(optarg);
753             break;
754         case ARG_RANDOM:
755             f->type = RANDOM_FISH;
756             break;
757         case ARG_SELECTED:
758             f->type = SELECTION_FISH;
759             break;
760         case ARG_RANDOM_POP:
761             f->num_fish = atoi(optarg);
762             break;
763         case ARG_FISH1:
764             f->fish1 = atoi(optarg);
765             break;
766         case ARG_FISH2:
767             f->fish2 = atoi(optarg);
768             break;
769         case ARG_FISH3:
770             f->fish3 = atoi(optarg);
771             break;
772         case ARG_FISH4:
773             f->fish4 = atoi(optarg);
774             break;
775         case ARG_FISH5:
776             f->fish5 = atoi(optarg);
777             break;
778         case ARG_FISH6:
779             f->fish6 = atoi(optarg);
780             break;
781         case ARG_BLOWFISH:
782             f->blowfish = atoi(optarg);
783             break;
784         case ARG_SWORDFISH:
785             f->swordfish = atoi(optarg);
786             break;
787         case ARG_BDWELLER:
788             f->bdweller = atoi(optarg);
789             break;
790         case ARG_FILLMORE:
791             f->fillmore = atoi(optarg);
792             break;
793         case ARG_SHERMAN:
794             f->sherman = atoi(optarg);
795             break;
796         case ARG_MEGAN:
797             f->megan = atoi(optarg);
798             break;
799         case ARG_HUNTER:
800             f->hunter = atoi(optarg);
801             break;
802         case ARG_PREY:
803             f->prey = atoi(optarg);
804             break;
805         case ARG_LORI:
806             f->lori = atoi(optarg);
807             break;
808         case ARG_ERNEST:
809             f->ernest = atoi(optarg);
810             break;
811         case ARG_SQUID:
812             f->squid = atoi(optarg);
813             break;
814         case ARG_HAWTHORNE:
815             f->hawthorne = atoi(optarg);
816             break;
817         case ARG_EAT:
818             f->eat = 1;
819             break;
820         case ARG_EXPLODE:
821             f->explode = 1;
822             break;
823         case ARG_REBIRTH:
824             f->rebirth = 1;
825             break;
826         case ARG_SCALEDIFF:
827             f->scale_diff = 1;
828             break;
829         case ARG_SPEED:
830             f->speed = atoi(optarg);
831             break;
832         case ARG_SCALE:
833             f->scale = atoi(optarg);
834         case ARG_HUNTERA:
835             f->hunter_agr = atoi(optarg);
836             break;
837         case ARG_SWORDA:
838             f->swordfish_agr = atoi(optarg);
839             break;
840         case ARG_SOUNDPRG:
841             s->prg = g_strdup_printf(optarg);
842             break;
843         case ARG_WINDOW_ID:
844             window_id = atoi(optarg);
845             break;
846         case ARG_FULLSCREEN:
847             fullscreen = 1;
848             break;
849         case ARG_BUBBLE:
850             bub->max_bubbles = atoi(optarg);
851             break;
852         case ARG_VIEW:
853             view = atoi(optarg);
854             break;
855         case ARG_DESKTOP:
856             bg->type = 0;
857             bg->desktop = 1;
858             break;
859         case ARG_COMICS:
860             comics = TRUE;
861             comics_prepare(IMAGE_PATH "/strips");
862             break;
863         case ARG_COMICS_DELAY:
864             comics_delay = atoi(optarg);
865             break;
866         case ARG_COMICS_DIR:
867             comics_clean();
868             comic_start = 0;
869             comic_buff = g_strdup(optarg);
870             for(i=0;i<strlen(optarg);i++){
871                 if(comic_buff[i] == ';'){
872                     comic_buff[i] = '\0';
873                     comics_prepare(comic_buff+comic_start);
874                     comic_start = i+1;
875                 }
876             }
877             comics_prepare(comic_buff+comic_start);
878             g_free(comic_buff);
879
880             break;
881         default:
882             break;
883         }
884     }
885
886     numfish += f->fish1;
887     numfish += f->fish2;
888     numfish += f->fish3;
889     numfish += f->fish4;
890     numfish += f->fish5;
891     numfish += f->fish6;
892     numfish += f->swordfish;
893     numfish += f->blowfish;
894     numfish += f->fillmore;
895     numfish += f->sherman;
896     numfish += f->prey;
897     numfish += f->hunter;
898     numfish += f->lori;
899     numfish += f->ernest;
900     numfish += f->squid;
901     numfish += f->megan;
902     numfish += f->bdweller;
903     numfish += f->hawthorne;
904
905     if(f->type == SELECTION_FISH)
906         f->num_fish = numfish;
907
908 }
909
910 int main(int argc, char **argv)
911 {
912     gdk_init(&argc, &argv);
913
914     ad.rnd = g_rand_new();
915
916     screensaver_init_param(argc, argv);
917     screensaver_init(0);
918
919     if(window_id==-1){
920         fprintf(stderr, "screensaver_main_sdl\n");
921         screensaver_main_sdl();
922     }
923     else{
924         fprintf(stderr, "screensaver_main_GDK\n");
925         screensaver_main_gdk();
926     }
927     return 0;
928 }
929
930
931 AquariumData *aquarium_get_settings_ptr(void)
932 {
933     return &ad;
934 }
935
936 unsigned char *aquarium_install_path(void)
937 {
938     return IMAGE_PATH;
939 }
940
941
942 void aquarium_draw_image(int x, int y, int idx, int rev, SA_Image *image)
943 {
944     if(window_id==-1)
945         screensaver_draw_image(x, y, idx, rev, image);
946     else
947         draw_image(x, y, idx, rev, image);
948 }
949
950 void aquarium_draw_pic_alpha(SA_Image *image, int w, int h, int x, int y, int idx, int alpha)
951 {
952     if(window_id==-1)
953         screensaver_draw_image(x, y, idx, 0, image);
954     else
955         draw_pic_alpha(image->image, w, h, x, y, idx,alpha);
956
957
958
959 void aquarium_clean_image(int x, int y, int w, int h)
960 {
961     if(window_id==-1)
962         screensaver_clean(x, y, w, h);
963 }
964
965 GdkPixbuf *gai_load_image(char *fname)
966 {
967     GError *msg = NULL;
968     GdkPixbuf *pix;
969     char *full_name;
970
971     full_name = g_strdup_printf("%s/%s",IMAGE_PATH,fname);
972     pix = gdk_pixbuf_new_from_file(full_name, &msg);
973     if(!pix){
974         printf("%s\n",msg->message);
975         exit(1);
976     }
977     g_free(full_name);
978
979     return pix;
980     
981 }
982 void gai_display_error_continue(char *msg)
983 {
984     printf(" *** Error: %s\n",msg);
985 }