root/modules/scrdump.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. send_data_to_file
  2. scrdump_start
  3. scrdump_frame
  4. scrdump_finish
  5. scrdump_task
  6. scrdump_schedule
  7. scrdump_menu_schedule
  8. scrdump_menu_exit
  9. _run
  10. _module_unloader
  11. _module_can_unload

   1 #include "camera_info.h"
   2 #include "lang.h"
   3 #include "conf.h"
   4 #include "shooting.h"
   5 #include "time.h"
   6 #include "clock.h"
   7 #include "task.h"
   8 
   9 #include "gui.h"
  10 #include "gui_menu.h"
  11 #include "gui_lang.h"
  12 #include "semaphore.h"
  13 
  14 static int running = 0;
  15 
  16 typedef struct {
  17     int handle;
  18     int (*send_data)(int handle, const char *buf, int part_size, int total_size, int, int, int); // total_size will be 0 except for the first call
  19 } dummy_ptp_data;
  20 
  21 extern int live_view_get_data(dummy_ptp_data *data, int flags);
  22 
  23 int send_data_to_file(int handle, const char *buf, int part_size, int total_size, __attribute__ ((unused))int u1, __attribute__ ((unused))int u2, __attribute__ ((unused))int u3)
  24 {
  25     // TODO write on some cams may require uncached, buffers are but structs + palette may not be
  26     // only the first call has total size set, write length of following record
  27     if(total_size) {
  28         write(handle, &total_size, sizeof(total_size));
  29     }
  30     write(handle, buf, part_size);
  31     return 0;
  32 }
  33 static dummy_ptp_data ptp_data = {
  34     -1,
  35     send_data_to_file,
  36 };
  37 static char fn[32];
  38 
  39 static int scrdump_start(void)
  40 {
  41     running = 1;
  42     int fd;
  43     static int lvdump_header[] = {
  44         0x766c6863, // magic chlv
  45         8, // size of version record
  46         1, // major ver
  47         0, // minor ver
  48     };
  49     // could be desirable but unlikely to work well. Better to use PTP
  50     if ( is_video_recording() ) {
  51         return -1;
  52     }
  53     // TODO might want to allow specifying name
  54     mkdir("A/DCIM");
  55     mkdir("A/DCIM/100CANON");
  56     fd = -1;
  57     int cnt = 0;
  58     do {
  59         sprintf(fn, "A/DCIM/100CANON/CRW_%04d.JPG", cnt++);
  60         if (stat(fn,0) != 0) {
  61             fd = open(fn, O_WRONLY|O_CREAT, 0777);
  62             break;
  63         }
  64     } while(cnt<9999);
  65     if (fd>=0) {
  66         ptp_data.handle = fd;
  67         // TODO write on some cams may require uncached
  68         write(fd, lvdump_header,sizeof(lvdump_header));
  69         return 0;
  70     }
  71     return -1;
  72 }
  73 static void scrdump_frame(int what)
  74 {
  75     // TODO could limit frames, time, roll over files at specific size
  76     if(ptp_data.handle >= 0) {
  77         live_view_get_data(&ptp_data,what);
  78     }
  79 }
  80 static void scrdump_finish(void)
  81 {
  82     if(ptp_data.handle >= 0) {
  83         close(ptp_data.handle);
  84         ptp_data.handle = -1;
  85         struct utimbuf t;
  86         t.actime = t.modtime = time(NULL);
  87         utime(fn, &t);
  88     }
  89 }
  90 
  91 // commands from the gui to the dumper task
  92 enum SCRDUMP_CMD
  93 {
  94     SCRDUMP_CMD_NONE = 0, // no command
  95     SCRDUMP_CMD_SCHEDULE, // schedule a dump
  96     SCRDUMP_CMD_EXIT,     // end task, ending any current dump
  97 };
  98 
  99 #define CMD_SEM_TIMEOUT 1000
 100 static int cmd_sem;   // semaphore for command and settings
 101 static int cmd_next;  // command for dumper task, cleared on receipt
 102 
 103 typedef struct {
 104     int frame_buffers; // buffer selection, as used by live_view_get_data
 105     int frame_count;   // number of frames to grab
 106     int frame_time;    // ms between frame starts
 107     int start_delay;   // ms delay from dump request to dump start
 108 } scrdump_settings_t;
 109 
 110 scrdump_settings_t settings_next; // settings from menu on SCRDUMP_CMD_SCHEDULE
 111 
 112 // states of the dumper task
 113 enum SCRDUMP_STATE
 114 {
 115     SCRDUMP_STATE_IDLE = 0, // nothing scheduled, just poll for commands
 116     SCRDUMP_STATE_PENDING,  // dump requested, not started
 117     SCRDUMP_STATE_RUN,      // dump frames
 118 };
 119 
 120 
 121 static int scrdump_task_running;
 122 void scrdump_task(void)
 123 {
 124     static scrdump_settings_t settings;
 125 
 126     int state = SCRDUMP_STATE_IDLE;
 127     int frames_left = 0;
 128 
 129     unsigned next_action_tick = get_tick_count();
 130 
 131     while(1) {
 132         if (!TakeSemaphore(cmd_sem, CMD_SEM_TIMEOUT)) {
 133             int cmd = cmd_next;
 134             cmd_next = SCRDUMP_CMD_NONE;
 135             if(cmd == SCRDUMP_CMD_SCHEDULE) {
 136                 if(state == SCRDUMP_STATE_RUN) {
 137                     scrdump_finish();
 138                 }
 139                 memcpy(&settings,&settings_next,sizeof(settings));
 140                 next_action_tick = (unsigned)get_tick_count() + settings.start_delay;
 141                 frames_left = settings.frame_count;
 142                 state = SCRDUMP_STATE_PENDING;
 143             } else if(cmd == SCRDUMP_CMD_EXIT) {
 144                 GiveSemaphore(cmd_sem);
 145                 if(state == SCRDUMP_STATE_RUN) {
 146                     scrdump_finish();
 147                 }
 148                 break;
 149             }
 150             GiveSemaphore(cmd_sem);
 151         }
 152         if(state == SCRDUMP_STATE_PENDING) {
 153             if(next_action_tick <= (unsigned)get_tick_count()) {
 154                 // if starting dump now, schedule first frame immediately, next_action_tick unchanged
 155                 if(scrdump_start() == 0) {
 156                     state = SCRDUMP_STATE_RUN;
 157                 } else { // failed
 158                     state = SCRDUMP_STATE_IDLE;
 159                 }
 160             }
 161         }
 162         if(state == SCRDUMP_STATE_RUN) {
 163             unsigned t = (unsigned)get_tick_count();
 164             if(next_action_tick <= t) {
 165                 if(frames_left > 0) {
 166                     scrdump_frame(settings.frame_buffers);
 167                     frames_left--;
 168 
 169                     // next frame from the start of this frame
 170                     next_action_tick = t + settings.frame_time;
 171                 }
 172                 if(frames_left == 0) {
 173                     scrdump_finish();
 174                     state = SCRDUMP_STATE_IDLE;
 175                 }
 176             }
 177         }
 178         if(state == SCRDUMP_STATE_IDLE) {
 179             next_action_tick =  (unsigned)get_tick_count() + 100;
 180         }
 181 
 182         unsigned now = (unsigned)get_tick_count();
 183         if(next_action_tick >= now) {
 184             unsigned sleep_time = next_action_tick - now;
 185             // sleep a maximum of 100ms to receive commands
 186             // minimum of 10 to avoid hogging cpu
 187             if(sleep_time > 100) {
 188                 sleep_time = 100;
 189             } else if(sleep_time < 10) {
 190                 sleep_time = 10;
 191             }
 192             msleep((long)sleep_time);
 193         } else {
 194             msleep(10);
 195         }
 196     }
 197     scrdump_task_running = 0;
 198     ExitTask();
 199 }
 200 
 201 // menu values
 202 static int scrdump_frames = 1;
 203 static int scrdump_frame_delay = 10;
 204 static int scrdump_buffers = 2; // both
 205 static int scrdump_skip = 0;
 206 static int scrdump_delay = 5;
 207 
 208 void scrdump_schedule(void) {
 209     // if it times out, cmd is ignored
 210     if (!TakeSemaphore(cmd_sem, CMD_SEM_TIMEOUT)) {
 211         cmd_next = SCRDUMP_CMD_SCHEDULE;
 212         // 1 = bitmap 2 = both
 213         if(scrdump_buffers > 0) {
 214             settings_next.frame_buffers = 0x4;
 215             // skip only applies if bitmap selected
 216             // TODO could theoretically want alpha only on d6?
 217             if(!scrdump_skip) {
 218 #ifdef THUMB_FW
 219                 settings_next.frame_buffers |= 0x10;
 220 #else
 221                 settings_next.frame_buffers |= 0x8;
 222 #endif
 223             }
 224         }
 225         // viewport setting
 226         // 0 = viewport 2 = both
 227         if(scrdump_buffers == 0 || scrdump_buffers == 2) {
 228             settings_next.frame_buffers |= 1;
 229         }
 230         settings_next.frame_count = scrdump_frames;
 231         settings_next.frame_time = scrdump_frame_delay*10;
 232         settings_next.start_delay = scrdump_delay*1000;
 233         GiveSemaphore(cmd_sem);
 234     }
 235 }
 236 void scrdump_menu_schedule(void)
 237 {
 238     scrdump_schedule();
 239     gui_set_mode(&altGuiHandler);
 240 }
 241 
 242 void scrdump_menu_exit(void)
 243 {
 244     // if it times out, cmd is ignored
 245     if (!TakeSemaphore(cmd_sem, CMD_SEM_TIMEOUT)) {
 246         cmd_next = SCRDUMP_CMD_EXIT;
 247         GiveSemaphore(cmd_sem);
 248         while(scrdump_task_running) {
 249             msleep(10);
 250         }
 251         gui_set_mode(&altGuiHandler);
 252         running = 0;
 253     }
 254 }
 255 
 256 
 257 static const char* scrdump_buffer_names[] =            { "Viewprt", "Bitmap", "Both"};
 258 static CMenuItem scrdump_submenu_items[] = {
 259     MENU_ITEM   (0x5c,(int)"Schedule dump",                 MENUITEM_PROC,                  scrdump_menu_schedule,      0 ),
 260     MENU_ITEM   (0x2a,(int)"Frames",                        MENUITEM_INT|MENUITEM_F_UNSIGNED|MENUITEM_F_MINMAX,   &scrdump_frames, MENU_MINMAX(1, 1000) ),
 261     MENU_ITEM   (0x2a,(int)"Frame Time (ms*10)",            MENUITEM_INT|MENUITEM_F_UNSIGNED|MENUITEM_F_MINMAX,   &scrdump_frame_delay, MENU_MINMAX(4, 1000)),
 262     MENU_ENUM2  (0x5c,(int)"Framebuffers",                  &scrdump_buffers,               scrdump_buffer_names ),
 263 #ifdef THUMB_FW
 264     MENU_ITEM   (0x5c,(int)"Skip Opacity",                  MENUITEM_BOOL,                  &scrdump_skip,         0 ),
 265 #else
 266     MENU_ITEM   (0x5c,(int)"Skip Palette",                  MENUITEM_BOOL,                  &scrdump_skip,         0 ),
 267 #endif
 268     MENU_ITEM   (0x2a,(int)"Dump Start Delay (s)",          MENUITEM_INT|MENUITEM_F_UNSIGNED|MENUITEM_F_MINMAX,   &scrdump_delay, MENU_MINMAX(0, 60)),
 269     MENU_ITEM   (0x5c,(int)"Exit module",                   MENUITEM_PROC,                  scrdump_menu_exit,      0 ),
 270     MENU_ITEM   (0x51,LANG_MENU_BACK,                       MENUITEM_UP,                    0,                                  0 ),
 271     {0}
 272 };
 273 
 274 static CMenu scrdump_submenu = {0x2a,(int)"Screen Dump Settings", scrdump_submenu_items };
 275 
 276 int _run()
 277 {
 278     running = 1;
 279     if(!cmd_sem) {
 280         cmd_sem = CreateBinarySemaphore("ScrDumpCmd", 1);
 281     }
 282     if(!scrdump_task_running) {
 283         // lower priority (higher number) than spytask, like dng reverser
 284         CreateTask("ScrDump",0x1A,0x800,scrdump_task);
 285         scrdump_task_running = 1;
 286     }
 287 
 288     gui_activate_sub_menu(&scrdump_submenu);
 289     return 0;
 290 }
 291 
 292 #include "simple_module.h"
 293 
 294 // =========  MODULE INIT =================
 295 
 296 /***************** BEGIN OF AUXILARY PART *********************
 297   ATTENTION: DO NOT REMOVE OR CHANGE SIGNATURES IN THIS SECTION
 298  **************************************************************/
 299 
 300 //---------------------------------------------------------
 301 // PURPOSE: Finalize module operations (close allocs, etc)
 302 // RETURN VALUE: 0-ok, 1-fail
 303 //---------------------------------------------------------
 304 int _module_unloader()
 305 {
 306     if(cmd_sem) {
 307         DeleteSemaphore(cmd_sem);
 308     }
 309     return 0;
 310 }
 311 
 312 int _module_can_unload()
 313 {
 314     return (running == 0);
 315 }
 316 
 317 /******************** Module Information structure ******************/
 318 
 319 libsimple_sym _libscrdump =
 320 {
 321     {
 322         0, _module_unloader, _module_can_unload, 0, _run
 323     },
 324 };
 325 
 326 ModuleInfo _module_info = {
 327     MODULEINFO_V1_MAGICNUM,
 328     sizeof(ModuleInfo),
 329     SIMPLE_MODULE_VERSION,        // Module version
 330 
 331     ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,         // Requirements of CHDK version
 332     ANY_PLATFORM_ALLOWED,       // Specify platform dependency
 333 
 334     (int)"Screen Record",
 335     MTYPE_TOOL|MTYPE_SUBMENU_TOOL, // configure with menu
 336 
 337     &_libscrdump.base,
 338 
 339     CONF_VERSION,               // CONF version
 340     CAM_SCREEN_VERSION,         // CAM SCREEN version
 341     ANY_VERSION,                // CAM SENSOR version
 342     CAM_INFO_VERSION,           // CAM INFO version
 343     0,
 344 };
 345 
 346 /*************** END OF AUXILARY PART *******************/

/* [<][>][^][v][top][bottom][index][help] */