source: trunk/core/action_stack.c @ 2088

Revision 2088, 7.7 KB checked in by tsv, 20 months ago (diff)

pack of small improvements:

  • respect OPT_SCRIPTING
  • better AutoISO menu handle
  • infrastructure improvements(mbox,mpopup, find_mnu)
  • Property svn:eol-style set to native
Line 
1#include "console.h"
2#include "stdlib.h"
3#include "platform.h"
4#include "camera.h"
5#include "conf.h"
6#include "kbd.h"
7#include "keyboard.h"
8#include "histogram.h"
9#include "action_stack.h"
10
11extern int usb_sync_wait ;
12
13
14typedef struct _action_stack
15{
16    int (*action_process)(long p);
17    long stack[ACTION_STACK_SIZE];
18    int stack_ptr;
19    long comp_id;
20    unsigned long delay_target_ticks;
21} action_stack_t;
22
23static action_stack_t** action_stacks = NULL;
24static int active_stack = -1;
25static int num_stacks = 0;
26static long task_comp_id = 1;
27
28// Returns true if the task denoted by comp_id has finished execution.
29// comp_id is returned by action_stack_create().
30int action_stack_is_finished(long comp_id)
31{
32    int i;
33    for (i = 0; i < num_stacks; ++i)
34    {
35        if (action_stacks[i]->comp_id == comp_id)
36            return 0;
37    }
38
39    return 1;
40}
41
42// Starts a new action stack with initial stack entry p.
43// The action stack is alive as long as its stack has entries.
44long action_stack_create(action_process proc_func, long p)
45{
46    // Cap the maximum number of action_stacks
47    if (num_stacks == MAX_ACTION_STACKS)
48        return -1;
49
50    // Initialize new action stack
51    action_stack_t** tmp = (action_stack_t**)malloc(sizeof(action_stack_t*) * (num_stacks + 1));
52    memcpy(tmp, action_stacks, sizeof(action_stack_t*) * num_stacks);
53
54    tmp[num_stacks] = (action_stack_t*)malloc(sizeof(action_stack_t));
55
56    action_stack_t* stack = tmp[num_stacks];
57    if(proc_func) {
58        stack->action_process = proc_func;
59    } else {
60        stack->action_process = action_stack_standard;
61    }
62
63    stack->stack_ptr = 0;
64    stack->comp_id = task_comp_id;
65    stack->delay_target_ticks = 0;
66    stack->stack[0] = p;
67
68    action_stack_t** old = action_stacks;
69    action_stacks = tmp;
70    ++num_stacks;
71
72    if (old != NULL)
73        free(old);
74
75    // Increment task_comp_id, handle wraparound,
76    // and do not take values already in use
77    do
78    {
79        ++task_comp_id;
80        if (task_comp_id < 0)
81            task_comp_id = 0;
82    } while( !action_stack_is_finished(task_comp_id) );
83    return stack->comp_id;
84}
85
86static void action_stack_finish(int task_id)
87{
88    action_stack_t** tmp = NULL;
89    if (num_stacks > 1)
90        tmp = (action_stack_t**)malloc(sizeof(action_stack_t*) * (num_stacks - 1));
91
92    int src_index, dst_index;
93    for (src_index = 0, dst_index = 0; src_index < num_stacks; ++src_index)
94    {
95        if (src_index != task_id)
96        {
97            tmp[dst_index] = action_stacks[src_index];
98            ++dst_index;
99        }
100        else
101        {
102            free(action_stacks[src_index]);
103        }
104    }
105
106    action_stack_t** old = action_stacks;
107    --num_stacks;
108    action_stacks = tmp;
109    free(old);
110}
111
112// Can only be called from an action stack
113void action_pop()
114{
115    if (active_stack == -1)
116        return;
117
118    --(action_stacks[active_stack]->stack_ptr);
119}
120
121// Can only be called from an action stack
122void action_push_delay(long msec)
123{
124    action_push(msec);
125    action_push(AS_SLEEP);
126}
127
128// Can only be called from an action stack
129void action_push_press(long key)
130{
131    // WARNING stack program flow is reversed
132    action_push_delay(CAM_KEY_PRESS_DELAY);
133    action_push(key);
134    action_push(AS_PRESS);
135}
136
137// Can only be called from an action stack
138void action_push_release(long key)
139{
140    // WARNING stack program flow is reversed
141    action_push_delay(CAM_KEY_RELEASE_DELAY);
142    action_push(key);
143    action_push(AS_RELEASE);
144}
145
146void action_push_click(long key)
147{
148// WARNING stack program flow is reversed
149    action_push_release(key);
150#if defined(CAM_KEY_CLICK_DELAY) // camera need delay for click
151    action_push_delay(CAM_KEY_CLICK_DELAY);
152#endif
153    action_push_press(key);
154}
155
156void action_wait_for_click(int timeout)
157{
158    // accept wait_click 0 for infinite, but use -1 internally to avoid confusion with generated waits
159    action_push(timeout?timeout:-1);
160    action_push(AS_WAIT_CLICK);
161}
162
163// Can only be called from an action stack
164void action_push(long p)
165{
166    if (active_stack == -1)
167        return;
168
169    action_stack_t* task = action_stacks[active_stack];
170    task->stack[++task->stack_ptr] = p;
171}
172
173// Can only be called from an action stack
174long action_get_prev(int p)
175{
176    if (active_stack == -1)
177        return 0;
178
179    action_stack_t* task = action_stacks[active_stack];
180    return task->stack[task->stack_ptr-(p-1)];
181}
182
183// handle initializing and checking a timeout value on the stack
184// p is the how far up the stack the timout value is
185// returns zero if the timeout has not expired, 1 if it has
186// does not pop the delay value off the stack or clear the delay value
187int action_process_delay(int p)
188{
189    unsigned t = get_tick_count();
190    // FIXME take care if overflow occurs
191    if (action_stacks[active_stack]->delay_target_ticks == 0)
192    {
193        /* setup timer */
194        long delay = action_get_prev(p);
195        /* delay of -1 signals indefinite (actually 1 day) delay*/
196        if(delay == -1) {
197            delay = 86400000;
198        }
199        action_stacks[active_stack]->delay_target_ticks = t+delay;
200        return 0;
201    }
202    if (action_stacks[active_stack]->delay_target_ticks <= t)
203    {
204        return 1;
205    }
206    return 0;
207}
208
209void action_clear_delay(void)
210{
211    action_stacks[active_stack]->delay_target_ticks = 0;
212}
213
214// Defines some standard operations. Returns false if it could not process anything.
215// Can only be called from an action stack
216int action_stack_standard(long p)
217{
218    long skey ;
219
220    switch (p)
221    {
222    case AS_PRESS:
223        skey=action_get_prev(2) ;
224        if ((skey == KEY_SHOOT_FULL) &&  conf.remote_enable && conf.synch_enable ) usb_sync_wait = 1 ;
225        kbd_key_press(skey);
226        action_pop();
227        action_pop();
228        break;
229    case AS_RELEASE:
230        kbd_key_release(action_get_prev(2));
231        action_pop();
232        action_pop();
233        break;
234    case AS_SLEEP:
235        if(action_process_delay(2))
236        {
237            action_clear_delay();
238            action_pop();
239            action_pop();
240        }
241        break;
242    case AS_WAIT_SAVE:
243        if (state_shooting_progress == SHOOTING_PROGRESS_DONE)
244            action_pop();
245        break;
246    case AS_WAIT_FLASH:
247        if (shooting_is_flash_ready())
248            action_pop();
249        break;
250    case AS_WAIT_CLICK:
251#ifdef OPT_SCRIPTING
252        if(action_process_delay(2) || (kbd_last_clicked = kbd_get_clicked_key()))
253        {
254            if (!kbd_last_clicked)
255                kbd_last_clicked=0xFFFF;
256#endif
257            action_clear_delay();
258            action_pop();
259            action_pop();
260#ifdef OPT_SCRIPTING
261        }
262#endif
263        break;
264    case AS_WAIT_SHOOTING_IN_PROGRESS:
265        if (shooting_in_progress() || MODE_IS_VIDEO(mode_get()))
266        {
267            action_pop();
268        }
269        break;
270    case AS_SHOOT:
271        state_shooting_progress = SHOOTING_PROGRESS_NONE;
272
273        // Initiate a shoot. Remember that stack program flow is reversed!
274        action_pop();
275        // XXX FIXME find out how to wait to jpeg save finished
276        action_push_delay(conf.script_shoot_delay*100);
277
278        action_push(AS_WAIT_SAVE);
279
280        action_push_release(KEY_SHOOT_HALF);
281        action_push_release(KEY_SHOOT_FULL);
282
283        action_push_press(KEY_SHOOT_FULL);
284
285        action_push(AS_WAIT_FLASH);
286        action_push(AS_WAIT_SHOOTING_IN_PROGRESS);
287
288        action_push_press(KEY_SHOOT_HALF);
289    default:
290        return 0;
291    }
292
293    return 1;
294}
295
296static void action_stack_process(int task_id)
297{
298    action_stack_t* stack = action_stacks[task_id];
299    if (stack->stack_ptr > -1)
300    {
301        stack->action_process(action_get_prev(1));
302    }
303    else
304    {
305        action_stack_finish(task_id);
306    }
307}
308
309void action_stack_process_all()
310{
311    for (active_stack = num_stacks - 1; active_stack >= 0; --active_stack)
312    {
313        action_stack_process(active_stack);
314    }
315
316    active_stack = -1;
317}
Note: See TracBrowser for help on using the repository browser.