1 #include "core/advdumper.hpp"
2 #include "core/command.hpp"
3 #include "core/dispatch.hpp"
4 #include "core/lua.hpp"
5 #include "core/misc.hpp"
6 #include "core/settings.hpp"
17 class raw_avsnoop
: public information_dispatch
20 raw_avsnoop(const std::string
& prefix
) throw(std::bad_alloc
)
21 : information_dispatch("dump-raw")
24 video
= new std::ofstream(prefix
+ ".video", std::ios::out
| std::ios::binary
);
25 audio
= new std::ofstream(prefix
+ ".audio", std::ios::out
| std::ios::binary
);
26 if(!*video
|| !*audio
)
27 throw std::runtime_error("Can't open output files");
28 have_dumped_frame
= false;
31 ~raw_avsnoop() throw()
37 void on_frame(struct lcscreen
& _frame
, uint32_t fps_n
, uint32_t fps_d
)
41 struct lua_render_context lrc
;
48 lrc
.width
= _frame
.width
;
49 lrc
.height
= _frame
.height
;
50 lua_callback_do_video(&lrc
);
51 dscr
.set_palette(16, 8, 0);
52 uint32_t hscl
= (_frame
.width
< 400) ? 2 : 1;
53 uint32_t vscl
= (_frame
.height
< 400) ? 2 : 1;
54 dscr
.reallocate(lrc
.left_gap
+ _frame
.width
* hscl
+ lrc
.right_gap
, lrc
.top_gap
+
55 _frame
.height
* vscl
+ lrc
.bottom_gap
, false);
56 dscr
.set_origin(lrc
.left_gap
, lrc
.top_gap
);
57 dscr
.copy_from(_frame
, hscl
, vscl
);
59 for(size_t i
= 0; i
< dscr
.height
; i
++)
60 video
->write(reinterpret_cast<char*>(dscr
.rowptr(i
)), 4 * dscr
.width
);
61 have_dumped_frame
= true;
64 void on_sample(short l
, short r
)
66 if(have_dumped_frame
&& audio
) {
68 buffer
[0] = static_cast<unsigned short>(l
);
69 buffer
[1] = static_cast<unsigned short>(l
) >> 8;
70 buffer
[2] = static_cast<unsigned short>(r
);
71 buffer
[3] = static_cast<unsigned short>(r
) >> 8;
72 audio
->write(buffer
, 4);
84 bool get_dumper_flag() throw()
91 bool have_dumped_frame
;
95 raw_avsnoop
* vid_dumper
;
97 void startdump(std::string prefix
)
100 throw std::runtime_error("Expected prefix");
102 throw std::runtime_error("RAW dumping already in progress");
104 vid_dumper
= new raw_avsnoop(prefix
);
105 } catch(std::bad_alloc
& e
) {
107 } catch(std::exception
& e
) {
108 std::ostringstream x
;
109 x
<< "Error starting RAW dump: " << e
.what();
110 throw std::runtime_error(x
.str());
112 messages
<< "Dumping to " << prefix
<< std::endl
;
113 information_dispatch::do_dumper_update();
119 throw std::runtime_error("No RAW video dump in progress");
121 vid_dumper
->on_dump_end();
122 messages
<< "RAW Dump finished" << std::endl
;
123 } catch(std::bad_alloc
& e
) {
125 } catch(std::exception
& e
) {
126 messages
<< "Error ending RAW dump: " << e
.what() << std::endl
;
130 information_dispatch::do_dumper_update();
133 function_ptr_command
<const std::string
&> raw_dump("dump-raw", "Start RAW capture",
134 "Syntax: dump-raw <prefix>\nStart RAW capture to <prefix>.video and <prefix>.audio.\n",
135 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
136 tokensplitter
t(args
);
137 std::string prefix
= t
.tail();
141 function_ptr_command
<> end_raw("end-raw", "End RAW capture",
142 "Syntax: end-raw\nEnd a RAW capture.\n",
143 []() throw(std::bad_alloc
, std::runtime_error
) {
147 class adv_raw_dumper
: public adv_dumper
150 adv_raw_dumper() : adv_dumper("INTERNAL-RAW") {information_dispatch::do_dumper_update(); }
151 ~adv_raw_dumper() throw();
152 std::set
<std::string
> list_submodes() throw(std::bad_alloc
)
154 std::set
<std::string
> x
;
158 bool wants_prefix(const std::string
& mode
) throw()
163 std::string
name() throw(std::bad_alloc
)
168 std::string
modename(const std::string
& mode
) throw(std::bad_alloc
)
175 return (vid_dumper
!= NULL
);
178 void start(const std::string
& mode
, const std::string
& targetname
) throw(std::bad_alloc
,
181 startdump(targetname
);
190 adv_raw_dumper::~adv_raw_dumper() throw()