diff options
| author | Eddy Pedroni <epedroni@pm.me> | 2025-11-16 18:03:00 +0100 |
|---|---|---|
| committer | Eddy Pedroni <epedroni@pm.me> | 2025-11-16 18:03:00 +0100 |
| commit | 34b30a75b1a741c704aff64edc12fbfbf51f6523 (patch) | |
| tree | 322389ec69a3ae3778c3015d0ea1636f5f2e0451 | |
| parent | e68dfd37d0e131be03d0f852f0e5d128f28155b6 (diff) | |
Add support for virtual devices
| -rw-r--r-- | daemon/src/config.cpp | 22 | ||||
| -rw-r--r-- | daemon/src/connection_manager.cpp | 6 | ||||
| -rw-r--r-- | daemon/src/device_connection.h | 35 | ||||
| -rw-r--r-- | daemon/src/main.cpp | 2 | ||||
| -rw-r--r-- | daemon/src/types.h | 3 |
5 files changed, 51 insertions, 17 deletions
diff --git a/daemon/src/config.cpp b/daemon/src/config.cpp index b711d52..6859571 100644 --- a/daemon/src/config.cpp +++ b/daemon/src/config.cpp @@ -49,7 +49,7 @@ Config_Loader::Config_Loader(std::string url) auto toml_config = toml::parse(m_file_contents); - auto* devices = toml_config["devices"].as_table(); + auto const * devices = toml_config["devices"].as_table(); if (!devices) { std::cerr << "Expected \"devices\" to be a table.\n"; @@ -58,7 +58,19 @@ Config_Loader::Config_Loader(std::string url) for (auto&& [id, name] : *devices) { - m_device_map[name.as_string()->get()] = id.str(); + m_device_map[name.as_string()->get()] = std::make_pair<Device_Id, bool>(std::string{id.str()}, false); + } + + auto const * virtual_devices = toml_config["virtual"].as_table(); + if (!virtual_devices) + { + std::cerr << "Expected \"virtual\" to be a table.\n"; + return; + } + + for (auto && [id, name] : *virtual_devices) + { + m_device_map[name.as_string()->get()] = std::make_pair<Device_Id, bool>(std::string{id.str()}, true); } } @@ -132,8 +144,9 @@ add_type_routes(Device_Map const & device_map, Device_Id const & from_device, Ro std::string to_device = device.as_string()->get(); if (to_device == "all") { - for (auto&& [name, id] : device_map) + for (auto&& [name, details] : device_map) { + Device_Id const & id = details.first; if (id == from_device) continue; if (auto sender = cm.get_sender(id)) { @@ -159,8 +172,9 @@ Config_Loader::compile_route_table(Connection_Manager const & cm) auto toml_config = toml::parse(m_file_contents); - for (auto && [name, id] : m_device_map) + for (auto && [name, details] : m_device_map) { + Device_Id const & id = details.first; auto * to_routes = toml_config["route"]["from"][id]["to"].as_table(); if (to_routes) { diff --git a/daemon/src/connection_manager.cpp b/daemon/src/connection_manager.cpp index f608ce3..4244a9c 100644 --- a/daemon/src/connection_manager.cpp +++ b/daemon/src/connection_manager.cpp @@ -34,9 +34,11 @@ Connection_Manager::Connection_Manager(Device_Map const & device_map, Submitter m_connections{}, m_detector(std::bind(&Connection_Manager::detect_devices, this)) { - for (auto const & [name, id] : device_map) + for (auto const & [name, details] : device_map) { - m_connections[id] = std::make_unique<Device_Connection>(id, name, submitter, callback); + Device_Id const & id = details.first; + bool const virtual_device = details.second; + m_connections[id] = std::make_unique<Device_Connection>(id, name, submitter, callback, virtual_device); } refresh_devices(true, false); } diff --git a/daemon/src/device_connection.h b/daemon/src/device_connection.h index 5f2b051..9113f04 100644 --- a/daemon/src/device_connection.h +++ b/daemon/src/device_connection.h @@ -14,11 +14,18 @@ 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): + Device_Connection(Device_Id const & source_id, std::string const & device_name, Submitter & submitter, RtMidiIn::RtMidiCallback callback, bool virtual_device): source_id(source_id), device_name(device_name), - submitter(submitter) + submitter(submitter), + virtual_device(virtual_device) { + if (virtual_device) + { + midi_in.openVirtualPort(device_name + " In"); + midi_out.openVirtualPort(device_name + " Out"); + } + midi_in.setCallback(callback, this); midi_in.ignoreTypes(true, false, true); } @@ -26,6 +33,7 @@ struct Device_Connection : public Sender Device_Id const & source_id; std::string const & device_name; Submitter & submitter; + bool const virtual_device; RtMidiIn midi_in {}; RtMidiOut midi_out {}; std::mutex mutex {}; @@ -34,7 +42,10 @@ struct Device_Connection : public Sender send(std::vector<std::uint8_t> const & payload) override { const std::lock_guard<std::mutex> lock(mutex); - if (midi_out.isPortOpen()) midi_out.sendMessage(&payload); + if (midi_out.isPortOpen() || virtual_device) + { + midi_out.sendMessage(&payload); + } } std::string @@ -46,17 +57,23 @@ struct Device_Connection : public Sender void connect(std::size_t port) { - const std::lock_guard<std::mutex> lock(mutex); - if (!midi_in.isPortOpen()) midi_in.openPort(port); - if (!midi_out.isPortOpen()) midi_out.openPort(port); + if (!virtual_device) + { + const std::lock_guard<std::mutex> lock(mutex); + if (!midi_in.isPortOpen()) midi_in.openPort(port); + if (!midi_out.isPortOpen()) midi_out.openPort(port); + } } void disconnect() { - const std::lock_guard<std::mutex> lock(mutex); - if (midi_in.isPortOpen()) midi_in.closePort(); - if (midi_out.isPortOpen()) midi_out.closePort(); + if (!virtual_device) + { + const std::lock_guard<std::mutex> lock(mutex); + if (midi_in.isPortOpen()) midi_in.closePort(); + if (midi_out.isPortOpen()) midi_out.closePort(); + } } }; diff --git a/daemon/src/main.cpp b/daemon/src/main.cpp index 8ca0dd6..b2b1e52 100644 --- a/daemon/src/main.cpp +++ b/daemon/src/main.cpp @@ -9,7 +9,7 @@ using namespace midi_router; -bool verbose = false; +bool const verbose = true; int main() { diff --git a/daemon/src/types.h b/daemon/src/types.h index 78e85df..251adf8 100644 --- a/daemon/src/types.h +++ b/daemon/src/types.h @@ -8,6 +8,7 @@ #include <map> #include <vector> #include <functional> +#include <utility> namespace midi_router { @@ -31,7 +32,7 @@ enum class Message_Type }; using Device_Id = std::string; -using Device_Map = std::map<std::string, Device_Id>; +using Device_Map = std::map<std::string, std::pair<Device_Id, bool>>; using Target_List = std::vector<std::reference_wrapper<Sender>>; using Route_Table = std::map<Device_Id, std::map<Message_Type, Target_List>>; |
