MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
PlotProcessor.hpp
Go to the documentation of this file.
1#pragma once
2
4
6
7namespace MayaFlux::Nodes {
8class Node;
9namespace Network {
10 class NodeNetwork;
11}
12}
13
14namespace MayaFlux::Buffers {
15class AudioBuffer;
16}
17
18namespace MayaFlux::Kakshya {
19
20/**
21 * @class PlotProcessor
22 * @brief DataProcessor that acquires per-series data from heterogeneous sources
23 * and writes into PlotContainer::m_data each process() call.
24 *
25 * Mirrors the source-binding model of DescriptorBindingsProcessor but targets
26 * CPU-side DataVariant storage rather than GPU descriptor sets. Each series slot
27 * in the container has one binding. All reads are EXTERNAL — the processor never
28 * drives node or network processing; it only samples already-processed state.
29 *
30 * Source types per series:
31 * NODE — single Node, reads get_last_output() → scalar appended or
32 * overwrites the series depending on mode (rolling vs snapshot)
33 * AUDIO_BUFFER — AudioBuffer, reads get_data() span → full series copy
34 * NETWORK — NodeNetwork with audio output, reads get_audio_buffer() → full series copy
35 * CALLABLE — std::function<void(std::vector<double>&)>, caller fills the series
36 * RAW — pending std::vector<double> pushed via set_raw(), swapped in on process()
37 *
38 * process() iterates all bindings, acquires from source, writes into the container's
39 * m_data variant at the bound series index, then copies m_data into processed_data.
40 * Called by Forma immediately before the geometry function runs.
41 */
42class MAYAFLUX_API PlotProcessor : public DataProcessor {
43public:
44 enum class SourceType : uint8_t {
45 NODE,
46 AUDIO_BUFFER,
47 NETWORK,
48 CALLABLE,
49 RAW,
50 };
51
53 SourceType source_type { SourceType::RAW };
54 DataDimension::Role role { DataDimension::Role::CUSTOM };
55 DataModality modality { DataModality::TENSOR_ND };
56
57 std::shared_ptr<Nodes::Node> node;
58 std::shared_ptr<Buffers::AudioBuffer> audio_buffer;
59 std::shared_ptr<Nodes::Network::NodeNetwork> network;
60 std::function<void(std::vector<double>&)> callable;
61
62 std::vector<double> pending_raw;
63 std::atomic_flag raw_dirty = ATOMIC_FLAG_INIT;
64 };
65
66 PlotProcessor() = default;
67 ~PlotProcessor() override = default;
68
69 // =========================================================================
70 // Binding
71 // =========================================================================
72
73 /**
74 * @brief Bind a series slot to a Node.
75 *
76 * Each process() calls Buffers::extract_multiple_samples(node, series_size),
77 * which handles snapshot context, save/restore state, and buffer lifecycle
78 * identically to NodeSourceProcessor. The series is filled with one full
79 * batch of node output per process() call.
80 *
81 * @param series_index Index returned by PlotContainer::add_series().
82 * @param node Node to read from.
83 */
84 void bind_node(uint32_t series_index,
85 std::shared_ptr<Nodes::Node> node);
86
87 /**
88 * @brief Bind a series slot to an AudioBuffer.
89 *
90 * Each process() copies the full buffer span into the series.
91 * Series size is resized to match the buffer on the first process() call.
92 *
93 * @param series_index Index returned by PlotContainer::add_series().
94 * @param buffer AudioBuffer to read from.
95 */
96 void bind_audio_buffer(uint32_t series_index,
97 std::shared_ptr<Buffers::AudioBuffer> buffer);
98
99 /**
100 * @brief Bind a series slot to a NodeNetwork with audio output.
101 *
102 * Each process() reads get_audio_buffer() and copies the result into the series.
103 * Fails at bind time if the network has no audio output mode.
104 *
105 * @param series_index Index returned by PlotContainer::add_series().
106 * @param network NodeNetwork to read from.
107 */
108 void bind_network(uint32_t series_index,
109 std::shared_ptr<Nodes::Network::NodeNetwork> network);
110
111 /**
112 * @brief Bind a series slot to a callable.
113 *
114 * Each process() calls fn with the series vector by reference. The callable
115 * fills or mutates it freely. Suitable for computed series, ring buffer views,
116 * and any source that does not fit the other patterns.
117 *
118 * @param series_index Index returned by PlotContainer::add_series().
119 * @param fn Callable invoked with the series vector each process().
120 */
121 void bind_callable(uint32_t series_index,
122 std::function<void(std::vector<double>&)> fn);
123
124 /**
125 * @brief Push raw sample data for a series.
126 *
127 * Lock-free pending swap. The data is committed into the container on the
128 * next process() call. Thread-safe: may be called from any thread.
129 *
130 * @param series_index Index returned by PlotContainer::add_series().
131 * @param data Samples to write. Copied into a pending buffer.
132 */
133 void set_raw(uint32_t series_index, std::vector<double> data);
134
135 /**
136 * @brief Remove a binding from a series slot.
137 * @param series_index Series index to unbind.
138 */
139 void unbind(uint32_t series_index);
140
141 /**
142 * @brief Set the role and modality for a series binding.
143 *
144 * Called by PlotContainer after every bind_* to propagate the semantic
145 * metadata declared on add_series() down into the binding. process() uses
146 * these values to tag each processed_data variant's dimension correctly,
147 * so DomainMapping can query by Role rather than by index.
148 *
149 * @param series_index Series index.
150 * @param role DataDimension::Role declared on add_series().
151 * @param modality DataModality declared on add_series().
152 */
153 void set_series_semantics(uint32_t series_index,
155 DataModality modality);
156
157 [[nodiscard]] bool has_binding(uint32_t series_index) const;
158
159 // =========================================================================
160 // DataProcessor
161 // =========================================================================
162
163 void on_attach(const std::shared_ptr<SignalSourceContainer>& container) override;
164 void on_detach(const std::shared_ptr<SignalSourceContainer>& container) override;
165
166 /**
167 * @brief Acquire data from all bound sources and write into the container.
168 *
169 * For each bound series: acquires from source, writes into container m_data,
170 * then copies m_data into processed_data. Unbound series are left unchanged.
171 * Called from the graphics thread by Forma before the geometry function runs.
172 */
173 void process(const std::shared_ptr<SignalSourceContainer>& container) override;
174
175 [[nodiscard]] bool is_processing() const override
176 {
177 return m_processing.load(std::memory_order_acquire);
178 }
179
180private:
181 void acquire_from_node(SeriesBinding& b, std::vector<double>& series);
182 void acquire_from_audio_buffer(SeriesBinding& b, std::vector<double>& series);
183 void acquire_from_network(SeriesBinding& b, std::vector<double>& series);
184 void acquire_from_callable(SeriesBinding& b, std::vector<double>& series);
185 void acquire_from_raw(SeriesBinding& b, std::vector<double>& series);
186
187 std::unordered_map<uint32_t, SeriesBinding> m_bindings;
188 std::atomic<bool> m_processing { false };
189};
190
191} // namespace MayaFlux::Kakshya
Core::GlobalNetworkConfig network
Definition Config.cpp:37
size_t b
Interface for processing data within SignalSourceContainer objects.
~PlotProcessor() override=default
bool is_processing() const override
Checks if the processor is currently performing processing.
std::unordered_map< uint32_t, SeriesBinding > m_bindings
DataProcessor that acquires per-series data from heterogeneous sources and writes into PlotContainer:...
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:81
Contains the node-based computational processing system components.
Definition Chronie.hpp:14
Role
Semantic role of the dimension.
Definition NDData.hpp:150
std::shared_ptr< Buffers::AudioBuffer > audio_buffer
std::function< void(std::vector< double > &)> callable
std::shared_ptr< Nodes::Network::NodeNetwork > network