1 #include "core/dispatch.hpp"
2 #include "library/globalwrap.hpp"
3 #include "core/keymapper.hpp"
4 #include "core/misc.hpp"
10 #define START_EH_BLOCK try {
11 #define END_EH_BLOCK(obj, call) } catch(std::bad_alloc& e) { \
13 } catch(std::exception& e) { \
14 messages << "[dumper " << obj->get_name() << "] Warning: " call ": " << e.what() \
17 messages << "[dumper " << obj->get_name() << "] Warning: " call ": Error code #" << code \
21 gameinfo_struct::gameinfo_struct() throw(std::bad_alloc
)
27 std::string
gameinfo_struct::get_readable_time(unsigned digits
) const throw(std::bad_alloc
)
29 double bias
= 0.5 * pow(10, -static_cast<int>(digits
));
30 double len
= length
+ bias
;
31 std::ostringstream str
;
33 double hours
= floor(len
/ 3600);
37 double minutes
= floor(len
/ 60);
39 double seconds
= floor(len
);
41 str
<< std::setw(2) << std::setfill('0') << minutes
<< ":" << seconds
;
46 str
<< '0' + static_cast<int>(len
);
53 size_t gameinfo_struct::get_author_count() const throw()
55 return authors
.size();
58 std::string
gameinfo_struct::get_author_short(size_t idx
) const throw(std::bad_alloc
)
60 if(idx
>= authors
.size())
62 const std::pair
<std::string
, std::string
>& x
= authors
[idx
];
69 uint64_t gameinfo_struct::get_rerecords() const throw()
72 uint64_t max
= 0xFFFFFFFFFFFFFFFFULL
;
73 for(size_t i
= 0; i
< rerecords
.length(); i
++) {
75 //No risk of overflow.
76 v
= v
* 10 + static_cast<unsigned>(rerecords
[i
] - '0');
77 else if(v
== max
/ 10) {
80 if(v
+ static_cast<unsigned>(rerecords
[i
] - '0') < v
)
82 v
= v
+ static_cast<unsigned>(rerecords
[i
] - '0');
92 globalwrap
<std::list
<information_dispatch
*>> _dispatch
;
93 globalwrap
<std::list
<information_dispatch
*>> dispatch_audio
;
94 uint32_t srate_n
= 32000;
96 struct gameinfo_struct sgi
;
97 bool recursive
= false;
100 information_dispatch::information_dispatch(const std::string
& name
) throw(std::bad_alloc
)
103 _dispatch().push_back(this);
104 known_if_dumper
= false;
105 marked_as_dumper
= false;
106 notified_as_dumper
= false;
109 information_dispatch::~information_dispatch() throw()
111 for(auto i
= _dispatch().begin(); i
!= _dispatch().end(); ++i
) {
113 _dispatch().erase(i
);
117 for(auto i
= dispatch_audio().begin(); i
!= dispatch_audio().end(); ++i
) {
119 dispatch_audio().erase(i
);
123 if(notified_as_dumper
)
124 for(auto& i
: _dispatch()) {
126 i
->on_destroy_dumper(target_name
);
127 END_EH_BLOCK(i
, "on_destroy_dumper");
131 void information_dispatch::on_frame(struct framebuffer::raw
& _frame
, uint32_t fps_n
, uint32_t fps_d
)
136 void information_dispatch::do_frame(struct framebuffer::raw
& _frame
, uint32_t fps_n
, uint32_t fps_d
) throw()
139 for(auto& i
: _dispatch()) {
141 i
->on_frame(_frame
, fps_n
, fps_d
);
142 END_EH_BLOCK(i
, "on_frame");
146 void information_dispatch::on_sample(short l
, short r
)
151 void information_dispatch::do_sample(short l
, short r
) throw()
154 for(auto& i
: dispatch_audio()) {
157 END_EH_BLOCK(i
, "on_sample");
161 void information_dispatch::on_dump_end()
166 void information_dispatch::do_dump_end() throw()
169 for(auto& i
: _dispatch()) {
172 END_EH_BLOCK(i
, "on_dump_end");
176 void information_dispatch::on_sound_rate(uint32_t rate_n
, uint32_t rate_d
)
178 if(!known_if_dumper
) {
179 marked_as_dumper
= get_dumper_flag();
180 known_if_dumper
= true;
182 if(marked_as_dumper
) {
183 messages
<< "[dumper " << get_name() << "] Warning: Sound sample rate changing not supported!"
188 void information_dispatch::do_sound_rate(uint32_t rate_n
, uint32_t rate_d
) throw()
191 uint32_t g
= gcd(rate_n
, rate_d
);
194 if(rate_n
== srate_n
&& rate_d
== srate_d
)
198 for(auto& i
: _dispatch()) {
200 i
->on_sound_rate(rate_n
, rate_d
);
201 END_EH_BLOCK(i
, "on_sound_rate");
205 std::pair
<uint32_t, uint32_t> information_dispatch::get_sound_rate() throw()
207 return std::make_pair(srate_n
, srate_d
);
210 void information_dispatch::on_gameinfo(const struct gameinfo_struct
& gi
)
215 void information_dispatch::do_gameinfo(const struct gameinfo_struct
& gi
) throw()
223 for(auto& i
: _dispatch()) {
226 END_EH_BLOCK(i
, "on_gameinfo");
230 const struct gameinfo_struct
& information_dispatch::get_gameinfo() throw()
235 bool information_dispatch::get_dumper_flag() throw()
240 void information_dispatch::on_new_dumper(const std::string
& dumper
)
245 void information_dispatch::on_destroy_dumper(const std::string
& dumper
)
250 unsigned information_dispatch::get_dumper_count() throw()
252 update_dumpers(true);
254 for(auto& i
: _dispatch())
255 if(i
->marked_as_dumper
)
265 std::set
<std::string
> information_dispatch::get_dumpers() throw(std::bad_alloc
)
268 std::set
<std::string
> r
;
270 for(auto& i
: _dispatch())
271 if(i
->notified_as_dumper
)
272 r
.insert(i
->get_name());
280 const std::string
& information_dispatch::get_name() throw()
285 void information_dispatch::update_dumpers(bool nocalls
) throw()
287 for(auto& i
: _dispatch()) {
288 if(!i
->known_if_dumper
) {
289 i
->marked_as_dumper
= i
->get_dumper_flag();
290 i
->known_if_dumper
= true;
292 if(i
->marked_as_dumper
&& !i
->notified_as_dumper
&& !nocalls
) {
293 for(auto& j
: _dispatch()) {
295 j
->on_new_dumper(i
->target_name
);
296 END_EH_BLOCK(j
, "on_new_dumper");
298 i
->notified_as_dumper
= true;
303 void information_dispatch::enable_send_sound() throw(std::bad_alloc
)
305 dispatch_audio().push_back(this);
308 void information_dispatch::on_dumper_update()
313 void information_dispatch::do_dumper_update() throw()
315 if(in_global_ctors())
317 for(auto& i
: _dispatch()) {
319 i
->on_dumper_update();
320 END_EH_BLOCK(i
, "on_dumper_update");
324 void dispatch_set_error_streams(std::ostream
* stream
)
326 notify_autofire_update
.errors_to(stream
);
327 notify_autohold_reconfigure
.errors_to(stream
);
328 notify_autohold_update
.errors_to(stream
);
329 notify_close
.errors_to(stream
);
330 notify_core_change
.errors_to(stream
);
331 notify_mode_change
.errors_to(stream
);
332 notify_new_core
.errors_to(stream
);
333 notify_screen_update
.errors_to(stream
);
334 notify_set_screen
.errors_to(stream
);
335 notify_sound_change
.errors_to(stream
);
336 notify_sound_unmute
.errors_to(stream
);
337 notify_status_update
.errors_to(stream
);
338 notify_subtitle_change
.errors_to(stream
);
339 notify_voice_stream_change
.errors_to(stream
);
340 notify_vu_change
.errors_to(stream
);
341 notify_core_changed
.errors_to(stream
);
342 notify_multitrack_change
.errors_to(stream
);
343 notify_title_change
.errors_to(stream
);
344 notify_branch_change
.errors_to(stream
);
345 notify_mbranch_change
.errors_to(stream
);
348 struct dispatch::source
<> notify_autohold_reconfigure("autohold_reconfigure");
349 struct dispatch::source
<unsigned, unsigned, unsigned, bool> notify_autohold_update("autohold_update");
350 struct dispatch::source
<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update("autofire_update");
351 struct dispatch::source
<> notify_close("notify_close");
352 struct dispatch::source
<framebuffer::fb
<false>&> notify_set_screen("set_screen");
353 struct dispatch::source
<std::pair
<std::string
, std::string
>> notify_sound_change("sound_change");
354 struct dispatch::source
<> notify_screen_update("screen_update");
355 struct dispatch::source
<> notify_status_update("status_update");
356 struct dispatch::source
<bool> notify_sound_unmute("sound_unmute");
357 struct dispatch::source
<bool> notify_mode_change("mode_change");
358 struct dispatch::source
<> notify_core_change("core_change");
359 struct dispatch::source
<bool> notify_core_changed("core_changed");
360 struct dispatch::source
<> notify_new_core("new_core");
361 struct dispatch::source
<> notify_voice_stream_change("voice_stream_change");
362 struct dispatch::source
<> notify_vu_change("vu_change");
363 struct dispatch::source
<> notify_subtitle_change("subtitle_change");
364 struct dispatch::source
<unsigned, unsigned, int> notify_multitrack_change("multitrack_change");
365 struct dispatch::source
<> notify_title_change("title_change");
366 struct dispatch::source
<> notify_branch_change("branch_change");
367 struct dispatch::source
<> notify_mbranch_change("mbranch_change");