aboutsummaryrefslogtreecommitdiffstats
path: root/daemon/src
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/src')
-rw-r--r--daemon/src/configuration.h17
-rw-r--r--daemon/src/connection_manager.cpp74
-rw-r--r--daemon/src/connection_manager.h34
-rw-r--r--daemon/src/main.cpp24
-rw-r--r--daemon/src/message.h42
-rw-r--r--daemon/src/routing.cpp24
-rw-r--r--daemon/src/routing.h24
-rw-r--r--daemon/src/types.h15
8 files changed, 251 insertions, 3 deletions
diff --git a/daemon/src/configuration.h b/daemon/src/configuration.h
new file mode 100644
index 0000000..4189315
--- /dev/null
+++ b/daemon/src/configuration.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "types.h"
+
+#include <map>
+
+namespace midi_router
+{
+
+struct Configuration
+{
+
+ Device_Map const devices;
+ Route_Map const routes;
+};
+
+} // namespace midi_router
diff --git a/daemon/src/connection_manager.cpp b/daemon/src/connection_manager.cpp
new file mode 100644
index 0000000..820f1d2
--- /dev/null
+++ b/daemon/src/connection_manager.cpp
@@ -0,0 +1,74 @@
+#include "connection_manager.h"
+
+#include <iostream>
+#include <rtmidi/RtMidi.h>
+
+namespace midi_router
+{
+
+struct Device_Connection
+{
+ Device_Id source_id;
+ std::function<void(Message const &)> const & submit;
+ RtMidiIn midi_in {};
+ RtMidiOut midi_out {};
+};
+
+static void
+callback(double time_stamp, std::vector<unsigned char> *raw, void *user_data)
+{
+ Device_Connection* device = static_cast<Device_Connection*>(user_data);
+
+ if (raw->size() != 3)
+ {
+ std::cerr << "Received message with wrong size from " << device->source_id << ", dropping\n";
+ }
+
+ Message message { device->source_id, {raw->at(0), raw->at(1), raw->at(2)} };
+ device->submit(message);
+}
+
+Connection_Manager::Connection_Manager(Device_Map const & device_map, std::function<void(Message const &)> const & submit):
+ m_device_map(device_map),
+ m_submit(submit),
+ m_connections{}
+ {
+ for (auto const & [name, id] : device_map)
+ {
+ m_connections[id] = std::make_unique<Device_Connection>(id, submit);
+ auto & connection = m_connections[id];
+
+ connection->midi_in.setCallback(&callback, connection.get());
+ connection->midi_in.ignoreTypes(true, true, 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";
+ }
+
+ }
+ }
+
+Connection_Manager::~Connection_Manager() = default;
+
+bool
+Connection_Manager::open_port(RtMidi* const 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/connection_manager.h b/daemon/src/connection_manager.h
new file mode 100644
index 0000000..240e436
--- /dev/null
+++ b/daemon/src/connection_manager.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "types.h"
+#include "message.h"
+
+#include <functional>
+#include <string>
+#include <map>
+#include <memory>
+
+class RtMidi;
+
+namespace midi_router
+{
+
+struct Device_Connection;
+
+class Connection_Manager
+{
+public:
+ Connection_Manager(Device_Map const & device_map, std::function<void(Message const &)> const & submit);
+
+ ~Connection_Manager();
+
+private:
+ static bool
+ open_port(RtMidi* const midi, std::string const & name);
+
+ Device_Map const & m_device_map;
+ std::function<void(Message const &)> m_submit;
+ std::map<std::string, std::unique_ptr<Device_Connection>> m_connections;
+};
+
+} // namespace midi_router
diff --git a/daemon/src/main.cpp b/daemon/src/main.cpp
index 68d0a96..dc72433 100644
--- a/daemon/src/main.cpp
+++ b/daemon/src/main.cpp
@@ -1,8 +1,26 @@
+#include "connection_manager.h"
+#include "configuration.h"
+#include "routing.h"
+
#include <iostream>
-#include <rtmidi/RtMidi.h>
-#include "concurrentqueue/blockingconcurrentqueue.h"
+#include <thread>
+#include <chrono>
+
+using namespace midi_router;
int main()
{
- std::cout << "Hello, world\n";
+ Configuration const config {{
+ {"Deluge MIDI 1", "deluge"},
+ {"MPK mini Plus MIDI 1", "mpk"},
+ }};
+
+ Router router {};
+ Connection_Manager cm { config.devices, [&](Message const & m){ router.submit(m); } }; // works
+ //Connection_Manager cm { config.devices, std::bind(&Router::submit, &router, std::placeholders::_1) }; // why doesn't this work?
+
+ while(true)
+ {
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
}
diff --git a/daemon/src/message.h b/daemon/src/message.h
new file mode 100644
index 0000000..9339118
--- /dev/null
+++ b/daemon/src/message.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "types.h"
+
+#include <string>
+#include <cstdint>
+#include <array>
+
+namespace midi_router
+{
+
+struct Message
+{
+ enum class Type
+ {
+ NOTE_OFF = 0x8u,
+ NOTE_ON = 0x9u,
+ POLY_AT = 0xAu,
+ CONTROL_CHANGE = 0xBu,
+ PROGRAM_CHANGE = 0xCu,
+ CHANNEL_AT = 0xDu,
+ PITCH_WHEEL = 0xEu,
+
+ CLOCK = 0xF8u,
+ MEAS_END = 0xF9u,
+ START = 0xFAu,
+ CONTINUE = 0xFBu,
+ STOP = 0xFCu,
+ };
+
+ Device_Id const & source_id;
+ std::array<std::uint8_t, 3> const bytes;
+
+ Type
+ type() const
+ {
+ if (bytes[0] & 0xF0 == 0xF0) return static_cast<Type>(bytes[0]);
+ else return static_cast<Type>(bytes[0] >> 4);
+ }
+};
+
+} // namespace midi_router
diff --git a/daemon/src/routing.cpp b/daemon/src/routing.cpp
new file mode 100644
index 0000000..709d815
--- /dev/null
+++ b/daemon/src/routing.cpp
@@ -0,0 +1,24 @@
+#include "routing.h"
+
+#include <iostream>
+
+namespace midi_router
+{
+
+void
+Router::route(Route_Map const & config) const
+{
+
+}
+
+void
+Router::submit(Message const & message)
+{
+ if (!m_queue.try_enqueue(message))
+ {
+ std::cout << "Failed to enqueue message from " << message.source_id << "\n";
+ }
+}
+
+} // namespace midi_router
+
diff --git a/daemon/src/routing.h b/daemon/src/routing.h
new file mode 100644
index 0000000..2d68391
--- /dev/null
+++ b/daemon/src/routing.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "message.h"
+#include "configuration.h"
+
+#include "concurrentqueue/blockingconcurrentqueue.h"
+
+namespace midi_router
+{
+
+class Router
+{
+public:
+ void
+ route(Route_Map const & config) const;
+
+ void
+ submit(Message const & message);
+
+private:
+ moodycamel::BlockingConcurrentQueue<Message> m_queue {};
+};
+
+} // namespace midi_router
diff --git a/daemon/src/types.h b/daemon/src/types.h
new file mode 100644
index 0000000..f09fb88
--- /dev/null
+++ b/daemon/src/types.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <string>
+#include <map>
+#include <vector>
+
+namespace midi_router
+{
+
+using Device_Id = std::string;
+using Device_Map = std::map<std::string, Device_Id>;
+using Target_List = std::vector<Device_Id>;
+using Route_Map = std::map<Device_Id, Target_List>;
+
+} // namespace midi_router