diff options
author | Roland Reichwein <mail@reichwein.it> | 2025-01-03 15:36:22 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2025-01-03 15:36:22 +0100 |
commit | 9de0b7f8937b7f6ce990132609f0b26851b31f2b (patch) | |
tree | a69f73358c9b75e5a11c9ed18d934964461360bf | |
parent | 05895c86bddf50aacb3bb5e6a6bcc073965341ef (diff) |
Monitor CPU
-rw-r--r-- | MIDI.h | 11 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | UI.cpp | 17 | ||||
-rw-r--r-- | cpuload.cpp | 71 | ||||
-rw-r--r-- | cpuload.h | 8 | ||||
-rw-r--r-- | debug.cpp | 3 | ||||
-rw-r--r-- | debug.h | 40 | ||||
-rw-r--r-- | main.cpp | 2 |
8 files changed, 152 insertions, 6 deletions
@@ -1,9 +1,12 @@ #pragma once #include "config.h" +#include "debug.h" #include <boost/signals2.hpp> +#include <fmt/format.h> + #include <iostream> class MIDI @@ -119,7 +122,7 @@ public: if((ev->type == SND_SEQ_EVENT_NOTEON) ||(ev->type == SND_SEQ_EVENT_NOTEOFF)) { const char *type = (ev->type == SND_SEQ_EVENT_NOTEON) ? "on " : "off"; - printf("[%d] Note %s: %2x vel(%2x), ch %2x\n", ((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_REAL) ? ev->time.time.tv_sec : ev->time.tick, + debug_cout << fmt::format("[{}] Note {}: {:2x} vel({:2x}), ch {:2x}\n", ((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_REAL) ? ev->time.time.tv_sec : ev->time.tick, type, ev->data.note.note, ev->data.note.velocity, @@ -132,17 +135,17 @@ public: } else if(ev->type == SND_SEQ_EVENT_CONTROLLER) { - printf("[%d] Control: %2x val(%2x)\n", ((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_REAL) ? ev->time.time.tv_sec : ev->time.tick, + debug_cout << fmt::format("[{}] Control: {:2x} val({:2x})\n", ((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_REAL) ? ev->time.time.tv_sec : ev->time.tick, ev->data.control.param, ev->data.control.value); } else if(ev->type == SND_SEQ_EVENT_CLOCK) { - printf("[%d] Clock\n", ((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_REAL) ? ev->time.time.tv_sec : ev->time.tick); + debug_cout << fmt::format("[{}] Clock\n", ((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_REAL) ? ev->time.time.tv_sec : ev->time.tick) << std::endl;; } else { - printf("[%d] Unknown: Unhandled Event Received\n", ev->time.tick); + debug_cout << fmt::format("[{}] Unknown: Unhandled Event Received\n", ev->time.tick) << std::endl;; } } @@ -9,7 +9,11 @@ SRCS= \ ClickStream.cpp \ config.cpp \ UI.cpp \ - Timer.cpp + Timer.cpp \ + debug.cpp \ + cpuload.cpp + +HEADERS=$(SRCS:.cpp=.h) OBJS=$(SRCS:.cpp=.o) @@ -1,15 +1,30 @@ #include "UI.h" +#include "cpuload.h" + +#include <algorithm> #include <iostream> +#include <string> + +#include <fmt/format.h> void UI::draw() { + std::vector<int> cpuloads = get_cpu_loads(); + std::cout << std::endl; std::cout << "- -- BPM +" << std::endl; std::cout << "Mode: Click __/__ (Clock Internal)" << std::endl; std::cout << "Status:" << std::endl; std::cout << " Alive/not alive" << std::endl; - std::cout << " CPU: --% --% ..." << std::endl; + + std::cout << " CPU:"; + for (auto& i: cpuloads) { + std::cout << fmt::format(" {:2}%", i); + } + int max = *std::max_element(cpuloads.begin(), cpuloads.end()); + std::cout << fmt::format(", max. {:2}%", max) << std::endl; + std::cout << " Notes/Channels: -- -- -- ... (Choose)" << std::endl; std::cout << " Timestamp: ------" << std::endl; std::cout << " Active sensing: ---" << std::endl; diff --git a/cpuload.cpp b/cpuload.cpp new file mode 100644 index 0000000..77abc3e --- /dev/null +++ b/cpuload.cpp @@ -0,0 +1,71 @@ +#include "cpuload.h" + +#include <chrono> +#include <numeric> + +#include <libreichwein/file.h> +#include <libreichwein/stringhelper.h> + +int get_number_of_cpus() +{ + int result{}; + std::string stat = Reichwein::File::getFile("/proc/stat"); + std::vector<std::string> lines = Reichwein::Stringhelper::split(stat, "\n"); + for (const auto& line: lines) { + std::vector<std::string> words = Reichwein::Stringhelper::split(line, " "); + // /proc/stat line, e.g.: cpu0 1132 34 1441 11311718 3675 127 438 + if (words.size() >= 8) { + if (words[0].size() > 3 && words[0].substr(0, 3) == "cpu") { + ++result; + } + } + } + return result; +} + +// returns empty vector if no data is available yet +// Note: to be called several times, because data is generated differentially from /proc/stat +std::vector<int> get_cpu_loads() +{ + using clock_type = std::chrono::high_resolution_clock; + static int number_of_cpus = get_number_of_cpus(); + static std::vector<int> stat_cpus_sum(number_of_cpus); + static std::vector<int> stat_cpus_idle(number_of_cpus); + static std::chrono::time_point<clock_type> timestamp{}; + + std::string stat = Reichwein::File::getFile("/proc/stat"); + + std::vector<std::string> lines = Reichwein::Stringhelper::split(stat, "\n"); + + std::vector<int> result; + + int i = 0; + for (const auto& line: lines) { + std::vector<std::string> words = Reichwein::Stringhelper::split(line, " "); + // /proc/stat line, e.g.: cpu0 1132 34 1441 11311718 3675 127 438 + // idle value is at index 4 + if (words.size() >= 8) { + if (words[0].size() > 3 && words[0].substr(0, 3) == "cpu") { + uint64_t sum = std::accumulate(words.begin() + 1, words.end(), uint64_t{}, [](uint64_t sum, const std::string& s){return sum + std::stoull(s);}); + uint64_t idle = std::stoull(words[4]); + + // previous data available + if (timestamp == std::chrono::time_point<clock_type>{}) + { + uint64_t sum_diff = sum - stat_cpus_sum[i]; + uint64_t idle_diff = idle - stat_cpus_idle[i]; + int percentage = (sum_diff == 0) ? 0 : ((sum_diff - idle_diff) * 100 / sum_diff); + result.push_back(percentage); + } + + stat_cpus_sum[i] = sum; + stat_cpus_idle[i] = idle; + + ++i; + } + } + } + + return result; +} + diff --git a/cpuload.h b/cpuload.h new file mode 100644 index 0000000..ae98071 --- /dev/null +++ b/cpuload.h @@ -0,0 +1,8 @@ +#pragma once + +#include <vector> + +int get_number_of_cpus(); + +// returns percentages of cpu load, for all cores +std::vector<int> get_cpu_loads(); diff --git a/debug.cpp b/debug.cpp new file mode 100644 index 0000000..09c9fcc --- /dev/null +++ b/debug.cpp @@ -0,0 +1,3 @@ +#include "debug.h" + +debug_ostream debug_cout; @@ -0,0 +1,40 @@ +#pragma once + +#include <iostream> +#include <ostream> + +class debug_ostream +{ +public: + debug_ostream(): m_active(false) {} + + void activate() + { + m_active = true; + } + + void deactivate() + { + m_active = false; + } + + template<typename T> + debug_ostream& operator<<(const T& arg) { + if (m_active) + std::cout << arg; + return *this; + } + + debug_ostream& operator<<( + std::basic_ostream<char>& (*func) + (std::basic_ostream<char>&) ) { + if (m_active) + std::cout << *func; + return *this; + } + +private: + bool m_active; +}; + +extern debug_ostream debug_cout; @@ -31,6 +31,8 @@ double diff_timespec(const struct timespec *time1, const struct timespec *time0) int main(void) { try { + //debug_cout.activate(); + MIDI midi; ClickStream stream; PCM pcm{stream}; |