-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathscreenshot.c
157 lines (131 loc) · 3.1 KB
/
screenshot.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2022 Codethink
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "cmd/cmd.h"
#include "cmd/private.h"
#include "msg/msg.h"
#include "util/cli.h"
#include "util/log.h"
#include "util/file.h"
#include "util/util.h"
#include "util/base64.h"
static struct cmd_screenshot_ctx {
const char *display;
const char *format;
bool finished;
} cmd_screenshot_g = {
.format = "png",
};
static const struct cli_table_entry cli_entries[] = {
CMD_CLI_COMMON("screenshot"),
{
.p = true,
.l = "FORMAT",
.t = CLI_STRING,
.v.s = &cmd_screenshot_g.format,
.d = "Image format: png, jpeg (default: png)."
},
};
static const struct cli_table cli = {
.entries = cli_entries,
.count = (sizeof(cli_entries))/(sizeof(*cli_entries)),
.min_positional = 2,
};
static bool cmd_screenshot_init(int argc, const char **argv,
struct cmd_options *options, void **pw_out)
{
int id;
if (!cmd_cli_parse(argc, argv, &cli, options)) {
return false;
}
cmd_screenshot_g.display = options->display;
msg_queue_for_send(&(const struct msg)
{
.type = MSG_TYPE_CAPTURE_SCREENSHOT,
.data = {
.capture_screenshot = {
.format = cmd_screenshot_g.format,
},
},
}, &id);
cmd_screenshot_g.finished = false;
*pw_out = &cmd_screenshot_g;
return true;
}
static bool get_data(const char *msg, size_t len,
const char **data_out, size_t *data_len)
{
const char *marker = "\"data\":\"";
const char *data;
const char *end;
data = strstr(msg, marker);
if (data == NULL) {
cdt_log(CDT_LOG_ERROR, "%s: Data not found: %*s",
__func__, (int)len, msg);
return false;
}
data += strlen(marker);
end = strchr(data, '"');
if (end == NULL || end < data) {
cdt_log(CDT_LOG_ERROR, "%s: Data terminator missing: %*s",
__func__, (int)len, msg);
return false;
}
*data_len = (size_t)(end - data);
*data_out = data;
return true;
}
static void cmd_screenshot_msg(void *pw, int id, const char *msg, size_t len)
{
struct cmd_screenshot_ctx *ctx = pw;
const char *data;
size_t data_len;
size_t scr_len;
uint8_t *scr;
(void)(id);
if (!get_data(msg, len, &data, &data_len)) {
ctx->finished = true;
return;
}
if (data_len == 0) {
cdt_log(CDT_LOG_ERROR, "%s: Zero length screenshot: %*s",
__func__, (int)len, msg);
ctx->finished = true;
return;
}
if (!base64_decode(data, data_len, &scr, &scr_len)) {
cdt_log(CDT_LOG_ERROR, "%s: Base64 decode failed", __func__);
ctx->finished = true;
return;
}
file_write(scr, scr_len,
"screenshot-%s.%s",
str_get_leaf(ctx->display),
ctx->format);
free(scr);
ctx->finished = true;
}
static bool cmd_screenshot_tick(void *pw)
{
struct cmd_screenshot_ctx *ctx = pw;
return !ctx->finished;
}
static void cmd_screenshot_help(int argc, const char **argv);
const struct cmd_table cmd_screenshot = {
.cmd = "screenshot",
.init = cmd_screenshot_init,
.help = cmd_screenshot_help,
.msg = cmd_screenshot_msg,
.tick = cmd_screenshot_tick,
};
static void cmd_screenshot_help(int argc, const char **argv)
{
cli_help(&cli, (argc > 0) ? argv[0] : "cdt");
}