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