#pragma once // STL includes #include #include // QT includes #include #include #include #include // Utils includes #include #include #include // global defines #define SMOOTHING_MODE_DEFAULT 0 #define SMOOTHING_MODE_PAUSE 1 class QTimer; class Logger; /// /// The PriorityMuxer handles the priority channels. Led values input/ images are written to the priority map /// and the muxer keeps track of all active priorities. The current priority can be queried and per /// priority the led colors. Handles also manual/auto selection mode, provides a lot of signals to hook into priority related events /// class PriorityMuxer : public QObject { Q_OBJECT public: /// /// The information structure for a single priority channel /// struct InputInfo { /// The priority of this channel int priority; /// The absolute timeout of the channel int64_t timeoutTime_ms; /// The colors for each led of the channel std::vector ledColors; /// The raw Image (size should be preprocessed!) Image image; /// The component hyperion::Components componentId; /// Who set it QString origin; /// id of smoothing config unsigned smooth_cfg; /// specific owner description QString owner; }; /// The lowest possible priority, which is used when no priority channels are active const static int LOWEST_PRIORITY; /// /// Constructs the PriorityMuxer for the given number of LEDs (used to switch to black when /// there are no priority channels /// /// @param ledCount The number of LEDs /// PriorityMuxer(int ledCount, QObject * parent); /// /// Destructor /// ~PriorityMuxer() override; /// /// @brief Start/Stop the PriorityMuxer update timer; On disabled no priority and timeout updates will be performend /// @param enable The new state /// void setEnable(bool enable); /// @brief Enable or disable auto source selection /// @param enable True if it should be enabled else false /// @param update True to update _currentPriority - INTERNAL usage. /// @return True if changed has been applied, false if the state is unchanged /// bool setSourceAutoSelectEnabled(bool enabel, bool update = true); /// /// @brief Get the state of source auto selection /// @return True if enabled, else false /// bool isSourceAutoSelectEnabled() const { return _sourceAutoSelectEnabled; } /// /// @brief Overwrite current lowest priority with manual selection; On success disables auto selection /// @param priority The /// @return True on success, false if priority not found /// bool setPriority(int priority); /// /// @brief Update all LED-Colors with min length of >= 1 to fit the new led length /// @param[in] ledCount The count of LEDs /// void updateLedColorsLength(int ledCount); /// /// Returns the current priority /// /// @return The current priority /// int getCurrentPriority() const { return _currentPriority; } /// /// Returns the previous priority before current priority /// /// @return The previous priority /// int getPreviousPriority() const { return _previousPriority; } /// /// Returns the state (enabled/disabled) of a specific priority channel /// @param priority The priority channel /// @return True if the priority channel exists else false /// bool hasPriority(int priority) const; /// /// Returns the number of active priorities /// /// @return The list with active priorities /// QList getPriorities() const; /// /// Returns the information of a specified priority channel. /// If a priority is no longer available the _lowestPriorityInfo (255) is returned /// /// @param priority The priority channel /// /// @return The information for the specified priority channel /// InputInfo getInputInfo(int priority) 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(int priority, hyperion::Components component, const QString& origin = "System", const QString& owner = "", unsigned smooth_cfg = SMOOTHING_MODE_DEFAULT); /// /// @brief Update the current color of a priority (previous registered with registerInput()) /// @param priority The priority to update /// @param ledColors The colors /// @param timeout_ms The new timeout (defaults to -1 endless) /// @return True on success, false when priority is not found /// bool setInput(int priority, const std::vector& ledColors, int64_t timeout_ms = -1); /// /// @brief Update the current image of a priority (prev registered with registerInput()) /// @param priority The priority to update /// @param image The new image /// @param timeout_ms The new timeout (defaults to -1 endless) /// @return True on success, false when priority is not found /// bool setInputImage(int priority, const Image& image, int64_t timeout_ms = -1); /// /// @brief Set the given priority to inactive /// @param priority The priority /// @return True on success false if not found /// bool setInputInactive(int priority); /// /// Clears the specified priority channel and update _currentPriority on success /// /// @param[in] priority The priority of the channel to clear /// @return True if priority has been cleared else false (not found) /// bool clearInput(int priority); /// /// Clears all priority channels /// void clearAll(bool forceClearAll=false); /// /// @brief Queue a manual push where muxer doesn't recognize them (e.g. continuous single color pushes) /// void queuePush() { emit timeRunner(); } signals: /// /// @brief Signal which emits when a effect or color with timeout > -1 is running, once per second /// void timeRunner(); /// /// @brief Emits whenever the visible priority has changed /// @param priority The new visible priority /// void visiblePriorityChanged(quint8 priority); /// /// @brief Emits whenever the current visible component changed /// @param comp The new component /// void visibleComponentChanged(hyperion::Components comp); /// /// @brief Emits whenever something changes which influences the priorities listing /// Emits also in 1s interval when a COLOR or EFFECT is running with a timeout > -1 /// void prioritiesChanged(); /// /// internal used signal to resolve treading issues with timer /// void signalTimeTrigger(); private slots: /// /// Slot which is called to adapt to 1s interval for signal timeRunner() / prioritiesChanged() /// void timeTrigger(); /// /// Updates the current time. Channels with a configured time out will be checked and cleared if /// required. /// void setCurrentTime(); private: /// /// @brief Get the component of the given priority /// @return The component /// hyperion::Components getComponentOfPriority(int priority) const; /// Logger instance Logger* _log; /// The current priority (lowest value in _activeInputs) int _currentPriority; /// The previous priority before current priority int _previousPriority; /// The manual select priority set with setPriority int _manualSelectedPriority; // The last visible component hyperion::Components _prevVisComp = hyperion::COMP_INVALID; /// The mapping from priority channel to led-information QMap _activeInputs; /// The information of the lowest priority channel InputInfo _lowestPriorityInfo; // Reflect the state of auto select bool _sourceAutoSelectEnabled; // Timer to update Muxer times independent QTimer* _updateTimer; QTimer* _timer; QTimer* _blockTimer; };