From 0cb4b08d406caff8cd2081ddb09bceb74d4e3a16 Mon Sep 17 00:00:00 2001
From: Roland Reichwein <mail@reichwein.it>
Date: Sat, 11 Jan 2025 12:25:03 +0100
Subject: MIDI bandwidth monitor

---
 MIDI.cpp     |  3 +--
 MIDI.h       |  2 +-
 MainLoop.cpp |  2 +-
 UI.cpp       | 22 ++++++++++++++++------
 UI.h         |  5 +++--
 5 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/MIDI.cpp b/MIDI.cpp
index 4713a55..1e43a96 100644
--- a/MIDI.cpp
+++ b/MIDI.cpp
@@ -149,7 +149,7 @@ void MIDI::process(snd_seq_event_t *ev)
     log_cout << fmt::format("[{}] Unknown MIDI event: {}", timestamp_from_event(ev), ev->type) << std::endl;
   }
 
-  signal_count_events();
+  signal_count_events(snd_seq_event_length(ev));
 }
 
 void MIDI::flush()
@@ -172,4 +172,3 @@ void MIDI::wait_for_event()
     throw std::runtime_error("Poll unsuccessful");
   }
 }
-
diff --git a/MIDI.h b/MIDI.h
index 8045684..9794e2c 100644
--- a/MIDI.h
+++ b/MIDI.h
@@ -19,7 +19,7 @@ public:
   boost::signals2::signal<void(int, int, uint64_t)> signal_note;
   boost::signals2::signal<void()> signal_active_sensing;
   boost::signals2::signal<void()> signal_clock;
-  boost::signals2::signal<void()> signal_count_events;
+  boost::signals2::signal<void(size_t)> signal_count_events;
 
   int fd();
 
diff --git a/MainLoop.cpp b/MainLoop.cpp
index c01ccdb..2ffcc0a 100644
--- a/MainLoop.cpp
+++ b/MainLoop.cpp
@@ -92,7 +92,7 @@ int MainLoop::run()
   m_midi.signal_active_sensing.connect([&](){m_ui.slot_active_sensing();});
   timer_500ms.elapsed.connect([&](){m_ui.draw();});
   signal_count_loops.connect([&](){m_ui.count_main_loops();});
-  m_midi.signal_count_events.connect([&](){m_ui.count_midi_events();});
+  m_midi.signal_count_events.connect([&](size_t size){m_ui.count_midi_events(size);});
   timer_10min.elapsed.connect([&](){m_config.persist();});
   m_midi.signal_note.connect([&](int channel, int note, uint64_t timestamp){m_ui.slot_midi_note(channel, note, timestamp);});
   m_midi.signal_clock.connect([&](){m_clock_click.receive_clock();});
diff --git a/UI.cpp b/UI.cpp
index 5332bba..a28608a 100644
--- a/UI.cpp
+++ b/UI.cpp
@@ -18,18 +18,24 @@ const int midi_monitor_max_size = 3;
 
 using namespace std::chrono_literals;
 
-static std::vector<std::string> mode_names{
+namespace {
+
+const int midi_bandwidth = 3125; // bytes/s
+
+std::vector<std::string> mode_names{
   "NoteClick", "Clock", "Internal"
 };
 
-static std::vector<std::string> output_names{
+std::vector<std::string> output_names{
   "Off", "On"
 };
 
-static std::vector<std::string> active_sensing_names{
+std::vector<std::string> active_sensing_names{
   "Not Detected", "Detected"
 };
 
+}
+
 IntervalCounter::IntervalCounter()
 {
 }
@@ -49,15 +55,16 @@ int IntervalCounter::get_count_per_second()
   return count_per_second;
 }
 
-void IntervalCounter::count()
+void IntervalCounter::count(uint64_t n)
 {
-  m_count++;
+  m_count += n;
 }
 
 UI::UI(Config& config):
   m_config(config),
   m_main_loops{},
   m_midi_events{},
+  m_midi_bytes{},
   m_midi_notes{},
   m_active_sensing_timestamp{},
   m_midi_timestamp{},
@@ -90,6 +97,7 @@ void UI::draw()
   std::vector<int> cpuloads = get_cpu_loads();
   int main_loops_per_second = m_main_loops.get_count_per_second();
   int midi_events_per_second = m_midi_events.get_count_per_second();
+  int midi_bytes_per_second = m_midi_bytes.get_count_per_second();
   int midi_notes_per_second = m_midi_notes.get_count_per_second();
 
   int temperature = m_temperature.read_degree();
@@ -165,6 +173,7 @@ void UI::draw()
   std::cout << "  MIDI Active Sensing: " << fmt::format(value_color, "{}", active_sensing_names[active_sensing_detected]) << std::endl;
   std::cout << fmt::format("  MIDI Events/s:{:3}", midi_events_per_second) << std::endl;
   std::cout << fmt::format("  MIDI Notes/s: {:3}", midi_notes_per_second) << std::endl;
+  std::cout << fmt::format("  MIDI Bytes/s: {:3} ({}%)", midi_bytes_per_second, midi_bytes_per_second * 100 / midi_bandwidth) << std::endl;
   std::cout << fmt::format("  MIDI Click:   {:3} BPM", m_note_bpm) << std::endl;
   std::cout << fmt::format("  MIDI Clock:   {:3} BPM", m_clock_bpm) << std::endl;
   std::cout << fmt::format("  Internal:     {:3} BPM", internal_bpm) << std::endl;
@@ -228,9 +237,10 @@ void UI::count_main_loops()
   m_main_loops.count();
 }
 
-void UI::count_midi_events()
+void UI::count_midi_events(size_t size)
 {
   m_midi_events.count();
+  m_midi_bytes.count(size);
 }
 
 void UI::count_midi_notes()
diff --git a/UI.h b/UI.h
index 02b0822..fa89c52 100644
--- a/UI.h
+++ b/UI.h
@@ -18,7 +18,7 @@ struct IntervalCounter
 public:
   IntervalCounter();
   int get_count_per_second();
-  void count();
+  void count(uint64_t n = 1);
 
 private:
   uint64_t m_count{};
@@ -46,7 +46,7 @@ public:
 
   // slots
   void count_main_loops();
-  void count_midi_events();
+  void count_midi_events(size_t size);
   void count_midi_notes();
   void slot_active_sensing();
   void slot_midi_note(int channel, int note, uint64_t timestamp);
@@ -58,6 +58,7 @@ private:
 
   IntervalCounter m_main_loops;
   IntervalCounter m_midi_events;
+  IntervalCounter m_midi_bytes;
   IntervalCounter m_midi_notes;
 
   std::chrono::time_point<clock_type> m_active_sensing_timestamp;
-- 
cgit v1.2.3