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


#include <glibmm/ustring.h>
#include <sigc++/sigc++.h>

/* 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/gstbus.h>
#include <gstreamermm/object.h>
#include <gstreamermm/clock.h>
#include <gstreamermm/message.h>
#include <glibmm/priorities.h>
//#include <glibmm/main.h> //For Glib::Source


#ifndef DOXYGEN_SHOULD_SKIP_THIS
typedef struct _GstBus GstBus;
typedef struct _GstBusClass GstBusClass;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gst
{ class Bus_Class; } // namespace Gst
namespace Gst
{

class Message;

/** @addtogroup gstreamermmEnums gstreamermm Enums and Flags */

/**
 * @ingroup gstreamermmEnums
 * @par Bitwise operators:
 * <tt>%BusFlags operator|(BusFlags, BusFlags)</tt><br>
 * <tt>%BusFlags operator&(BusFlags, BusFlags)</tt><br>
 * <tt>%BusFlags operator^(BusFlags, BusFlags)</tt><br>
 * <tt>%BusFlags operator~(BusFlags)</tt><br>
 * <tt>%BusFlags& operator|=(BusFlags&, BusFlags)</tt><br>
 * <tt>%BusFlags& operator&=(BusFlags&, BusFlags)</tt><br>
 * <tt>%BusFlags& operator^=(BusFlags&, BusFlags)</tt><br>
 */
enum BusFlags
{
  BUS_FLUSHING = (GST_OBJECT_FLAG_LAST << 0),
  BUS_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 1)
};

/** @ingroup gstreamermmEnums */
inline BusFlags operator|(BusFlags lhs, BusFlags rhs)
  { return static_cast<BusFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); }

/** @ingroup gstreamermmEnums */
inline BusFlags operator&(BusFlags lhs, BusFlags rhs)
  { return static_cast<BusFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs)); }

/** @ingroup gstreamermmEnums */
inline BusFlags operator^(BusFlags lhs, BusFlags rhs)
  { return static_cast<BusFlags>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs)); }

/** @ingroup gstreamermmEnums */
inline BusFlags operator~(BusFlags flags)
  { return static_cast<BusFlags>(~static_cast<unsigned>(flags)); }

/** @ingroup gstreamermmEnums */
inline BusFlags& operator|=(BusFlags& lhs, BusFlags rhs)
  { return (lhs = static_cast<BusFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs))); }

/** @ingroup gstreamermmEnums */
inline BusFlags& operator&=(BusFlags& lhs, BusFlags rhs)
  { return (lhs = static_cast<BusFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs))); }

/** @ingroup gstreamermmEnums */
inline BusFlags& operator^=(BusFlags& lhs, BusFlags rhs)
  { return (lhs = static_cast<BusFlags>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs))); }

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

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

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


namespace Gst
{


/** The result values for a Gst::Bus::SlotMessageSync.
 * - Gst::BUS_DROP - Drop the message.
 * - Gst::BUS_PASS - Pass the message to the async queue.
 * - Gst::BUS_ASYNC - Pass message to async queue, continue if message is
 * handled.
 * @ingroup gstreamermmEnums
 */
enum BusSyncReply
{
  BUS_DROP,
  BUS_PASS,
  BUS_ASYNC
};

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

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

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


namespace Gst
{


/** A class that encompasses the GStreamer asynchronous message bus subsystem.
 * The Gst::Bus is an object responsible for delivering Messages in a first-in
 * first-out way from the streaming threads to the application.
 *
 * Since the application typically only wants to deal with delivery of these
 * messages from one thread, the Gst::Bus will marshall the messages between
 * different threads. This is important since the actual streaming of media is
 * done in another thread than the application.
 *
 * The Gst::Bus provides support for GSource based notifications. This makes it
 * possible to handle the delivery in the glib mainloop.
 *
 * TODO: Correct C API reference in following paragraph:
 *
 * The GSource callback function gst_bus_async_signal_func() can be used to
 * convert all bus messages into signal emissions.
 *
 * A message is posted on the bus with the post() method. With the peek() and
 * pop() methods one can look at or retrieve a previously posted message.
 *
 * The bus can be polled with the poll() method. This methods blocks up to the
 * specified timeout value until one of the specified messages types is posted
 * on the bus. The application can then pop() the messages from the bus to
 * handle them. Alternatively the application can register an asynchronous bus
 * function using add_watch(). This function will install a GSource in the
 * default glib main loop and will deliver messages a short while after they
 * have been posted. Note that the main loop should be running for the
 * asynchronous callbacks.
 *
 * It is also possible to get messages from the bus without any thread
 * marshalling with the set_sync_handler() method. This makes it possible to
 * react to a message in the same thread that posted the message on the bus.
 * This should only be used if the application is able to deal with messages
 * from different threads.
 *
 * Every Gst::Pipeline has one bus.
 *
 * Note that a Gst::Pipeline will set its bus into flushing state when
 * changing from READY to NULL state.
 *
 * Last reviewed on 2006-03-12 (0.10.5)
 */

class Bus : public Object
{
  
#ifndef DOXYGEN_SHOULD_SKIP_THIS

public:
  typedef Bus CppObjectType;
  typedef Bus_Class CppClassType;
  typedef GstBus BaseObjectType;
  typedef GstBusClass BaseClassType;

private:  friend class Bus_Class;
  static CppClassType bus_class_;

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

protected:
  explicit Bus(const Glib::ConstructParams& construct_params);
  explicit Bus(GstBus* castitem);

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

public:
  virtual ~Bus();

  /** Get the GType for this class, for use with the underlying GObject type system.
   */
  static GType get_type()      G_GNUC_CONST;

#ifndef DOXYGEN_SHOULD_SKIP_THIS


  static GType get_base_type() G_GNUC_CONST;
#endif

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

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

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

private:


protected:
  Bus();

public:
  /** For example,
   * bool on_bus_message(const Glib::RefPtr<Gst::Bus>& bus, const
   * Glib::RefPtr<Gst::Message>& message);.
   * The message function should return true if it wants to continue to receive
   * messages, or false otherwise.
   */
  typedef sigc::slot< bool, const Glib::RefPtr<Gst::Bus>&, const Glib::RefPtr<Gst::Message>& > SlotMessage;

  /** For example,
   * BusSyncReply on_bus_sync_message(const Glib::RefPtr<Gst::Bus>& bus, const
   * Glib::RefPtr<Gst::Message>& message);.
   */
  typedef sigc::slot< BusSyncReply, const Glib::RefPtr<Gst::Bus>&, const Glib::RefPtr<Gst::Message>& > SlotMessageSync;

  /** Creates a new Gst::Bus instance.
   *
   * @return The new Gst::Bus instance.
   */
  
  static Glib::RefPtr<Bus> create();


  /** Post a message on the given bus. Ownership of the message
   * is taken by the bus.
   * @param message The Gst::Message to post.
   * @return <tt>true</tt> if the message could be posted, <tt>false</tt> if the bus is flushing.
   * 
   * MT safe.
   */
  bool post(const Glib::RefPtr<Gst::Message>& message);
  
  /** Check if there are pending messages on the bus that
   * should be handled.
   * @return <tt>true</tt> if there are messages on the bus to be handled, <tt>false</tt>
   * otherwise.
   * 
   * MT safe.
   */
  bool have_pending() const;
  
  /** Peek the message on the top of the bus' queue. The message will remain
   * on the bus' message queue. A reference is returned, and needs to be unreffed
   * by the caller.
   * @return The Gst::Message that is on the bus, or <tt>0</tt> if the
   * bus is empty.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Message> peek();
  
  /** Peek the message on the top of the bus' queue. The message will remain
   * on the bus' message queue. A reference is returned, and needs to be unreffed
   * by the caller.
   * @return The Gst::Message that is on the bus, or <tt>0</tt> if the
   * bus is empty.
   * 
   * MT safe.
   */
  Glib::RefPtr<const Gst::Message> peek() const;
  
  /** Get a message from the bus.
   * @return The Gst::Message that is on the bus, or <tt>0</tt> if the
   * bus is empty. The message is taken from the bus and needs to be unreffed
   * with gst_message_unref() after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Message> pop();
  
  /** Get a message matching @a type from the bus.  Will discard all messages on
   * the bus that do not match @a type and that have been posted before the first
   * message that does match @a type.  If there is no message matching @a type on
   * the bus, all messages will be discarded.
   * @param types Message types to take into account.
   * @return The next Gst::Message matching @a type that is on
   * the bus, or <tt>0</tt> if the bus is empty or there is no message matching
   *  @a type. The message is taken from the bus and needs to be unreffed with
   * gst_message_unref() after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Message> pop(MessageType message_type);
  
  /** Get a message from the bus, waiting up to the specified timeout.
   * 
   * If @a timeout is 0, this function behaves like pop(). If @a timeout is
   * Gst::CLOCK_TIME_NONE, this function will block forever until a message was
   * posted on the bus.
   * @param timeout A timeout.
   * @return The Gst::Message that is on the bus after the
   * specified timeout or <tt>0</tt> if the bus is empty after the timeout expired.
   * The message is taken from the bus and needs to be unreffed with
   * gst_message_unref() after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Message> pop(ClockTime timeout);
  
  /** Get a message from the bus whose type matches the message type mask @a types,
   * waiting up to the specified timeout (and discarding any messages that do not
   * match the mask provided).
   * 
   * If @a timeout is 0, this function behaves like pop_filtered(). If
   *  @a timeout is Gst::CLOCK_TIME_NONE, this function will block forever until a
   * matching message was posted on the bus.
   * @param timeout A timeout in nanoseconds, or GST_CLOCK_TIME_NONE to wait forever.
   * @param types Message types to take into account, GST_MESSAGE_ANY for any type.
   * @return A Gst::Message matching the filter in @a types,
   * or <tt>0</tt> if no matching message was found on the bus until the timeout
   * expired. The message is taken from the bus and needs to be unreffed
   * with gst_message_unref() after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Message> pop(ClockTime timeout, MessageType message_type);
  
  /** If @a flushing, flush out and unref any messages queued in the bus. Releases
   * references to the message origin objects. Will flush future messages until
   * set_flushing() sets @a flushing to #<tt>false</tt>.
   * 
   * MT safe.
   * @param flushing Whether or not to flush the bus.
   */
  void set_flushing(bool flushing =  true);

//TODO Glib::Source has a strange cobject constructor.
//#m4 __CONVERSION(`GSource*',`Glib::RefPtr<Glib::Source>', `Glib::wrap($3)')
//  _WRAP_METHOD(Glib::RefPtr<Glib::Source> create_watch(), gst_bus_create_watch)

  /** Adds a bus watch to the default main context with the given priority.
   * The slot is used to receive asynchronous messages in the main loop.
   *
   * The watch can be removed using remove_watch() or by returning false from
   * slot.
   *
   * @param slot The slot to call when a message is received.
   * @param priority The priority of the watch.
   * @return The event source id. MT safe.
   */
  guint add_watch(const SlotMessage& slot, int priority = Glib::PRIORITY_DEFAULT);
  

  /** Removes bus watch with event source id from main context.
   *
   * @param The event source id.
   * @return true if removal was succesful, false otherwise.
   */
  bool remove_watch(guint watch_id);

  /** Sets the synchronous handler on the bus. The slot will be called every
   * time a new message is posted on the bus. Note that the function will be
   * called in the same thread context as the posting object (synchronously).
   * This function is usually only called by the creator of the bus.
   * Applications should handle messages asynchronously using the watch and
   * poll functions or enable the "sync-message" signal emission with
   * enable_sync_message_emission().
   *
   * @param slot The handler slot to install.
   */
  void set_sync_handler(const SlotMessageSync& slot);
  
  
  /** Instructs GStreamer to stop emitting the "sync-message" signal for this bus.
   * See enable_sync_message_emission() for more information.
   * 
   * In the event that multiple pieces of code have called
   * enable_sync_message_emission(), the sync-message emissions will only
   * be stopped after all calls to enable_sync_message_emission() were
   * "cancelled" by calling this function. In this way the semantics are exactly
   * the same as Gst::Object::ref() that which calls enable should also call
   * disable.
   * 
   * MT safe.
   */
  void disable_sync_message_emission();
  
  /** Instructs GStreamer to emit the "sync-message" signal after running the bus's
   * sync handler. This function is here so that code can ensure that they can
   * synchronously receive messages without having to affect what the bin's sync
   * handler is.
   * 
   * This function may be called multiple times. To clean up, the caller is
   * responsible for calling disable_sync_message_emission() as many times
   * as this function is called.
   * 
   * While this function looks similar to add_signal_watch(), it is not
   * exactly the same -- this function enables <em>synchronous</em> emission of
   * signals when messages arrive; add_signal_watch() adds an idle callback
   * to pop messages off the bus <em>asynchronously</em>. The sync-message signal
   * comes from the thread of whatever object posted the message; the "message"
   * signal is marshalled to the main thread via the main loop.
   * 
   * MT safe.
   */
  void enable_sync_message_emission();

  
  /** Adds a bus signal watch to the default main context with the given @a priority
   * (e.g.\ PRIORITY_DEFAULT). Since 0.10.33 it is also possible to use a
   * non-default main context set up using Glib::main_context_push_thread_default()
   * (before one had to create a bus watch source and attach it to the desired
   * main context 'manually').
   * 
   * After calling this statement, the bus will emit the "message" signal for each
   * message posted on the bus when the main loop is running.
   * 
   * This function may be called multiple times. To clean up, the caller is
   * responsible for calling remove_signal_watch() as many times as this
   * function is called.
   * 
   * There can only be a single bus watch per bus, you must remove any signal
   * watch before you can set another type of watch.
   * 
   * MT safe.
   * @param priority The priority of the watch.
   */
  void add_signal_watch(int priority =  Glib::PRIORITY_DEFAULT);
  

  /** Removes a signal watch previously added with add_signal_watch().
   * 
   * MT safe.
   */
  void remove_signal_watch();
  
  /** Poll the bus for messages. Will block while waiting for messages to come.
   * You can specify a maximum time to poll with the @a timeout parameter. If
   *  @a timeout is negative, this function will block indefinitely.
   * 
   * All messages not in @a events will be popped off the bus and will be ignored.
   * 
   * Because poll is implemented using the "message" signal enabled by
   * add_signal_watch(), calling poll() will cause the "message"
   * signal to be emitted for every message that poll sees. Thus a "message"
   * signal handler will see the same messages that this function sees -- neither
   * will steal messages from the other.
   * 
   * This function will run a main loop from the default main context when
   * polling.
   * 
   * You should never use this function, since it is pure evil. This is
   * especially true for GUI applications based on Gtk+ or Qt, but also for any
   * other non-trivial application that uses the GLib main loop. As this function
   * runs a GLib main loop, any callback attached to the default GLib main
   * context may be invoked. This could be timeouts, GUI events, I/O events etc.;
   * even if poll() is called with a 0 timeout. Any of these callbacks
   * may do things you do not expect, e.g. destroy the main application window or
   * some other resource; change other application state; display a dialog and
   * run another main loop until the user clicks it away. In short, using this
   * function may add a lot of complexity to your code through unexpected
   * re-entrancy and unexpected changes to your application's state.
   * 
   * For 0 timeouts use pop_filtered() instead of this function; for
   * other short timeouts use timed_pop_filtered(); everything else is
   * better handled by setting up an asynchronous bus watch and doing things
   * from there.
   * @param events A mask of Gst::MessageType, representing the set of message types to
   * poll for.
   * @param timeout The poll timeout, as a Gst::ClockTimeDiff, or -1 to poll
   * indefinitely.
   * @return The message that was received, or <tt>0</tt> if the
   * poll timed out. The message is taken from the bus and needs to be
   * unreffed with gst_message_unref() after usage.
   */
  Glib::RefPtr<Gst::Message> poll(MessageType message_type, ClockTimeDiff timeout);

 
/**
   * @par Slot Prototype:
   * <tt>void on_my_%message(const Glib::RefPtr<Gst::Message>& message)</tt>
   *
   * A message has been posted on the bus. This signal is emitted from a
   * GSource added to the mainloop. this signal will only be emitted when
   * there is a mainloop running.
   * @param message The message that has been posted asynchronously.
   */

  Glib::SignalProxy1< void,const Glib::RefPtr<Gst::Message>& > signal_message();

  
/**
   * @par Slot Prototype:
   * <tt>void on_my_%sync_message(const Glib::RefPtr<Gst::Message>& message)</tt>
   *
   * A message has been posted on the bus. This signal is emitted from the
   * thread that posted the message so one has to be careful with locking.
   * 
   * This signal will not be emitted by default, you have to set up
   * Gst::Bus::sync_signal_handler() as a sync handler if you want this
   * signal to be emitted when a message is posted on the bus, like this:
   * 
   * gst_bus_set_sync_handler (bus, gst_bus_sync_signal_handler, yourdata);
   * 
   * @param message The message that has been posted synchronously.
   */

  Glib::SignalProxy1< void,const Glib::RefPtr<Gst::Message>& > signal_sync_message();


public:

public:
  //C++ methods used to invoke GTK+ virtual functions:

protected:
  //GTK+ Virtual Functions (override these to change behaviour):

  //Default Signal Handlers::
  /// This is a default handler for the signal signal_message().
  virtual void on_message(const Glib::RefPtr<Gst::Message>& message);
  /// This is a default handler for the signal signal_sync_message().
  virtual void on_sync_message(const Glib::RefPtr<Gst::Message>& message);


};

} //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::Bus
   */
  Glib::RefPtr<Gst::Bus> wrap(GstBus* object, bool take_copy = false);
}


#endif /* _GSTREAMERMM_BUS_H */

