1 #include "lua/internal.hpp"
2 #include "library/string.hpp"
3 #include "library/minmax.hpp"
4 #include "core/movie.hpp"
5 #include "core/moviedata.hpp"
6 #include "core/window.hpp"
9 void update_movie_state();
17 friend class lua_inputmovie
;
19 lua_inputframe(lua::state
& L
, controller_frame _f
);
20 static size_t overcommit(controller_frame _f
) { return 0; }
21 int get_button(lua::state
& L
, lua::parameters
& P
)
23 unsigned port
, controller
, button
;
25 P(P
.skipped(), port
, controller
, button
);
27 short value
= getbutton(port
, controller
, button
);
28 L
.pushboolean(value
? 1 : 0);
31 int get_axis(lua::state
& L
, lua::parameters
& P
)
33 unsigned port
, controller
, button
;
35 P(P
.skipped(), port
, controller
, button
);
37 short value
= getbutton(port
, controller
, button
);
41 int set_axis(lua::state
& L
, lua::parameters
& P
)
43 unsigned port
, controller
, button
;
46 P(P
.skipped(), port
, controller
, button
);
47 if(P
.is_boolean()) value
= P
.arg
<bool>() ? 1 : 0;
48 else if(P
.is_number()) value
= P
.arg
<short>();
50 P
.expected("number or boolean");
52 setbutton(port
, controller
, button
, value
);
55 int serialize(lua::state
& L
, lua::parameters
& P
)
57 char buf
[MAX_SERIALIZED_SIZE
];
62 int unserialize(lua::state
& L
, lua::parameters
& P
)
68 f
.deserialize(buf
.c_str());
71 int get_stride(lua::state
& L
, lua::parameters
& P
)
73 L
.pushnumber(f
.size());
76 controller_frame
& get_frame()
82 char buf
[MAX_SERIALIZED_SIZE
];
87 short getbutton(unsigned port
, unsigned controller
, unsigned index
)
89 return f
.axis3(port
, controller
, index
);
91 void setbutton(unsigned port
, unsigned controller
, unsigned index
, short value
)
93 return f
.axis3(port
, controller
, index
, value
);
98 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
= false);
99 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
)
101 movie
& m
= movb
.get_movie();
102 if(port
== 0 && controller
== 0 && button
== 0)
103 return m
.get_pollcounters().max_polls() + (extra0
? 1 : 0);
104 if(port
== 0 && controller
== 0 && m
.get_pollcounters().get_framepflag())
105 return max(m
.get_pollcounters().get_polls(port
, controller
, button
), (uint32_t)1);
106 return m
.get_pollcounters().get_polls(port
, controller
, button
);
109 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
110 bool allow_past_end
= false);
112 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
115 movie
& m
= movb
.get_movie();
116 if(!m
.readonly_mode())
117 throw std::runtime_error("Not in read-only mode");
118 if(!allow_past_end
&& frame
>= movb
.get_mfile().input
->size())
119 throw std::runtime_error("Index out of movie");
120 int32_t pc
= get_pc_for(port
, controller
, button
, true);
122 throw std::runtime_error("Invalid control to edit");
123 uint64_t firstframe
= m
.get_current_frame_first_subframe();
124 uint64_t minframe
= firstframe
+ pc
;
125 uint64_t msize
= movb
.get_mfile().input
->size();
126 if(minframe
> msize
|| firstframe
>= msize
)
127 throw std::runtime_error("Can not edit finished movie");
129 throw std::runtime_error("Can not edit past");
132 int current_first_subframe(lua::state
& L
, lua::parameters
& P
)
134 movie
& m
= movb
.get_movie();
135 L
.pushnumber(m
.get_current_frame_first_subframe());
139 int pollcounter(lua::state
& L
, lua::parameters
& P
)
141 unsigned port
, controller
, button
;
143 P(port
, controller
, button
);
146 ret
= get_pc_for(port
, controller
, button
);
151 controller_frame_vector
& framevector(lua::state
& L
, lua::parameters
& P
);
153 int _copy_movie(lua::state
& L
, lua::parameters
& P
)
155 controller_frame_vector
& v
= framevector(L
, P
);
157 lua::_class
<lua_inputmovie
>::create(L
, v
);
161 int _get_frame(lua::state
& L
, lua::parameters
& P
)
164 controller_frame_vector
& v
= framevector(L
, P
);
169 throw std::runtime_error("Requested frame outside movie");
170 controller_frame _f
= v
[n
];
171 lua::_class
<lua_inputframe
>::create(L
, _f
);
175 int _set_frame(lua::state
& L
, lua::parameters
& P
)
179 controller_frame_vector
& v
= framevector(L
, P
);
184 throw std::runtime_error("Requested frame outside movie");
185 //Checks if requested frame is from movie.
186 if(&v
== movb
.get_mfile().input
)
187 check_can_edit(0, 0, 0, n
);
189 v
[n
] = f
->get_frame();
191 if(&v
== movb
.get_mfile().input
) {
192 //This can't add frames, so no need to adjust the movie.
193 update_movie_state();
194 platform::notify_status();
199 int _get_size(lua::state
& L
, lua::parameters
& P
)
201 controller_frame_vector
& v
= framevector(L
, P
);
203 L
.pushnumber(v
.size());
207 int _count_frames(lua::state
& L
, lua::parameters
& P
)
209 controller_frame_vector
& v
= framevector(L
, P
);
211 L
.pushnumber(v
.count_frames());
215 int _find_frame(lua::state
& L
, lua::parameters
& P
)
218 controller_frame_vector
& v
= framevector(L
, P
);
222 L
.pushnumber(v
.find_frame(n
));
226 int _blank_frame(lua::state
& L
, lua::parameters
& P
)
228 controller_frame_vector
& v
= framevector(L
, P
);
230 controller_frame _f
= v
.blank_frame(true);
231 lua::_class
<lua_inputframe
>::create(L
, _f
);
235 int _append_frames(lua::state
& L
, lua::parameters
& P
)
238 controller_frame_vector
& v
= framevector(L
, P
);
243 controller_frame_vector::notify_freeze
freeze(v
);
244 for(uint64_t i
= 0; i
< count
; i
++)
245 v
.append(v
.blank_frame(true));
247 if(&v
== movb
.get_mfile().input
) {
248 update_movie_state();
249 platform::notify_status();
254 int _append_frame(lua::state
& L
, lua::parameters
& P
)
257 controller_frame_vector
& v
= framevector(L
, P
);
261 v
.append(v
.blank_frame(true));
262 if(&v
== movb
.get_mfile().input
) {
263 update_movie_state();
264 platform::notify_status();
265 check_can_edit(0, 0, 0, v
.size() - 1);
267 v
[v
.size() - 1] = f
->get_frame();
268 if(&v
== movb
.get_mfile().input
) {
269 if(!v
[v
.size() - 1].sync()) {
270 update_movie_state();
272 platform::notify_status();
277 int _truncate(lua::state
& L
, lua::parameters
& P
)
280 controller_frame_vector
& v
= framevector(L
, P
);
285 throw std::runtime_error("Requested truncate length longer than existing");
286 if(&v
== movb
.get_mfile().input
)
287 check_can_edit(0, 0, 0, n
);
289 if(&v
== movb
.get_mfile().input
) {
290 update_movie_state();
291 platform::notify_status();
296 int _edit(lua::state
& L
, lua::parameters
& P
)
299 unsigned port
, controller
, button
;
301 controller_frame_vector
& v
= framevector(L
, P
);
303 P(frame
, port
, controller
, button
);
304 if(P
.is_boolean()) value
= P
.arg
<bool>() ? 1 : 0;
305 else if(P
.is_number()) P(value
);
307 P
.expected("number or boolean");
309 if(&v
== movb
.get_mfile().input
)
310 check_can_edit(port
, controller
, button
, frame
);
311 v
[frame
].axis3(port
, controller
, button
, value
);
313 if(&v
== movb
.get_mfile().input
) {
314 update_movie_state();
315 platform::notify_status();
321 int _copy_frames(lua::state
& L
, lua::parameters
& P
)
323 uint64_t dst
, src
, count
;
324 bool backwards
= same
;
326 controller_frame_vector
& dstv
= framevector(L
, P
);
328 controller_frame_vector
& srcv
= same
? dstv
: framevector(L
, P
);
330 if(same
) P(backwards
);
332 if(src
>= srcv
.size() || src
+ count
< src
)
333 throw std::runtime_error("Source index out of movie");
334 if(dst
> dstv
.size() || dst
+ count
< dst
)
335 throw std::runtime_error("Destination index out of movie");
337 if(&dstv
== movb
.get_mfile().input
)
338 check_can_edit(0, 0, 0, dst
, true);
341 controller_frame_vector::notify_freeze
freeze(dstv
);
342 //Add enough blank frames to make the copy.
343 while(dst
+ count
> dstv
.size())
344 dstv
.append(dstv
.blank_frame(false));
346 for(uint64_t i
= backwards
? (count
- 1) : 0; i
< count
; i
= backwards
? (i
- 1) : (i
+ 1))
347 dstv
[dst
+ i
] = srcv
[src
+ i
];
349 if(&dstv
== movb
.get_mfile().input
) {
350 update_movie_state();
351 platform::notify_status();
356 int _serialize(lua::state
& L
, lua::parameters
& P
)
358 std::string filename
;
361 controller_frame_vector
& v
= framevector(L
, P
);
365 std::ofstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::out
);
367 throw std::runtime_error("Can't open file to write output to");
369 uint64_t stride
= v
.get_stride();
370 uint64_t pageframes
= v
.get_frames_per_page();
371 uint64_t vsize
= v
.size();
374 uint64_t count
= (vsize
> pageframes
) ? pageframes
: vsize
;
375 size_t bytes
= count
* stride
;
376 unsigned char* content
= v
.get_page_buffer(pagenum
++);
377 file
.write(reinterpret_cast<char*>(content
), bytes
);
381 char buf
[MAX_SERIALIZED_SIZE
];
382 for(uint64_t i
= 0; i
< v
.size(); i
++) {
384 file
<< buf
<< std::endl
;
393 lua_inputmovie(lua::state
& L
, const controller_frame_vector
& _v
);
394 lua_inputmovie(lua::state
& L
, controller_frame
& _f
);
395 static size_t overcommit(const controller_frame_vector
& _v
) { return 0; }
396 static size_t overcommit(controller_frame
& _f
) { return 0; }
397 int copy_movie(lua::state
& L
, lua::parameters
& P
)
399 return _copy_movie(L
, P
);
401 int get_frame(lua::state
& L
, lua::parameters
& P
)
403 return _get_frame(L
, P
);
405 int set_frame(lua::state
& L
, lua::parameters
& P
)
407 return _set_frame(L
, P
);
409 int get_size(lua::state
& L
, lua::parameters
& P
)
411 return _get_size(L
, P
);
413 int count_frames(lua::state
& L
, lua::parameters
& P
)
415 return _count_frames(L
, P
);
417 int find_frame(lua::state
& L
, lua::parameters
& P
)
419 return _find_frame(L
, P
);
421 int blank_frame(lua::state
& L
, lua::parameters
& P
)
423 return _blank_frame(L
, P
);
425 int append_frames(lua::state
& L
, lua::parameters
& P
)
427 return _append_frames(L
, P
);
429 int append_frame(lua::state
& L
, lua::parameters
& P
)
431 return _append_frame(L
, P
);
433 int truncate(lua::state
& L
, lua::parameters
& P
)
435 return _truncate(L
, P
);
437 int edit(lua::state
& L
, lua::parameters
& P
)
441 int copy_frames(lua::state
& L
, lua::parameters
& P
)
443 return _copy_frames
<true>(L
, P
);
445 int serialize(lua::state
& L
, lua::parameters
& P
)
447 return _serialize(L
, P
);
449 int debugdump(lua::state
& L
, lua::parameters
& P
)
451 char buf
[MAX_SERIALIZED_SIZE
];
452 for(uint64_t i
= 0; i
< v
.size(); i
++) {
454 messages
<< buf
<< std::endl
;
458 controller_frame_vector
* get_frame_vector()
465 return (stringfmt() << s
<< " " << ((s
!= 1) ? "frames" : "frame")).str();
468 void common_init(lua::state
& L
);
469 controller_frame_vector v
;
472 int copy_movie(lua::state
& L
, lua::parameters
& P
)
474 return _copy_movie(L
, P
);
477 int get_frame(lua::state
& L
, lua::parameters
& P
)
479 return _get_frame(L
, P
);
482 int set_frame(lua::state
& L
, lua::parameters
& P
)
484 return _set_frame(L
, P
);
487 int get_size(lua::state
& L
, lua::parameters
& P
)
489 return _get_size(L
, P
);
492 int count_frames(lua::state
& L
, lua::parameters
& P
)
494 return _count_frames(L
, P
);
497 int find_frame(lua::state
& L
, lua::parameters
& P
)
499 return _find_frame(L
, P
);
502 int blank_frame(lua::state
& L
, lua::parameters
& P
)
504 return _blank_frame(L
, P
);
507 int append_frames(lua::state
& L
, lua::parameters
& P
)
509 return _append_frames(L
, P
);
512 int append_frame(lua::state
& L
, lua::parameters
& P
)
514 return _append_frame(L
, P
);
517 int truncate(lua::state
& L
, lua::parameters
& P
)
519 return _truncate(L
, P
);
522 int edit(lua::state
& L
, lua::parameters
& P
)
527 int copy_frames2(lua::state
& L
, lua::parameters
& P
)
529 return _copy_frames
<false>(L
, P
);
532 int copy_frames(lua::state
& L
, lua::parameters
& P
)
534 return _copy_frames
<true>(L
, P
);
537 int serialize(lua::state
& L
, lua::parameters
& P
)
539 return _serialize(L
, P
);
542 int unserialize(lua::state
& L
, lua::parameters
& P
)
545 std::string filename
;
548 P(f
, filename
, binary
);
550 std::ifstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::in
);
552 throw std::runtime_error("Can't open file to read input from");
553 lua_inputmovie
* m
= lua::_class
<lua_inputmovie
>::create(L
, f
->get_frame());
554 controller_frame_vector
& v
= *m
->get_frame_vector();
555 controller_frame_vector::notify_freeze
freeze(v
);
557 uint64_t stride
= v
.get_stride();
558 uint64_t pageframes
= v
.get_frames_per_page();
561 size_t pagesize
= stride
* pageframes
;
563 v
.resize(vsize
+ pageframes
);
564 unsigned char* contents
= v
.get_page_buffer(pagenum
++);
565 file
.read(reinterpret_cast<char*>(contents
), pagesize
);
566 vsize
+= (file
.gcount() / stride
);
571 controller_frame tmpl
= v
.blank_frame(false);
573 std::getline(file
, line
);
575 if(line
.length() == 0)
577 tmpl
.deserialize(line
.c_str());
584 int current_branch(lua::state
& L
, lua::parameters
& P
)
586 L
.pushlstring(movb
.get_mfile().current_branch());
590 int get_branches(lua::state
& L
, lua::parameters
& P
)
592 for(auto& i
: movb
.get_mfile().branches
)
593 L
.pushlstring(i
.first
);
594 return movb
.get_mfile().branches
.size();
597 controller_frame_vector
& framevector(lua::state
& L
, lua::parameters
& P
)
601 return *movb
.get_mfile().input
;
602 } else if(P
.is_string()) {
605 if(!movb
.get_mfile().branches
.count(x
))
606 throw std::runtime_error("No such branch");
607 return movb
.get_mfile().branches
[x
];
608 } else if(P
.is
<lua_inputmovie
>())
609 return *(P
.arg
<lua_inputmovie
*>()->get_frame_vector());
611 return *movb
.get_mfile().input
;
614 lua::_class
<lua_inputmovie
> class_inputmovie(lua_class_movie
, "INPUTMOVIE", {}, {
615 {"copy_movie", &lua_inputmovie::copy_movie
},
616 {"get_frame", &lua_inputmovie::get_frame
},
617 {"set_frame", &lua_inputmovie::set_frame
},
618 {"get_size", &lua_inputmovie::get_size
},
619 {"count_frames", &lua_inputmovie::count_frames
},
620 {"find_frame", &lua_inputmovie::find_frame
},
621 {"blank_frame", &lua_inputmovie::blank_frame
},
622 {"append_frames", &lua_inputmovie::append_frames
},
623 {"append_frame", &lua_inputmovie::append_frame
},
624 {"truncate", &lua_inputmovie::truncate
},
625 {"edit", &lua_inputmovie::edit
},
626 {"debugdump", &lua_inputmovie::debugdump
},
627 {"copy_frames", &lua_inputmovie::copy_frames
},
628 {"serialize", &lua_inputmovie::serialize
},
629 }, &lua_inputmovie::print
);
631 lua::_class
<lua_inputframe
> class_inputframe(lua_class_movie
, "INPUTFRAME", {}, {
632 {"get_button", &lua_inputframe::get_button
},
633 {"get_axis", &lua_inputframe::get_axis
},
634 {"set_axis", &lua_inputframe::set_axis
},
635 {"set_button", &lua_inputframe::set_axis
},
636 {"serialize", &lua_inputframe::serialize
},
637 {"unserialize", &lua_inputframe::unserialize
},
638 {"get_stride", &lua_inputframe::get_stride
},
639 }, &lua_inputframe::print
);
641 lua::functions
inputmovie_fns(lua_func_misc
, "movie", {
642 {"current_first_subframe", current_first_subframe
},
643 {"pollcounter", pollcounter
},
644 {"copy_movie", copy_movie
},
645 {"get_frame", get_frame
},
646 {"set_frame", set_frame
},
647 {"get_size", get_size
},
648 {"count_frames", count_frames
},
649 {"find_frame", find_frame
},
650 {"blank_frame", blank_frame
},
651 {"append_frames", append_frames
},
652 {"append_frame", append_frame
},
653 {"truncate", truncate
},
655 {"copy_frames2", copy_frames2
},
656 {"copy_frames", copy_frames
},
657 {"serialize", serialize
},
658 {"unserialize", unserialize
},
659 {"current_branch", current_branch
},
660 {"get_branches", get_branches
},
663 lua_inputframe::lua_inputframe(lua::state
& L
, controller_frame _f
)
668 void lua_inputmovie::common_init(lua::state
& L
)
672 lua_inputmovie::lua_inputmovie(lua::state
& L
, const controller_frame_vector
& _v
)
678 lua_inputmovie::lua_inputmovie(lua::state
& L
, controller_frame
& f
)
680 v
.clear(f
.porttypes());