Skip to content

Commit

Permalink
[Game API] Update to v1.1.0: Controller layouts
Browse files Browse the repository at this point in the history
  • Loading branch information
garbear committed Oct 22, 2018
1 parent 19526d4 commit 7a34275
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 95 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ set(LIBRETRO_SOURCES src/client.cpp
src/audio/SingleFrameAudio.cpp
src/GameInfoLoader.cpp
src/input/ButtonMapper.cpp
src/input/ControllerLayout.cpp
src/input/ControllerTopology.cpp
src/input/DefaultControllerTranslator.cpp
src/input/DefaultKeyboardTranslator.cpp
Expand Down Expand Up @@ -48,6 +49,7 @@ set(LIBRETRO_HEADERS src/GameInfoLoader.h
src/audio/AudioStream.h
src/audio/SingleFrameAudio.h
src/input/ButtonMapper.h
src/input/ControllerLayout.h
src/input/ControllerTopology.h
src/input/DefaultControllerDefines.h
src/input/DefaultControllerTranslator.h
Expand Down
2 changes: 1 addition & 1 deletion game.libretro/addon.xml.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="game.libretro"
name="Libretro Compatibility"
version="1.0.39"
version="1.1.0"
provider-name="Team-Kodi">
<backwards-compatibility abi="1.0.0"/>
<requires>@ADDON_DEPENDS@</requires>
Expand Down
32 changes: 22 additions & 10 deletions src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,14 +433,26 @@ void FreeTopology(game_input_topology* topology)
CControllerTopology::FreeTopology(topology);
}

bool EnableKeyboard(bool enable, const game_controller* controller)
void SetControllerLayouts(const game_controller_layout* controllers, unsigned int controller_count)
{
if (controllers == nullptr)
return;

std::vector<game_controller_layout> controllerStructs;
for (unsigned int i = 0; i < controller_count; i++)
controllerStructs.emplace_back(controllers[i]);

CInputManager::Get().SetControllerLayouts(controllerStructs);
}

bool EnableKeyboard(bool enable, const char* controller_id)
{
bool bSuccess = false;

if (enable)
{
if (controller != nullptr)
bSuccess = CInputManager::Get().EnableKeyboard(*controller);
if (controller_id != nullptr)
bSuccess = CInputManager::Get().EnableKeyboard(controller_id);
}
else
{
Expand All @@ -451,14 +463,14 @@ bool EnableKeyboard(bool enable, const game_controller* controller)
return bSuccess;
}

bool EnableMouse(bool enable, const game_controller* controller)
bool EnableMouse(bool enable, const char* controller_id)
{
bool bSuccess = false;

if (enable)
{
if (controller != nullptr)
bSuccess = CInputManager::Get().EnableMouse(*controller);
if (controller_id != nullptr)
bSuccess = CInputManager::Get().EnableMouse(controller_id);
}
else
{
Expand All @@ -469,7 +481,7 @@ bool EnableMouse(bool enable, const game_controller* controller)
return bSuccess;
}

bool ConnectController(bool connect, const char *port_address, const game_controller* controller)
bool ConnectController(bool connect, const char *port_address, const char* controller_id)
{
if (port_address == nullptr)
return false;
Expand All @@ -479,10 +491,10 @@ bool ConnectController(bool connect, const char *port_address, const game_contro

if (connect)
{
if (controller == nullptr || controller->controller_id == nullptr)
if (controller_id == nullptr)
return false;

strController = controller->controller_id;
strController = controller_id;
}

const int port = CInputManager::Get().GetPortIndex(strPortAddress);
Expand All @@ -496,7 +508,7 @@ bool ConnectController(bool connect, const char *port_address, const game_contro

if (connect)
{
device = CInputManager::Get().ConnectController(strPortAddress, *controller);
device = CInputManager::Get().ConnectController(strPortAddress, controller_id);
}
else
{
Expand Down
78 changes: 78 additions & 0 deletions src/input/ControllerLayout.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (C) 2018 Team Kodi
* http://kodi.tv
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this Program; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/

#include "ControllerLayout.h"

#include "kodi_game_types.h"

using namespace LIBRETRO;

CControllerLayout::CControllerLayout(const game_controller_layout &controller) :
m_controllerId(controller.controller_id != nullptr ? controller.controller_id : ""),
m_bProvidesInput(controller.provides_input)
{
if (controller.digital_buttons != nullptr)
{
for (unsigned int i = 0; i < controller.digital_button_count; i++)
m_digitalButtons.emplace_back(controller.digital_buttons[i]);
}

if (controller.analog_buttons != nullptr)
{
for (unsigned int i = 0; i < controller.analog_button_count; i++)
m_analogButtons.emplace_back(controller.analog_buttons[i]);
}

if (controller.analog_sticks != nullptr)
{
for (unsigned int i = 0; i < controller.analog_stick_count; i++)
m_analogSticks.emplace_back(controller.analog_sticks[i]);
}

if (controller.accelerometers != nullptr)
{
for (unsigned int i = 0; i < controller.accelerometer_count; i++)
m_accelerometers.emplace_back(controller.accelerometers[i]);
}

if (controller.keys != nullptr)
{
for (unsigned int i = 0; i < controller.key_count; i++)
m_keys.emplace_back(controller.keys[i]);
}

if (controller.rel_pointers != nullptr)
{
for (unsigned int i = 0; i < controller.rel_pointer_count; i++)
m_relPointers.emplace_back(controller.rel_pointers[i]);
}

if (controller.abs_pointers != nullptr)
{
for (unsigned int i = 0; i < controller.abs_pointer_count; i++)
m_absPointers.emplace_back(controller.abs_pointers[i]);
}

if (controller.motors != nullptr)
{
for (unsigned int i = 0; i < controller.motor_count; i++)
m_motors.emplace_back(controller.motors[i]);
}
}
49 changes: 49 additions & 0 deletions src/input/ControllerLayout.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2018 Team Kodi
* http://kodi.tv
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this Program; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#pragma once

#include <string>
#include <vector>

struct game_controller_layout;

namespace LIBRETRO
{
class CControllerLayout
{
public:
CControllerLayout(const game_controller_layout &controller);

const std::string &ControllerID() const { return m_controllerId; }
bool ProvidesInput() const { return m_bProvidesInput; }

private:
std::string m_controllerId;
bool m_bProvidesInput;
std::vector<std::string> m_digitalButtons;
std::vector<std::string> m_analogButtons;
std::vector<std::string> m_analogSticks;
std::vector<std::string> m_accelerometers;
std::vector<std::string> m_keys;
std::vector<std::string> m_relPointers;
std::vector<std::string> m_absPointers;
std::vector<std::string> m_motors;
};
}
5 changes: 1 addition & 4 deletions src/input/ControllerTopology.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,14 @@
*/
#pragma once

#include <kodi/kodi_game_types.h>
#include "kodi_game_types.h"

#include <memory>
#include <string>
#include <vector>

class TiXmlElement;

struct game_input_device;
struct game_input_port;

namespace LIBRETRO
{
class CControllerTopology
Expand Down
64 changes: 39 additions & 25 deletions src/input/InputManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,29 @@ libretro_device_caps_t CInputManager::GetDeviceCaps(void) const
1 << RETRO_DEVICE_POINTER;
}

bool CInputManager::EnableKeyboard(const game_controller &controller)

void CInputManager::SetControllerLayouts(const std::vector<game_controller_layout> &controllers)
{
bool bSuccess = false;
m_controllerLayouts.clear();

const std::string controllerId = controller.controller_id != nullptr ? controller.controller_id : "";
for (const auto &controller : controllers)
{
if (controller.controller_id != nullptr)
m_controllerLayouts[controller.controller_id].reset(new CControllerLayout(controller));
}
}

bool CInputManager::EnableKeyboard(const std::string &controllerId)
{
bool bSuccess = false;

if (!CControllerTopology::GetInstance().SetDevice(GAME_PORT_KEYBOARD, controllerId))
{
esyslog("Error: Keyboard \"%s\" not supported", controllerId.c_str());
}
else
{
DevicePtr device(new CLibretroDevice(controller));
DevicePtr device(new CLibretroDevice(controllerId));
m_keyboard = std::move(device);
bSuccess = true;
}
Expand All @@ -80,19 +90,17 @@ void CInputManager::DisableKeyboard()
m_keyboard.reset();
}

bool CInputManager::EnableMouse(const game_controller &controller)
bool CInputManager::EnableMouse(const std::string &controllerId)
{
bool bSuccess = false;

const std::string controllerId = controller.controller_id != nullptr ? controller.controller_id : "";

if (!CControllerTopology::GetInstance().SetDevice(GAME_PORT_MOUSE, controllerId))
{
esyslog("Error: Mouse \"%s\" not supported", controllerId.c_str());
}
else
{
DevicePtr device(new CLibretroDevice(controller));
DevicePtr device(new CLibretroDevice(controllerId));
m_mouse = std::move(device);
bSuccess = true;
}
Expand All @@ -106,7 +114,7 @@ void CInputManager::DisableMouse()
m_mouse.reset();
}

libretro_device_t CInputManager::ConnectController(const std::string &address, const game_controller &controller)
libretro_device_t CInputManager::ConnectController(const std::string &address, const std::string &controllerId)
{
unsigned int deviceType = RETRO_DEVICE_NONE; // Unmasked device type

Expand All @@ -115,28 +123,34 @@ libretro_device_t CInputManager::ConnectController(const std::string &address, c
{
esyslog("Failed to connect controller, invalid port address: %s", address.c_str());
}
else if (controller.controller_id)
else if (!controllerId.empty())
{
const bool bProvidesInput = controller.provides_input;

if (!CControllerTopology::GetInstance().SetController(address, controller.controller_id, bProvidesInput))
auto it = m_controllerLayouts.find(controllerId);
if (it != m_controllerLayouts.end())
{
esyslog("Error: Controller port \"%s\" (libretro port %d) does not accept %s",
address.c_str(), port, controller.controller_id);
}
else
{
DevicePtr device(new CLibretroDevice(controller));
const CControllerLayout &controller = *it->second;

const bool bProvidesInput = controller.ProvidesInput();

if (device->Subclass() != RETRO_SUBCLASS_NONE)
deviceType = RETRO_DEVICE_SUBCLASS(device->Type(), device->Subclass());
if (!CControllerTopology::GetInstance().SetController(address, controllerId, bProvidesInput))
{
esyslog("Error: Controller port \"%s\" (libretro port %d) does not accept %s",
address.c_str(), port, controllerId.c_str());
}
else
deviceType = device->Type();
{
DevicePtr device(new CLibretroDevice(controllerId));

if (port >= m_controllers.size())
m_controllers.resize(port + 1);
if (device->Subclass() != RETRO_SUBCLASS_NONE)
deviceType = RETRO_DEVICE_SUBCLASS(device->Type(), device->Subclass());
else
deviceType = device->Type();

if (port >= m_controllers.size())
m_controllers.resize(port + 1);

m_controllers[port] = std::move(device);
m_controllers[port] = std::move(device);
}
}
}

Expand Down
Loading

0 comments on commit 7a34275

Please sign in to comment.