From 8614b890d377a45a765c2fab3b230512648f8b13 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sun, 24 Apr 2022 15:31:45 +1000 Subject: [PATCH] osd/modules/input: Detect joystick reconnection with SDL. (#9605) Also improved display name scheme for joystick axes and buttons. --- src/osd/modules/input/input_common.h | 4 +- src/osd/modules/input/input_dinput.cpp | 8 +- src/osd/modules/input/input_dinput.h | 4 +- src/osd/modules/input/input_rawinput.cpp | 22 +- src/osd/modules/input/input_sdl.cpp | 312 +++++++++++++--------- src/osd/modules/input/input_sdlcommon.cpp | 2 +- src/osd/modules/input/input_sdlcommon.h | 44 +-- src/osd/modules/input/input_win32.cpp | 14 +- src/osd/modules/input/input_x11.cpp | 12 +- src/osd/modules/input/input_xinput.cpp | 2 +- 10 files changed, 230 insertions(+), 194 deletions(-) diff --git a/src/osd/modules/input/input_common.h b/src/osd/modules/input/input_common.h index 45661fe957c..a26d6f5375e 100644 --- a/src/osd/modules/input/input_common.h +++ b/src/osd/modules/input/input_common.h @@ -447,7 +447,7 @@ protected: public: const osd_options * options() const { return m_options; } - input_device_list * devicelist() { return &m_devicelist; } + input_device_list & devicelist() { return m_devicelist; } bool input_enabled() const { return m_input_enabled; } bool input_paused() const { return m_input_paused; } bool mouse_enabled() const { return m_mouse_enabled; } @@ -504,7 +504,7 @@ public: virtual void exit() override { - devicelist()->free_all_devices(); + devicelist().free_all_devices(); } protected: diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp index 8ceb29e21f4..7295b23de12 100644 --- a/src/osd/modules/input/input_dinput.cpp +++ b/src/osd/modules/input/input_dinput.cpp @@ -238,7 +238,7 @@ public: result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_REL); if (result != DI_OK && result != DI_PROPNOEFFECT) { - osd_printf_error("DirectInput: Unable to set relative mode for mouse %u (%s)\n", static_cast(devicelist()->size()), devinfo->name()); + osd_printf_error("DirectInput: Unable to set relative mode for mouse %u (%s)\n", static_cast(devicelist().size()), devinfo->name()); goto error; } @@ -277,7 +277,7 @@ public: error: if (devinfo) - devicelist()->free_device(*devinfo); + devicelist().free_device(*devinfo); goto exit; } }; @@ -449,10 +449,10 @@ void dinput_joystick_device::poll() int dinput_joystick_device::configure() { HRESULT result; - auto devicelist = static_cast(module()).devicelist(); + auto &devicelist = static_cast(module()).devicelist(); // temporary approximation of index - int devindex = devicelist->size(); + int devindex = devicelist.size(); // set absolute mode result = dinput_set_dword_property(dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_ABS); diff --git a/src/osd/modules/input/input_dinput.h b/src/osd/modules/input/input_dinput.h index 8600e73a04d..20bced84883 100644 --- a/src/osd/modules/input/input_dinput.h +++ b/src/osd/modules/input/input_dinput.h @@ -72,7 +72,7 @@ public: std::string utf8_instance_id = utf8_instance_name + " product_" + guid_to_string(instance->guidProduct) + " instance_" + guid_to_string(instance->guidInstance); // allocate memory for the device object - TDevice &devinfo = module.devicelist()->create_device(machine, std::move(utf8_instance_name), std::move(utf8_instance_id), module); + TDevice &devinfo = module.devicelist().create_device(machine, std::move(utf8_instance_name), std::move(utf8_instance_id), module); // attempt to create a device result = m_dinput->CreateDevice(instance->guidInstance, devinfo.dinput.device.GetAddressOf(), nullptr); @@ -133,7 +133,7 @@ public: return &devinfo; error: - module.devicelist()->free_device(devinfo); + module.devicelist().free_device(devinfo); return nullptr; } diff --git a/src/osd/modules/input/input_rawinput.cpp b/src/osd/modules/input/input_rawinput.cpp index 10b47a60e31..6424a0d1099 100644 --- a/src/osd/modules/input/input_rawinput.cpp +++ b/src/osd/modules/input/input_rawinput.cpp @@ -489,7 +489,7 @@ public: m_global_inputs_enabled = downcast(machine.options()).global_inputs(); // If we added no devices, no need to register for notifications - if (devicelist()->empty()) + if (devicelist().empty()) return; // finally, register to receive raw input WM_INPUT messages if we found devices @@ -539,7 +539,7 @@ protected: tname.reset(); - TDevice &devinfo = devicelist()->create_device(machine, std::move(utf8_name), std::move(utf8_id), *this); + TDevice &devinfo = devicelist().create_device(machine, std::move(utf8_name), std::move(utf8_id), *this); // Add the handle devinfo.set_handle(rawinputdevice.hDevice); @@ -594,14 +594,14 @@ protected: // find the device in the list and update auto target_device = std::find_if( - devicelist()->begin(), - devicelist()->end(), + devicelist().begin(), + devicelist().end(), [input] (auto const &device) { auto devinfo = dynamic_cast(device.get()); return devinfo && (input->header.hDevice == devinfo->device_handle()); }); - if (devicelist()->end() == target_device) + if (devicelist().end() == target_device) return false; static_cast(target_device->get())->queue_events(input, 1); @@ -629,14 +629,14 @@ protected: // find the device in the list and update auto target_device = std::find_if( - devicelist()->begin(), - devicelist()->end(), + devicelist().begin(), + devicelist().end(), [&utf8_id] (auto const &device) { auto devinfo = dynamic_cast(device.get()); return devinfo && !devinfo->device_handle() && (devinfo->id() == utf8_id); }); - if (devicelist()->end() == target_device) + if (devicelist().end() == target_device) return false; static_cast(target_device->get())->set_handle(rawinputdevice); @@ -652,15 +652,15 @@ protected: // find the device in the list and update auto target_device = std::find_if( - devicelist()->begin(), - devicelist()->end(), + devicelist().begin(), + devicelist().end(), [rawinputdevice] (auto const &device) { auto devinfo = dynamic_cast(device.get()); return devinfo && (rawinputdevice == devinfo->device_handle()); }); - if (devicelist()->end() == target_device) + if (devicelist().end() == target_device) return false; (*target_device)->reset(); diff --git a/src/osd/modules/input/input_sdl.cpp b/src/osd/modules/input/input_sdl.cpp index 58901627bcf..8937e4cb2a6 100644 --- a/src/osd/modules/input/input_sdl.cpp +++ b/src/osd/modules/input/input_sdl.cpp @@ -20,12 +20,13 @@ #include #include // ReSharper disable once CppUnusedIncludeDirective -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include // MAME headers #include "emu.h" @@ -373,6 +374,14 @@ protected: class sdl_keyboard_device : public sdl_device { public: + // state information for a keyboard + struct keyboard_state + { + int32_t state[0x3ff]; // must be int32_t! + int8_t oldkey[MAX_KEYS]; + int8_t currkey[MAX_KEYS]; + }; + keyboard_state keyboard; sdl_keyboard_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : @@ -483,6 +492,13 @@ private: int last_y; public: + // state information for a mouse + struct mouse_state + { + int32_t lX, lY; + int32_t buttons[MAX_BUTTONS]; + }; + mouse_state mouse; sdl_mouse_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : @@ -602,40 +618,40 @@ public: // sdl_joystick_device //============================================================ -// state information for a joystick -struct sdl_joystick_state -{ - int32_t axes[MAX_AXES]; - int32_t buttons[MAX_BUTTONS]; - int32_t hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS]; - int32_t balls[MAX_AXES]; -}; - -struct sdl_api_state -{ - SDL_Joystick *device; - SDL_Haptic *hapdevice; - SDL_JoystickID joystick_id; -}; - class sdl_joystick_device : public sdl_device { public: + // state information for a joystick + struct sdl_joystick_state + { + int32_t axes[MAX_AXES]; + int32_t buttons[MAX_BUTTONS]; + int32_t hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS]; + int32_t balls[MAX_AXES]; + }; + + struct sdl_api_state + { + SDL_Joystick *device = nullptr; + SDL_Haptic *hapdevice = nullptr; + SDL_JoystickID joystick_id; + std::optional serial; + }; + sdl_joystick_state joystick; sdl_api_state sdl_state; sdl_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : sdl_device(machine, std::move(name), std::move(id), DEVICE_CLASS_JOYSTICK, module), - joystick({{0}}), - sdl_state({ nullptr }) + joystick({{0}}) { } ~sdl_joystick_device() { - if (sdl_state.device != nullptr) + if (sdl_state.device) { - if (sdl_state.hapdevice != nullptr) + if (sdl_state.hapdevice) { SDL_HapticClose(sdl_state.hapdevice); sdl_state.hapdevice = nullptr; @@ -665,38 +681,10 @@ public: break; case SDL_JOYHATMOTION: - if (sdlevent.jhat.value & SDL_HAT_UP) - { - joystick.hatsU[sdlevent.jhat.hat] = 0x80; - } - else - { - joystick.hatsU[sdlevent.jhat.hat] = 0; - } - if (sdlevent.jhat.value & SDL_HAT_DOWN) - { - joystick.hatsD[sdlevent.jhat.hat] = 0x80; - } - else - { - joystick.hatsD[sdlevent.jhat.hat] = 0; - } - if (sdlevent.jhat.value & SDL_HAT_LEFT) - { - joystick.hatsL[sdlevent.jhat.hat] = 0x80; - } - else - { - joystick.hatsL[sdlevent.jhat.hat] = 0; - } - if (sdlevent.jhat.value & SDL_HAT_RIGHT) - { - joystick.hatsR[sdlevent.jhat.hat] = 0x80; - } - else - { - joystick.hatsR[sdlevent.jhat.hat] = 0; - } + joystick.hatsU[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_UP) ? 0x80 : 0; + joystick.hatsD[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_DOWN) ? 0x80 : 0; + joystick.hatsL[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_LEFT) ? 0x80 : 0; + joystick.hatsR[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_RIGHT) ? 0x80 : 0; break; case SDL_JOYBUTTONDOWN: @@ -704,6 +692,21 @@ public: if (sdlevent.jbutton.button < MAX_BUTTONS) joystick.buttons[sdlevent.jbutton.button] = (sdlevent.jbutton.state == SDL_PRESSED) ? 0x80 : 0; break; + + case SDL_JOYDEVICEREMOVED: + osd_printf_verbose("Joystick: %s [GUID %s] disconnected\n", name(), id()); + reset(); + if (sdl_state.device) + { + if (sdl_state.hapdevice) + { + SDL_HapticClose(sdl_state.hapdevice); + sdl_state.hapdevice = nullptr; + } + SDL_JoystickClose(sdl_state.device); + sdl_state.device = nullptr; + } + break; } } }; @@ -786,9 +789,10 @@ public: void handle_event(SDL_Event &sdlevent) override { // By default dispatch event to every device - devicelist()->for_each_device([&sdlevent](auto device) { - downcast(device)->queue_events(&sdlevent, 1); - }); + devicelist().for_each_device( + [&sdlevent](auto device) { + downcast(device)->queue_events(&sdlevent, 1); + }); } }; @@ -810,13 +814,12 @@ public: { sdl_input_module::input_init(machine); - static int event_types[] = { - static_cast(SDL_KEYDOWN), - static_cast(SDL_KEYUP), - static_cast(SDL_TEXTINPUT) - }; + static int const event_types[] = { + int(SDL_KEYDOWN), + int(SDL_KEYUP), + int(SDL_TEXTINPUT) }; - sdl_event_manager::instance().subscribe(event_types, std::size(event_types), this); + sdl_event_manager::instance().subscribe(event_types, this); // Read our keymap and store a pointer to our table m_key_trans_table = sdlinput_read_keymap(machine); @@ -826,7 +829,7 @@ public: osd_printf_verbose("Keyboard: Start initialization\n"); // SDL only has 1 keyboard add it now - auto &devinfo = devicelist()->create_device(machine, "System keyboard", "System keyboard", *this); + auto &devinfo = devicelist().create_device(machine, "System keyboard", "System keyboard", *this); // populate it for (int keynum = 0; local_table[keynum].mame_key != ITEM_ID_INVALID; keynum++) @@ -942,19 +945,18 @@ public: { sdl_input_module::input_init(machine); - static int event_types[] = { - static_cast(SDL_MOUSEMOTION), - static_cast(SDL_MOUSEBUTTONDOWN), - static_cast(SDL_MOUSEBUTTONUP), - static_cast(SDL_MOUSEWHEEL) - }; + static int const event_types[] = { + int(SDL_MOUSEMOTION), + int(SDL_MOUSEBUTTONDOWN), + int(SDL_MOUSEBUTTONUP), + int(SDL_MOUSEWHEEL) }; - sdl_event_manager::instance().subscribe(event_types, std::size(event_types), this); + sdl_event_manager::instance().subscribe(event_types, this); osd_printf_verbose("Mouse: Start initialization\n"); // SDL currently only supports one mouse - auto &devinfo = devicelist()->create_device(machine, "System mouse", "System mouse", *this); + auto &devinfo = devicelist().create_device(machine, "System mouse", "System mouse", *this); // add the axes devinfo.device()->add_item("X", ITEM_ID_XAXIS, generic_axis_get_state, &devinfo.mouse.lX); @@ -981,12 +983,15 @@ void devmap_register(device_map_t &devmap, int physical_idx, const std::string & auto entry = std::find_if( std::begin(devmap.map), std::end(devmap.map), - [&name] (auto &item) { return (item.name == name) && (item.physical < 0); }); + [&name] (auto const &item) { return (item.name == name) && (item.physical < 0); }); // If we didn't find it by name, find the first free slot if (entry == std::end(devmap.map)) { - entry = std::find_if(std::begin(devmap.map), std::end(devmap.map), [] (auto &item) { return item.name.empty(); }); + entry = std::find_if( + std::begin(devmap.map), + std::end(devmap.map), + [] (auto const &item) { return item.name.empty(); }); } if (entry != std::end(devmap.map)) @@ -1054,13 +1059,12 @@ public: char tempname[512]; - m_sixaxis_mode = downcast(options())->sixaxis(); + m_sixaxis_mode = downcast(options())->sixaxis(); devmap_init(machine, &m_joy_map, SDLOPTION_JOYINDEX, 8, "Joystick mapping"); osd_printf_verbose("Joystick: Start initialization\n"); - int physical_stick; - for (physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++) + for (int physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++) { std::string joy_name = remove_spaces(SDL_JoystickNameForIndex(physical_stick)); devmap_register(m_joy_map, physical_stick, joy_name); @@ -1073,28 +1077,40 @@ public: if (!devinfo) continue; - physical_stick = m_joy_map.map[stick].physical; - SDL_Joystick *joy = SDL_JoystickOpen(physical_stick); + int const physical_stick = m_joy_map.map[stick].physical; + SDL_Joystick *const joy = SDL_JoystickOpen(physical_stick); SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy); char guid_str[256]; guid_str[0] = '\0'; - SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)-1); + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1); devinfo->sdl_state.device = joy; devinfo->sdl_state.joystick_id = SDL_JoystickInstanceID(joy); devinfo->sdl_state.hapdevice = SDL_HapticOpenFromJoystick(joy); - - osd_printf_verbose("Joystick: %s [GUID %s]\n", SDL_JoystickNameForIndex(physical_stick), guid_str); - osd_printf_verbose("Joystick: ... %d axes, %d buttons %d hats %d balls\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy), SDL_JoystickNumBalls(joy)); - osd_printf_verbose("Joystick: ... Physical id %d mapped to logical id %d\n", physical_stick, stick + 1); - if (devinfo->sdl_state.hapdevice != nullptr) - { - osd_printf_verbose("Joystick: ... Has haptic capability\n"); - } +#if SDL_VERSION_ATLEAST(2, 0, 14) + char const *const serial = SDL_JoystickGetSerial(joy); + if (serial) + devinfo->sdl_state.serial = serial; + else +#endif // SDL_VERSION_ATLEAST(2, 0, 14) + devinfo->sdl_state.serial = std::nullopt; + + osd_printf_verbose("Joystick: %s [GUID %s] Vendor ID %04X, Product ID %04X, Revision %04X\n", + SDL_JoystickNameForIndex(physical_stick), + guid_str, + SDL_JoystickGetVendor(joy), + SDL_JoystickGetProduct(joy), + SDL_JoystickGetProductVersion(joy)); + osd_printf_verbose("Joystick: ... %d axes, %d buttons %d hats %d balls\n", + SDL_JoystickNumAxes(joy), + SDL_JoystickNumButtons(joy), + SDL_JoystickNumHats(joy), + SDL_JoystickNumBalls(joy)); + osd_printf_verbose("Joystick: ... Physical id %d mapped to logical id %d\n", physical_stick, stick + 1); + if (devinfo->sdl_state.hapdevice) + osd_printf_verbose("Joystick: ... Has haptic capability\n"); else - { osd_printf_verbose("Joystick: ... Does not have haptic capability\n"); - } // loop over all axes for (int axis = 0; axis < SDL_JoystickNumAxes(joy); axis++) @@ -1108,7 +1124,7 @@ public: else itemid = ITEM_ID_OTHER_AXIS_ABSOLUTE; - snprintf(tempname, sizeof(tempname), "A%d %s", axis, devinfo->name().c_str()); + snprintf(tempname, sizeof(tempname), "A%d", axis + 1); devinfo->device()->add_item(tempname, itemid, generic_axis_get_state, &devinfo->joystick.axes[axis]); } @@ -1128,7 +1144,7 @@ public: else itemid = ITEM_ID_OTHER_SWITCH; - snprintf(tempname, sizeof(tempname), "button %d", button); + snprintf(tempname, sizeof(tempname), "Button %d", button + 1); devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.buttons[button]); } @@ -1137,16 +1153,16 @@ public: { input_item_id itemid; - snprintf(tempname, sizeof(tempname), "hat %d Up", hat); + snprintf(tempname, sizeof(tempname), "Hat %d Up", hat + 1); itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1UP + 4 * hat : ITEM_ID_OTHER_SWITCH); devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsU[hat]); - snprintf(tempname, sizeof(tempname), "hat %d Down", hat); + snprintf(tempname, sizeof(tempname), "Hat %d Down", hat + 1); itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1DOWN + 4 * hat : ITEM_ID_OTHER_SWITCH); devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsD[hat]); - snprintf(tempname, sizeof(tempname), "hat %d Left", hat); + snprintf(tempname, sizeof(tempname), "Hat %d Left", hat + 1); itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1LEFT + 4 * hat : ITEM_ID_OTHER_SWITCH); devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsL[hat]); - snprintf(tempname, sizeof(tempname), "hat %d Right", hat); + snprintf(tempname, sizeof(tempname), "Hat %d Right", hat + 1); itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1RIGHT + 4 * hat : ITEM_ID_OTHER_SWITCH); devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsR[hat]); } @@ -1161,46 +1177,90 @@ public: else itemid = ITEM_ID_OTHER_AXIS_RELATIVE; - snprintf(tempname, sizeof(tempname), "R%d %s", ball * 2, devinfo->name().c_str()); + snprintf(tempname, sizeof(tempname), "R%d X", ball + 1); devinfo->device()->add_item(tempname, (input_item_id)itemid, generic_axis_get_state, &devinfo->joystick.balls[ball * 2]); - snprintf(tempname, sizeof(tempname), "R%d %s", ball * 2 + 1, devinfo->name().c_str()); + snprintf(tempname, sizeof(tempname), "R%d Y", ball + 1); devinfo->device()->add_item(tempname, (input_item_id)(itemid + 1), generic_axis_get_state, &devinfo->joystick.balls[ball * 2 + 1]); } } - static int event_types[] = { - static_cast(SDL_JOYAXISMOTION), - static_cast(SDL_JOYBALLMOTION), - static_cast(SDL_JOYHATMOTION), - static_cast(SDL_JOYBUTTONDOWN), - static_cast(SDL_JOYBUTTONUP) - }; + static int const event_types[] = { + int(SDL_JOYAXISMOTION), + int(SDL_JOYBALLMOTION), + int(SDL_JOYHATMOTION), + int(SDL_JOYBUTTONDOWN), + int(SDL_JOYBUTTONUP), + int(SDL_JOYDEVICEADDED), + int(SDL_JOYDEVICEREMOVED) }; - sdl_event_manager::instance().subscribe(event_types, std::size(event_types), this); + sdl_event_manager::instance().subscribe(event_types, this); osd_printf_verbose("Joystick: End initialization\n"); } virtual void handle_event(SDL_Event &sdlevent) override { - // Figure out which joystick this event id destined for - auto target_device = std::find_if( - devicelist()->begin(), - devicelist()->end(), - [&sdlevent] (auto &device) - { - std::unique_ptr &ptr = device; - return downcast(ptr.get())->sdl_state.joystick_id == sdlevent.jdevice.which; - }); - - // If we find a matching joystick, dispatch the event to the joystick - if (target_device != devicelist()->end()) + if (SDL_JOYDEVICEADDED == sdlevent.type) { - downcast((*target_device).get())->queue_events(&sdlevent, 1); + SDL_Joystick *const joy = SDL_JoystickOpen(sdlevent.jdevice.which); + if (joy) + { + SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy); + char guid_str[256]; + guid_str[0] = '\0'; + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1); + char const *serial = nullptr; +#if SDL_VERSION_ATLEAST(2, 0, 14) + serial = SDL_JoystickGetSerial(joy); +#endif + auto target_device = std::find_if( + devicelist().begin(), + devicelist().end(), + [&guid_str, &serial] (auto const &device) + { + auto &devinfo = downcast(*device); + return + !devinfo.sdl_state.device && + (devinfo.id() == guid_str) && + ((serial && devinfo.sdl_state.serial && (*devinfo.sdl_state.serial == serial)) || (!serial && !devinfo.sdl_state.serial)); + }); + if (devicelist().end() != target_device) + { + auto &devinfo = downcast(**target_device); + devinfo.sdl_state.device = joy; + devinfo.sdl_state.joystick_id = SDL_JoystickInstanceID(joy); + devinfo.sdl_state.hapdevice = SDL_HapticOpenFromJoystick(joy); + osd_printf_verbose("Joystick: %s [GUID %s] reconnected\n", devinfo.name(), guid_str); + } + else + { + SDL_JoystickClose(joy); + } + } + } + else + { + // Figure out which joystick this event id destined for + sdl_joystick_device *const target_device = find_joystick(sdlevent.jdevice.which); // FIXME: this depends on SDL_JoystickID being the same size as Sint32 + + // If we find a matching joystick, dispatch the event to the joystick + if (target_device) + target_device->queue_events(&sdlevent, 1); } } private: + sdl_joystick_device *find_joystick(SDL_JoystickID instance) + { + for (auto &ptr : devicelist()) + { + sdl_joystick_device *const device = downcast(ptr.get()); + if (device->sdl_state.device && (device->sdl_state.joystick_id == instance)) + return device; + } + return nullptr; + } + sdl_joystick_device *create_joystick_device(running_machine &machine, device_map_t *devmap, int index, input_device_class devclass) { char tempname[20]; @@ -1215,16 +1275,16 @@ private: { snprintf(tempname, std::size(tempname), "NC%d", index); m_sixaxis_mode - ? devicelist()->create_device(machine, tempname, guid_str, *this) - : devicelist()->create_device(machine, tempname, guid_str, *this); + ? devicelist().create_device(machine, tempname, guid_str, *this) + : devicelist().create_device(machine, tempname, guid_str, *this); } return nullptr; } return m_sixaxis_mode - ? &devicelist()->create_device(machine, std::string(devmap->map[index].name), guid_str, *this) - : &devicelist()->create_device(machine, std::string(devmap->map[index].name), guid_str, *this); + ? &devicelist().create_device(machine, std::string(devmap->map[index].name), guid_str, *this) + : &devicelist().create_device(machine, std::string(devmap->map[index].name), guid_str, *this); } }; diff --git a/src/osd/modules/input/input_sdlcommon.cpp b/src/osd/modules/input/input_sdlcommon.cpp index 92e3653e4d1..1f84e28f2f6 100644 --- a/src/osd/modules/input/input_sdlcommon.cpp +++ b/src/osd/modules/input/input_sdlcommon.cpp @@ -267,7 +267,7 @@ void sdl_osd_interface::release_keys() { auto keybd = dynamic_cast(m_keyboard_input); if (keybd != nullptr) - keybd->devicelist()->reset_devices(); + keybd->devicelist().reset_devices(); } bool sdl_osd_interface::should_hide_mouse() diff --git a/src/osd/modules/input/input_sdlcommon.h b/src/osd/modules/input/input_sdlcommon.h index 030a8ca4bd7..74b12a875ba 100644 --- a/src/osd/modules/input/input_sdlcommon.h +++ b/src/osd/modules/input/input_sdlcommon.h @@ -8,40 +8,17 @@ // //============================================================ -#ifndef INPUT_SDLCOMMON_H_ -#define INPUT_SDLCOMMON_H_ +#ifndef MAME_OSD_INPUT_INPUT_SDLCOMMON_H +#define MAME_OSD_INPUT_INPUT_SDLCOMMON_H + +#pragma once -#include #include +#include #define MAX_DEVMAP_ENTRIES 16 #define SDL_MODULE_EVENT_BUFFER_SIZE 5 -// state information for a keyboard -struct keyboard_state -{ - int32_t state[0x3ff]; // must be int32_t! - int8_t oldkey[MAX_KEYS]; - int8_t currkey[MAX_KEYS]; -}; - -// state information for a mouse -struct mouse_state -{ - int32_t lX, lY; - int32_t buttons[MAX_BUTTONS]; -}; - - -// state information for a joystick; DirectInput state must be first element -struct joystick_state -{ - SDL_Joystick *device; - int32_t axes[MAX_AXES]; - int32_t buttons[MAX_BUTTONS]; - int32_t hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS]; - int32_t balls[MAX_AXES]; -}; struct device_map_t { @@ -79,15 +56,14 @@ public: { } - void subscribe(int* event_types, int num_event_types, TSubscriber *subscriber) + template + void subscribe(int const (&event_types)[N], TSubscriber *subscriber) { std::lock_guard scope_lock(m_lock); // Add the subscription - for (int i = 0; i < num_event_types; i++) - { - m_subscription_index.emplace(event_types[i], subscriber); - } + for (int i : event_types) + m_subscription_index.emplace(i, subscriber); } void unsubscribe(TSubscriber *subscriber) @@ -199,4 +175,4 @@ static inline void devmap_init(running_machine &machine, device_map_t *devmap, c } } -#endif +#endif // MAME_OSD_INPUT_INPUT_SDLCOMMON_H diff --git a/src/osd/modules/input/input_win32.cpp b/src/osd/modules/input/input_win32.cpp index ff154140f7f..a02b2ee426e 100644 --- a/src/osd/modules/input/input_win32.cpp +++ b/src/osd/modules/input/input_win32.cpp @@ -74,7 +74,7 @@ public: virtual void input_init(running_machine &machine) override { // Add a single win32 keyboard device that we'll monitor using Win32 - auto &devinfo = devicelist()->create_device(machine, "Win32 Keyboard 1", "Win32 Keyboard 1", *this); + auto &devinfo = devicelist().create_device(machine, "Win32 Keyboard 1", "Win32 Keyboard 1", *this); keyboard_trans_table &table = keyboard_trans_table::instance(); @@ -106,7 +106,7 @@ public: case INPUT_EVENT_KEYDOWN: case INPUT_EVENT_KEYUP: args = static_cast(eventdata); - devicelist()->for_each_device([args](auto device) + devicelist().for_each_device([args](auto device) { auto keyboard = dynamic_cast(device); if (keyboard != nullptr) @@ -206,7 +206,7 @@ public: return; // allocate a device - auto &devinfo = devicelist()->create_device(machine, "Win32 Mouse 1", "Win32 Mouse 1", *this); + auto &devinfo = devicelist().create_device(machine, "Win32 Mouse 1", "Win32 Mouse 1", *this); // populate the axes for (int axisnum = 0; axisnum < 2; axisnum++) @@ -235,7 +235,7 @@ public: return false; auto args = static_cast(eventdata); - devicelist()->for_each_device([args](auto device) + devicelist().for_each_device([args](auto device) { auto mouse = dynamic_cast(device); if (mouse != nullptr) @@ -268,7 +268,7 @@ public: m_lightgun_shared_axis_mode = downcast(machine.options()).dual_lightgun(); // Since we are about to be added to the list, the current size is the zero-based index of where we will be - m_gun_index = downcast(module).devicelist()->size(); + m_gun_index = downcast(module).devicelist().size(); } void poll() override @@ -391,7 +391,7 @@ public: static const char *const gun_names[] = { "Win32 Gun 1", "Win32 Gun 2" }; // allocate a device - auto &devinfo = devicelist()->create_device(machine, gun_names[gunnum], gun_names[gunnum], *this); + auto &devinfo = devicelist().create_device(machine, gun_names[gunnum], gun_names[gunnum], *this); // populate the axes for (int axisnum = 0; axisnum < 2; axisnum++) @@ -421,7 +421,7 @@ public: return false; auto args = static_cast(eventdata); - devicelist()->for_each_device([args](auto device) + devicelist().for_each_device([args](auto device) { auto lightgun = dynamic_cast(device); if (lightgun != nullptr) diff --git a/src/osd/modules/input/input_x11.cpp b/src/osd/modules/input/input_x11.cpp index e7481d6470e..0657e99fd2d 100644 --- a/src/osd/modules/input/input_x11.cpp +++ b/src/osd/modules/input/input_x11.cpp @@ -538,9 +538,9 @@ public: osd_printf_verbose("Device %i: Registered %i events.\n", static_cast(info->id), events_registered); // register ourself to handle events from event manager - int event_types[] = { motion_type, button_press_type, button_release_type }; + int const event_types[] = { motion_type, button_press_type, button_release_type }; osd_printf_verbose("Events types to register: motion:%d, press:%d, release:%d\n", motion_type, button_press_type, button_release_type); - x11_event_manager::instance().subscribe(event_types, std::size(event_types), this); + x11_event_manager::instance().subscribe(event_types, this); } osd_printf_verbose("Lightgun: End initialization\n"); @@ -582,14 +582,14 @@ public: } // Figure out which lightgun this event id destined for - auto target_device = std::find_if(devicelist()->begin(), devicelist()->end(), [deviceid](auto &device) + auto target_device = std::find_if(devicelist().begin(), devicelist().end(), [deviceid](auto &device) { std::unique_ptr &ptr = device; return downcast(ptr.get())->x11_state.deviceid == deviceid; }); // If we find a matching lightgun, dispatch the event to the lightgun - if (target_device != devicelist()->end()) + if (target_device != devicelist().end()) { downcast((*target_device).get())->queue_events(&xevent, 1); } @@ -604,7 +604,7 @@ private: { char tempname[20]; snprintf(tempname, std::size(tempname), "NC%d", index); - return &devicelist()->create_device(machine, tempname, tempname, *this); + return &devicelist().create_device(machine, tempname, tempname, *this); } else { @@ -612,7 +612,7 @@ private: } } - return &devicelist()->create_device(machine, std::string(m_lightgun_map.map[index].name), std::string(m_lightgun_map.map[index].name), *this); + return &devicelist().create_device(machine, std::string(m_lightgun_map.map[index].name), std::string(m_lightgun_map.map[index].name), *this); } void add_lightgun_buttons(XAnyClassPtr first_info_class, int num_classes, x11_lightgun_device &devinfo) const diff --git a/src/osd/modules/input/input_xinput.cpp b/src/osd/modules/input/input_xinput.cpp index 8c75240abf7..152e16b4e81 100644 --- a/src/osd/modules/input/input_xinput.cpp +++ b/src/osd/modules/input/input_xinput.cpp @@ -186,7 +186,7 @@ xinput_joystick_device * xinput_api_helper::create_xinput_device(running_machine snprintf(device_name, sizeof(device_name), "XInput Player %u", index + 1); // allocate the device object - auto &devinfo = module.devicelist()->create_device(machine, device_name, device_name, module, shared_from_this()); + auto &devinfo = module.devicelist().create_device(machine, device_name, device_name, module, shared_from_this()); // Set the player ID devinfo.xinput_state.player_index = index;