Skip to content

Commit

Permalink
refactor: Simplified handling of disconnect/reconnect of MIDI devices
Browse files Browse the repository at this point in the history
  • Loading branch information
mfep committed May 17, 2024
1 parent 2cf21f0 commit 0be5131
Show file tree
Hide file tree
Showing 22 changed files with 193 additions and 462 deletions.
3 changes: 0 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,12 @@ set(sources
src/ActivityIndicator.cpp
src/Application.cpp
src/ConfigFile.cpp
src/DisconnectedMidiInNode.cpp
src/DisconnectedMidiOutNode.cpp
src/KeyboardShortcutAggregator.cpp
src/Licenses.cpp
src/LogNode.cpp
src/MidiChannelNode.cpp
src/MidiInNode.cpp
src/MidiOutNode.cpp
src/MidiPortWatchdog.cpp
src/Node.cpp
src/NodeEditor.cpp
src/NodeFactory.cpp
Expand Down
28 changes: 0 additions & 28 deletions src/DisconnectedMidiInNode.cpp

This file was deleted.

23 changes: 0 additions & 23 deletions src/DisconnectedMidiInNode.hpp

This file was deleted.

29 changes: 0 additions & 29 deletions src/DisconnectedMidiOutNode.cpp

This file was deleted.

24 changes: 0 additions & 24 deletions src/DisconnectedMidiOutNode.hpp

This file was deleted.

95 changes: 68 additions & 27 deletions src/MidiInNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,25 @@
namespace mc
{

MidiInNode::MidiInNode(const midi::InputInfo& input_info,
MidiInNode::MidiInNode(std::string_view input_name,
std::shared_ptr<midi::InputNode> midi_input_node,
const PortNameDisplay& port_name_display)
: m_input_info(input_info), m_midi_input_node(midi_input_node),
: m_input_name(input_name), m_midi_input_node(midi_input_node),
m_port_name_display(&port_name_display)
{
m_midi_input_node->enable_message_types(m_message_type_mask);
m_midi_input_node->add_observer(this);
if (m_midi_input_node)
{
m_midi_input_node->enable_message_types(m_message_type_mask);
m_midi_input_node->add_observer(this);
}
}

MidiInNode::~MidiInNode()
{
m_midi_input_node->remove_observer(this);
if (m_midi_input_node)
{
m_midi_input_node->remove_observer(this);
}
}

void MidiInNode::accept_serializer(nlohmann::json& j, const NodeSerializer& serializer) const
Expand All @@ -40,37 +46,39 @@ midi::Node* MidiInNode::get_midi_node()

void MidiInNode::render_internal()
{
check_midi_node_connected();

ImNodes::BeginNodeTitleBar();
const std::string node_title = m_port_name_display->get_port_name(m_input_info);
const std::string node_title = m_port_name_display->get_port_name(m_input_name);
ImGui::TextUnformatted(node_title.c_str());
ImNodes::EndNodeTitleBar();
ImNodes::BeginOutputAttribute(out_id());
m_midi_activity.render();
ImGui::SameLine();
ImGui::TextUnformatted("all channels");
if (m_midi_input_node)
{
m_midi_activity.render();
ImGui::SameLine();
ImGui::TextUnformatted("all channels");
}
else
{
ImGui::TextUnformatted("disconnected");
}
ImNodes::EndOutputAttribute();

if (m_midi_input_node == nullptr)
{
return;
}

ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4{});
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4{});
if (ImGui::TreeNode("Advanced"))
{
bool message_type_mask_changed = false;
if (ImGui::Checkbox("Receive SysEx", &m_message_type_mask.m_sysex_enabled))
{
message_type_mask_changed = true;
}
if (ImGui::Checkbox("Receive MIDI Clock", &m_message_type_mask.m_time_enabled))
{
message_type_mask_changed = true;
}
if (ImGui::Checkbox("Receive Active Sensing", &m_message_type_mask.m_sensing_enabled))
{
message_type_mask_changed = true;
}
if (message_type_mask_changed)
{
m_midi_input_node->enable_message_types(m_message_type_mask);
}
midi::MessageTypeMask new_message_type_mask;
ImGui::Checkbox("Receive SysEx", &new_message_type_mask.m_sysex_enabled);
ImGui::Checkbox("Receive MIDI Clock", &new_message_type_mask.m_time_enabled);
ImGui::Checkbox("Receive Active Sensing", &new_message_type_mask.m_sensing_enabled);
set_message_type_mask(new_message_type_mask);
ImGui::TreePop();
}
ImGui::PopStyleColor(2);
Expand All @@ -81,10 +89,43 @@ void MidiInNode::message_processed(std::span<const unsigned char> /*message_byte
m_midi_activity.trigger();
}

void MidiInNode::check_midi_node_connected()
{
const auto input_opt = midi::MidiProbe::get_valid_input(m_input_name);
if (input_opt && m_midi_input_node == nullptr)
{
m_midi_input_node = std::make_shared<midi::InputNode>(*input_opt);
m_midi_input_node->enable_message_types(m_message_type_mask);
m_midi_input_node->add_observer(this);
for (auto output_connected_node : get_output_connections())
{
if (auto node = output_connected_node.lock(); node != nullptr)
{
if (auto* midi_node = node->get_midi_node(); midi_node != nullptr)
{
midi::Connection::create(*m_midi_input_node, *midi_node);
}
}
}
}
else if (!input_opt && m_midi_input_node != nullptr)
{
m_midi_input_node->remove_observer(this);
m_midi_input_node = nullptr;
}
}

void MidiInNode::set_message_type_mask(midi::MessageTypeMask new_value)
{
if (m_message_type_mask == new_value)
{
return;
}
m_message_type_mask = new_value;
m_midi_input_node->enable_message_types(new_value);
if (m_midi_input_node)
{
m_midi_input_node->enable_message_types(new_value);
}
}

} // namespace mc
8 changes: 5 additions & 3 deletions src/MidiInNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "midi/MessageTypeMask.hpp"
#include "midi/MidiInfo.hpp"

#include <optional>

namespace mc
{
namespace midi
Expand All @@ -18,14 +20,13 @@ class PortNameDisplay;
class MidiInNode final : public Node, private midi::GraphObserver
{
public:
MidiInNode(const midi::InputInfo& input_info,
MidiInNode(std::string_view input_name,
std::shared_ptr<midi::InputNode> midi_input_node,
const PortNameDisplay& port_name_display);

~MidiInNode();

void accept_serializer(nlohmann::json& j, const NodeSerializer& serializer) const override;
const midi::InputInfo& get_info() const { return m_input_info; }

protected:
midi::Node* get_midi_node() override;
Expand All @@ -34,9 +35,10 @@ class MidiInNode final : public Node, private midi::GraphObserver
void render_internal() override;
void message_processed(std::span<const unsigned char> message_bytes) override;

void check_midi_node_connected();
void set_message_type_mask(midi::MessageTypeMask new_value);

midi::InputInfo m_input_info;
std::string m_input_name;
std::shared_ptr<midi::InputNode> m_midi_input_node;
ActivityIndicator m_midi_activity;
const PortNameDisplay* m_port_name_display;
Expand Down
58 changes: 50 additions & 8 deletions src/MidiOutNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,30 @@

#include "NodeSerializer.hpp"
#include "PortNameDisplay.hpp"
#include "midi/MidiProbe.hpp"
#include "midi/OutputNode.hpp"

namespace mc
{

MidiOutNode::MidiOutNode(const midi::OutputInfo& output_info,
MidiOutNode::MidiOutNode(std::string_view output_name,
std::shared_ptr<midi::OutputNode> midi_output_node,
const PortNameDisplay& port_name_display)
: m_output_info(output_info), m_midi_output_node(midi_output_node),
: m_output_name(output_name), m_midi_output_node(midi_output_node),
m_port_name_display(&port_name_display)
{
m_midi_output_node->add_observer(this);
if (m_midi_output_node)
{
m_midi_output_node->add_observer(this);
}
}

MidiOutNode::~MidiOutNode()
{
m_midi_output_node->remove_observer(this);
if (m_midi_output_node)
{
m_midi_output_node->remove_observer(this);
}
}

void MidiOutNode::accept_serializer(nlohmann::json& j, const NodeSerializer& serializer) const
Expand All @@ -36,14 +43,24 @@ midi::Node* MidiOutNode::get_midi_node()

void MidiOutNode::render_internal()
{
check_midi_node_connected();

ImNodes::BeginNodeTitleBar();
const std::string node_title = m_port_name_display->get_port_name(m_output_info);
const std::string node_title = m_port_name_display->get_port_name(m_output_name);
ImGui::TextUnformatted(node_title.c_str());
ImNodes::EndNodeTitleBar();
ImNodes::BeginInputAttribute(in_id());
m_midi_activity.render();
ImGui::SameLine();
ImGui::TextUnformatted("all channels");

if (m_midi_output_node)
{
m_midi_activity.render();
ImGui::SameLine();
ImGui::TextUnformatted("all channels");
}
else
{
ImGui::TextUnformatted("disconnected");
}

ImNodes::EndInputAttribute();
}
Expand All @@ -53,4 +70,29 @@ void MidiOutNode::message_received(std::span<const unsigned char> /*message_byte
m_midi_activity.trigger();
}

void MidiOutNode::check_midi_node_connected()
{
const auto output_opt = midi::MidiProbe::get_valid_output(m_output_name);
if (output_opt && m_midi_output_node == nullptr)
{
m_midi_output_node = std::make_shared<midi::OutputNode>(*output_opt);
m_midi_output_node->add_observer(this);
for (auto input_connected_node : get_input_connections())
{
if (auto node = input_connected_node.lock(); node != nullptr)
{
if (auto* midi_node = node->get_midi_node(); midi_node != nullptr)
{
midi::Connection::create(*midi_node, *m_midi_output_node);
}
}
}
}
else if (!output_opt && m_midi_output_node != nullptr)
{
m_midi_output_node->remove_observer(this);
m_midi_output_node = nullptr;
}
}

} // namespace mc
Loading

0 comments on commit 0be5131

Please sign in to comment.