/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2012  Collabora Ltd.
 *
 *
 *  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 <unistd.h>
#include <stdint.h>
#include <string.h>
#include <poll.h>

#include <gst/rtp/gstrtppayloads.h>
#include "gstavdtpsrc.h"

GST_DEBUG_CATEGORY_STATIC (avdtpsrc_debug);
#define GST_CAT_DEFAULT (avdtpsrc_debug)

enum
{
  PROP_0,
  PROP_TRANSPORT,
};

#define parent_class gst_avdtp_src_parent_class
G_DEFINE_TYPE (GstAvdtpSrc, gst_avdtp_src, GST_TYPE_BASE_SRC);

static GstStaticPadTemplate gst_avdtp_src_template =
    GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("application/x-rtp, "
        "media = (string) \"audio\","
        "payload = (int) "
        GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
        "clock-rate = (int) { 16000, 32000, "
        "44100, 48000 }, " "encoding-name = (string) \"SBC\"; "
        "application/x-rtp, "
        "media = (string) \"audio\","
        "payload = (int) "
        GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
        "clock-rate = (int) { 8000, 11025, 12000, 16000, "
        "22050, 2400, 32000, 44100, 48000, 64000, 88200, 96000 }, "
        "encoding-name = (string) \"MP4A-LATM\"; "));

static void gst_avdtp_src_finalize (GObject * object);
static void gst_avdtp_src_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static void gst_avdtp_src_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);

static GstCaps *gst_avdtp_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
static gboolean gst_avdtp_src_query (GstBaseSrc * bsrc, GstQuery * query);
static gboolean gst_avdtp_src_start (GstBaseSrc * bsrc);
static gboolean gst_avdtp_src_stop (GstBaseSrc * bsrc);
static GstFlowReturn gst_avdtp_src_create (GstBaseSrc * bsrc, guint64 offset,
    guint length, GstBuffer ** outbuf);
static gboolean gst_avdtp_src_unlock (GstBaseSrc * bsrc);
static gboolean gst_avdtp_src_unlock_stop (GstBaseSrc * bsrc);

static void
gst_avdtp_src_class_init (GstAvdtpSrcClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (klass);

  parent_class = g_type_class_peek_parent (klass);

  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_avdtp_src_finalize);
  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_avdtp_src_set_property);
  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_avdtp_src_get_property);

  basesrc_class->start = GST_DEBUG_FUNCPTR (gst_avdtp_src_start);
  basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_avdtp_src_stop);
  basesrc_class->create = GST_DEBUG_FUNCPTR (gst_avdtp_src_create);
  basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_avdtp_src_unlock);
  basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_avdtp_src_unlock_stop);
  basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_avdtp_src_getcaps);
  basesrc_class->query = GST_DEBUG_FUNCPTR (gst_avdtp_src_query);

  g_object_class_install_property (gobject_class, PROP_TRANSPORT,
      g_param_spec_string ("transport",
          "Transport", "Use configured transport", NULL, G_PARAM_READWRITE));

  gst_element_class_set_static_metadata (element_class,
      "Bluetooth AVDTP Source",
      "Source/Audio/Network/RTP",
      "Receives audio from an A2DP device",
      "Arun Raghavan <arun.raghavan@collabora.co.uk>");

  GST_DEBUG_CATEGORY_INIT (avdtpsrc_debug, "avdtpsrc", 0,
      "Bluetooth AVDTP Source");

  gst_element_class_add_static_pad_template (element_class,
      &gst_avdtp_src_template);
}

static void
gst_avdtp_src_init (GstAvdtpSrc * avdtpsrc)
{
  avdtpsrc->poll = gst_poll_new (TRUE);

  avdtpsrc->duration = GST_CLOCK_TIME_NONE;

  gst_base_src_set_format (GST_BASE_SRC (avdtpsrc), GST_FORMAT_TIME);
  gst_base_src_set_live (GST_BASE_SRC (avdtpsrc), TRUE);
  gst_base_src_set_do_timestamp (GST_BASE_SRC (avdtpsrc), TRUE);
}

static void
gst_avdtp_src_finalize (GObject * object)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (object);

  gst_poll_free (avdtpsrc->poll);

  gst_avdtp_connection_reset (&avdtpsrc->conn);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
gst_avdtp_src_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (object);

  switch (prop_id) {
    case PROP_TRANSPORT:
      g_value_set_string (value, avdtpsrc->conn.transport);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_avdtp_src_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (object);

  switch (prop_id) {
    case PROP_TRANSPORT:
      gst_avdtp_connection_set_transport (&avdtpsrc->conn,
          g_value_get_string (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static gboolean
gst_avdtp_src_query (GstBaseSrc * bsrc, GstQuery * query)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
  gboolean ret = FALSE;

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_DURATION:{
      GstFormat format;

      if (avdtpsrc->duration != GST_CLOCK_TIME_NONE) {
        gst_query_parse_duration (query, &format, NULL);

        if (format == GST_FORMAT_TIME) {
          gst_query_set_duration (query, format, (gint64) avdtpsrc->duration);
          ret = TRUE;
        }
      }

      break;
    }

    default:
      ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
  }

  return ret;
}

static GstCaps *
gst_avdtp_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
  GstCaps *caps = NULL, *ret = NULL;

  if (avdtpsrc->dev_caps) {
    const GValue *value;
    const char *format;
    int rate;
    GstStructure *structure = gst_caps_get_structure (avdtpsrc->dev_caps, 0);

    format = gst_structure_get_name (structure);

    if (g_str_equal (format, "audio/x-sbc")) {
      /* FIXME: we can return a fixed payload type once we
       * are in PLAYING */
      caps = gst_caps_new_simple ("application/x-rtp",
          "media", G_TYPE_STRING, "audio",
          "payload", GST_TYPE_INT_RANGE, 96, 127,
          "encoding-name", G_TYPE_STRING, "SBC", NULL);
    } else if (g_str_equal (format, "audio/mpeg")) {
      caps = gst_caps_new_simple ("application/x-rtp",
          "media", G_TYPE_STRING, "audio",
          "payload", GST_TYPE_INT_RANGE, 96, 127,
          "encoding-name", G_TYPE_STRING, "MP4A-LATM", NULL);

      value = gst_structure_get_value (structure, "mpegversion");
      if (!value || !G_VALUE_HOLDS_INT (value)) {
        GST_ERROR_OBJECT (avdtpsrc, "Failed to get mpegversion");
        return NULL;
      }
      gst_caps_set_simple (caps, "mpegversion", G_TYPE_INT,
          g_value_get_int (value), NULL);

      value = gst_structure_get_value (structure, "channels");
      if (!value || !G_VALUE_HOLDS_INT (value)) {
        GST_ERROR_OBJECT (avdtpsrc, "Failed to get channels");
        return NULL;
      }
      gst_caps_set_simple (caps, "channels", G_TYPE_INT,
          g_value_get_int (value), NULL);

      value = gst_structure_get_value (structure, "base-profile");
      if (!value || !G_VALUE_HOLDS_STRING (value)) {
        GST_ERROR_OBJECT (avdtpsrc, "Failed to get base-profile");
        return NULL;
      }
      gst_caps_set_simple (caps, "base-profile", G_TYPE_STRING,
          g_value_get_string (value), NULL);

    } else {
      GST_ERROR_OBJECT (avdtpsrc,
          "Only SBC and MPEG-2/4 are supported at the moment");
    }

    value = gst_structure_get_value (structure, "rate");
    if (!value || !G_VALUE_HOLDS_INT (value)) {
      GST_ERROR_OBJECT (avdtpsrc, "Failed to get sample rate");
      return NULL;
    }
    rate = g_value_get_int (value);

    gst_caps_set_simple (caps, "clock-rate", G_TYPE_INT, rate, NULL);

    if (filter) {
      ret = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
      gst_caps_unref (caps);
    } else
      ret = caps;
  } else {
    GST_DEBUG_OBJECT (avdtpsrc, "device not open, using template caps");
    ret = GST_BASE_SRC_CLASS (parent_class)->get_caps (bsrc, filter);
  }

  return ret;
}

static void
avrcp_metadata_cb (GstAvrcpConnection * avrcp, GstTagList * taglist,
    gpointer user_data)
{
  GstAvdtpSrc *src = GST_AVDTP_SRC (user_data);
  guint64 duration;

  if (gst_tag_list_get_uint64 (taglist, GST_TAG_DURATION, &duration)) {
    src->duration = duration;
    gst_element_post_message (GST_ELEMENT (src),
        gst_message_new_duration_changed (GST_OBJECT (src)));
  }

  gst_pad_push_event (GST_BASE_SRC_PAD (src),
      gst_event_new_tag (gst_tag_list_copy (taglist)));
  gst_element_post_message (GST_ELEMENT (src),
      gst_message_new_tag (GST_OBJECT (src), taglist));
}

static void
gst_avdtp_src_start_avrcp (GstAvdtpSrc * src)
{
  gchar *path, **strv;
  int i;

  /* Strip out the /fdX in /org/bluez/dev_.../fdX */
  strv = g_strsplit (src->conn.transport, "/", -1);

  for (i = 0; strv[i]; i++);
  g_return_if_fail (i > 0);

  g_free (strv[i - 1]);
  strv[i - 1] = NULL;

  path = g_strjoinv ("/", strv);
  g_strfreev (strv);

  src->avrcp = gst_avrcp_connection_new (path, avrcp_metadata_cb, src, NULL);

  g_free (path);
}

static void
gst_avdtp_src_stop_avrcp (GstAvdtpSrc * src)
{
  gst_avrcp_connection_free (src->avrcp);
}

static gboolean
gst_avdtp_src_start (GstBaseSrc * bsrc)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);

  /* None of this can go into prepare() since we need to set up the
   * connection to figure out what format the device is going to send us.
   */

  if (!gst_avdtp_connection_acquire (&avdtpsrc->conn, FALSE)) {
    GST_ERROR_OBJECT (avdtpsrc, "Failed to acquire connection");
    return FALSE;
  }

  if (!gst_avdtp_connection_get_properties (&avdtpsrc->conn)) {
    GST_ERROR_OBJECT (avdtpsrc, "Failed to get transport properties");
    goto fail;
  }

  if (!gst_avdtp_connection_conf_recv_stream_fd (&avdtpsrc->conn)) {
    GST_ERROR_OBJECT (avdtpsrc, "Failed to configure stream fd");
    goto fail;
  }

  GST_DEBUG_OBJECT (avdtpsrc, "Setting block size to link MTU (%d)",
      avdtpsrc->conn.data.link_mtu);
  gst_base_src_set_blocksize (GST_BASE_SRC (avdtpsrc),
      avdtpsrc->conn.data.link_mtu);

  avdtpsrc->dev_caps = gst_avdtp_connection_get_caps (&avdtpsrc->conn);
  if (!avdtpsrc->dev_caps) {
    GST_ERROR_OBJECT (avdtpsrc, "Failed to get device caps");
    goto fail;
  }

  gst_poll_fd_init (&avdtpsrc->pfd);
  avdtpsrc->pfd.fd = g_io_channel_unix_get_fd (avdtpsrc->conn.stream);

  gst_poll_add_fd (avdtpsrc->poll, &avdtpsrc->pfd);
  gst_poll_fd_ctl_read (avdtpsrc->poll, &avdtpsrc->pfd, TRUE);
  gst_poll_set_flushing (avdtpsrc->poll, FALSE);

  g_atomic_int_set (&avdtpsrc->unlocked, FALSE);

  gst_avdtp_src_start_avrcp (avdtpsrc);

  return TRUE;

fail:
  gst_avdtp_connection_release (&avdtpsrc->conn);
  return FALSE;
}

static gboolean
gst_avdtp_src_stop (GstBaseSrc * bsrc)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);

  gst_poll_remove_fd (avdtpsrc->poll, &avdtpsrc->pfd);
  gst_poll_set_flushing (avdtpsrc->poll, TRUE);

  gst_avdtp_src_stop_avrcp (avdtpsrc);
  gst_avdtp_connection_release (&avdtpsrc->conn);

  if (avdtpsrc->dev_caps) {
    gst_caps_unref (avdtpsrc->dev_caps);
    avdtpsrc->dev_caps = NULL;
  }

  return TRUE;
}

static GstFlowReturn
gst_avdtp_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
    GstBuffer ** outbuf)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
  GstBuffer *buf = NULL;
  GstMapInfo info;
  int ret;

  if (g_atomic_int_get (&avdtpsrc->unlocked))
    return GST_FLOW_FLUSHING;

  /* We don't operate in GST_FORMAT_BYTES, so offset is ignored */

  while ((ret = gst_poll_wait (avdtpsrc->poll, GST_CLOCK_TIME_NONE))) {
    if (g_atomic_int_get (&avdtpsrc->unlocked))
      /* We're unlocked, time to gtfo */
      return GST_FLOW_FLUSHING;

    if (ret < 0)
      /* Something went wrong */
      goto read_error;

    if (ret > 0)
      /* Got some data */
      break;
  }

  ret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc, offset, length, outbuf);
  if (G_UNLIKELY (ret != GST_FLOW_OK))
    goto alloc_failed;

  buf = *outbuf;

  gst_buffer_map (buf, &info, GST_MAP_WRITE);

  ret = read (avdtpsrc->pfd.fd, info.data, length);

  if (ret < 0)
    goto read_error;
  else if (ret == 0) {
    GST_INFO_OBJECT (avdtpsrc, "Got EOF on the transport fd");
    goto eof;
  }

  if (ret < length)
    gst_buffer_set_size (buf, ret);

  GST_LOG_OBJECT (avdtpsrc, "Read %d bytes", ret);

  gst_buffer_unmap (buf, &info);
  *outbuf = buf;

  return GST_FLOW_OK;

alloc_failed:
  {
    GST_DEBUG_OBJECT (bsrc, "alloc failed: %s", gst_flow_get_name (ret));
    return ret;
  }

read_error:
  GST_ERROR_OBJECT (avdtpsrc, "Error while reading audio data: %s",
      strerror (errno));
  gst_buffer_unref (buf);
  return GST_FLOW_ERROR;

eof:
  gst_buffer_unref (buf);
  return GST_FLOW_EOS;
}

static gboolean
gst_avdtp_src_unlock (GstBaseSrc * bsrc)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);

  g_atomic_int_set (&avdtpsrc->unlocked, TRUE);

  gst_poll_set_flushing (avdtpsrc->poll, TRUE);

  return TRUE;
}

static gboolean
gst_avdtp_src_unlock_stop (GstBaseSrc * bsrc)
{
  GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);

  g_atomic_int_set (&avdtpsrc->unlocked, FALSE);

  gst_poll_set_flushing (avdtpsrc->poll, FALSE);

  /* Flush out any stale data that might be buffered */
  gst_avdtp_connection_conf_recv_stream_fd (&avdtpsrc->conn);

  return TRUE;
}

gboolean
gst_avdtp_src_plugin_init (GstPlugin * plugin)
{
  return gst_element_register (plugin, "avdtpsrc", GST_RANK_NONE,
      GST_TYPE_AVDTP_SRC);
}
