/*
 *
 *  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 "gstsbcparse.h"

GST_DEBUG_CATEGORY_STATIC(sbc_parse_debug);
#define GST_CAT_DEFAULT sbc_parse_debug

GST_BOILERPLATE(GstSbcParse, gst_sbc_parse, GstElement, GST_TYPE_ELEMENT);

static const GstElementDetails sbc_parse_details =
	GST_ELEMENT_DETAILS("Bluetooth SBC parser",
				"Codec/Parser/Audio",
				"Parse a SBC audio stream",
				"Marcel Holtmann <marcel@holtmann.org>");

static GstStaticPadTemplate sbc_parse_sink_factory =
	GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
		GST_STATIC_CAPS("audio/x-sbc,"
				"parsed = (boolean) false"));

static GstStaticPadTemplate sbc_parse_src_factory =
	GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS,
		GST_STATIC_CAPS("audio/x-sbc, "
				"rate = (int) { 16000, 32000, 44100, 48000 }, "
				"channels = (int) [ 1, 2 ], "
				"mode = (string) { \"mono\", \"dual\", \"stereo\", \"joint\" }, "
				"blocks = (int) { 4, 8, 12, 16 }, "
				"subbands = (int) { 4, 8 }, "
				"allocation = (string) { \"snr\", \"loudness\" },"
				"bitpool = (int) [ 2, 64 ],"
				"parsed = (boolean) true"));

static GstFlowReturn sbc_parse_chain(GstPad *pad, GstBuffer *buffer)
{
	GstSbcParse *parse = GST_SBC_PARSE(gst_pad_get_parent(pad));
	GstFlowReturn res = GST_FLOW_OK;
	guint size, offset = 0;
	guint8 *data;

	/* FIXME use a gstadpter */
	if (parse->buffer) {
		GstBuffer *temp;
		temp = buffer;
		buffer = gst_buffer_span(parse->buffer, 0, buffer,
			GST_BUFFER_SIZE(parse->buffer)
			+ GST_BUFFER_SIZE(buffer));
		gst_buffer_unref(parse->buffer);
		gst_buffer_unref(temp);
		parse->buffer = NULL;
	}

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

	while (offset < size) {
		GstBuffer *output;
		int consumed;

		consumed = sbc_parse(&parse->new_sbc, data + offset,
					size - offset);
		if (consumed <= 0)
			break;

		if (parse->first_parsing || (memcmp(&parse->sbc,
				&parse->new_sbc, sizeof(sbc_t)) != 0)) {

			memcpy(&parse->sbc, &parse->new_sbc, sizeof(sbc_t));
			if (parse->outcaps != NULL)
				gst_caps_unref(parse->outcaps);

			parse->outcaps = gst_sbc_parse_caps_from_sbc(
						&parse->sbc);

			parse->first_parsing = FALSE;
		}

		res = gst_pad_alloc_buffer_and_set_caps(parse->srcpad,
						GST_BUFFER_OFFSET_NONE,
						consumed, parse->outcaps, &output);

		if (res != GST_FLOW_OK)
			goto done;

		memcpy(GST_BUFFER_DATA(output), data + offset, consumed);

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

		offset += consumed;
	}

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

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

	return res;
}

static GstStateChangeReturn sbc_parse_change_state(GstElement *element,
						GstStateChange transition)
{
	GstSbcParse *parse = GST_SBC_PARSE(element);

	switch (transition) {
	case GST_STATE_CHANGE_READY_TO_PAUSED:
		GST_DEBUG("Setup subband codec");

		parse->channels = -1;
		parse->rate = -1;
		parse->first_parsing = TRUE;

		sbc_init(&parse->sbc, 0);
		break;

	case GST_STATE_CHANGE_PAUSED_TO_READY:
		GST_DEBUG("Finish subband codec");

		if (parse->buffer) {
			gst_buffer_unref(parse->buffer);
			parse->buffer = NULL;
		}
		if (parse->outcaps != NULL) {
			gst_caps_unref(parse->outcaps);
			parse->outcaps = NULL;
		}

		sbc_finish(&parse->sbc);
		break;

	default:
		break;
	}

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

static void gst_sbc_parse_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_parse_sink_factory));

	gst_element_class_add_pad_template(element_class,
		gst_static_pad_template_get(&sbc_parse_src_factory));

	gst_element_class_set_details(element_class, &sbc_parse_details);
}

static void gst_sbc_parse_class_init(GstSbcParseClass *klass)
{
	GstElementClass *element_class = GST_ELEMENT_CLASS(klass);

	parent_class = g_type_class_peek_parent(klass);

	element_class->change_state = GST_DEBUG_FUNCPTR(sbc_parse_change_state);

	GST_DEBUG_CATEGORY_INIT(sbc_parse_debug, "sbcparse", 0,
				"SBC parsing element");
}

static void gst_sbc_parse_init(GstSbcParse *self, GstSbcParseClass *klass)
{
	self->sinkpad = gst_pad_new_from_static_template(
		&sbc_parse_sink_factory, "sink");
	gst_pad_set_chain_function(self->sinkpad,
		GST_DEBUG_FUNCPTR(sbc_parse_chain));
	gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);

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

	self->outcaps = NULL;
	self->buffer = NULL;
	self->channels = -1;
	self->rate = -1;
	self->first_parsing = TRUE;
}

gboolean gst_sbc_parse_plugin_init(GstPlugin *plugin)
{
	return gst_element_register(plugin, "sbcparse", GST_RANK_NONE,
							GST_TYPE_SBC_PARSE);
}

