OXYGENHUB
◆ main openmsx / src / commands / MSXCommandController.cc
5.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "MSXCommandController.hh"
2
3
#include "GlobalCommandController.hh"
4
#include "Interpreter.hh"
5
6
#include "Event.hh"
7
#include "MSXEventDistributor.hh"
8
#include "MSXException.hh"
9
#include "MSXMotherBoard.hh"
10
#include "Reactor.hh"
11
#include "Setting.hh"
12
#include "SettingsManager.hh"
13
14
#include "TemporaryString.hh"
15
#include "stl.hh"
16
17
#include <algorithm>
18
#include <iostream>
19
#include <memory>
20
21
namespace openmsx {
22
23
MSXCommandController::MSXCommandController(
24
		GlobalCommandController& globalCommandController_,
25
		Reactor& reactor_,
26
		MSXMotherBoard& motherboard_,
27
		MSXEventDistributor& msxEventDistributor_,
28
		const std::string& machineID_)
29
	: globalCommandController(globalCommandController_)
30
	, reactor(reactor_)
31
	, motherboard(motherboard_)
32
	, msxEventDistributor(msxEventDistributor_)
33
	, machineID(strCat("::", machineID_, "::"))
34
{
35
	globalCommandController.getInterpreter().createNamespace(machineID);
36
37
	machineInfoCommand.emplace(*this, "machine_info");
38
	machineInfoCommand->setAllowedInEmptyMachine(true);
39
40
	msxEventDistributor.registerEventListener(*this);
41
}
42
43
MSXCommandController::~MSXCommandController()
44
{
45
	msxEventDistributor.unregisterEventListener(*this);
46
47
	machineInfoCommand.reset();
48
49
	#ifndef NDEBUG
50
	for (const auto* c : commandMap) {
51
		std::cout << "Command not unregistered: " << c->getName() << '\n';
52
	}
53
	for (const auto* s : settings) {
54
		std::cout << "Setting not unregistered: " << s->getFullName() << '\n';
55
	}
56
	assert(commandMap.empty());
57
	assert(settings.empty());
58
	#endif
59
60
	globalCommandController.getInterpreter().deleteNamespace(machineID);
61
}
62
63
TemporaryString MSXCommandController::getFullName(std::string_view name)
64
{
65
	return tmpStrCat(machineID, name);
66
}
67
68
void MSXCommandController::registerCommand(Command& command, zstring_view str)
69
{
70
	assert(!hasCommand(str));
71
	assert(command.getName() == str);
72
	commandMap.insert_noDuplicateCheck(&command);
73
74
	auto fullname = getFullName(str);
75
	globalCommandController.registerCommand(command, fullname);
76
	globalCommandController.registerProxyCommand(str);
77
78
	command.setAllowedInEmptyMachine(false);
79
}
80
81
void MSXCommandController::unregisterCommand(Command& command, std::string_view str)
82
{
83
	assert(hasCommand(str));
84
	assert(command.getName() == str);
85
	commandMap.erase(str);
86
87
	globalCommandController.unregisterProxyCommand(str);
88
	auto fullname = getFullName(str);
89
	globalCommandController.unregisterCommand(command, fullname);
90
}
91
92
void MSXCommandController::registerCompleter(CommandCompleter& completer,
93
                                             std::string_view str)
94
{
95
	auto fullname = getFullName(str);
96
	globalCommandController.registerCompleter(completer, fullname);
97
}
98
99
void MSXCommandController::unregisterCompleter(CommandCompleter& completer,
100
                                               std::string_view str)
101
{
102
	auto fullname = getFullName(str);
103
	globalCommandController.unregisterCompleter(completer, fullname);
104
}
105
106
void MSXCommandController::registerSetting(Setting& setting)
107
{
108
	setting.setPrefix(machineID);
109
110
	settings.push_back(&setting);
111
112
	globalCommandController.registerProxySetting(setting);
113
	globalCommandController.getSettingsManager().registerSetting(setting);
114
	globalCommandController.getInterpreter().registerSetting(setting);
115
}
116
117
void MSXCommandController::unregisterSetting(Setting& setting)
118
{
119
	move_pop_back(settings, rfind_unguarded(settings, &setting));
120
121
	globalCommandController.unregisterProxySetting(setting);
122
	globalCommandController.getInterpreter().unregisterSetting(setting);
123
	globalCommandController.getSettingsManager().unregisterSetting(setting);
124
}
125
126
Setting* MSXCommandController::findSetting(std::string_view name) const
127
{
128
	auto it = std::ranges::find(settings, name, &Setting::getBaseName);
129
	return it != settings.end() ? *it : nullptr;
130
}
131
132
Command* MSXCommandController::findCommand(std::string_view name) const
133
{
134
	auto it = commandMap.find(name);
135
	return (it != end(commandMap)) ? *it : nullptr;
136
}
137
138
bool MSXCommandController::hasCommand(std::string_view command) const
139
{
140
	return findCommand(command) != nullptr;
141
}
142
143
TclObject MSXCommandController::executeCommand(zstring_view command,
144
                                               CliConnection* connection)
145
{
146
	return globalCommandController.executeCommand(command, connection);
147
}
148
149
MSXCliComm& MSXCommandController::getCliComm()
150
{
151
	return motherboard.getMSXCliComm();
152
}
153
154
Interpreter& MSXCommandController::getInterpreter()
155
{
156
	return globalCommandController.getInterpreter();
157
}
158
159
void MSXCommandController::signalMSXEvent(
160
	const Event& event, EmuTime /*time*/) noexcept
161
{
162
	if (getType(event) != EventType::MACHINE_ACTIVATED) return;
163
164
	// simple way to synchronize proxy settings
165
	for (const auto* s : settings) {
166
		try {
167
			getInterpreter().setVariable(
168
				s->getFullNameObj(), s->getValue());
169
		} catch (MSXException&) {
170
			// ignore
171
		}
172
	}
173
}
174
175
bool MSXCommandController::isActive() const
176
{
177
	return reactor.getMotherBoard() == &motherboard;
178
}
179
180
void MSXCommandController::transferSettings(const MSXCommandController& from)
181
{
182
	const auto& fromPrefix = from.getPrefix();
183
	const auto& manager = globalCommandController.getSettingsManager();
184
	for (const auto* s : settings) {
185
		if (const auto* fromSetting = manager.findSetting(fromPrefix, s->getBaseName())) {
186
			if (!fromSetting->needTransfer()) continue;
187
			try {
188
				getInterpreter().setVariable(
189
					s->getFullNameObj(), fromSetting->getValue());
190
			} catch (MSXException&) {
191
				// ignore
192
			}
193
		}
194
	}
195
}
196
197
} // namespace openmsx