mirror of
https://github.com/niellun/FastCarPlay.git
synced 2026-06-07 09:38:25 +02:00
Message queue for sending
This commit is contained in:
@@ -82,6 +82,14 @@ public:
|
||||
return waitFlag.load();
|
||||
}
|
||||
|
||||
bool waitFor(atomic<bool> &waitFlag, uint32_t timeoutMs, uint8_t count = 0)
|
||||
{
|
||||
unique_lock<std::mutex> lock(_mtx);
|
||||
_lock.wait_for(lock, std::chrono::milliseconds(timeoutMs), [&]
|
||||
{ return _count > count || !waitFlag.load(); });
|
||||
return waitFlag.load();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_data = std::make_unique<std::unique_ptr<T>[]>(_size);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef SRC_STRUCT_AUDIO_CHUNK
|
||||
#define SRC_STRUCT_AUDIO_CHUNK
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class AudioChunk
|
||||
{
|
||||
public:
|
||||
AudioChunk(uint16_t size)
|
||||
: data(nullptr), size(size)
|
||||
{
|
||||
if (size > 0)
|
||||
data = static_cast<uint8_t *>(malloc(size));
|
||||
}
|
||||
|
||||
~AudioChunk()
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
// Deleted copy constructor/assignment
|
||||
AudioChunk(const AudioChunk &) = delete;
|
||||
AudioChunk &operator=(const AudioChunk &) = delete;
|
||||
|
||||
uint8_t *data;
|
||||
uint16_t size;
|
||||
};
|
||||
|
||||
#endif /* SRC_STRUCT_AUDIO_CHUNK */
|
||||
@@ -0,0 +1,189 @@
|
||||
#ifndef SRC_STRUCT_COMMAND
|
||||
#define SRC_STRUCT_COMMAND
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
|
||||
#include "helper/functions.h"
|
||||
#include "helper/protocol_const.h"
|
||||
#include "struct/audio_chunk.h"
|
||||
#include "struct/multitouch.h"
|
||||
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
Command(const Command &) = delete;
|
||||
Command &operator=(const Command &) = delete;
|
||||
|
||||
Command(int cmd, bool encrypt = true, uint32_t size = 0)
|
||||
: command(cmd), encryption(encrypt), length(size), data(nullptr)
|
||||
{
|
||||
if (size > 0)
|
||||
data = static_cast<uint8_t *>(malloc(size));
|
||||
}
|
||||
|
||||
Command(int cmd, uint32_t value, bool encrypt = true)
|
||||
: Command(cmd, encrypt, 4)
|
||||
{
|
||||
write_uint32_le(data, value);
|
||||
}
|
||||
|
||||
Command(int cmd, bool encrypt, uint8_t *buffer, uint32_t size)
|
||||
: command(cmd), encryption(encrypt), length(size), data(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
~Command()
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
free(data);
|
||||
data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> Init(int width, int height, int fps)
|
||||
{
|
||||
std::unique_ptr<Command> result(new Command(CMD_OPEN, true, 28));
|
||||
write_uint32_le(result->data + 0, width);
|
||||
write_uint32_le(result->data + 4, height);
|
||||
write_uint32_le(result->data + 8, fps);
|
||||
write_uint32_le(result->data + 12, 5);
|
||||
write_uint32_le(result->data + 16, 49152);
|
||||
write_uint32_le(result->data + 20, 2);
|
||||
write_uint32_le(result->data + 24, 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> File(const char *filename, const uint8_t *data, uint32_t length)
|
||||
{
|
||||
// filename is assumed null‑terminated, so strlen + 1 to include the '\0'
|
||||
uint32_t fn_len = strlen(filename) + 1;
|
||||
|
||||
// Total buffer size: 4 (fn_len) + fn_len + 4 (content_len) + content_len
|
||||
std::unique_ptr<Command> result(new Command(CMD_SEND_FILE, true, 4 + fn_len + 4 + length));
|
||||
uint8_t *buf = result->data;
|
||||
|
||||
// 1) filename length (LE)
|
||||
write_uint32_le(buf, fn_len);
|
||||
buf += 4;
|
||||
|
||||
// 2) filename bytes (including the '\0')
|
||||
std::memcpy(buf, filename, fn_len);
|
||||
buf += fn_len;
|
||||
|
||||
// 3) content length (LE)
|
||||
write_uint32_le(buf, length);
|
||||
buf += 4;
|
||||
|
||||
// 4) content bytes
|
||||
if (length > 0 && data)
|
||||
std::memcpy(buf, data, length);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> File(const char *filename, const char *value)
|
||||
{
|
||||
uint32_t len = std::strlen(value);
|
||||
if (len > 16)
|
||||
throw std::invalid_argument("String too long (max 16 bytes)");
|
||||
// note: we send only the ASCII bytes, no trailing '\0'
|
||||
return File(filename, reinterpret_cast<const uint8_t *>(value), len);
|
||||
}
|
||||
|
||||
// overload for a single 32‑bit integer
|
||||
static std::unique_ptr<Command> File(const char *filename, int value)
|
||||
{
|
||||
uint8_t buffer[4];
|
||||
write_uint32_le(buffer, value);
|
||||
return File(filename, buffer, 4);
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> Control(uint32_t value, bool encrypt = false)
|
||||
{
|
||||
return std::unique_ptr<Command>(new Command(CMD_CONTROL, value, encrypt));
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> Encryption(uint32_t seed)
|
||||
{
|
||||
return std::unique_ptr<Command>(new Command(CMD_ENCRYPTION, seed, false));
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> String(uint32_t cmd, const char *str, bool encrypt = true)
|
||||
{
|
||||
uint32_t length = std::strlen(str);
|
||||
std::unique_ptr<Command> result(new Command(cmd, encrypt, length));
|
||||
if (length > 0)
|
||||
std::memcpy(result->data, str, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static std::unique_ptr<Command> String(uint32_t cmd, const char *format, Args... args)
|
||||
{
|
||||
char buffer[512];
|
||||
std::snprintf(buffer, sizeof(buffer), format, args...);
|
||||
return String(cmd, buffer);
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> Touch(uint32_t action, float x, float y)
|
||||
{
|
||||
std::unique_ptr<Command> result(new Command(CMD_TOUCH, false, 16));
|
||||
write_uint32_le(result->data, action);
|
||||
write_uint32_le(result->data + 4, int(10000 * x));
|
||||
write_uint32_le(result->data + 8, int(10000 * y));
|
||||
write_uint32_le(result->data + 12, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> Click(float x, float y, bool down)
|
||||
{
|
||||
return Touch(down ? 14 : 16, x, y);
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> Move(float x, float y)
|
||||
{
|
||||
return Touch(15, x, y);
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> Audio(std::unique_ptr<AudioChunk> chunk)
|
||||
{
|
||||
std::unique_ptr<Command> result(new Command(CMD_AUDIO_DATA, false, chunk->data, chunk->size));
|
||||
chunk->data = nullptr;
|
||||
write_uint32_le(result->data, 5);
|
||||
write_uint32_le(result->data + 4, 0);
|
||||
write_uint32_le(result->data + 8, 3);
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Command> MultiTouch(const Multitouch &touches)
|
||||
{
|
||||
int count = touches.size();
|
||||
if (count == 0)
|
||||
return nullptr;
|
||||
|
||||
std::unique_ptr<Command> result(new Command(CMD_MULTI_TOUCH, false, sizeof(Multitouch::Touch) * count));
|
||||
uint8_t *buf = result->data;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
const Multitouch::Touch &t = touches[i];
|
||||
write_float_le(buf + 0, t.x);
|
||||
write_float_le(buf + 4, t.y);
|
||||
write_uint32_le(buf + 8, static_cast<uint32_t>(t.state));
|
||||
write_uint32_le(buf + 12, static_cast<uint32_t>(t.id));
|
||||
buf += 16;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int command;
|
||||
bool encryption;
|
||||
uint32_t length;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
#endif /* SRC_STRUCT_COMMAND */
|
||||
Reference in New Issue
Block a user