void video_frame(uint32_t id, uint8_t *img_data, uint16_t width, uint16_t height, _Bool resize) { if (!video_win[id]) { debug("frame for null window %u\n", id); return; } if (resize) { XWindowChanges changes = { .width = width, .height = height }; XConfigureWindow(display, video_win[id], CWWidth | CWHeight, &changes); } XWindowAttributes attrs; XGetWindowAttributes(display, video_win[id], &attrs); XImage image = { .width = attrs.width, .height = attrs.height, .depth = 24, .bits_per_pixel = 32, .format = ZPixmap, .byte_order = LSBFirst, .bitmap_unit = 8, .bitmap_bit_order = LSBFirst, .bytes_per_line = attrs.width * 4, .red_mask = 0xFF0000, .green_mask = 0xFF00, .blue_mask = 0xFF, .data = (char*)img_data }; /* scale image if needed */ uint8_t *new_data = malloc(attrs.width * attrs.height * 4); if (new_data && (attrs.width != width || attrs.height != height)) { scale_rgbx_image(img_data, width, height, new_data, attrs.width, attrs.height); image.data = (char*)new_data; } GC default_gc = DefaultGC(display, screen); Pixmap pixmap = XCreatePixmap(display, window, attrs.width, attrs.height, depth); XPutImage(display, pixmap, default_gc, &image, 0, 0, 0, 0, attrs.width, attrs.height); XCopyArea(display, pixmap, video_win[id], default_gc, 0, 0, attrs.width, attrs.height, 0, 0); XFreePixmap(display, pixmap); free(new_data); } void video_begin(uint32_t id, char_t *name, STRING_IDX name_length, uint16_t width, uint16_t height) { Window *win = &video_win[id]; if(*win) { return; } *win = XCreateSimpleWindow(display, RootWindow(display, screen), 0, 0, width, height, 0, BlackPixel(display, screen), WhitePixel(display, screen)); // Fallback name in ISO8859-1. XStoreName(display, *win, "Video Preview"); // UTF-8 name for those WMs that can display it. XChangeProperty(display, *win, XA_NET_NAME, XA_UTF8_STRING, 8, PropModeReplace, name, name_length); XSetWMProtocols(display, *win, &wm_delete_window, 1); /* set WM_CLASS */ XClassHint hint = { .res_name = "utoxvideo", .res_class = "utoxvideo" }; XSetClassHint(display, *win, &hint); XMapWindow(display, *win); debug("new window %u\n", id); } void video_end(uint32_t id) { if(!video_win[id]) { return; } XDestroyWindow(display, video_win[id]); video_win[id] = None; debug("killed window %u\n", id); } Display *deskdisplay; int deskscreen; XShmSegmentInfo shminfo; void initshm(void) { deskdisplay = XOpenDisplay(NULL); deskscreen = DefaultScreen(deskdisplay); debug("desktop: %u %u\n", scr->width, scr->height); max_video_width = scr->width; max_video_height = scr->height; }
void video_frame(uint16_t id, uint8_t *img_data, uint16_t width, uint16_t height, bool resize) { Window *win = &video_win[id]; if (id == UINT16_MAX) { // Preview window win = &preview; } if (!*win) { LOG_TRACE("Video", "frame for null window %u" , id); return; } if (resize) { XWindowChanges changes = {.width = width, .height = height }; XConfigureWindow(display, *win, CWWidth | CWHeight, &changes); } XWindowAttributes attrs; XGetWindowAttributes(display, video_win[id], &attrs); XImage image = { .width = attrs.width, .height = attrs.height, .depth = 24, .bits_per_pixel = 32, .format = ZPixmap, .byte_order = LSBFirst, .bitmap_unit = 8, .bitmap_bit_order = LSBFirst, .bytes_per_line = attrs.width * 4, .red_mask = 0xFF0000, .green_mask = 0xFF00, .blue_mask = 0xFF, .data = (char *)img_data }; /* scale image if needed */ uint8_t *new_data = malloc(attrs.width * attrs.height * 4); if (new_data && (attrs.width != width || attrs.height != height)) { scale_rgbx_image(img_data, width, height, new_data, attrs.width, attrs.height); image.data = (char *)new_data; } GC default_gc = DefaultGC(display, def_screen_num); Pixmap pixmap = XCreatePixmap(display, main_window.window, attrs.width, attrs.height, default_depth); XPutImage(display, pixmap, default_gc, &image, 0, 0, 0, 0, attrs.width, attrs.height); XCopyArea(display, pixmap, *win, default_gc, 0, 0, attrs.width, attrs.height, 0, 0); XFreePixmap(display, pixmap); free(new_data); } void video_begin(uint16_t id, char *name, uint16_t name_length, uint16_t width, uint16_t height) { Window *win = &video_win[id]; if (id == UINT16_MAX) { // Preview window win = &preview; } if (*win) { return; } *win = XCreateSimpleWindow(display, RootWindow(display, def_screen_num), 0, 0, width, height, 0, BlackPixel(display, def_screen_num), WhitePixel(display, def_screen_num)); // Fallback name in ISO8859-1. XStoreName(display, *win, "Video Preview"); // UTF-8 name for those WMs that can display it. XChangeProperty(display, *win, XA_NET_NAME, XA_UTF8_STRING, 8, PropModeReplace, (uint8_t *)name, name_length); XSetWMProtocols(display, *win, &wm_delete_window, 1); /* set WM_CLASS */ XClassHint hint = {.res_name = "utoxvideo", .res_class = "utoxvideo" }; XSetClassHint(display, *win, &hint); XMapWindow(display, *win); LOG_TRACE("Video", "new window %u" , id); } void video_end(uint16_t id) { Window *win = &video_win[id]; if (id == UINT16_MAX) { // Preview window win = &preview; } XDestroyWindow(display, *win); *win = None; LOG_NOTE("Video", "killed window %u" , id); }