feat: scaffold project framework with engine, node skeleton, and passthrough node
- CMake build system with vcpkg dependency management - libdmf-node: Node interface, port definitions, WebSocket control server, node runner with MXL lifecycle management - libdmf-engine: Graph model (nodes/edges CRUD, serialization), FlowManager (UUID + V210 NMOS flow definitions), ProcessManager (fork/exec node processes), ApiServer (REST API for graph control) - Passthrough node: reads V210 grains from MXL, copies, writes to MXL - Unit tests for Graph and FlowManager (6 cases, 21 assertions) - MXL SDK as git submodule (symlinked from extern/mxl)
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <dmf-engine/graph.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
struct lws_context;
|
||||
|
||||
namespace dmf_engine {
|
||||
|
||||
using RequestHandler = std::function<std::string(const std::string& method, const std::string& path, const std::string& body)>;
|
||||
|
||||
class ApiServer {
|
||||
public:
|
||||
ApiServer(uint16_t port, Graph& graph, class FlowManager& flow_manager, class ProcessManager& process_manager);
|
||||
~ApiServer();
|
||||
|
||||
ApiServer(const ApiServer&) = delete;
|
||||
ApiServer& operator=(const ApiServer&) = delete;
|
||||
|
||||
void poll(int timeout_ms);
|
||||
|
||||
private:
|
||||
void handle_rest(const std::string& method, const std::string& path, const std::string& body,
|
||||
std::string& response_status, std::string& response_content_type, std::string& response_body);
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
} // namespace dmf_engine
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <dmf-engine/types.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace dmf_engine {
|
||||
|
||||
class FlowManager {
|
||||
public:
|
||||
FlowManager();
|
||||
|
||||
FlowId create_flow_id();
|
||||
nlohmann::json create_v210_flow_def(const FlowId& flow_id, int width, int height, int fps_numerator, int fps_denominator) const;
|
||||
|
||||
private:
|
||||
int flow_counter_ = 0;
|
||||
};
|
||||
|
||||
} // namespace dmf_engine
|
||||
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <dmf-engine/types.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace dmf_engine {
|
||||
|
||||
enum class NodeState {
|
||||
Stopped,
|
||||
Starting,
|
||||
Running,
|
||||
Stopping,
|
||||
};
|
||||
|
||||
struct GraphNode {
|
||||
NodeId id;
|
||||
std::string type;
|
||||
nlohmann::json config;
|
||||
NodeState state = NodeState::Stopped;
|
||||
uint16_t control_port = 0;
|
||||
int pid = 0;
|
||||
};
|
||||
|
||||
struct GraphEdge {
|
||||
EdgeId id;
|
||||
NodeId from_node;
|
||||
PortId from_port;
|
||||
NodeId to_node;
|
||||
PortId to_port;
|
||||
FlowId flow_id;
|
||||
nlohmann::json flow_def;
|
||||
};
|
||||
|
||||
class Graph {
|
||||
public:
|
||||
NodeId add_node(const std::string& type, const nlohmann::json& config = {});
|
||||
bool remove_node(const NodeId& node_id);
|
||||
const GraphNode* get_node(const NodeId& node_id) const;
|
||||
std::vector<GraphNode> get_nodes() const;
|
||||
|
||||
EdgeId add_edge(const NodeId& from_node, const PortId& from_port,
|
||||
const NodeId& to_node, const PortId& to_port,
|
||||
const FlowId& flow_id, const nlohmann::json& flow_def);
|
||||
bool remove_edge(const EdgeId& edge_id);
|
||||
std::vector<GraphEdge> get_edges() const;
|
||||
std::vector<GraphEdge> get_edges_for_node(const NodeId& node_id) const;
|
||||
|
||||
nlohmann::json serialize() const;
|
||||
|
||||
private:
|
||||
std::unordered_map<NodeId, GraphNode> nodes_;
|
||||
std::unordered_map<EdgeId, GraphEdge> edges_;
|
||||
int next_node_num_ = 0;
|
||||
};
|
||||
|
||||
} // namespace dmf_engine
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <dmf-engine/graph.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace dmf_engine {
|
||||
|
||||
class ProcessManager {
|
||||
public:
|
||||
bool start_node(GraphNode& node, const std::string& mxl_domain, uint16_t base_port);
|
||||
bool stop_node(GraphNode& node);
|
||||
void stop_all();
|
||||
|
||||
bool is_running(const NodeId& node_id) const;
|
||||
|
||||
private:
|
||||
std::string find_node_binary(const std::string& node_type) const;
|
||||
};
|
||||
|
||||
} // namespace dmf_engine
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace dmf_engine {
|
||||
|
||||
using NodeId = std::string;
|
||||
using EdgeId = std::string;
|
||||
using FlowId = std::string;
|
||||
using PortId = std::string;
|
||||
|
||||
} // namespace dmf_engine
|
||||
Reference in New Issue
Block a user