#ifndef TAGPARSER_PROGRESS_FEEDBACK_H #define TAGPARSER_PROGRESS_FEEDBACK_H #include "./exceptions.h" #include #include #include #include namespace Media { template class BasicProgressFeedback { public: using Callback = std::function; BasicProgressFeedback(const Callback &callback, const Callback &percentageOnlyCallback = Callback()); BasicProgressFeedback(Callback &&callback, Callback &&percentageOnlyCallback = Callback()); const std::string &step() const; byte stepPercentage() const; byte overallPercentage() const; void updateStep(const std::string &step, byte stepPercentage = 0); void updateStep(std::string &&step, byte stepPercentage = 0); void updateStepPercentage(byte stepPercentage); void updateStepPercentageFromFraction(double stepPercentage); void updateOverallPercentage(byte overallPercentage); private: Callback m_callback; Callback m_percentageOnlyCallback; std::string m_step; byte m_stepPercentage; byte m_overallPercentage; }; template inline BasicProgressFeedback::BasicProgressFeedback(const Callback &callback, const Callback &percentageOnlyCallback) : m_callback(callback) , m_percentageOnlyCallback(percentageOnlyCallback) , m_stepPercentage(0) , m_overallPercentage(0) { } template inline BasicProgressFeedback::BasicProgressFeedback(Callback &&callback, Callback &&percentageOnlyCallback) : m_callback(callback) , m_percentageOnlyCallback(percentageOnlyCallback) , m_stepPercentage(0) , m_overallPercentage(0) { } template inline const std::string &BasicProgressFeedback::step() const { return m_step; } template inline byte BasicProgressFeedback::stepPercentage() const { return m_stepPercentage; } template inline byte BasicProgressFeedback::overallPercentage() const { return m_overallPercentage; } template inline void BasicProgressFeedback::updateStep(const std::string &step, byte stepPercentage) { m_step = step; m_stepPercentage = stepPercentage; if (m_callback) { m_callback(*static_cast(this)); } } template inline void BasicProgressFeedback::updateStep(std::string &&step, byte stepPercentage) { m_step = step; m_stepPercentage = stepPercentage; if (m_callback) { m_callback(*static_cast(this)); } } template inline void BasicProgressFeedback::updateStepPercentage(byte stepPercentage) { m_stepPercentage = stepPercentage; if (m_percentageOnlyCallback) { m_percentageOnlyCallback(*static_cast(this)); } else if (m_callback) { m_callback(*static_cast(this)); } } template inline void BasicProgressFeedback::updateStepPercentageFromFraction(double stepPercentage) { updateStepPercentage(static_cast(stepPercentage * 100.0)); } template inline void BasicProgressFeedback::updateOverallPercentage(byte overallPercentage) { m_overallPercentage = overallPercentage; if (m_percentageOnlyCallback) { m_percentageOnlyCallback(*static_cast(this)); } else if (m_callback) { m_callback(*static_cast(this)); } } class ProgressFeedback : public BasicProgressFeedback { ProgressFeedback(const Callback &callback, const Callback &percentageOnlyCallback = Callback()); ProgressFeedback(Callback &&callback, Callback &&percentageOnlyCallback = Callback()); }; inline ProgressFeedback::ProgressFeedback(const Callback &callback, const Callback &percentageOnlyCallback) : BasicProgressFeedback(callback, percentageOnlyCallback) { } inline ProgressFeedback::ProgressFeedback(Callback &&callback, Callback &&percentageOnlyCallback) : BasicProgressFeedback(callback, percentageOnlyCallback) { } class AbortableProgressFeedback : public BasicProgressFeedback { public: AbortableProgressFeedback(const Callback &callback, const Callback &percentageOnlyCallback = Callback()); AbortableProgressFeedback(Callback &&callback, Callback &&percentageOnlyCallback = Callback()); bool isAborted() const; void tryToAbort(); void stopIfAborted() const; void nextStepOrStop(const std::string &step, byte stepPercentage = 0); void nextStepOrStop(std::string &&step, byte stepPercentage = 0); private: std::atomic_bool m_aborted; }; inline AbortableProgressFeedback::AbortableProgressFeedback(const Callback &callback, const Callback &percentageOnlyCallback) : BasicProgressFeedback(callback, percentageOnlyCallback) , m_aborted(false) { } inline AbortableProgressFeedback::AbortableProgressFeedback(Callback &&callback, Callback &&percentageOnlyCallback) : BasicProgressFeedback(callback, percentageOnlyCallback) , m_aborted(false) { } inline bool AbortableProgressFeedback::isAborted() const { return m_aborted.load(); } inline void AbortableProgressFeedback::tryToAbort() { return m_aborted.store(true); } inline void AbortableProgressFeedback::stopIfAborted() const { if (isAborted()) { throw OperationAbortedException(); } } inline void AbortableProgressFeedback::nextStepOrStop(const std::string &status, byte percentage) { if (isAborted()) { throw OperationAbortedException(); } updateStep(status, percentage); } inline void AbortableProgressFeedback::nextStepOrStop(std::string &&status, byte percentage) { if (isAborted()) { throw OperationAbortedException(); } updateStep(status, percentage); } } #endif // TAGPARSER_PROGRESS_FEEDBACK_H