From 73366165d468791abf4e87d1a2adc8f37f0b9d54 Mon Sep 17 00:00:00 2001 From: Annwan Date: Sun, 29 Sep 2024 06:05:51 +0200 Subject: [PATCH] [UNBORKED] basic functionality --- src/Application.cppm | 35 ++++++++++++++-------------- src/Node.cppm | 25 ++++++++++---------- src/Nodes/ConstantNode.cpp | 13 +++++++++++ src/Nodes/InputNode.cpp | 7 +++--- src/Nodes/OutputNode.cpp | 11 ++++----- src/Nodes/SplitterNode.cpp | 4 ++-- src/Nodes/StreamSpecConstantNode.cpp | 34 --------------------------- src/Nodes/StringConstantNode.cpp | 13 ----------- src/Port.cppm | 26 +++++++-------------- src/Ports/OutputPort.cpp | 3 +-- 10 files changed, 63 insertions(+), 108 deletions(-) create mode 100644 src/Nodes/ConstantNode.cpp delete mode 100644 src/Nodes/StreamSpecConstantNode.cpp delete mode 100644 src/Nodes/StringConstantNode.cpp diff --git a/src/Application.cppm b/src/Application.cppm index 9e8af0b..b395feb 100644 --- a/src/Application.cppm +++ b/src/Application.cppm @@ -17,6 +17,7 @@ export module Application; import Node; import Base; import Button; +using command_line_options::detail::concat; using command_line_options::detail::list; namespace ffmpegraph { export class Application { @@ -62,10 +63,9 @@ Application::Application(std::string _title) InitWindow(800, 600, this->title.c_str()); SetTargetFPS(60); SetExitKey(KEY_NULL); - add_buttons.emplace_back(0, 0, 200, 20, "String Constant"); + add_buttons.emplace_back(0, 0, 200, 20, "Constant"); add_buttons.emplace_back(0, 0, 200, 20, "File Input"); add_buttons.emplace_back(0, 0, 200, 20, "File Output"); - add_buttons.emplace_back(0, 0, 200, 20, "Stream Spec Constant"); add_buttons.emplace_back(0, 0, 200, 20, "Splitter"); AllOptions::each([&]() { add_buttons.emplace_back(0, 0, 200, 20, std::string(T::label_view)); }); run_button.width = 10 + MeasureText("Run", 10); @@ -88,14 +88,7 @@ void Application::OnLeftClick() { if (current_state == State::ADDING) { usz i = 0; current_state = State::DEFAULT; - list::each([&]() { - if (add_buttons[i++].IsHovered()) { - nodes.push_back(std::make_unique()); - selected_node = nodes.back().get(); - current_state = State::EDITING; - } - }); - AllOptions::each([&]() { + concat, AllOptions>::each([&]() { if (add_buttons[i++].IsHovered()) { nodes.push_back(std::make_unique()); selected_node = nodes.back().get(); @@ -163,18 +156,20 @@ Result<> Application::ExecuteGraph() { if (auto n = dynamic_cast(raw_node)) { if (auto c = n->out.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); } } - if (auto n = dynamic_cast(raw_node)) { + if (auto n = dynamic_cast(raw_node)) { if (auto c = n->out.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); } } if (auto _ = dynamic_cast(raw_node)) {} // OutputNode doesn’t have output ports. - if (auto n = dynamic_cast(raw_node)) { - if (auto c = n->out.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); } - } if (auto n = dynamic_cast(raw_node)) { if (auto c = n->out1.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); } if (auto c = n->out2.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); } } + AllOptions::each([&] { + if (auto n = dynamic_cast(raw_node)) { + if (auto c = n->out.GetConnected()) { adj_list[index_map[c->owner]].insert(index_map[raw_node]); } + } + }); } // TODO add cases for all new types of nodes @@ -198,6 +193,12 @@ Result<> Application::ExecuteGraph() { } void Application::OnKeyPressed(i32 key) { + if (current_state == State::DEFAULT and key == KEY_C) { + nodes.push_back(std::make_unique()); + selected_node = nodes.back().get(); + current_state = State::EDITING; + return; + } if ((key == KEY_EQUAL or key == KEY_KP_ADD) and current_state == State::DEFAULT) { current_state = State::ADDING; } if (current_state != State::EDITING) return; if (key == KEY_DELETE) { @@ -213,7 +214,7 @@ void Application::OnKeyPressed(i32 key) { current_state = State::DEFAULT; return; } - auto selected = dynamic_cast(selected_node); + auto selected = dynamic_cast(selected_node); if (not selected) return; if (key == KEY_ENTER or key == KEY_KP_ENTER) { selected_node = nullptr; @@ -257,7 +258,7 @@ void Application::Render() { framecounter++; if (not(framecounter % 300) and not message_queue.empty()) { message_queue.pop_back(); } BeginDrawing(); - ClearBackground(RAYWHITE); + ClearBackground(LIGHTGRAY); message_queue.resize(std::min(message_queue.size(), usz(10))); i32 offset = 15; for (auto &message : message_queue) { @@ -268,7 +269,7 @@ void Application::Render() { auto maxx = GetScreenWidth(); auto currentx = 10; auto currenty = 10; - for (auto b : add_buttons) { + for (auto &b : add_buttons) { b.pos_x = currentx; b.pos_y = currenty; b.Render(); diff --git a/src/Node.cppm b/src/Node.cppm index bf52120..9ed8666 100644 --- a/src/Node.cppm +++ b/src/Node.cppm @@ -9,6 +9,7 @@ import Base; using command_line_options::detail::list; using command_line_options::detail::static_string; +using command_line_options::detail::sort; export namespace ffmpegraph { struct Node { @@ -53,22 +54,14 @@ struct OutputNode : Node { InputPort filename; }; -struct StringConstantNode : Node { - StringConstantNode(); +struct ConstantNode : Node { + ConstantNode(); Label label; StringUserInput in; OutputPort out; Result<> Run() override; }; -struct StreamSpecConstantNode : Node { - StreamSpecConstantNode(); - Result<> Run() override; - Label label; - StringUserInput in; - OutputPort out; -}; - struct SplitterNode : Node { SplitterNode(); Result<> Run() override; @@ -122,7 +115,7 @@ struct SpecOptionNode : Node { Result<> Run() override { out.SetValue( std::format( - "{} {}{}{} {}", prev.GetValue(), ffmpegopt.sv(), std::get_if(&spec.GetValue()) ? "" : ":", + "{} {}{}{} {}", prev.GetValue(), ffmpegopt.sv(), spec.GetValue().empty() ? "" : ":", spec.GetValue(), arg.GetValue() ) ); @@ -137,6 +130,12 @@ struct SpecOptionNode : Node { static constexpr std::string_view label_view = name.sv(); }; + +template +struct get_option_name { + static constexpr std::string_view value = opt::label_view; +}; + // General options using ForceFormatOptionNode = OptionNode<"Force Format", "-f", PortTypeE::STRING>; using StreamLoopOptionNode = OptionNode<"Loop Stream", "-stream_loop", PortTypeE::INT, "Count">; @@ -158,11 +157,11 @@ using FrameLimitOptionNode = SpecOptionNode<"Frame Limit", "-frames", PortTypeE: using QualityScaleOptionNode = SpecOptionNode<"Quality Scale", "-qscale", PortTypeE::STRING>; using PresetOptionNode = SpecOptionNode<"Preset", "-pre", PortTypeE::STRING>; using ExtractAttachment = SpecOptionNode<"Extract Attachment", "-dump_attachment", PortTypeE::STRING, "Filename">; -using AllOptions = list< +using AllOptions = sort; + DispositionOptionNode, FrameLimitOptionNode, QualityScaleOptionNode, PresetOptionNode, ExtractAttachment>>; // -program [title=title:][program_num=program_num:]st=stream[:st=stream...] // -stream_group diff --git a/src/Nodes/ConstantNode.cpp b/src/Nodes/ConstantNode.cpp new file mode 100644 index 0000000..38dce4a --- /dev/null +++ b/src/Nodes/ConstantNode.cpp @@ -0,0 +1,13 @@ +module Node; +using namespace ffmpegraph; + +ConstantNode::ConstantNode() + : label("Constant", this), in("Text", this), out("Out", this, PortTypeE::CONSTANT) { + ports.push_back(&label); + ports.push_back(&in); + ports.push_back(&out); +} +Result<> ConstantNode::Run() { + out.SetValue(in.data); + return {}; +} diff --git a/src/Nodes/InputNode.cpp b/src/Nodes/InputNode.cpp index 164526a..e8fdd5c 100644 --- a/src/Nodes/InputNode.cpp +++ b/src/Nodes/InputNode.cpp @@ -1,6 +1,5 @@ module; #include -#include module Node; using namespace ffmpegraph; @@ -18,8 +17,8 @@ InputNode::InputNode() } Result<> InputNode::Run() { - auto data = std::get_if(&filename.GetValue()); - if (not data or data->empty()) return Error("File Input needs a filename "); - out.SetValue(std::format("{} {} -i '{}'", prev.GetValue(), opts.GetValue(), *data)); + auto& data = filename.GetValue(); + if (data.empty()) return Error("File Input needs a filename "); + out.SetValue(std::format("{} {} -i '{}'", prev.GetValue(), opts.GetValue(), data)); return {}; } diff --git a/src/Nodes/OutputNode.cpp b/src/Nodes/OutputNode.cpp index 71bffed..8d711ea 100644 --- a/src/Nodes/OutputNode.cpp +++ b/src/Nodes/OutputNode.cpp @@ -1,6 +1,5 @@ module; #include -#include module Node; using namespace ffmpegraph; @@ -16,9 +15,9 @@ OutputNode::OutputNode() } Result<> OutputNode::Run() { - auto data = std::get_if(&prev.GetValue()); - if (not data) return {}; - auto fname = std::get_if(&filename.GetValue()); - auto path = fname and not fname->empty() ? std::string_view{*fname} : "/tmp/ffmpegraph_out"; - return Error("ffmpeg -nostdin {} {} '{}'", *data, opts.GetValue(), path); + auto& data = prev.GetValue(); + if (data.empty()) return {}; + auto& fname = filename.GetValue(); + auto path = not fname.empty() ? std::string_view{fname} : "/tmp/ffmpegraph_out"; + return Error("ffmpeg -nostdin {} {} '{}'", data, opts.GetValue(), path); } diff --git a/src/Nodes/SplitterNode.cpp b/src/Nodes/SplitterNode.cpp index 37642d9..e902931 100644 --- a/src/Nodes/SplitterNode.cpp +++ b/src/Nodes/SplitterNode.cpp @@ -26,8 +26,8 @@ void SplitterNode::OnConnect() { void SplitterNode::OnDisconnect() { in.type = out1.type = out2.type = PortTypeE::GENERIC; - out1.Disconnect(); - out2.Disconnect(); + if (out1.GetConnected() != &in) out1.Disconnect(); + if (out2.GetConnected() != &in) out2.Disconnect(); } diff --git a/src/Nodes/StreamSpecConstantNode.cpp b/src/Nodes/StreamSpecConstantNode.cpp deleted file mode 100644 index 86ad484..0000000 --- a/src/Nodes/StreamSpecConstantNode.cpp +++ /dev/null @@ -1,34 +0,0 @@ -module Node; -using namespace ffmpegraph; - -StreamSpecConstantNode::StreamSpecConstantNode() - : label("Stream Specifier Constant", this), in("Stream Specifier", this), out("Out", this, PortTypeE::STREAM) { - ports.push_back(&label); - ports.push_back(&in); - ports.push_back(&out); -} -Result<> StreamSpecConstantNode::Run() { - // TODO validate that - // → - // - // [vVasdt](:)? - // g:(:)? - // p:(:)? - // # - // i: - // m:(:)? - // disp:(:)? - // u - // → [1-9][0-9]* - // → - // - // # - // i: - // → [a-zA-Z0-9_-]+ - // → - // - // + - - out.SetValue(in.data); - return {}; -} diff --git a/src/Nodes/StringConstantNode.cpp b/src/Nodes/StringConstantNode.cpp deleted file mode 100644 index 6029bee..0000000 --- a/src/Nodes/StringConstantNode.cpp +++ /dev/null @@ -1,13 +0,0 @@ -module Node; -using namespace ffmpegraph; - -StringConstantNode::StringConstantNode() - : label("String Constant", this), in("Text", this), out("Out", this, PortTypeE::STRING) { - ports.push_back(&label); - ports.push_back(&in); - ports.push_back(&out); -} -Result<> StringConstantNode::Run() { - out.SetValue(in.data); - return {}; -} diff --git a/src/Port.cppm b/src/Port.cppm index 6d5cbdc..2b04e39 100644 --- a/src/Port.cppm +++ b/src/Port.cppm @@ -2,7 +2,6 @@ module; #include #include #include -#include export module Node:Port; import Base; using namespace std::literals; @@ -16,6 +15,7 @@ enum struct PortTypeE { OPTIONS, INPUTS, DURATION, + CONSTANT }; struct PortType { @@ -38,6 +38,7 @@ template <> struct std::formatter : std::formatter struct std::formatter : std::formatter; -} -template <> struct std::formatter : std::formatter { - template auto format(ffmpegraph::PortData const& data, FormatContext& ctx) const { - auto repr = std::visit( - utils::Overloaded{ - [](std::monostate) { return ""s; }, - [](std::string const& x) { return x; }, - [](i32 x) { return std::to_string(x); }, - }, - data - ); - return formatter::format(repr, ctx); - } -}; +// Once upon a time, this was a 'std::variant'; regrettably, Clang disagreed with that +// notion. So now, instead, look at the port type to figure +// out what this is supposed to be. +using PortData = std::string; +} export namespace ffmpegraph { struct Port { @@ -81,7 +73,7 @@ struct OutputPort; struct InputPort : Port { protected: - PortData value = std::monostate{}; + PortData value; public: InputPort(std::string name, Node* owner, PortType type) : Port(std::move(name), owner), type(type) {} PortData const& GetValue() const; diff --git a/src/Ports/OutputPort.cpp b/src/Ports/OutputPort.cpp index 528cfbf..fbd6ebb 100644 --- a/src/Ports/OutputPort.cpp +++ b/src/Ports/OutputPort.cpp @@ -12,9 +12,8 @@ bool OutputPort::TryConnect(InputPort& ip) { ip.type = type; ip.owner->OnConnect(); } - if (ip.type == type) { + if (ip.type == type or type == PortTypeE::CONSTANT) { connected = &ip; - return true; } return false;