openMSX
AfterCommand.cc
Go to the documentation of this file.
1 #include "AfterCommand.hh"
2 #include "CommandController.hh"
3 #include "CliComm.hh"
4 #include "Schedulable.hh"
5 #include "EventDistributor.hh"
6 #include "InputEventFactory.hh"
7 #include "Reactor.hh"
8 #include "MSXMotherBoard.hh"
9 #include "RTSchedulable.hh"
10 #include "EmuTime.hh"
11 #include "CommandException.hh"
12 #include "TclObject.hh"
13 #include "ranges.hh"
14 #include "stl.hh"
15 #include "view.hh"
16 #include <iterator>
17 #include <memory>
18 #include <sstream>
19 
20 using std::move;
21 using std::ostringstream;
22 using std::string;
23 using std::string_view;
24 using std::vector;
25 using std::unique_ptr;
26 
27 namespace openmsx {
28 
29 class AfterCmd
30 {
31 public:
32  virtual ~AfterCmd() = default;
33  string_view getCommand() const;
34  const string& getId() const;
35  virtual string getType() const = 0;
36  void execute();
37 protected:
39  const TclObject& command);
40  unique_ptr<AfterCmd> removeSelf();
41 
44  string id;
45  static inline unsigned lastAfterId = 0;
46 };
47 
48 class AfterTimedCmd : public AfterCmd, private Schedulable
49 {
50 public:
51  double getTime() const;
52  void reschedule();
53 protected:
54  AfterTimedCmd(Scheduler& scheduler,
56  const TclObject& command, double time);
57 private:
58  void executeUntil(EmuTime::param time) override;
59  void schedulerDeleted() override;
60 
61  double time; // Zero when expired, otherwise the original duration (to
62  // be able to reschedule for 'after idle').
63 };
64 
65 class AfterTimeCmd final : public AfterTimedCmd
66 {
67 public:
68  AfterTimeCmd(Scheduler& scheduler,
70  const TclObject& command, double time);
71  string getType() const override;
72 };
73 
74 class AfterIdleCmd final : public AfterTimedCmd
75 {
76 public:
77  AfterIdleCmd(Scheduler& scheduler,
79  const TclObject& command, double time);
80  string getType() const override;
81 };
82 
83 template<EventType T>
84 class AfterEventCmd final : public AfterCmd
85 {
86 public:
88  const TclObject& type,
89  const TclObject& command);
90  string getType() const override;
91 private:
92  const string type;
93 };
94 
95 class AfterInputEventCmd final : public AfterCmd
96 {
97 public:
100  const TclObject& command);
101  string getType() const override;
102  AfterCommand::EventPtr getEvent() const { return event; }
103 private:
105 };
106 
107 class AfterRealTimeCmd final : public AfterCmd, private RTSchedulable
108 {
109 public:
111  const TclObject& command, double time);
112  string getType() const override;
113 
114 private:
115  void executeRT() override;
116 };
117 
118 
120  EventDistributor& eventDistributor_,
121  CommandController& commandController_)
122  : Command(commandController_, "after")
123  , reactor(reactor_)
124  , eventDistributor(eventDistributor_)
125 {
126  // TODO DETACHED <-> EMU types should be cleaned up
127  // (moved to event iso listener?)
128  eventDistributor.registerEventListener(
129  OPENMSX_KEY_UP_EVENT, *this);
130  eventDistributor.registerEventListener(
131  OPENMSX_KEY_DOWN_EVENT, *this);
132  eventDistributor.registerEventListener(
134  eventDistributor.registerEventListener(
136  eventDistributor.registerEventListener(
138  eventDistributor.registerEventListener(
140  eventDistributor.registerEventListener(
142  eventDistributor.registerEventListener(
143  OPENMSX_JOY_HAT_EVENT, *this);
144  eventDistributor.registerEventListener(
146  eventDistributor.registerEventListener(
148  eventDistributor.registerEventListener(
150  eventDistributor.registerEventListener(
151  OPENMSX_BREAK_EVENT, *this);
152  eventDistributor.registerEventListener(
153  OPENMSX_QUIT_EVENT, *this);
154  eventDistributor.registerEventListener(
155  OPENMSX_BOOT_EVENT, *this);
156  eventDistributor.registerEventListener(
158  eventDistributor.registerEventListener(
160 }
161 
163 {
164  eventDistributor.unregisterEventListener(
166  eventDistributor.unregisterEventListener(
168  eventDistributor.unregisterEventListener(
169  OPENMSX_BOOT_EVENT, *this);
170  eventDistributor.unregisterEventListener(
171  OPENMSX_QUIT_EVENT, *this);
172  eventDistributor.unregisterEventListener(
173  OPENMSX_BREAK_EVENT, *this);
174  eventDistributor.unregisterEventListener(
176  eventDistributor.unregisterEventListener(
178  eventDistributor.unregisterEventListener(
180  eventDistributor.unregisterEventListener(
181  OPENMSX_JOY_HAT_EVENT, *this);
182  eventDistributor.unregisterEventListener(
184  eventDistributor.unregisterEventListener(
186  eventDistributor.unregisterEventListener(
188  eventDistributor.unregisterEventListener(
190  eventDistributor.unregisterEventListener(
192  eventDistributor.unregisterEventListener(
193  OPENMSX_KEY_DOWN_EVENT, *this);
194  eventDistributor.unregisterEventListener(
195  OPENMSX_KEY_UP_EVENT, *this);
196 }
197 
199 {
200  if (tokens.size() < 2) {
201  throw CommandException("Missing argument");
202  }
203  string_view subCmd = tokens[1].getString();
204  if (subCmd == "time") {
205  afterTime(tokens, result);
206  } else if (subCmd == "realtime") {
207  afterRealTime(tokens, result);
208  } else if (subCmd == "idle") {
209  afterIdle(tokens, result);
210  } else if (subCmd == "frame") {
211  afterEvent<OPENMSX_FINISH_FRAME_EVENT>(tokens, result);
212  } else if (subCmd == "break") {
213  afterEvent<OPENMSX_BREAK_EVENT>(tokens, result);
214  } else if (subCmd == "quit") {
215  afterEvent<OPENMSX_QUIT_EVENT>(tokens, result);
216  } else if (subCmd == "boot") {
217  afterEvent<OPENMSX_BOOT_EVENT>(tokens, result);
218  } else if (subCmd == "machine_switch") {
219  afterEvent<OPENMSX_MACHINE_LOADED_EVENT>(tokens, result);
220  } else if (subCmd == "info") {
221  afterInfo(tokens, result);
222  } else if (subCmd == "cancel") {
223  afterCancel(tokens, result);
224  } else {
225  try {
226  // A valid integer?
227  int time = tokens[1].getInt(getInterpreter());
228  afterTclTime(time, tokens, result);
229  } catch (CommandException&) {
230  try {
231  // A valid event name?
232  afterInputEvent(
234  tokens[1], getInterpreter()),
235  tokens, result);
236  } catch (MSXException&) {
237  throw SyntaxError();
238  }
239  }
240  }
241 }
242 
243 static double getTime(Interpreter& interp, const TclObject& obj)
244 {
245  double time = obj.getDouble(interp);
246  if (time < 0) {
247  throw CommandException("Not a valid time specification");
248  }
249  return time;
250 }
251 
252 void AfterCommand::afterTime(span<const TclObject> tokens, TclObject& result)
253 {
254  checkNumArgs(tokens, 4, Prefix{2}, "seconds command");
255  MSXMotherBoard* motherBoard = reactor.getMotherBoard();
256  if (!motherBoard) return;
257  double time = getTime(getInterpreter(), tokens[2]);
258  auto cmd = std::make_unique<AfterTimeCmd>(
259  motherBoard->getScheduler(), *this, tokens[3], time);
260  result = cmd->getId();
261  afterCmds.push_back(move(cmd));
262 }
263 
264 void AfterCommand::afterRealTime(span<const TclObject> tokens, TclObject& result)
265 {
266  checkNumArgs(tokens, 4, Prefix{2}, "seconds command");
267  double time = getTime(getInterpreter(), tokens[2]);
268  auto cmd = std::make_unique<AfterRealTimeCmd>(
269  reactor.getRTScheduler(), *this, tokens[3], time);
270  result = cmd->getId();
271  afterCmds.push_back(move(cmd));
272 }
273 
274 void AfterCommand::afterTclTime(
275  int ms, span<const TclObject> tokens, TclObject& result)
276 {
277  TclObject command;
278  command.addListElements(view::drop(tokens, 2));
279  auto cmd = std::make_unique<AfterRealTimeCmd>(
280  reactor.getRTScheduler(), *this, command, ms / 1000.0);
281  result = cmd->getId();
282  afterCmds.push_back(move(cmd));
283 }
284 
285 template<EventType T>
286 void AfterCommand::afterEvent(span<const TclObject> tokens, TclObject& result)
287 {
288  checkNumArgs(tokens, 3, "command");
289  auto cmd = std::make_unique<AfterEventCmd<T>>(*this, tokens[1], tokens[2]);
290  result = cmd->getId();
291  afterCmds.push_back(move(cmd));
292 }
293 
294 void AfterCommand::afterInputEvent(
295  const EventPtr& event, span<const TclObject> tokens, TclObject& result)
296 {
297  checkNumArgs(tokens, 3, "command");
298  auto cmd = std::make_unique<AfterInputEventCmd>(*this, event, tokens[2]);
299  result = cmd->getId();
300  afterCmds.push_back(move(cmd));
301 }
302 
303 void AfterCommand::afterIdle(span<const TclObject> tokens, TclObject& result)
304 {
305  checkNumArgs(tokens, 4, Prefix{2}, "seconds command");
306  MSXMotherBoard* motherBoard = reactor.getMotherBoard();
307  if (!motherBoard) return;
308  double time = getTime(getInterpreter(), tokens[2]);
309  auto cmd = std::make_unique<AfterIdleCmd>(
310  motherBoard->getScheduler(), *this, tokens[3], time);
311  result = cmd->getId();
312  afterCmds.push_back(move(cmd));
313 }
314 
315 void AfterCommand::afterInfo(span<const TclObject> /*tokens*/, TclObject& result)
316 {
317  ostringstream str;
318  for (auto& cmd : afterCmds) {
319  str << cmd->getId() << ": ";
320  str << cmd->getType() << ' ';
321  if (auto cmd2 = dynamic_cast<const AfterTimedCmd*>(cmd.get())) {
322  str.precision(3);
323  str << std::fixed << std::showpoint << cmd2->getTime() << ' ';
324  }
325  str << cmd->getCommand()
326  << '\n';
327  }
328  result = str.str();
329 }
330 
331 void AfterCommand::afterCancel(span<const TclObject> tokens, TclObject& /*result*/)
332 {
333  checkNumArgs(tokens, AtLeast{3}, "id|command");
334  if (tokens.size() == 3) {
335  auto id = tokens[2].getString();
336  auto it = ranges::find_if(afterCmds,
337  [&](auto& e) { return e->getId() == id; });
338  if (it != end(afterCmds)) {
339  afterCmds.erase(it);
340  return;
341  }
342  }
343  TclObject command;
344  command.addListElements(view::drop(tokens, 2));
345  string_view cmdStr = command.getString();
346  auto it = ranges::find_if(afterCmds,
347  [&](auto& e) { return e->getCommand() == cmdStr; });
348  if (it != end(afterCmds)) {
349  afterCmds.erase(it);
350  // Tcl manual is not clear about this, but it seems
351  // there's only occurence of this command canceled.
352  // It's also not clear which of the (possibly) several
353  // matches is canceled.
354  return;
355  }
356  // It's not an error if no match is found
357 }
358 
359 string AfterCommand::help(const vector<string>& /*tokens*/) const
360 {
361  return "after time <seconds> <command> execute a command after some time (MSX time)\n"
362  "after realtime <seconds> <command> execute a command after some time (realtime)\n"
363  "after idle <seconds> <command> execute a command after some time being idle\n"
364  "after frame <command> execute a command after a new frame is drawn\n"
365  "after break <command> execute a command after a breakpoint is reached\n"
366  "after boot <command> execute a command after a (re)boot\n"
367  "after machine_switch <command> execute a command after a switch to a new machine\n"
368  "after info list all postponed commands\n"
369  "after cancel <id> cancel the postponed command with given id\n";
370 }
371 
372 void AfterCommand::tabCompletion(vector<string>& tokens) const
373 {
374  if (tokens.size() == 2) {
375  static constexpr const char* const cmds[] = {
376  "time", "realtime", "idle", "frame", "break", "boot",
377  "machine_switch", "info", "cancel",
378  };
379  completeString(tokens, cmds);
380  }
381  // TODO : make more complete
382 }
383 
384 // Execute the cmds for which the predicate returns true, and erase those from afterCmds.
385 template<typename PRED> void AfterCommand::executeMatches(PRED pred)
386 {
387  AfterCmds matches;
388  // Usually there are very few matches (typically even 0 or 1), so no
389  // need to reserve() space.
390  auto p = partition_copy_remove(afterCmds, std::back_inserter(matches), pred);
391  afterCmds.erase(p.second, end(afterCmds));
392  for (auto& c : matches) {
393  c->execute();
394  }
395 }
396 
397 template<EventType T> struct AfterEventPred {
398  bool operator()(const unique_ptr<AfterCmd>& x) const {
399  return dynamic_cast<AfterEventCmd<T>*>(x.get()) != nullptr;
400  }
401 };
402 template<EventType T> void AfterCommand::executeEvents()
403 {
404  executeMatches(AfterEventPred<T>());
405 }
406 
408  bool operator()(const unique_ptr<AfterCmd>& x) const {
409  if (auto* cmd = dynamic_cast<AfterTimedCmd*>(x.get())) {
410  if (cmd->getTime() == 0.0) {
411  return true;
412  }
413  }
414  return false;
415  }
416 };
417 
420  : event(std::move(event_)) {}
421  bool operator()(const unique_ptr<AfterCmd>& x) const {
422  if (auto* cmd = dynamic_cast<AfterInputEventCmd*>(x.get())) {
423  if (cmd->getEvent()->matches(*event)) return true;
424  }
425  return false;
426  }
428 };
429 
430 int AfterCommand::signalEvent(const std::shared_ptr<const Event>& event)
431 {
432  if (event->getType() == OPENMSX_FINISH_FRAME_EVENT) {
433  executeEvents<OPENMSX_FINISH_FRAME_EVENT>();
434  } else if (event->getType() == OPENMSX_BREAK_EVENT) {
435  executeEvents<OPENMSX_BREAK_EVENT>();
436  } else if (event->getType() == OPENMSX_BOOT_EVENT) {
437  executeEvents<OPENMSX_BOOT_EVENT>();
438  } else if (event->getType() == OPENMSX_QUIT_EVENT) {
439  executeEvents<OPENMSX_QUIT_EVENT>();
440  } else if (event->getType() == OPENMSX_MACHINE_LOADED_EVENT) {
441  executeEvents<OPENMSX_MACHINE_LOADED_EVENT>();
442  } else if (event->getType() == OPENMSX_AFTER_TIMED_EVENT) {
443  executeMatches(AfterEmuTimePred());
444  } else {
445  executeMatches(AfterInputEventPred(event));
446  for (auto& c : afterCmds) {
447  if (auto* cmd = dynamic_cast<AfterIdleCmd*>(c.get())) {
448  cmd->reschedule();
449  }
450  }
451  }
452  return 0;
453 }
454 
455 
456 // class AfterCmd
457 
458 AfterCmd::AfterCmd(AfterCommand& afterCommand_, const TclObject& command_)
459  : afterCommand(afterCommand_), command(command_)
460 {
461  ostringstream str;
462  str << "after#" << ++lastAfterId;
463  id = str.str();
464 }
465 
466 string_view AfterCmd::getCommand() const
467 {
468  return command.getString();
469 }
470 
471 const string& AfterCmd::getId() const
472 {
473  return id;
474 }
475 
477 {
478  try {
480  } catch (CommandException& e) {
482  "Error executing delayed command: ", e.getMessage());
483  }
484 }
485 
486 unique_ptr<AfterCmd> AfterCmd::removeSelf()
487 {
488  auto it = rfind_if_unguarded(afterCommand.afterCmds,
489  [&](std::unique_ptr<AfterCmd>& e) { return e.get() == this; });
490  auto result = move(*it);
491  afterCommand.afterCmds.erase(it);
492  return result;
493 }
494 
495 
496 // class AfterTimedCmd
497 
499  Scheduler& scheduler_,
500  AfterCommand& afterCommand_,
501  const TclObject& command_, double time_)
502  : AfterCmd(afterCommand_, command_)
503  , Schedulable(scheduler_)
504  , time(time_)
505 {
506  reschedule();
507 }
508 
510 {
511  return time;
512 }
513 
515 {
516  removeSyncPoint();
518 }
519 
520 void AfterTimedCmd::executeUntil(EmuTime::param /*time*/)
521 {
522  time = 0.0; // execute on next event
523  afterCommand.eventDistributor.distributeEvent(
524  std::make_shared<SimpleEvent>(OPENMSX_AFTER_TIMED_EVENT));
525 }
526 
527 void AfterTimedCmd::schedulerDeleted()
528 {
529  removeSelf();
530 }
531 
532 
533 // class AfterTimeCmd
534 
536  Scheduler& scheduler_,
537  AfterCommand& afterCommand_,
538  const TclObject& command_, double time_)
539  : AfterTimedCmd(scheduler_, afterCommand_, command_, time_)
540 {
541 }
542 
543 string AfterTimeCmd::getType() const
544 {
545  return "time";
546 }
547 
548 
549 // class AfterIdleCmd
550 
552  Scheduler& scheduler_,
553  AfterCommand& afterCommand_,
554  const TclObject& command_, double time_)
555  : AfterTimedCmd(scheduler_, afterCommand_, command_, time_)
556 {
557 }
558 
559 string AfterIdleCmd::getType() const
560 {
561  return "idle";
562 }
563 
564 
565 // class AfterEventCmd
566 
567 template<EventType T>
569  AfterCommand& afterCommand_, const TclObject& type_,
570  const TclObject& command_)
571  : AfterCmd(afterCommand_, command_), type(type_.getString())
572 {
573 }
574 
575 template<EventType T>
577 {
578  return type;
579 }
580 
581 
582 // AfterInputEventCmd
583 
585  AfterCommand& afterCommand_,
586  AfterCommand::EventPtr event_,
587  const TclObject& command_)
588  : AfterCmd(afterCommand_, command_)
589  , event(std::move(event_))
590 {
591 }
592 
594 {
595  return event->toString();
596 }
597 
598 // class AfterRealTimeCmd
599 
601  RTScheduler& rtScheduler, AfterCommand& afterCommand_,
602  const TclObject& command_, double time)
603  : AfterCmd(afterCommand_, command_)
604  , RTSchedulable(rtScheduler)
605 {
606  scheduleRT(uint64_t(time * 1e6)); // micro seconds
607 }
608 
610 {
611  return "realtime";
612 }
613 
614 void AfterRealTimeCmd::executeRT()
615 {
616  // Remove self before executing, but keep self alive till the end of
617  // this method. Otherwise execute could execute 'after cancel ..' and
618  // removeSelf() asserts that it can't find itself anymore.
619  auto self = removeSelf();
620  execute();
621 }
622 
623 } // namespace openmsx
openmsx::AfterEventCmd::getType
string getType() const override
Definition: AfterCommand.cc:576
openmsx::AfterInputEventPred::AfterInputEventPred
AfterInputEventPred(AfterCommand::EventPtr event_)
Definition: AfterCommand.cc:419
openmsx::AfterCmd::getCommand
string_view getCommand() const
Definition: AfterCommand.cc:466
openmsx::CommandException
Definition: CommandException.hh:8
openmsx::Completer::checkNumArgs
void checkNumArgs(span< const TclObject > tokens, unsigned exactly, const char *errMessage) const
Definition: Completer.cc:178
openmsx::OPENMSX_MOUSE_WHEEL_EVENT
@ OPENMSX_MOUSE_WHEEL_EVENT
Definition: Event.hh:20
openmsx::AfterInputEventPred::event
AfterCommand::EventPtr event
Definition: AfterCommand.cc:427
openmsx::OPENMSX_JOY_AXIS_MOTION_EVENT
@ OPENMSX_JOY_AXIS_MOTION_EVENT
Definition: Event.hh:22
openmsx::AfterEventCmd::AfterEventCmd
AfterEventCmd(AfterCommand &afterCommand, const TclObject &type, const TclObject &command)
Definition: AfterCommand.cc:568
openmsx::AfterInputEventCmd::AfterInputEventCmd
AfterInputEventCmd(AfterCommand &afterCommand, AfterCommand::EventPtr event, const TclObject &command)
Definition: AfterCommand.cc:584
openmsx::Scheduler
Definition: Scheduler.hh:33
openmsx::AfterInputEventPred
Definition: AfterCommand.cc:418
openmsx::OPENMSX_QUIT_EVENT
@ OPENMSX_QUIT_EVENT
Definition: Event.hh:33
openmsx::OPENMSX_AFTER_TIMED_EVENT
@ OPENMSX_AFTER_TIMED_EVENT
Send when an after-emutime command should be executed.
Definition: Event.hh:57
openmsx::OPENMSX_MOUSE_MOTION_EVENT
@ OPENMSX_MOUSE_MOTION_EVENT
Definition: Event.hh:15
openmsx::RTSchedulable
Definition: RTSchedulable.hh:10
openmsx::CommandController
Definition: CommandController.hh:17
openmsx::AfterCmd::getId
const string & getId() const
Definition: AfterCommand.cc:471
openmsx::OPENMSX_BOOT_EVENT
@ OPENMSX_BOOT_EVENT
Definition: Event.hh:36
openmsx::AfterCmd::command
TclObject command
Definition: AfterCommand.cc:43
openmsx::EmuDuration
Definition: EmuDuration.hh:18
TclObject.hh
openmsx::TclObject::getDouble
double getDouble(Interpreter &interp) const
Definition: TclObject.cc:92
openmsx::AfterCommand::AfterTimedCmd
friend class AfterTimedCmd
Definition: AfterCommand.hh:55
openmsx::AfterCommand::AfterCommand
AfterCommand(Reactor &reactor, EventDistributor &eventDistributor, CommandController &commandController)
Definition: AfterCommand.cc:119
openmsx::OPENMSX_JOY_HAT_EVENT
@ OPENMSX_JOY_HAT_EVENT
Definition: Event.hh:24
openmsx::OPENMSX_BREAK_EVENT
@ OPENMSX_BREAK_EVENT
Definition: Event.hh:47
openmsx::Schedulable
Every class that wants to get scheduled at some point must inherit from this class.
Definition: Schedulable.hh:33
ranges.hh
Schedulable.hh
openmsx::AfterIdleCmd::AfterIdleCmd
AfterIdleCmd(Scheduler &scheduler, AfterCommand &afterCommand, const TclObject &command, double time)
Definition: AfterCommand.cc:551
openmsx::MSXException
Definition: MSXException.hh:9
RTSchedulable.hh
openmsx::RTScheduler
Definition: RTScheduler.hh:19
openmsx::AfterTimeCmd
Definition: AfterCommand.cc:65
openmsx::AfterCmd::id
string id
Definition: AfterCommand.cc:44
openmsx::AfterTimedCmd::getTime
double getTime() const
Definition: AfterCommand.cc:509
openmsx::OPENMSX_KEY_DOWN_EVENT
@ OPENMSX_KEY_DOWN_EVENT
Definition: Event.hh:13
openmsx::InputEventFactory::createInputEvent
EventPtr createInputEvent(const TclObject &str, Interpreter &interp)
Definition: InputEventFactory.cc:255
openmsx::EventDistributor
Definition: EventDistributor.hh:16
openmsx::AfterIdleCmd
Definition: AfterCommand.cc:74
AfterCommand.hh
openmsx::AfterCmd::lastAfterId
static unsigned lastAfterId
Definition: AfterCommand.cc:45
span
Definition: span.hh:34
openmsx::AfterEmuTimePred
Definition: AfterCommand.cc:407
openmsx::Reactor
Contains the main loop of openMSX.
Definition: Reactor.hh:66
openmsx::Completer::completeString
static void completeString(std::vector< std::string > &tokens, ITER begin, ITER end, bool caseSensitive=true)
Definition: Completer.hh:125
openmsx::Schedulable::setSyncPoint
void setSyncPoint(EmuTime::param timestamp)
Definition: Schedulable.cc:23
openmsx::AfterEmuTimePred::operator()
bool operator()(const unique_ptr< AfterCmd > &x) const
Definition: AfterCommand.cc:408
Reactor.hh
CommandController.hh
openmsx::RTSchedulable::scheduleRT
void scheduleRT(uint64_t delta)
Definition: RTSchedulable.cc:16
openmsx::AfterTimeCmd::getType
string getType() const override
Definition: AfterCommand.cc:543
view::drop
auto drop(Range &&range, size_t n)
Definition: view.hh:288
openmsx::CliComm::printWarning
void printWarning(std::string_view message)
Definition: CliComm.cc:10
openmsx::AfterCommand::~AfterCommand
~AfterCommand()
Definition: AfterCommand.cc:162
openmsx::AfterCmd::afterCommand
AfterCommand & afterCommand
Definition: AfterCommand.cc:42
openmsx::AfterCommand::EventPtr
std::shared_ptr< const Event > EventPtr
Definition: AfterCommand.hh:20
openmsx::AfterTimeCmd::AfterTimeCmd
AfterTimeCmd(Scheduler &scheduler, AfterCommand &afterCommand, const TclObject &command, double time)
Definition: AfterCommand.cc:535
openmsx::CommandController::getCliComm
virtual CliComm & getCliComm()=0
openmsx::Reactor::getMotherBoard
MSXMotherBoard * getMotherBoard() const
Definition: Reactor.cc:368
openmsx::OPENMSX_MOUSE_BUTTON_UP_EVENT
@ OPENMSX_MOUSE_BUTTON_UP_EVENT
Definition: Event.hh:17
EventDistributor.hh
openmsx::AfterCmd::execute
void execute()
Definition: AfterCommand.cc:476
openmsx::AfterCommand
Definition: AfterCommand.hh:17
openmsx::AfterEventCmd
Definition: AfterCommand.cc:84
openmsx::AfterInputEventCmd
Definition: AfterCommand.cc:95
partition_copy_remove
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().
Definition: stl.hh:212
openmsx::SyntaxError
Definition: CommandException.hh:14
openmsx::TclObject::executeCommand
TclObject executeCommand(Interpreter &interp, bool compile=false)
Interpret this TclObject as a command and execute it.
Definition: TclObject.cc:172
view.hh
InputEventFactory.hh
openmsx::AfterIdleCmd::getType
string getType() const override
Definition: AfterCommand.cc:559
openmsx::InputEventFactory::EventPtr
std::shared_ptr< const Event > EventPtr
Definition: InputEventFactory.hh:15
openmsx::AfterTimedCmd::AfterTimedCmd
AfterTimedCmd(Scheduler &scheduler, AfterCommand &afterCommand, const TclObject &command, double time)
Definition: AfterCommand.cc:498
openmsx::AfterRealTimeCmd
Definition: AfterCommand.cc:107
openmsx::AfterTimedCmd
Definition: AfterCommand.cc:48
openmsx::x
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:1419
span::size
constexpr index_type size() const noexcept
Definition: span.hh:296
EmuTime.hh
openmsx::AfterCmd::~AfterCmd
virtual ~AfterCmd()=default
openmsx::OPENMSX_MACHINE_LOADED_EVENT
@ OPENMSX_MACHINE_LOADED_EVENT
Send when a (new) machine configuration is loaded.
Definition: Event.hh:60
openmsx::Schedulable::getCurrentTime
EmuTime::param getCurrentTime() const
Convenience method: This is the same as getScheduler().getCurrentTime().
Definition: Schedulable.cc:49
openmsx::TclObject::getString
std::string_view getString() const
Definition: TclObject.cc:102
openmsx::AfterCmd::removeSelf
unique_ptr< AfterCmd > removeSelf()
Definition: AfterCommand.cc:486
openmsx::OPENMSX_MOUSE_BUTTON_DOWN_EVENT
@ OPENMSX_MOUSE_BUTTON_DOWN_EVENT
Definition: Event.hh:18
openmsx::Command
Definition: Command.hh:40
openmsx::AfterCommand::tabCompletion
void tabCompletion(std::vector< std::string > &tokens) const override
Attempt tab completion for this command.
Definition: AfterCommand.cc:372
stl.hh
openmsx::AfterCmd::getType
virtual string getType() const =0
openmsx::TclObject
Definition: TclObject.hh:21
openmsx::AfterEventPred
Definition: AfterCommand.cc:397
ranges::find_if
auto find_if(InputRange &&range, UnaryPredicate pred)
Definition: ranges.hh:113
openmsx::OPENMSX_KEY_UP_EVENT
@ OPENMSX_KEY_UP_EVENT
Definition: Event.hh:12
openmsx::AfterInputEventCmd::getType
string getType() const override
Definition: AfterCommand.cc:593
openmsx::OPENMSX_JOY_BUTTON_DOWN_EVENT
@ OPENMSX_JOY_BUTTON_DOWN_EVENT
Definition: Event.hh:27
openmsx::EventDistributor::registerEventListener
void registerEventListener(EventType type, EventListener &listener, Priority priority=OTHER)
Registers a given object to receive certain events.
Definition: EventDistributor.cc:23
openmsx::AfterInputEventPred::operator()
bool operator()(const unique_ptr< AfterCmd > &x) const
Definition: AfterCommand.cc:421
openmsx::OPENMSX_FINISH_FRAME_EVENT
@ OPENMSX_FINISH_FRAME_EVENT
Sent when VDP (V99x8 or V9990) reaches the end of a frame.
Definition: Event.hh:39
CliComm.hh
openmsx::MSXException::getMessage
const std::string & getMessage() const &
Definition: MSXException.hh:23
openmsx::EventDistributor::unregisterEventListener
void unregisterEventListener(EventType type, EventListener &listener)
Unregisters a previously registered event listener.
Definition: EventDistributor.cc:35
openmsx::AfterCmd::AfterCmd
AfterCmd(AfterCommand &afterCommand, const TclObject &command)
Definition: AfterCommand.cc:458
openmsx::AfterTimedCmd::reschedule
void reschedule()
Definition: AfterCommand.cc:514
openmsx::AfterEventPred::operator()
bool operator()(const unique_ptr< AfterCmd > &x) const
Definition: AfterCommand.cc:398
openmsx::AfterRealTimeCmd::getType
string getType() const override
Definition: AfterCommand.cc:609
openmsx::Interpreter
Definition: Interpreter.hh:16
CommandException.hh
openmsx::AfterCmd
Definition: AfterCommand.cc:29
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
MSXMotherBoard.hh
openmsx::AfterCommand::execute
void execute(span< const TclObject > tokens, TclObject &result) override
Execute this command.
Definition: AfterCommand.cc:198
openmsx::AfterRealTimeCmd::AfterRealTimeCmd
AfterRealTimeCmd(RTScheduler &rtScheduler, AfterCommand &afterCommand, const TclObject &command, double time)
Definition: AfterCommand.cc:600
openmsx::CommandCompleter::getInterpreter
Interpreter & getInterpreter() const final
Definition: Command.cc:41
openmsx::AfterInputEventCmd::getEvent
AfterCommand::EventPtr getEvent() const
Definition: AfterCommand.cc:102
openmsx::OPENMSX_JOY_BUTTON_UP_EVENT
@ OPENMSX_JOY_BUTTON_UP_EVENT
Definition: Event.hh:26
openmsx::Reactor::getRTScheduler
RTScheduler & getRTScheduler()
Definition: Reactor.hh:80
rfind_if_unguarded
auto rfind_if_unguarded(RANGE &range, PRED pred)
Definition: stl.hh:160
openmsx::CommandCompleter::getCommandController
CommandController & getCommandController() const
Definition: Command.hh:25
openmsx::Schedulable::removeSyncPoint
bool removeSyncPoint()
Definition: Schedulable.cc:28
openmsx::AfterCommand::help
std::string help(const std::vector< std::string > &tokens) const override
Print help for this command.
Definition: AfterCommand.cc:359
openmsx::EventDistributor::distributeEvent
void distributeEvent(const EventPtr &event)
Schedule the given event for delivery.
Definition: EventDistributor.cc:44