/* GStreamer
 * Copyright (C) <2005> Luca Ognibene <luogni@tin.it>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "ximageutil.h"

GType
gst_meta_ximage_api_get_type (void)
{
  static volatile GType type;
  static const gchar *tags[] = { "memory", NULL };

  if (g_once_init_enter (&type)) {
    GType _type = gst_meta_api_type_register ("GstMetaXImageSrcAPI", tags);
    g_once_init_leave (&type, _type);
  }
  return type;
}

const GstMetaInfo *
gst_meta_ximage_get_info (void)
{
  static const GstMetaInfo *meta_ximage_info = NULL;

  if (g_once_init_enter (&meta_ximage_info)) {
    const GstMetaInfo *meta =
        gst_meta_register (gst_meta_ximage_api_get_type (), "GstMetaXImageSrc",
        sizeof (GstMetaXImage), (GstMetaInitFunction) NULL,
        (GstMetaFreeFunction) NULL, (GstMetaTransformFunction) NULL);
    g_once_init_leave (&meta_ximage_info, meta);
  }
  return meta_ximage_info;
}

#ifdef HAVE_XSHM
static gboolean error_caught = FALSE;

static int
ximageutil_handle_xerror (Display * display, XErrorEvent * xevent)
{
  char error_msg[1024];

  XGetErrorText (display, xevent->error_code, error_msg, 1024);
  GST_DEBUG ("ximageutil failed to use XShm calls. error: %s", error_msg);
  error_caught = TRUE;
  return 0;
}

/* This function checks that it is actually really possible to create an image
   using XShm */
gboolean
ximageutil_check_xshm_calls (GstXContext * xcontext)
{
  XImage *ximage;
  XShmSegmentInfo SHMInfo;
  size_t size;
  int (*handler) (Display *, XErrorEvent *);
  gboolean result = FALSE;
  gboolean did_attach = FALSE;

  g_return_val_if_fail (xcontext != NULL, FALSE);

  /* Sync to ensure any older errors are already processed */
  XSync (xcontext->disp, FALSE);

  /* Set defaults so we don't free these later unnecessarily */
  SHMInfo.shmaddr = ((void *) -1);
  SHMInfo.shmid = -1;

  /* Setting an error handler to catch failure */
  error_caught = FALSE;
  handler = XSetErrorHandler (ximageutil_handle_xerror);

  /* Trying to create a 1x1 ximage */
  GST_DEBUG ("XShmCreateImage of 1x1");

  ximage = XShmCreateImage (xcontext->disp, xcontext->visual,
      xcontext->depth, ZPixmap, NULL, &SHMInfo, 1, 1);

  /* Might cause an error, sync to ensure it is noticed */
  XSync (xcontext->disp, FALSE);
  if (!ximage || error_caught) {
    GST_WARNING ("could not XShmCreateImage a 1x1 image");
    goto beach;
  }
  size = ximage->height * ximage->bytes_per_line;

  SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
  if (SHMInfo.shmid == -1) {
    GST_WARNING ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
        size);
    goto beach;
  }

  SHMInfo.shmaddr = shmat (SHMInfo.shmid, 0, 0);
  if (SHMInfo.shmaddr == ((void *) -1)) {
    GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
    goto beach;
  }

  /* Delete the SHM segment. It will actually go away automatically
   * when we detach now */
  shmctl (SHMInfo.shmid, IPC_RMID, 0);

  ximage->data = SHMInfo.shmaddr;
  SHMInfo.readOnly = FALSE;

  if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
    GST_WARNING ("Failed to XShmAttach");
    goto beach;
  }

  /* Sync to ensure we see any errors we caused */
  XSync (xcontext->disp, FALSE);

  if (!error_caught) {
    did_attach = TRUE;
    /* store whether we succeeded in result */
    result = TRUE;
  }
beach:
  /* Sync to ensure we swallow any errors we caused and reset error_caught */
  XSync (xcontext->disp, FALSE);
  error_caught = FALSE;
  XSetErrorHandler (handler);

  if (did_attach) {
    XShmDetach (xcontext->disp, &SHMInfo);
    XSync (xcontext->disp, FALSE);
  }
  if (SHMInfo.shmaddr != ((void *) -1))
    shmdt (SHMInfo.shmaddr);
  if (ximage)
    XDestroyImage (ximage);
  return result;
}
#endif /* HAVE_XSHM */

/* This function gets the X Display and global info about it. Everything is
   stored in our object and will be cleaned when the object is disposed. Note
   here that caps for supported format are generated without any window or
   image creation */
GstXContext *
ximageutil_xcontext_get (GstElement * parent, const gchar * display_name)
{
  GstXContext *xcontext = NULL;
  XPixmapFormatValues *px_formats = NULL;
  gint nb_formats = 0, i;

  xcontext = g_new0 (GstXContext, 1);

  xcontext->disp = XOpenDisplay (display_name);
  GST_DEBUG_OBJECT (parent, "opened display %p", xcontext->disp);
  if (!xcontext->disp) {
    g_free (xcontext);
    return NULL;
  }
  xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
  xcontext->visual = DefaultVisualOfScreen (xcontext->screen);
  xcontext->root = RootWindowOfScreen (xcontext->screen);
  xcontext->white = WhitePixelOfScreen (xcontext->screen);
  xcontext->black = BlackPixelOfScreen (xcontext->screen);
  xcontext->depth = DefaultDepthOfScreen (xcontext->screen);

  xcontext->width = WidthOfScreen (xcontext->screen);
  xcontext->height = HeightOfScreen (xcontext->screen);

  xcontext->widthmm = WidthMMOfScreen (xcontext->screen);
  xcontext->heightmm = HeightMMOfScreen (xcontext->screen);

  xcontext->caps = NULL;

  GST_DEBUG_OBJECT (parent, "X reports %dx%d pixels and %d mm x %d mm",
      xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
  ximageutil_calculate_pixel_aspect_ratio (xcontext);

  /* We get supported pixmap formats at supported depth */
  px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);

  if (!px_formats) {
    XCloseDisplay (xcontext->disp);
    g_free (xcontext);
    return NULL;
  }

  /* We get bpp value corresponding to our running depth */
  for (i = 0; i < nb_formats; i++) {
    if (px_formats[i].depth == xcontext->depth)
      xcontext->bpp = px_formats[i].bits_per_pixel;
  }

  XFree (px_formats);

  xcontext->endianness =
      (ImageByteOrder (xcontext->disp) ==
      LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;

#ifdef HAVE_XSHM
  /* Search for XShm extension support */
  if (XShmQueryExtension (xcontext->disp) &&
      ximageutil_check_xshm_calls (xcontext)) {
    xcontext->use_xshm = TRUE;
    GST_DEBUG ("ximageutil is using XShm extension");
  } else {
    xcontext->use_xshm = FALSE;
    GST_DEBUG ("ximageutil is not using XShm extension");
  }
#endif /* HAVE_XSHM */

  /* our caps system handles 24/32bpp RGB as big-endian. */
  if ((xcontext->bpp == 24 || xcontext->bpp == 32) &&
      xcontext->endianness == G_LITTLE_ENDIAN) {
    xcontext->endianness = G_BIG_ENDIAN;
    xcontext->r_mask_output = GUINT32_TO_BE (xcontext->visual->red_mask);
    xcontext->g_mask_output = GUINT32_TO_BE (xcontext->visual->green_mask);
    xcontext->b_mask_output = GUINT32_TO_BE (xcontext->visual->blue_mask);
    if (xcontext->bpp == 24) {
      xcontext->r_mask_output >>= 8;
      xcontext->g_mask_output >>= 8;
      xcontext->b_mask_output >>= 8;
    }
  } else {
    xcontext->r_mask_output = xcontext->visual->red_mask;
    xcontext->g_mask_output = xcontext->visual->green_mask;
    xcontext->b_mask_output = xcontext->visual->blue_mask;
  }

  return xcontext;
}

/* This function cleans the X context. Closing the Display and unrefing the
   caps for supported formats. */
void
ximageutil_xcontext_clear (GstXContext * xcontext)
{
  g_return_if_fail (xcontext != NULL);

  if (xcontext->caps != NULL)
    gst_caps_unref (xcontext->caps);

  XCloseDisplay (xcontext->disp);

  g_free (xcontext);
}

/* This function calculates the pixel aspect ratio based on the properties
 * in the xcontext structure and stores it there. */
void
ximageutil_calculate_pixel_aspect_ratio (GstXContext * xcontext)
{
  gint par[][2] = {
    {1, 1},                     /* regular screen */
    {16, 15},                   /* PAL TV */
    {11, 10},                   /* 525 line Rec.601 video */
    {54, 59}                    /* 625 line Rec.601 video */
  };
  gint i;
  gint index;
  gdouble ratio;
  gdouble delta;

#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))

  /* first calculate the "real" ratio based on the X values;
   * which is the "physical" w/h divided by the w/h in pixels of the display */
  ratio = (gdouble) (xcontext->widthmm * xcontext->height)
      / (xcontext->heightmm * xcontext->width);

  /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
   * override here */
  if (xcontext->width == 720 && xcontext->height == 576) {
    ratio = 4.0 * 576 / (3.0 * 720);
  }
  GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);

  /* now find the one from par[][2] with the lowest delta to the real one */
  delta = DELTA (0);
  index = 0;

  for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
    gdouble this_delta = DELTA (i);

    if (this_delta < delta) {
      index = i;
      delta = this_delta;
    }
  }

  GST_DEBUG ("Decided on index %d (%d/%d)", index,
      par[index][0], par[index][1]);

  xcontext->par_n = par[index][0];
  xcontext->par_d = par[index][1];
  GST_DEBUG ("set xcontext PAR to %d/%d\n", xcontext->par_n, xcontext->par_d);
}

static gboolean
gst_ximagesrc_buffer_dispose (GstBuffer * ximage)
{
  GstElement *parent;
  GstMetaXImage *meta;
  gboolean ret = TRUE;

  meta = GST_META_XIMAGE_GET (ximage);

  parent = meta->parent;
  if (parent == NULL) {
    g_warning ("XImageSrcBuffer->ximagesrc == NULL");
    goto beach;
  }

  if (meta->return_func)
    ret = meta->return_func (parent, ximage);

beach:
  return ret;
}

void
gst_ximage_buffer_free (GstBuffer * ximage)
{
  GstMetaXImage *meta;

  meta = GST_META_XIMAGE_GET (ximage);

  /* make sure it is not recycled */
  meta->width = -1;
  meta->height = -1;
  gst_buffer_unref (ximage);
}

/* This function handles GstXImageSrcBuffer creation depending on XShm availability */
GstBuffer *
gst_ximageutil_ximage_new (GstXContext * xcontext,
    GstElement * parent, int width, int height, BufferReturnFunc return_func)
{
  GstBuffer *ximage = NULL;
  GstMetaXImage *meta;
  gboolean succeeded = FALSE;

  ximage = gst_buffer_new ();
  GST_MINI_OBJECT_CAST (ximage)->dispose =
      (GstMiniObjectDisposeFunction) gst_ximagesrc_buffer_dispose;

  meta = GST_META_XIMAGE_ADD (ximage);
  meta->width = width;
  meta->height = height;

#ifdef HAVE_XSHM
  meta->SHMInfo.shmaddr = ((void *) -1);
  meta->SHMInfo.shmid = -1;

  if (xcontext->use_xshm) {
    meta->ximage = XShmCreateImage (xcontext->disp,
        xcontext->visual, xcontext->depth,
        ZPixmap, NULL, &meta->SHMInfo, meta->width, meta->height);
    if (!meta->ximage) {
      GST_WARNING_OBJECT (parent,
          "could not XShmCreateImage a %dx%d image", meta->width, meta->height);

      /* Retry without XShm */
      xcontext->use_xshm = FALSE;
      goto no_xshm;
    }

    /* we have to use the returned bytes_per_line for our shm size */
    meta->size = meta->ximage->bytes_per_line * meta->ximage->height;
    meta->SHMInfo.shmid = shmget (IPC_PRIVATE, meta->size, IPC_CREAT | 0777);
    if (meta->SHMInfo.shmid == -1)
      goto beach;

    meta->SHMInfo.shmaddr = shmat (meta->SHMInfo.shmid, 0, 0);
    if (meta->SHMInfo.shmaddr == ((void *) -1))
      goto beach;

    /* Delete the SHM segment. It will actually go away automatically
     * when we detach now */
    shmctl (meta->SHMInfo.shmid, IPC_RMID, 0);

    meta->ximage->data = meta->SHMInfo.shmaddr;
    meta->SHMInfo.readOnly = FALSE;

    if (XShmAttach (xcontext->disp, &meta->SHMInfo) == 0)
      goto beach;

    XSync (xcontext->disp, FALSE);
  } else
  no_xshm:
#endif /* HAVE_XSHM */
  {
    meta->ximage = XCreateImage (xcontext->disp,
        xcontext->visual,
        xcontext->depth,
        ZPixmap, 0, NULL, meta->width, meta->height, xcontext->bpp, 0);
    if (!meta->ximage)
      goto beach;

    /* we have to use the returned bytes_per_line for our image size */
    meta->size = meta->ximage->bytes_per_line * meta->ximage->height;
    meta->ximage->data = g_malloc (meta->size);

    XSync (xcontext->disp, FALSE);
  }
  succeeded = TRUE;

  gst_buffer_append_memory (ximage,
      gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, meta->ximage->data,
          meta->size, 0, meta->size, NULL, NULL));

  /* Keep a ref to our src */
  meta->parent = gst_object_ref (parent);
  meta->return_func = return_func;
beach:
  if (!succeeded) {
    gst_ximage_buffer_free (ximage);
    ximage = NULL;
  }

  return ximage;
}

/* This function destroys a GstXImageBuffer handling XShm availability */
void
gst_ximageutil_ximage_destroy (GstXContext * xcontext, GstBuffer * ximage)
{
  GstMetaXImage *meta;

  meta = GST_META_XIMAGE_GET (ximage);

  /* We might have some buffers destroyed after changing state to NULL */
  if (!xcontext)
    goto beach;

  g_return_if_fail (ximage != NULL);

#ifdef HAVE_XSHM
  if (xcontext->use_xshm) {
    if (meta->SHMInfo.shmaddr != ((void *) -1)) {
      XShmDetach (xcontext->disp, &meta->SHMInfo);
      XSync (xcontext->disp, 0);
      shmdt (meta->SHMInfo.shmaddr);
    }
    if (meta->ximage)
      XDestroyImage (meta->ximage);

  } else
#endif /* HAVE_XSHM */
  {
    if (meta->ximage) {
      XDestroyImage (meta->ximage);
    }
  }

  XSync (xcontext->disp, FALSE);
beach:
  if (meta->parent) {
    /* Release the ref to our parent */
    gst_object_unref (meta->parent);
    meta->parent = NULL;
  }

  return;
}
