// -*- c++ -*-
// Generated by gtkmmproc -- DO NOT MODIFY!
#ifndef _GSTREAMERMM_RINGBUFFER_H
#define _GSTREAMERMM_RINGBUFFER_H


#include <glibmm.h>

/* gstreamermm - a C++ wrapper for gstreamer
 *
 * Copyright 2008-2009 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/audio/gstringbuffer.h>
#include <gstreamermm/caps.h>
#include <gstreamermm/object.h>
#include <gstreamermm/format.h>


#ifndef DOXYGEN_SHOULD_SKIP_THIS
typedef struct _GstRingBuffer GstRingBuffer;
typedef struct _GstRingBufferClass GstRingBufferClass;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gst
{ class RingBuffer_Class; } // namespace Gst
namespace Gst
{

/** @addtogroup gstreamermmEnums Enums and Flags */

/**
 * @ingroup gstreamermmEnums
 */
enum RingBufferSegState
{
  SEGSTATE_INVALID,
  SEGSTATE_EMPTY,
  SEGSTATE_FILLED,
  SEGSTATE_PARTIAL
};

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

template <>
class Value<Gst::RingBufferSegState> : public Glib::Value_Enum<Gst::RingBufferSegState>
{
public:
  static GType value_type() G_GNUC_CONST;
};

} // namespace Glib
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gst
{

/**
 * @ingroup gstreamermmEnums
 */
enum RingBufferState
{
  RING_BUFFER_STATE_STOPPED,
  RING_BUFFER_STATE_PAUSED,
  RING_BUFFER_STATE_STARTED
};

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

template <>
class Value<Gst::RingBufferState> : public Glib::Value_Enum<Gst::RingBufferState>
{
public:
  static GType value_type() G_GNUC_CONST;
};

} // namespace Glib
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gst
{

/**
 * @ingroup gstreamermmEnums
 */
enum BufferFormat
{
  UNKNOWN,
  S8,
  U8,
  S16_LE,
  S16_BE,
  U16_LE,
  U16_BE,
  S24_LE,
  S24_BE,
  U24_LE,
  U24_BE,
  S32_LE,
  S32_BE,
  U32_LE,
  U32_BE,
  S24_3LE,
  S24_3BE,
  U24_3LE,
  U24_3BE,
  S20_3LE,
  S20_3BE,
  U20_3LE,
  U20_3BE,
  S18_3LE,
  S18_3BE,
  U18_3LE,
  U18_3BE,
  FLOAT32_LE,
  FLOAT32_BE,
  FLOAT64_LE,
  FLOAT64_BE,
  MU_LAW,
  A_LAW,
  IMA_ADPCM,
  MPEG,
  GSM,
  IEC958,
  AC3,
  EAC3,
  DTS
};

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

template <>
class Value<Gst::BufferFormat> : public Glib::Value_Enum<Gst::BufferFormat>
{
public:
  static GType value_type() G_GNUC_CONST;
};

} // namespace Glib
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gst
{

/**
 * @ingroup gstreamermmEnums
 */
enum BufferFormatType
{
  BUFTYPE_LINEAR,
  BUFTYPE_FLOAT,
  BUFTYPE_MU_LAW,
  BUFTYPE_A_LAW,
  BUFTYPE_IMA_ADPCM,
  BUFTYPE_MPEG,
  BUFTYPE_GSM,
  BUFTYPE_IEC958,
  BUFTYPE_AC3,
  BUFTYPE_EAC3,
  BUFTYPE_DTS
};

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

template <>
class Value<Gst::BufferFormatType> : public Glib::Value_Enum<Gst::BufferFormatType>
{
public:
  static GType value_type() G_GNUC_CONST;
};

} // namespace Glib
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gst
{


/** The structure containing the format specification of a Gst::RingBuffer.
 *@see Gst::RingBuffer::acquire().
 */
class RingBufferSpec
{
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef RingBufferSpec CppObjectType;
  typedef GstRingBufferSpec BaseObjectType;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

private:

public:
  /// Construct a Gst::RingBufferSpec from a GstRingBufferSpec.
  RingBufferSpec(const GstRingBufferSpec* castitem);

  /** The caps that generated the Spec. */
  Glib::RefPtr<Gst::Caps> caps;

  /** The sample type.
   */
  Gst::BufferFormatType type;

  /** The sample format.
   */
  Gst::BufferFormat format;

  /** The sample sign.
   */
  bool          sign;

  /** The endianness of the samples.
   */
  bool          bigend;

  /** The width of the samples.
   */
  int           width;

  /** The depth of the samples.
   */
  int           depth;

  /** The samplerate.
   */
  int           rate;

  /** The number of channels.
   */
  int           channels;

  /** The latency in microseconds.
   */
  guint64       latency_time;

  /**  The total buffer size in microseconds.
   */
  guint64       buffer_time;

  /** The size of one segment in bytes.
   */
  int           segsize;

  /** The total number of segments.
   */
  int           segtotal;

  /** Number of bytes of one sample.
  */
  int           bytes_per_sample;

  /** Bytes representing one sample of silence.
  */
  guint8        silence_sample[32];

  /** Number of segments queued in the lower level device, defaults to
   * segtotal.
   */
  int           seglatency;

#ifndef DOXYGEN_SHOULD_SKIP_THIS
  void copy_fields_from(const GstRingBufferSpec& spec);
  void copy_fields_to(GstRingBufferSpec& spec) const;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


};

/** Gst::RingBuffer — Base class for audio ringbuffer implementations.
 * This object is the base class for audio ringbuffers used by the base audio
 * source and sink classes.
 *
 * The ringbuffer abstracts a circular buffer of data. One reader and one
 * writer can operate on the data from different threads in a lockfree manner.
 * The base class is sufficiently flexible to be used as an abstraction for DMA
 * based ringbuffers as well as a pure software implementations.
 *
 * Last reviewed on 2006-02-02 (0.10.4).
 * @ingroup GstBaseClasses
 */

class RingBuffer : public Gst::Object 
{
  
#ifndef DOXYGEN_SHOULD_SKIP_THIS

public:
  typedef RingBuffer CppObjectType;
  typedef RingBuffer_Class CppClassType;
  typedef GstRingBuffer BaseObjectType;
  typedef GstRingBufferClass BaseClassType;

private:  friend class RingBuffer_Class;
  static CppClassType ringbuffer_class_;

private:
  // noncopyable
  RingBuffer(const RingBuffer&);
  RingBuffer& operator=(const RingBuffer&);

protected:
  explicit RingBuffer(const Glib::ConstructParams& construct_params);
  explicit RingBuffer(GstRingBuffer* castitem);

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

public:
  virtual ~RingBuffer();

#ifndef DOXYGEN_SHOULD_SKIP_THIS
  static GType get_type()      G_GNUC_CONST;


  static GType get_base_type() G_GNUC_CONST;
#endif

  ///Provides access to the underlying C GObject.
  GstRingBuffer*       gobj()       { return reinterpret_cast<GstRingBuffer*>(gobject_); }

  ///Provides access to the underlying C GObject.
  const GstRingBuffer* gobj() const { return reinterpret_cast<GstRingBuffer*>(gobject_); }

  ///Provides access to the underlying C instance. The caller is responsible for unrefing it. Use when directly setting fields in structs.
  GstRingBuffer* gobj_copy();

private:

  
public:
  /** For example,
   * bool on_fill(const Glib::RefPtr<Gst::RingBuffer>& rbuf, guint8* data,
   * guint len);.
   * This slot is set with set_fill_slot() and is called to fill the memory at
   * data with len bytes of samples.
   */
  typedef sigc::slot<void, guint8*, guint> SlotFill;

  //TODO: _MEMBER_GET(cond, cond, Glib::Cond, GCond*)

  /** Sets the given fill slot on the buffer. The slot will be called every
   * time a segment has been written to a device.
   *
   * MT safe.
   *
   * @param slot The fill slot to set.
   */
  void set_fill_slot(const SlotFill& slot);
  

  /** Allocate the resources for the ringbuffer. This function fills in the
   * data pointer of the ring buffer with a valid Gst::Buffer to which samples
   * can be written.
   *
   * @param spec The specs of the buffer.
   *
   * @return true if the device could be acquired, false on error. MT safe. 
   */
  bool acquire(const Gst::RingBufferSpec& spec);
  

  /** Free the resources of the ringbuffer.
   * @return <tt>true</tt> if the device could be released, <tt>false</tt> on error.
   * 
   * MT safe.
   */
  bool release();
  
  /** Check if the ringbuffer is acquired and ready to use.
   * @return <tt>true</tt> if the ringbuffer is acquired, <tt>false</tt> on error.
   * 
   * MT safe.
   */
  bool is_acquired() const;
  
  /** Activate @a buf to start or stop pulling data.
   * 
   * MT safe.
   * @param active The new mode.
   * @return <tt>true</tt> if the device could be activated in the requested mode,
   * <tt>false</tt> on error.
   * 
   * Since: 0.10.22.
   */
  bool activate(bool active);
  
  /** Check if @a buf is activated.
   * 
   * MT safe.
   * @return <tt>true</tt> if the device is active.
   * 
   * Since: 0.10.22.
   */
  bool is_active() const;
  
  /** Start processing samples from the ringbuffer.
   * @return <tt>true</tt> if the device could be started, <tt>false</tt> on error.
   * 
   * MT safe.
   */
  bool start();
  
  /** Pause processing samples from the ringbuffer.
   * @return <tt>true</tt> if the device could be paused, <tt>false</tt> on error.
   * 
   * MT safe.
   */
  bool pause();
  
  /** Stop processing samples from the ringbuffer.
   * @return <tt>true</tt> if the device could be stopped, <tt>false</tt> on error.
   * 
   * MT safe.
   */
  bool stop();
  
  /** Get the number of samples queued in the audio device. This is
   * usually less than the segment size but can be bigger when the
   * implementation uses another internal buffer between the audio
   * device.
   * 
   * For playback ringbuffers this is the amount of samples transfered from the
   * ringbuffer to the device but still not played.
   * 
   * For capture ringbuffers this is the amount of samples in the device that are
   * not yet transfered to the ringbuffer.
   * @return The number of samples queued in the audio device.
   * 
   * MT safe.
   */
  guint get_delay() const;
  
  /** Get the number of samples that were processed by the ringbuffer
   * since it was last started. This does not include the number of samples not
   * yet processed (see delay()).
   * @return The number of samples processed by the ringbuffer.
   * 
   * MT safe.
   */
  guint64 get_samples_done() const;
  
  /** Make sure that the next sample written to the device is
   * accounted for as being the @a sample sample written to the
   * device. This value will be used in reporting the current
   * sample position of the ringbuffer.
   * 
   * This function will also clear the buffer with silence.
   * 
   * MT safe.
   * @param sample The sample number to set.
   */
  void set_sample(guint64 sample);
  
  /** Same as commit_full() but with a in_samples and out_samples
   * equal to @a len, ignoring accum.
   * @param sample The sample position of the data.
   * @param data The data to commit.
   * @param len The number of samples in the data to commit.
   * @return The number of samples written to the ringbuffer or -1 on
   * error.
   * 
   * MT safe.
   */
  guint commit(guint64 sample, guchar* data, guint len);
  
  /** Commit @a in_samples samples pointed to by @a data to the ringbuffer @a buf. 
   * 
   *  @a in_samples and @a out_samples define the rate conversion to perform on the the
   * samples in @a data. For negative rates, @a out_samples must be negative and
   *  @a in_samples positive.
   * 
   * When @a out_samples is positive, the first sample will be written at position @a sample
   * in the ringbuffer. When @a out_samples is negative, the last sample will be written to
   *  @a sample in reverse order.
   * 
   *  @a out_samples does not need to be a multiple of the segment size of the ringbuffer
   * although it is recommended for optimal performance. 
   * 
   *  @a accum will hold a temporary accumulator used in rate conversion and should be
   * set to 0 when this function is first called. In case the commit operation is
   * interrupted, one can resume the processing by passing the previously returned
   *  @a accum value back to this function.
   * 
   * MT safe.
   * @param sample The sample position of the data.
   * @param data The data to commit.
   * @param in_samples The number of samples in the data to commit.
   * @param out_samples The number of samples to write to the ringbuffer.
   * @param accum Accumulator for rate conversion.
   * @return The number of samples written to the ringbuffer or -1 on error. The
   * number of samples written can be less than @a out_samples when @a buf was interrupted
   * with a flush or stop.
   * 
   * Since: 0.10.11.
   */
  guint commit(guint64& sample, guchar* data, int in_samples, int out_samples, int& accum);
  
  /** Convert @a src_val in @a src_fmt to the equivalent value in @a dest_fmt. The result
   * will be put in @a dest_val.
   * @param src_fmt The source format.
   * @param src_val The source value.
   * @param dest_fmt The destination format.
   * @param dest_val A location to store the converted value.
   * @return <tt>true</tt> if the conversion succeeded.
   * 
   * Since: 0.10.22.
   */
  bool convert(Gst::Format src_fmt, gint64 src_val, Gst::Format dest_fmt, gint64& dest_val) const;
  
  /** Returns: <tt>false</tt> if the buffer is not started.
   * @param segment The segment to read.
   * @param readptr The pointer to the memory where samples can be read.
   * @param len The number of bytes to read.
   * @return <tt>false</tt> if the buffer is not started.
   * 
   * MT safe.
   */
  bool prepare_read(int& segment, guint8*& readptr, int& len);
  
  /** Read @a len samples from the ringbuffer into the memory pointed 
   * to by @a data.
   * The first sample should be read from position @a sample in
   * the ringbuffer.
   * 
   *  @a len should not be a multiple of the segment size of the ringbuffer
   * although it is recommended.
   * @param sample The sample position of the data.
   * @param data Where the data should be read.
   * @param len The number of samples in data to read.
   * @return The number of samples read from the ringbuffer or -1 on
   * error.
   * 
   * MT safe.
   */
  guint read(guint64 sample, guchar* data, guint len);
  
  /** Clear the given segment of the buffer with silence samples.
   * This function is used by subclasses.
   * 
   * MT safe.
   * @param segment The segment to clear.
   */
  void clear(int segment);
  
  /** Fill the ringbuffer with silence.
   * 
   * MT safe.
   */
  void clear_all();
  
  /** Subclasses should call this function to notify the fact that 
   *  @a advance segments are now processed by the device.
   * 
   * MT safe.
   * @param advance The number of segments written.
   */
  void advance(guint advance);
  
  /** Close the audio device associated with the ring buffer. The ring buffer
   * should already have been released via release().
   * @return <tt>true</tt> if the device could be closed, <tt>false</tt> on error.
   * 
   * MT safe.
   */
  bool close_device();
  
  /** Open the audio device associated with the ring buffer. Does not perform any
   * setup on the device. You must open the device before acquiring the ring
   * buffer.
   * @return <tt>true</tt> if the device could be opened, <tt>false</tt> on error.
   * 
   * MT safe.
   */
  bool open_device();
  
  /** Checks the status of the device associated with the ring buffer.
   * @return <tt>true</tt> if the device was open, <tt>false</tt> if it was closed.
   * 
   * MT safe.
   */
  bool device_is_open() const;
  
  /** Tell the ringbuffer that it is allowed to start playback when
   * the ringbuffer is filled with samples. 
   * 
   * MT safe.
   * 
   * Since: 0.10.6
   * @param allowed The new value.
   */
  void set_may_start(bool allowed);

  /** Parse caps into a Gst::RingBufferSpec.
   *
   * @param spec A Gst::RingBufferSpec.
   * @param caps the Gst::Caps to parse.
   * @return true if the caps could be parsed.
   */
  static bool parse_caps(Gst::RingBufferSpec& spec, const Glib::RefPtr<Gst::Caps>& caps);

  
  /** Set the ringbuffer to flushing mode or normal mode.
   * 
   * MT safe.
   * @param flushing The new mode.
   */
  void set_flushing(bool flushing);

  //TODO: Wrap vfuncs.

#ifndef DOXYGEN_SHOULD_SKIP_THIS
private:
  SlotFill* slot;
  bool _slot_set;
#endif


public:

public:
  //C++ methods used to invoke GTK+ virtual functions:
#ifdef GLIBMM_VFUNCS_ENABLED
#endif //GLIBMM_VFUNCS_ENABLED

protected:
  //GTK+ Virtual Functions (override these to change behaviour):
#ifdef GLIBMM_VFUNCS_ENABLED
#endif //GLIBMM_VFUNCS_ENABLED

  //Default Signal Handlers::
#ifdef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
#endif //GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED


};

} // namespace Gst


namespace Glib
{
  /** A Glib::wrap() method for this object.
   * 
   * @param object The C instance.
   * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
   * @result A C++ instance that wraps this C instance.
   *
   * @relates Gst::RingBuffer
   */
  Glib::RefPtr<Gst::RingBuffer> wrap(GstRingBuffer* object, bool take_copy = false);
}


#endif /* _GSTREAMERMM_RINGBUFFER_H */

