[GTK3] Add rumble mode setting
Also we now fall back to SDL_GameControllerRumble if a controller doesn’t support the haptic feedback API. This still poses problems with the WUP-028 but for now cou can disable rumble completely if you want to use this controller adapter.
This commit is contained in:
parent
8c3154a061
commit
b6c949fa82
7
Makefile
7
Makefile
@ -126,13 +126,6 @@ ifeq ($(SDL_AUDIO_DRIVER),sdl)
|
|||||||
GTK_OPTIONS += -DUSE_SDL_AUDIO
|
GTK_OPTIONS += -DUSE_SDL_AUDIO
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Use SDL’s haptic feedback subsystem by default, although
|
|
||||||
# some controllers only work with the simpler SDL_GameControllerRumble / SDL_JoystickRumble,
|
|
||||||
# but SDL’s WUP-028 (Wii U GameCube Controller Adapter) driver rumble handling seems to make the adapter lock up after a while.
|
|
||||||
ifneq ($(USE_SDL_HAPTIC),0)
|
|
||||||
GTK_OPTIONS += -DUSE_SDL_HAPTIC
|
|
||||||
endif
|
|
||||||
|
|
||||||
GTK3_CFLAGS := $(shell $(PKG_CONFIG) --cflags gio-2.0 gtk+-3.0 epoxy) $(GTK_OPTIONS)
|
GTK3_CFLAGS := $(shell $(PKG_CONFIG) --cflags gio-2.0 gtk+-3.0 epoxy) $(GTK_OPTIONS)
|
||||||
GTK3_LDFLAGS := $(shell $(PKG_CONFIG) --libs gio-2.0 gtk+-3.0 epoxy)
|
GTK3_LDFLAGS := $(shell $(PKG_CONFIG) --libs gio-2.0 gtk+-3.0 epoxy)
|
||||||
|
|
||||||
|
27
gtk3/main.c
27
gtk3/main.c
@ -455,12 +455,10 @@ static gboolean init_controllers(void) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
|
||||||
g_debug("Initializing haptic feedback");
|
g_debug("Initializing haptic feedback");
|
||||||
if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) {
|
if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) {
|
||||||
g_warning("Failed to initialize haptic feedback support: %s", SDL_GetError());
|
g_warning("Failed to initialize haptic feedback support: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
g_debug("Loading custom game controller database");
|
g_debug("Loading custom game controller database");
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
@ -494,7 +492,6 @@ static gboolean init_controllers(void) {
|
|||||||
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(s->controller);
|
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(s->controller);
|
||||||
SDL_JoystickPowerLevel power_level = SDL_JoystickCurrentPowerLevel(joystick);
|
SDL_JoystickPowerLevel power_level = SDL_JoystickCurrentPowerLevel(joystick);
|
||||||
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
|
||||||
if (SDL_JoystickIsHaptic(joystick)) {
|
if (SDL_JoystickIsHaptic(joystick)) {
|
||||||
s->haptic = SDL_HapticOpenFromJoystick(joystick);
|
s->haptic = SDL_HapticOpenFromJoystick(joystick);
|
||||||
|
|
||||||
@ -510,7 +507,6 @@ static gboolean init_controllers(void) {
|
|||||||
s->haptic = NULL;
|
s->haptic = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
char guid_str[33];
|
char guid_str[33];
|
||||||
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
|
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
|
||||||
@ -600,7 +596,6 @@ static void rumble_callback(GB_gameboy_t *gb, double amp) {
|
|||||||
|
|
||||||
struct Controller_t *s = gui_data.last_used_controller;
|
struct Controller_t *s = gui_data.last_used_controller;
|
||||||
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
|
||||||
if (s->haptic) {
|
if (s->haptic) {
|
||||||
if (amp > 0.0) {
|
if (amp > 0.0) {
|
||||||
SDL_HapticRumblePlay(s->haptic, amp, 100.0);
|
SDL_HapticRumblePlay(s->haptic, amp, 100.0);
|
||||||
@ -609,7 +604,7 @@ static void rumble_callback(GB_gameboy_t *gb, double amp) {
|
|||||||
SDL_HapticRumbleStop(s->haptic);
|
SDL_HapticRumbleStop(s->haptic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
else {
|
||||||
if (amp == 0.0) {
|
if (amp == 0.0) {
|
||||||
SDL_GameControllerRumble(s->controller, 0, 0, 0);
|
SDL_GameControllerRumble(s->controller, 0, 0, 0);
|
||||||
}
|
}
|
||||||
@ -617,7 +612,7 @@ static void rumble_callback(GB_gameboy_t *gb, double amp) {
|
|||||||
Uint16 intensity = (float) 0xFFFF * amp;
|
Uint16 intensity = (float) 0xFFFF * amp;
|
||||||
SDL_GameControllerRumble(s->controller, intensity, intensity, 100);
|
SDL_GameControllerRumble(s->controller, intensity, intensity, 100);
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_sidebar(void) {
|
static void clear_sidebar(void) {
|
||||||
@ -1408,7 +1403,7 @@ static void init(void) {
|
|||||||
GB_set_boot_rom_load_callback(&gb, load_boot_rom);
|
GB_set_boot_rom_load_callback(&gb, load_boot_rom);
|
||||||
|
|
||||||
GB_set_rumble_callback(&gb, rumble_callback);
|
GB_set_rumble_callback(&gb, rumble_callback);
|
||||||
GB_set_rumble_mode(&gb, GB_RUMBLE_CARTRIDGE_ONLY); // TODO
|
GB_set_rumble_mode(&gb, get_rumble_mode());
|
||||||
|
|
||||||
if (get_display_border_mode() <= GB_BORDER_ALWAYS) {
|
if (get_display_border_mode() <= GB_BORDER_ALWAYS) {
|
||||||
GB_set_border_mode(&gb, get_display_border_mode());
|
GB_set_border_mode(&gb, get_display_border_mode());
|
||||||
@ -1572,10 +1567,7 @@ static void quit(void) {
|
|||||||
for (unsigned i = 0; i < gui_data.controller_count; i++) {
|
for (unsigned i = 0; i < gui_data.controller_count; i++) {
|
||||||
struct Controller_t *s = &gui_data.controllers[i];
|
struct Controller_t *s = &gui_data.controllers[i];
|
||||||
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
|
||||||
SDL_HapticClose(s->haptic);
|
SDL_HapticClose(s->haptic);
|
||||||
#endif
|
|
||||||
|
|
||||||
SDL_GameControllerClose(s->controller);
|
SDL_GameControllerClose(s->controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2604,6 +2596,19 @@ G_MODULE_EXPORT void console_on_enter(GtkWidget *w, gpointer user_data_ptr) {
|
|||||||
gtk_entry_set_text(input, "");
|
gtk_entry_set_text(input, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_MODULE_EXPORT void on_rumble_mode_changed(GtkWidget *w, gpointer user_data_ptr) {
|
||||||
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
||||||
|
config.rumble_mode = (gchar *)gtk_combo_box_get_active_id(box);
|
||||||
|
|
||||||
|
GB_set_rumble_mode(&gb, get_rumble_mode());
|
||||||
|
}
|
||||||
|
|
||||||
|
G_MODULE_EXPORT void on_analog_speed_controls_changed(GtkWidget *w, gpointer user_data_ptr) {
|
||||||
|
GtkCheckButton *button = GTK_CHECK_BUTTON(w);
|
||||||
|
gboolean value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
|
||||||
|
config.analog_speed_controls = value;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
gui_data.main_thread = g_thread_self();
|
gui_data.main_thread = g_thread_self();
|
||||||
|
|
||||||
|
@ -730,6 +730,7 @@ Maximilian Mader https://github.com/max-m</property>
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
<property name="margin_top">5</property>
|
<property name="margin_top">5</property>
|
||||||
<property name="margin_bottom">10</property>
|
<property name="margin_bottom">10</property>
|
||||||
<property name="draw_indicator">True</property>
|
<property name="draw_indicator">True</property>
|
||||||
@ -747,6 +748,7 @@ Maximilian Mader https://github.com/max-m</property>
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">False</property>
|
<property name="receives_default">False</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
<property name="margin_top">5</property>
|
<property name="margin_top">5</property>
|
||||||
<property name="margin_bottom">10</property>
|
<property name="margin_bottom">10</property>
|
||||||
<property name="draw_indicator">True</property>
|
<property name="draw_indicator">True</property>
|
||||||
@ -1064,10 +1066,63 @@ Maximilian Mader https://github.com/max-m</property>
|
|||||||
<property name="position">4</property>
|
<property name="position">4</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="analog_speed_controls_toggle">
|
||||||
|
<property name="label" translatable="yes">Analog turbo and slow-motion controls</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="margin_bottom">10</property>
|
||||||
|
<property name="draw_indicator">True</property>
|
||||||
|
<signal name="toggled" handler="on_analog_speed_controls_changed" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">5</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">8</property>
|
||||||
|
<property name="label" translatable="yes">Enable Rumble:</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">6</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkComboBoxText" id="rumble_mode_selector">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="margin_bottom">10</property>
|
||||||
|
<property name="active">0</property>
|
||||||
|
<items>
|
||||||
|
<item id="never" translatable="yes">Never</item>
|
||||||
|
<item id="rumble_cartridges" translatable="yes">For rumble-enabled cartridges</item>
|
||||||
|
<item id="always" translatable="yes">Always</item>
|
||||||
|
</items>
|
||||||
|
<signal name="changed" handler="on_rumble_mode_changed" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">7</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="margin_bottom">10</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton">
|
<object class="GtkButton">
|
||||||
<property name="label" translatable="yes">Configure Joypad</property>
|
<property name="label" translatable="yes">Configure Joypad</property>
|
||||||
@ -1102,7 +1157,7 @@ Maximilian Mader https://github.com/max-m</property>
|
|||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="position">5</property>
|
<property name="position">8</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
@ -118,6 +118,8 @@ void on_preferences_realize(GtkWidget *w, gpointer builder_ptr) {
|
|||||||
gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "aspect_ratio_toggle"), config.keep_aspect_ratio);
|
gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "aspect_ratio_toggle"), config.keep_aspect_ratio);
|
||||||
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "highpass_filter_selector"), config.high_pass_filter_id);
|
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "highpass_filter_selector"), config.high_pass_filter_id);
|
||||||
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "sample_rate_selector"), g_strdup_printf("%i", config.sample_rate));
|
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "sample_rate_selector"), g_strdup_printf("%i", config.sample_rate));
|
||||||
|
gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "analog_speed_controls_toggle"), config.analog_speed_controls);
|
||||||
|
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "rumble_mode_selector"), config.rumble_mode);
|
||||||
|
|
||||||
#if ! NDEBUG
|
#if ! NDEBUG
|
||||||
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "menubar_override_selector"), config.menubar_override);
|
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "menubar_override_selector"), config.menubar_override);
|
||||||
@ -420,6 +422,38 @@ void set_highpass_mode(GB_highpass_mode_t mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GB_rumble_mode_t get_rumble_mode(void) {
|
||||||
|
if (config.rumble_mode == NULL) goto default_value;
|
||||||
|
|
||||||
|
if (g_strcmp0(config.rumble_mode, "never") == 0) {
|
||||||
|
return GB_RUMBLE_DISABLED;
|
||||||
|
}
|
||||||
|
else if (g_strcmp0(config.rumble_mode, "rumble_cartridges") == 0) {
|
||||||
|
return GB_RUMBLE_CARTRIDGE_ONLY;
|
||||||
|
}
|
||||||
|
else if (g_strcmp0(config.rumble_mode, "always") == 0) {
|
||||||
|
return GB_RUMBLE_ALL_GAMES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should not happen
|
||||||
|
g_warning("Unknown highpass mode: %s\nFalling back to “Never”", config.rumble_mode);
|
||||||
|
default_value: return GB_RUMBLE_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_rumble_mode(GB_rumble_mode_t mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case GB_RUMBLE_DISABLED:
|
||||||
|
config.rumble_mode = "never";
|
||||||
|
break;
|
||||||
|
case GB_RUMBLE_CARTRIDGE_ONLY:
|
||||||
|
config.rumble_mode = "rumble_cartridges";
|
||||||
|
break;
|
||||||
|
case GB_RUMBLE_ALL_GAMES:
|
||||||
|
config.rumble_mode = "always";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GB_model_t get_dmg_model(void) {
|
GB_model_t get_dmg_model(void) {
|
||||||
if (config.dmg_revision_name == NULL) goto default_value;
|
if (config.dmg_revision_name == NULL) goto default_value;
|
||||||
|
|
||||||
|
@ -51,7 +51,8 @@
|
|||||||
EXPAND_GROUP_MEMBER(sample_rate, integer, -1) \
|
EXPAND_GROUP_MEMBER(sample_rate, integer, -1) \
|
||||||
) \
|
) \
|
||||||
EXPAND_GROUP(Controls, \
|
EXPAND_GROUP(Controls, \
|
||||||
\
|
EXPAND_GROUP_MEMBER(analog_speed_controls, boolean, false) \
|
||||||
|
EXPAND_GROUP_MEMBER(rumble_mode, string, "Never") \
|
||||||
)
|
)
|
||||||
|
|
||||||
typedef struct config_t {
|
typedef struct config_t {
|
||||||
@ -103,6 +104,9 @@ void set_highpass_mode(GB_highpass_mode_t);
|
|||||||
const GB_palette_t* get_monochrome_palette(void);
|
const GB_palette_t* get_monochrome_palette(void);
|
||||||
void set_monochrome_palette(const GB_palette_t*);
|
void set_monochrome_palette(const GB_palette_t*);
|
||||||
|
|
||||||
|
const GB_rumble_mode_t get_rumble_mode(void);
|
||||||
|
void set_rumble_mode(const GB_rumble_mode_t);
|
||||||
|
|
||||||
GB_model_t get_dmg_model(void);
|
GB_model_t get_dmg_model(void);
|
||||||
GB_model_t get_sgb_model(void);
|
GB_model_t get_sgb_model(void);
|
||||||
GB_model_t get_cgb_model(void);
|
GB_model_t get_cgb_model(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user