|
13 | 13 | #include <QMultiMap> |
14 | 14 | #include <QRegularExpression> |
15 | 15 | #include <QStringList> |
| 16 | +#include <QEventLoop> |
16 | 17 |
|
17 | 18 | // hyperion includes |
18 | 19 | #include <leddevice/LedDeviceWrapper.h> |
@@ -60,6 +61,7 @@ using namespace hyperion; |
60 | 61 | namespace { |
61 | 62 |
|
62 | 63 | constexpr std::chrono::milliseconds NEW_TOKEN_REQUEST_TIMEOUT{ 180000 }; |
| 64 | +constexpr std::chrono::milliseconds LED_DATA_TIMEOUT { 1000 }; |
63 | 65 |
|
64 | 66 | const char TOKEN_TAG[] = "token"; |
65 | 67 | constexpr int TOKEN_TAG_LENGTH = sizeof(TOKEN_TAG) - 1; |
@@ -404,53 +406,78 @@ void JsonAPI::handleCommand(const JsonApiCommand& cmd, const QJsonObject &messag |
404 | 406 | void JsonAPI::handleGetImageSnapshotCommand(const QJsonObject &message, const JsonApiCommand &cmd) |
405 | 407 | { |
406 | 408 | QString replyMsg; |
407 | | - QString filetype = message["filetype"].toString(); |
| 409 | + QString imageFormat = message["format"].toString("PNG"); |
408 | 410 | const PriorityMuxer::InputInfo priorityInfo = _hyperion->getPriorityInfo(_hyperion->getCurrentPriority()); |
409 | 411 | Image<ColorRgb> image = priorityInfo.image; |
410 | 412 | QImage snapshot(reinterpret_cast<const uchar *>(image.memptr()), image.width(), image.height(), qsizetype(3) * image.width(), QImage::Format_RGB888); |
411 | 413 | QByteArray byteArray; |
412 | 414 |
|
413 | 415 | QBuffer buffer{&byteArray}; |
414 | 416 | buffer.open(QIODevice::WriteOnly); |
415 | | - if (!snapshot.save(&buffer, filetype.toUtf8().constData())) |
| 417 | + if (!snapshot.save(&buffer, imageFormat.toUtf8().constData())) |
416 | 418 | { |
417 | | - replyMsg = QString("Failed to create snapshot of the current image in %1 format").arg(filetype); |
| 419 | + replyMsg = QString("Failed to create snapshot of the current image in %1 format").arg(imageFormat); |
418 | 420 | sendErrorReply(replyMsg, cmd); |
419 | 421 | return; |
420 | 422 | } |
421 | 423 | QByteArray base64Image = byteArray.toBase64(); |
422 | 424 |
|
423 | 425 | QJsonObject info; |
424 | | - info["format"] = filetype; |
| 426 | + info["format"] = imageFormat; |
425 | 427 | info["width"] = image.width(); |
426 | 428 | info["height"] = image.height(); |
427 | | - info["data"] = QString::fromLatin1(base64Image.data()); |
| 429 | + info["data"] = base64Image.constData(); |
428 | 430 | sendSuccessDataReply(info, cmd); |
429 | 431 | } |
430 | 432 |
|
431 | | -void JsonAPI::handleGetLedSnapshotCommand(const QJsonObject &message, const JsonApiCommand &cmd) |
| 433 | +void JsonAPI::handleGetLedSnapshotCommand(const QJsonObject& /*message*/, const JsonApiCommand &cmd) |
432 | 434 | { |
433 | | - QString replyMsg; |
434 | | - const PriorityMuxer::InputInfo priorityInfo = _hyperion->getPriorityInfo(_hyperion->getCurrentPriority()); |
435 | | - const std::vector<ColorRgb> ledColors = _hyperion->getImageProcessor()->process(priorityInfo.image); |
| 435 | + std::vector<ColorRgb> ledColors; |
| 436 | + QEventLoop loop; |
| 437 | + QTimer timer; |
| 438 | + |
| 439 | + // Timeout handling (ensuring loop quits on timeout) |
| 440 | + timer.setSingleShot(true); |
| 441 | + connect(&timer, &QTimer::timeout, this, [&loop]() { |
| 442 | + loop.quit(); // Stop waiting if timeout occurs |
| 443 | + }); |
| 444 | + |
| 445 | + // Capture LED colors when the LED data signal is emitted (execute only once) |
| 446 | + std::unique_ptr<QObject> context{new QObject}; |
| 447 | + QObject* pcontext = context.get(); |
| 448 | + connect(_hyperion, &Hyperion::ledDeviceData, pcontext, |
| 449 | + [this, &loop, context = std::move(context), &ledColors, cmd](std::vector<ColorRgb> ledColorsUpdate) mutable { |
| 450 | + ledColors = ledColorsUpdate; |
| 451 | + loop.quit(); // ✅ Ensure the event loop quits immediately when data is received |
| 452 | + |
| 453 | + QJsonArray ledRgbColorsArray; |
| 454 | + for (const auto &color : ledColors) |
| 455 | + { |
| 456 | + QJsonArray rgbArray; |
| 457 | + rgbArray.append(color.red); |
| 458 | + rgbArray.append(color.green); |
| 459 | + rgbArray.append(color.blue); |
| 460 | + ledRgbColorsArray.append(rgbArray); |
| 461 | + } |
| 462 | + QJsonObject info; |
| 463 | + info["leds"] = ledRgbColorsArray; |
| 464 | + |
| 465 | + sendSuccessDataReply(info, cmd); |
| 466 | + context.reset(); |
| 467 | + } |
| 468 | + ); |
| 469 | + |
| 470 | + // Start the timer and wait for either the signal or timeout |
| 471 | + timer.start(LED_DATA_TIMEOUT); |
| 472 | + loop.exec(); |
| 473 | + |
| 474 | + // If no data was received, return an error |
436 | 475 | if (ledColors.empty()) |
437 | 476 | { |
438 | | - replyMsg = "No led colors available"; |
| 477 | + QString replyMsg = QString("No LED color data available, i.e.no LED update was done within the last %1 ms").arg(LED_DATA_TIMEOUT.count()); |
439 | 478 | sendErrorReply(replyMsg, cmd); |
440 | 479 | return; |
441 | 480 | } |
442 | | - QJsonArray ledColorsArray; |
443 | | - for (const auto &color : ledColors) |
444 | | - { |
445 | | - QJsonArray rgbArray; |
446 | | - rgbArray.append(color.red); |
447 | | - rgbArray.append(color.green); |
448 | | - rgbArray.append(color.blue); |
449 | | - ledColorsArray.append(rgbArray); |
450 | | - } |
451 | | - QJsonObject info; |
452 | | - info["leds"] = ledColorsArray; |
453 | | - sendSuccessDataReply(info, cmd); |
454 | 481 | } |
455 | 482 |
|
456 | 483 | void JsonAPI::handleInstanceDataCommand(const QJsonObject &message, const JsonApiCommand &cmd) |
|
0 commit comments