]> git.vomp.tv Git - vompclient.git/blob - inputlirc.cc
Rename Log class filenames to oldlog
[vompclient.git] / inputlirc.cc
1 /*
2     Copyright 2020 Chris Tallon
3
4     This file is part of VOMP.
5
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.
10
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.
15
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/>.
18 */
19
20 #include <sstream>
21 #include <algorithm>
22 #include <stdexcept>
23
24 #include "config.h"
25 #include "oldlog.h"
26
27 #include "inputman.h"
28
29 #include "inputlirc.h"
30
31 const char* InputLIRC::myModName = "InputLIRC";
32
33 bool InputLIRC::init()
34 {
35   if (initted) return false;
36   initted = true;
37   log = Log::getInstance();
38   log->log(myModName, Log::DEBUG, "Starting InputLIRC");
39
40   if (!tcp.init())
41   {
42     log->log(myModName, Log::DEBUG, "TCP init error");
43     initted = false;
44     return false;
45   }
46
47   bool arraySuccess = Config::getInstance()->foreachInArray("input_lirc", "remotes", [&] (const std::string& remoteName)
48   {
49     log->log(myModName, Log::DEBUG, "Remote name: %s", remoteName.c_str());
50
51
52     bool objSuccess = Config::getInstance()->foreachPairInObject("input_lirc", remoteName, [&] (const std::string& lircName, const std::string& vompName)
53     {
54       UCHAR keyNumber = InputMan::getVompKeyNumber(vompName.c_str());
55
56       log->log(myModName, Log::DEBUG, "  Lirc: %s, vomp: %s, vomp-number %i", lircName.c_str(), vompName.c_str(), keyNumber);
57
58       remotes[remoteName][lircName] = keyNumber;
59     });
60
61     if (!objSuccess)
62     {
63       log->log(myModName, Log::ERR, "Error reading config for remote %s", remoteName.c_str());
64     }
65   });
66
67   if (!arraySuccess)
68   {
69     log->log(myModName, Log::DEBUG, "Error reading remotes list");
70   }
71   else
72   {
73     log->log(myModName, Log::DEBUG, "Remotes array read OK");
74   }
75
76
77   using RemotesType = std::map<std::string, std::map<std::string, UCHAR>>;
78   using ButtonsType = std::map<std::string, UCHAR>;
79
80   for(RemotesType::iterator i = remotes.begin(); i != remotes.end(); i++)
81   {
82     ButtonsType& b = i->second;
83     for(ButtonsType:: iterator j = b.begin(); j != b.end(); j++)
84     {
85       log->log(myModName, Log::DEBUG, "%s - %s - %i", i->first.c_str(), j->first.c_str(), j->second);
86     }
87   }
88
89   return true;
90 }
91
92 void InputLIRC::shutdown()
93 {
94   stop();
95
96   remotes.clear(); // FIXME ?
97
98   initted = false;
99 }
100
101 bool InputLIRC::start(const std::string& ip, USHORT port)
102 {
103   // FIXME implement unix domain socket connection
104
105   bool tr = tcp.connect(ip, port); // NCONFIG
106   if (!tr)
107   {
108     log->log(myModName, Log::DEBUG, "InputLIRC TCP connect failed");
109     return false;
110   }
111
112   threadStartProtect.lock(); // Make sure listenThread is fully initted before start returns
113   listenThread = std::thread( [this]
114   {
115     threadStartProtect.lock();
116     threadStartProtect.unlock();
117     listenLoop();
118   });
119   threadStartProtect.unlock();
120
121   log->log(myModName, Log::DEBUG, "InputLIRC command client started");
122   return true;
123 }
124
125 void InputLIRC::stop()
126 {
127   std::lock_guard<std::mutex> lg(threadStartProtect); // Also use it to protect against starting while stopping
128
129   if (!tcp.status()) return;
130
131   if (listenThread.joinable())
132   {
133     threadReqStop = true;
134     tcp.abortCall();
135     listenThread.join();
136     threadReqStop = false;
137   }
138
139   tcp.shutdown();  
140 }
141
142 void InputLIRC::listenLoop()
143 {
144   bool readSuccess;
145
146   while(1)
147   {
148     std::stringstream ss = tcp.readString(&readSuccess, 0);
149
150     if (threadReqStop) return;
151
152     if (!readSuccess)
153     {
154       if (!tcp.status())
155       {
156         log->log(myModName, Log::CRIT, "TCP status fail");
157         return;
158       } // return to stop this thread
159
160       continue;
161     }
162
163     log->log(myModName, Log::DEBUG, "got data: %s", ss.str().c_str());
164
165     std::string remoteName, remoteButton;
166     int repeatCount;
167     if (parse(ss.str(), remoteName, remoteButton, repeatCount))
168       log->log(myModName, Log::DEBUG, "Remote: '%s', Button: '%s', Count: '%i'", remoteName.c_str(), remoteButton.c_str(), repeatCount);
169     else
170       log->log(myModName, Log::ERR, "Parse error");
171     
172     UCHAR button;
173     try
174     {
175       button = remotes.at(remoteName).at(remoteButton);
176     }
177     catch (std::exception& e)
178     {
179       log->log(myModName, Log::ERR, "Remote button not found");
180       continue;
181     }
182     
183     if (repeatCount == 0) sendInputKey(button);
184   }
185 }
186
187 bool InputLIRC::parse(const std::string& input, std::string& remoteName, std::string& remoteButton, int& repeatCount)
188 {
189   UINT pos{}, found{};
190   found = input.find(" ", pos);
191   if (found == std::string::npos) return false;
192   pos = found + 1; // pos at 00
193   found = input.find(" ", pos);
194   if (found == std::string::npos) return false;
195   std::string rcString = input.substr(pos, found - pos);
196   try { repeatCount = std::stoi(rcString, 0, 16); } catch (std::exception& e) { return false; }
197   pos = found + 1; // pos at KE
198   found = input.find(" ", pos);
199   if (found == std::string::npos)
200   {
201     remoteButton = input.substr(pos);
202     return true;
203   }
204   remoteButton = input.substr(pos, found - pos);
205   pos = found + 1;
206   if ((input.length() - pos) > 0)
207     remoteName = input.substr(pos);
208   return true;
209 }
210
211
212 // const char* InputLIRC::getHardCodedHardwareKeyNamesForVompKey(UCHAR /* vompKey */)
213 // {
214 //   return "";
215 // }
216
217 std::string InputLIRC::getHardwareKeyName(HWC_TYPE /* hardwareKey */)
218 {
219   std::string retval;
220   return retval;
221 }