MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Engine.cpp
Go to the documentation of this file.
1#include "Engine.hpp"
2
11
13
14#ifdef MAYAFLUX_PLATFORM_MACOS
15#include <CoreFoundation/CoreFoundation.h>
16#include <unistd.h>
17#endif
18
19#ifdef MAYAFLUX_PLATFORM_WINDOWS
21#endif
22
23namespace MayaFlux::Core {
24
25//-------------------------------------------------------------------------
26// Initialization and Lifecycle
27//-------------------------------------------------------------------------
28
30 : m_stochastic_engine(new Kinesis::Stochastic::Stochastic(Kinesis::Stochastic::Algorithm::UNIFORM))
31{
32}
33
35{
36 End();
37}
38
39Engine::Engine(Engine&& other) noexcept
40 : m_stream_info(other.m_stream_info)
41 , m_graphics_config(other.m_graphics_config)
42 , m_is_paused(other.m_is_paused)
43 , m_is_initialized(other.m_is_initialized)
44 , m_should_shutdown(other.m_should_shutdown.load())
45 , m_scheduler(std::move(other.m_scheduler))
46 , m_node_graph_manager(std::move(other.m_node_graph_manager))
47 , m_buffer_manager(std::move(other.m_buffer_manager))
48 , m_subsystem_manager(std::move(other.m_subsystem_manager))
49 , m_window_manager(std::move(other.m_window_manager))
50 , m_event_manager(std::move(other.m_event_manager))
51 , m_input_manager(std::move(other.m_input_manager))
52 , m_io_manager(std::move(other.m_io_manager))
53 , m_stochastic_engine(std::move(other.m_stochastic_engine))
54{
55 other.m_is_initialized = false;
56 other.m_is_paused = false;
57}
58
60{
61 if (this != &other) {
62 End();
63
64 m_stream_info = other.m_stream_info;
65 m_graphics_config = other.m_graphics_config;
66
67 m_subsystem_manager = std::move(other.m_subsystem_manager);
68 m_node_graph_manager = std::move(other.m_node_graph_manager);
69 m_buffer_manager = std::move(other.m_buffer_manager);
70 m_scheduler = std::move(other.m_scheduler);
71 m_window_manager = std::move(other.m_window_manager);
72 m_event_manager = std::move(other.m_event_manager);
73 m_input_manager = std::move(other.m_input_manager);
74 m_io_manager = std::move(other.m_io_manager);
75 m_stochastic_engine = std::move(other.m_stochastic_engine);
76
77 m_is_initialized = other.m_is_initialized;
78 m_is_paused = other.m_is_paused;
79 m_should_shutdown = other.m_should_shutdown.load();
80
81 other.m_is_initialized = false;
82 other.m_is_paused = false;
83 }
84 return *this;
85}
86
88{
89#ifdef MAYAFLUX_PLATFORM_WINDOWS
90 if (Parallel::g_MainThreadId == 0) {
91 Parallel::g_MainThreadId = GetCurrentThreadId();
92 }
93#endif // MAYAFLUX_PLATFORM_WINDOWS
94
96}
97
98void Engine::Init(const GlobalStreamInfo& streamInfo)
99{
101}
102
103void Engine::Init(const GlobalStreamInfo& streamInfo, const GlobalGraphicsConfig& graphics_config, const GlobalInputConfig& input_config, const GlobalNetworkConfig& network_config)
104{
106 m_stream_info = streamInfo;
107 m_graphics_config = graphics_config;
108 m_input_config = input_config;
109 m_network_config = network_config;
110
111 m_scheduler = std::make_shared<Vruta::TaskScheduler>(m_stream_info.sample_rate);
112 m_event_manager = std::make_shared<Vruta::EventManager>();
113 m_input_manager = std::make_shared<InputManager>();
114
115 m_buffer_manager = std::make_shared<Buffers::BufferManager>(
119
120 m_node_graph_manager = std::make_shared<Nodes::NodeGraphManager>(
122
123 m_node_graph_manager->set_node_config(m_node_config);
124
125 m_io_manager = std::make_shared<IO::IOManager>(
127
129 m_window_manager = std::make_shared<WindowManager>(m_graphics_config);
130 } else {
131 MF_WARN(Journal::Component::Core, Journal::Context::Init, "No windowing backend selected - running in audio-only mode");
132 }
133
134 m_subsystem_manager = std::make_shared<SubsystemManager>(
136
137 m_subsystem_manager->create_audio_subsystem(m_stream_info);
138
139 m_subsystem_manager->create_graphics_subsystem(m_graphics_config);
140
141 m_subsystem_manager->create_network_subsystem(m_network_config);
142
143 m_subsystem_manager->create_input_subsystem(m_input_config);
144
145 m_buffer_manager->initialize_buffer_service();
146
147 m_is_initialized = true;
148
149 MF_PRINT(Journal::Component::Core, Journal::Context::Init, "Audio backend: RtAudio, Sample rate: {}", m_stream_info.sample_rate);
150}
151
153{
154 if (!m_is_initialized) {
155 Init();
156 }
157 m_subsystem_manager->start_all_subsystems();
158}
159
161{
163 return;
164 }
165
166 m_subsystem_manager->pause_all_subsystems();
167 m_is_paused = true;
168}
169
171{
172 if (!m_is_paused || !m_is_initialized) {
173 return;
174 }
175
176 m_subsystem_manager->resume_all_subsystems();
177 m_is_paused = false;
178}
179
181{
183 return false;
184 }
185
186 if (m_is_initialized) {
187 auto status = m_subsystem_manager->query_subsystem_status();
188 for (const auto& [type, readiness] : status) {
189 const auto& [is_ready, is_running] = readiness;
190 if (is_ready && is_running) {
191 return true;
192 }
193 }
194 }
195 return false;
196}
197
199{
200#ifdef MAYAFLUX_PLATFORM_MACOS
201 run_macos_event_loop();
202#elif defined(MAYAFLUX_PLATFORM_WINDOWS)
203 run_windows_event_loop();
204#else
205 // Simple blocking wait on other platforms
206 std::cin.get();
207#endif
208
209 m_should_shutdown.store(true, std::memory_order_release);
210
212 "Shutdown requested, awaiting all subsystem termination ......");
213}
214
216{
217 m_should_shutdown.store(true, std::memory_order_release);
218
219#ifdef MAYAFLUX_PLATFORM_MACOS
220 CFRunLoopStop(CFRunLoopGetMain());
221#elif defined(MAYAFLUX_PLATFORM_WINDOWS)
222 PostThreadMessage(Parallel::g_MainThreadId, WM_QUIT, 0, 0);
223#endif
224}
225
227{
228 return m_should_shutdown.load(std::memory_order_acquire);
229}
230
231#ifdef MAYAFLUX_PLATFORM_MACOS
232void Engine::run_macos_event_loop()
233{
234 CFRunLoopRef runLoop = CFRunLoopGetMain();
235
236 dispatch_source_t stdinSource = dispatch_source_create(
237 DISPATCH_SOURCE_TYPE_READ,
238 STDIN_FILENO,
239 0,
240 dispatch_get_main_queue());
241
242 dispatch_source_set_event_handler(stdinSource, ^{
243 char buf[1024];
244 ssize_t bytes_read = read(STDIN_FILENO, buf, sizeof(buf));
245 if (bytes_read > 0) {
247 }
248 });
249
250 dispatch_resume(stdinSource);
251
252 double timeout_seconds = 1.0 / static_cast<double>(m_graphics_config.target_frame_rate);
253
255 "Main thread event loop running (polling at {}fps)",
257
258 while (!is_shutdown_requested()) {
259 CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout_seconds, false);
260 }
261
262 dispatch_source_cancel(stdinSource);
263 dispatch_release(stdinSource);
264
266 "Main thread event loop exiting");
267}
268#endif
269
270#ifdef MAYAFLUX_PLATFORM_WINDOWS
271void Engine::run_windows_event_loop()
272{
273 MSG msg;
274 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
275
276 auto stdinSource = std::thread([this]() {
277 std::cin.get();
279 });
280
282 "Main thread event loop running");
283
284 while (!is_shutdown_requested()) {
285 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
286 if (msg.message == WM_QUIT) {
288 break;
289 }
290
291 if (msg.message == MAYAFLUX_WM_DISPATCH) {
292 auto* task = reinterpret_cast<std::function<void()>*>(msg.lParam);
293 if (task) {
294 (*task)();
295 delete task;
296 }
297 } else {
298 TranslateMessage(&msg);
299 DispatchMessage(&msg);
300 }
301 }
302
303 std::this_thread::sleep_for(std::chrono::milliseconds(1));
304 }
305
306 if (stdinSource.joinable()) {
307 stdinSource.detach();
308 }
309
311 "Main thread event loop exiting");
312}
313#endif
314
316{
317 if (!m_is_initialized)
318 return;
319
321 m_node_graph_manager->terminate_active_processing();
322 }
323
325 m_subsystem_manager->stop();
326 }
327
328 if (m_scheduler) {
329 m_scheduler->terminate_all_tasks();
330 }
331
332 if (m_buffer_manager) {
333 m_buffer_manager->terminate_active_buffers();
334 m_buffer_manager.reset();
335 }
336
337 if (m_window_manager) {
338 m_window_manager->set_terminate();
339 auto windows = m_window_manager->get_windows();
340 for (auto& window : windows) {
341 m_window_manager->destroy_window(window, true);
342 }
343 m_window_manager.reset();
344 }
345
347 m_node_graph_manager.reset();
348 }
349
351 m_subsystem_manager->shutdown();
352 }
353
354 m_is_initialized = false;
355 m_is_paused = false;
356}
357
359{
361 return m_node_graph_manager->get_node_config();
362 }
363
364 return m_node_config;
365}
366
368{
369 m_node_config = config;
371 m_node_graph_manager->set_node_config(config);
372 }
373}
374
375} // namespace MayaFlux::Core
#define MF_INFO(comp, ctx,...)
#define MF_PRINT(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
void Init()
Initializes all system components and prepares for processing.
Definition Engine.cpp:87
std::shared_ptr< SubsystemManager > m_subsystem_manager
Definition Engine.hpp:402
void await_shutdown()
Blocks until shutdown is requested (main thread event loop)
Definition Engine.cpp:198
std::shared_ptr< IO::IOManager > m_io_manager
IO manager for video/audio loading and dispatch.
Definition Engine.hpp:406
GlobalNetworkConfig m_network_config
Network configuration.
Definition Engine.hpp:387
GlobalGraphicsConfig m_graphics_config
Graphics/windowing configuration.
Definition Engine.hpp:385
void request_shutdown()
Request shutdown from any thread.
Definition Engine.cpp:215
void Resume()
Resumes processing from paused state.
Definition Engine.cpp:170
std::shared_ptr< Vruta::EventManager > m_event_manager
Event manager (currently only glfw events)
Definition Engine.hpp:404
std::shared_ptr< Buffers::BufferManager > m_buffer_manager
Buffer manager.
Definition Engine.hpp:401
void set_node_config(const Nodes::NodeConfig &config)
Sets the node processing configuration.
Definition Engine.cpp:367
GlobalStreamInfo m_stream_info
Stream configuration.
Definition Engine.hpp:384
bool is_running() const
Checks if the coordinated processing system is currently active.
Definition Engine.cpp:180
void Start()
Starts the coordinated processing of all subsystems.
Definition Engine.cpp:152
Nodes::NodeConfig & get_node_config()
Gets the current node processing configuration.
Definition Engine.cpp:358
std::atomic< bool > m_should_shutdown
Definition Engine.hpp:393
void Pause()
Pauses all processing while maintaining system state.
Definition Engine.cpp:160
bool m_is_paused
Pause state flag.
Definition Engine.hpp:390
std::shared_ptr< WindowManager > m_window_manager
Window manager (Windowing subsystem)
Definition Engine.hpp:403
Engine()
Constructs a new Engine instance.
Definition Engine.cpp:29
std::shared_ptr< Vruta::TaskScheduler > m_scheduler
Task scheduler.
Definition Engine.hpp:399
std::shared_ptr< InputManager > m_input_manager
Input manager (HID/MIDI/etc.)
Definition Engine.hpp:405
Nodes::NodeConfig m_node_config
Node processing configuration.
Definition Engine.hpp:388
~Engine()
Destroys the Engine instance and cleans up resources.
Definition Engine.cpp:34
bool is_shutdown_requested() const
Check if shutdown has been requested.
Definition Engine.cpp:226
void End()
Stops all processing and performs clean shutdown.
Definition Engine.cpp:315
std::shared_ptr< Nodes::NodeGraphManager > m_node_graph_manager
Node graph manager.
Definition Engine.hpp:400
Engine & operator=(const Engine &)=delete
GlobalInputConfig m_input_config
Input configuration.
Definition Engine.hpp:386
Central lifecycle manager and component orchestrator for the MayaFlux processing system.
Definition Engine.hpp:80
@ Init
Engine/subsystem initialization.
@ Runtime
General runtime operations (default fallback)
@ Core
Core engine, backend, subsystems.
void End()
Stops and cleans up the default engine.
Definition Core.cpp:146
@ NONE
No windowing (offscreen rendering only)
uint32_t target_frame_rate
Target frame rate for visual processing (Hz)
WindowingBackend windowing_backend
Selected windowing backend.
Configuration for the InputSubsystem.
Configuration for the NetworkSubsystem.
uint32_t channels
Number of discrete channels in this set.
bool enabled
Whether this channel set is active in the stream.
uint32_t buffer_size
Number of samples per processing block.
ChannelConfig input
Configuration for input signal channels (disabled by default)
uint32_t sample_rate
Number of samples processed per second (Hz)
ChannelConfig output
Configuration for output signal channels.
Comprehensive configuration for digital audio stream processing.
Configuration settings for individual audio nodes.
Definition NodeSpec.hpp:29