-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
576 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#include "LogNode.hpp" | ||
|
||
#include "NodeSerializer.hpp" | ||
|
||
#include "midi/MessageView.hpp" | ||
|
||
#include "imgui.h" | ||
#include "imnodes.h" | ||
#include "spdlog/spdlog.h" | ||
|
||
#include <format> | ||
|
||
mc::LogNode::MessageDisplay::MessageDisplay(const duration_t& alive_time) | ||
{ | ||
m_alive_until = std::chrono::system_clock::now() + alive_time; | ||
} | ||
|
||
mc::LogNode::NoteMessageDisplay::NoteMessageDisplay( | ||
int channel, int note, int velocity, bool note_on, MessageDisplay::duration_t alive_time) | ||
: MessageDisplay(alive_time), m_channel(channel), m_note(note), m_velocity(velocity), | ||
m_note_on(note_on) | ||
{ | ||
} | ||
|
||
bool mc::LogNode::NoteMessageDisplay::alive() const | ||
{ | ||
return m_note_on || std::chrono::system_clock::now() <= m_alive_until; | ||
} | ||
|
||
void mc::LogNode::NoteMessageDisplay::render() const | ||
{ | ||
const char* on_or_off = m_note_on ? "on" : "off"; | ||
ImGui::Text( | ||
"Note %s channel: %i note: %i velocity: %i", on_or_off, m_channel, m_note, m_velocity); | ||
} | ||
|
||
std::string_view mc::LogNode::LogMidiNode::name() | ||
{ | ||
return "Log Node"; | ||
} | ||
|
||
mc::LogNode::LogNode() | ||
{ | ||
m_log_midi_node.add_observer(this); | ||
} | ||
|
||
mc::LogNode::~LogNode() | ||
{ | ||
m_log_midi_node.remove_observer(this); | ||
} | ||
|
||
void mc::LogNode::accept_serializer(nlohmann::json& j, const NodeSerializer& serializer) const | ||
{ | ||
serializer.serialize_node(j, *this); | ||
} | ||
|
||
mc::midi::Node* mc::LogNode::get_midi_node() | ||
{ | ||
return &m_log_midi_node; | ||
} | ||
|
||
void mc::LogNode::render_internal() | ||
{ | ||
ImNodes::BeginNodeTitleBar(); | ||
ImGui::TextUnformatted("Inspector"); | ||
ImNodes::EndNodeTitleBar(); | ||
ImNodes::BeginInputAttribute(in_id()); | ||
m_input_indicator.render(); | ||
ImGui::SameLine(); | ||
ImGui::TextUnformatted("MIDI in"); | ||
ImNodes::EndInputAttribute(); | ||
|
||
for (const auto& note_display : m_note_displays) | ||
{ | ||
note_display.render(); | ||
} | ||
|
||
std::erase_if(m_note_displays, [](const auto& note_display) { | ||
return !note_display.alive(); | ||
}); | ||
} | ||
|
||
void mc::LogNode::message_received(std::span<const unsigned char> message_bytes) | ||
{ | ||
m_input_indicator.trigger(); | ||
midi::MessageView message(message_bytes); | ||
midi::tag_overloads channel_message_visitor{ | ||
[this]<class T>(midi::NoteMessageViewTag, T note_message_view) { | ||
const int channel = note_message_view.get_channel(); | ||
const int note = note_message_view.get_note(); | ||
const bool is_note_on = | ||
std::is_same_v<midi::message_view_tag_t<T>, midi::NoteOnMessageViewTag>; | ||
NoteMessageDisplay new_note_message_display( | ||
channel, note, note_message_view.get_velocity(), is_note_on, default_duration); | ||
auto existing_it = std::find_if( | ||
m_note_displays.begin(), m_note_displays.end(), [&](const auto& display) { | ||
return display.get_channel() == channel && display.get_note() == note; | ||
}); | ||
|
||
if (existing_it == m_note_displays.end()) | ||
{ | ||
m_note_displays.emplace_back(new_note_message_display); | ||
} | ||
else | ||
{ | ||
*existing_it = new_note_message_display; | ||
} | ||
}, | ||
[]<class Tag>( | ||
Tag, auto) -> std::enable_if_t<!std::is_base_of_v<midi::NoteMessageViewTag, Tag>> {}}; | ||
midi::tag_overloads message_visitor{ | ||
[&](midi::ChannelMessageViewTag, auto channel_message_view) { | ||
std::visit(channel_message_visitor, channel_message_view.parse()); | ||
}, | ||
[](auto, auto) {}}; | ||
std::visit(message_visitor, message.parse()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#pragma once | ||
|
||
#include "ActivityIndicator.hpp" | ||
#include "Node.hpp" | ||
#include "midi/MidiGraph.hpp" | ||
|
||
#include <chrono> | ||
#include <cstdint> | ||
#include <deque> | ||
#include <span> | ||
#include <string_view> | ||
|
||
namespace mc | ||
{ | ||
|
||
class LogNode final : public Node, private midi::GraphObserver | ||
{ | ||
private: | ||
class LogMidiNode final : public midi::Node | ||
{ | ||
public: | ||
std::string_view name() override; | ||
}; | ||
|
||
class MessageDisplay | ||
{ | ||
public: | ||
using duration_t = std::chrono::duration<int>; | ||
|
||
explicit MessageDisplay(const duration_t& alive_time); | ||
virtual ~MessageDisplay() = default; | ||
|
||
protected: | ||
std::chrono::time_point<std::chrono::system_clock> m_alive_until; | ||
}; | ||
|
||
class NoteMessageDisplay final : public MessageDisplay | ||
{ | ||
public: | ||
NoteMessageDisplay(int channel, | ||
int note, | ||
int velocity, | ||
bool note_on, | ||
MessageDisplay::duration_t alive_time); | ||
bool alive() const; | ||
void render() const; | ||
|
||
int get_channel() const { return m_channel; } | ||
int get_note() const { return m_note; } | ||
|
||
private: | ||
int m_channel; | ||
int m_note; | ||
int m_velocity; | ||
bool m_note_on; | ||
}; | ||
|
||
public: | ||
LogNode(); | ||
~LogNode(); | ||
|
||
void accept_serializer(nlohmann::json& j, const NodeSerializer& serializer) const override; | ||
|
||
protected: | ||
midi::Node* get_midi_node() override; | ||
void render_internal() override; | ||
|
||
private: | ||
void message_received(std::span<const unsigned char> message_bytes) override; | ||
|
||
static constexpr inline MessageDisplay::duration_t default_duration = std::chrono::seconds(2); | ||
|
||
LogMidiNode m_log_midi_node; | ||
ActivityIndicator m_input_indicator; | ||
|
||
std::deque<NoteMessageDisplay> m_note_displays; | ||
|
||
friend class NodeSerializer; | ||
}; | ||
|
||
} // namespace mc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.