/
Hyperion.h
580 lines (467 loc) · 17.8 KB
/
Hyperion.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
#pragma once
// stl includes
#include <list>
#include <QMap>
// QT includes
#include <QString>
#include <QStringList>
#include <QSize>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QFileSystemWatcher>
#include <QMutex>
// hyperion-utils includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/Logger.h>
#include <utils/Components.h>
#include <utils/VideoMode.h>
// Hyperion includes
#include <hyperion/LedString.h>
#include <hyperion/PriorityMuxer.h>
#include <hyperion/ColorAdjustment.h>
#include <hyperion/ComponentRegister.h>
// Effect engine includes
#include <effectengine/EffectDefinition.h>
#include <effectengine/ActiveEffectDefinition.h>
#include <effectengine/EffectSchema.h>
// settings utils
#include <utils/settings.h>
// Forward class declaration
class QTimer;
class HyperionDaemon;
class ImageProcessor;
class MessageForwarder;
class LinearColorSmoothing;
class EffectEngine;
class MultiColorAdjustment;
class ColorAdjustment;
class SettingsManager;
class BGEffectHandler;
class CaptureCont;
class BoblightServer;
class LedDeviceWrapper;
///
/// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through
/// the priority muxer.
///
class Hyperion : public QObject
{
Q_OBJECT
public:
/// Type definition of the info structure used by the priority muxer
typedef PriorityMuxer::InputInfo InputInfo;
///
/// RGB-Color channel enumeration
///
enum RgbChannel
{
BLACK, WHITE, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, INVALID
};
///
/// Destructor; cleans up resources
///
~Hyperion();
///
/// free all alocated objects, should be called only from constructor or before restarting hyperion
///
void freeObjects(bool emitCloseSignal=false);
///
/// @brief creates a new Hyperion instance, usually called from the Hyperion Daemon
/// @param[in] daemon The Hyperion daemon parent
/// @param[in] instance The instance id
/// @param[in] rootPath Root path of all hyperion userdata
/// @return Hyperion instance pointer
///
static Hyperion* initInstance(HyperionDaemon* daemon, const quint8& instance, const QString configFile, const QString rootPath);
///
/// @brief Get a pointer of this Hyperion instance
/// @return Hyperion instance pointer
///
static Hyperion* getInstance();
///
/// @brief Get a pointer to the effect engine
/// @return EffectEngine instance pointer
///
EffectEngine* getEffectEngineInstance() { return _effectEngine; };
///
/// @brief Get a pointer to the priorityMuxer instance
/// @return PriorityMuxer instance pointer
///
PriorityMuxer* getMuxerInstance() { return &_muxer; };
ImageProcessor* getImageProcessor() { return _imageProcessor; };
///
/// @brief Get a setting by settings::type from SettingsManager
/// @param type The settingsType from enum
/// @return Data Document
///
QJsonDocument getSetting(const settings::type& type);
///
/// @brief Save a complete json config
/// @param config The entire config object
/// @param correct If true will correct json against schema before save
/// @return True on success else false
///
bool saveSettings(QJsonObject config, const bool& correct = false);
///
/// Returns the number of attached leds
///
unsigned getLedCount() const;
///
/// @brief Return the size of led grid
///
QSize getLedGridSize() const { return _ledGridSize; };
///
/// Returns the current priority
///
/// @return The current priority
///
int getCurrentPriority() const;
///
/// Returns true if current priority is given priority
///
/// @return bool
///
bool isCurrentPriority(const int priority) const;
///
/// Returns a list of all registered priorities
///
/// @return The list with priorities
///
QList<int> getActivePriorities() const;
///
/// Returns the information of a specific priorrity channel
///
/// @param[in] priority The priority channel
///
/// @return The information of the given, a not found priority will return lowest priority as fallback
///
const InputInfo getPriorityInfo(const int priority) const;
///
/// @brief Save an effect
/// @param obj The effect args
/// @param[out] resultMsg The feedback message
/// @return True on success else false
///
bool saveEffect(const QJsonObject& obj, QString& resultMsg);
///
/// @brief Delete an effect by name.
/// @param[in] effectName The effect name to delete
/// @param[out] resultMsg The message on error
/// @return True on success else false
///
bool deleteEffect(const QString& effectName, QString& resultMsg);
/// Get the list of available effects
/// @return The list of available effects
const std::list<EffectDefinition> &getEffects() const;
/// Get the list of active effects
/// @return The list of active effects
const std::list<ActiveEffectDefinition> &getActiveEffects();
/// Get the list of available effect schema files
/// @return The list of available effect schema files
const std::list<EffectSchema> &getEffectSchemas();
/// gets the current json config object from SettingsManager
/// @return json config
const QJsonObject& getQJsonConfig();
/// get path+filename of configfile
/// @return the current config path+filename
QString getConfigFilePath() { return _configFile; };
/// get filename of configfile
/// @return the current config filename
QString getConfigFileName() const;
///
/// @brief Register a new input by priority, the priority is not active (timeout -100 isn't muxer recognized) until you start to update the data with setInput()
/// A repeated call to update the base data of a known priority won't overwrite their current timeout
/// @param[in] priority The priority of the channel
/// @param[in] component The component of the channel
/// @param[in] origin Who set the channel (CustomString@IP)
/// @param[in] owner Specific owner string, might be empty
/// @param[in] smooth_cfg The smooth id to use
///
void registerInput(const int priority, const hyperion::Components& component, const QString& origin = "System", const QString& owner = "", unsigned smooth_cfg = 0);
/// enable/disable automatic/priorized source selection
/// @param enabled the state
void setSourceAutoSelectEnabled(bool enabled);
/// set current input source to visible
/// @param priority the priority channel which should be vidible
/// @return true if success, false on error
bool setCurrentSourcePriority(int priority );
/// gets current state of automatic/priorized source selection
/// @return the state
bool sourceAutoSelectEnabled();
///
/// @brief Called from components to update their current state. DO NOT CALL FROM USERS
/// @param[in] component The component from enum
/// @param[in] state The state of the component [true | false]
///
void setNewComponentState(const hyperion::Components& component, const bool& state);
///
/// @brief Enable/Disable components during runtime, called from external API (requests)
///
/// @param component The component from enum
/// @param state The state of the component [true | false]
///
void setComponentState(const hyperion::Components component, const bool state);
ComponentRegister& getComponentRegister() { return _componentRegister; };
bool configModified() { return _configMod; };
bool configWriteable() { return _configWrite; };
/// gets the methode how image is maped to leds
const int & getLedMappingType();
/// get the root path for all hyperion user data files
const QString &getRootPath() { return _rootPath; };
/// get unique id per instance
const QString &getId(){ return _id; };
/// set unique id
void setId(QString id){ _id = id; };
int getLatchTime() const;
/// forward smoothing config
unsigned addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequency_hz=25.0, unsigned updateDelay=0);
const VideoMode & getCurrentVideoMode();
///
/// @brief Get the current active led device
/// @return The device nam
/// e
const QString & getActiveDevice();
public slots:
///
/// @brief Update the current color of a priority (prev registered with registerInput())
/// DO NOT use this together with setInputImage() at the same time!
/// @param priority The priority to update
/// @param ledColors The colors
/// @param timeout_ms The new timeout (defaults to -1 endless)
/// @param clearEffect Should be true when NOT called from an effect
/// @return True on success, false when priority is not found
///
bool setInput(const int priority, const std::vector<ColorRgb>& ledColors, const int timeout_ms = -1, const bool& clearEffect = true);
///
/// @brief Update the current image of a priority (prev registered with registerInput())
/// DO NOT use this together with setInput() at the same time!
/// @param priority The priority to update
/// @param image The new image
/// @param timeout_ms The new timeout (defaults to -1 endless)
/// @param clearEffect Should be true when NOT called from an effect
/// @return True on success, false when priority is not found
///
bool setInputImage(const int priority, const Image<ColorRgb>& image, int64_t timeout_ms = -1, const bool& clearEffect = true);
///
/// @brief Set the given priority to inactive
/// @param priority The priority
/// @return True on success false if not found
///
bool setInputInactive(const quint8& priority);
///
/// Writes a single color to all the leds for the given time and priority
/// Registers comp color or provided type against muxer
/// Should be never used to update leds continuous
///
/// @param[in] priority The priority of the written color
/// @param[in] ledColor The color to write to the leds
/// @param[in] origin The setter
/// @param[in] timeout_ms The time the leds are set to the given color [ms]
///
void setColor(int priority, const ColorRgb &ledColor, const int timeout_ms = -1, const QString& origin = "System" ,bool clearEffects = true);
///
/// Returns the list with unique adjustment identifiers
/// @return The list with adjustment identifiers
///
const QStringList & getAdjustmentIds() const;
///
/// Returns the ColorAdjustment with the given identifier
/// @return The adjustment with the given identifier (or nullptr if the identifier does not exist)
///
ColorAdjustment * getAdjustment(const QString& id);
/// Tell Hyperion that the corrections have changed and the leds need to be updated
void adjustmentsUpdated();
///
/// Clears the given priority channel. This will switch the led-colors to the colors of the next
/// lower priority channel (or off if no more channels are set)
///
/// @param[in] priority The priority channel
/// @return True on success else false (not found)
///
bool clear(int priority);
///
/// @brief Clears all priority channels. This will switch the leds off until a new priority is written.
///
void clearall(bool forceClearAll=false);
/// Run the specified effect on the given priority channel and optionally specify a timeout
/// @param effectName Name of the effec to run
/// @param priority The priority channel of the effect
/// @param timeout The timeout of the effect (after the timout, the effect will be cleared)
int setEffect(const QString & effectName, int priority, int timeout = -1, const QString & origin="System");
/// Run the specified effect on the given priority channel and optionally specify a timeout
/// @param effectName Name of the effec to run
/// @param args arguments of the effect script
/// @param priority The priority channel of the effect
/// @param timeout The timeout of the effect (after the timout, the effect will be cleared)
int setEffect(const QString &effectName
, const QJsonObject &args
, int priority
, int timeout = -1
, const QString &pythonScript = ""
, const QString &origin="System"
, const QString &imageData = ""
);
/// sets the methode how image is maped to leds at ImageProcessor
void setLedMappingType(const int& mappingType);
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(const VideoMode& mode);
public:
static Hyperion *_hyperion;
signals:
/// Signal which is emitted when a priority channel is actively cleared
/// This signal will not be emitted when a priority channel time out
void channelCleared(int priority);
/// Signal which is emitted when all priority channels are actively cleared
/// This signal will not be emitted when a priority channel time out
void allChannelsCleared();
///
/// @brief Emits whenever a user request a component state change, it's up the component to listen
/// and update the component state at the componentRegister
/// @param component The component from enum
/// @param enabled The new state of the component
///
void componentStateChanged(const hyperion::Components component, bool enabled);
///
/// @brief Emits whenever the imageToLedsMapping has changed
/// @param mappingType The new mapping type
///
void imageToLedsMappingChanged(const int& mappingType);
///
/// @brief Emits whenever the visible priority delivers a image which is applied in update()
/// priorities with ledColors won't emit this signal
/// @param image The current image
///
void currentImage(const Image<ColorRgb> & image);
void closing();
/// Signal which is emitted, when a new json message should be forwarded
void forwardJsonMessage(QJsonObject);
/// Signal which is emitted, when a new system proto image should be forwarded
void forwardSystemProtoMessage(const QString, const Image<ColorRgb>);
/// Signal which is emitted, when a new V4l proto image should be forwarded
void forwardV4lProtoMessage(const QString, const Image<ColorRgb>);
///
/// @brief Is emitted from clients who request a videoMode change
///
void videoMode(const VideoMode& mode);
///
/// @brief A new videoMode was requested (called from Daemon!)
///
void newVideoMode(const VideoMode& mode);
///
/// @brief Emits whenever a config part changed. SIGNAL PIPE helper for SettingsManager -> HyperionDaemon
/// @param type The settings type from enum
/// @param data The data as QJsonDocument
///
void settingsChanged(const settings::type& type, const QJsonDocument& data);
///
/// @brief Emits whenever the adjustments have been updated
///
void adjustmentChanged();
///
/// @brief Signal pipe from EffectEngine to external, emits when effect list has been updated
///
void effectListUpdated();
///
/// @brief Emits whenever new data should be pushed to the LedDeviceWrapper which forwards it to the threaded LedDevice
///
void ledDeviceData(const std::vector<ColorRgb>& ledValues);
///
/// @brief Emits whenever new untransformed ledColos data is available, reflects the current visible device
///
void rawLedColors(const std::vector<ColorRgb>& ledValues);
private slots:
///
/// Updates the priority muxer with the current time and (re)writes the led color with applied
/// transforms.
///
void update();
/// check for configWriteable and modified changes, called by _fsWatcher or fallback _cTimer
void checkConfigState(QString cfile = NULL);
///
/// @brief Apply ComponentRegister emits for COMP_ALL. Enables/Disables core timers
/// @param comp The component
/// @param state The new state of the component
///
void updatedComponentState(const hyperion::Components comp, const bool state);
///
/// @brief Apply settings updates for LEDS and COLOR
/// @param type The type from enum
/// @param config The configuration
///
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
///
/// @brief Handle priority updates from Priority Muxer
/// @param priority The new visible priority
///
void handlePriorityChanges(const quint8 &priority);
private:
///
/// Constructs the Hyperion instance based on the given Json configuration
///
/// @param[in] qjsonConfig The Json configuration
///
Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString configFile, const QString rootPath);
/// The parent Hyperion Daemon
HyperionDaemon* _daemon;
/// Settings manager of this instance
SettingsManager* _settingsManager;
/// Register that holds component states
ComponentRegister _componentRegister;
/// The specifiation of the led frame construction and picture integration
LedString _ledString;
/// specifiation of cloned leds
LedString _ledStringClone;
/// Image Processor
ImageProcessor* _imageProcessor;
std::vector<ColorOrder> _ledStringColorOrder;
/// The priority muxer
PriorityMuxer _muxer;
/// The adjustment from raw colors to led colors
MultiColorAdjustment * _raw2ledAdjustment;
/// The actual LedDeviceWrapper
LedDeviceWrapper* _ledDeviceWrapper;
/// The smoothing LedDevice
LinearColorSmoothing * _deviceSmooth;
/// Effect engine
EffectEngine * _effectEngine;
// Message forwarder
MessageForwarder * _messageForwarder;
/// the name of config file
QString _configFile;
/// root path for all hyperion user data files
QString _rootPath;
/// unique id per instance
QString _id;
/// Logger instance
Logger * _log;
/// count of hardware leds
unsigned _hwLedCount;
QByteArray _configHash;
QSize _ledGridSize;
/// Store the previous compID for smarter update()
hyperion::Components _prevCompId;
/// Observe filesystem changes (_configFile), if failed use Timer
QFileSystemWatcher _fsWatcher;
QTimer* _cTimer;
/// holds the prev states of configWriteable and modified
bool _prevConfigMod = false;
bool _prevConfigWrite = true;
/// holds the current states of configWriteable and modified
bool _configMod = false;
bool _configWrite = true;
/// Background effect instance, kept active to react on setting changes
BGEffectHandler* _BGEffectHandler;
/// Capture control for Daemon native capture
CaptureCont* _captureCont;
/// buffer for leds (with adjustment)
std::vector<ColorRgb> _ledBuffer;
/// Boblight instance
BoblightServer* _boblightServer;
/// mutex
QMutex _changes;
};