/* 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/interfaces/mixer.h>
#include <gst/interfaces/mixeroptions.h>
#include <gstreamermm/mixertrack.h>
#include <gstreamermm/message.h>
#include <glibmm/interface.h>

_DEFS(gstreamermm,gst)

namespace Gst
{

_WRAP_ENUM(MixerType, GstMixerType)
_WRAP_ENUM(MixerFlags, GstMixerFlags)
_WRAP_ENUM(MixerMessageType, GstMixerMessageType)

class MixerOptions;
class MixerTrack;

/** An interface for elements that provide mixer operations.
 * @ingroup GstInterfaces
 */
class Mixer : public Glib::Interface
{
  _CLASS_INTERFACE(Mixer, GstMixer, GST_MIXER, GstMixerClass)

public:
#m4 _CONVERSION(`const GList*', `std::vector< Glib::RefPtr<Gst::MixerTrack> >', `Glib::ListHandler< Glib::RefPtr<Gst::MixerTrack> >::list_to_vector(const_cast<GList*>($3), Glib::OWNERSHIP_NONE)')
  /** Returns a list of available tracks for this mixer/element. Note that it
   * is allowed for sink (output) elements to only provide the output tracks
   * in this list. Likewise, for sources (inputs), it is allowed to only
   * provide input elements in this list.
   *
   * @return A std::vector<> consisting of zero or more Gst::MixerTrack. 
   */
  _WRAP_METHOD(std::vector< Glib::RefPtr<Gst::MixerTrack> > list_tracks(), gst_mixer_list_tracks)

#m4 _CONVERSION(`const GList*', `std::vector< Glib::RefPtr<const Gst::MixerTrack> >', `Glib::ListHandler< Glib::RefPtr<const Gst::MixerTrack> >::list_to_vector(const_cast<GList*>($3), Glib::OWNERSHIP_NONE)')
  /** Returns a list of available tracks for this mixer/element. Note that it
   * is allowed for sink (output) elements to only provide the output tracks
   * in this list. Likewise, for sources (inputs), it is allowed to only
   * provide input elements in this list.
   *
   * @return A std::vector<> consisting of zero or more Gst::MixerTrack. 
   */
  _WRAP_METHOD(std::vector< Glib::RefPtr<const Gst::MixerTrack> > list_tracks() const, gst_mixer_list_tracks)

  /** Get the current volume(s) on the given track.
   *
   * @param track the Gst::MixerTrack to get the volume from.
   * @return an array of integers (of size track->num_channels) to with the
   * current volume of each channel in the given track. 
   */
  std::vector<int> get_volume(const Glib::RefPtr<const Gst::MixerTrack>& track) const;
  _IGNORE(gst_mixer_get_volume)

#m4 _CONVERSION(`const std::vector<int>&', `gint*', `Glib::ArrayHandler<int>::vector_to_array($3).data()')
  _WRAP_METHOD(void set_volume(const Glib::RefPtr<Gst::MixerTrack>& track, const std::vector<int>& volumes), gst_mixer_set_volume)

  _WRAP_METHOD(void set_mute(const Glib::RefPtr<Gst::MixerTrack>& track, bool mute), gst_mixer_set_mute)
  _WRAP_METHOD(void set_record(const Glib::RefPtr<Gst::MixerTrack>& track, bool record), gst_mixer_set_record)
  _WRAP_METHOD(void set_option(const Glib::RefPtr<Gst::MixerOptions>& opts, const Glib::ustring& value), gst_mixer_set_option)
  _WRAP_METHOD(void mute_toggled(const Glib::RefPtr<Gst::MixerTrack>& track, bool mute), gst_mixer_mute_toggled)
  _WRAP_METHOD(void record_toggled(const Glib::RefPtr<Gst::MixerTrack>& track, bool record), gst_mixer_record_toggled)
  _WRAP_METHOD(void volume_changed(const Glib::RefPtr<Gst::MixerTrack>& track, const std::vector<int>& volumes), gst_mixer_volume_changed)
  _WRAP_METHOD(void option_changed(const Glib::RefPtr<Gst::MixerOptions>& opts, const Glib::ustring& value), gst_mixer_option_changed)
  _WRAP_METHOD(void options_list_changed(const Glib::RefPtr<Gst::MixerOptions>& opts), gst_mixer_options_list_changed)
  _WRAP_METHOD(Glib::ustring get_option(const Glib::RefPtr<const Gst::MixerOptions>& opts) const, gst_mixer_get_option)
  _WRAP_METHOD(void mixer_changed(), gst_mixer_mixer_changed)
  _WRAP_METHOD(Gst::MixerFlags get_mixer_flags() const, gst_mixer_get_mixer_flags)
  _WRAP_METHOD(Gst::MixerType get_mixer_type() const, gst_mixer_get_mixer_type)
  _WRAP_METHOD(static Gst::MixerMessageType get_message_type(const Glib::RefPtr<Gst::Message>& message), gst_mixer_message_get_type)

  // Signals were deprecated before we could wrap them (see header file).  It
  // looks like messages to the bus have replaced the signals (see the
  // Gst::MessageMixer* classes):
  _IGNORE_SIGNAL(mute_toggled, record_toggled, volume_changed, option_changed)

  virtual std::vector<int> get_volume_vfunc(const Glib::RefPtr<const Gst::MixerTrack>& track) const;

  virtual std::vector< Glib::RefPtr<Gst::MixerTrack> > list_tracks_vfunc();

#m4 _CONVERSION(`GstMixerTrack*',`const Glib::RefPtr<Gst::MixerTrack>&', `Glib::wrap(($3), true)')

#m4 _CONVERSION(`gint*', `const std::vector<int>&', `Glib::ArrayHandler<int>::array_to_vector(($3), Glib::OWNERSHIP_NONE)')
  _WRAP_VFUNC(void set_volume(const Glib::RefPtr<Gst::MixerTrack>& track, const std::vector<int>& volumes), "set_volume")

  _WRAP_VFUNC(void set_mute(const Glib::RefPtr<Gst::MixerTrack>& track, bool mute), "set_mute")
  _WRAP_VFUNC(void set_record(const Glib::RefPtr<Gst::MixerTrack>& track, bool record), "set_record")

#m4 _CONVERSION(`GstMixerOptions*',`const Glib::RefPtr<Gst::MixerOptions>&', `Glib::wrap(($3), true)')
  _WRAP_VFUNC(void set_option(const Glib::RefPtr<Gst::MixerOptions>& opts, const Glib::ustring& value), "set_option")

#m4 _CONVERSION(`Glib::ustring', `const gchar*', `($3).c_str()')
#m4 _CONVERSION(`GstMixerOptions*',`const Glib::RefPtr<const Gst::MixerOptions>&', `Glib::wrap(($3), true)')
  _WRAP_VFUNC(Glib::ustring get_option(const Glib::RefPtr<const Gst::MixerOptions>& opts) const, "get_option")

  _WRAP_VFUNC(Gst::MixerFlags get_mixer_flags() const, "get_mixer_flags")

protected:
#m4begin
  _PUSH(SECTION_PCC_CLASS_INIT_VFUNCS)
  klass->get_volume = &get_volume_vfunc_callback;
  klass->list_tracks = &list_tracks_vfunc_callback;
  _SECTION(SECTION_PH_VFUNCS)
  static void get_volume_vfunc_callback(GstMixer* self, GstMixerTrack* track, gint* volumes);
  static const GList* list_tracks_vfunc_callback(GstMixer* self);
  _POP()
#m4end
};

/** A mute-toggled Gst::Mixer message.
 */
class MessageMixerMuteToggled : public Message
{
public:
  explicit MessageMixerMuteToggled(GstMessage* castitem);

  /** Extracts the contents of a mute-toggled bus message. Reads the
   * Gst::MixerTrack that has changed, and the new value of the mute flag.
   * 
   * The Gst::MixerTrack remains valid until the message is freed.
   *
   * @param track Reference to hold a Gst::MixerTrack object.
   * @param mute A reference to hold the bool new value.
   *
   * Since 0.10.14.
   */
  void parse(Glib::RefPtr<Gst::MixerTrack>& track, bool& mute) const;
  _IGNORE(gst_mixer_message_parse_mute_toggled)

  /** Extracts the contents of a mute-toggled bus message. Reads the
   * Gst::MixerTrack that has changed, and the new value of the mute flag.
   * 
   * The Gst::MixerTrack remains valid until the message is freed.
   *
   * @return the Gst::MixerTrack object.
   */
  Glib::RefPtr<Gst::MixerTrack> parse();

  /** Extracts the contents of a mute-toggled bus message. Reads the
   * Gst::MixerTrack that has changed, and the new value of the mute flag.
   * 
   * The Gst::MixerTrack remains valid until the message is freed.
   *
   * @return the Gst::MixerTrack object.
   */
  Glib::RefPtr<const Gst::MixerTrack> parse() const;

  /** Extracts the contents of a mute-toggled bus message. Reads the new value
   * of the mute flag.
   * 
   * @return The bool new value.
   */

  bool parse_mute() const;
};

/** A record-toggled Gst::Mixer message.
 */
class MessageMixerRecordToggled : public Message
{
public:
  explicit MessageMixerRecordToggled(GstMessage* castitem);

  /** Extracts the contents of a record-toggled bus message. Reads the
   * Gst::MixerTrack that has changed, and the new value of the recording flag.
   *
   * The Gst::MixerTrack remains valid until the message is freed.
   *
   * @param track A reference to hold the Gst::MixerTrack object.
   * @param record A reference to hold the bool value.
   *
   * Since 0.10.14.
   */
  void parse(Glib::RefPtr<Gst::MixerTrack>& track, bool& record) const;
  _IGNORE(gst_mixer_message_parse_record_toggled)

  /** Extracts the contents of a record-toggled bus message. Reads the
   * Gst::MixerTrack that has changed.
   *
   * The Gst::MixerTrack remains valid until the message is freed.
   *
   * @return A reference to the Gst::MixerTrack object.
   */
  Glib::RefPtr<Gst::MixerTrack> parse();

  /** Extracts the contents of a record-toggled bus message. Reads the
   * Gst::MixerTrack that has changed.
   *
   * The Gst::MixerTrack remains valid until the message is freed.
   *
   * @return A reference to the Gst::MixerTrack object.
   */
  Glib::RefPtr<const Gst::MixerTrack> parse() const;

  /** Extracts the contents of a record-toggled bus message. Reads the new
   * value of the recording flag.
   *
   * @return The bool value.
   */
  bool parse_record() const;
};

/** A volume-changed Gst::Mixer message.
 */
class MessageMixerVolumeChanged : public Message
{
public:
  explicit MessageMixerVolumeChanged(GstMessage* castitem);

  /** Parses a volume-changed notification message and extracts the track
   * object it refers to, as well as an array of volumes and the size of the
   * volumes array.
   *
   * The track object remains valid until the message is freed.
   *
   * @param track A reference to hold a Gst::MixerTrack object.
   * @param volumes A reference to receive an array of int values.
   *
   * Since 0.10.14.
   */
  void parse(Glib::RefPtr<Gst::MixerTrack>& track, std::vector<int>& volumes) const;
  _IGNORE(gst_mixer_message_parse_volume_changed)

  /** Parses a volume-changed notification message and extracts the track
   * object it refers to.
   *
   * The track object remains valid until the message is freed.
   *
   * @return a Gst::MixerTrack object.
   */
  Glib::RefPtr<Gst::MixerTrack> parse();

  /** Parses a volume-changed notification message and extracts the track
   * object it refers to.
   *
   * The track object remains valid until the message is freed.
   *
   * @return a Gst::MixerTrack object.
   */
  Glib::RefPtr<const Gst::MixerTrack> parse() const;

  /** Parses a volume-changed notification message and extracts the array of
   * volumes.
   *
   * @return The array of volume int values.
   */
  std::vector<int> parse_volumes() const;
};

/** An option-changed Gst::Mixer message.
 */
class MessageMixerOptionChanged : public Message
{
public:
  explicit MessageMixerOptionChanged(GstMessage* castitem);

  /** Extracts the Gst::MixerOptions and new value from a option-changed bus
   * notification message.
   *
   * The Gst::MixerOptions remain valid until the message is freed.
   *
   * @param options A reference to hold the Gst::MixerOptions object.
   * @param value Location to store the new options value.
   *
   * Since 0.10.14.
   */
  void parse(Glib::RefPtr<Gst::MixerOptions>& options,
    Glib::ustring& value) const;
  _IGNORE(gst_mixer_message_parse_option_changed)

  /** Extracts the Gst::MixerOptions from a option-changed bus notification
   * message.
   *
   * The Gst::MixerOptions remain valid until the message is freed.
   *
   * @return The Gst::MixerOptions object.
   */
  Glib::RefPtr<Gst::MixerOptions> parse();

  /** Extracts the Gst::MixerOptions from a option-changed bus notification
   * message.
   *
   * The Gst::MixerOptions remain valid until the message is freed.
   *
   * @return The Gst::MixerOptions object.
   */
  Glib::RefPtr<const Gst::MixerOptions> parse() const;

  /** Extracts the new value of the option from a option-changed bus
   * notification message.
   *
   * @return The new options value.
   */
  Glib::ustring parse_value() const;
};

/** An option-list-changed Gst::Mixer message, osted when the list of available
 * options for a GstMixerOptions object has changed (Since: 0.10.18).
 */
class MessageMixerOptionsListChanged : public Message
{
public:
  explicit MessageMixerOptionsListChanged(GstMessage* castitem);

  /** Extracts the Gst::MixerOptions whose value list has changed from an
   * options-list-changed bus notification message.
   *
   * The options object returned remains valid until the message is freed.
   *
   * Since 0.10.18.
   */
  Glib::RefPtr<Gst::MixerOptions> parse();
  _IGNORE(gst_mixer_message_parse_options_list_changed)

  /** Extracts the Gst::MixerOptions whose value list has changed from an
   * options-list-changed bus notification message.
   *
   * The options object returned remains valid until the message is freed.
   *
   * Since 0.10.18.
   */
  Glib::RefPtr<const Gst::MixerOptions> parse() const;
};

/** A mixer-changed Gst::Mixer message, posted when the list of available mixer
 * tracks has changed. The application should re-build its interface in this
 * case (Since: 0.10.18).
 */
class MessageMixerChanged : public Message
{
public:
  explicit MessageMixerChanged(GstMessage* castitem);
};

} // namespace Gst
