1 #include "core/command.hpp"
2 #include "core/dispatch.hpp"
3 #include "core/misc.hpp"
4 #include "core/render.hpp"
5 #include "core/window.hpp"
8 #include <boost/iostreams/categories.hpp>
9 #include <boost/iostreams/copy.hpp>
10 #include <boost/iostreams/stream.hpp>
11 #include <boost/iostreams/stream_buffer.hpp>
12 #include <boost/iostreams/filter/symmetric.hpp>
13 #include <boost/iostreams/filter/zlib.hpp>
14 #include <boost/iostreams/filtering_stream.hpp>
15 #include <boost/iostreams/device/back_inserter.hpp>
17 #define MAXMESSAGES 5000
18 #define INIT_WIN_SIZE 6
23 function_ptr_command
<> identify_key("show-plugins", "Show plugins in use",
24 "Syntax: show-plugins\nShows plugins in use.\n",
25 []() throw(std::bad_alloc
, std::runtime_error
) {
26 window::message(std::string("Graphics:\t") + graphics_plugin_name
);
27 window::message(std::string("Sound:\t") + sound_plugin_name
);
28 window::message(std::string("Joystick:\t") + joystick_plugin_name
);
31 function_ptr_command
<const std::string
&> enable_sound("enable-sound", "Enable/Disable sound",
32 "Syntax: enable-sound <on/off>\nEnable or disable sound.\n",
33 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
35 if(s
== "on" || s
== "true" || s
== "1" || s
== "enable" || s
== "enabled") {
36 if(!window::sound_initialized())
37 throw std::runtime_error("Sound failed to initialize and is disabled");
38 window::sound_enable(true);
39 } else if(s
== "off" || s
== "false" || s
== "0" || s
== "disable" || s
== "disabled") {
40 if(window::sound_initialized())
41 window::sound_enable(false);
43 throw std::runtime_error("Bad sound setting");
46 function_ptr_command
<const std::string
&> set_sound_device("set-sound-device", "Set sound device",
47 "Syntax: set-sound-device <id>\nSet sound device to <id>.\n",
48 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
49 if(!window::sound_initialized())
50 throw std::runtime_error("Sound failed to initialize and is disabled");
51 window::set_sound_device(args
);
54 function_ptr_command
<> get_sound_devices("show-sound-devices", "Show sound devices",
55 "Syntax: show-sound-devices\nShow listing of available sound devices\n",
56 []() throw(std::bad_alloc
, std::runtime_error
) {
57 if(!window::sound_initialized())
58 throw std::runtime_error("Sound failed to initialize and is disabled");
59 auto r
= window::get_sound_devices();
60 auto s
= window::get_current_sound_device();
61 std::string dname
= "unknown";
64 window::out() << "Detected " << r
.size() << " sound output devices."
67 window::out() << "Audio device " << i
.first
<< ": " << i
.second
<< std::endl
;
68 window::out() << "Currently using device " << window::get_current_sound_device() << " ("
69 << dname
<< ")" << std::endl
;
72 function_ptr_command
<> get_sound_status("show-sound-status", "Show sound status",
73 "Syntax: show-sound-status\nShow current sound status\n",
74 []() throw(std::bad_alloc
, std::runtime_error
) {
75 window::out() << "Sound plugin: " << sound_plugin_name
<< std::endl
;
76 if(!window::sound_initialized())
77 window::out() << "Sound initialization failed, sound disabled" << std::endl
;
79 auto r
= window::get_sound_devices();
80 auto s
= window::get_current_sound_device();
81 std::string dname
= "unknown";
84 window::out() << "Current sound device " << s
<< " (" << dname
<< ")" << std::endl
;
88 std::map
<std::string
, std::string
> emustatus
;
93 typedef char char_type
;
94 typedef boost::iostreams::sink_tag category
;
95 window_output(window
* win
)
103 std::streamsize
write(const char* s
, std::streamsize n
)
105 size_t oldsize
= stream
.size();
106 stream
.resize(oldsize
+ n
);
107 memcpy(&stream
[oldsize
], s
, n
);
109 size_t lf
= stream
.size();
110 for(size_t i
= 0; i
< stream
.size(); i
++)
111 if(stream
[i
] == '\n') {
115 if(lf
== stream
.size())
117 std::string
foo(stream
.begin(), stream
.begin() + lf
);
118 window::message(foo
);
119 if(lf
+ 1 < stream
.size())
120 memmove(&stream
[0], &stream
[lf
+ 1], stream
.size() - lf
- 1);
121 stream
.resize(stream
.size() - lf
- 1);
126 std::vector
<char> stream
;
129 class msgcallback
: public messagebuffer::update_handler
132 ~msgcallback() throw() {};
133 void messagebuffer_update() throw(std::bad_alloc
, std::runtime_error
)
135 window::notify_message();
139 std::ofstream system_log
;
140 bool sounds_enabled
= true;
143 std::map
<std::string
, std::string
>& window::get_emustatus() throw()
148 void window::sound_enable(bool enable
) throw()
150 _sound_enable(enable
);
151 sounds_enabled
= enable
;
152 information_dispatch::do_sound_unmute(enable
);
155 void window::set_sound_device(const std::string
& dev
) throw()
158 _set_sound_device(dev
);
159 } catch(std::exception
& e
) {
160 out() << "Error changing sound device: " << e
.what() << std::endl
;
162 //After failed change, we don't know what is selected.
163 information_dispatch::do_sound_change(get_current_sound_device());
166 bool window::is_sound_enabled() throw()
168 return sounds_enabled
;
174 msgbuf
.register_handler(msg_callback_obj
);
175 system_log
.open("lsnes.log", std::ios_base::out
| std::ios_base::app
);
176 time_t curtime
= __real_time(NULL
);
177 struct tm
* tm
= localtime(&curtime
);
179 strftime(buffer
, 1023, "%Y-%m-%d %H:%M:%S %Z", tm
);
180 system_log
<< "-----------------------------------------------------------------------" << std::endl
;
181 system_log
<< "lsnes started at " << buffer
<< std::endl
;
182 system_log
<< "-----------------------------------------------------------------------" << std::endl
;
194 msgbuf
.unregister_handler(msg_callback_obj
);
195 time_t curtime
= __real_time(NULL
);
196 struct tm
* tm
= localtime(&curtime
);
198 strftime(buffer
, 1023, "%Y-%m-%d %H:%M:%S %Z", tm
);
199 system_log
<< "-----------------------------------------------------------------------" << std::endl
;
200 system_log
<< "lsnes shutting down at " << buffer
<< std::endl
;
201 system_log
<< "-----------------------------------------------------------------------" << std::endl
;
205 std::ostream
& window::out() throw(std::bad_alloc
)
207 static std::ostream
* cached
= NULL
;
210 cached
= new boost::iostreams::stream
<window_output
>(win
);
214 messagebuffer
window::msgbuf(MAXMESSAGES
, INIT_WIN_SIZE
);
217 void window::message(const std::string
& msg
) throw(std::bad_alloc
)
219 std::string msg2
= msg
;
221 size_t s
= msg2
.find_first_of("\n");
223 if(s
>= msg2
.length()) {
224 msgbuf
.add_message(forlog
= msg2
);
226 system_log
<< forlog
<< std::endl
;
229 msgbuf
.add_message(forlog
= msg2
.substr(0, s
));
231 system_log
<< forlog
<< std::endl
;
232 msg2
= msg2
.substr(s
+ 1);
237 void window::fatal_error() throw()
239 time_t curtime
= __real_time(NULL
);
240 struct tm
* tm
= localtime(&curtime
);
242 strftime(buffer
, 1023, "%Y-%m-%d %H:%M:%S %Z", tm
);
243 system_log
<< "-----------------------------------------------------------------------" << std::endl
;
244 system_log
<< "lsnes paniced at " << buffer
<< std::endl
;
245 system_log
<< "-----------------------------------------------------------------------" << std::endl
;