aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DEPENDENCIES1
-rw-r--r--TODO2
-rw-r--r--po/sv.po33
-rw-r--r--src/kern-linux.c91
-rw-r--r--src/kern.h5
-rw-r--r--src/png.c1
-rw-r--r--src/scrotty.c31
7 files changed, 92 insertions, 72 deletions
diff --git a/DEPENDENCIES b/DEPENDENCIES
index 491cdf4..99ee910 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -7,6 +7,7 @@ RUNTIME DEPENDENCIES:
BUILD DEPENDENCIES:
+ linux-api-headers
make
coreutils
glibc (any libc with getopt_long)
diff --git a/TODO b/TODO
index 42d3998..70fddbe 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,5 @@
Take the screenshot of the framebuffers more simultaneously. (async)
-Support framebuffers with other depths.
-
Investigate Hurd support.
Make a release-test script that validates that the
diff --git a/po/sv.po b/po/sv.po
index 7f1e7bb..92191be 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: scrotty 1.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-12-12 09:08+0100\n"
+"POT-Creation-Date: 2015-12-13 16:52+0100\n"
"PO-Revision-Date: 2015-12-07 18:50+0100\n"
"Last-Translator: Mattias Andrée <maandree@member.fsf.org>\n"
"Language-Team: none\n"
@@ -17,61 +17,66 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: src/scrotty.c:224
+#: src/scrotty.c:223
#, c-format
msgid "Saved framebuffer %i to %s.\n"
msgstr "Bildrutebuffert %i sparad till %s.\n"
-#: src/scrotty.c:358 src/scrotty.c:361 src/scrotty.c:367 src/scrotty.c:373
-#: src/scrotty.c:377 src/scrotty.c:383 src/scrotty.c:391
+#: src/scrotty.c:359 src/scrotty.c:362 src/scrotty.c:368 src/scrotty.c:374
+#: src/scrotty.c:378 src/scrotty.c:384 src/scrotty.c:392
#, c-format
msgid "%s: %s. Type '%s --help' for help.\n"
msgstr "%s: %s. Kör '%s --help' för hjälp.\n"
-#: src/scrotty.c:358
+#: src/scrotty.c:359
msgid "--device is used twice"
msgstr "--device förkommer mer än en gång"
-#: src/scrotty.c:361 src/scrotty.c:367
+#: src/scrotty.c:362 src/scrotty.c:368
msgid "Invalid device number, not a non-negative integer"
msgstr "Ogiltigt enhetsnummer, måste vara ett ickenegativt heltal"
-#: src/scrotty.c:373
+#: src/scrotty.c:374
msgid "--exec is used twice"
msgstr "--exec förkommer mer än en gång"
-#: src/scrotty.c:377
+#: src/scrotty.c:378
msgid "Invalid input"
msgstr "Ogiltig indata"
-#: src/scrotty.c:383
+#: src/scrotty.c:384
msgid "FILENAME-PATTERN is used twice"
msgstr "FILNAMNSMÖNSTER förekommer mer än en gång"
-#: src/scrotty.c:391
+#: src/scrotty.c:392
msgid "--exec cannot be combined with piping"
msgstr "--exec kan inte kombineras med rördragning"
-#: src/scrotty.c:403
+#: src/scrotty.c:404
#, c-format
msgid "%s: It looks like you are inside a display server. If this is correct, what you see is probably not what you get.\n"
msgstr "%s: Det ser ut som att du är innan för en grafikserver. Om detta är korrect, vad de ser är troligtvis inte vad du får.\n"
-#: src/scrotty.c:413
+#: src/scrotty.c:412
#, c-format
msgid "%s: %s: %s\n"
msgstr "%s: %s: %s\n"
-#: src/scrotty.c:421
+#: src/scrotty.c:422
#, c-format
msgid "%s: The selected device does not exist.\n"
msgstr "%s: Vald enhet existerar inte.\n"
-#: src/kern-linux.c:41
+#: src/kern-linux.c:52
#, c-format
msgid "%s: Unable to find a framebuffer. If you have a file named %s/MAKEDEV, run it with '-d /dev/fb' as root, or try running '%s'.\n"
msgstr "%s: Kunde inte hitta någon bildrutebuffert. Om filen %s/MAKEDEV finns ditt system, kör den med '-d /dev/fb' som root, eller testa att köra '%s'.\n"
+#: src/kern-linux.c:106
+#, c-format
+msgid "%s: Unsupported framebuffer configurations: pixels are not encoded in whole bytes.\n"
+msgstr "%s: Ickestödd bildrutebuffertsinställningar: pixlar är inte kodade i hela byte:ar.\n"
+
#: src/info.c:32
#, fuzzy, c-format
msgid ""
diff --git a/src/kern-linux.c b/src/kern-linux.c
index e6ca1a2..071d3fc 100644
--- a/src/kern-linux.c
+++ b/src/kern-linux.c
@@ -20,6 +20,9 @@
#include "kern.h"
#include "png.h"
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+
/**
@@ -27,6 +30,14 @@
*/
const int alt_fbpath_limit = 2;
+struct data
+{
+ unsigned long start;
+ unsigned long end;
+ long hblank;
+ unsigned long position;
+};
+
/**
@@ -67,53 +78,49 @@ get_fbpath (int altpath, int fbno)
* Get the dimensions of a framebuffer.
*
* @param fbno The number of the framebuffer.
- * @param fbpath The path to the framebuffer device..
+ * @param fbfd File descriptor for framebuffer device.
* @param width Output parameter for the width of the image.
* @param height Output parameter for the height of the image.
* @parma data Additional data to pass to `convert_fb_to_png`.
* @return Zero on success, -1 on error.
*/
int
-measure (int fbno, char *restrict fbpath, long *restrict width,
- long *restrict height, void **restrict data)
+measure (int fbno, int fbfd, long *restrict width, long *restrict height, void **restrict data)
{
- static char buf[sizeof (SYSDIR "/class/graphics/fb/virtual_size") + 3 * sizeof(int)];
- /* The string "/class/graphics/fb/virtual_size" is large enought for the call (*) "*/
- char *delim;
- int sizefd = -1;
- ssize_t got;
- int saved_errno;
+ static struct data d;
+ struct fb_fix_screeninfo fixinfo;
+ struct fb_var_screeninfo varinfo;
+ unsigned long int linelength;
- /* Open the file with the framebuffer's dimensions. */
- sprintf (buf, "%s/class/graphics/fb%i/virtual_size", SYSDIR, fbno);
- sizefd = open (buf, O_RDONLY);
- if (sizefd == -1)
- FILE_FAILURE (buf);
+ if (ioctl (fbfd, FBIOGET_FSCREENINFO, &fixinfo))
+ goto fail;
- /* Get the dimensions of the framebuffer. */
- got = read (sizefd, buf, sizeof (buf) / sizeof (char) - 1); /* (*) */
- if (got < 0)
+ if (ioctl (fbfd, FBIOGET_VSCREENINFO, &varinfo))
goto fail;
- 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);
+ *width = varinfo.xres;
+ *height = varinfo.yres;
- return 0;
+ if (varinfo.bits_per_pixel & 7)
+ {
+ fprintf(stderr, _("%s: Unsupported framebuffer configurations: "
+ "pixels are not encoded in whole bytes.\n"), execname);
+ exit(1);
+ }
+ linelength = fixinfo.line_length / (varinfo.bits_per_pixel / 8);
+ d.start = varinfo.yoffset * linelength;
+ d.start += varinfo.xoffset;
+ d.end = d.start + linelength * varinfo.yres;
+ d.hblank = linelength - *width;
+ d.position = 0;
+
+ /* TODO depth support */
+
+ *data = &d;
+ return 0;
fail:
- saved_errno = errno;
- if (sizefd >= 0)
- close (sizefd);
- errno = saved_errno;
return -1;
-
- (void) fbpath;
}
@@ -133,16 +140,19 @@ measure (int fbno, char *restrict fbpath, long *restrict width,
* @param data Data from `measure`.
* @return Zero on success, -1 on error.
*/
-int convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char *restrict buf,
- size_t n, long width3, size_t *restrict adjustment, long *restrict state,
- void *restrict data)
+int
+convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char *restrict buf, size_t n,
+ long width3, size_t *restrict adjustment, long *restrict state, void *restrict data)
{
const uint32_t *restrict pixel;
int r, g, b;
size_t off;
long x3 = *state;
+ struct data d = *(struct data *)data;
+ unsigned long pos = d.position;
+ long lineend = width3 + d.hblank * 3;
- for (off = 0; off < n; off += 4)
+ for (off = 0; off < n; off += 4, pos++)
{
/* A pixel in the framebuffer is formatted as `%{blue}%{green}%{red}%{x}`
in big-endian binary, or `%{x}%{red}%{green}%{blue}` in little-endian binary. */
@@ -151,9 +161,13 @@ int convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char
g = (*pixel >> 8) & 255;
b = (*pixel >> 0) & 255;
- SAVE_PNG_PIXEL (pixbuf, x3, r, g, b);
+ if ((pos < d.start) || (pos >= d.end))
+ continue;
+
+ if (x3 < width3)
+ SAVE_PNG_PIXEL (pixbuf, x3, r, g, b);
x3 += 3;
- if (x3 == width3)
+ if (x3 == lineend)
{
SAVE_PNG_ROW (pngbuf, pixbuf);
x3 = 0;
@@ -162,6 +176,7 @@ int convert_fb_to_png (png_struct *pngbuf, png_byte *restrict pixbuf, const char
*adjustment = (off != n ? 4 : 0);
*state = x3;
+ ((struct data *)data)->position = pos;
return 0;
}
diff --git a/src/kern.h b/src/kern.h
index 5bd191c..3810c5f 100644
--- a/src/kern.h
+++ b/src/kern.h
@@ -55,14 +55,13 @@ char *get_fbpath (int altpath, int fbno);
* Get the dimensions of a framebuffer.
*
* @param fbno The number of the framebuffer.
- * @param fbpath The path to the framebuffer device..
+ * @param fbfd File descriptor for framebuffer device.
* @param width Output parameter for the width of the image.
* @param height Output parameter for the height of the image.
* @parma data Additional data to pass to `convert_fb_to_png`.
* @return Zero on success, -1 on error.
*/
-int measure (int fbno, char *restrict fbpath, long *restrict width,
- long *restrict height, void **restrict data);
+int measure (int fbno, int fbfd, long *restrict width, long *restrict height, void **restrict data);
/**
* Convert read data from a framebuffer to PNG pixel data.
diff --git a/src/png.c b/src/png.c
index ad889e1..504cdf0 100644
--- a/src/png.c
+++ b/src/png.c
@@ -71,6 +71,7 @@ save_png (int fbfd, long width, long height, int imgfd, void *restrict data)
goto fail;
/* Initialise PNG write, and write head. */
+ errno = 0;
if (setjmp (png_jmpbuf(pngbuf))) /* Failing libpng calls jump here. */
goto fail;
png_init_io (pngbuf, file);
diff --git a/src/scrotty.c b/src/scrotty.c
index bce7036..5ab39fe 100644
--- a/src/scrotty.c
+++ b/src/scrotty.c
@@ -66,7 +66,7 @@ static int try_alt_fbpath = 0;
/**
* Create an image of a framebuffer.
*
- * @param fbname The framebuffer device.
+ * @param fbfd File descriptor for framebuffer device.
* @param imgname The pathname of the output image, `NULL` for piping.
* @param width The width of the image.
* @param height The height of the image.
@@ -74,10 +74,10 @@ static int try_alt_fbpath = 0;
* @return Zero on success, -1 on error.
*/
static int
-save (const char *fbpath, const char *imgpath, long width,
+save (int fbfd, const char *imgpath, long width,
long height, void *restrict data)
{
- int imgfd = STDOUT_FILENO, fbfd = -1, piping = (imgpath == NULL);
+ int imgfd = STDOUT_FILENO, piping = (imgpath == NULL);
int saved_errno;
/* Open output file. */
@@ -89,11 +89,6 @@ save (const char *fbpath, const char *imgpath, long width,
FILE_FAILURE (imgpath);
}
- /* Open the framebuffer device for reading. */
- fbfd = open (fbpath, O_RDONLY);
- if (fbfd == -1)
- FILE_FAILURE (fbpath);
-
/* Save image. */
if (save_png (fbfd, width, height, imgfd, data) < 0)
goto fail;
@@ -105,8 +100,6 @@ save (const char *fbpath, const char *imgpath, long width,
fail:
saved_errno = errno;
- if (fbfd >= 0)
- close (fbfd);
if ((imgfd >= 0) && !piping)
close (imgfd);
errno = saved_errno;
@@ -198,6 +191,7 @@ save_fb (int fbno, const char *filepattern, const char *execpattern)
char *execargs = NULL;
long width, height;
void *data = NULL;
+ int fbfd = -1;
int rc = 0, saved_errno = 0;
/* Get pathname for framebuffer, and stop if we have read all existing ones. */
@@ -205,8 +199,13 @@ save_fb (int fbno, const char *filepattern, const char *execpattern)
if (access (fbpath, F_OK))
return 1;
+ /* Open the framebuffer device for reading. */
+ fbfd = open (fbpath, O_RDONLY);
+ if (fbfd == -1)
+ FILE_FAILURE (fbpath);
+
/* Get the size of the framebuffer. */
- if (measure (fbno, fbpath, &width, &height, &data) < 0)
+ if (measure (fbno, fbfd, &width, &height, &data) < 0)
goto fail;
/* Get output pathname. */
@@ -218,7 +217,7 @@ save_fb (int fbno, const char *filepattern, const char *execpattern)
}
/* Take a screenshot of the current framebuffer. */
- if (save (fbpath, imgpath, width, height, data) < 0)
+ if (save (fbfd, imgpath, width, height, data) < 0)
goto fail;
if (imgpath)
fprintf (stderr, _("Saved framebuffer %i to %s.\n"), fbno, imgpath);
@@ -242,6 +241,8 @@ save_fb (int fbno, const char *filepattern, const char *execpattern)
saved_errno = errno;
rc = -1;
done:
+ if (fbfd >= 0)
+ close (fbfd);
free (execargs);
free (imgpath);
return errno = saved_errno, rc;
@@ -407,11 +408,11 @@ main (int argc, char *argv[])
return 0;
fail:
- if (failure_file == NULL)
- perror (execname);
- else
+ if (failure_file != NULL)
fprintf (stderr, _("%s: %s: %s\n"),
execname, strerror (errno), failure_file);
+ else if (errno)
+ perror (execname);
return 1;
no_fb: