/* gstreamermm - a C++ wrapper for gstreamer
 *
 * Copyright 2008 The gstreamermm Development Team
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <gst/gst.h>
#include <gstreamermm/miniobject.h>
#include <gstreamermm/clock.h>
#include <gstreamermm/memory.h>
#include <gstreamermm/mapinfo.h>

_DEFS(gstreamermm,gst)

namespace Gst
{

_WRAP_ENUM(BufferFlags, GstBufferFlags)
_WRAP_ENUM(BufferCopyFlags, GstBufferCopyFlags)

/** A data-passing buffer type, supporting sub-buffers.
 * Buffers are the basic unit of data transfer in GStreamer. The Gst::Buffer
 * type provides all the state necessary to define a region of memory as part
 * of a stream. Sub-buffers are also supported, allowing a smaller region of a
 * buffer to become its own buffer, with mechanisms in place to ensure that
 * neither memory space goes away prematurely.
 *
 * Buffers are usually created with create(). After a buffer has been created
 * one will typically allocate memory for it and set the size of the buffer
 * data. The following example creates a buffer that can hold a given video
 * frame with a given width, height and bits per plane.
 */
class Buffer : public MiniObject
{
  _CLASS_OPAQUE_REFCOUNTED(Buffer, GstBuffer, gst_buffer_new, gst_buffer_ref, gst_buffer_unref)
  _IGNORE(gst_buffer_ref, gst_buffer_unref)

public:
  /** Create a copy of the given buffer. This will also make a newly allocated
   * copy of the data the source buffer contains.
   * @return The Gst::Buffer copy.
   */
  Glib::RefPtr<Gst::Buffer> copy() const;

  _WRAP_METHOD(void copy_into(Glib::RefPtr<Gst::Buffer> source_buffer, BufferCopyFlags flags, gsize offset, gsize size), gst_buffer_copy_into)

  static Glib::RefPtr<Gst::Buffer> create(guint size);

  /** Makes a writable buffer from the given buffer. If the source buffer is
   * already writable, this will simply return the same buffer. A copy will
   * otherwise be made.
   * @return A buffer (possibly the same pointer) that is writable.
   */
  Glib::RefPtr<Gst::Buffer> create_writable();

  _WRAP_METHOD(Glib::RefPtr<Gst::Memory> get_memory(guint idx) const, gst_buffer_get_memory)

  _WRAP_METHOD(gsize get_size   () const, gst_buffer_get_size)

  _WRAP_METHOD(Glib::RefPtr<Gst::Memory> get_all_memory() const, gst_buffer_get_all_memory)

  _WRAP_METHOD(gsize fill(gsize offset, gconstpointer src, gsize size), gst_buffer_fill)

  _WRAP_METHOD(Glib::RefPtr<Gst::Buffer> append(const Glib::RefPtr<Gst::Buffer>& buf) const, gst_buffer_append)

  _WRAP_METHOD(Glib::RefPtr<Gst::Buffer> append_region(const Glib::RefPtr<Gst::Buffer>& buf, gssize offset, gssize size) const, gst_buffer_append_region)

  _WRAP_METHOD(void replace_memory_range(guint idx, gint length, Glib::RefPtr<Gst::Memory> mem), gst_buffer_replace_memory_range)

  _WRAP_METHOD(void remove_memory(guint idx), gst_buffer_remove_memory)

  _WRAP_METHOD(void remove_all_memory(), gst_buffer_remove_all_memory)

  _WRAP_METHOD(gsize memset(gsize offset, guint8 val, gsize size), gst_buffer_memset)

  _WRAP_METHOD(void replace_memory(guint idx, Glib::RefPtr<Gst::Memory> mem), gst_buffer_replace_memory)

  _WRAP_METHOD(gsize extract(gsize offset, gpointer dest, gsize size), gst_buffer_extract)

  _WRAP_METHOD(int memcmp(gsize offset, gconstpointer mem, gsize size), gst_buffer_memcmp)

  _MEMBER_GET(pts, pts, ClockTime, GstClockTime)
  _MEMBER_SET(pts, pts, ClockTime, GstClockTime)

  _MEMBER_GET(dts, dts, ClockTime, GstClockTime)
  _MEMBER_SET(dts, dts, ClockTime, GstClockTime)

  /** Get duration of this buffer.
   * @return he duration in nanoseconds (as a Gst::ClockTime) of the data in
   * the buffer. Value will be Gst::CLOCK_TIME_NONE if the duration is unknown.
   */
  _MEMBER_GET(duration, duration, ClockTime, GstClockTime)
  _MEMBER_SET(duration, duration, ClockTime, GstClockTime)

  _WRAP_METHOD(bool map(const Glib::RefPtr<Gst::MapInfo>& info, MapFlags flags), gst_buffer_map)

  _WRAP_METHOD(void unmap(const Glib::RefPtr<Gst::MapInfo>& info), gst_buffer_unmap)
  /** Get the offset of this buffer.
   * @return The offset in the source file of the beginning of this buffer.
   */
  _MEMBER_GET(offset, offset, guint64, guint64)

  /** Get the offset end of this buffer.
   * @return The offset in the source file of the end of this buffer.
   */
  _MEMBER_GET(offset_end, offset_end, guint64, guint64)
};

}//namespace Gst
