Initial commit for Linux-only controller for Valve Steam Machine using
the leds-valve kernel module and sysfs interface
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_ValveSteamMachine_Linux.cpp |
|
||||
| |
|
||||
| RGBController for Valve Steam Machine LEDs |
|
||||
| |
|
||||
| Adam Honse ([email protected]) 23 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController_ValveSteamMachine_Linux.h"
|
||||
#include <cctype>
|
||||
|
||||
/**------------------------------------------------------------------*\
|
||||
@name Valve Steam Machine LEDs
|
||||
@category LEDStrip
|
||||
@type
|
||||
@save :x:
|
||||
@direct :white_check_mark:
|
||||
@effects :white_check_mark:
|
||||
@detectors DetectValveSteamMachineControllers
|
||||
@comment
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
RGBController_ValveSteamMachine::RGBController_ValveSteamMachine(ValveSteamMachineController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetName();
|
||||
vendor = "Valve";
|
||||
type = DEVICE_TYPE_LEDSTRIP;
|
||||
description = "Valve Steam Machine Device";
|
||||
location = controller->GetLEDPath(0);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| If the device supports hardware effects, add them as |
|
||||
| modes. Effects are stored as strings; the mode value |
|
||||
| is the index into the available effects list. |
|
||||
\*-----------------------------------------------------*/
|
||||
effects = controller->GetAvailableEffects();
|
||||
|
||||
for(unsigned int effect_idx = 0; effect_idx < effects.size(); effect_idx++)
|
||||
{
|
||||
unsigned int effect_color_mode;
|
||||
unsigned int effect_flags;
|
||||
std::string effect_name = effects[effect_idx];
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Determine flags and color mode for effect |
|
||||
\*-------------------------------------------------*/
|
||||
if(effect_name == "off")
|
||||
{
|
||||
effect_flags = 0;
|
||||
effect_color_mode = MODE_COLORS_NONE;
|
||||
}
|
||||
else if(effect_name == "rainbow" || effect_name == "demo")
|
||||
{
|
||||
effect_flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
effect_color_mode = MODE_COLORS_RANDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
effect_flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
effect_color_mode = MODE_COLORS_PER_LED;
|
||||
}
|
||||
|
||||
if(effect_name == "breath" || effect_name == "patrol" || effect_name == "rainbow" || effect_name == "demo")
|
||||
{
|
||||
effect_flags |= MODE_FLAG_HAS_SPEED;
|
||||
}
|
||||
|
||||
/*---------------------------------------------*\
|
||||
| The OpenRGB common name for manual mode is |
|
||||
| Direct |
|
||||
\*---------------------------------------------*/
|
||||
if(effect_name == "manual")
|
||||
{
|
||||
effect_name = "Direct";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!effect_name.empty())
|
||||
{
|
||||
effect_name[0] = std::toupper((unsigned char)effect_name[0]);
|
||||
}
|
||||
}
|
||||
|
||||
mode new_mode;
|
||||
new_mode.name = effect_name;
|
||||
new_mode.value = effect_idx;
|
||||
new_mode.flags = effect_flags;
|
||||
new_mode.color_mode = effect_color_mode;
|
||||
new_mode.speed_min = 20;
|
||||
new_mode.speed_max = 0;
|
||||
new_mode.speed = 10;
|
||||
new_mode.brightness_min = 0;
|
||||
new_mode.brightness_max = 0xFF;
|
||||
new_mode.brightness = 0x38;
|
||||
modes.push_back(new_mode);
|
||||
}
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_ValveSteamMachine::~RGBController_ValveSteamMachine()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
delete controller;
|
||||
}
|
||||
|
||||
void RGBController_ValveSteamMachine::SetupZones()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Create a single linear zone containing all LEDs |
|
||||
\*-----------------------------------------------------*/
|
||||
zone led_zone;
|
||||
led_zone.name = "Steam Machine LEDs";
|
||||
led_zone.type = ZONE_TYPE_LINEAR;
|
||||
led_zone.leds_min = (unsigned int)controller->GetLEDCount();
|
||||
led_zone.leds_max = (unsigned int)controller->GetLEDCount();
|
||||
led_zone.leds_count = (unsigned int)controller->GetLEDCount();
|
||||
|
||||
zones.push_back(led_zone);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Create LED entries for each LED in the controller |
|
||||
\*-----------------------------------------------------*/
|
||||
for(unsigned int led_idx = 0; led_idx < controller->GetLEDCount(); led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = "Steam Machine LED " + std::to_string(led_idx);
|
||||
new_led.value = led_idx;
|
||||
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_ValveSteamMachine::DeviceUpdateLEDs()
|
||||
{
|
||||
for(unsigned int led_idx = 0; led_idx < controller->GetLEDCount(); led_idx++)
|
||||
{
|
||||
DeviceUpdateSingleLED(led_idx);
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_ValveSteamMachine::DeviceUpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_ValveSteamMachine::DeviceUpdateSingleLED(int led)
|
||||
{
|
||||
unsigned char red = RGBGetRValue(colors[led]);
|
||||
unsigned char grn = RGBGetGValue(colors[led]);
|
||||
unsigned char blu = RGBGetBValue(colors[led]);
|
||||
|
||||
controller->SetLEDColor(led, red, grn, blu);
|
||||
}
|
||||
|
||||
void RGBController_ValveSteamMachine::DeviceUpdateMode()
|
||||
{
|
||||
if((unsigned int)active_mode < effects.size())
|
||||
{
|
||||
controller->SetEffect(effects[active_mode]);
|
||||
controller->SetBrightness(modes[active_mode].brightness);
|
||||
controller->SetDelay(modes[active_mode].speed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| RGBController_ValveSteamMachine_Linux.h |
|
||||
| |
|
||||
| RGBController for Valve Steam Machine LEDs |
|
||||
| |
|
||||
| Adam Honse ([email protected]) 23 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "ValveSteamMachineController_Linux.h"
|
||||
|
||||
class RGBController_ValveSteamMachine : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_ValveSteamMachine(ValveSteamMachineController* controller_ptr);
|
||||
~RGBController_ValveSteamMachine();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void DeviceUpdateZoneLEDs(int zone);
|
||||
void DeviceUpdateSingleLED(int led);
|
||||
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
ValveSteamMachineController* controller;
|
||||
std::vector<std::string> effects;
|
||||
};
|
||||
@@ -0,0 +1,142 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| ValveSteamMachineControllerDetect_Linux.cpp |
|
||||
| |
|
||||
| Detector for Valve Steam Machine LEDs |
|
||||
| |
|
||||
| Adam Honse ([email protected]) 23 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include "DetectionManager.h"
|
||||
#include "filesystem.h"
|
||||
#include "RGBController_ValveSteamMachine_Linux.h"
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Helper function to extract the numeric index enclosed |
|
||||
| in brackets from a LED directory name for proper |
|
||||
| numerical sorting. |
|
||||
| For example, "valve-leds[2]" -> 2, "valve-leds[10]" -> 10.|
|
||||
\*---------------------------------------------------------*/
|
||||
static int GetLEDNumber(const std::string& path)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Extract the directory name from the full path |
|
||||
\*-----------------------------------------------------*/
|
||||
std::string dir_name = filesystem::path(path).filename().string();
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Find the last '[' and ']' in the directory name to |
|
||||
| extract the numeric index enclosed in brackets. |
|
||||
| For example, "valve-leds[10]" -> 10. |
|
||||
\*-----------------------------------------------------*/
|
||||
size_t bracket_start = dir_name.rfind('[');
|
||||
size_t bracket_end = dir_name.rfind(']');
|
||||
|
||||
if(bracket_start != std::string::npos &&
|
||||
bracket_end != std::string::npos &&
|
||||
bracket_end > bracket_start)
|
||||
{
|
||||
std::string num_str = dir_name.substr(bracket_start + 1, bracket_end - bracket_start - 1);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Verify the extracted substring is all digits |
|
||||
| before converting, to avoid exceptions from |
|
||||
| std::stoi. |
|
||||
\*-------------------------------------------------*/
|
||||
bool all_digits = true;
|
||||
|
||||
for(char c : num_str)
|
||||
{
|
||||
if(!std::isdigit(static_cast<unsigned char>(c)))
|
||||
{
|
||||
all_digits = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(all_digits && !num_str.empty())
|
||||
{
|
||||
return(std::stoi(num_str));
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Sort from highest to lowest, as Steam Machine LEDs go |
|
||||
| from 0 on the right to 16 on the left |
|
||||
\*---------------------------------------------------------*/
|
||||
static bool CompareLEDPaths(const std::string& a, const std::string& b)
|
||||
{
|
||||
return(GetLEDNumber(a) > GetLEDNumber(b));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Detect leds-valve sysfs LEDs |
|
||||
\*---------------------------------------------------------*/
|
||||
void DetectValveLEDs(std::vector<std::string>& led_paths)
|
||||
{
|
||||
const std::string leds_class_path = "/sys/class/leds";
|
||||
|
||||
if(!filesystem::exists(leds_class_path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(const filesystem::directory_entry& entry : filesystem::directory_iterator(leds_class_path))
|
||||
{
|
||||
std::string led_dir = entry.path().string();
|
||||
|
||||
if(led_dir.find("valve-leds") != std::string::npos)
|
||||
{
|
||||
led_paths.push_back(led_dir);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Sort the LED paths numerically by their bracket |
|
||||
| enclosed index to ensure correct ordering from [N] |
|
||||
| to [0] |
|
||||
\*-----------------------------------------------------*/
|
||||
std::sort(led_paths.begin(), led_paths.end(), CompareLEDPaths);
|
||||
}
|
||||
|
||||
DetectedControllers DetectValveSteamMachineControllers()
|
||||
{
|
||||
DetectedControllers detected_controllers;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Detect Steam Machine (leds-valve) LED controller |
|
||||
\*-----------------------------------------------------*/
|
||||
if(detected_controllers.size() == 0)
|
||||
{
|
||||
std::vector<std::string> valve_led_paths;
|
||||
|
||||
DetectValveLEDs(valve_led_paths);
|
||||
|
||||
if(valve_led_paths.size() > 0)
|
||||
{
|
||||
ValveSteamMachineController* controller = new ValveSteamMachineController("Valve Steam Machine");
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < valve_led_paths.size(); led_idx++)
|
||||
{
|
||||
controller->AddLED(valve_led_paths[led_idx]);
|
||||
}
|
||||
|
||||
RGBController_ValveSteamMachine* rgb_controller = new RGBController_ValveSteamMachine(controller);
|
||||
|
||||
detected_controllers.push_back(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
return(detected_controllers);
|
||||
}
|
||||
|
||||
REGISTER_DETECTOR("Valve Steam Machine", DetectValveSteamMachineControllers);
|
||||
@@ -0,0 +1,227 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| ValveSteamMachineController_Linux.cpp |
|
||||
| |
|
||||
| Driver for Valve Steam Machine LEDs |
|
||||
| |
|
||||
| Adam Honse ([email protected]) 23 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "ValveSteamMachineController_Linux.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
ValveSteamMachineController::ValveSteamMachineController(std::string dev_name)
|
||||
{
|
||||
name = dev_name;
|
||||
}
|
||||
|
||||
ValveSteamMachineController::~ValveSteamMachineController()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string ValveSteamMachineController::GetName()
|
||||
{
|
||||
return(name);
|
||||
}
|
||||
|
||||
void ValveSteamMachineController::AddLED(std::string led_path)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Ensure the path ends with a slash |
|
||||
\*-----------------------------------------------------*/
|
||||
std::string path = led_path;
|
||||
|
||||
if(path.back() != '/')
|
||||
{
|
||||
path += '/';
|
||||
}
|
||||
|
||||
led_paths.push_back(path);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Open the brightness and multi_intensity files |
|
||||
\*-----------------------------------------------------*/
|
||||
std::ofstream brightness_file;
|
||||
brightness_file.open(path + "brightness");
|
||||
led_brightness.push_back(std::move(brightness_file));
|
||||
|
||||
std::ofstream multi_intensity_file;
|
||||
multi_intensity_file.open(path + "multi_intensity");
|
||||
led_multi_intensity.push_back(std::move(multi_intensity_file));
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Open the brightness_scale and delay files on the |
|
||||
| first LED only. Setting these on any one LED applies |
|
||||
| to the entire strip, so we only need to open it once. |
|
||||
\*-----------------------------------------------------*/
|
||||
if(led_paths.size() == 1)
|
||||
{
|
||||
led_brightness_scale.open(path + "brightness_scale");
|
||||
led_delay.open(path + "delay");
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Check if the effect_index file exists to determine |
|
||||
| if hardware effects are supported by this LED. The |
|
||||
| effect_index file contains a list of available effect |
|
||||
| names, while the effect file is used to set the |
|
||||
| active effect. |
|
||||
\*-----------------------------------------------------*/
|
||||
std::ifstream effect_index_test(path + "effect_index");
|
||||
|
||||
if(effect_index_test.good())
|
||||
{
|
||||
effect_index_test.close();
|
||||
|
||||
std::ofstream effect_file;
|
||||
effect_file.open(path + "effect");
|
||||
led_effect.push_back(std::move(effect_file));
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Read available effects from the first LED only |
|
||||
\*-------------------------------------------------*/
|
||||
if(led_paths.size() == 1)
|
||||
{
|
||||
ReadAvailableEffects(path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
effect_index_test.close();
|
||||
}
|
||||
}
|
||||
|
||||
size_t ValveSteamMachineController::GetLEDCount()
|
||||
{
|
||||
return(led_paths.size());
|
||||
}
|
||||
|
||||
std::string ValveSteamMachineController::GetLEDPath(unsigned int led_idx)
|
||||
{
|
||||
if(led_idx < led_paths.size())
|
||||
{
|
||||
return(led_paths[led_idx]);
|
||||
}
|
||||
|
||||
return("");
|
||||
}
|
||||
|
||||
std::vector<std::string> ValveSteamMachineController::GetAvailableEffects()
|
||||
{
|
||||
return(available_effects);
|
||||
}
|
||||
|
||||
void ValveSteamMachineController::ReadAvailableEffects(std::string first_led_path)
|
||||
{
|
||||
std::ifstream effect_index_file(first_led_path + "effect_index");
|
||||
|
||||
if(!effect_index_file.good())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| The effect_index file contains a list of available |
|
||||
| effect names separated by whitespace. The effect |
|
||||
| file itself gives the currently active effect when |
|
||||
| read, and is used to set the active effect when |
|
||||
| written. |
|
||||
\*-----------------------------------------------------*/
|
||||
std::string content;
|
||||
std::string line;
|
||||
|
||||
while(std::getline(effect_index_file, line))
|
||||
{
|
||||
content += line + " ";
|
||||
}
|
||||
|
||||
effect_index_file.close();
|
||||
|
||||
std::istringstream stream(content);
|
||||
std::string token;
|
||||
|
||||
while(stream >> token)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Add to list if not already present |
|
||||
\*-------------------------------------------------*/
|
||||
if(std::find(available_effects.begin(), available_effects.end(), token) == available_effects.end())
|
||||
{
|
||||
available_effects.push_back(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValveSteamMachineController::SetLEDColor(unsigned int led_idx, unsigned char red, unsigned char grn, unsigned char blu)
|
||||
{
|
||||
if(led_idx >= led_paths.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Use multi_intensity to set RGB values. This is the |
|
||||
| leds-valve sysfs LED interface pattern. |
|
||||
\*-----------------------------------------------------*/
|
||||
std::string color_str = std::to_string((unsigned int)red) + " "
|
||||
+ std::to_string((unsigned int)grn) + " "
|
||||
+ std::to_string((unsigned int)blu);
|
||||
|
||||
led_multi_intensity[led_idx].write(color_str.c_str(), color_str.length());
|
||||
led_multi_intensity[led_idx].flush();
|
||||
}
|
||||
|
||||
void ValveSteamMachineController::SetLEDEffect(unsigned int led_idx, std::string effect)
|
||||
{
|
||||
if(led_idx >= led_paths.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(led_effect.size() <= led_idx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
led_effect[led_idx].write(effect.c_str(), effect.length());
|
||||
led_effect[led_idx].flush();
|
||||
}
|
||||
|
||||
void ValveSteamMachineController::SetEffect(std::string effect)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Setting the effect on one LED applies it to all LEDs |
|
||||
| on the device, so we only need to set it on the first |
|
||||
| LED |
|
||||
\*-----------------------------------------------------*/
|
||||
if(led_effect.size() > 0)
|
||||
{
|
||||
led_effect[0].write(effect.c_str(), effect.length());
|
||||
led_effect[0].flush();
|
||||
}
|
||||
}
|
||||
|
||||
void ValveSteamMachineController::SetBrightness(unsigned int brightness)
|
||||
{
|
||||
if(led_brightness_scale.is_open())
|
||||
{
|
||||
std::string brightness_str = std::to_string(brightness);
|
||||
led_brightness_scale.write(brightness_str.c_str(), brightness_str.length());
|
||||
led_brightness_scale.flush();
|
||||
}
|
||||
}
|
||||
|
||||
void ValveSteamMachineController::SetDelay(unsigned int delay)
|
||||
{
|
||||
if(led_delay.is_open())
|
||||
{
|
||||
std::string delay_str = std::to_string(delay);
|
||||
led_delay.write(delay_str.c_str(), delay_str.length());
|
||||
led_delay.flush();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| ValveSteamMachineController_Linux.h |
|
||||
| |
|
||||
| Driver for Valve Steam Machine LEDs |
|
||||
| |
|
||||
| Adam Honse ([email protected]) 23 Jul 2026 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ValveSteamMachineController
|
||||
{
|
||||
public:
|
||||
ValveSteamMachineController(std::string dev_name);
|
||||
~ValveSteamMachineController();
|
||||
|
||||
std::string GetName();
|
||||
|
||||
void AddLED(std::string led_path);
|
||||
size_t GetLEDCount();
|
||||
|
||||
std::string GetLEDPath(unsigned int led_idx);
|
||||
|
||||
std::vector<std::string> GetAvailableEffects();
|
||||
bool SupportsEffects();
|
||||
|
||||
void SetLEDColor(unsigned int led_idx, unsigned char red, unsigned char grn, unsigned char blu);
|
||||
void SetLEDEffect(unsigned int led_idx, std::string effect);
|
||||
void SetEffect(std::string effect);
|
||||
void SetBrightness(unsigned int brightness);
|
||||
void SetDelay(unsigned int delay);
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
std::vector<std::string> led_paths;
|
||||
std::vector<std::ofstream> led_brightness;
|
||||
std::vector<std::ofstream> led_multi_intensity;
|
||||
std::vector<std::ofstream> led_effect;
|
||||
std::ofstream led_brightness_scale;
|
||||
std::ofstream led_delay;
|
||||
std::vector<std::string> available_effects;
|
||||
|
||||
void ReadAvailableEffects(std::string first_led_path);
|
||||
};
|
||||
Reference in New Issue
Block a user