main.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include <csignal>
  2. #include <cstdint>
  3. #include <cstdlib>
  4. #include <getopt.h>
  5. #include <iostream>
  6. #include <led-matrix.h>
  7. #include <string>
  8. #include <unistd.h>
  9. #include <zmq.hpp>
  10. class ServerOptions {
  11. public:
  12. enum class Args { endpoint = 1, bytes_per_pixel };
  13. std::string endpoint = "tcp://*:42024";
  14. int bytes_per_pixel = 3;
  15. static ServerOptions from_args(int argc, char *argv[]) {
  16. ServerOptions server_options;
  17. static struct option long_opts[]{
  18. {"zmq-endpoint", required_argument, nullptr,
  19. static_cast<int>(ServerOptions::Args::endpoint)},
  20. {"bytes-per-pixel", required_argument, nullptr,
  21. static_cast<int>(ServerOptions::Args::bytes_per_pixel)},
  22. {nullptr, 0, nullptr, 0}};
  23. int opt_code;
  24. int opt_index;
  25. while ((opt_code = getopt_long(argc, argv, "", long_opts, &opt_index)) !=
  26. -1) {
  27. switch (opt_code) {
  28. case static_cast<int>(ServerOptions::Args::endpoint):
  29. server_options.endpoint = std::string(optarg);
  30. break;
  31. case static_cast<int>(ServerOptions::Args::bytes_per_pixel):
  32. server_options.bytes_per_pixel = std::stoi(optarg);
  33. break;
  34. }
  35. }
  36. return server_options;
  37. }
  38. };
  39. volatile bool running = true;
  40. void handle_interrupt(const int signo) { running = false; }
  41. int main(int argc, char *argv[]) {
  42. std::signal(SIGINT, handle_interrupt);
  43. std::signal(SIGTERM, handle_interrupt);
  44. rgb_matrix::RGBMatrix::Options matrix_opts;
  45. rgb_matrix::RuntimeOptions runtime_opts;
  46. ParseOptionsFromFlags(&argc, &argv, &matrix_opts, &runtime_opts);
  47. auto server_options = ServerOptions::from_args(argc, argv);
  48. auto matrix = CreateMatrixFromOptions(matrix_opts, runtime_opts);
  49. if (matrix == nullptr) {
  50. return 1;
  51. }
  52. matrix->set_luminance_correct(true);
  53. zmq::context_t zmq_ctx;
  54. zmq::socket_t zmq_sock(zmq_ctx, zmq::socket_type::rep);
  55. zmq_sock.bind(server_options.endpoint.c_str());
  56. std::cout << "Listening on " << server_options.endpoint
  57. << " @ " << (server_options.bytes_per_pixel) * 8 << "BPP" << std::endl;
  58. size_t expected_frame_size =
  59. matrix->width() * matrix->height() * server_options.bytes_per_pixel;
  60. uint8_t frame[expected_frame_size];
  61. std::cout << "Frame dimensions: " << matrix->width() << "x" << matrix->height() << std::endl;
  62. std::cout << "Expected frame size: " << expected_frame_size << " bytes" << std::endl;
  63. while (running) {
  64. size_t frame_size = zmq_sock.recv(&frame, expected_frame_size);
  65. zmq_sock.send(nullptr, 0);
  66. if (frame_size != expected_frame_size) {
  67. std::cout << "Frame size mismatch! Expected " << expected_frame_size
  68. << " but got " << frame_size << std::endl;
  69. } else {
  70. for (auto y = 0; y < matrix->height(); y++) {
  71. for (auto x = 0; x < matrix->width(); x++) {
  72. uint8_t r =
  73. frame[y * matrix->width() * server_options.bytes_per_pixel +
  74. x * server_options.bytes_per_pixel + 0];
  75. uint8_t g =
  76. frame[y * matrix->width() * server_options.bytes_per_pixel +
  77. x * server_options.bytes_per_pixel + 1];
  78. uint8_t b =
  79. frame[y * matrix->width() * server_options.bytes_per_pixel +
  80. x * server_options.bytes_per_pixel + 2];
  81. matrix->SetPixel(x, y, r, g, b);
  82. }
  83. }
  84. }
  85. }
  86. delete matrix;
  87. return 0;
  88. }