Get rid of direct references to emulation thread in branchesmenu.cpp

This commit is contained in:
Ilari Liusvaara 2014-05-31 18:16:05 +03:00
parent 6bad138d8b
commit d7c6cd1905
6 changed files with 164 additions and 75 deletions

View file

@ -13,6 +13,7 @@ class memwatch_set;
class controller_state; class controller_state;
class button_mapping; class button_mapping;
class emulator_dispatch; class emulator_dispatch;
class input_queue;
namespace command namespace command
{ {
class group; class group;
@ -169,7 +170,7 @@ class project_state
public: public:
project_state(voice_commentary& _commentary, memwatch_set& _mwatch, command::group& _command, project_state(voice_commentary& _commentary, memwatch_set& _mwatch, command::group& _command,
controller_state& _controls, settingvar::cache& _setcache, button_mapping& _buttons, controller_state& _controls, settingvar::cache& _setcache, button_mapping& _buttons,
emulator_dispatch& _edispatch); emulator_dispatch& _edispatch, input_queue& _iqueue);
~project_state(); ~project_state();
/** /**
* Get currently active project. * Get currently active project.
@ -223,6 +224,49 @@ public:
* Copy macros to project. * Copy macros to project.
*/ */
void copy_macros(project_info& p, controller_state& s); void copy_macros(project_info& p, controller_state& s);
/**
* Fill branch name map.
*
* Notes: Safe to call from another thread.
*/
void F_get_branch_map(uint64_t& cur, std::map<uint64_t, std::string>& namemap,
std::map<uint64_t, std::set<uint64_t>>& childmap);
/**
* Arrange current project to be flushed later.
*
* Notes: Safe to call from another thread.
*/
void F_call_flush(std::function<void(std::exception&)> onerror);
/**
* Arrage branch to be created.
*
* Notes: Safe to call from another thread.
*/
void F_create_branch(uint64_t id, const std::string& name, std::function<void(std::exception&)> onerror);
/**
* Arrage branch to be renamed.
*
* Notes: Safe to call from another thread.
*/
void F_rename_branch(uint64_t id, const std::string& name, std::function<void(std::exception&)> onerror);
/**
* Arrage branch to be reparented.
*
* Notes: Safe to call from another thread.
*/
void F_reparent_branch(uint64_t id, uint64_t pid, std::function<void(std::exception&)> onerror);
/**
* Arrage branch to be deleted.
*
* Notes: Safe to call from another thread.
*/
void F_delete_branch(uint64_t id, std::function<void(std::exception&)> onerror);
/**
* Arrage branch to be switched.
*
* Notes: Safe to call from another thread.
*/
void F_switch_branch(uint64_t id, std::function<void(std::exception&)> onerror);
private: private:
project_info* active_project; project_info* active_project;
voice_commentary& commentary; voice_commentary& commentary;
@ -232,6 +276,7 @@ private:
settingvar::cache& setcache; settingvar::cache& setcache;
button_mapping& buttons; button_mapping& buttons;
emulator_dispatch& edispatch; emulator_dispatch& edispatch;
input_queue& iqueue;
}; };
#endif #endif

View file

@ -107,6 +107,7 @@ void show_message_ok(wxWindow* parent, const std::string& title, const std::stri
bool run_show_error(wxWindow* parent, const std::string& title, const std::string& text, std::function<void()> fn); bool run_show_error(wxWindow* parent, const std::string& title, const std::string& text, std::function<void()> fn);
void show_exception(wxWindow* parent, const std::string& title, const std::string& text, std::exception& e); void show_exception(wxWindow* parent, const std::string& title, const std::string& text, std::exception& e);
void show_exception_any(wxWindow* parent, const std::string& title, const std::string& text, std::exception& e);
//Some important windows (if open). //Some important windows (if open).
extern wxwin_messages* msg_window; extern wxwin_messages* msg_window;

View file

@ -68,6 +68,8 @@ emulator_instance::emulator_instance()
D.prealloc(buttons); D.prealloc(buttons);
D.init(dispatch); D.init(dispatch);
D.init(command);
D.init(iqueue, *command);
D.init(mlogic); D.init(mlogic);
D.init(memory); D.init(memory);
D.init(lua); D.init(lua);
@ -79,7 +81,6 @@ emulator_instance::emulator_instance()
D.init(mbranch, *mlogic, *dispatch); D.init(mbranch, *mlogic, *dispatch);
D.init(controls, *project, *mlogic, *buttons, *dispatch); D.init(controls, *project, *mlogic, *buttons, *dispatch);
D.init(keyboard); D.init(keyboard);
D.init(command);
D.init(mapper, *keyboard, *command); D.init(mapper, *keyboard, *command);
D.init(fbuf, *subtitles, *settings, *mwatch, *keyboard, *dispatch); D.init(fbuf, *subtitles, *settings, *mwatch, *keyboard, *dispatch);
D.init(buttons, *controls, *mapper, *keyboard, *fbuf, *dispatch); D.init(buttons, *controls, *mapper, *keyboard, *fbuf, *dispatch);
@ -91,10 +92,9 @@ emulator_instance::emulator_instance()
D.init(abindmanager, *mapper, *command); D.init(abindmanager, *mapper, *command);
D.init(nrrdata); D.init(nrrdata);
D.init(cmapper, *memory, *mlogic); D.init(cmapper, *memory, *mlogic);
D.init(project, *commentary, *mwatch, *command, *controls, *setcache, *buttons, *dispatch); D.init(project, *commentary, *mwatch, *command, *controls, *setcache, *buttons, *dispatch, *iqueue);
D.init(dbg, *dispatch); D.init(dbg, *dispatch);
D.init(framerate); D.init(framerate);
D.init(iqueue, *command);
D.init(mdumper); D.init(mdumper);
status_A->valid = false; status_A->valid = false;

View file

@ -9,6 +9,7 @@
#include "core/moviedata.hpp" #include "core/moviedata.hpp"
#include "core/moviefile.hpp" #include "core/moviefile.hpp"
#include "core/project.hpp" #include "core/project.hpp"
#include "core/queue.hpp"
#include "library/directory.hpp" #include "library/directory.hpp"
#include "library/minmax.hpp" #include "library/minmax.hpp"
#include "library/string.hpp" #include "library/string.hpp"
@ -24,6 +25,16 @@ void do_flush_slotinfo();
namespace namespace
{ {
void fill_namemap(project_info& p, uint64_t id, std::map<uint64_t, std::string>& namemap,
std::map<uint64_t, std::set<uint64_t>>& childmap)
{
namemap[id] = p.get_branch_name(id);
auto s = p.branch_children(id);
for(auto i : s)
fill_namemap(p, i, namemap, childmap);
childmap[id] = s;
}
void concatenate(std::vector<char>& data, const std::vector<char>& app) void concatenate(std::vector<char>& data, const std::vector<char>& app)
{ {
size_t dsize = data.size(); size_t dsize = data.size();
@ -188,9 +199,9 @@ namespace
project_state::project_state(voice_commentary& _commentary, memwatch_set& _mwatch, command::group& _command, project_state::project_state(voice_commentary& _commentary, memwatch_set& _mwatch, command::group& _command,
controller_state& _controls, settingvar::cache& _setcache, button_mapping& _buttons, controller_state& _controls, settingvar::cache& _setcache, button_mapping& _buttons,
emulator_dispatch& _edispatch) emulator_dispatch& _edispatch, input_queue& _iqueue)
: commentary(_commentary), mwatch(_mwatch), command(_command), controls(_controls), setcache(_setcache), : commentary(_commentary), mwatch(_mwatch), command(_command), controls(_controls), setcache(_setcache),
buttons(_buttons), edispatch(_edispatch) buttons(_buttons), edispatch(_edispatch), iqueue(_iqueue)
{ {
active_project = NULL; active_project = NULL;
} }
@ -479,6 +490,80 @@ void project_state::copy_macros(project_info& p, controller_state& s)
p.macros[i] = s.get_macro(i).serialize(); p.macros[i] = s.get_macro(i).serialize();
} }
void project_state::F_get_branch_map(uint64_t& cur, std::map<uint64_t, std::string>& namemap,
std::map<uint64_t, std::set<uint64_t>>& childmap)
{
iqueue.run([this, &cur, &namemap, &childmap]() {
auto p = this->get();
if(!p) return;
fill_namemap(*p, 0, namemap, childmap);
cur = p->get_current_branch();
});
}
void project_state::F_call_flush(std::function<void(std::exception&)> onerror)
{
iqueue.run_async([this]() {
auto p = this->get();
if(p) p->flush();
}, onerror);
}
void project_state::F_create_branch(uint64_t id, const std::string& name,
std::function<void(std::exception&)> onerror)
{
iqueue.run_async([this, id, name]() {
auto p = this->get();
if(!p) return;
p->create_branch(id, name);
p->flush();
}, onerror);
}
void project_state::F_rename_branch(uint64_t id, const std::string& name,
std::function<void(std::exception&)> onerror)
{
iqueue.run_async([this, id, name]() {
auto p = this->get();
if(!p) return;
p->set_branch_name(id, name);
p->flush();
update_movie_state();
}, onerror);
}
void project_state::F_reparent_branch(uint64_t id, uint64_t pid, std::function<void(std::exception&)> onerror)
{
iqueue.run_async([this, id, pid]() {
auto p = this->get();
if(!p) return;
p->set_parent_branch(id, pid);
p->flush();
update_movie_state();
}, onerror);
}
void project_state::F_delete_branch(uint64_t id, std::function<void(std::exception&)> onerror)
{
iqueue.run_async([this, id]() {
auto p = this->get();
if(!p) return;
p->delete_branch(id);
p->flush();
}, onerror);
}
void project_state::F_switch_branch(uint64_t id, std::function<void(std::exception&)> onerror)
{
iqueue.run_async([this, id]() {
auto p = this->get();
if(!p) return;
p->set_current_branch(id);
p->flush();
update_movie_state();
}, onerror);
}
project_info::project_info(emulator_dispatch& _dispatch) project_info::project_info(emulator_dispatch& _dispatch)
: edispatch(_dispatch) : edispatch(_dispatch)
{ {
@ -530,6 +615,8 @@ void project_info::set_parent_branch(uint64_t bid, uint64_t pbid)
throw std::runtime_error("Invalid branch ID"); throw std::runtime_error("Invalid branch ID");
if(pbid && !branches.count(pbid)) if(pbid && !branches.count(pbid))
throw std::runtime_error("Invalid parent branch ID"); throw std::runtime_error("Invalid parent branch ID");
if(bid == pbid)
throw std::runtime_error("Branch can't be its own parent");
for(auto& i : branches) { for(auto& i : branches) {
uint64_t j = i.first; uint64_t j = i.first;
while(j) { while(j) {

View file

@ -13,16 +13,6 @@ void update_movie_state();
namespace namespace
{ {
void fill_namemap(project_info& p, uint64_t id, std::map<uint64_t, std::string>& namemap,
std::map<uint64_t, std::set<uint64_t>>& childmap)
{
namemap[id] = p.get_branch_name(id);
auto s = p.branch_children(id);
for(auto i : s)
fill_namemap(p, i, namemap, childmap);
childmap[id] = s;
}
//Tree of branches. //Tree of branches.
class branches_tree : public wxTreeCtrl class branches_tree : public wxTreeCtrl
{ {
@ -68,12 +58,7 @@ namespace
std::map<uint64_t, std::string> namemap; std::map<uint64_t, std::string> namemap;
std::map<uint64_t, std::set<uint64_t>> childmap; std::map<uint64_t, std::set<uint64_t>> childmap;
uint64_t cur = 0; uint64_t cur = 0;
lsnes_instance.iqueue->run([&cur, &namemap, &childmap]() { lsnes_instance.project->F_get_branch_map(cur, namemap, childmap);
auto p = lsnes_instance.project->get();
if(!p) return;
fill_namemap(*p, 0, namemap, childmap);
cur = p->get_current_branch();
});
current = cur; current = cur;
selection cursel = get_selection(); selection cursel = get_selection();
std::set<uint64_t> expanded; std::set<uint64_t> expanded;
@ -103,13 +88,6 @@ namespace
return names[id]; return names[id];
return ""; return "";
} }
void call_project_flush()
{
lsnes_instance.iqueue->run_async([] {
auto p = CORE().project->get();
if(p) p->flush();
}, [](std::exception& e) {});
}
private: private:
void build_tree(uint64_t id, wxTreeItemId parent, std::map<uint64_t, std::set<uint64_t>>& childmap, void build_tree(uint64_t id, wxTreeItemId parent, std::map<uint64_t, std::set<uint64_t>>& childmap,
std::map<uint64_t, std::string>& namemap) std::map<uint64_t, std::string>& namemap)
@ -236,26 +214,17 @@ namespace
} catch(canceled_exception& e) { } catch(canceled_exception& e) {
return; return;
} }
lsnes_instance.iqueue->run([this, id, newname]() { lsnes_instance.project->F_create_branch(id, newname, [this](std::exception& e) {
run_show_error(this, "Error creating branch", "Can't create branch", [id, newname]() { show_exception_any(this, "Error creating branch", "Can't create branch", e);
auto p = CORE().project->get();
if(p) p->create_branch(id, newname);
});
}); });
branches->call_project_flush();
} }
void on_select(wxCommandEvent& e) void on_select(wxCommandEvent& e)
{ {
uint64_t id = get_selected_id(); uint64_t id = get_selected_id();
if(id == 0xFFFFFFFFFFFFFFFFULL) return; if(id == 0xFFFFFFFFFFFFFFFFULL) return;
lsnes_instance.iqueue->run([this, id]() { lsnes_instance.project->F_switch_branch(id, [this](std::exception& e) {
run_show_error(this, "Error setting branch", "Can't set branch", [id]() { show_exception_any(this, "Error setting branch", "Can't set branch", e);
auto p = CORE().project->get();
if(p) p->set_current_branch(id);
});
}); });
branches->call_project_flush();
update_movie_state();
} }
void on_rename(wxCommandEvent& e) void on_rename(wxCommandEvent& e)
{ {
@ -268,14 +237,9 @@ namespace
} catch(canceled_exception& e) { } catch(canceled_exception& e) {
return; return;
} }
lsnes_instance.iqueue->run([this, id, newname]() { lsnes_instance.project->F_rename_branch(id, newname, [this](std::exception& e) {
run_show_error(this, "Error renaming branch", "Can't rename branch", [id, newname]() { show_exception_any(this, "Error renaming branch", "Can't rename branch", e);
auto p = CORE().project->get();
if(p) p->set_branch_name(id, newname);
});
}); });
branches->call_project_flush();
update_movie_state();
} }
void on_reparent(wxCommandEvent& e) void on_reparent(wxCommandEvent& e)
{ {
@ -291,27 +255,17 @@ namespace
pid = bsel->get_selection(); pid = bsel->get_selection();
if(pid == 0xFFFFFFFFFFFFFFFFULL) return; if(pid == 0xFFFFFFFFFFFFFFFFULL) return;
bsel->Destroy(); bsel->Destroy();
lsnes_instance.iqueue->run([this, id, pid]() { lsnes_instance.project->F_reparent_branch(id, pid, [this](std::exception& e) {
run_show_error(this, "Error reparenting branch", "Can't reparent branch", show_exception_any(this, "Error reparenting branch", "Can't reparent branch", e);
[id, pid]() {
auto p = CORE().project->get();
if(p) p->set_parent_branch(id, pid);
});
}); });
branches->call_project_flush();
update_movie_state();
} }
void on_delete(wxCommandEvent& e) void on_delete(wxCommandEvent& e)
{ {
uint64_t id = get_selected_id(); uint64_t id = get_selected_id();
if(id == 0xFFFFFFFFFFFFFFFFULL) return; if(id == 0xFFFFFFFFFFFFFFFFULL) return;
lsnes_instance.iqueue->run([this, id]() { lsnes_instance.project->F_delete_branch(id, [this](std::exception& e) {
run_show_error(this, "Error deleting branch", "Can't delete branch", [id]() { show_exception_any(this, "Error deleting branch", "Can't delete branch", e);
auto p = CORE().project->get();
if(p) p->delete_branch(id);
});
}); });
branches->call_project_flush();
} }
void on_close(wxCommandEvent& e) void on_close(wxCommandEvent& e)
{ {
@ -407,13 +361,8 @@ void branches_menu::on_select(wxCommandEvent& e)
if(!branch_ids.count(id)) return; if(!branch_ids.count(id)) return;
uint64_t bid = branch_ids[id]; uint64_t bid = branch_ids[id];
std::string err; std::string err;
lsnes_instance.iqueue->run_async([this, bid]() { lsnes_instance.project->F_switch_branch(bid, [this](std::exception& e) {
auto p = CORE().project->get(); show_exception_any(this->pwin, "Error changing branch", "Can't change branch", e);
if(p) p->set_current_branch(bid);
if(p) p->flush();
update_movie_state();
}, [this](std::exception& e) {
show_exception(this->pwin, "Error changing branch", "Can't change branch", e);
}); });
} }
@ -421,11 +370,8 @@ void branches_menu::update()
{ {
std::map<uint64_t, std::string> namemap; std::map<uint64_t, std::string> namemap;
std::map<uint64_t, std::set<uint64_t>> childmap; std::map<uint64_t, std::set<uint64_t>> childmap;
lsnes_instance.iqueue->run([&namemap, &childmap]() { uint64_t cur;
auto p = CORE().project->get(); lsnes_instance.project->F_get_branch_map(cur, namemap, childmap);
if(!p) return;
fill_namemap(*p, 0, namemap, childmap);
});
//First destroy everything that isn't a menu. //First destroy everything that isn't a menu.
for(auto i : otheritems) for(auto i : otheritems)
i.parent->Delete(i.item); i.parent->Delete(i.item);

View file

@ -753,3 +753,13 @@ void show_exception(wxWindow* parent, const std::string& title, const std::strin
std::string _text = (text == "") ? err : (text + ": " + err); std::string _text = (text == "") ? err : (text + ": " + err);
show_message_ok(parent, _title, _text, wxICON_EXCLAMATION); show_message_ok(parent, _title, _text, wxICON_EXCLAMATION);
} }
void show_exception_any(wxWindow* parent, const std::string& title, const std::string& text, std::exception& e)
{
std::string err = e.what();
std::string _title = title;
std::string _text = (text == "") ? err : (text + ": " + err);
runuifun([parent, _title, _text]() {
show_message_ok(parent, _title, _text, wxICON_EXCLAMATION);
});
}