Files
OpenRGB/RGBController/RGBController_Network.cpp
Adam Honse c0826fbe83 Settings Rework
* Add JSON string configuration field to RGBController to store device-specific configurations
    * This JSON string holds both configuration and schema
    * Add settings schema tracking to SettingsManager
    * Implement dynamic settings widget that generates a settings UI based on a JSON schema
    * Implement SettingsManager callback for notifying of settings changes and settings schema updates
    * Always enable Entire Device zone option and use it to enable Edit Device
    * Rename SaveSizes to SaveConfiguration in ProfileManager and Sizes.json to Configuration.json
    * Add zone flag for indicating that a zone's geometry may change, informing profile manager to ignore this check
    * Remove Theme setting and Theme Manager, as this didn't work on most setups anyways and Qt6 has proper Windows dark theming
2026-05-04 22:50:47 -05:00

600 lines
24 KiB
C++

/*---------------------------------------------------------*\
| RGBController_Network.cpp |
| |
| RGBController implementation that represents a remote |
| RGBController instance from a connected OpenRGB server |
| |
| Adam Honse (CalcProgrammer1) 11 Apr 2020 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include "RGBController_Network.h"
RGBController_Network::RGBController_Network(NetworkClient * client_ptr, unsigned int dev_id_val)
{
client = client_ptr;
dev_id = dev_id_val;
}
RGBController_Network::~RGBController_Network()
{
Shutdown();
}
unsigned int RGBController_Network::GetID()
{
return(dev_id);
}
void RGBController_Network::ClearSegments(int zone)
{
client->SendRequest_RGBController_ClearSegments(dev_id, zone);
client->SendRequest_ControllerData(dev_id);
client->WaitOnControllerData();
}
void RGBController_Network::AddSegment(int zone, segment new_segment)
{
/*-----------------------------------------------------*\
| Lock access mutex |
\*-----------------------------------------------------*/
AccessMutex.lock_shared();
/*-----------------------------------------------------*\
| Initialize variables |
\*-----------------------------------------------------*/
unsigned int data_size = 0;
/*-----------------------------------------------------*\
| Calculate data size |
\*-----------------------------------------------------*/
data_size += sizeof(data_size);
data_size += sizeof(zone);
data_size += GetSegmentDescriptionSize(new_segment, client->GetProtocolVersion());
/*-----------------------------------------------------*\
| Create data buffer |
\*-----------------------------------------------------*/
unsigned char * data_buf = new unsigned char[data_size];
unsigned char * data_ptr = data_buf;
/*-----------------------------------------------------*\
| Copy in data size |
\*-----------------------------------------------------*/
memcpy(data_ptr, &data_size, sizeof(data_size));
data_ptr += sizeof(data_size);
/*-----------------------------------------------------*\
| Copy in zone index |
\*-----------------------------------------------------*/
memcpy(data_ptr, &zone, sizeof(zone));
data_ptr += sizeof(zone);
/*-----------------------------------------------------*\
| Copy in segment description |
\*-----------------------------------------------------*/
data_ptr = GetSegmentDescriptionData(data_ptr, new_segment, client->GetProtocolVersion());
/*-----------------------------------------------------*\
| Unlock access mutex |
\*-----------------------------------------------------*/
AccessMutex.unlock_shared();
client->SendRequest_RGBController_AddSegment(dev_id, data_buf, data_size);
delete[] data_buf;
client->SendRequest_ControllerData(dev_id);
client->WaitOnControllerData();
}
void RGBController_Network::ConfigureZone(int zone_idx, zone new_zone)
{
/*-----------------------------------------------------*\
| ConfigureZone was introduced in protocol version 6 |
| For previous protocols, call ResizeZone and |
| ClearSegments/AddSegments. |
\*-----------------------------------------------------*/
if(client->GetProtocolVersion() < 6)
{
/*-------------------------------------------------*\
| Resize zone if size is manually configured |
\*-------------------------------------------------*/
if(new_zone.flags & ZONE_FLAG_MANUALLY_CONFIGURED_SIZE)
{
ResizeZone(zone_idx, new_zone.leds_count);
}
/*-------------------------------------------------*\
| Update segments if segments manually configured |
\*-------------------------------------------------*/
if(new_zone.flags & ZONE_FLAG_MANUALLY_CONFIGURED_SEGMENTS)
{
ClearSegments(zone_idx);
for(std::size_t segment_idx = 0; segment_idx < new_zone.segments.size(); segment_idx++)
{
AddSegment(zone_idx, new_zone.segments[segment_idx]);
}
}
return;
}
/*-----------------------------------------------------*\
| Lock access mutex |
\*-----------------------------------------------------*/
AccessMutex.lock_shared();
/*-----------------------------------------------------*\
| Initialize variables |
\*-----------------------------------------------------*/
unsigned int data_size = 0;
/*-----------------------------------------------------*\
| Calculate data size |
\*-----------------------------------------------------*/
data_size += sizeof(data_size);
data_size += sizeof(zone);
data_size += GetZoneDescriptionSize(new_zone, client->GetProtocolVersion());
/*-----------------------------------------------------*\
| Create data buffer |
\*-----------------------------------------------------*/
unsigned char * data_buf = new unsigned char[data_size];
unsigned char * data_ptr = data_buf;
/*-----------------------------------------------------*\
| Copy in data size |
\*-----------------------------------------------------*/
memcpy(data_ptr, &data_size, sizeof(data_size));
data_ptr += sizeof(data_size);
/*-----------------------------------------------------*\
| Copy in zone index |
\*-----------------------------------------------------*/
memcpy(data_ptr, &zone_idx, sizeof(zone_idx));
data_ptr += sizeof(zone_idx);
/*-----------------------------------------------------*\
| Copy in segment description |
\*-----------------------------------------------------*/
data_ptr = GetZoneDescriptionData(data_ptr, new_zone, client->GetProtocolVersion());
/*-----------------------------------------------------*\
| Unlock access mutex |
\*-----------------------------------------------------*/
AccessMutex.unlock_shared();
client->SendRequest_RGBController_ConfigureZone(dev_id, data_buf, data_size);
delete[] data_buf;
client->SendRequest_ControllerData(dev_id);
client->WaitOnControllerData();
}
void RGBController_Network::ResizeZone(int zone, int new_size)
{
client->SendRequest_RGBController_ResizeZone(dev_id, zone, new_size);
client->SendRequest_ControllerData(dev_id);
client->WaitOnControllerData();
}
void RGBController_Network::DeviceUpdateLEDs()
{
unsigned char * data = CreateUpdateLEDsPacket(client->GetProtocolVersion());
unsigned int size;
memcpy(&size, &data[0], sizeof(unsigned int));
client->SendRequest_RGBController_UpdateLEDs(dev_id, data, size);
delete[] data;
}
void RGBController_Network::DeviceUpdateZoneLEDs(int zone)
{
unsigned char * data = CreateUpdateZoneLEDsPacket(zone);
unsigned int size;
memcpy(&size, &data[0], sizeof(unsigned int));
client->SendRequest_RGBController_UpdateZoneLEDs(dev_id, data, size);
delete[] data;
}
void RGBController_Network::DeviceUpdateSingleLED(int led)
{
unsigned char * data = CreateUpdateSingleLEDPacket(led);
client->SendRequest_RGBController_UpdateSingleLED(dev_id, data, sizeof(int) + sizeof(RGBColor));
delete[] data;
}
void RGBController_Network::SetCustomMode()
{
client->SendRequest_RGBController_SetCustomMode(dev_id);
client->SendRequest_ControllerData(dev_id);
client->WaitOnControllerData();
}
void RGBController_Network::DeviceUpdateMode()
{
unsigned char * data;
unsigned int size;
data = CreateUpdateModePacket(active_mode, &size, client->GetProtocolVersion());
client->SendRequest_RGBController_UpdateMode(dev_id, data, size);
delete[] data;
}
void RGBController_Network::DeviceUpdateZoneMode(int zone)
{
unsigned char * data;
unsigned int size;
data = CreateUpdateZoneModePacket(zone, zones[zone].active_mode, &size, client->GetProtocolVersion());
client->SendRequest_RGBController_UpdateZoneMode(dev_id, data, size);
delete[] data;
}
void RGBController_Network::DeviceSaveMode()
{
unsigned char * data;
unsigned int size;
data = CreateUpdateModePacket(active_mode, &size, client->GetProtocolVersion());
client->SendRequest_RGBController_SaveMode(dev_id, data, size);
delete[] data;
}
void RGBController_Network::SetDeviceSpecificConfiguration(nlohmann::json configuration_json)
{
std::string json_string = configuration_json.dump();
client->SendRequest_RGBController_SetDeviceSpecificConfiguration(dev_id, (unsigned char *)json_string.c_str(), strlen(json_string.c_str()) + 1);
client->SendRequest_ControllerData(dev_id);
client->WaitOnControllerData();
}
void RGBController_Network::SetDeviceSpecificZoneConfiguration(int zone, nlohmann::json configuration_json)
{
/*-----------------------------------------------------*\
| Initialize variables |
\*-----------------------------------------------------*/
unsigned int data_size = 0;
std::string json_string = configuration_json.dump();
unsigned int json_string_size = strlen(json_string.c_str()) +1;
/*-----------------------------------------------------*\
| Calculate data size |
\*-----------------------------------------------------*/
data_size += sizeof(int);
data_size += sizeof(json_string_size);
data_size += json_string_size;
/*-----------------------------------------------------*\
| Create data buffer |
\*-----------------------------------------------------*/
unsigned char * data_buf = new unsigned char[data_size];
unsigned char * data_ptr = data_buf;
/*-----------------------------------------------------*\
| Copy in zone |
\*-----------------------------------------------------*/
memcpy(data_ptr, &zone, sizeof(zone));
data_ptr += sizeof(zone);
/*-----------------------------------------------------*\
| Copy in string size |
\*-----------------------------------------------------*/
memcpy(data_ptr, &json_string_size, sizeof(json_string_size));
data_ptr += sizeof(json_string_size);
memcpy(data_ptr, json_string.c_str(), json_string_size);
data_ptr += json_string_size;
client->SendRequest_RGBController_SetDeviceSpecificZoneConfiguration(dev_id, data_buf, data_size);
delete[] data_buf;
client->SendRequest_ControllerData(dev_id);
client->WaitOnControllerData();
}
/*-----------------------------------------------------*\
| This function overrides RGBController::UpdateLEDs()! |
| Normally, UpdateLEDs() sets a flag for the updater |
| thread to update the device asynchronously, which |
| prevents delays updating local devices. This causes |
| instability and flickering with network devices though|
| so for the network implementation, process all updates|
| synchronously. |
\*-----------------------------------------------------*/
void RGBController_Network::UpdateLEDs()
{
AccessMutex.lock_shared();
DeviceUpdateLEDs();
AccessMutex.unlock_shared();
}
void RGBController_Network::UpdateMode()
{
AccessMutex.lock_shared();
DeviceUpdateMode();
AccessMutex.unlock_shared();
}
unsigned char * RGBController_Network::CreateUpdateLEDsPacket(unsigned int protocol_version)
{
/*-----------------------------------------------------*\
| Lock access mutex |
\*-----------------------------------------------------*/
AccessMutex.lock_shared();
/*-----------------------------------------------------*\
| Initialize variables |
\*-----------------------------------------------------*/
unsigned int data_size = 0;
/*-----------------------------------------------------*\
| Calculate data size |
\*-----------------------------------------------------*/
data_size += sizeof(data_size);
data_size += RGBController::GetColorDescriptionSize(this, protocol_version);
/*-----------------------------------------------------*\
| Create data buffer |
\*-----------------------------------------------------*/
unsigned char * data_buf = new unsigned char[data_size];
unsigned char * data_ptr = data_buf;
/*-----------------------------------------------------*\
| Copy in data size |
\*-----------------------------------------------------*/
memcpy(data_ptr, &data_size, sizeof(data_size));
data_ptr += sizeof(data_size);
/*-----------------------------------------------------*\
| Copy in color data |
\*-----------------------------------------------------*/
data_ptr = RGBController::GetColorDescriptionData(data_ptr, this, protocol_version);
/*-----------------------------------------------------*\
| Unlock access mutex |
\*-----------------------------------------------------*/
AccessMutex.unlock_shared();
return(data_buf);
}
unsigned char * RGBController_Network::CreateUpdateModePacket(int mode_idx, unsigned int* size, unsigned int protocol_version)
{
/*-----------------------------------------------------*\
| Lock access mutex |
\*-----------------------------------------------------*/
AccessMutex.lock_shared();
/*-----------------------------------------------------*\
| Initialize variables |
\*-----------------------------------------------------*/
unsigned int data_size = 0;
/*-----------------------------------------------------*\
| Calculate data size |
\*-----------------------------------------------------*/
data_size += sizeof(data_size);
data_size += sizeof(mode_idx);
data_size += GetModeDescriptionSize(modes[mode_idx], protocol_version);
/*-----------------------------------------------------*\
| Create data buffer |
\*-----------------------------------------------------*/
unsigned char* data_buf = new unsigned char[data_size];
unsigned char* data_ptr = data_buf;
/*-----------------------------------------------------*\
| Copy in data size |
\*-----------------------------------------------------*/
memcpy(data_ptr, &data_size, sizeof(data_size));
data_ptr += sizeof(data_size);
/*-----------------------------------------------------*\
| Copy in mode index |
\*-----------------------------------------------------*/
memcpy(data_ptr, &mode_idx, sizeof(mode_idx));
data_ptr += sizeof(mode_idx);
/*-----------------------------------------------------*\
| Copy in mode description |
\*-----------------------------------------------------*/
data_ptr = GetModeDescriptionData(data_ptr, modes[mode_idx], protocol_version);
/*-----------------------------------------------------*\
| Unlock access mutex |
\*-----------------------------------------------------*/
AccessMutex.unlock_shared();
*size = data_size;
return(data_buf);
}
unsigned char * RGBController_Network::CreateUpdateSingleLEDPacket(int led)
{
/*-----------------------------------------------------*\
| Lock access mutex |
\*-----------------------------------------------------*/
AccessMutex.lock_shared();
/*-----------------------------------------------------*\
| Fixed size descrption: |
| int: LED index |
| RGBColor: LED color |
\*-----------------------------------------------------*/
unsigned char *data_buf = new unsigned char[sizeof(int) + sizeof(RGBColor)];
/*-----------------------------------------------------*\
| Copy in LED index |
\*-----------------------------------------------------*/
memcpy(&data_buf[0], &led, sizeof(int));
/*-----------------------------------------------------*\
| Copy in LED color |
\*-----------------------------------------------------*/
memcpy(&data_buf[sizeof(led)], &colors[led], sizeof(RGBColor));
/*-----------------------------------------------------*\
| Unlock access mutex |
\*-----------------------------------------------------*/
AccessMutex.unlock_shared();
return(data_buf);
}
unsigned char * RGBController_Network::CreateUpdateZoneLEDsPacket(int zone)
{
/*-----------------------------------------------------*\
| Lock access mutex |
\*-----------------------------------------------------*/
AccessMutex.lock_shared();
unsigned int data_ptr = 0;
unsigned int data_size = 0;
unsigned short num_colors = zones[zone].leds_count;
/*-----------------------------------------------------*\
| Calculate data size |
\*-----------------------------------------------------*/
data_size += sizeof(data_size);
data_size += sizeof(zone);
data_size += sizeof(num_colors);
data_size += num_colors * sizeof(RGBColor);
/*-----------------------------------------------------*\
| Create data buffer |
\*-----------------------------------------------------*/
unsigned char *data_buf = new unsigned char[data_size];
/*-----------------------------------------------------*\
| Copy in data size |
\*-----------------------------------------------------*/
memcpy(&data_buf[data_ptr], &data_size, sizeof(data_size));
data_ptr += sizeof(data_size);
/*-----------------------------------------------------*\
| Copy in zone index |
\*-----------------------------------------------------*/
memcpy(&data_buf[data_ptr], &zone, sizeof(zone));
data_ptr += sizeof(zone);
/*-----------------------------------------------------*\
| Copy in number of colors (data) |
\*-----------------------------------------------------*/
memcpy(&data_buf[data_ptr], &num_colors, sizeof(unsigned short));
data_ptr += sizeof(unsigned short);
/*-----------------------------------------------------*\
| Copy in colors |
\*-----------------------------------------------------*/
for(int color_index = 0; color_index < num_colors; color_index++)
{
/*-------------------------------------------------*\
| Copy in color (data) |
\*-------------------------------------------------*/
memcpy(&data_buf[data_ptr], &zones[zone].colors[color_index], sizeof(zones[zone].colors[color_index]));
data_ptr += sizeof(zones[zone].colors[color_index]);
}
/*-----------------------------------------------------*\
| Unlock access mutex |
\*-----------------------------------------------------*/
AccessMutex.unlock_shared();
return(data_buf);
}
unsigned char * RGBController_Network::CreateUpdateZoneModePacket(int zone_idx, int mode_idx, unsigned int* size, unsigned int protocol_version)
{
/*-----------------------------------------------------*\
| Lock access mutex |
\*-----------------------------------------------------*/
AccessMutex.lock_shared();
/*-----------------------------------------------------*\
| Initialize variables |
\*-----------------------------------------------------*/
unsigned int data_size = 0;
/*-----------------------------------------------------*\
| Calculate data size |
\*-----------------------------------------------------*/
data_size += sizeof(data_size);
data_size += sizeof(zone_idx);
data_size += sizeof(mode_idx);
if(mode_idx >= 0)
{
data_size += GetModeDescriptionSize(zones[zone_idx].modes[mode_idx], protocol_version);
}
/*-----------------------------------------------------*\
| Create data buffer |
\*-----------------------------------------------------*/
unsigned char* data_buf = new unsigned char[data_size];
unsigned char* data_ptr = data_buf;
/*-----------------------------------------------------*\
| Copy in data size |
\*-----------------------------------------------------*/
memcpy(data_ptr, &data_size, sizeof(data_size));
data_ptr += sizeof(data_size);
/*-----------------------------------------------------*\
| Copy in zone index |
\*-----------------------------------------------------*/
memcpy(data_ptr, &zone_idx, sizeof(zone_idx));
data_ptr += sizeof(zone_idx);
/*-----------------------------------------------------*\
| Copy in mode index |
\*-----------------------------------------------------*/
memcpy(data_ptr, &mode_idx, sizeof(mode_idx));
data_ptr += sizeof(mode_idx);
/*-----------------------------------------------------*\
| Copy in mode description |
\*-----------------------------------------------------*/
if(mode_idx >= 0)
{
data_ptr = GetModeDescriptionData(data_ptr, zones[zone_idx].modes[mode_idx], protocol_version);
}
/*-----------------------------------------------------*\
| Unlock access mutex |
\*-----------------------------------------------------*/
AccessMutex.unlock_shared();
*size = data_size;
return(data_buf);
}