diff options
author | Eddy Pedroni <epedroni@pm.me> | 2025-07-24 07:27:51 +0200 |
---|---|---|
committer | Eddy Pedroni <epedroni@pm.me> | 2025-07-24 07:27:51 +0200 |
commit | 49880b85de3d18f21792b9333571a396975697a0 (patch) | |
tree | 0e287353e6705b72f98e73d967bf3b91d9bc15b8 | |
parent | c5c195ff5318f00d544c0fbceb133abcc4ba7a5a (diff) |
Add udev notification support for connecting/disconnecting devices
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | daemon/Makefile | 2 | ||||
m--------- | daemon/include/udevw | 0 | ||||
-rw-r--r-- | daemon/src/connection_manager.cpp | 69 | ||||
-rw-r--r-- | daemon/src/connection_manager.h | 8 | ||||
-rw-r--r-- | daemon/src/device_connection.h | 81 | ||||
-rw-r--r-- | daemon/src/main.cpp | 2 |
7 files changed, 105 insertions, 60 deletions
diff --git a/.gitmodules b/.gitmodules index f69032b..ee7c8f8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "daemon/include/tomlplusplus"] path = daemon/include/tomlplusplus url = https://github.com/marzer/tomlplusplus.git +[submodule "daemon/include/udevw"] + path = daemon/include/udevw + url = https://github.com/SpencerMichaels/udevw.git diff --git a/daemon/Makefile b/daemon/Makefile index 9869b08..4b08c32 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -24,7 +24,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS)) # These files will have .d instead of .o as the output. CPPFLAGS := -O3 -std=c++23 $(INC_FLAGS) -MMD -MP -LDFLAGS := -lrtmidi -lcurl +LDFLAGS := -lrtmidi -lcurl -ludev # The final build step. $(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) diff --git a/daemon/include/udevw b/daemon/include/udevw new file mode 160000 +Subproject 71228484dcafcb7f22c1a2223f779376d61b47d diff --git a/daemon/src/connection_manager.cpp b/daemon/src/connection_manager.cpp index 6de1800..ac4c6cb 100644 --- a/daemon/src/connection_manager.cpp +++ b/daemon/src/connection_manager.cpp @@ -1,41 +1,15 @@ #include "connection_manager.h" -#include "sender.h" +#include "device_connection.h" + +#include "udevw/include/udevw.hpp" #include <iostream> -#include <rtmidi/RtMidi.h> +#include <chrono> namespace midi_router { -struct Device_Connection : public Sender -{ - Device_Connection(Device_Id const & source_id, Submitter & submitter): - source_id(source_id), - submitter(submitter) - {} - - Device_Id const & source_id; - Submitter & submitter; - RtMidiIn midi_in {}; - RtMidiOut midi_out {}; - - void - send(std::vector<std::uint8_t> const & payload) override - { - if (midi_out.isPortOpen()) - { - midi_out.sendMessage(&payload); - } - } - - std::string - get_id() const override - { - return source_id; - } -}; - static void callback(double time_stamp, std::vector<unsigned char> *raw, void *user_data) { @@ -56,26 +30,13 @@ callback(double time_stamp, std::vector<unsigned char> *raw, void *user_data) Connection_Manager::Connection_Manager(Device_Map const & device_map, Submitter & submitter): m_device_map(device_map), m_submitter(submitter), - m_connections{} + m_connections{}, + m_detector(std::bind(&Connection_Manager::detect_devices, this)) { for (auto const & [name, id] : device_map) { - m_connections[id] = std::make_unique<Device_Connection>(id, submitter); - auto & connection = m_connections[id]; - - connection->midi_in.setCallback(&callback, connection.get()); - connection->midi_in.ignoreTypes(true, false, true); - - if (!open_port(&connection->midi_in, name)) - { - std::cerr << "Input port not found for device " << name << "\n"; - } - - if (!open_port(&connection->midi_out, name)) - { - std::cerr << "Output port not found for device " << name << "\n"; - } - + m_connections[id] = std::make_unique<Device_Connection>(id, name, submitter, callback); + m_connections[id]->open(); } } @@ -87,18 +48,18 @@ Connection_Manager::get_sender(Device_Id const & device) const return *m_connections.at(device); } -bool -Connection_Manager::open_port(RtMidi* const midi, std::string const & name) +void +Connection_Manager::detect_devices() { - for (std::size_t i = 0; i < midi->getPortCount(); ++i) + while (true) { - if (midi->getPortName(i).contains(name)) + std::cout << "Polling for devices\n"; + std::this_thread::sleep_for(std::chrono::seconds(1)); + for (auto && [id, connection] : m_connections) { - midi->openPort(i); - return true; + connection->open(); } } - return false; } } // namespace midi_router diff --git a/daemon/src/connection_manager.h b/daemon/src/connection_manager.h index e15eaaa..21977a4 100644 --- a/daemon/src/connection_manager.h +++ b/daemon/src/connection_manager.h @@ -7,8 +7,7 @@ #include <string> #include <memory> #include <map> - -class RtMidi; +#include <thread> namespace midi_router { @@ -26,12 +25,13 @@ public: get_sender(Device_Id const & device) const; private: - static bool - open_port(RtMidi* const midi, std::string const & name); + void + detect_devices(); Device_Map const & m_device_map; Submitter & m_submitter; std::map<Device_Id, std::unique_ptr<Device_Connection>> m_connections; + std::thread m_detector; }; } // namespace midi_router diff --git a/daemon/src/device_connection.h b/daemon/src/device_connection.h new file mode 100644 index 0000000..17e354d --- /dev/null +++ b/daemon/src/device_connection.h @@ -0,0 +1,81 @@ +#pragma once + +#include "types.h" +#include "submitter.h" +#include "sender.h" + +#include <rtmidi/RtMidi.h> + +#include <string> + +namespace midi_router +{ + +struct Device_Connection : public Sender +{ + Device_Connection(Device_Id const & source_id, std::string const & device_name, Submitter & submitter, RtMidiIn::RtMidiCallback callback): + source_id(source_id), + device_name(device_name), + submitter(submitter) + { + midi_in.setCallback(callback, this); + midi_in.ignoreTypes(true, false, true); + } + + Device_Id const & source_id; + std::string const & device_name; + Submitter & submitter; + RtMidiIn midi_in {}; + RtMidiOut midi_out {}; + + void + send(std::vector<std::uint8_t> const & payload) override + { + midi_out.sendMessage(&payload); + } + + std::string + get_id() const override + { + return source_id; + } + + void + open() + { + if (!open_port(midi_in, device_name)) + { + std::cerr << "Input port not found for device " << device_name << "\n"; + } + + if (!open_port(midi_out, device_name)) + { + std::cerr << "Output port not found for device " << device_name << "\n"; + } + } + + void + close() + { + midi_in.closePort(); + midi_out.closePort(); + } + +private: + bool + open_port(RtMidi & midi, std::string const & name) + { + for (std::size_t i = 0; i < midi.getPortCount(); ++i) + { + if (midi.getPortName(i).contains(name)) + { + midi.openPort(i); + return true; + } + } + return false; + } +}; + +} // namespace midi_router + diff --git a/daemon/src/main.cpp b/daemon/src/main.cpp index 8ca0dd6..f131f92 100644 --- a/daemon/src/main.cpp +++ b/daemon/src/main.cpp @@ -9,7 +9,7 @@ using namespace midi_router; -bool verbose = false; +bool verbose = true; int main() { |