#pragma once #include "config.h" #include <chrono> #include <deque> #include <utility> #include <boost/signals2.hpp> using clock_type = std::chrono::high_resolution_clock; struct IntervalCounter { public: IntervalCounter(); int get_count_per_second(); void count(); private: uint64_t m_count{}; uint64_t m_count_checkpoint{}; std::chrono::time_point<clock_type> m_checkpoint_timestamp{}; }; class UI { public: UI(Config& config); void draw(); void handle_input(); bool key_available(); // signals, from user input boost::signals2::signal<void(int)> signal_bpm; boost::signals2::signal<void(int, int)> signal_note_set_from_midi; boost::signals2::signal<void(int)> signal_mode; boost::signals2::signal<void(int)> signal_output; // slots void count_main_loops(); void count_midi_events(); void slot_active_sensing(); void slot_midi_note(int channel, int note, uint64_t timestamp); void slot_note_bpm(int bpm); void slot_clock_bpm(int bpm); private: Config& m_config; IntervalCounter m_main_loops; IntervalCounter m_midi_events; std::chrono::time_point<clock_type> m_active_sensing_timestamp; uint64_t m_midi_timestamp; std::deque<std::pair<int,int>> m_midi_monitor; int m_note_bpm; int m_clock_bpm; };