EchoMap 2026-07-25 6d3977c
An experimental cross-platform digital signal processing application for sound-source localisation.
Loading...
Searching...
No Matches
EchoMapWeb.cpp
Go to the documentation of this file.
1
9
10#if defined(__EMSCRIPTEN__) || defined(__DOXYGEN__)
11
12#include "EchoMapWeb.hpp"
13
14#include <emscripten/emscripten.h>
15
19#include "../objects/Signal.hpp"
23#include "../utility/Logger.hpp"
24
25#ifndef __EMSCRIPTEN_PTHREADS__
26#warning "The Emscripten application will be single-threaded."
27#endif // __EMSCRIPTEN_PTHREADS__
28
29namespace echomap
30{
31
33 Notification& notification
34)
35{
37 // clang-format off
38
41 [this](const CancelProjectLoadNotification& n) { handle_notification(n); },
42 [this](const CompleteProjectLoadNotification& n) { handle_notification(n); },
43 [this](RegisterVFSMappingNotification& n) { handle_notification(n); },
44 },
45
46 // clang-format on
47 notification
48 );
49}
50
51void EchoMapWeb::handle_result(
52 LoadProjectResult&& result
53)
54{
55 if (active_modal != nullptr) {
56 LOG_WARN("Ignoring request to change active Project since there is an active modal.");
57 return;
58 }
59
60 auto&& new_project = std::move(result).take_project();
61
62 if (!new_project->observe_unloaded_signals().empty()) {
63 // Raise the modal to query for the sources.
64 active_modal = std::make_unique<MapSourcesModal>(this, new_project.get());
65 unloaded_project = std::move(new_project);
66 } else
67 change_active_project(std::move(new_project));
68}
69
70void EchoMapWeb::handle_result(
72)
73{
74 Project* target = nullptr;
75
76 // Determine whether the result relates to a Signal bound to the active Project or the unloaded Project.
77
78 if (project != nullptr && result.get_project_id() == project->get_id())
79 target = project.get();
80 else if (unloaded_project != nullptr && result.get_project_id() == unloaded_project->get_id())
81 target = unloaded_project.get();
82
83 if (target == nullptr) {
85 "Dropping LoadSignalFileResult, which was intended for the unavailable Project with ID {}.",
86 result.get_project_id()
87 );
88
89 return;
90 }
91
92 // Add the signals to the target Project.
93
94 for (auto&& signals = std::move(result).take_signals(); auto signal : signals | std::views::as_rvalue)
95 target->add_signal(std::move(signal));
96
97 // If it was an unloaded Project, and all signals are now loaded, it can become the active Project.
98
99 if (target == unloaded_project.get() && unloaded_project->observe_unloaded_signals().empty())
100 change_active_project(std::move(unloaded_project));
101}
102
103void EchoMapWeb::handle_notification(
104 const CancelProjectLoadNotification& notification
105)
106{
107 notification.verify_project(unloaded_project.get());
108
109 active_modal.reset();
110 unloaded_project.reset();
111}
112
113void EchoMapWeb::handle_notification(
114 const CompleteProjectLoadNotification& notification
115)
116{
117 notification.verify_project(unloaded_project.get());
118
119 // For each group, create a worker notification to load the corresponding file.
120
121 for (auto&& [vfs_path, factories] : unloaded_project->take_unloaded_factories()) {
122
123 if (!vfs_path.has_value())
124 throw std::runtime_error("Refusing CompleteProjectLoadNotification due to an incomplete VFS mapping.");
125
126 // Once these notifications return, if everything is loaded correctly, we'll change the active project.
127 worker.submit(
128 std::make_unique<LoadSignalFileTask>(unloaded_project->get_id(), *vfs_path, std::move(factories))
129 );
130 }
131
132 active_modal.reset();
133}
134
135void EchoMapWeb::handle_notification(
137) const
138{
139 notification.verify_project(unloaded_project.get());
140
141 try {
142 unloaded_project->add_vfs_mapping_for_unavailable_signal(
143 notification.external,
144 std::move(notification.internal)
145 );
146 } catch (const std::runtime_error&) {
147 throw IgnoredWarning(
149 "Dropping RegisterVFSMappingNotification since we don't need a mapping for {}.",
150 notification.external.c_str()
151 )
152 );
153 }
154}
155
157 void* const echomap_instance
158)
159{
160 auto* instance = static_cast<EchoMapWeb*>(echomap_instance);
161 instance->render();
162}
163
165{
166 emscripten_set_main_loop_arg(&EchoMapWeb::render_shim, this, 0, true);
167}
168
169EchoMapWeb::EchoMapWeb() = default;
170
171EchoMapWeb::~EchoMapWeb() = default;
172
173} // namespace echomap
174
175#endif // __EMSCRIPTEN__
AllNotifications specification.
EchoMapWeb specification.
IProjectPanel specification.
IgnoredWarning specification.
LoadSignalFileTask specification.
EchoMap portable logger specification.
#define LOG_F_WARN(msg,...)
Logs a formatted warning-level message using echomap::Logger::log_f.
Definition Logger.hpp:115
#define LOG_WARN(msg)
Logs an unformatted warning-level message using echomap::Logger::log.
Definition Logger.hpp:162
IndividualUploadModal specification.
PartialProject specification.
Audio signal class specification.
static void render_shim(void *echomap_instance)
Invokes the renderer from a static context given an untyped mutable pointer to the EchoMap object ins...
void run_event_loop() override
Runs the platform-dependent event loop to manage and propagate interaction with the EchoMap applicati...
void visit_notification(Notification &notification) override
Uses std::visit on the given notification to invoke the corresponding handler.
std::unique_ptr< PartialProject > unloaded_project
Owning container for the unloaded Project.
std::unique_ptr< Project > project
Owning container for the active Project.
Definition EchoMap.hpp:245
std::unique_ptr< IPanel > active_modal
The current active non-ErrorModal modal panel.
Definition EchoMap.hpp:246
auto make_common_notification_visitors()
Produce an overload set for std::visit for all platform-independent Notification objects.
Definition EchoMap.hpp:94
Worker worker
Multi-threaded worker for scheduling heavy computation tasks.
Definition EchoMap.hpp:238
Denotes a loaded Project completed by a LoadProjectTask job.
T format(T... args)
std::variant< AddChannelMappingNotification, ModifySensorColourNotification, ModifySensorPositionNotification, ProjectSelectionCompleteNotification, ClearErrorNotification, RaiseFileChooserNotification, RegisterVFSMappingNotification, CompleteProjectLoadNotification, CancelProjectLoadNotification > Notification
A Notification is a trivial message sent exclusively to the EchoMap controller.
T make_unique(T... args)
The main EchoMap outermost namespace for all non-exported symbols.
T signal(T... args)
A notification indicating that a pending Project load should be cancelled.
A notification indicating that a pending Project is ready to be loaded.
A notification to indicate a new VFS mapping from an external source.
A helper type for succinctly specifying callable visitors over a variant alternative.
T visit(T... args)