Fix race between killing object and drawing object
[lsnes.git] / src / core / ui-services.cpp
blobceed96648bf99377903a272316b6ffee6fef95a8
1 #include "cmdhelp/lua.hpp"
2 #include "core/advdumper.hpp"
3 #include "core/command.hpp"
4 #include "core/dispatch.hpp"
5 #include "core/instance.hpp"
6 #include "core/moviedata.hpp"
7 #include "core/project.hpp"
8 #include "core/queue.hpp"
9 #include "core/rom.hpp"
10 #include "core/ui-services.hpp"
11 #include "library/keyboard.hpp"
13 namespace
15 void fill_namemap(project_info& p, uint64_t id, std::map<uint64_t, std::string>& namemap,
16 std::map<uint64_t, std::set<uint64_t>>& childmap)
18 namemap[id] = p.get_branch_name(id);
19 auto s = p.branch_children(id);
20 for(auto i : s)
21 fill_namemap(p, i, namemap, childmap);
22 childmap[id] = s;
25 void update_dumperinfo(emulator_instance& inst, std::map<std::string, dumper_information_1>& new_dumpers,
26 dumper_factory_base* d)
28 struct dumper_information_1 inf;
29 inf.factory = d;
30 inf.name = d->name();
31 std::set<std::string> mset = d->list_submodes();
32 for(auto i : mset)
33 inf.modes[i] = d->modename(i);
34 inf.active = inst.mdumper->busy(d);
35 inf.hidden = d->hidden();
36 new_dumpers[d->id()] = inf;
40 void do_flush_slotinfo();
42 void UI_get_branch_map(emulator_instance& inst, uint64_t& cur, std::map<uint64_t, std::string>& namemap,
43 std::map<uint64_t, std::set<uint64_t>>& childmap)
45 auto project = inst.project;
46 inst.iqueue->run([project, &cur, &namemap, &childmap]() {
47 auto p = project->get();
48 if(!p) return;
49 fill_namemap(*p, 0, namemap, childmap);
50 cur = p->get_current_branch();
51 });
54 void UI_call_flush(emulator_instance& inst, std::function<void(std::exception&)> onerror)
56 auto project = inst.project;
57 inst.iqueue->run_async([project]() {
58 auto p = project->get();
59 if(p) p->flush();
60 }, onerror);
63 void UI_create_branch(emulator_instance& inst, uint64_t id, const std::string& name,
64 std::function<void(std::exception&)> onerror)
66 auto project = inst.project;
67 inst.iqueue->run_async([project, id, name]() {
68 auto p = project->get();
69 if(!p) return;
70 p->create_branch(id, name);
71 p->flush();
72 }, onerror);
75 void UI_rename_branch(emulator_instance& inst, uint64_t id, const std::string& name,
76 std::function<void(std::exception&)> onerror)
78 auto project = inst.project;
79 auto supdater = inst.supdater;
80 inst.iqueue->run_async([project, supdater, id, name]() {
81 auto p = project->get();
82 if(!p) return;
83 p->set_branch_name(id, name);
84 p->flush();
85 supdater->update();
86 }, onerror);
89 void UI_reparent_branch(emulator_instance& inst, uint64_t id, uint64_t pid,
90 std::function<void(std::exception&)> onerror)
92 auto project = inst.project;
93 auto supdater = inst.supdater;
94 inst.iqueue->run_async([project, supdater, id, pid]() {
95 auto p = project->get();
96 if(!p) return;
97 p->set_parent_branch(id, pid);
98 p->flush();
99 supdater->update();
100 }, onerror);
103 void UI_delete_branch(emulator_instance& inst, uint64_t id, std::function<void(std::exception&)> onerror)
105 auto project = inst.project;
106 inst.iqueue->run_async([project, id]() {
107 auto p = project->get();
108 if(!p) return;
109 p->delete_branch(id);
110 p->flush();
111 }, onerror);
114 void UI_switch_branch(emulator_instance& inst, uint64_t id, std::function<void(std::exception&)> onerror)
116 auto project = inst.project;
117 auto supdater = inst.supdater;
118 inst.iqueue->run_async([project, supdater, id]() {
119 auto p = project->get();
120 if(!p) return;
121 p->set_current_branch(id);
122 p->flush();
123 supdater->update();
124 }, onerror);
127 project_author_info UI_load_author_info(emulator_instance& inst)
129 project_author_info x;
130 inst.iqueue->run([&inst, &x]() {
131 project_info* proj = inst.project->get();
132 x.is_project = (proj != NULL);
133 x.autorunlua = false;
134 if(proj) {
135 x.projectname = proj->name;
136 x.directory = proj->directory;
137 x.prefix = proj->prefix;
138 x.luascripts = proj->luascripts;
139 x.gamename = proj->gamename;
140 for(auto i : proj->authors)
141 x.authors.push_back(i);
142 } else {
143 x.prefix = get_mprefix_for_project();
144 x.gamename = inst.mlogic->get_mfile().gamename;
145 for(auto i : inst.mlogic->get_mfile().authors)
146 x.authors.push_back(i);
149 return x;
152 void UI_save_author_info(emulator_instance& inst, project_author_info& info)
154 inst.iqueue->run([&inst, info]() {
155 project_info* proj = inst.project->get();
156 std::set<std::string> oldscripts;
157 std::vector<std::pair<std::string, std::string>> _authors(info.authors.begin(), info.authors.end());
158 if(proj) {
159 for(auto i : proj->luascripts)
160 oldscripts.insert(i);
161 proj->gamename = info.gamename;
162 proj->authors = _authors;
163 proj->prefix = info.prefix;
164 proj->directory = info.directory;
165 proj->name = info.projectname;
166 proj->luascripts = info.luascripts;
167 proj->flush();
168 //For save status to immediately update.
169 do_flush_slotinfo();
170 inst.supdater->update();
171 inst.dispatch->title_change();
172 } else {
173 inst.mlogic->get_mfile().gamename = info.gamename;
174 inst.mlogic->get_mfile().authors = _authors;
175 set_mprefix_for_project(info.prefix);
177 if(proj && info.autorunlua)
178 for(auto i : info.luascripts)
179 if(!oldscripts.count(i))
180 inst.command->invoke(CLUA::run.name, i);
184 dumper_information UI_get_dumpers(emulator_instance& inst)
186 dumper_information x;
187 inst.iqueue->run([&inst, &x]() {
188 std::set<dumper_factory_base*> dset = dumper_factory_base::get_dumper_set();
189 for(auto i : dset)
190 update_dumperinfo(inst, x.dumpers, i);
192 return x;
195 void UI_start_dump(emulator_instance& inst, dumper_factory_base& factory, const std::string& mode,
196 const std::string& prefix)
198 lsnes_instance.iqueue->run([&inst, &factory, mode, prefix]() {
199 inst.mdumper->start(factory, mode, prefix);
203 void UI_end_dump(emulator_instance& inst, dumper_factory_base& factory)
205 lsnes_instance.iqueue->run([&inst, &factory]() {
206 auto in = inst.mdumper->get_instance(&factory);
207 delete in;
211 void UI_do_keypress(emulator_instance& inst, const keyboard::modifier_set& mods, keyboard::key_key& key,
212 bool polarity)
214 auto _key = &key;
215 inst.iqueue->run_async([mods, _key, polarity]() {
216 _key->set_state(mods, polarity ? 1 : 0);
217 }, [](std::exception& e) {});
220 bool UI_has_movie(emulator_instance& inst)
222 bool ret = false;
223 lsnes_instance.iqueue->run([&inst, &ret]() {
224 ret = !!*inst.mlogic && !inst.rom->isnull();
226 return ret;
229 void UI_save_movie(emulator_instance& inst, std::ostringstream& stream)
231 lsnes_instance.iqueue->run([&inst, &stream]() {
232 auto prj = inst.project->get();
233 if(prj) {
234 inst.mlogic->get_mfile().gamename = prj->gamename;
235 inst.mlogic->get_mfile().authors = prj->authors;
237 inst.mlogic->get_mfile().dyn.active_macros.clear();
238 inst.mlogic->get_mfile().save(stream, inst.mlogic->get_rrdata(), false);
242 std::pair<std::string, std::string> UI_lookup_platform_and_game(emulator_instance& inst)
244 std::string plat;
245 std::string game;
246 lsnes_instance.iqueue->run([&inst, &plat, &game]() {
247 auto prj = inst.project->get();
248 if(prj)
249 game = prj->gamename;
250 else
251 game = inst.mlogic->get_mfile().gamename;
252 plat = lookup_sysregion_mapping(inst.mlogic->get_mfile().gametype->get_name());
254 return std::make_pair(plat, game);
257 std::string UI_get_project_otherpath(emulator_instance& inst)
259 std::string path;
260 lsnes_instance.iqueue->run([&inst, &path]() {
261 path = inst.project->otherpath();
263 return path;
266 std::string UI_get_project_moviepath(emulator_instance& inst)
268 std::string path;
269 lsnes_instance.iqueue->run([&inst, &path]() {
270 path = inst.project->moviepath();
272 return path;
275 bool UI_in_project_context(emulator_instance& inst)
277 bool pc;
278 lsnes_instance.iqueue->run([&inst, &pc]() {
279 pc = (inst.project->get() != NULL);
281 return pc;