VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / utils / CarlaRunner.hpp
blobc22f1b0314dd092d95b2de03a39c86e39cfab70a
1 /*
2 * Carla Runner
3 * Copyright (C) 2022-2023 Filipe Coelho <falktx@falktx.com>
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #ifndef CARLA_RUNNER_HPP_INCLUDED
18 #define CARLA_RUNNER_HPP_INCLUDED
20 #include "CarlaUtils.hpp"
22 #ifndef CARLA_OS_WASM
23 # include "CarlaThread.hpp"
24 #else
25 # include "CarlaString.hpp"
26 # include <emscripten/html5.h>
27 #endif
29 // -------------------------------------------------------------------------------------------------------------------
30 // CarlaRunner class
32 /**
33 This is a handy class that handles "idle" time in either background or main thread,
34 whichever is more suitable to the target platform.
35 Typically background threads on desktop platforms, main thread on web.
37 A single function is expected to be implemented by subclasses,
38 which directly allows it to stop the runner by returning false.
40 You can use it for quick operations that do not need to be handled in the main thread if possible.
41 The target is to spread out execution over many runs, instead of spending a lot of time on a single task.
43 class CarlaRunner
45 protected:
47 * Constructor.
49 CarlaRunner(const char* const runnerName = nullptr) noexcept
50 #ifndef CARLA_OS_WASM
51 : fRunnerThread(this, runnerName),
52 fTimeInterval(0)
53 #else
54 : fRunnerName(runnerName),
55 fIntervalId(0)
56 #endif
61 * Destructor.
63 virtual ~CarlaRunner() /*noexcept*/
65 CARLA_SAFE_ASSERT(! isRunnerActive());
67 stopRunner();
71 * Virtual function to be implemented by the subclass.
72 * Return true to keep running, false to stop execution.
74 virtual bool run() = 0;
77 * Check if the runner should stop.
78 * To be called from inside the runner to know if a stop request has been made.
80 bool shouldRunnerStop() const noexcept
82 #ifndef CARLA_OS_WASM
83 return fRunnerThread.shouldThreadExit();
84 #else
85 return fIntervalId == 0;
86 #endif
89 // ---------------------------------------------------------------------------------------------------------------
91 public:
93 * Check if the runner is active.
95 bool isRunnerActive() noexcept
97 #ifndef CARLA_OS_WASM
98 return fRunnerThread.isThreadRunning();
99 #else
100 return fIntervalId != 0;
101 #endif
105 * Start the thread.
107 bool startRunner(const uint timeIntervalMilliseconds = 0) noexcept
109 #ifndef CARLA_OS_WASM
110 CARLA_SAFE_ASSERT_RETURN(!fRunnerThread.isThreadRunning(), false);
111 fTimeInterval = timeIntervalMilliseconds;
112 return fRunnerThread.startThread();
113 #else
114 CARLA_SAFE_ASSERT_RETURN(fIntervalId == 0, false);
115 fIntervalId = emscripten_set_interval(_entryPoint, timeIntervalMilliseconds, this);
116 return true;
117 #endif
121 * Stop the runner.
122 * This will signal the runner to stop if active, and wait until it finishes.
124 bool stopRunner() noexcept
126 #ifndef CARLA_OS_WASM
127 return fRunnerThread.stopThread(-1);
128 #else
129 signalRunnerShouldStop();
130 return true;
131 #endif
135 * Tell the runner to stop as soon as possible.
137 void signalRunnerShouldStop() noexcept
139 #ifndef CARLA_OS_WASM
140 fRunnerThread.signalThreadShouldExit();
141 #else
142 if (fIntervalId != 0)
144 emscripten_clear_interval(fIntervalId);
145 fIntervalId = 0;
147 #endif
150 // ---------------------------------------------------------------------------------------------------------------
153 * Returns the name of the runner.
154 * This is the name that gets set in the constructor.
156 const CarlaString& getRunnerName() const noexcept
158 #ifndef CARLA_OS_WASM
159 return fRunnerThread.getThreadName();
160 #else
161 return fRunnerName;
162 #endif
165 // ---------------------------------------------------------------------------------------------------------------
167 private:
168 #ifndef CARLA_OS_WASM
169 class RunnerThread : public CarlaThread
171 CarlaRunner* const runner;
173 public:
174 RunnerThread(CarlaRunner* const r, const char* const rn)
175 : CarlaThread(rn),
176 runner(r) {}
178 protected:
179 void run() override
181 const uint timeInterval = runner->fTimeInterval;
183 while (!shouldThreadExit())
185 bool stillRunning = false;
187 try {
188 stillRunning = runner->run();
189 } catch(...) {}
191 if (stillRunning && !shouldThreadExit())
193 if (timeInterval != 0)
194 carla_msleep(timeInterval);
196 // FIXME
197 // pthread_yield();
198 continue;
201 break;
205 CARLA_DECLARE_NON_COPYABLE(RunnerThread)
206 } fRunnerThread;
208 uint fTimeInterval;
209 #else
210 const CarlaString fRunnerName;
211 long fIntervalId;
213 void _runEntryPoint() noexcept
215 bool stillRunning = false;
217 try {
218 stillRunning = run();
219 } catch(...) {}
221 if (fIntervalId != 0 && !stillRunning)
223 emscripten_clear_interval(fIntervalId);
224 fIntervalId = 0;
228 static void _entryPoint(void* const userData) noexcept
230 static_cast<CarlaRunner*>(userData)->_runEntryPoint();
232 #endif
234 CARLA_DECLARE_NON_COPYABLE(CarlaRunner)
237 // -------------------------------------------------------------------------------------------------------------------
239 #endif // CARLA_RUNNER_HPP_INCLUDED