Changeset 1083


Ignore:
Timestamp:
03/07/11 04:46:52 (2 years ago)
Author:
reyalP
Message:

temporary branch for ptp message system

Location:
branches/reyalp-ptp
Files:
9 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/reyalp-ptp/core/action_stack.c

    r1050 r1083  
    169169} 
    170170 
     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 
     175int 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 
     192void action_clear_delay(void) 
     193{ 
     194    action_stacks[active_stack]->delay_target_ticks = 0; 
     195} 
     196 
    171197// Defines some standard operations. Returns false if it could not process anything. 
    172198// Can only be called from an action stack 
     
    188214        break; 
    189215    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(); 
    207221        } 
    208222        break; 
     
    239253        break; 
    240254    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(); 
    261262        } 
    262263        break; 
  • branches/reyalp-ptp/core/action_stack.h

    r1032 r1083  
    1919    AS_WAIT_CLICK, 
    2020    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, size, &data 
    2224}; 
    2325 
     
    3234void action_wait_for_click(int timeout); 
    3335void action_pop(); 
     36int action_process_delay(int p); 
     37void action_clear_delay(void); 
    3438long action_get_prev(int p); 
    3539int action_stack_standard(long p); 
  • branches/reyalp-ptp/core/luascript.c

    r1036 r1083  
    1515#include "action_stack.h" 
    1616#include "motion_detector.h" 
     17#include "ptp.h" 
    1718 
    1819#include "../lib/lua/lstate.h"  // for L->nCcalls, baseCcalls 
     
    2021lua_State* L; 
    2122lua_State* Lt; 
    22 int lua_keep_result; 
    23  
    24 void *lua_consume_result() 
    25 { 
    26   lua_State* r = L; 
     23 
     24static int lua_script_is_ptp; 
     25static int yield_hook_enabled; 
     26 
     27static void lua_script_disable_yield_hook(void) { 
     28    yield_hook_enabled = 0; 
     29} 
     30static void lua_script_enable_yield_hook(void) { 
     31    yield_hook_enabled = 1; 
     32} 
     33 
     34// create a ptp message from the given stack index 
     35// incompatible types will return a TYPE_UNSUPPORTED message 
     36static ptp_script_msg *lua_create_usb_msg( lua_State* L, int index, unsigned msgtype) { 
     37    // TODO maybe we should just pass the lua type constants 
     38    unsigned datatype, datasize = 4; 
     39    int ivalue = 0; 
     40    void *data = &ivalue; 
     41    int ltype = lua_type(L,index); 
     42    switch(ltype) { 
     43        case LUA_TNONE: 
     44            return NULL; // nothing on the stack, no message generated 
     45        break; 
     46        case LUA_TNIL: 
     47            datatype = PTP_CHDK_TYPE_NIL; 
     48        break; 
     49        case LUA_TBOOLEAN: 
     50            datatype = PTP_CHDK_TYPE_BOOLEAN; 
     51            ivalue = lua_toboolean(L,index); 
     52        break; 
     53        case LUA_TNUMBER: 
     54            datatype = PTP_CHDK_TYPE_INTEGER; 
     55            ivalue = lua_tonumber(L,index); 
     56        break; 
     57        case LUA_TSTRING: 
     58            datatype = PTP_CHDK_TYPE_STRING; 
     59            data = (char *)lua_tolstring(L,index,&datasize); 
     60        break; 
     61        // TODO this converts to a string and returns as STRING, format as described at  
     62        // http://chdk.setepontos.com/index.php?topic=4338.msg62606#msg62606 
     63        // for compatibility with current PTPCAM/PTPCAMGUI implementation 
     64        // later we should switch to a proper serialized table with it's own return type 
     65        case LUA_TTABLE:  
     66            lua_script_disable_yield_hook(); // don't want to yeild while converting 
     67            lua_getglobal(L, "usb_msg_table_to_string"); // push function 
     68            lua_pushvalue(L, index); // copy specified index to top of stack 
     69            lua_pcall(L,1,1,0); // this will leave an error message as a string on the stack if call fails 
     70            lua_script_enable_yield_hook(); 
     71                        // an empty table will be returned as an empty string 
     72                        // a non-string should never show up here 
     73            if ( !(lua_isstring(L,-1) /*&& ( lua_objlen(L,-1) > 0 )*/)) {  
     74                return NULL; 
     75            } 
     76            datatype = PTP_CHDK_TYPE_STRING; 
     77            data = (char *)lua_tolstring(L,-1,&datasize); 
     78            lua_pop(L,1); 
     79        break; 
     80        default: 
     81            datatype = PTP_CHDK_TYPE_UNSUPPORTED; 
     82            data = (char *)lua_typename(L,ltype); // return type name as message data 
     83            datasize = strlen(data); 
     84    } 
     85    return ptp_script_create_msg(msgtype,datatype,datasize,data); 
     86} 
     87 
     88void lua_script_reset() 
     89{ 
     90  lua_close( L ); 
    2791  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; 
    3992} 
    4093 
    4194static void lua_count_hook(lua_State *L, lua_Debug *ar) 
    4295{ 
    43   if( L->nCcalls <= L->baseCcalls ) 
     96  if( L->nCcalls <= L->baseCcalls && yield_hook_enabled ) 
    4497    lua_yield( L, 0 ); 
    4598} 
    4699 
    47 int lua_script_start( char const* script ) 
    48 { 
    49   lua_keep_result = 0; 
     100void lua_script_error(lua_State *Lt,int runtime) 
     101{ 
     102    const char *err = lua_tostring( Lt, -1 ); 
     103    script_console_add_line( err ); 
     104    if(runtime) { 
     105        if(lua_script_is_ptp) { 
     106            ptp_script_write_error_msg(PTP_CHDK_S_ERRTYPE_RUN, err); 
     107            script_end(); 
     108        } else if(conf.debug_lua_restart_on_error) { 
     109            lua_script_reset(); 
     110            script_start_gui(0); 
     111        } else { 
     112            script_wait_and_end(); 
     113        } 
     114    } else { 
     115        if(lua_script_is_ptp) { 
     116            ptp_script_write_error_msg(PTP_CHDK_S_ERRTYPE_COMPILE, err); 
     117            lua_script_reset(); 
     118        } else { 
     119            script_print_screen_end(); 
     120            script_wait_and_end(); 
     121        } 
     122    } 
     123} 
     124 
     125 
     126// TODO more stuff from script.c should be moved here 
     127void lua_script_finish(lua_State *L)  
     128{ 
     129    if(lua_script_is_ptp) { 
     130        // send all return values as RET messages 
     131        int i,end = lua_gettop(L); 
     132        for(i=1;i<=end; i++) { 
     133            // if the queue is full return values will be silently discarded 
     134            // incompatible types will be returned as TYPE_UNSUPPORTED to preserve expected number and order of return values 
     135            ptp_script_write_msg(lua_create_usb_msg(L,i,PTP_CHDK_S_MSGTYPE_RET));  
     136        } 
     137    } 
     138} 
     139 
     140int lua_script_start( char const* script, int ptp ) 
     141{ 
     142  lua_script_is_ptp = ptp; 
    50143  L = lua_open(); 
    51144  luaL_openlibs( L ); 
     
    55148  lua_setfield( L, LUA_REGISTRYINDEX, "Lt" ); 
    56149  if( luaL_loadstring( Lt, script ) != 0 ) { 
    57     script_console_add_line( lua_tostring( Lt, -1 ) ); 
    58     lua_script_reset(); 
     150    lua_script_error(Lt,0); 
    59151    return 0; 
    60152  } 
    61153  lua_sethook(Lt, lua_count_hook, LUA_MASKCOUNT, 1000 ); 
     154  lua_script_enable_yield_hook(); 
    62155  return 1; 
    63156} 
     
    13871480        return 1; 
    13881481} 
     1482 
     1483#ifdef CAM_CHDK_PTP 
     1484/* 
     1485msg = read_usb_msg([timeout]) 
     1486read a message from the CHDK ptp interface. 
     1487Returns the next available message as a string, or nil if no messages are available 
     1488If timeout is given and not zero, wait until a message is available or timeout expires 
     1489*/ 
     1490static int luaCB_read_usb_msg( lua_State* L ) 
     1491{ 
     1492  int timeout = luaL_optnumber( L, 1, 0 ); 
     1493  if(timeout) { 
     1494    action_push(timeout); 
     1495    action_push(AS_SCRIPT_READ_USB_MSG); 
     1496    return lua_yield( L, 0 ); 
     1497  } 
     1498  ptp_script_msg *msg = ptp_script_read_msg(); 
     1499  if(msg) { 
     1500    lua_pushlstring(L,msg->data,msg->size); 
     1501    return 1; 
     1502  } 
     1503  lua_pushnil(L); 
     1504  return 1; 
     1505} 
     1506 
     1507/* 
     1508status = write_usb_msg(msg,[timeout]) 
     1509writes a message to the CHDK ptp interface 
     1510msg may be nil, boolean, number, string or table (table has some restrictions, will be converted to string) 
     1511returns true if the message was queued successfully, otherwise false 
     1512if timeout is set and not zero, wait until message is written or timeout expires 
     1513NOTE strings will not include a terminating NULL, must be handled by recipient 
     1514*/ 
     1515static int luaCB_write_usb_msg( lua_State* L ) 
     1516{ 
     1517  ptp_script_msg *msg; 
     1518  int timeout = luaL_optnumber( L, 2, 0 ); 
     1519  // TODO would it be better to either ignore this or return nil ? 
     1520  // a write_usb_msg(function_which_returns_no_value()) is an error in this case 
     1521  // replacing with nil might be more luaish 
     1522  if(lua_gettop(L) < 1) { 
     1523    return luaL_error(L,"missing argument"); 
     1524  } 
     1525  msg=lua_create_usb_msg(L,1,PTP_CHDK_S_MSGTYPE_USER); 
     1526  // for user messages, trying to create a message from an incompatible type throws an error 
     1527  if(msg->subtype == PTP_CHDK_TYPE_UNSUPPORTED) { 
     1528    free(msg); 
     1529    return luaL_error(L,"unsupported type"); 
     1530  } 
     1531  if(!msg) { 
     1532    return luaL_error(L,"failed to create message"); 
     1533  } 
     1534  if(timeout) { 
     1535    action_push(timeout); 
     1536    action_push((int)msg); 
     1537    action_push(AS_SCRIPT_WRITE_USB_MSG); 
     1538    return lua_yield( L, 0 ); 
     1539  } 
     1540  lua_pushboolean(L,ptp_script_write_msg(msg));  
     1541  return 1; 
     1542} 
     1543#endif 
    13891544 
    13901545void register_lua_funcs( lua_State* L ) 
     
    15541709#endif 
    15551710   FUNC(reboot); 
    1556 } 
     1711#ifdef CAM_CHDK_PTP 
     1712   FUNC(read_usb_msg); 
     1713   FUNC(write_usb_msg); 
     1714   luaL_dostring(L,"function usb_msg_table_to_string(t)" 
     1715                    " local v2s=function(v)" 
     1716                        " local t=type(v)" 
     1717                        " if t=='string' then return v end" 
     1718                        " if t=='number' or t=='boolean' or t=='nil' then return tostring(v) end" 
     1719                        " return '' end" 
     1720                    " local r=''" 
     1721                    " for k,v in pairs(t) do" 
     1722                        " local s,vs=''" 
     1723                        " if type(v)=='table' then" 
     1724                            " for i=1,table.maxn(v) do" 
     1725                            " s=s..'\\t'..v2s(v[i]) end" 
     1726                        " else" 
     1727                            " vs=v2s(v)" 
     1728                            " if #vs then s=s..'\\t'..vs end" 
     1729                        " end" 
     1730                        " vs=v2s(k)" 
     1731                        " if #vs>0 and #s>0 then r=r..vs..s..'\\n' end" 
     1732                    " end" 
     1733                    " return r" 
     1734                   " end"); 
     1735 
     1736#endif 
     1737} 
  • branches/reyalp-ptp/core/luascript.h

    r1021 r1083  
    44#include "lua.h" 
    55 
    6 void *lua_consume_result(); 
    76void lua_script_reset(); 
    8 int lua_script_start( char const* script ); 
     7int lua_script_start( char const* script,int is_ptp ); 
     8void lua_script_error( lua_State* L,int runtime ); 
     9void lua_script_finish( lua_State* L ); 
    910extern void register_lua_funcs( lua_State* L ); 
    1011// run the "restore" function at the end of a script 
     
    1314extern lua_State* L; 
    1415extern lua_State* Lt; 
    15 extern int lua_keep_result; 
    1616 
    1717#endif 
  • branches/reyalp-ptp/core/ptp.c

    r1078 r1083  
    1414#include "script.h" 
    1515#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 
     18static unsigned script_run_id;  
    2719#endif 
    2820 
     
    6456 
    6557  return 1; 
     58} 
     59 
     60// camera will shut down if you ignore a recv data phase 
     61static 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); 
    6678} 
    6779 
     
    94106} 
    95107 
     108#ifdef OPT_LUA 
     109// TODO this could be a generic ring buffer of words 
     110#define PTP_SCRIPT_MSG_Q_LEN 16 
     111typedef 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 
     118ptp_script_msg_q msg_q_in; // messages to pc from script 
     119ptp_script_msg_q msg_q_out; // messages to script from pc 
     120 
     121unsigned 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 
     128unsigned script_msg_q_full(ptp_script_msg_q *q) { 
     129  return (script_msg_q_next(q->w) == q->r); 
     130} 
     131 
     132unsigned script_msg_q_empty(ptp_script_msg_q *q) { 
     133  return (q->w == q->r); 
     134} 
     135 
     136int 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 
     150ptp_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 
     161ptp_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 
     177int 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 
     182ptp_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} 
     199int 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 
    96212static int handle_ptp( 
    97213               int h, ptp_data *data, int opcode, int sess_id, int trans_id, 
     
    100216  static union { 
    101217    char *str; 
    102 #ifdef OPT_LUA 
    103     lua_State *lua_state; 
    104 #endif 
    105218  } temp_data; 
    106219  static int temp_data_kind = 0; // 0: nothing, 1: ascii string, 2: lua object 
     
    115228  ptp.num_param = 0; 
    116229   
     230  // TODO calling this on every PTP command is not good, 
     231  // since it figures out free memory by repeatedly malloc'ing! 
    117232  buf_size=core_get_free_memory()>>1; 
    118233 
     
    139254#ifdef OPT_SCRIPTING 
    140255      ptp.param1 |= script_is_running()?PTP_CHDK_SCRIPT_STATUS_RUN:0; 
     256      ptp.param1 |= (!script_msg_q_empty(&msg_q_out))?PTP_CHDK_SCRIPT_STATUS_MSG:0; 
    141257#endif 
    142258      break; 
     
    210326          l = temp_data_extra; 
    211327        } 
    212 #ifdef OPT_LUA 
    213         else { // temp_data_kind == 2 
    214           s = lua_tolstring(get_lua_thread(temp_data.lua_state),1,&l); 
    215         } 
    216 #endif 
    217328 
    218329        if ( !send_ptp_data(data,s,l) ) 
     
    227338          free(temp_data.str); 
    228339        } 
    229 #ifdef OPT_LUA 
    230         else if ( temp_data_kind == 2 ) 
    231         { 
    232           lua_close(temp_data.lua_state); 
    233         } 
    234 #endif 
    235340        temp_data_kind = 0; 
    236341 
     
    257362          free(temp_data.str); 
    258363        } 
    259 #ifdef OPT_LUA 
    260         else if ( temp_data_kind == 2 ) 
    261         { 
    262           lua_close(temp_data.lua_state); 
    263         } 
    264 #endif 
    265364        temp_data_kind = 0; 
    266365      } 
     
    392491 
    393492#ifdef OPT_LUA 
     493    // TODO this should flush data even if scripting isn't supported 
    394494    case PTP_CHDK_ExecuteScript: 
    395495      { 
    396496        int s; 
    397497        char *buf; 
     498 
     499        script_run_id++; 
     500        ptp.num_param = 2; 
     501        ptp.param1 = script_run_id; 
    398502 
    399503        if ( param2 != PTP_CHDK_SL_LUA ) 
     
    414518        recv_ptp_data(data,buf,s); 
    415519 
    416         long script_action_stack = script_start_ptp(buf, param3&PTP_CHDK_ES_RESULT); 
     520        // error details will be passed in a message 
     521        if (script_start_ptp(buf) < 0) { 
     522          ptp.param2 = PTP_CHDK_S_ERRTYPE_COMPILE; 
     523        } else { 
     524                  ptp.param2 = PTP_CHDK_S_ERRTYPE_NONE; 
     525                } 
    417526 
    418527        free(buf); 
    419528         
    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       } 
     529        break; 
     530      } 
     531    case PTP_CHDK_ReadScriptMsg: 
     532    { 
     533      ptp_script_msg *msg = dequeue_script_msg(&msg_q_out); 
     534      ptp.num_param = 4; 
     535      if(!msg) { 
     536        // return a fully formed message for easier handling 
     537        ptp.param1 = PTP_CHDK_S_MSGTYPE_NONE; 
     538        ptp.param2 = 0; 
     539        ptp.param3 = 0; 
     540        ptp.param4 = 4; 
     541        // looks like we need to send some data no matter what 
     542        if ( !send_ptp_data(data,"\0\0\0",4) ) 
     543        { 
     544          ptp.code = PTP_RC_GeneralError; 
     545        } 
     546        break; 
     547      } 
     548      ptp.param1 = msg->type; 
     549      ptp.param2 = msg->subtype; 
     550      ptp.param3 = msg->script_id; 
     551      ptp.param4 = msg->size; 
     552 
     553      // NOTE message is lost if sending failed 
     554      if ( !send_ptp_data(data,msg->data,msg->size) ) 
     555      { 
     556        ptp.code = PTP_RC_GeneralError; 
     557      } 
     558      free(msg); 
     559      break; 
     560    } 
     561    case PTP_CHDK_WriteScriptMsg: 
     562    { 
     563      int msg_size; 
     564      ptp_script_msg *msg; 
     565      ptp.num_param = 1; 
     566      ptp.param1 = PTP_CHDK_S_MSGSTATUS_OK; 
     567      if (!script_is_running()) { 
     568        ptp.param1 = PTP_CHDK_S_MSGSTATUS_NOTRUN; 
     569      } 
     570      // check if target script for message is running 
     571      if(param2 && param2 != script_run_id) { 
     572        ptp.param1 = PTP_CHDK_S_MSGSTATUS_BADID; 
     573      } 
     574      if(script_msg_q_full(&msg_q_in)) { 
     575        ptp.param1 = PTP_CHDK_S_MSGSTATUS_QFULL; 
     576      } 
     577 
     578      msg_size = data->get_data_size(data->handle); 
     579 
     580      // if something was wrong, don't bother creating message, just flush 
     581      if(ptp.param1 != PTP_CHDK_S_MSGSTATUS_OK) { 
     582        flush_recv_ptp_data(data,msg_size); 
     583        break; 
     584      } 
     585      msg = ptp_script_create_msg(PTP_CHDK_S_MSGTYPE_USER,PTP_CHDK_TYPE_STRING,msg_size,NULL); 
     586      if ( !msg ) // malloc error or zero size 
     587      { 
     588        // if size is zero, things will get hosed no matter what 
     589        flush_recv_ptp_data(data,msg_size); 
     590        ptp.code = PTP_RC_GeneralError; 
     591        break; 
     592      } 
     593      msg->script_id = param2; 
     594      if ( !recv_ptp_data(data,msg->data,msg->size) ) 
     595      { 
     596        ptp.code = PTP_RC_GeneralError; 
     597        free(msg); 
     598        break; 
     599      } 
     600      if( !enqueue_script_msg(&msg_q_in,msg) ) { 
     601        ptp.code = PTP_RC_GeneralError; 
     602        free(msg); 
     603      } 
     604      break; 
     605    } 
    550606#endif 
    551607 
  • branches/reyalp-ptp/core/ptp.h

    r1051 r1083  
    11#ifndef __PTP_H 
    22#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 
    95/* 
    106protocol version history 
    1170.1 - initial proposal from mweerden, + luar 
    1280.2 - Added ScriptStatus and ScriptSupport, based on work by ultimA 
     91.0 - removed old script result code (luar), replace with message system 
    1310*/ 
    1411 
     
    3936  PTP_CHDK_ExecuteScript,   // data is script to be executed 
    4037                            // 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 
    4545  PTP_CHDK_ScriptSupport,   // Which scripting interfaces are supported in this build 
    4646                            // 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 message type: none, script error, script return, user, TODO chdk console data 
     50                            // return param2 is message subtype: for script return and users this is chdk_ptp_type, for error it may be an error code (TBD) 
     51                            // return param3 is script id of script that generated the message 
     52                            // return param4 is length of the message data 
     53                            // return data is message. 
     54                            // A minum of 4 bytes of zeros is returned if there would not be data otherwise 
     55  PTP_CHDK_WriteScriptMsg,  // write a message for scripts running on camera 
     56                            // input param2 is target script id, 0=don't care. Messages for a non-running script will be discarded 
     57                            // data length is handled by ptp data phase 
     58                            // input messages do not have type or subtype, they are always a string destined for the script (similar to USER/string) 
     59                            // output param1 is status (OK,queue full,wrong script,script not running) 
    4860} ptp_chdk_command; 
    4961 
    50 // data types as used by TempData and ExecuteScript 
     62// data types as used by ReadScriptMessage 
    5163enum { 
    52   PTP_CHDK_TYPE_NOTHING = 0, 
     64  PTP_CHDK_TYPE_UNSUPPORTED = 0, // type name will be returned in data 
    5365  PTP_CHDK_TYPE_NIL, 
    5466  PTP_CHDK_TYPE_BOOLEAN, 
    5567  PTP_CHDK_TYPE_INTEGER, 
    56   PTP_CHDK_TYPE_STRING 
     68  PTP_CHDK_TYPE_STRING, // NOTE tables currently returned as string 
    5769} ptp_chdk_type; 
    5870 
     
    6476                                   // just clear 
    6577 
    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 
     78// Script Languages - for execution only lua is supported for now 
    7779#define PTP_CHDK_SL_LUA    0 
    7880#define PTP_CHDK_SL_UBASIC 1 
    7981 
    8082// bit flags for script status 
    81 #define PTP_CHDK_SCRIPT_STATUS_RUN   0x1 
     83#define PTP_CHDK_SCRIPT_STATUS_RUN   0x1 // script running 
     84#define PTP_CHDK_SCRIPT_STATUS_MSG   0x2 // messages waiting 
    8285// bit flags for scripting support 
    8386#define PTP_CHDK_SCRIPT_SUPPORT_LUA  0x1 
    8487 
     88// message types 
     89#define PTP_CHDK_S_MSGTYPE_NONE  0 // no messages waiting 
     90#define PTP_CHDK_S_MSGTYPE_ERR   1 // error message 
     91#define PTP_CHDK_S_MSGTYPE_RET   2 // script return value 
     92#define PTP_CHDK_S_MSGTYPE_USER  3 // message queued by script 
     93 
     94// error subtypes for PTP_CHDK_S_MSGTYPE_ERR and script startup status 
     95#define PTP_CHDK_S_ERRTYPE_NONE    0 
     96#define PTP_CHDK_S_ERRTYPE_COMPILE 1 
     97#define PTP_CHDK_S_ERRTYPE_RUN     2 
     98 
     99// message status 
     100#define PTP_CHDK_S_MSGSTATUS_OK     0 // queued ok 
     101#define PTP_CHDK_S_MSGSTATUS_NOTRUN 1 // no script is running 
     102#define PTP_CHDK_S_MSGSTATUS_QFULL  2 // queue is full 
     103#define PTP_CHDK_S_MSGSTATUS_BADID  3 // specified ID is not running 
    85104#endif // __PTP_H 
  • branches/reyalp-ptp/core/script.c

    r1051 r1083  
    467467} 
    468468 
    469 static void wait_and_end(void) 
     469void script_wait_and_end(void) 
    470470{ 
    471471        script_console_add_line("PRESS SHUTTER TO CLOSE"); 
     
    496496 
    497497            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); 
    505499                return; 
    506500            } 
    507501 
    508502            if (Lres != LUA_YIELD) { 
     503                // add ptp result 
     504                lua_script_finish(Lt); 
    509505                script_console_add_line(lang_str(LANG_CONSOLE_TEXT_FINISHED)); 
    510506                action_pop(); 
     
    556552            } 
    557553            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 
    558584        default: 
    559585            if (!action_stack_standard(p) && !state_kbd_script_run) 
     
    630656    if( is_lua() ) { 
    631657#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) ) { 
    635659            return -1; 
    636660        } 
     
    673697} 
    674698 
    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) 
     700long script_start_ptp( char *script ) 
     701{ 
     702  if (!lua_script_start(script,1)) return -1; 
    680703  state_lua_kbd_first_call_to_resume = 1; 
    681704  state_kbd_script_run = 1; 
  • branches/reyalp-ptp/include/platform.h

    r1024 r1083  
    541541void init_chdk_ptp_task(); 
    542542 
     543typedef 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; 
     550int ptp_script_write_msg(ptp_script_msg *msg); 
     551ptp_script_msg* ptp_script_read_msg(void); 
     552ptp_script_msg* ptp_script_create_msg(unsigned type, unsigned subtype, unsigned datasize, const void *data); 
     553int ptp_script_write_error_msg(unsigned errtype, const char *err); 
     554 
    543555#endif // CAM_CHDK_PTP 
    544556 
  • branches/reyalp-ptp/include/script.h

    r1036 r1083  
    3232//------------------------------------------------------------------- 
    3333 
    34 extern long script_start_ptp(char *script, int keep_result); 
    3534long script_stack_start(); 
    3635int script_is_running(); 
     
    4241int script_keyid_by_name( const char *name ); 
    4342#ifdef OPT_LUA 
    44 long script_start_ptp( char *script , int keep_result ); 
     43long script_start_ptp( char *script ); 
    4544#endif 
     45void script_wait_and_end(); 
    4646 
    4747#endif 
Note: See TracChangeset for help on using the changeset viewer.