]> git.vomp.tv Git - vompclient.git/blob - inputudp.cc
43 CWFs
[vompclient.git] / inputudp.cc
1 /*
2     Copyright 2006-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 <fcntl.h>
21 #ifndef WIN32
22 #include <unistd.h>
23 #endif
24
25 #include "log.h"
26 #include "config.h"
27
28 #include "inputudp.h"
29
30 static const char* TAG = "InputUDP";
31
32 const char* InputUDP::myModName = "InputUDP";
33
34 bool InputUDP::init()
35 {
36   if (initted) return false;
37   initted = true;
38   log = LogNT::getInstance();
39   int port = 2000;
40   Config::getInstance()->getInt("input_udp", "port", port);
41
42   log->debug(TAG, "Starting InputUDP command server on port {}", port);
43
44   if (!udp6.init(static_cast<USHORT>(port)))
45   {
46     log->debug(TAG, "UDP6 init error");
47     initted = false;
48     return false;
49   }
50
51 #ifdef WIN32
52   quitPipe = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
53   if (quitPipe == INVALID_SOCKET)
54   {
55     log->error(TAG, "Win32 socket fail");
56 #else
57   if (pipe2(pfds, O_NONBLOCK) == -1)
58   {
59     log->error(TAG, "pipe2() fail");
60 #endif
61     udp6.shutdown();
62     initted = false;
63     return false;
64   }
65
66   return true;
67 }
68
69 void InputUDP::shutdown()
70 {
71 #ifdef WIN32
72   CLOSESOCKET(quitPipe);
73 #endif
74
75   udp6.shutdown();
76
77 #ifndef WIN32
78   CLOSESOCKET(pfds[1]);
79   CLOSESOCKET(pfds[0]);
80 #endif
81
82   initted = false;
83 }
84
85 bool InputUDP::start()
86 {
87   threadStartProtect.lock(); // Make sure listenThread is fully initted before start returns
88   listenThread = std::thread( [this]
89   {
90     threadStartProtect.lock();
91     threadStartProtect.unlock();
92     listenLoop();
93   });
94   threadStartProtect.unlock();
95
96   log->debug(TAG, "InputUDP command server started");
97   return true;
98 }
99
100 void InputUDP::stop()
101 {
102   std::lock_guard<std::mutex> lg(threadStartProtect); // Also use it to protect against starting while stopping
103
104   if (!initted) return;
105
106   if (listenThread.joinable())
107   {
108 #ifdef WIN32
109     log->debug(TAG, "Calling CLOSESOCKET on WIN32 quitPipe");
110
111     CLOSESOCKET(quitPipe);
112 #else
113     write(pfds[1], "1", 1); // break the select in listenLoop
114 #endif
115     listenThread.join();
116   }
117 }
118
119 void InputUDP::listenLoop()
120 {
121   int retval;
122   while(1)
123   {
124 #ifdef WIN32
125     retval = udp6.waitforMessage(3, quitPipe);
126 #else
127     retval = udp6.waitforMessage(3, pfds[0]);
128 #endif
129     log->debug(TAG, "Back from waitForMessage");
130
131     if (retval == 2)
132     {
133       processRequest(udp6.getData(), udp6.getDataLength());
134     }
135     else if (retval == 3) // quit
136     {
137       log->debug(TAG, "quit");
138       break;
139     }
140     else
141     {
142       log->crit(TAG, "Wait for packet error");
143       return;
144     }
145   }
146 }
147
148 void InputUDP::processRequest(const void* data, UINT length)
149 {
150   log->debug(TAG, "Got request");
151
152   char* temp = new char[length + 1];
153   memcpy(temp, data, length);
154   temp[length] = '\0';
155   UINT command = static_cast<UINT>(atoi(temp));
156   delete[] temp;
157
158   log->debug(TAG, "Command {} recieved", command);
159   sendInputKey(command);
160 }
161
162 const char* InputUDP::getHardCodedHardwareKeyNamesForVompKey(UCHAR /* vompKey */)
163 {
164   return "";
165 }
166
167 std::string InputUDP::getHardwareKeyName(HWC_TYPE /* hardwareKey */)
168 {
169   std::string retval;
170   return retval;
171 }