2022-01-21 19:22:13 +00:00
|
|
|
#pragma once
|
2024-01-28 20:46:54 +00:00
|
|
|
#include <utils/net.h>
|
2022-01-21 19:22:13 +00:00
|
|
|
#include <dsp/stream.h>
|
|
|
|
#include <dsp/types.h>
|
|
|
|
#include <atomic>
|
|
|
|
#include <queue>
|
|
|
|
#include <server_protocol.h>
|
|
|
|
#include <atomic>
|
|
|
|
#include <map>
|
|
|
|
#include <vector>
|
2022-06-17 15:34:23 +00:00
|
|
|
#include <dsp/compression/sample_stream_decompressor.h>
|
2022-01-21 19:22:13 +00:00
|
|
|
#include <dsp/sink.h>
|
2022-06-17 15:34:23 +00:00
|
|
|
#include <dsp/routing/stream_link.h>
|
2022-01-26 12:23:55 +00:00
|
|
|
#include <zstd.h>
|
2022-01-21 19:22:13 +00:00
|
|
|
|
|
|
|
#define PROTOCOL_TIMEOUT_MS 10000
|
|
|
|
|
|
|
|
namespace server {
|
|
|
|
class PacketWaiter {
|
|
|
|
public:
|
|
|
|
bool await(int timeout) {
|
|
|
|
std::unique_lock lck(readyMtx);
|
2022-01-22 01:30:08 +00:00
|
|
|
return readyCnd.wait_for(lck, std::chrono::milliseconds(timeout), [=](){ return dataReady || canceled; }) && !canceled;
|
2022-01-21 19:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void handled() {
|
|
|
|
{
|
|
|
|
std::lock_guard lck(handledMtx);
|
|
|
|
dataHandled = true;
|
|
|
|
}
|
|
|
|
handledCnd.notify_all();
|
|
|
|
}
|
|
|
|
|
|
|
|
void notify() {
|
|
|
|
// Tell waiter that data is ready
|
|
|
|
{
|
|
|
|
std::lock_guard lck(readyMtx);
|
|
|
|
dataReady = true;
|
|
|
|
}
|
|
|
|
readyCnd.notify_all();
|
|
|
|
|
|
|
|
// Wait for waiter to handle the request
|
|
|
|
{
|
|
|
|
std::unique_lock lck(readyMtx);
|
|
|
|
handledCnd.wait(lck, [=](){ return dataHandled; });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 01:30:08 +00:00
|
|
|
void cancel() {
|
|
|
|
canceled = true;
|
|
|
|
notify();
|
|
|
|
}
|
|
|
|
|
2022-01-21 19:22:13 +00:00
|
|
|
void reset() {
|
|
|
|
std::lock_guard lck1(readyMtx);
|
|
|
|
std::lock_guard lck2(handledMtx);
|
|
|
|
dataReady = false;
|
|
|
|
dataHandled = false;
|
2022-01-22 01:30:08 +00:00
|
|
|
canceled = false;
|
2022-01-21 19:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool dataReady = false;
|
|
|
|
bool dataHandled = false;
|
2022-01-22 01:30:08 +00:00
|
|
|
bool canceled = 0;
|
2022-01-21 19:22:13 +00:00
|
|
|
|
|
|
|
std::condition_variable readyCnd;
|
|
|
|
std::condition_variable handledCnd;
|
|
|
|
|
|
|
|
std::mutex readyMtx;
|
|
|
|
std::mutex handledMtx;
|
|
|
|
};
|
|
|
|
|
2024-04-08 14:59:05 +00:00
|
|
|
enum ConnectionError {
|
|
|
|
CONN_ERR_TIMEOUT = -1,
|
|
|
|
CONN_ERR_BUSY = -2
|
|
|
|
};
|
|
|
|
|
2024-01-28 20:46:54 +00:00
|
|
|
class Client {
|
2022-01-21 19:22:13 +00:00
|
|
|
public:
|
2024-01-28 20:46:54 +00:00
|
|
|
Client(std::shared_ptr<net::Socket> sock, dsp::stream<dsp::complex_t>* out);
|
|
|
|
~Client();
|
2022-01-21 19:22:13 +00:00
|
|
|
|
|
|
|
void showMenu();
|
|
|
|
|
|
|
|
void setFrequency(double freq);
|
|
|
|
double getSampleRate();
|
|
|
|
|
2022-06-17 15:34:23 +00:00
|
|
|
void setSampleType(dsp::compression::PCMType type);
|
2022-01-26 12:23:55 +00:00
|
|
|
void setCompression(bool enabled);
|
2022-01-21 19:22:13 +00:00
|
|
|
|
|
|
|
void start();
|
|
|
|
void stop();
|
|
|
|
|
|
|
|
void close();
|
|
|
|
bool isOpen();
|
|
|
|
|
|
|
|
int bytes = 0;
|
2022-01-22 01:30:08 +00:00
|
|
|
bool serverBusy = false;
|
2022-01-21 19:22:13 +00:00
|
|
|
|
|
|
|
private:
|
2024-01-28 20:46:54 +00:00
|
|
|
void worker();
|
2022-01-21 19:22:13 +00:00
|
|
|
|
2022-01-22 01:30:08 +00:00
|
|
|
int getUI();
|
2022-01-21 19:22:13 +00:00
|
|
|
|
|
|
|
void sendPacket(PacketType type, int len);
|
|
|
|
void sendCommand(Command cmd, int len);
|
|
|
|
void sendCommandAck(Command cmd, int len);
|
|
|
|
|
|
|
|
PacketWaiter* awaitCommandAck(Command cmd);
|
|
|
|
void commandAckHandled(PacketWaiter* waiter);
|
|
|
|
std::map<PacketWaiter*, Command> commandAckWaiters;
|
|
|
|
|
|
|
|
static void dHandler(dsp::complex_t *data, int count, void *ctx);
|
|
|
|
|
2024-01-28 20:46:54 +00:00
|
|
|
std::shared_ptr<net::Socket> sock;
|
2022-01-21 19:22:13 +00:00
|
|
|
|
|
|
|
dsp::stream<uint8_t> decompIn;
|
2022-06-17 15:34:23 +00:00
|
|
|
dsp::compression::SampleStreamDecompressor decomp;
|
|
|
|
dsp::routing::StreamLink<dsp::complex_t> link;
|
2022-01-21 19:22:13 +00:00
|
|
|
dsp::stream<dsp::complex_t>* output;
|
|
|
|
|
|
|
|
uint8_t* rbuffer = NULL;
|
|
|
|
uint8_t* sbuffer = NULL;
|
|
|
|
|
|
|
|
PacketHeader* r_pkt_hdr = NULL;
|
|
|
|
uint8_t* r_pkt_data = NULL;
|
|
|
|
CommandHeader* r_cmd_hdr = NULL;
|
|
|
|
uint8_t* r_cmd_data = NULL;
|
|
|
|
|
|
|
|
PacketHeader* s_pkt_hdr = NULL;
|
|
|
|
uint8_t* s_pkt_data = NULL;
|
|
|
|
CommandHeader* s_cmd_hdr = NULL;
|
|
|
|
uint8_t* s_cmd_data = NULL;
|
|
|
|
|
|
|
|
SmGui::DrawList dl;
|
|
|
|
std::mutex dlMtx;
|
|
|
|
|
2022-01-26 12:23:55 +00:00
|
|
|
ZSTD_DCtx* dctx;
|
|
|
|
|
2024-01-28 20:46:54 +00:00
|
|
|
std::thread workerThread;
|
|
|
|
|
2022-01-21 19:22:13 +00:00
|
|
|
double currentSampleRate = 1000000.0;
|
|
|
|
};
|
|
|
|
|
2024-01-28 20:46:54 +00:00
|
|
|
std::shared_ptr<Client> connect(std::string host, uint16_t port, dsp::stream<dsp::complex_t>* out);
|
2022-01-21 19:22:13 +00:00
|
|
|
}
|