]> git.vomp.tv Git - vompclient.git/blob - inputlirc.cc
OSDOpenVG: Render on demand: Fix backing out of a view render race
[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 "log.h"
25
26 #include "inputlirc.h"
27
28 const char* InputLIRC::myModName = "InputLIRC";
29
30 bool InputLIRC::init()
31 {
32   if (initted) return false;
33   initted = true;
34   log = Log::getInstance();
35   log->log(myModName, Log::DEBUG, "Starting InputLIRC");
36
37   if (!tcp.init())
38   {
39     log->log(myModName, Log::DEBUG, "TCP init error");
40     initted = false;
41     return false;
42   }
43
44   /* FIXME
45    * Hard code remote keys for now. Put lines like this in inputlirc.conf
46    * The 'THREE' is the VOMP key name, see input.h
47    * remotes["lirc-remote-name"]["lirc-button-name"] = THREE;
48   */
49   #include "inputlirc.conf"
50   
51   return true;
52 }
53
54 void InputLIRC::shutdown()
55 {
56   stop();
57
58   remotes.clear(); // FIXME ?
59
60   initted = false;
61 }
62
63 bool InputLIRC::start(const std::string& ip, USHORT port)
64 {
65   // FIXME implement unix domain socket connection
66
67   bool tr = tcp.connect(ip, port); // NCONFIG
68   if (!tr)
69   {
70     log->log(myModName, Log::DEBUG, "InputLIRC TCP connect failed");
71     return false;
72   }
73
74   threadStartProtect.lock(); // Make sure listenThread is fully initted before start returns
75   listenThread = std::thread( [this]
76   {
77     threadStartProtect.lock();
78     threadStartProtect.unlock();
79     listenLoop();
80   });
81   threadStartProtect.unlock();
82
83   log->log(myModName, Log::DEBUG, "InputLIRC command client started");
84   return true;
85 }
86
87 void InputLIRC::stop()
88 {
89   std::lock_guard<std::mutex> lg(threadStartProtect); // Also use it to protect against starting while stopping
90
91   if (!tcp.status()) return;
92
93   if (listenThread.joinable())
94   {
95     threadReqStop = true;
96     tcp.abortCall();
97     listenThread.join();
98     threadReqStop = false;
99   }
100
101   tcp.shutdown();  
102 }
103
104 void InputLIRC::listenLoop()
105 {
106   bool readSuccess;
107
108   while(1)
109   {
110     std::stringstream ss = tcp.readString(&readSuccess, 0);
111
112     if (threadReqStop) return;
113
114     if (!readSuccess)
115     {
116       if (!tcp.status())
117       {
118         log->log(myModName, Log::CRIT, "TCP status fail");
119         return;
120       } // return to stop this thread
121
122       continue;
123     }
124
125     log->log(myModName, Log::DEBUG, "got data: %s", ss.str().c_str());
126
127     std::string remoteName, remoteButton;
128     int repeatCount;
129     if (parse(ss.str(), remoteName, remoteButton, repeatCount))
130       log->log(myModName, Log::DEBUG, "Remote: '%s', Button: '%s', Count: '%i'", remoteName.c_str(), remoteButton.c_str(), repeatCount);
131     else
132       log->log(myModName, Log::ERR, "Parse error");
133     
134     UCHAR button;
135     try
136     {
137       button = remotes.at(remoteName).at(remoteButton);
138     }
139     catch (std::exception& e)
140     {
141       log->log(myModName, Log::ERR, "Remote button not found");
142       continue;
143     }
144     
145     if (repeatCount == 0) sendInputKey(button);
146   }
147 }
148
149 bool InputLIRC::parse(const std::string& input, std::string& remoteName, std::string& remoteButton, int& repeatCount)
150 {
151   UINT pos{}, found{};
152   found = input.find(" ", pos);
153   if (found == std::string::npos) return false;
154   pos = found + 1; // pos at 00
155   found = input.find(" ", pos);
156   if (found == std::string::npos) return false;
157   std::string rcString = input.substr(pos, found - pos);
158   try { repeatCount = std::stoi(rcString, 0, 16); } catch (std::exception& e) { return false; }
159   pos = found + 1; // pos at KE
160   found = input.find(" ", pos);
161   if (found == std::string::npos)
162   {
163     remoteButton = input.substr(pos);
164     return true;
165   }
166   remoteButton = input.substr(pos, found - pos);
167   pos = found + 1;
168   if ((input.length() - pos) > 0)
169     remoteName = input.substr(pos);
170   return true;
171 }
172
173
174 // const char* InputLIRC::getHardCodedHardwareKeyNamesForVompKey(UCHAR /* vompKey */)
175 // {
176 //   return "";
177 // }
178
179 std::string InputLIRC::getHardwareKeyName(HWC_TYPE /* hardwareKey */)
180 {
181   std::string retval;
182   return retval;
183 }