summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2025-01-03 17:31:21 +0100
committerRoland Reichwein <mail@reichwein.it>2025-01-03 17:31:21 +0100
commit7d98b5d410233fd9608ed5682f5a98b283f83d12 (patch)
tree8e3f24c126ffc4494a8b07ba48906e0ed97bc409
parent9de0b7f8937b7f6ce990132609f0b26851b31f2b (diff)
Diagnostics
-rw-r--r--MIDI.h2
-rw-r--r--PCM.h11
-rw-r--r--UI.cpp35
-rw-r--r--UI.h16
-rw-r--r--main.cpp17
5 files changed, 69 insertions, 12 deletions
diff --git a/MIDI.h b/MIDI.h
index 5ce050e..0dbc4aa 100644
--- a/MIDI.h
+++ b/MIDI.h
@@ -69,6 +69,8 @@ public:
if (npfd != 1) {
std::cout << "Warning: " << std::to_string(npfd) << " poll fds for MIDI" << std::endl;
+ } else if (fd() <= 2) {
+ std::cout << "Warning: Bad MIDI fd: " << std::to_string(fd()) << std::endl;
}
}
diff --git a/PCM.h b/PCM.h
index c9d7f7f..2c338f3 100644
--- a/PCM.h
+++ b/PCM.h
@@ -5,6 +5,7 @@
#include "config.h"
#include <alsa/asoundlib.h>
+#include <fmt/format.h>
#include <iostream>
#include <string>
@@ -18,8 +19,7 @@ public:
{
// non-blocking
if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
- printf("Playback open error: %s\n", snd_strerror(err));
- exit(EXIT_FAILURE);
+ throw std::runtime_error(fmt::format("Playback open error: {}", snd_strerror(err)));
}
if ((err = snd_pcm_set_params(handle,
SND_PCM_FORMAT_S16_LE,
@@ -28,8 +28,7 @@ public:
f_sample,
1,
100000)) < 0) { // latency in us
- printf("Playback open error: %s\n", snd_strerror(err));
- exit(EXIT_FAILURE);
+ throw std::runtime_error(fmt::format("Playback open error: {}", snd_strerror(err)));
}
m_stream.generate();
@@ -54,6 +53,8 @@ public:
if (npfd != 1) {
std::cout << "Warning: " << std::to_string(npfd) << " poll fds for pcm" << std::endl;
+ } else if (fd() <= 2) {
+ std::cout << "Warning: Bad PCM fd: " << std::to_string(fd()) << std::endl;
}
}
@@ -62,7 +63,7 @@ public:
// pass the remaining samples, otherwise they're dropped in close
err = snd_pcm_drain(handle);
if (err < 0)
- printf("snd_pcm_drain failed: %s\n", snd_strerror(err));
+ std::cerr << fmt::format("snd_pcm_drain failed: {}", snd_strerror(err)) << std::endl;
snd_pcm_close(handle);
free(pfd);
diff --git a/UI.cpp b/UI.cpp
index e1d33c9..f9b2512 100644
--- a/UI.cpp
+++ b/UI.cpp
@@ -8,13 +8,35 @@
#include <fmt/format.h>
+using namespace std::chrono_literals;
+
+UI::UI(): m_main_loops{}, m_main_loops_checkpoint{}, m_main_loops_timestamp{}
+{
+}
+
+int UI::get_main_loops_per_second()
+{
+ // calculate result
+ std::chrono::time_point<clock_type> now = clock_type::now();
+ uint64_t diff_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_main_loops_timestamp).count();
+ uint64_t loops_per_second = (diff_ms == 0 || m_main_loops_checkpoint == 0) ? 0 : ((m_main_loops - m_main_loops_checkpoint) * 1000 / diff_ms);
+
+ // update state
+ m_main_loops_timestamp = now;
+ m_main_loops_checkpoint = m_main_loops;
+
+ return loops_per_second;
+}
+
void UI::draw()
{
std::vector<int> cpuloads = get_cpu_loads();
+ int main_loops_per_second = get_main_loops_per_second();
std::cout << std::endl;
std::cout << "- -- BPM +" << std::endl;
std::cout << "Mode: Click __/__ (Clock Internal)" << std::endl;
+ std::cout << std::endl;
std::cout << "Status:" << std::endl;
std::cout << " Alive/not alive" << std::endl;
@@ -28,6 +50,15 @@ void UI::draw()
std::cout << " Notes/Channels: -- -- -- ... (Choose)" << std::endl;
std::cout << " Timestamp: ------" << std::endl;
std::cout << " Active sensing: ---" << std::endl;
- std::cout << " Clock: ____" << std::endl;
- std::cout << " Click: ____" << std::endl;
+ std::cout << " Clock: ____ BPM" << std::endl;
+ std::cout << " Click: ____ BPM" << std::endl;
+
+ std::cout << fmt::format(" Main loops/s: {}", main_loops_per_second) << std::endl;
}
+
+void UI::count_main_loops()
+{
+ ++m_main_loops;
+ //std::cout << "DEBUG:" << m_main_loops << std::endl;
+}
+
diff --git a/UI.h b/UI.h
index 60b168c..077e3a9 100644
--- a/UI.h
+++ b/UI.h
@@ -1,9 +1,23 @@
#pragma once
+#include <chrono>
+
class UI
{
public:
- UI(){}
+ using clock_type = std::chrono::high_resolution_clock;
+
+ UI();
void draw();
+
+ void count_main_loops();
+
+private:
+
+ int get_main_loops_per_second();
+
+ uint64_t m_main_loops;
+ uint64_t m_main_loops_checkpoint;
+ std::chrono::time_point<clock_type> m_main_loops_timestamp;
};
diff --git a/main.cpp b/main.cpp
index 19cf681..4c33bc4 100644
--- a/main.cpp
+++ b/main.cpp
@@ -43,32 +43,41 @@ int main(void)
Timer timer_300ms(300ms, true);
timer_300ms.start();
+ // Main signals
+ boost::signals2::signal<void()> signal_count_loops;
+
// Signal-Slot Connections:
midi.signal_click.connect([&](){stream.click();});
timer_300ms.elapsed.connect([&](){ui.draw();});
+ signal_count_loops.connect([&](){ui.count_main_loops();});
while (true) {
//std::cout << "Main loop entered." << std::endl;
+ signal_count_loops();
+
fd_set read_set;
FD_ZERO(&read_set);
FD_SET(midi.fd(), &read_set);
+#if 0
+ // PCM fd almost always writeable: for single frames at high speed
fd_set write_set;
FD_ZERO(&write_set);
FD_SET(pcm.fd(), &write_set);
+#endif
struct timeval timeout;
- timeout.tv_sec = 0;
+ timeout.tv_sec = 1;
timeout.tv_usec = 300000;
- int result = select(FD_SETSIZE, &read_set, &write_set, NULL, &timeout);
+ int result = select(FD_SETSIZE, &read_set, nullptr/*&write_set*/, nullptr, &timeout);
if (result < 0) {
throw std::runtime_error("select() failed");
} else if (result == 0) {
- throw std::runtime_error("select() timeout");
+ std::cout << "select() timeout" << std::endl;
}
- if (midi.event_ready())
+ while (midi.event_ready())
{
//std::cout << "read..." << std::endl;
auto event = midi.read();