aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRainer Hochecker <fernetmenta@online.de>2018-04-15 12:53:44 +0200
committerGitHub <noreply@github.com>2018-04-15 12:53:44 +0200
commit50f98abb88ee12da611436df412a0a1ddd0e8c5c (patch)
tree3e0f6b210d0fdf45a12e58e6f4306b8df0cedbef
parent326fb2d1d3adc8514e53a4e7dd4698489a7b6ed6 (diff)
parentbac44c410e4d8dc6f3ea5ea136f37634198db9e2 (diff)
Merge pull request #13761 from FernetMenta/lirc
lirc: redesign, fix
-rw-r--r--CMakeLists.txt7
-rw-r--r--cmake/modules/FindLircClient.cmake36
-rw-r--r--docs/README.linux3
-rw-r--r--docs/README.ubuntu2
-rw-r--r--xbmc/AppParamParser.cpp4
-rw-r--r--xbmc/ServiceManager.cpp3
-rw-r--r--xbmc/input/IRTranslator.cpp10
-rw-r--r--xbmc/input/IRTranslator.h6
-rw-r--r--xbmc/input/InputManager.cpp40
-rw-r--r--xbmc/input/InputManager.h5
-rw-r--r--xbmc/platform/linux/OptionalsReg.cpp32
-rw-r--r--xbmc/platform/linux/OptionalsReg.h14
-rw-r--r--xbmc/platform/linux/input/CMakeLists.txt2
-rw-r--r--xbmc/platform/linux/input/LIRC.cpp439
-rw-r--r--xbmc/platform/linux/input/LIRC.h65
-rw-r--r--xbmc/powermanagement/PowerManager.cpp14
-rw-r--r--xbmc/windowing/WinSystem.cpp6
-rw-r--r--xbmc/windowing/X11/WinSystemX11GLContext.cpp2
-rw-r--r--xbmc/windowing/X11/WinSystemX11GLContext.h3
-rw-r--r--xbmc/windowing/XBMC_events.h9
-rw-r--r--xbmc/windowing/gbm/WinSystemGbm.cpp1
-rw-r--r--xbmc/windowing/gbm/WinSystemGbm.h2
-rw-r--r--xbmc/windowing/rpi/WinSystemRpi.cpp1
-rw-r--r--xbmc/windowing/rpi/WinSystemRpi.h2
-rw-r--r--xbmc/windowing/wayland/WinSystemWayland.cpp1
-rw-r--r--xbmc/windowing/wayland/WinSystemWayland.h3
26 files changed, 234 insertions, 478 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1aafc21a54..18568cd550 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,7 +64,6 @@ if(NOT WIN32)
option(WITH_CPU "build with given cpu" OFF)
endif()
if(CORE_SYSTEM_NAME STREQUAL linux)
- option(ENABLE_LIRC "Enable LIRC support?" ON)
option(ENABLE_EVENTCLIENTS "Enable event clients support?" OFF)
endif()
@@ -149,6 +148,7 @@ set(optional_deps Alsa
CCache
DBus
LCMS2
+ LircClient
MDNS
MicroHttpd
PulseAudio
@@ -201,11 +201,6 @@ if(ENABLE_OPTICAL)
list(APPEND DEP_DEFINES -DHAS_DVD_DRIVE -DHAS_CDDA_RIPPER)
endif()
-if(ENABLE_LIRC)
- set(LIRC_DEVICE /dev/lircd CACHE STRING "LIRC device to use")
- list(APPEND DEP_DEFINES -DLIRC_DEVICE="${LIRC_DEVICE}" -DHAS_LIRC=1)
-endif()
-
if(ENABLE_AIRTUNES)
find_package(Shairplay)
if(SHAIRPLAY_FOUND)
diff --git a/cmake/modules/FindLircClient.cmake b/cmake/modules/FindLircClient.cmake
new file mode 100644
index 0000000000..528c38e8ee
--- /dev/null
+++ b/cmake/modules/FindLircClient.cmake
@@ -0,0 +1,36 @@
+# FindLircClient
+# -----------
+# Finds the liblirc_client library
+#
+# This will will define the following variables::
+#
+# LIRCCLIENT_FOUND - if false, do not try to link to lirc_client
+# LIRCCLIENT_INCLUDE_DIRS - where to find lirc/lirc_client.h
+# LIRCCLIENT_LIBRARYS - the library to link against
+# LIRCCLIENT_DEFINITIONS - the lirc definitions
+
+if(PKG_CONFIG_FOUND)
+ pkg_check_modules(PC_LIRC lirc QUIET)
+endif()
+
+find_path(LIRCCLIENT_INCLUDE_DIR lirc/lirc_client.h PATHS ${PC_LIRC_INCLUDEDIR})
+find_library(LIRCCLIENT_LIBRARY lirc_client PATHS ${PC_LIRC_LIBDIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(LircClient
+ REQUIRED_VARS LIRCCLIENT_LIBRARY LIRCCLIENT_INCLUDE_DIR)
+
+if(LIRCCLIENT_FOUND)
+ set(LIRCCLIENT_LIBRARIES ${LIRCCLIENT_LIBRARY})
+ set(LIRCCLIENT_INCLUDE_DIRS ${LIRCCLIENT_INCLUDE_DIR})
+ set(LIRCCLIENT_DEFINITIONS -DHAS_LIRC=1)
+
+ if(NOT TARGET LIRCCLIENT::LIRCCLIENT)
+ add_library(LIRCCLIENT::LIRCCLIENT UNKNOWN IMPORTED)
+ set_target_properties(LIRCCLIENT::LIRCCLIENT PROPERTIES
+ IMPORTED_LOCATION "${LIRCCLIENT_LIBRARYS}"
+ INTERFACE_INCLUDE_DIRECTORIES "${LIRCCLIENT_INCLUDE_DIRS}")
+ endif()
+endif()
+
+mark_as_advanced(LIRCCLIENT_LIBRARY LIRCCLIENT_INCLUDE_DIR) \ No newline at end of file
diff --git a/docs/README.linux b/docs/README.linux
index 5826dfbaa4..ee1c5b4cf4 100644
--- a/docs/README.linux
+++ b/docs/README.linux
@@ -57,7 +57,8 @@ Build-Depends: autoconf, automake, autopoint, autotools-dev, cmake, curl,
libtag1-dev (>= 1.8), libtinyxml-dev (>= 2.6.2), libtool, libudev-dev,
libusb-dev, libva-dev, libvdpau-dev, libxml2-dev,
libxmu-dev, libxrandr-dev, libxslt1-dev, libxt-dev, lsb-release, rapidjson-dev,
- nasm [!amd64], python-dev, python-imaging, python-support, swig, uuid-dev, yasm, zlib1g-dev
+ nasm [!amd64], python-dev, python-imaging, python-support, swig, uuid-dev, yasm, zlib1g-dev,
+ liblirc-dev
If you want to build with Wayland instead of X11, you will need:
wayland-protocols (>= 1.7), libwaylandpp-dev
diff --git a/docs/README.ubuntu b/docs/README.ubuntu
index 83c971de27..fba3d86cf9 100644
--- a/docs/README.ubuntu
+++ b/docs/README.ubuntu
@@ -91,7 +91,7 @@ For Ubuntu (all versions >= 7.04):
libsqlite3-dev libssh-dev libssl-dev libtinyxml-dev libtool libudev-dev libusb-dev \
libva-dev libvdpau-dev libxml2-dev libxmu-dev libxrandr-dev \
libxrender-dev libxslt1-dev libxt-dev mesa-utils nasm pmount python-dev python-imaging \
- python-sqlite rapidjson-dev swig uuid-dev yasm zlib1g-dev
+ python-sqlite rapidjson-dev swig uuid-dev yasm zlib1g-dev liblirc-dev
For >= 10.10:
$ sudo apt-get install autopoint libltdl-dev
diff --git a/xbmc/AppParamParser.cpp b/xbmc/AppParamParser.cpp
index 31f671f7b3..cbe5d1cf8b 100644
--- a/xbmc/AppParamParser.cpp
+++ b/xbmc/AppParamParser.cpp
@@ -98,10 +98,6 @@ void CAppParamParser::DisplayHelp()
printf("\t\t\tenables network settings.\n");
printf(" -p or --portable\t%s will look for configurations in install folder instead of ~/.%s\n", CSysInfo::GetAppName().c_str(), lcAppName.c_str());
printf(" --legacy-res\t\tEnables screen resolutions such as PAL, NTSC, etc.\n");
-#ifdef HAS_LIRC
- printf(" -l or --lircdev\tLircDevice to use default is " LIRC_DEVICE " .\n");
- printf(" -n or --nolirc\tdo not use Lirc, i.e. no remote input.\n");
-#endif
printf(" --debug\t\tEnable debug logging\n");
printf(" --version\t\tPrint version information\n");
printf(" --test\t\tEnable test mode. [FILE] required.\n");
diff --git a/xbmc/ServiceManager.cpp b/xbmc/ServiceManager.cpp
index 9423e49866..6847a6b317 100644
--- a/xbmc/ServiceManager.cpp
+++ b/xbmc/ServiceManager.cpp
@@ -173,8 +173,7 @@ bool CServiceManager::InitStageTwo(const CAppParamParser &params)
m_contextMenuManager.reset(new CContextMenuManager(*m_addonMgr.get()));
m_gameControllerManager.reset(new GAME::CControllerManager);
- m_inputManager.reset(new CInputManager(params,
- *m_profileManager));
+ m_inputManager.reset(new CInputManager(params));
m_inputManager->InitializeInputs();
m_peripherals.reset(new PERIPHERALS::CPeripherals(*m_announcementManager,
diff --git a/xbmc/input/IRTranslator.cpp b/xbmc/input/IRTranslator.cpp
index 18ef268f85..98f40ef599 100644
--- a/xbmc/input/IRTranslator.cpp
+++ b/xbmc/input/IRTranslator.cpp
@@ -19,6 +19,7 @@
*/
#include "IRTranslator.h"
+#include "ServiceBroker.h"
#include "filesystem/File.h"
#include "input/remote/IRRemote.h"
#include "profiles/ProfilesManager.h"
@@ -30,8 +31,7 @@
#include <stdlib.h>
#include <vector>
-CIRTranslator::CIRTranslator(const CProfilesManager &profileManager) :
- m_profileManager(profileManager)
+CIRTranslator::CIRTranslator()
{
}
@@ -50,7 +50,7 @@ void CIRTranslator::Load(const std::string &irMapName)
else
CLog::Log(LOGDEBUG, "CIRTranslator::Load - no system %s found, skipping", irMapName.c_str());
- irMapPath = m_profileManager.GetUserDataItem(irMapName);
+ irMapPath = CServiceBroker::GetProfileManager().GetUserDataItem(irMapName);
if (XFILE::CFile::Exists(irMapPath))
success |= LoadIRMap(irMapPath);
else
@@ -63,7 +63,9 @@ void CIRTranslator::Load(const std::string &irMapName)
bool CIRTranslator::LoadIRMap(const std::string &irMapPath)
{
std::string remoteMapTag = URIUtils::GetFileName(irMapPath);
- URIUtils::RemoveExtension(remoteMapTag);
+ size_t lastindex = remoteMapTag.find_last_of(".");
+ if (lastindex != std::string::npos)
+ remoteMapTag = remoteMapTag.substr(0, lastindex);
StringUtils::ToLower(remoteMapTag);
// Load our xml file, and fill up our mapping tables
diff --git a/xbmc/input/IRTranslator.h b/xbmc/input/IRTranslator.h
index 1326f5d9d5..50a61dc666 100644
--- a/xbmc/input/IRTranslator.h
+++ b/xbmc/input/IRTranslator.h
@@ -23,13 +23,12 @@
#include <memory>
#include <string>
-class CProfilesManager;
class TiXmlNode;
class CIRTranslator
{
public:
- CIRTranslator(const CProfilesManager &profileManager);
+ CIRTranslator();
/*!
* \brief Loads Lircmap.xml/IRSSmap.xml
@@ -50,9 +49,6 @@ private:
bool LoadIRMap(const std::string &irMapPath);
void MapRemote(TiXmlNode *pRemote, const std::string &szDevice);
- // Construction parameters
- const CProfilesManager &m_profileManager;
-
using IRButtonMap = std::map<std::string, std::string>;
std::map<std::string, std::shared_ptr<IRButtonMap>> m_irRemotesMap;
diff --git a/xbmc/input/InputManager.cpp b/xbmc/input/InputManager.cpp
index 90a8c680d5..ec3dc8d897 100644
--- a/xbmc/input/InputManager.cpp
+++ b/xbmc/input/InputManager.cpp
@@ -62,11 +62,10 @@ using namespace MESSAGING;
CreateRemoteControlFunc CInputManager::m_createRemoteControl = nullptr;
-CInputManager::CInputManager(const CAppParamParser &params,
- const CProfilesManager &profileManager) :
+CInputManager::CInputManager(const CAppParamParser &params) :
m_keymapEnvironment(new CKeymapEnvironment),
m_buttonTranslator(new CButtonTranslator),
- m_irTranslator(new CIRTranslator(profileManager)),
+ m_irTranslator(new CIRTranslator()),
m_customControllerTranslator(new CCustomControllerTranslator),
m_touchTranslator(new CTouchTranslator),
m_joystickTranslator(new CJoystickMapper),
@@ -470,6 +469,12 @@ bool CInputManager::OnEvent(XBMC_Event& newEvent)
}
break;
} //case
+ case XBMC_BUTTON:
+ {
+ CKey key(newEvent.keybutton.button, newEvent.keybutton.holdtime);
+ OnKey(key);
+ break;
+ }
}//switch
return true;
@@ -736,10 +741,6 @@ bool CInputManager::ExecuteInputAction(const CAction &action)
bool CInputManager::HasBuiltin(const std::string& command)
{
- if (HasRemoteControl())
- return command == "lirc.stop" ||
- command == "lirc.start" ||
- command == "lirc.send";
return false;
}
@@ -747,29 +748,7 @@ int CInputManager::ExecuteBuiltin(const std::string& execute, const std::vector<
{
if (HasRemoteControl())
{
- if (execute == "lirc.stop")
- {
- m_RemoteControl->Disconnect();
- m_RemoteControl->SetEnabled(false);
- }
- else if (execute == "lirc.start")
- {
- m_RemoteControl->SetEnabled(true);
- m_RemoteControl->Initialize();
- }
- else if (execute == "lirc.send")
- {
- std::string command;
- for (int i = 0; i < (int)params.size(); i++)
- {
- command += params[i];
- if (i < (int)params.size() - 1)
- command += ' ';
- }
- m_RemoteControl->AddSendCommand(command);
- }
- else
- return -1;
+ return -1;
}
return 0;
}
@@ -1013,3 +992,4 @@ void CInputManager::RegisterRemoteControl(CreateRemoteControlFunc createFunc)
{
m_createRemoteControl = createFunc;
}
+
diff --git a/xbmc/input/InputManager.h b/xbmc/input/InputManager.h
index 6020bb8452..c62d875821 100644
--- a/xbmc/input/InputManager.h
+++ b/xbmc/input/InputManager.h
@@ -48,6 +48,7 @@ class IWindowKeymap;
namespace KODI
{
+
namespace KEYBOARD
{
class IKeyboardDriverHandler;
@@ -78,8 +79,7 @@ class CInputManager : public ISettingCallback,
public Observable
{
public:
- explicit CInputManager(const CAppParamParser &params,
- const CProfilesManager &profileManager);
+ explicit CInputManager(const CAppParamParser &params);
CInputManager(const CInputManager&) = delete;
CInputManager const& operator=(CInputManager const&) = delete;
~CInputManager() override;
@@ -287,6 +287,7 @@ public:
virtual void UnregisterMouseDriverHandler(KODI::MOUSE::IMouseDriverHandler* handler);
static void RegisterRemoteControl(CreateRemoteControlFunc createFunc);
+
private:
/*! \brief Process keyboard event and translate into an action
diff --git a/xbmc/platform/linux/OptionalsReg.cpp b/xbmc/platform/linux/OptionalsReg.cpp
index 34bd08d18f..9b393f648d 100644
--- a/xbmc/platform/linux/OptionalsReg.cpp
+++ b/xbmc/platform/linux/OptionalsReg.cpp
@@ -74,3 +74,35 @@ bool OPTIONALS::SndioRegister()
return false;
}
#endif
+
+//-----------------------------------------------------------------------------
+// Lirc
+//-----------------------------------------------------------------------------
+
+#ifdef HAS_LIRC
+#include "platform/linux/input/LIRC.h"
+#include "ServiceBroker.h"
+class OPTIONALS::CLircContainer
+{
+public:
+ CLircContainer()
+ {
+ m_lirc.Start();
+ }
+protected:
+ CLirc m_lirc;
+};
+#else
+class OPTIONALS::CLircContainer
+{
+};
+#endif
+
+OPTIONALS::CLircContainer* OPTIONALS::LircRegister()
+{
+ return new CLircContainer();
+}
+void OPTIONALS::delete_CLircContainer::operator()(CLircContainer *p) const
+{
+ delete p;
+}
diff --git a/xbmc/platform/linux/OptionalsReg.h b/xbmc/platform/linux/OptionalsReg.h
index cda502374c..07a985b18a 100644
--- a/xbmc/platform/linux/OptionalsReg.h
+++ b/xbmc/platform/linux/OptionalsReg.h
@@ -46,3 +46,17 @@ namespace OPTIONALS
{
bool SndioRegister();
}
+
+//-----------------------------------------------------------------------------
+// Lirc
+//-----------------------------------------------------------------------------
+
+namespace OPTIONALS
+{
+class CLircContainer;
+CLircContainer* LircRegister();
+struct delete_CLircContainer
+{
+ void operator()(CLircContainer *p) const;
+};
+}
diff --git a/xbmc/platform/linux/input/CMakeLists.txt b/xbmc/platform/linux/input/CMakeLists.txt
index 0b0561e009..c8cf402e3e 100644
--- a/xbmc/platform/linux/input/CMakeLists.txt
+++ b/xbmc/platform/linux/input/CMakeLists.txt
@@ -1,7 +1,7 @@
set(SOURCES "")
set(HEADERS "")
-if(LIRC_DEVICE)
+if(LIRCCLIENT_FOUND)
list(APPEND SOURCES LIRC.cpp)
list(APPEND HEADERS LIRC.h)
endif()
diff --git a/xbmc/platform/linux/input/LIRC.cpp b/xbmc/platform/linux/input/LIRC.cpp
index a72d646d94..cfc48f6ef7 100644
--- a/xbmc/platform/linux/input/LIRC.cpp
+++ b/xbmc/platform/linux/input/LIRC.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (C) 2007-2013 Team XBMC
+* Copyright (C) 2007-2018 Team XBMC
* http://kodi.tv
*
* This Program is free software; you can redistribute it and/or modify
@@ -18,389 +18,126 @@
*
*/
-#include "threads/SystemClock.h"
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <limits.h>
-#include <unistd.h>
#include "LIRC.h"
-#ifdef HAVE_INOTIFY
-#include <sys/inotify.h>
-#endif
-#include "input/InputManager.h"
-#include "platform/linux/PlatformDefs.h"
-#include "utils/log.h"
-#include "settings/AdvancedSettings.h"
-#include "utils/TimeUtils.h"
-#include "threads/SingleLock.h"
+#include "Application.h"
#include "ServiceBroker.h"
+#include "profiles/ProfilesManager.h"
+#include "settings/AdvancedSettings.h"
+#include "utils/log.h"
+#include <lirc/lirc_client.h>
+#include <fcntl.h>
+#include <sys/socket.h>
-#define LIRC_MAP_FILENAME "Lircmap.xml"
-
-KODI::REMOTE::IRemoteControl* CRemoteControl::CreateInstance()
-{
- return new CRemoteControl();
-}
-
-void CRemoteControl::Register()
-{
- CInputManager::RegisterRemoteControl(CRemoteControl::CreateInstance);
-}
-
-CRemoteControl::CRemoteControl()
- : CThread("RemoteControl")
- , m_fd(-1)
-#ifdef HAVE_INOTIFY
- , m_inotify_fd(-1)
- , m_inotify_wd(-1)
-#endif
- , m_file(nullptr)
- , m_holdTime(0)
- , m_button(0)
- , m_bInitialized(false)
- , m_inReply(false)
- , m_nrSending(0)
- , m_used(true)
- , m_deviceName(LIRC_DEVICE)
-{
-}
-
-CRemoteControl::~CRemoteControl()
-{
- if (m_file != NULL)
- fclose(m_file);
-}
-
-std::string CRemoteControl::GetMapFile()
-{
- return LIRC_MAP_FILENAME;
-}
-
-void CRemoteControl::SetEnabled(bool bEnabled)
-{
- m_used = bEnabled;
- if (!bEnabled)
- CLog::Log(LOGINFO, "LIRC %s: disabled", __FUNCTION__);
-}
-
-void CRemoteControl::Reset()
+CLirc::CLirc() : CThread("Lirc")
{
- m_button = 0;
- m_holdTime = 0;
}
-void CRemoteControl::Disconnect()
+CLirc::~CLirc()
{
- CSingleLock lock(m_CS);
- //make sure that any new function calls abort directly
- m_bInitialized = false;
- m_event.Set();
-
- if (IsRunning())
- StopThread();
-
- if (m_fd != -1)
{
- if (m_file != NULL)
- fclose(m_file);
- if (m_fd != -1)
- close(m_fd);
- m_fd = -1;
- m_file = NULL;
-#ifdef HAVE_INOTIFY
- if (m_inotify_wd >= 0) {
- inotify_rm_watch(m_inotify_fd, m_inotify_wd);
- m_inotify_wd = -1;
- }
- if (m_inotify_fd >= 0)
- close(m_inotify_fd);
-#endif
-
- m_inReply = false;
- m_nrSending = 0;
- m_sendData.clear();
+ CSingleLock lock(m_critSection);
+ if (m_fd > 0)
+ shutdown(m_fd, SHUT_RDWR);
}
+ StopThread();
}
-void CRemoteControl::SetDeviceName(const std::string& name)
+void CLirc::Start()
{
- if (name.length() > 0)
- m_deviceName = name;
- else
- m_deviceName = LIRC_DEVICE;
-}
-
-void CRemoteControl::Initialize()
-{
- //Create must not be called twice, make sure to lock before
- //check IsRunning() so that any other thread will block until
- //we know IsRunning is true and will not call Create again
- CSingleLock lock(m_CS);
-
- if (m_bInitialized || !m_used || IsRunning())
- return;
-
Create();
-}
-void CRemoteControl::Process()
-{
- struct sockaddr_un addr;
- if (m_deviceName.length() >= sizeof(addr.sun_path))
- {
- CLog::Log(LOGERROR, "LIRC %s: device name is too long (%" PRIdS"), maximum is %" PRIdS"",
- __FUNCTION__, m_deviceName.length(), sizeof(addr.sun_path));
- return;
- }
-
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, m_deviceName.c_str());
-
- CLog::Log(LOGINFO, "LIRC %s: using: %s", __FUNCTION__, addr.sun_path);
-
- int iAttempt = 0;
- unsigned int iMsRetryDelay = 5000;
-
- // try to connect 60 times @ a 5 second interval (5 minutes)
- // multiple tries because LIRC service might be up and running a little later then xbmc on boot.
- while (!m_bStop && iAttempt <= 60)
- {
- if (Connect(addr, iAttempt == 0))
- {
- m_bInitialized = true;
- break;
- }
-
- if (iAttempt == 0)
- CLog::Log(LOGINFO, "CRemoteControl::Process - failed to connect to LIRC, will keep retrying every %d seconds", iMsRetryDelay / 1000);
-
- ++iAttempt;
-
- if (AbortableWait(m_event, iMsRetryDelay) == WAIT_INTERRUPTED)
- break;
- }
-
- if (!m_bInitialized)
- {
- CLog::Log(LOGDEBUG, "Failed to connect to LIRC. Giving up.");
- }
-}
-
-bool CRemoteControl::CheckDevice() {
- if (!m_bInitialized || !m_used)
- return false;
-
-#ifdef HAVE_INOTIFY
- if (m_inotify_fd < 0 || m_inotify_wd < 0)
- return true; // inotify wasn't setup for some reason, assume all is well
- int bufsize = sizeof(struct inotify_event) + PATH_MAX;
- char buf[bufsize];
- int ret = read(m_inotify_fd, buf, bufsize);
- for (int i = 0; i + (int)sizeof(struct inotify_event) <= ret;) {
- struct inotify_event* e = (struct inotify_event*)(buf+i);
- if (e->mask & IN_DELETE_SELF) {
- CLog::Log(LOGDEBUG, "LIRC device removed, disconnecting...");
- Disconnect();
- return false;
- }
- i += sizeof(struct inotify_event)+e->len;
- }
-#endif
- return true;
+ SetPriority(GetMinPriority());
}
-void CRemoteControl::Update()
+void CLirc::Process()
{
- if (!m_bInitialized || !m_used )
- return;
-
- if (!CheckDevice())
- return;
-
- uint32_t now = XbmcThreads::SystemClockMillis();
+ m_profileId = CServiceBroker::GetProfileManager().GetCurrentProfileId();
+ m_irTranslator.Load("Lircmap.xml");
- char buf[128];
- // Read a line from the socket
- while (true)
+ while (!m_bStop)
{
{
- CSingleLock lock(m_CS);
- if (fgets(buf, sizeof(buf), m_file) == NULL)
- break;
- }
-
- // Remove the \n
- buf[strlen(buf)-1] = '\0';
-
- // Parse the result. Sample line:
- // 000000037ff07bdd 00 OK mceusb
- char scanCode[128];
- char buttonName[128];
- char repeatStr[4];
- char deviceName[128];
- sscanf(buf, "%s %s %s %s", &scanCode[0], &repeatStr[0], &buttonName[0], &deviceName[0]);
-
- //beginning of lirc reply packet
- //we get one when lirc is done sending something
- if (!m_inReply && strcmp("BEGIN", scanCode) == 0)
- {
- m_inReply = true;
- continue;
- }
- else if (m_inReply && strcmp("END", scanCode) == 0) //end of lirc reply packet
- {
- m_inReply = false;
- if (m_nrSending > 0)
- m_nrSending--;
- continue;
- }
-
- if (m_inReply)
- continue;
-
- // Some template LIRC configuration have button names in apostrophes or quotes.
- // If we got a quoted button name, strip 'em
- unsigned int buttonNameLen = strlen(buttonName);
- if ( buttonNameLen > 2
- && ( (buttonName[0] == '\'' && buttonName[buttonNameLen-1] == '\'')
- || ((buttonName[0] == '"' && buttonName[buttonNameLen-1] == '"') ) ) )
- {
- memmove( buttonName, buttonName + 1, buttonNameLen - 2 );
- buttonName[ buttonNameLen - 2 ] = '\0';
+ CSingleLock lock(m_critSection);
+ m_fd = lirc_init(const_cast<char*>("kodi"), 0);
+ if (m_fd <= 0)
+ {
+ CSingleExit lock(m_critSection);
+ Sleep(1000);
+ continue;
+ }
}
- m_button = CServiceBroker::GetInputManager().TranslateLircRemoteString(deviceName, buttonName);
-
- char *end = NULL;
- long repeat = strtol(repeatStr, &end, 16);
- if (!end || *end != 0)
- CLog::Log(LOGERROR, "LIRC: invalid non-numeric character in expression %s", repeatStr);
- if (repeat == 0)
- {
- CLog::Log(LOGDEBUG, "LIRC: %s - NEW at %d:%s (%s)", __FUNCTION__, now, buf, buttonName);
- m_firstClickTime = now;
- m_holdTime = 0;
- return;
- }
- else if (repeat > g_advancedSettings.m_remoteDelay)
- {
- m_holdTime = now - m_firstClickTime;
- }
- else
+ char *code;
+ while (!m_bStop)
{
- m_holdTime = 0;
- m_button = 0;
+ int ret = lirc_nextcode(&code);
+ if (ret < 0)
+ {
+ lirc_deinit();
+ Sleep(1000);
+ break;
+ }
+ if (code != nullptr)
+ {
+ if (m_profileId != CServiceBroker::GetProfileManager().GetCurrentProfileId())
+ {
+ m_profileId = CServiceBroker::GetProfileManager().GetCurrentProfileId();
+ m_irTranslator.Load("Lircmap.xml");
+ }
+ ProcessCode(code);
+ free(code);
+ }
}
}
- //drop commands when already sending
- //because keypresses come in faster than lirc can send we risk hammering the daemon with commands
- CSingleLock lock(m_CS);
-
- if (m_nrSending > 0)
- {
- m_sendData.clear();
- }
- else if (!m_sendData.empty())
- {
- fputs(m_sendData.c_str(), m_file);
- fflush(m_file);
-
- //nr of newlines equals nr of commands
- for (int i = 0; i < (int)m_sendData.size(); i++)
- if (m_sendData[i] == '\n')
- m_nrSending++;
+ lirc_deinit();
+}
- m_sendData.clear();
- }
+void CLirc::ProcessCode(char *buf)
+{
+ // Parse the result. Sample line:
+ // 000000037ff07bdd 00 OK mceusb
+ char scanCode[128];
+ char buttonName[128];
+ char repeatStr[4];
+ char deviceName[128];
+ sscanf(buf, "%s %s %s %s", &scanCode[0], &repeatStr[0], &buttonName[0], &deviceName[0]);
- if (feof(m_file) != 0)
+ // Some template LIRC configuration have button names in apostrophes or quotes.
+ // If we got a quoted button name, strip 'em
+ unsigned int buttonNameLen = strlen(buttonName);
+ if (buttonNameLen > 2 &&
+ ((buttonName[0] == '\'' && buttonName[buttonNameLen-1] == '\'') ||
+ ((buttonName[0] == '"' && buttonName[buttonNameLen-1] == '"'))))
{
- CSingleExit ex(m_CS); //Disconnect takes the lock
- Disconnect();
+ memmove(buttonName, buttonName + 1, buttonNameLen - 2);
+ buttonName[buttonNameLen - 2] = '\0';
}
-}
-uint16_t CRemoteControl::GetButton() const
-{
- return m_button;
-}
+ int button = m_irTranslator.TranslateButton(deviceName, buttonName);
-uint32_t CRemoteControl::GetHoldTimeMs() const
-{
- return m_holdTime;
-}
+ char *end = nullptr;
+ long repeat = strtol(repeatStr, &end, 16);
+ if (!end || *end != 0)
+ CLog::Log(LOGERROR, "LIRC: invalid non-numeric character in expression %s", repeatStr);
-void CRemoteControl::AddSendCommand(const std::string& command)
-{
- if (!m_bInitialized || !m_used)
+ if (repeat == 0)
+ {
+ CLog::Log(LOGDEBUG, "LIRC: - NEW %s %s %s %s (%s)", &scanCode[0], &repeatStr[0], &buttonName[0], &deviceName[0], buttonName);
+ m_firstClickTime = XbmcThreads::SystemClockMillis();
+
+ XBMC_Event newEvent;
+ newEvent.type = XBMC_BUTTON;
+ newEvent.keybutton.button = button;
+ newEvent.keybutton.holdtime = 0;
+ g_application.OnEvent(newEvent);
return;
-
- CSingleLock lock(m_CS);
-
- m_sendData += command;
- m_sendData += '\n';
-}
-
-bool CRemoteControl::Connect(struct sockaddr_un addr, bool logMessages)
-{
- bool bResult = false;
- // Open the socket from which we will receive the remote commands
- if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) != -1)
+ }
+ else if (repeat > g_advancedSettings.m_remoteDelay)
{
- // Connect to the socket
- if (connect(m_fd, (struct sockaddr *)&addr, sizeof(addr)) != -1)
- {
- int opts;
- if ((opts = fcntl(m_fd, F_GETFL)) != -1)
- {
- // Set the socket to non-blocking
- opts = (opts | O_NONBLOCK);
- if (fcntl(m_fd, F_SETFL, opts) != -1)
- {
- if ((m_file = fdopen(m_fd, "r+")) != NULL)
- {
-#ifdef HAVE_INOTIFY
- // Setup inotify so we can disconnect if lircd is restarted
- if ((m_inotify_fd = inotify_init()) >= 0)
- {
- // Set the fd non-blocking
- if ((opts = fcntl(m_inotify_fd, F_GETFL)) != -1)
- {
- opts |= O_NONBLOCK;
- if (fcntl(m_inotify_fd, F_SETFL, opts) != -1)
- {
- // Set an inotify watch on the lirc device
- if ((m_inotify_wd = inotify_add_watch(m_inotify_fd, m_deviceName.c_str(), IN_DELETE_SELF)) != -1)
- {
- bResult = true;
- CLog::Log(LOGINFO, "LIRC %s: successfully started", __FUNCTION__);
- }
- else
- CLog::Log(LOGDEBUG, "LIRC: Failed to initialize Inotify. LIRC device will not be monitored.");
- }
- }
- }
-#else
- bResult = true;
- CLog::Log(LOGINFO, "LIRC %s: successfully started", __FUNCTION__);
-#endif
- }
- else
- CLog::Log(LOGERROR, "LIRC %s: fdopen failed: %s", __FUNCTION__, strerror(errno));
- }
- else
- CLog::Log(LOGERROR, "LIRC %s: fcntl(F_SETFL) failed: %s", __FUNCTION__, strerror(errno));
- }
- else
- CLog::Log(LOGERROR, "LIRC %s: fcntl(F_GETFL) failed: %s", __FUNCTION__, strerror(errno));
- }
- else if (logMessages)
- CLog::Log(LOGINFO, "LIRC %s: connect failed: %s", __FUNCTION__, strerror(errno));
+ XBMC_Event newEvent;
+ newEvent.type = XBMC_BUTTON;
+ newEvent.keybutton.button = button;
+ newEvent.keybutton.holdtime = XbmcThreads::SystemClockMillis() - m_firstClickTime;
+ g_application.OnEvent(newEvent);
}
- else if (logMessages)
- CLog::Log(LOGINFO, "LIRC %s: socket failed: %s", __FUNCTION__, strerror(errno));
-
- return bResult;
}
diff --git a/xbmc/platform/linux/input/LIRC.h b/xbmc/platform/linux/input/LIRC.h
index aa24c4f603..d8c8ddbf51 100644
--- a/xbmc/platform/linux/input/LIRC.h
+++ b/xbmc/platform/linux/input/LIRC.h
@@ -1,5 +1,5 @@
/*
-* Copyright (C) 2007-2013 Team XBMC
+* Copyright (C) 2007-2018 Team XBMC
* http://kodi.tv
*
* This Program is free software; you can redistribute it and/or modify
@@ -20,62 +20,25 @@
#pragma once
-#include <string>
-#include <atomic>
-
-#include "input/remote/IRemoteControl.h"
#include "threads/Thread.h"
-#include "threads/Event.h"
+#include "threads/CriticalSection.h"
+#include "input/IRTranslator.h"
+#include <string>
-class CRemoteControl : public KODI::REMOTE::IRemoteControl, CThread
+class CLirc : CThread
{
public:
- CRemoteControl();
- ~CRemoteControl() override;
- void Initialize() override;
- void Disconnect() override;
- void Reset() override;
- void Update() override;
- uint16_t GetButton() const override;
- /*! \brief retrieve the time in milliseconds that the button has been held
- \return time in milliseconds the button has been down
- */
- uint32_t GetHoldTimeMs() const override;
- void SetDeviceName(const std::string& name) override;
- void SetEnabled(bool bEnabled) override;
- bool IsInUse() const override { return m_used; }
- bool IsInitialized() const override { return m_bInitialized; }
- void AddSendCommand(const std::string& command) override;
- std::string GetMapFile() override;
-
- static IRemoteControl* CreateInstance();
- static void Register();
+ CLirc();
+ ~CLirc() override;
+ void Start();
protected:
void Process() override;
+ void ProcessCode(char *buf);
- bool Connect(struct sockaddr_un addr, bool logMessages);
-
-private:
- int m_fd;
-#ifdef HAVE_INOTIFY
- int m_inotify_fd;
- int m_inotify_wd;
-#endif
- FILE* m_file;
- unsigned int m_holdTime;
- int32_t m_button;
-
- std::atomic<bool> m_bInitialized;
- std::atomic<bool> m_inReply;
- std::atomic<int> m_nrSending;
-
- bool m_used;
- uint32_t m_firstClickTime;
- std::string m_deviceName;
- bool CheckDevice();
- std::string m_sendData;
- CEvent m_event;
- CCriticalSection m_CS;
-
+ int m_fd = -1;
+ uint32_t m_firstClickTime = 0;
+ CCriticalSection m_critSection;
+ CIRTranslator m_irTranslator;
+ int m_profileId;
};
diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp
index 6f177b97fd..9582aec05e 100644
--- a/xbmc/powermanagement/PowerManager.cpp
+++ b/xbmc/powermanagement/PowerManager.cpp
@@ -184,13 +184,6 @@ void CPowerManager::OnSleep()
CLog::Log(LOGNOTICE, "%s: Running sleep jobs", __FUNCTION__);
- // stop lirc
- if (CBuiltins::GetInstance().HasCommand("LIRC.Stop"))
- {
- CLog::Log(LOGNOTICE, "%s: Stopping lirc", __FUNCTION__);
- CBuiltins::GetInstance().Execute("LIRC.Stop");
- }
-
CServiceBroker::GetPVRManager().OnSleep();
StorePlayerState();
g_application.StopPlaying();
@@ -224,13 +217,6 @@ void CPowerManager::OnWake()
g_application.ResetScreenSaver();
#endif
- // restart lirc
- if (CBuiltins::GetInstance().HasCommand("LIRC.Start"))
- {
- CLog::Log(LOGNOTICE, "%s: Restarting lirc", __FUNCTION__);
- CBuiltins::GetInstance().Execute("LIRC.Start");
- }
-
CServiceBroker::GetActiveAE()->Resume();
g_application.UpdateLibraries();
CServiceBroker::GetWeatherManager().Refresh();
diff --git a/xbmc/windowing/WinSystem.cpp b/xbmc/windowing/WinSystem.cpp
index e41194cd7a..3bb63a7bed 100644
--- a/xbmc/windowing/WinSystem.cpp
+++ b/xbmc/windowing/WinSystem.cpp
@@ -30,9 +30,6 @@
#if HAS_GLES
#include "guilib/GUIFontTTFGL.h"
#endif
-#if HAS_LIRC
-#include "platform/linux/input/LIRC.h"
-#endif
CWinSystemBase::CWinSystemBase()
{
@@ -42,9 +39,6 @@ CWinSystemBase::CWinSystemBase()
m_gfxContext->ResetScreenParameters((RESOLUTION)i);
m_gfxContext->ResetOverscan((RESOLUTION)i, CDisplaySettings::GetInstance().GetResolutionInfo(i).Overscan);
}
-#if HAS_LIRC
- CRemoteControl::Register();
-#endif
}
CWinSystemBase::~CWinSystemBase() = default;
diff --git a/xbmc/windowing/X11/WinSystemX11GLContext.cpp b/xbmc/windowing/X11/WinSystemX11GLContext.cpp
index f46cbf25f6..17b83a0548 100644
--- a/xbmc/windowing/X11/WinSystemX11GLContext.cpp
+++ b/xbmc/windowing/X11/WinSystemX11GLContext.cpp
@@ -77,6 +77,8 @@ CWinSystemX11GLContext::CWinSystemX11GLContext()
}
}
}
+
+ m_lirc.reset(OPTIONALS::LircRegister());
}
CWinSystemX11GLContext::~CWinSystemX11GLContext()
diff --git a/xbmc/windowing/X11/WinSystemX11GLContext.h b/xbmc/windowing/X11/WinSystemX11GLContext.h
index 59ca4221b0..441bec8e95 100644
--- a/xbmc/windowing/X11/WinSystemX11GLContext.h
+++ b/xbmc/windowing/X11/WinSystemX11GLContext.h
@@ -24,6 +24,7 @@
#include "EGL/egl.h"
#include "rendering/gl/RenderSystemGL.h"
+#include "platform/linux/OptionalsReg.h"
#include <memory>
class CGLContext;
@@ -71,4 +72,6 @@ protected:
void operator()(CVaapiProxy *p) const;
};
std::unique_ptr<CVaapiProxy, delete_CVaapiProxy> m_vaapiProxy;
+
+ std::unique_ptr<OPTIONALS::CLircContainer, OPTIONALS::delete_CLircContainer> m_lirc;
};
diff --git a/xbmc/windowing/XBMC_events.h b/xbmc/windowing/XBMC_events.h
index 853614f1a8..f6d00992ba 100644
--- a/xbmc/windowing/XBMC_events.h
+++ b/xbmc/windowing/XBMC_events.h
@@ -43,6 +43,7 @@ typedef enum {
XBMC_VIDEOMOVE, /* User moved the window */
XBMC_MODECHANGE, /* Video mode must be changed */
XBMC_TOUCH,
+ XBMC_BUTTON, /* Button (remote) pressed */
XBMC_SETFOCUS,
XBMC_USEREVENT,
@@ -114,6 +115,13 @@ typedef struct XBMC_SetFocusEvent {
int y; /* y position */
} XBMC_SetFocusEvent;
+/* Button event structure */
+typedef struct XBMC_ButtonEvent
+{
+ uint32_t button;
+ uint32_t holdtime;
+} XBMC_ButtonEvent;
+
/* General event structure */
typedef struct XBMC_Event {
uint8_t type;
@@ -129,6 +137,7 @@ typedef struct XBMC_Event {
XBMC_UserEvent user;
XBMC_AppCommandEvent appcommand;
XBMC_TouchEvent touch;
+ XBMC_ButtonEvent keybutton;
XBMC_SetFocusEvent focus;
};
} XBMC_Event;
diff --git a/xbmc/windowing/gbm/WinSystemGbm.cpp b/xbmc/windowing/gbm/WinSystemGbm.cpp
index f96b8782ff..45783bd9f1 100644
--- a/xbmc/windowing/gbm/WinSystemGbm.cpp
+++ b/xbmc/windowing/gbm/WinSystemGbm.cpp
@@ -71,6 +71,7 @@ CWinSystemGbm::CWinSystemGbm() :
m_winEvents.reset(new CWinEventsLinux());
CLinuxPowerSyscall::Register();
+ m_lirc.reset(OPTIONALS::LircRegister());
}
bool CWinSystemGbm::InitWindowSystem()
diff --git a/xbmc/windowing/gbm/WinSystemGbm.h b/xbmc/windowing/gbm/WinSystemGbm.h
index 87a5afcbae..90771df278 100644
--- a/xbmc/windowing/gbm/WinSystemGbm.h
+++ b/xbmc/windowing/gbm/WinSystemGbm.h
@@ -23,6 +23,7 @@
#include <gbm.h>
#include <EGL/egl.h>
+#include "platform/linux/OptionalsReg.h"
#include "threads/CriticalSection.h"
#include "windowing/WinSystem.h"
#include "DRMUtils.h"
@@ -69,4 +70,5 @@ protected:
bool m_delayDispReset;
XbmcThreads::EndTime m_dispResetTimer;
+ std::unique_ptr<OPTIONALS::CLircContainer, OPTIONALS::delete_CLircContainer> m_lirc;
};
diff --git a/xbmc/windowing/rpi/WinSystemRpi.cpp b/xbmc/windowing/rpi/WinSystemRpi.cpp
index 0bcd31890a..82534f27c2 100644
--- a/xbmc/windowing/rpi/WinSystemRpi.cpp
+++ b/xbmc/windowing/rpi/WinSystemRpi.cpp
@@ -57,6 +57,7 @@ CWinSystemRpi::CWinSystemRpi()
AE::CAESinkFactory::ClearSinks();
CAESinkPi::Register();
CLinuxPowerSyscall::Register();
+ m_lirc.reset(OPTIONALS::LircRegister());
}
CWinSystemRpi::~CWinSystemRpi()
diff --git a/xbmc/windowing/rpi/WinSystemRpi.h b/xbmc/windowing/rpi/WinSystemRpi.h
index b6efbe0bbf..b002426c66 100644
--- a/xbmc/windowing/rpi/WinSystemRpi.h
+++ b/xbmc/windowing/rpi/WinSystemRpi.h
@@ -21,6 +21,7 @@
#pragma once
#include "RPIUtils.h"
+#include "platform/linux/OptionalsReg.h"
#include "rendering/gles/RenderSystemGLES.h"
#include "threads/CriticalSection.h"
#include "windowing/WinSystem.h"
@@ -65,4 +66,5 @@ protected:
CCriticalSection m_resourceSection;
std::vector<IDispResource*> m_resources;
+ std::unique_ptr<OPTIONALS::CLircContainer, OPTIONALS::delete_CLircContainer> m_lirc;
};
diff --git a/xbmc/windowing/wayland/WinSystemWayland.cpp b/xbmc/windowing/wayland/WinSystemWayland.cpp
index bfedc8bb26..be7c40d23f 100644
--- a/xbmc/windowing/wayland/WinSystemWayland.cpp
+++ b/xbmc/windowing/wayland/WinSystemWayland.cpp
@@ -175,6 +175,7 @@ CWinSystemWayland::CWinSystemWayland()
}
m_winEvents.reset(new CWinEventsWayland());
CLinuxPowerSyscall::Register();
+ m_lirc.reset(OPTIONALS::LircRegister());
}
CWinSystemWayland::~CWinSystemWayland() noexcept
diff --git a/xbmc/windowing/wayland/WinSystemWayland.h b/xbmc/windowing/wayland/WinSystemWayland.h
index dab870df7a..786d8c722b 100644
--- a/xbmc/windowing/wayland/WinSystemWayland.h
+++ b/xbmc/windowing/wayland/WinSystemWayland.h
@@ -36,6 +36,7 @@
#include "Seat.h"
#include "Signals.h"
#include "ShellSurface.h"
+#include "platform/linux/OptionalsReg.h"
#include "threads/CriticalSection.h"
#include "threads/Event.h"
#include "utils/ActorProtocol.h"
@@ -296,6 +297,8 @@ private:
std::uint32_t m_lastAckedSerial{0u};
/// Whether this is the first call to SetFullScreen
bool m_isInitialSetFullScreen{true};
+
+ std::unique_ptr<OPTIONALS::CLircContainer, OPTIONALS::delete_CLircContainer> m_lirc;
};