diff options
-rw-r--r-- | MIDI.h | 2 | ||||
-rw-r--r-- | PCM.h | 11 | ||||
-rw-r--r-- | UI.cpp | 35 | ||||
-rw-r--r-- | UI.h | 16 | ||||
-rw-r--r-- | main.cpp | 17 |
5 files changed, 69 insertions, 12 deletions
@@ -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; } } @@ -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); @@ -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; +} + @@ -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; }; @@ -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(); |