chiark / gitweb /
mention --upload at top of README
[ypp-sc-tools.main.git] / pctb / pages.c
index 0081161..482c959 100644 (file)
@@ -301,7 +301,7 @@ static int identical(const Snapshot *a, const Snapshot *b) {
     return 0;
 
   int compare_to= a->h;
-  if (max_relevant_y && compare_to > max_relevant_y)
+  if (max_relevant_y>=0 && compare_to > max_relevant_y)
     compare_to= max_relevant_y;
   
   return !memcmp(a->data, b->data, a->w * 3 * compare_to);
@@ -321,45 +321,57 @@ static void wait_for_stability(Snapshot **output,
   va_start(al,fmt);
 
   Snapshot *last=0;
+  int nidentical=0;
   /* waits longer if we're going to return an image identical to previously
    * if previously==0, all images are considered identical to it */
 
   char *doing;
   sysassert( vasprintf(&doing,fmt,al) >=0 );
-  progress("%s",doing);
 
   debugf("PAGING  wait_for_stability"
          "  last_input=%f previously=%p `%s'\n",
          last_input, previously, doing);
 
+  double min_interval= 25000; /*us*/
   for (;;) {
-    double at_snapshot= timestamp();
-    double need_sleep= min_update_allowance - (at_snapshot - last_input);
-    if (need_sleep > 0) { delay(need_sleep); continue; }
+    progress_spinner("%s",doing);
+    
+    double since_last_input= timestamp() - last_input;
+    double this_interval= min_interval - since_last_input;
 
-    snapshot(output);
+    if (this_interval >= 0)
+      usleep(this_interval);
 
-    if (!with_keypress &&
-       !(previously && identical(*output,previously))) {
-      debugf("PAGING  wait_for_stability  simple\n");
-      break;
-    }
+    snapshot(output);
 
-    if (last && identical(*output,last)) {
-      debugf("PAGING  wait_for_stability  stabilised\n");
-      break;
+    if (!last) {
+      debugf("PAGING  wait_for_stability first...\n");
+      last=*output; *output=0;
+    } else if (!identical(*output,last)) {
+      debugf("PAGING  wait_for_stability changed...\n");
+      free(last); last=*output; *output=0;
+      nidentical=0;
+      if (!with_keypress) {
+       min_interval *= 3.0;
+       min_interval += 0.5;
+      }
+    } else {
+      nidentical++;
+      int threshold=
+       !previously ? 3 :
+       identical(*output,previously) ? 5
+       : 1;
+      debugf("PAGING  wait_for_stability nidentical=%d threshold=%d\n",
+             nidentical, threshold);
+      if (nidentical >= threshold)
+       break;
+
+      min_interval += 0.5;
+      min_interval *= 2.0;
     }
-    
-    progress_spinner("%s",doing);
-
-    debugf("PAGING  wait_for_stability  retry\n");
-
-    free_snapshot(&last); last=*output; *output=0;
 
     if (with_keypress)
       with_keypress();
-
-    delay(0.5);
   }
 
   free_snapshot(&last);
@@ -485,24 +497,18 @@ static void set_focus_commodity(void) {
 static CanonImage *convert_page(Snapshot *sn, RgbImage *ri) {
   CanonImage *im;
 
-  fprintf(screenshot_file,
-         "P6\n"
-         "%d %d\n"
-         "255\n", sn->w, sn->h);
+  fwrite_ppmraw(screenshot_file, sn);
+  if (ri) memcpy(ri->data, sn->data, ri->h * ri->w * 3);
 
+  unsigned char *pixel= sn->data;
   CANONICALISE_IMAGE(im, sn->w, sn->h, {
-    int i;
-    rgb= 0;
-    for (i=0; i<3; i++) {
-      rgb <<= 8;
-      unsigned long sample= RI_PIXEL(sn,x,y)[i];
-      rgb |= sample;
-      fputc(sample, screenshot_file);
-    }
-    if (ri)
-      CANONIMG_ALSO_STORERGB(ri);
+    rgb=
+      (pixel[0] << 16) |
+      (pixel[1] <<  8) |
+      (pixel[2]      );
+    pixel += 3;
   });
-
+    
   sysassert(!ferror(screenshot_file));
   sysassert(!fflush(screenshot_file));
 
@@ -547,6 +553,7 @@ static void prepare_ypp_client(void) {
 
 void take_screenshots(void) {
   Snapshot *current=0, *last=0;
+  RgbImage *page0_store;
 
   prepare_ypp_client();
   
@@ -555,6 +562,8 @@ void take_screenshots(void) {
   wait_for_stability(&current,0, send_pgup_many,
                     "paging up to top of commodity list...");
 
+  page0_rgbimage= page0_store= alloc_rgb_image(current->w, current->h);
+
   /* now to actually page down */
   for (;;) {
     debugf("paging page %d\n",npages);
@@ -563,8 +572,8 @@ void take_screenshots(void) {
       fatal("Paging down seems to generate too many pages - max is %d.",
            MAX_PAGES);
     
-    page_images[npages]= convert_page(current, 0);
-    free_snapshot(&last); last=current; current=0;
+    page_images[npages]= convert_page(current, page0_store);
+    free_snapshot(&last); last=current; current=0; page0_store=0;
 
     debugf("PAGING page %d converted\n",npages);
 
@@ -586,6 +595,7 @@ void take_screenshots(void) {
 
   debugf("PAGING all done.\n");
   progress_log("collected %d screenshots.",npages);
+  assert(!page0_store);
 }    
 
 void take_one_screenshot(void) {
@@ -605,112 +615,116 @@ void set_yppclient_window(unsigned long wul) {
 
 DEBUG_DEFINE_SOME_DEBUGF(findypp,debugfind)
 
+static int nfound;
+static Atom wm_name;
+static int screen;
+
+static void findypp_recurse(int depth, int targetdepth, Window w) {
+  unsigned int nchildren;
+  int i;
+  Window *children=0;
+  Window gotroot, gotparent;
+
+  static const char prefix[]= "Puzzle Pirates - ";
+  static const char onthe[]= " on the ";
+  static const char suffix[]= " ocean";
+#define S(x) (sizeof((x))-1)
+
+  debugfind("FINDYPP %d/%d screen %d  %*s %lx",
+           depth,targetdepth,screen,
+           depth,"",(unsigned long)w);
+  
+  if (depth!=targetdepth) {
+    xassert( XQueryTree(disp,w,
+                       &gotroot,&gotparent,
+                       &children,&nchildren) );
+    debugfind(" nchildren=%d\n",nchildren);
+  
+    for (i=0; i<nchildren; i++) {
+      Window child= children[i];
+      findypp_recurse(depth+1, targetdepth, child);
+    }
+    XFree(children);
+    return;
+  }
+    
+
+  int gotfmt;
+  Atom gottype;
+  unsigned long len, gotbytesafter;
+  char *title;
+  unsigned char *gottitle=0;
+  xassert( !XGetWindowProperty(disp,w, wm_name,0,512, False,
+                              AnyPropertyType,&gottype, &gotfmt, &len,
+                              &gotbytesafter, &gottitle) );
+  title= (char*)gottitle;
+
+  if (DEBUGP(findypp)) {
+    debugfind(" gf=%d len=%lu gba=%lu \"", gotfmt,len,gotbytesafter);
+    char *p;
+    for (p=title; p < title+len; p++) {
+      char c= *p;
+      if (c>=' ' && c<=126) fputc(c,debug);
+      else fprintf(debug,"\\x%02x",c & 0xff);
+    }
+    fputs("\": ",debug);
+  }
+
+#define REQUIRE(pred)                                                  \
+  if (!(pred)) { debugfind(" failed test  %s\n", #pred); return; }     \
+  else
+
+  REQUIRE( gottype!=None );
+  REQUIRE( len );
+  REQUIRE( gotfmt==8 );
+
+  REQUIRE( len >= S(prefix) + 1 + S(onthe) + 1 + S(suffix) );
+
+  char *spc1= strchr(  title        + S(prefix), ' ');  REQUIRE(spc1);
+  char *spc2= strrchr((title + len) - S(suffix), ' ');  REQUIRE(spc2);
+
+  REQUIRE( (title + len) - spc1  >= S(onthe)  + S(suffix) );
+  REQUIRE(  spc2         - title >= S(prefix) + S(onthe) );
+
+  REQUIRE( !memcmp(title,                   prefix, S(prefix)) );
+  REQUIRE( !memcmp(title + len - S(suffix), suffix, S(suffix))  );
+  REQUIRE( !memcmp(spc1,                    onthe,  S(onthe))  );
+
+#define ASSIGN(what, start, end)                       \
+  what= masprintf("%.*s", (end)-(start), start);       \
+  if (o_##what) REQUIRE( !strcasecmp(o_##what, what) );        \
+  else
+
+  ASSIGN(ocean,  spc1 + S(onthe),   (title + len) - S(suffix));
+  ASSIGN(pirate, title + S(prefix),  spc1);
+
+  debugfind(" YES!\n");
+  id= w;
+  nfound++;
+  progress_log("found YPP client (0x%lx):"
+              " %s ocean - %s.",
+              (unsigned long)id, ocean, pirate);
+}
+
 void find_yppclient_window(void) {
-  Window root, gotroot, gotparent;
-  int screen;
-  int nfound=0;
+  int targetdepth;
+
+  nfound=0;
   
   if (id) return;
   
   progress("looking for YPP client window...");
 
-  static const char prefix[]= "Puzzle Pirates - ";
-  static const char onthe[]= " on the ";
-  static const char suffix[]= " ocean";
-#define S(x) (sizeof((x))-1)
+  xassert( (wm_name= XInternAtom(disp,"WM_NAME",True)) != None);
 
-  Atom wm_name= XInternAtom(disp,"WM_NAME",True);
-  xassert(wm_name != None);
-
-  for (screen=0; screen<ScreenCount(disp); screen++) {
-    debugfind("FINDYPP screen %d\n", screen);
-    root= RootWindow(disp,screen);
-    unsigned int nchildren1;
-    Window *children1=0;
-
-    xassert( XQueryTree(disp,root,
-                 &gotroot,&gotparent,
-                 &children1,&nchildren1) );
-    debugfind("FINDYPP screen %d nchildren1=%d\n", screen, nchildren1);
-
-    int i;
-    for (i=0; i<nchildren1; i++) {
-      Window w1= children1[i];
-      unsigned int nchildren2;
-      Window *children2=0;
-
-      xassert( XQueryTree(disp,w1,
-                         &gotroot,&gotparent,
-                         &children2,&nchildren2) );
-      debugfind("FINDYPP screen %d c1[%2d]=0x%08lx nchildren2=%d\n",
-               screen, i, (unsigned long)w1, nchildren2);
-
-      int j;
-      for (j=-1; j<(int)nchildren2; j++) {
-       Window w2= j<0 ? w1 : children2[j];
-       debugfind("FINDYPP screen %d c1[%2d]=0x%08lx c2[%2d]=0x%08lx",
-                 screen, i, (unsigned long)w1, j, (unsigned long)w2);
-
-       int gotfmt;
-       Atom gottype;
-       unsigned long len, gotbytesafter;
-       char *title;
-       unsigned char *gottitle=0;
-       xassert( !XGetWindowProperty(disp,w2, wm_name,0,512, False,
-                                    AnyPropertyType,&gottype, &gotfmt, &len,
-                                    &gotbytesafter, &gottitle) );
-       title= (char*)gottitle;
-
-       if (DEBUGP(findypp)) {
-         debugfind(" gf=%d len=%lu gba=%lu \"", gotfmt,len,gotbytesafter);
-         char *p;
-         for (p=title; p < title+len; p++) {
-           char c= *p;
-           if (c>=' ' && c<=126) fputc(c,debug);
-           else fprintf(debug,"\\x%02x",c & 0xff);
-         }
-         fputs("\": ",debug);
-       }
-
-#define REQUIRE(pred)                                                     \
-        if (!(pred)) { debugfind(" failed test  %s\n", #pred); continue; } \
-        else
-
-       REQUIRE( gottype!=None );
-       REQUIRE( len );
-       REQUIRE( gotfmt==8 );
-
-       REQUIRE( len >= S(prefix) + 1 + S(onthe) + 1 + S(suffix) );
-
-       char *spc1= strchr(  title        + S(prefix), ' ');  REQUIRE(spc1);
-       char *spc2= strrchr((title + len) - S(suffix), ' ');  REQUIRE(spc2);
-
-       REQUIRE( (title + len) - spc1  >= S(onthe)  + S(suffix) );
-       REQUIRE(  spc2         - title >= S(prefix) + S(onthe) );
-
-       REQUIRE( !memcmp(title,                   prefix, S(prefix)) );
-       REQUIRE( !memcmp(title + len - S(suffix), suffix, S(suffix))  );
-       REQUIRE( !memcmp(spc1,                    onthe,  S(onthe))  );
-
-#define ASSIGN(what, start, end)                               \
-       what= masprintf("%.*s", (end)-(start), start);          \
-       if (o_##what) REQUIRE( !strcasecmp(o_##what, what) );   \
-       else
-
-       ASSIGN(ocean,  spc1 + S(onthe),   (title + len) - S(suffix));
-       ASSIGN(pirate, title + S(prefix),  spc1);
-
-       debugfind(" YES!\n");
-       id= w2;
-       nfound++;
-       progress_log("found YPP client (0x%lx):"
-                    " %s ocean - %s.",
-                    (unsigned long)id, ocean, pirate);
-      }
-      if (children2) XFree(children2);
+  for (targetdepth=1; targetdepth<4; targetdepth++) {
+    for (screen=0; screen<ScreenCount(disp); screen++) {
+      debugfind("FINDYPP screen %d\n", screen);
+      findypp_recurse(0,targetdepth, RootWindow(disp,screen));
     }
-    if (children1) XFree(children1);
+    if (nfound) break;
   }
+
   if (nfound>1)
     fatal("Found several possible YPP clients.   Close one,\n"
          " disambiguate with --pirate or --ocean,"