25#include <sys/syscall.h> 
   33#include <winpr/thread.h> 
   34#include <winpr/string.h> 
   35#include <winpr/platform.h> 
   39#if GST_VERSION_MAJOR > 0 
   40#include <gst/video/videooverlay.h> 
   42#include <gst/interfaces/xoverlay.h> 
   46#include <X11/extensions/Xrandr.h> 
   47#include <X11/extensions/shape.h> 
   49#include <freerdp/channels/tsmf.h> 
   51#include "tsmf_platform.h" 
   52#include "tsmf_constants.h" 
   53#include "tsmf_decoder.h" 
   55#if !defined(WITH_XEXT) 
   56#warning "Building TSMF without shape extension support" 
   69#if GST_VERSION_MAJOR > 0 
   70  GstVideoOverlay* overlay;
 
   80static const char* get_shm_id()
 
   82  static char shm_id[128];
 
   83  sprintf_s(shm_id, 
sizeof(shm_id), 
"/com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
 
   87static GstBusSyncReply tsmf_platform_bus_sync_handler(GstBus* bus, GstMessage* message,
 
   90  struct X11Handle* hdl;
 
   94  if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
 
   97#if GST_VERSION_MAJOR > 0 
   98  if (!gst_is_video_overlay_prepare_window_handle_message(message))
 
  101  if (!gst_structure_has_name(message->structure, 
"prepare-xwindow-id"))
 
  105  hdl = (
struct X11Handle*)decoder->platform;
 
  109#if GST_VERSION_MAJOR > 0 
  110    hdl->overlay = GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(message));
 
  111    gst_video_overlay_set_window_handle(hdl->overlay, hdl->subwin);
 
  112    gst_video_overlay_handle_events(hdl->overlay, FALSE);
 
  114    hdl->overlay = GST_X_OVERLAY(GST_MESSAGE_SRC(message));
 
  115#if GST_CHECK_VERSION(0, 10, 31) 
  116    gst_x_overlay_set_window_handle(hdl->overlay, hdl->subwin);
 
  118    gst_x_overlay_set_xwindow_id(hdl->overlay, hdl->subwin);
 
  120    gst_x_overlay_handle_events(hdl->overlay, TRUE);
 
  123    if (hdl->subwinWidth != -1 && hdl->subwinHeight != -1 && hdl->subwinX != -1 &&
 
  126#if GST_VERSION_MAJOR > 0 
  127      if (!gst_video_overlay_set_render_rectangle(hdl->overlay, 0, 0, hdl->subwinWidth,
 
  130        WLog_ERR(TAG, 
"Could not resize overlay!");
 
  133      gst_video_overlay_expose(hdl->overlay);
 
  135      if (!gst_x_overlay_set_render_rectangle(hdl->overlay, 0, 0, hdl->subwinWidth,
 
  138        WLog_ERR(TAG, 
"Could not resize overlay!");
 
  141      gst_x_overlay_expose(hdl->overlay);
 
  143      XLockDisplay(hdl->disp);
 
  144      XMoveResizeWindow(hdl->disp, hdl->subwin, hdl->subwinX, hdl->subwinY, hdl->subwinWidth,
 
  146      XSync(hdl->disp, FALSE);
 
  147      XUnlockDisplay(hdl->disp);
 
  152    g_warning(
"Window was not available before retrieving the overlay!");
 
  155  gst_message_unref(message);
 
  160const char* tsmf_platform_get_video_sink(
void)
 
  162  return "autovideosink";
 
  165const char* tsmf_platform_get_audio_sink(
void)
 
  167  return "autoaudiosink";
 
  172  struct X11Handle* hdl;
 
  177  if (decoder->platform)
 
  180  hdl = calloc(1, 
sizeof(
struct X11Handle));
 
  183    WLog_ERR(TAG, 
"Could not allocate handle.");
 
  187  decoder->platform = hdl;
 
  188  hdl->shmid = shm_open(get_shm_id(), (O_RDWR | O_CREAT), (PROT_READ | PROT_WRITE));
 
  189  if (hdl->shmid == -1)
 
  191    char ebuffer[256] = { 0 };
 
  192    WLog_ERR(TAG, 
"failed to get access to shared memory - shmget(%s): %i - %s", get_shm_id(),
 
  193             errno, winpr_strerror(errno, ebuffer, 
sizeof(ebuffer)));
 
  197  hdl->xfwin = mmap(0, 
sizeof(
void*), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0);
 
  198  if (hdl->xfwin == MAP_FAILED)
 
  200    WLog_ERR(TAG, 
"shmat failed!");
 
  204  hdl->disp = XOpenDisplay(NULL);
 
  207    WLog_ERR(TAG, 
"Failed to open display");
 
  211  hdl->subwinMapped = FALSE;
 
  214  hdl->subwinWidth = -1;
 
  215  hdl->subwinHeight = -1;
 
  225  if (decoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
  242  bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe));
 
  244#if GST_VERSION_MAJOR > 0 
  245  gst_bus_set_sync_handler(bus, (GstBusSyncHandler)tsmf_platform_bus_sync_handler, decoder, NULL);
 
  247  gst_bus_set_sync_handler(bus, (GstBusSyncHandler)tsmf_platform_bus_sync_handler, decoder);
 
  252    WLog_ERR(TAG, 
"gst_pipeline_get_bus failed!");
 
  256  gst_object_unref(bus);
 
  263  struct X11Handle* hdl = decoder->platform;
 
  269    XCloseDisplay(hdl->disp);
 
  272    munmap(0, 
sizeof(
void*));
 
  278  decoder->platform = NULL;
 
  285  struct X11Handle* hdl;
 
  287  if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
 
  289    decoder->ready = TRUE;
 
  297    if (!decoder->platform)
 
  300    hdl = (
struct X11Handle*)decoder->platform;
 
  304      XLockDisplay(hdl->disp);
 
  305      hdl->subwin = XCreateSimpleWindow(hdl->disp, *(
int*)hdl->xfwin, 0, 0, 1, 1, 0, 0, 0);
 
  306      XUnlockDisplay(hdl->disp);
 
  310        WLog_ERR(TAG, 
"Could not create subwindow!");
 
  314    tsmf_window_map(decoder);
 
  316    decoder->ready = TRUE;
 
  317#if defined(WITH_XEXT) 
  319    XLockDisplay(hdl->disp);
 
  320    hdl->has_shape = XShapeQueryExtension(hdl->disp, &event, &error);
 
  321    XUnlockDisplay(hdl->disp);
 
  331  struct X11Handle* hdl;
 
  336  if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
 
  341  if (!decoder->platform)
 
  344  hdl = (
struct X11Handle*)decoder->platform;
 
  345  DEBUG_TSMF(
"resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height);
 
  349#if GST_VERSION_MAJOR > 0 
  351    if (!gst_video_overlay_set_render_rectangle(hdl->overlay, 0, 0, width, height))
 
  353      WLog_ERR(TAG, 
"Could not resize overlay!");
 
  356    gst_video_overlay_expose(hdl->overlay);
 
  358    if (!gst_x_overlay_set_render_rectangle(hdl->overlay, 0, 0, width, height))
 
  360      WLog_ERR(TAG, 
"Could not resize overlay!");
 
  363    gst_x_overlay_expose(hdl->overlay);
 
  371    hdl->subwinWidth = width;
 
  372    hdl->subwinHeight = height;
 
  374    XLockDisplay(hdl->disp);
 
  375    XMoveResizeWindow(hdl->disp, hdl->subwin, hdl->subwinX, hdl->subwinY, hdl->subwinWidth,
 
  380      tsmf_window_unmap(decoder);
 
  382      tsmf_window_map(decoder);
 
  384#if defined(WITH_XEXT) 
  387      XRectangle* xrects = NULL;
 
  391        xrects = calloc(1, 
sizeof(XRectangle));
 
  394        xrects->width = width;
 
  395        xrects->height = height;
 
  399        xrects = calloc(nr_rects, 
sizeof(XRectangle));
 
  404        for (
int i = 0; i < nr_rects; i++)
 
  406          xrects[i].x = rects[i].x - x;
 
  407          xrects[i].y = rects[i].y - y;
 
  408          xrects[i].width = rects[i].width;
 
  409          xrects[i].height = rects[i].height;
 
  412        XShapeCombineRectangles(hdl->disp, hdl->subwin, ShapeBounding, x, y, xrects,
 
  413                                nr_rects, ShapeSet, 0);
 
  418    XSync(hdl->disp, FALSE);
 
  419    XUnlockDisplay(hdl->disp);
 
  427  struct X11Handle* hdl;
 
  431  hdl = (
struct X11Handle*)decoder->platform;
 
  434  if ((hdl->subwin) && (!hdl->subwinMapped))
 
  436    XLockDisplay(hdl->disp);
 
  437    XMapWindow(hdl->disp, hdl->subwin);
 
  438    hdl->subwinMapped = TRUE;
 
  439    XSync(hdl->disp, FALSE);
 
  440    XUnlockDisplay(hdl->disp);
 
  448  struct X11Handle* hdl;
 
  452  hdl = (
struct X11Handle*)decoder->platform;
 
  455  if ((hdl->subwin) && (hdl->subwinMapped))
 
  457    XLockDisplay(hdl->disp);
 
  458    XUnmapWindow(hdl->disp, hdl->subwin);
 
  459    hdl->subwinMapped = FALSE;
 
  460    XSync(hdl->disp, FALSE);
 
  461    XUnlockDisplay(hdl->disp);
 
  469  struct X11Handle* hdl;
 
  474  decoder->ready = FALSE;
 
  476  if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
 
  479  if (!decoder->platform)
 
  482  hdl = (
struct X11Handle*)decoder->platform;
 
  486    XLockDisplay(hdl->disp);
 
  487    XDestroyWindow(hdl->disp, hdl->subwin);
 
  488    XSync(hdl->disp, FALSE);
 
  489    XUnlockDisplay(hdl->disp);
 
  494  hdl->subwinMapped = FALSE;
 
  497  hdl->subwinWidth = -1;
 
  498  hdl->subwinHeight = -1;