/* poppler-media.cc: glib interface to MediaRendition
 *
 * Copyright (C) 2010 Carlos Garcia Campos <carlosgc@gnome.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "config.h"

#include <errno.h>
#include <glib/gstdio.h>

#include "poppler-media.h"
#include "poppler-private.h"

/**
 * SECTION: poppler-media
 * @short_description: Media
 * @title: PopplerMedia
 */

typedef struct _PopplerMediaClass PopplerMediaClass;

struct _PopplerMedia
{
  GObject   parent_instance;

  gchar  *filename;

  gchar  *mime_type;
  Object stream;
};

struct _PopplerMediaClass
{
  GObjectClass parent_class;
};

G_DEFINE_TYPE (PopplerMedia, poppler_media, G_TYPE_OBJECT);

static void
poppler_media_finalize (GObject *object)
{
  PopplerMedia *media = POPPLER_MEDIA(object);

  if (media->filename) {
    g_free (media->filename);
    media->filename = NULL;
  }

  if (media->mime_type) {
    g_free (media->mime_type);
    media->mime_type = NULL;
  }

  media->stream = Object();

  G_OBJECT_CLASS (poppler_media_parent_class)->finalize (object);
}

static void
poppler_media_class_init (PopplerMediaClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->finalize = poppler_media_finalize;
}

static void
poppler_media_init (PopplerMedia *media)
{
}

PopplerMedia *
_poppler_media_new (MediaRendition *poppler_media)
{
  PopplerMedia *media;

  g_assert (poppler_media != NULL);

  media = POPPLER_MEDIA (g_object_new (POPPLER_TYPE_MEDIA, NULL));

  if (poppler_media->getIsEmbedded()) {
    GooString* mime_type;

    media->stream = poppler_media->getEmbbededStreamObject()->copy();
    mime_type = poppler_media->getContentType();
    if (mime_type)
      media->mime_type = g_strdup (mime_type->getCString());
  } else {
    media->filename = g_strdup (poppler_media->getFileName()->getCString());
  }

  return media;
}

/**
* poppler_media_get_filename:
* @poppler_media: a #PopplerMedia
*
* Returns the media clip filename, in case of non-embedded media. filename might be
* a local relative or absolute path or a URI
*
* Return value: a filename, return value is owned by #PopplerMedia and should not be freed
*
* Since: 0.14
*/
const gchar *
poppler_media_get_filename (PopplerMedia *poppler_media)
{
  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), NULL);
  g_return_val_if_fail (!poppler_media->stream.isStream(), NULL);

  return poppler_media->filename;
}

/**
 * poppler_media_is_embedded:
 * @poppler_media: a #PopplerMedia
 *
 * Whether the media clip is embedded in the PDF. If the result is %TRUE, the embedded stream
 * can be saved with poppler_media_save() or poppler_media_save_to_callback() function.
 * If the result is %FALSE, the media clip filename can be retrieved with
 * poppler_media_get_filename() function.
 *
 * Return value: %TRUE if media clip is embedded, %FALSE otherwise
 *
 * Since: 0.14
 */
gboolean
poppler_media_is_embedded (PopplerMedia *poppler_media)
{
  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), FALSE);

  return poppler_media->stream.isStream();
}

/**
 * poppler_media_get_mime_type:
 * @poppler_media: a #PopplerMedia
 *
 * Returns the media clip mime-type
 *
 * Return value: the mime-type, return value is owned by #PopplerMedia and should not be freed
 *
 * Since: 0.14
 */
const gchar *
poppler_media_get_mime_type (PopplerMedia *poppler_media)
{
  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), NULL);

  return poppler_media->mime_type;
}

static gboolean
save_helper (const gchar  *buf,
	     gsize         count,
	     gpointer      data,
	     GError      **error)
{
  FILE *f = (FILE *) data;
  gsize n;

  n = fwrite (buf, 1, count, f);
  if (n != count)
    {
      g_set_error (error,
		   G_FILE_ERROR,
		   g_file_error_from_errno (errno),
		   "Error writing to media file: %s",
		   g_strerror (errno));
      return FALSE;
    }

  return TRUE;
}

/**
 * poppler_media_save:
 * @poppler_media: a #PopplerMedia
 * @filename: name of file to save
 * @error: (allow-none): return location for error, or %NULL.
 *
 * Saves embedded stream of @poppler_media to a file indicated by @filename.
 * If @error is set, %FALSE will be returned.
 * Possible errors include those in the #G_FILE_ERROR domain
 * and whatever the save function generates.
 *
 * Return value: %TRUE, if the file successfully saved
 *
 * Since: 0.14
 */
gboolean
poppler_media_save (PopplerMedia *poppler_media,
		    const char   *filename,
		    GError      **error)
{
  gboolean result;
  FILE *f;

  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), FALSE);
  g_return_val_if_fail (poppler_media->stream.isStream(), FALSE);

  f = g_fopen (filename, "wb");

  if (f == NULL)
    {
      gchar *display_name = g_filename_display_name (filename);
      g_set_error (error,
		   G_FILE_ERROR,
		   g_file_error_from_errno (errno),
		   "Failed to open '%s' for writing: %s",
		   display_name,
		   g_strerror (errno));
      g_free (display_name);
      return FALSE;
    }

  result = poppler_media_save_to_callback (poppler_media, save_helper, f, error);

  if (fclose (f) < 0)
    {
      gchar *display_name = g_filename_display_name (filename);
      g_set_error (error,
		   G_FILE_ERROR,
		   g_file_error_from_errno (errno),
		   "Failed to close '%s', all data may not have been saved: %s",
		   display_name,
		   g_strerror (errno));
      g_free (display_name);
      return FALSE;
    }

  return result;
}

#define BUF_SIZE 1024

/**
 * poppler_media_save_to_callback:
 * @poppler_media: a #PopplerMedia
 * @save_func: (scope call): a function that is called to save each block of data that the save routine generates.
 * @user_data: user data to pass to the save function.
 * @error: (allow-none): return location for error, or %NULL.
 *
 * Saves embedded stream of @poppler_media by feeding the produced data to @save_func. Can be used
 * when you want to store the media clip stream to something other than a file, such as
 * an in-memory buffer or a socket. If @error is set, %FALSE will be
 * returned. Possible errors include those in the #G_FILE_ERROR domain and
 * whatever the save function generates.
 *
 * Return value: %TRUE, if the save successfully completed
 *
 * Since: 0.14
 */
gboolean
poppler_media_save_to_callback (PopplerMedia        *poppler_media,
				PopplerMediaSaveFunc save_func,
				gpointer             user_data,
				GError             **error)
{
  Stream *stream;
  gchar buf[BUF_SIZE];
  int i;
  gboolean eof_reached = FALSE;

  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), FALSE);
  g_return_val_if_fail (poppler_media->stream.isStream(), FALSE);

  stream = poppler_media->stream.getStream();
  stream->reset();

  do
    {
      int data;

      for (i = 0; i < BUF_SIZE; i++)
	{
	  data = stream->getChar ();
	  if (data == EOF)
	    {
	      eof_reached = TRUE;
	      break;
	    }
	  buf[i] = data;
	}

      if (i > 0)
	{
	  if (! (save_func) (buf, i, user_data, error))
	    {
	      stream->close ();
	      return FALSE;
	    }
	}
    }
  while (! eof_reached);

  stream->close ();

  return TRUE;
}
