Respond to load commands when an id is present
This commit is contained in:
parent
9601ed79f1
commit
9860ed544f
@ -127,6 +127,10 @@ img_by_internal_id(GraphicsManager *self, size_t id) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char add_response[512] = {0};
|
||||||
|
static bool has_add_respose = false;
|
||||||
|
|
||||||
|
#define ABRT(...) { snprintf(add_response, (sizeof(add_response)/sizeof(add_response[0])) - 1, __VA_ARGS__); has_add_respose = true; goto err; }
|
||||||
static inline bool
|
static inline bool
|
||||||
inflate_zlib(GraphicsManager UNUSED *self, Image *img, uint8_t *buf, size_t bufsz) {
|
inflate_zlib(GraphicsManager UNUSED *self, Image *img, uint8_t *buf, size_t bufsz) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
@ -141,18 +145,9 @@ inflate_zlib(GraphicsManager UNUSED *self, Image *img, uint8_t *buf, size_t bufs
|
|||||||
z.avail_out = img->load_data.data_sz;
|
z.avail_out = img->load_data.data_sz;
|
||||||
z.next_out = decompressed;
|
z.next_out = decompressed;
|
||||||
int ret;
|
int ret;
|
||||||
if ((ret = inflateInit(&z)) != Z_OK) {
|
if ((ret = inflateInit(&z)) != Z_OK) ABRT("Failed to initialize inflate with error code: %d", ret);
|
||||||
REPORT_ERROR("Failed to initialize inflate with error code: %d", ret);
|
if ((ret = inflate(&z, Z_FINISH)) != Z_STREAM_END) ABRT("Failed to inflate image data with error code: %d", ret);
|
||||||
goto err;
|
if (z.avail_out) ABRT("Failed to inflate image data with error code: %d", ret);
|
||||||
}
|
|
||||||
if ((ret = inflate(&z, Z_FINISH)) != Z_STREAM_END) {
|
|
||||||
REPORT_ERROR("Failed to inflate image data with error code: %d", ret);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (z.avail_out) {
|
|
||||||
REPORT_ERROR("Failed to inflate image data with error code: %d", ret);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
free_load_data(&img->load_data);
|
free_load_data(&img->load_data);
|
||||||
img->load_data.buf_capacity = img->load_data.data_sz;
|
img->load_data.buf_capacity = img->load_data.data_sz;
|
||||||
img->load_data.buf = decompressed;
|
img->load_data.buf = decompressed;
|
||||||
@ -238,15 +233,16 @@ err:
|
|||||||
return ok;
|
return ok;
|
||||||
#undef RE
|
#undef RE
|
||||||
}
|
}
|
||||||
|
#undef ABRT
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
add_trim_predicate(Image *img) {
|
add_trim_predicate(Image *img) {
|
||||||
return !img->data_loaded || (!img->client_id && !img->refcnt);
|
return !img->data_loaded || (!img->client_id && !img->refcnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
static void
|
|
||||||
handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload) {
|
handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload) {
|
||||||
|
#define ABRT(...) { snprintf(add_response, (sizeof(add_response)/sizeof(add_response[0])) - 1, __VA_ARGS__); has_add_respose = true; return false; }
|
||||||
bool existing, init_img = true;
|
bool existing, init_img = true;
|
||||||
Image *img;
|
Image *img;
|
||||||
unsigned char tt = g->transmission_type ? g->transmission_type : 'd';
|
unsigned char tt = g->transmission_type ? g->transmission_type : 'd';
|
||||||
@ -255,7 +251,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
if (tt == 'd' && (g->more && self->loading_image)) init_img = false;
|
if (tt == 'd' && (g->more && self->loading_image)) init_img = false;
|
||||||
if (init_img) {
|
if (init_img) {
|
||||||
size_t sz = g->data_width * g->data_height;
|
size_t sz = g->data_width * g->data_height;
|
||||||
if (!sz) return; // ignore images with zero size
|
if (!sz) return false; // ignore images with zero size
|
||||||
remove_images(self, add_trim_predicate);
|
remove_images(self, add_trim_predicate);
|
||||||
img = find_or_create_image(self, g->id, &existing);
|
img = find_or_create_image(self, g->id, &existing);
|
||||||
if (existing) {
|
if (existing) {
|
||||||
@ -277,8 +273,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
img->load_data.is_4byte_aligned = fmt == RGBA || (img->width % 4 == 0);
|
img->load_data.is_4byte_aligned = fmt == RGBA || (img->width % 4 == 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("Unknown image format: %u", fmt);
|
ABRT("Unknown image format: %u", fmt);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
img->load_data.data_sz = sz;
|
img->load_data.data_sz = sz;
|
||||||
if (tt == 'd') {
|
if (tt == 'd') {
|
||||||
@ -292,16 +287,14 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
img = img_by_internal_id(self, self->loading_image);
|
img = img_by_internal_id(self, self->loading_image);
|
||||||
if (img == NULL) {
|
if (img == NULL) {
|
||||||
self->loading_image = 0;
|
self->loading_image = 0;
|
||||||
REPORT_ERROR("%s", "More payload loading refers to non-existent image");
|
ABRT("%s", "More payload loading refers to non-existent image");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int fd;
|
int fd;
|
||||||
switch(tt) {
|
switch(tt) {
|
||||||
case 'd': // direct
|
case 'd': // direct
|
||||||
if (g->payload_sz >= img->load_data.buf_capacity - img->load_data.buf_used) {
|
if (g->payload_sz >= img->load_data.buf_capacity - img->load_data.buf_used) {
|
||||||
REPORT_ERROR("%s", "Too much data transmitted");
|
ABRT("%s", "Too much data transmitted");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
memcpy(img->load_data.buf + img->load_data.buf_used, payload, g->payload_sz);
|
memcpy(img->load_data.buf + img->load_data.buf_used, payload, g->payload_sz);
|
||||||
img->load_data.buf_used += g->payload_sz;
|
img->load_data.buf_used += g->payload_sz;
|
||||||
@ -313,8 +306,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
if (tt == 's') fd = shm_open((const char*)payload, O_RDONLY, 0);
|
if (tt == 's') fd = shm_open((const char*)payload, O_RDONLY, 0);
|
||||||
else fd = open((const char*)payload, O_CLOEXEC | O_RDONLY);
|
else fd = open((const char*)payload, O_CLOEXEC | O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
REPORT_ERROR("Failed to open file for graphics transmission with error: [%d] %s", errno, strerror(errno));
|
ABRT("Failed to open file for graphics transmission with error: [%d] %s", errno, strerror(errno));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
img->load_data.fd = fd;
|
img->load_data.fd = fd;
|
||||||
img->data_loaded = mmap_img_file(self, img);
|
img->data_loaded = mmap_img_file(self, img);
|
||||||
@ -322,10 +314,9 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
else if (tt == 's') shm_unlink((const char*)payload);
|
else if (tt == 's') shm_unlink((const char*)payload);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("Unknown transmission type: %c", g->transmission_type);
|
ABRT("Unknown transmission type: %c", g->transmission_type);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!img->data_loaded) return;
|
if (!img->data_loaded) return false;
|
||||||
bool needs_processing = g->compressed || fmt == PNG;
|
bool needs_processing = g->compressed || fmt == PNG;
|
||||||
if (needs_processing) {
|
if (needs_processing) {
|
||||||
uint8_t *buf; size_t bufsz;
|
uint8_t *buf; size_t bufsz;
|
||||||
@ -334,20 +325,20 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
case 'z':
|
case 'z':
|
||||||
IB;
|
IB;
|
||||||
if (!inflate_zlib(self, img, buf, bufsz)) {
|
if (!inflate_zlib(self, img, buf, bufsz)) {
|
||||||
img->data_loaded = false; return;
|
img->data_loaded = false; return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("Unknown image compression: %c", g->compressed);
|
ABRT("Unknown image compression: %c", g->compressed);
|
||||||
img->data_loaded = false; return;
|
img->data_loaded = false; return false;
|
||||||
}
|
}
|
||||||
switch(fmt) {
|
switch(fmt) {
|
||||||
case PNG:
|
case PNG:
|
||||||
IB;
|
IB;
|
||||||
if (!inflate_png(self, img, buf, bufsz)) {
|
if (!inflate_png(self, img, buf, bufsz)) {
|
||||||
img->data_loaded = false; return;
|
img->data_loaded = false; return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
@ -355,35 +346,50 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
#undef IB
|
#undef IB
|
||||||
img->load_data.data = img->load_data.buf;
|
img->load_data.data = img->load_data.buf;
|
||||||
if (img->load_data.buf_used < img->load_data.data_sz) {
|
if (img->load_data.buf_used < img->load_data.data_sz) {
|
||||||
REPORT_ERROR("Insufficient image data: %zu < %zu", img->load_data.buf_used, img->load_data.data_sz);
|
ABRT("Insufficient image data: %zu < %zu", img->load_data.buf_used, img->load_data.data_sz);
|
||||||
img->data_loaded = false;
|
img->data_loaded = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tt == 'd') {
|
if (tt == 'd') {
|
||||||
if (img->load_data.buf_used < img->load_data.data_sz) {
|
if (img->load_data.buf_used < img->load_data.data_sz) {
|
||||||
REPORT_ERROR("Insufficient image data: %zu < %zu", img->load_data.buf_used, img->load_data.data_sz);
|
ABRT("Insufficient image data: %zu < %zu", img->load_data.buf_used, img->load_data.data_sz);
|
||||||
img->data_loaded = false;
|
img->data_loaded = false;
|
||||||
} else img->load_data.data = img->load_data.buf;
|
} else img->load_data.data = img->load_data.buf;
|
||||||
} else {
|
} else {
|
||||||
if (img->load_data.mapped_file_sz < img->load_data.data_sz) {
|
if (img->load_data.mapped_file_sz < img->load_data.data_sz) {
|
||||||
REPORT_ERROR("Insufficient image data: %zu < %zu", img->load_data.mapped_file_sz, img->load_data.data_sz);
|
ABRT("Insufficient image data: %zu < %zu", img->load_data.mapped_file_sz, img->load_data.data_sz);
|
||||||
img->data_loaded = false;
|
img->data_loaded = false;
|
||||||
} else img->load_data.data = img->load_data.mapped_file;
|
} else img->load_data.data = img->load_data.mapped_file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return img->data_loaded;
|
||||||
|
#undef ABRT
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
const char*
|
||||||
grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload) {
|
grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload) {
|
||||||
|
static char rbuf[sizeof(add_response)/sizeof(add_response[0])];
|
||||||
|
bool data_loaded;
|
||||||
|
|
||||||
switch(g->action) {
|
switch(g->action) {
|
||||||
case 0:
|
case 0:
|
||||||
case 't':
|
case 't':
|
||||||
handle_add_command(self, g, payload);
|
has_add_respose = false;
|
||||||
|
data_loaded = handle_add_command(self, g, payload);
|
||||||
|
if (g->id) {
|
||||||
|
if (!has_add_respose) {
|
||||||
|
if (!data_loaded) break;
|
||||||
|
snprintf(add_response, 10, "OK");
|
||||||
|
}
|
||||||
|
snprintf(rbuf, sizeof(rbuf)/sizeof(rbuf[0]) - 1, "\033_Gq=%u;%s\033\\", g->id, add_response);
|
||||||
|
return rbuf;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("Unknown graphics command action: %c", g->action);
|
REPORT_ERROR("Unknown graphics command action: %c", g->action);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@ -50,4 +50,4 @@ PyTypeObject GraphicsManager_Type;
|
|||||||
GraphicsManager* grman_realloc(GraphicsManager *, index_type lines, index_type columns);
|
GraphicsManager* grman_realloc(GraphicsManager *, index_type lines, index_type columns);
|
||||||
void grman_clear(GraphicsManager*);
|
void grman_clear(GraphicsManager*);
|
||||||
GraphicsManager* grman_free(GraphicsManager*);
|
GraphicsManager* grman_free(GraphicsManager*);
|
||||||
void grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload);
|
const char* grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload);
|
||||||
|
|||||||
@ -409,9 +409,18 @@ END_ALLOW_CASE_RANGE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
write_to_child(Screen *self, const char *data, size_t sz) {
|
||||||
|
if (self->window_id) schedule_write_to_child(self->window_id, data, sz);
|
||||||
|
if (self->test_child != Py_None) { PyObject *r = PyObject_CallMethod(self->test_child, "write", "y#", data, sz); if (r == NULL) PyErr_Print(); Py_CLEAR(r); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#define write_str_to_child(s) write_to_child(self, (s), sizeof((s)) - 1)
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const uint8_t *payload) {
|
screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const uint8_t *payload) {
|
||||||
grman_handle_command(self->grman, cmd, payload);
|
const char *response = grman_handle_command(self->grman, cmd, payload);
|
||||||
|
if (response != NULL) write_to_child(self, response, strlen(response));
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
@ -973,14 +982,6 @@ screen_bell(Screen UNUSED *self) {
|
|||||||
request_window_attention();
|
request_window_attention();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
write_to_child(Screen *self, const char *data, size_t sz) {
|
|
||||||
if (self->window_id) schedule_write_to_child(self->window_id, data, sz);
|
|
||||||
if (self->test_child != Py_None) { PyObject *r = PyObject_CallMethod(self->test_child, "write", "y#", data, sz); if (r == NULL) PyErr_Print(); Py_CLEAR(r); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#define write_str_to_child(s) write_to_child(self, (s), sizeof((s)) - 1)
|
|
||||||
|
|
||||||
void
|
void
|
||||||
report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
|
report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
|
||||||
if (mode == 0) {
|
if (mode == 0) {
|
||||||
|
|||||||
@ -218,10 +218,10 @@ escape code will look like:
|
|||||||
```
|
```
|
||||||
|
|
||||||
Here the `q` value will be the same as was sent by the client in the original
|
Here the `q` value will be the same as was sent by the client in the original
|
||||||
request. The payload data will be a base-64 encoded UTF-8 string. The string
|
request. The payload data will be a ASCII encoded string containing only
|
||||||
will be `OK` if reading the pixel data succeeded or an error message. Clients
|
printable characters and spaces. The string will be `OK` if reading the pixel
|
||||||
can set the width and height to zero to avoid actually drawing anything on
|
data succeeded or an error message. Clients can set the width and height to
|
||||||
screen during the test.
|
zero to avoid actually drawing anything on screen during the test.
|
||||||
|
|
||||||
|
|
||||||
===== Remote client
|
===== Remote client
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user