#include "muebreceiver.h" #include <QNetworkDatagram> #include <QUdpSocket> #include "configuration.h" class MuebReceiverPrivate { Q_DECLARE_PUBLIC(MuebReceiver) Q_DISABLE_COPY(MuebReceiverPrivate) public: explicit MuebReceiverPrivate(MuebReceiver *q) : frame(configuration.frame()), q_ptr(q) { socket.bind(configuration.broadcast_animation_port()); QObject::connect(&socket, &QUdpSocket::readyRead, q, &MuebReceiver::readPendingDatagrams); qInfo() << "[MuebReceiver] UDP Socket will receive packets on port" << configuration.broadcast_animation_port(); } Configuration configuration; libmueb::Frame frame; QUdpSocket socket; MuebReceiver *q_ptr; }; MuebReceiver::MuebReceiver(QObject *parent) : QObject(parent), d_ptr_(new MuebReceiverPrivate(this)) {} MuebReceiver::~MuebReceiver() { delete d_ptr_; } MuebReceiver &MuebReceiver::Instance() { static MuebReceiver instance; return instance; } libmueb::Frame MuebReceiver::frame() { return d_ptr_->frame; } inline void datagram_uncompress_error() { qWarning() << "[MuebReceiver] Processed packet is invalid! Check the header " "or packet contents(size)"; } void MuebReceiver::readPendingDatagrams() { while (d_ptr_->socket.hasPendingDatagrams()) { if (d_ptr_->socket.pendingDatagramSize() == d_ptr_->configuration.packet_size()) { QNetworkDatagram datagram = d_ptr_->socket.receiveDatagram(); QByteArray data = datagram.data(); // Process datagram // Packet header check // Check protocol if (data[0] != d_ptr_->configuration.protocol_type()) { datagram_uncompress_error(); return; } auto packet_number = data[1]; if (packet_number >= d_ptr_->configuration.max_packet_number() || packet_number < 0) { datagram_uncompress_error(); return; } data.remove(0, d_ptr_->configuration.packet_header_size()); auto frame_begin = d_ptr_->frame.bits() + packet_number * d_ptr_->configuration.max_pixel_per_datagram(); // Uncompress 1 byte into 2 color components if (d_ptr_->configuration.color_depth() < 5) { for (auto i : data) { *frame_begin = i & 0xf0; frame_begin++; *frame_begin = (i & 0x0f) << d_ptr_->configuration.factor(); frame_begin++; } // No compression } else { // FIXME use better copy method for (auto i : data) { *frame_begin = i; frame_begin++; } } emit(FrameChanged(d_ptr_->frame)); } // Drop invalid packet else { qWarning() << "[MuebReceiver] Packet has invalid size!" << d_ptr_->socket.pendingDatagramSize() << "bytes"; d_ptr_->socket.receiveDatagram(0); } } }