Changeset 1101
- Timestamp:
- 03/23/11 04:41:29 (2 years ago)
- Location:
- trunk
- Files:
-
- 10 edited
-
. (modified) (1 prop)
-
core/action_stack.c (modified) (3 diffs)
-
core/action_stack.h (modified) (2 diffs)
-
core/luascript.c (modified) (5 diffs)
-
core/luascript.h (modified) (2 diffs)
-
core/ptp.c (modified) (11 diffs)
-
core/ptp.h (modified) (3 diffs)
-
core/script.c (modified) (5 diffs)
-
include/platform.h (modified) (1 diff)
-
include/script.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/reyalp-ptp (added) merged: 1083,1090,1095-1096,1100
- Property svn:mergeinfo changed
-
trunk/core/action_stack.c
r1050 r1101 169 169 } 170 170 171 // handle initializing and checking a timeout value on the stack 172 // p is the how far up the stack the timout value is 173 // returns zero if the timeout has not expired, 1 if it has 174 // does not pop the delay value off the stack or clear the delay value 175 int action_process_delay(int p) 176 { 177 int t = get_tick_count(); 178 // FIXME take care if overflow occurs 179 if (action_stacks[active_stack]->delay_target_ticks == 0) 180 { 181 /* setup timer */ 182 action_stacks[active_stack]->delay_target_ticks = t+action_get_prev(p); 183 return 0; 184 } 185 if (action_stacks[active_stack]->delay_target_ticks <= t) 186 { 187 return 1; 188 } 189 return 0; 190 } 191 192 void action_clear_delay(void) 193 { 194 action_stacks[active_stack]->delay_target_ticks = 0; 195 } 196 171 197 // Defines some standard operations. Returns false if it could not process anything. 172 198 // Can only be called from an action stack … … 188 214 break; 189 215 case AS_SLEEP: 190 t = get_tick_count(); 191 // FIXME take care if overflow occurs 192 if (action_stacks[active_stack]->delay_target_ticks == 0) 193 { 194 /* setup timer */ 195 action_stacks[active_stack]->delay_target_ticks = t+action_get_prev(2); 196 } 197 else 198 { 199 if (action_stacks[active_stack]->delay_target_ticks <= t) 200 { 201 action_stacks[active_stack]->delay_target_ticks = 0; 202 203 // pop sleep op. 204 action_pop(); 205 action_pop(); 206 } 216 if(action_process_delay(2)) 217 { 218 action_clear_delay(); 219 action_pop(); 220 action_pop(); 207 221 } 208 222 break; … … 239 253 break; 240 254 case AS_WAIT_CLICK: 241 t = get_tick_count(); 242 if (action_stacks[active_stack]->delay_target_ticks == 0) 243 { 244 /* setup timer */ 245 action_stacks[active_stack]->delay_target_ticks = t+((action_get_prev(2))?action_get_prev(2):86400000); 246 } 247 else 248 { 249 kbd_last_clicked = kbd_get_clicked_key(); 250 if (kbd_last_clicked || (action_stacks[active_stack]->delay_target_ticks <= t)) 251 { 252 if (!kbd_last_clicked) 253 kbd_last_clicked=0xFFFF; 254 255 action_stacks[active_stack]->delay_target_ticks = 0; 256 257 // pop up 258 action_pop(); 259 action_pop(); 260 } 255 if(action_process_delay(2) || (kbd_last_clicked = kbd_get_clicked_key())) 256 { 257 if (!kbd_last_clicked) 258 kbd_last_clicked=0xFFFF; 259 action_clear_delay(); 260 action_pop(); 261 action_pop(); 261 262 } 262 263 break; -
trunk/core/action_stack.h
r1032 r1101 19 19 AS_WAIT_CLICK, 20 20 AS_SCRIPT_RUN, 21 AS_MOTION_DETECTOR 21 AS_MOTION_DETECTOR, 22 AS_SCRIPT_READ_USB_MSG, // params: timeout 23 AS_SCRIPT_WRITE_USB_MSG, // params: timeout, msg 22 24 }; 23 25 … … 32 34 void action_wait_for_click(int timeout); 33 35 void action_pop(); 36 int action_process_delay(int p); 37 void action_clear_delay(void); 34 38 long action_get_prev(int p); 35 39 int action_stack_standard(long p); -
trunk/core/luascript.c
r1036 r1101 15 15 #include "action_stack.h" 16 16 #include "motion_detector.h" 17 #include "ptp.h" 17 18 18 19 #include "../lib/lua/lstate.h" // for L->nCcalls, baseCcalls … … 20 21 lua_State* L; 21 22 lua_State* Lt; 22 int lua_keep_result; 23 24 void *lua_consume_result() 25 { 26 lua_State* r = L; 23 24 static int lua_script_is_ptp; 25 26 static int yield_hook_enabled; 27 28 static void lua_script_disable_yield_hook(void) { 29 yield_hook_enabled = 0; 30 } 31 static void lua_script_enable_yield_hook(void) { 32 yield_hook_enabled = 1; 33 } 34 35 #ifdef CAM_CHDK_PTP 36 // create a ptp message from the given stack index 37 // incompatible types will return a TYPE_UNSUPPORTED message 38 static ptp_script_msg *lua_create_usb_msg( lua_State* L, int index, unsigned msgtype) { 39 // TODO maybe we should just pass the lua type constants 40 unsigned datatype, datasize = 4; 41 int ivalue = 0; 42 void *data = &ivalue; 43 int ltype = lua_type(L,index); 44 switch(ltype) { 45 case LUA_TNONE: 46 return NULL; // nothing on the stack, no message generated 47 break; 48 case LUA_TNIL: 49 datatype = PTP_CHDK_TYPE_NIL; 50 break; 51 case LUA_TBOOLEAN: 52 datatype = PTP_CHDK_TYPE_BOOLEAN; 53 ivalue = lua_toboolean(L,index); 54 break; 55 case LUA_TNUMBER: 56 datatype = PTP_CHDK_TYPE_INTEGER; 57 ivalue = lua_tonumber(L,index); 58 break; 59 case LUA_TSTRING: 60 datatype = PTP_CHDK_TYPE_STRING; 61 data = (char *)lua_tolstring(L,index,&datasize); 62 break; 63 // TODO this converts to a string and returns as STRING, format as described at 64 // http://chdk.setepontos.com/index.php?topic=4338.msg62606#msg62606 65 // for compatibility with current PTPCAM/PTPCAMGUI implementation 66 // later we should switch to a proper serialized table with it's own return type 67 case LUA_TTABLE: 68 lua_script_disable_yield_hook(); // don't want to yeild while converting 69 lua_getglobal(L, "usb_msg_table_to_string"); // push function 70 lua_pushvalue(L, index); // copy specified index to top of stack 71 lua_pcall(L,1,1,0); // this will leave an error message as a string on the stack if call fails 72 lua_script_enable_yield_hook(); 73 // an empty table will be returned as an empty string 74 // a non-string should never show up here 75 if ( !(lua_isstring(L,-1) /*&& ( lua_objlen(L,-1) > 0 )*/)) { 76 return NULL; 77 } 78 datatype = PTP_CHDK_TYPE_STRING; 79 data = (char *)lua_tolstring(L,-1,&datasize); 80 lua_pop(L,1); 81 break; 82 default: 83 datatype = PTP_CHDK_TYPE_UNSUPPORTED; 84 data = (char *)lua_typename(L,ltype); // return type name as message data 85 datasize = strlen(data); 86 } 87 return ptp_script_create_msg(msgtype,datatype,datasize,data); 88 } 89 90 void lua_script_error_ptp(int runtime, const char *err) { 91 if(runtime) { 92 ptp_script_write_error_msg(PTP_CHDK_S_ERRTYPE_RUN, err); 93 script_end(); 94 } else { 95 ptp_script_write_error_msg(PTP_CHDK_S_ERRTYPE_COMPILE, err); 96 lua_script_reset(); 97 } 98 } 99 #endif 100 101 void lua_script_reset() 102 { 103 lua_close( L ); 27 104 L = 0; 28 return r;29 }30 31 void lua_script_reset()32 {33 if ( !lua_keep_result )34 {35 lua_close( L );36 L = 0;37 }38 Lt = 0;39 105 } 40 106 41 107 static void lua_count_hook(lua_State *L, lua_Debug *ar) 42 108 { 43 if( L->nCcalls <= L->baseCcalls )109 if( L->nCcalls <= L->baseCcalls && yield_hook_enabled ) 44 110 lua_yield( L, 0 ); 45 111 } 46 112 47 int lua_script_start( char const* script ) 48 { 49 lua_keep_result = 0; 113 void lua_script_error(lua_State *Lt,int runtime) 114 { 115 const char *err = lua_tostring( Lt, -1 ); 116 script_console_add_line( err ); 117 if(lua_script_is_ptp) { 118 #ifdef CAM_CHDK_PTP 119 lua_script_error_ptp(runtime,err); 120 #endif 121 } else { 122 if(runtime) { 123 if(conf.debug_lua_restart_on_error) { 124 lua_script_reset(); 125 script_start_gui(0); 126 } else { 127 script_wait_and_end(); 128 } 129 } else { 130 script_print_screen_end(); 131 script_wait_and_end(); 132 } 133 } 134 } 135 136 137 // TODO more stuff from script.c should be moved here 138 void lua_script_finish(lua_State *L) 139 { 140 #ifdef CAM_CHDK_PTP 141 if(lua_script_is_ptp) { 142 // send all return values as RET messages 143 int i,end = lua_gettop(L); 144 for(i=1;i<=end; i++) { 145 // if the queue is full return values will be silently discarded 146 // incompatible types will be returned as TYPE_UNSUPPORTED to preserve expected number and order of return values 147 ptp_script_write_msg(lua_create_usb_msg(L,i,PTP_CHDK_S_MSGTYPE_RET)); 148 } 149 } 150 #endif 151 } 152 153 int lua_script_start( char const* script, int ptp ) 154 { 155 lua_script_is_ptp = ptp; 50 156 L = lua_open(); 51 157 luaL_openlibs( L ); … … 55 161 lua_setfield( L, LUA_REGISTRYINDEX, "Lt" ); 56 162 if( luaL_loadstring( Lt, script ) != 0 ) { 57 script_console_add_line( lua_tostring( Lt, -1 ) ); 58 lua_script_reset(); 163 lua_script_error(Lt,0); 59 164 return 0; 60 165 } 61 166 lua_sethook(Lt, lua_count_hook, LUA_MASKCOUNT, 1000 ); 167 lua_script_enable_yield_hook(); 62 168 return 1; 63 169 } … … 1387 1493 return 1; 1388 1494 } 1495 1496 #ifdef CAM_CHDK_PTP 1497 /* 1498 msg = read_usb_msg([timeout]) 1499 read a message from the CHDK ptp interface. 1500 Returns the next available message as a string, or nil if no messages are available 1501 If timeout is given and not zero, wait until a message is available or timeout expires 1502 */ 1503 static int luaCB_read_usb_msg( lua_State* L ) 1504 { 1505 int timeout = luaL_optnumber( L, 1, 0 ); 1506 if(timeout) { 1507 action_push(timeout); 1508 action_push(AS_SCRIPT_READ_USB_MSG); 1509 return lua_yield( L, 0 ); 1510 } 1511 ptp_script_msg *msg = ptp_script_read_msg(); 1512 if(msg) { 1513 lua_pushlstring(L,msg->data,msg->size); 1514 return 1; 1515 } 1516 lua_pushnil(L); 1517 return 1; 1518 } 1519 1520 /* 1521 status = write_usb_msg(msg,[timeout]) 1522 writes a message to the CHDK ptp interface 1523 msg may be nil, boolean, number, string or table (table has some restrictions, will be converted to string) 1524 returns true if the message was queued successfully, otherwise false 1525 if timeout is set and not zero, wait until message is written or timeout expires 1526 NOTE strings will not include a terminating NULL, must be handled by recipient 1527 */ 1528 static int luaCB_write_usb_msg( lua_State* L ) 1529 { 1530 ptp_script_msg *msg; 1531 int timeout = luaL_optnumber( L, 2, 0 ); 1532 // TODO would it be better to either ignore this or return nil ? 1533 // a write_usb_msg(function_which_returns_no_value()) is an error in this case 1534 // replacing with nil might be more luaish 1535 if(lua_gettop(L) < 1) { 1536 return luaL_error(L,"missing argument"); 1537 } 1538 msg=lua_create_usb_msg(L,1,PTP_CHDK_S_MSGTYPE_USER); 1539 // for user messages, trying to create a message from an incompatible type throws an error 1540 if(msg->subtype == PTP_CHDK_TYPE_UNSUPPORTED) { 1541 free(msg); 1542 return luaL_error(L,"unsupported type"); 1543 } 1544 if(!msg) { 1545 return luaL_error(L,"failed to create message"); 1546 } 1547 if(timeout) { 1548 action_push(timeout); 1549 action_push((int)msg); 1550 action_push(AS_SCRIPT_WRITE_USB_MSG); 1551 return lua_yield( L, 0 ); 1552 } 1553 lua_pushboolean(L,ptp_script_write_msg(msg)); 1554 return 1; 1555 } 1556 #endif 1389 1557 1390 1558 void register_lua_funcs( lua_State* L ) … … 1554 1722 #endif 1555 1723 FUNC(reboot); 1556 } 1724 #ifdef CAM_CHDK_PTP 1725 FUNC(read_usb_msg); 1726 FUNC(write_usb_msg); 1727 luaL_dostring(L,"function usb_msg_table_to_string(t)" 1728 " local v2s=function(v)" 1729 " local t=type(v)" 1730 " if t=='string' then return v end" 1731 " if t=='number' or t=='boolean' or t=='nil' then return tostring(v) end" 1732 " return '' end" 1733 " local r=''" 1734 " for k,v in pairs(t) do" 1735 " local s,vs=''" 1736 " if type(v)=='table' then" 1737 " for i=1,table.maxn(v) do" 1738 " s=s..'\\t'..v2s(v[i]) end" 1739 " else" 1740 " vs=v2s(v)" 1741 " if #vs then s=s..'\\t'..vs end" 1742 " end" 1743 " vs=v2s(k)" 1744 " if #vs>0 and #s>0 then r=r..vs..s..'\\n' end" 1745 " end" 1746 " return r" 1747 " end"); 1748 1749 #endif 1750 } -
trunk/core/luascript.h
r1021 r1101 4 4 #include "lua.h" 5 5 6 void *lua_consume_result();7 6 void lua_script_reset(); 8 int lua_script_start( char const* script ); 7 int lua_script_start( char const* script,int is_ptp ); 8 void lua_script_error( lua_State* L,int runtime ); 9 void lua_script_finish( lua_State* L ); 9 10 extern void register_lua_funcs( lua_State* L ); 10 11 // run the "restore" function at the end of a script … … 13 14 extern lua_State* L; 14 15 extern lua_State* Lt; 15 extern int lua_keep_result;16 16 17 17 #endif -
trunk/core/ptp.c
r1078 r1101 14 14 #include "script.h" 15 15 #include "action_stack.h" 16 17 static lua_State *get_lua_thread(lua_State *L) 18 { 19 lua_State *Lt; 20 21 lua_getfield(L,LUA_REGISTRYINDEX,"Lt"); 22 Lt = lua_tothread(L,-1); 23 lua_pop(L,1); 24 25 return Lt; 26 } 16 // process id for scripts, increments before each attempt to run script 17 // does not handle wraparound 18 static unsigned script_run_id; 27 19 #endif 28 20 … … 64 56 65 57 return 1; 58 } 59 60 // camera will shut down if you ignore a recv data phase 61 static void flush_recv_ptp_data(ptp_data *data,int size) { 62 char *buf; 63 buf = malloc((size > buf_size) ? buf_size:size); 64 if(!buf) // buf_size should always be less then available memory 65 return; 66 while ( size > 0 ) 67 { 68 if ( size >= buf_size ) 69 { 70 recv_ptp_data(data,buf,buf_size); 71 size -= buf_size; 72 } else { 73 recv_ptp_data(data,buf,size); 74 size = 0; 75 } 76 } 77 free(buf); 66 78 } 67 79 … … 94 106 } 95 107 108 #ifdef OPT_LUA 109 // TODO this could be a generic ring buffer of words 110 #define PTP_SCRIPT_MSG_Q_LEN 16 111 typedef struct { 112 unsigned r; // index of current read value 113 unsigned w; // index of next write value, if w == r, empty TODO "full" currently wastes a slot 114 ptp_script_msg *q[PTP_SCRIPT_MSG_Q_LEN]; 115 } ptp_script_msg_q; 116 117 // TODO it would be better to allocate these only when needed 118 ptp_script_msg_q msg_q_in; // messages to pc from script 119 ptp_script_msg_q msg_q_out; // messages to script from pc 120 121 unsigned script_msg_q_next(unsigned i) { 122 if(i == PTP_SCRIPT_MSG_Q_LEN - 1) { 123 return 0; 124 } 125 return i+1; 126 } 127 128 unsigned script_msg_q_full(ptp_script_msg_q *q) { 129 return (script_msg_q_next(q->w) == q->r); 130 } 131 132 unsigned script_msg_q_empty(ptp_script_msg_q *q) { 133 return (q->w == q->r); 134 } 135 136 int enqueue_script_msg(ptp_script_msg_q *q,ptp_script_msg *msg) { 137 unsigned w = script_msg_q_next(q->w); 138 if(w == q->r) { 139 return 0; 140 } 141 // zero size messages don't make any sense 142 if(msg == NULL || msg->size == 0) { 143 return 0; 144 } 145 q->q[q->w] = msg; 146 q->w = w; 147 return 1; 148 } 149 150 ptp_script_msg* dequeue_script_msg(ptp_script_msg_q *q) { 151 ptp_script_msg *msg; 152 if(script_msg_q_empty(q)) { 153 return NULL; 154 } 155 msg = q->q[q->r]; 156 q->r = script_msg_q_next(q->r); 157 return msg; 158 } 159 160 // public interface for script 161 ptp_script_msg* ptp_script_create_msg(unsigned type, unsigned subtype, unsigned datasize, const void *data) { 162 ptp_script_msg *msg; 163 if(!datasize) { 164 return NULL; 165 } 166 msg = malloc(sizeof(ptp_script_msg) + datasize); 167 msg->size = datasize; 168 msg->type = type; 169 msg->subtype = subtype; 170 // caller may fill in data themselves 171 if(data) { 172 memcpy(msg->data,data,msg->size); 173 } 174 return msg; 175 } 176 177 int ptp_script_write_msg(ptp_script_msg *msg) { 178 msg->script_id = script_run_id; 179 return enqueue_script_msg(&msg_q_out,msg); 180 } 181 182 ptp_script_msg* ptp_script_read_msg(void) { 183 ptp_script_msg *msg; 184 while(1) { 185 msg = dequeue_script_msg(&msg_q_in); 186 // no messages 187 if(!msg) { 188 return NULL; 189 } 190 // does message belong to our script 191 if(!msg->script_id || msg->script_id == script_run_id) { 192 return msg; 193 } else { 194 // no: discard and keep looking 195 free(msg); 196 } 197 } 198 } 199 int ptp_script_write_error_msg(unsigned errtype, const char *err) { 200 if(script_msg_q_full(&msg_q_out)) { 201 return 0; 202 } 203 ptp_script_msg *msg = ptp_script_create_msg(PTP_CHDK_S_MSGTYPE_ERR,errtype,strlen(err),err); 204 if(!msg) { 205 return 0; 206 } 207 return ptp_script_write_msg(msg); 208 } 209 210 #endif 211 96 212 static int handle_ptp( 97 213 int h, ptp_data *data, int opcode, int sess_id, int trans_id, … … 100 216 static union { 101 217 char *str; 102 #ifdef OPT_LUA103 lua_State *lua_state;104 #endif105 218 } temp_data; 106 219 static int temp_data_kind = 0; // 0: nothing, 1: ascii string, 2: lua object … … 115 228 ptp.num_param = 0; 116 229 230 // TODO calling this on every PTP command is not good, 231 // since it figures out free memory by repeatedly malloc'ing! 117 232 buf_size=core_get_free_memory()>>1; 118 233 … … 139 254 #ifdef OPT_SCRIPTING 140 255 ptp.param1 |= script_is_running()?PTP_CHDK_SCRIPT_STATUS_RUN:0; 256 #ifdef OPT_LUA 257 ptp.param1 |= (!script_msg_q_empty(&msg_q_out))?PTP_CHDK_SCRIPT_STATUS_MSG:0; 258 #endif 141 259 #endif 142 260 break; … … 210 328 l = temp_data_extra; 211 329 } 212 #ifdef OPT_LUA213 else { // temp_data_kind == 2214 s = lua_tolstring(get_lua_thread(temp_data.lua_state),1,&l);215 }216 #endif217 330 218 331 if ( !send_ptp_data(data,s,l) ) … … 227 340 free(temp_data.str); 228 341 } 229 #ifdef OPT_LUA230 else if ( temp_data_kind == 2 )231 {232 lua_close(temp_data.lua_state);233 }234 #endif235 342 temp_data_kind = 0; 236 343 … … 257 364 free(temp_data.str); 258 365 } 259 #ifdef OPT_LUA260 else if ( temp_data_kind == 2 )261 {262 lua_close(temp_data.lua_state);263 }264 #endif265 366 temp_data_kind = 0; 266 367 } … … 392 493 393 494 #ifdef OPT_LUA 495 // TODO this should flush data even if scripting isn't supported 394 496 case PTP_CHDK_ExecuteScript: 395 497 { 396 498 int s; 397 499 char *buf; 500 501 script_run_id++; 502 ptp.num_param = 2; 503 ptp.param1 = script_run_id; 398 504 399 505 if ( param2 != PTP_CHDK_SL_LUA ) … … 414 520 recv_ptp_data(data,buf,s); 415 521 416 long script_action_stack = script_start_ptp(buf, param3&PTP_CHDK_ES_RESULT); 522 // error details will be passed in a message 523 if (script_start_ptp(buf) < 0) { 524 ptp.param2 = PTP_CHDK_S_ERRTYPE_COMPILE; 525 } else { 526 ptp.param2 = PTP_CHDK_S_ERRTYPE_NONE; 527 } 417 528 418 529 free(buf); 419 530 420 if (script_action_stack < 0) 421 { 422 ptp.code = PTP_RC_InvalidParameter; 423 break; 424 } 425 else 426 { 427 428 if ( param3 & PTP_CHDK_ES_WAIT ) 429 { 430 431 while ( script_is_running() ) 432 msleep(100); 433 434 if ( param3 & PTP_CHDK_ES_RESULT ) 435 { 436 lua_State *Lt; 437 temp_data.lua_state = lua_consume_result(); 438 Lt = get_lua_thread(temp_data.lua_state); 439 temp_data_kind = 2; 440 if ( lua_gettop(Lt) == 0 ) 441 { 442 temp_data_extra = PTP_CHDK_TYPE_NOTHING; 443 } else if ( lua_isnil(Lt,1) ) 444 { 445 temp_data_extra = PTP_CHDK_TYPE_NIL; 446 } else if ( lua_isboolean(Lt,1) ) 447 { 448 temp_data_extra = PTP_CHDK_TYPE_BOOLEAN; 449 } else if ( lua_isnumber(Lt,1) ) 450 { 451 temp_data_extra = PTP_CHDK_TYPE_INTEGER; 452 } else if ( lua_isstring(Lt,1) ) 453 { 454 temp_data_extra = PTP_CHDK_TYPE_STRING; 455 } else if ( lua_istable(Lt,1) ) 456 { 457 temp_data_extra = PTP_CHDK_TYPE_NOTHING; 458 int i; 459 int count = 0; 460 lua_pushstring(Lt,""); 461 lua_pushnil(Lt); 462 while (lua_next(Lt,1) ) 463 { 464 lua_pushvalue(Lt,-2); 465 lua_insert(Lt,-4); 466 if ( lua_istable(Lt,-1) && (lua_objlen(Lt,-1) > 0) ) 467 { 468 lua_pushstring(Lt,""); 469 for ( i = 1; i <= lua_objlen(Lt,-2); i++ ) 470 { 471 lua_rawgeti(Lt,-2,i); 472 if ( lua_isnil(Lt,-1) ) 473 { 474 lua_pushstring(Lt,"nil"); 475 lua_remove(Lt,-2); 476 } 477 if ( lua_isboolean(Lt,-1) ) 478 { 479 lua_pushstring(Lt,lua_toboolean(Lt,-1)?"true":"false"); 480 lua_remove(Lt,-2); 481 } 482 if ( !lua_isstring(Lt,-1) ) 483 { 484 lua_pop(Lt,1); 485 lua_pushstring(Lt,""); 486 } 487 if ( lua_objlen(Lt,-2) > 0 ) 488 { 489 lua_pushlstring(Lt,"\t",1); 490 lua_insert(Lt,-2); 491 lua_concat(Lt,3); 492 } 493 else lua_concat(Lt,2); 494 } 495 lua_remove(Lt,-2); 496 } 497 if ( lua_isboolean(Lt,-1) ) 498 { 499 lua_pushstring(Lt,lua_toboolean(Lt,-1)?"true":"false"); 500 lua_remove(Lt,-2); 501 } 502 if ( lua_isstring(Lt,-1) ) 503 { 504 lua_pushlstring(Lt,"\t",1); 505 lua_insert(Lt,-2); 506 if ( lua_objlen(Lt,-4) > 0 ) 507 { 508 lua_pushlstring(Lt,"\n",1); 509 lua_insert(Lt,-4); 510 lua_concat(Lt, 5); 511 } 512 else lua_concat(Lt, 4); 513 } 514 else lua_pop(Lt,2); 515 lua_insert(Lt,-2); 516 lua_pushvalue(Lt,-1); //set entry to nil for save memory 517 lua_pushnil(Lt); 518 lua_settable(Lt,1); 519 } 520 if ( lua_gettop(Lt) == 2 ) lua_remove(Lt,1); 521 if ( lua_isstring(Lt,1) && ( lua_objlen(Lt,1) > 0 )) temp_data_extra = PTP_CHDK_TYPE_STRING; 522 } else { 523 temp_data_extra = PTP_CHDK_TYPE_NOTHING; 524 } 525 ptp.num_param = 1; 526 ptp.param1 = temp_data_extra; 527 if ( temp_data_extra != PTP_CHDK_TYPE_STRING ) 528 { 529 if ( temp_data_extra == PTP_CHDK_TYPE_BOOLEAN ) 530 { 531 ptp.num_param = 2; 532 ptp.param2 = lua_toboolean(Lt,1); 533 } if ( temp_data_extra == PTP_CHDK_TYPE_INTEGER ) 534 { 535 ptp.num_param = 2; 536 ptp.param2 = lua_tonumber(Lt,1); 537 } 538 lua_close(Lt); 539 temp_data_kind = 0; 540 } else { 541 ptp.num_param = 2; 542 ptp.param2 = lua_objlen(Lt,1); 543 } 544 } 545 } 546 } 547 548 break; 549 } 531 break; 532 } 533 case PTP_CHDK_ReadScriptMsg: 534 { 535 ptp_script_msg *msg = dequeue_script_msg(&msg_q_out); 536 ptp.num_param = 4; 537 if(!msg) { 538 // return a fully formed message for easier handling 539 ptp.param1 = PTP_CHDK_S_MSGTYPE_NONE; 540 ptp.param2 = 0; 541 ptp.param3 = 0; 542 ptp.param4 = 4; 543 // looks like we need to send some data no matter what 544 if ( !send_ptp_data(data,"\0\0\0",4) ) 545 { 546 ptp.code = PTP_RC_GeneralError; 547 } 548 break; 549 } 550 ptp.param1 = msg->type; 551 ptp.param2 = msg->subtype; 552 ptp.param3 = msg->script_id; 553 ptp.param4 = msg->size; 554 555 // NOTE message is lost if sending failed 556 if ( !send_ptp_data(data,msg->data,msg->size) ) 557 { 558 ptp.code = PTP_RC_GeneralError; 559 } 560 free(msg); 561 break; 562 } 563 case PTP_CHDK_WriteScriptMsg: 564 { 565 int msg_size; 566 ptp_script_msg *msg; 567 ptp.num_param = 1; 568 ptp.param1 = PTP_CHDK_S_MSGSTATUS_OK; 569 if (!script_is_running()) { 570 ptp.param1 = PTP_CHDK_S_MSGSTATUS_NOTRUN; 571 } else if(param2 && param2 != script_run_id) {// check if target script for message is running 572 ptp.param1 = PTP_CHDK_S_MSGSTATUS_BADID; 573 } else if(script_msg_q_full(&msg_q_in)) { 574 ptp.param1 = PTP_CHDK_S_MSGSTATUS_QFULL; 575 } 576 577 msg_size = data->get_data_size(data->handle); 578 579 // if something was wrong, don't bother creating message, just flush 580 if(ptp.param1 != PTP_CHDK_S_MSGSTATUS_OK) { 581 flush_recv_ptp_data(data,msg_size); 582 break; 583 } 584 msg = ptp_script_create_msg(PTP_CHDK_S_MSGTYPE_USER,PTP_CHDK_TYPE_STRING,msg_size,NULL); 585 if ( !msg ) // malloc error or zero size 586 { 587 // if size is zero, things will get hosed no matter what 588 flush_recv_ptp_data(data,msg_size); 589 ptp.code = PTP_RC_GeneralError; 590 break; 591 } 592 msg->script_id = param2; 593 if ( !recv_ptp_data(data,msg->data,msg->size) ) 594 { 595 ptp.code = PTP_RC_GeneralError; 596 free(msg); 597 break; 598 } 599 if( !enqueue_script_msg(&msg_q_in,msg) ) { 600 ptp.code = PTP_RC_GeneralError; 601 free(msg); 602 } 603 break; 604 } 550 605 #endif 551 606 -
trunk/core/ptp.h
r1051 r1101 1 1 #ifndef __PTP_H 2 2 #define __PTP_H 3 4 // N.B.: not checking to see if CAM_CHDK_PTP is set as ptp.h is currently 5 // only included by ptp.c (which already checks this before including ptp.h) 6 7 #define PTP_CHDK_VERSION_MAJOR 0 // increase only with backwards incompatible changes (and reset minor) 8 #define PTP_CHDK_VERSION_MINOR 2 // increase with extensions of functionality 3 #define PTP_CHDK_VERSION_MAJOR 1 // increase only with backwards incompatible changes (and reset minor) 4 #define PTP_CHDK_VERSION_MINOR 0 // increase with extensions of functionality 9 5 /* 10 6 protocol version history 11 7 0.1 - initial proposal from mweerden, + luar 12 8 0.2 - Added ScriptStatus and ScriptSupport, based on work by ultimA 9 1.0 - removed old script result code (luar), replace with message system 13 10 */ 14 11 … … 39 36 PTP_CHDK_ExecuteScript, // data is script to be executed 40 37 // param2 is language of script 41 // param3 is for the ES flags below 42 PTP_CHDK_ScriptStatus, // Script execution status 43 // param1 CHDK_PTP_SCRIPT_STATUS_RUN is set if a script running, cleared if not 44 // all other bits and params are reserved for future use 38 // return param1 is script id, like a process id 39 // return param2 is status, PTP_CHDK_S_ERRTYPE* 40 PTP_CHDK_ScriptStatus, // Script execution status 41 // return param1 bits 42 // CHDK_PTP_SCRIPT_STATUS_RUN is set if a script running, cleared if not 43 // CHDK_PTP_SCRIPT_STATUS_MSG is set if script messages from script waiting to be read 44 // all other bits and params are reserved for future use 45 45 PTP_CHDK_ScriptSupport, // Which scripting interfaces are supported in this build 46 46 // param1 CHDK_PTP_SUPPORT_LUA is set if lua is supported, cleared if not 47 // all other bits and params are reserved for future use 47 // all other bits and params are reserved for future use 48 PTP_CHDK_ReadScriptMsg, // read next message from camera script system 49 // return param1 is chdk_ptp_s_msg_type 50 // return param2 is message subtype: 51 // for script return and users this is ptp_chdk_script_data_type 52 // for error it may be an error ptp_chdk_script_error_type 53 // return param3 is script id of script that generated the message 54 // return param4 is length of the message data 55 // return data is message. 56 // A minimum of 4 bytes of zeros is returned if there would not be data otherwise 57 PTP_CHDK_WriteScriptMsg, // write a message for scripts running on camera 58 // input param2 is target script id, 0=don't care. Messages for a non-running script will be discarded 59 // data length is handled by ptp data phase 60 // input messages do not have type or subtype, they are always a string destined for the script (similar to USER/string) 61 // output param1 is ptp_chdk_script_msg_status 48 62 } ptp_chdk_command; 49 63 50 // data types as used by TempData and ExecuteScript64 // data types as used by ReadScriptMessage 51 65 enum { 52 PTP_CHDK_TYPE_ NOTHING = 0,66 PTP_CHDK_TYPE_UNSUPPORTED = 0, // type name will be returned in data 53 67 PTP_CHDK_TYPE_NIL, 54 68 PTP_CHDK_TYPE_BOOLEAN, 55 69 PTP_CHDK_TYPE_INTEGER, 56 PTP_CHDK_TYPE_STRING 57 } ptp_chdk_ type;70 PTP_CHDK_TYPE_STRING, // NOTE tables currently returned as string 71 } ptp_chdk_script_data_type; 58 72 59 73 // TempData flags … … 64 78 // just clear 65 79 66 // ExecuteScript flags 67 #define PTP_CHDK_ES_WAIT 0x1 // do not return after script initialisation 68 // but wait until execution has finished 69 // (should only be used with short execution 70 // times) 71 #define PTP_CHDK_ES_RESULT 0x2 // only in combination with WAIT; return 72 // param1 will be the ptp_chdk_type of the 73 // code result and param2 the value (booleans 74 // and integers) or length (strings) 75 76 // Script Languages - for execution 80 // Script Languages - for execution only lua is supported for now 77 81 #define PTP_CHDK_SL_LUA 0 78 82 #define PTP_CHDK_SL_UBASIC 1 79 83 80 84 // bit flags for script status 81 #define PTP_CHDK_SCRIPT_STATUS_RUN 0x1 85 #define PTP_CHDK_SCRIPT_STATUS_RUN 0x1 // script running 86 #define PTP_CHDK_SCRIPT_STATUS_MSG 0x2 // messages waiting 82 87 // bit flags for scripting support 83 88 #define PTP_CHDK_SCRIPT_SUPPORT_LUA 0x1 84 89 90 // message types 91 enum { 92 PTP_CHDK_S_MSGTYPE_NONE = 0, // no messages waiting 93 PTP_CHDK_S_MSGTYPE_ERR, // error message 94 PTP_CHDK_S_MSGTYPE_RET, // script return value 95 PTP_CHDK_S_MSGTYPE_USER, // message queued by script 96 // TODO chdk console data ? 97 } ptp_chdk_script_msg_type; 98 99 // error subtypes for PTP_CHDK_S_MSGTYPE_ERR and script startup status 100 enum { 101 PTP_CHDK_S_ERRTYPE_NONE = 0, 102 PTP_CHDK_S_ERRTYPE_COMPILE, 103 PTP_CHDK_S_ERRTYPE_RUN, 104 } ptp_chdk_script_error_type; 105 106 // message status 107 enum { 108 PTP_CHDK_S_MSGSTATUS_OK = 0, // queued ok 109 PTP_CHDK_S_MSGSTATUS_NOTRUN, // no script is running 110 PTP_CHDK_S_MSGSTATUS_QFULL, // queue is full 111 PTP_CHDK_S_MSGSTATUS_BADID, // specified ID is not running 112 } ptp_chdk_script_msg_status; 85 113 #endif // __PTP_H -
trunk/core/script.c
r1051 r1101 467 467 } 468 468 469 static voidwait_and_end(void)469 void script_wait_and_end(void) 470 470 { 471 471 script_console_add_line("PRESS SHUTTER TO CLOSE"); … … 496 496 497 497 if (Lres != LUA_YIELD && Lres != 0) { 498 script_console_add_line( lua_tostring( Lt, -1 ) ); 499 if(conf.debug_lua_restart_on_error){ 500 lua_script_reset(); 501 script_start_gui(0); 502 } else { 503 wait_and_end(); 504 } 498 lua_script_error(Lt,1); 505 499 return; 506 500 } 507 501 508 502 if (Lres != LUA_YIELD) { 503 // add ptp result 504 lua_script_finish(Lt); 509 505 script_console_add_line(lang_str(LANG_CONSOLE_TEXT_FINISHED)); 510 506 action_pop(); … … 556 552 } 557 553 break; 554 #if defined(OPT_LUA) && defined(CAM_CHDK_PTP) 555 case AS_SCRIPT_READ_USB_MSG: 556 if(L) { // only lua supported for now 557 ptp_script_msg *msg = ptp_script_read_msg(); 558 if(action_process_delay(2) || msg) { 559 if(msg) { 560 lua_pushlstring( Lt,msg->data,msg->size); 561 } else { 562 lua_pushnil(Lt); 563 } 564 action_clear_delay(); 565 action_pop(); 566 action_pop(); 567 } 568 } 569 break; 570 case AS_SCRIPT_WRITE_USB_MSG: 571 if(L) { // only lua supported for now 572 ptp_script_msg *msg = (ptp_script_msg *)action_get_prev(2); 573 int r = ptp_script_write_msg(msg); 574 if(action_process_delay(3) || r) { 575 action_clear_delay(); 576 action_pop(); 577 action_pop(); 578 action_pop(); 579 lua_pushboolean(Lt,r); 580 } 581 } 582 break; 583 #endif 558 584 default: 559 585 if (!action_stack_standard(p) && !state_kbd_script_run) … … 630 656 if( is_lua() ) { 631 657 #ifdef OPT_LUA 632 if( !lua_script_start(script_source_str) ) { 633 script_print_screen_end(); 634 wait_and_end(); 658 if( !lua_script_start(script_source_str,0) ) { 635 659 return -1; 636 660 } … … 673 697 } 674 698 675 #ifdef OPT_LUA 676 long script_start_ptp( char *script , int keep_result ) 677 { 678 if (!lua_script_start(script)) return -1; 679 lua_keep_result = keep_result; 699 #if defined(OPT_LUA) && defined(CAM_CHDK_PTP) 700 long script_start_ptp( char *script ) 701 { 702 if (!lua_script_start(script,1)) return -1; 680 703 state_lua_kbd_first_call_to_resume = 1; 681 704 state_kbd_script_run = 1; -
trunk/include/platform.h
r1024 r1101 541 541 void init_chdk_ptp_task(); 542 542 543 typedef struct { 544 unsigned size; 545 unsigned script_id; // id of script message is to/from 546 unsigned type; 547 unsigned subtype; 548 char data[]; 549 } ptp_script_msg; 550 int ptp_script_write_msg(ptp_script_msg *msg); 551 ptp_script_msg* ptp_script_read_msg(void); 552 ptp_script_msg* ptp_script_create_msg(unsigned type, unsigned subtype, unsigned datasize, const void *data); 553 int ptp_script_write_error_msg(unsigned errtype, const char *err); 554 543 555 #endif // CAM_CHDK_PTP 544 556 -
trunk/include/script.h
r1036 r1101 32 32 //------------------------------------------------------------------- 33 33 34 extern long script_start_ptp(char *script, int keep_result);35 34 long script_stack_start(); 36 35 int script_is_running(); … … 42 41 int script_keyid_by_name( const char *name ); 43 42 #ifdef OPT_LUA 44 long script_start_ptp( char *script , int keep_result);43 long script_start_ptp( char *script ); 45 44 #endif 45 void script_wait_and_end(); 46 46 47 47 #endif
Note: See TracChangeset
for help on using the changeset viewer.