2 Copyright 2020 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
29 #include "inputlirc.h"
31 static const char* TAG = "InputLIRC";
33 const char* InputLIRC::myModName = "InputLIRC";
35 bool InputLIRC::init()
37 if (initted) return false;
39 log = LogNT::getInstance();
40 log->debug(TAG, "Starting InputLIRC");
44 log->debug(TAG, "TCP init error");
49 bool arraySuccess = Config::getInstance()->foreachInArray("input_lirc", "remotes", [&] (const std::string& remoteName)
51 log->debug(TAG, "Remote name: {}", remoteName);
54 bool objSuccess = Config::getInstance()->foreachPairInObject("input_lirc", remoteName, [&] (const std::string& lircName, const std::string& vompName)
56 UCHAR keyNumber = InputMan::getVompKeyNumber(vompName.c_str());
58 log->debug(TAG, " Lirc: {}, vomp: {}, vomp-number {}", lircName, vompName, keyNumber);
60 remotes[remoteName][lircName] = keyNumber;
65 log->error(TAG, "Error reading config for remote {}", remoteName);
71 log->debug(TAG, "Error reading remotes list");
75 log->debug(TAG, "Remotes array read OK");
79 using RemotesType = std::map<std::string, std::map<std::string, UCHAR>>;
80 using ButtonsType = std::map<std::string, UCHAR>;
82 for(RemotesType::iterator i = remotes.begin(); i != remotes.end(); i++)
84 ButtonsType& b = i->second;
85 for(ButtonsType:: iterator j = b.begin(); j != b.end(); j++)
87 log->debug(TAG, "{} - {} - {}", i->first.c_str(), j->first.c_str(), j->second);
94 void InputLIRC::shutdown()
98 remotes.clear(); // FIXME ?
103 bool InputLIRC::start()
105 log->debug(TAG, "Start called");
110 bool checkA = Config::getInstance()->getString("input_lirc", "lirc_ip", lircIP);
112 /* bool checkB = */ Config::getInstance()->getInt("input_lirc", "lirc_port", lircPort);
113 std::string lircSocket;
114 bool checkC = Config::getInstance()->getString("input_lirc", "lirc_socket", lircSocket);
121 LogNT::getInstance()->info(TAG, "Starting with unix socket: {}", lircSocket);
122 tr = tcp.connectSocket(lircSocket);
124 else if (checkA) // If no checkC, must be checkA
126 LogNT::getInstance()->info(TAG, "Starting with IP: {} {}", lircIP, lircPort);
127 tr = tcp.connect(lircIP, static_cast<USHORT>(lircPort));
132 log->debug(TAG, "TCP connect failed");
136 threadStartProtect.lock(); // Make sure listenThread is fully initted before start returns
137 listenThread = std::thread( [this]
139 threadStartProtect.lock();
140 threadStartProtect.unlock();
143 threadStartProtect.unlock();
145 log->debug(TAG, "Started");
149 void InputLIRC::stop()
151 std::lock_guard<std::mutex> lg(threadStartProtect); // Also use it to protect against starting while stopping
153 if (!tcp.status()) return;
155 if (listenThread.joinable())
157 threadReqStop = true;
160 threadReqStop = false;
166 void InputLIRC::listenLoop()
172 std::stringstream ss = tcp.readString(&readSuccess, 0);
174 if (threadReqStop) return;
180 log->crit(TAG, "TCP status fail");
182 } // return to stop this thread
187 log->debug(TAG, "got data: {}", ss.str());
189 std::string remoteName, remoteButton;
191 if (parse(ss.str(), remoteName, remoteButton, repeatCount))
192 log->debug(TAG, "Remote: '{}', Button: '{}', Count: '{}'", remoteName, remoteButton, repeatCount);
194 log->error(TAG, "Parse error");
199 button = remotes.at(remoteName).at(remoteButton);
201 catch (std::exception& e)
203 log->error(TAG, "Remote button not found");
207 log->debug(TAG, "Submitting vomp key: '{}'", button);
208 if (repeatCount == 0) sendInputKey(button);
212 bool InputLIRC::parse(const std::string& input, std::string& remoteName, std::string& remoteButton, int& repeatCount)
215 found = input.find(" ", pos);
216 if (found == std::string::npos) return false;
217 pos = found + 1; // pos at 00
218 found = input.find(" ", pos);
219 if (found == std::string::npos) return false;
220 std::string rcString = input.substr(pos, found - pos);
221 try { repeatCount = std::stoi(rcString, 0, 16); } catch (std::exception& e) { return false; }
222 pos = found + 1; // pos at KE
223 found = input.find(" ", pos);
224 if (found == std::string::npos)
226 remoteButton = input.substr(pos);
229 remoteButton = input.substr(pos, found - pos);
231 if ((input.length() - pos) > 0)
232 remoteName = input.substr(pos);
237 // const char* InputLIRC::getHardCodedHardwareKeyNamesForVompKey(UCHAR /* vompKey */)
242 std::string InputLIRC::getHardwareKeyName(HWC_TYPE /* hardwareKey */)