aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddy Pedroni <epedroni@pm.me>2025-07-24 07:27:51 +0200
committerEddy Pedroni <epedroni@pm.me>2025-07-24 07:27:51 +0200
commit49880b85de3d18f21792b9333571a396975697a0 (patch)
tree0e287353e6705b72f98e73d967bf3b91d9bc15b8
parentc5c195ff5318f00d544c0fbceb133abcc4ba7a5a (diff)
Add udev notification support for connecting/disconnecting devices
-rw-r--r--.gitmodules3
-rw-r--r--daemon/Makefile2
m---------daemon/include/udevw0
-rw-r--r--daemon/src/connection_manager.cpp69
-rw-r--r--daemon/src/connection_manager.h8
-rw-r--r--daemon/src/device_connection.h81
-rw-r--r--daemon/src/main.cpp2
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()
{