1 #include "cmdhelp/loadlib.hpp"
2 #include "core/command.hpp"
3 #include "core/dispatch.hpp"
4 #include "core/instance.hpp"
5 #include "core/loadlib.hpp"
6 #include "core/messages.hpp"
7 #include "core/misc.hpp"
8 #include "core/rom.hpp"
9 #include "interface/c-interface.hpp"
10 #include "interface/romtype.hpp"
11 #include "library/command.hpp"
12 #include "library/directory.hpp"
13 #include "library/filelist.hpp"
14 #include "library/loadlib.hpp"
15 #include "library/opus.hpp"
16 #include "library/running-executable.hpp"
24 std::map
<unsigned, loadlib::module
*> modules
;
25 unsigned next_mod
= 0;
27 std::string
get_name(std::string path
)
29 #if defined(_WIN32) || defined(_WIN64)
30 const char* sep
= "\\/";
32 const char* sep
= "/";
34 size_t p
= path
.find_last_of(sep
);
36 if(p
== std::string::npos
)
39 name
= path
.substr(p
+ 1);
43 std::string
get_user_library_dir()
45 return get_config_path() + "/autoload";
48 std::string
get_system_library_dir()
52 path
= running_executable();
56 #if __WIN32__ || __WIN64__
57 const char* sep
= "\\/";
59 const char* sep
= "/";
61 size_t p
= path
.find_last_of(sep
);
62 if(p
>= path
.length())
67 path
= path
.substr(0, p
);
68 #if !__WIN32__ && !__WIN64__
69 //If executable is in /bin, translate library path to corresponding /lib/lsnes.
70 regex_results r
= regex("(.*)/bin", path
);
71 if(r
) path
= r
[1] + "/lib/lsnes";
74 path
= path
+ "/plugins";
79 void handle_post_loadlibrary()
82 new_core_flag
= false;
83 core_core::initialize_new_cores();
88 void with_loaded_library(const loadlib::module
& l
)
91 if(!opus::libopus_loaded())
92 opus::load_libopus(l
);
94 //This wasn't libopus.
99 module_loading
= NULL
;
101 module_loading
= NULL
;
104 messages
<< "Loaded library '" << l
.get_libname() << "'" << std::endl
;
105 modules
[next_mod
++] = const_cast<loadlib::module
*>(&l
);
108 bool with_unloaded_library(loadlib::module
& l
)
110 //Check that this module is not needed.
111 if(!CORE().rom
->get_internal_rom_type().safe_to_unload(l
)) {
112 messages
<< "Current core is from this module, can't unload" << std::endl
;
116 try_uninit_c_module(l
);
119 messages
<< "Unloading library '" << l
.get_libname() << "'" << std::endl
;
120 //Spot removed cores.
123 notify_new_core(); //In case only unload made it go away.
129 void load_libraries(std::set
<std::string
> libs
, bool system
,
130 void(*on_error
)(const std::string
& libname
, const std::string
& err
, bool system
))
132 std::set
<std::string
> blacklist
;
133 std::set
<std::string
> killlist
;
134 //System plugins can't be killlisted nor blacklisted.
136 filelist
_blacklist(get_user_library_dir() + "/blacklist", get_user_library_dir());
137 filelist
_killlist(get_user_library_dir() + "/killlist", get_user_library_dir());
138 killlist
= _killlist
.enumerate();
139 blacklist
= _blacklist
.enumerate();
140 //Try to kill the libs that don't exist anymore.
142 if(killlist
.count(get_name(i
)))
144 killlist
= _killlist
.enumerate();
145 //All killlisted plugins are automatically blacklisted.
146 for(auto i
: killlist
)
150 std::string extension
= loadlib::library::extension();
152 if(i
.length() < extension
.length() + 1)
154 if(i
[i
.length() - extension
.length() - 1] != '.')
157 if(tmp
.substr(i
.length() - extension
.length()) != extension
)
159 if(blacklist
.count(get_name(i
)))
162 with_loaded_library(*new loadlib::module(loadlib::library(i
)));
163 } catch(std::exception
& e
) {
164 std::string x
= "Can't load '" + i
+ "': " + e
.what();
167 on_error(get_name(i
), e
.what(), system
);
168 messages
<< x
<< std::endl
;
173 command::fnptr
<command::arg_filename
> CMD_load_library(lsnes_cmds
, CLOADLIB::load
,
174 [](command::arg_filename args
) {
175 with_loaded_library(*new loadlib::module(loadlib::library(args
)));
176 handle_post_loadlibrary();
179 command::fnptr
<const std::string
&> CMD_unload_library(lsnes_cmds
, CLOADLIB::unload
,
180 [](const std::string
& args
) {
181 unsigned libid
= parse_value
<unsigned>(args
);
182 if(!modules
.count(libid
))
183 throw std::runtime_error("No such library loaded");
184 if(with_unloaded_library(*modules
[libid
]))
185 modules
.erase(libid
);
188 command::fnptr
<> CMD_list_library(lsnes_cmds
, CLOADLIB::list
,
190 for(auto i
: modules
)
191 messages
<< "#" << i
.first
<< " [" << i
.second
->get_libname() << "]" << std::endl
;
195 void autoload_libraries(void(*on_error
)(const std::string
& libname
, const std::string
& err
, bool system
))
198 auto libs
= directory::enumerate(get_user_library_dir(), ".*");
199 load_libraries(libs
, false, on_error
);
200 } catch(std::exception
& e
) {
201 messages
<< e
.what() << std::endl
;
204 auto libs
= directory::enumerate(get_system_library_dir(), ".*");
205 load_libraries(libs
, true, on_error
);
206 } catch(std::exception
& e
) {
207 messages
<< e
.what() << std::endl
;
209 handle_post_loadlibrary();
212 std::string
loadlib_debug_get_user_library_dir() { return get_user_library_dir(); }
213 std::string
loadlib_debug_get_system_library_dir() { return get_system_library_dir(); }