openMSX
VideoSourceSetting.cc
Go to the documentation of this file.
2#include "CommandException.hh"
3#include "Completer.hh"
4#include "StringOp.hh"
5#include "ranges.hh"
6#include "stl.hh"
7
8namespace openmsx {
9
11 : Setting(commandController_, "videosource",
12 "selects the video source to display on the screen",
13 TclObject("none"), DONT_SAVE)
14{
15 sources = { { "none", 0 } };
16
17 setChecker([this](TclObject& newValue) {
18 checkSetValue(newValue.getString()); // may throw
19 });
20 init();
21}
22
23void VideoSourceSetting::checkSetValue(std::string_view newValue) const
24{
25 // Special case: in case there are no video sources registered (yet),
26 // the only allowed value is "none". In case there is at least one
27 // registered source, this special value "none" should be hidden.
28 if (((newValue == "none") && (sources.size() > 1)) ||
29 ((newValue != "none") && !has(newValue))) {
30 throw CommandException("video source not available");
31 }
32}
33
35{
36 // Always try to find a better value than "none".
37 std::string_view str = getValue().getString();
38 if (str != "none") {
39 // If current value is allowed, then keep it.
40 if (int id = has(str)) {
41 return id;
42 }
43 }
44 // Search the best value from the current set of allowed values.
45 int id = 0;
46 if (!id) { id = has("Video9000"); } // in
47 if (!id) { id = has("MSX"); } // order
48 if (!id) { id = has("GFX9000"); } // of
49 if (!id) { id = has("Laserdisc"); } // preference
50 if (!id) {
51 // This handles the "none" case, but also stuff like
52 // multiple V99x8/V9990 chips. Prefer the source with
53 // highest id (=newest).
54 id = max_value(sources, &Source::id);
55 }
56 setSource(id); // store new value
57 return id;
58}
59
61{
62 auto it = find_unguarded(sources, id, &Source::id);
63 setValue(TclObject(it->name));
64}
65
66std::string_view VideoSourceSetting::getTypeString() const
67{
68 return "enumeration";
69}
70
71std::vector<std::string_view> VideoSourceSetting::getPossibleValues() const
72{
73 std::vector<std::string_view> result;
74 if (sources.size() == 1) {
75 assert(sources.front().name == "none");
76 result.emplace_back("none");
77 } else {
78 for (const auto& [name, val] : sources) {
79 if (val != 0) {
80 result.emplace_back(name);
81 }
82 }
83 }
84 return result;
85}
86
88{
89 TclObject valueList;
91 result.addListElement(valueList);
92}
93
94void VideoSourceSetting::tabCompletion(std::vector<std::string>& tokens) const
95{
97 false); // case insensitive
98}
99
100int VideoSourceSetting::registerVideoSource(const std::string& source)
101{
102 static int counter = 0; // id's are globally unique
103
104 assert(!has(source));
105 sources.emplace_back(Source{source, ++counter});
106
107 // First announce extended set of allowed values before announcing a
108 // (possibly) different value.
110 setSource(getSource()); // via source to (possibly) adjust value
111
112 return counter;
113}
114
116{
117 move_pop_back(sources, rfind_unguarded(sources, source, &Source::id));
118
119 // First notify the (possibly) changed value before announcing the
120 // shrunken set of values.
121 setSource(getSource()); // via source to (possibly) adjust value
123}
124
125bool VideoSourceSetting::has(int val) const
126{
127 return contains(sources, val, &Source::id);
128}
129
130int VideoSourceSetting::has(std::string_view val) const
131{
132 auto it = ranges::find_if(sources, [&](auto& p) {
134 return cmp(p.name, val);
135 });
136 return (it != end(sources)) ? it->id : 0;
137}
138
139
141 VideoSourceSetting& setting_, const std::string& name)
142 : setting(setting_)
143 , id(setting.registerVideoSource(name))
144{
145}
146
151
152} // namespace openmsx
BaseSetting * setting
uintptr_t id
static void completeString(std::vector< std::string > &tokens, ITER begin, ITER end, bool caseSensitive=true)
Definition Completer.hh:133
void setChecker(std::function< void(TclObject &)> checkFunc_)
Set value-check-callback.
Definition Setting.hh:145
const TclObject & getValue() const final
Gets the current value of this setting as a TclObject.
Definition Setting.hh:133
void setValue(const TclObject &newValue) final
Change the value of this setting to the given value.
Definition Setting.cc:81
void notifyPropertyChange() const
Definition Setting.cc:111
void addListElement(const T &t)
Definition TclObject.hh:127
void addListElements(ITER first, ITER last)
Definition TclObject.hh:128
zstring_view getString() const
Definition TclObject.cc:142
VideoSourceActivator(VideoSourceSetting &setting, const std::string &name)
void tabCompletion(std::vector< std::string > &tokens) const override
Complete a partly typed value.
void additionalInfo(TclObject &result) const override
Helper method for info().
VideoSourceSetting(CommandController &commandController)
std::string_view getTypeString() const override
Returns a string describing the setting type (integer, string, ..) Could be used in a GUI to pick an ...
int registerVideoSource(const std::string &source)
std::vector< std::string_view > getPossibleValues() const
This file implemented 3 utility functions:
Definition Autofire.cc:9
auto find_if(InputRange &&range, UnaryPredicate pred)
Definition ranges.hh:173
ITER find_unguarded(ITER first, ITER last, const VAL &val, Proj proj={})
Faster alternative to 'find' when it's guaranteed that the value will be found (if not the behavior i...
Definition stl.hh:72
auto max_value(InputIterator first, InputIterator last, Proj proj={})
Definition stl.hh:224
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
Definition stl.hh:134
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.
Definition stl.hh:109
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
Definition stl.hh:32
constexpr auto end(const zstring_view &x)