source: trunk/core/luascript.c @ 1527

Revision 1527, 66.3 KB checked in by philmoz, 17 months ago (diff)

Merge latest code from reyalp-flt branch to main trunk.

  • Property svn:eol-style set to native
Line 
1#include "luascript.h"
2#include "kbd.h"
3#include "platform.h"
4#include "script.h"
5#include "lua.h"
6#include "lualib.h"
7#include "lauxlib.h"
8#include "conf.h"
9#include "shot_histogram.h"
10#include "stdlib.h"
11#include "raw.h"
12#include "modules.h"
13#include "levent.h"
14#include "console.h"
15#include "action_stack.h"
16#include "motion_detector.h"
17#include "ptp.h"
18#include "core.h"
19#include "gui_fselect.h"
20#include "lang.h"
21#include "gui_lang.h"
22#include "gui_draw.h"
23#include "module_load.h"
24
25#include "../lib/lua/lstate.h"  // for L->nCcalls, baseCcalls
26
27lua_State* L;
28lua_State* Lt;
29
30static int lua_script_is_ptp;
31static int run_first_resume; // 1 first 'resume', 0 = resuming from yield
32static int run_start_tick; // tick count at start of this kbd_task iteration
33static int run_hook_count; // number of calls to the count hook this kbd_task iteration
34#define YIELD_CHECK_COUNT 100 // check for yield every N vm instructions
35#define YIELD_MAX_COUNT_DEFAULT 25 // 25 checks = 2500 vm instructions
36#define YIELD_MAX_MS_DEFAULT 10
37static unsigned yield_max_count;
38static unsigned yield_max_ms;
39static int yield_hook_enabled;
40
41static void lua_script_disable_yield_hook(void) {
42    yield_hook_enabled = 0;
43}
44static void lua_script_enable_yield_hook(void) {
45    yield_hook_enabled = 1;
46}
47
48#ifdef CAM_CHDK_PTP
49// create a ptp message from the given stack index
50// incompatible types will return a TYPE_UNSUPPORTED message
51static ptp_script_msg *lua_create_usb_msg( lua_State* L, int index, unsigned msgtype) {
52    // TODO maybe we should just pass the lua type constants
53    unsigned datatype, datasize = 4;
54    int ivalue = 0;
55    void *data = &ivalue;
56    int ltype = lua_type(L,index);
57    switch(ltype) {
58        case LUA_TNONE:
59            return NULL; // nothing on the stack, no message generated
60        break;
61        case LUA_TNIL:
62            datatype = PTP_CHDK_TYPE_NIL;
63        break;
64        case LUA_TBOOLEAN:
65            datatype = PTP_CHDK_TYPE_BOOLEAN;
66            ivalue = lua_toboolean(L,index);
67        break;
68        case LUA_TNUMBER:
69            datatype = PTP_CHDK_TYPE_INTEGER;
70            ivalue = lua_tonumber(L,index);
71        break;
72        case LUA_TSTRING:
73            datatype = PTP_CHDK_TYPE_STRING;
74            data = (char *)lua_tolstring(L,index,&datasize);
75        break;
76        // TODO this uses usb_msg_table_to_string to serialize the table
77        // the default format is described in
78        // http://chdk.setepontos.com/index.php?topic=4338.msg62606#msg62606
79        // other formats can be implemented by overriding this function in your lua code
80        case LUA_TTABLE: {
81            int result;
82            lua_script_disable_yield_hook(); // don't want to yield while converting
83            lua_getglobal(L, "usb_msg_table_to_string"); // push function
84            lua_pushvalue(L, index); // copy specified index to top of stack
85            result = lua_pcall(L,1,1,0); // this will leave an error message as a string on the stack if call fails
86            lua_script_enable_yield_hook();
87            if( result ) {
88                // if called from lua, throw a normal error
89                if( msgtype == PTP_CHDK_S_MSGTYPE_USER ) {
90                    luaL_error(L,lua_tostring(L,-1));
91                    return NULL; // not reached
92                } else { // if it's a return, convert the message to an ERR
93                    msgtype = PTP_CHDK_S_MSGTYPE_ERR;
94                    datatype = PTP_CHDK_S_ERRTYPE_RUN;
95                    data = (char *)lua_tolstring(L,-1,&datasize);
96                    break;
97                }
98            }
99            // an empty table is returned as an empty string by default
100            // a non-string should never show up here
101            if ( !lua_isstring(L,-1) ) {
102                return NULL;
103            }
104            datatype = PTP_CHDK_TYPE_TABLE;
105            data = (char *)lua_tolstring(L,-1,&datasize);
106            lua_pop(L,1);
107        }
108        break;
109        default:
110            datatype = PTP_CHDK_TYPE_UNSUPPORTED;
111            data = (char *)lua_typename(L,ltype); // return type name as message data
112            datasize = strlen(data);
113    }
114    return ptp_script_create_msg(msgtype,datatype,datasize,data);
115}
116
117void lua_script_error_ptp(int runtime, const char *err) {
118    if(runtime) {
119        ptp_script_write_error_msg(PTP_CHDK_S_ERRTYPE_RUN, err);
120        script_end();
121    } else {
122        ptp_script_write_error_msg(PTP_CHDK_S_ERRTYPE_COMPILE, err);
123        lua_script_reset();
124    }
125}
126#endif
127
128void lua_script_reset()
129{
130  module_rawop_unload();
131  lua_close( L );
132  L = 0;
133}
134
135static void lua_count_hook(lua_State *L, lua_Debug *ar)
136{
137  run_hook_count++;
138  if( L->nCcalls > L->baseCcalls || !yield_hook_enabled )
139    return;
140  if(run_hook_count >= yield_max_count || get_tick_count() - run_start_tick >= yield_max_ms)
141    lua_yield( L, 0 );
142}
143
144void lua_script_error(lua_State *Lt,int runtime)
145{
146    const char *err = lua_tostring( Lt, -1 );
147    script_console_add_line( err );
148    if(lua_script_is_ptp) {
149#ifdef CAM_CHDK_PTP
150        lua_script_error_ptp(runtime,err);
151#endif
152    } else {
153        if(runtime) {
154            if(conf.debug_lua_restart_on_error) {
155                lua_script_reset();
156                script_start_gui(0);
157            } else {
158                script_wait_and_end();
159            }
160        } else {
161            script_print_screen_end();
162            script_wait_and_end();
163        }
164    }
165}
166
167
168// TODO more stuff from script.c should be moved here
169void lua_script_finish(lua_State *L)
170{
171#ifdef CAM_CHDK_PTP
172    if(lua_script_is_ptp) {
173        // send all return values as RET messages
174        int i,end = lua_gettop(L);
175        for(i=1;i<=end; i++) {
176            ptp_script_msg *msg = lua_create_usb_msg(L,i,PTP_CHDK_S_MSGTYPE_RET);
177            // if the queue is full return values will be silently discarded
178            // incompatible types will be returned as TYPE_UNSUPPORTED to preserve expected number and order of return values
179            if(msg) {
180                ptp_script_write_msg(msg);
181                // create_usb_msg may convert the message to an error
182                if(msg->type != PTP_CHDK_S_MSGTYPE_RET) {
183                    break;
184                }
185            } else {
186                ptp_script_write_error_msg(PTP_CHDK_S_ERRTYPE_RUN, "error creating return msg");
187                break;
188            }
189        }
190    }
191#endif
192}
193
194int lua_script_start( char const* script, int ptp )
195{
196  lua_script_is_ptp = ptp;
197  L = lua_open();
198  luaL_openlibs( L );
199  register_lua_funcs( L );
200
201  Lt = lua_newthread( L );
202  lua_setfield( L, LUA_REGISTRYINDEX, "Lt" );
203  if( luaL_loadstring( Lt, script ) != 0 ) {
204    lua_script_error(Lt,0);
205    return 0;
206  }
207  lua_sethook(Lt, lua_count_hook, LUA_MASKCOUNT, YIELD_CHECK_COUNT );
208  lua_script_enable_yield_hook();
209  run_first_resume = 1;
210  yield_max_count = YIELD_MAX_COUNT_DEFAULT;
211  yield_max_ms = YIELD_MAX_MS_DEFAULT;
212  return 1;
213}
214
215// run a timeslice of lua script
216void lua_script_run(void)
217{
218    int Lres;
219    int top;
220    if (run_first_resume) {
221        run_first_resume = 0;
222        top = 0;
223    } else {
224        top = lua_gettop(Lt);
225    }
226    run_start_tick = get_tick_count();
227    run_hook_count = 0;
228    Lres = lua_resume( Lt, top );
229
230    if (Lres == LUA_YIELD) {
231        // yielded
232        return;
233    } else if(Lres != 0) {
234        lua_script_error(Lt,1);
235        return;
236    } else {
237        // finished normally, add ptp result
238        lua_script_finish(Lt);
239        script_console_add_line(lang_str(LANG_CONSOLE_TEXT_FINISHED));
240        action_pop();
241        script_end();
242    }
243}
244
245// run the "restore" function at the end of a script
246void lua_run_restore()
247{
248        lua_getglobal(Lt, "restore");
249        if (lua_isfunction(Lt, -1)) {
250                if (lua_pcall( Lt, 0, 0, 0 )) {
251                        script_console_add_line( lua_tostring( Lt, -1 ) );
252                }
253        }
254}
255
256// get key ID of key name at arg, throw error if invalid
257static int lua_get_key_arg( lua_State * L, int narg )
258{
259    int k = script_keyid_by_name( luaL_checkstring( L, narg ) );
260    if(!k)
261        luaL_error( L, "unknown key" );
262    return k;
263}
264
265#ifdef OPT_CURVES
266#include "curves.h"
267
268static int luaCB_set_curve_state( lua_State* L )
269{
270  int value;
271  value=luaL_checknumber( L, 1 );
272
273  conf.curve_enable = value;
274  if ( libcurves && libcurves->curve_init_mode)
275                libcurves->curve_init_mode();
276
277  return 0;
278}
279#endif
280
281static int luaCB_set_aflock(lua_State* L)
282{
283  int val = luaL_checknumber(L, 1);
284  if (val>0) DoAFLock();  // 1: enable AFLock
285  else UnlockAF();       // 0: disable unlock AF
286  return 0;
287}
288
289
290static int luaCB_shoot( lua_State* L )
291{
292  action_push(AS_SHOOT);
293  return lua_yield( L, 0 );
294}
295
296static int luaCB_sleep( lua_State* L )
297{
298  action_push_delay( luaL_checknumber( L, 1 ) );
299  return lua_yield( L, 0 );
300}
301
302// for press,release and click
303static int luaCB_keyfunc( lua_State* L )
304{
305  void* func = lua_touserdata( L, lua_upvalueindex(1) );
306  ((void(*)(long))func)( lua_get_key_arg( L, 1 ) );
307  return lua_yield( L, 0 );
308}
309
310static int luaCB_cls( lua_State* L )
311{
312  console_clear();
313  return 0;
314}
315
316static int luaCB_set_console_layout( lua_State* L )
317{
318  console_set_layout(luaL_checknumber( L, 1 ),luaL_checknumber( L, 2 ),luaL_checknumber( L, 3 ),luaL_checknumber( L, 4 ));
319  return 0;
320}
321
322static int luaCB_set_console_autoredraw( lua_State* L )
323{
324  console_set_autoredraw(luaL_checknumber(L,1));
325  return 0;
326}
327
328static int luaCB_console_redraw( lua_State* L )
329{
330  console_redraw();
331  return 0;
332}
333static int luaCB_get_av96( lua_State* L )
334{
335  lua_pushnumber( L, shooting_get_av96() );
336  return 1;
337}
338
339static int luaCB_get_bv96( lua_State* L )
340{
341  lua_pushnumber( L, shooting_get_bv96() );
342  return 1;
343}
344
345static int luaCB_get_day_seconds( lua_State* L )
346{
347  lua_pushnumber( L, shooting_get_day_seconds() );
348  return 1;
349}
350
351static int luaCB_get_disk_size( lua_State* L )
352{
353  lua_pushnumber( L, GetTotalCardSpaceKb() );
354  return 1;
355}
356
357static int luaCB_get_dof( lua_State* L )
358{
359  lua_pushnumber( L, shooting_get_depth_of_field() );
360  return 1;
361}
362
363static int luaCB_get_far_limit( lua_State* L )
364{
365  lua_pushnumber( L, shooting_get_far_limit_of_acceptable_sharpness() );
366  return 1;
367}
368
369static int luaCB_get_free_disk_space( lua_State* L )
370{
371  lua_pushnumber( L, GetFreeCardSpaceKb() );
372  return 1;
373}
374
375static int luaCB_get_focus( lua_State* L )
376{
377  lua_pushnumber( L, shooting_get_subject_distance() );
378  return 1;
379}
380
381static int luaCB_get_hyp_dist( lua_State* L )
382{
383  lua_pushnumber( L, shooting_get_hyperfocal_distance() );
384  return 1;
385}
386
387static int luaCB_get_iso_market( lua_State* L )
388{
389  lua_pushnumber( L, shooting_get_iso_market() );
390  return 1;
391}
392
393static int luaCB_get_iso_mode( lua_State* L )
394{
395  lua_pushnumber( L, shooting_get_iso_mode() );
396  return 1;
397}
398
399static int luaCB_get_iso_real( lua_State* L )
400{
401  lua_pushnumber( L, shooting_get_iso_real() );
402  return 1;
403}
404
405static int luaCB_get_jpg_count( lua_State* L )
406{
407  lua_pushnumber( L, GetJpgCount() );
408  return 1;
409}
410
411static int luaCB_get_near_limit( lua_State* L )
412{
413  lua_pushnumber( L, shooting_get_near_limit_of_acceptable_sharpness() );
414  return 1;
415}
416
417/*
418val=get_prop(id)
419get propcase value identified by id
420the propcase is read as a short and sign extended to an int
421*/
422static int luaCB_get_prop( lua_State* L )
423{
424  lua_pushnumber( L, shooting_get_prop( luaL_checknumber( L, 1 ) ) );
425  return 1;
426}
427
428/*
429val=get_prop_str(prop_id,length)
430get the value of a propertycase as a string
431numeric values may be extracted using string.byte or or the binstr.lua module
432returns the value as a string, or false if the underlying propcase call returned non-zero
433*/
434static int luaCB_get_prop_str( lua_State* L ) {
435    void *buf;
436    unsigned size;
437    unsigned prop_id = luaL_checknumber( L, 1 );
438    size = luaL_checknumber( L, 2 );
439    buf = malloc(size);
440    if(!buf) {
441        return luaL_error( L, "malloc failed in luaCB_get_prop" );
442    }
443    if(get_property_case(prop_id,buf,size) == 0) {
444        lua_pushlstring( L, buf, size );
445    } else {
446        lua_pushboolean( L, 0);
447    }
448    free(buf);
449    return 1;
450}
451
452static int luaCB_get_raw_count( lua_State* L )
453{
454  lua_pushnumber( L, GetRawCount() );
455  return 1;
456}
457
458static int luaCB_get_sv96( lua_State* L )
459{
460  lua_pushnumber( L, shooting_get_sv96() );
461  return 1;
462}
463
464static int luaCB_get_tick_count( lua_State* L )
465{
466  lua_pushnumber( L, shooting_get_tick_count() );
467  return 1;
468}
469
470static int luaCB_get_exp_count( lua_State* L )
471{
472  lua_pushnumber( L, get_exposure_counter() );
473  return 1;
474}
475
476static int luaCB_get_tv96( lua_State* L )
477{
478  lua_pushnumber( L, shooting_get_tv96() );
479  return 1;
480}
481
482static int luaCB_get_user_av_id( lua_State* L )
483{
484  lua_pushnumber( L, shooting_get_user_av_id() );
485  return 1;
486}
487
488static int luaCB_get_user_av96( lua_State* L )
489{
490  lua_pushnumber( L, shooting_get_user_av96() );
491  return 1;
492}
493
494static int luaCB_get_user_tv_id( lua_State* L )
495{
496  lua_pushnumber( L, shooting_get_user_tv_id() );
497  return 1;
498}
499
500static int luaCB_get_user_tv96( lua_State* L )
501{
502  lua_pushnumber( L, shooting_get_user_tv96() );
503  return 1;
504}
505
506static int luaCB_get_vbatt( lua_State* L )
507{
508  lua_pushnumber( L, stat_get_vbatt() );
509  return 1;
510}
511
512static int luaCB_get_zoom( lua_State* L )
513{
514  lua_pushnumber( L, shooting_get_zoom() );
515  return 1;
516}
517
518static int luaCB_get_parameter_data( lua_State* L )
519{
520  extern long* FlashParamsTable[];
521
522  unsigned size;
523  unsigned id = luaL_checknumber( L, 1 );
524  unsigned val;
525
526  if (id >= get_flash_params_count()) {
527    // return nil
528    return 0;
529  }
530
531  size = FlashParamsTable[id][1]>>16;
532  if (size == 0) {
533    // return nil
534    return 0;
535  }
536  if (size >= 1 && size <= 4) {
537    val = 0;
538    get_parameter_data( id, &val, size );
539    lua_pushlstring( L, (char *)&val, size );
540    // for convenience, params that fit in a number are returned in one as a second result
541    lua_pushnumber( L, val );
542    return 2;
543  }
544  else {
545    char *buf = malloc(size);
546    if(!buf) {
547      luaL_error( L, "malloc failed in luaCB_get_parameter_data" );
548    }
549    get_parameter_data( id, buf, size );
550    lua_pushlstring( L, buf, size );
551    free(buf);
552    return 1;
553  }
554}
555
556static int luaCB_get_flash_params_count( lua_State* L )
557{
558  lua_pushnumber( L, get_flash_params_count() );
559  return 1;
560}
561
562static int luaCB_set_av96_direct( lua_State* L )
563{
564  shooting_set_av96_direct( luaL_checknumber( L, 1 ), SET_LATER );
565  return 0;
566}
567
568static int luaCB_set_av96( lua_State* L )
569{
570  shooting_set_av96( luaL_checknumber( L, 1 ), SET_LATER );
571  return 0;
572}
573
574static int luaCB_set_focus( lua_State* L )
575{
576    int to = luaL_checknumber( L, 1 );
577    int m=mode_get()&MODE_SHOOTING_MASK;
578    int mode_video=MODE_IS_VIDEO(m);
579
580#if CAM_HAS_MANUAL_FOCUS
581    if (shooting_get_focus_mode() || (mode_video)) shooting_set_focus(to, SET_NOW);
582    else shooting_set_focus(to, SET_LATER);
583#else
584    if (mode_video) shooting_set_focus(to, SET_NOW);
585    else shooting_set_focus(to, SET_LATER);   
586#endif   
587  return 0;
588}
589
590static int luaCB_set_iso_mode( lua_State* L )
591{
592  shooting_set_iso_mode( luaL_checknumber( L, 1 ) );
593  return 0;
594}
595
596static int luaCB_set_iso_real( lua_State* L )
597{
598  shooting_set_iso_real( luaL_checknumber( L, 1 ), SET_LATER);
599  return 0;
600}
601
602static int luaCB_set_led( lua_State* L )
603{
604  int to, to1, to2;
605  to = luaL_checknumber( L, 1 );
606  to1 = luaL_checknumber( L, 2 );
607  to2 = 200;
608  if( lua_isnumber( L, 3 ) )
609    to2 = lua_tonumber( L, 3 );
610  camera_set_led(to, to1, to2);
611  return 0;
612}
613
614static int luaCB_set_nd_filter( lua_State* L )
615{
616  shooting_set_nd_filter_state( luaL_checknumber( L, 1 ), SET_LATER);
617  return 0;
618}
619
620/*
621set_prop(id,value)
622the value is treated as a short
623*/
624static int luaCB_set_prop( lua_State* L )
625{
626  shooting_set_prop(luaL_checknumber( L, 1 ), luaL_checknumber( L, 2 ));
627  return 0;
628}
629
630/*
631status=set_prop_str(prop_id,value)
632set propertycase value as a string. Length is taken from the string
633numeric propcase values may be assembled by setting byte values using string.char or the binstr module
634status: boolean - true if the underlying propcase call returns 0, otherwise false
635*/
636static int luaCB_set_prop_str( lua_State *L ) {
637    int prop_id;
638    unsigned len;
639    const char *str;
640    prop_id = luaL_checknumber( L, 1 );
641    str = luaL_checklstring( L, 2, &len );
642    if(str && len > 0) {
643        lua_pushboolean( L, (set_property_case(prop_id,(void *)str,len) == 0));
644    } else {
645        return luaL_error( L, "invalid value");
646    }
647    return 1;
648}
649
650static int luaCB_set_raw_nr( lua_State* L )
651{
652  camera_set_nr(luaL_checknumber( L, 1 ));
653  return 0;
654}
655
656static int luaCB_get_raw_nr( lua_State* L )
657{
658  lua_pushnumber( L, camera_get_nr() );
659  return 1;
660}
661
662static int luaCB_set_raw( lua_State* L )
663{
664  camera_set_raw(luaL_checknumber( L, 1 ));
665  return 0;
666}
667
668static int luaCB_get_raw( lua_State* L )
669{
670  lua_pushnumber( L, conf.save_raw );
671  return 1;
672}
673
674static int luaCB_set_sv96( lua_State* L )
675{
676  shooting_set_sv96(luaL_checknumber( L, 1 ), SET_LATER);
677  return 0;
678}
679
680static int luaCB_set_tv96_direct( lua_State* L )
681{
682  shooting_set_tv96_direct(luaL_checknumber( L, 1 ), SET_LATER);
683  return 0;
684}
685
686static int luaCB_set_tv96( lua_State* L )
687{
688  shooting_set_tv96(luaL_checknumber( L, 1 ), SET_LATER);
689  return 0;
690}
691
692static int luaCB_set_user_av_by_id_rel( lua_State* L )
693{
694  shooting_set_user_av_by_id_rel(luaL_checknumber( L, 1 ));
695  return 0;
696}
697
698static int luaCB_set_user_av_by_id( lua_State* L )
699{
700  shooting_set_user_av_by_id(luaL_checknumber( L, 1 ));
701  return 0;
702}
703
704static int luaCB_set_user_av96( lua_State* L )
705{
706  shooting_set_user_av96(luaL_checknumber( L, 1 ));
707  return 0;
708}
709
710static int luaCB_set_user_tv_by_id_rel( lua_State* L )
711{
712  shooting_set_user_tv_by_id_rel(luaL_checknumber( L, 1 ));
713  return 0;
714}
715
716static int luaCB_set_user_tv_by_id( lua_State* L )
717{
718  shooting_set_user_tv_by_id(luaL_checknumber( L, 1 ));
719  return 0;
720}
721
722static int luaCB_set_user_tv96( lua_State* L )
723{
724  shooting_set_user_tv96(luaL_checknumber( L, 1 ));
725  return 0;
726}
727
728static int luaCB_set_zoom_speed( lua_State* L )
729{
730  shooting_set_zoom_speed(luaL_checknumber( L, 1 ));
731  return 0;
732}
733
734static int luaCB_set_zoom_rel( lua_State* L )
735{
736  shooting_set_zoom_rel(luaL_checknumber( L, 1 ));
737  return 0;
738}
739
740static int luaCB_set_zoom( lua_State* L )
741{
742  shooting_set_zoom(luaL_checknumber( L, 1 ));
743  return 0;
744}
745
746static int luaCB_wait_click( lua_State* L )
747{
748  int timeout = luaL_optnumber( L, 1, 0 );
749  action_wait_for_click(timeout);
750  return lua_yield( L, 0 );
751}
752
753static int luaCB_is_pressed( lua_State* L )
754{
755  lua_pushboolean( L, script_key_is_pressed(lua_get_key_arg( L, 1 )));
756  return 1;
757}
758
759static int luaCB_is_key( lua_State* L )
760{
761  lua_pushboolean( L, script_key_is_clicked(lua_get_key_arg( L, 1 )));
762  return 1;
763}
764
765#if CAM_HAS_JOGDIAL
766static int luaCB_wheel_right( lua_State* L )
767{
768  JogDial_CW();
769  return 0;
770}
771
772static int luaCB_wheel_left( lua_State* L )
773{
774  JogDial_CCW();
775  return 0;
776}
777#endif
778
779static int luaCB_md_get_cell_diff( lua_State* L )
780{
781  lua_pushnumber( L, md_get_cell_diff(luaL_checknumber(L,1),
782                                      luaL_checknumber(L,2)));
783  return 1;
784}
785
786static int luaCB_md_detect_motion( lua_State* L )
787{
788  int columns = (luaL_optnumber(L,1,6));
789  int rows = (luaL_optnumber(L,2,4));
790  int pixel_measure_mode = (luaL_optnumber(L,3,1));
791  int detection_timeout = (luaL_optnumber(L,4,10000));
792  int measure_interval = (luaL_optnumber(L,5,7));
793  int threshold = (luaL_optnumber(L,6,10));
794  int draw_grid = (luaL_optnumber(L,7,1));
795   // arg 8 is the return value in ubasic. We
796   // ignore it here. - AUJ
797  int clipping_region_mode = (luaL_optnumber(L,9,0));
798  int clipping_region_column1 = (luaL_optnumber(L,10,0));
799  int clipping_region_row1 = (luaL_optnumber(L,11,0));
800  int clipping_region_column2 = (luaL_optnumber(L,12,0));
801  int clipping_region_row2 = (luaL_optnumber(L,13,0));
802  int parameters = (luaL_optnumber(L,14,1));
803  int pixels_step = (luaL_optnumber(L,15,6));
804  int msecs_before_trigger = (luaL_optnumber(L,16,0));
805  if(md_init_motion_detector(
806    columns, rows, pixel_measure_mode, detection_timeout,
807    measure_interval, threshold, draw_grid,
808    clipping_region_mode,
809    clipping_region_column1, clipping_region_row1,
810    clipping_region_column2, clipping_region_row2,
811    parameters, pixels_step, msecs_before_trigger
812  ))
813    return lua_yield(L, 0);
814  else
815    return luaL_error( L, "md_init_motion_detector failed" );
816}
817
818static void file_browser_selected(const char *fn) {
819    // Reconnect button input to script - will also signal action stack
820    // that file browser is finished and return last selected file
821    // to script caller
822    state_kbd_script_run = 1;
823    // Clear the Func/Set key so that when the script exits, pressing
824    // the Func/Set key again will enter the Script menu, not the File Browser
825    kbd_reset_autoclicked_key();
826
827        lua_pushstring( Lt, (fn && fn[0])? fn : NULL );
828
829}
830
831static int luaCB_file_browser( lua_State* L ) {
832    // Disconnect button input from script so buttons will work in file browser
833    state_kbd_script_run = 0;
834    // Push file browser action onto stack - will loop doing nothing until file browser exits
835    action_push(AS_FILE_BROWSER);
836    // Switch to file browser gui mode. Path can be supplied in call or defaults to "A" (root directory).
837    module_fselect_init(LANG_STR_FILE_BROWSER, luaL_optstring( L, 1, "A" ), "A", file_browser_selected);
838    // Yield the script so that the action stack will process the AS_FILE_BROWSER action
839    return lua_yield(L, 0);
840}
841
842unsigned char script_colors[][2]  = {
843
844#ifdef CAM_USE_COLORED_ICONS
845                                        {COLOR_TRANSPARENT,         COLOR_TRANSPARENT},         //  1   trans
846                                        {COLOR_BLACK,               COLOR_BLACK},               //  2   black
847                                        {COLOR_WHITE,               COLOR_WHITE},               //  3   white
848                                       
849                                        {COLOR_ICON_PLY_RED,        COLOR_ICON_REC_RED},        //  4   red
850                                        {COLOR_ICON_PLY_RED_DK,     COLOR_ICON_REC_RED_DK},     //  5   red_dark
851                                        {COLOR_ICON_PLY_RED_LT,     COLOR_ICON_REC_RED_LT},     //  6   red_light
852                                        {COLOR_ICON_PLY_GREEN,      COLOR_ICON_REC_GREEN},      //  7   green
853                                        {COLOR_ICON_PLY_GREEN_DK,   COLOR_ICON_REC_GREEN_DK},   //  8   green_dark
854                                        {COLOR_ICON_PLY_GREEN_LT,   COLOR_ICON_REC_GREEN_LT},   //  9   green_light
855                                        {COLOR_HISTO_B_PLAY,        COLOR_HISTO_B},             //  10  blue
856                                        {COLOR_HISTO_B_PLAY,        COLOR_HISTO_B},             //  11  blue_dark   - placeholder
857                                        {COLOR_HISTO_B_PLAY,        COLOR_HISTO_B},             //  12  blue_light  - placeholder
858
859                                        {COLOR_ICON_PLY_GREY,       COLOR_ICON_REC_GREY},       //  13  grey
860                                        {COLOR_ICON_PLY_GREY_DK,    COLOR_ICON_REC_GREY_DK},    //  14  grey_dark
861                                        {COLOR_ICON_PLY_GREY_LT,    COLOR_ICON_REC_GREY_LT},    //  15  grey_light
862
863                                        {COLOR_ICON_PLY_YELLOW,     COLOR_ICON_REC_YELLOW},     //  16  yellow
864                                        {COLOR_ICON_PLY_YELLOW_DK,  COLOR_ICON_REC_YELLOW_DK},  //  17  yellow_dark
865                                        {COLOR_ICON_PLY_YELLOW_LT,  COLOR_ICON_REC_YELLOW_LT}   //  18  yellow_light
866#else
867                                        {COLOR_TRANSPARENT,         COLOR_TRANSPARENT},         //  1   trans
868                                        {COLOR_BLACK,               COLOR_BLACK},               //  2   black
869                                        {COLOR_WHITE,               COLOR_WHITE},               //  3   white
870                                       
871                                        {COLOR_HISTO_R_PLAY,        COLOR_HISTO_R},             //  4   red
872                                        {COLOR_HISTO_R_PLAY,        COLOR_HISTO_R},             //  5   red_dark    - placeholder
873                                        {COLOR_HISTO_R_PLAY,        COLOR_HISTO_R},             //  6   red_light   - placeholder
874                                        {COLOR_HISTO_G_PLAY,        COLOR_HISTO_G},             //  7   green
875                                        {COLOR_HISTO_G_PLAY,        COLOR_HISTO_G},             //  8   green_dark  - placeholder
876                                        {COLOR_HISTO_G_PLAY,        COLOR_HISTO_G},             //  9   green_light - placeholder
877                                        {COLOR_HISTO_B_PLAY,        COLOR_HISTO_B},             //  10  blue
878                                        {COLOR_HISTO_B_PLAY,        COLOR_HISTO_B},             //  11  blue_dark   - placeholder
879                                        {COLOR_HISTO_B_PLAY,        COLOR_HISTO_B},             //  12  blue_light  - placeholder
880
881                                        {COLOR_BLACK,               COLOR_BLACK},                           //  13  grey        - placeholder (there's no universal grey)
882                                        {COLOR_BLACK,               COLOR_BLACK},                           //  14  grey_dark   - placeholder (there's no universal grey)
883                                        {COLOR_WHITE,               COLOR_WHITE},               //  15  grey_light  - placeholder (there's no universal grey)
884
885                                        {COLOR_WHITE,               COLOR_WHITE},               //  16  yellow      - placeholder
886                                        {COLOR_WHITE,               COLOR_WHITE},               //  17  yellow_dark - placeholder
887                                        {COLOR_WHITE,               COLOR_WHITE}                //  18  yellow_light- placeholder
888#endif
889                                    };
890
891static int get_color(int cl) {
892    char out=0;                     //defaults to 0 if any wrong number
893
894    if (cl<256)
895        out=cl;
896    else {
897        if (cl-256<sizeof(script_colors)) {
898            if((mode_get()&MODE_MASK) == MODE_REC)
899                out=script_colors[cl-256][1];
900            else
901                out=script_colors[cl-256][0];
902        }
903    }
904    return out;
905}
906
907static int luaCB_draw_pixel( lua_State* L ) {
908  coord x1=luaL_checknumber(L,1);
909  coord y1=luaL_checknumber(L,2);
910  color cl=get_color(luaL_checknumber(L,3));
911  draw_pixel(x1,y1,cl);
912  return 1;
913}
914
915static int luaCB_draw_line( lua_State* L ) {
916  coord x1=luaL_checknumber(L,1);
917  coord y1=luaL_checknumber(L,2);
918  coord x2=luaL_checknumber(L,3);
919  coord y2=luaL_checknumber(L,4);
920  color cl=get_color(luaL_checknumber(L,5));
921  draw_line(x1,y1,x2,y2,cl);
922  return 1;
923}
924
925static int luaCB_draw_rect( lua_State* L ) {
926  coord x1=luaL_checknumber(L,1);
927  coord y1=luaL_checknumber(L,2);
928  coord x2=luaL_checknumber(L,3);
929  coord y2=luaL_checknumber(L,4);
930  color cl=get_color(luaL_checknumber(L,5));
931  int   th=luaL_optnumber(L,6,1);
932  draw_rect_thick(x1,y1,x2,y2,cl,th);
933  return 1;
934}
935
936static int luaCB_draw_rect_filled( lua_State* L ) {
937  coord x1 =luaL_checknumber(L,1);
938  coord y1 =luaL_checknumber(L,2);
939  coord x2 =luaL_checknumber(L,3);
940  coord y2 =luaL_checknumber(L,4);
941  color clf=get_color(luaL_checknumber(L,5));
942  color clb=get_color(luaL_checknumber(L,6));
943  int   th =luaL_optnumber(L,7,1);
944  clf=256*clb+clf;
945  draw_filled_rect_thick(x1,y1,x2,y2,clf,th);
946  return 1;
947}
948
949static int luaCB_draw_ellipse( lua_State* L ) {
950  coord x1=luaL_checknumber(L,1);
951  coord y1=luaL_checknumber(L,2);
952  coord a=luaL_checknumber(L,3);
953  coord b=luaL_checknumber(L,4);
954  color cl=get_color(luaL_checknumber(L,5));
955  draw_ellipse(x1,y1,a,b,cl);
956  return 1;
957}
958
959static int luaCB_draw_ellipse_filled( lua_State* L ) {
960  coord x1=luaL_checknumber(L,1);
961  coord y1=luaL_checknumber(L,2);
962  coord a=luaL_checknumber(L,3);
963  coord b=luaL_checknumber(L,4);
964  color cl=256*get_color(luaL_checknumber(L,5));
965  draw_filled_ellipse(x1,y1,a,b,cl);
966  return 1;
967}
968
969static int luaCB_draw_string( lua_State* L ) {
970  coord x1=luaL_checknumber(L,1);
971  coord y1=luaL_checknumber(L,2);
972  const char *t = luaL_checkstring( L, 3 );
973  color clf=get_color(luaL_checknumber(L,4));
974  color clb=get_color(luaL_checknumber(L,5));
975  clf=256*clb+clf;
976  draw_string(x1,y1,t,clf);
977  return 1;
978}
979
980static int luaCB_draw_clear( lua_State* L ) {
981  draw_restore();
982  return 1;
983}
984
985static int luaCB_autostarted( lua_State* L )
986{
987  lua_pushboolean( L, camera_get_script_autostart() );
988  return 1;
989}
990
991static int luaCB_get_autostart( lua_State* L )
992{
993  lua_pushnumber( L, conf.script_startup );
994  return 1;
995}
996
997static int luaCB_set_autostart( lua_State* L )
998{
999  int to;
1000  to = luaL_checknumber( L, 1 );
1001  if ( to >= 0 && to <= 2 ) conf.script_startup = to;
1002  conf_save();
1003  return 0;
1004}
1005
1006static int luaCB_get_usb_power( lua_State* L )
1007{
1008  if (luaL_optnumber( L, 1, 0 )) lua_pushnumber( L, get_usb_power(1) );
1009  else lua_pushnumber( L, get_usb_power(0) );
1010  return 1;
1011}
1012
1013static int luaCB_exit_alt( lua_State* L )
1014{
1015  exit_alt();
1016  return 0;
1017}
1018
1019// optional parameter is 0 for soft shutdown (default) or 1 for hard/immediate
1020static int luaCB_shut_down( lua_State* L )
1021{
1022  if ( luaL_optnumber(L,1,0) == 1 )
1023  {
1024    shutdown();
1025  } else {
1026  camera_shutdown_in_a_second();
1027  }
1028  return 0;
1029}
1030
1031static int luaCB_print_screen( lua_State* L )
1032{
1033 
1034  if (lua_isboolean( L, 1 ))
1035    script_print_screen_statement( lua_toboolean( L, 1 ) );
1036  else
1037    script_print_screen_statement( luaL_checknumber( L, 1 )+10000 );
1038  return 0;
1039}
1040
1041static int luaCB_get_movie_status( lua_State* L )
1042{
1043  lua_pushnumber( L, movie_status );
1044  return 1;
1045}
1046
1047static int luaCB_set_movie_status( lua_State* L )
1048{
1049  int to;
1050  switch(luaL_checknumber( L, 1 )) {
1051    case 1:
1052      if (movie_status == 4) {
1053        movie_status = 1;
1054      }
1055    break;
1056    case 2:
1057      if (movie_status == 1) {
1058        movie_status = 4;
1059      }
1060    break;
1061    case 3:
1062      if (movie_status == 1 || movie_status == 4) {
1063        movie_status = 5;
1064      }
1065    break;
1066  }
1067  return 0;
1068}
1069
1070static int luaCB_get_drive_mode( lua_State* L )
1071{
1072  lua_pushnumber( L, shooting_get_drive_mode() );
1073  return 1;
1074}
1075
1076static int luaCB_get_focus_mode( lua_State* L )
1077{
1078  lua_pushnumber( L, shooting_get_prop(PROPCASE_FOCUS_MODE) );
1079  return 1;
1080}
1081
1082static int luaCB_get_flash_mode( lua_State* L )
1083{
1084  lua_pushnumber( L, shooting_get_prop(PROPCASE_FLASH_MODE) );
1085  return 1;
1086}
1087
1088static int luaCB_get_shooting( lua_State* L )
1089{
1090  lua_pushboolean( L, shooting_get_prop(PROPCASE_SHOOTING) );
1091  return 1;
1092}
1093
1094static int luaCB_get_flash_ready( lua_State* L )
1095{
1096  lua_pushboolean( L, shooting_get_prop(PROPCASE_IS_FLASH_READY) );
1097  return 1;
1098}
1099
1100static int luaCB_get_IS_mode( lua_State* L )
1101{
1102  lua_pushnumber( L, shooting_get_prop(PROPCASE_IS_MODE) );
1103  return 1;
1104}
1105
1106static int luaCB_get_orientation_sensor( lua_State* L )
1107{
1108  lua_pushnumber( L, shooting_get_prop(PROPCASE_ORIENTATION_SENSOR) );
1109  return 1;
1110}
1111
1112static int luaCB_get_zoom_steps( lua_State* L )
1113{
1114  lua_pushnumber( L, zoom_points );
1115  return 1;
1116}
1117
1118static int luaCB_get_nd_present( lua_State* L )
1119{
1120  int to;
1121  #if !CAM_HAS_ND_FILTER
1122  to = 0;
1123  #endif
1124  #if CAM_HAS_ND_FILTER && !CAM_HAS_IRIS_DIAPHRAGM
1125  to = 1;
1126  #endif
1127  #if CAM_HAS_ND_FILTER && CAM_HAS_IRIS_DIAPHRAGM
1128  to = 2;
1129  #endif
1130  lua_pushnumber( L, to );
1131  return 1;
1132}
1133
1134static int luaCB_get_propset( lua_State* L )
1135{
1136  lua_pushnumber( L, CAM_PROPSET );
1137  return 1;
1138}
1139
1140static int luaCB_get_ev( lua_State* L )
1141{
1142  lua_pushnumber( L, shooting_get_prop(PROPCASE_EV_CORRECTION_1) );
1143  return 1;
1144}
1145
1146static int luaCB_set_ev( lua_State* L )
1147{
1148  int to;
1149  to = luaL_checknumber( L, 1 );
1150  shooting_set_prop(PROPCASE_EV_CORRECTION_1, to);
1151  shooting_set_prop(PROPCASE_EV_CORRECTION_2, to);
1152  return 0;
1153}
1154
1155static int luaCB_get_histo_range( lua_State* L )
1156{
1157  int from = (luaL_checknumber(L,1));
1158  int to = (luaL_checknumber(L,2));
1159  if (shot_histogram_isenabled()) lua_pushnumber( L, shot_histogram_get_range(from, to) );
1160  else lua_pushnumber( L, -1 ); // TODO should probably return nil
1161  return 1;
1162}
1163
1164static int luaCB_shot_histo_enable( lua_State* L )
1165{
1166  shot_histogram_set(luaL_checknumber( L, 1 ));
1167  return 0;
1168}
1169
1170static int luaCB_play_sound( lua_State* L )
1171{
1172  play_sound(luaL_checknumber( L, 1 ));
1173  return 0;
1174}
1175
1176static int luaCB_get_temperature( lua_State* L )
1177{
1178  int which = (luaL_checknumber( L, 1 ));
1179  int temp = -100; // do something insane if users passes bad value
1180  switch (which)
1181  {
1182    case 0:
1183      temp = get_optical_temp();
1184      break;
1185    case 1:
1186      temp = get_ccd_temp();
1187      break;
1188    case 2:
1189      temp = get_battery_temp();
1190      break;
1191  }
1192  lua_pushnumber( L, temp );
1193  return 1;
1194}
1195
1196static int luaCB_get_time( lua_State* L )
1197{
1198  int r = -1;
1199  unsigned long t2 = time(NULL);
1200  static struct tm *ttm;
1201  ttm = localtime(&t2);
1202  const char *t = luaL_checkstring( L, 1 );
1203  if (strncmp("s", t, 1)==0) r = ( L, ttm->tm_sec );
1204  else if (strncmp("m", t, 1)==0) r = ( L, ttm->tm_min );
1205  else if (strncmp("h", t, 1)==0) r = ( L, ttm->tm_hour );
1206  else if (strncmp("D", t, 1)==0) r = ( L, ttm->tm_mday );
1207  else if (strncmp("M", t, 1)==0) r = ( L, ttm->tm_mon+1 );
1208  else if (strncmp("Y", t, 1)==0) r = ( L, 1900+ttm->tm_year );
1209  lua_pushnumber( L, r );
1210  return 1;
1211}
1212
1213/*
1214  val=peek(address[,size])
1215  return the value found at address in memory, or nil if address or size is invalid
1216  size is optional 1=byte 2=halfword 4=word. defaults is 4
1217*/
1218static int luaCB_peek( lua_State* L )
1219{
1220  unsigned addr = luaL_checknumber(L,1);
1221  unsigned size = luaL_optnumber(L, 2, 4);
1222  switch(size) {
1223    case 1:
1224      lua_pushnumber( L, *(unsigned char *)(addr) );
1225    break;
1226    case 2:
1227      if (addr & 0x1) {
1228        lua_pushnil(L);
1229      }
1230      else {
1231        lua_pushnumber( L, *(unsigned short *)(addr) );
1232      }
1233    break;
1234    case 4:
1235      if (addr & 0x3) {
1236        lua_pushnil(L);
1237      }
1238      else {
1239        lua_pushnumber( L, *(unsigned *)(addr) );
1240      }
1241    break;
1242    default:
1243      lua_pushnil(L);
1244
1245  }
1246  return 1;
1247}
1248
1249/*
1250  status=poke(address,value[,size])
1251  writes value to address in memory
1252  size is optional 1=byte 2=halfword 4=word. defaults is 4
1253  returns true, or nil if address or size is invalid
1254*/
1255static int luaCB_poke( lua_State* L )
1256{
1257  unsigned addr = luaL_checknumber(L,1);
1258  unsigned val = luaL_checknumber(L,2);
1259  unsigned size = luaL_optnumber(L, 3, 4);
1260  int status = 0;
1261  switch(size) {
1262    case 1:
1263        *(unsigned char *)(addr) = (unsigned char)val;
1264        status=1;
1265    break;
1266    case 2:
1267      if (!(addr & 0x1)) {
1268        *(unsigned short *)(addr) = (unsigned short)val;
1269        status=1;
1270      }
1271    break;
1272    case 4:
1273      if (!(addr & 0x3)) {
1274        *(unsigned *)(addr) = val;
1275        status=1;
1276      }
1277    break;
1278  }
1279  if(status) {
1280    lua_pushboolean(L,1);
1281  }
1282  else {
1283    lua_pushnil(L);
1284  }
1285  return 1;
1286}
1287
1288static int luaCB_bitand( lua_State* L )
1289{
1290  int v1 = (luaL_checknumber(L,1));
1291  int v2 = (luaL_checknumber(L,2));
1292  lua_pushnumber( L, v1 & v2 );
1293  return 1;
1294}
1295
1296static int luaCB_bitor( lua_State* L )
1297{
1298  int v1 = (luaL_checknumber(L,1));
1299  int v2 = (luaL_checknumber(L,2));
1300  lua_pushnumber( L, v1 | v2 );
1301  return 1;
1302}
1303
1304static int luaCB_bitxor( lua_State* L )
1305{
1306  int v1 = (luaL_checknumber(L,1));
1307  int v2 = (luaL_checknumber(L,2));
1308  lua_pushnumber( L, v1 ^ v2 );
1309  return 1;
1310}
1311
1312static int luaCB_bitshl( lua_State* L )
1313{
1314  int val = (luaL_checknumber(L,1));
1315  unsigned shift = (luaL_checknumber(L,2));
1316  lua_pushnumber( L, val << shift );
1317  return 1;
1318}
1319
1320static int luaCB_bitshri( lua_State* L )
1321{
1322  int val = (luaL_checknumber(L,1));
1323  unsigned shift = (luaL_checknumber(L,2));
1324  lua_pushnumber( L, val >> shift );
1325  return 1;
1326}
1327
1328static int luaCB_bitshru( lua_State* L )
1329{
1330  unsigned val = (luaL_checknumber(L,1));
1331  unsigned shift = (luaL_checknumber(L,2));
1332  lua_pushnumber( L, val >> shift );
1333  return 1;
1334}
1335
1336static int luaCB_bitnot( lua_State* L )
1337{
1338  unsigned val = (luaL_checknumber(L,1));
1339  lua_pushnumber( L, ~val );
1340  return 1;
1341}
1342
1343static void set_string_field(lua_State* L, const char *key, const char *val)
1344{
1345  lua_pushstring(L, val);
1346  lua_setfield(L, -2, key);
1347}
1348
1349static void set_number_field(lua_State* L, const char *key, int val)
1350{
1351  lua_pushnumber(L, val);
1352  lua_setfield(L, -2, key);
1353}
1354
1355static int luaCB_get_buildinfo( lua_State* L )
1356{
1357  lua_createtable(L, 0, 8);
1358  set_string_field( L,"platform", PLATFORM );
1359  set_string_field( L,"platsub", PLATFORMSUB );
1360  set_string_field( L,"version", HDK_VERSION );
1361  set_string_field( L,"build_number", BUILD_NUMBER );
1362  set_string_field( L,"build_date", __DATE__ );
1363  set_string_field( L,"build_time", __TIME__ );
1364#ifndef CAM_DRYOS
1365  set_string_field( L,"os", "vxworks" );
1366#else
1367  set_string_field( L,"os", "dryos" );
1368#endif
1369  set_number_field( L, "platformid", PLATFORMID );
1370  return 1;
1371}
1372
1373static int luaCB_get_mode( lua_State* L )
1374{
1375  int m = mode_get();
1376  lua_pushboolean( L, (m&MODE_MASK) != MODE_PLAY );
1377  lua_pushboolean( L, MODE_IS_VIDEO(m) );
1378  lua_pushnumber( L, m );
1379  return 3;
1380}
1381
1382// TODO sanity check file ?
1383static int luaCB_set_raw_develop( lua_State* L )
1384{
1385  raw_prepare_develop(luaL_optstring( L, 1, NULL ));
1386  return 0;
1387}
1388
1389static int luaCB_raw_merge_start( lua_State* L )
1390{
1391  int op = luaL_checknumber(L,1);
1392  if (!module_rawop_load())
1393    return luaL_argerror(L,1,"fail to load raw merge module");
1394
1395  if ( API_VERSION_MATCH_REQUIREMENT( librawop->version, 1, 0 ) &&
1396       (op == RAW_OPERATION_SUM || op == RAW_OPERATION_AVERAGE) ) {
1397    librawop->raw_merge_start(op);
1398  }
1399  else {
1400    return luaL_argerror(L,1,"invalid raw merge op");
1401  }
1402  return 0;
1403}
1404
1405// TODO sanity check file ?
1406static int luaCB_raw_merge_add_file( lua_State* L )
1407{
1408  if (!module_rawop_load())
1409    return luaL_argerror(L,1,"fail to load raw merge module");
1410  librawop->raw_merge_add_file(luaL_checkstring( L, 1 ));
1411  return 0;
1412}
1413
1414static int luaCB_raw_merge_end( lua_State* L )
1415{
1416  if (!module_rawop_load())
1417    return luaL_argerror(L,1,"fail to load raw merge module");
1418  librawop->raw_merge_end();
1419  return 0;
1420}
1421
1422// Enable/disable LCD back light (input argument 1/0)
1423static int luaCB_set_backlight( lua_State* L )
1424{
1425  int val = (luaL_checknumber(L,1));
1426
1427  if (val > 0) TurnOnBackLight();
1428  else TurnOffBackLight();
1429  return 0;
1430}
1431
1432// get the string or number passed in index and return it as an event id
1433static unsigned levent_id_from_lua_arg( lua_State* L, int index)
1434{
1435  unsigned event_id;
1436  if (lua_type(L, index) == LUA_TSTRING) {
1437    const char *ev_name = lua_tostring(L, index);
1438        event_id = levent_id_for_name(ev_name);
1439    if (event_id == 0) {
1440        return luaL_error( L, "bad event name '%s'", ev_name );
1441    }
1442  }
1443  // could check here if it is in the table, but even valid ones can crash
1444  // so we avoid searching the table if given a number
1445  else if (lua_type(L,index) == LUA_TNUMBER){
1446        event_id = lua_tonumber(L,index);
1447  }
1448  else {
1449    return luaL_error( L, "expected event name or id" );
1450  }
1451  return event_id;
1452}
1453
1454/*
1455  get a value where boolean or 0/!0 are accepted for on/off.
1456  normal lua toboolean will convert 0 to true, but ubasic and c users
1457  will expect 0 to be off
1458  intentional HACK: numbers greater than 1 are returned as is
1459*/
1460static unsigned on_off_value_from_lua_arg( lua_State* L, int index)
1461{
1462  if( lua_isboolean(L,index) ) {
1463        return lua_toboolean(L,index);
1464  }
1465  else {
1466        return luaL_checknumber(L,index);
1467  }
1468}
1469
1470/*
1471  return the index of an event, given it's name or event id
1472*/
1473static unsigned levent_index_from_id_lua_arg( lua_State* L, int index )
1474{
1475  if (lua_type(L, index) == LUA_TSTRING) {
1476        return levent_index_for_name(lua_tostring(L, index));
1477  }
1478  else if (lua_type(L,index) == LUA_TNUMBER){
1479        return levent_index_for_id(lua_tonumber(L,index));
1480  }
1481  else {
1482    return luaL_error( L, "expected string or number" );
1483  }
1484}
1485
1486/*
1487  name,id,param = get_levent_def(event)
1488  event is an event id (number) or name (string)
1489  returns nil if event is not found
1490*/
1491static int luaCB_get_levent_def( lua_State* L )
1492{
1493  unsigned event_index = levent_index_from_id_lua_arg(L,1);
1494  if (event_index == LEVENT_INVALID_INDEX) {
1495    lua_pushnil(L);
1496    return 1;
1497  }
1498  lua_pushstring(L, levent_table[event_index].name);
1499  lua_pushnumber(L, levent_table[event_index].id);
1500  lua_pushnumber(L, levent_table[event_index].param);
1501  return 3;
1502}
1503
1504/*
1505  index=get_levent_index(event)
1506  event is an event id (number) or name (string)
1507  returns index or nil if not found
1508*/
1509static int luaCB_get_levent_index( lua_State* L )
1510{
1511  unsigned event_index = levent_index_from_id_lua_arg(L,1);
1512  if (event_index == LEVENT_INVALID_INDEX) {
1513    lua_pushnil(L);
1514  }
1515  else {
1516    lua_pushnumber(L, event_index);
1517  }
1518  return 1;
1519}
1520
1521/*
1522  name,id,param = get_levent_def_by_index(event_index)
1523  event_index is number index into the event table
1524  returns nil if event is not found
1525*/
1526static int luaCB_get_levent_def_by_index( lua_State* L )
1527{
1528  unsigned i = luaL_checknumber(L,1);
1529  if(i >= levent_count()) {
1530        lua_pushnil(L);
1531    return 1;
1532  }
1533  lua_pushstring(L, levent_table[i].name);
1534  lua_pushnumber(L, levent_table[i].id);
1535  lua_pushnumber(L, levent_table[i].param);
1536  return 3;
1537}
1538
1539/*
1540  post_levent_*(event[,unk])
1541  post the event with PostLogicalEventToUI or PostLogicaEventForNotPowerType
1542  This sends the event. The difference between functions isn't clear.
1543  event is an event id (number) or name (string).
1544  unk is an optional number whose meaning is unknown, defaults to zero.
1545    Based on code, other values would probably be a pointer.
1546        This is NOT the 3rd item in the event table.
1547*/
1548static int luaCB_post_levent_to_ui( lua_State* L )
1549{
1550  unsigned event_id,arg;
1551
1552  event_id = levent_id_from_lua_arg(L,1);
1553  arg = luaL_optnumber(L, 2, 0);
1554  PostLogicalEventToUI(event_id,arg);
1555  return 0;
1556}
1557
1558static int luaCB_post_levent_for_npt( lua_State* L )
1559{
1560  unsigned event_id,arg;
1561
1562  event_id = levent_id_from_lua_arg(L,1);
1563  arg = luaL_optnumber(L, 2, 0);
1564  PostLogicalEventForNotPowerType(event_id,arg);
1565  return 0;
1566}
1567
1568/*
1569  set_levent_active(event,state)
1570  event is an event id (number) or name (string)
1571  state is a numeric or boolean state. true or non zero numbers turn on zero, false or nil turn off
1572  exact meaning is unknown, but it has something to do with the delivery of the specified event.
1573*/
1574static int luaCB_set_levent_active( lua_State* L )
1575{
1576  unsigned event_id;
1577  unsigned state;
1578
1579  event_id = levent_id_from_lua_arg(L,1);
1580  state = on_off_value_from_lua_arg(L,2);
1581  SetLogicalEventActive(event_id,state);
1582  return 0;
1583}
1584
1585/*
1586  set_levent_script_mode(state)
1587  state is numeric or boolean state. true or non zero numbers turn on zero, false or nil turn off
1588  exact meaning is unknown, but it has something to do with the behavior of events and/or SetLogicalEventActive.
1589*/
1590static int luaCB_set_levent_script_mode( lua_State* L )
1591{
1592  SetScriptMode(on_off_value_from_lua_arg(L,1));
1593  return 0;
1594}
1595
1596/*
1597  result=set_capture_mode_canon(value)
1598  where value is a valid PROPCASE_SHOOTING_MODE value for the current camera
1599  result is true if the camera is in rec mode
1600*/
1601static int luaCB_set_capture_mode_canon( lua_State* L )
1602{
1603  int modenum = luaL_checknumber(L,1);
1604  // if the value as negative, assume it is a mistakenly sign extended PROPCASE_SHOOTING_MODE value
1605  if(modenum < 0)
1606    modenum &= 0xFFFF;
1607  lua_pushboolean( L, shooting_set_mode_canon(modenum) );
1608  return 1;
1609}
1610
1611/*
1612 result=set_capture_mode(modenum)
1613 where modenum is a valid CHDK modemap value
1614 result is true if modenum is a valid modemap value, otherwise false
1615*/
1616static int luaCB_set_capture_mode( lua_State* L )
1617{
1618  int modenum = luaL_checknumber(L,1);
1619  lua_pushboolean( L, shooting_set_mode_chdk(modenum) );
1620  return 1;
1621}
1622
1623/*
1624 result=is_capture_mode_valid(modenum)
1625 where modenum is a valid CHDK modemap value
1626 result is true if modenum is a valid modemap value, otherwise false
1627*/
1628static int luaCB_is_capture_mode_valid( lua_State* L )
1629{
1630  int modenum = luaL_checknumber(L,1);
1631  lua_pushboolean( L, shooting_mode_chdk2canon(modenum) != -1 );
1632  return 1;
1633}
1634
1635/*
1636  set_record(state)
1637  if state is 0 (or false) the camera is set to play mode. If 1 or true, the camera is set to record mode.
1638  NOTE: this only begins the mode change. Script should wait until get_mode() reflects the change,
1639  before doing anything that requires the new mode. e.g.
1640  set_record(true)
1641  while not get_mode() do
1642        sleep(10)
1643  end
1644*/
1645static int luaCB_set_record( lua_State* L )
1646{
1647  if(on_off_value_from_lua_arg(L,1)) {
1648    levent_set_record();
1649  }
1650  else {
1651    levent_set_play();
1652  }
1653  return 0;
1654}
1655
1656// switch mode (0 = playback, 1 = record)
1657// only for when USB is connected
1658static int luaCB_switch_mode_usb( lua_State* L )
1659{
1660  int mode = luaL_checknumber(L,1);
1661
1662  if ( mode != 0 && mode != 1 )
1663  {
1664    return 0;
1665  }
1666
1667  return switch_mode_usb(mode);
1668}
1669 
1670#ifdef CAM_CHDK_PTP
1671// PTP Live View functions
1672
1673// Function used to get viewport, bitmap and palette data via PTP
1674// Address of this function sent back to client program which then
1675// calls this with options to determine what to transfer
1676static int handle_video_transfer(ptp_data *data, int flags, int arg2)
1677{
1678    int total_size;             // Calculated total size of data to transfer to client
1679
1680    // Structure containing the info for the current live view frame
1681    // This information may change across calls
1682    struct {
1683        int vp_xoffset;             // Viewport X offset in pixels (for cameras with variable image size)
1684        int vp_yoffset;             // Viewpoer Y offset in pixels (for cameras with variable image size)
1685        int vp_width;               // Actual viewport width in pixels (for cameras with variable image size)
1686        int vp_height;              // Actual viewport height in pixels (for cameras with variable image size)
1687        int vp_buffer_start;        // Offset in data transferred where the viewport data starts
1688        int vp_buffer_size;         // Size of viewport data sent (in bytes)
1689        int bm_buffer_start;        // Offset in data transferred where the bitmap data starts
1690        int bm_buffer_size;         // Size of bitmap data sent (in bytes)
1691        int palette_type;           // Camera palette type
1692                                    // (0 = no palette, 1 = 16 x 4 byte AYUV values, 2 = 16 x 4 byte AYUV values with A = 0..3, 3 = 256 x 4 byte AYUV values with A = 0..3)
1693        int palette_buffer_start;   // Offset in data transferred where the palette data starts
1694        int palette_buffer_size;    // Size of palette data sent (in bytes)
1695    } vid_info;
1696
1697    // Populate the above structure with the current default details
1698    vid_info.vp_xoffset = vid_get_viewport_xoffset_proper();
1699    vid_info.vp_yoffset = vid_get_viewport_yoffset_proper();
1700    vid_info.vp_width = vid_get_viewport_width_proper();
1701    vid_info.vp_height = vid_get_viewport_height_proper();
1702    vid_info.vp_buffer_start = 0;
1703    vid_info.vp_buffer_size = 0;
1704    vid_info.bm_buffer_start = 0;
1705    vid_info.bm_buffer_size = 0;
1706    vid_info.palette_type = vid_get_palette_type();
1707    vid_info.palette_buffer_start = 0;
1708    vid_info.palette_buffer_size = 0;
1709
1710    total_size = sizeof(vid_info);
1711
1712    // Add viewport details if requested
1713    if ( flags & 0x1 ) // live buffer
1714    {
1715        vid_info.vp_buffer_start = total_size;
1716        vid_info.vp_buffer_size = (vid_get_viewport_buffer_width_proper()*vid_get_viewport_max_height()*6)/4;
1717        total_size += vid_info.vp_buffer_size;
1718    }
1719
1720    // Add bitmap details if requested
1721    if ( flags & 0x4 ) // bitmap buffer
1722    {
1723        vid_info.bm_buffer_start = total_size;
1724        vid_info.bm_buffer_size = camera_screen.buffer_width*camera_screen.height;
1725        total_size += vid_info.bm_buffer_size;
1726    }
1727
1728    // Add palette detals if requested
1729    if ( flags & 0x8 ) // bitmap palette
1730    {
1731        vid_info.palette_buffer_start = total_size;
1732        vid_info.palette_buffer_size = vid_get_palette_size();
1733        total_size += vid_info.palette_buffer_size;
1734    }
1735
1736    // Send header structure (along with total size to be sent)
1737    data->send_data(data->handle,(char*)&vid_info,sizeof(vid_info),total_size,0,0,0);
1738
1739    // Send viewport data if requested
1740    if ( flags & 0x1 )
1741    {
1742        data->send_data(data->handle,vid_get_viewport_active_buffer(),vid_info.vp_buffer_size,0,0,0,0);
1743    }
1744
1745    // Send bitmap data if requested
1746    if ( flags & 0x4 )
1747    {
1748        data->send_data(data->handle,vid_get_bitmap_active_buffer(),vid_info.bm_buffer_size,0,0,0,0);
1749    }
1750
1751    // Send palette data if requested
1752    if ( flags & 0x8 )
1753    {
1754        data->send_data(data->handle,vid_get_bitmap_active_palette(),vid_info.palette_buffer_size,0,0,0,0);
1755    }
1756
1757    return 0;
1758}
1759
1760// Lua function to return base info for PTP live view, including address of above transfer function
1761static int luaCB_get_video_details( lua_State* L )
1762{
1763    // Structure to popualate with live view details
1764    // These details are static and only need to be retrieved once
1765    struct {
1766        int transfer_function;      // Address of transfer function above
1767        int vp_max_width;           // Maximum viewport width (in pixels)
1768        int vp_max_height;          // Maximum viewport height (in pixels)
1769        int vp_buffer_width;        // Viewport buffer width in case buffer is wider than visible viewport (in pixels)
1770        int bm_max_width;           // Maximum width of bitmap (in pixels)
1771        int bm_max_height;          // Maximum height of bitmap (in pixels)
1772        int bm_buffer_width;        // Bitmap buffer width in case buffer is wider than visible bitmap (in pixels)
1773        int lcd_aspect_ratio;       // 0 = 4:3, 1 = 16:9
1774    } details;
1775
1776    // Populate structure info
1777    details.transfer_function = (int) handle_video_transfer;
1778    details.vp_max_width = vid_get_viewport_max_width();
1779    details.vp_max_height = vid_get_viewport_max_height();
1780    details.vp_buffer_width = vid_get_viewport_buffer_width_proper();
1781#if CAM_USES_ASPECT_CORRECTION
1782    details.bm_max_width = ASPECT_XCORRECTION(camera_screen.width);
1783#else
1784    details.bm_max_width = camera_screen.width;
1785#endif
1786    details.bm_max_height = camera_screen.height;
1787    details.bm_buffer_width = camera_screen.buffer_width;
1788    details.lcd_aspect_ratio = vid_get_aspect_ratio();
1789
1790    // Send data back to client
1791    lua_pushlstring( L, (char *) &details, sizeof(details) );
1792
1793    return 1;
1794}
1795#endif
1796
1797/*
1798pack the lua args into a buffer to pass to the native code calling functions
1799currently only handles strings/numbers
1800start is the stack index of the first arg
1801*/
1802#ifdef OPT_LUA_CALL_NATIVE
1803static int pack_native_args( lua_State* L, unsigned start, unsigned *argbuf)
1804{
1805  unsigned i;
1806  unsigned end = lua_gettop(L);
1807
1808  for(i = start; i <= end; i++,argbuf++) {
1809    if (lua_type(L, i) == LUA_TSTRING) {
1810        *argbuf=(unsigned)lua_tostring( L, i);
1811    }
1812    else if (lua_type(L, i) == LUA_TNUMBER) {
1813        *argbuf=lua_tonumber( L, i);
1814    }
1815    else {
1816      return 0;
1817    }
1818  }
1819  return 1;
1820}
1821
1822/*
1823Native function call interface. Can be used to call canon eventprocs or arbitrary
1824pointers.
1825
1826NOTE: this is preliminary, interface may change in later versions!
1827All arguments must be strings or numbers.
1828If the function expects to modify it's arguments via a pointer,
1829then you must provide a number that is a valid pointer.
1830
1831You can use the "AllocateMemory" eventproc to obtain buffers.
1832
1833If the function tries to write to a string passed from lua, Bad Things may happen.
1834
1835This is potentially dangerous, functions exist which can destroy the onboard firmware.
1836*/
1837
1838/*
1839result=call_func_ptr(ptr,...)
1840ptr: address of a valid ARM or Thumb function, which uses the normal C calling convention.
1841result: R0 value after the call returns
1842*/
1843static int luaCB_call_func_ptr( lua_State* L)
1844{
1845  unsigned *argbuf=NULL;
1846  unsigned i;
1847  unsigned n_args = lua_gettop(L)-1;
1848  void *fptr;
1849
1850  fptr=(void *)luaL_checknumber( L, 1 );
1851
1852  if (n_args) {
1853    argbuf=malloc(n_args * 4);
1854    if(!argbuf) {
1855      return luaL_error( L, "malloc fail" );
1856    }
1857    if(!pack_native_args(L, 2, argbuf)) {
1858      free(argbuf);
1859      return luaL_error( L, "expected string or number" );
1860    }
1861  }
1862 
1863  lua_pushnumber( L, call_func_ptr(fptr, argbuf, n_args) );
1864  free(argbuf);
1865  return 1;
1866}
1867
1868/*
1869Call an event procedure
1870
1871result=call_event_proc("EventprocName",...)
1872result is the value returned by ExecuteEventProcedure, which is -1 if the eventproc is not found,
1873or the eventproc return value (which could also be -1)
1874NOTE:
1875Many eventprocs are not registered by default, but can be loaded by calling another event proc
1876Some useful ones are
1877SystemEventInit
1878        includes AllocateMemory, FreeMemory, sprintf, memcpy, Fut functions, log ...
1879UI_RegistDebugEventProc
1880        includes capture mode functions, PTM_ functions and much more
1881RegisterProductTestEvent
1882        includes PT_ functions
1883
1884Others:
1885RegisterShootSeqEvent
1886RegisterNRTableEvent
1887*/
1888
1889// grab from lowlevel
1890extern unsigned _ExecuteEventProcedure(const char *name,...);
1891static int luaCB_call_event_proc( lua_State* L )
1892{
1893  const char *evpname;
1894  unsigned *argbuf;
1895  unsigned i;
1896  unsigned n_args = lua_gettop(L);
1897
1898  evpname=luaL_checkstring( L, 1 );
1899
1900  argbuf=malloc(n_args * 4);
1901  if (!argbuf) {
1902    return luaL_error( L, "malloc fail" );
1903  }
1904
1905  // event proc name is first arg
1906  *argbuf = (unsigned)evpname;
1907 
1908  if(!pack_native_args(L,2,argbuf+1)) {
1909    free(argbuf);
1910    return luaL_error( L, "expected string or number" );
1911  }
1912 
1913  lua_pushnumber( L, call_func_ptr(_ExecuteEventProcedure,argbuf,n_args) );
1914  free(argbuf);
1915  return 1;
1916}
1917
1918#endif // OPT_LUA_CALL_NATIVE
1919
1920/*
1921result = reboot(["filename"])
1922returns false on failure, does not return on success
1923see lib/armutil/reboot.c for details
1924*/
1925static int luaCB_reboot( lua_State* L )
1926{
1927        lua_pushboolean(L, reboot(luaL_optstring( L, 1, NULL )));
1928        return 1;
1929}
1930
1931static int luaCB_get_config_value( lua_State* L ) {
1932    unsigned int argc = lua_gettop(L);
1933    unsigned int id, i;
1934    int ret = 1;
1935    tConfigVal configVal;
1936   
1937    if( argc>=1 ) {
1938        id = luaL_checknumber(L, 1);
1939        switch( conf_getValue(id, &configVal) ) {
1940            case CONF_VALUE:
1941                lua_pushnumber(L, configVal.numb);
1942            break;
1943            case CONF_INT_PTR:
1944                lua_createtable(L, 0, configVal.numb);
1945                for( i=0; i<configVal.numb; i++ ) {
1946                    lua_pushinteger(L, configVal.pInt[i]);
1947                    lua_rawseti(L, -2, i+1);  //t[i+1]=configVal.pInt[i]
1948                }
1949            break;
1950            case CONF_CHAR_PTR:
1951                lua_pushstring(L, configVal.str);
1952            break;
1953            case CONF_OSD_POS_PTR:
1954                lua_pushnumber(L, configVal.pos.x);
1955                lua_pushnumber(L, configVal.pos.y); ret++;
1956            break;
1957            default:
1958                if( argc>=2) { //Default
1959                    ret = argc-1;
1960                } else {
1961                    lua_pushnil(L);
1962                }
1963            break;
1964        }
1965    } else {
1966        lua_pushnil(L);
1967    }
1968    return ret;
1969}
1970
1971static int luaCB_set_config_value( lua_State* L ) {
1972    unsigned int argc = lua_gettop(L);
1973    unsigned int id, i, j;
1974    tConfigVal configVal = {0,0,0,0};  //initialize isXXX
1975   
1976    if( argc>=2 ) {
1977        id = luaL_checknumber(L, 1);
1978        for( i=2; i<=argc; i++) {
1979            switch( lua_type(L, i) ) {
1980                case LUA_TNUMBER:
1981                    if( !configVal.isNumb ) {
1982                        configVal.numb = luaL_checknumber(L, i);
1983                        configVal.isNumb++;
1984                    }
1985                    switch( configVal.isPos ) {
1986                        case 0: configVal.pos.x = luaL_checknumber(L, i); configVal.isPos++; break;
1987                        case 1: configVal.pos.y = luaL_checknumber(L, i); configVal.isPos++; break;
1988                    }
1989                break;
1990                case LUA_TSTRING:
1991                    if( !configVal.isStr ) {
1992                        configVal.str = (char*)luaL_checkstring(L, i);
1993                        configVal.isStr++;
1994                    }
1995                break;
1996                case LUA_TTABLE:
1997                    if( !configVal.isPInt ) {
1998                        configVal.numb = lua_objlen(L, i);
1999                        if( configVal.pInt ) {
2000                            free(configVal.pInt);
2001                            configVal.pInt = NULL;
2002                        }
2003                        configVal.pInt = malloc(configVal.numb*sizeof(int));
2004                        if( configVal.pInt ) {
2005                            for( j=1; j<=configVal.numb; j++) {
2006                                lua_rawgeti(L, i, j);
2007                                configVal.pInt[j-1] = lua_tointeger(L, -1);
2008                                lua_pop(L, 1);
2009                            }
2010                        }
2011                        configVal.isPInt++;
2012                    }
2013                break;
2014            }
2015        }
2016        lua_pushboolean(L, conf_setValue(id, configVal));
2017        if( configVal.pInt ) {
2018            free(configVal.pInt);
2019            configVal.pInt = NULL;
2020        }
2021    } else lua_pushboolean(L, 0);
2022    return 1;
2023}
2024#ifdef CAM_CHDK_PTP
2025/*
2026msg = read_usb_msg([timeout])
2027read a message from the CHDK ptp interface.
2028Returns the next available message as a string, or nil if no messages are available
2029If timeout is given and not zero, wait until a message is available or timeout expires
2030*/
2031static int luaCB_read_usb_msg( lua_State* L )
2032{
2033  int timeout = luaL_optnumber( L, 1, 0 );
2034  if(timeout) {
2035    action_push(timeout);
2036    action_push(AS_SCRIPT_READ_USB_MSG);
2037    return lua_yield( L, 0 );
2038  }
2039  ptp_script_msg *msg = ptp_script_read_msg();
2040  if(msg) {
2041    lua_pushlstring(L,msg->data,msg->size);
2042    return 1;
2043  }
2044  lua_pushnil(L);
2045  return 1;
2046}
2047
2048/*
2049status = write_usb_msg(msg,[timeout])
2050writes a message to the CHDK ptp interface
2051msg may be nil, boolean, number, string or table (table has some restrictions, will be converted to string)
2052returns true if the message was queued successfully, otherwise false
2053if timeout is set and not zero, wait until message is written or timeout expires
2054NOTE strings will not include a terminating NULL, must be handled by recipient
2055*/
2056static int luaCB_write_usb_msg( lua_State* L )
2057{
2058  ptp_script_msg *msg;
2059  int timeout = luaL_optnumber( L, 2, 0 );
2060  // TODO would it be better to either ignore this or return nil ?
2061  // a write_usb_msg(function_which_returns_no_value()) is an error in this case
2062  // replacing with nil might be more luaish
2063  if(lua_gettop(L) < 1) {
2064    return luaL_error(L,"missing argument");
2065  }
2066  msg=lua_create_usb_msg(L,1,PTP_CHDK_S_MSGTYPE_USER);
2067  // for user messages, trying to create a message from an incompatible type throws an error
2068  if(msg->subtype == PTP_CHDK_TYPE_UNSUPPORTED) {
2069    free(msg);
2070    return luaL_error(L,"unsupported type");
2071  }
2072  if(!msg) {
2073    return luaL_error(L,"failed to create message");
2074  }
2075  if(timeout) {
2076    action_push(timeout);
2077    action_push((int)msg);
2078    action_push(AS_SCRIPT_WRITE_USB_MSG);
2079    return lua_yield( L, 0 );
2080  }
2081  lua_pushboolean(L,ptp_script_write_msg(msg));
2082  return 1;
2083}
2084#endif
2085
2086/* helper for meminfo to set table field only if valid */
2087static void set_meminfo_num( lua_State* L,const char *name, int val) {
2088    if(val != -1) {
2089        set_number_field( L, name, val );
2090    }
2091}
2092/*
2093meminfo=get_meminfo([heapname])
2094get camera memory information
2095heapname="system" or "exmem" if not given, meminfo is returned for heap used by CHDK for malloc
2096meminfo is false if the requested heapname isn't valid ("exmem" when exmem is not enabled, or unknown)
2097otherwise, a table of the form
2098meminfo = {
2099    name -- string "system" or "exmem"
2100    chdk_malloc -- bool, this is the heap used by CHDK for malloc
2101    chdk_start -- number, load address of CHDK
2102    chdk_size -- number, size of CHDK image
2103    -- all the following are numbers, will not be set if not available
2104    start_address
2105    end_address
2106    total_size
2107    allocated_size
2108    allocated_peak
2109    allocated_count
2110    free_size
2111    free_block_max_size
2112    free_block_count
2113}
2114NOTES
2115* under vxworks and cameras without GetMemInfo only the only valid fields
2116  for the system heap will be those defined by chdk and free_block_max_size
2117* the meaning of fields may not correspond exactly between exmem and system
2118*/
2119static int luaCB_get_meminfo( lua_State* L ) {
2120    // for memory info, duplicated from lowlevel
2121    extern const char _start,_end;
2122
2123#if defined(OPT_EXMEM_MALLOC) && !defined(OPT_EXMEM_TESTING)
2124    const char *default_heapname="exmem";
2125#else
2126    const char *default_heapname="system";
2127#endif
2128    const char *heapname = luaL_optstring( L, 1, default_heapname );
2129    cam_meminfo meminfo;
2130
2131    if(strcmp(heapname,"system") == 0) {
2132#if defined(CAM_FIRMWARE_MEMINFO)
2133        GetMemInfo(&meminfo);
2134#else
2135        memset(&meminfo,0xFF,sizeof(cam_meminfo));
2136        meminfo.free_block_max_size = core_get_free_memory();
2137#endif
2138    }
2139#if defined(OPT_EXMEM_MALLOC) && !defined(OPT_EXMEM_TESTING)
2140    else if(strcmp(heapname,"exmem") == 0) {
2141        GetExMemInfo(&meminfo);
2142        meminfo.allocated_count = -1; // not implemented in suba
2143    }
2144#endif
2145    else {
2146        lua_pushboolean(L,0);
2147        return 1;
2148    }
2149    // adjust start and size, if CHDK is loaded at heap start
2150    if(meminfo.start_address == (int)(&_start)) {
2151        meminfo.start_address += MEMISOSIZE;
2152        meminfo.total_size -= MEMISOSIZE;
2153    }
2154    lua_createtable(L, 0, 13); // might not always use 13, but doesn't hurt
2155    set_string_field( L,"name", heapname );
2156    lua_pushboolean( L, (strcmp(heapname,default_heapname)==0));
2157    lua_setfield(L, -2, "chdk_malloc");
2158    set_number_field( L, "chdk_start", (int)(&_start) );
2159    set_number_field( L, "chdk_size", MEMISOSIZE );
2160    set_meminfo_num( L, "start_address", meminfo.start_address );
2161    set_meminfo_num( L, "end_address", meminfo.end_address);
2162    set_meminfo_num( L, "total_size", meminfo.total_size);
2163    set_meminfo_num( L, "allocated_size", meminfo.allocated_size);
2164    set_meminfo_num( L, "allocated_peak", meminfo.allocated_peak);
2165    set_meminfo_num( L, "allocated_count", meminfo.allocated_count);
2166    set_meminfo_num( L, "free_size", meminfo.free_size);
2167    set_meminfo_num( L, "free_block_max_size", meminfo.free_block_max_size);
2168    set_meminfo_num( L, "free_block_count", meminfo.free_block_count);
2169    return 1;
2170}
2171
2172/*
2173set scheduling parameters
2174old_max_count,old_max_ms=set_yield(max_count,max_ms)
2175*/
2176static int luaCB_set_yield( lua_State* L )
2177{
2178  lua_pushnumber(L,yield_max_count);
2179  lua_pushnumber(L,yield_max_ms);
2180  yield_max_count = luaL_optnumber(L,1,YIELD_MAX_COUNT_DEFAULT);
2181  yield_max_ms = luaL_optnumber(L,2,YIELD_MAX_MS_DEFAULT);
2182  return 2;
2183}
2184
2185
2186static void register_func( lua_State* L, const char *name, void *func) {
2187  lua_pushcfunction( L, func );
2188  lua_setglobal( L, name );
2189}
2190
2191#define FUNC( X ) { #X, luaCB_##X },
2192static const luaL_Reg chdk_funcs[] = {
2193  FUNC(shoot)
2194  FUNC(sleep)
2195  FUNC(cls)
2196  FUNC(set_console_layout)
2197  FUNC(set_console_autoredraw)
2198  FUNC(console_redraw)
2199  FUNC(get_av96)
2200  FUNC(get_av96)
2201  FUNC(get_bv96)
2202  FUNC(get_day_seconds)
2203  FUNC(get_disk_size)
2204  FUNC(get_dof)
2205  FUNC(get_far_limit)
2206  FUNC(get_free_disk_space)
2207  FUNC(get_focus)
2208  FUNC(get_hyp_dist)
2209  FUNC(get_iso_market)
2210  FUNC(get_iso_mode)
2211  FUNC(get_iso_real)
2212  FUNC(get_jpg_count)
2213  FUNC(get_near_limit)
2214  FUNC(get_prop)
2215  FUNC(get_prop_str)
2216  FUNC(get_raw_count)
2217  FUNC(get_raw_nr)
2218  FUNC(get_raw)
2219  FUNC(get_sv96)
2220  FUNC(get_tick_count)
2221  FUNC(get_tv96)
2222  FUNC(get_user_av_id)
2223  FUNC(get_user_av96)
2224  FUNC(get_user_tv_id)
2225  FUNC(get_user_tv96)
2226  FUNC(get_vbatt)
2227  FUNC(get_zoom)
2228  FUNC(get_exp_count)
2229  FUNC(get_flash_params_count)
2230  FUNC(get_parameter_data)
2231
2232  FUNC(set_av96_direct)
2233  FUNC(set_av96)
2234  FUNC(set_focus)
2235  FUNC(set_iso_mode)
2236  FUNC(set_iso_real)
2237  FUNC(set_led)
2238  FUNC(set_nd_filter)
2239  FUNC(set_prop)
2240  FUNC(set_prop_str)
2241  FUNC(set_raw_nr)
2242  FUNC(set_raw)
2243  FUNC(set_sv96)
2244  FUNC(set_tv96_direct)
2245  FUNC(set_tv96)
2246  FUNC(set_user_av_by_id_rel)
2247  FUNC(set_user_av_by_id)
2248  FUNC(set_user_av96)
2249  FUNC(set_user_tv_by_id_rel)
2250  FUNC(set_user_tv_by_id)
2251  FUNC(set_user_tv96)
2252  FUNC(set_zoom_speed)
2253  FUNC(set_zoom_rel)
2254  FUNC(set_zoom)
2255
2256  FUNC(wait_click)
2257  FUNC(is_pressed)
2258  FUNC(is_key)
2259#ifdef CAM_HAS_JOGDIAL
2260  FUNC(wheel_right)
2261  FUNC(wheel_left)
2262#endif
2263  FUNC(md_get_cell_diff)
2264  FUNC(md_detect_motion)
2265  FUNC(autostarted)
2266  FUNC(get_autostart)
2267  FUNC(set_autostart)
2268  FUNC(get_usb_power)
2269  FUNC(exit_alt)
2270  FUNC(shut_down)
2271  FUNC(print_screen)
2272
2273  FUNC(get_focus_mode)
2274  FUNC(get_propset)
2275  FUNC(get_zoom_steps)
2276  FUNC(get_drive_mode)
2277  FUNC(get_flash_mode)
2278  FUNC(get_shooting)
2279  FUNC(get_flash_ready)
2280  FUNC(get_IS_mode)
2281  FUNC(set_ev)
2282  FUNC(get_ev)
2283  FUNC(get_orientation_sensor)
2284  FUNC(get_nd_present)
2285  FUNC(get_movie_status)
2286  FUNC(set_movie_status)
2287 
2288  FUNC(get_histo_range)
2289  FUNC(shot_histo_enable)
2290  FUNC(play_sound)
2291  FUNC(get_temperature)
2292  FUNC(peek)
2293  FUNC(poke)
2294  FUNC(bitand)
2295  FUNC(bitor)
2296  FUNC(bitxor)
2297  FUNC(bitshl)
2298  FUNC(bitshri)
2299  FUNC(bitshru)
2300  FUNC(bitnot)
2301
2302  FUNC(get_time)
2303
2304  FUNC(get_buildinfo)
2305  FUNC(get_mode)
2306 
2307  FUNC(set_raw_develop)
2308  // NOTE these functions normally run in the spytask.
2309  // called from lua they will run from kbd task instead
2310  FUNC(raw_merge_start)
2311  FUNC(raw_merge_add_file)
2312  FUNC(raw_merge_end)
2313  FUNC(set_backlight)
2314   FUNC(set_aflock)
2315#ifdef OPT_CURVES
2316   FUNC(set_curve_state)
2317#endif
2318// get levent definition by name or id, nil if not found
2319   FUNC(get_levent_def)
2320// get levent definition by index, nil if out of range
2321   FUNC(get_levent_def_by_index)
2322// get levent index from name or ID
2323   FUNC(get_levent_index)
2324   FUNC(post_levent_to_ui)
2325   FUNC(post_levent_for_npt)
2326   FUNC(set_levent_active)
2327   FUNC(set_levent_script_mode)
2328
2329   FUNC(set_capture_mode)
2330   FUNC(set_capture_mode_canon)
2331   FUNC(is_capture_mode_valid)
2332
2333   FUNC(set_record)
2334   FUNC(switch_mode_usb)
2335#ifdef CAM_CHDK_PTP
2336   FUNC(get_video_details)
2337#endif
2338
2339#ifdef OPT_LUA_CALL_NATIVE
2340   FUNC(call_event_proc)
2341   FUNC(call_func_ptr)
2342#endif
2343   FUNC(reboot)
2344   FUNC(get_config_value)
2345   FUNC(set_config_value)
2346#ifdef CAM_CHDK_PTP
2347   FUNC(read_usb_msg)
2348   FUNC(write_usb_msg)
2349#endif
2350   FUNC(get_meminfo)
2351
2352   FUNC(file_browser)
2353   
2354   FUNC(draw_pixel)
2355   FUNC(draw_line)
2356   FUNC(draw_rect)
2357   FUNC(draw_rect_filled)
2358   FUNC(draw_ellipse)
2359   FUNC(draw_ellipse_filled)
2360   FUNC(draw_clear)
2361   FUNC(draw_string)
2362
2363   FUNC(set_yield)
2364
2365  {NULL, NULL},
2366};
2367
2368void register_lua_funcs( lua_State* L )
2369{
2370  const luaL_reg *r;
2371  lua_pushlightuserdata( L, action_push_click );
2372  lua_pushcclosure( L, luaCB_keyfunc, 1 );
2373  lua_setglobal( L, "click" );
2374
2375  lua_pushlightuserdata( L, action_push_press );
2376  lua_pushcclosure( L, luaCB_keyfunc, 1 );
2377  lua_setglobal( L, "press" );
2378
2379  lua_pushlightuserdata( L, action_push_release );
2380  lua_pushcclosure( L, luaCB_keyfunc, 1 );
2381  lua_setglobal( L, "release" );
2382
2383  for(r=chdk_funcs;r->name;r++) {
2384    lua_pushcfunction( L, r->func );
2385    lua_setglobal( L, r->name );
2386  }
2387#ifdef CAM_CHDK_PTP
2388   luaL_dostring(L,"function usb_msg_table_to_string(t)"
2389                    " local v2s=function(v)"
2390                        " local t=type(v)"
2391                        " if t=='string' then return v end"
2392                        " if t=='number' or t=='boolean' or t=='nil' then return tostring(v) end"
2393                        " return '' end"
2394                    " local r=''"
2395                    " for k,v in pairs(t) do"
2396                        " local s,vs=''"
2397                        " if type(v)=='table' then"
2398                            " for i=1,table.maxn(v) do"
2399                            " s=s..'\\t'..v2s(v[i]) end"
2400                        " else"
2401                            " vs=v2s(v)"
2402                            " if #vs then s=s..'\\t'..vs end"
2403                        " end"
2404                        " vs=v2s(k)"
2405                        " if #vs>0 and #s>0 then r=r..vs..s..'\\n' end"
2406                    " end"
2407                    " return r"
2408                   " end");
2409
2410#endif
2411}
Note: See TracBrowser for help on using the repository browser.