Main Page · Modules · All Classes · Class Hierarchy
MALedsController.cpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #include "MALedsController.hpp"
23 
24 #include "core/MADevice.hpp"
25 #include "core/MARandomness.hpp"
26 #include "core/MAValueGenerators.hpp"
27 #include "types/skits/MALedSkit.hpp"
28 #include "types/MARobotState.hpp"
29 #include "types/MATorso.hpp"
30 
31 #include <MCLog.hpp>
32 
33 #include <boost/algorithm/string/predicate.hpp>
34 
35 namespace MA
36 {
38 }
39 
40 namespace
41 {
42 // Current face mode (0 or 1)
43 MCThreadLocalData<int> FaceMode(true);
44 
45 void CheckStaticLedsVariables()
46 {
47  if (unlikely(!FaceMode.get()))
48  {
49  FaceMode.reset(new int);
50  *FaceMode = 0;
51  }
52 }
53 }
54 
55 MALedsController::MALedsController() : MAController(MA::LedController), LedModeForSkitter(-1),
56  ShownBatteryLevel(-1), MaximumValue(0.4, 0.05, 1.0)
57 {
58  CheckStaticLedsVariables();
59  if (MA::Leds.get())
60  {
61  MC_WARNING("The global leds controller is overridden.");
62  }
63  MA::Leds.reset(this);
64 
65  MA_BIND_TRANSITION_ACTION(MALedsController, ShowSleepingEyes)
66  MA_BIND_TRANSITION_ACTION(MALedsController, ShowAwakenEyes)
67  MA_BIND_TRANSITION_ACTION(MALedsController, ShowBatteryChargingAnim)
68  MA_BIND_TRANSITION_ACTION(MALedsController, ShowCrownStrokedAnim)
69  MA_BIND_TRANSITION_ACTION(MALedsController, ShowHappyAnim)
70  MA_BIND_TRANSITION_ACTION(MALedsController, ShowSadAnim)
71  MA_BIND_TRANSITION_ACTION(MALedsController, ShowBatteryLevel)
72  MA_BIND_TRANSITION_ACTION(MALedsController, ShowDataUploadStatus)
73  MA_BIND_TRANSITION_ACTION(MALedsController, ShowClientConnectedStatus)
74  MA_BIND_TRANSITION_ACTION(MALedsController, ShowNoNetworkStatus)
75  MA_BIND_TRANSITION_ACTION(MALedsController, ShowStartup)
76  MA_BIND_TRANSITION_ACTION(MALedsController, ShowAngryFace)
77  MA_BIND_TRANSITION_ACTION(MALedsController, HeavyCalculation);
78  MA_BIND_TRANSITION_ACTION(MALedsController, SwitchSoundProfile);
79  MA_BIND_TRANSITION_ACTION(MALedsController, NormalVolumeControl);
80  MA_BIND_TRANSITION_ACTION(MALedsController, AdaptiveVolumeControl);
81  MA_BIND_TRANSITION_ACTION(MALedsController, ShowPickUpMode);
82  MA_BIND_TRANSITION_ACTION(MALedsController, ShowGameMode);
83  MA_BIND_TRANSITION_ACTION(MALedsController, FadeOutEarsGreen);
84  MA_BIND_TRANSITION_ACTION(MALedsController, FadeOutEarsRed);
85  MA_BIND_TRANSITION_ACTION(MALedsController, FadeOutCrownWhite);
86 
87  // Specify the expression LED modes
88  TransitionLedModes[ShowBatteryChargingAnimStr] = 0;
89  TransitionLedModes[ShowHappyAnimStr] = 1;
90  TransitionLedModes[ShowSadAnimStr] = 1;
91  TransitionLedModes[ShowAngryFaceStr] = 0;
92 }
93 
94 
95 MALedsController::~MALedsController()
96 {
97  if (MA::Leds.get() == this)
98  MA::Leds.release();
99 }
100 
101 
103 {
104  // Nothing to do
105 }
106 
107 
108 MA::DeviceList MALedsController::GetMotors() const
109 {
110  // No motors for the controller
111  return MA::DeviceList();
112 }
113 
114 
115 int MALedsController::StartTransition(const std::string& name)
116 {
117  // The expression is already active
118  if (IsTransitionActive(name))
119  return 0;
120 
121  // Check and set new face LED mode if needed
122  auto LedModeIter = TransitionLedModes.find(name);
123 
124  if (LedModeIter != TransitionLedModes.end() && (int)LedModeIter->second != *FaceMode)
125  {
126  *FaceMode = (int)LedModeIter->second;
127  }
128  if (LedModeForSkitter >= 0)
129  *FaceMode = LedModeForSkitter;
130 
131  return MAController::StartTransition(name);
132 }
133 
134 
135 void MALedsController::StopTransition(const std::string& name)
136 {
137  auto TransitionIter = Transitions.find(name);
138 
139  if (TransitionIter == Transitions.end())
140  {
141  // Call to have warning message for the missing transition
143  return;
144  }
145  LedModeForSkitter = -1;
146  MA::DeviceGeneratorsMap& ContainerMap = TransitionIter->second.get<2>();
147 
149  for (auto& container : ContainerMap)
150  {
151  MADevice* Device = container.first;
152  MAGeneratorContainer* Container = container.second;
153 
154  // Make sure that the container exists
155  if (Device->HasGeneratorContainer(*Container))
156  {
157  Container->BlockExpiredSignal();
158  if (!Container->IsStarted())
159  {
160  // If the container has not been started yet, it can be removed...
161  Device->DeleteGeneratorContainer(*Container);
162  } else {
163  // ...otherwise swapping the generators inside with a fade out animation
164  MAGeneratorContainer* NewContainer = nullptr;
165 
166  NewContainer = new MAGeneratorContainer(*new MASimpleGenerator(MCFloatInfinity(), 0.0, 300));
167  Device->SwapGeneratorContainer(*Container, *NewContainer);
168  Container->CalculateCurrentValue(Device->GetRealSensorValue());
169  NewContainer->Start(Container->GetCurrentValue());
170  delete Container;
171  }
172  }
173  }
175 
176  if (name == ShowBatteryLevelStr)
177  {
178  ShownBatteryLevel = -1;
179  }
180 }
181 
182 
183 int MALedsController::GetFaceMode()
184 {
185  CheckStaticLedsVariables();
186  return *FaceMode;
187 }
188 
189 
190 void MALedsController::ResetSkitterFaceMode()
191 {
192  LedModeForSkitter = -1;
193 }
194 
195 
196 void MALedsController::SetMaximumValue(float new_value)
197 {
198  MANum<float> NewValue(new_value, MaximumValue.GetMin(), MaximumValue.GetMax());
199 
200  if (NewValue == MaximumValue)
201  return;
202 
203  MaximumValue = (float)NewValue;
204 
205  // Apply the new limit to the devices
206  for (int i = 0; i < 14; i++)
207  {
208  Face[i]->SetSoftLimit(MaximumValue);
209  }
210  BackFBlue->SetSoftLimit(MaximumValue);
211  BackMOrange->SetSoftLimit(MaximumValue);
212  BackRRed->SetSoftLimit(MaximumValue);
213  BackFWhite->SetSoftLimit(MaximumValue);
214  BackMWhite->SetSoftLimit(MaximumValue);
215  BackRWhite->SetSoftLimit(MaximumValue);
216 }
217 
218 
219 float MALedsController::GetMaximumValue() const
220 {
221  return (float)MaximumValue;
222 }
223 
224 
225 int MALedsController::GetShownBatteryLevel() const
226 {
227  return ShownBatteryLevel;
228 }
229 
230 
232 MA::DeviceGeneratorsMap MALedsController::ShowAwakenEyes()
233 {
234  MAGeneratorBase* Generator = nullptr;
235  MA::DeviceGeneratorsMap DeviceGenerators;
236 
237  Generator = new MASimpleGenerator(0.0, (float)MaximumValue, 2000);
238  AddGenerator(DeviceGenerators, *Face[8], *Face[8]->AddGenerator(*Generator), true);
239  Generator = new MASimpleGenerator(0.0, (float)MaximumValue, 2000);
240  AddGenerator(DeviceGenerators, *Face[9], *Face[9]->AddGenerator(*Generator), true);
241  return DeviceGenerators;
242 }
243 
244 
245 MA::DeviceGeneratorsMap MALedsController::ShowSleepingEyes()
246 {
247  MAGeneratorBase* Generator = nullptr;
248  MA::DeviceGeneratorsMap DeviceGenerators;
249 
250  Generator = new MAPeriodicGenerator(0.0, 0.2, 0, 3000, 0, 3000, 0, true);
251  AddGenerator(DeviceGenerators, *Face[8], *Face[8]->AddGenerator(*Generator), true);
252  Generator = new MAPeriodicGenerator(0.0, 0.2, 0, 3000, 0, 3000, 0, true);
253  AddGenerator(DeviceGenerators, *Face[9], *Face[9]->AddGenerator(*Generator), true);
254  return DeviceGenerators;
255 }
256 
257 
258 MA::DeviceGeneratorsMap MALedsController::ShowBatteryChargingAnim()
259 {
260  MAGeneratorBase* Generator = nullptr;
261  MA::DeviceGeneratorsMap DeviceGenerators;
262 
263  float MaxValue = MCMin((float)0.3, (float)MaximumValue);
264  int Speed = 1000;
265 
266  Generator = new MAPeriodicGenerator(0.0, MaxValue, 0, Speed, 4*Speed, Speed, 4*Speed, true);
267  AddGenerator(DeviceGenerators, *Face[2].get(), *Face[2]->AddGenerator(*Generator), true);
268  Generator = new MAPeriodicGenerator(0.0, MaxValue, Speed, Speed, 4*Speed, Speed, 3*Speed, true);
269  AddGenerator(DeviceGenerators, *Face[4].get(), *Face[4]->AddGenerator(*Generator), true);
270  Generator = new MAPeriodicGenerator(0.0, MaxValue, Speed*2, Speed, 4*Speed, Speed, 2*Speed, true);
271  AddGenerator(DeviceGenerators, *Face[11].get(), *Face[11]->AddGenerator(*Generator), true);
272  Generator = new MAPeriodicGenerator(0.0, MaxValue, Speed*3, Speed, 4*Speed, Speed, Speed, true);
273  AddGenerator(DeviceGenerators, *Face[5].get(), *Face[5]->AddGenerator(*Generator), true);
274  Generator = new MAPeriodicGenerator(0.0, MaxValue, Speed*4, Speed, 4*Speed, Speed, 0, true);
275  AddGenerator(DeviceGenerators, *Face[3].get(), *Face[3]->AddGenerator(*Generator), true);
276  return DeviceGenerators;
277 }
278 
279 
280 MA::DeviceGeneratorsMap MALedsController::ShowCrownStrokedAnim()
281 {
282  MAGeneratorBase* Generator = nullptr;
283  MAGeneratorContainer* Container = nullptr;
284  MA::DeviceGeneratorsMap DeviceGenerators;
285 
286  Generator = new MAPeriodicGenerator(0.0, 1.0, 200, 0, 200, 0, 0);
287  Container = HeadYellow->AddGenerator(*Generator);
288  Generator = new MAPeriodicGenerator(0.0, 1.0, 200, 0, 200, 0, 0); // -V760 (PVS Studio suppression)
289  Container->AddGenerator(*Generator);
290  Generator = new MAPeriodicGenerator(0.0, 1.0, 200, 0, 200, 0, 0);
291  Container->AddGenerator(*Generator);
292  AddGenerator(DeviceGenerators, *HeadYellow, *Container);
293  return DeviceGenerators;
294 }
295 
296 
297 MA::DeviceGeneratorsMap MALedsController::ShowHappyAnim()
298 {
299  MA::DeviceGeneratorsMap DeviceGenerators;
300  MAGeneratorBase* Generator = nullptr;
301  MA_RANDOM_POINT_1(HappyAnim, 1, 6);
302 
303  // Happy expression #1
304  if (HappyAnim == 1)
305  {
306  // Animation direction: <- ->
307  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
308  AddGenerator(DeviceGenerators, *Face[2].get(), *Face[2]->AddGenerator(*Generator));
309  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
310  AddGenerator(DeviceGenerators, *Face[3].get(), *Face[3]->AddGenerator(*Generator));
311  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 200, 200, 100, 300, 0);
312  AddGenerator(DeviceGenerators, *Face[0].get(), *Face[0]->AddGenerator(*Generator));
313  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 200, 200, 100, 300, 0);
314  AddGenerator(DeviceGenerators, *Face[1].get(), *Face[1]->AddGenerator(*Generator));
315  }
316  // Happy expression #2
317  if (HappyAnim == 2)
318  {
319  // Animation direction: -> <-
320  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
321  AddGenerator(DeviceGenerators, *Face[0].get(), *Face[0]->AddGenerator(*Generator));
322  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
323  AddGenerator(DeviceGenerators, *Face[1].get(), *Face[1]->AddGenerator(*Generator));
324  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 200, 200, 100, 300, 0);
325  AddGenerator(DeviceGenerators, *Face[2].get(), *Face[2]->AddGenerator(*Generator));
326  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 200, 200, 100, 300, 0);
327  AddGenerator(DeviceGenerators, *Face[3].get(), *Face[3]->AddGenerator(*Generator));
328  }
329  // Happy expression #3
330  if (HappyAnim == 3)
331  {
332  // Animation direction: ->
333  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 300, 300, 0);
334  AddGenerator(DeviceGenerators, *Face[0].get(), *Face[0]->AddGenerator(*Generator));
335  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 100, 100, 300, 300, 0);
336  AddGenerator(DeviceGenerators, *Face[2].get(), *Face[2]->AddGenerator(*Generator));
337  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 200, 100, 300, 300, 0);
338  AddGenerator(DeviceGenerators, *Face[3].get(), *Face[3]->AddGenerator(*Generator));
339  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 300, 100, 300, 300, 0);
340  AddGenerator(DeviceGenerators, *Face[1].get(), *Face[1]->AddGenerator(*Generator));
341  }
342  // Happy expression #4
343  if (HappyAnim == 4)
344  {
345  // Animation direction: <-
346  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 300, 300, 0);
347  AddGenerator(DeviceGenerators, *Face[1].get(), *Face[1]->AddGenerator(*Generator));
348  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 100, 100, 300, 300, 0);
349  AddGenerator(DeviceGenerators, *Face[3].get(), *Face[3]->AddGenerator(*Generator));
350  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 200, 100, 300, 300, 0);
351  AddGenerator(DeviceGenerators, *Face[2].get(), *Face[2]->AddGenerator(*Generator));
352  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 300, 100, 300, 300, 0);
353  AddGenerator(DeviceGenerators, *Face[0].get(), *Face[0]->AddGenerator(*Generator));
354  }
355  // Happy expression #5
356  if (HappyAnim == 5)
357  {
358  // Increasing together, but decreasing separately
359  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 300, 300, 0);
360  AddGenerator(DeviceGenerators, *Face[0].get(), *Face[0]->AddGenerator(*Generator));
361  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 400, 300, 0);
362  AddGenerator(DeviceGenerators, *Face[2].get(), *Face[2]->AddGenerator(*Generator));
363  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 400, 300, 0);
364  AddGenerator(DeviceGenerators, *Face[3].get(), *Face[3]->AddGenerator(*Generator));
365  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 300, 300, 0);
366  AddGenerator(DeviceGenerators, *Face[1].get(), *Face[1]->AddGenerator(*Generator));
367  }
368  // Happy expression #6
369  if (HappyAnim == 6)
370  {
371  // Increasing together, but decreasing separately
372  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 400, 300, 0);
373  AddGenerator(DeviceGenerators, *Face[0].get(), *Face[0]->AddGenerator(*Generator));
374  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 300, 300, 0);
375  AddGenerator(DeviceGenerators, *Face[2].get(), *Face[2]->AddGenerator(*Generator));
376  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 300, 300, 0);
377  AddGenerator(DeviceGenerators, *Face[3].get(), *Face[3]->AddGenerator(*Generator));
378  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 400, 300, 0);
379  AddGenerator(DeviceGenerators, *Face[1].get(), *Face[1]->AddGenerator(*Generator));
380  }
381  return DeviceGenerators;
382 }
383 
384 
385 MA::DeviceGeneratorsMap MALedsController::ShowSadAnim()
386 {
387  MA::DeviceGeneratorsMap DeviceGenerators;
388  MAGeneratorBase* Generator = nullptr;
389  MA_RANDOM_POINT_1(SadAnim, 1, 4);
390 
391  // Sad expression #1
392  if (SadAnim == 1)
393  {
394  // Animation direction: <- ->
395  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
396  AddGenerator(DeviceGenerators, *Face[12].get(), *Face[12]->AddGenerator(*Generator));
397  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 200, 200, 100, 300, 0);
398  AddGenerator(DeviceGenerators, *Face[13].get(), *Face[13]->AddGenerator(*Generator));
399  }
400  // Sad expression #2
401  if (SadAnim == 2)
402  {
403  // Animation direction: -> <-
404  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
405  AddGenerator(DeviceGenerators, *Face[13].get(), *Face[13]->AddGenerator(*Generator));
406  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 200, 200, 100, 300, 0);
407  AddGenerator(DeviceGenerators, *Face[12].get(), *Face[12]->AddGenerator(*Generator));
408  }
409  // Sad expression #3
410  if (SadAnim == 3)
411  {
412  // Increasing together, but decreasing separately
413  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 300, 300, 0);
414  AddGenerator(DeviceGenerators, *Face[12].get(), *Face[12]->AddGenerator(*Generator));
415  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 400, 300, 0);
416  AddGenerator(DeviceGenerators, *Face[13].get(), *Face[13]->AddGenerator(*Generator));
417  }
418  // Sad expression #4
419  if (SadAnim == 4)
420  {
421  // Increasing together, but decreasing separately
422  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 400, 300, 0);
423  AddGenerator(DeviceGenerators, *Face[12].get(), *Face[12]->AddGenerator(*Generator));
424  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 100, 300, 300, 0);
425  AddGenerator(DeviceGenerators, *Face[13].get(), *Face[13]->AddGenerator(*Generator));
426  }
427  return DeviceGenerators;
428 }
429 
430 
431 MA::DeviceGeneratorsMap MALedsController::ShowBatteryLevel()
432 {
433  if (ShownBatteryLevel == (int)MA::RobotState->Torso->BatteryLevel)
434  {
435  return MA::DeviceGeneratorsMap();
436  }
437  MA::DeviceGeneratorsMap DeviceGenerators;
438  MA::DeviceList DevicesToClear;
439  MAGeneratorBase* Generator = nullptr;
440 
441  ShownBatteryLevel = (int)MA::RobotState->Torso->BatteryLevel;
442 
443  // The intensity of the first LED (MaxValue -> 0.0) follows the battery level
444  // 100 % -> 66 %
445  if (ShownBatteryLevel >= 66)
446  {
447  Generator = new MASimpleGenerator(BackFBlue->GetSensorValue(),
448  ((float)ShownBatteryLevel-66.0) / 34.0*(float)MaximumValue, 2000);
449  AddGenerator(DeviceGenerators, *BackFBlue.get(), *BackFBlue->AddGenerator(*Generator), true);
450  if (ShownBatteryLevel > 82)
451  {
452  DevicesToClear.push_back(BackMOrange.get());
453  }
454  DevicesToClear.push_back(BackRRed.get());
455  }
456 
457  // The intensity of the second LED (0.0 <- MaxValue / 2 -> 0.0) follows the battery level
458  // 82 % <- 50 % -> 18 %
459  if (ShownBatteryLevel >= 18 && ShownBatteryLevel <= 82)
460  {
461  float Level = (int)ShownBatteryLevel >= 50 ? 82-ShownBatteryLevel : (int)ShownBatteryLevel-18;
462 
463  Generator = new MASimpleGenerator(BackMOrange->GetSensorValue(),
464  Level / 32.0*(float)MaximumValue, 2000);
465  AddGenerator(DeviceGenerators, *BackMOrange.get(), *BackMOrange->AddGenerator(*Generator), true);
466  if (ShownBatteryLevel < 66)
467  {
468  DevicesToClear.push_back(BackFBlue.get());
469  }
470  if (ShownBatteryLevel > 32 && ShownBatteryLevel < 66)
471  {
472  DevicesToClear.push_back(BackRRed.get());
473  }
474  }
475 
476  // The intensity of the third LED (0.0 -> ~?) follows the battery level
477  // 32 % -> 10 %
478  if (ShownBatteryLevel >= 10 && ShownBatteryLevel <= 32)
479  {
480  // Remove old value generators by force
481  Generator = new MASimpleGenerator(BackRRed->GetSensorValue(),
482  (float)(32.0-ShownBatteryLevel) / 32.0*(float)MaximumValue, 2000);
483  AddGenerator(DeviceGenerators, *BackRRed.get(), *BackRRed->AddGenerator(*Generator), true);
484  if (ShownBatteryLevel < 18)
485  {
486  DevicesToClear.push_back(BackMOrange.get());
487  DevicesToClear.push_back(BackFBlue.get());
488  }
489  } else
490  // Start the low battery animation
491  if (ShownBatteryLevel < 10)
492  {
493  // Setup the periodic animation with start value
494  float MaxValue = 22.0 / 32.0*(float)MaximumValue;
495 
496  Generator = new MAPeriodicGenerator(0.0, MaxValue, 0, 3000, 0, 3000, 0, true);
497  Generator->Start(BackRRed->GetSensorValue());
498  AddGenerator(DeviceGenerators, *BackRRed.get(), *BackRRed->AddGenerator(*Generator), true);
499  DevicesToClear.push_back(BackMOrange.get());
500  DevicesToClear.push_back(BackFBlue.get());
501  }
502 
503  // Clear the device values if needed
504  for (auto& device : DevicesToClear)
505  {
506  if (device->GetNextValue() > 0.0)
507  {
508  Generator = new MASimpleGenerator(device->GetSensorValue(), 0.0, 2000);
509  device->AddGenerator(*Generator);
510  }
511  }
512  return DeviceGenerators;
513 }
514 
515 
516 MA::DeviceGeneratorsMap MALedsController::ShowDataUploadStatus()
517 {
518  MA::DeviceGeneratorsMap DeviceGenerators;
519  MAGeneratorBase* Generator = nullptr;
520 
521  Generator = new MAPeriodicGenerator(0, 1, 100, 0, 800, 0, 100, false);
522  AddGenerator(DeviceGenerators, *HeadWifi.get(), *HeadWifi->AddGenerator(*Generator));
523  return DeviceGenerators;
524 }
525 
526 
527 MA::DeviceGeneratorsMap MALedsController::ShowClientConnectedStatus()
528 {
529  MA::DeviceGeneratorsMap DeviceGenerators;
530  MAGeneratorBase* Generator = nullptr;
531 
532  Generator = new MAPeriodicGenerator(0, 1, 100, 0, 1000, 0, 100, false);
533  AddGenerator(DeviceGenerators, *EarsBlue.get(), *EarsBlue->AddGenerator(*Generator));
534  return DeviceGenerators;
535 }
536 
537 
538 MA::DeviceGeneratorsMap MALedsController::ShowNoNetworkStatus()
539 {
540  MA::DeviceGeneratorsMap DeviceGenerators;
541  MAGeneratorBase* Generator = nullptr;
542  MAGeneratorContainer* Container = nullptr;
543 
544  Generator = new MAPeriodicGenerator(0, 1.0, 300, 0, 200, 0, 300);
545  Container = new MAGeneratorContainer(*Generator);
546  Generator = new MAPeriodicGenerator(0, 1.0, 100, 0, 200, 0, 300);
547  Container->AddGenerator(*Generator);
548  EarsBlue->AddGeneratorContainer(*Container);
549  AddGenerator(DeviceGenerators, *EarsBlue.get(), *Container);
550  return DeviceGenerators;
551 }
552 
553 
554 MA::DeviceGeneratorsMap MALedsController::ShowStartup()
555 {
556  MA::DeviceGeneratorsMap DeviceGenerators;
557  MAGeneratorBase* Generator = nullptr;
558 
559  Generator = new MAPeriodicGenerator(0.0, 0.6, 0, 3000, 9000, 3000, 0);
560  AddGenerator(DeviceGenerators, *BackFWhite.get(), *BackFWhite->AddGenerator(*Generator));
561  Generator = new MAPeriodicGenerator(0.0, 0.6, 3000, 3000, 6000, 3000, 0);
562  AddGenerator(DeviceGenerators, *BackMWhite.get(), *BackMWhite->AddGenerator(*Generator));
563  Generator = new MAPeriodicGenerator(0.0, 0.6, 6000, 3000, 3000, 3000, 0);
564  AddGenerator(DeviceGenerators, *BackRWhite.get(), *BackRWhite->AddGenerator(*Generator));
565  return DeviceGenerators;
566 }
567 
568 
569 MA::DeviceGeneratorsMap MALedsController::ShowAngryFace()
570 {
571  MAGeneratorBase* Generator = nullptr;
572  MA::DeviceGeneratorsMap DeviceGenerators;
573 
574  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
575  AddGenerator(DeviceGenerators, *Face[2].get(), *Face[2]->AddGenerator(*Generator));
576  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
577  AddGenerator(DeviceGenerators, *Face[3].get(), *Face[3]->AddGenerator(*Generator));
578  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
579  AddGenerator(DeviceGenerators, *Face[4].get(), *Face[4]->AddGenerator(*Generator));
580  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
581  AddGenerator(DeviceGenerators, *Face[5].get(), *Face[5]->AddGenerator(*Generator));
582  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
583  AddGenerator(DeviceGenerators, *Face[12].get(), *Face[12]->AddGenerator(*Generator));
584  Generator = new MAPeriodicGenerator(0.0, MaximumValue, 0, 200, 300, 300, 0);
585  AddGenerator(DeviceGenerators, *Face[13].get(), *Face[13]->AddGenerator(*Generator));
586  return DeviceGenerators;
587 }
588 
589 
590 MA::DeviceGeneratorsMap MALedsController::HeavyCalculation()
591 {
592  MA::DeviceGeneratorsMap DeviceGenerators;
593  MAGeneratorContainer* Container = nullptr;
594 
595  Container = new MAGeneratorContainer(*new MASimpleGenerator(HeadWhite->GetNextValue(), 1.0, 10));
596  Container->AddGenerator(*new MADelayGenerator(300));
597  Container->AddGenerator(*new MASimpleGenerator(MCFloatInfinity(), 0.0, 10));
598  HeadWhite->AddGeneratorContainer(*Container);
599  AddGenerator(DeviceGenerators, *HeadWhite.get(), *Container);
600  return DeviceGenerators;
601 }
602 
603 
604 MA::DeviceGeneratorsMap MALedsController::SwitchSoundProfile()
605 {
606  MA::DeviceGeneratorsMap DeviceGenerators;
607  MAGeneratorBase* Generator = nullptr;
608  MAGeneratorContainer* Container = nullptr;
609 
610  Generator = new MASimpleGenerator(BackFWhite->GetNextValue(), 0, 100);
611  Container = new MAGeneratorContainer(*Generator);
612  Generator = new MAPeriodicGenerator(0, MaximumValue, 100, 0, 800, 0, 100, false);
613  Container->AddGenerator(*Generator);
614  BackFWhite->AddGeneratorContainer(*Container);
615  AddGenerator(DeviceGenerators, *BackFWhite.get(), *Container);
616  return DeviceGenerators;
617 }
618 
619 
620 MA::DeviceGeneratorsMap MALedsController::NormalVolumeControl()
621 {
622  MA::DeviceGeneratorsMap DeviceGenerators;
623  MAGeneratorBase* Generator = nullptr;
624  MAGeneratorContainer* Container = nullptr;
625 
626  Generator = new MASimpleGenerator(BackRWhite->GetNextValue(), 0, 100);
627  Container = new MAGeneratorContainer(*Generator);
628  Generator = new MAPeriodicGenerator(0, MaximumValue, 100, 0, 800, 0, 100, false);
629  Container->AddGenerator(*Generator);
630  BackRWhite->AddGeneratorContainer(*Container);
631  AddGenerator(DeviceGenerators, *BackRWhite.get(), *Container);
632  return DeviceGenerators;
633 }
634 
635 
636 MA::DeviceGeneratorsMap MALedsController::AdaptiveVolumeControl()
637 {
638  MA::DeviceGeneratorsMap DeviceGenerators;
639  MAGeneratorBase* Generator = nullptr;
640  MAGeneratorContainer* Container = nullptr;
641 
642  Generator = new MASimpleGenerator(BackRWhite->GetNextValue(), 0, 100);
643  Container = new MAGeneratorContainer(*Generator);
644  Generator = new MAPeriodicGenerator(0, MaximumValue, 100, 0, 800, 0, 100, false); // -V760 (PVS Studio suppression)
645  Container->AddGenerator(*Generator);
646  Generator = new MAPeriodicGenerator(0, MaximumValue, 100, 0, 800, 0, 100, false);
647  Container->AddGenerator(*Generator);
648  BackRWhite->AddGeneratorContainer(*Container);
649  AddGenerator(DeviceGenerators, *BackRWhite.get(), *Container);
650  return DeviceGenerators;
651 }
652 
653 
654 MA::DeviceGeneratorsMap MALedsController::ShowPickUpMode()
655 {
656  MA::DeviceGeneratorsMap DeviceGenerators;
657  MAGeneratorBase* Generator = nullptr;
658  MAGeneratorContainer* Container = nullptr;
659 
660  // Suppress the other ear LEDs
661  Generator = new MAPeriodicGenerator(0, -1, 0, 0, 3600000, 0, 0, false);
662  AddGenerator(DeviceGenerators, *EarsBlue.get(), *EarsBlue->AddGenerator(*Generator), false);
663  Generator = new MAPeriodicGenerator(0, -1, 0, 0, 3600000, 0, 0, false);
664  AddGenerator(DeviceGenerators, *EarsRed.get(), *EarsRed->AddGenerator(*Generator), false);
665  // Generators for pick-up mode
666  Generator = new MASimpleGenerator(EarsGreen->GetNextValue(), 0, 200);
667  Container = new MAGeneratorContainer(*Generator);
668  Generator = new MAPeriodicGenerator(0, 1, 300, 0, 800, 0, 300, true);
669  Container->AddGenerator(*Generator);
670  EarsGreen->AddGeneratorContainer(*Container);
671  AddGenerator(DeviceGenerators, *EarsGreen.get(), *Container, true);
672  return DeviceGenerators;
673 }
674 
675 
676 MA::DeviceGeneratorsMap MALedsController::ShowGameMode()
677 {
678  MA::DeviceGeneratorsMap DeviceGenerators;
679  MAGeneratorBase* Generator = nullptr;
680  MAGeneratorContainer* Container = nullptr;
681 
682  // Suppress the other ear LEDs
683  Generator = new MAPeriodicGenerator(0, -1, 0, 0, 3600000, 0, 0, false);
684  AddGenerator(DeviceGenerators, *EarsBlue.get(), *EarsBlue->AddGenerator(*Generator), false);
685  Generator = new MAPeriodicGenerator(0, -1, 0, 0, 3600000, 0, 0, false);
686  AddGenerator(DeviceGenerators, *EarsGreen.get(), *EarsGreen->AddGenerator(*Generator), false);
687  // Generators for game mode
688  Container = new MAGeneratorContainer(*new MASimpleGenerator(EarsRed->GetNextValue(), 0, 200));
689  Container->AddGenerator(*new MASimpleGenerator(1, 1, 1000));
690  EarsRed->AddGeneratorContainer(*Container);
691  AddGenerator(DeviceGenerators, *EarsRed.get(), *Container, false);
692  return DeviceGenerators;
693 }
694 
695 
696 MA::DeviceGeneratorsMap MALedsController::FadeOutEarsGreen()
697 {
698  MA::DeviceGeneratorsMap DeviceGenerators;
699  MAGeneratorContainer* Container = nullptr;
700 
701  Container = new MAGeneratorContainer(*new MASimpleGenerator(0, 0, 600));
702  EarsGreen->AddGeneratorContainer(*Container);
703  AddGenerator(DeviceGenerators, *EarsGreen.get(), *Container);
704  return DeviceGenerators;
705 }
706 
707 
708 MA::DeviceGeneratorsMap MALedsController::FadeOutEarsRed()
709 {
710  MA::DeviceGeneratorsMap DeviceGenerators;
711  MAGeneratorContainer* Container = nullptr;
712 
713  Container = new MAGeneratorContainer(*new MASimpleGenerator(0, 0, 600));
714  EarsRed->AddGeneratorContainer(*Container);
715  AddGenerator(DeviceGenerators, *EarsRed.get(), *Container);
716  return DeviceGenerators;
717 }
718 
719 
720 MA::DeviceGeneratorsMap MALedsController::FadeOutCrownWhite()
721 {
722  MA::DeviceGeneratorsMap DeviceGenerators;
723  MAGeneratorBase* Generator = nullptr;
724  MAGeneratorContainer* Container = nullptr;
725 
726  Generator = new MASimpleGenerator(0, 0, 600);
727  Container = new MAGeneratorContainer(*Generator);
728  HeadWhite->AddGeneratorContainer(*Container);
729  AddGenerator(DeviceGenerators, *HeadWhite.get(), *Container);
730  return DeviceGenerators;
731 }
733 
734 
735 void MALedsController::AddGenerator(MA::DeviceGeneratorsMap& device_generators, MADevice& device,
736  MAGeneratorContainer& container, bool permanent)
737 {
738  if (!permanent && container.GetDuration() < 0)
739  {
740  MC_WARNING("The generator container can not be infinite for a temporary transition!");
741  return;
742  }
743  if (!permanent && container.GetStartingValue() != 0.0)
744  {
745  MC_WARNING("The generator container must start with zero for a temporary transition!");
746  return;
747  }
748  if (!device.HasGeneratorContainer(container))
749  {
750  MC_WARNING("The device does not have this container!");
751  return;
752  }
753  // Note: Permanent expressions can end up in non-zero target values
754  if (boost::starts_with(device.GetDisplayName(), "Face") && !permanent && container.GetTargetValue() != 0.0)
755  {
756  MC_WARNING("The generator container does not decrease back to zero!");
757  return;
758  }
759  if (!container.IsAbsolute())
760  {
761  MC_WARNING("The generator container has uncertain start or target value!");
762  return;
763  }
764  // Add an infinite delay to the end of the container of a permanent expression if needed
765  if (permanent && container.GetDuration() >= 0)
766  {
767  container.MakePermanent();
768  }
769  // Find and remove the colliding expressions
770  if (permanent)
771  {
772  MC::StringList DeviceTransitions = GetActiveTransitionsByDevice(device);
773 
774  for (auto& transition : DeviceTransitions)
775  {
776  StopTransition(transition);
777  }
778  }
779  // Insert the new generator container
780  device_generators.insert(MA::DeviceGeneratorPair(&device, &container));
781 }
782 
783 
784 void MALedsController::ClearFace()
785 {
786  if (IsAnyActiveTransition())
787  {
788  MC_WARNING("The face LEDs can not be cleared when any expression is active.");
789  MC_WARNING("The intention of the function is to clear the LEDs on start-up.");
790  return;
791  }
792  // oled3_MODE_A -> 0 and we want to be a bit portable/testable at this level on x86/x64
793  *FaceMode = 0;
794  for (int i = 0; i < 14; i++)
795  Face[i]->SetNextValue(0.0);
797  MC_LOG("Clear face");
798 }
799 
800 
801 MA::DeviceGeneratorsMap MALedsController::GetSkitTransitionGenerators(MA::SkitBaseSPtr skit)
802 {
803  MALedSkit* LedSkit = dynamic_cast<MALedSkit*>(skit.get());
804 
805  if (!LedSkit)
806  return MA::DeviceGeneratorsMap();
807 
808  MA::DeviceGeneratorsMap DeviceGenerators;
809  MAGeneratorContainer* Container = nullptr;
810 
811  Container = LedSkit->GetGeneratorContainer(MA::BackFBlue);
812  if (Container)
813  {
814  BackFBlue->ClearGenerators();
815  BackFBlue->AddGeneratorContainer(*Container);
816  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, BackFBlue.get(), Container);
817  }
818  Container = LedSkit->GetGeneratorContainer(MA::BackFWhite);
819  if (Container)
820  {
821  BackFWhite->ClearGenerators();
822  BackFWhite->AddGeneratorContainer(*Container);
823  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, BackFWhite.get(), Container);
824  }
825  Container = LedSkit->GetGeneratorContainer(MA::BackMOrange);
826  if (Container)
827  {
828  BackMOrange->ClearGenerators();
829  BackMOrange->AddGeneratorContainer(*Container);
830  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, BackMOrange.get(), Container);
831  }
832  Container = LedSkit->GetGeneratorContainer(MA::BackMWhite);
833  if (Container)
834  {
835  BackMWhite->ClearGenerators();
836  BackMWhite->AddGeneratorContainer(*Container);
837  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, BackMWhite.get(), Container);
838  }
839  Container = LedSkit->GetGeneratorContainer(MA::BackRRed);
840  if (Container)
841  {
842  BackRRed->ClearGenerators();
843  BackRRed->AddGeneratorContainer(*Container);
844  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, BackRRed.get(), Container);
845  }
846  Container = LedSkit->GetGeneratorContainer(MA::BackRWhite);
847  if (Container)
848  {
849  BackRWhite->ClearGenerators();
850  BackRWhite->AddGeneratorContainer(*Container);
851  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, BackRWhite.get(), Container);
852  }
853  Container = LedSkit->GetGeneratorContainer(MA::HeadWiFi);
854  if (Container)
855  {
856  HeadWifi->ClearGenerators();
857  HeadWifi->AddGeneratorContainer(*Container);
858  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, HeadWifi.get(), Container);
859  }
860  Container = LedSkit->GetGeneratorContainer(MA::HeadYellow);
861  if (Container)
862  {
863  HeadYellow->ClearGenerators();
864  HeadYellow->AddGeneratorContainer(*Container);
865  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, HeadYellow.get(), Container);
866  }
867  Container = LedSkit->GetGeneratorContainer(MA::HeadWhite);
868  if (Container)
869  {
870  HeadWhite->ClearGenerators();
871  HeadWhite->AddGeneratorContainer(*Container);
872  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, HeadWhite.get(), Container);
873  }
874  Container = LedSkit->GetGeneratorContainer(MA::EarsRed);
875  if (Container)
876  {
877  EarsRed->ClearGenerators();
878  EarsRed->AddGeneratorContainer(*Container);
879  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, EarsRed.get(), Container);
880  }
881  Container = LedSkit->GetGeneratorContainer(MA::EarsGreen);
882  if (Container)
883  {
884  EarsGreen->ClearGenerators();
885  EarsGreen->AddGeneratorContainer(*Container);
886  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, EarsGreen.get(), Container);
887  }
888  Container = LedSkit->GetGeneratorContainer(MA::EarsBlue);
889  if (Container)
890  {
891  EarsBlue->ClearGenerators();
892  EarsBlue->AddGeneratorContainer(*Container);
893  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, EarsBlue.get(), Container);
894  }
895  // Face LEDs
896  bool LockMode0 = false;
897  bool LockMode1 = false;
898 
899  Container = LedSkit->GetGeneratorContainer(MA::Face1White);
900  if (Container && !LockMode1) // -V560 (PVS Studio suppression)
901  {
902  Face[0]->ClearGenerators();
903  Face[0]->AddGeneratorContainer(*Container);
904  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[0].get(), Container);
905  LockMode0 = true;
906  }
907  Container = LedSkit->GetGeneratorContainer(MA::Face1Color);
908  if (Container && !LockMode0)
909  {
910  Face[0]->ClearGenerators();
911  Face[0]->AddGeneratorContainer(*Container);
912  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[0].get(), Container);
913  LockMode1 = true;
914  }
915  Container = LedSkit->GetGeneratorContainer(MA::Face2White);
916  if (Container && !LockMode1)
917  {
918  Face[1]->ClearGenerators();
919  Face[1]->AddGeneratorContainer(*Container);
920  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[1].get(), Container);
921  LockMode0 = true;
922  }
923  Container = LedSkit->GetGeneratorContainer(MA::Face2Color);
924  if (Container && !LockMode0)
925  {
926  Face[1]->ClearGenerators();
927  Face[1]->AddGeneratorContainer(*Container);
928  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[1].get(), Container);
929  LockMode1 = true;
930  }
931  Container = LedSkit->GetGeneratorContainer(MA::Face3White);
932  if (Container && !LockMode1)
933  {
934  Face[2]->ClearGenerators();
935  Face[2]->AddGeneratorContainer(*Container);
936  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[2].get(), Container);
937  LockMode0 = true;
938  }
939  Container = LedSkit->GetGeneratorContainer(MA::Face3Color);
940  if (Container && !LockMode0)
941  {
942  Face[2]->ClearGenerators();
943  Face[2]->AddGeneratorContainer(*Container);
944  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[2].get(), Container);
945  LockMode1 = true;
946  }
947  Container = LedSkit->GetGeneratorContainer(MA::Face4White);
948  if (Container && !LockMode1)
949  {
950  Face[3]->ClearGenerators();
951  Face[3]->AddGeneratorContainer(*Container);
952  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[3].get(), Container);
953  LockMode0 = true;
954  }
955  Container = LedSkit->GetGeneratorContainer(MA::Face4Color);
956  if (Container && !LockMode0)
957  {
958  Face[3]->ClearGenerators();
959  Face[3]->AddGeneratorContainer(*Container);
960  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[3].get(), Container);
961  LockMode1 = true;
962  }
963  Container = LedSkit->GetGeneratorContainer(MA::Face5White);
964  if (Container)
965  {
966  Face[4]->ClearGenerators();
967  Face[4]->AddGeneratorContainer(*Container);
968  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[4].get(), Container);
969  }
970  Container = LedSkit->GetGeneratorContainer(MA::Face6White);
971  if (Container)
972  {
973  Face[5]->ClearGenerators();
974  Face[5]->AddGeneratorContainer(*Container);
975  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[5].get(), Container);
976  }
977  Container = LedSkit->GetGeneratorContainer(MA::Face7White);
978  if (Container)
979  {
980  Face[6]->ClearGenerators();
981  Face[6]->AddGeneratorContainer(*Container);
982  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[6].get(), Container);
983  }
984  Container = LedSkit->GetGeneratorContainer(MA::Face8White);
985  if (Container)
986  {
987  Face[7]->ClearGenerators();
988  Face[7]->AddGeneratorContainer(*Container);
989  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[7].get(), Container);
990  }
991  Container = LedSkit->GetGeneratorContainer(MA::Face9White);
992  if (Container)
993  {
994  Face[8]->ClearGenerators();
995  Face[8]->AddGeneratorContainer(*Container);
996  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[8].get(), Container);
997  }
998  Container = LedSkit->GetGeneratorContainer(MA::Face10White);
999  if (Container)
1000  {
1001  Face[9]->ClearGenerators();
1002  Face[9]->AddGeneratorContainer(*Container);
1003  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[9].get(), Container);
1004  }
1005  Container = LedSkit->GetGeneratorContainer(MA::Face11White);
1006  if (Container)
1007  {
1008  Face[10]->ClearGenerators();
1009  Face[10]->AddGeneratorContainer(*Container);
1010  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[10].get(), Container);
1011  }
1012  Container = LedSkit->GetGeneratorContainer(MA::Face12White);
1013  if (Container)
1014  {
1015  Face[11]->ClearGenerators();
1016  Face[11]->AddGeneratorContainer(*Container);
1017  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[11].get(), Container);
1018  }
1019  Container = LedSkit->GetGeneratorContainer(MA::Face13Color0);
1020  if (Container && !LockMode1)
1021  {
1022  Face[12]->ClearGenerators();
1023  Face[12]->AddGeneratorContainer(*Container);
1024  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[12].get(), Container);
1025  LockMode0 = true;
1026  }
1027  Container = LedSkit->GetGeneratorContainer(MA::Face13Color1);
1028  if (Container && !LockMode0)
1029  {
1030  Face[12]->ClearGenerators();
1031  Face[12]->AddGeneratorContainer(*Container);
1032  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[12].get(), Container);
1033  LockMode1 = true;
1034  }
1035  Container = LedSkit->GetGeneratorContainer(MA::Face14Color0);
1036  if (Container && !LockMode1)
1037  {
1038  Face[13]->ClearGenerators();
1039  Face[13]->AddGeneratorContainer(*Container);
1040  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[13].get(), Container);
1041  LockMode0 = true;
1042  }
1043  Container = LedSkit->GetGeneratorContainer(MA::Face14Color1);
1044  if (Container && !LockMode0)
1045  {
1046  Face[13]->ClearGenerators();
1047  Face[13]->AddGeneratorContainer(*Container);
1048  MA_INSERT_DEVICEGENERATOR(DeviceGenerators, Face[13].get(), Container);
1049  }
1050  LedModeForSkitter = -1;
1051 
1052  if (LockMode0)
1053  LedModeForSkitter = 0;
1054  if (LockMode1)
1055  LedModeForSkitter = 1;
1056 
1057  return DeviceGenerators;
1058 }
Delay generator class.
bool IsAbsolute() const
Check if the container is absolute.
virtual void StopTransition(const std::string &name) override
Stop a transition.
#define MA_RANDOM_POINT_1(_variable_name, _min, _max)
Set a random point with one value.
void AddGenerator(MAGeneratorBase &generator, bool in_front=false)
Add a new generator after the last internal generator.
virtual MA::DeviceGeneratorsMap GetSkitTransitionGenerators(MA::SkitBaseSPtr skit) override
Get skit transition generators.
const T MCMin(const U &container)
Get the minimal value of a container.
float GetTargetValue() const
Get the final target value of the container.
int GetDuration() const
Get the container duration.
virtual int StartTransition(const std::string &name) override
Start a transition.
void CalculateCurrentValue(float device_value)
Calculate the current value based on a device value.
LED sequence (LED skit) class.
Definition: MALedSkit.hpp:87
void MakePermanent()
Make the generator container infinite long (permanent)
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
Base class for the controllers.
Device class.
Definition: MADevice.hpp:57
static bool IsVerbose()
Get the verbosity of the controller domain.
bool IsAnyActiveTransition()
Check if any transition is active.
Simple generator class.
MAGeneratorContainer * GetGeneratorContainer(unsigned int device) const
Get generator container for a device.
Definition: MALedSkit.cpp:264
void Start(float device_value)
Start the first generator in the container based on a device value.
bool IsStarted() const
Check if the container has been started.
virtual void StopTransition(const std::string &name)
Stop a transition.
float GetCurrentValue()
Get the current value.
Generator container class.
Leds controller class.
MC::StringList GetActiveTransitionsByDevice(const MADevice &device)
Get a transition list by device.
virtual MA::DeviceList GetMotors() const override
Get the list of the motors.
virtual int StartTransition(const std::string &name)
Start a transition.
Base class for generators.
virtual void Start()
Start the generator.
float MCFloatInfinity()
Get float infinity.
Definition: MCDefs.cpp:110
bool IsTransitionActive(const std::string &name)
Whenever the transition is still active.
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...
float GetStartingValue() const
Get the starting value of the container.
Periodic generator class (waveform _/‾\_)
#define MC_LOG(...)
Debug macro.
Definition: MCLog.hpp:41
Robot state.
MA::TransitionMap Transitions
The map of the transitions.
virtual void UpdateRobotState(MARobotState &robot_state) override
Update the robot state.
#define MA_CONTAINER_LOCK_OTHER_FILE(_container)
Lock a container in an other file.
void BlockExpiredSignal()
Block the expiration signal of the container.