AwesomeStudioPedal
A programmable, multi-profile foot controller for DAWs, score readers, and studio automation
Loading...
Searching...
No Matches
profile_manager.cpp
Go to the documentation of this file.
1#include "profile_manager.h"
2#include "config.h"
3#include "delayed_action.h"
4#include <vector>
5
6ProfileManager::ProfileManager(std::vector<ILEDController*> leds) : selectLeds(std::move(leds))
7{
8 updateLEDs();
9}
10
11void ProfileManager::addProfile(uint8_t profileIndex, std::unique_ptr<Profile> profile)
12{
13 if (profileIndex < MAX_PROFILES)
14 {
15 profileSlots[profileIndex] = std::move(profile);
16 }
17}
18
19Action* ProfileManager::getAction(uint8_t profileIndex, uint8_t button) const
20{
21 if (profileIndex < MAX_PROFILES && profileSlots[profileIndex])
22 {
23 return profileSlots[profileIndex]->getAction(button);
24 }
25 return nullptr;
26}
27
28const Profile* ProfileManager::getProfile(uint8_t profileIndex) const
29{
30 if (profileIndex < MAX_PROFILES && profileSlots[profileIndex])
31 {
32 return profileSlots[profileIndex].get();
33 }
34 return nullptr;
35}
36
38{
39 uint8_t numProfiles = hardwareConfig.numProfiles;
40 uint8_t next = currentProfile;
41 for (uint8_t i = 0; i < numProfiles; i++)
42 {
43 int temp = (next + 1) % numProfiles;
44 next = static_cast<uint8_t>(temp);
45 if (profileSlots[next])
46 {
47 break;
48 }
49 }
50 currentProfile = next;
51 postSwitchBlink = true;
52 blinkStarted = false;
53 blinkPhase = 0;
54 blinkStartTime = 0;
55
56 return currentProfile;
57}
58
67void ProfileManager::updateLEDs()
68{
69 if (postSwitchBlink)
70 {
71 return;
72 }
73
74 uint8_t numLeds = hardwareConfig.numSelectLeds;
75 uint8_t numProfiles = hardwareConfig.numProfiles;
76
77 if (numProfiles <= numLeds)
78 {
79 // One-hot: exactly one LED on for the current profile
80 for (uint8_t i = 0; i < numLeds && i < static_cast<uint8_t>(selectLeds.size()); i++)
81 {
82 selectLeds[i]->setState(i == currentProfile);
83 }
84 }
85 else
86 {
87 // Binary: encode 1-based profile number
88 auto bits = static_cast<uint8_t>(currentProfile + 1);
89 for (uint8_t i = 0; i < numLeds && i < static_cast<uint8_t>(selectLeds.size()); i++)
90 {
91 selectLeds[i]->setState((bits & (1U << i)) != 0);
92 }
93 }
94}
95
96void ProfileManager::update(uint32_t now)
97{
98 if (! postSwitchBlink)
99 {
100 return;
101 }
102
103 if (! blinkStarted)
104 {
105 blinkStarted = true;
106 blinkStartTime = now;
107 for (auto* led : selectLeds)
108 {
109 led->setState(true);
110 }
111 return;
112 }
113
114 uint32_t elapsed = now - blinkStartTime;
115 auto phase = static_cast<uint8_t>(elapsed / BLINK_INTERVAL);
116
117 if (phase == blinkPhase)
118 {
119 return;
120 }
121 blinkPhase = phase;
122
123 uint8_t totalHalfCycles = BLINK_COUNT * 2;
124 if (phase >= totalHalfCycles)
125 {
126 postSwitchBlink = false;
127 updateLEDs();
128 return;
129 }
130
131 bool on = (phase % 2 == 0);
132 for (auto* led : selectLeds)
133 {
134 led->setState(on);
135 }
136}
137
138void ProfileManager::setCurrentProfile(uint8_t profileIndex)
139{
140 if (profileIndex < MAX_PROFILES && profileSlots[profileIndex])
141 {
142 currentProfile = profileIndex;
143 updateLEDs();
144 }
145}
146
148{
149 currentProfile = 0;
150 uint8_t numProfiles = hardwareConfig.numProfiles;
151 for (uint8_t i = 0; i < numProfiles; i++)
152 {
153 if (profileSlots[i])
154 {
155 currentProfile = i;
156 break;
157 }
158 }
159 postSwitchBlink = false;
160 updateLEDs();
161}
162
163const std::string& ProfileManager::getProfileName(uint8_t profileIndex) const
164{
165 if (profileIndex < MAX_PROFILES && profileSlots[profileIndex])
166 {
167 return profileSlots[profileIndex]->getName();
168 }
169 static const std::string emptyString;
170 return emptyString;
171}
172
174{
175 for (const auto& slot : profileSlots)
176 {
177 if (! slot)
178 {
179 continue;
180 }
181 for (uint8_t b = 0; b < Profile::MAX_BUTTONS; b++)
182 {
183 const Action* action = slot->getAction(b);
184 if (action && action->isInProgress())
185 {
186 return true;
187 }
188 }
189 }
190 return false;
191}
192
194{
195 switch (actionType)
196 {
198 return "SendString";
200 return "SendChar";
202 return "SendKey";
204 return "SendMediaKey";
206 return "SerialOutput";
208 return "Delayed";
209 default:
210 return "Unknown";
211 }
212}
Base class for all pedal actions.
Definition action.h:12
virtual bool isInProgress() const
Returns true if the action is currently in progress (e.g.
Definition action.h:37
ProfileManager(std::vector< ILEDController * > leds)
bool hasActiveDelayedAction() const
Returns true if any DelayedAction across all profiles is currently running.
const std::string & getProfileName(uint8_t profileIndex) const
const Profile * getProfile(uint8_t profileIndex) const
static constexpr uint8_t MAX_PROFILES
2^6 − 1 (6 select LEDs max)
Action * getAction(uint8_t profileIndex, uint8_t button) const
static const char * getActionTypeString(Action::Type actionType)
void resetToFirstProfile()
Reset to the first populated slot (or slot 0 if all empty)
void setCurrentProfile(uint8_t profileIndex)
Directly set the current profile without triggering blink feedback.
void update(uint32_t now)
Drive timed LED behaviour — call every loop iteration.
uint8_t switchProfile()
Advance to the next populated profile slot and trigger blink feedback.
void addProfile(uint8_t profileIndex, std::unique_ptr< Profile > profile)
Represents a single button configuration profile.
Definition profile.h:15
static constexpr uint8_t MAX_BUTTONS
Maximum buttons per profile (A–Z)
Definition profile.h:17
const HardwareConfig hardwareConfig
Global hardware configuration instance.
std::vector< ILEDController * > selectLeds
Definition main.cpp:67
uint8_t numSelectLeds
Profile-select LEDs wired; caps profiles at 2^n − 1.
Definition config.h:20
uint8_t numProfiles
Number of active profiles (1..MAX_PROFILES)
Definition config.h:19