16using std::string_view;
21 : motherBoard(motherBoard_)
23 motherBoard.getCommandController(),
24 motherBoard.getStateChangeDistributor(),
25 motherBoard.getScheduler())
27 motherBoard.getCommandController(),
28 motherBoard.getStateChangeDistributor(),
29 motherBoard.getScheduler())
30 , pluggableInfo (motherBoard.getMachineInfoCommand())
31 , connectorInfo (motherBoard.getMachineInfoCommand())
32 , connectionClassInfo(motherBoard.getMachineInfoCommand())
42 for (
auto& c : connectors) {
43 std::cerr <<
"ERROR: Connector still registered at shutdown: "
44 << c->getName() <<
'\n';
51 connectors.push_back(&connector);
65 pluggables.push_back(std::move(pluggable));
72PluggingController::PlugCmd::PlugCmd(
81void PluggingController::PlugCmd::execute(
82 std::span<const TclObject> tokens, TclObject& result_, EmuTime::param time)
84 checkNumArgs(tokens, Between{1, 3}, Prefix{1},
"?connector? ?pluggable?");
86 auto& pluggingController =
OUTER(PluggingController, plugCmd);
87 switch (tokens.size()) {
89 for (
auto& c : pluggingController.connectors) {
91 c->getPlugged().getName(),
'\n');
95 const auto& connector = pluggingController.getConnector(tokens[1].getString());
96 strAppend(result, connector.getName(),
": ",
97 connector.getPlugged().getName());
101 string_view connName = tokens[1].getString();
102 string_view plugName = tokens[2].getString();
103 auto& connector = pluggingController.getConnector(connName);
104 auto& pluggable = pluggingController.getPluggable(plugName);
105 if (&connector.getPlugged() == &pluggable) {
109 if (connector.getClass() != pluggable.getClass()) {
110 throw CommandException(
"plug: ", plugName,
111 " doesn't fit in ", connName);
113 connector.unplug(time);
115 connector.plug(pluggable, time);
116 pluggingController.getCliComm().update(
118 }
catch (PlugException& e) {
119 throw CommandException(
"plug: plug failed: ",
e.getMessage());
127string PluggingController::PlugCmd::help(std::span<const TclObject> )
const
129 return "Plugs a plug into a connector\n"
130 " plug [connector] [plug]";
133void PluggingController::PlugCmd::tabCompletion(std::vector<string>& tokens)
const
135 auto& pluggingController =
OUTER(PluggingController, plugCmd);
136 if (tokens.size() == 2) {
139 pluggingController.connectors,
140 [](
auto& c) -> std::string_view { return c->getName(); }));
141 }
else if (tokens.size() == 3) {
143 const auto* connector = pluggingController.findConnector(tokens[1]);
144 string_view className = connector ? connector->getClass() : string_view{};
146 [&](
auto& p) { return p->getClass() == className; }),
147 [](
auto& p) -> string_view { return p->getName(); }));
151bool PluggingController::PlugCmd::needRecord(std::span<const TclObject> tokens)
const
153 return tokens.size() == 3;
159PluggingController::UnplugCmd::UnplugCmd(
160 CommandController& commandController_,
161 StateChangeDistributor& stateChangeDistributor_,
162 Scheduler& scheduler_)
163 : RecordedCommand(commandController_, stateChangeDistributor_,
164 scheduler_,
"unplug")
168void PluggingController::UnplugCmd::execute(
169 std::span<const TclObject> tokens, TclObject& , EmuTime::param time)
171 checkNumArgs(tokens, 2,
"connector");
172 auto& pluggingController =
OUTER(PluggingController, unplugCmd);
173 string_view connName = tokens[1].getString();
174 auto& connector = pluggingController.getConnector(connName);
175 connector.unplug(time);
179string PluggingController::UnplugCmd::help(std::span<const TclObject> )
const
181 return "Unplugs a plug from a connector\n"
182 " unplug [connector]";
185void PluggingController::UnplugCmd::tabCompletion(std::vector<string>& tokens)
const
187 if (tokens.size() == 2) {
190 OUTER(PluggingController, unplugCmd).connectors,
191 [](
auto* c) -> std::string_view {
return c->getName(); }));
198 return (it !=
end(connectors)) ? *it :
nullptr;
201Connector& PluggingController::getConnector(string_view name)
const
206 throw CommandException(
"No such connector: ", name);
212 return (it !=
end(pluggables)) ? it->get() :
nullptr;
215Pluggable& PluggingController::getPluggable(string_view name)
const
220 throw CommandException(
"No such pluggable: ", name);
236PluggingController::PluggableInfo::PluggableInfo(
238 :
InfoTopic(machineInfoCommand,
"pluggable")
242void PluggingController::PluggableInfo::execute(
243 std::span<const TclObject> tokens, TclObject& result)
const
245 auto& pluggingController =
OUTER(PluggingController, pluggableInfo);
246 switch (tokens.size()) {
248 result.addListElements(
250 [](
auto& p) { return p->getName(); }));
253 const auto& pluggable = pluggingController.getPluggable(
254 tokens[2].getString());
255 result = pluggable.getDescription();
259 throw CommandException(
"Too many parameters");
263string PluggingController::PluggableInfo::help(std::span<const TclObject> )
const
265 return "Shows a list of available pluggables. "
266 "Or show info on a specific pluggable.";
269void PluggingController::PluggableInfo::tabCompletion(std::vector<string>& tokens)
const
271 if (tokens.size() == 3) {
273 OUTER(PluggingController, pluggableInfo).pluggables,
274 [](
auto& p) -> std::string_view {
return p->getName(); }));
280PluggingController::ConnectorInfo::ConnectorInfo(
281 InfoCommand& machineInfoCommand)
282 : InfoTopic(machineInfoCommand,
"connector")
286void PluggingController::ConnectorInfo::execute(
287 std::span<const TclObject> tokens, TclObject& result)
const
289 auto& pluggingController =
OUTER(PluggingController, connectorInfo);
290 switch (tokens.size()) {
292 result.addListElements(
294 [](
auto& c) { return c->getName(); }));
297 const auto& connector = pluggingController.getConnector(tokens[2].getString());
298 result = connector.getDescription();
302 throw CommandException(
"Too many parameters");
306string PluggingController::ConnectorInfo::help(std::span<const TclObject> )
const
308 return "Shows a list of available connectors.";
311void PluggingController::ConnectorInfo::tabCompletion(std::vector<string>& tokens)
const
313 if (tokens.size() == 3) {
315 OUTER(PluggingController, connectorInfo).connectors,
316 [](
auto& c) -> std::string_view {
return c->getName(); }));
322PluggingController::ConnectionClassInfo::ConnectionClassInfo(
323 InfoCommand& machineInfoCommand)
324 : InfoTopic(machineInfoCommand,
"connectionclass")
328void PluggingController::ConnectionClassInfo::execute(
329 std::span<const TclObject> tokens, TclObject& result)
const
331 const auto& pluggingController =
OUTER(PluggingController, connectionClassInfo);
332 switch (tokens.size()) {
334 std::vector<string_view> classes;
335 classes.reserve(pluggingController.connectors.size());
336 for (
auto& c : pluggingController.connectors) {
337 classes.push_back(c->getClass());
339 for (
const auto& p : pluggingController.pluggables) {
340 auto c = p->getClass();
341 if (!
contains(classes, c)) classes.push_back(c);
343 result.addListElements(classes);
347 const auto& arg = tokens[2].getString();
348 if (
const auto* connector = pluggingController.findConnector(arg)) {
349 result = connector->getClass();
352 if (
const auto* pluggable = pluggingController.findPluggable(arg)) {
353 result = pluggable->getClass();
356 throw CommandException(
"No such connector or pluggable");
359 throw CommandException(
"Too many parameters");
363string PluggingController::ConnectionClassInfo::help(std::span<const TclObject> )
const
365 return "Shows the class a connector or pluggable belongs to.";
368void PluggingController::ConnectionClassInfo::tabCompletion(std::vector<string>& tokens)
const
370 if (tokens.size() == 3) {
371 auto& pluggingController =
OUTER(PluggingController, connectionClassInfo);
374 [](
auto& c) -> std::string_view { return c->getName(); }),
376 [](
auto& p) -> std::string_view { return p->getName(); }));
377 completeString(tokens, names);
virtual void update(UpdateType type, std::string_view name, std::string_view value)=0
Represents something you can plug devices into.
const std::string & getName() const
Name that identifies this connector.
virtual void unplug(EmuTime::param time)
This unplugs the currently inserted Pluggable from this Connector.
EmuTime::param getCurrentTime() const
Convenience method: This is the same as getScheduler().getCurrentTime().
MSXCliComm & getMSXCliComm()
static void createAll(PluggingController &controller, MSXMotherBoard &motherBoard)
virtual std::string_view getName() const
Name used to identify this pluggable.
void registerPluggable(std::unique_ptr< Pluggable > pluggable)
Add a Pluggable to the registry.
void unregisterConnector(Connector &connector)
Pluggable * findPluggable(std::string_view name) const
Return the Pluggable with given name or nullptr if there is none with this name.
PluggingController(MSXMotherBoard &motherBoard)
void registerConnector(Connector &connector)
Connectors must be (un)registered.
Connector * findConnector(std::string_view name) const
Return the Connector with given name or nullptr if there is none with this name.
CliComm & getCliComm()
Access to the MSX specific CliComm, so that Connectors can get it.
EmuTime::param getCurrentTime() const
Convenience method: get current time.
Commands that directly influence the MSX state should send and events so that they can be recorded by...
This file implemented 3 utility functions:
auto find(InputRange &&range, const T &value)
auto filter(ForwardRange &&range, Predicate pred)
constexpr auto transform(Range &&range, UnaryOp op)
#define OUTER(type, member)
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
auto rfind_unguarded(RANGE &range, const VAL &val, Proj proj={})
Similar to the find(_if)_unguarded functions above, but searches from the back to front.
auto concat(const Range &range, Tail &&... tail)
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
void strAppend(std::string &result, Ts &&...ts)
constexpr auto end(const zstring_view &x)