/* 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/gstbuffer.h>
#include <gstreamermm/miniobject.h>
#include <gstreamermm/wrap.h>
#include <gstreamermm/caps.h>

_DEFS(gstreamermm,gst)

namespace Gst
{

_WRAP_ENUM(BufferFlag, GstBufferFlag)
_WRAP_ENUM(BufferCopyFlags, GstBufferCopyFlags)

/** Gst::Buffer - 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
{
protected:
  _CLASS_GSTMINIOBJECT(Buffer, GstBuffer, GST_BUFFER, Gst::MiniObject, GstMiniObject)

public:
  _WRAP_METHOD(static Glib::RefPtr<Gst::Buffer> create(), gst_buffer_new)
  _WRAP_METHOD(static Glib::RefPtr<Gst::Buffer> create(guint size), gst_buffer_try_new_and_alloc)

  /** 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_metadata(const Glib::RefPtr<Gst::Buffer>& source_buffer, BufferCopyFlags flags), gst_buffer_copy_metadata)
  _WRAP_METHOD(bool is_metadata_writable() const, gst_buffer_is_metadata_writable)

  /** 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();

  //This is const because it always returns a new buffer:
  _WRAP_METHOD(Glib::RefPtr<Gst::Buffer> make_metadata_writable() const, gst_buffer_make_metadata_writable)

  _WRAP_METHOD(Glib::RefPtr<Gst::Caps> get_caps(), gst_buffer_get_caps)
  _WRAP_METHOD(Glib::RefPtr<const Gst::Caps> get_caps() const, gst_buffer_get_caps, constversion)
  _WRAP_METHOD(void set_caps(const Glib::RefPtr<Gst::Caps>& caps), gst_buffer_set_caps)
  _WRAP_METHOD(Glib::RefPtr<Gst::Buffer> create_sub(const guint& offset, const guint& size), gst_buffer_create_sub)
  _WRAP_METHOD(Glib::RefPtr<const Gst::Buffer> create_sub(const guint& offset, const guint& size) const, gst_buffer_create_sub, constversion)
  _WRAP_METHOD(bool is_span_fast(const Glib::RefPtr<const Gst::Buffer>& other_buffer) const, gst_buffer_is_span_fast)

  //This is const because it always returns a new buffer:
  _WRAP_METHOD(Glib::RefPtr<Gst::Buffer> span(const guint32& offset, const Glib::RefPtr<Gst::Buffer>& other_buffer, const guint32& len) const, gst_buffer_span)

  //We ignore gst_buffer_join() because it is just a C convenience function.
  //It is gst_buffer_merge() with unrefs.
  _IGNORE(gst_buffer_join)

  //This is const because it always returns a new buffer:
  _WRAP_METHOD(Glib::RefPtr<Gst::Buffer> merge(const Glib::RefPtr<const Gst::Buffer>& other_buffer) const, gst_buffer_merge)

  /** Get the data element of this buffer.
   * @returns A pointer to the data element of this buffer.
   */
  _MEMBER_GET(data, data, guint8*, guint8*)

  /** Get the size of this buffer.
   * @return The size in bytes of the data in this buffer.
   */
  _MEMBER_GET(size, size, guint, guint)

  /** Get the timestamp of this buffer.
   * @return The timestamp in nanoseconds (as a Gst::ClockTime) of the data in
   * the buffer. Value will be Gst::CLOCK_TIME_NONE if the timestamp is
   * unknown.
   */
  _MEMBER_GET(timestamp, timestamp, 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)

  /** 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)

  /** Get the malloc data of this buffer.
   * @return A pointer to any data allocated for this buffer using g_malloc().
   * If this is non-NULL, this memory will be freed at the end of the buffer's
   * lifecycle (i.e. when its refcount becomes zero).
   */
  _MEMBER_GET(malloc_data, malloc_data, guint8*, guint8*)

  //gst_buffer_stamp is depricated so ignore it.
  _IGNORE(gst_buffer_stamp)
};

}//namespace Gst
