MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Lila.cpp
Go to the documentation of this file.
1#include "Lila.hpp"
2
4#include "Server.hpp"
5
6#include "Commentator.hpp"
7
8#ifdef MAYAFLUX_PLATFORM_MACOS
9#include <CoreFoundation/CoreFoundation.h>
10#endif
11
12namespace Lila {
13
15 : m_interpreter(std::make_unique<ClangInterpreter>())
16 , m_current_mode(OperationMode::Direct)
17 , server_loop_rate(0.1F)
18{
19 LILA_DEBUG(Emitter::SYSTEM, "Lila instance created");
20}
21
23{
24 stop_server();
25 LILA_DEBUG(Emitter::SYSTEM, "Lila instance destroyed");
26}
27
28bool Lila::initialize(OperationMode mode, int server_port) noexcept
29{
30 LILA_INFO(Emitter::SYSTEM, "Initializing Lila");
31 m_current_mode = mode;
32
33 if (!initialize_interpreter()) {
34 LILA_ERROR(Emitter::SYSTEM, "Failed to initialize interpreter");
35 return false;
36 }
37
38 if (mode == OperationMode::Server || mode == OperationMode::Both) {
39 if (!initialize_server(server_port)) {
40 LILA_ERROR(Emitter::SYSTEM, "Failed to initialize server");
41 return false;
42 }
43 }
44
45 LILA_INFO(Emitter::SYSTEM, "Lila initialized successfully");
46 return true;
47}
48
50{
51 LILA_DEBUG(Emitter::SYSTEM, "Initializing interpreter subsystem");
52 return m_interpreter->initialize();
53}
54
56{
57 if (m_server && m_server->is_running()) {
58 LILA_WARN(Emitter::SYSTEM, "Stopping existing server before starting new one");
59 stop_server();
60 }
61
62 LILA_DEBUG(Emitter::SYSTEM,
63 std::string("Initializing server on port ") + std::to_string(port));
64
65 m_server = std::make_unique<Server>(port);
66
67 m_server->set_message_handler([this](std::string_view message) {
68 return this->handle_server_message(message);
69 });
70
71 return m_server->start();
72}
73
74std::expected<std::string, std::string> Lila::handle_server_message(std::string_view message)
75{
76 if (message.empty()) {
77 return R"({"status":"error","message":"Empty message"})";
78 }
79
80 auto result = m_interpreter->eval(std::string(message));
81
82 if (result.success) {
83 if (m_success_callback) {
84 m_success_callback();
85 }
86 return "";
87 }
88
89 if (m_error_callback) {
90 m_error_callback(result.error);
91 }
92
93 return std::unexpected(escape_json(result.error));
94}
95
96bool Lila::eval(const std::string& code)
97{
98 if (!m_interpreter) {
99 LILA_ERROR(Emitter::SYSTEM, "Cannot eval: interpreter not initialized");
100 return false;
101 }
102
103 auto result = m_interpreter->eval(code);
104
105 if (result.success && m_success_callback) {
106 m_success_callback();
107 } else if (!result.success && m_error_callback) {
108 m_error_callback(result.error);
109 }
110
111 return result.success;
112}
113
114bool Lila::eval_file(const std::string& filepath)
115{
116 if (!m_interpreter) {
117 LILA_ERROR(Emitter::SYSTEM, "Cannot eval file: interpreter not initialized");
118 return false;
119 }
120
121 auto result = m_interpreter->eval_file(filepath);
122 return result.success;
123}
124
125void Lila::start_server(int port)
126{
127 LILA_INFO(Emitter::SYSTEM,
128 std::string("Starting server on port ") + std::to_string(port));
129
130 initialize_server(port);
131}
132
134{
135 if (m_server) {
136 LILA_INFO(Emitter::SYSTEM, "Stopping server");
137 m_server->stop();
138 m_server.reset();
139 }
140}
141
143{
144 return m_server && m_server->is_running();
145}
146
147void* Lila::get_symbol_address(const std::string& name)
148{
149 return m_interpreter ? m_interpreter->get_symbol_address(name) : nullptr;
150}
151
152std::vector<std::string> Lila::get_defined_symbols()
153{
154 return m_interpreter ? m_interpreter->get_defined_symbols() : std::vector<std::string> {};
155}
156
157void Lila::add_include_path(const std::string& path)
158{
159 if (m_interpreter) {
160 m_interpreter->add_include_path(path);
161 }
162}
163
164void Lila::add_compile_flag(const std::string& flag)
165{
166 if (m_interpreter) {
167 m_interpreter->add_compile_flag(flag);
168 }
169}
170
171void Lila::on_success(std::function<void()> callback)
172{
173 m_success_callback = std::move(callback);
174 LILA_DEBUG(Emitter::SYSTEM, "Success callback registered");
175}
176
177void Lila::on_error(std::function<void(const std::string&)> callback)
178{
179 m_error_callback = std::move(callback);
180 LILA_DEBUG(Emitter::SYSTEM, "Error callback registered");
181}
182
183void Lila::on_server_started(std::function<void()> callback)
184{
185 if (m_server) {
186 m_server->on_server_started(std::move(callback));
187 LILA_DEBUG(Emitter::SYSTEM, "Server started callback registered");
188 }
189}
190
191void Lila::on_server_client_connected(std::function<void(const ClientInfo&)> callback)
192{
193 if (m_server) {
194 m_server->on_client_connected(std::move(callback));
195 LILA_DEBUG(Emitter::SYSTEM, "Client connected callback registered");
196 }
197}
198
199void Lila::on_server_client_disconnected(std::function<void(const ClientInfo&)> callback)
200{
201 if (m_server) {
202 m_server->on_client_disconnected(std::move(callback));
203 LILA_DEBUG(Emitter::SYSTEM, "Client disconnected callback registered");
204 }
205}
206
207std::string Lila::get_last_error() const
208{
209 return m_interpreter ? m_interpreter->get_last_error() : "Interpreter not initialized";
210}
211
212OperationMode Lila::get_current_mode() const
213{
214 return m_current_mode;
215}
216
217void Lila::await_shutdown(const std::atomic<bool>* external_flag)
218{
219 LILA_INFO(Emitter::SYSTEM, "Entering main event loop");
220
221#ifdef MAYAFLUX_PLATFORM_MACOS
222 while (!m_shutdown_requested.load(std::memory_order_acquire) && (!external_flag || external_flag->load(std::memory_order_acquire))) {
223 if (!is_server_running()) {
224 LILA_ERROR(Emitter::SYSTEM, "Server stopped unexpectedly");
225 break;
226 }
227 CFRunLoopRunInMode(kCFRunLoopDefaultMode, server_loop_rate, false);
228 }
229#else
230 while (!m_shutdown_requested.load(std::memory_order_acquire) && (!external_flag || external_flag->load(std::memory_order_acquire))) {
231 if (!is_server_running()) {
232 LILA_ERROR(Emitter::SYSTEM, "Server stopped unexpectedly");
233 break;
234 }
235 std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(server_loop_rate * 1000)));
236 }
237#endif
238
239 LILA_INFO(Emitter::SYSTEM, "Exiting main event loop");
240}
241
243{
244 m_shutdown_requested.store(true, std::memory_order_release);
245
246#ifdef MAYAFLUX_PLATFORM_MACOS
247 CFRunLoopStop(CFRunLoopGetMain());
248#endif
249}
250
251std::string Lila::escape_json(const std::string& str)
252{
253 std::string escaped;
254 escaped.reserve(str.size());
255
256 for (char c : str) {
257 switch (c) {
258 case '"':
259 escaped += "\\\"";
260 break;
261 case '\\':
262 escaped += "\\\\";
263 break;
264 case '\n':
265 escaped += "\\n";
266 break;
267 case '\r':
268 escaped += "\\r";
269 break;
270 case '\t':
271 escaped += "\\t";
272 break;
273 default:
274 if (c >= 0x20) {
275 escaped += c;
276 }
277 }
278 }
279 return escaped;
280}
281
282} // namespace Lila
#define LILA_WARN(emitter, msg)
#define LILA_ERROR(emitter, msg)
#define LILA_DEBUG(emitter, msg)
#define LILA_INFO(emitter, msg)
Embedded Clang interpreter for live code evaluation in MayaFlux.
std::vector< std::string > get_defined_symbols()
Gets a list of all defined symbols.
Definition Lila.cpp:152
static std::string escape_json(const std::string &str)
Escapes a string for safe JSON encoding.
Definition Lila.cpp:251
bool eval(const std::string &code)
Evaluates a C++ code snippet directly.
Definition Lila.cpp:96
void on_error(std::function< void(const std::string &)> callback)
Registers a callback for code evaluation errors.
Definition Lila.cpp:177
std::expected< std::string, std::string > handle_server_message(std::string_view message)
Definition Lila.cpp:74
void stop_server()
Stops the TCP server and disconnects all clients.
Definition Lila.cpp:133
OperationMode get_current_mode() const
Gets the current operation mode.
Definition Lila.cpp:212
void * get_symbol_address(const std::string &name)
Gets the address of a symbol defined in the interpreter.
Definition Lila.cpp:147
bool initialize_interpreter()
Definition Lila.cpp:49
void on_server_client_disconnected(std::function< void(const ClientInfo &)> callback)
Registers a callback for client disconnections (server mode)
Definition Lila.cpp:199
bool initialize_server(int port)
Definition Lila.cpp:55
bool initialize(OperationMode mode=OperationMode::Direct, int server_port=9090) noexcept
Initializes the live coding environment.
Definition Lila.cpp:28
void request_shutdown()
Request shutdown from any thread.
Definition Lila.cpp:242
void on_server_client_connected(std::function< void(const ClientInfo &)> callback)
Registers a callback for new client connections (server mode)
Definition Lila.cpp:191
void add_compile_flag(const std::string &flag)
Adds a compile flag for code evaluation.
Definition Lila.cpp:164
void add_include_path(const std::string &path)
Adds an include path for code evaluation.
Definition Lila.cpp:157
~Lila()
Destructor; cleans up interpreter and server resources.
Definition Lila.cpp:22
void start_server(int port=9090)
Starts the TCP server for remote live coding.
Definition Lila.cpp:125
bool eval_file(const std::string &filepath)
Evaluates a C++ code file directly.
Definition Lila.cpp:114
std::string get_last_error() const
Gets the last error message.
Definition Lila.cpp:207
bool is_server_running() const
Checks if the server is currently running.
Definition Lila.cpp:142
void await_shutdown(const std::atomic< bool > *external_flag)
Blocks until server shutdown (main thread event loop)
Definition Lila.cpp:217
Lila()
Constructs a Lila instance.
Definition Lila.cpp:14
void on_success(std::function< void()> callback)
Registers a callback for successful code evaluation.
Definition Lila.cpp:171
void on_server_started(std::function< void()> callback)
Registers a callback for server start events.
Definition Lila.cpp:183
Information about a connected client.
Definition EventBus.hpp:58