All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mike10004.xvfbmanager.XwdScreenshooter Maven / Gradle / Ivy

The newest version!
package com.github.mike10004.xvfbmanager;

import io.github.mike10004.subprocess.ProcessMonitor;
import io.github.mike10004.subprocess.ProcessResult;
import io.github.mike10004.subprocess.ProcessTracker;
import io.github.mike10004.subprocess.Subprocess;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Objects.requireNonNull;

/**
 * Implementation of a screenshooter that executes an X utility.
 * Uses {@code xwd} to capture a screenshot of the
 * framebuffer. The raw output file (as returned by {@link Screenshot#asByteSource()}
 * is in {@code xwd} format. Use the {@code xwdtopnm} program to export it to a PNM file.
 */
public class XwdScreenshooter implements Screenshooter {

    private static final String PROG_XWD = "xwd";

    private static final ImmutableSet requiredPrograms = ImmutableSet.of(PROG_XWD);

    public static Iterable getRequiredPrograms() {
        return requiredPrograms;
    }

    private static final Logger log = LoggerFactory.getLogger(XwdScreenshooter.class);

    private final ProcessTracker processTracker;
    private final String display;
    private final File outputDir;

    public XwdScreenshooter(ProcessTracker processTracker, String display, File outputDir) {
        this.processTracker = requireNonNull(processTracker);
        this.display = checkNotNull(display);
        this.outputDir = checkNotNull(outputDir);
    }

    @Override
    public XwdFileScreenshot capture() throws IOException, XvfbException {
        File xwdFile = File.createTempFile("screenshot", ".xwd", outputDir);
        ProcessMonitor xwdMonitor = Subprocess.running(PROG_XWD)
                .args("-display", display, "-root", "-silent", "-out", xwdFile.getAbsolutePath())
                .build()
                .launcher(processTracker)
                .outputStrings(Charset.defaultCharset()) // xwd presumably uses platform charset
                .launch();
        ProcessResult xwdResult;
        try {
            xwdResult = xwdMonitor.await();
        } catch (InterruptedException e) {
            log.error("interrupted while waiting for " + PROG_XWD, e);
            ProcessKilling.termOrKill(xwdMonitor.destructor(), 100, TimeUnit.MILLISECONDS);
            throw new ScreenshooterException("failed to take screenshot due to interruption", e);
        }
        log.debug("xwd process finished: {}", xwdResult);
        String stderrText = StringUtils.abbreviate(xwdResult.content().stderr(), 512);
        if (xwdResult.exitCode() != 0) {
            throw new ScreenshooterException("xwd failed with code " + xwdResult.exitCode() + " and stderr: " + stderrText);
        }
        return XwdFileScreenshot.from(xwdFile);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy