108 m_bgThread = std::thread(&StreamOutletPrivate::run,
this);
118 if (m_bgThread.joinable()) {
129 std::lock_guard<std::mutex> lock(m_queueMutex);
130 m_sampleQueue.push(sample);
139 std::lock_guard<std::mutex> lock(m_queueMutex);
140 for (
const auto& sample : chunk) {
141 m_sampleQueue.push(sample);
160 return m_nClients.load() > 0;
176 QTcpServer tcpServer;
177 if (!tcpServer.listen(QHostAddress::Any, 0)) {
178 qDebug() <<
"[lsl::stream_outlet] Failed to start TCP server:" << tcpServer.errorString();
186 QUdpSocket udpSocket;
188 udpSocket.setSocketOption(QAbstractSocket::MulticastTtlOption, 1);
193 QByteArray handshake(
"LSL1", 4);
195 handshake.append(
reinterpret_cast<const char*
>(&ch),
sizeof(
int));
198 std::string discoveryPayload = m_info.
to_string();
201 std::vector<QTcpSocket*> clients;
203 auto lastBroadcast = std::chrono::steady_clock::now() - std::chrono::seconds(10);
208 while (tcpServer.waitForNewConnection(0)) {
209 QTcpSocket* client = tcpServer.nextPendingConnection();
212 client->write(handshake);
214 clients.push_back(client);
215 m_nClients.store(
static_cast<int>(clients.size()));
220 auto now = std::chrono::steady_clock::now();
221 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastBroadcast).count();
222 if (elapsed >= BROADCAST_INTERVAL_MS) {
223 QByteArray datagram(discoveryPayload.c_str(),
static_cast<int>(discoveryPayload.size()));
224 udpSocket.writeDatagram(datagram, DISCOVERY_MULTICAST_GROUP, DISCOVERY_PORT);
230 std::lock_guard<std::mutex> lock(m_queueMutex);
231 while (!m_sampleQueue.empty()) {
232 const std::vector<float>& sample = m_sampleQueue.front();
233 QByteArray sampleData(
reinterpret_cast<const char*
>(sample.data()),
234 static_cast<int>(sample.size() *
sizeof(
float)));
237 auto it = clients.begin();
238 while (it != clients.end()) {
239 QTcpSocket* client = *it;
240 if (client->state() != QAbstractSocket::ConnectedState) {
242 it = clients.erase(it);
245 client->write(sampleData);
254 for (QTcpSocket* client : clients) {
258 m_nClients.store(
static_cast<int>(clients.size()));
261 std::this_thread::sleep_for(std::chrono::milliseconds(1));
265 for (QTcpSocket* client : clients) {
266 client->disconnectFromHost();
277 std::atomic<bool> m_bRunning;
278 std::thread m_bgThread;
280 std::mutex m_queueMutex;
281 std::queue<std::vector<float>> m_sampleQueue;
282 std::atomic<int> m_nClients{0};