Add automatic input rate checkbox. Use as default.

This commit is contained in:
Brandon Wright 2018-05-02 17:43:32 -05:00
parent d726c6a8dd
commit 5874559a3e
6 changed files with 157 additions and 106 deletions

View File

@ -403,6 +403,7 @@ Snes9xConfig::save_config_file (void)
xml_out_int (xml, "sound_sync", Settings.SoundSync);
xml_out_int (xml, "dynamic_rate_control", Settings.DynamicRateControl);
xml_out_int (xml, "dynamic_rate_limit", Settings.DynamicRateLimit);
xml_out_int (xml, "auto_input_rate", auto_input_rate);
/* Snes9X core-stored variables */
xml_out_int (xml, "transparency", Settings.Transparency);
@ -667,6 +668,10 @@ Snes9xConfig::set_option (const char *name, const char *value)
Settings.DynamicRateLimit = atoi (value);
Settings.DynamicRateLimit = CLAMP (Settings.DynamicRateLimit, 1, 1000);
}
else if (!strcasecmp (name, "auto_input_rate"))
{
auto_input_rate = atoi (value);
}
else if (!strcasecmp (name, "gaussian_interpolation"))
{
}

View File

@ -465,66 +465,22 @@ event_input_rate_changed (GtkRange *range, gpointer data)
return;
}
static double XRRGetExactRefreshRate (Display *dpy, Window window)
{
XRRScreenResources *resources = NULL;
XRROutputInfo *output_info = NULL;
XRRCrtcInfo *crtc_info = NULL;
RROutput output;
int event_base;
int error_base;
int version_major;
int version_minor;
double refresh_rate = 0.0;
int i;
if (!XRRQueryExtension (dpy, &event_base, &error_base) ||
!XRRQueryVersion (dpy, &version_major, &version_minor))
{
return refresh_rate;
}
resources = XRRGetScreenResources (dpy, window);
output = XRRGetOutputPrimary (dpy, window);
output_info = XRRGetOutputInfo (dpy, resources, output);
crtc_info = XRRGetCrtcInfo (dpy, resources, output_info->crtc);
for (i = 0; i < resources->nmode; i++)
{
if (resources->modes[i].id == crtc_info->mode)
{
XRRModeInfo *m = &resources->modes[i];
refresh_rate = (double) m->dotClock / m->hTotal / m->vTotal;
refresh_rate /= m->modeFlags & RR_DoubleScan ? 2 : 1;
refresh_rate /= m->modeFlags & RR_ClockDivideBy2 ? 2 : 1;
refresh_rate *= m->modeFlags & RR_DoubleClock ? 2 : 1;
break;
}
}
XRRFreeCrtcInfo (crtc_info);
XRRFreeOutputInfo (output_info);
XRRFreeScreenResources (resources);
return refresh_rate;
}
static void
event_set_input_rate (GtkButton *widget, gpointer data)
void
event_auto_input_rate_toggled (GtkToggleButton *togglebutton, gpointer data)
{
Snes9xPreferences *preferences = (Snes9xPreferences *) data;
GdkWindow *gdk_window = gtk_widget_get_window (GTK_WIDGET(top_level->get_window()));
Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdk_window));
Window window = GDK_COMPAT_WINDOW_XID (gdk_window);
double rate = XRRGetExactRefreshRate(dpy, window);
if (rate != 0.0)
preferences->set_slider("sound_input_rate", (int) (rate * 32040 / 60.09881389744051 + 0.5));
if (gtk_toggle_button_get_active (togglebutton))
{
preferences->set_slider("sound_input_rate", top_level->get_auto_input_rate ());
gtk_widget_set_sensitive (preferences->get_widget("sound_input_rate"), FALSE);
}
else
{
gtk_widget_set_sensitive (preferences->get_widget("sound_input_rate"), TRUE);
}
}
static void
event_about_clicked (GtkButton *widget, gpointer data)
{
@ -620,7 +576,7 @@ Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) :
{ "game_data_browse", G_CALLBACK (event_game_data_browse) },
{ "game_data_clear", G_CALLBACK (event_game_data_clear) },
{ "about_clicked", G_CALLBACK (event_about_clicked) },
{ "set_input_rate", G_CALLBACK (event_set_input_rate) },
{ "auto_input_rate_toggled", G_CALLBACK (event_auto_input_rate_toggled) },
#ifdef USE_JOYSTICK
{ "calibrate", G_CALLBACK (event_calibrate) },
#endif
@ -737,6 +693,9 @@ Snes9xPreferences::move_settings_to_dialog (void)
set_spin ("num_threads", config->num_threads);
set_check ("mute_sound_check", config->mute_sound);
set_check ("mute_sound_turbo_check", config->mute_sound_turbo);
set_check ("auto_input_rate", config->auto_input_rate);
gtk_widget_set_sensitive (get_widget("sound_input_rate"),
config->auto_input_rate ? FALSE : TRUE);
set_spin ("sound_buffer_size", config->sound_buffer_size);
set_slider ("sound_input_rate", config->sound_input_rate);
set_check ("sync_sound", Settings.SoundSync);
@ -826,16 +785,15 @@ Snes9xPreferences::get_settings_from_dialog (void)
int sound_needs_restart = 0;
int gfx_needs_restart = 0;
if ((config->sound_driver != get_combo ("sound_driver")) ||
(config->mute_sound != get_check ("mute_sound_check")) ||
(config->sound_buffer_size != (int) get_spin ("sound_buffer_size"))||
(Settings.Stereo != get_check ("stereo_check")) ||
(config->sound_playback_rate !=
(7 - (get_combo ("playback_combo")))) ||
(config->sound_input_rate != get_slider ("sound_input_rate")) ||
(Settings.SoundSync != get_check ("sync_sound")) ||
(Settings.DynamicRateControl != get_check ("dynamic_rate_control"))
)
if ((config->sound_driver != get_combo ("sound_driver")) ||
(config->mute_sound != get_check ("mute_sound_check")) ||
(config->sound_buffer_size != (int) get_spin ("sound_buffer_size")) ||
(Settings.Stereo != get_check ("stereo_check")) ||
(config->sound_playback_rate != (7 - (get_combo ("playback_combo")))) ||
(config->sound_input_rate != get_slider ("sound_input_rate")) ||
(config->auto_input_rate != get_check ("auto_input_rate")) ||
(Settings.SoundSync != get_check ("sync_sound")) ||
(Settings.DynamicRateControl != get_check ("dynamic_rate_control")))
{
sound_needs_restart = 1;
}
@ -889,6 +847,7 @@ Snes9xPreferences::get_settings_from_dialog (void)
config->sound_playback_rate = 7 - (get_combo ("playback_combo"));
config->sound_buffer_size = get_spin ("sound_buffer_size");
config->sound_input_rate = get_slider ("sound_input_rate");
config->auto_input_rate = get_check ("auto_input_rate");
Settings.SoundSync = get_check ("sync_sound");
config->mute_sound = get_check ("mute_sound_check");
config->mute_sound_turbo = get_check ("mute_sound_turbo_check");

View File

@ -1529,6 +1529,74 @@ Snes9xWindow::toggle_fullscreen_mode (void)
enter_fullscreen_mode ();
}
static double XRRGetExactRefreshRate (Display *dpy, Window window)
{
XRRScreenResources *resources = NULL;
XRROutputInfo *output_info = NULL;
XRRCrtcInfo *crtc_info = NULL;
RROutput output;
int event_base;
int error_base;
int version_major;
int version_minor;
double refresh_rate = 0.0;
int i;
if (!XRRQueryExtension (dpy, &event_base, &error_base) ||
!XRRQueryVersion (dpy, &version_major, &version_minor))
{
return refresh_rate;
}
resources = XRRGetScreenResources (dpy, window);
output = XRRGetOutputPrimary (dpy, window);
output_info = XRRGetOutputInfo (dpy, resources, output);
crtc_info = XRRGetCrtcInfo (dpy, resources, output_info->crtc);
for (i = 0; i < resources->nmode; i++)
{
if (resources->modes[i].id == crtc_info->mode)
{
XRRModeInfo *m = &resources->modes[i];
refresh_rate = (double) m->dotClock / m->hTotal / m->vTotal;
refresh_rate /= m->modeFlags & RR_DoubleScan ? 2 : 1;
refresh_rate /= m->modeFlags & RR_ClockDivideBy2 ? 2 : 1;
refresh_rate *= m->modeFlags & RR_DoubleClock ? 2 : 1;
break;
}
}
XRRFreeCrtcInfo (crtc_info);
XRRFreeOutputInfo (output_info);
XRRFreeScreenResources (resources);
return refresh_rate;
}
double
Snes9xWindow::get_refresh_rate (void)
{
Window xid = gdk_x11_window_get_xid(gtk_widget_get_window (window));
Display *dpy = gdk_x11_display_get_xdisplay(gtk_widget_get_display (window));
double refresh_rate = XRRGetExactRefreshRate (dpy, xid);
if (refresh_rate < 10.0)
{
printf ("Warning: Couldn't read refresh rate.\n");
refresh_rate = 60.0;
}
return refresh_rate;
}
int
Snes9xWindow::get_auto_input_rate (void)
{
return (int) (get_refresh_rate () * 32040.0 / 60.09881389744051 + 0.5);
}
static void set_bypass_compositor (Display *dpy, Window window, unsigned char bypass)
{
Atom net_wm_bypass_compositor = XInternAtom (dpy, "_NET_WM_BYPASS_COMPOSITOR", False);
@ -1569,6 +1637,12 @@ Snes9xWindow::enter_fullscreen_mode (void)
{
config->change_display_resolution = 0;
}
if (gui_config->auto_input_rate)
{
Settings.SoundInputRate = top_level->get_auto_input_rate ();
S9xUpdateDynamicRate (1, 1);
}
}
/* Make sure everything is done synchronously */
@ -1623,6 +1697,12 @@ Snes9xWindow::leave_fullscreen_mode (void)
config->xrr_crtc_info->rotation,
&config->xrr_output,
1);
if (gui_config->auto_input_rate)
{
Settings.SoundInputRate = top_level->get_auto_input_rate ();
S9xUpdateDynamicRate (1, 1);
}
}
gtk_window_unfullscreen (GTK_WINDOW (window));

View File

@ -61,6 +61,8 @@ class Snes9xWindow : public GtkBuilderWindow
void resize_to_multiple (int factor);
void resize_viewport (int width, int height);
void expose (void);
double get_refresh_rate (void);
int get_auto_input_rate (void);
cairo_t *get_cairo (void);
void release_cairo (void);

View File

@ -127,7 +127,14 @@ S9xPortSoundInit (void)
{
driver->init ();
Settings.SoundInputRate = CLAMP (gui_config->sound_input_rate, 8000, 48000);
if (gui_config->auto_input_rate)
{
Settings.SoundInputRate = top_level->get_auto_input_rate ();
}
else
{
Settings.SoundInputRate = CLAMP (gui_config->sound_input_rate, 8000, 48000);
}
Settings.SoundPlaybackRate = playback_rates[gui_config->sound_playback_rate];

View File

@ -4047,7 +4047,22 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="auto_input_rate">
<property name="label" translatable="yes">Automatically adjust input rate to display</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Sets the correct input rate based on the display's refresh rate</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="auto_input_rate_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="dynamic_rate_control">
<property name="label" translatable="yes">Dynamic rate control</property>
@ -4060,7 +4075,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
@ -4077,7 +4092,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
<child>
@ -4093,7 +4108,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
<property name="position">5</property>
</packing>
</child>
<child>
@ -4109,7 +4124,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
<property name="position">6</property>
</packing>
</child>
<child>
@ -4171,8 +4186,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4185,8 +4200,8 @@
<property name="label" translatable="yes">Buffer size:</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4199,8 +4214,8 @@
<property name="label" translatable="yes">Dynamic rate limit:</property>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4229,8 +4244,8 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options">GTK_FILL</property>
<property name="x_options">GTK_FILL</property>
</packing>
@ -4243,8 +4258,8 @@
<property name="label" translatable="yes">Input rate:</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4262,8 +4277,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
@ -4297,23 +4312,6 @@
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkButton" id="set_input_rate_button">
<property name="label" translatable="yes">Automatically Set Input Rate</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="set_input_rate" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label139">
<property name="visible">True</property>
@ -4322,8 +4320,8 @@
<property name="label" translatable="yes">Video rate:</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4337,8 +4335,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
@ -4346,7 +4344,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
<property name="position">7</property>
</packing>
</child>
</object>