openMSX
VideoSourceSetting.cc
Go to the documentation of this file.
1 #include "VideoSourceSetting.hh"
2 #include "CommandException.hh"
3 #include "Completer.hh"
4 #include "StringOp.hh"
5 #include "ranges.hh"
6 #include "stl.hh"
7 
8 namespace 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 
23 void VideoSourceSetting::checkSetValue(std::string_view newValue) const
24 {
25  // Special case: in case there are no videosources 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 
66 std::string_view VideoSourceSetting::getTypeString() const
67 {
68  return "enumeration";
69 }
70 
71 std::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;
90  valueList.addListElements(getPossibleValues());
91  result.addListElement(valueList);
92 }
93 
94 void VideoSourceSetting::tabCompletion(std::vector<std::string>& tokens) const
95 {
96  Completer::completeString(tokens, getPossibleValues(),
97  false); // case insensitive
98 }
99 
100 int 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  // shrinked set of values.
121  setSource(getSource()); // via source to (possibly) adjust value
123 }
124 
125 bool VideoSourceSetting::has(int val) const
126 {
127  return contains(sources, val, &Source::id);
128 }
129 
130 int VideoSourceSetting::has(std::string_view val) const
131 {
132  auto it = ranges::find_if(sources, [&](auto& p) {
133  StringOp::casecmp cmp;
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 {
144  id = setting.registerVideoSource(name);
145 }
146 
148 {
149  setting.unregisterVideoSource(id);
150 }
151 
152 } // namespace openmsx
BaseSetting * setting
Definition: Interpreter.cc:27
uintptr_t id
Definition: Interpreter.cc:26
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:160
const TclObject & getValue() const final
Gets the current value of this setting as a TclObject.
Definition: Setting.hh:142
void setValue(const TclObject &newValue) final
Change the value of this setting to the given value.
Definition: Setting.cc:82
void notifyPropertyChange() const
Definition: Setting.cc:115
void addListElement(const T &t)
Definition: TclObject.hh:129
void addListElements(ITER first, ITER last)
Definition: TclObject.hh:130
zstring_view getString() const
Definition: TclObject.cc:111
VideoSourceActivator(VideoSourceSetting &setting, const std::string &name)
void tabCompletion(std::vector< std::string > &tokens) const override
Complete a partly typed value.
void unregisterVideoSource(int source)
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)
This file implemented 3 utility functions:
Definition: Autofire.cc:9
auto find_if(InputRange &&range, UnaryPredicate pred)
Definition: ranges.hh:143
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)
Definition: zstring_view.hh:84