34 [[nodiscard]]
auto getId()
const {
return id; }
51 [[nodiscard]]
double getTime()
const;
58 void executeUntil(EmuTime::param time)
override;
59 void schedulerDeleted()
override;
87 [[nodiscard]] std::string_view
getType()
const;
111 void executeRT()
override;
125 :
Command(commandController_,
"after")
127 , eventDistributor(eventDistributor_)
142 for (
auto idx : afterCmds) {
143 afterCmdPool.remove(idx);
157 if (tokens.size() < 2) {
160 std::string_view subCmd = tokens[1].getString();
161 if (subCmd ==
"time") {
162 afterTime(tokens, result);
163 }
else if (subCmd ==
"realtime") {
164 afterRealTime(tokens, result);
165 }
else if (subCmd ==
"idle") {
166 afterIdle(tokens, result);
167 }
else if (subCmd ==
"frame") {
169 }
else if (subCmd ==
"break") {
171 }
else if (subCmd ==
"quit") {
173 }
else if (subCmd ==
"boot") {
175 }
else if (subCmd ==
"machine_switch") {
177 }
else if (subCmd ==
"info") {
178 afterInfo(tokens, result);
179 }
else if (subCmd ==
"cancel") {
180 afterCancel(tokens, result);
183 if (
auto time = tokens[1].getOptionalInt()) {
184 afterTclTime(*time, tokens, result);
208void AfterCommand::afterTime(std::span<const TclObject> tokens, TclObject& result)
212 if (!motherBoard)
return;
214 auto [idx, ptr] = afterCmdPool.emplace(
215 std::in_place_type_t<AfterTimeCmd>{},
216 motherBoard->getScheduler(), *
this, tokens[3], time);
217 result = std::get<AfterTimeCmd>(*ptr).getIdStr();
218 afterCmds.push_back(idx);
221void AfterCommand::afterRealTime(std::span<const TclObject> tokens, TclObject& result)
225 auto [idx, ptr] = afterCmdPool.emplace(
226 std::in_place_type_t<AfterRealTimeCmd>{},
228 result = std::get<AfterRealTimeCmd>(*ptr).getIdStr();
229 afterCmds.push_back(idx);
232void AfterCommand::afterTclTime(
233 int ms, std::span<const TclObject> tokens, TclObject& result)
236 command.addListElements(
view::drop(tokens, 2));
237 auto [idx, ptr] = afterCmdPool.emplace(
238 std::in_place_type_t<AfterRealTimeCmd>{},
240 result = std::get<AfterRealTimeCmd>(*ptr).getIdStr();
241 afterCmds.push_back(idx);
244void AfterCommand::afterSimpleEvent(std::span<const TclObject> tokens, TclObject& result,
EventType type)
247 auto [idx, ptr] = afterCmdPool.emplace(
248 std::in_place_type_t<AfterSimpleEventCmd>{},
249 *
this, tokens[2], type);
250 result = std::get<AfterSimpleEventCmd>(*ptr).getIdStr();
251 afterCmds.push_back(idx);
254void AfterCommand::afterInputEvent(
255 Event event, std::span<const TclObject> tokens, TclObject& result)
258 auto [idx, ptr] = afterCmdPool.emplace(
259 std::in_place_type_t<AfterInputEventCmd>{},
260 *
this, std::move(event), tokens[2]);
261 result = std::get<AfterInputEventCmd>(*ptr).getIdStr();
262 afterCmds.push_back(idx);
265void AfterCommand::afterIdle(std::span<const TclObject> tokens, TclObject& result)
269 if (!motherBoard)
return;
271 auto [idx, ptr] = afterCmdPool.emplace(
272 std::in_place_type_t<AfterIdleCmd>{},
273 motherBoard->getScheduler(), *
this, tokens[3], time);
274 result = std::get<AfterIdleCmd>(*ptr).getIdStr();
275 afterCmds.push_back(idx);
278void AfterCommand::afterInfo(std::span<const TclObject> , TclObject& result)
const
280 auto printTime = [](std::ostream& os,
const AfterTimedCmd& cmd) {
282 os << std::fixed << std::showpoint << cmd.getTime() <<
' ';
285 std::ostringstream str;
286 for (
auto idx : afterCmds) {
287 const auto& var = afterCmdPool[idx];
288 std::visit([&](
const AfterCmd& cmd) { str << cmd.getIdStr() <<
": "; }, var);
290 [&](
const AfterTimeCmd& cmd ) { str <<
"time "; printTime(str, cmd); },
291 [&](
const AfterIdleCmd& cmd ) { str <<
"idle "; printTime(str, cmd); },
292 [&](
const AfterSimpleEventCmd& cmd ) { str << cmd.getType() <<
' '; },
293 [&](
const AfterInputEventCmd& cmd ) { str <<
toString(cmd.getEvent()) <<
' '; },
296 std::visit([&](
const AfterCmd& cmd) { str << cmd.getCommand().getString() <<
'\n'; }, var);
301void AfterCommand::afterCancel(std::span<const TclObject> tokens, TclObject& )
304 if (tokens.size() == 3) {
305 if (
auto idStr = tokens[2].getString(); idStr.starts_with(
"after#")) {
306 if (
auto id = StringOp::stringTo<unsigned>(idStr.substr(6))) {
307 auto equalId = [
id = *
id](
Index idx) {
308 return std::visit([&](
const AfterCmd& cmd) {
309 return cmd.getId() ==
id;
310 }, afterCmdPool[idx]);
313 it !=
end(afterCmds)) {
316 afterCmdPool.remove(idx);
323 command.addListElements(
view::drop(tokens, 2));
324 std::string_view cmdStr = command.getString();
325 auto equalCmd = [&](
Index idx) {
326 return std::visit([&](
const AfterCmd& cmd) {
327 return cmd.getCommand() == cmdStr;
328 }, afterCmdPool[idx]);
331 it !=
end(afterCmds)) {
334 afterCmdPool.remove(idx);
346 return "after time <seconds> <command> execute a command after some time (MSX time)\n"
347 "after realtime <seconds> <command> execute a command after some time (realtime)\n"
348 "after idle <seconds> <command> execute a command after some time being idle\n"
349 "after frame <command> execute a command after a new frame is drawn\n"
350 "after break <command> execute a command after a breakpoint is reached\n"
351 "after boot <command> execute a command after a (re)boot\n"
352 "after machine_switch <command> execute a command after a switch to a new machine\n"
353 "after info list all postponed commands\n"
354 "after cancel <id> cancel the postponed command with given id\n";
359 if (tokens.size() == 2) {
360 using namespace std::literals;
361 static constexpr std::array cmds = {
362 "time"sv,
"realtime"sv,
"idle"sv,
"frame"sv,
"break"sv,
"boot"sv,
363 "machine_switch"sv,
"info"sv,
"cancel"sv,
371void AfterCommand::executeMatches(std::predicate<Index>
auto pred)
373 static std::vector<Index>
matches;
379 afterCmds.erase(p.second,
end(afterCmds));
383 afterCmdPool.remove(idx);
392 [&](
const AfterCmd& ) {
return false; }
393 }, afterCmdPool[idx]);
397void AfterCommand::executeSimpleEvents(
EventType type)
405 [&](
const AfterTimedCmd& cmd) {
return cmd.getTime() == 0.0; },
406 [&](
const AfterCmd& ) {
return false; }
407 }, afterCmdPool[idx]);
417 [&](
const AfterCmd& ) {
return false; }
418 }, afterCmdPool[idx]);
423bool AfterCommand::signalEvent(
const Event& event)
427 executeSimpleEvents(
getType(event));
440 for (
auto idx : afterCmds) {
444 }, afterCmdPool[idx]);
455 : afterCommand(afterCommand_), command(
std::move(command_)),
id(++lastAfterId)
465 "Error executing delayed command: ", e.getMessage());
472 return std::visit([&](
const AfterCmd& cmd) {
return &cmd ==
this; },
506void AfterTimedCmd::executeUntil(EmuTime::param )
512void AfterTimedCmd::schedulerDeleted()
515 afterCmdPool.remove(idx);
546 :
AfterCmd(afterCommand_,
std::move(command_)), type(type_)
555 case BREAK:
return "break";
556 case BOOT:
return "boot";
557 case QUIT:
return "quit";
571 , event(
std::move(event_))
587void AfterRealTimeCmd::executeRT()
594 afterCmdPool.remove(idx);
AfterCmd(AfterCommand &afterCommand, TclObject command)
const auto & getCommand() const
AfterCommand & afterCommand
AfterCommand::Index removeSelf()
static unsigned lastAfterId
friend class AfterTimedCmd
AfterCommand(Reactor &reactor, EventDistributor &eventDistributor, CommandController &commandController)
void execute(std::span< const TclObject > tokens, TclObject &result) override
Execute this command.
std::string help(std::span< const TclObject > tokens) const override
Print help for this command.
friend class AfterRealTimeCmd
void tabCompletion(std::vector< std::string > &tokens) const override
Attempt tab completion for this command.
AfterIdleCmd(Scheduler &scheduler, AfterCommand &afterCommand, TclObject command, double time)
AfterRealTimeCmd(RTScheduler &rtScheduler, AfterCommand &afterCommand, TclObject command, double time)
EventType getTypeEnum() const
std::string_view getType() const
AfterSimpleEventCmd(AfterCommand &afterCommand, TclObject command, EventType type)
AfterTimeCmd(Scheduler &scheduler, AfterCommand &afterCommand, TclObject command, double time)
AfterTimedCmd(Scheduler &scheduler, AfterCommand &afterCommand, TclObject command, double time)
Send when an after-EmuTime command should be executed.
void printWarning(std::string_view message)
CommandController & getCommandController() const
Interpreter & getInterpreter() const final
virtual CliComm & getCliComm()=0
static void completeString(std::vector< std::string > &tokens, ITER begin, ITER end, bool caseSensitive=true)
void checkNumArgs(std::span< const TclObject > tokens, unsigned exactly, const char *errMessage) const
void unregisterEventListener(EventType type, EventListener &listener)
Unregisters a previously registered event listener.
void distributeEvent(Event &&event)
Schedule the given event for delivery.
void registerEventListener(EventType type, EventListener &listener, Priority priority=Priority::OTHER)
Registers a given object to receive certain events.
This event is send when a device (v99x8, v9990, video9000, laserdisc) reaches the end of a frame.
void scheduleRT(uint64_t delta)
Contains the main loop of openMSX.
MSXMotherBoard * getMotherBoard() const
RTScheduler & getRTScheduler()
Every class that wants to get scheduled at some point must inherit from this class.
void setSyncPoint(EmuTime::param timestamp)
EmuTime::param getCurrentTime() const
Convenience method: This is the same as getScheduler().getCurrentTime().
TclObject executeCommand(Interpreter &interp, bool compile=false)
Interpret this TclObject as a command and execute it.
double getDouble(Interpreter &interp) const
This file implemented 3 utility functions:
bool matches(const Event &self, const Event &other)
Does this event 'match' the given event.
std::variant< AfterTimeCmd, AfterIdleCmd, AfterSimpleEventCmd, AfterInputEventCmd, AfterRealTimeCmd > AllAfterCmds
EventType getType(const Event &event)
std::string toString(const BooleanInput &input)
std::variant< KeyUpEvent, KeyDownEvent, MouseMotionEvent, MouseButtonUpEvent, MouseButtonDownEvent, MouseWheelEvent, JoystickAxisMotionEvent, JoystickHatEvent, JoystickButtonUpEvent, JoystickButtonDownEvent, OsdControlReleaseEvent, OsdControlPressEvent, WindowEvent, TextEvent, FileDropEvent, QuitEvent, FinishFrameEvent, CliCommandEvent, GroupEvent, BootEvent, FrameDrawnEvent, BreakEvent, SwitchRendererEvent, TakeReverseSnapshotEvent, AfterTimedEvent, MachineLoadedEvent, MachineActivatedEvent, MachineDeactivatedEvent, MidiInReaderEvent, MidiInWindowsEvent, MidiInCoreMidiEvent, MidiInCoreMidiVirtualEvent, MidiInALSAEvent, Rs232TesterEvent, Rs232NetEvent, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
auto find_if(InputRange &&range, UnaryPredicate pred)
constexpr auto drop(Range &&range, size_t n)
std::pair< OutputIt, ForwardIt > partition_copy_remove(ForwardIt first, ForwardIt last, OutputIt out_true, UnaryPredicate p)
This is like a combination of partition_copy() and remove().
constexpr auto rfind_if_unguarded(RANGE &range, PRED pred)
TemporaryString tmpStrCat(Ts &&... ts)
bool operator()(AfterCommand::Index idx) const
bool operator()(AfterCommand::Index idx) const
constexpr auto end(const zstring_view &x)