/* rygel-audio-transcoder.c generated by valac 0.40.8, 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.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.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;
enum  {
	RYGEL_AUDIO_TRANSCODER_0_PROPERTY,
	RYGEL_AUDIO_TRANSCODER_NUM_PROPERTIES
};
static GParamSpec* rygel_audio_transcoder_properties[RYGEL_AUDIO_TRANSCODER_NUM_PROPERTIES];
#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;
#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;
	GstCaps* _tmp1_;
	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);
	self = (RygelAudioTranscoder*) rygel_gst_transcoder_construct (object_type, name, content_type, dlna_profile, extension);
	self->audio_bitrate = audio_bitrate;
	if (container_caps != NULL) {
		GstCaps* _tmp0_;
		_tmp0_ = gst_caps_from_string (container_caps);
		_gst_caps_unref0 (self->container_format);
		self->container_format = _tmp0_;
	}
	_tmp1_ = gst_caps_from_string (audio_codec_caps);
	_gst_caps_unref0 (self->audio_codec_format);
	self->audio_codec_format = _tmp1_;
	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;
	GstCaps* _tmp1_;
	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);
	self = (RygelAudioTranscoder*) rygel_gst_transcoder_construct (object_type, name, content_type, dlna_profile, extension);
	self->audio_bitrate = audio_bitrate;
	if (container_caps != NULL) {
		GstCaps* _tmp0_;
		_tmp0_ = gst_caps_from_string (container_caps);
		_gst_caps_unref0 (self->container_format);
		self->container_format = _tmp0_;
	}
	_tmp1_ = gst_caps_from_string (audio_codec_caps);
	_gst_caps_unref0 (self->audio_codec_format);
	self->audio_codec_format = _tmp1_;
	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;
	RygelAudioItem* audio_item = NULL;
	RygelAudioItem* _tmp1_;
	guint distance = 0U;
	RygelAudioItem* _tmp2_;
	gint _tmp3_;
	gint _tmp4_;
	self = (RygelAudioTranscoder*) base;
	g_return_val_if_fail (item != NULL, 0U);
	if (!G_TYPE_CHECK_INSTANCE_TYPE (item, RYGEL_TYPE_AUDIO_ITEM)) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = G_TYPE_CHECK_INSTANCE_TYPE (item, RYGEL_TYPE_VIDEO_ITEM);
	}
	if (_tmp0_) {
		result = G_MAXUINT;
		return result;
	}
	_tmp1_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_TYPE (item, RYGEL_TYPE_AUDIO_ITEM) ? ((RygelAudioItem*) item) : NULL);
	audio_item = _tmp1_;
	distance = 0;
	_tmp2_ = audio_item;
	_tmp3_ = rygel_audio_item_get_bitrate (_tmp2_);
	_tmp4_ = _tmp3_;
	if (_tmp4_ > 0) {
		guint _tmp5_;
		RygelAudioItem* _tmp6_;
		gint _tmp7_;
		gint _tmp8_;
		gint _tmp9_;
		_tmp5_ = distance;
		_tmp6_ = audio_item;
		_tmp7_ = rygel_audio_item_get_bitrate (_tmp6_);
		_tmp8_ = _tmp7_;
		_tmp9_ = self->audio_bitrate;
		distance = _tmp5_ + abs (_tmp8_ - _tmp9_);
	}
	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_;
	const gchar* _tmp1_;
	const gchar* _tmp2_;
	GstEncodingAudioProfile* _tmp3_;
	GstEncodingAudioProfile* _tmp4_;
	GstCaps* _tmp5_;
	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_;
		const gchar* _tmp7_;
		const gchar* _tmp8_;
		GstEncodingContainerProfile* _tmp9_;
		GstEncodingContainerProfile* _tmp10_;
		GstEncodingAudioProfile* _tmp11_;
		GstEncodingProfile* _tmp12_;
		_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;
	RygelMediaResource* _tmp0_;
	RygelMediaResource* _tmp1_;
	RygelMediaResource* _tmp2_;
	gint _tmp3_;
	self = (RygelAudioTranscoder*) base;
	g_return_val_if_fail (item != NULL, NULL);
	_tmp0_ = RYGEL_GST_TRANSCODER_CLASS (rygel_audio_transcoder_parent_class)->get_resource_for_item (G_TYPE_CHECK_INSTANCE_CAST (self, RYGEL_TYPE_GST_TRANSCODER, RygelGstTranscoder), item);
	resource = _tmp0_;
	_tmp1_ = resource;
	if (_tmp1_ == NULL) {
		result = NULL;
		_g_object_unref0 (resource);
		return result;
	}
	_tmp2_ = resource;
	_tmp3_ = self->audio_bitrate;
	rygel_media_resource_set_sample_freq (_tmp2_, _tmp3_);
	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 = (guint (*) (RygelGstTranscoder *, RygelMediaFileItem*)) rygel_audio_transcoder_real_get_distance;
	((RygelGstTranscoderClass *) klass)->get_encoding_profile = (GstEncodingProfile* (*) (RygelGstTranscoder *)) rygel_audio_transcoder_real_get_encoding_profile;
	((RygelGstTranscoderClass *) klass)->get_resource_for_item = (RygelMediaResource* (*) (RygelGstTranscoder *, RygelMediaFileItem*)) 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;
}



