fixed conflict
[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     ad.proximity = 0;
586         window = gdk_window_foreign_new((Window)window_id);
587         gdk_window_show(window);
588         gc = gdk_gc_new(window);
589     }
590
591     if(fullscreen){
592         screen_width = gdk_screen_width();
593         screen_height = gdk_screen_height();
594
595         display=XOpenDisplay(NULL);
596         sdl_command = g_strdup_printf("SDL_WINDOWID=%d",
597                                       (int)RootWindowOfScreen(ScreenOfDisplay(display, DefaultScreen(display))));
598         putenv(sdl_command);
599         ad.proximity = 0;
600         sdl_flags |= SDL_FULLSCREEN;
601     }
602
603     ad.xmax = screen_width;
604     ad.ymax = screen_height;
605   
606     ad.virtual_aquarium_x = ad.xmax + 2 * VIRTUAL_AQUARIUM_DX;
607     ad.virtual_aquarium_y = ad.ymax + 2 * VIRTUAL_AQUARIUM_DY;
608
609     ad.ymin = ad.xmin = ad.viewpoint_start_x = ad.viewpoint_start_y = 0;
610
611     ad.rgb = g_malloc0(ad.xmax*3*ad.ymax);
612     ad.bgr = g_malloc0(ad.xmax*3*ad.ymax);
613     original_bg = g_malloc0(ad.xmax*3*ad.ymax);
614
615     background_init();
616     fish_init();
617     fish_turn();
618     bottom_init();
619     bubble_init();
620
621     memcpy(ad.rgb, ad.bgr, ad.xmax*3*ad.ymax);
622     memcpy(original_bg, ad.bgr, ad.xmax*3*ad.ymax);
623
624
625     if(fullscreen || window_id == -1)
626         init_sdl(sdl_flags);
627
628
629     fish_settings = fish_get_settings_ptr();
630     bubble_settings = bubble_get_settings_ptr();
631
632     fish_dest = g_malloc0(sizeof(SDL_Rect)*(fish_settings->num_fish + 
633                                             bubble_settings->max_bubbles));
634     fish_src = g_malloc0(sizeof(SDL_Rect)*(fish_settings->num_fish +
635                                            bubble_settings->max_bubbles));
636     clean_dest = g_malloc0(sizeof(SDL_Rect)*(fish_settings->num_fish  + 
637                                              bubble_settings->max_bubbles));
638
639     thisfish = g_malloc0(sizeof(SDL_Surface*)*(fish_settings->num_fish + bubble_settings->max_bubbles));
640     
641 }
642
643 int htoi(char *str)
644 {
645   int i,sum=0,d;
646
647   if(str[0]!='0' || str[1]!='x') return -1;
648   for(i=2;i<strlen(str);i++){
649     d=0;
650     if(str[i]>='0' && str[i]<='9') d=(int)(str[i]-'0');
651     if(str[i]>='A' && str[i]<='F') d=(int)(str[i]-'A'+10);
652     if(str[i]>='a' && str[i]<='f') d=(int)(str[i]-'a'+10);
653
654     sum+=d;
655     sum=sum<<4;
656   }
657
658   return(sum>>4);
659 }
660
661 void screensaver_init_param(int argc, char **argv)
662 {
663     int i,c, numfish = 0, comic_start;
664     char *comic_buff;
665
666     Sound_settings *s, sound_settings = {0,TYPE_MP3, NULL};
667     Bubble_settings *bub, bubble_settings = {20};
668     Bottom_settings *b, bottom_settings = {1,5,1,75,3};
669     Background_settings *bg, background_settings = {NULL,NULL, 2,0, 
670                                                     (GaiColor){0, 100, 150, 0},
671                                                     (GaiColor){10,120, 250, 0},
672                                                     (GaiColor){0,0,0,0}};
673     Fish_settings *f, fish_settings = {1, 1, 75, 0, 100, 1, 15, 0, 75, 75,
674                                        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
675     struct option cmdline_options[] = {
676         {"sound", no_argument, NULL, ARG_SOUND},
677         {"soundprg", required_argument, NULL, ARG_SOUNDPRG},
678         {"ogg", no_argument, NULL, ARG_OGG},
679
680
681         {"seafloor", no_argument, NULL, ARG_SEAFLOOR},
682         {"plants", required_argument, NULL, ARG_PLANTS},
683         {"plantscale", required_argument, NULL, ARG_PLANTSCALE},
684         {"bottomanimals", required_argument, NULL, ARG_BOTTOMANIMALS},
685
686         {"bg_solid", no_argument, NULL, ARG_BG_SOLID},
687         {"bg_shaded", no_argument, NULL, ARG_BG_SHADED},
688         {"bg_wateralike", no_argument, NULL, ARG_BG_WATERALIKE},
689         {"bg_image", no_argument, NULL, ARG_BG_IMAGE},
690
691
692         {"lcr", required_argument, NULL, ARG_LCR},
693         {"lcg", required_argument, NULL, ARG_LCG},
694         {"lcb", required_argument, NULL, ARG_LCB},
695
696         {"ucr", required_argument, NULL, ARG_UCR},
697         {"ucg", required_argument, NULL, ARG_UCG},
698         {"ucb", required_argument, NULL, ARG_UCB},
699         
700         {"bg_image_file", required_argument, NULL, ARG_BG_IMAGE_FILE},
701
702         {"comics", no_argument, NULL, ARG_COMICS},
703         {"comics_dir", required_argument, NULL, ARG_COMICS_DIR},
704         {"comics_delay", required_argument, NULL, ARG_COMICS_DELAY},
705
706
707         {"random", no_argument, NULL, ARG_RANDOM},
708         {"selected", no_argument, NULL, ARG_SELECTED},
709         {"random_pop", required_argument, NULL, ARG_RANDOM_POP},
710
711         {"fish1", required_argument, NULL, ARG_FISH1},
712         {"fish2", required_argument, NULL, ARG_FISH2},
713         {"fish3", required_argument, NULL, ARG_FISH3},
714         {"fish4", required_argument, NULL, ARG_FISH4},
715         {"fish5", required_argument, NULL, ARG_FISH5},
716         {"fish6", required_argument, NULL, ARG_FISH6},
717         {"swordfish", required_argument, NULL, ARG_SWORDFISH},
718         {"blowfish", required_argument, NULL, ARG_BLOWFISH},
719         {"bdweller", required_argument, NULL, ARG_BDWELLER},
720         {"fillmore", required_argument, NULL, ARG_FILLMORE},
721         {"sherman", required_argument, NULL, ARG_SHERMAN},
722         {"megan", required_argument, NULL, ARG_MEGAN},
723         {"hunter", required_argument, NULL, ARG_HUNTER},
724         {"prey", required_argument, NULL, ARG_PREY},
725         {"lori", required_argument, NULL, ARG_LORI},
726         {"ernest", required_argument, NULL, ARG_ERNEST},
727         {"squid", required_argument, NULL, ARG_SQUID},
728         {"hawthorne", required_argument, NULL, ARG_HAWTHORNE},
729
730         {"eat", no_argument, NULL, ARG_EAT},
731         {"explode", no_argument, NULL, ARG_EXPLODE},
732         {"rebirth", no_argument, NULL, ARG_REBIRTH},
733         {"scalediff", no_argument, NULL, ARG_SCALEDIFF},
734         {"speed", required_argument, NULL, ARG_SPEED},
735         {"scale", required_argument, NULL, ARG_SCALE},
736         {"huntera", required_argument, NULL, ARG_HUNTERA},
737         {"sworda", required_argument, NULL, ARG_SWORDA},
738         {"window-id", required_argument, NULL, ARG_WINDOW_ID},
739         {"root", no_argument, NULL, ARG_FULLSCREEN},
740         {"bubble", required_argument, NULL, ARG_BUBBLE},
741         {"desktop", no_argument, NULL, ARG_DESKTOP},
742         {"view", required_argument, NULL, ARG_VIEW},
743         {0,0,0,0}};
744
745
746     b = bottom_get_settings_ptr();
747     bub = bubble_get_settings_ptr();
748     bg = background_get_settings_ptr();
749     f = fish_get_settings_ptr();
750     s = sound_get_settings_ptr();
751
752     memcpy(f,&fish_settings, sizeof(Fish_settings));
753     memcpy(bg,&background_settings, sizeof(Background_settings));
754     memcpy(b,&bottom_settings, sizeof(Bottom_settings));
755     memcpy(bub, &bubble_settings, sizeof(Bubble_settings));
756     memcpy(s, &sound_settings, sizeof(Sound_settings));
757 fprintf(stderr, "1BG %i\n",bg->desktop);
758
759     while ((c =
760             getopt_long_only(argc, argv, "", cmdline_options, NULL)) != -1){
761
762         switch(c){
763
764         case ARG_SEAFLOOR:
765             b->have_sea_floor = 1;
766             break;
767         case ARG_SOUND:
768             s->on = 1;
769             break;
770         case ARG_PLANTS:
771             b->max_plants = atoi(optarg);
772             break;
773         case ARG_PLANTSCALE:
774             b->scale = atoi(optarg);
775             break;
776         case ARG_BOTTOMANIMALS:
777             b->num_bottom_animals = atoi(optarg);
778             break;
779         case ARG_OGG:
780             s->type = TYPE_OGG;
781             break;
782         case ARG_BG_SOLID:
783             bg->type = BG_SOLID;
784             bg->desktop = 0;
785             break;
786         case ARG_BG_SHADED:
787             bg->type = BG_SHADED;
788             bg->desktop = 0;
789             break;
790         case ARG_BG_WATERALIKE:
791             bg->type = BG_WATER;
792             bg->desktop = 0;
793             break;
794         case ARG_BG_IMAGE:
795             bg->type = BG_IMAGE;
796             bg->desktop = 0;
797             break;
798         case ARG_LCR:
799             bg->solid_c.r = bg->shaded_bot_c.r = atoi(optarg);
800             break;
801         case ARG_LCG:
802             bg->solid_c.g = bg->shaded_bot_c.g = atoi(optarg);
803             break;
804         case ARG_LCB:
805             bg->solid_c.b = bg->shaded_bot_c.b = atoi(optarg);
806             break;
807         case ARG_UCR:
808             bg->shaded_top_c.r = atoi(optarg);
809             break;
810         case ARG_UCG:
811             bg->shaded_top_c.g = atoi(optarg);
812             break;
813         case ARG_UCB:
814             bg->shaded_top_c.b = atoi(optarg);
815             break;
816         case ARG_BG_IMAGE_FILE:
817             bg->imagename = g_strdup_printf(optarg);
818             break;
819         case ARG_RANDOM:
820             f->type = RANDOM_FISH;
821             break;
822         case ARG_SELECTED:
823             f->type = SELECTION_FISH;
824             break;
825         case ARG_RANDOM_POP:
826             f->num_fish = atoi(optarg);
827             break;
828         case ARG_FISH1:
829             f->fish1 = atoi(optarg);
830             break;
831         case ARG_FISH2:
832             f->fish2 = atoi(optarg);
833             break;
834         case ARG_FISH3:
835             f->fish3 = atoi(optarg);
836             break;
837         case ARG_FISH4:
838             f->fish4 = atoi(optarg);
839             break;
840         case ARG_FISH5:
841             f->fish5 = atoi(optarg);
842             break;
843         case ARG_FISH6:
844             f->fish6 = atoi(optarg);
845             break;
846         case ARG_BLOWFISH:
847             f->blowfish = atoi(optarg);
848             break;
849         case ARG_SWORDFISH:
850             f->swordfish = atoi(optarg);
851             break;
852         case ARG_BDWELLER:
853             f->bdweller = atoi(optarg);
854             break;
855         case ARG_FILLMORE:
856             f->fillmore = atoi(optarg);
857             break;
858         case ARG_SHERMAN:
859             f->sherman = atoi(optarg);
860             break;
861         case ARG_MEGAN:
862             f->megan = atoi(optarg);
863             break;
864         case ARG_HUNTER:
865             f->hunter = atoi(optarg);
866             break;
867         case ARG_PREY:
868             f->prey = atoi(optarg);
869             break;
870         case ARG_LORI:
871             f->lori = atoi(optarg);
872             break;
873         case ARG_ERNEST:
874             f->ernest = atoi(optarg);
875             break;
876         case ARG_SQUID:
877             f->squid = atoi(optarg);
878             break;
879         case ARG_HAWTHORNE:
880             f->hawthorne = atoi(optarg);
881             break;
882         case ARG_EAT:
883             f->eat = 1;
884             break;
885         case ARG_EXPLODE:
886             f->explode = 1;
887             break;
888         case ARG_REBIRTH:
889             f->rebirth = 1;
890             break;
891         case ARG_SCALEDIFF:
892             f->scale_diff = 1;
893             break;
894         case ARG_SPEED:
895             f->speed = atoi(optarg);
896             break;
897         case ARG_SCALE:
898             f->scale = atoi(optarg);
899         case ARG_HUNTERA:
900             f->hunter_agr = atoi(optarg);
901             break;
902         case ARG_SWORDA:
903             f->swordfish_agr = atoi(optarg);
904             break;
905         case ARG_SOUNDPRG:
906             s->prg = g_strdup_printf(optarg);
907             break;
908         case ARG_WINDOW_ID:
909             window_id = atoi(optarg);
910             break;
911         case ARG_FULLSCREEN:
912             fullscreen = 1;
913             break;
914         case ARG_BUBBLE:
915             bub->max_bubbles = atoi(optarg);
916             break;
917         case ARG_VIEW:
918             view = atoi(optarg);
919             break;
920         case ARG_DESKTOP:
921             bg->type = 0;
922             bg->desktop = 1;
923             break;
924         case ARG_COMICS:
925             comics = TRUE;
926             comics_prepare(IMAGE_PATH "/strips");
927             break;
928         case ARG_COMICS_DELAY:
929             comics_delay = atoi(optarg);
930             break;
931         case ARG_COMICS_DIR:
932             comics_clean();
933             comic_start = 0;
934             comic_buff = g_strdup(optarg);
935             for(i=0;i<strlen(optarg);i++){
936                 if(comic_buff[i] == ';'){
937                     comic_buff[i] = '\0';
938                     comics_prepare(comic_buff+comic_start);
939                     comic_start = i+1;
940                 }
941             }
942             comics_prepare(comic_buff+comic_start);
943             g_free(comic_buff);
944
945             break;
946         default:
947             break;
948         }
949     }
950
951     numfish += f->fish1;
952     numfish += f->fish2;
953     numfish += f->fish3;
954     numfish += f->fish4;
955     numfish += f->fish5;
956     numfish += f->fish6;
957     numfish += f->swordfish;
958     numfish += f->blowfish;
959     numfish += f->fillmore;
960     numfish += f->sherman;
961     numfish += f->prey;
962     numfish += f->hunter;
963     numfish += f->lori;
964     numfish += f->ernest;
965     numfish += f->squid;
966     numfish += f->megan;
967     numfish += f->bdweller;
968     numfish += f->hawthorne;
969
970     if(f->type == SELECTION_FISH)
971         f->num_fish = numfish;
972
973 }
974
975
976 int main(int argc, char **argv)
977 {
978     gdk_init(&argc, &argv);
979
980     ad.rnd = g_rand_new();
981
982     screensaver_init_param(argc, argv);
983     screensaver_init(0);
984
985     if(window_id==-1){
986             screensaver_main_sdl();
987     }
988     else{
989             screensaver_main_gdk();
990     }
991     return 0;
992 }
993
994
995 AquariumData *aquarium_get_settings_ptr(void)
996 {
997     return &ad;
998 }
999
1000 unsigned char *aquarium_install_path(void)
1001 {
1002     return IMAGE_PATH;
1003 }
1004
1005
1006 void aquarium_draw_image(int x, int y, int idx, int rev, SA_Image *image)
1007 {
1008     if(window_id==-1)
1009         screensaver_draw_image(x, y, idx, rev, image);
1010     else
1011         draw_image(x, y, idx, rev, image);
1012 }
1013
1014 void aquarium_draw_pic_alpha(SA_Image *image, int w, int h, int x, int y, int idx, int alpha)
1015 {
1016     if(window_id==-1)
1017         screensaver_draw_image(x, y, idx, 0, image);
1018     else
1019         draw_pic_alpha(image->image, w, h, x, y, idx,alpha);
1020
1021
1022
1023 void aquarium_clean_image(int x, int y, int w, int h)
1024 {
1025     if(window_id==-1)
1026         screensaver_clean(x, y, w, h);
1027 }
1028
1029 GdkPixbuf *gai_load_image(char *fname)
1030 {
1031     GError *msg = NULL;
1032     GdkPixbuf *pix;
1033     char *full_name;
1034
1035     full_name = g_strdup_printf("%s/%s",IMAGE_PATH,fname);
1036     pix = gdk_pixbuf_new_from_file(full_name, &msg);
1037     if(!pix){
1038         printf("%s\n",msg->message);
1039         exit(1);
1040     }
1041     g_free(full_name);
1042
1043     return pix;
1044     
1045 }
1046 void gai_display_error_continue(char *msg)
1047 {
1048     printf(" *** Error: %s\n",msg);
1049 }