1 #include "core/command.hpp"
2 #include "core/dispatch.hpp"
3 #include "core/loadlib.hpp"
4 #include "core/messages.hpp"
5 #include "core/misc.hpp"
6 #include "interface/c-interface.hpp"
7 #include "interface/romtype.hpp"
8 #include "library/command.hpp"
9 #include "library/directory.hpp"
10 #include "library/filelist.hpp"
11 #include "library/loadlib.hpp"
12 #include "library/opus.hpp"
13 #include "library/running-executable.hpp"
21 std::map
<unsigned, loadlib::module
*> modules
;
22 unsigned next_mod
= 0;
24 std::string
get_name(std::string path
)
26 #if defined(_WIN32) || defined(_WIN64)
27 const char* sep
= "\\/";
29 const char* sep
= "/";
31 size_t p
= path
.find_last_of(sep
);
33 if(p
== std::string::npos
)
36 name
= path
.substr(p
+ 1);
40 std::string
get_user_library_dir()
42 return get_config_path() + "/autoload";
45 std::string
get_system_library_dir()
49 path
= running_executable();
53 #if __WIN32__ || __WIN64__
54 const char* sep
= "\\/";
56 const char* sep
= "/";
58 size_t p
= path
.find_last_of(sep
);
59 if(p
>= path
.length())
64 path
= path
.substr(0, p
);
65 #if !__WIN32__ && !__WIN64__
66 //If executable is in /bin, translate library path to corresponding /lib/lsnes.
67 regex_results r
= regex("(.*)/bin", path
);
68 if(r
) path
= r
[1] + "/lib/lsnes";
71 path
= path
+ "/plugins";
76 void handle_post_loadlibrary()
79 new_core_flag
= false;
80 core_core::initialize_new_cores();
85 void with_loaded_library(const loadlib::module
& l
)
88 if(!opus::libopus_loaded())
89 opus::load_libopus(l
);
91 //This wasn't libopus.
98 messages
<< "Loaded library '" << l
.get_libname() << "'" << std::endl
;
99 modules
[next_mod
++] = const_cast<loadlib::module
*>(&l
);
102 void with_unloaded_library(loadlib::module
& l
)
105 try_uninit_c_module(l
);
108 messages
<< "Unloading library '" << l
.get_libname() << "'" << std::endl
;
109 //Spot removed cores.
116 void load_libraries(std::set
<std::string
> libs
, bool system
,
117 void(*on_error
)(const std::string
& libname
, const std::string
& err
, bool system
))
119 std::set
<std::string
> blacklist
;
120 std::set
<std::string
> killlist
;
121 //System plugins can't be killlisted nor blacklisted.
123 filelist
_blacklist(get_user_library_dir() + "/blacklist", get_user_library_dir());
124 filelist
_killlist(get_user_library_dir() + "/killlist", get_user_library_dir());
125 killlist
= _killlist
.enumerate();
126 blacklist
= _blacklist
.enumerate();
127 //Try to kill the libs that don't exist anymore.
129 if(killlist
.count(get_name(i
)))
131 killlist
= _killlist
.enumerate();
132 //All killlisted plugins are automatically blacklisted.
133 for(auto i
: killlist
)
137 std::string extension
= loadlib::library::extension();
139 if(i
.length() < extension
.length() + 1)
141 if(i
[i
.length() - extension
.length() - 1] != '.')
144 if(tmp
.substr(i
.length() - extension
.length()) != extension
)
146 if(blacklist
.count(get_name(i
)))
149 with_loaded_library(*new loadlib::module(loadlib::library(i
)));
150 } catch(std::exception
& e
) {
151 std::string x
= "Can't load '" + i
+ "': " + e
.what();
154 on_error(get_name(i
), e
.what(), system
);
155 messages
<< x
<< std::endl
;
160 command::fnptr
<const std::string
&> CMD_unload_library(lsnes_cmds
, "unload-library", "", "",
161 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
162 unsigned libid
= parse_value
<unsigned>(args
);
163 if(!modules
.count(libid
))
164 throw std::runtime_error("No such library loaded");
165 with_unloaded_library(*modules
[libid
]);
166 modules
.erase(libid
);
169 command::fnptr
<> CMD_list_library(lsnes_cmds
, "list-libraries", "", "",
170 []() throw(std::bad_alloc
, std::runtime_error
) {
171 for(auto i
: modules
)
172 messages
<< "#" << i
.first
<< " [" << i
.second
->get_libname() << "]" << std::endl
;
176 void autoload_libraries(void(*on_error
)(const std::string
& libname
, const std::string
& err
, bool system
))
179 auto libs
= directory::enumerate(get_user_library_dir(), ".*");
180 load_libraries(libs
, false, on_error
);
181 } catch(std::exception
& e
) {
182 messages
<< e
.what() << std::endl
;
185 auto libs
= directory::enumerate(get_system_library_dir(), ".*");
186 load_libraries(libs
, true, on_error
);
187 } catch(std::exception
& e
) {
188 messages
<< e
.what() << std::endl
;
190 handle_post_loadlibrary();