source: trunk/core/script.c @ 977

Revision 977, 16.9 KB checked in by reyalp, 3 years ago (diff)

renames and cleanup in preparation for making script optional. From ultimA in http://chdk.setepontos.com/index.php?topic=5793.msg57064#msg57064

  • 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 "conf.h"
8#include "script.h"
9
10//-------------------------------------------------------------------
11
12#define SCRIPT_MAX_CONSOLE_LINES      14
13#define SCRIPT_MAX_LINE_LENGTH        45
14
15//-------------------------------------------------------------------
16const char *script_source_str=NULL; //ERR99
17char cfg_name[100] = "\0";
18char cfg_set_name[100] = "\0";
19int script_console_num_lines, script_console_line_length, script_console_x, script_console_y, auto_redraw=1;
20
21static const char *ubasic_script_default =
22#if 0
23    "@title Default script\n"
24    "@param a Shoot count\n"
25    "@default a 2\n"
26    "@param b Step\n"
27    "@default b 3\n"
28
29    "sleep 1000\n"
30
31    "if a<1 then let a=2\n"
32    "if b<1 then let b=3\n"
33
34    "for s=1 to a\n"
35      "shoot\n"
36      "for n=1 to b\n"
37        "click \"right\"\n"
38      "next n\n"
39    "next s\n"
40    "shoot\n"
41
42    "for n=1 to a*b\n"
43      "click \"left\"\n"
44    "next n\n"
45
46    "end\n";
47#else
48    "@title Default Script\n"
49    "@param a Times to Repeat\n"
50    "@default a 5\n"
51    "@param b Display Delay\n"
52    "@default b 3\n"
53
54    "if a<1 then let a=1\n"
55    "if b<1 then let b=1\n"
56
57    "for n=1 to a\n"
58        "if n>1 then print \"*****\"\n"
59        "print \"This is a default script.\"\n"
60        "sleep 1000\n"
61        "print \"Scripts run when shutter\"\n"
62        "sleep 1000\n"
63        "print \"is pressed in ALT mode.\"\n"
64        "sleep 1000\n"
65        "print \"Press shutter to exit.\"\n"
66        "sleep b*1000\n"
67    "next n\n"
68
69    "end\n";
70#endif
71
72char script_title[36];
73char script_params[SCRIPT_NUM_PARAMS][28];
74int script_param_order[SCRIPT_NUM_PARAMS];
75static char script_params_update[SCRIPT_NUM_PARAMS];
76static int script_loaded_params[SCRIPT_NUM_PARAMS];
77//static char script_console_buf[script_console_num_lines][script_console_line_length+1];
78static char **script_console_buf;
79static int script_con_start_line=0; // oldest valid line in console
80static int script_con_num_lines=0; // number of valid lines
81
82//-------------------------------------------------------------------
83static void process_title(const char *title) {
84    register const char *ptr = title;
85    register int i=0;
86
87    while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
88    while (i<(sizeof(script_title)-1) && ptr[i] && ptr[i]!='\r' && ptr[i]!='\n') {
89        script_title[i]=ptr[i];
90        ++i;
91    }
92    script_title[i]=0;
93}
94
95//-------------------------------------------------------------------
96static int process_param(const char *param, int update) {
97    register const char *ptr = param;
98    register int n, i=0;
99
100    while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
101    if (ptr[0] && (ptr[0]>='a' && ptr[0]<='a'+SCRIPT_NUM_PARAMS) && (ptr[1]==' ' || ptr[1]=='\t')) {
102        n=ptr[0]-'a';
103        ptr+=2;
104        while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
105                script_params_update[n] = 1;
106        while (i<(sizeof(script_params[0])-1) && ptr[i] && ptr[i]!='\r' && ptr[i]!='\n') {
107                        if (update)
108                        { if (script_params[n][i]!=ptr[i]) { script_params_update[n] = 0; break; }
109                        } else script_params[n][i]=ptr[i];
110            ++i;
111        }
112                if (!update) script_params[n][i]=0;
113        n++;
114    } else n=0; // ??? else produce error message   
115    return n; // n=1 if '@param a' was processed, n=2 for 'b' ... n=26 for 'z'. n=0 if failed.
116}
117
118//-------------------------------------------------------------------
119static void process_default(const char *param, char update) {
120    register const char *ptr = param;
121    register int n;
122
123    while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
124    if (ptr[0] && (ptr[0]>='a' && ptr[0]<='a'+SCRIPT_NUM_PARAMS) && (ptr[1]==' ' || ptr[1]=='\t')) {
125        n=ptr[0]-'a';
126        ptr+=2;
127                if (!update || script_params_update[n])
128        {
129                        conf.ubasic_vars[n] = strtol(ptr, NULL, 0);
130            script_loaded_params[n] = conf.ubasic_vars[n];
131        }
132    } // ??? else produce error message
133}
134
135//-------------------------------------------------------------------
136static void script_scan(const char *fn, int update_vars) {
137    register const char *ptr = script_source_str;
138    register int i, j=0, n;
139    char *c;
140
141    c=strrchr(fn, '/');
142    strncpy(script_title, (c)?c+1:fn, sizeof(script_title));
143    script_title[sizeof(script_title)-1]=0;
144    for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
145        script_params[i][0]=0;
146        script_param_order[i]=0;
147    }
148
149    while (ptr[0]) {
150        while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
151        if (ptr[0]=='@') {
152            if (strncmp("@title", ptr, 6)==0) {
153                ptr+=6;
154                process_title(ptr);
155            } else if (strncmp("@param", ptr, 6)==0) {
156                ptr+=6;
157                n=process_param(ptr, 0); // n=1 if '@param a' was processed, n=2 for 'b' ... n=26 for 'z'. n=0 if failed.
158                if (n>0 && n<=SCRIPT_NUM_PARAMS) {
159                  script_param_order[j]=n;
160                  j++;
161                }
162            } else if (update_vars && strncmp("@default", ptr, 8)==0) {
163                ptr+=8;
164                process_default(ptr, 0);
165            }
166        }
167        while (ptr[0] && ptr[0]!='\n') ++ptr; // unless end of line
168        if (ptr[0]) ++ptr;
169    }
170
171    /*for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
172        if (script_params[i][0]) break;
173    }
174    if (i==SCRIPT_NUM_PARAMS) { // there was no @param in script
175        for (i=0; i<3; ++i) {
176            strcpy(script_params[i], "Var. ? value");
177            script_params[i][5]='a'+i;
178        }
179    }*/
180}
181
182void set_params_values_name(const char *fn, int param_set)
183{
184        int shift;
185        register char *ptr = (param_set >= 0 ? cfg_set_name : cfg_name);
186        const char *name;
187       
188        if (fn == NULL || fn[0] == 0) { ptr[0] = 0; return; }
189       
190        strncpy(ptr, SCRIPT_DATA_PATH, 100); ptr[99]=0;
191        shift = strlen(SCRIPT_DATA_PATH);
192        name = strrchr(fn, '/');
193        if (name) name++; else name=fn;
194        strncpy(ptr+shift, name, 100-shift); ptr[99]=0;
195        shift = strlen(ptr); if (shift >= 100) shift=99;
196
197        if (param_set >= 0)
198                sprintf(ptr+shift-4, "_%d\0", param_set); else
199                strcpy(ptr+shift-3, "cfg\0");
200}
201
202//-------------------------------------------------------------------
203int load_params_values(const char *fn, int update_vars, int read_param_set)
204{
205        int i, fd=-1, rcnt;
206        register const char *ptr;       
207        struct stat st;
208        char *buf;
209       
210        if (fn == NULL || fn[0] == 0) return 0;
211        if (read_param_set)
212        {
213                set_params_values_name(fn, -1);
214                // find param set
215                fd = open(cfg_name, O_RDONLY, 0777);
216                if (fd >= 0)
217                {
218                        buf=umalloc(16);
219                        rcnt = read(fd, buf, 15);
220                        buf[rcnt] = 0;
221                        close(fd);
222                        conf.script_param_set = strtol(buf, NULL, 0);
223                        ufree(buf);
224                } else conf.script_param_set = 0;
225        }
226        set_params_values_name(fn, conf.script_param_set);
227        if (!update_vars) return 0;
228       
229        // open and read file
230        if (stat(cfg_set_name,&st) != 0)
231                return 0;
232        buf=umalloc(st.st_size+1);
233        if(!buf)
234                return 0;
235        fd = open(cfg_set_name, O_RDONLY, 0777);
236        if (fd < 0) {
237                ufree(buf);
238                return 0;
239        }
240        rcnt = read(fd, buf, st.st_size);
241        buf[rcnt] = 0;
242        close(fd);
243
244        for(i = 0; i < SCRIPT_NUM_PARAMS; ++i) script_params_update[i]=0;
245    ptr = buf;
246
247    while (ptr[0])
248        {
249        while (ptr[0]==' ' || ptr[0]=='\t') ++ptr; // whitespaces
250        if (ptr[0]=='@')
251                {
252            if (strncmp("@param", ptr, 6) == 0)
253                        {
254                ptr+=6;
255                                process_param(ptr, 1);
256            } else if (strncmp("@default", ptr, 8)==0) {
257                ptr+=8;
258                                process_default(ptr, 1);
259            }
260        }
261        while (ptr[0] && ptr[0]!='\n') ++ptr; // unless end of line
262        if (ptr[0]) ++ptr;
263    }
264        ufree(buf);
265        return 1;
266}
267
268//-------------------------------------------------------------------
269void save_params_values(int unconditional)
270{
271        int i, n, fd, changed=0;
272        char *buf,*p;
273        for(i = 0; i < SCRIPT_NUM_PARAMS; i++)
274        {
275                if (script_loaded_params[i] != conf.ubasic_vars[i]) changed++;
276                script_loaded_params[i] = conf.ubasic_vars[i];
277        }
278        if (!unconditional && !changed) return;
279
280        if (cfg_name[0] == 0) set_params_values_name(conf.script_file, -1);
281        fd = open(cfg_name, O_WRONLY|O_CREAT, 0777);
282        if (fd >= 0)
283        {
284                char s[20];
285                sprintf(s, " %d\n", conf.script_param_set);
286                write(fd, s, strlen(s));
287                close(fd);
288        }
289       
290        // open and read file
291        set_params_values_name(conf.script_file, conf.script_param_set);
292
293        buf=umalloc(SCRIPT_NUM_PARAMS*(28 + 20)); // max possible params * (param description + some extra for @default etc)
294        if(!buf)
295                return;
296
297        fd = open(cfg_set_name, O_WRONLY|O_CREAT, 0777);
298        if (fd < 0) {
299                ufree(buf);
300                return;
301        }
302        buf[0] = 0;
303        p=buf;
304        for(n = 0; n < SCRIPT_NUM_PARAMS; ++n)
305        {
306                if (script_params[n][0] != 0)
307                {
308                        p+=sprintf(p,"@param %c %s\n@default %c %d\n",'a'+n,script_params[n],'a'+n,conf.ubasic_vars[n]);
309                }
310        }
311        write(fd, buf, strlen(buf));
312        close(fd);
313        ufree(buf);
314}
315
316
317
318//-------------------------------------------------------------------
319void script_load(const char *fn, int saved_params) {
320    int i, update_vars;
321    FILE *fd = NULL;
322    struct stat st;
323   
324    auto_redraw=1;
325    script_console_num_lines=5;
326    script_console_line_length=25;
327    script_console_y=SCRIPT_MAX_CONSOLE_LINES-script_console_num_lines;
328    script_console_x=0;
329    script_console_buf=malloc(script_console_num_lines*sizeof(char*));
330    for (i=0;i<script_console_num_lines;i++){
331      script_console_buf[i]=malloc(script_console_line_length*sizeof(char)+1);
332    }
333    script_con_start_line=0;
334    script_con_num_lines=0;
335
336//    save_params_values(0);
337
338    if(script_source_str && script_source_str != ubasic_script_default)
339        free((void *)script_source_str);
340
341    script_source_str = ubasic_script_default;
342    update_vars = (strcmp(fn, conf.script_file) != 0) || !saved_params || (saved_params == 2);  // update if new file
343
344    if (!fn[0]) { // load internal script
345        if (!conf.script_file[0]) { // internal script was used last time
346            fd = fopen(SCRIPT_DEFAULT_FILENAME, "rb");
347            if (fd) {
348                fn = SCRIPT_DEFAULT_FILENAME;
349                update_vars = 1;
350            }
351        }
352    } else {
353        fd = fopen(fn, "rb");
354        if (!fd) {
355            conf.script_file[0]=0;
356            update_vars = 1;
357        }
358    }
359    // zero size = default script
360    if(stat(fn,&st) != 0 || st.st_size == 0) {
361        conf.script_file[0]=0;
362        update_vars = 1;
363        if(fd) {
364            fclose(fd);
365            fd=0;
366        }
367    }
368    if (fd){
369        int rcnt;
370        char *buf;
371
372        buf = malloc(st.st_size+1);
373        if(!buf) {
374            fclose(fd);
375            return;
376        }
377
378        // TODO we could process the script here to reduce size
379        // or compile for lua
380        rcnt = fread(buf, 1, st.st_size,fd);
381        if (rcnt > 0){
382            buf[rcnt] = 0;
383            script_source_str = buf;
384            strcpy(conf.script_file, fn);
385        }
386        else {
387            free(buf);
388        }
389        fclose(fd);
390    }
391
392    if (update_vars) {
393        for (i=0; i<SCRIPT_NUM_PARAMS; ++i) {
394            conf.ubasic_vars[i] = 0;
395            script_loaded_params[i] = 0;
396        }
397    }
398    script_scan(conf.script_file, update_vars);
399    if (saved_params)
400        load_params_values(conf.script_file, update_vars, (saved_params!=2));   
401    gui_update_script_submenu();
402}
403
404//-------------------------------------------------------------------
405void script_console_clear() {
406    register int i;
407
408    for (i=0; i<script_console_num_lines; ++i) {
409        script_console_buf[i][0]=0;
410    }
411    script_con_num_lines=script_con_start_line=0;
412    if(auto_redraw) draw_restore();
413}
414
415//-------------------------------------------------------------------
416static inline int script_con_line_index(int i) {
417    return i%script_console_num_lines;
418}
419
420void script_console_draw(int drawing) {
421  int i,c,l;
422  if(drawing){
423    for(c = 0; c < script_con_num_lines; ++c) {
424      i=script_con_line_index(script_con_start_line+c);
425      l=strlen(script_console_buf[i]);
426      draw_txt_string(script_console_x, script_console_y+script_console_num_lines-script_con_num_lines+c, script_console_buf[i], MAKE_COLOR(COLOR_BG, COLOR_FG));
427      for (; l<script_console_line_length; ++l)
428        draw_txt_char(script_console_x+l, script_console_y+script_console_num_lines-script_con_num_lines+c, ' ', MAKE_COLOR(COLOR_BG, COLOR_FG));
429    }
430  }
431}
432
433static int  print_screen_p;             // print_screen predicate: 0-off 1-on.
434static int  print_screen_d = -1;        // print_screen file descriptor.
435//static const char print_screen_file[] ="A/CHDK/SCRIPTS/PR_SCREEN.TXT";
436static const char print_screen_file_prefix[] = "A/CHDK/LOGS/LOG_";
437char print_screen_file[25];
438static const char extension_txt[] = ".TXT";
439
440void script_print_screen_init()
441{
442  print_screen_p = 0;
443  if (print_screen_d >= 0) {
444    close(print_screen_d);
445    print_screen_d = -1;
446  }
447}
448
449void script_print_screen_end()
450{
451  if (print_screen_d >= 0) {
452    close(print_screen_d);
453    print_screen_d = -1;
454    print_screen_p = 0;
455  }
456}
457
458void script_print_screen_statement(int val)
459{
460  print_screen_p = val;
461  if (val) {
462    if (print_screen_d>=0) close(print_screen_d);
463    int i=0;
464    int c=0;
465    static char file_number[5];
466    strcpy(print_screen_file, print_screen_file_prefix);
467    if (val<0) val = -val;
468    while (val > 9999) val += -10000;
469    for (i=10; i<=1000; i=i*10) { if (val<i) ++c; }
470    for (i=1; i<=c; ++i) { sprintf(file_number, "%d", 0); strcat(print_screen_file, file_number); }
471    sprintf(file_number, "%d", val);
472    strcat(print_screen_file, file_number);
473    strcat(print_screen_file, extension_txt);
474    print_screen_d = open(print_screen_file, O_WRONLY|O_CREAT|O_TRUNC, 0777);
475  }
476}
477
478//-------------------------------------------------------------------
479void script_console_start_line() {
480    if (script_console_num_lines==script_con_num_lines) {
481        script_con_start_line=script_con_line_index(script_con_start_line+1);
482    }
483    else {
484        ++script_con_num_lines;
485    }
486     script_console_buf[script_con_line_index(script_con_start_line+script_con_num_lines-1)][0]=0;
487}
488
489void script_console_add_text(const char *str) {
490    char *cur;
491    int curlen;
492    int left;
493
494    do {
495        cur = script_console_buf[script_con_line_index(script_con_start_line+script_con_num_lines-1)];
496        curlen = strlen(cur);
497        left = script_console_line_length-curlen;
498        if(strlen(str) > left) {
499            strncpy(cur+curlen,str,left);
500            cur[script_console_line_length]=0;
501            script_console_start_line();
502            str+=left;
503        }
504        else {
505            strcat(cur,str);
506            break;
507        }
508    } while(1);
509}
510
511void script_console_add_line(const char *str) {
512    script_console_start_line();
513    script_console_add_text(str);
514    if (print_screen_p && print_screen_d>=0) {
515        char nl = '\n';
516                // TODO this should be uncached memory
517        write(print_screen_d, str, strlen(str) );
518        write(print_screen_d, &nl, 1);
519    }
520    script_console_draw(auto_redraw);
521}
522//-------------------------------------------------------------------
523void script_console_set_layout(int x1, int y1, int x2, int y2) { //untere linke Ecke(x1,y1), obere reche Ecke(x2,y2) - lower left corner (x1,y1), upper right corner(x2,y2)
524  int i,len,newLinesCount,newLineLength,newNumLines,lineDelta,idx;
525  char **tmp;
526  if(x1>=0 && x1<x2 && x1<=SCRIPT_MAX_LINE_LENGTH && y1>=0 && y1<y2 && y1<=SCRIPT_MAX_CONSOLE_LINES && x2<=SCRIPT_MAX_LINE_LENGTH && y2<=SCRIPT_MAX_CONSOLE_LINES) {
527    //In neuen Puffer kopieren - copy to new buffer
528    newLineLength=x2-x1;
529    newLinesCount=y2-y1;
530    if(newLineLength!=script_console_line_length || newLinesCount!=script_console_num_lines) {
531      lineDelta=script_con_num_lines-newLinesCount;
532      if(lineDelta<0) lineDelta=0;
533      newNumLines=0;
534      tmp=malloc(newLinesCount*sizeof(char*)); //realloc Nachbildung - realloc emulation
535      for(i=0;i<newLinesCount;i++){
536        tmp[i]=malloc(newLineLength*sizeof(char)+1);
537        if(i<script_con_num_lines){
538          newNumLines++;
539          idx=script_con_line_index(script_con_start_line+i+lineDelta);
540          len=strlen(script_console_buf[idx]);
541          if(len>newLineLength) len=newLineLength;
542          strncpy(tmp[i],script_console_buf[idx],len);
543          tmp[i][len]=0x0;
544        } else tmp[i][0]=0x0;
545      }
546      //Speicher freigeben - free memory
547      for(i=0;i<script_console_num_lines;i++) {
548        free(script_console_buf[i]);
549      }
550      free(script_console_buf);
551      //neue Werte setzten - set new values
552      script_console_buf=tmp;
553      script_con_start_line=0;
554      script_con_num_lines=newNumLines;
555      script_console_num_lines=newLinesCount;
556      script_console_line_length=newLineLength;
557    }
558    script_console_x=x1;
559    script_console_y=SCRIPT_MAX_CONSOLE_LINES-y2;
560    if(auto_redraw) draw_restore();
561  }
562}
563//-------------------------------------------------------------------
564void script_console_set_autoredraw(int value){
565  auto_redraw=value;
566}
567//-------------------------------------------------------------------
568void script_console_redraw(){
569  draw_restore();
570  script_console_draw(1);
571}
572//-------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.