From f05b6cd55c63876cf0e5ee7f4f106a26a46f8b66 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 27 Nov 2015 10:39:18 -0500 Subject: [PATCH] Implement swaygrab for still images --- sway.1.txt | 2 +- swaygrab.1.txt | 9 ++++++++ swaygrab/main.c | 56 +++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/sway.1.txt b/sway.1.txt index f8d01ec3..c0715841 100644 --- a/sway.1.txt +++ b/sway.1.txt @@ -81,4 +81,4 @@ source contributors. For more information about sway development, see See Also -------- -**sway**(5) +**sway**(5) **swaymsg**(1) **swaygrab**(1) diff --git a/swaygrab.1.txt b/swaygrab.1.txt index 68bea3e8..54a1c37a 100644 --- a/swaygrab.1.txt +++ b/swaygrab.1.txt @@ -31,6 +31,15 @@ Options Use the specified socket path. Otherwise, swaymsg will ask sway where the socket is (which is the value of $SWAYSOCK, then of $I3SOCK). +Examples +-------- + +swaygrab HDMI-A-1 output.png:: + Grab the contents of HDMI-A-1 and write to output.png. + +swaygrab -c HDMI-A-1 output.webm:: + Capture a webm of HDMI-A-1. + Authors ------- diff --git a/swaygrab/main.c b/swaygrab/main.c index bd64bd93..1edda490 100644 --- a/swaygrab/main.c +++ b/swaygrab/main.c @@ -1,5 +1,9 @@ #include #include +#include +#include +#include +#include #include "log.h" #include "ipc-client.h" @@ -7,8 +11,42 @@ void sway_terminate(void) { exit(1); } -int main(int argc, const char **argv) { - int capture; +int numlen(int n) { + if (n >= 1000000) return 7; + if (n >= 100000) return 6; + if (n >= 10000) return 5; + if (n >= 1000) return 4; + if (n >= 100) return 3; + if (n >= 10) return 2; + return 1; +} + +void grab_and_apply_magick(const char *file, const char *output, int socketfd) { + uint32_t len = strlen(output); + char *pixels = ipc_single_command(socketfd, + IPC_SWAY_GET_PIXELS, output, &len); + uint32_t *u32pixels = (uint32_t *)(pixels + 1); + uint32_t width = u32pixels[0]; + uint32_t height = u32pixels[1]; + pixels += 9; + + if (width == 0 || height == 0) { + sway_abort("Unknown output %s.", output); + } + + const char *fmt = "convert -depth 8 -size %dx%d+0 rgba:- -flip %s"; + char *cmd = malloc(strlen(fmt) - 6 /*args*/ + + numlen(width) + numlen(height) + strlen(file) + 1); + sprintf(cmd, fmt, width, height, file); + + FILE *f = popen(cmd, "w"); + fwrite(pixels, 1, len, f); + fflush(f); + fclose(f); +} + +int main(int argc, char **argv) { + static int capture = 0; char *socket_path = NULL; init_log(L_INFO); @@ -51,15 +89,21 @@ int main(int argc, const char **argv) { } } - if (optind >= argc) { - sway_abort("Expected output file on command line. See `man swaygrab`"); + if (optind >= argc - 1) { + sway_abort("Expected output and file on command line. See `man swaygrab`"); } - char *out = argv[optind]; + char *file = argv[optind + 1]; + char *output = argv[optind]; int socketfd = ipc_open_socket(socket_path); free(socket_path); + if (!capture) { + grab_and_apply_magick(file, output, socketfd); + } else { + sway_abort("Capture is not yet supported"); + } + close(socketfd); - free(out); return 0; }