diff options
| -rw-r--r-- | src/scrotty.c | 81 | 
1 files changed, 57 insertions, 24 deletions
| diff --git a/src/scrotty.c b/src/scrotty.c index 850e448..d62abb1 100644 --- a/src/scrotty.c +++ b/src/scrotty.c @@ -66,33 +66,22 @@ static const char* inttable[] =   *    * @param   fbname  The framebuffer device   * @param   fbno    The number of the framebuffer + * @param   width   The width of the image + * @param   height  The height of the image   * @param   fd      The file descriptor connected to `convert`'s stdin   * @return          Zero on success, -1 on error   */ -static int save_pnm(const char* fbpath, int fbno, int fd) +static int save_pnm(const char* fbpath, int fbno, long width, long height, int fd)  {    char buf[PATH_MAX];    FILE* file; -  int saved_errno, sizefd, fbfd, r, g, b; +  int saved_errno, fbfd, r, g, b;    ssize_t got, off; -  /* Open the file with the framebuffer's dimensions. */ -  sprintf(buf, SYSDIR "/class/graphics/fb%i/virtual_size", fbno); -  if (sizefd = open(buf, O_RDONLY), sizefd < 0) -    return -1; -   -  /* Get the dimensions of the framebuffer. */ -  if (got = read(sizefd, buf, sizeof(buf) / sizeof(char) - 1), got < 0) -    return saved_errno = errno, close(sizefd), errno = saved_errno, -1; -  close(sizefd); -  /* The read content is formated as `%{1},%{2}\n`, we want it do be `%{1} %{2}\n\0`. */ -  buf[got] = '\0'; -  *strchr(buf, ',') = ' '; -      /* Open the framebuffer device for reading. */    if (fbfd = open(fbpath, O_RDONLY), fbfd < 0)      return -1; - +      /* Create a FILE*, for writing, for the image file. */    file = fdopen(fd, "w");    if (file == NULL) @@ -100,7 +89,7 @@ static int save_pnm(const char* fbpath, int fbno, int fd)    /* The PNM image should begin with `P3\n%{width} %{height}\n%{colour max=255}\n`.       ('\n' and ' ' can be exchanged at will.) */ -  fprintf(file, "P3\n%s255\n", buf); +  fprintf(file, "P3\n%l %l255\n", width, height);    /* Convert raw framebuffer data into an PNM image. */    for (off = 0;;) @@ -149,10 +138,12 @@ static int save_pnm(const char* fbpath, int fbno, int fd)   * @param   fbname    The framebuffer device   * @param   imgname   The pathname of the output image   * @param   fbno      The number of the framebuffer + * @param   width     The width of the image + * @param   height    The height of the image   * @param   execname  `argv[0]` from `main`   * @return            Zero on success, -1 on error   */ -static int save(const char* fbpath, const char* imgpath, int fbno, const char* execname) +static int save(const char* fbpath, const char* imgpath, int fbno, long width, long height, const char* execname)  {    int pipe_rw[2];    pid_t pid, reaped; @@ -161,11 +152,11 @@ static int save(const char* fbpath, const char* imgpath, int fbno, const char* e    /* Create a pipe that for sending data into the `convert` program. */    if (pipe(pipe_rw) < 0)      return -1; - +      /* Fork the process, the child will exec. `convert`. */    if (pid = fork(), pid == -1)      return saved_errno = errno, close(pipe_rw[0]), close(pipe_rw[1]), errno = saved_errno, -1; - +      /* Child process: */    if (pid == 0)      { @@ -190,23 +181,60 @@ static int save(const char* fbpath, const char* imgpath, int fbno, const char* e    close(pipe_rw[0]);    /* Create a PNM-image of the framebuffer. */ -  if (save_pnm(fbpath, fbno, pipe_rw[1]) < 0) +  if (save_pnm(fbpath, fbno, width, height, pipe_rw[1]) < 0)      return saved_errno = errno, close(pipe_rw[1]), errno = saved_errno, -1;    /* Close the write-end of the pipe. */    close(pipe_rw[1]); - +      /* Wait for `convert` to exit. */    for (reaped = 0; reaped != pid;)      if (reaped = waitpid(pid, &status, 0), reaped < 0)        return -1; - +      /* Return successfully if and only if `convert` did. */    return status == 0 ? 0 : -1;  }  /** + * Get the dimensions of the framebuffer + *  + * @param   fbno    The number of the framebuffer + * @param   width   Output parameter for the width of the image + * @param   height  Output parameter for the height of the image + * @return          Zero on success, -1 on error + */ +static int measure(int fbno, long* width, long* height) +{ +  char buf[PATH_MAX]; +  char* delim; +  int sizefd, saved_errno; +  ssize_t got; +   +  /* Open the file with the framebuffer's dimensions. */ +  sprintf(buf, SYSDIR "/class/graphics/fb%i/virtual_size", fbno); +  if (sizefd = open(buf, O_RDONLY), sizefd < 0) +    return -1; +   +  /* Get the dimensions of the framebuffer. */ +  if (got = read(sizefd, buf, sizeof(buf) / sizeof(char) - 1), got < 0) +    return saved_errno = errno, close(sizefd), errno = saved_errno, -1; +  close(sizefd); +   +  /* The read content is formated as `%{width},%{height}\n`, +     convert it to `%{width}\0%{height}\0` and parse it. */ +  buf[got] = '\0'; +  delim = strchr(buf, ','); +  *delim++ = '\0'; +  *width = atol(buf); +  *height = atol(delim); +   +  return 0; +} + + +/**   * Take a screenshow of all framebuffers   *    * @param   argc  The number of elements in `argv` @@ -218,6 +246,7 @@ int main(int argc, char* argv[])    char fbpath[PATH_MAX];    char imgpath[PATH_MAX];    int i, fbno; +  long width, height;    (void) argc; @@ -229,6 +258,10 @@ int main(int argc, char* argv[])        if (access(fbpath, F_OK))  	break; +      /* Get the size of the framebuffer. */ +      if (measure(fbno, &width, &height) < 0) +	return perror(*argv), 1; +              /* Get output pathname. */        sprintf(imgpath, "fb%i.png", fbno);        if (access(imgpath, F_OK) == 0) @@ -240,7 +273,7 @@ int main(int argc, char* argv[])  	  }        /* Take a screenshot of the current framebuffer. */ -      if (save(fbpath, imgpath, fbno, *argv) < 0) +      if (save(fbpath, imgpath, fbno, width, height, *argv) < 0)  	return perror(*argv), 1;        fprintf(stderr, "Saved framebuffer %i to %s\n", fbno, imgpath);      } | 
