#pragma once #include "common/string.h" #include "core/host_interface.h" #include #include #include #include #include #include #include #include #include class ControllerInterface; namespace FrontendCommon { class SaveStateSelectorUI; } class CommonHostInterface : public HostInterface { public: friend ControllerInterface; using HostKeyCode = s32; using InputButtonHandler = std::function; using InputAxisHandler = std::function; using ControllerRumbleCallback = std::function; struct HotkeyInfo { String category; String name; String display_name; InputButtonHandler handler; }; using HotkeyInfoList = std::vector; /// Returns the name of the frontend. virtual const char* GetFrontendName() const = 0; virtual bool Initialize() override; virtual void Shutdown() override; virtual bool BootSystem(const SystemBootParameters& parameters) override; virtual void PowerOffSystem() override; /// Returns a list of all available hotkeys. ALWAYS_INLINE const HotkeyInfoList& GetHotkeyInfoList() const { return m_hotkeys; } /// Access to current controller interface. ALWAYS_INLINE ControllerInterface* GetControllerInterface() const { return m_controller_interface.get(); } /// Returns true if running in batch mode, i.e. exit after emulation. ALWAYS_INLINE bool InBatchMode() const { return m_batch_mode; } /// Parses command line parameters for all frontends. bool ParseCommandLineParameters(int argc, char* argv[], std::unique_ptr* out_boot_params); protected: CommonHostInterface(); ~CommonHostInterface(); /// Request the frontend to exit. virtual void RequestExit() = 0; virtual bool IsFullscreen() const; virtual bool SetFullscreen(bool enabled); virtual std::unique_ptr CreateAudioStream(AudioBackend backend) override; virtual std::unique_ptr CreateControllerInterface(); virtual void OnSystemCreated() override; virtual void OnSystemPaused(bool paused) override; virtual void OnSystemDestroyed() override; virtual void OnControllerTypeChanged(u32 slot) override; virtual void DrawImGuiWindows() override; virtual void SetDefaultSettings(SettingsInterface& si) override; virtual std::optional GetHostKeyCode(const std::string_view key_code) const; virtual bool AddButtonToInputMap(const std::string& binding, const std::string_view& device, const std::string_view& button, InputButtonHandler handler); virtual bool AddAxisToInputMap(const std::string& binding, const std::string_view& device, const std::string_view& axis, InputAxisHandler handler); virtual bool AddRumbleToInputMap(const std::string& binding, u32 controller_index, u32 num_motors); /// Reloads the input map from config. Callable from controller interface. virtual void UpdateInputMap() = 0; /// Returns a list of all input profiles. first - name, second - path std::vector> GetInputProfileList() const; /// Applies the specified input profile. void ApplyInputProfile(const char* profile_path, SettingsInterface& si); /// Saves the current input configuration to the specified profile name. bool SaveInputProfile(const char* profile_path, SettingsInterface& si); void RegisterHotkey(String category, String name, String display_name, InputButtonHandler handler); bool HandleHostKeyEvent(HostKeyCode code, bool pressed); void UpdateInputMap(SettingsInterface& si); void AddControllerRumble(u32 controller_index, u32 num_motors, ControllerRumbleCallback callback); void UpdateControllerRumble(); void StopControllerRumble(); std::unique_ptr m_controller_interface; private: void RegisterGeneralHotkeys(); void RegisterGraphicsHotkeys(); void RegisterSaveStateHotkeys(); void UpdateControllerInputMap(SettingsInterface& si); void UpdateHotkeyInputMap(SettingsInterface& si); void ClearAllControllerBindings(SettingsInterface& si); HotkeyInfoList m_hotkeys; std::unique_ptr m_save_state_selector_ui; // input key maps std::map m_keyboard_input_handlers; // controller vibration motors/rumble struct ControllerRumbleState { enum : u32 { MAX_MOTORS = 2 }; u32 controller_index; u32 num_motors; std::array last_strength; ControllerRumbleCallback update_callback; }; std::vector m_controller_vibration_motors; // running in batch mode? i.e. exit after stopping emulation bool m_batch_mode = false; };