summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2025-01-04 09:22:17 +0100
committerRoland Reichwein <mail@reichwein.it>2025-01-04 09:22:17 +0100
commit9351c6d9812523b0b8027f2b2e0de54c27004bc2 (patch)
tree6cbf97a8a699630f83bdc1bc93a51736874e82bb
parent0399f008b22482c46d37fa15e6be205b85681011 (diff)
Fix config
-rw-r--r--Click.h6
-rw-r--r--MIDI.h23
-rw-r--r--PCM.h3
-rw-r--r--UI.cpp2
-rw-r--r--UI.h8
-rw-r--r--config.cpp12
-rw-r--r--config.h3
-rw-r--r--main.cpp20
8 files changed, 62 insertions, 15 deletions
diff --git a/Click.h b/Click.h
index 0c2d0c7..7861d33 100644
--- a/Click.h
+++ b/Click.h
@@ -38,10 +38,14 @@ public:
virtual ~NoteClick(){}
+ // signals
boost::signals2::signal<void()> signal_click;
- void receive_note(int channel, int note)
+ // slots
+ void receive_note(int channel, int note, uint64_t timestamp)
{
+ (void) timestamp;
+
if (true || (channel == m_channel && note == m_note)) {
signal_click();
}
diff --git a/MIDI.h b/MIDI.h
index 23024c3..96c9eb7 100644
--- a/MIDI.h
+++ b/MIDI.h
@@ -32,7 +32,7 @@ public:
throw std::runtime_error("MIDI port couldn't be opened");
}
- log_cout << "in_port: " << std::to_string(in_port) << std::endl;
+ debug_cout << "in_port: " << std::to_string(in_port) << std::endl;
#if 1
snd_seq_addr_t sender, dest;
@@ -80,7 +80,7 @@ public:
free(pfd);
}
- boost::signals2::signal<void(int, int)> signal_note;
+ boost::signals2::signal<void(int, int, uint64_t)> signal_note;
boost::signals2::signal<void()> signal_active_sensing;
boost::signals2::signal<void()> signal_clock;
@@ -121,40 +121,45 @@ public:
return ev;
}
+ uint64_t timestamp_from_event(const snd_seq_event_t *ev)
+ {
+ return ((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_REAL) ? ev->time.time.tv_sec : ev->time.tick;
+ }
+
// returns if click starts
void process(const snd_seq_event_t *ev)
{
if ((ev->type == SND_SEQ_EVENT_NOTEON) ||(ev->type == SND_SEQ_EVENT_NOTEOFF)) {
+ uint64_t timestamp = timestamp_from_event(ev);
const char *type = (ev->type == SND_SEQ_EVENT_NOTEON) ? "on " : "off";
- 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,
+ debug_cout << fmt::format("[{}] Note {}: {:2x} vel({:2x}), ch {:2x}\n", timestamp,
type,
ev->data.note.note,
ev->data.note.velocity,
ev->data.control.channel);
if (ev->type == SND_SEQ_EVENT_NOTEON) {
- signal_note(ev->data.control.channel, ev->data.note.note);
+ signal_note(ev->data.control.channel, ev->data.note.note, timestamp);
}
}
else if (ev->type == SND_SEQ_EVENT_CONTROLLER)
{
- 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,
+ debug_cout << fmt::format("[{}] Control: {:2x} val({:2x})\n", timestamp_from_event(ev),
ev->data.control.param,
ev->data.control.value);
}
else if (ev->type == SND_SEQ_EVENT_SENSING)
{
signal_active_sensing();
- debug_cout << fmt::format("[{}] Active Sensing\n", ((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_REAL) ? ev->time.time.tv_sec : ev->time.tick) << std::endl;
+ debug_cout << fmt::format("[{}] Active Sensing\n", timestamp_from_event(ev)) << std::endl;
}
else if (ev->type == SND_SEQ_EVENT_CLOCK)
{
signal_clock();
- 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;
+ debug_cout << fmt::format("[{}] Clock\n", timestamp_from_event(ev)) << std::endl;
}
else
{
- log_cout << fmt::format("[{}] Unknown MIDI event: {}\n", ev->time.tick, ev->type) << std::endl;
+ log_cout << fmt::format("[{}] Unknown MIDI event: {}\n", timestamp_from_event(ev), ev->type) << std::endl;
}
}
diff --git a/PCM.h b/PCM.h
index a74b2ea..a9e251c 100644
--- a/PCM.h
+++ b/PCM.h
@@ -1,6 +1,7 @@
#pragma once
#include "config.h"
+#include "debug.h"
#include "log.h"
#include <libreichwein/file.h>
@@ -132,7 +133,7 @@ public:
if (0 > snd_pcm_avail_delay(handle, &avail, &delay)) {
log_cout << "Error detecting avail and delay" << std::endl;
} else {
- log_cout << fmt::format("Delay: {}, avail. buffer; {} frames", delay, avail) << std::endl;
+ debug_cout << fmt::format("Delay: {}, avail. buffer; {} frames", delay, avail) << std::endl;
}
generate();
diff --git a/UI.cpp b/UI.cpp
index c083d53..c699aba 100644
--- a/UI.cpp
+++ b/UI.cpp
@@ -54,7 +54,7 @@ void UI::draw()
std::cout << fmt::format(", max. {:2}%", max) << std::endl;
std::cout << " Notes/Channels: -- -- -- ... (Choose)" << std::endl;
- std::cout << " Timestamp: ------" << std::endl;
+ std::cout << " MIDI Timestamp: ------" << std::endl;
std::cout << fmt::format(" Active sensing: {}", active_sensing_detected) << std::endl;
std::cout << " Clock: ____ BPM" << std::endl;
std::cout << " Click: ____ BPM" << std::endl;
diff --git a/UI.h b/UI.h
index 3041566..f507d2e 100644
--- a/UI.h
+++ b/UI.h
@@ -2,6 +2,8 @@
#include <chrono>
+#include <boost/signals2.hpp>
+
class UI
{
public:
@@ -11,6 +13,12 @@ public:
void draw();
+ // signals
+ boost::signals2::signal<void()> bpm_plus;
+ boost::signals2::signal<void()> bpm_minus;
+ boost::signals2::signal<void()> note_set_from_midi;
+ boost::signals2::signal<void()> mode;
+
// slots
void count_main_loops();
void slot_active_sensing();
diff --git a/config.cpp b/config.cpp
index b6460f2..2cd061c 100644
--- a/config.cpp
+++ b/config.cpp
@@ -15,6 +15,16 @@ std::string config_filename = "click.cfg";
Config::Config()
{
+ recover();
+}
+
+Config::~Config()
+{
+ persist();
+}
+
+void Config::recover()
+{
try {
// presets / defaults
m_midi_channel = CLICK_CHANNEL;
@@ -41,7 +51,7 @@ Config::Config()
}
}
-Config::~Config()
+void Config::persist()
{
std::string config = fmt::format("midi_channel={}\n", m_midi_channel) +
fmt::format("midi_note={}\n", m_midi_note) +
diff --git a/config.h b/config.h
index f93e6a9..07d3819 100644
--- a/config.h
+++ b/config.h
@@ -28,6 +28,9 @@ public:
int get_bpm();
void set_bpm(int bpm);
+ void recover();
+ void persist();
+
private:
int m_midi_channel;
int m_midi_note;
diff --git a/main.cpp b/main.cpp
index 7d423f6..5e078d9 100644
--- a/main.cpp
+++ b/main.cpp
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
+#include <signal.h>
#include <boost/signals2.hpp>
@@ -30,8 +31,18 @@ double diff_timespec(const struct timespec *time1, const struct timespec *time0)
+ (time1->tv_nsec - time0->tv_nsec) / 1000000000.0;
}
+bool run_flag = true;
+
+void signal_handler(int) {
+ run_flag = false;
+ std::cout << "Signal received. Terminating." << std::endl;
+}
+
int main(void)
{
+ signal(SIGTERM, signal_handler);
+ signal(SIGINT, signal_handler);
+
try {
//debug_cout.activate();
log_cout.activate();
@@ -55,21 +66,25 @@ int main(void)
Timer timer_500ms(500ms, true);
timer_500ms.start();
+ Timer timer_10min(10min, true);
+ timer_10min.start();
+
// Main signals
boost::signals2::signal<void()> signal_count_loops;
//
// Signal-Slot Connections:
//
- midi.signal_note.connect([&](int channel, int note){note_click->receive_note(channel, note);});
+ midi.signal_note.connect([&](int channel, int note, uint64_t timestamp){note_click->receive_note(channel, note, timestamp);});
note_click->signal_click.connect([&](){pcm.click();});
midi.signal_active_sensing.connect([&](){ui.slot_active_sensing();});
timer_500ms.elapsed.connect([&](){ui.draw();});
signal_count_loops.connect([&](){ui.count_main_loops();});
+ timer_10min.elapsed.connect([&](){config.persist();});
midi.flush();
- while (true) {
+ while (run_flag) {
debug_cout << "Main loop entered." << std::endl;
signal_count_loops();
@@ -110,6 +125,7 @@ int main(void)
// handle timers, TODO: make updates more efficient at scale
timer_500ms.update();
+ timer_10min.update();
}
} catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;