Publish LumaOps source
This commit is contained in:
@@ -0,0 +1,287 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| E131ControllerDetect.cpp |
|
||||
| |
|
||||
| Detector for E1.31 devices |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Detector.h"
|
||||
#include "RGBController.h"
|
||||
#include "RGBController_E131.h"
|
||||
#include "SettingsManager.h"
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
* DetectE131Controllers *
|
||||
* *
|
||||
* Detect devices supported by the E131 driver *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
|
||||
void DetectE131Controllers()
|
||||
{
|
||||
json e131_settings;
|
||||
|
||||
std::vector<std::vector<E131Device>> device_lists;
|
||||
E131Device dev;
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Get E1.31 settings from settings manager |
|
||||
\*-------------------------------------------------*/
|
||||
e131_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("E131Devices");
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If the E1.31 settings contains devices, process |
|
||||
\*-------------------------------------------------*/
|
||||
if(e131_settings.contains("devices"))
|
||||
{
|
||||
for(unsigned int device_idx = 0; device_idx < e131_settings["devices"].size(); device_idx++)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Clear E1.31 device data |
|
||||
\*-------------------------------------------------*/
|
||||
dev.name = "";
|
||||
dev.ip = "";
|
||||
dev.type = ZONE_TYPE_SINGLE;
|
||||
dev.num_leds = 0;
|
||||
dev.rgb_order = E131_RGB_ORDER_RBG;
|
||||
dev.matrix_order = E131_MATRIX_ORDER_HORIZONTAL_TOP_LEFT;
|
||||
dev.matrix_width = 0;
|
||||
dev.matrix_height = 0;
|
||||
dev.start_channel = 1;
|
||||
dev.start_universe = 1;
|
||||
dev.keepalive_time = 0;
|
||||
dev.universe_size = 512;
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("name"))
|
||||
{
|
||||
dev.name = e131_settings["devices"][device_idx]["name"];
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("ip"))
|
||||
{
|
||||
dev.ip = e131_settings["devices"][device_idx]["ip"];
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("num_leds"))
|
||||
{
|
||||
dev.num_leds = e131_settings["devices"][device_idx]["num_leds"];
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("start_universe"))
|
||||
{
|
||||
dev.start_universe = e131_settings["devices"][device_idx]["start_universe"];
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("start_channel"))
|
||||
{
|
||||
dev.start_channel = e131_settings["devices"][device_idx]["start_channel"];
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("keepalive_time"))
|
||||
{
|
||||
dev.keepalive_time = e131_settings["devices"][device_idx]["keepalive_time"];
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("matrix_order"))
|
||||
{
|
||||
if(e131_settings["devices"][device_idx]["matrix_order"].is_string())
|
||||
{
|
||||
std::string matrix_order_val = e131_settings["devices"][device_idx]["matrix_order"];
|
||||
|
||||
if(matrix_order_val == "HORIZONTAL_TOP_LEFT")
|
||||
{
|
||||
dev.matrix_order = E131_MATRIX_ORDER_HORIZONTAL_TOP_LEFT;
|
||||
}
|
||||
else if(matrix_order_val == "HORIZONTAL_TOP_RIGHT")
|
||||
{
|
||||
dev.matrix_order = E131_MATRIX_ORDER_HORIZONTAL_TOP_RIGHT;
|
||||
}
|
||||
else if(matrix_order_val == "HORIZONTAL_BOTTOM_LEFT")
|
||||
{
|
||||
dev.matrix_order = E131_MATRIX_ORDER_HORIZONTAL_BOTTOM_LEFT;
|
||||
}
|
||||
else if(matrix_order_val == "HORIZONTAL_BOTTOM_RIGHT")
|
||||
{
|
||||
dev.matrix_order = E131_MATRIX_ORDER_HORIZONTAL_BOTTOM_RIGHT;
|
||||
}
|
||||
else if(matrix_order_val == "VERTICAL_TOP_LEFT")
|
||||
{
|
||||
dev.matrix_order = E131_MATRIX_ORDER_VERTICAL_TOP_LEFT;
|
||||
}
|
||||
else if(matrix_order_val == "VERTICAL_TOP_RIGHT")
|
||||
{
|
||||
dev.matrix_order = E131_MATRIX_ORDER_VERTICAL_TOP_RIGHT;
|
||||
}
|
||||
else if(matrix_order_val == "VERTICAL_BOTTOM_LEFT")
|
||||
{
|
||||
dev.matrix_order = E131_MATRIX_ORDER_VERTICAL_BOTTOM_LEFT;
|
||||
}
|
||||
else if(matrix_order_val == "VERTICAL_BOTTOM_RIGHT")
|
||||
{
|
||||
dev.matrix_order = E131_MATRIX_ORDER_VERTICAL_BOTTOM_RIGHT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dev.matrix_order = e131_settings["devices"][device_idx]["matrix_order"];
|
||||
}
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("rgb_order"))
|
||||
{
|
||||
if(e131_settings["devices"][device_idx]["rgb_order"].is_string())
|
||||
{
|
||||
std::string rgb_order_val = e131_settings["devices"][device_idx]["rgb_order"];
|
||||
|
||||
if(rgb_order_val == "RGB")
|
||||
{
|
||||
dev.rgb_order = E131_RGB_ORDER_RGB;
|
||||
}
|
||||
else if(rgb_order_val == "RBG")
|
||||
{
|
||||
dev.rgb_order = E131_RGB_ORDER_RBG;
|
||||
}
|
||||
else if(rgb_order_val == "GRB")
|
||||
{
|
||||
dev.rgb_order = E131_RGB_ORDER_GRB;
|
||||
}
|
||||
else if(rgb_order_val == "GBR")
|
||||
{
|
||||
dev.rgb_order = E131_RGB_ORDER_GBR;
|
||||
}
|
||||
else if(rgb_order_val == "BRG")
|
||||
{
|
||||
dev.rgb_order = E131_RGB_ORDER_BRG;
|
||||
}
|
||||
else if(rgb_order_val == "BGR")
|
||||
{
|
||||
dev.rgb_order = E131_RGB_ORDER_BGR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dev.rgb_order = e131_settings["devices"][device_idx]["rgb_order"];
|
||||
}
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("matrix_width"))
|
||||
{
|
||||
dev.matrix_width = e131_settings["devices"][device_idx]["matrix_width"];
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("matrix_height"))
|
||||
{
|
||||
dev.matrix_height = e131_settings["devices"][device_idx]["matrix_height"];
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("universe_size"))
|
||||
{
|
||||
dev.universe_size = e131_settings["devices"][device_idx]["universe_size"];
|
||||
}
|
||||
|
||||
if(e131_settings["devices"][device_idx].contains("type"))
|
||||
{
|
||||
if(e131_settings["devices"][device_idx]["type"].is_string())
|
||||
{
|
||||
std::string type_val = e131_settings["devices"][device_idx]["type"];
|
||||
|
||||
if(type_val == "SINGLE")
|
||||
{
|
||||
dev.type = ZONE_TYPE_SINGLE;
|
||||
}
|
||||
else if(type_val == "LINEAR")
|
||||
{
|
||||
dev.type = ZONE_TYPE_LINEAR;
|
||||
}
|
||||
else if(type_val == "MATRIX")
|
||||
{
|
||||
dev.type = ZONE_TYPE_MATRIX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dev.type = e131_settings["devices"][device_idx]["type"];
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Determine whether to create a new list or add this device |
|
||||
| to an existing list. A device is added to an existing |
|
||||
| list if both devices share one or more universes for the |
|
||||
| same output destination |
|
||||
\*---------------------------------------------------------*/
|
||||
bool device_added_to_existing_list = false;
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Track grouping for all controllers. |
|
||||
\*---------------------------------------------------------*/
|
||||
for(unsigned int list_idx = 0; list_idx < device_lists.size(); list_idx++)
|
||||
{
|
||||
for(unsigned int device_idx = 0; device_idx < device_lists[list_idx].size(); device_idx++)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Determine if there is any overlap between this device and |
|
||||
| any existing device list |
|
||||
| Offset the end by two - one because the range is 1-512 |
|
||||
| rather than 0-511, and one because the start channel is |
|
||||
| included in the first set of 3 channels. |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned int dev_start = dev.start_universe;
|
||||
unsigned int list_start = device_lists[list_idx][device_idx].start_universe;
|
||||
unsigned int dev_end = dev.start_universe + ((dev.start_channel + (3 * dev.num_leds) - 2) / 512);
|
||||
unsigned int list_end = device_lists[list_idx][device_idx].start_universe + ((device_lists[list_idx][device_idx].start_channel + (3 * device_lists[list_idx][device_idx].num_leds) - 2) / 512);
|
||||
std::string dev_ip = dev.ip;
|
||||
std::string list_ip = device_lists[list_idx][device_idx].ip;
|
||||
|
||||
bool overlap = dev_ip == list_ip && !(dev_end < list_start || list_end < dev_start);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Check if any universes used by this new device exist in |
|
||||
| the existing device. If so, add the new device to the |
|
||||
| existing list. |
|
||||
\*---------------------------------------------------------*/
|
||||
if(overlap)
|
||||
{
|
||||
device_lists[list_idx].push_back(dev);
|
||||
device_added_to_existing_list = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(device_added_to_existing_list)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| If the device did not overlap with existing devices, |
|
||||
| create a new list for it |
|
||||
\*---------------------------------------------------------*/
|
||||
if(!device_added_to_existing_list)
|
||||
{
|
||||
std::vector<E131Device> new_list;
|
||||
|
||||
new_list.push_back(dev);
|
||||
|
||||
device_lists.push_back(new_list);
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int list_idx = 0; list_idx < device_lists.size(); list_idx++)
|
||||
{
|
||||
RGBController_E131* rgb_controller;
|
||||
rgb_controller = new RGBController_E131(device_lists[list_idx]);
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
} /* DetectE131Controllers() */
|
||||
|
||||
REGISTER_DETECTOR("E1.31", DetectE131Controllers);
|
||||
@@ -0,0 +1,470 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_E131.cpp |
|
||||
| |
|
||||
| RGBController for E1.31 devices |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 18 Oct 2019 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <e131.h>
|
||||
#include <math.h>
|
||||
#include "RGBController_E131.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name E1.31 Devices
|
||||
@category LEDStrip
|
||||
@type E1.31
|
||||
@save :x:
|
||||
@direct :white_check_mark:
|
||||
@effects :x:
|
||||
@detectors DetectE131Controllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_E131::RGBController_E131(std::vector<E131Device> device_list)
|
||||
{
|
||||
bool multicast = false;
|
||||
|
||||
devices = device_list;
|
||||
|
||||
name = "E1.31 Device Group";
|
||||
type = DEVICE_TYPE_LEDSTRIP;
|
||||
description = "E1.31 Streaming ACN Device";
|
||||
location = "E1.31: ";
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| If this controller only represents a |
|
||||
| single device, use the device name for the|
|
||||
| controller name |
|
||||
\*-----------------------------------------*/
|
||||
if(devices.size() == 1)
|
||||
{
|
||||
name = devices[0].name;
|
||||
}
|
||||
else if(devices[0].ip != "")
|
||||
{
|
||||
name += " (" + devices[0].ip + ")";
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Append the destination address to the |
|
||||
| location field |
|
||||
\*-----------------------------------------*/
|
||||
if(devices[0].ip != "")
|
||||
{
|
||||
location += "Unicast " + devices[0].ip + ", ";
|
||||
}
|
||||
else
|
||||
{
|
||||
location += "Multicast, ";
|
||||
multicast = true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Calculate universe list |
|
||||
| Use this to fill in the location field |
|
||||
\*-----------------------------------------*/
|
||||
std::vector<unsigned int> universe_list;
|
||||
|
||||
for(unsigned int device_idx = 0; device_idx < devices.size(); device_idx++)
|
||||
{
|
||||
float universe_size = (float)devices[device_idx].universe_size;
|
||||
unsigned int total_universes = (unsigned int)ceil( ( ( devices[device_idx].num_leds * 3 ) + devices[device_idx].start_channel ) / universe_size );
|
||||
|
||||
for(unsigned int univ_idx = 0; univ_idx < total_universes; univ_idx++)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
for(unsigned int univ_list_idx = 0; univ_list_idx < universe_list.size(); univ_list_idx++)
|
||||
{
|
||||
if((devices[device_idx].start_universe + univ_idx) == universe_list[univ_list_idx])
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
universe_list.push_back(devices[device_idx].start_universe + univ_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Append "Universe" and make plural if there|
|
||||
| are multiple universes in use |
|
||||
\*-----------------------------------------*/
|
||||
location += "Universe";
|
||||
|
||||
if(universe_list.size() > 1)
|
||||
{
|
||||
location += "s ";
|
||||
}
|
||||
else
|
||||
{
|
||||
location += " ";
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Append comma separated list of universes |
|
||||
\*-----------------------------------------*/
|
||||
for(unsigned int univ_list_idx = 0; univ_list_idx < universe_list.size(); univ_list_idx++)
|
||||
{
|
||||
location += std::to_string(universe_list[univ_list_idx]);
|
||||
|
||||
if(univ_list_idx < (universe_list.size() - 1))
|
||||
{
|
||||
location += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Set up modes |
|
||||
\*-----------------------------------------*/
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Create E1.31 socket |
|
||||
\*-----------------------------------------*/
|
||||
sockfd = e131_socket();
|
||||
|
||||
keepalive_delay = 0ms;
|
||||
|
||||
SetupZones();
|
||||
|
||||
for (std::size_t device_idx = 0; device_idx < devices.size(); device_idx++)
|
||||
{
|
||||
/*-----------------------------------------*\
|
||||
| Update keepalive delay |
|
||||
\*-----------------------------------------*/
|
||||
if(devices[device_idx].keepalive_time > 0)
|
||||
{
|
||||
if(keepalive_delay.count() == 0 || keepalive_delay.count() > devices[device_idx].keepalive_time)
|
||||
{
|
||||
keepalive_delay = std::chrono::milliseconds(devices[device_idx].keepalive_time);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Add Universes |
|
||||
\*-----------------------------------------*/
|
||||
float universe_size = (float)devices[device_idx].universe_size;
|
||||
unsigned int total_universes = (unsigned int)ceil( ( ( devices[device_idx].num_leds * 3 ) + devices[device_idx].start_channel ) / universe_size );
|
||||
|
||||
for (unsigned int univ_idx = 0; univ_idx < total_universes; univ_idx++)
|
||||
{
|
||||
unsigned int universe = devices[device_idx].start_universe + univ_idx;
|
||||
bool universe_exists = false;
|
||||
|
||||
for (std::size_t pkt_idx = 0; pkt_idx < packets.size(); pkt_idx++)
|
||||
{
|
||||
if(universes[pkt_idx] == universe)
|
||||
{
|
||||
universe_exists = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!universe_exists)
|
||||
{
|
||||
e131_packet_t packet;
|
||||
e131_addr_t dest_addr;
|
||||
|
||||
e131_pkt_init(&packet, (uint16_t)universe, (uint16_t)universe_size);
|
||||
|
||||
if(multicast)
|
||||
{
|
||||
e131_multicast_dest(&dest_addr, universe, E131_DEFAULT_PORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
e131_unicast_dest(&dest_addr, devices[0].ip.c_str(), E131_DEFAULT_PORT);
|
||||
}
|
||||
|
||||
packets.push_back(packet);
|
||||
universes.push_back(universe);
|
||||
dest_addrs.push_back(dest_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Generate matrix maps |
|
||||
\*-----------------------------------------*/
|
||||
if(devices[device_idx].type == ZONE_TYPE_MATRIX)
|
||||
{
|
||||
unsigned int led_idx = 0;
|
||||
matrix_map_type * new_map = new matrix_map_type;
|
||||
|
||||
new_map->width = devices[device_idx].matrix_width;
|
||||
new_map->height = devices[device_idx].matrix_height;
|
||||
new_map->map = new unsigned int[devices[device_idx].matrix_width * devices[device_idx].matrix_height];
|
||||
|
||||
switch(devices[device_idx].matrix_order)
|
||||
{
|
||||
case E131_MATRIX_ORDER_HORIZONTAL_TOP_LEFT:
|
||||
for(unsigned int y = 0; y < new_map->height; y++)
|
||||
{
|
||||
for(unsigned int x = 0; x < new_map->width; x++)
|
||||
{
|
||||
new_map->map[(y * new_map->width) + x] = led_idx;
|
||||
led_idx++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E131_MATRIX_ORDER_HORIZONTAL_TOP_RIGHT:
|
||||
for(unsigned int y = 0; y < new_map->height; y++)
|
||||
{
|
||||
for(int x = new_map->width - 1; x >= 0; x--)
|
||||
{
|
||||
new_map->map[(y * new_map->width) + x] = led_idx;
|
||||
led_idx++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E131_MATRIX_ORDER_HORIZONTAL_BOTTOM_LEFT:
|
||||
for(int y = new_map->height; y >= 0; y--)
|
||||
{
|
||||
for(unsigned int x = 0; x < new_map->width; x++)
|
||||
{
|
||||
new_map->map[(y * new_map->width) + x] = led_idx;
|
||||
led_idx++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E131_MATRIX_ORDER_HORIZONTAL_BOTTOM_RIGHT:
|
||||
for(int y = new_map->height; y >= 0; y--)
|
||||
{
|
||||
for(int x = new_map->width - 1; x >= 0; x--)
|
||||
{
|
||||
new_map->map[(y * new_map->width) + x] = led_idx;
|
||||
led_idx++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E131_MATRIX_ORDER_VERTICAL_TOP_LEFT:
|
||||
for(unsigned int x = 0; x < new_map->width; x++)
|
||||
{
|
||||
for(unsigned int y = 0; y < new_map->height; y++)
|
||||
{
|
||||
new_map->map[(y * new_map->width) + x] = led_idx;
|
||||
led_idx++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E131_MATRIX_ORDER_VERTICAL_TOP_RIGHT:
|
||||
for(int x = new_map->width - 1; x >= 0; x--)
|
||||
{
|
||||
for(unsigned int y = 0; y < new_map->height; y++)
|
||||
{
|
||||
new_map->map[(y * new_map->width) + x] = led_idx;
|
||||
led_idx++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E131_MATRIX_ORDER_VERTICAL_BOTTOM_LEFT:
|
||||
for(unsigned int x = 0; x < new_map->width; x++)
|
||||
{
|
||||
for(int y = new_map->height - 1; y >= 0; y--)
|
||||
{
|
||||
new_map->map[(y * new_map->width) + x] = led_idx;
|
||||
led_idx++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E131_MATRIX_ORDER_VERTICAL_BOTTOM_RIGHT:
|
||||
for(int x = new_map->width - 1; x >= 0; x--)
|
||||
{
|
||||
for(int y = new_map->height - 1; y >= 0; y--)
|
||||
{
|
||||
new_map->map[(y * new_map->width) + x] = led_idx;
|
||||
led_idx++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
zones[device_idx].matrix_map = new_map;
|
||||
}
|
||||
}
|
||||
|
||||
if(keepalive_delay.count() > 0)
|
||||
{
|
||||
keepalive_thread_run = 1;
|
||||
keepalive_thread = new std::thread(&RGBController_E131::KeepaliveThreadFunction, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
keepalive_thread_run = 0;
|
||||
keepalive_thread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RGBController_E131::~RGBController_E131()
|
||||
{
|
||||
if(keepalive_thread != nullptr)
|
||||
{
|
||||
keepalive_thread_run = 0;
|
||||
keepalive_thread->join();
|
||||
delete keepalive_thread;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Delete the matrix map |
|
||||
\*---------------------------------------------------------*/
|
||||
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
|
||||
{
|
||||
if(zones[zone_index].matrix_map != NULL)
|
||||
{
|
||||
if(zones[zone_index].matrix_map->map != NULL)
|
||||
{
|
||||
delete zones[zone_index].matrix_map->map;
|
||||
}
|
||||
|
||||
delete zones[zone_index].matrix_map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_E131::SetupZones()
|
||||
{
|
||||
/*-----------------------------------------*\
|
||||
| Add Zones |
|
||||
\*-----------------------------------------*/
|
||||
for(std::size_t zone_idx = 0; zone_idx < devices.size(); zone_idx++)
|
||||
{
|
||||
zone led_zone;
|
||||
led_zone.name = devices[zone_idx].name;
|
||||
led_zone.type = devices[zone_idx].type;
|
||||
led_zone.leds_min = devices[zone_idx].num_leds;
|
||||
led_zone.leds_max = devices[zone_idx].num_leds;
|
||||
led_zone.leds_count = devices[zone_idx].num_leds;
|
||||
led_zone.matrix_map = NULL;
|
||||
|
||||
zones.push_back(led_zone);
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Add LEDs |
|
||||
\*-----------------------------------------*/
|
||||
for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++)
|
||||
{
|
||||
for(std::size_t led_idx = 0; led_idx < zones[zone_idx].leds_count; led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
|
||||
new_led.name = zones[zone_idx].name + " LED ";
|
||||
new_led.name.append(std::to_string(led_idx));
|
||||
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_E131::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_E131::DeviceUpdateLEDs()
|
||||
{
|
||||
int color_idx = 0;
|
||||
|
||||
last_update_time = std::chrono::steady_clock::now();
|
||||
|
||||
for(std::size_t device_idx = 0; device_idx < devices.size(); device_idx++)
|
||||
{
|
||||
float universe_size = (float)devices[device_idx].universe_size;
|
||||
unsigned int total_universes = (unsigned int)ceil( ( ( devices[device_idx].num_leds * 3 ) + devices[device_idx].start_channel ) / universe_size );
|
||||
unsigned int channel_idx = devices[device_idx].start_channel;
|
||||
unsigned int led_idx = 0;
|
||||
unsigned int rgb_idx = 0;
|
||||
bool done = false;
|
||||
|
||||
for (unsigned int univ_idx = 0; univ_idx < total_universes; univ_idx++)
|
||||
{
|
||||
unsigned int universe = devices[device_idx].start_universe + univ_idx;
|
||||
|
||||
for(std::size_t packet_idx = 0; packet_idx < packets.size(); packet_idx++)
|
||||
{
|
||||
if(!done && (universes[packet_idx] == universe))
|
||||
{
|
||||
while(!done && (channel_idx <= universe_size))
|
||||
{
|
||||
switch(rgb_idx)
|
||||
{
|
||||
case 0:
|
||||
packets[packet_idx].dmp.prop_val[channel_idx] = RGBGetRValue( colors[color_idx] );
|
||||
rgb_idx = 1;
|
||||
break;
|
||||
case 1:
|
||||
packets[packet_idx].dmp.prop_val[channel_idx] = RGBGetGValue( colors[color_idx] );
|
||||
rgb_idx = 2;
|
||||
break;
|
||||
case 2:
|
||||
packets[packet_idx].dmp.prop_val[channel_idx] = RGBGetBValue( colors[color_idx] );
|
||||
rgb_idx = 0;
|
||||
led_idx++;
|
||||
color_idx++;
|
||||
break;
|
||||
}
|
||||
|
||||
if(led_idx >= devices[device_idx].num_leds)
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
|
||||
channel_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
channel_idx = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for(std::size_t packet_idx = 0; packet_idx < packets.size(); packet_idx++)
|
||||
{
|
||||
e131_send(sockfd, &packets[packet_idx], &dest_addrs[packet_idx]);
|
||||
packets[packet_idx].frame.seq_number++;
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_E131::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_E131::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_E131::DeviceUpdateMode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RGBController_E131::KeepaliveThreadFunction()
|
||||
{
|
||||
while(keepalive_thread_run.load())
|
||||
{
|
||||
if((std::chrono::steady_clock::now() - last_update_time) > ( keepalive_delay * 0.95f ) )
|
||||
{
|
||||
UpdateLEDs();
|
||||
}
|
||||
std::this_thread::sleep_for(keepalive_delay / 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_E131.h |
|
||||
| |
|
||||
| RGBController for E1.31 devices |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 18 Oct 2019 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <e131.h>
|
||||
#include "RGBController.h"
|
||||
|
||||
typedef unsigned int e131_rgb_order;
|
||||
|
||||
enum
|
||||
{
|
||||
E131_RGB_ORDER_RGB,
|
||||
E131_RGB_ORDER_RBG,
|
||||
E131_RGB_ORDER_GRB,
|
||||
E131_RGB_ORDER_GBR,
|
||||
E131_RGB_ORDER_BRG,
|
||||
E131_RGB_ORDER_BGR
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
E131_MATRIX_ORDER_HORIZONTAL_TOP_LEFT,
|
||||
E131_MATRIX_ORDER_HORIZONTAL_TOP_RIGHT,
|
||||
E131_MATRIX_ORDER_HORIZONTAL_BOTTOM_LEFT,
|
||||
E131_MATRIX_ORDER_HORIZONTAL_BOTTOM_RIGHT,
|
||||
E131_MATRIX_ORDER_VERTICAL_TOP_LEFT,
|
||||
E131_MATRIX_ORDER_VERTICAL_TOP_RIGHT,
|
||||
E131_MATRIX_ORDER_VERTICAL_BOTTOM_LEFT,
|
||||
E131_MATRIX_ORDER_VERTICAL_BOTTOM_RIGHT
|
||||
};
|
||||
|
||||
typedef unsigned int e131_matrix_order;
|
||||
|
||||
struct E131Device
|
||||
{
|
||||
std::string name;
|
||||
std::string ip;
|
||||
unsigned int num_leds;
|
||||
unsigned int start_universe;
|
||||
unsigned int start_channel;
|
||||
unsigned int keepalive_time;
|
||||
e131_rgb_order rgb_order;
|
||||
zone_type type;
|
||||
unsigned int matrix_width;
|
||||
unsigned int matrix_height;
|
||||
unsigned int universe_size;
|
||||
e131_matrix_order matrix_order;
|
||||
};
|
||||
|
||||
class RGBController_E131 : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_E131(std::vector<E131Device> device_list);
|
||||
~RGBController_E131();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
void KeepaliveThreadFunction();
|
||||
|
||||
private:
|
||||
std::vector<E131Device> devices;
|
||||
std::vector<e131_packet_t> packets;
|
||||
std::vector<e131_addr_t> dest_addrs;
|
||||
std::vector<unsigned int> universes;
|
||||
int sockfd;
|
||||
std::thread * keepalive_thread;
|
||||
std::atomic<bool> keepalive_thread_run;
|
||||
std::chrono::milliseconds keepalive_delay;
|
||||
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
|
||||
};
|
||||
Reference in New Issue
Block a user