mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-05-21 22:45:42 -04:00
215 lines
5.4 KiB
C++
215 lines
5.4 KiB
C++
#include "vty_host_interface.h"
|
|
#include "common/log.h"
|
|
#include "common/string_util.h"
|
|
#include "evdev_key_names.h"
|
|
#include "frontend-common/ini_settings_interface.h"
|
|
#include "imgui.h"
|
|
#include <fcntl.h>
|
|
#include <linux/input-event-codes.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
Log_SetChannel(VTYHostInterface);
|
|
|
|
VTYHostInterface::VTYHostInterface() = default;
|
|
|
|
VTYHostInterface::~VTYHostInterface()
|
|
{
|
|
CloseEVDevFDs();
|
|
}
|
|
|
|
std::unique_ptr<NoGUIHostInterface> VTYHostInterface::Create()
|
|
{
|
|
return std::make_unique<VTYHostInterface>();
|
|
}
|
|
|
|
bool VTYHostInterface::Initialize()
|
|
{
|
|
if (!NoGUIHostInterface::Initialize())
|
|
return false;
|
|
|
|
OpenEVDevFDs();
|
|
|
|
signal(SIGTERM, SIGTERMHandler);
|
|
signal(SIGINT, SIGTERMHandler);
|
|
signal(SIGQUIT, SIGTERMHandler);
|
|
return true;
|
|
}
|
|
|
|
void VTYHostInterface::Shutdown()
|
|
{
|
|
CloseEVDevFDs();
|
|
NoGUIHostInterface::Shutdown();
|
|
}
|
|
|
|
bool VTYHostInterface::IsFullscreen() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool VTYHostInterface::SetFullscreen(bool enabled)
|
|
{
|
|
return enabled;
|
|
}
|
|
|
|
void VTYHostInterface::FixIncompatibleSettings(bool display_osd_messages)
|
|
{
|
|
NoGUIHostInterface::FixIncompatibleSettings(display_osd_messages);
|
|
|
|
// Some things we definitely don't want.
|
|
g_settings.confim_power_off = false;
|
|
}
|
|
|
|
bool VTYHostInterface::CreatePlatformWindow(bool fullscreen)
|
|
{
|
|
SetImGuiKeyMap();
|
|
return true;
|
|
}
|
|
|
|
void VTYHostInterface::DestroyPlatformWindow()
|
|
{
|
|
// nothing to destroy, it's all in the context
|
|
}
|
|
|
|
std::optional<WindowInfo> VTYHostInterface::GetPlatformWindowInfo()
|
|
{
|
|
WindowInfo wi;
|
|
wi.type = WindowInfo::Type::Display;
|
|
wi.surface_width = 0;
|
|
wi.surface_height = 0;
|
|
wi.surface_refresh_rate = 0.0f;
|
|
wi.surface_format = WindowInfo::SurfaceFormat::Auto;
|
|
|
|
const std::string fullscreen_mode = m_settings_interface->GetStringValue("GPU", "FullscreenMode", "");
|
|
if (!fullscreen_mode.empty())
|
|
{
|
|
if (!ParseFullscreenMode(fullscreen_mode, &wi.surface_width, &wi.surface_height, &wi.surface_refresh_rate))
|
|
{
|
|
Log_ErrorPrintf("Failed to parse fullscreen mode '%s'", fullscreen_mode.c_str());
|
|
}
|
|
}
|
|
|
|
return wi;
|
|
}
|
|
|
|
void VTYHostInterface::PollAndUpdate()
|
|
{
|
|
PollEvDevKeyboards();
|
|
|
|
NoGUIHostInterface::PollAndUpdate();
|
|
}
|
|
|
|
void VTYHostInterface::OpenEVDevFDs()
|
|
{
|
|
for (int i = 0; i < 1000; i++)
|
|
{
|
|
TinyString path;
|
|
path.Format("/dev/input/event%d", i);
|
|
|
|
int fd = open(path, O_RDONLY | O_NONBLOCK);
|
|
if (fd < 0)
|
|
break;
|
|
|
|
struct libevdev* obj;
|
|
if (libevdev_new_from_fd(fd, &obj) != 0)
|
|
{
|
|
Log_ErrorPrintf("libevdev_new_from_fd(%s) failed", path.GetCharArray());
|
|
close(fd);
|
|
continue;
|
|
}
|
|
|
|
Log_DevPrintf("Input path: %s", path.GetCharArray());
|
|
Log_DevPrintf("Input device name: \"%s\"", libevdev_get_name(obj));
|
|
Log_DevPrintf("Input device ID: bus %#x vendor %#x product %#x", libevdev_get_id_bustype(obj),
|
|
libevdev_get_id_vendor(obj), libevdev_get_id_product(obj));
|
|
if (!libevdev_has_event_code(obj, EV_KEY, KEY_SPACE))
|
|
{
|
|
Log_DevPrintf("This device does not look like a keyboard");
|
|
libevdev_free(obj);
|
|
close(fd);
|
|
continue;
|
|
}
|
|
|
|
const int grab_res = libevdev_grab(obj, LIBEVDEV_GRAB);
|
|
if (grab_res != 0)
|
|
Log_WarningPrintf("Failed to grab '%s' (%s): %d", libevdev_get_name(obj), path.GetCharArray(), grab_res);
|
|
|
|
m_evdev_keyboards.push_back({obj, fd});
|
|
}
|
|
}
|
|
|
|
void VTYHostInterface::CloseEVDevFDs()
|
|
{
|
|
for (const EvDevKeyboard& kb : m_evdev_keyboards)
|
|
{
|
|
libevdev_grab(kb.obj, LIBEVDEV_UNGRAB);
|
|
libevdev_free(kb.obj);
|
|
close(kb.fd);
|
|
}
|
|
m_evdev_keyboards.clear();
|
|
}
|
|
|
|
void VTYHostInterface::PollEvDevKeyboards()
|
|
{
|
|
for (const EvDevKeyboard& kb : m_evdev_keyboards)
|
|
{
|
|
struct input_event ev;
|
|
while (libevdev_next_event(kb.obj, LIBEVDEV_READ_FLAG_NORMAL, &ev) == 0)
|
|
{
|
|
// auto-repeat
|
|
if (ev.value == 2)
|
|
continue;
|
|
|
|
const bool pressed = (ev.value == 1);
|
|
const HostKeyCode code = static_cast<HostKeyCode>(ev.code);
|
|
if (static_cast<unsigned>(code) < countof(ImGuiIO::KeysDown))
|
|
ImGui::GetIO().KeysDown[code] = pressed;
|
|
|
|
HandleHostKeyEvent(code, pressed);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VTYHostInterface::SetImGuiKeyMap()
|
|
{
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
io.KeyMap[ImGuiKey_Tab] = KEY_TAB;
|
|
io.KeyMap[ImGuiKey_LeftArrow] = KEY_LEFT;
|
|
io.KeyMap[ImGuiKey_RightArrow] = KEY_RIGHT;
|
|
io.KeyMap[ImGuiKey_UpArrow] = KEY_UP;
|
|
io.KeyMap[ImGuiKey_DownArrow] = KEY_DOWN;
|
|
io.KeyMap[ImGuiKey_PageUp] = KEY_PAGEUP;
|
|
io.KeyMap[ImGuiKey_PageDown] = KEY_PAGEDOWN;
|
|
io.KeyMap[ImGuiKey_Home] = KEY_HOME;
|
|
io.KeyMap[ImGuiKey_End] = KEY_END;
|
|
io.KeyMap[ImGuiKey_Insert] = KEY_INSERT;
|
|
io.KeyMap[ImGuiKey_Delete] = KEY_DELETE;
|
|
io.KeyMap[ImGuiKey_Backspace] = KEY_BACKSPACE;
|
|
io.KeyMap[ImGuiKey_Space] = KEY_SPACE;
|
|
io.KeyMap[ImGuiKey_Enter] = KEY_ENTER;
|
|
io.KeyMap[ImGuiKey_Escape] = KEY_ESC;
|
|
io.KeyMap[ImGuiKey_KeyPadEnter] = KEY_KPENTER;
|
|
io.KeyMap[ImGuiKey_A] = KEY_A;
|
|
io.KeyMap[ImGuiKey_C] = KEY_C;
|
|
io.KeyMap[ImGuiKey_V] = KEY_V;
|
|
io.KeyMap[ImGuiKey_X] = KEY_X;
|
|
io.KeyMap[ImGuiKey_Y] = KEY_Y;
|
|
io.KeyMap[ImGuiKey_Z] = KEY_Z;
|
|
}
|
|
|
|
std::optional<VTYHostInterface::HostKeyCode> VTYHostInterface::GetHostKeyCode(const std::string_view key_code) const
|
|
{
|
|
std::optional<int> kc = EvDevKeyNames::GetKeyCodeForName(key_code);
|
|
if (!kc.has_value())
|
|
return std::nullopt;
|
|
|
|
return static_cast<HostKeyCode>(kc.value());
|
|
}
|
|
|
|
void VTYHostInterface::SIGTERMHandler(int sig)
|
|
{
|
|
Log_InfoPrintf("Recieved SIGTERM");
|
|
static_cast<VTYHostInterface*>(g_host_interface)->m_quit_request = true;
|
|
signal(sig, SIG_DFL);
|
|
}
|