/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2004-2009  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 "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);
}


