[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
|
||||
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_LDFLAGS := $(shell $(PKG_CONFIG) --libs gio-2.0 gtk+-3.0 epoxy)
|
||||
|
||||
|
77
gtk3/main.c
77
gtk3/main.c
@ -455,12 +455,10 @@ static gboolean init_controllers(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
g_debug("Initializing haptic feedback");
|
||||
if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) {
|
||||
g_warning("Failed to initialize haptic feedback support: %s", SDL_GetError());
|
||||
}
|
||||
#endif
|
||||
g_debug("Initializing haptic feedback");
|
||||
if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) {
|
||||
g_warning("Failed to initialize haptic feedback support: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
g_debug("Loading custom game controller database");
|
||||
GError *error = NULL;
|
||||
@ -494,23 +492,21 @@ static gboolean init_controllers(void) {
|
||||
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(s->controller);
|
||||
SDL_JoystickPowerLevel power_level = SDL_JoystickCurrentPowerLevel(joystick);
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
if (SDL_JoystickIsHaptic(joystick)) {
|
||||
s->haptic = SDL_HapticOpenFromJoystick(joystick);
|
||||
if (SDL_JoystickIsHaptic(joystick)) {
|
||||
s->haptic = SDL_HapticOpenFromJoystick(joystick);
|
||||
|
||||
if (s->haptic && SDL_HapticRumbleSupported(s->haptic)) {
|
||||
SDL_HapticRumbleInit(s->haptic);
|
||||
}
|
||||
else {
|
||||
if (s->haptic == NULL) {
|
||||
g_warning("%s", SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_HapticClose(s->haptic);
|
||||
s->haptic = NULL;
|
||||
}
|
||||
if (s->haptic && SDL_HapticRumbleSupported(s->haptic)) {
|
||||
SDL_HapticRumbleInit(s->haptic);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if (s->haptic == NULL) {
|
||||
g_warning("%s", SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_HapticClose(s->haptic);
|
||||
s->haptic = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char guid_str[33];
|
||||
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
|
||||
@ -600,16 +596,15 @@ static void rumble_callback(GB_gameboy_t *gb, double amp) {
|
||||
|
||||
struct Controller_t *s = gui_data.last_used_controller;
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
if (s->haptic) {
|
||||
if (amp > 0.0) {
|
||||
SDL_HapticRumblePlay(s->haptic, amp, 100.0);
|
||||
}
|
||||
else {
|
||||
SDL_HapticRumbleStop(s->haptic);
|
||||
}
|
||||
if (s->haptic) {
|
||||
if (amp > 0.0) {
|
||||
SDL_HapticRumblePlay(s->haptic, amp, 100.0);
|
||||
}
|
||||
#else
|
||||
else {
|
||||
SDL_HapticRumbleStop(s->haptic);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (amp == 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;
|
||||
SDL_GameControllerRumble(s->controller, intensity, intensity, 100);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
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_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) {
|
||||
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++) {
|
||||
struct Controller_t *s = &gui_data.controllers[i];
|
||||
|
||||
#ifdef USE_SDL_HAPTIC
|
||||
SDL_HapticClose(s->haptic);
|
||||
#endif
|
||||
|
||||
SDL_HapticClose(s->haptic);
|
||||
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, "");
|
||||
}
|
||||
|
||||
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[]) {
|
||||
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="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>
|
||||
@ -747,6 +748,7 @@ Maximilian Mader https://github.com/max-m</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>
|
||||
@ -1064,10 +1066,63 @@ Maximilian Mader https://github.com/max-m</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</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>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_top">5</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Configure Joypad</property>
|
||||
@ -1102,7 +1157,7 @@ Maximilian Mader https://github.com/max-m</property>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
<property name="position">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
</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_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_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
|
||||
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) {
|
||||
if (config.dmg_revision_name == NULL) goto default_value;
|
||||
|
||||
|
@ -51,7 +51,8 @@
|
||||
EXPAND_GROUP_MEMBER(sample_rate, integer, -1) \
|
||||
) \
|
||||
EXPAND_GROUP(Controls, \
|
||||
\
|
||||
EXPAND_GROUP_MEMBER(analog_speed_controls, boolean, false) \
|
||||
EXPAND_GROUP_MEMBER(rumble_mode, string, "Never") \
|
||||
)
|
||||
|
||||
typedef struct config_t {
|
||||
@ -103,6 +104,9 @@ void set_highpass_mode(GB_highpass_mode_t);
|
||||
const GB_palette_t* get_monochrome_palette(void);
|
||||
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_sgb_model(void);
|
||||
GB_model_t get_cgb_model(void);
|
||||
|
Loading…
Reference in New Issue
Block a user