feat: load pipeline graph from graph.json
studio-manager now accepts an optional path argument: dmf-studio-manager graph.json load_graph() parses nodes and edges from JSON, generating fresh UUIDs for each MXL flow on every launch. Falls back to hardcoded build_graph() when no argument is given. graph.json at repo root defines the current testpattern→ndiout pipeline. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+18
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{ "id": "testpattern", "type": "testpattern", "params": { "pattern": "bars" } },
|
||||||
|
{ "id": "ndiout", "type": "ndiout", "params": {} }
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"from": "testpattern", "from_port": "flow_id",
|
||||||
|
"to": "ndiout", "to_port": "flow_id",
|
||||||
|
"format": { "kind": "video", "width": 1920, "height": 1080, "fps_num": 25, "fps_den": 1 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "testpattern", "from_port": "audio_flow_id",
|
||||||
|
"to": "ndiout", "to_port": "audio_flow_id",
|
||||||
|
"format": { "kind": "audio", "sample_rate": 48000, "channels": 2, "bit_depth": 32 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+42
-1
@@ -5,6 +5,8 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -37,6 +39,45 @@ static std::string gen_uuid() {
|
|||||||
|
|
||||||
// --- Pipeline graph ----------------------------------------------------------
|
// --- Pipeline graph ----------------------------------------------------------
|
||||||
|
|
||||||
|
static dmf::FlowGraph load_graph(const std::string& path) {
|
||||||
|
std::ifstream f(path);
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "[studio-manager] cannot open graph file: %s\n", path.c_str());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << f.rdbuf();
|
||||||
|
|
||||||
|
auto j = nlohmann::json::parse(ss.str(), nullptr, /*allow_exceptions=*/false);
|
||||||
|
if (j.is_discarded()) {
|
||||||
|
fprintf(stderr, "[studio-manager] invalid JSON in %s\n", path.c_str());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dmf::FlowGraph g;
|
||||||
|
for (const auto& n : j.at("nodes")) {
|
||||||
|
g.nodes.push_back({
|
||||||
|
n.at("id").get<std::string>(),
|
||||||
|
n.at("type").get<std::string>(),
|
||||||
|
n.value("params", nlohmann::json::object())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (const auto& e : j.at("edges")) {
|
||||||
|
g.edges.push_back({
|
||||||
|
gen_uuid(),
|
||||||
|
e.at("from").get<std::string>(),
|
||||||
|
e.at("from_port").get<std::string>(),
|
||||||
|
e.value("to", std::string{}),
|
||||||
|
e.value("to_port", std::string{}),
|
||||||
|
e.at("format")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "[studio-manager] loaded graph from %s (%zu nodes, %zu edges)\n",
|
||||||
|
path.c_str(), g.nodes.size(), g.edges.size());
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
static dmf::FlowGraph build_graph() {
|
static dmf::FlowGraph build_graph() {
|
||||||
dmf::FlowGraph g;
|
dmf::FlowGraph g;
|
||||||
const std::string tp_video_flow = gen_uuid();
|
const std::string tp_video_flow = gen_uuid();
|
||||||
@@ -164,7 +205,7 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Build and launch the pipeline graph ---
|
// --- Build and launch the pipeline graph ---
|
||||||
const dmf::FlowGraph graph = build_graph();
|
const dmf::FlowGraph graph = (argc > 1) ? load_graph(argv[1]) : build_graph();
|
||||||
|
|
||||||
for (const auto& e : graph.edges)
|
for (const auto& e : graph.edges)
|
||||||
fprintf(stderr, "[studio-manager] flow %s → %s id=%s\n",
|
fprintf(stderr, "[studio-manager] flow %s → %s id=%s\n",
|
||||||
|
|||||||
Reference in New Issue
Block a user