/* rygel-audio-transcoder.c generated by valac 0.31.1.6-4f062, the Vala compiler
 * generated from rygel-audio-transcoder.vala, do not modify */

/*
 * Copyright (C) 2011 Nokia Corporation.
 * Copyright (C) 2012 Intel Corporation.
 * Copyright (C) 2013 Cable Television Laboratories, Inc.
 *
 * Author: Jens Georg <jensg@openismus.com>
 *         Prasanna Modem <prasanna@ecaspia.com>
 *
 * 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 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 program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <glib.h>
#include <glib-object.h>
#include <rygel-server.h>
#include <gst/pbutils/pbutils.h>
#include <gst/gst.h>
#include <stdlib.h>
#include <string.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_AUDIO_TRANSCODER (rygel_audio_transcoder_get_type ())
#define RYGEL_AUDIO_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RYGEL_TYPE_AUDIO_TRANSCODER, RygelAudioTranscoder))
#define RYGEL_AUDIO_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RYGEL_TYPE_AUDIO_TRANSCODER, RygelAudioTranscoderClass))
#define RYGEL_IS_AUDIO_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RYGEL_TYPE_AUDIO_TRANSCODER))
#define RYGEL_IS_AUDIO_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RYGEL_TYPE_AUDIO_TRANSCODER))
#define RYGEL_AUDIO_TRANSCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RYGEL_TYPE_AUDIO_TRANSCODER, RygelAudioTranscoderClass))

typedef struct _RygelAudioTranscoder RygelAudioTranscoder;
typedef struct _RygelAudioTranscoderClass RygelAudioTranscoderClass;
typedef struct _RygelAudioTranscoderPrivate RygelAudioTranscoderPrivate;
#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);
};

struct _RygelAudioTranscoder {
	RygelGstTranscoder parent_instance;
	RygelAudioTranscoderPrivate * priv;
	gint audio_bitrate;
	GstCaps* container_format;
	GstCaps* audio_codec_format;
};

struct _RygelAudioTranscoderClass {
	RygelGstTranscoderClass parent_class;
};


static gpointer rygel_audio_transcoder_parent_class = NULL;

GType rygel_gst_transcoder_get_type (void) G_GNUC_CONST;
GType rygel_audio_transcoder_get_type (void) G_GNUC_CONST;
enum  {
	RYGEL_AUDIO_TRANSCODER_DUMMY_PROPERTY
};
#define RYGEL_AUDIO_TRANSCODER_NO_CONTAINER NULL
RygelAudioTranscoder* rygel_audio_transcoder_construct (GType object_type, const gchar* name, const gchar* content_type, const gchar* dlna_profile, gint audio_bitrate, const gchar* container_caps, const gchar* audio_codec_caps, const gchar* extension);
RygelGstTranscoder* rygel_gst_transcoder_construct (GType object_type, const gchar* name, const gchar* mime_type, const gchar* dlna_profile, const gchar* extension);
RygelAudioTranscoder* rygel_audio_transcoder_construct_with_class (GType object_type, const gchar* name, const gchar* content_type, const gchar* dlna_profile, gint audio_bitrate, const gchar* container_caps, const gchar* audio_codec_caps, const gchar* extension);
static guint rygel_audio_transcoder_real_get_distance (RygelGstTranscoder* base, RygelMediaFileItem* item);
static GstEncodingProfile* rygel_audio_transcoder_real_get_encoding_profile (RygelGstTranscoder* base);
const gchar* rygel_gst_transcoder_get_preset (RygelGstTranscoder* self);
static RygelMediaResource* rygel_audio_transcoder_real_get_resource_for_item (RygelGstTranscoder* base, RygelMediaFileItem* item);
RygelMediaResource* rygel_gst_transcoder_get_resource_for_item (RygelGstTranscoder* self, RygelMediaFileItem* item);
static void rygel_audio_transcoder_finalize (GObject* obj);


RygelAudioTranscoder* rygel_audio_transcoder_construct (GType object_type, const gchar* name, const gchar* content_type, const gchar* dlna_profile, gint audio_bitrate, const gchar* container_caps, const gchar* audio_codec_caps, const gchar* extension) {
	RygelAudioTranscoder * self = NULL;
	const gchar* _tmp0_ = NULL;
	const gchar* _tmp1_ = NULL;
	const gchar* _tmp2_ = NULL;
	const gchar* _tmp3_ = NULL;
	gint _tmp4_ = 0;
	const gchar* _tmp5_ = NULL;
	const gchar* _tmp8_ = NULL;
	GstCaps* _tmp9_ = NULL;
	g_return_val_if_fail (name != NULL, NULL);
	g_return_val_if_fail (content_type != NULL, NULL);
	g_return_val_if_fail (dlna_profile != NULL, NULL);
	g_return_val_if_fail (audio_codec_caps != NULL, NULL);
	g_return_val_if_fail (extension != NULL, NULL);
	_tmp0_ = name;
	_tmp1_ = content_type;
	_tmp2_ = dlna_profile;
	_tmp3_ = extension;
	self = (RygelAudioTranscoder*) rygel_gst_transcoder_construct (object_type, _tmp0_, _tmp1_, _tmp2_, _tmp3_);
	_tmp4_ = audio_bitrate;
	self->audio_bitrate = _tmp4_;
	_tmp5_ = container_caps;
	if (_tmp5_ != NULL) {
		const gchar* _tmp6_ = NULL;
		GstCaps* _tmp7_ = NULL;
		_tmp6_ = container_caps;
		_tmp7_ = gst_caps_from_string (_tmp6_);
		_gst_caps_unref0 (self->container_format);
		self->container_format = _tmp7_;
	}
	_tmp8_ = audio_codec_caps;
	_tmp9_ = gst_caps_from_string (_tmp8_);
	_gst_caps_unref0 (self->audio_codec_format);
	self->audio_codec_format = _tmp9_;
	return self;
}


RygelAudioTranscoder* rygel_audio_transcoder_construct_with_class (GType object_type, const gchar* name, const gchar* content_type, const gchar* dlna_profile, gint audio_bitrate, const gchar* container_caps, const gchar* audio_codec_caps, const gchar* extension) {
	RygelAudioTranscoder * self = NULL;
	const gchar* _tmp0_ = NULL;
	const gchar* _tmp1_ = NULL;
	const gchar* _tmp2_ = NULL;
	const gchar* _tmp3_ = NULL;
	gint _tmp4_ = 0;
	const gchar* _tmp5_ = NULL;
	const gchar* _tmp8_ = NULL;
	GstCaps* _tmp9_ = NULL;
	g_return_val_if_fail (name != NULL, NULL);
	g_return_val_if_fail (content_type != NULL, NULL);
	g_return_val_if_fail (dlna_profile != NULL, NULL);
	g_return_val_if_fail (audio_codec_caps != NULL, NULL);
	g_return_val_if_fail (extension != NULL, NULL);
	_tmp0_ = name;
	_tmp1_ = content_type;
	_tmp2_ = dlna_profile;
	_tmp3_ = extension;
	self = (RygelAudioTranscoder*) rygel_gst_transcoder_construct (object_type, _tmp0_, _tmp1_, _tmp2_, _tmp3_);
	_tmp4_ = audio_bitrate;
	self->audio_bitrate = _tmp4_;
	_tmp5_ = container_caps;
	if (_tmp5_ != NULL) {
		const gchar* _tmp6_ = NULL;
		GstCaps* _tmp7_ = NULL;
		_tmp6_ = container_caps;
		_tmp7_ = gst_caps_from_string (_tmp6_);
		_gst_caps_unref0 (self->container_format);
		self->container_format = _tmp7_;
	}
	_tmp8_ = audio_codec_caps;
	_tmp9_ = gst_caps_from_string (_tmp8_);
	_gst_caps_unref0 (self->audio_codec_format);
	self->audio_codec_format = _tmp9_;
	return self;
}


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


static guint rygel_audio_transcoder_real_get_distance (RygelGstTranscoder* base, RygelMediaFileItem* item) {
	RygelAudioTranscoder * self;
	guint result = 0U;
	gboolean _tmp0_ = FALSE;
	RygelMediaFileItem* _tmp1_ = NULL;
	RygelAudioItem* audio_item = NULL;
	RygelMediaFileItem* _tmp3_ = NULL;
	RygelAudioItem* _tmp4_ = NULL;
	guint distance = 0U;
	RygelAudioItem* _tmp5_ = NULL;
	gint _tmp6_ = 0;
	gint _tmp7_ = 0;
	self = (RygelAudioTranscoder*) base;
	g_return_val_if_fail (item != NULL, 0U);
	_tmp1_ = item;
	if (!G_TYPE_CHECK_INSTANCE_TYPE (_tmp1_, RYGEL_TYPE_AUDIO_ITEM)) {
		_tmp0_ = TRUE;
	} else {
		RygelMediaFileItem* _tmp2_ = NULL;
		_tmp2_ = item;
		_tmp0_ = G_TYPE_CHECK_INSTANCE_TYPE (_tmp2_, RYGEL_TYPE_VIDEO_ITEM);
	}
	if (_tmp0_) {
		result = G_MAXUINT;
		return result;
	}
	_tmp3_ = item;
	_tmp4_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_TYPE (_tmp3_, RYGEL_TYPE_AUDIO_ITEM) ? ((RygelAudioItem*) _tmp3_) : NULL);
	audio_item = _tmp4_;
	distance = 0;
	_tmp5_ = audio_item;
	_tmp6_ = rygel_audio_item_get_bitrate (_tmp5_);
	_tmp7_ = _tmp6_;
	if (_tmp7_ > 0) {
		guint _tmp8_ = 0U;
		RygelAudioItem* _tmp9_ = NULL;
		gint _tmp10_ = 0;
		gint _tmp11_ = 0;
		gint _tmp12_ = 0;
		gint _tmp13_ = 0;
		_tmp8_ = distance;
		_tmp9_ = audio_item;
		_tmp10_ = rygel_audio_item_get_bitrate (_tmp9_);
		_tmp11_ = _tmp10_;
		_tmp12_ = self->audio_bitrate;
		_tmp13_ = abs (_tmp11_ - _tmp12_);
		distance = _tmp8_ + _tmp13_;
	}
	result = distance;
	_g_object_unref0 (audio_item);
	return result;
}


static GstEncodingProfile* rygel_audio_transcoder_real_get_encoding_profile (RygelGstTranscoder* base) {
	RygelAudioTranscoder * self;
	GstEncodingProfile* result = NULL;
	GstEncodingAudioProfile* enc_audio_profile = NULL;
	GstCaps* _tmp0_ = NULL;
	const gchar* _tmp1_ = NULL;
	const gchar* _tmp2_ = NULL;
	GstEncodingAudioProfile* _tmp3_ = NULL;
	GstEncodingAudioProfile* _tmp4_ = NULL;
	GstCaps* _tmp5_ = NULL;
	self = (RygelAudioTranscoder*) base;
	_tmp0_ = self->audio_codec_format;
	_tmp1_ = rygel_gst_transcoder_get_preset ((RygelGstTranscoder*) self);
	_tmp2_ = _tmp1_;
	_tmp3_ = gst_encoding_audio_profile_new (_tmp0_, _tmp2_, NULL, (guint) 1);
	enc_audio_profile = _tmp3_;
	_tmp4_ = enc_audio_profile;
	gst_encoding_profile_set_name ((GstEncodingProfile*) _tmp4_, "audio");
	_tmp5_ = self->container_format;
	if (_tmp5_ != NULL) {
		GstEncodingContainerProfile* enc_container_profile = NULL;
		GstCaps* _tmp6_ = NULL;
		const gchar* _tmp7_ = NULL;
		const gchar* _tmp8_ = NULL;
		GstEncodingContainerProfile* _tmp9_ = NULL;
		GstEncodingContainerProfile* _tmp10_ = NULL;
		GstEncodingAudioProfile* _tmp11_ = NULL;
		GstEncodingProfile* _tmp12_ = NULL;
		_tmp6_ = self->container_format;
		_tmp7_ = rygel_gst_transcoder_get_preset ((RygelGstTranscoder*) self);
		_tmp8_ = _tmp7_;
		_tmp9_ = gst_encoding_container_profile_new ("container", NULL, _tmp6_, _tmp8_);
		enc_container_profile = _tmp9_;
		_tmp10_ = enc_container_profile;
		_tmp11_ = enc_audio_profile;
		_tmp12_ = _g_object_ref0 ((GstEncodingProfile*) _tmp11_);
		gst_encoding_container_profile_add_profile (_tmp10_, _tmp12_);
		result = (GstEncodingProfile*) enc_container_profile;
		_g_object_unref0 (enc_audio_profile);
		return result;
	}
	result = (GstEncodingProfile*) enc_audio_profile;
	return result;
}


static RygelMediaResource* rygel_audio_transcoder_real_get_resource_for_item (RygelGstTranscoder* base, RygelMediaFileItem* item) {
	RygelAudioTranscoder * self;
	RygelMediaResource* result = NULL;
	RygelMediaResource* resource = NULL;
	RygelMediaFileItem* _tmp0_ = NULL;
	RygelMediaResource* _tmp1_ = NULL;
	RygelMediaResource* _tmp2_ = NULL;
	RygelMediaResource* _tmp3_ = NULL;
	gint _tmp4_ = 0;
	self = (RygelAudioTranscoder*) base;
	g_return_val_if_fail (item != NULL, NULL);
	_tmp0_ = item;
	_tmp1_ = RYGEL_GST_TRANSCODER_CLASS (rygel_audio_transcoder_parent_class)->get_resource_for_item (G_TYPE_CHECK_INSTANCE_CAST (self, RYGEL_TYPE_GST_TRANSCODER, RygelGstTranscoder), _tmp0_);
	resource = _tmp1_;
	_tmp2_ = resource;
	if (_tmp2_ == NULL) {
		result = NULL;
		_g_object_unref0 (resource);
		return result;
	}
	_tmp3_ = resource;
	_tmp4_ = self->audio_bitrate;
	rygel_media_resource_set_sample_freq (_tmp3_, _tmp4_);
	result = resource;
	return result;
}


static void rygel_audio_transcoder_class_init (RygelAudioTranscoderClass * klass) {
	rygel_audio_transcoder_parent_class = g_type_class_peek_parent (klass);
	((RygelGstTranscoderClass *) klass)->get_distance = rygel_audio_transcoder_real_get_distance;
	((RygelGstTranscoderClass *) klass)->get_encoding_profile = rygel_audio_transcoder_real_get_encoding_profile;
	((RygelGstTranscoderClass *) klass)->get_resource_for_item = rygel_audio_transcoder_real_get_resource_for_item;
	G_OBJECT_CLASS (klass)->finalize = rygel_audio_transcoder_finalize;
}


static void rygel_audio_transcoder_instance_init (RygelAudioTranscoder * self) {
	self->container_format = NULL;
	self->audio_codec_format = NULL;
}


static void rygel_audio_transcoder_finalize (GObject* obj) {
	RygelAudioTranscoder * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, RYGEL_TYPE_AUDIO_TRANSCODER, RygelAudioTranscoder);
	_gst_caps_unref0 (self->container_format);
	_gst_caps_unref0 (self->audio_codec_format);
	G_OBJECT_CLASS (rygel_audio_transcoder_parent_class)->finalize (obj);
}


/**
 * Base class for all transcoders that handle audio.
 */
GType rygel_audio_transcoder_get_type (void) {
	static volatile gsize rygel_audio_transcoder_type_id__volatile = 0;
	if (g_once_init_enter (&rygel_audio_transcoder_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (RygelAudioTranscoderClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) rygel_audio_transcoder_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RygelAudioTranscoder), 0, (GInstanceInitFunc) rygel_audio_transcoder_instance_init, NULL };
		GType rygel_audio_transcoder_type_id;
		rygel_audio_transcoder_type_id = g_type_register_static (RYGEL_TYPE_GST_TRANSCODER, "RygelAudioTranscoder", &g_define_type_info, G_TYPE_FLAG_ABSTRACT);
		g_once_init_leave (&rygel_audio_transcoder_type_id__volatile, rygel_audio_transcoder_type_id);
	}
	return rygel_audio_transcoder_type_id__volatile;
}



