Use urandom / rtlgenrandom
[lsnes.git] / src / platform / wxwidgets / editor-multitrack.cpp
blobf0c6ca9023133f631cbe9b7aaba76c61b9eae90b
1 #include "core/controller.hpp"
2 #include "core/movie.hpp"
3 #include "core/moviedata.hpp"
4 #include "core/multitrack.hpp"
5 #include "core/dispatch.hpp"
6 #include "core/window.hpp"
8 #include "interface/controller.hpp"
9 #include "core/mainloop.hpp"
10 #include "platform/wxwidgets/platform.hpp"
11 #include "platform/wxwidgets/textrender.hpp"
12 #include "library/minmax.hpp"
13 #include "library/string.hpp"
14 #include "library/utf8.hpp"
16 #include <algorithm>
17 #include <cstring>
18 #include <wx/wx.h>
19 #include <wx/event.h>
20 #include <wx/control.h>
21 #include <wx/combobox.h>
22 #include <wx/statline.h>
23 #include <wx/spinctrl.h>
25 #define MTMODE_PRESERVE "Preserve"
26 #define MTMODE_OVERWRITE "Overwrite"
27 #define MTMODE_OR "OR"
28 #define MTMODE_XOR "XOR"
30 namespace
34 class wxeditor_multitrack : public wxDialog
36 public:
37 wxeditor_multitrack(wxWindow* parent);
38 ~wxeditor_multitrack() throw();
39 bool ShouldPreventAppExit() const;
40 void on_wclose(wxCloseEvent& e);
41 void on_control(wxCommandEvent& e);
42 private:
43 struct dispatch::target<> ahreconfigure;
44 struct dispatch::target<bool> ahmodechange;
45 struct dispatch::target<unsigned, unsigned, int> ahmtchange;
46 struct controller_info
48 unsigned port;
49 unsigned controller;
50 wxStaticText* text;
51 wxComboBox* mode;
53 struct controller_info2
55 std::string name;
56 unsigned port;
57 unsigned controller;
59 std::vector<controller_info> controllers;
60 void update_controls();
61 bool closing;
62 wxFlexGridSizer* vsizer;
63 const port_type_set* typeset;
66 namespace
68 wxeditor_multitrack* multitrack_open;
71 wxeditor_multitrack::~wxeditor_multitrack() throw() {}
73 wxeditor_multitrack::wxeditor_multitrack(wxWindow* parent)
74 : wxDialog(parent, wxID_ANY, wxT("lsnes: Multitrack recording"), wxDefaultPosition, wxSize(-1, -1))
76 typeset = NULL;
77 closing = false;
78 Centre();
79 vsizer = new wxFlexGridSizer(0, 2, 0, 0);
80 SetSizer(vsizer);
81 Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(wxeditor_multitrack::on_wclose));
82 update_controls();
83 vsizer->SetSizeHints(this);
84 Fit();
86 ahreconfigure.set(notify_autohold_reconfigure, [this]() {
87 if(typeset && *typeset == controls.get_blank().porttypes())
88 return; //Don't reconfigure if no change.
89 multitrack_editor.config_altered();
90 runuifun([this]() {
91 try {
92 this->update_controls();
93 } catch(std::runtime_error& e) {
94 //Close the window.
95 bool wasc = closing;
96 closing = true;
97 multitrack_open = NULL;
98 runemufn([]() { multitrack_editor.enable(false); });
99 if(!wasc)
100 Destroy();
104 ahmodechange.set(notify_mode_change, [this](bool readonly) {
105 runuifun([this, readonly]() {
106 for(auto i : controllers)
107 i.mode->Enable(readonly);
110 ahmtchange.set(notify_multitrack_change, [this](unsigned port, unsigned controller, int state) {
111 runuifun([this, port, controller, state]() {
112 for(auto i : controllers) {
113 if(i.port == port && i.controller == controller) {
114 auto cb = i.mode;
115 if(state == multitrack_edit::MT_OR)
116 cb->SetStringSelection(towxstring(MTMODE_OR));
117 if(state == multitrack_edit::MT_OVERWRITE)
118 cb->SetStringSelection(towxstring(MTMODE_OVERWRITE));
119 if(state == multitrack_edit::MT_PRESERVE)
120 cb->SetStringSelection(towxstring(MTMODE_PRESERVE));
121 if(state == multitrack_edit::MT_XOR)
122 cb->SetStringSelection(towxstring(MTMODE_XOR));
129 void wxeditor_multitrack::on_control(wxCommandEvent& e)
131 int id = e.GetId();
132 if(id < wxID_HIGHEST + 1)
133 return;
134 size_t ctrl = id - wxID_HIGHEST - 1;
135 if(ctrl >= controllers.size())
136 return;
137 controller_info& ci = controllers[ctrl];
138 std::string mode = tostdstring(ci.mode->GetStringSelection());
139 runemufn([ci, mode]() {
140 if(mode == MTMODE_PRESERVE)
141 multitrack_editor.set(ci.port, ci.controller, multitrack_edit::MT_PRESERVE);
142 else if(mode == MTMODE_OVERWRITE)
143 multitrack_editor.set(ci.port, ci.controller, multitrack_edit::MT_OVERWRITE);
144 else if(mode == MTMODE_OR)
145 multitrack_editor.set(ci.port, ci.controller, multitrack_edit::MT_OR);
146 else if(mode == MTMODE_XOR)
147 multitrack_editor.set(ci.port, ci.controller, multitrack_edit::MT_XOR);
151 void wxeditor_multitrack::update_controls()
153 bool readonly = movb.get_movie().readonly_mode();
155 for(auto i : controllers) {
156 vsizer->Detach(i.text);
157 vsizer->Detach(i.mode);
158 i.text->Destroy();
159 i.mode->Destroy();
161 controllers.clear();
162 std::vector<controller_info2> info;
163 runemufn([this, &info](){
164 std::map<std::string, unsigned> next_in_class;
165 controller_frame model = controls.get_blank();
166 const port_type_set& pts = model.porttypes();
167 typeset = &pts;
168 unsigned cnum_g = 0;
169 for(unsigned i = 0;; i++) {
170 auto pcid = controls.lcid_to_pcid(i);
171 if(pcid.first < 0)
172 break;
173 const port_type& pt = pts.port_type(pcid.first);
174 const port_controller_set& pci = *(pt.controller_info);
175 if((ssize_t)pci.controllers.size() <= pcid.second)
176 continue;
177 const port_controller& pc = pci.controllers[pcid.second];
178 //First check that this has non-hidden stuff.
179 bool has_buttons = false;
180 for(unsigned k = 0; k < pc.buttons.size(); k++) {
181 const port_controller_button& pcb = pc.buttons[k];
182 if(!pcb.shadow)
183 has_buttons = true;
185 if(!has_buttons)
186 continue;
187 //Okay, a valid controller.
188 if(!next_in_class.count(pc.cclass))
189 next_in_class[pc.cclass] = 1;
190 uint32_t cnum = next_in_class[pc.cclass]++;
191 controller_info2 _info;
192 _info.name = (stringfmt() << pc.cclass << "-" << cnum).str();
193 _info.port = pcid.first;
194 _info.controller = pcid.second;
195 info.push_back(_info);
196 cnum_g++;
199 if(info.empty())
200 throw std::runtime_error("No controllers");
201 unsigned index = 0;
202 for(auto i : info) {
203 struct controller_info _info;
204 _info.port = i.port;
205 _info.controller = i.controller;
206 _info.text = new wxStaticText(this, wxID_ANY, towxstring(i.name));
207 vsizer->Add(_info.text, 0, wxGROW);
208 std::vector<wxString> choices;
209 choices.push_back(towxstring(MTMODE_PRESERVE));
210 choices.push_back(towxstring(MTMODE_OVERWRITE));
211 choices.push_back(towxstring(MTMODE_OR));
212 choices.push_back(towxstring(MTMODE_XOR));
213 _info.mode = new wxComboBox(this, wxID_HIGHEST + 1 + index, choices[0], wxDefaultPosition,
214 wxDefaultSize, choices.size(), &choices[0], wxCB_READONLY);
215 _info.mode->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED,
216 wxCommandEventHandler(wxeditor_multitrack::on_control), NULL, this);
217 if(!readonly)
218 _info.mode->Enable(false);
219 vsizer->Add(_info.mode, 0, wxGROW);
220 controllers.push_back(_info);
221 index++;
223 vsizer->Layout();
224 Fit();
227 bool wxeditor_multitrack::ShouldPreventAppExit() const { return false; }
229 void wxeditor_multitrack::on_wclose(wxCloseEvent& e)
231 bool wasc = closing;
232 closing = true;
233 multitrack_open = NULL;
234 runemufn([]() { multitrack_editor.enable(false); });
235 if(!wasc)
236 Destroy();
239 void wxeditor_multitrack_display(wxWindow* parent)
241 if(multitrack_open)
242 return;
243 wxeditor_multitrack* v;
244 try {
245 v = new wxeditor_multitrack(parent);
246 } catch(std::runtime_error& e) {
247 wxMessageBox(_T("No controllers present"), _T("Error"), wxICON_EXCLAMATION | wxOK, parent);
248 return;
250 v->Show();
251 multitrack_open = v;
252 runemufn([]() { multitrack_editor.enable(true); });