+static void send_pgup(void) {
+ fprintf(stderr,"PAGING PageUp\n");
+ send_key(XK_Prior);
+}
+static void send_pgdown(void) {
+ fprintf(stderr,"PAGING PageDown\n");
+ send_key(XK_Next);
+}
+
+static double timestamp(void) {
+ struct timeval tv;
+ int r;
+
+ r= gettimeofday(&tv,0); eassert(!r);
+ return (tv.tv_sec - tv_startup.tv_sec) +
+ (tv.tv_usec - tv_startup.tv_usec) * 1e-6;
+}
+
+static double worst_snapshot= 0.050, worst_stabilise= 0.100;
+
+static void snapshot(CanonImage **output) {
+ free(*output);
+ double a= timestamp();
+ *output= screenshot_now();
+ fprintf(stderr,"PAGING snapshot\n");
+ double b= timestamp();
+ double it_took= b-a;
+ fprintf(stderr,"PAGING snapshot took=%f\n",it_took);
+ if (it_took > worst_snapshot)
+ worst_snapshot= it_took;
+}
+
+static void snapshot_idle(void) {
+ int r;
+ r= usleep(worst_snapshot * 1e6 * 2);
+ /* spend no more than 1/3 of our time constantly snapshotting */
+ eassert(!r);
+}
+
+static int identical(const CanonImage *a, const CanonImage *b) {
+ return !(memcmp(a, b, sizeof(*a)) ||
+ memcmp(a->d, b->d, a->w * a->h));
+}
+
+static void wait_for_stability(CanonImage **output,
+ const CanonImage *previously,
+ void (*with_keypress)(void)) {
+ CanonImage *last=0;
+ /* waits longer if we're going to return an image identical to previously
+ * if previously==0, all images are considered identical to it */
+
+ double when_started= timestamp();
+ double last_change= when_started;
+ double it_took= -1;
+
+ fprintf(stderr,"PAGING wait_for_stability"
+ " worst_snapshot=%f worst_stabilise=%f\n",
+ worst_snapshot, worst_stabilise);
+
+ for (;;) {
+ snapshot(output);
+ double right_now= timestamp();
+
+ if (!last || !identical(*output,last)) {
+ fprintf(stderr,"PAGING wait_for_stability changed...\n");
+ last_change= right_now;
+ free(last); last=*output; *output=0;
+ it_took= -1;
+ } else {
+ if (it_took<0)
+ it_took= right_now - when_started;
+
+ double threshold= (worst_stabilise + worst_snapshot) * 3;
+ if (!previously || identical(*output,previously))
+ threshold *= 2; threshold += 1.5;
+
+ double stable_for= right_now - last_change;
+ fprintf(stderr,"PAGING wait_for_stability"
+ " worst_snapshot=%f worst_stabilise=%f"
+ " stable for %f thresh %f...\n",
+ worst_snapshot, worst_stabilise,
+ stable_for, threshold);
+
+ if (stable_for > threshold)
+ break;
+ }
+ if (with_keypress)
+ with_keypress();
+ snapshot_idle();
+ }
+
+ if (it_took > worst_stabilise)
+ worst_stabilise= it_took;
+
+ free(last);
+ fprintf(stderr,"PAGING wait_for_stability done.\n");
+}
+
+static void read_pages(void) {
+ CanonImage *current=0, *last;
+
+ raise_and_set_focus();
+
+ /* page to the top - keep pressing page up until the image stops changing */
+ wait_for_stability(¤t,0, send_pgup);
+
+ /* now to actually page down */
+ for (;;) {
+ fprintf(stderr,"PAGING page %d\n",npages);
+ eassert(npages < MAX_PAGES);
+ page_images[npages++]= last= current;
+ send_pgdown();
+ wait_for_stability(¤t,last, 0);
+ if (npages && /* first pagedown doesn't do much */
+ identical(current,last)) {
+ free(current);
+ break;
+ }
+ }
+ fprintf(stderr,"PAGING all done.\n");
+}
+