31 [[nodiscard]]
auto getId()
const {
return id; }
48 [[nodiscard]]
double getTime()
const;
55 void executeUntil(EmuTime::param time)
override;
56 void schedulerDeleted()
override;
84 [[nodiscard]] std::string_view
getType()
const;
108 void executeRT()
override;
122 :
Command(commandController_,
"after")
124 , eventDistributor(eventDistributor_)
164 for (
auto idx : afterCmds) {
165 afterCmdPool.remove(idx);
204 if (tokens.size() < 2) {
207 std::string_view subCmd = tokens[1].getString();
208 if (subCmd ==
"time") {
209 afterTime(tokens, result);
210 }
else if (subCmd ==
"realtime") {
211 afterRealTime(tokens, result);
212 }
else if (subCmd ==
"idle") {
213 afterIdle(tokens, result);
214 }
else if (subCmd ==
"frame") {
216 }
else if (subCmd ==
"break") {
218 }
else if (subCmd ==
"quit") {
220 }
else if (subCmd ==
"boot") {
222 }
else if (subCmd ==
"machine_switch") {
224 }
else if (subCmd ==
"info") {
225 afterInfo(tokens, result);
226 }
else if (subCmd ==
"cancel") {
227 afterCancel(tokens, result);
230 if (
auto time = tokens[1].getOptionalInt()) {
231 afterTclTime(*time, tokens, result);
255void AfterCommand::afterTime(std::span<const TclObject> tokens, TclObject& result)
259 if (!motherBoard)
return;
261 auto [idx, ptr] = afterCmdPool.emplace(
262 std::in_place_type_t<AfterTimeCmd>{},
263 motherBoard->getScheduler(), *
this, tokens[3], time);
264 result = std::get<AfterTimeCmd>(*ptr).getIdStr();
265 afterCmds.push_back(idx);
268void AfterCommand::afterRealTime(std::span<const TclObject> tokens, TclObject& result)
272 auto [idx, ptr] = afterCmdPool.emplace(
273 std::in_place_type_t<AfterRealTimeCmd>{},
275 result = std::get<AfterRealTimeCmd>(*ptr).getIdStr();
276 afterCmds.push_back(idx);
279void AfterCommand::afterTclTime(
280 int ms, std::span<const TclObject> tokens, TclObject& result)
283 command.addListElements(
view::drop(tokens, 2));
284 auto [idx, ptr] = afterCmdPool.emplace(
285 std::in_place_type_t<AfterRealTimeCmd>{},
287 result = std::get<AfterRealTimeCmd>(*ptr).getIdStr();
288 afterCmds.push_back(idx);
291void AfterCommand::afterSimpleEvent(std::span<const TclObject> tokens, TclObject& result,
EventType type)
294 auto [idx, ptr] = afterCmdPool.emplace(
295 std::in_place_type_t<AfterSimpleEventCmd>{},
296 *
this, tokens[2], type);
297 result = std::get<AfterSimpleEventCmd>(*ptr).getIdStr();
298 afterCmds.push_back(idx);
301void AfterCommand::afterInputEvent(
302 const Event& event, std::span<const TclObject> tokens, TclObject& result)
305 auto [idx, ptr] = afterCmdPool.emplace(
306 std::in_place_type_t<AfterInputEventCmd>{},
307 *
this, event, tokens[2]);
308 result = std::get<AfterInputEventCmd>(*ptr).getIdStr();
309 afterCmds.push_back(idx);
312void AfterCommand::afterIdle(std::span<const TclObject> tokens, TclObject& result)
316 if (!motherBoard)
return;
318 auto [idx, ptr] = afterCmdPool.emplace(
319 std::in_place_type_t<AfterIdleCmd>{},
320 motherBoard->getScheduler(), *
this, tokens[3], time);
321 result = std::get<AfterIdleCmd>(*ptr).getIdStr();
322 afterCmds.push_back(idx);
325void AfterCommand::afterInfo(std::span<const TclObject> , TclObject& result)
327 auto printTime = [](std::ostream& os,
const AfterTimedCmd& cmd) {
329 os << std::fixed << std::showpoint << cmd.getTime() <<
' ';
332 std::ostringstream str;
333 for (
auto idx : afterCmds) {
334 auto& var = afterCmdPool[idx];
337 [&](AfterTimeCmd& cmd ) { str <<
"time "; printTime(str, cmd); },
338 [&](AfterIdleCmd& cmd ) { str <<
"idle "; printTime(str, cmd); },
339 [&](AfterSimpleEventCmd& cmd ) { str << cmd.getType() <<
' '; },
340 [&](AfterInputEventCmd& cmd ) { str <<
toString(cmd.getEvent()) <<
' '; },
348void AfterCommand::afterCancel(std::span<const TclObject> tokens, TclObject& )
351 if (tokens.size() == 3) {
352 if (
auto idStr = tokens[2].getString(); idStr.starts_with(
"after#")) {
353 if (
auto id = StringOp::stringTo<unsigned>(idStr.substr(6))) {
354 auto equalId = [
id = *
id](
Index idx) {
356 return cmd.getId() ==
id;
357 }, afterCmdPool[idx]);
360 it !=
end(afterCmds)) {
363 afterCmdPool.remove(idx);
370 command.addListElements(
view::drop(tokens, 2));
371 std::string_view cmdStr = command.getString();
372 auto equalCmd = [&](
Index idx) {
374 return cmd.getCommand() == cmdStr;
375 }, afterCmdPool[idx]);
378 it !=
end(afterCmds)) {
381 afterCmdPool.remove(idx);
393 return "after time <seconds> <command> execute a command after some time (MSX time)\n"
394 "after realtime <seconds> <command> execute a command after some time (realtime)\n"
395 "after idle <seconds> <command> execute a command after some time being idle\n"
396 "after frame <command> execute a command after a new frame is drawn\n"
397 "after break <command> execute a command after a breakpoint is reached\n"
398 "after boot <command> execute a command after a (re)boot\n"
399 "after machine_switch <command> execute a command after a switch to a new machine\n"
400 "after info list all postponed commands\n"
401 "after cancel <id> cancel the postponed command with given id\n";
406 if (tokens.size() == 2) {
407 using namespace std::literals;
408 static constexpr std::array cmds = {
409 "time"sv,
"realtime"sv,
"idle"sv,
"frame"sv,
"break"sv,
"boot"sv,
410 "machine_switch"sv,
"info"sv,
"cancel"sv,
418void AfterCommand::executeMatches(std::predicate<Index>
auto pred)
420 static std::vector<Index>
matches;
426 afterCmds.erase(p.second,
end(afterCmds));
430 afterCmdPool.remove(idx);
440 }, afterCmdPool[idx]);
444void AfterCommand::executeSimpleEvents(
EventType type)
454 }, afterCmdPool[idx]);
465 }, afterCmdPool[idx]);
470int AfterCommand::signalEvent(
const Event& event)
474 executeSimpleEvents(
getType(event));
487 for (
auto idx : afterCmds) {
491 }, afterCmdPool[idx]);
502 : afterCommand(afterCommand_), command(
std::move(command_)),
id(++lastAfterId)
512 "Error executing delayed command: ",
e.getMessage());
553void AfterTimedCmd::executeUntil(EmuTime::param )
557 Event::create<AfterTimedEvent>());
560void AfterTimedCmd::schedulerDeleted()
563 afterCmdPool.remove(idx);
594 :
AfterCmd(afterCommand_,
std::move(command_)), type(type_)
618 , event(
std::move(event_))
634void AfterRealTimeCmd::executeRT()
641 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=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.
auto visit(Visitor &&visitor, const Event &event)
std::variant< AfterTimeCmd, AfterIdleCmd, AfterSimpleEventCmd, AfterInputEventCmd, AfterRealTimeCmd > AllAfterCmds
EventType getType(const Event &event)
std::string toString(const Event &event)
Get a string representation of this 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)