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
, lua::parameters
& P
)
22 unsigned port
, controller
, button
;
24 P(P
.skipped(), port
, controller
, button
);
26 short value
= getbutton(port
, controller
, button
);
27 L
.pushboolean(value
? 1 : 0);
30 int get_axis(lua::state
& L
, lua::parameters
& P
)
32 unsigned port
, controller
, button
;
34 P(P
.skipped(), port
, controller
, button
);
36 short value
= getbutton(port
, controller
, button
);
40 int set_axis(lua::state
& L
, lua::parameters
& P
)
42 unsigned port
, controller
, button
;
45 P(P
.skipped(), port
, controller
, button
);
46 if(P
.is_boolean()) value
= P
.arg
<bool>() ? 1 : 0;
47 else if(P
.is_number()) value
= P
.arg
<short>();
49 P
.expected("number or boolean");
51 setbutton(port
, controller
, button
, value
);
54 int serialize(lua::state
& L
, lua::parameters
& P
)
56 char buf
[MAX_SERIALIZED_SIZE
];
61 int unserialize(lua::state
& L
, lua::parameters
& P
)
67 f
.deserialize(buf
.c_str());
70 int get_stride(lua::state
& L
, lua::parameters
& P
)
72 L
.pushnumber(f
.size());
75 controller_frame
& get_frame()
81 char buf
[MAX_SERIALIZED_SIZE
];
86 short getbutton(unsigned port
, unsigned controller
, unsigned index
)
88 return f
.axis3(port
, controller
, index
);
90 void setbutton(unsigned port
, unsigned controller
, unsigned index
, short value
)
92 return f
.axis3(port
, controller
, index
, value
);
97 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
= false);
98 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
)
100 movie
& m
= movb
.get_movie();
101 if(port
== 0 && controller
== 0 && button
== 0)
102 return m
.get_pollcounters().max_polls() + (extra0
? 1 : 0);
103 if(port
== 0 && controller
== 0 && m
.get_pollcounters().get_framepflag())
104 return max(m
.get_pollcounters().get_polls(port
, controller
, button
), (uint32_t)1);
105 return m
.get_pollcounters().get_polls(port
, controller
, button
);
108 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
109 bool allow_past_end
= false);
111 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
114 movie
& m
= movb
.get_movie();
115 if(!m
.readonly_mode())
116 throw std::runtime_error("Not in read-only mode");
117 if(!allow_past_end
&& frame
>= movb
.get_movie().get_frame_vector().size())
118 throw std::runtime_error("Index out of movie");
119 int32_t pc
= get_pc_for(port
, controller
, button
, true);
121 throw std::runtime_error("Invalid control to edit");
122 uint64_t firstframe
= m
.get_current_frame_first_subframe();
123 uint64_t minframe
= firstframe
+ pc
;
124 uint64_t msize
= movb
.get_movie().get_frame_vector().size();
125 if(minframe
> msize
|| firstframe
>= msize
)
126 throw std::runtime_error("Can not edit finished movie");
128 throw std::runtime_error("Can not edit past");
131 lua::fnptr2
movie_cfs(lua_func_misc
, "movie.current_first_subframe", [](lua::state
& L
, lua::parameters
& P
)
133 movie
& m
= movb
.get_movie();
134 L
.pushnumber(m
.get_current_frame_first_subframe());
138 lua::fnptr2
movie_pc(lua_func_misc
, "movie.pollcounter", [](lua::state
& L
, lua::parameters
& P
) -> int {
139 unsigned port
, controller
, button
;
141 P(port
, controller
, button
);
144 ret
= get_pc_for(port
, controller
, button
);
149 controller_frame_vector
& framevector(lua::state
& L
, lua::parameters
& P
);
151 int _copy_movie(lua::state
& L
, lua::parameters
& P
)
153 controller_frame_vector
& v
= framevector(L
, P
);
155 lua_inputmovie
* m
= lua::_class
<lua_inputmovie
>::create(L
, v
);
159 int _get_frame(lua::state
& L
, lua::parameters
& P
)
162 controller_frame_vector
& v
= framevector(L
, P
);
167 throw std::runtime_error("Requested frame outside movie");
168 controller_frame _f
= v
[n
];
169 lua_inputframe
* f
= lua::_class
<lua_inputframe
>::create(L
, _f
);
173 int _set_frame(lua::state
& L
, lua::parameters
& P
)
177 controller_frame_vector
& v
= framevector(L
, P
);
182 throw std::runtime_error("Requested frame outside movie");
183 //Checks if requested frame is from movie.
184 if(&v
== &movb
.get_movie().get_frame_vector())
185 check_can_edit(0, 0, 0, n
);
187 v
[n
] = f
->get_frame();
189 if(&v
== &movb
.get_movie().get_frame_vector()) {
190 //This can't add frames, so no need to adjust the movie.
191 update_movie_state();
192 platform::notify_status();
197 int _get_size(lua::state
& L
, lua::parameters
& P
)
200 controller_frame_vector
& v
= framevector(L
, P
);
202 L
.pushnumber(v
.size());
206 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
);
227 uint64_t s
= v
.size();
228 for(uint64_t i
= 0; i
< s
; i
++)
229 if(v
[i
].sync() && ++c
== n
) {
237 int _blank_frame(lua::state
& L
, lua::parameters
& P
)
240 controller_frame_vector
& v
= framevector(L
, P
);
242 controller_frame _f
= v
.blank_frame(true);
243 lua_inputframe
* f
= lua::_class
<lua_inputframe
>::create(L
, _f
);
247 int _append_frames(lua::state
& L
, lua::parameters
& P
)
250 controller_frame_vector
& v
= framevector(L
, P
);
255 controller_frame_vector::notify_freeze
freeze(v
);
256 for(uint64_t i
= 0; i
< count
; i
++)
257 v
.append(v
.blank_frame(true));
259 if(&v
== &movb
.get_movie().get_frame_vector()) {
260 update_movie_state();
261 platform::notify_status();
266 int _append_frame(lua::state
& L
, lua::parameters
& P
)
269 controller_frame_vector
& v
= framevector(L
, P
);
273 v
.append(v
.blank_frame(true));
274 if(&v
== &movb
.get_movie().get_frame_vector()) {
275 update_movie_state();
276 platform::notify_status();
277 check_can_edit(0, 0, 0, v
.size() - 1);
279 v
[v
.size() - 1] = f
->get_frame();
280 if(&v
== &movb
.get_movie().get_frame_vector()) {
281 if(!v
[v
.size() - 1].sync()) {
282 update_movie_state();
284 platform::notify_status();
289 int _truncate(lua::state
& L
, lua::parameters
& P
)
292 controller_frame_vector
& v
= framevector(L
, P
);
297 throw std::runtime_error("Requested truncate length longer than existing");
298 if(&v
== &movb
.get_movie().get_frame_vector())
299 check_can_edit(0, 0, 0, n
);
301 if(&v
== &movb
.get_movie().get_frame_vector()) {
302 update_movie_state();
303 platform::notify_status();
308 int _edit(lua::state
& L
, lua::parameters
& P
)
311 unsigned port
, controller
, button
;
313 controller_frame_vector
& v
= framevector(L
, P
);
315 P(frame
, port
, controller
, button
);
316 if(P
.is_boolean()) value
= P
.arg
<bool>() ? 1 : 0;
317 else if(P
.is_number()) P(value
);
319 P
.expected("number or boolean");
321 movie
& m
= movb
.get_movie();
322 if(&v
== &movb
.get_movie().get_frame_vector())
323 check_can_edit(port
, controller
, button
, frame
);
324 v
[frame
].axis3(port
, controller
, button
, value
);
326 if(&v
== &movb
.get_movie().get_frame_vector()) {
327 update_movie_state();
328 platform::notify_status();
334 int _copy_frames(lua::state
& L
, lua::parameters
& P
)
336 uint64_t dst
, src
, count
;
337 bool backwards
= same
;
339 controller_frame_vector
& dstv
= framevector(L
, P
);
341 controller_frame_vector
& srcv
= same
? dstv
: framevector(L
, P
);
343 if(same
) P(backwards
);
345 if(src
>= srcv
.size() || src
+ count
< src
)
346 throw std::runtime_error("Source index out of movie");
347 if(dst
> dstv
.size() || dst
+ count
< dst
)
348 throw std::runtime_error("Destination index out of movie");
350 movie
& m
= movb
.get_movie();
351 if(&dstv
== &movb
.get_movie().get_frame_vector())
352 check_can_edit(0, 0, 0, dst
, true);
355 controller_frame_vector::notify_freeze
freeze(dstv
);
356 //Add enough blank frames to make the copy.
357 while(dst
+ count
> dstv
.size())
358 dstv
.append(dstv
.blank_frame(false));
360 for(uint64_t i
= backwards
? (count
- 1) : 0; i
< count
; i
= backwards
? (i
- 1) : (i
+ 1))
361 dstv
[dst
+ i
] = srcv
[src
+ i
];
363 if(&dstv
== &movb
.get_movie().get_frame_vector()) {
364 update_movie_state();
365 platform::notify_status();
370 int _serialize(lua::state
& L
, lua::parameters
& P
)
372 std::string filename
;
375 controller_frame_vector
& v
= framevector(L
, P
);
379 std::ofstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::out
);
381 throw std::runtime_error("Can't open file to write output to");
383 uint64_t pages
= v
.get_page_count();
384 uint64_t stride
= v
.get_stride();
385 uint64_t pageframes
= v
.get_frames_per_page();
386 uint64_t vsize
= v
.size();
389 uint64_t count
= (vsize
> pageframes
) ? pageframes
: vsize
;
390 size_t bytes
= count
* stride
;
391 unsigned char* content
= v
.get_page_buffer(pagenum
++);
392 file
.write(reinterpret_cast<char*>(content
), bytes
);
396 char buf
[MAX_SERIALIZED_SIZE
];
397 for(uint64_t i
= 0; i
< v
.size(); i
++) {
399 file
<< buf
<< std::endl
;
408 lua_inputmovie(lua::state
& L
, const controller_frame_vector
& _v
);
409 lua_inputmovie(lua::state
& L
, controller_frame
& _f
);
410 int copy_movie(lua::state
& L
, lua::parameters
& P
)
412 return _copy_movie(L
, P
);
414 int get_frame(lua::state
& L
, lua::parameters
& P
)
416 return _get_frame(L
, P
);
418 int set_frame(lua::state
& L
, lua::parameters
& P
)
420 return _set_frame(L
, P
);
422 int get_size(lua::state
& L
, lua::parameters
& P
)
424 return _get_size(L
, P
);
426 int count_frames(lua::state
& L
, lua::parameters
& P
)
428 return _count_frames(L
, P
);
430 int find_frame(lua::state
& L
, lua::parameters
& P
)
432 return _find_frame(L
, P
);
434 int blank_frame(lua::state
& L
, lua::parameters
& P
)
436 return _blank_frame(L
, P
);
438 int append_frames(lua::state
& L
, lua::parameters
& P
)
440 return _append_frames(L
, P
);
442 int append_frame(lua::state
& L
, lua::parameters
& P
)
444 return _append_frame(L
, P
);
446 int truncate(lua::state
& L
, lua::parameters
& P
)
448 return _truncate(L
, P
);
450 int edit(lua::state
& L
, lua::parameters
& P
)
454 int copy_frames(lua::state
& L
, lua::parameters
& P
)
456 return _copy_frames
<true>(L
, P
);
458 int serialize(lua::state
& L
, lua::parameters
& P
)
460 return _serialize(L
, P
);
462 int debugdump(lua::state
& L
, lua::parameters
& P
)
464 char buf
[MAX_SERIALIZED_SIZE
];
465 for(uint64_t i
= 0; i
< v
.size(); i
++) {
467 messages
<< buf
<< std::endl
;
471 controller_frame_vector
* get_frame_vector()
478 return (stringfmt() << s
<< " " << ((s
!= 1) ? "frames" : "frame")).str();
481 void common_init(lua::state
& L
);
482 controller_frame_vector v
;
485 lua::fnptr2
movie_getdata(lua_func_misc
, "movie.copy_movie", [](lua::state
& L
, lua::parameters
& P
) -> int {
486 return _copy_movie(L
, P
);
489 lua::fnptr2
movie_getframe(lua_func_misc
, "movie.get_frame", [](lua::state
& L
, lua::parameters
& P
) -> int {
490 return _get_frame(L
, P
);
493 lua::fnptr2
movie_setframe(lua_func_misc
, "movie.set_frame", [](lua::state
& L
, lua::parameters
& P
) -> int {
494 return _set_frame(L
, P
);
497 lua::fnptr2
movie_get_size(lua_func_misc
, "movie.get_size", [](lua::state
& L
, lua::parameters
& P
) -> int {
498 return _get_size(L
, P
);
501 lua::fnptr2
movie_count_frames(lua_func_misc
, "movie.count_frames", [](lua::state
& L
, lua::parameters
& P
)
503 return _count_frames(L
, P
);
506 lua::fnptr2
movie_find_frame(lua_func_misc
, "movie.find_frame", [](lua::state
& L
, lua::parameters
& P
) -> int {
507 return _find_frame(L
, P
);
510 lua::fnptr2
movie_blank_frame(lua_func_misc
, "movie.blank_frame", [](lua::state
& L
, lua::parameters
& P
)
512 return _blank_frame(L
, P
);
515 lua::fnptr2
movie_append_frames(lua_func_misc
, "movie.append_frames", [](lua::state
& L
, lua::parameters
& P
)
517 return _append_frames(L
, P
);
520 lua::fnptr2
movie_append_frame(lua_func_misc
, "movie.append_frame", [](lua::state
& L
, lua::parameters
& P
)
522 return _append_frame(L
, P
);
525 lua::fnptr2
movie_truncate(lua_func_misc
, "movie.truncate", [](lua::state
& L
, lua::parameters
& P
) -> int {
526 return _truncate(L
, P
);
529 lua::fnptr2
movie_edit(lua_func_misc
, "movie.edit", [](lua::state
& L
, lua::parameters
& P
) -> int {
533 lua::fnptr2
movie_copyframe2(lua_func_misc
, "movie.copy_frames2", [](lua::state
& L
, lua::parameters
& P
)
535 return _copy_frames
<false>(L
, P
);
538 lua::fnptr2
movie_copyframe(lua_func_misc
, "movie.copy_frames", [](lua::state
& L
, lua::parameters
& P
) -> int {
539 return _copy_frames
<true>(L
, P
);
542 lua::fnptr2
movie_serialize(lua_func_misc
, "movie.serialize", [](lua::state
& L
, lua::parameters
& P
) -> int {
543 return _serialize(L
, P
);
546 lua::fnptr2
movie_unserialize(lua_func_misc
, "movie.unserialize", [](lua::state
& L
, lua::parameters
& P
)
549 std::string filename
;
552 P(f
, filename
, binary
);
554 std::ifstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::in
);
556 throw std::runtime_error("Can't open file to read input from");
557 lua_inputmovie
* m
= lua::_class
<lua_inputmovie
>::create(L
, f
->get_frame());
558 controller_frame_vector
& v
= *m
->get_frame_vector();
559 controller_frame_vector::notify_freeze
freeze(v
);
561 uint64_t stride
= v
.get_stride();
562 uint64_t pageframes
= v
.get_frames_per_page();
565 size_t pagesize
= stride
* pageframes
;
567 v
.resize(vsize
+ pageframes
);
568 unsigned char* contents
= v
.get_page_buffer(pagenum
++);
569 file
.read(reinterpret_cast<char*>(contents
), pagesize
);
570 vsize
+= (file
.gcount() / stride
);
575 controller_frame tmpl
= v
.blank_frame(false);
577 std::getline(file
, line
);
579 if(line
.length() == 0)
581 tmpl
.deserialize(line
.c_str());
589 controller_frame_vector
& framevector(lua::state
& L
, lua::parameters
& P
)
593 return movb
.get_movie().get_frame_vector();
594 } else if(P
.is
<lua_inputmovie
>())
595 return *(P
.arg
<lua_inputmovie
*>()->get_frame_vector());
597 return movb
.get_movie().get_frame_vector();
600 lua::_class
<lua_inputmovie
> class_inputmovie(lua_class_movie
, "INPUTMOVIE", {}, {
601 {"copy_movie", &lua_inputmovie::copy_movie
},
602 {"get_frame", &lua_inputmovie::get_frame
},
603 {"set_frame", &lua_inputmovie::set_frame
},
604 {"get_size", &lua_inputmovie::get_size
},
605 {"count_frames", &lua_inputmovie::count_frames
},
606 {"find_frame", &lua_inputmovie::find_frame
},
607 {"blank_frame", &lua_inputmovie::blank_frame
},
608 {"append_frames", &lua_inputmovie::append_frames
},
609 {"append_frame", &lua_inputmovie::append_frame
},
610 {"truncate", &lua_inputmovie::truncate
},
611 {"edit", &lua_inputmovie::edit
},
612 {"debugdump", &lua_inputmovie::debugdump
},
613 {"copy_frames", &lua_inputmovie::copy_frames
},
614 {"serialize", &lua_inputmovie::serialize
},
615 }, &lua_inputmovie::print
);
617 lua::_class
<lua_inputframe
> class_inputframe(lua_class_movie
, "INPUTFRAME", {}, {
618 {"get_button", &lua_inputframe::get_button
},
619 {"get_axis", &lua_inputframe::get_axis
},
620 {"set_axis", &lua_inputframe::set_axis
},
621 {"set_button", &lua_inputframe::set_axis
},
622 {"serialize", &lua_inputframe::serialize
},
623 {"unserialize", &lua_inputframe::unserialize
},
624 {"get_stride", &lua_inputframe::get_stride
},
625 }, &lua_inputframe::print
);
627 lua_inputframe::lua_inputframe(lua::state
& L
, controller_frame _f
)
632 void lua_inputmovie::common_init(lua::state
& L
)
636 lua_inputmovie::lua_inputmovie(lua::state
& L
, const controller_frame_vector
& _v
)
642 lua_inputmovie::lua_inputmovie(lua::state
& L
, controller_frame
& f
)
644 v
.clear(f
.porttypes());