source: xplra/src/client/c/hu/varadiistvan/xplra/XPlane.h@ 110:9ac6386fe9ff

Last change on this file since 110:9ac6386fe9ff was 110:9ac6386fe9ff, checked in by István Váradi <ivaradi@…>, 17 months ago

The C++ client API can connect over TCP

File size: 12.5 KB
Line 
1// Copyright (c) 2013 by István Váradi
2
3// This file is part of XPLRA, a remote-access plugin for X-Plane
4
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7
8// 1. Redistributions of source code must retain the above copyright notice, this
9// list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25// The views and conclusions contained in the software and documentation are those
26// of the authors and should not be interpreted as representing official policies,
27// either expressed or implied, of the FreeBSD Project.
28
29#ifndef HU_VARADIISTVAN_XPLRA_XPLANE_H
30#define HU_VARADIISTVAN_XPLRA_XPLANE_H
31//-----------------------------------------------------------------------------
32
33#include "Exception.h"
34
35#include <hu/varadiistvan/scpl/io/Waiter.h>
36
37#include <set>
38#include <memory>
39
40#include <inttypes.h>
41
42//-----------------------------------------------------------------------------
43
44namespace hu { namespace varadiistvan { namespace scpl { namespace io {
45
46class BufferedStream;
47class DataStream;
48
49} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
50
51//------------------------------------------------------------------------------
52
53namespace hu { namespace varadiistvan { namespace xplra {
54
55//------------------------------------------------------------------------------
56
57class MultiBuffer;
58class MultiGetter;
59class MultiSetter;
60
61//------------------------------------------------------------------------------
62
63/**
64 * The main class to access X-Plane.
65 *
66 * The calls are synchronous and not thread-safe.
67 */
68class XPlane
69{
70private:
71 /**
72 * The default TCP port.
73 */
74 static const unsigned short defaultTCPPort = 0x5852;
75
76 /**
77 * Type for the set of multi-dataref buffers.
78 */
79 typedef std::set<MultiBuffer*> multiBuffers_t;
80
81 /**
82 * The waiter to use.
83 */
84 scpl::io::Waiter waiter;
85
86 /**
87 * The client socket as a stream, over which we are communicating with X-Plane.
88 */
89 scpl::io::BufferedStream* socket;
90
91 /**
92 * The data stream to handle the data conversions.
93 */
94 scpl::io::DataStream* stream;
95
96 /**
97 * The buffers created by this object.
98 */
99 multiBuffers_t multiBuffers;
100
101public:
102 /**
103 * Construct the object. It will not be connected to the simulator
104 * yet.
105 */
106 XPlane() noexcept;
107
108 /**
109 * Destroy the object. If connected, the connection will be
110 * closed. It destroys all existing buffers, so their references
111 * become invalid.
112 */
113 ~XPlane() noexcept;
114
115 /**
116 * Connect to the simulator locally.
117 */
118 void connect();
119
120 /**
121 * Connect to the simulator on TCP to the given address.
122 */
123 void connectTCP(const std::string& address,
124 unsigned short port = defaultTCPPort);
125
126 /**
127 * Check if we are connected to the simulator.
128 */
129 bool isConnected() const noexcept;
130
131 /**
132 * Disconnect from the simulator.
133 */
134 void disconnect() noexcept;
135
136 /**
137 * Create a new getter of multiple datarefs and return a reference
138 * to it.
139 */
140 MultiGetter& createMultiGetter() noexcept;
141
142 /**
143 * Create a new setter of multiple datarefs and return a reference
144 * to it.
145 */
146 MultiSetter& createMultiSetter() noexcept;
147
148 /**
149 * Destroy the given getter or setter of multiple datarefs. As the
150 * buffer is unregistered, if it has been registered previously,
151 * and unregistration may fail, this function might throw an
152 * exception.
153 *
154 * @return if the buffer was found and could be destroyed
155 */
156 bool destroyMultiBuffer(MultiBuffer& buffer);
157
158 /**
159 * Get the versions of X-Plane, XPLM and the XPLRA plugin.
160 */
161 void getVersions(int& xplaneVersion, int& xplmVersion, int& xplraVersion);
162
163 /**
164 * Reload the plugins loaded in X-Plane. After this the connection
165 * fails.
166 */
167 void reloadPlugins();
168
169 /**
170 * Save the current situation into the file with the given path,
171 * which is relative to the directory of X-Plane.
172 */
173 void saveSituation(const char* path);
174
175 /**
176 * Get the integer value of the dataref with the given name.
177 */
178 int getInt(const char* name);
179
180 /**
181 * Get a float value.
182 */
183 float getFloat(const char* name);
184
185 /**
186 * Get a double value.
187 */
188 double getDouble(const char* name);
189
190 /**
191 * Get a possibly partial array of floats.
192 *
193 * @param name the name of the dataref
194 * @param dest the destination buffer
195 * @param length the length of the destination buffer
196 * @param offset the offset from which to get the array
197 *
198 * @return the number of values acquired actually
199 */
200 size_t getFloatArray(const char* name, float* dest,
201 size_t length, size_t offset = 0);
202
203 /**
204 * Get a possibly partial array of floats. The result array will
205 * be created with a length needed to hold the returned value.
206 *
207 * @param name the name of the dataref
208 * @param length will contain the number of floats read
209 * @param offset the offset from which to get the array
210 */
211 float* getFloatArray(const char* name, size_t& length,
212 size_t offset = 0);
213
214 /**
215 * Get a possibly partial array of integers.
216 *
217 * @param name the name of the dataref
218 * @param dest the destination buffer
219 * @param length the length of the destination buffer
220 * @param offset the offset from which to get the array
221 *
222 * @return the number of values acquired actually
223 */
224 size_t getIntArray(const char* name, int32_t* dest,
225 size_t length, size_t offset = 0);
226
227 /**
228 * Get a possibly partial array of integers. The result array will
229 * be created with a length needed to hold the returned value.
230 *
231 * @param name the name of the dataref
232 * @param length will contain the number of integers read
233 * @param offset the offset from which to get the array
234 */
235 int32_t* getIntArray(const char* name, size_t& length,
236 size_t offset = 0);
237
238 /**
239 * Get a possibly partial array of bytes.
240 *
241 * @param name the name of the dataref
242 * @param dest the destination buffer
243 * @param length the length of the destination buffer
244 * @param offset the offset from which to get the array
245 *
246 * @return the number of values acquired actually
247 */
248 size_t getByteArray(const char* name, uint8_t* dest,
249 size_t length, size_t offset = 0);
250
251 /**
252 * Get a possibly partial array of bytes. The result array will
253 * be created with a length needed to hold the returned value.
254 *
255 * @param name the name of the dataref
256 * @param length will contain the number of bytes read on return
257 * @param offset the offset from which to get the array
258 */
259 uint8_t* getByteArray(const char* name, size_t& length,
260 size_t offset = 0);
261
262 /**
263 * Get a string. A string is a byte array.
264 */
265 std::string getString(const char* name, size_t offset = 0);
266
267 /**
268 * Set the given dataref to the given integer value.
269 */
270 void setInt(const char* name, int value);
271
272 /**
273 * Set the given dataref to the given float value.
274 */
275 void setFloat(const char* name, float value);
276
277 /**
278 * Set the given dataref to the given double value.
279 */
280 void setDouble(const char* name, double value);
281
282 /**
283 * Set the given float array to values in the given buffer.
284 */
285 void setFloatArray(const char* name, const float* values, size_t length,
286 size_t offset = 0);
287
288 /**
289 * Set the given integer array to values in the given buffer.
290 */
291 void setIntArray(const char* name, const int32_t* values, size_t length,
292 size_t offset = 0);
293
294 /**
295 * Set the given byte array to values in the given buffer.
296 */
297 void setByteArray(const char* name, const uint8_t* values, size_t length,
298 size_t offset = 0);
299
300 /**
301 * Set the given string to the given value. Since strings are byte
302 * arrays, and the bytes after the string should be zeroed, the
303 * length must be given. The string will be converted to a byte
304 * array of the given length, padded with 0s.
305 */
306 void setString(const char* name, const char* value, size_t length,
307 size_t offset = 0);
308
309 /**
310 * Show a textual message for a certain duration.
311 */
312 void showMessage(const char* message, float duration);
313
314 /**
315 * Register the given hotkey codes for listening. If there is an
316 * existing set of hotkeys registered, those will be overwritten.
317 */
318 void registerHotkeys(const uint16_t* codes, size_t length);
319
320 /**
321 * Query the registered hotkeys whether they were pressed.
322 */
323 void queryHotkeys(uint8_t* states, size_t length);
324
325 /**
326 * Unregister the hotkeys.
327 */
328 void unregisterHotkeys();
329
330private:
331 /**
332 * Check if we have a stream and if it has not failed.
333 */
334 void checkStream();
335
336 /**
337 * Check the given protocol result. If it signifies an error,
338 * throw a ProtocolException with the correct error code.
339 */
340 void checkResult(uint8_t result, bool hasParameter = false,
341 long parameter = 0);
342
343 /**
344 * Read and check the result. If it signifies an error,
345 * throw a ProtocolException with the correct error code. If there
346 * is some problem with the stream, an IOException is thrown.
347 */
348 void checkResult(bool multi = false);
349
350 /**
351 * Issue the command to get a single, scalar value. The result is
352 * also checked, but the value should be read by the caller.
353 */
354 void getScalar(const char* name, uint8_t type);
355
356 /**
357 * Issue the command to get an array of values of the given
358 * type. It checks the result and retrieves the number of value
359 * items available.
360 *
361 * @return the number of value items available
362 */
363 size_t getArray(const char* name, uint8_t type,
364 ssize_t length, size_t offset);
365
366
367 /**
368 * Issue the command to set a scalar value of the given type.
369 */
370 void setScalar(const char* name, uint8_t type);
371
372 /**
373 * Issue the command to set an array value of the given type.
374 */
375 void setArray(const char* name, uint8_t type, size_t length,
376 size_t offset);
377
378 /**
379 * Connect with the given socket.
380 */
381 template <class ClientSocket>
382 void connect(std::unique_ptr<ClientSocket> clientSocket);
383
384 friend class MultiBuffer;
385 friend class MultiGetter;
386 friend class MultiSetter;
387};
388
389//------------------------------------------------------------------------------
390// Inline definitions
391//------------------------------------------------------------------------------
392
393inline XPlane::XPlane() noexcept :
394 socket(0),
395 stream(0)
396{
397}
398
399//------------------------------------------------------------------------------
400
401inline bool XPlane::isConnected() const noexcept
402{
403 return socket!=0;
404}
405
406//------------------------------------------------------------------------------
407
408} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
409
410//------------------------------------------------------------------------------
411#endif // HU_VARADIISTVAN_XPLRA_XPLANE_H
412
413// Local Variables:
414// mode: C++
415// c-basic-offset: 4
416// indent-tabs-mode: nil
417// End:
Note: See TracBrowser for help on using the repository browser.