/* rygel-jpeg-transcoder.c generated by valac 0.42.1.67-6c68, the Vala compiler
 * generated from rygel-jpeg-transcoder.vala, do not modify */

/*
 * Copyright (C) 2010 Nokia Corporation.
 * Copyright (C) 2018 Jens Georg <mail@jensge.org>
 *
 * Author: Jens Georg <jensg@openismus.com>
 *         Jens Georg <mail@jensge.org>
 *
 * This file is part of Rygel.
 *
 * Rygel is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Rygel 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <glib-object.h>
#include <rygel-server.h>
#include <glib.h>
#include <gst/pbutils/pbutils.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include <math.h>
#include <gst/gst.h>
#include <libgupnp-av/gupnp-av.h>

#define RYGEL_TYPE_GST_TRANSCODER (rygel_gst_transcoder_get_type ())
#define RYGEL_GST_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RYGEL_TYPE_GST_TRANSCODER, RygelGstTranscoder))
#define RYGEL_GST_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RYGEL_TYPE_GST_TRANSCODER, RygelGstTranscoderClass))
#define RYGEL_IS_GST_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RYGEL_TYPE_GST_TRANSCODER))
#define RYGEL_IS_GST_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RYGEL_TYPE_GST_TRANSCODER))
#define RYGEL_GST_TRANSCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RYGEL_TYPE_GST_TRANSCODER, RygelGstTranscoderClass))

typedef struct _RygelGstTranscoder RygelGstTranscoder;
typedef struct _RygelGstTranscoderClass RygelGstTranscoderClass;
typedef struct _RygelGstTranscoderPrivate RygelGstTranscoderPrivate;

#define RYGEL_TYPE_JPEG_TRANSCODER (rygel_jpeg_transcoder_get_type ())
#define RYGEL_JPEG_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RYGEL_TYPE_JPEG_TRANSCODER, RygelJPEGTranscoder))
#define RYGEL_JPEG_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RYGEL_TYPE_JPEG_TRANSCODER, RygelJPEGTranscoderClass))
#define RYGEL_IS_JPEG_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RYGEL_TYPE_JPEG_TRANSCODER))
#define RYGEL_IS_JPEG_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RYGEL_TYPE_JPEG_TRANSCODER))
#define RYGEL_JPEG_TRANSCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RYGEL_TYPE_JPEG_TRANSCODER, RygelJPEGTranscoderClass))

typedef struct _RygelJPEGTranscoder RygelJPEGTranscoder;
typedef struct _RygelJPEGTranscoderClass RygelJPEGTranscoderClass;
typedef struct _RygelJPEGTranscoderPrivate RygelJPEGTranscoderPrivate;
enum  {
	RYGEL_JPEG_TRANSCODER_0_PROPERTY,
	RYGEL_JPEG_TRANSCODER_NUM_PROPERTIES
};
static GParamSpec* rygel_jpeg_transcoder_properties[RYGEL_JPEG_TRANSCODER_NUM_PROPERTIES];
#define _g_free0(var) (var = (g_free (var), NULL))
#define _gst_caps_unref0(var) ((var == NULL) ? NULL : (var = (gst_caps_unref (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

struct _RygelGstTranscoder {
	GObject parent_instance;
	RygelGstTranscoderPrivate * priv;
};

struct _RygelGstTranscoderClass {
	GObjectClass parent_class;
	RygelMediaResource* (*get_resource_for_item) (RygelGstTranscoder* self, RygelMediaFileItem* item);
	guint (*get_distance) (RygelGstTranscoder* self, RygelMediaFileItem* item);
	GstEncodingProfile* (*get_encoding_profile) (RygelGstTranscoder* self, RygelMediaFileItem* item);
};

struct _RygelJPEGTranscoder {
	RygelGstTranscoder parent_instance;
	RygelJPEGTranscoderPrivate * priv;
};

struct _RygelJPEGTranscoderClass {
	RygelGstTranscoderClass parent_class;
};

static gpointer rygel_jpeg_transcoder_parent_class = NULL;

GType rygel_gst_transcoder_get_type (void) G_GNUC_CONST;
GType rygel_jpeg_transcoder_get_type (void) G_GNUC_CONST;
#define RYGEL_JPEG_TRANSCODER_PROFILE_TEMPLATE "image/jpeg,framerate=(fraction)1/1,width=%d,height=%d"
RygelJPEGTranscoder* rygel_jpeg_transcoder_new (void);
RygelJPEGTranscoder* rygel_jpeg_transcoder_construct (GType object_type);
RygelGstTranscoder* rygel_gst_transcoder_construct (GType object_type,
                                                    const gchar* name,
                                                    const gchar* mime_type,
                                                    const gchar* dlna_profile,
                                                    const gchar* extension);
static void rygel_jpeg_transcoder_calculate_dimensions (RygelJPEGTranscoder* self,
                                                 RygelVisualItem* item,
                                                 gint* width,
                                                 gint* height);
static GstEncodingProfile* rygel_jpeg_transcoder_real_get_encoding_profile (RygelGstTranscoder* base,
                                                                     RygelMediaFileItem* file_item);
static guint rygel_jpeg_transcoder_real_get_distance (RygelGstTranscoder* base,
                                               RygelMediaFileItem* item);
static RygelMediaResource* rygel_jpeg_transcoder_real_get_resource_for_item (RygelGstTranscoder* base,
                                                                      RygelMediaFileItem* item);
RygelMediaResource* rygel_gst_transcoder_get_resource_for_item (RygelGstTranscoder* self,
                                                                RygelMediaFileItem* item);

RygelJPEGTranscoder*
rygel_jpeg_transcoder_construct (GType object_type)
{
	RygelJPEGTranscoder * self = NULL;
	self = (RygelJPEGTranscoder*) rygel_gst_transcoder_construct (object_type, "JPEG_SM", "image/jpeg", "JPEG_SM", "jpg");
	return self;
}

RygelJPEGTranscoder*
rygel_jpeg_transcoder_new (void)
{
	return rygel_jpeg_transcoder_construct (RYGEL_TYPE_JPEG_TRANSCODER);
}

static void
rygel_jpeg_transcoder_calculate_dimensions (RygelJPEGTranscoder* self,
                                            RygelVisualItem* item,
                                            gint* width,
                                            gint* height)
{
	gint _vala_width = 0;
	gint _vala_height = 0;
	gboolean _tmp0_ = FALSE;
	gint _tmp1_;
	gint _tmp2_;
	gboolean _tmp9_ = FALSE;
	gint _tmp10_;
	gint _tmp11_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (item != NULL);
	_tmp1_ = rygel_visual_item_get_width (item);
	_tmp2_ = _tmp1_;
	if (_tmp2_ <= 640) {
		gint _tmp3_;
		gint _tmp4_;
		_tmp3_ = rygel_visual_item_get_height (item);
		_tmp4_ = _tmp3_;
		_tmp0_ = _tmp4_ <= 480;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		gint _tmp5_;
		gint _tmp6_;
		gint _tmp7_;
		gint _tmp8_;
		_tmp5_ = rygel_visual_item_get_width (item);
		_tmp6_ = _tmp5_;
		_vala_width = _tmp6_;
		_tmp7_ = rygel_visual_item_get_height (item);
		_tmp8_ = _tmp7_;
		_vala_height = _tmp8_;
		if (width) {
			*width = _vala_width;
		}
		if (height) {
			*height = _vala_height;
		}
		return;
	}
	_vala_width = 640;
	_vala_height = 480;
	_tmp10_ = rygel_visual_item_get_width (item);
	_tmp11_ = _tmp10_;
	if (_tmp11_ > 0) {
		gint _tmp12_;
		gint _tmp13_;
		_tmp12_ = rygel_visual_item_get_height (item);
		_tmp13_ = _tmp12_;
		_tmp9_ = _tmp13_ > 0;
	} else {
		_tmp9_ = FALSE;
	}
	if (_tmp9_) {
		gfloat dar = 0.0F;
		gint _tmp14_;
		gint _tmp15_;
		gint _tmp16_;
		gint _tmp17_;
		_tmp14_ = rygel_visual_item_get_width (item);
		_tmp15_ = _tmp14_;
		_tmp16_ = rygel_visual_item_get_height (item);
		_tmp17_ = _tmp16_;
		dar = ((gfloat) _tmp15_) / ((gfloat) _tmp17_);
		if (((gdouble) dar) > (4.0 / 3.0)) {
			_vala_height = (gint) lrint (640.0 / dar);
		} else {
			_vala_width = (gint) lrint (480.0 * dar);
		}
	}
	if (width) {
		*width = _vala_width;
	}
	if (height) {
		*height = _vala_height;
	}
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static GstEncodingProfile*
rygel_jpeg_transcoder_real_get_encoding_profile (RygelGstTranscoder* base,
                                                 RygelMediaFileItem* file_item)
{
	RygelJPEGTranscoder * self;
	GstEncodingProfile* result = NULL;
	RygelVisualItem* item = NULL;
	RygelVisualItem* _tmp0_;
	gint width = 0;
	gint height = 0;
	gint _tmp1_ = 0;
	gint _tmp2_ = 0;
	GstCaps* caps = NULL;
	gchar* _tmp3_;
	gchar* _tmp4_;
	GstCaps* _tmp5_;
	GstCaps* _tmp6_;
	GstEncodingVideoProfile* profile = NULL;
	GstEncodingVideoProfile* _tmp7_;
	self = (RygelJPEGTranscoder*) base;
	g_return_val_if_fail (file_item != NULL, NULL);
	_tmp0_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_TYPE (file_item, RYGEL_TYPE_VISUAL_ITEM) ? ((RygelVisualItem*) file_item) : NULL);
	item = _tmp0_;
	width = -1;
	height = -1;
	rygel_jpeg_transcoder_calculate_dimensions (self, item, &_tmp1_, &_tmp2_);
	width = _tmp1_;
	height = _tmp2_;
	_tmp3_ = g_strdup_printf (RYGEL_JPEG_TRANSCODER_PROFILE_TEMPLATE, width, height);
	_tmp4_ = _tmp3_;
	_tmp5_ = gst_caps_from_string (_tmp4_);
	_tmp6_ = _tmp5_;
	_g_free0 (_tmp4_);
	caps = _tmp6_;
	_tmp7_ = gst_encoding_video_profile_new (caps, NULL, NULL, (guint) 1);
	profile = _tmp7_;
	result = (GstEncodingProfile*) profile;
	_gst_caps_unref0 (caps);
	_g_object_unref0 (item);
	return result;
}

static guint
rygel_jpeg_transcoder_real_get_distance (RygelGstTranscoder* base,
                                         RygelMediaFileItem* item)
{
	RygelJPEGTranscoder * self;
	guint result = 0U;
	const gchar* _tmp0_;
	const gchar* _tmp1_;
	const gchar* _tmp6_;
	const gchar* _tmp7_;
	self = (RygelJPEGTranscoder*) base;
	g_return_val_if_fail (item != NULL, 0U);
	_tmp0_ = rygel_media_object_get_id ((RygelMediaObject*) item);
	_tmp1_ = _tmp0_;
	g_debug ("rygel-jpeg-transcoder.vala:77: Getting distance of JPEG transcoder to " \
"%s", _tmp1_);
	if (!G_TYPE_CHECK_INSTANCE_TYPE (item, RYGEL_TYPE_IMAGE_ITEM)) {
		const gchar* _tmp2_;
		const gchar* _tmp3_;
		_tmp2_ = rygel_media_object_get_id ((RygelMediaObject*) item);
		_tmp3_ = _tmp2_;
		g_debug ("rygel-jpeg-transcoder.vala:80: %s is not an image, skipping", _tmp3_);
		result = G_MAXUINT;
		return result;
	}
	if (G_TYPE_CHECK_INSTANCE_TYPE (item, RYGEL_TYPE_VIDEO_ITEM)) {
		const gchar* _tmp4_;
		const gchar* _tmp5_;
		_tmp4_ = rygel_media_object_get_id ((RygelMediaObject*) item);
		_tmp5_ = _tmp4_;
		g_debug ("rygel-jpeg-transcoder.vala:86: %s is a VideoItem, skipping", _tmp5_);
		result = G_MAXUINT;
		return result;
	}
	_tmp6_ = rygel_media_file_item_get_dlna_profile (item);
	_tmp7_ = _tmp6_;
	if (g_strcmp0 (_tmp7_, "JPEG_SM") == 0) {
		const gchar* _tmp8_;
		const gchar* _tmp9_;
		_tmp8_ = rygel_media_object_get_id ((RygelMediaObject*) item);
		_tmp9_ = _tmp8_;
		g_debug ("rygel-jpeg-transcoder.vala:92: %s is already JPEG_SM, skipping", _tmp9_);
		result = G_MAXUINT;
		return result;
	}
	result = (guint) 1;
	return result;
}

static RygelMediaResource*
rygel_jpeg_transcoder_real_get_resource_for_item (RygelGstTranscoder* base,
                                                  RygelMediaFileItem* item)
{
	RygelJPEGTranscoder * self;
	RygelMediaResource* result = NULL;
	RygelMediaResource* resource = NULL;
	RygelMediaResource* _tmp0_;
	GUPnPDLNAFlags _tmp1_;
	GUPnPDLNAFlags _tmp2_;
	GUPnPDLNAFlags _tmp3_;
	GUPnPDLNAFlags _tmp4_;
	gint width = 0;
	gint height = 0;
	gint _tmp5_ = 0;
	gint _tmp6_ = 0;
	self = (RygelJPEGTranscoder*) base;
	g_return_val_if_fail (item != NULL, NULL);
	_tmp0_ = RYGEL_GST_TRANSCODER_CLASS (rygel_jpeg_transcoder_parent_class)->get_resource_for_item (G_TYPE_CHECK_INSTANCE_CAST (self, RYGEL_TYPE_GST_TRANSCODER, RygelGstTranscoder), item);
	resource = _tmp0_;
	rygel_media_resource_set_dlna_operation (resource, GUPNP_DLNA_OPERATION_NONE);
	_tmp1_ = rygel_media_resource_get_dlna_flags (resource);
	_tmp2_ = _tmp1_;
	rygel_media_resource_set_dlna_flags (resource, _tmp2_ & (~GUPNP_DLNA_FLAGS_STREAMING_TRANSFER_MODE));
	_tmp3_ = rygel_media_resource_get_dlna_flags (resource);
	_tmp4_ = _tmp3_;
	rygel_media_resource_set_dlna_flags (resource, _tmp4_ | GUPNP_DLNA_FLAGS_INTERACTIVE_TRANSFER_MODE);
	rygel_jpeg_transcoder_calculate_dimensions (self, G_TYPE_CHECK_INSTANCE_TYPE (item, RYGEL_TYPE_VISUAL_ITEM) ? ((RygelVisualItem*) item) : NULL, &_tmp5_, &_tmp6_);
	width = _tmp5_;
	height = _tmp6_;
	rygel_media_resource_set_width (resource, width);
	rygel_media_resource_set_height (resource, height);
	result = resource;
	return result;
}

static void
rygel_jpeg_transcoder_class_init (RygelJPEGTranscoderClass * klass)
{
	rygel_jpeg_transcoder_parent_class = g_type_class_peek_parent (klass);
	((RygelGstTranscoderClass *) klass)->get_encoding_profile = (GstEncodingProfile* (*) (RygelGstTranscoder*, RygelMediaFileItem*)) rygel_jpeg_transcoder_real_get_encoding_profile;
	((RygelGstTranscoderClass *) klass)->get_distance = (guint (*) (RygelGstTranscoder*, RygelMediaFileItem*)) rygel_jpeg_transcoder_real_get_distance;
	((RygelGstTranscoderClass *) klass)->get_resource_for_item = (RygelMediaResource* (*) (RygelGstTranscoder*, RygelMediaFileItem*)) rygel_jpeg_transcoder_real_get_resource_for_item;
}

static void
rygel_jpeg_transcoder_instance_init (RygelJPEGTranscoder * self)
{
}

GType
rygel_jpeg_transcoder_get_type (void)
{
	static volatile gsize rygel_jpeg_transcoder_type_id__volatile = 0;
	if (g_once_init_enter (&rygel_jpeg_transcoder_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (RygelJPEGTranscoderClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) rygel_jpeg_transcoder_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RygelJPEGTranscoder), 0, (GInstanceInitFunc) rygel_jpeg_transcoder_instance_init, NULL };
		GType rygel_jpeg_transcoder_type_id;
		rygel_jpeg_transcoder_type_id = g_type_register_static (RYGEL_TYPE_GST_TRANSCODER, "RygelJPEGTranscoder", &g_define_type_info, 0);
		g_once_init_leave (&rygel_jpeg_transcoder_type_id__volatile, rygel_jpeg_transcoder_type_id);
	}
	return rygel_jpeg_transcoder_type_id__volatile;
}

