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