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