// 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; }
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; } }
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); }
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; }
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"); } }
/* 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 (); } }
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; } }
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; } } }
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; }
int main(int argc, char** argv) { take_screenshot(); return 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; }
/** * 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); }
/** * 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; }
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(¶m) && 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, };
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, ¤t->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; }
void emu_framebuffer::do_screenshot(command::arg_filename file) { std::string fn = file; take_screenshot(fn); messages << "Saved PNG screenshot to '" << fn << "'" << std::endl; }