1 #include "lua/internal.hpp"
2 #include "library/string.hpp"
3 #include "library/minmax.hpp"
4 #include "core/dispatch.hpp"
5 #include "core/instance.hpp"
6 #include "core/moviedata.hpp"
7 #include "core/messages.hpp"
8 #include "core/window.hpp"
18 friend class lua_inputmovie
;
20 lua_inputframe(lua::state
& L
, portctrl::frame _f
);
21 static size_t overcommit(portctrl::frame _f
) { return 0; }
22 int get_button(lua::state
& L
, lua::parameters
& P
)
24 unsigned port
, controller
, button
;
26 P(P
.skipped(), port
, controller
, button
);
28 short value
= getbutton(port
, controller
, button
);
29 L
.pushboolean(value
? 1 : 0);
32 int get_axis(lua::state
& L
, lua::parameters
& P
)
34 unsigned port
, controller
, button
;
36 P(P
.skipped(), port
, controller
, button
);
38 short value
= getbutton(port
, controller
, button
);
42 int set_axis(lua::state
& L
, lua::parameters
& P
)
44 unsigned port
, controller
, button
;
47 P(P
.skipped(), port
, controller
, button
);
48 if(P
.is_boolean()) value
= P
.arg
<bool>() ? 1 : 0;
49 else if(P
.is_number()) value
= P
.arg
<short>();
51 P
.expected("number or boolean");
53 setbutton(port
, controller
, button
, value
);
56 int serialize(lua::state
& L
, lua::parameters
& P
)
58 char buf
[MAX_SERIALIZED_SIZE
];
63 int unserialize(lua::state
& L
, lua::parameters
& P
)
69 f
.deserialize(buf
.c_str());
72 int get_stride(lua::state
& L
, lua::parameters
& P
)
74 L
.pushnumber(f
.size());
77 portctrl::frame
& get_frame()
83 char buf
[MAX_SERIALIZED_SIZE
];
88 short getbutton(unsigned port
, unsigned controller
, unsigned index
)
90 return f
.axis3(port
, controller
, index
);
92 void setbutton(unsigned port
, unsigned controller
, unsigned index
, short value
)
94 return f
.axis3(port
, controller
, index
, value
);
99 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
= false);
100 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
)
102 movie
& m
= CORE().mlogic
->get_movie();
103 if(port
== 0 && controller
== 0 && button
== 0)
104 return m
.get_pollcounters().max_polls() + (extra0
? 1 : 0);
105 if(port
== 0 && controller
== 0 && m
.get_pollcounters().get_framepflag())
106 return max(m
.get_pollcounters().get_polls(port
, controller
, button
), (uint32_t)1);
107 return m
.get_pollcounters().get_polls(port
, controller
, button
);
110 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
111 bool allow_past_end
= false);
113 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
117 movie
& m
= core
.mlogic
->get_movie();
118 if(!m
.readonly_mode())
119 throw std::runtime_error("Not in playback mode");
120 if(!allow_past_end
&& frame
>= core
.mlogic
->get_mfile().input
->size())
121 throw std::runtime_error("Index out of movie");
122 int32_t pc
= get_pc_for(port
, controller
, button
, true);
124 throw std::runtime_error("Invalid control to edit");
125 uint64_t firstframe
= m
.get_current_frame_first_subframe();
126 uint64_t minframe
= firstframe
+ pc
;
127 uint64_t msize
= core
.mlogic
->get_mfile().input
->size();
128 if(minframe
> msize
|| firstframe
>= msize
)
129 throw std::runtime_error("Can not edit finished movie");
131 throw std::runtime_error("Can not edit past");
134 int current_first_subframe(lua::state
& L
, lua::parameters
& P
)
136 movie
& m
= CORE().mlogic
->get_movie();
137 L
.pushnumber(m
.get_current_frame_first_subframe());
141 int pollcounter(lua::state
& L
, lua::parameters
& P
)
143 unsigned port
, controller
, button
;
145 P(port
, controller
, button
);
148 ret
= get_pc_for(port
, controller
, button
);
153 portctrl::frame_vector
& framevector(lua::state
& L
, lua::parameters
& P
);
155 int _copy_movie(lua::state
& L
, lua::parameters
& P
)
157 portctrl::frame_vector
& v
= framevector(L
, P
);
159 lua::_class
<lua_inputmovie
>::create(L
, v
);
163 int _get_frame(lua::state
& L
, lua::parameters
& P
)
166 portctrl::frame_vector
& v
= framevector(L
, P
);
171 throw std::runtime_error("Requested frame outside movie");
172 portctrl::frame _f
= v
[n
];
173 lua::_class
<lua_inputframe
>::create(L
, _f
);
177 int _set_frame(lua::state
& L
, lua::parameters
& P
)
182 portctrl::frame_vector
& v
= framevector(L
, P
);
187 throw std::runtime_error("Requested frame outside movie");
188 //Checks if requested frame is from movie.
189 if(&v
== core
.mlogic
->get_mfile().input
)
190 check_can_edit(0, 0, 0, n
);
192 v
[n
] = f
->get_frame();
194 if(&v
== core
.mlogic
->get_mfile().input
) {
195 //This can't add frames, so no need to adjust the movie.
196 core
.supdater
->update();
197 core
.dispatch
->status_update();
202 int _get_size(lua::state
& L
, lua::parameters
& P
)
204 portctrl::frame_vector
& v
= framevector(L
, P
);
206 L
.pushnumber(v
.size());
210 int _count_frames(lua::state
& L
, lua::parameters
& P
)
212 portctrl::frame_vector
& v
= framevector(L
, P
);
214 L
.pushnumber(v
.count_frames());
218 int _find_frame(lua::state
& L
, lua::parameters
& P
)
221 portctrl::frame_vector
& v
= framevector(L
, P
);
225 L
.pushnumber(v
.find_frame(n
));
229 int _subframe_to_frame(lua::state
& L
, lua::parameters
& P
)
232 portctrl::frame_vector
& v
= framevector(L
, P
);
236 L
.pushnumber(v
.subframe_to_frame(n
));
240 int _blank_frame(lua::state
& L
, lua::parameters
& P
)
242 portctrl::frame_vector
& v
= framevector(L
, P
);
244 portctrl::frame _f
= v
.blank_frame(true);
245 lua::_class
<lua_inputframe
>::create(L
, _f
);
249 int _append_frames(lua::state
& L
, lua::parameters
& P
)
253 portctrl::frame_vector
& v
= framevector(L
, P
);
258 portctrl::frame_vector::notify_freeze
freeze(v
);
259 for(uint64_t i
= 0; i
< count
; i
++)
260 v
.append(v
.blank_frame(true));
262 if(&v
== core
.mlogic
->get_mfile().input
) {
263 core
.supdater
->update();
264 core
.dispatch
->status_update();
269 int _append_frame(lua::state
& L
, lua::parameters
& P
)
273 portctrl::frame_vector
& v
= framevector(L
, P
);
277 v
.append(v
.blank_frame(true));
278 if(&v
== core
.mlogic
->get_mfile().input
) {
279 core
.supdater
->update();
280 core
.dispatch
->status_update();
281 check_can_edit(0, 0, 0, v
.size() - 1);
283 v
[v
.size() - 1] = f
->get_frame();
284 if(&v
== core
.mlogic
->get_mfile().input
) {
285 if(!v
[v
.size() - 1].sync()) {
286 core
.supdater
->update();
288 core
.dispatch
->status_update();
293 int _truncate(lua::state
& L
, lua::parameters
& P
)
297 portctrl::frame_vector
& v
= framevector(L
, P
);
302 throw std::runtime_error("Requested truncate length longer than existing");
303 if(&v
== core
.mlogic
->get_mfile().input
)
304 check_can_edit(0, 0, 0, n
);
306 if(&v
== core
.mlogic
->get_mfile().input
) {
307 core
.supdater
->update();
308 core
.dispatch
->status_update();
313 int _edit(lua::state
& L
, lua::parameters
& P
)
317 unsigned port
, controller
, button
;
319 portctrl::frame_vector
& v
= framevector(L
, P
);
321 P(frame
, port
, controller
, button
);
322 if(P
.is_boolean()) value
= P
.arg
<bool>() ? 1 : 0;
323 else if(P
.is_number()) P(value
);
325 P
.expected("number or boolean");
327 if(&v
== core
.mlogic
->get_mfile().input
)
328 check_can_edit(port
, controller
, button
, frame
);
329 v
[frame
].axis3(port
, controller
, button
, value
);
331 if(&v
== core
.mlogic
->get_mfile().input
) {
332 core
.supdater
->update();
333 core
.dispatch
->status_update();
339 int _copy_frames(lua::state
& L
, lua::parameters
& P
)
342 uint64_t dst
, src
, count
;
343 bool backwards
= same
;
345 portctrl::frame_vector
& dstv
= framevector(L
, P
);
347 portctrl::frame_vector
& srcv
= same
? dstv
: framevector(L
, P
);
349 if(same
) P(backwards
);
351 if(src
>= srcv
.size() || src
+ count
< src
)
352 throw std::runtime_error("Source index out of movie");
353 if(dst
> dstv
.size() || dst
+ count
< dst
)
354 throw std::runtime_error("Destination index out of movie");
356 if(&dstv
== core
.mlogic
->get_mfile().input
)
357 check_can_edit(0, 0, 0, dst
, true);
360 portctrl::frame_vector::notify_freeze
freeze(dstv
);
361 //Add enough blank frames to make the copy.
362 while(dst
+ count
> dstv
.size())
363 dstv
.append(dstv
.blank_frame(false));
365 for(uint64_t i
= backwards
? (count
- 1) : 0; i
< count
; i
= backwards
? (i
- 1) : (i
+ 1))
366 dstv
[dst
+ i
] = srcv
[src
+ i
];
368 if(&dstv
== core
.mlogic
->get_mfile().input
) {
369 core
.supdater
->update();
370 core
.dispatch
->status_update();
375 int _serialize(lua::state
& L
, lua::parameters
& P
)
377 std::string filename
;
380 portctrl::frame_vector
& v
= framevector(L
, P
);
384 std::ofstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::out
);
386 throw std::runtime_error("Can't open file to write output to");
388 uint64_t stride
= v
.get_stride();
389 uint64_t pageframes
= v
.get_frames_per_page();
390 uint64_t vsize
= v
.size();
393 uint64_t count
= (vsize
> pageframes
) ? pageframes
: vsize
;
394 size_t bytes
= count
* stride
;
395 unsigned char* content
= v
.get_page_buffer(pagenum
++);
396 file
.write(reinterpret_cast<char*>(content
), bytes
);
400 char buf
[MAX_SERIALIZED_SIZE
];
401 for(uint64_t i
= 0; i
< v
.size(); i
++) {
403 file
<< buf
<< std::endl
;
412 lua_inputmovie(lua::state
& L
, const portctrl::frame_vector
& _v
);
413 lua_inputmovie(lua::state
& L
, portctrl::frame
& _f
);
414 static size_t overcommit(const portctrl::frame_vector
& _v
) { return 0; }
415 static size_t overcommit(portctrl::frame
& _f
) { return 0; }
416 int copy_movie(lua::state
& L
, lua::parameters
& P
)
418 return _copy_movie(L
, P
);
420 int get_frame(lua::state
& L
, lua::parameters
& P
)
422 return _get_frame(L
, P
);
424 int set_frame(lua::state
& L
, lua::parameters
& P
)
426 return _set_frame(L
, P
);
428 int get_size(lua::state
& L
, lua::parameters
& P
)
430 return _get_size(L
, P
);
432 int count_frames(lua::state
& L
, lua::parameters
& P
)
434 return _count_frames(L
, P
);
436 int find_frame(lua::state
& L
, lua::parameters
& P
)
438 return _find_frame(L
, P
);
440 int subframe_to_frame(lua::state
& L
, lua::parameters
& P
)
442 return _subframe_to_frame(L
, P
);
444 int blank_frame(lua::state
& L
, lua::parameters
& P
)
446 return _blank_frame(L
, P
);
448 int append_frames(lua::state
& L
, lua::parameters
& P
)
450 return _append_frames(L
, P
);
452 int append_frame(lua::state
& L
, lua::parameters
& P
)
454 return _append_frame(L
, P
);
456 int truncate(lua::state
& L
, lua::parameters
& P
)
458 return _truncate(L
, P
);
460 int edit(lua::state
& L
, lua::parameters
& P
)
464 int copy_frames(lua::state
& L
, lua::parameters
& P
)
466 return _copy_frames
<true>(L
, P
);
468 int serialize(lua::state
& L
, lua::parameters
& P
)
470 return _serialize(L
, P
);
472 int debugdump(lua::state
& L
, lua::parameters
& P
)
474 char buf
[MAX_SERIALIZED_SIZE
];
475 for(uint64_t i
= 0; i
< v
.size(); i
++) {
477 messages
<< buf
<< std::endl
;
481 portctrl::frame_vector
* get_frame_vector()
488 return (stringfmt() << s
<< " " << ((s
!= 1) ? "frames" : "frame")).str();
491 void common_init(lua::state
& L
);
492 portctrl::frame_vector v
;
495 int copy_movie(lua::state
& L
, lua::parameters
& P
)
497 return _copy_movie(L
, P
);
500 int get_frame(lua::state
& L
, lua::parameters
& P
)
502 return _get_frame(L
, P
);
505 int set_frame(lua::state
& L
, lua::parameters
& P
)
507 return _set_frame(L
, P
);
510 int get_size(lua::state
& L
, lua::parameters
& P
)
512 return _get_size(L
, P
);
515 int count_frames(lua::state
& L
, lua::parameters
& P
)
517 return _count_frames(L
, P
);
520 int find_frame(lua::state
& L
, lua::parameters
& P
)
522 return _find_frame(L
, P
);
525 int subframe_to_frame(lua::state
& L
, lua::parameters
& P
)
527 return _subframe_to_frame(L
, P
);
530 int blank_frame(lua::state
& L
, lua::parameters
& P
)
532 return _blank_frame(L
, P
);
535 int append_frames(lua::state
& L
, lua::parameters
& P
)
537 return _append_frames(L
, P
);
540 int append_frame(lua::state
& L
, lua::parameters
& P
)
542 return _append_frame(L
, P
);
545 int truncate(lua::state
& L
, lua::parameters
& P
)
547 return _truncate(L
, P
);
550 int edit(lua::state
& L
, lua::parameters
& P
)
555 int copy_frames2(lua::state
& L
, lua::parameters
& P
)
557 return _copy_frames
<false>(L
, P
);
560 int copy_frames(lua::state
& L
, lua::parameters
& P
)
562 return _copy_frames
<true>(L
, P
);
565 int serialize(lua::state
& L
, lua::parameters
& P
)
567 return _serialize(L
, P
);
570 int unserialize(lua::state
& L
, lua::parameters
& P
)
573 std::string filename
;
576 P(f
, filename
, binary
);
578 std::ifstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::in
);
580 throw std::runtime_error("Can't open file to read input from");
581 lua_inputmovie
* m
= lua::_class
<lua_inputmovie
>::create(L
, f
->get_frame());
582 portctrl::frame_vector
& v
= *m
->get_frame_vector();
583 portctrl::frame_vector::notify_freeze
freeze(v
);
585 uint64_t stride
= v
.get_stride();
586 uint64_t pageframes
= v
.get_frames_per_page();
589 size_t pagesize
= stride
* pageframes
;
591 v
.resize(vsize
+ pageframes
);
592 unsigned char* contents
= v
.get_page_buffer(pagenum
++);
593 file
.read(reinterpret_cast<char*>(contents
), pagesize
);
594 vsize
+= (file
.gcount() / stride
);
599 portctrl::frame tmpl
= v
.blank_frame(false);
601 std::getline(file
, line
);
603 if(line
.length() == 0)
605 tmpl
.deserialize(line
.c_str());
612 int current_branch(lua::state
& L
, lua::parameters
& P
)
614 L
.pushlstring(CORE().mlogic
->get_mfile().current_branch());
618 int get_branches(lua::state
& L
, lua::parameters
& P
)
621 for(auto& i
: core
.mlogic
->get_mfile().branches
)
622 L
.pushlstring(i
.first
);
623 return core
.mlogic
->get_mfile().branches
.size();
626 portctrl::frame_vector
& framevector(lua::state
& L
, lua::parameters
& P
)
631 return *core
.mlogic
->get_mfile().input
;
632 } else if(P
.is_string()) {
635 if(!core
.mlogic
->get_mfile().branches
.count(x
))
636 throw std::runtime_error("No such branch");
637 return core
.mlogic
->get_mfile().branches
[x
];
638 } else if(P
.is
<lua_inputmovie
>())
639 return *(P
.arg
<lua_inputmovie
*>()->get_frame_vector());
641 return *core
.mlogic
->get_mfile().input
;
644 lua::_class
<lua_inputmovie
> LUA_class_inputmovie(lua_class_movie
, "INPUTMOVIE", {}, {
645 {"copy_movie", &lua_inputmovie::copy_movie
},
646 {"get_frame", &lua_inputmovie::get_frame
},
647 {"set_frame", &lua_inputmovie::set_frame
},
648 {"get_size", &lua_inputmovie::get_size
},
649 {"count_frames", &lua_inputmovie::count_frames
},
650 {"find_frame", &lua_inputmovie::find_frame
},
651 {"subframe_to_frame", &lua_inputmovie::subframe_to_frame
},
652 {"blank_frame", &lua_inputmovie::blank_frame
},
653 {"append_frames", &lua_inputmovie::append_frames
},
654 {"append_frame", &lua_inputmovie::append_frame
},
655 {"truncate", &lua_inputmovie::truncate
},
656 {"edit", &lua_inputmovie::edit
},
657 {"debugdump", &lua_inputmovie::debugdump
},
658 {"copy_frames", &lua_inputmovie::copy_frames
},
659 {"serialize", &lua_inputmovie::serialize
},
660 }, &lua_inputmovie::print
);
662 lua::_class
<lua_inputframe
> LUA_class_inputframe(lua_class_movie
, "INPUTFRAME", {}, {
663 {"get_button", &lua_inputframe::get_button
},
664 {"get_axis", &lua_inputframe::get_axis
},
665 {"set_axis", &lua_inputframe::set_axis
},
666 {"set_button", &lua_inputframe::set_axis
},
667 {"serialize", &lua_inputframe::serialize
},
668 {"unserialize", &lua_inputframe::unserialize
},
669 {"get_stride", &lua_inputframe::get_stride
},
670 }, &lua_inputframe::print
);
672 lua::functions
LUA_inputmovie_fns(lua_func_misc
, "movie", {
673 {"current_first_subframe", current_first_subframe
},
674 {"pollcounter", pollcounter
},
675 {"copy_movie", copy_movie
},
676 {"get_frame", get_frame
},
677 {"set_frame", set_frame
},
678 {"get_size", get_size
},
679 {"count_frames", count_frames
},
680 {"find_frame", find_frame
},
681 {"subframe_to_frame", subframe_to_frame
},
682 {"blank_frame", blank_frame
},
683 {"append_frames", append_frames
},
684 {"append_frame", append_frame
},
685 {"truncate", truncate
},
687 {"copy_frames2", copy_frames2
},
688 {"copy_frames", copy_frames
},
689 {"serialize", serialize
},
690 {"unserialize", unserialize
},
691 {"current_branch", current_branch
},
692 {"get_branches", get_branches
},
695 lua_inputframe::lua_inputframe(lua::state
& L
, portctrl::frame _f
)
700 void lua_inputmovie::common_init(lua::state
& L
)
704 lua_inputmovie::lua_inputmovie(lua::state
& L
, const portctrl::frame_vector
& _v
)
710 lua_inputmovie::lua_inputmovie(lua::state
& L
, portctrl::frame
& f
)
712 v
.clear(f
.porttypes());