// This function takes a small screenshot at the specified position, checks for
// the magic pattern, and then fills in the measurement struct with data
// decoded from the pixels of the pattern. Returns true if successful, false
// if the screenshot failed or the magic pattern was not present.
static bool read_data_from_screen(uint32_t x, uint32_t y,
  const uint8_t magic_pattern[], measurement_t *out) {
  assert(out);
  screenshot *screenshot = take_screenshot(x, y, pattern_pixels, 1);
  if (!screenshot) {
    return false;
  }
  if (screenshot->width != pattern_pixels) {
    free_screenshot(screenshot);
    return false;
  }
  // Check that the magic pattern is there, starting at the first pixel.
  size_t found_x, found_y;
  if (!find_pattern(magic_pattern, screenshot, &found_x, &found_y) ||
    found_x || found_y) {
    free_screenshot(screenshot);
    return false;
  }
  out->javascript_frames = screenshot->pixels[pattern_magic_pixels * 4 + 0];
  out->key_down_events = screenshot->pixels[pattern_magic_pixels * 4 + 1];
  out->test_mode = (test_mode_t) screenshot->pixels[pattern_magic_pixels * 4 + 2];
  out->scroll_position = screenshot->pixels[(pattern_magic_pixels + 1) * 4];
  out->css_frames = screenshot->pixels[(pattern_magic_pixels + 2) * 4];
  out->screenshot_time = screenshot->time_nanoseconds;
  free_screenshot(screenshot);
  debug_log("javascript frames: %d, javascript events: %d, scroll position: %d"
      ", css frames: %d, test mode: %d", out->javascript_frames,
      out->key_down_events, out->scroll_position, out->css_frames,
      out->test_mode);
  return true;
}
Exemple #2
0
void OpenglApplication::handle_event( const SDL_Event& event )
{
    camera_control.handle_event( this, event );

    // open to add more event handlers
    switch ( event.type )
    {
    case SDL_KEYDOWN:
        switch ( event.key.keysym.sym )
        {
        case KEY_SCREENSHOT:
            take_screenshot();
            break;
		case KEY_PAUSE:
			isUpdateAll = !isUpdateAll;
			project.modifyWaterStatus(isUpdateAll);
			break;
		case KEY_MESH:
			isMeshOnly = !isMeshOnly;
			project.modifyMesh(isMeshOnly);
			break;
		case KEY_TRANSPARENT:
			isTransparent = !isTransparent;
			project.modifyTransparency(isTransparent);
        default:
            break;
        }
    default:
        break;
    }
}
Exemple #3
0
static void
on_screenshot_clicked (GtkToolButton *ssbt, void *user_data)
{
    char * fname = get_unique_filename (NULL, "viewer", 1, "ppm");
    take_screenshot (user_data, fname);
    free (fname);
}
Exemple #4
0
void PhysicsApplication::handle_event( const SDL_Event& event )
{
    camera_control.handle_event( this, event );

    switch ( event.type )
    {
    case SDL_KEYDOWN:
        switch ( event.key.keysym.sym )
        {
        case KEY_SCREENSHOT:
            take_screenshot();
            break;
        case SDLK_UP:
            speed *= 2;
            break;
        case SDLK_DOWN:
            speed /= 2;
            break;
        case SDLK_SPACE:
            pause = !pause;
            break;
        default:
            break;
        }
    default:
        break;
    }
}
DBusHandlerResult dbus_handler (DBusConnection *bus,
                                DBusMessage    *message,
                                void           *user_data)
{
  if (dbus_message_is_signal (message, "org.gnome.ScreenshotGrabber",
                              "take_screenshot"))
    {
      take_screenshot ();
      DBUS_HANDLER_RESULT_HANDLED; 
    }
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
int
main (int    argc,
      char **argv)
{
  int             ret;
  DBusConnection *bus;
  DBusMessage    *msg;
  DBusError       err = {0};

  gtk_init (&argc, &argv);

  bus = dbus_bus_get (DBUS_BUS_SESSION, &err);
  if (dbus_error_is_set (&err))
    goto exit;

  ret = dbus_bus_request_name (bus, "org.gnome.ScreenshotGrabber",
                               DBUS_NAME_FLAG_DO_NOT_QUEUE, &err);
  if (dbus_error_is_set (&err))
    goto exit;

  if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    {
      msg = dbus_message_new_signal ("/org/gnome/ScreenshotGrabber",
                                     "org.gnome.ScreenshotGrabber",
                                     "take_screenshot");
      dbus_connection_send (bus, msg, NULL);
      dbus_message_unref (msg);
      return 0;
    }

  dbus_connection_setup_with_g_main (bus, NULL);

  dbus_bus_add_match (bus, "type='signal',"
      "interface='org.gnome.ScreenshotGrabber',"
      "path='/org/gnome/ScreenshotGrabber'", &err);
  if (dbus_error_is_set (&err))
    goto exit;
  dbus_connection_add_filter (bus, dbus_handler, NULL, NULL);

  take_screenshot ();

  gtk_main ();

exit:
  if (dbus_error_is_set (&err))
    {
      fprintf (stderr, "[E] DBus: %s\n", err.message);
      dbus_error_free (&err);
    }

  return 0;
}
Exemple #7
0
int  vid_screenshot(char *filename)
{
	unsigned long drv;
	char id[10];
	char * fn = filename;
	if (fn == NULL) {
		fn = screenshot_filename("gnuboy.bmp");
	}
	printf("Saving screenshot %s...\n", fn);
	if (take_screenshot(fn, (void*)0xAC202800) == 0) {
		printf("Screenshot capture failed\n");
	}
}
Exemple #8
0
/* Renders one frame and handles the SDL window */
void
pn_render (void)
{
  SDL_Event event;

  /* Handle window events */
  while (SDL_PollEvent (&event))
    {
      switch (event.type)
	{
	case SDL_QUIT:
	  pn_quit ();
	  g_assert_not_reached ();
	case SDL_KEYDOWN:
	  switch (event.key.keysym.sym)
	    {
	    case SDLK_ESCAPE:
	      pn_quit ();
	      g_assert_not_reached ();
	    case SDLK_RETURN:
	      if (event.key.keysym.mod & (KMOD_ALT | KMOD_META))
		toggle_fullscreen ();
	      break;
	    case SDLK_BACKQUOTE:
	      take_screenshot ();
	      break;
	    default:
              break;
	    }
	  break;
	case SDL_VIDEORESIZE:
	  resize_video (event.resize.w, event.resize.h);
	  break;
	}
    }

  pn_new_beat = pn_is_new_beat();

  if (pn_rc->actuator)
    {
      exec_actuator (pn_rc->actuator);
      blit_to_screen ();
    }
}
Exemple #9
0
void GlslApplication::handle_event( const SDL_Event& event )
{
    camera_control.handle_event( this, event );

    switch ( event.type )
    {
    case SDL_KEYDOWN:
        switch ( event.key.keysym.sym )
        {
        case KEY_SCREENSHOT:
            take_screenshot();
            break;
        default:
            break;
        }
    default:
        break;
    }
}
Exemple #10
0
void Main::flip(bool no_cap) {
	fps_count();

	if(screenshot_next_flip) {
		take_screenshot();
		screenshot_next_flip = false;
	}

	SDL_Flip(screen);
	frame++;
	if(!no_cap && (fps_cap == true) && (fps->get_ticks() < frame_delay)) {
		SDL_Delay((frame_delay) - fps->get_ticks());
	}

	fps->start();

	if(autoreset) {
		if(frame - last_activity == (unsigned int)FRAMES_UNTIL_RESET) {
			running = false;
			is_reset = true;
		}
	}
}
Exemple #11
0
void main_loop(void)
{
    int neo_emu_done = 0;
    int overclk=CF_VAL(cf_get_item_by_name("overclock"));

    Uint32 cpu_68k_timeslice = (overclk==0?200000:200000+(overclk*200000/100.0));
    Uint32 cpu_68k_timeslice_scanline = cpu_68k_timeslice/262.0;
//    Uint32 cpu_z80_timeslice = 100000;
    Uint32 cpu_z80_timeslice = 73333;
    Uint32 tm_cycle=0;

    /*    Uint32 cpu_z80_timeslice=66666; // is it 4Mhz or 6Mhz ???? 4 seems to work fine....
       UPDATE: it's clear now that it's 6Mhz -> kof96 presentation */

    Uint32 cpu_z80_timeslice_interlace = cpu_z80_timeslice / (float) nb_interlace;
    char ksym_code[5];
    SDL_Event event;
    Uint16 scancode, i, a;
    char input_buf[20];
    Uint8 show_keysym=0;
    CONF_ITEM* item = cf_get_item_by_name("invertjoy");
    int invert_joy = 0;
    if (item)
    	invert_joy=CF_BOOL(item);

    reset_frame_skip();
    my_timer();
    //printf("Cpuspeed: %d\n",cpu_68k_timeslice);
/*
    printf("%s\n",&memory.cpu[0x100]);
    printf("NGH = %04x\n",READ_WORD(&memory.cpu[0x108]));
    printf("SSN = %04x\n",READ_WORD(&memory.cpu[0x114]));
*/

    while (!neo_emu_done) {
	if (conf.test_switch == 1)
	    conf.test_switch = 0;


	while (SDL_PollEvent(&event)) {
	    switch (event.type) {
	    case SDL_JOYAXISMOTION:
		joy_axe[event.jaxis.which][event.jaxis.axis] = event.jaxis.value;
		if (show_keysym) {
		    sprintf(ksym_code, "%d", event.jaxis.axis);
		    draw_message(ksym_code);
		}
		break;

	    case SDL_JOYHATMOTION:
		    switch (event.jhat.value) {
		    case SDL_HAT_CENTERED:
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which]] = 0;
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which] + 1] = 0;
			    break;
			    
		    case SDL_HAT_UP:
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which] + 1] = -32767;
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which]] = 0;
			    break;
			    
		    case SDL_HAT_DOWN:
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which] + 1] = 32767;
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which]] = 0;
			    break;
			    
		    case SDL_HAT_LEFT:
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which]] = -32767;
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which] + 1] = 0;
			    break;
			    
		    case SDL_HAT_RIGHT:
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which]] = 32767;
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which] + 1] = 0;
			    break;
			    
		    case SDL_HAT_RIGHTUP:
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which]] = 32767;
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which] + 1] = -32767;
			    break;
			    
		    case SDL_HAT_RIGHTDOWN:
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which]] = 32767;
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which] + 1] = 32767;
			    break;
			    
		    case SDL_HAT_LEFTUP:
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which]] = -32767;
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which] + 1] = -32767;
			    break;
			    
		    case SDL_HAT_LEFTDOWN:
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which]] = -32767;
			    joy_axe[event.jhat.which][(event.jhat.hat * 2) + joy_numaxes[event.jhat.which] + 1] = 32767;
			    break;
			    
		    }
		    
		    if (show_keysym) {
			    sprintf(ksym_code, "%d", event.jhat.hat);
			    draw_message(ksym_code);
		    }
		    break;


	    case SDL_JOYBUTTONDOWN:
		joy_button[event.jbutton.which][event.jbutton.button] = 1;
		
		if (show_keysym) {
		    sprintf(ksym_code, "%d", event.jbutton.button);
		    draw_message(ksym_code);
		}
		break;
	    case SDL_JOYBUTTONUP:
		joy_button[event.jbutton.which][event.jbutton.button] = 0;
		break;

	    case SDL_KEYUP:
		if (player)
		{
			switch(event.key.keysym.sym)
			{
			case 273:
				key[264] = 0;
				break;
			case 275:
				key[274] = 0;
				break;
			case 274:
				key[261] = 0;
				break;
			case 276:
				key[260] = 0;
				break;
			case 122:
				key[108] = 0;
				break;
			case 120:
				key[59] = 0;
				break;
			case 97:
				key[111] = 0;
				break;
			case 115:
				key[112] = 0;
				break;
			case 49:
				key[50] = 0;
				break;
			case 51:
				key[52] = 0;
				break;
			default:
				key[event.key.keysym.sym] = 0;
				break;
			}
		}
		else
			key[event.key.keysym.sym] = 0;
		break;
	    case SDL_KEYDOWN:
		scancode = event.key.keysym.sym;
		if (show_keysym) {
		    sprintf(ksym_code, "%d", scancode);
		    draw_message(ksym_code);
		}
		if (player)
		{
			switch(scancode)
			{
			case 273:
				key[264] = 1;
				break;
			case 275:
				key[274] = 1;
				break;
			case 274:
				key[261] = 1;
				break;
			case 276:
				key[260] = 1;
				break;
			case 122:
				key[108] = 1;
				break;
			case 120:
				key[59] = 1;
				break;
			case 97:
				key[111] = 1;
				break;
			case 115:
				key[112] = 1;
				break;
			case 49:
				key[50] = 1;
				break;
			case 51:
				key[52] = 1;
				break;
			default:
				key[scancode] = 1;
				break;
			}
		}
		else
			key[scancode] = 1;

		switch (scancode) {
		case SDLK_ESCAPE:
		    neo_emu_done = 1;
#ifdef __QNXNTO__
		    shutdown = 1;
#endif
		    break;	// ESC
/*
		case SDLK_TAB:
		    main_gngeo_gui();
		    break;
*/
		case SDLK_F1:
		    draw_message("Reset");
		    //neogeo_init();
		    cpu_68k_reset();
		    break;
		case SDLK_F2:
		    take_screenshot();
		    draw_message("Screenshot saved");
		    break;
		case SDLK_F3:
		    draw_message("Test Switch ON");
		    conf.test_switch = 1;
		    break;
		case SDLK_F5:
		    show_fps ^= SDL_TRUE;
		    break;
		case SDLK_F4:
		    show_keysym = 1 - show_keysym;
		    if (show_keysym)
			draw_message("Show keysym code : ON");
		    else
			draw_message("Show keysym code : OFF");
		    break;
		case SDLK_F6:
		    slow_motion = 1 - slow_motion;
		    if (slow_motion)
			draw_message("SlowMotion : ON");
		    else {
			draw_message("SlowMotion : OFF");
			reset_frame_skip();
		    }
		    break;
		case SDLK_F7:
		    //screen_set_effect("scanline");
		    if (conf.debug) {
			dbg_step = 1;
		    }
		    break;
		case SDLK_F8: 
		{
		    int val;
		    char *endptr;
		    text_input("Save to slot [0-999]? ",16,227,input_buf,3);
		    val=strtol(input_buf,&endptr,10);
		    if (input_buf != endptr) {
			pending_save_state=val+1;
		    }
		}
		break;
		case SDLK_F9:
		{
		    int val;
		    char *endptr;
		    text_input("Load from slot [0-999]? ",16,227,input_buf,3);
		    val=strtol(input_buf,&endptr,10);
		    if (input_buf != endptr) {
			pending_load_state=val+1;
		    }
		}
		break; 
		case SDLK_F10:
		    autoframeskip ^= SDL_TRUE;
		    if (autoframeskip) {
			reset_frame_skip();
			draw_message("AutoFrameSkip : ON");
		    } else
			draw_message("AutoFrameSkip : OFF");
		    break;
		case SDLK_F11:
		    sleep_idle ^= SDL_TRUE;
		    if (sleep_idle)
			draw_message("Sleep idle : ON");
		    else
			draw_message("Sleep idle : OFF");
		    break;
		case SDLK_F12:
		    screen_fullscreen();
		    break;
#ifdef __QNXNTO__
		case SDLK_F13:
			neo_emu_done = 1;
			break;
		case SDLK_F14:
			if (player)
			{
				key[52] = 0;
				key[50] = 0;
				key[112] = 0;
				key[111] = 0;
				key[59] = 0;
				key[108] = 0;
				key[260] = 0;
				key[261] = 0;
				key[274] = 0;
				key[264] = 0;
			}
			player = !player;
			break;
#endif
		}
		break;
	    case SDL_VIDEORESIZE:
		conf.res_x=event.resize.w;
		conf.res_y=event.resize.h;
		screen_resize(event.resize.w, event.resize.h);
		break;
		case SDL_ACTIVEEVENT:
			if (event.active.state & SDL_APPINPUTFOCUS)
			{
				if (!event.active.gain)
				{
					int J;
					SDL_PauseAudio(1);
					while (1)
					{
						usleep(10000);
						if (SDL_PollEvent(&event))
						{
							if (event.type == SDL_ACTIVEEVENT)
							{
								if (event.active.state & SDL_APPINPUTFOCUS)
								{
									if (event.active.gain)
										break;
								}
							}
							else if (event.type == SDL_QUIT)
							{
								neo_emu_done = 1;
								break;
							}
						}
					}
					SDL_PauseAudio(0);
				    reset_frame_skip();
				}
			}
			break;
		case SDL_USEREVENT:
			reset_frame_skip();
			break;
	    case SDL_QUIT:
		neo_emu_done = 1;
#ifdef __QNXNTO__
		shutdown = 1;
#endif
		break;
	    default:
		break;
	    }
	}

	/* update the internal representation of keyslot */
	update_p1_key();
	update_p2_key();
	update_start();
	update_coin();

	if (slow_motion)
	    SDL_Delay(100);

	if (conf.sound) {
	    PROFILER_START(PROF_Z80);
	    for (i = 0; i < nb_interlace; i++) {
		cpu_z80_run(cpu_z80_timeslice_interlace);
		my_timer();
	    }
	    PROFILER_STOP(PROF_Z80);
	} /*
	    else
	    my_timer();*/

	if (!conf.debug) {
	    if (conf.raster) {
		for (i = 0; i < 261; i++) {
		    tm_cycle=cpu_68k_run(cpu_68k_timeslice_scanline-tm_cycle);
		    if (update_scanline())
			cpu_68k_interrupt(2);
		}
		tm_cycle=cpu_68k_run(cpu_68k_timeslice_scanline-tm_cycle);
		state_handling(pending_save_state,pending_load_state);
		
		update_screen();
		cpu_68k_interrupt(1);
	    } else {
		PROFILER_START(PROF_68K);
		tm_cycle=cpu_68k_run(cpu_68k_timeslice-tm_cycle);
		PROFILER_STOP(PROF_68K);
		a = neo_interrupt();
		
		/* state handling (we save/load before interrupt) */
		state_handling(pending_save_state,pending_load_state);
		
		if (a) {
		    cpu_68k_interrupt(a);
		}
	    }
	} else {
	    /* we arre in debug mode -> we are just here for event handling */
	    neo_emu_done=1;
	}
#ifdef ENABLE_PROFILER
	profiler_show_stat();
#endif
	PROFILER_START(PROF_ALL);
    }
}
// Main test function. Locates the given magic pixel pattern on the screen, then
// runs one full latency test, sending input events and recording responses. On
// success, the results of the test are reported in the output parameters, and
// true is returned. If the test fails, the error parameter is filled in with
// an error message and false is returned.
bool measure_latency(
    const uint8_t magic_pattern[],
    double *out_key_down_latency_ms,
    double *out_scroll_latency_ms,
    double *out_max_js_pause_time_ms,
    double *out_max_css_pause_time_ms,
    double *out_max_scroll_pause_time_ms,
    char **error) {
  screenshot *screenshot = take_screenshot(0, 0, UINT32_MAX, UINT32_MAX);
  if (!screenshot) {
    *error = "Failed to take screenshot.";
    return false;
  }
  assert(screenshot->width > 0 && screenshot->height > 0);

  size_t x, y;
  bool found_pattern = find_pattern(magic_pattern, screenshot, &x, &y);
  free_screenshot(screenshot);
  if (!found_pattern) {
    *error = "Failed to find test pattern on screen.";
    return false;
  }
  uint8_t full_pattern[pattern_bytes];
  for (int i = 0; i < pattern_magic_bytes; i++) {
    full_pattern[i] = magic_pattern[i];
  }
  measurement_t measurement;
  measurement_t previous_measurement;
  memset(&measurement, 0, sizeof(measurement_t));
  memset(&previous_measurement, 0, sizeof(measurement_t));
  int screenshots = 0;
  bool first_screenshot_successful = read_data_from_screen((uint32_t)x,
      (uint32_t) y, magic_pattern, &measurement);
  if (!first_screenshot_successful) {
    *error = "Failed to read data from test pattern.";
    return false;
  }
  if (measurement.test_mode == TEST_MODE_NATIVE_REFERENCE) {
    uint8_t *test_pattern = (uint8_t *)malloc(pattern_bytes);
    memset(test_pattern, 0, pattern_bytes);
    for (int i = 0; i < pattern_magic_bytes; i++) {
      test_pattern[i] = rand();
    }
    if (!open_native_reference_window(test_pattern)) {
      *error = "Failed to open native reference window.";
      return false;
    }
    bool return_value = measure_latency(test_pattern, out_key_down_latency_ms, out_scroll_latency_ms, out_max_js_pause_time_ms, out_max_css_pause_time_ms, out_max_scroll_pause_time_ms, error);
    if (!close_native_reference_window()) {
      debug_log("Failed to close native reference window.");
    };
    return return_value;
  }
  int64_t start_time = measurement.screenshot_time;
  previous_measurement = measurement;
  statistic javascript_frames;
  statistic css_frames;
  statistic key_down_events;
  statistic scroll_stats;
  init_statistic("javascript_frames", &javascript_frames,
      measurement.javascript_frames, start_time);
  init_statistic("key_down_events", &key_down_events,
      measurement.key_down_events, start_time);
  init_statistic("css_frames", &css_frames, measurement.css_frames, start_time);
  init_statistic("scroll", &scroll_stats, measurement.scroll_position,
      start_time);
  int sent_events = 0;
  int scroll_x = x + 40;
  int scroll_y = y + 40;
  int64_t last_scroll_sent = start_time;
  if (measurement.test_mode == TEST_MODE_SCROLL_LATENCY) {
    send_scroll_down(scroll_x, scroll_y);
    scroll_stats.previous_change_time = get_nanoseconds();
  }
  while(true) {
    bool screenshot_successful = read_data_from_screen((uint32_t)x,
        (uint32_t) y, magic_pattern, &measurement);
    if (!screenshot_successful) {
      *error = "Test window moved during test. The test window must remain "
          "stationary and focused during the entire test.";
      return false;
    }
    if (measurement.test_mode == TEST_MODE_ABORT) {
      *error = "Test aborted.";
      return false;
    }
    screenshots++;
    int64_t screenshot_time = measurement.screenshot_time;
    int64_t previous_screenshot_time = previous_measurement.screenshot_time;
    debug_log("screenshot time %f",
        (screenshot_time - previous_screenshot_time) /
            (double)nanoseconds_per_millisecond);
    update_statistic(&javascript_frames, measurement.javascript_frames,
        screenshot_time, previous_screenshot_time);
    update_statistic(&key_down_events, measurement.key_down_events,
        screenshot_time, previous_screenshot_time);
    update_statistic(&css_frames, measurement.css_frames, screenshot_time,
        previous_screenshot_time);
    bool scroll_updated = update_statistic(&scroll_stats,
        measurement.scroll_position, screenshot_time, previous_screenshot_time);

    if (measurement.test_mode == TEST_MODE_JAVASCRIPT_LATENCY) {
      if (key_down_events.measurements >= latency_measurements_to_take) {
        break;
      }
      if (key_down_events.value_delta > sent_events) {
        *error = "More events received than sent! This is probably a bug in "
            "the test.";
        return false;
      }
      if (screenshot_time - key_down_events.previous_change_time >
          event_response_timeout_ms * nanoseconds_per_millisecond) {
        *error = "Browser did not respond to keyboard input. Make sure the "
            "test page remains focused for the entire test.";
        return false;
      }
      if (key_down_events.value_delta == sent_events) {
        // We want to avoid sending input events at a predictable time relative
        // to frames, so introduce a random delay of up to 1 frame (16.67 ms)
        // before sending the next event.
        usleep((rand() % 17) * 1000);
        if (!send_keystroke_z()) {
          *error = "Failed to send keystroke for \"Z\" key to test window.";
          return false;
        }
        key_down_events.previous_change_time = get_nanoseconds();
        sent_events++;
      }
    } else if (measurement.test_mode == TEST_MODE_SCROLL_LATENCY) {
        if (scroll_stats.measurements >= latency_measurements_to_take) {
          break;
        }
        if (screenshot_time - scroll_stats.previous_change_time >
            event_response_timeout_ms * nanoseconds_per_millisecond) {
          *error = "Browser did not respond to scroll events. Make sure the "
              "test page remains focused for the entire test.";
          return false;
        }
        if (scroll_updated) {
          // We saw the start of a scroll. Wait for the scroll animation to
          // finish before continuing. We assume the animation is finished if
          // it's been 100 milliseconds since we last saw the scroll position
          // change.
          int64_t scroll_update_time = screenshot_time;
          int64_t scroll_wait_start_time = screenshot_time;
          while (screenshot_time - scroll_update_time <
                 100 * nanoseconds_per_millisecond) {
            screenshot_successful = read_data_from_screen((uint32_t)x,
                (uint32_t) y, magic_pattern, &measurement);
            if (!screenshot_successful) {
              *error = "Test window moved during test. The test window must "
                  "remain stationary and focused during the entire test.";
              return false;
            }
            screenshot_time = measurement.screenshot_time;
            if (screenshot_time - scroll_wait_start_time >
                nanoseconds_per_second) {
              *error = "Browser kept scrolling for more than 1 second after a "
                  "single scrollwheel event.";
              return false;
            }
            if (measurement.scroll_position != scroll_stats.value) {
              scroll_stats.value = measurement.scroll_position;
              scroll_update_time = screenshot_time;
            }
          }
          // We want to avoid sending input events at a predictable time
          // relative to frames, so introduce a random delay of up to 1 frame
          // (16.67 ms) before sending the next event.
          usleep((rand() % 17) * 1000);
          send_scroll_down(scroll_x, scroll_y);
          scroll_stats.previous_change_time = get_nanoseconds();
        }
    } else if (measurement.test_mode == TEST_MODE_PAUSE_TIME) {
      // For the pause time test we want the browser to scroll continuously.
      // Send a scroll event every frame.
      if (screenshot_time - last_scroll_sent >
          17 * nanoseconds_per_millisecond) {
        send_scroll_down(scroll_x, scroll_y);
        last_scroll_sent = get_nanoseconds();
      }
    } else if (measurement.test_mode == TEST_MODE_PAUSE_TIME_TEST_FINISHED) {
      break;
    } else {
      *error = "Invalid test type. This is a bug in the test.";
      return false;
    }

    if (screenshot_time - start_time >
        test_timeout_ms * nanoseconds_per_millisecond) {
      *error = "Timeout.";
      return false;
    }
    previous_measurement = measurement;
    usleep(0);
  }
  // The latency we report is the midpoint of the interval given by the average
  // upper and lower bounds we've computed.
  *out_key_down_latency_ms =
      (upper_bound_ms(&key_down_events) + lower_bound_ms(&key_down_events)) / 2;
  *out_scroll_latency_ms =
      (upper_bound_ms(&scroll_stats) + lower_bound_ms(&scroll_stats) / 2);
  *out_max_js_pause_time_ms =
      javascript_frames.max_lower_bound / (double) nanoseconds_per_millisecond;
  *out_max_css_pause_time_ms =
      css_frames.max_lower_bound / (double) nanoseconds_per_millisecond;
  *out_max_scroll_pause_time_ms =
      scroll_stats.max_lower_bound / (double) nanoseconds_per_millisecond;
  debug_log("out_key_down_latency_ms: %f out_scroll_latency_ms: %f "
      "out_max_js_pause_time_ms: %f out_max_css_pause_time: %f\n "
      "out_max_scroll_pause_time_ms: %f",
      *out_key_down_latency_ms,
      *out_scroll_latency_ms,
      *out_max_js_pause_time_ms,
      *out_max_css_pause_time_ms,
      *out_max_scroll_pause_time_ms);
  return true;
}
Exemple #13
0
int main(int argc, char** argv) {
    take_screenshot();
    return 0;
}
Exemple #14
0
int main(int argc, char *argv[]) {
    struct spwd *sp = getspnam(getenv("USER"));
    if (!sp) {
        fprintf(stderr, "Get password failed\n");
        return EXIT_FAILURE;
    }
    char *password = sp->sp_pwdp;

    // Parse command line parameters.
    struct arguments arguments = {
        .radius = 16,
        .iterations = 2,
    };
    argp_parse(&argp, argc, argv, 0, NULL, &arguments);

    // Connect to X11.
    xcb_connection_t *conn = xcb_connect(NULL, NULL);
    const xcb_setup_t *setup = xcb_get_setup(conn);
    xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
    xcb_screen_t *screen = iter.data;

    // Initialize keyboard stuff.
    Keyboard keyboard = {
        .conn = conn,
    };
    init_keyboard(&keyboard);

    // Take a screenshot and blur it.
    xcb_image_t *screenshot = take_screenshot(conn, screen);
    blur_image(screenshot, arguments.radius, arguments.iterations);

    // Create window.
    xcb_window_t window = create_window(conn, screen, screenshot);

    if (!grab_inputs(conn, screen)) {
        fprintf(stderr, "Failed to grab keyboard and pointer.\n");
        exit(EXIT_FAILURE);
    }

    xcb_map_window(conn, window);

    // Original screenshot image is not needed anymore because it's copied to the X server as pixmap.
    xcb_image_destroy(screenshot);

    xcb_flush(conn);

    // XXX: Max password length?
    char input[256] = { '\0' };
    char *cursor = &input[0];

    running = true;
    xcb_generic_event_t *event;
    while (running && (event = xcb_wait_for_event(conn))) {
        switch (event->response_type & ~0x80) {
            case XCB_EXPOSE:
                break;
            case XCB_KEY_PRESS:
                if (handle_key_press(&keyboard, ((xcb_key_press_event_t *)event)->detail, input, &cursor)) {
                    if (strcmp(crypt(input, password), password) == 0) {
                        running = false;
                    } else {
                        input[0] = '\0';
                        cursor = &input[0];
                    }
                }
                break;
            default:
                if (event->response_type == keyboard.first_xkb_event) {
                    process_keyboard_event(&keyboard, event);
                }
                break;
        }
        free(event);
    }

    free_keyboard(&keyboard);

    xcb_unmap_window(conn, window);
    xcb_destroy_window(conn, window);
    xcb_disconnect(conn);

    return EXIT_SUCCESS;
}
Exemple #15
0
/**
 * event_cmd_ctl:
 * @cmd                  : Event command index.
 *
 * Performs program event command with index @cmd.
 *
 * Returns: true (1) on success, otherwise false (0).
 **/
bool event_cmd_ctl(enum event_command cmd, void *data)
{
   unsigned i                = 0;
   bool boolean              = false;
   settings_t *settings      = config_get_ptr();
   rarch_system_info_t *info = NULL;

   runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &info);

   (void)i;

   switch (cmd)
   {
      case EVENT_CMD_MENU_REFRESH:
#ifdef HAVE_MENU
         menu_driver_ctl(RARCH_MENU_CTL_REFRESH, NULL);
#endif
         break;
      case EVENT_CMD_SET_PER_GAME_RESOLUTION:
#if defined(GEKKO)
         {
            unsigned width = 0, height = 0;

            event_cmd_ctl(EVENT_CMD_VIDEO_SET_ASPECT_RATIO, NULL);

            if (video_driver_get_video_output_size(&width, &height))
            {
               char msg[128] = {0};

               video_driver_set_video_mode(width, height, true);

               if (width == 0 || height == 0)
                  strlcpy(msg, "Resolution: DEFAULT", sizeof(msg));
               else
                  snprintf(msg, sizeof(msg),"Resolution: %dx%d",width, height);
               runloop_msg_queue_push(msg, 1, 100, true);
            }
         }
#endif
         break;
      case EVENT_CMD_LOAD_CONTENT_PERSIST:
#ifdef HAVE_DYNAMIC
         event_cmd_ctl(EVENT_CMD_LOAD_CORE, NULL);
#endif
         rarch_ctl(RARCH_CTL_LOAD_CONTENT, NULL);
         break;
#ifdef HAVE_FFMPEG
      case EVENT_CMD_LOAD_CONTENT_FFMPEG:
         rarch_ctl(RARCH_CTL_LOAD_CONTENT_FFMPEG, NULL);
         break;
#endif
      case EVENT_CMD_LOAD_CONTENT_IMAGEVIEWER:
         rarch_ctl(RARCH_CTL_LOAD_CONTENT_IMAGEVIEWER, NULL);
         break;
      case EVENT_CMD_LOAD_CONTENT:
         {
#ifdef HAVE_DYNAMIC
            event_cmd_ctl(EVENT_CMD_LOAD_CONTENT_PERSIST, NULL);
#else
            char *fullpath = NULL;
            runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath);
            runloop_ctl(RUNLOOP_CTL_SET_LIBRETRO_PATH, settings->libretro);
            event_cmd_ctl(EVENT_CMD_EXEC, (void*)fullpath);
            event_cmd_ctl(EVENT_CMD_QUIT, NULL);
#endif
         }
         break;
      case EVENT_CMD_LOAD_CORE_DEINIT:
#ifdef HAVE_MENU
         menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_DEINIT, NULL);
#endif
         break;
      case EVENT_CMD_LOAD_CORE_PERSIST:
         event_cmd_ctl(EVENT_CMD_LOAD_CORE_DEINIT, NULL);
         {
#ifdef HAVE_MENU
            bool *ptr = NULL;
            struct retro_system_info *system = NULL;

            menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &system);

            if (menu_driver_ctl(RARCH_MENU_CTL_LOAD_NO_CONTENT_GET, &ptr))
            {
               core_info_ctx_find_t info_find;

#if defined(HAVE_DYNAMIC)
               if (!(*settings->libretro))
                  return false;

               libretro_get_system_info(settings->libretro, system,
                     ptr);
#endif
               info_find.path = settings->libretro;

               if (!core_info_ctl(CORE_INFO_CTL_LOAD, &info_find))
                  return false;
            }
#endif
         }
         break;
      case EVENT_CMD_LOAD_CORE:
         event_cmd_ctl(EVENT_CMD_LOAD_CORE_PERSIST, NULL);
#ifndef HAVE_DYNAMIC
         event_cmd_ctl(EVENT_CMD_QUIT, NULL);
#endif
         break;
      case EVENT_CMD_LOAD_STATE:
         /* Immutable - disallow savestate load when
          * we absolutely cannot change game state. */
         if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            return false;

#ifdef HAVE_NETPLAY
         if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
            return false;
#endif

#ifdef HAVE_CHEEVOS
         if (settings->cheevos.hardcore_mode_enable)
            return false;
#endif

         event_main_state(cmd);
         break;
      case EVENT_CMD_RESIZE_WINDOWED_SCALE:
         {
            unsigned idx = 0;
            unsigned *window_scale = NULL;

            runloop_ctl(RUNLOOP_CTL_GET_WINDOWED_SCALE, &window_scale);

            if (*window_scale == 0)
               return false;

            settings->video.scale = *window_scale;

            if (!settings->video.fullscreen)
               event_cmd_ctl(EVENT_CMD_REINIT, NULL);

            runloop_ctl(RUNLOOP_CTL_SET_WINDOWED_SCALE, &idx);
         }
         break;
      case EVENT_CMD_MENU_TOGGLE:
#ifdef HAVE_MENU
         if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
            rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);
         else
            rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL);
#endif
         break;
      case EVENT_CMD_CONTROLLERS_INIT:
         event_init_controllers();
         break;
      case EVENT_CMD_RESET:
         RARCH_LOG("%s.\n", msg_hash_to_str(MSG_RESET));
         runloop_msg_queue_push(msg_hash_to_str(MSG_RESET), 1, 120, true);

#ifdef HAVE_CHEEVOS
         cheevos_ctl(CHEEVOS_CTL_SET_CHEATS, NULL);
#endif
         core_ctl(CORE_CTL_RETRO_RESET, NULL);
         break;
      case EVENT_CMD_SAVE_STATE:
#ifdef HAVE_CHEEVOS
         if (settings->cheevos.hardcore_mode_enable)
            return false;
#endif

         if (settings->savestate_auto_index)
            settings->state_slot++;

         event_main_state(cmd);
         break;
      case EVENT_CMD_SAVE_STATE_DECREMENT:
         /* Slot -1 is (auto) slot. */
         if (settings->state_slot >= 0)
            settings->state_slot--;
         break;
      case EVENT_CMD_SAVE_STATE_INCREMENT:
         settings->state_slot++;
         break;
      case EVENT_CMD_TAKE_SCREENSHOT:
         if (!take_screenshot())
            return false;
         break;
      case EVENT_CMD_UNLOAD_CORE:
         runloop_ctl(RUNLOOP_CTL_PREPARE_DUMMY, NULL);
         event_cmd_ctl(EVENT_CMD_LOAD_CORE_DEINIT, NULL);
         break;
      case EVENT_CMD_QUIT:
         rarch_ctl(RARCH_CTL_QUIT, NULL);
         break;
      case EVENT_CMD_CHEEVOS_HARDCORE_MODE_TOGGLE:
#ifdef HAVE_CHEEVOS
         cheevos_ctl(CHEEVOS_CTL_TOGGLE_HARDCORE_MODE, NULL);
#endif
         break;
      case EVENT_CMD_REINIT:
         {
            struct retro_hw_render_callback *hwr = NULL;
            video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr);

            if (hwr->cache_context)
               video_driver_ctl(
                     RARCH_DISPLAY_CTL_SET_VIDEO_CACHE_CONTEXT, NULL);
            else
               video_driver_ctl(
                     RARCH_DISPLAY_CTL_UNSET_VIDEO_CACHE_CONTEXT, NULL);

            video_driver_ctl(
                  RARCH_DISPLAY_CTL_UNSET_VIDEO_CACHE_CONTEXT_ACK, NULL);
            event_cmd_ctl(EVENT_CMD_RESET_CONTEXT, NULL);
            video_driver_ctl(
                  RARCH_DISPLAY_CTL_UNSET_VIDEO_CACHE_CONTEXT, NULL);

            /* Poll input to avoid possibly stale data to corrupt things. */
            input_driver_ctl(RARCH_INPUT_CTL_POLL, NULL);

#ifdef HAVE_MENU
            menu_display_ctl(
                  MENU_DISPLAY_CTL_SET_FRAMEBUFFER_DIRTY_FLAG, NULL);

            if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
               event_cmd_ctl(EVENT_CMD_VIDEO_SET_BLOCKING_STATE, NULL);
#endif
         }
         break;
      case EVENT_CMD_CHEATS_DEINIT:
         cheat_manager_state_free();
         break;
      case EVENT_CMD_CHEATS_INIT:
         event_cmd_ctl(EVENT_CMD_CHEATS_DEINIT, NULL);
         event_init_cheats();
         break;
      case EVENT_CMD_CHEATS_APPLY:
         cheat_manager_apply_cheats();
         break;
      case EVENT_CMD_REWIND_DEINIT:
#ifdef HAVE_NETPLAY
         if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
            return false;
#endif
#ifdef HAVE_CHEEVOS
         if (settings->cheevos.hardcore_mode_enable)
            return false;
#endif

         state_manager_event_deinit();
         break;
      case EVENT_CMD_REWIND_INIT:
#ifdef HAVE_CHEEVOS
         if (settings->cheevos.hardcore_mode_enable)
            return false;
#endif
#ifdef HAVE_NETPLAY
         if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
#endif
            init_rewind();
         break;
      case EVENT_CMD_REWIND_TOGGLE:
         if (settings->rewind_enable)
            event_cmd_ctl(EVENT_CMD_REWIND_INIT, NULL);
         else
            event_cmd_ctl(EVENT_CMD_REWIND_DEINIT, NULL);
         break;
      case EVENT_CMD_AUTOSAVE_DEINIT:
#ifdef HAVE_THREADS
         autosave_event_deinit();
#endif
         break;
      case EVENT_CMD_AUTOSAVE_INIT:
         event_cmd_ctl(EVENT_CMD_AUTOSAVE_DEINIT, NULL);
#ifdef HAVE_THREADS
         autosave_event_init();
#endif
         break;
      case EVENT_CMD_AUTOSAVE_STATE:
         event_save_auto_state();
         break;
      case EVENT_CMD_AUDIO_STOP:
         if (!audio_driver_ctl(RARCH_AUDIO_CTL_ALIVE, NULL))
            return false;

         if (!audio_driver_ctl(RARCH_AUDIO_CTL_STOP, NULL))
            return false;
         break;
      case EVENT_CMD_AUDIO_START:
         if (audio_driver_ctl(RARCH_AUDIO_CTL_ALIVE, NULL))
            return false;

         if (!settings->audio.mute_enable && 
               !audio_driver_ctl(RARCH_AUDIO_CTL_START, NULL))
         {
            RARCH_ERR("Failed to start audio driver. "
                  "Will continue without audio.\n");
            audio_driver_ctl(RARCH_AUDIO_CTL_UNSET_ACTIVE, NULL);
         }
         break;
      case EVENT_CMD_AUDIO_MUTE_TOGGLE:
         {
            const char *msg = !settings->audio.mute_enable ?
               msg_hash_to_str(MSG_AUDIO_MUTED):
               msg_hash_to_str(MSG_AUDIO_UNMUTED);

            if (!audio_driver_ctl(RARCH_AUDIO_CTL_MUTE_TOGGLE, NULL))
            {
               RARCH_ERR("%s.\n",
                     msg_hash_to_str(MSG_FAILED_TO_UNMUTE_AUDIO));
               return false;
            }

            runloop_msg_queue_push(msg, 1, 180, true);
            RARCH_LOG("%s\n", msg);
         }
         break;
      case EVENT_CMD_OVERLAY_DEINIT:
#ifdef HAVE_OVERLAY
         input_overlay_free();
#endif
         break;
      case EVENT_CMD_OVERLAY_INIT:
         event_cmd_ctl(EVENT_CMD_OVERLAY_DEINIT, NULL);
#ifdef HAVE_OVERLAY
         input_overlay_init();
#endif
         break;
      case EVENT_CMD_OVERLAY_NEXT:
#ifdef HAVE_OVERLAY
         input_overlay_next(settings->input.overlay_opacity);
#endif
         break;
      case EVENT_CMD_DSP_FILTER_DEINIT:
         audio_driver_dsp_filter_free();
         break;
      case EVENT_CMD_DSP_FILTER_INIT:
         event_cmd_ctl(EVENT_CMD_DSP_FILTER_DEINIT, NULL);
         if (!*settings->audio.dsp_plugin)
            break;
         audio_driver_dsp_filter_init(settings->audio.dsp_plugin);
         break;
      case EVENT_CMD_GPU_RECORD_DEINIT:
         video_driver_ctl(RARCH_DISPLAY_CTL_GPU_RECORD_DEINIT, NULL);
         break;
      case EVENT_CMD_RECORD_DEINIT:
         if (!recording_deinit())
            return false;
         break;
      case EVENT_CMD_RECORD_INIT:
         event_cmd_ctl(EVENT_CMD_HISTORY_DEINIT, NULL);
         if (!recording_init())
            return false;
         break;
      case EVENT_CMD_HISTORY_DEINIT:
         if (g_defaults.history)
         {
            content_playlist_write_file(g_defaults.history);
            content_playlist_free(g_defaults.history);
         }
         g_defaults.history = NULL;
         break;
      case EVENT_CMD_HISTORY_INIT:
         event_cmd_ctl(EVENT_CMD_HISTORY_DEINIT, NULL);
         if (!settings->history_list_enable)
            return false;
         RARCH_LOG("%s: [%s].\n",
               msg_hash_to_str(MSG_LOADING_HISTORY_FILE),
               settings->content_history_path);
         g_defaults.history = content_playlist_init(
               settings->content_history_path,
               settings->content_history_size);
         break;
      case EVENT_CMD_CORE_INFO_DEINIT:
         core_info_ctl(CORE_INFO_CTL_LIST_DEINIT, NULL);
         break;
      case EVENT_CMD_CORE_INFO_INIT:
         event_cmd_ctl(EVENT_CMD_CORE_INFO_DEINIT, NULL);

         if (*settings->libretro_directory)
            core_info_ctl(CORE_INFO_CTL_LIST_INIT, NULL);
         break;
      case EVENT_CMD_CORE_DEINIT:
         {
            struct retro_hw_render_callback *hwr = NULL;
            video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr);
            event_deinit_core(true);

            if (hwr)
               memset(hwr, 0, sizeof(*hwr));

            break;
         }
      case EVENT_CMD_CORE_INIT:
         if (!event_init_core(data))
            return false;
         break;
      case EVENT_CMD_VIDEO_APPLY_STATE_CHANGES:
         video_driver_ctl(RARCH_DISPLAY_CTL_APPLY_STATE_CHANGES, NULL);
         break;
      case EVENT_CMD_VIDEO_SET_NONBLOCKING_STATE:
         boolean = true; /* fall-through */
      case EVENT_CMD_VIDEO_SET_BLOCKING_STATE:
         video_driver_ctl(RARCH_DISPLAY_CTL_SET_NONBLOCK_STATE, &boolean);
         break;
      case EVENT_CMD_VIDEO_SET_ASPECT_RATIO:
         video_driver_ctl(RARCH_DISPLAY_CTL_SET_ASPECT_RATIO, NULL);
         break;
      case EVENT_CMD_AUDIO_SET_NONBLOCKING_STATE:
         boolean = true; /* fall-through */
      case EVENT_CMD_AUDIO_SET_BLOCKING_STATE:
         audio_driver_set_nonblocking_state(boolean);
         break;
      case EVENT_CMD_OVERLAY_SET_SCALE_FACTOR:
#ifdef HAVE_OVERLAY
         input_overlay_set_scale_factor(settings->input.overlay_scale);
#endif
         break;
      case EVENT_CMD_OVERLAY_SET_ALPHA_MOD:
#ifdef HAVE_OVERLAY
         input_overlay_set_alpha_mod(settings->input.overlay_opacity);
#endif
         break;
      case EVENT_CMD_AUDIO_REINIT:
         {
            int flags = DRIVER_AUDIO;
            driver_ctl(RARCH_DRIVER_CTL_UNINIT, &flags);
            driver_ctl(RARCH_DRIVER_CTL_INIT, &flags);
         }
         break;
      case EVENT_CMD_RESET_CONTEXT:
         {
            /* RARCH_DRIVER_CTL_UNINIT clears the callback struct so we
             * need to make sure to keep a copy */
            struct retro_hw_render_callback *hwr = NULL;
            struct retro_hw_render_callback hwr_copy;
            int flags = DRIVERS_CMD_ALL;

            video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr);

            memcpy(&hwr_copy, hwr, sizeof(hwr_copy));

            driver_ctl(RARCH_DRIVER_CTL_UNINIT, &flags);

            memcpy(hwr, &hwr_copy, sizeof(*hwr));

            driver_ctl(RARCH_DRIVER_CTL_INIT, &flags);
         }
         break;
      case EVENT_CMD_QUIT_RETROARCH:
         rarch_ctl(RARCH_CTL_FORCE_QUIT, NULL);
         break;
      case EVENT_CMD_SHUTDOWN:
#if defined(__linux__) && !defined(ANDROID)
         runloop_msg_queue_push("Shutting down...", 1, 180, true);
         rarch_ctl(RARCH_CTL_FORCE_QUIT, NULL);
         system("shutdown -P now");
#endif
         break;
      case EVENT_CMD_REBOOT:
#if defined(__linux__) && !defined(ANDROID)
         runloop_msg_queue_push("Rebooting...", 1, 180, true);
         rarch_ctl(RARCH_CTL_FORCE_QUIT, NULL);
         system("shutdown -r now");
#endif
         break;
      case EVENT_CMD_RESUME:
         rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);
         if (ui_companion_is_on_foreground())
            ui_companion_driver_toggle();
         break;
      case EVENT_CMD_RESTART_RETROARCH:
         if (!frontend_driver_set_fork(FRONTEND_FORK_RESTART))
            return false;
         break;
      case EVENT_CMD_MENU_SAVE_CURRENT_CONFIG:
         event_save_current_config();
         break;
      case EVENT_CMD_MENU_SAVE_CONFIG:
         if (!event_save_core_config())
            return false;
         break;
      case EVENT_CMD_SHADERS_APPLY_CHANGES:
#ifdef HAVE_MENU
         menu_shader_manager_apply_changes();
#endif
         break;
      case EVENT_CMD_PAUSE_CHECKS:
         if (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL))
         {
            RARCH_LOG("%s\n", msg_hash_to_str(MSG_PAUSED));
            event_cmd_ctl(EVENT_CMD_AUDIO_STOP, NULL);

            if (settings->video.black_frame_insertion)
               video_driver_ctl(RARCH_DISPLAY_CTL_CACHED_FRAME_RENDER, NULL);
         }
         else
         {
            RARCH_LOG("%s\n", msg_hash_to_str(MSG_UNPAUSED));
            event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL);
         }
         break;
      case EVENT_CMD_PAUSE_TOGGLE:
         boolean = runloop_ctl(RUNLOOP_CTL_IS_PAUSED,  NULL);
         boolean = !boolean;
         runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean);
         event_cmd_ctl(EVENT_CMD_PAUSE_CHECKS, NULL);
         break;
      case EVENT_CMD_UNPAUSE:
         boolean = false;

         runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean);
         event_cmd_ctl(EVENT_CMD_PAUSE_CHECKS, NULL);
         break;
      case EVENT_CMD_PAUSE:
         boolean = true;

         runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean);
         event_cmd_ctl(EVENT_CMD_PAUSE_CHECKS, NULL);
         break;
      case EVENT_CMD_MENU_PAUSE_LIBRETRO:
#ifdef HAVE_MENU
         if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
         {
            if (settings->menu.pause_libretro)
               event_cmd_ctl(EVENT_CMD_AUDIO_STOP, NULL);
            else
               event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL);
         }
         else
         {
            if (settings->menu.pause_libretro)
               event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL);
         }
#endif
         break;
      case EVENT_CMD_SHADER_DIR_DEINIT:
         runloop_ctl(RUNLOOP_CTL_SHADER_DIR_DEINIT, NULL);
         break;
      case EVENT_CMD_SHADER_DIR_INIT:
         event_cmd_ctl(EVENT_CMD_SHADER_DIR_DEINIT, NULL);

         if (!runloop_ctl(RUNLOOP_CTL_SHADER_DIR_INIT, NULL))
            return false;
         break;
      case EVENT_CMD_SAVEFILES:
         {
            global_t  *global         = global_get_ptr();
            if (!global->savefiles || !global->sram.use)
               return false;

            for (i = 0; i < global->savefiles->size; i++)
            {
               ram_type_t ram;
               ram.type    = global->savefiles->elems[i].attr.i;
               ram.path    = global->savefiles->elems[i].data;

               RARCH_LOG("%s #%u %s \"%s\".\n",
                     msg_hash_to_str(MSG_SAVING_RAM_TYPE),
                     ram.type,
                     msg_hash_to_str(MSG_TO),
                     ram.path);
               content_ctl(CONTENT_CTL_SAVE_RAM_FILE, &ram);
            }
         }
         return true;
      case EVENT_CMD_SAVEFILES_DEINIT:
         {
            global_t  *global         = global_get_ptr();
            if (!global)
               break;

            if (global->savefiles)
               string_list_free(global->savefiles);
            global->savefiles = NULL;
         }
         break;
      case EVENT_CMD_SAVEFILES_INIT:
         {
            global_t  *global         = global_get_ptr();
            global->sram.use = global->sram.use && !global->sram.save_disable;
#ifdef HAVE_NETPLAY
            global->sram.use = global->sram.use && 
               (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)
                || !global->netplay.is_client);
#endif

            if (!global->sram.use)
               RARCH_LOG("%s\n",
                     msg_hash_to_str(MSG_SRAM_WILL_NOT_BE_SAVED));

            if (global->sram.use)
               event_cmd_ctl(EVENT_CMD_AUTOSAVE_INIT, NULL);
         }
         break;
      case EVENT_CMD_BSV_MOVIE_DEINIT:
         bsv_movie_ctl(BSV_MOVIE_CTL_DEINIT, NULL);
         break;
      case EVENT_CMD_BSV_MOVIE_INIT:
         event_cmd_ctl(EVENT_CMD_BSV_MOVIE_DEINIT, NULL);
         bsv_movie_ctl(BSV_MOVIE_CTL_INIT, NULL);
         break;
      case EVENT_CMD_NETPLAY_DEINIT:
#ifdef HAVE_NETPLAY
         deinit_netplay();
#endif
         break;
      case EVENT_CMD_NETWORK_DEINIT:
#ifdef HAVE_NETWORKING
         network_deinit();
#endif
         break;
      case EVENT_CMD_NETWORK_INIT:
#ifdef HAVE_NETWORKING
         network_init();
#endif
         break;
      case EVENT_CMD_NETPLAY_INIT:
         event_cmd_ctl(EVENT_CMD_NETPLAY_DEINIT, NULL);
#ifdef HAVE_NETPLAY
         if (!init_netplay())
            return false;
#endif
         break;
      case EVENT_CMD_NETPLAY_FLIP_PLAYERS:
#ifdef HAVE_NETPLAY
         netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, NULL);
#endif
         break;
      case EVENT_CMD_FULLSCREEN_TOGGLE:
         if (!video_driver_ctl(RARCH_DISPLAY_CTL_HAS_WINDOWED, NULL))
            return false;

         /* If we go fullscreen we drop all drivers and
          * reinitialize to be safe. */
         settings->video.fullscreen = !settings->video.fullscreen;
         event_cmd_ctl(EVENT_CMD_REINIT, NULL);
         break;
      case EVENT_CMD_COMMAND_DEINIT:
         input_driver_ctl(RARCH_INPUT_CTL_COMMAND_DEINIT, NULL);
         break;
      case EVENT_CMD_COMMAND_INIT:
         event_cmd_ctl(EVENT_CMD_COMMAND_DEINIT, NULL);
         input_driver_ctl(RARCH_INPUT_CTL_COMMAND_INIT, NULL);
         break;
      case EVENT_CMD_REMOTE_DEINIT:
         input_driver_ctl(RARCH_INPUT_CTL_REMOTE_DEINIT, NULL);
         break;
      case EVENT_CMD_REMOTE_INIT:
         event_cmd_ctl(EVENT_CMD_REMOTE_DEINIT, NULL);
         input_driver_ctl(RARCH_INPUT_CTL_REMOTE_INIT, NULL);
         break;
      case EVENT_CMD_TEMPORARY_CONTENT_DEINIT:
         content_ctl(CONTENT_CTL_DEINIT, NULL);
         break;
      case EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT:
         {
            global_t  *global         = global_get_ptr();
            if (!global)
               break;

            if (global->subsystem_fullpaths)
               string_list_free(global->subsystem_fullpaths);
            global->subsystem_fullpaths = NULL;
         }
         break;
      case EVENT_CMD_LOG_FILE_DEINIT:
         retro_main_log_file_deinit();
         break;
      case EVENT_CMD_DISK_APPEND_IMAGE:
         {
            const char *path = (const char*)data;
            if (string_is_empty(path))
               return false;
            return event_disk_control_append_image(path);
         }
      case EVENT_CMD_DISK_EJECT_TOGGLE:
         if (info && info->disk_control_cb.get_num_images)
         {
            const struct retro_disk_control_callback *control =
               (const struct retro_disk_control_callback*)
               &info->disk_control_cb;

            if (control)
            {
               bool new_state = !control->get_eject_state();
               event_disk_control_set_eject(new_state, true);
            }
         }
         else
            runloop_msg_queue_push(
                  msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
                  1, 120, true);
         break;
      case EVENT_CMD_DISK_NEXT:
         if (info && info->disk_control_cb.get_num_images)
         {
            const struct retro_disk_control_callback *control =
               (const struct retro_disk_control_callback*)
               &info->disk_control_cb;

            if (!control)
               return false;

            if (!control->get_eject_state())
               return false;

            event_check_disk_next(control);
         }
         else
            runloop_msg_queue_push(
                  msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
                  1, 120, true);
         break;
      case EVENT_CMD_DISK_PREV:
         if (info && info->disk_control_cb.get_num_images)
         {
            const struct retro_disk_control_callback *control =
               (const struct retro_disk_control_callback*)
               &info->disk_control_cb;

            if (!control)
               return false;

            if (!control->get_eject_state())
               return false;

            event_check_disk_prev(control);
         }
         else
            runloop_msg_queue_push(
                  msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
                  1, 120, true);
         break;
      case EVENT_CMD_RUMBLE_STOP:
         for (i = 0; i < MAX_USERS; i++)
         {
            input_driver_set_rumble_state(i, RETRO_RUMBLE_STRONG, 0);
            input_driver_set_rumble_state(i, RETRO_RUMBLE_WEAK, 0);
         }
         break;
      case EVENT_CMD_GRAB_MOUSE_TOGGLE:
         {
            bool ret = false;
            static bool grab_mouse_state  = false;

            grab_mouse_state = !grab_mouse_state;

            if (grab_mouse_state)
               ret = input_driver_ctl(RARCH_INPUT_CTL_GRAB_MOUSE, NULL);
            else
               ret = input_driver_ctl(RARCH_INPUT_CTL_UNGRAB_MOUSE, NULL);

            if (!ret)
               return false;

            RARCH_LOG("%s: %s.\n",
                  msg_hash_to_str(MSG_GRAB_MOUSE_STATE),
                  grab_mouse_state ? "yes" : "no");

            if (grab_mouse_state)
               video_driver_ctl(RARCH_DISPLAY_CTL_HIDE_MOUSE, NULL);
            else
               video_driver_ctl(RARCH_DISPLAY_CTL_SHOW_MOUSE, NULL);
         }
         break;
      case EVENT_CMD_PERFCNT_REPORT_FRONTEND_LOG:
         rarch_perf_log();
         break;
      case EVENT_CMD_VOLUME_UP:
         event_set_volume(0.5f);
         break;
      case EVENT_CMD_VOLUME_DOWN:
         event_set_volume(-0.5f);
         break;
      case EVENT_CMD_SET_FRAME_LIMIT:
         runloop_ctl(RUNLOOP_CTL_SET_FRAME_LIMIT, NULL);
         break;
      case EVENT_CMD_EXEC:
         return event_cmd_exec(data);
      case EVENT_CMD_NONE:
      default:
         return false;
   }

   return true;
}
int
main (int argc, char **argv)
{
	gchar c;		/* used for argument parsing */
	const gchar *filename;
	gint width = 0;
	gint height = 0;
	poptContext optCon;	/* context for parsing command-line options */

	const struct poptOption optionsTable[] = {
		{"width", 'w', POPT_ARG_INT, &width, 0,
		 "Width of the output image (to be resized)", "Width"},
		{"height", 'h', POPT_ARG_INT, &height, 0,
		 "Height of the output image (to be resized)", "Height"},
		POPT_AUTOHELP {NULL, 0, 0, NULL, 0}
	};

	optCon =
	    poptGetContext (NULL, argc, (const char **) argv, optionsTable,
			    0);
	poptSetOtherOptionHelp (optCon, "[options] <filename>");

	if (argc < 2) {
		poptPrintUsage (optCon, stderr, 0);
		return 1;
	}

	while ((c = poptGetNextOpt (optCon)) >= 0) {
		switch (c) {
		case 'w':
			if (width <= 0) {
				width = 0;
			}
			break;
		case 'h':
			if (height <= 0) {
				height = 0;
			}
			break;
		}
	}
	filename = poptGetArg (optCon);
	if ((filename == NULL) || !(poptPeekArg (optCon) == NULL)) {
		poptPrintUsage (optCon, stderr, 0);
		g_printerr ("\n\tYou must to specify the output filename"
			    " such as screenshot.png\n");
		return -1;
	}

	if (c < -1) {
		/* an error occurred during option processing */
		g_printerr ("%s: %s\n",
			    poptBadOption (optCon, POPT_BADOPTION_NOALIAS),
			    poptStrerror (c));
		return 1;
	}

	gdk_init (&argc, &argv);

	take_screenshot (filename, width, height);

	poptFreeContext (optCon);

	return 0;
}
int main(int argc, char**argv) {
    FILE *png = NULL;
    FILE *fb_in = NULL;
    char outfile[PATH_MAX] = "";

    char * soundfile = NULL;
    int do_increment = 0;

    int c;
    while ((c = getopt(argc, argv, "s:i")) != -1) {
        switch (c) {
            case 's': soundfile = optarg; break;
            case 'i': do_increment = 1; break;
            case '?':
            case 'h':
                usage(); exit(1);
        }
    }
    argc -= optind;
    argv += optind;

    if (argc < 1) {
        usage(); exit(1);
    }

    strlcpy(outfile, argv[0], PATH_MAX);
    if (do_increment) {
        struct stat st;
        char base[PATH_MAX] = "";
        int i = 0;
        while (stat(outfile, &st) == 0) {
            if (!base[0]) {
                char *p = strrchr(outfile, '.');
                if (p) *p = '\0';
                strcpy(base, outfile);
            }
            snprintf(outfile, PATH_MAX, "%s-%d.png", base, ++i);
        }
    }

    fb_in = fopen("/dev/graphics/fb0", "r");
    if (!fb_in) {
        fprintf(stderr, "error: could not read framebuffer\n");
        exit(1);
    }

    /* switch to non-root user and group */
    gid_t groups[] = { AID_LOG, AID_SDCARD_RW };
    setgroups(sizeof(groups)/sizeof(groups[0]), groups);
    setuid(AID_SHELL);

    png = fopen(outfile, "w");
    if (!png) {
        fprintf(stderr, "error: writing file %s: %s\n",
                outfile, strerror(errno));
        exit(1);
    }

    take_screenshot(fb_in, png);

    if (soundfile) {
        fork_sound(soundfile);
    }

    exit(0);
}
Exemple #18
0
/**
 * event_command:
 * @cmd                  : Event command index.
 *
 * Performs RetroArch event command with index @cmd.
 *
 * Returns: true (1) on success, otherwise false (0).
 **/
bool event_command(enum event_command cmd)
{
   unsigned i           = 0;
   bool boolean         = false;
   runloop_t *runloop   = rarch_main_get_ptr();
   driver_t  *driver    = driver_get_ptr();
   global_t  *global    = global_get_ptr();
   settings_t *settings = config_get_ptr();
   rarch_system_info_t *system = rarch_system_info_get_ptr();

   (void)i;

   switch (cmd)
   {
      case EVENT_CMD_LOAD_CONTENT_PERSIST:
#ifdef HAVE_DYNAMIC
         event_command(EVENT_CMD_LOAD_CORE);
#endif
         rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT);
         break;
#ifdef HAVE_FFMPEG
      case EVENT_CMD_LOAD_CONTENT_FFMPEG:
         rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT_FFMPEG);
         break;
#endif
      case EVENT_CMD_LOAD_CONTENT_IMAGEVIEWER:
         rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT_IMAGEVIEWER);
         break;
      case EVENT_CMD_LOAD_CONTENT:
#ifdef HAVE_DYNAMIC
         event_command(EVENT_CMD_LOAD_CONTENT_PERSIST);
#else
         rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH,
               (void*)settings->libretro);
         rarch_environment_cb(RETRO_ENVIRONMENT_EXEC,
               (void*)global->fullpath);
         event_command(EVENT_CMD_QUIT);
#endif
         break;
      case EVENT_CMD_LOAD_CORE_DEINIT:
#ifdef HAVE_DYNAMIC
         libretro_free_system_info(&global->menu.info);
#endif
         break;
      case EVENT_CMD_LOAD_CORE_PERSIST:
         event_command(EVENT_CMD_LOAD_CORE_DEINIT);
         {
#ifdef HAVE_MENU
            menu_handle_t *menu = menu_driver_get_ptr();
            if (menu)
               event_update_system_info(&global->menu.info,
                     &menu->load_no_content);
#endif
         }
         break;
      case EVENT_CMD_LOAD_CORE:
         event_command(EVENT_CMD_LOAD_CORE_PERSIST);
#ifndef HAVE_DYNAMIC
         event_command(EVENT_CMD_QUIT);
#endif
         break;
      case EVENT_CMD_LOAD_STATE:
         /* Immutable - disallow savestate load when 
          * we absolutely cannot change game state. */
         if (global->bsv.movie)
            return false;

#ifdef HAVE_NETPLAY
         if (driver->netplay_data)
            return false;
#endif
         event_main_state(cmd);
         break;
      case EVENT_CMD_RESIZE_WINDOWED_SCALE:
         if (global->pending.windowed_scale == 0)
            return false;

         settings->video.scale = global->pending.windowed_scale;

         if (!settings->video.fullscreen)
            event_command(EVENT_CMD_REINIT);

         global->pending.windowed_scale = 0;
         break;
      case EVENT_CMD_MENU_TOGGLE:
         if (menu_driver_alive())
            rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED);
         else
            rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING);
         break;
      case EVENT_CMD_CONTROLLERS_INIT:
         event_init_controllers();
         break;
      case EVENT_CMD_RESET:
         RARCH_LOG(RETRO_LOG_RESETTING_CONTENT);
         rarch_main_msg_queue_push("Reset.", 1, 120, true);
         pretro_reset();

         /* bSNES since v073r01 resets controllers to JOYPAD
          * after a reset, so just enforce it here. */
         event_command(EVENT_CMD_CONTROLLERS_INIT);
         break;
      case EVENT_CMD_SAVE_STATE:
         if (settings->savestate_auto_index)
            settings->state_slot++;

         event_main_state(cmd);
         break;
      case EVENT_CMD_TAKE_SCREENSHOT:
         if (!take_screenshot())
            return false;
         break;
      case EVENT_CMD_PREPARE_DUMMY:
         {
#ifdef HAVE_MENU
            menu_handle_t *menu = menu_driver_get_ptr();
            if (menu)
               menu->load_no_content = false;
#endif
            rarch_main_data_deinit();

            *global->fullpath = '\0';

            rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT);
         }
         break;
      case EVENT_CMD_UNLOAD_CORE:
         event_command(EVENT_CMD_PREPARE_DUMMY);
         event_command(EVENT_CMD_LOAD_CORE_DEINIT);
         break;
      case EVENT_CMD_QUIT:
         rarch_main_set_state(RARCH_ACTION_STATE_QUIT);
         break;
      case EVENT_CMD_REINIT:
         {
            const struct retro_hw_render_callback *hw_render =
               (const struct retro_hw_render_callback*)video_driver_callback();

            driver->video_cache_context     = hw_render->cache_context;
            driver->video_cache_context_ack = false;
            event_command(EVENT_CMD_RESET_CONTEXT);
            driver->video_cache_context     = false;

            /* Poll input to avoid possibly stale data to corrupt things. */
            input_driver_poll();

#ifdef HAVE_MENU
            menu_display_fb_set_dirty();

            if (menu_driver_alive())
               event_command(EVENT_CMD_VIDEO_SET_BLOCKING_STATE);
#endif
         }
         break;
      case EVENT_CMD_CHEATS_DEINIT:
         if (!global)
            break;

         if (global->cheat)
            cheat_manager_free(global->cheat);
         global->cheat = NULL;
         break;
      case EVENT_CMD_CHEATS_INIT:
         event_command(EVENT_CMD_CHEATS_DEINIT);
         event_init_cheats();
         break;
      case EVENT_CMD_REMAPPING_DEINIT:
         break;
      case EVENT_CMD_REMAPPING_INIT:
         event_command(EVENT_CMD_REMAPPING_DEINIT);
         event_init_remapping();
         break;
      case EVENT_CMD_REWIND_DEINIT:
         if (!global)
            break;
#ifdef HAVE_NETPLAY
         if (driver->netplay_data)
            return false;
#endif
         if (global->rewind.state)
            state_manager_free(global->rewind.state);
         global->rewind.state = NULL;
         break;
      case EVENT_CMD_REWIND_INIT:
         init_rewind();
         break;
      case EVENT_CMD_REWIND_TOGGLE:
         if (settings->rewind_enable)
            event_command(EVENT_CMD_REWIND_INIT);
         else
            event_command(EVENT_CMD_REWIND_DEINIT);
         break;
      case EVENT_CMD_AUTOSAVE_DEINIT:
#ifdef HAVE_THREADS
         event_deinit_autosave();
#endif
         break;
      case EVENT_CMD_AUTOSAVE_INIT:
         event_command(EVENT_CMD_AUTOSAVE_DEINIT);
#ifdef HAVE_THREADS
         event_init_autosave();
#endif
         break;
      case EVENT_CMD_AUTOSAVE_STATE:
         event_save_auto_state();
         break;
      case EVENT_CMD_AUDIO_STOP:
         if (!driver->audio_data)
            return false;
         if (!audio_driver_alive())
            return false;

         if (!audio_driver_stop())
            return false;
         break;
      case EVENT_CMD_AUDIO_START:
         if (!driver->audio_data || audio_driver_alive())
            return false;

         if (!settings->audio.mute_enable && !audio_driver_start())
         {
            RARCH_ERR("Failed to start audio driver. Will continue without audio.\n");
            driver->audio_active = false;
         }
         break;
      case EVENT_CMD_AUDIO_MUTE_TOGGLE:
         {
            const char *msg = !settings->audio.mute_enable ?
               "Audio muted." : "Audio unmuted.";

            if (!audio_driver_mute_toggle())
            {
               RARCH_ERR("Failed to unmute audio.\n");
               return false;
            }

            rarch_main_msg_queue_push(msg, 1, 180, true);
            RARCH_LOG("%s\n", msg);
         }
         break;
      case EVENT_CMD_OVERLAY_DEINIT:
#ifdef HAVE_OVERLAY
         if (driver->overlay)
            input_overlay_free(driver->overlay);
         driver->overlay = NULL;

         memset(&driver->overlay_state, 0, sizeof(driver->overlay_state));
#endif
         break;
      case EVENT_CMD_OVERLAY_INIT:
         event_command(EVENT_CMD_OVERLAY_DEINIT);
#ifdef HAVE_OVERLAY
         if (driver->osk_enable)
         {
            if (!*settings->osk.overlay)
               break;
         }
         else
         {
            if (!*settings->input.overlay)
               break;
         }

         driver->overlay = input_overlay_new(driver->osk_enable ? settings->osk.overlay : settings->input.overlay,
               driver->osk_enable ? settings->osk.enable   : settings->input.overlay_enable,
               settings->input.overlay_opacity, settings->input.overlay_scale);
         if (!driver->overlay)
            RARCH_ERR("Failed to load overlay.\n");
#endif
         break;
      case EVENT_CMD_OVERLAY_NEXT:
#ifdef HAVE_OVERLAY
         input_overlay_next(driver->overlay, settings->input.overlay_opacity);
#endif
         break;
      case EVENT_CMD_DSP_FILTER_DEINIT:
         if (!global)
            break;

         audio_driver_dsp_filter_free();
         break;
      case EVENT_CMD_DSP_FILTER_INIT:
         event_command(EVENT_CMD_DSP_FILTER_DEINIT);
         if (!*settings->audio.dsp_plugin)
            break;
         audio_driver_dsp_filter_init(settings->audio.dsp_plugin);
         break;
      case EVENT_CMD_GPU_RECORD_DEINIT:
         if (!global)
            break;

         if (global->record.gpu_buffer)
            free(global->record.gpu_buffer);
         global->record.gpu_buffer = NULL;
         break;
      case EVENT_CMD_RECORD_DEINIT:
         if (!recording_deinit())
            return false;
         break;
      case EVENT_CMD_RECORD_INIT:
         event_command(EVENT_CMD_HISTORY_DEINIT);
         if (!recording_init())
            return false;
         break;
      case EVENT_CMD_HISTORY_DEINIT:
         if (g_defaults.history)
         {
            content_playlist_write_file(g_defaults.history);
            content_playlist_free(g_defaults.history);
         }
         g_defaults.history = NULL;
         break;
      case EVENT_CMD_HISTORY_INIT:
         event_command(EVENT_CMD_HISTORY_DEINIT);
         if (!settings->history_list_enable)
            return false;
         RARCH_LOG("Loading history file: [%s].\n", settings->content_history_path);
         g_defaults.history = content_playlist_init(
               settings->content_history_path,
               settings->content_history_size);
         break;
      case EVENT_CMD_CORE_INFO_DEINIT:
         if (!global)
            break;

         if (global->core_info)
            core_info_list_free(global->core_info);
         global->core_info = NULL;
         break;
      case EVENT_CMD_DATA_RUNLOOP_FREE:
         rarch_main_data_free();
         break;
      case EVENT_CMD_CORE_INFO_INIT:
         event_command(EVENT_CMD_CORE_INFO_DEINIT);

         if (*settings->libretro_directory)
            global->core_info = core_info_list_new();
         break;
      case EVENT_CMD_CORE_DEINIT:
      {
         struct retro_hw_render_callback *cb = video_driver_callback();
         event_deinit_core(true);

         if (cb)
            memset(cb, 0, sizeof(*cb));

         break;
      }
      case EVENT_CMD_CORE_INIT:
         if (!event_init_core())
            return false;
         break;
      case EVENT_CMD_VIDEO_APPLY_STATE_CHANGES:
         video_driver_apply_state_changes();
         break;
      case EVENT_CMD_VIDEO_SET_NONBLOCKING_STATE:
         boolean = true; /* fall-through */
      case EVENT_CMD_VIDEO_SET_BLOCKING_STATE:
         video_driver_set_nonblock_state(boolean);
         break;
      case EVENT_CMD_VIDEO_SET_ASPECT_RATIO:
         video_driver_set_aspect_ratio(settings->video.aspect_ratio_idx);
         break;
      case EVENT_CMD_AUDIO_SET_NONBLOCKING_STATE:
         boolean = true; /* fall-through */
      case EVENT_CMD_AUDIO_SET_BLOCKING_STATE:
         audio_driver_set_nonblock_state(boolean);
         break;
      case EVENT_CMD_OVERLAY_SET_SCALE_FACTOR:
#ifdef HAVE_OVERLAY
         input_overlay_set_scale_factor(driver->overlay,
               settings->input.overlay_scale);
#endif
         break;
      case EVENT_CMD_OVERLAY_SET_ALPHA_MOD:
#ifdef HAVE_OVERLAY
         input_overlay_set_alpha_mod(driver->overlay,
               settings->input.overlay_opacity);
#endif
         break;
      case EVENT_CMD_DRIVERS_DEINIT:
         uninit_drivers(DRIVERS_CMD_ALL);
         break;
      case EVENT_CMD_DRIVERS_INIT:
         init_drivers(DRIVERS_CMD_ALL);
         break;
      case EVENT_CMD_AUDIO_REINIT:
         uninit_drivers(DRIVER_AUDIO);
         init_drivers(DRIVER_AUDIO);
         break;
      case EVENT_CMD_RESET_CONTEXT:
         event_command(EVENT_CMD_DRIVERS_DEINIT);
         event_command(EVENT_CMD_DRIVERS_INIT);
         break;
      case EVENT_CMD_QUIT_RETROARCH:
         rarch_main_set_state(RARCH_ACTION_STATE_FORCE_QUIT);
         break;
      case EVENT_CMD_RESUME:
         rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED);
         break;
      case EVENT_CMD_RESTART_RETROARCH:
#if defined(GEKKO) && defined(HW_RVL)
         fill_pathname_join(global->fullpath, g_defaults.core_dir,
               SALAMANDER_FILE,
               sizeof(global->fullpath));
#endif
         if (driver->frontend_ctx && driver->frontend_ctx->set_fork)
            driver->frontend_ctx->set_fork(true, false);
         break;
      case EVENT_CMD_MENU_SAVE_CONFIG:
         if (!event_save_core_config())
            return false;
         break;
      case EVENT_CMD_SHADERS_APPLY_CHANGES:
#ifdef HAVE_MENU
         menu_shader_manager_apply_changes();
#endif
         break;
      case EVENT_CMD_PAUSE_CHECKS:
         if (runloop->is_paused)
         {
            RARCH_LOG("Paused.\n");
            event_command(EVENT_CMD_AUDIO_STOP);

            if (settings->video.black_frame_insertion)
               video_driver_cached_frame();
         }
         else
         {
            RARCH_LOG("Unpaused.\n");
            event_command(EVENT_CMD_AUDIO_START);
         }
         break;
      case EVENT_CMD_PAUSE_TOGGLE:
         runloop->is_paused = !runloop->is_paused;
         event_command(EVENT_CMD_PAUSE_CHECKS);
         break;
      case EVENT_CMD_UNPAUSE:
         runloop->is_paused = false;
         event_command(EVENT_CMD_PAUSE_CHECKS);
         break;
      case EVENT_CMD_PAUSE:
         runloop->is_paused = true;
         event_command(EVENT_CMD_PAUSE_CHECKS);
         break;
      case EVENT_CMD_MENU_PAUSE_LIBRETRO:
         if (menu_driver_alive())
         {
            if (settings->menu.pause_libretro)
               event_command(EVENT_CMD_AUDIO_STOP);
            else
               event_command(EVENT_CMD_AUDIO_START);
         }
         else
         {
            if (settings->menu.pause_libretro)
               event_command(EVENT_CMD_AUDIO_START);
         }
         break;
      case EVENT_CMD_SHADER_DIR_DEINIT:
         if (!global)
            break;

         dir_list_free(global->shader_dir.list);
         global->shader_dir.list = NULL;
         global->shader_dir.ptr  = 0;
         break;
      case EVENT_CMD_SHADER_DIR_INIT:
         event_command(EVENT_CMD_SHADER_DIR_DEINIT);

         if (!*settings->video.shader_dir)
            return false;

         global->shader_dir.list = dir_list_new_special(NULL, DIR_LIST_SHADERS);

         if (!global->shader_dir.list || global->shader_dir.list->size == 0)
         {
            event_command(EVENT_CMD_SHADER_DIR_DEINIT);
            return false;
         }

         global->shader_dir.ptr  = 0;
         dir_list_sort(global->shader_dir.list, false);

         for (i = 0; i < global->shader_dir.list->size; i++)
            RARCH_LOG("Found shader \"%s\"\n",
                  global->shader_dir.list->elems[i].data);
         break;
      case EVENT_CMD_SAVEFILES:
         event_save_files();
         break;
      case EVENT_CMD_SAVEFILES_DEINIT:
         if (!global)
            break;

         if (global->savefiles)
            string_list_free(global->savefiles);
         global->savefiles = NULL;
         break;
      case EVENT_CMD_SAVEFILES_INIT:
         global->use_sram = global->use_sram && !global->sram_save_disable
#ifdef HAVE_NETPLAY
            && (!driver->netplay_data || !global->netplay_is_client)
#endif
            ;

         if (!global->use_sram)
            RARCH_LOG("SRAM will not be saved.\n");

         if (global->use_sram)
            event_command(EVENT_CMD_AUTOSAVE_INIT);
         break;
      case EVENT_CMD_MSG_QUEUE_DEINIT:
         rarch_main_msg_queue_free();
         break;
      case EVENT_CMD_MSG_QUEUE_INIT:
         event_command(EVENT_CMD_MSG_QUEUE_DEINIT);
         rarch_main_msg_queue_init();
         rarch_main_data_init_queues();
         break;
      case EVENT_CMD_BSV_MOVIE_DEINIT:
         if (!global)
            break;

         if (global->bsv.movie)
            bsv_movie_free(global->bsv.movie);
         global->bsv.movie = NULL;
         break;
      case EVENT_CMD_BSV_MOVIE_INIT:
         event_command(EVENT_CMD_BSV_MOVIE_DEINIT);
         event_init_movie();
         break;
      case EVENT_CMD_NETPLAY_DEINIT:
#ifdef HAVE_NETPLAY
         deinit_netplay();
#endif
         break;
      case EVENT_CMD_NETWORK_DEINIT:
#ifdef HAVE_NETWORKING
         network_deinit();
#endif
         break;
      case EVENT_CMD_NETWORK_INIT:
#ifdef HAVE_NETWORKING
         network_init();
#endif
         break;
      case EVENT_CMD_NETPLAY_INIT:
         event_command(EVENT_CMD_NETPLAY_DEINIT);
#ifdef HAVE_NETPLAY
         if (!init_netplay())
            return false;
#endif
         break;
      case EVENT_CMD_NETPLAY_FLIP_PLAYERS:
#ifdef HAVE_NETPLAY
         {
            netplay_t *netplay = (netplay_t*)driver->netplay_data;
            if (!netplay)
               return false;
            netplay_flip_users(netplay);
         }
#endif
         break;
      case EVENT_CMD_FULLSCREEN_TOGGLE:
         if (!video_driver_has_windowed())
            return false;

         /* If we go fullscreen we drop all drivers and 
          * reinitialize to be safe. */
         settings->video.fullscreen = !settings->video.fullscreen;
         event_command(EVENT_CMD_REINIT);
         break;
      case EVENT_CMD_COMMAND_DEINIT:
#ifdef HAVE_COMMAND
         if (driver->command)
            rarch_cmd_free(driver->command);
         driver->command = NULL;
#endif
         break;
      case EVENT_CMD_COMMAND_INIT:
         event_command(EVENT_CMD_COMMAND_DEINIT);

#ifdef HAVE_COMMAND
         event_init_command();
#endif
         break;
      case EVENT_CMD_TEMPORARY_CONTENT_DEINIT:
         if (!global)
            break;

         if (global->temporary_content)
            event_free_temporary_content();
         global->temporary_content = NULL;
         break;
      case EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT:
         if (!global)
            break;

         if (global->subsystem_fullpaths)
            string_list_free(global->subsystem_fullpaths);
         global->subsystem_fullpaths = NULL;
         break;
      case EVENT_CMD_LOG_FILE_DEINIT:
         if (!global)
            break;

         if (global->log_file && global->log_file != stderr)
            fclose(global->log_file);
         global->log_file = NULL;
         break;
      case EVENT_CMD_DISK_EJECT_TOGGLE:
         if (system && system->disk_control.get_num_images)
         {
            const struct retro_disk_control_callback *control = 
               (const struct retro_disk_control_callback*)
               &system->disk_control;

            if (control)
               event_check_disk_eject(control);
         }
         else
            rarch_main_msg_queue_push("Core does not support Disk Options.", 1, 120, true);
         break;
      case EVENT_CMD_DISK_NEXT:
         if (system && system->disk_control.get_num_images)
         {
            const struct retro_disk_control_callback *control = 
               (const struct retro_disk_control_callback*)
               &system->disk_control;

            if (!control)
               return false;

            if (!control->get_eject_state())
               return false;

            event_check_disk_next(control);
         }
         else
            rarch_main_msg_queue_push("Core does not support Disk Options.", 1, 120, true);
         break;
      case EVENT_CMD_DISK_PREV:
         if (system && system->disk_control.get_num_images)
         {
            const struct retro_disk_control_callback *control = 
               (const struct retro_disk_control_callback*)
               &system->disk_control;

            if (!control)
               return false;

            if (!control->get_eject_state())
               return false;

            event_check_disk_prev(control);
         }
         else
            rarch_main_msg_queue_push("Core does not support Disk Options.", 1, 120, true);
         break;
      case EVENT_CMD_RUMBLE_STOP:
         for (i = 0; i < MAX_USERS; i++)
         {
            input_driver_set_rumble_state(i, RETRO_RUMBLE_STRONG, 0);
            input_driver_set_rumble_state(i, RETRO_RUMBLE_WEAK, 0);
         }
         break;
      case EVENT_CMD_GRAB_MOUSE_TOGGLE:
         {
            static bool grab_mouse_state  = false;

            grab_mouse_state = !grab_mouse_state;

            if (!driver->input || !input_driver_grab_mouse(grab_mouse_state))
               return false;

            RARCH_LOG("Grab mouse state: %s.\n",
                  grab_mouse_state ? "yes" : "no");

            video_driver_show_mouse(!grab_mouse_state);
         }
         break;
      case EVENT_CMD_PERFCNT_REPORT_FRONTEND_LOG:
         rarch_perf_log();
         break;
      case EVENT_CMD_VOLUME_UP:
         event_set_volume(0.5f);
         break;
      case EVENT_CMD_VOLUME_DOWN:
         event_set_volume(-0.5f);
         break;
      case EVENT_CMD_NONE:
      default:
         goto error;
   }

   return true;

error:
   return false;
}
Exemple #19
0
static bool recreate_dispmanx(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;
    int display_nr = 0;
    int layer = 0;

    MP_VERBOSE(ctx, "Recreating DISPMANX state...\n");

    destroy_dispmanx(ctx);

    p->display = vc_dispmanx_display_open(display_nr);
    p->update = vc_dispmanx_update_start(0);
    if (!p->display || !p->update) {
        MP_FATAL(ctx, "Could not get DISPMANX objects.\n");
        goto fail;
    }

    uint32_t dispw, disph;
    if (graphics_get_display_size(0, &dispw, &disph) < 0) {
        MP_FATAL(ctx, "Could not get display size.\n");
        goto fail;
    }
    p->w = dispw;
    p->h = disph;

    if (ctx->vo->opts->fullscreen) {
        p->x = p->y = 0;
    } else {
        struct vo_win_geometry geo;
        struct mp_rect screenrc = {0, 0, p->w, p->h};

        vo_calc_window_geometry(ctx->vo, &screenrc, &geo);

        mp_rect_intersection(&geo.win, &screenrc);

        p->x = geo.win.x0;
        p->y = geo.win.y0;
        p->w = geo.win.x1 - geo.win.x0;
        p->h = geo.win.y1 - geo.win.y0;
    }

    // dispmanx is like a neanderthal version of Wayland - you can add an
    // overlay any place on the screen.
    VC_RECT_T dst = {.x = p->x, .y = p->y, .width = p->w, .height = p->h};
    VC_RECT_T src = {.width = p->w << 16, .height = p->h << 16};
    VC_DISPMANX_ALPHA_T alpha = {
        .flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE,
        .opacity = 0xFF,
    };
    p->window = vc_dispmanx_element_add(p->update, p->display, layer, &dst, 0,
                                        &src, DISPMANX_PROTECTION_NONE, &alpha,
                                        0, 0);
    if (!p->window) {
        MP_FATAL(ctx, "Could not add DISPMANX element.\n");
        goto fail;
    }

    vc_dispmanx_update_submit_sync(p->update);
    p->update = vc_dispmanx_update_start(0);

    p->egl_window = (EGL_DISPMANX_WINDOW_T){
        .element = p->window,
        .width = p->w,
        .height = p->h,
    };
    p->egl_surface = eglCreateWindowSurface(p->egl_display, p->egl_config,
                                            &p->egl_window, NULL);

    if (p->egl_surface == EGL_NO_SURFACE) {
        MP_FATAL(ctx, "Could not create EGL surface!\n");
        goto fail;
    }

    if (!eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface,
                        p->egl_context))
    {
        MP_FATAL(ctx, "Failed to set context!\n");
        goto fail;
    }

    p->display_fps = 0;
    TV_GET_STATE_RESP_T tvstate;
    TV_DISPLAY_STATE_T tvstate_disp;
    if (!vc_tv_get_state(&tvstate) && !vc_tv_get_display_state(&tvstate_disp)) {
        if (tvstate_disp.state & (VC_HDMI_HDMI | VC_HDMI_DVI)) {
            p->display_fps = tvstate_disp.display.hdmi.frame_rate;

            HDMI_PROPERTY_PARAM_T param = {
                .property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE,
            };
            if (!vc_tv_hdmi_get_property(&param) &&
                param.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC)
                p->display_fps = p->display_fps / 1.001;
        } else {
            p->display_fps = tvstate_disp.display.sdtv.frame_rate;
        }
    }

    p->win_params[0] = display_nr;
    p->win_params[1] = layer;
    p->win_params[2] = p->x;
    p->win_params[3] = p->y;

    ctx->vo->dwidth = p->w;
    ctx->vo->dheight = p->h;
    ra_gl_ctx_resize(ctx->swapchain, p->w, p->h, 0);

    ctx->vo->want_redraw = true;

    vo_event(ctx->vo, VO_EVENT_WIN_STATE);
    return true;

fail:
    destroy_dispmanx(ctx);
    return false;
}

static void rpi_swap_buffers(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;
    eglSwapBuffers(p->egl_display, p->egl_surface);
}

static bool rpi_init(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);

    bcm_host_init();

    vc_tv_register_callback(tv_callback, ctx);

    p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (!eglInitialize(p->egl_display, NULL, NULL)) {
        MP_FATAL(ctx, "EGL failed to initialize.\n");
        goto fail;
    }

    if (!mpegl_create_context(ctx, p->egl_display, &p->egl_context, &p->egl_config))
        goto fail;

    if (recreate_dispmanx(ctx) < 0)
        goto fail;

    mpegl_load_functions(&p->gl, ctx->log);

    struct ra_gl_ctx_params params = {
        .swap_buffers = rpi_swap_buffers,
        .native_display_type = "MPV_RPI_WINDOW",
        .native_display = p->win_params,
    };

    if (!ra_gl_ctx_init(ctx, &p->gl, params))
        goto fail;

    return true;

fail:
    rpi_uninit(ctx);
    return false;
}

static bool rpi_reconfig(struct ra_ctx *ctx)
{
    return recreate_dispmanx(ctx);
}

static struct mp_image *take_screenshot(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;

    if (!p->display)
        return NULL;

    struct mp_image *img = mp_image_alloc(IMGFMT_BGR0, p->w, p->h);
    if (!img)
        return NULL;

    DISPMANX_RESOURCE_HANDLE_T resource =
        vc_dispmanx_resource_create(VC_IMAGE_ARGB8888,
                                    img->w | ((img->w * 4) << 16), img->h,
                                    &(int32_t){0});
    if (!resource)
        goto fail;

    if (vc_dispmanx_snapshot(p->display, resource, 0))
        goto fail;

    VC_RECT_T rc = {.width = img->w, .height = img->h};
    if (vc_dispmanx_resource_read_data(resource, &rc, img->planes[0], img->stride[0]))
        goto fail;

    vc_dispmanx_resource_delete(resource);
    return img;

fail:
    vc_dispmanx_resource_delete(resource);
    talloc_free(img);
    return NULL;
}

static int rpi_control(struct ra_ctx *ctx, int *events, int request, void *arg)
{
    struct priv *p = ctx->priv;

    switch (request) {
    case VOCTRL_SCREENSHOT_WIN:
        *(struct mp_image **)arg = take_screenshot(ctx);
        return VO_TRUE;
    case VOCTRL_FULLSCREEN:
        recreate_dispmanx(ctx);
        return VO_TRUE;
    case VOCTRL_CHECK_EVENTS:
        if (atomic_fetch_and(&p->reload_display, 0)) {
            MP_WARN(ctx, "Recovering from display mode switch...\n");
            recreate_dispmanx(ctx);
        }
        return VO_TRUE;
    case VOCTRL_GET_DISPLAY_FPS:
        *(double *)arg = p->display_fps;
        return VO_TRUE;
    }

    return VO_NOTIMPL;
}

const struct ra_ctx_fns ra_ctx_rpi = {
    .type           = "opengl",
    .name           = "rpi",
    .reconfig       = rpi_reconfig,
    .control        = rpi_control,
    .init           = rpi_init,
    .uninit         = rpi_uninit,
};
Exemple #20
0
int video_display_process(uint8_t* frame, int width, int height, int size) {

	//if we get a NULL frame, stop displaying.
	if(frame == NULL) {
		video_display_destroy();
		return 0;
	}

	//first time called ? Initialize things.
	if(!initialized) {
		if(video_display_init_size(width, height) < 0) {
			fprintf(stderr, "[~][Display] Failed initialization.\n");
			return -1;
		}
		if(video_display_set_size(width, height) < 0)
			return -1;
		initialized = 1;
	}

	//check whether the size of the video has changed
	if (width != current_width || height != current_height)
		if (video_display_set_size(width, height) < 0)
			return -1;

	//check whether there's new stuff in the input com buffer
	double new_update = jakopter_com_get_timestamp(com_in);
	if (new_update > prev_update) {
		update_infos();
		if (want_screenshot) {
			take_screenshot(frame, size);
			want_screenshot = 0;
			jakopter_com_write_int(com_in, 24, 0);
		}
		prev_update = new_update;
	}
	pthread_mutex_lock(&mutex_process);

	if (current_process != NULL) {
		current_process(frame, width, height, size);
	}
	pthread_mutex_unlock(&mutex_process);

	unload_element();

	if (load_element() < 0)
		fprintf(stderr, "Couldn't load graphic element\n");

	// update the texture with our new frame
	if (SDL_UpdateTexture(frameTex, NULL, frame, width) < 0) {
		fprintf(stderr, "[~][Display] Failed to update frame texture : %s\n", SDL_GetError());
		return -1;
	}

	//clear the renderer, then update it so that we get the new frame displayed.
	SDL_RenderClear(renderer);
	SDL_RenderCopy(renderer, frameTex, NULL, NULL);
	//SDL_RenderFillRect(renderer, &rectangle);
	//draw all overlay elements, when they exist
	int i = 0;
	for (i = 0 ; i < VIDEO_NB_NAV_INFOS ; i++)
		if (graphs[i].tex != NULL)
			SDL_RenderCopy(renderer, graphs[i].tex, NULL, &graphs[i].pos);

	pthread_mutex_lock(&mutex_graphics_list);
	struct graphics_list *current = icon_registry;
	while (current != NULL) {
		if (current->graphic != NULL && current->graphic->tex != NULL){
			int ret = SDL_RenderCopy(renderer, current->graphic->tex, NULL, &current->graphic->pos);
			if (ret < 0)
				fprintf(stderr, "[~][display] RenderCopy() failed: %s\n", SDL_GetError());
		}

		current = current->next;
	}
	pthread_mutex_unlock(&mutex_graphics_list);

	draw_attitude_indic();
	draw_compass();
	SDL_RenderPresent(renderer);

	return 0;
}
Exemple #21
0
void emu_framebuffer::do_screenshot(command::arg_filename file)
{
	std::string fn = file;
	take_screenshot(fn);
	messages << "Saved PNG screenshot to '" << fn << "'" << std::endl;
}