aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddy Pedroni <epedroni@pm.me>2025-11-16 18:03:00 +0100
committerEddy Pedroni <epedroni@pm.me>2025-11-16 18:03:00 +0100
commit34b30a75b1a741c704aff64edc12fbfbf51f6523 (patch)
tree322389ec69a3ae3778c3015d0ea1636f5f2e0451
parente68dfd37d0e131be03d0f852f0e5d128f28155b6 (diff)
Add support for virtual devices
-rw-r--r--daemon/src/config.cpp22
-rw-r--r--daemon/src/connection_manager.cpp6
-rw-r--r--daemon/src/device_connection.h35
-rw-r--r--daemon/src/main.cpp2
-rw-r--r--daemon/src/types.h3
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>>;