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 int get_button(lua_state
& L
, const std::string
& fname
)
22 unsigned port
= L
.get_numeric_argument
<unsigned>(2, fname
.c_str());
23 unsigned controller
= L
.get_numeric_argument
<unsigned>(3, fname
.c_str());
24 unsigned button
= L
.get_numeric_argument
<unsigned>(4, fname
.c_str());
25 short value
= getbutton(port
, controller
, button
);
26 L
.pushboolean(value
? 1 : 0);
29 int get_axis(lua_state
& L
, const std::string
& fname
)
31 unsigned port
= L
.get_numeric_argument
<unsigned>(2, fname
.c_str());
32 unsigned controller
= L
.get_numeric_argument
<unsigned>(3, fname
.c_str());
33 unsigned button
= L
.get_numeric_argument
<unsigned>(4, fname
.c_str());
34 short value
= getbutton(port
, controller
, button
);
38 int set_axis(lua_state
& L
, const std::string
& fname
)
40 unsigned port
= L
.get_numeric_argument
<unsigned>(2, fname
.c_str());
41 unsigned controller
= L
.get_numeric_argument
<unsigned>(3, fname
.c_str());
42 unsigned button
= L
.get_numeric_argument
<unsigned>(4, fname
.c_str());
44 if(L
.type(5) == LUA_TBOOLEAN
)
45 value
= L
.toboolean(5);
46 else if(L
.type(5) == LUA_TNUMBER
)
47 value
= L
.get_numeric_argument
<short>(5, fname
.c_str());
49 (stringfmt() << "Expected argument 5 of " << fname
<< " to be boolean or "
50 << "number").throwex();
51 setbutton(port
, controller
, button
, value
);
54 int serialize(lua_state
& L
, const std::string
& fname
)
56 char buf
[MAX_SERIALIZED_SIZE
];
61 int unserialize(lua_state
& L
, const std::string
& fname
)
63 std::string buf
= L
.get_string(2, fname
.c_str());
64 f
.deserialize(buf
.c_str());
67 int get_stride(lua_state
& L
, const std::string
& fname
)
69 L
.pushnumber(f
.size());
72 controller_frame
& get_frame()
78 char buf
[MAX_SERIALIZED_SIZE
];
83 short getbutton(unsigned port
, unsigned controller
, unsigned index
)
85 return f
.axis3(port
, controller
, index
);
87 void setbutton(unsigned port
, unsigned controller
, unsigned index
, short value
)
89 return f
.axis3(port
, controller
, index
, value
);
94 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
= false);
95 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
)
97 movie
& m
= movb
.get_movie();
98 if(port
== 0 && controller
== 0 && button
== 0)
99 return m
.get_pollcounters().max_polls() + (extra0
? 1 : 0);
100 if(port
== 0 && controller
== 0 && m
.get_pollcounters().get_framepflag())
101 return max(m
.get_pollcounters().get_polls(port
, controller
, button
), (uint32_t)1);
102 return m
.get_pollcounters().get_polls(port
, controller
, button
);
105 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
106 bool allow_past_end
= false);
108 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
111 movie
& m
= movb
.get_movie();
112 if(!m
.readonly_mode())
113 throw std::runtime_error("Not in read-only mode");
114 if(!allow_past_end
&& frame
>= movb
.get_movie().get_frame_vector().size())
115 throw std::runtime_error("Index out of movie");
116 int32_t pc
= get_pc_for(port
, controller
, button
, true);
118 throw std::runtime_error("Invalid control to edit");
119 uint64_t firstframe
= m
.get_current_frame_first_subframe();
120 uint64_t minframe
= firstframe
+ pc
;
121 uint64_t msize
= movb
.get_movie().get_frame_vector().size();
122 if(minframe
> msize
|| firstframe
>= msize
)
123 throw std::runtime_error("Can not edit finished movie");
125 throw std::runtime_error("Can not edit past");
128 function_ptr_luafun
movie_cfs(lua_func_misc
, "movie.current_first_subframe", [](lua_state
& L
,
129 const std::string
& fname
) -> int {
130 movie
& m
= movb
.get_movie();
131 L
.pushnumber(m
.get_current_frame_first_subframe());
135 function_ptr_luafun
movie_pc(lua_func_misc
, "movie.pollcounter", [](lua_state
& L
, const std::string
& fname
)
137 unsigned port
= L
.get_numeric_argument
<unsigned>(1, fname
.c_str());
138 unsigned controller
= L
.get_numeric_argument
<unsigned>(2, fname
.c_str());
139 unsigned button
= L
.get_numeric_argument
<unsigned>(3, fname
.c_str());
141 ret
= get_pc_for(port
, controller
, button
);
146 controller_frame_vector
& framevector(lua_state
& L
, int& ptr
, const std::string
& fname
);
148 int _copy_movie(lua_state
& L
, const std::string
& fname
)
151 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
153 lua_inputmovie
* m
= lua_class
<lua_inputmovie
>::create(L
, v
);
157 int _get_frame(lua_state
& L
, const std::string
& fname
)
160 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
162 uint64_t n
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
164 throw std::runtime_error("Requested frame outside movie");
165 controller_frame _f
= v
[n
];
166 lua_inputframe
* f
= lua_class
<lua_inputframe
>::create(L
, _f
);
170 int _set_frame(lua_state
& L
, const std::string
& fname
)
173 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
175 uint64_t n
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
177 throw std::runtime_error("Requested frame outside movie");
178 //Checks if requested frame is from movie.
179 if(&v
== &movb
.get_movie().get_frame_vector())
180 check_can_edit(0, 0, 0, n
);
182 lua_inputframe
* f
= lua_class
<lua_inputframe
>::get(L
, ptr
++, fname
.c_str());
184 if(v
[n
].sync()) adjust
--;
185 v
[n
] = f
->get_frame();
186 if(v
[n
].sync()) adjust
++;
188 if(&v
== &movb
.get_movie().get_frame_vector()) {
189 movb
.get_movie().adjust_frame_count(adjust
);
190 update_movie_state();
191 platform::notify_status();
196 int _get_size(lua_state
& L
, const std::string
& fname
)
199 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
201 L
.pushnumber(v
.size());
205 int _count_frames(lua_state
& L
, const std::string
& fname
)
208 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
211 uint64_t s
= v
.size();
212 for(uint64_t i
= 0; i
< s
; i
++)
219 int _find_frame(lua_state
& L
, const std::string
& fname
)
222 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
224 uint64_t n
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
230 uint64_t s
= v
.size();
231 for(uint64_t i
= 0; i
< s
; i
++)
232 if(v
[i
].sync() && ++c
== n
) {
240 int _blank_frame(lua_state
& L
, const std::string
& fname
)
243 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
245 controller_frame _f
= v
.blank_frame(true);
246 lua_inputframe
* f
= lua_class
<lua_inputframe
>::create(L
, _f
);
250 int _append_frames(lua_state
& L
, const std::string
& fname
)
253 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
255 uint64_t count
= L
.get_numeric_argument
<uint64_t>(ptr
++, "lua_inputmovie::append_frames");
256 for(uint64_t i
= 0; i
< count
; i
++)
257 v
.append(v
.blank_frame(true));
258 if(&v
== &movb
.get_movie().get_frame_vector()) {
259 movb
.get_movie().adjust_frame_count(count
);
260 update_movie_state();
261 platform::notify_status();
266 int _append_frame(lua_state
& L
, const std::string
& fname
)
269 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
271 lua_inputframe
* f
= lua_class
<lua_inputframe
>::get(L
, ptr
++, fname
.c_str());
273 v
.append(v
.blank_frame(true));
274 if(&v
== &movb
.get_movie().get_frame_vector()) {
275 movb
.get_movie().adjust_frame_count(1);
276 update_movie_state();
277 platform::notify_status();
278 check_can_edit(0, 0, 0, v
.size() - 1);
280 v
[v
.size() - 1] = f
->get_frame();
281 if(&v
== &movb
.get_movie().get_frame_vector()) {
282 if(!v
[v
.size() - 1].sync()) {
283 movb
.get_movie().adjust_frame_count(-1);
284 update_movie_state();
286 platform::notify_status();
291 int _truncate(lua_state
& L
, const std::string
& fname
)
294 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
296 uint64_t n
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
298 throw std::runtime_error("Requested truncate length longer than existing");
299 if(&v
== &movb
.get_movie().get_frame_vector())
300 check_can_edit(0, 0, 0, n
);
302 if(&v
== &movb
.get_movie().get_frame_vector()) {
303 movb
.get_movie().recount_frames();
304 update_movie_state();
305 platform::notify_status();
310 int _edit(lua_state
& L
, const std::string
& fname
)
313 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
315 uint64_t frame
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
316 unsigned port
= L
.get_numeric_argument
<unsigned>(ptr
++, fname
.c_str());
317 unsigned controller
= L
.get_numeric_argument
<unsigned>(ptr
++, fname
.c_str());
318 unsigned button
= L
.get_numeric_argument
<unsigned>(ptr
++, fname
.c_str());
321 if(L
.type(ptr
) == LUA_TBOOLEAN
)
322 value
= L
.toboolean(ptr
);
323 else if(L
.type(ptr
) == LUA_TNUMBER
)
324 value
= L
.get_numeric_argument
<short>(ptr
++, fname
.c_str());
326 (stringfmt() << "Expected argument " << (ptr
- 1) << " of " << fname
<< " to be boolean or "
327 << "number").throwex();
328 movie
& m
= movb
.get_movie();
329 if(&v
== &movb
.get_movie().get_frame_vector())
330 check_can_edit(port
, controller
, button
, frame
);
331 if(port
== 0 && controller
== 0 && button
== 0)
332 if(v
[frame
].sync() && !value
) schange
= -1;
333 v
[frame
].axis3(port
, controller
, button
, value
);
334 if(port
== 0 && controller
== 0 && button
== 0)
335 if(!v
[frame
].sync() && value
) schange
= 1;
337 if(&v
== &movb
.get_movie().get_frame_vector()) {
339 movb
.get_movie().adjust_frame_count(schange
);
340 update_movie_state();
342 platform::notify_status();
348 int _copy_frames(lua_state
& L
, const std::string
& fname
)
351 controller_frame_vector
& dstv
= framevector(L
, ptr
, fname
);
352 uint64_t dst
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
353 controller_frame_vector
& srcv
= same
? dstv
: framevector(L
, ptr
, fname
);
354 uint64_t src
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
355 uint64_t count
= L
.get_numeric_argument
<uint64_t>(ptr
++, fname
.c_str());
357 bool backwards
= same
? L
.get_bool(ptr
++, fname
.c_str()) : same
;
359 if(src
>= srcv
.size() || src
+ count
< src
)
360 throw std::runtime_error("Source index out of movie");
361 if(dst
> dstv
.size() || dst
+ count
< dst
)
362 throw std::runtime_error("Destination index out of movie");
364 movie
& m
= movb
.get_movie();
365 if(&dstv
== &movb
.get_movie().get_frame_vector())
366 check_can_edit(0, 0, 0, dst
, true);
368 //Add enough blank frames to make the copy.
369 while(dst
+ count
> dstv
.size())
370 dstv
.append(dstv
.blank_frame(false));
372 for(uint64_t i
= backwards
? (count
- 1) : 0; i
< count
; i
= backwards
? (i
- 1) : (i
+ 1)) {
373 if(dstv
[dst
+ i
].sync()) schange
--;
374 dstv
[dst
+ i
] = srcv
[src
+ i
];
375 if(dstv
[dst
+ i
].sync()) schange
++;
377 if(&dstv
== &movb
.get_movie().get_frame_vector()) {
379 movb
.get_movie().adjust_frame_count(schange
);
380 update_movie_state();
382 platform::notify_status();
387 int _serialize(lua_state
& L
, const std::string
& fname
)
390 controller_frame_vector
& v
= framevector(L
, ptr
, fname
);
391 std::string filename
= L
.get_string(ptr
++, fname
.c_str());
392 bool binary
= L
.get_bool(ptr
++, fname
.c_str());
393 std::ofstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::out
);
395 throw std::runtime_error("Can't open file to write output to");
397 uint64_t pages
= v
.get_page_count();
398 uint64_t stride
= v
.get_stride();
399 uint64_t pageframes
= v
.get_frames_per_page();
400 uint64_t vsize
= v
.size();
403 uint64_t count
= (vsize
> pageframes
) ? pageframes
: vsize
;
404 size_t bytes
= count
* stride
;
405 unsigned char* content
= v
.get_page_buffer(pagenum
++);
406 file
.write(reinterpret_cast<char*>(content
), bytes
);
410 char buf
[MAX_SERIALIZED_SIZE
];
411 for(uint64_t i
= 0; i
< v
.size(); i
++) {
413 file
<< buf
<< std::endl
;
422 lua_inputmovie(lua_state
& L
, const controller_frame_vector
& _v
);
423 lua_inputmovie(lua_state
& L
, controller_frame
& _f
);
424 int copy_movie(lua_state
& L
, const std::string
& fname
)
426 return _copy_movie(L
, fname
.c_str());
428 int get_frame(lua_state
& L
, const std::string
& fname
)
430 return _get_frame(L
, fname
.c_str());
432 int set_frame(lua_state
& L
, const std::string
& fname
)
434 return _set_frame(L
, fname
.c_str());
436 int get_size(lua_state
& L
, const std::string
& fname
)
438 return _get_size(L
, fname
.c_str());
440 int count_frames(lua_state
& L
, const std::string
& fname
)
442 return _count_frames(L
, fname
.c_str());
444 int find_frame(lua_state
& L
, const std::string
& fname
)
446 return _find_frame(L
, fname
.c_str());
448 int blank_frame(lua_state
& L
, const std::string
& fname
)
450 return _blank_frame(L
, fname
.c_str());
452 int append_frames(lua_state
& L
, const std::string
& fname
)
454 return _append_frames(L
, fname
.c_str());
456 int append_frame(lua_state
& L
, const std::string
& fname
)
458 return _append_frame(L
, fname
.c_str());
460 int truncate(lua_state
& L
, const std::string
& fname
)
462 return _truncate(L
, fname
.c_str());
464 int edit(lua_state
& L
, const std::string
& fname
)
466 return _edit(L
, fname
.c_str());
468 int copy_frames(lua_state
& L
, const std::string
& fname
)
470 return _copy_frames
<true>(L
, fname
.c_str());
472 int serialize(lua_state
& L
, const std::string
& fname
)
474 return _serialize(L
, fname
.c_str());
476 int debugdump(lua_state
& L
, const std::string
& fname
)
478 char buf
[MAX_SERIALIZED_SIZE
];
479 for(uint64_t i
= 0; i
< v
.size(); i
++) {
481 messages
<< buf
<< std::endl
;
485 controller_frame_vector
* get_frame_vector()
492 return (stringfmt() << s
<< " " << ((s
!= 1) ? "frames" : "frame")).str();
495 void common_init(lua_state
& L
);
496 controller_frame_vector v
;
499 function_ptr_luafun
movie_getdata(lua_func_misc
, "movie.copy_movie", [](lua_state
& L
,
500 const std::string
& fname
) -> int {
501 return _copy_movie(L
, fname
);
504 function_ptr_luafun
movie_getframe(lua_func_misc
, "movie.get_frame", [](lua_state
& L
,
505 const std::string
& fname
) -> int {
506 return _get_frame(L
, fname
);
509 function_ptr_luafun
movie_setframe(lua_func_misc
, "movie.set_frame", [](lua_state
& L
,
510 const std::string
& fname
) -> int {
511 return _set_frame(L
, fname
);
514 function_ptr_luafun
movie_get_size(lua_func_misc
, "movie.get_size", [](lua_state
& L
,
515 const std::string
& fname
) -> int {
516 return _get_size(L
, fname
);
519 function_ptr_luafun
movie_count_frames(lua_func_misc
, "movie.count_frames", [](lua_state
& L
,
520 const std::string
& fname
) -> int {
521 return _count_frames(L
, fname
);
524 function_ptr_luafun
movie_find_frame(lua_func_misc
, "movie.find_frame", [](lua_state
& L
,
525 const std::string
& fname
) -> int {
526 return _find_frame(L
, fname
);
529 function_ptr_luafun
movie_blank_frame(lua_func_misc
, "movie.blank_frame", [](lua_state
& L
,
530 const std::string
& fname
) -> int {
531 return _blank_frame(L
, fname
);
534 function_ptr_luafun
movie_append_frames(lua_func_misc
, "movie.append_frames", [](lua_state
& L
,
535 const std::string
& fname
) -> int {
536 return _append_frames(L
, fname
);
539 function_ptr_luafun
movie_append_frame(lua_func_misc
, "movie.append_frame", [](lua_state
& L
,
540 const std::string
& fname
) -> int {
541 return _append_frame(L
, fname
);
544 function_ptr_luafun
movie_truncate(lua_func_misc
, "movie.truncate", [](lua_state
& L
, const std::string
& fname
)
546 return _truncate(L
, fname
);
549 function_ptr_luafun
movie_edit(lua_func_misc
, "movie.edit", [](lua_state
& L
, const std::string
& fname
)
551 return _edit(L
, fname
);
554 function_ptr_luafun
movie_copyframe2(lua_func_misc
, "movie.copy_frames2", [](lua_state
& L
,
555 const std::string
& fname
) -> int {
556 return _copy_frames
<false>(L
, fname
);
559 function_ptr_luafun
movie_copyframe(lua_func_misc
, "movie.copy_frames", [](lua_state
& L
,
560 const std::string
& fname
) -> int {
561 return _copy_frames
<true>(L
, fname
);
564 function_ptr_luafun
movie_serialize(lua_func_misc
, "movie.serialize", [](lua_state
& L
,
565 const std::string
& fname
) -> int {
566 return _serialize(L
, fname
);
569 function_ptr_luafun
movie_unserialize(lua_func_misc
, "movie.unserialize", [](lua_state
& L
,
570 const std::string
& fname
) -> int {
571 lua_inputframe
* f
= lua_class
<lua_inputframe
>::get(L
, 1, fname
.c_str());
572 std::string filename
= L
.get_string(2, fname
.c_str());
573 bool binary
= L
.get_bool(3, fname
.c_str());
574 std::ifstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::in
);
576 throw std::runtime_error("Can't open file to read input from");
577 lua_inputmovie
* m
= lua_class
<lua_inputmovie
>::create(L
, f
->get_frame());
578 controller_frame_vector
& v
= *m
->get_frame_vector();
580 uint64_t stride
= v
.get_stride();
581 uint64_t pageframes
= v
.get_frames_per_page();
584 size_t pagesize
= stride
* pageframes
;
586 v
.resize(vsize
+ pageframes
);
587 unsigned char* contents
= v
.get_page_buffer(pagenum
++);
588 file
.read(reinterpret_cast<char*>(contents
), pagesize
);
589 vsize
+= (file
.gcount() / stride
);
594 controller_frame tmpl
= v
.blank_frame(false);
596 std::getline(file
, line
);
598 if(line
.length() == 0)
600 tmpl
.deserialize(line
.c_str());
608 controller_frame_vector
& framevector(lua_state
& L
, int& ptr
, const std::string
& fname
)
610 if(L
.type(ptr
) == LUA_TNIL
) { //NONE can be handled as else case.
612 return movb
.get_movie().get_frame_vector();
613 } else if(lua_class
<lua_inputmovie
>::is(L
, ptr
))
614 return *lua_class
<lua_inputmovie
>::get(L
, ptr
++, fname
.c_str())->get_frame_vector();
616 return movb
.get_movie().get_frame_vector();
620 DECLARE_LUACLASS(lua_inputmovie
, "INPUTMOVIE");
621 DECLARE_LUACLASS(lua_inputframe
, "INPUTFRAME");
625 lua_inputframe::lua_inputframe(lua_state
& L
, controller_frame _f
)
628 objclass
<lua_inputframe
>().bind_multi(L
, {
629 {"get_button", &lua_inputframe::get_button
},
630 {"get_axis", &lua_inputframe::get_axis
},
631 {"set_axis", &lua_inputframe::set_axis
},
632 {"set_button", &lua_inputframe::set_axis
},
633 {"serialize", &lua_inputframe::serialize
},
634 {"unserialize", &lua_inputframe::unserialize
},
635 {"get_stride", &lua_inputframe::get_stride
},
639 void lua_inputmovie::common_init(lua_state
& L
)
641 objclass
<lua_inputmovie
>().bind_multi(L
, {
642 {"copy_movie", &lua_inputmovie::copy_movie
},
643 {"get_frame", &lua_inputmovie::get_frame
},
644 {"set_frame", &lua_inputmovie::set_frame
},
645 {"get_size", &lua_inputmovie::get_size
},
646 {"count_frames", &lua_inputmovie::count_frames
},
647 {"find_frame", &lua_inputmovie::find_frame
},
648 {"blank_frame", &lua_inputmovie::blank_frame
},
649 {"append_frames", &lua_inputmovie::append_frames
},
650 {"append_frame", &lua_inputmovie::append_frame
},
651 {"truncate", &lua_inputmovie::truncate
},
652 {"edit", &lua_inputmovie::edit
},
653 {"debugdump", &lua_inputmovie::debugdump
},
654 {"copy_frames", &lua_inputmovie::copy_frames
},
655 {"serialize", &lua_inputmovie::serialize
},
659 lua_inputmovie::lua_inputmovie(lua_state
& L
, const controller_frame_vector
& _v
)
665 lua_inputmovie::lua_inputmovie(lua_state
& L
, controller_frame
& f
)
667 v
.clear(f
.porttypes());