PageRenderTime 70ms CodeModel.GetById 33ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/visualizations/Goom/goom2k4-0/sdl-goom/sdl_goom.c

http://github.com/xbmc/xbmc
C | 746 lines | 564 code | 113 blank | 69 comment | 114 complexity | 726524981df931bf4ee2059918f4f3dd MD5 | raw file
  1#include <glib.h>
  2#include <gtk/gtk.h>
  3#include "goom_config.h"
  4
  5#include <SDL.h>
  6#include <SDL_thread.h>
  7
  8#include <string.h>
  9#include <stdlib.h>
 10#include <stdio.h>
 11#include <unistd.h>
 12#include <sys/time.h>
 13#include <sys/types.h>
 14
 15#include "goom_tools.h"
 16#include "goom.h"
 17
 18#include "frame_rate_tester.h"
 19#include "gmtimer.h"
 20
 21#include "pixeldoubler.h"
 22#include "sdl_pixeldoubler.h"
 23
 24#include "readme.c"
 25
 26#include "gtk-support.h"
 27#include "gtk-interface.h"
 28
 29#include "sdl_goom.h"
 30
 31static SdlGoom sdlGoom;
 32
 33//#define BENCHMARK_X86
 34#ifdef BENCHMARK_X86
 35#include <stdint.h>
 36static uint64_t GetTick()
 37{
 38  uint64_t x;
 39  /* __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));*/
 40  asm volatile ("RDTSC" : "=A" (x));
 41  return x;
 42}
 43#endif
 44
 45/**
 46 * Callback des parametres
 47 */
 48static void screen_size_changed (PluginParam *);
 49static void fps_limit_changed (PluginParam *);
 50static void pix_double_changed (PluginParam *);
 51static void hide_cursor_changed (PluginParam *);
 52
 53/** 
 54 * Initialise les parametres de la version SDL
 55 */
 56static void init_parameters() {
 57
 58	static char *resolutions[4] = {"320x240","400x300","640x480","800x600"};
 59    static struct ListVal reslist = {
 60        value:0,
 61        nbChoices:4,
 62        choices:resolutions
 63    };
 64
 65	sdlGoom.screen_size = secure_param ();
 66	sdlGoom.screen_size.name = "Window's Size:";
 67	sdlGoom.screen_size.desc = "";
 68	sdlGoom.screen_size.type = PARAM_LISTVAL;
 69	sdlGoom.screen_size.param.slist = reslist;
 70	sdlGoom.screen_size.changed = screen_size_changed;
 71    set_list_param_value(&sdlGoom.screen_size, "400x300");
 72
 73	sdlGoom.fps_limit = secure_param ();
 74	sdlGoom.fps_limit.name = "Frame Rate:";
 75	sdlGoom.fps_limit.desc = "";
 76	sdlGoom.fps_limit.type = PARAM_INTVAL;
 77	sdlGoom.fps_limit.param.ival.min = 1;
 78	sdlGoom.fps_limit.param.ival.max = 35;
 79	sdlGoom.fps_limit.param.ival.value = 30;
 80	sdlGoom.fps_limit.param.ival.step = 1;
 81	sdlGoom.fps_limit.changed = fps_limit_changed;
 82
 83	sdlGoom.pix_double = secure_param ();
 84	sdlGoom.pix_double.name = "Double Pixel";
 85	sdlGoom.pix_double.type = PARAM_BOOLVAL;
 86	sdlGoom.pix_double.changed = pix_double_changed;
 87	BVAL(sdlGoom.pix_double) = 0;
 88
 89	sdlGoom.hide_cursor = secure_param ();
 90	sdlGoom.hide_cursor.name = "Hide Cursor";
 91	sdlGoom.hide_cursor.type = PARAM_BOOLVAL;
 92	sdlGoom.hide_cursor.changed = hide_cursor_changed;
 93	BVAL(sdlGoom.hide_cursor) = 1;
 94
 95	sdlGoom.display_fps = secure_param ();
 96	sdlGoom.display_fps.name = "Display FPS";
 97	sdlGoom.display_fps.type = PARAM_BOOLVAL;
 98	BVAL(sdlGoom.display_fps) = 0;
 99
100	sdlGoom.screen = plugin_parameters("Display", 7);
101	sdlGoom.screen.params[0]=&sdlGoom.screen_size;
102	sdlGoom.screen.params[1]=&sdlGoom.pix_double;
103	sdlGoom.screen.params[2]=0;
104	sdlGoom.screen.params[3]=&sdlGoom.fps_limit;
105	sdlGoom.screen.params[4]=&sdlGoom.display_fps;
106	sdlGoom.screen.params[5]=0;
107	sdlGoom.screen.params[6]=&sdlGoom.hide_cursor;
108
109	sdlGoom.config_win = 0;
110	sdlGoom.screen_height = 300;
111	sdlGoom.screen_width = 400;
112	sdlGoom.doublepix = 0;
113	sdlGoom.active = 1;
114}
115
116/*
117 * Methodes utilitaires
118 */
119char *sdl_goom_set_doublepix (int dp);
120static void apply_double ();
121
122
123static int resx = 400;
124static int resy = 300;
125static int doublepix = 0;
126static int doubledec = 0;
127
128static int MAX_FRAMERATE = 32;
129static double INTERPIX = 1000.0f / 32;
130
131static SDL_Surface *surface = NULL;
132static int is_fs = 0;
133
134/* static void thread_func (); */
135
136static void sdl_goom_init (int argc, char **argv);
137static void sdl_goom_cleanup ();
138static void sdl_goom_loop ();
139static void sdl_goom_render_pcm (gint16 data[2][512], gchar *title);
140
141static Surface *gsurf2 = NULL;
142static Surface gsurf;
143static char *main_script = NULL;
144static char *init_script = NULL;
145
146static int     fini = 0;
147static int     disable = 0;
148static gint16  snd_data[2][512];
149
150#include <signal.h>
151
152void on_kill(int i) {
153  fini    = 1;
154  disable = 1;
155}
156
157int main (int argc, char **argv) {
158
159	gtk_set_locale ();
160	gtk_init (&argc, &argv);
161
162	sdl_goom_init(argc, argv);
163  signal(SIGQUIT, on_kill);
164	sdl_goom_loop();
165	sdl_goom_cleanup();
166	return 0;
167}
168
169static char *load_file(const char *fname)
170{
171    FILE *f = fopen(fname, "rt");
172    long size;
173    char *sc;
174
175    if (!f) {
176        fprintf(stderr, "Could not load file %s\n", fname);
177        return "";
178    }
179    
180    fseek(f, 0L, SEEK_END);
181    size = ftell(f);
182    rewind(f);
183    sc = (char*)malloc(size+1);
184    fread(sc,1,size,f);
185    sc[size] = 0;
186    fclose(f);
187    printf("%s loaded\n", fname);
188    return sc;
189}
190
191static void display_help()
192{
193    printf("usage: goom2 <init_script> <main_script>\n");
194}
195
196static void check_arg(int argc, char *argv)
197{
198    static int has_init = 0;
199    static int has_main = 0;
200
201    if (argv[0] == '-') {
202        if ((!strcmp(argv,"-h"))||(!strcmp(argv,"--help"))) {
203            display_help();
204            exit(0);
205        }
206    }
207    else if (!has_init) {
208        init_script = load_file(argv);
209        has_init = 1;
210    }
211    else if (!has_main) {
212        main_script = load_file(argv);
213        has_main = 1;
214    }
215}
216
217void sdl_goom_init (int argc, char **argv)
218{
219	gint16  data[2][512];
220	int     i;
221    int init_flags = SDL_INIT_VIDEO;
222
223    for (i=1; i<argc; ++i) {
224        check_arg(i,argv[i]);
225    }
226
227	init_parameters();
228
229#ifdef VERBOSE
230	printf ("--> INITIALIZING GOOM\n");
231#endif
232
233	fini = FALSE;
234#ifdef THIS_MAKES_ATI_CARDS_TO_CRASH__linux__
235  /* This Hack Allows Hardware Surface on Linux */
236  setenv("SDL_VIDEODRIVER","dga",0);
237
238  if (SDL_Init(init_flags) < 0) {
239    printf(":-( Could not use DGA. Try using goom2 as root.\n");
240    setenv("SDL_VIDEODRIVER","x11",1);
241    if (SDL_Init(init_flags) < 0) {
242      fprintf(stderr, "SDL initialisation error:  %s\n", SDL_GetError());
243      exit(1);
244    }
245  }
246  else {
247    printf(":-) DGA Available !\n");
248    SDL_WM_GrabInput(SDL_GRAB_ON);
249  }
250#else
251  if ( SDL_Init(init_flags) < 0 ) {
252    fprintf(stderr, "SDL initialisation error:  %s\n", SDL_GetError());
253    exit(1);
254  }
255#endif
256	surface = SDL_SetVideoMode (resx, resy, 32,
257								SDL_RESIZABLE|SDL_SWSURFACE);
258	SDL_WM_SetCaption ("What A Goom!!", NULL);
259	SDL_ShowCursor (0);
260	SDL_EnableKeyRepeat (0, 0);
261  atexit(SDL_Quit);
262
263	apply_double ();
264	sdlGoom.plugin = goom_init (resx, resy);
265
266    /*if (init_script != NULL) {
267        gsl_ex(sdlGoom.plugin, init_script);
268    }
269
270    if (main_script != NULL) {
271        goom_set_main_script(sdlGoom.plugin, main_script);
272    }*/
273
274	for (i = 0; i < 512; i++) {
275		data[0][i] = 0;
276		data[1][i] = 0;
277	}
278
279	framerate_tester_init ();
280}
281
282/* retourne x>>s , en testant le signe de x */
283#define ShiftRight(_x,_s) ((_x<0) ? -(-_x>>_s) : (_x>>_s))
284
285static void
286sdl_goom_loop()
287{
288	static double tnext = 0;
289	static gint16 prev0 = 0;
290	static int     i, j;
291  gchar *ptitle = NULL;
292  static char title[2048];
293
294	if (tnext < 0.01)
295		tnext = INTERPIX + SDL_GetTicks();
296
297	while (!fini) {
298		double t;
299		sdl_goom_render_pcm (snd_data, ptitle);
300    ptitle = NULL;
301
302		/* load the sound data */
303		{
304			fd_set rfds;
305			struct timeval tv;
306			int retval;
307
308			tv.tv_sec = 0;
309			tv.tv_usec = 10;
310
311			FD_ZERO(&rfds);
312			FD_SET(0, &rfds);
313			retval = select(1, &rfds, NULL, NULL, &tv);
314
315			if (retval) {
316        int type;
317        read (0, &type, sizeof(int));
318        switch (type) {
319          case 0:
320            read (0, snd_data, 512*2*2);
321            break;
322          case 1:
323            read (0, title, 2048);
324            ptitle = &title[0];
325            break;
326          case 2:
327            fini = 1;
328            disable = TRUE;
329            break;
330        }
331      }
332		}
333
334		if (prev0 == snd_data[0][0]) {
335			for (i = 0; i < 2; i++)
336				for (j = 0; j < 512; j++)
337					snd_data[i][j] = ShiftRight((snd_data[i][j] * 31),5);
338		}
339		prev0 = snd_data[0][0];
340
341		t = SDL_GetTicks();
342		if (t < tnext) {
343			float t2s = (tnext-t);
344			while (t2s>20) {
345				usleep(20*1000);
346				gtk_main_iteration_do(FALSE);
347				t = SDL_GetTicks();
348				t2s = tnext-t;
349			}
350			tnext += INTERPIX;
351		}
352		else {
353			tnext = t+INTERPIX;
354		}
355		i = 0;
356		while (gtk_main_iteration_do(FALSE) == TRUE) {
357			if (i++ > 10)
358				break;
359		}
360	}
361	/*  else {
362	 *    gtk_main_quit();
363	 *  }
364	 */
365}
366
367static void
368sdl_goom_cleanup (void)
369{
370#ifdef VERBOSE
371	printf ("--> CLEANUP GOOM\n");
372#endif
373
374	if (is_fs) {
375		SDL_WM_ToggleFullScreen (surface);
376	}
377	SDL_Quit ();
378
379	goom_close (sdlGoom.plugin);
380	framerate_tester_close ();
381}
382
383
384/*===============================*/
385
386static void apply_double () {
387
388	if (gsurf2) surface_delete (&gsurf2);
389	if (!doublepix)
390		return;
391
392	if (surface->format->BytesPerPixel == 4)
393		doublepix = 2;
394	else
395		doublepix = 1;
396
397	if (doublepix==2) {
398		resx /= 2;
399		resy /= 2;
400		doubledec = 0;
401	}
402	else if (doublepix == 1) {
403		doubledec = resx % 32;
404		resx = resx - doubledec;
405		resx /= 2;
406		resy /= 2;
407		doubledec /= 2;
408		gsurf2 = surface_new (resx*2,resy*2);
409	}
410
411	gsurf.width = resx;
412	gsurf.height = resy;
413	gsurf.size = resx*resy;
414}
415
416
417static char * resize_win (int w, int h, int force) {
418	static char s[256];
419	if ((w != sdlGoom.screen_width)||(h != sdlGoom.screen_height)||force) {
420		static SDL_Event e;
421		e.resize.type = SDL_VIDEORESIZE;
422		e.resize.w = w;
423		e.resize.h = h;
424		SDL_PushEvent (&e);
425	}
426	sprintf (s,"%dx%d",w,h);
427	return s;
428}
429
430static void
431sdl_goom_render_pcm (gint16 data[2][512], gchar *title)
432{
433#ifdef BENCHMARK_X86
434  uint64_t t0,t1,t2;
435#endif
436	static char *msg_tab[] = {
437		"What a GOOM! version " VERSION
438		  "\n\n\n\n\n\n\n\n"
439		  "an iOS sotfware production.\n"
440		  "\n\n\n"
441		  "http://www.ios-software.com/",
442		goom_readme,
443		goom_big_readme,
444		"Copyright (c)2000-2004, by Jeko"
445	};
446	static int msg_pos = 0;
447#define ENCORE_NUL_LOCK (32*200)
448	static int encore_nul = 0;
449
450	guint32 *buf;
451	SDL_Surface *tmpsurf = NULL;
452
453	/* static int spos = -1; */
454
455	gchar  *message = NULL;
456
457	/* TODO : Utiliser une commande dans le pipe *
458	 * int     pos = xmms_remote_get_playlist_pos (jeko_vp.xmms_session);
459	 */
460
461	int forceMode = 0;
462
463#define NBresoli 11
464	static int resoli = 7;
465	static int resolx[] = {320,320,400,400,512,512,640,640,640,800,800};
466	static int resoly[] = {180,240,200,300,280,384,320,400,480,400,600};
467
468	int i;
469	SDL_Event event;
470
471	/* Check for events */
472	while (SDL_PollEvent (&event)) {	/* Loop until there are no events left on 
473										 * the queue */
474		switch (event.type) { /* Process the appropiate event type */
475			case SDL_QUIT:
476				{
477					fini = 1;
478					disable = TRUE;
479				}
480				break;
481
482			case SDL_ACTIVEEVENT:
483				if (event.active.state & SDL_APPACTIVE)
484					sdlGoom.active = event.active.gain;
485				break;
486
487			case SDL_KEYDOWN: /* Handle a KEYDOWN event */
488				if (event.key.keysym.sym == SDLK_TAB) {
489					SDL_WM_ToggleFullScreen (surface);
490					is_fs = !is_fs;
491				}
492
493				if (event.key.keysym.sym == SDLK_q) {
494					fini = 1;
495				}
496                /*
497                 * TODO : GERER TOUT CA AVEC XMMS REMOTE CTRL ? ou le pipe *
498                 if (event.key.keysym.sym == SDLK_q) {
499                 xmms_remote_quit (jeko_vp.xmms_session);
500                 }
501
502                 if (event.key.keysym.sym == SDLK_x)
503                 xmms_remote_play (jeko_vp.xmms_session);
504                 if (event.key.keysym.sym == SDLK_c)
505                 xmms_remote_pause (jeko_vp.xmms_session);
506                 if (event.key.keysym.sym == SDLK_v)
507                 xmms_remote_stop (jeko_vp.xmms_session);
508                 if (event.key.keysym.sym == SDLK_b)
509                 xmms_remote_playlist_next (jeko_vp.xmms_session);
510                 if (event.key.keysym.sym == SDLK_z)
511                 xmms_remote_playlist_prev (jeko_vp.xmms_session);
512                 */
513
514				if (event.key.keysym.sym == SDLK_f) {
515					BVAL(sdlGoom.display_fps) = !BVAL(sdlGoom.display_fps);
516					sdlGoom.display_fps.change_listener(&sdlGoom.display_fps);
517				}
518
519				if ((event.key.keysym.sym == SDLK_KP_PLUS) && (resoli+1<NBresoli)) {
520					resoli = resoli+1;
521					resize_win (resolx[resoli],resoly[resoli],FALSE);
522				}
523				if ((event.key.keysym.sym == SDLK_KP_MINUS) && (resoli>0)) {
524					resoli = resoli-1;
525					resize_win (resolx[resoli],resoly[resoli],FALSE);
526				}
527
528				if (event.key.keysym.sym == SDLK_KP_MULTIPLY) {
529					title = sdl_goom_set_doublepix (!doublepix);
530				}
531				if (event.key.keysym.sym == SDLK_ESCAPE) {
532          if (is_fs) {
533  					SDL_WM_ToggleFullScreen (surface);
534	  				is_fs = !is_fs;
535          }
536          else if (sdlGoom.config_win == 0) {
537						sdlGoom.config_win = create_config_window ();
538						gtk_data_init (&sdlGoom);
539						gtk_widget_show (sdlGoom.config_win);
540						message = "";
541					}
542					else {
543						message = "Configuration Window is Already Open";
544					}
545				}
546				if (event.key.keysym.sym == SDLK_SPACE) {
547					encore_nul = ENCORE_NUL_LOCK;
548				}
549
550				if (event.key.keysym.sym == SDLK_F1)
551					forceMode = 1;
552				if (event.key.keysym.sym == SDLK_F2)
553					forceMode = 2;
554				if (event.key.keysym.sym == SDLK_F3)
555					forceMode = 3;
556				if (event.key.keysym.sym == SDLK_F4)
557					forceMode = 4;
558				if (event.key.keysym.sym == SDLK_F5)
559					forceMode = 5;
560				if (event.key.keysym.sym == SDLK_F6)
561					forceMode = 6;
562				if (event.key.keysym.sym == SDLK_F7)
563					forceMode = 7;
564				if (event.key.keysym.sym == SDLK_F8)
565					forceMode = 8;
566				if (event.key.keysym.sym == SDLK_F9)
567					forceMode = 9;
568				if (event.key.keysym.sym == SDLK_F10)
569					forceMode = 10;
570
571				break;
572			case SDL_VIDEORESIZE:
573				resx = sdlGoom.screen_width = event.resize.w;
574				resy = sdlGoom.screen_height = event.resize.h;
575				sdlGoom.doublepix = doublepix;
576				{
577					static char s[512];
578					sprintf (s,"%dx%d",resx,resy);
579					title = s;
580					set_list_param_value(&sdlGoom.screen_size, s);
581					sdlGoom.screen_size.change_listener (&sdlGoom.screen_size);
582				}
583				surface = SDL_SetVideoMode (resx, resy, 32,
584											SDL_RESIZABLE|SDL_SWSURFACE);
585				apply_double();
586				goom_set_resolution (sdlGoom.plugin,resx, resy);
587				if (is_fs)
588					SDL_WM_ToggleFullScreen (surface);
589				break;
590				/* default:	* Report an unhandled event */
591				/* printf("I don't know what this event is!\n"); */
592		}
593	}
594
595	for (i=0;i<512;i++)
596		if (data[0][i]>2) {
597			if (encore_nul > ENCORE_NUL_LOCK)
598				encore_nul = 0;
599			break;
600		}
601
602	if ((i == 512) && (!encore_nul))
603		encore_nul = ENCORE_NUL_LOCK + 100;
604
605	if (encore_nul == ENCORE_NUL_LOCK) {
606		message = msg_tab[msg_pos];
607		msg_pos ++;
608		msg_pos %= 4;
609	}
610
611	if (encore_nul)
612		encore_nul --;
613
614	if (!sdlGoom.active) {
615		return;
616	}
617
618	/*
619	 *  TODO:
620	 *  if (pos != spos) {
621	 *    title = xmms_remote_get_playlist_title (jeko_vp.xmms_session, pos);
622	 *    spos = pos;
623	 *  }
624	 */
625
626#ifdef BENCHMARK_X86
627  t0 = GetTick();
628#endif
629  if (doublepix == 0)
630    goom_set_screenbuffer(sdlGoom.plugin, surface->pixels);
631
632	buf = goom_update (sdlGoom.plugin, data, forceMode,
633					   BVAL(sdlGoom.display_fps)?framerate_tester_getvalue ():-1,
634					   title, message);
635
636#ifdef BENCHMARK_X86
637  t1 = GetTick();
638#endif
639
640	if (doublepix == 2) {
641		gsurf.buf = buf;
642		sdl_pixel_doubler (&gsurf,surface);
643	} else if (doublepix == 1) {
644		SDL_Rect rect;
645		gsurf.buf = buf;
646		pixel_doubler (&gsurf,gsurf2);
647		tmpsurf =
648		  SDL_CreateRGBSurfaceFrom (gsurf2->buf, resx*2, resy*2,
649									32, resx*8,
650									0x00ff0000, 0x0000ff00, 0x000000ff,
651									0x00000000);
652		rect.x = doubledec;
653		rect.y = 0;
654		rect.w = resx * 2;
655		rect.h = resy * 2;
656		SDL_BlitSurface (tmpsurf, NULL, surface, &rect);
657		SDL_FreeSurface (tmpsurf);
658	}
659	else {
660/*    tmpsurf =
661      SDL_CreateRGBSurfaceFrom (buf, resx, resy, 32, resx * 4,
662                                0x00ff0000, 0x0000ff00, 0x000000ff,
663                                0x00000000);
664    SDL_BlitSurface (tmpsurf, NULL, surface, NULL);
665    SDL_FreeSurface (tmpsurf);
666    SDL_LockSurface(surface);
667    memcpy(surface->pixels, buf, resx * resy * 4);
668    SDL_UnlockSurface(surface);
669*/
670	}
671	SDL_Flip (surface);
672#ifdef BENCHMARK_X86
673  t2 = GetTick();
674
675  t2 -= t1;
676  t1 -= t0;
677  {
678    double ft1, ft2;
679    static double min_t1 = 1000.0,
680                  min_t2 = 1000.0;
681    static double moy_t1 = 150.0;
682    static double moy_t2 = 40.0;
683
684    ft1 = (double)(t1 / sdlGoom.plugin->screen.size);
685    ft2 = (double)(t2 / sdlGoom.plugin->screen.size);
686
687    if (ft1 < min_t1)
688      min_t1 = ft1;
689    if (ft2 < min_t2)
690      min_t2 = ft2;
691
692    moy_t1 = ((moy_t1 * 15.0) + ft1) / 16.0;
693    moy_t2 = ((moy_t2 * 15.0) + ft2) / 16.0;
694    printf("UPDATE = %4.0f/%3.0f CPP ", moy_t1, min_t1);
695    printf("DISPLAY = %4.0f/%3.0f CPP\n", moy_t2, min_t2);
696  }
697#endif
698
699	framerate_tester_newframe ();
700}
701
702
703char *sdl_goom_set_doublepix (int dp) {
704	if (doublepix && dp) return " ";
705	if (!doublepix && !dp) return " ";
706
707	doublepix = dp;
708	BVAL(sdlGoom.pix_double) = dp;
709	sdlGoom.pix_double.change_listener(&sdlGoom.pix_double);
710	if (doublepix)
711		return resize_win (resx,resy,TRUE);
712	else
713		return resize_win (resx*2,resy*2,TRUE);
714}
715
716void sdl_goom_set_fps (int fps) {
717	MAX_FRAMERATE = fps;
718	INTERPIX = 1000.0 / MAX_FRAMERATE;
719}
720
721void pix_double_changed (PluginParam *p) {
722	sdl_goom_set_doublepix (BVAL(*p));
723}
724
725void screen_size_changed (PluginParam *p) {
726	int i;
727	static struct Resol { char*name; int x; int y; } res[4] = {
728		{"320x240", 320, 240},
729		{"400x300", 400, 300},
730		{"640x480", 640, 480},
731		{"800x600", 800, 600}};
732
733		for (i=4;i--;) {
734			if (!strcmp(LVAL(*p),res[i].name))
735				resize_win (res[i].x,res[i].y,FALSE);
736		}
737}
738
739void fps_limit_changed (PluginParam *p) {
740	MAX_FRAMERATE = IVAL(*p);
741	INTERPIX = 1000.0 / MAX_FRAMERATE;
742}
743
744void hide_cursor_changed (PluginParam *p) {
745	SDL_ShowCursor(!BVAL(*p));
746}