source: branches/release-1_0/core/script.c @ 1948

Revision 1948, 30.8 KB checked in by msl, 11 months ago (diff)

Typos corrected.

  • Property svn:eol-style set to native
Line 
1#include "stdlib.h"
2#include "keyboard.h"
3#include "platform.h"
4#include "core.h"
5#include "gui.h"
6#include "gui_draw.h"
7#include "gui_menu.h"
8#include "conf.h"
9#include "script.h"
10#include "console.h"
11#include "action_stack.h"
12#include "motion_detector.h"
13#include "shot_histogram.h"
14#include "lang.h"
15#include "gui_lang.h"
16#include "kbd.h"
17
18#ifdef OPT_LUA
19#include "lauxlib.h"
20#endif
21
22//-------------------------------------------------------------------
23
24const char *script_source_str=NULL; // ptr to content of script
25char cfg_name[100] = "\0";          // buffer to make string "DATAPATH/scriptname.cfg"
26char cfg_set_name[100] = "\0";      // buffer to make string "DATAPATH/scriptname_PARAMSET"
27
28static const char *lua_script_default =
29    "--[[\n"
30    "@title Default Script\n"
31    "]]\n"
32#if defined(VER_CHDK)
33    "chdk_def_lang=1\n"
34#else
35    "chdk_def_lang=2\n"
36#endif
37    "langs     = {}\n"
38    "langs[1]  = {[\"name\"]=\"ENGLISH\",  [\"font_cp\"]=0,  [\"hint\"]=\"CHDK language changed to english\"}\n"
39    "langs[2]  = {[\"name\"]=\"GERMAN\",   [\"font_cp\"]=2,  [\"hint\"]=\"CHDK-Sprache auf deutsch geändert\"}\n"
40    "langs[13] = {[\"name\"]=\"RUSSIAN\",  [\"font_cp\"]=1,  [\"hint\"]=\"CHDK language changed to russian\"}\n"
41   
42    "function get_cam_language()\n"
43        "local l\n"
44        "if get_propset()==1 then\n"
45            "l=get_prop(196)/256\n"
46            "if l>7 then l=l+1 end\n"
47            "if l>22 then l=l+1 end\n"
48        "else\n"
49            "l=get_prop(61)/256\n"
50        "end\n"
51        "return l+1\n"
52    "end\n"
53   
54    "function get_chdk_language()\n"
55        "local l=0\n"
56        "local lf=get_config_value(64)\n"
57        "if lf==\"\" then\n"
58            "l=chdk_def_lang\n"
59        "else\n"
60            "for i,v in ipairs(langs) do\n"
61                "if string.find(lf, v[\"name\"]..\".LNG\")~=nil then\n"
62                    "l=i\n"
63                    "break\n"
64                "end\n"
65            "end\n"
66        "end\n"
67        "return l\n"
68    "end\n"
69   
70    "function file_exists(name)\n"
71         "local f=io.open(name,\"r\")\n"
72         "if f~=nil then io.close(f) return true else return false end\n"
73    "end\n"
74   
75   
76    "chdk_lang=get_chdk_language()\n"
77    "cam_lang=get_cam_language()\n"
78   
79    "if cam_lang~=chdk_lang then\n"
80        "if chdk_lang==0 or cam_lang==chdk_def_lang then\n"
81            "set_config_value(64,\"\")\n"
82            "set_config_value(65,langs[chdk_def_lang].font_cp)\n"
83            "print(langs[chdk_def_lang].hint)\n"
84        "elseif langs[cam_lang]~=nil then\n"
85            "if file_exists(\"A/CHDK/LANG/\"..langs[cam_lang].name..\".LNG\") then\n"
86                "set_config_value(64,\"A/CHDK/LANG/\"..langs[cam_lang].name..\".LNG\")\n"
87                "set_config_value(65,langs[cam_lang].font_cp)\n"
88                "print(langs[cam_lang].hint)\n"
89            "else\n"
90                "print(langs[cam_lang].name..\".LNG is missing\")\n"
91            "end\n"
92        "else\n"
93            "print(\"unknown language id (\"..cam_lang..\")\")\n"
94        "end\n"
95    "else\n"
96        "print(\";)\")\n"
97    "end\n";
98
99// ================ SCRIPT PARAMETERS ==========
100char script_title[36];                                      // Title of current script
101
102//
103// 1. Values of script parameters are stored in conf.script_vars
104// 2. Encoding scheme is: array[VAR-'a'] = value
105
106char script_params[SCRIPT_NUM_PARAMS][28];                  // Parameter title
107short script_param_order[SCRIPT_NUM_PARAMS];                // Ordered as_in_script list of variables ( [idx] = id_of_var )
108                                                            // to display in same order in script
109int script_range_values[SCRIPT_NUM_PARAMS];                 // Min/Max values for param validation
110short script_range_types[SCRIPT_NUM_PARAMS];                // Specifies if range values is signed (-9999-32767) or unsigned (0-65535)
111                                                            // Note: -9999 limit on negative values is due to current gui_menu code (and because menu only displays chars)
112const char **script_named_values[SCRIPT_NUM_PARAMS];        // Array of list values for named parameters
113int script_named_counts[SCRIPT_NUM_PARAMS];                 // Count of # of entries in each script_list_values array
114char *script_named_strings[SCRIPT_NUM_PARAMS];              // Base storage for named value string data
115static char script_params_update[SCRIPT_NUM_PARAMS];        // Flag is such parameter exist
116static int script_loaded_params[SCRIPT_NUM_PARAMS];         // Copy of original values of parameters
117                                                            // (detect are they changed or not)
118
119static long running_script_stack_name = -1;                 // ID of action_stack, which used to control script processing
120
121//-------------------------------------------------------------------
122
123const char* skip_whitespace(const char* p)  { while (*p==' ' || *p=='\t') p++; return p; }  // Skip past whitespace
124const char* skip_token(const char* p)       { while (*p && *p!='\r' && *p!='\n' && *p!=' ' && *p!='\t') p++; return p; }  // Skip past current token value
125const char* skip_toeol(const char* p)       { while (*p!='\r' && *p!='\n') p++; return p; } // Skip to end of line
126
127//-------------------------------------------------------------------
128static void process_title(const char *title) {
129    register const char *ptr = title;
130    register int i=0;
131
132    ptr = skip_whitespace(ptr);
133    while (i<(sizeof(script_title)-1) && ptr[i] && ptr[i]!='\r' && ptr[i]!='\n') {
134        script_title[i]=ptr[i];
135        ++i;
136    }
137    script_title[i]=0;
138}
139
140//-------------------------------------------------------------------
141// Process one entry "@param VAR TITLE"
142//      param = ptr right after descriptor (should point to var)
143//      update = 0 - get
144//               1 - check is such parameter exists in loaded script
145// RESULT: script_params[VAR] - parameter title
146//         script_params_update[VAR]
147// RETURN VALUE: 0 if err, 1..26 = id of var
148//-------------------------------------------------------------------
149static int process_param(const char *param, int update)
150{
151    register const char *ptr = param;
152    register int n, i=0;
153
154    ptr = skip_whitespace(ptr);
155    if (ptr[0] && (ptr[0]>='a' && ptr[0]<='a'+SCRIPT_NUM_PARAMS) && (ptr[1]==' ' || ptr[1]=='\t')) {
156        n=ptr[0]-'a';
157        ptr = skip_whitespace(ptr+2);
158        script_params_update[n] = 1;
159        while (i<(sizeof(script_params[0])-1) && ptr[i] && ptr[i]!='\r' && ptr[i]!='\n') {
160            if (update) {
161                if (script_params[n][i]!=ptr[i])
162                    { script_params_update[n] = 0; break; }
163            }
164            else
165                script_params[n][i]=ptr[i];
166            ++i;
167        }
168        if (!update) script_params[n][i]=0;
169        n++;
170    } else n=0; // ??? else produce error message   
171    return n; // n=1 if '@param a' was processed, n=2 for 'b' ... n=26 for 'z'. n=0 if failed.
172}
173
174//-------------------------------------------------------------------
175// Process one entry "@default VAR VALUE"
176//      param = ptr right after descriptor (should point to var)
177//      update = 0 - get
178//               1 - only if updated
179//-------------------------------------------------------------------
180static void process_default(const char *param, char update)
181{
182    register const char *ptr = param;
183    register int n;
184
185    ptr = skip_whitespace(ptr);
186    if (ptr[0] && (ptr[0]>='a' && ptr[0]<='a'+SCRIPT_NUM_PARAMS) && (ptr[1]==' ' || ptr[1]=='\t')) {
187        n=ptr[0]-'a';
188        ptr = skip_whitespace(ptr+2);
189        if (!update || script_params_update[n])
190        {
191            conf.script_vars[n] = strtol(ptr, NULL, 0);
192            script_loaded_params[n] = conf.script_vars[n];
193        }
194    } // ??? else produce error message
195}
196
197//-------------------------------------------------------------------
198// Process one entry "@range VAR MIN MAX"
199//      param = ptr right after descriptor (should point to var)
200//      update = 0 - get
201//               1 - only if updated
202//-------------------------------------------------------------------
203static void process_range(const char *param, char update)
204{
205    register const char *ptr = param;
206    register int n;
207
208    ptr = skip_whitespace(ptr);
209    if (ptr[0] && (ptr[0]>='a' && ptr[0]<='a'+SCRIPT_NUM_PARAMS) && (ptr[1]==' ' || ptr[1]=='\t'))
210    {
211        n=ptr[0]-'a';
212        ptr = skip_whitespace(ptr+2);
213        if (!update || script_params_update[n])
214        {
215            int min = strtol(ptr,NULL,0);
216            ptr = skip_whitespace(skip_token(ptr));
217            int max = strtol(ptr,NULL,0);
218            script_range_values[n] = MENU_MINMAX(min,max);
219            if ((min == 0) && (max == 1))
220                script_range_types[n] = MENUITEM_BOOL;
221            else if ((min >= 0) && (max >= 0))
222                script_range_types[n] = MENUITEM_INT|MENUITEM_F_MINMAX|MENUITEM_F_UNSIGNED;
223            else
224                script_range_types[n] = MENUITEM_INT|MENUITEM_F_MINMAX;
225        }
226    } // ??? else produce error message
227}
228
229//-------------------------------------------------------------------
230// Process one entry "@values VAR A B C D ..."
231//      param = ptr right after descriptor (should point to var)
232//      update = 0 - get
233//               1 - only if updated
234//-------------------------------------------------------------------
235static void process_values(const char *param, char update)
236{
237    register const char *ptr = param;
238    register int n;
239
240    ptr = skip_whitespace(ptr);
241    if (ptr[0] && (ptr[0]>='a' && ptr[0]<='a'+SCRIPT_NUM_PARAMS) && (ptr[1]==' ' || ptr[1]=='\t'))
242    {
243        n=ptr[0]-'a';
244        ptr = skip_whitespace(ptr+2);
245        if (!update || script_params_update[n])
246        {
247            int len = skip_toeol(ptr) - ptr;
248            script_named_strings[n] = malloc(len+1);
249            strncpy(script_named_strings[n], ptr, len);
250            script_named_strings[n][len] = 0;
251
252            const char *p = script_named_strings[n];
253            int cnt = 0;
254            while (*p)
255            {
256                p = skip_whitespace(skip_token(p));
257                cnt++;
258            }
259            script_named_counts[n] = cnt;
260            script_named_values[n] = malloc(cnt * sizeof(char*));
261
262            p = script_named_strings[n];
263            cnt = 0;
264            while (*p)
265            {
266                script_named_values[n][cnt] = p;
267                p = skip_token(p);
268                if (*p)
269                {
270                    *((char*)p) = 0;
271                    p = skip_whitespace(p+1);
272                }
273                cnt++;
274            }
275        }
276    } // ??? else produce error message
277}
278
279//-------------------------------------------------------------------
280// PURPOSE: Parse script for @xxx
281// PARAMETERS:  fn - full path of script
282//              update_vars - 1 process "@defaults", 0 do not
283// RESULTS:  script_title
284//           script_params
285//           script_params_order
286//           script_loaded_params, conf.script_vars
287//-------------------------------------------------------------------
288static void script_scan(const char *fn, int update_vars) {
289    register const char *ptr = script_source_str;
290    register int i, j=0, n;
291    char *c;
292
293    c=strrchr(fn, '/');
294    strncpy(script_title, (c)?c+1:fn, sizeof(script_title));
295    script_title[sizeof(script_title)-1]=0;
296    for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
297        script_params[i][0]=0;
298        script_param_order[i]=0;
299        script_range_values[i] = 0;
300        if (script_named_values[i]) free(script_named_values[i]);
301        script_named_values[i] = 0;
302        if (script_named_strings[i]) free(script_named_strings[i]);
303        script_named_strings[i] = 0;
304        script_named_counts[i] = 0;
305    }
306
307    while (ptr[0]) {
308        ptr = skip_whitespace(ptr);
309        if (ptr[0]=='@') {
310            if (strncmp("@title", ptr, 6)==0) {
311                ptr+=6;
312                process_title(ptr);
313            } else if (strncmp("@param", ptr, 6)==0) {
314                ptr+=6;
315                n=process_param(ptr, 0); // n=1 if '@param a' was processed, n=2 for 'b' ... n=26 for 'z'. n=0 if failed.
316                if (n>0 && n<=SCRIPT_NUM_PARAMS) {
317                  script_param_order[j]=n;
318                  j++;
319                }
320            } else if (update_vars && strncmp("@default", ptr, 8)==0) {
321                ptr+=8;
322                process_default(ptr, 0);
323            } else if (update_vars && strncmp("@range", ptr, 6)==0) {
324                ptr+=6;
325                process_range(ptr, 0);
326            } else if (update_vars && strncmp("@values", ptr, 7)==0) {
327                ptr+=7;
328                process_values(ptr, 0);
329            }
330        }
331        while (ptr[0] && ptr[0]!='\n') ++ptr; // unless end of line
332        if (ptr[0]) ++ptr;
333    }
334
335    /*for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
336        if (script_params[i][0]) break;
337    }
338    if (i==SCRIPT_NUM_PARAMS) { // there was no @param in script
339        for (i=0; i<3; ++i) {
340            strcpy(script_params[i], "Var. ? value");
341            script_params[i][5]='a'+i;
342        }
343    }*/
344}
345
346//-------------------------------------------------------------------
347// PURPOSE:     Create filename of paramset
348// PARAMETERS:  fn - full path of script
349//              param_set - >=0 = num of paramset, <0 = made .cfg
350// RESULT:  name at cfg_set_name or cfg_name (depending on param_set)
351//-------------------------------------------------------------------
352void set_params_values_name(const char *fn, int param_set)
353{
354    int shift;
355    register char *ptr = (param_set >= 0 ? cfg_set_name : cfg_name);
356    const char *name;
357   
358    if (fn == NULL || fn[0] == 0) { ptr[0] = 0; return; }
359   
360    strncpy(ptr, SCRIPT_DATA_PATH, 100); ptr[99]=0;
361    shift = strlen(SCRIPT_DATA_PATH);
362    name = strrchr(fn, '/');
363    if (name) name++; else name=fn;
364    strncpy(ptr+shift, name, 100-shift); ptr[99]=0;
365    shift = strlen(ptr); if (shift >= 100) shift=99;
366
367    if (param_set >= 0)
368        sprintf(ptr+shift-4, "_%d\0", param_set);
369    else
370        strcpy(ptr+shift-3, "cfg\0");
371}
372
373//-------------------------------------------------------------------
374//-------------------------------------------------------------------
375// PURPOSE:     Load parameters from paramset for script
376// PARAMETERS:  fn - full path of script
377//              update_vars - if true load parameters,
378//                                  otherwise do not
379//              read_param_set - if true load required paramset to conf.script_param_set
380//                                  from .cfg, otherwise use paramset 0
381// NOTES:       touched conf.script_param_set
382//-------------------------------------------------------------------
383int load_params_values(const char *fn, int update_vars, int read_param_set)
384{
385    int i, fd=-1, rcnt;
386    register const char *ptr;   
387    struct stat st;
388    char *buf;
389   
390    if (fn == NULL || fn[0] == 0) return 0;
391    if (read_param_set)
392    {
393        set_params_values_name(fn, -1);
394        // find param set
395        fd = open(cfg_name, O_RDONLY, 0777);
396        if (fd >= 0)
397        {
398            buf=umalloc(16);
399            rcnt = read(fd, buf, 15);
400            buf[rcnt] = 0;
401            close(fd);
402            conf.script_param_set = strtol(buf, NULL, 0);
403            ufree(buf);
404        } else conf.script_param_set = 0;
405    }
406    set_params_values_name(fn, conf.script_param_set);
407    if (!update_vars) return 0;
408   
409    // open and read file
410    if (stat(cfg_set_name,&st) != 0)
411        return 0;
412    buf=umalloc(st.st_size+1);
413    if(!buf)
414        return 0;
415    fd = open(cfg_set_name, O_RDONLY, 0777);
416    if (fd < 0) {
417        ufree(buf);
418        return 0;
419    }
420    rcnt = read(fd, buf, st.st_size);
421    buf[rcnt] = 0;
422    close(fd);
423
424    for(i = 0; i < SCRIPT_NUM_PARAMS; ++i) script_params_update[i]=0;
425    ptr = buf;
426
427    while (ptr[0])
428    {
429        while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
430        if (ptr[0]=='@')
431        {
432            if (strncmp("@param", ptr, 6) == 0)
433            {
434                ptr+=6;
435                process_param(ptr, 1);
436            } else if (strncmp("@default", ptr, 8)==0) {
437                ptr+=8;
438                process_default(ptr, 1);
439            } else if (strncmp("@range", ptr, 6)==0) {
440                ptr+=6;
441                process_range(ptr, 1);
442            } else if (strncmp("@values", ptr, 7)==0) {
443                ptr+=7;
444                process_values(ptr, 0);
445            }
446        }
447        while (ptr[0] && ptr[0]!='\n') ++ptr; // unless end of line
448        if (ptr[0]) ++ptr;
449    }
450    ufree(buf);
451    return 1;
452}
453
454//-------------------------------------------------------------------
455// PURPOSE:     Save parameters to paramset for script
456//                  Use: conf.script_file, conf.script_param_set
457// PARAMETERS:  unconditional - if 0 then save only if values are changed
458//                                  (script_loaded_params[i] != conf.script_vars[i])
459//                              otherwise mean "save always"
460//
461// NOTE:    1. create SCRIPT_DATA_PATH/scriptname.cfg
462//                      which store # of last saved paramset
463//          2. create SCRIPT_DATA_PATH/scriptname_PARAMSETNUM
464//                      which contain @param/@defaults pair with values
465//-------------------------------------------------------------------
466void save_params_values(int unconditional)
467{
468    int i, n, fd, changed=0;
469    char *buf;
470    for(i = 0; i < SCRIPT_NUM_PARAMS; i++)
471    {
472        if (script_loaded_params[i] != conf.script_vars[i]) changed++;
473        script_loaded_params[i] = conf.script_vars[i];
474    }
475    if (!unconditional && !changed) return;
476
477    if (cfg_name[0] == 0) set_params_values_name(conf.script_file, -1);
478    fd = open(cfg_name, O_WRONLY|O_CREAT, 0777);
479    if (fd >= 0)
480    {
481        char s[20];
482        sprintf(s, " %d\n", conf.script_param_set);
483        write(fd, s, strlen(s));
484        close(fd);
485    }
486   
487    // open and read file
488    set_params_values_name(conf.script_file, conf.script_param_set);
489
490    // max possible params * (param description + some extra for @default etc)
491    buf=umalloc(256);
492    if(!buf)
493        return;
494
495    fd = open(cfg_set_name, O_WRONLY|O_CREAT, 0777);
496    if (fd < 0) {
497        ufree(buf);
498        return;
499    }
500    buf[0] = 0;
501    for(n = 0; n < SCRIPT_NUM_PARAMS; ++n)
502    {
503        if (script_params[n][0] != 0)
504        {
505            sprintf(buf,"@param %c %s\n@default %c %d\n",'a'+n,script_params[n],'a'+n,conf.script_vars[n]);
506            if (script_range_values[n] != 0)
507                sprintf(buf+strlen(buf),"@range %c %d %d\n",'a'+n,(short)(script_range_values[n]&0xFFFF),(short)(script_range_values[n]>>16));
508            if (script_named_counts[n] != 0)
509            {
510                sprintf(buf+strlen(buf),"@values %c",'a'+n);
511                for (i=0; i<script_named_counts[n]; i++)
512                    sprintf(buf+strlen(buf)," %s",script_named_values[n][i]);
513                strcat(buf,"\n");
514            }
515            write(fd, buf, strlen(buf));
516        }
517    }
518    close(fd);
519    ufree(buf);
520}
521
522
523
524//-------------------------------------------------------------------
525// PURPOSE: Load script to memory ( and free malloc previous if exists)
526// PARAMETERS:  fn - full path of script
527//              saved_params -  0= reset all parameters to defaults
528//                              1= load last stored paramset, if script was switched
529//                              2= load paramset #0
530//
531// RESULTS: conf.script_file
532//          script_source_str - loaded script file content
533//
534// NOTES:  1. Try to load fn, if fn or file is empty - SCRIPT_DEFAULT_FILENAME,
535//                if default not exists - use builtin
536//         2. Update conf.script_file, title, submenu
537//-------------------------------------------------------------------
538void script_load(const char *fn, int saved_params) {
539    int i, update_vars;
540    FILE *fd = NULL;
541    struct stat st;
542   
543//    save_params_values(0);
544
545    if(script_source_str && script_source_str != lua_script_default)
546        free((void *)script_source_str);
547
548    script_source_str = lua_script_default;
549    update_vars = (strcmp(fn, conf.script_file) != 0) || !saved_params || (saved_params == 2);  // update if new file
550
551    if (!fn[0]) { // load internal script
552        if (!conf.script_file[0]) { // internal script was used last time
553            fd = fopen(SCRIPT_DEFAULT_FILENAME, "rb");
554            if (fd) {
555                fn = SCRIPT_DEFAULT_FILENAME;
556                update_vars = 1;
557            }
558        }
559    } else {
560        fd = fopen(fn, "rb");
561        if (!fd) {
562            conf.script_file[0]=0;
563            update_vars = 1;
564        }
565    }
566
567    // zero size = default script
568    if(stat(fn,&st) != 0 || st.st_size == 0) {
569        conf.script_file[0]=0;
570        update_vars = 1;
571        if(fd) {
572            fclose(fd);
573            fd=0;
574        }
575    }
576
577
578    if (fd){
579        int rcnt;
580        char *buf;
581
582        buf = malloc(st.st_size+2);
583        if(!buf) {
584            fclose(fd);
585            return;
586        }
587
588        // TODO we could process the script here to reduce size
589        // or compile for lua
590        rcnt = fread(buf, 1, st.st_size,fd);
591        if (rcnt > 0){
592            buf[rcnt] = '\n';
593            buf[rcnt+1] = 0;
594            script_source_str = buf;
595            strcpy(conf.script_file, fn);
596        }
597        else {
598            free(buf);
599        }
600        fclose(fd);
601    }
602
603    if (update_vars) {
604        for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
605            conf.script_vars[i] = 0;
606            script_loaded_params[i] = 0;
607        }
608    }
609    script_scan(conf.script_file, update_vars);
610    if (saved_params)
611        load_params_values(conf.script_file, update_vars, (saved_params!=2));
612    gui_update_script_submenu();
613}
614
615//-------------------------------------------------------------------
616static int  print_screen_p;             // print_screen predicate: 0-off 1-on.
617static int  print_screen_d = -1;        // print_screen file descriptor.
618char print_screen_file[25];
619
620void script_print_screen_init()
621{
622    print_screen_p = 0;
623    if (print_screen_d >= 0) {
624        close(print_screen_d);
625        print_screen_d = -1;
626    }
627}
628
629void script_print_screen_end()
630{
631    if (print_screen_d >= 0) {
632        close(print_screen_d);
633        print_screen_d = -1;
634        print_screen_p = 0;
635    }
636}
637
638void script_print_screen_statement(int val)
639{
640  // Negative values for 'val' parameter will append to log file,
641  // positive values will truncate the log file
642  int flag_trunc = O_TRUNC;
643
644  print_screen_p = val;
645  if (val) {
646    if (print_screen_d>=0) close(print_screen_d);
647    if (val<0) {
648       flag_trunc = 0;
649       val = -val;
650    }
651    while (val > 9999) val -= 10000;
652    sprintf(print_screen_file, "A/CHDK/LOGS/LOG_%04d.TXT", val);
653    print_screen_d = open(print_screen_file, O_WRONLY|O_CREAT|flag_trunc, 0777);
654    if (print_screen_d>=0) lseek(print_screen_d,0,SEEK_END);
655  }
656}
657
658void script_console_add_line(const char *str)
659{
660    console_add_line(str);
661
662    if (print_screen_p && (print_screen_d >= 0)) {
663        char nl = '\n';
664        // TODO this should be uncached memory
665        write(print_screen_d, str, strlen(str) );
666        write(print_screen_d, &nl, 1);
667    }
668}
669
670static int is_lua( const char* script_file)
671{
672  int len;
673  char const* s;
674 
675  s = script_file;
676  len = strlen( s );
677  return !s[0] || (len >= 4 && ( s[len-1] == 'a' || s[len-1] == 'A' )
678    && ( s[len-2] == 'u' || s[len-2] == 'U' )
679    && ( s[len-3] == 'l' || s[len-3] == 'L' )
680    && s[len-4] == '.');
681}
682
683void script_wait_and_end(void)
684{
685    script_console_add_line("PRESS SHUTTER TO CLOSE");
686
687    // We're not running any more, but we have scheduled stuff that
688    // needs to finish. So keep the script marked as running, but don't
689    // call any more scripting functions.
690    state_kbd_script_run = 3;
691}
692
693static void process_script()
694{   // Note: This function is called from an action stack for AS_SCRIPT_RUN.
695
696    if (state_kbd_script_run != 3) {
697#ifdef OPT_LUA
698        if( L ) {
699            lua_script_run();
700        } else
701#endif
702        {
703#ifdef OPT_UBASIC
704            ubasic_run();
705            if (ubasic_finished()) {
706                script_console_add_line(lang_str(LANG_CONSOLE_TEXT_FINISHED));
707                action_pop();
708                script_end();
709            }   
710#endif
711        }
712    }
713}
714
715static int script_action_stack(long p)
716{
717    // process stack operations
718    switch (p) {
719        case AS_SCRIPT_RUN:
720            if (state_kbd_script_run)
721                process_script();
722            else
723                action_pop();
724            break;
725        case AS_FILE_BROWSER:
726            // state_kbd_script_run is set to 0 when the file browser is started from a Lua script
727            // it is reset back to 1 when the file browser exits and control is returned back to
728            // the script
729            if (state_kbd_script_run)
730            {
731                action_pop();
732#ifdef OPT_LUA
733                if (L)
734                {
735                    // Last selected file is returned by this function in gui_fselect.c
736                    extern char* gui_fselect_result();
737                    // Send file name back to script caller
738                    lua_pushstring( Lt, gui_fselect_result() );
739                }
740#endif
741            }
742            break;
743        case AS_MOTION_DETECTOR:
744            if(md_detect_motion()==0)
745            {
746                action_pop();
747#ifdef OPT_LUA
748                if (L)
749                {
750                       // We need to recover the motion detector's
751                       // result and push
752                       // it onto the thread's stack.
753                       lua_pushnumber( Lt, md_get_result() );
754                } else
755#endif
756                {
757#ifdef OPT_UBASIC
758                    ubasic_set_md_ret(md_get_result());
759#endif
760                }
761            }
762            break;
763#if defined(OPT_LUA) && defined(CAM_CHDK_PTP)
764        case AS_SCRIPT_READ_USB_MSG:
765            if(L) { // only lua supported for now
766                ptp_script_msg *msg = ptp_script_read_msg();
767                if(action_process_delay(2) || msg) {
768                    if(msg) {
769                        lua_pushlstring( Lt,msg->data,msg->size);
770                    } else {
771                        lua_pushnil(Lt);
772                    }
773                    action_clear_delay();
774                    action_pop();
775                    action_pop();
776                }
777            }
778            break;
779        case AS_SCRIPT_WRITE_USB_MSG:
780            if(L) { // only lua supported for now
781                ptp_script_msg *msg = (ptp_script_msg *)action_get_prev(2);
782                int r = ptp_script_write_msg(msg);
783                if(action_process_delay(3) || r) {
784                    action_clear_delay();
785                    action_pop();
786                    action_pop();
787                    action_pop();
788                    lua_pushboolean(Lt,r);
789                }
790            }
791            break;
792#endif
793        default:
794            if (!action_stack_standard(p) && !state_kbd_script_run)
795            {
796                /*finished();*/
797                action_pop();
798                script_end();
799            }
800            break;
801    }
802   
803    return 1;
804}
805
806long script_stack_start()
807{
808    running_script_stack_name = action_stack_create(&script_action_stack, AS_SCRIPT_RUN);
809    return running_script_stack_name;
810}
811
812int script_is_running()
813{
814    return !action_stack_is_finished(running_script_stack_name);
815}
816
817void script_end()
818{
819    script_print_screen_end();
820#ifdef OPT_LUA
821    if( L ) {
822      lua_script_reset();
823    } else
824#endif
825    {
826#ifdef OPT_UBASIC
827      ubasic_end();
828#endif
829    }
830        md_close_motion_detector();
831        shot_histogram_set(0);
832    kbd_key_release_all();
833    state_kbd_script_run = 0;
834
835    conf_update_prevent_shutdown();
836
837    vid_bitmap_refresh();
838}
839
840long script_start_gui( int autostart )
841{
842    int i;
843
844    shot_histogram_set(0);
845    if (autostart)
846        auto_started = 1;
847    else
848        auto_started = 0;
849
850    kbd_last_clicked = 0;
851
852    /*if (!autostart)*/ kbd_key_release_all();
853
854    console_clear();
855    script_print_screen_init();
856
857    if (conf.script_param_save) {
858        save_params_values(0);
859    }
860    if( autostart )
861        script_console_add_line("***Autostart***");
862    else
863        script_console_add_line(lang_str(LANG_CONSOLE_TEXT_STARTED));
864
865    if( is_lua( conf.script_file ) ) {
866#ifdef OPT_LUA
867        if( !lua_script_start(script_source_str,0) ) {
868            return -1;
869        }
870        for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
871            if( script_params[i][0] ) {
872                char var = 'a'+i;
873                lua_pushlstring( L, &var, 1 );
874                lua_pushnumber( L, conf.script_vars[i] );
875                lua_settable( L, LUA_GLOBALSINDEX );
876            }
877        }
878#else
879        char msg[64];
880        sprintf(msg,lang_str(LANG_CONSOLE_SCRIPT_DISABLED_IN_BUILD),"Lua");
881        console_add_line(msg);
882        return -1;
883#endif
884    } else
885    { // ubasic
886#ifdef OPT_UBASIC
887        ubasic_init(script_source_str);
888
889        for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
890            ubasic_set_variable(i, conf.script_vars[i]);
891        }
892#else
893        char msg[64];
894        sprintf(msg,lang_str(LANG_CONSOLE_SCRIPT_DISABLED_IN_BUILD),"UBASIC");
895        console_add_line(msg);
896        return -1;
897#endif
898    }
899
900    state_kbd_script_run = 1;
901
902    conf_update_prevent_shutdown();
903
904    return script_stack_start();
905}
906
907#if defined(OPT_LUA) && defined(CAM_CHDK_PTP)
908long script_start_ptp( char *script )
909{
910  if (!lua_script_start(script,1)) return -1;
911  state_kbd_script_run = 1;
912  kbd_set_block(1);
913  auto_started = 0;
914  return script_stack_start();
915}
916#endif
917
918int script_key_is_pressed(int k)
919{
920    if (k==0xFF)
921        return get_usb_power(1);
922    if (k > 0)
923        return kbd_is_key_pressed(k);
924    return 0;
925}
926
927int script_key_is_clicked(int k)
928{
929    if (k==0xFF)
930        return get_usb_power(1);
931    if (k > 0)
932        return (kbd_last_clicked == k);
933    return 0;
934}
935
936static const struct Keynames {
937    int keyid;
938    char *keyname;
939} keynames[] = {
940    { KEY_UP,           "up"         },
941    { KEY_DOWN,         "down"       },
942    { KEY_LEFT,         "left"       },
943    { KEY_RIGHT,        "right"      },
944    { KEY_SET,          "set"        },
945    { KEY_SHOOT_HALF,   "shoot_half" },
946    { KEY_SHOOT_FULL,   "shoot_full" },
947    { KEY_SHOOT_FULL_ONLY,   "shoot_full_only" },
948    { KEY_ZOOM_IN,      "zoom_in"    },
949    { KEY_ZOOM_OUT,     "zoom_out"   },
950    { KEY_MENU,         "menu"       },
951    { KEY_DISPLAY,      "display"    },
952    { KEY_PRINT,        "print"      },
953    { KEY_ERASE,        "erase"      },
954    { KEY_ISO,          "iso"        },
955    { KEY_FLASH,        "flash"      },
956    { KEY_MF,           "mf"         },
957    { KEY_MACRO,        "macro"      },
958    { KEY_VIDEO,        "video"      },
959    { KEY_TIMER,        "timer"      },
960    { KEY_EXPO_CORR,    "expo_corr"  },
961    { KEY_MICROPHONE,   "fe"         },
962    { KEY_ZOOM_ASSIST,  "zoom_assist"},
963    { KEY_AE_LOCK,      "ae_lock"    },
964    { KEY_METERING,     "metering_mode"},
965    { 0xFF,             "remote"     },
966    { 0xFFFF,           "no_key"     },
967};
968
969int script_keyid_by_name (const char *n)
970{
971    int i;
972    for (i=0;i<sizeof(keynames)/sizeof(keynames[0]);i++)
973    if (strcmp(keynames[i].keyname,n) == 0)
974        return keynames[i].keyid;
975    return 0;
976}
Note: See TracBrowser for help on using the repository browser.