summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2025-01-03 15:36:22 +0100
committerRoland Reichwein <mail@reichwein.it>2025-01-03 15:36:22 +0100
commit9de0b7f8937b7f6ce990132609f0b26851b31f2b (patch)
treea69f73358c9b75e5a11c9ed18d934964461360bf
parent05895c86bddf50aacb3bb5e6a6bcc073965341ef (diff)
Monitor CPU
-rw-r--r--MIDI.h11
-rw-r--r--Makefile6
-rw-r--r--UI.cpp17
-rw-r--r--cpuload.cpp71
-rw-r--r--cpuload.h8
-rw-r--r--debug.cpp3
-rw-r--r--debug.h40
-rw-r--r--main.cpp2
8 files changed, 152 insertions, 6 deletions
diff --git a/MIDI.h b/MIDI.h
index f0175bc..5ce050e 100644
--- a/MIDI.h
+++ b/MIDI.h
@@ -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;;
}
}
diff --git a/Makefile b/Makefile
index 8ef3555..1fc0bbd 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/UI.cpp b/UI.cpp
index f0eb0c3..e1d33c9 100644
--- a/UI.cpp
+++ b/UI.cpp
@@ -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;
diff --git a/debug.h b/debug.h
new file mode 100644
index 0000000..1965de0
--- /dev/null
+++ b/debug.h
@@ -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;
diff --git a/main.cpp b/main.cpp
index 53e2947..19cf681 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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};