/**
   * Tries to start a server on the specified port.
   *
   * @param host - host name (IP) to use
   * @param port - port to use for opened socket
   */
  private void init(String host, int port) {
    if (host != null) {
      this.host = host;
    } else {
      try {
        this.host = InetAddress.getLocalHost().getHostAddress();
      } catch (UnknownHostException xcp) {
        xcp.printStackTrace();
        this.host = null;
      }
    }

    try {
      serverSocket = new ServerSocket(port);
    } catch (IOException xcp) {
      handleFailureToCreateServerSocket(port, xcp);
      return;
    }

    // Get port being used for server socket
    this.port = serverSocket.getLocalPort();

    // Create a server thread and start it listening
    Runnable serverConnectionDaemon = new ServerConnectionDaemon();
    ThreadTools.startAsDaemon(serverConnectionDaemon, "Data Object Server Conn Daemon");

    printIfDebug(
        ".init: comm server started listening on:\n"
            + "\thost = "
            + this.host
            + "\n\tport = "
            + this.port);
  }
  private boolean tryToMakeDemuxer(final Path path) {
    PrintTools.debug(
        this,
        garbageCollectAndPrintUsedMemoryInMB(false)
            + " tryToMakeDemuxer "
            + path.getFileName().toString());

    timedOut = true;
    ThreadTools.executeWithTimeout(
        MP4VideoDemuxer.class.getSimpleName() + demuxerThreadIndex++,
        new Runnable() {
          @Override
          public void run() {
            try {
              demuxer = new MP4VideoDemuxer(path.toFile());
              timedOut = false;
            } catch (IOException e) {
              e.printStackTrace();
            }
          }
        },
        1000,
        TimeUnit.MILLISECONDS);
    if (timedOut) PrintTools.error("Demuxer.init() timed out!");
    return timedOut;
  }
  public static void startController(WandererController wandererController) {
    AcsellSetup.startStreamingData();

    YoVariableRegistry registry = new YoVariableRegistry("wanderer");
    WandererRobotModel robotModel = new WandererRobotModel(true, true);
    PeriodicThreadScheduler scheduler = new PeriodicRealtimeThreadScheduler(45);
    YoVariableServer variableServer =
        new YoVariableServer(
            WandererSingleThreadedController.class,
            scheduler,
            robotModel.getLogModelProvider(),
            robotModel.getLogSettings(),
            0.01);

    AcsellSetup wandererSetup = new AcsellSetup(variableServer);
    PriorityParameters priority = new PriorityParameters(PriorityParameters.getMaximumPriority());
    WandererSingleThreadedController communicator =
        new WandererSingleThreadedController(
            robotModel, priority, variableServer, wandererController, registry);

    variableServer.start();

    wandererSetup.start();
    communicator.start();

    ThreadTools.sleepForever();
  }
  public void startPlaying() {
    PrintTools.info(garbageCollectAndPrintUsedMemoryInMB(false) + "startPlaying() ");

    ExecutorService executor =
        Executors.newSingleThreadExecutor(
            ThreadTools.getNamedThreadFactory(
                getClass().getSimpleName() + videoPlayerThreadIndex++));
    executor.execute(
        new Runnable() {
          @Override
          public void run() {
            while (true) {
              if (currentPathToVideo == null) {
                ThreadTools.sleep(10);
              } else {
                boolean demuxerCreatedSuccessfully = tryToMakeDemuxer(currentPathToVideo);
                if (demuxerCreatedSuccessfully) {
                  playVideo(demuxer);
                } else {
                  currentPathToVideo = null;
                }

                if (demuxer != null) {
                  demuxer.delete();
                }
              }

              readyForUpdate = true;
            }
          }
        });
    executor.shutdown();
  }
  public void playVideo(MP4VideoDemuxer demuxer) {
    try {
      long sleepTimeMillisPerFrame = (long) (1000.0 / FRAME_RATE);
      long previousTimeMillis = System.currentTimeMillis();

      demuxer.seekToFrame(0);
      YUVPicture picture;
      while (true) {
        picture = demuxer.getNextFrame();

        if (picture == null) {
          if (LOOP_FOREVER) {
            demuxer.seekToFrame(0);
            return;
          } else {
            break;
          }
        }

        long currentTimeMillis = System.currentTimeMillis();

        doTheNextFrame(picture);

        long timeDelta = currentTimeMillis - previousTimeMillis;
        long timeToSleep = sleepTimeMillisPerFrame - timeDelta;
        if (timeToSleep < 1) timeToSleep = 1;
        if (timeToSleep > sleepTimeMillisPerFrame) timeToSleep = sleepTimeMillisPerFrame;

        ThreadTools.sleep(timeToSleep);
        previousTimeMillis = currentTimeMillis;
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  public void findEntryBoxAndEnterValue(String name, double value) {
    JPanelFixture entryBoxArrayPanel = focusedWindow.panel("EntryBoxArrayPanel");
    JPanelFixture enumEntryBox = entryBoxArrayPanel.panel(name + "_YoEntryBox");
    JTextComponentFixture textBox = enumEntryBox.textBox();

    // For some reason deleting, and then entering doesn't seem to work. It only deletes part of the
    // text!?
    // Instead here we have to call setText.
    // textBox.deleteText();
    // textBox.enterText(Double.toString(value) + "\n");

    textBox.setText(Double.toString(value));
    textBox.enterText("\n");
    ThreadTools.sleep(500);
  }
  public static void main(String[] args) {
    final ArrayList<MP4VideoDemuxer> demuxers = new ArrayList<>();

    for (i = 0; i < 1000; i++) {
      ThreadTools.executeWithTimeout(
          "demuxer" + i,
          new Runnable() {
            @Override
            public void run() {
              MP4VideoDemuxer demuxer;
              try {
                System.out.println("i = " + i);
                demuxer =
                    new MP4VideoDemuxer(
                        Paths.get(
                                "20150920_0009_Atlas_DRCPushRecoveryMultiStepTest.testMultiStepForwardAndContinueWalking.mp4")
                            .toFile());

                for (int j = 0; j < 5; j++) {
                  demuxer.getNextFrame();
                }
                demuxer.delete();
                demuxers.add(demuxer);
              } catch (IOException e) {
                e.printStackTrace();
              }
            }
          },
          500,
          TimeUnit.MILLISECONDS);
    }

    System.gc();

    ThreadTools.sleepSeconds(10.0);
  }
  public SimulationGUITestFixture(final SimulationConstructionSet scs) {
    FailOnThreadViolationRepaintManager.install();

    this.scs = scs;

    JFrame frame =
        GuiActionRunner.execute(
            new GuiQuery<JFrame>() {
              protected JFrame executeInEDT() throws SimulationExceededMaximumTimeException {
                JFrame jFrame = scs.getJFrame();

                return jFrame;
              }
            });
    focusedWindow = new FrameFixture(frame);

    ThreadTools.sleep(1000);
    focusedWindow.focus();

    mainSCSWindow = focusedWindow;
  }
  public void connect() {
    //      try
    //      {
    //
    //      }
    //      catch (IOException e)
    //      {
    //         throw new RuntimeException(e);
    //      }

    boolean isConnected = false;
    System.out.println("[GazeboOutputWriter] Connecting to " + address);
    while (!isConnected) {
      try {
        channel = SocketChannel.open();
        channel.configureBlocking(true);
        channel.socket().setKeepAlive(true);
        channel.socket().setReuseAddress(true);
        channel.socket().setSoLinger(false, 0);
        channel.socket().setTcpNoDelay(true);

        channel.connect(address);
        isConnected = true;
        sendInitialState();
      } catch (IOException e) {
        System.out.println("Connect failed.");
        try {
          channel.close();
        } catch (IOException e1) {
          e1.printStackTrace();
        }
        ThreadTools.sleep(3000);
        isConnected = false;
      }
    }

    System.out.println("[GazeboOutputWriter] Connected");
    System.out.println("num of joints = " + joints.size());
  }
  @After
  public void destroySimulationAndRecycleMemory() {
    if (simulationTestingParameters.getKeepSCSUp()) {
      ThreadTools.sleepForever();
    }

    // Do this here in case a test fails. That way the memory will be recycled.
    if (drcFlatGroundWalkingTrack != null) {
      drcFlatGroundWalkingTrack.destroySimulation();
      drcFlatGroundWalkingTrack = null;
    }

    if (blockingSimulationRunner != null) {
      blockingSimulationRunner.destroySimulation();
      blockingSimulationRunner = null;
    }

    pushRobotController = null;
    doubleSupportStartConditions = null;
    pushCondition = null;
    MemoryTools.printCurrentMemoryUsageAndReturnUsedMemoryInMB(
        getClass().getSimpleName() + " after test.");
  }
  @After
  public void destroySimulationAndRecycleMemory() {
    if (simulationTestingParameters.getKeepSCSUp()) {
      ThreadTools.sleepForever();
    }

    // Do this here in case a test fails. That way the memory will be recycled.
    if (drcSimulationTestHelper != null) {
      drcSimulationTestHelper.destroySimulation();
      drcSimulationTestHelper = null;
    }

    if (behaviorCommunicatorClient != null) {
      behaviorCommunicatorClient.close();
    }

    if (behaviorCommunicatorServer != null) {
      behaviorCommunicatorServer.close();
    }

    MemoryTools.printCurrentMemoryUsageAndReturnUsedMemoryInMB(
        getClass().getSimpleName() + " after test.");
  }