public static void main(String[] args) throws Exception {
    List<String> msgfilecontents = new ArrayList<String>();
    if (args.length > 0) msgfilecontents = readLines(new FileReader(args[0]));
    POMsgSource msgsrc = new POMsgSource(msgfilecontents);
    final List<String> msgstrings = msgsrc.getMsgStrings();
    String screenshotSavePath = "";
    List<String> existingScreenshotPaths = new ArrayList<String>();
    if (args.length > 1) {
      screenshotSavePath = args[1] + "/";
      File screenshotDir = new File(screenshotSavePath);
      if (!screenshotDir.exists()) {
        screenshotDir.mkdirs();
      } else {
        for (String filename : screenshotDir.list()) {
          filename = screenshotSavePath + filename;
          existingScreenshotPaths.add(filename);
        }
      }
    }
    ScreenshotTaker st = new ScreenshotTaker(msgsrc, screenshotSavePath);
    st.guisetup();
    st.addNewAnnotations(new HashMap<String, MsgAnnotation>());
    for (String filename : existingScreenshotPaths) {
      // add those messages that are covered by existing screenshots to matchedMsgStrs
      System.out.println(filename);
      List<ImgMatch> matches = Main.getImgMatches(filename);
      HashMap<String, MsgAnnotation> annotations =
          Main.msgToAnnotationsTwoPass(msgstrings, GCollectionUtils.singleElemList(matches));
      st.addNewAnnotations(annotations);
      st.processedImages.add(st.hashable(matches));
    }
    st.show();
    st.runme();

    // long prev_screenshot_time = 0;

  }
  public void runme() throws Exception {
    BufferedImage img = null;
    boolean imgCaptured = false;
    String imgMatchesHashable = null;
    List<ImgMatch> imgMatches = null;

    while (true) {
      if (frame.isFocused()) {
        imgCaptured = false;
        continue;
      }
      if (!recordingCheckbox.isSelected()) {
        imgCaptured = false;
        continue;
      }

      // if (curtime < prev_screenshot_time + 250) {
      //    continue;
      // }
      // captureNewImage();
      if (!imgCaptured) {
        img = captureNewImage();
        if (sameImages(img, prevImg)) continue;
        imgMatches = Main.getImgMatches(img, "");
        imgMatchesHashable = hashable(imgMatches);
      }

      if (frame.isFocused()) {
        imgCaptured = false;
        continue;
      }
      if (!recordingCheckbox.isSelected()) {
        imgCaptured = false;
        continue;
      }

      boolean containsNewMsgStrs = false;
      int origNumMatchedMsgStrs = 0;

      BufferedImage displayImage = null;
      if (msgstrings.size() == 0) {
        displayImage = img;
      } else {

        /*
        if (imgMatches.size() > 300) {
            System.err.println("too many words");
            continue;
        }
        */

        final MutableValue<HashMap<String, MsgAnnotation>> retv =
            new MutableValue<HashMap<String, MsgAnnotation>>();
        final List<ImgMatch> imgMatchesF = imgMatches;
        Thread tx =
            new Thread(
                new Runnable() {

                  @Override
                  public void run() {
                    // TODO Auto-generated method stub
                    try {
                      retv.value =
                          Main.msgToAnnotationsTwoPass(
                              msgstrings, GCollectionUtils.singleElemList(imgMatchesF));
                    } catch (Exception e) {
                      e.printStackTrace();
                    }
                  }
                });
        tx.start();
        boolean interrupted = false;

        while (tx.isAlive()) {
          if (!recordingCheckbox.isSelected()) continue;
          if (frame.isFocused()) continue;
          BufferedImage newImg = captureNewImage();
          if (frame.isFocused()) continue;
          if (!recordingCheckbox.isSelected()) continue;
          if (!sameImages(img, newImg)) {
            List<ImgMatch> newImgMatches = Main.getImgMatches(newImg, "");
            String newImgMatchesHashable = hashable(newImgMatches);
            if (!processedImages.contains(newImgMatchesHashable)) {
              interrupted = true;
              tx.interrupt();
              imgCaptured = true;
              img = newImg;
              imgMatches = newImgMatches;
              imgMatchesHashable = newImgMatchesHashable;
              break;
            }
          }
          tx.join(1000);
        }

        // tx.join();
        HashMap<String, MsgAnnotation> annotations = retv.value;
        if (interrupted || annotations == null) continue;

        imgCaptured = false;
        processedImages.add(imgMatchesHashable);

        displayImage = deepCopy(img);
        origNumMatchedMsgStrs = matchedMsgStrs.size();

        addNewAnnotations(annotations);

        annotateScreenshot(displayImage, annotations);

        // HashMap<String, MsgAnnotation> annotations = Main.msgToAnnotationsWithTimeout(msgstrings,
        // GCollectionUtils.singleElemList(imgMatches), 3000);
        // if (annotations == null)
        // 	continue;

      }
      if (origNumMatchedMsgStrs != matchedMsgStrs.size()) {
        // updateMatchCount();
        containsNewMsgStrs = true;
      }
      //  prev_screenshot_time = curtime;
      if (savingScreenshots && containsNewMsgStrs) {
        while (new File(screenshotSavePath + screenshotNum + ".png").exists()) {
          ++screenshotNum;
        }
        ImageIO.write(img, "png", new File(screenshotSavePath + screenshotNum + ".png"));
      }
      picLabel.setIcon(new ImageIcon(displayImage));
      prevImg = img;
    }
  }