/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This library 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.
 *
 *  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
 *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string.h>

#include "gstpragma.h"
#include "gstsbcutil.h"
#include "gstsbcdec.h"

GST_DEBUG_CATEGORY_STATIC(sbc_dec_debug);
#define GST_CAT_DEFAULT sbc_dec_debug

GST_BOILERPLATE(GstSbcDec, gst_sbc_dec, GstElement, GST_TYPE_ELEMENT);

static const GstElementDetails sbc_dec_details =
	GST_ELEMENT_DETAILS("Bluetooth SBC decoder",
				"Codec/Decoder/Audio",
				"Decode a SBC audio stream",
				"Marcel Holtmann <marcel@holtmann.org>");

static GstStaticPadTemplate sbc_dec_sink_factory =
	GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
		GST_STATIC_CAPS("audio/x-sbc"));

static GstStaticPadTemplate sbc_dec_src_factory =
	GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS,
		GST_STATIC_CAPS("audio/x-raw-int, "
				"rate = (int) { 16000, 32000, 44100, 48000 }, "
				"channels = (int) [ 1, 2 ], "
				"endianness = (int) BYTE_ORDER, "
				"signed = (boolean) true, "
				"width = (int) 16, "
				"depth = (int) 16"));

static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)
{
	GstSbcDec *dec = GST_SBC_DEC(gst_pad_get_parent(pad));
	GstFlowReturn res = GST_FLOW_OK;
	guint size, codesize, offset = 0;
	guint8 *data;

	codesize = sbc_get_codesize(&dec->sbc);

	if (dec->buffer) {
		GstBuffer *temp = buffer;
		buffer = gst_buffer_span(dec->buffer, 0, buffer,
			GST_BUFFER_SIZE(dec->buffer) + GST_BUFFER_SIZE(buffer));
		gst_buffer_unref(temp);
		gst_buffer_unref(dec->buffer);
		dec->buffer = NULL;
	}

	data = GST_BUFFER_DATA(buffer);
	size = GST_BUFFER_SIZE(buffer);

	while (offset < size) {
		GstBuffer *output;
		GstPadTemplate *template;
		GstCaps *caps;
		int consumed;

		res = gst_pad_alloc_buffer_and_set_caps(dec->srcpad,
						GST_BUFFER_OFFSET_NONE,
						codesize, NULL, &output);

		if (res != GST_FLOW_OK)
			goto done;

		consumed = sbc_decode(&dec->sbc, data + offset, size - offset,
					GST_BUFFER_DATA(output), codesize,
					NULL);
		if (consumed <= 0)
			break;

		/* we will reuse the same caps object */
		if (dec->outcaps == NULL) {
			caps = gst_caps_new_simple("audio/x-raw-int",
					"rate", G_TYPE_INT,
					gst_sbc_parse_rate_from_sbc(
						dec->sbc.frequency),
					"channels", G_TYPE_INT,
					gst_sbc_get_channel_number(
						dec->sbc.mode),
					NULL);

			template = gst_static_pad_template_get(&sbc_dec_src_factory);

			dec->outcaps = gst_caps_intersect(caps,
						gst_pad_template_get_caps(template));

			gst_caps_unref(caps);
		}

		gst_buffer_set_caps(output, dec->outcaps);

		/* FIXME get a real timestamp */
		GST_BUFFER_TIMESTAMP(output) = GST_CLOCK_TIME_NONE;

		res = gst_pad_push(dec->srcpad, output);
		if (res != GST_FLOW_OK)
			goto done;

		offset += consumed;
	}

	if (offset < size)
		dec->buffer = gst_buffer_create_sub(buffer,
							offset, size - offset);

done:
	gst_buffer_unref(buffer);
	gst_object_unref(dec);

	return res;
}

static GstStateChangeReturn sbc_dec_change_state(GstElement *element,
						GstStateChange transition)
{
	GstSbcDec *dec = GST_SBC_DEC(element);

	switch (transition) {
	case GST_STATE_CHANGE_READY_TO_PAUSED:
		GST_DEBUG("Setup subband codec");
		if (dec->buffer) {
			gst_buffer_unref(dec->buffer);
			dec->buffer = NULL;
		}
		sbc_init(&dec->sbc, 0);
		dec->outcaps = NULL;
		break;

	case GST_STATE_CHANGE_PAUSED_TO_READY:
		GST_DEBUG("Finish subband codec");
		if (dec->buffer) {
			gst_buffer_unref(dec->buffer);
			dec->buffer = NULL;
		}
		sbc_finish(&dec->sbc);
		if (dec->outcaps) {
			gst_caps_unref(dec->outcaps);
			dec->outcaps = NULL;
		}
		break;

	default:
		break;
	}

	return parent_class->change_state(element, transition);
}

static void gst_sbc_dec_base_init(gpointer g_class)
{
	GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);

	gst_element_class_add_pad_template(element_class,
		gst_static_pad_template_get(&sbc_dec_sink_factory));

	gst_element_class_add_pad_template(element_class,
		gst_static_pad_template_get(&sbc_dec_src_factory));

	gst_element_class_set_details(element_class, &sbc_dec_details);
}

static void gst_sbc_dec_class_init(GstSbcDecClass *klass)
{
	GstElementClass *element_class = GST_ELEMENT_CLASS(klass);

	parent_class = g_type_class_peek_parent(klass);

	element_class->change_state = GST_DEBUG_FUNCPTR(sbc_dec_change_state);

	GST_DEBUG_CATEGORY_INIT(sbc_dec_debug, "sbcdec", 0,
						"SBC decoding element");
}

static void gst_sbc_dec_init(GstSbcDec *self, GstSbcDecClass *klass)
{
	self->sinkpad = gst_pad_new_from_static_template(
			&sbc_dec_sink_factory, "sink");
	gst_pad_set_chain_function(self->sinkpad, GST_DEBUG_FUNCPTR(
			sbc_dec_chain));
	gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);

	self->srcpad = gst_pad_new_from_static_template(
			&sbc_dec_src_factory, "src");
	gst_element_add_pad(GST_ELEMENT(self), self->srcpad);

	self->outcaps = NULL;
}

gboolean gst_sbc_dec_plugin_init(GstPlugin *plugin)
{
	return gst_element_register(plugin, "sbcdec", GST_RANK_PRIMARY,
							GST_TYPE_SBC_DEC);
}


