/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *
 * This file is part of NMM. 
 * 
 * NMM is free software; you can redistribute it and/or modify it    
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; only version 2 of the License.      
 * 
 * NMM 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 General Public 
 * License for more details.  
 * 
 * You should have received a copy of the GNU General Public License 
 * along with NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef NMM_ISinkController_HPP
#define NMM_ISinkController_HPP

#include "nmm/nmm_prefix.hpp"

#include "nmm/comm/Interface.hpp"
#include "nmm/comm/messaging/Event.hpp"
#include "nmm/comm/messaging/IllegalStateException.hpp"
#include <memory>

#include "IController.hpp"

#include "visibility.hpp"

namespace NMM
{

  class ISinkSynchronizer;
  /** Interface of a sink controller.
   * This is the interface of a controller which provides synchronization for a sink node.
   */

  class DLLEXPORT ISinkController : virtual public IController { 
  public:
    ISinkController() : NMM::Interface(ISinkController::ISinkController_type, "NMM") { };

    ISinkController(NMM::NMMObject& parent) : NMM::Interface (parent, ISinkController::ISinkController_type, "NMM") { };

    virtual ~ISinkController() {};

    static const char* ISinkController_type;

    virtual  string getInterfaceType() const { return ISinkController_type; }

    NMM::Interface* copy() const { return new ISinkController(*this); }
    static void used(); 
    static const char* setMaxDelay_event;
    static const char* setMaxAverageDelay_event;
    static const char* setTheoLatency_event;
    static const char* setDefaultTheoLatency_event;
    static const char* setSinkSynchronizer_event;
    static const char* setAverageCount_event;
    static const char* setMaxDiscardingCount_event;
    static const char* waitForReset_event;
    static const char* restart_event;
    static const char* enableWaitToPresent_event;
    static const char* setMinWaitInterval_event;
    static const char* enableFirstBufferInTime_event;
    static const char* enableBlocking_event;
    /** Set the maximum acceptable delay of a buffer.
     * This method sets the maximum delay of a buffer that should be tolerated.
     * If the difference between the arrival time of the buffer and its presentation system time
     * is greater than this value, then the buffer is too late to be presented in time.
     * The delay must be positive, otherwise this method fails.
     *
     * @param max_delay Maximum acceptable delay
     * @return @c SUCCESS if this method succeeded, @c FAILURE otherwise
     */

    virtual Result setMaxDelay(const Interval& max_delay)
      throw(const NMM::SerializedException&);
    /** Set the maximum acceptable deviation from the theoretical latency.
     * This method sets the maximum deviation of the average latency measured by a node from the
     * theoretical latency computed by the synchronizer. If the difference between these values
     * exceeds the maximum acceptable deviation, the new average measured latency is propagated
     * to the synchronizer which in turn propagates the new theoretical latency to all sinks.
     *
     * @param value The maximum acceptable deviation from the theoretical latency
     * @return SUCCESS
     */

    virtual Result setMaxAverageDelay(const Interval& value)
      throw(const NMM::SerializedException&);
    /** Set the theoretical latency.
     * This method is called by the synchronizer to tell the controllers the
     * theoretical latency of the pipeline.
     *
     * @param value Theoretical latency
     * @return SUCCESS
     */

    virtual Result setTheoLatency(const Interval& value)
      throw(const NMM::SerializedException&);
    /** Set the default theoretical latency.
     * This method is called by the synchronizer to tell the controllers the
     * default theoretical latency of the pipeline. This value is used as the
     * theoretical latency if no value for the theoretical latency is available
     * from the synchronizer.
     *
     * @param value Default theoretical latency
     * @return SUCCESS
     */

    virtual Result setDefaultTheoLatency(const Interval& value)
      throw(const NMM::SerializedException&);
    /** Sets the synchronizer which synchronizes this controller.
     * This method is called by the synchronizer when a controller has been added.
     * The synchronizer passes an interface to itself and the sink ID to the controller.
     * The controller needs to specify the sink ID when communicating with the synchronizer
     * using the synchronizer interface.
     *
     * @param sync An interface of the synchronizer
     * @param sink_id ID of this controller at the synchronizer
     * @return SUCCESS
     */

    virtual Result setSinkSynchronizer(const ISinkSynchronizer* sync, const nmm_int32& sink_id)
      throw(const NMM::SerializedException&);
    /** Set the number of samples for computing the average latency.
     * This method sets the number of buffers used to compute the average latency.
     * A small number means that the synchronizer is told the
     * average latency of incoming buffers very often. That means the
     * synchronization reacts very quickly (and this reaction may be visible)
     * For this reason higher values (such as 50 for audio and 20 for video) 
     * are recommended.
     *
     * @param value Number of samples for computing the average latency
     */

    virtual Result setAverageCount(const nmm_int32& value)
      throw(const NMM::SerializedException&);
     /** Set the maximum number of buffers to discard.
     * This method sets the maximal number of buffers that can be discarded before at least
     * one buffer is presented.
     *
     * @param value Maximum number of buffers to discard
     * @return SUCCESS
     */

    virtual Result setMaxDiscardingCount(const nmm_int32& value)
      throw(const NMM::SerializedException&);
    /** Wait for a syncReset event.
     * This method is called by the synchronizer during a synchronization reset.
     * The controller has to wait until the node has received a syncReset event.
     * During this time, the node continues processing buffers.
     *
     * If the node has already received a syncReset event, the controller does nothing.
     *
     * @return SUCCESS
     */

    virtual Result waitForReset()
      throw(const NMM::SerializedException&);
    /** Restart the controller.
     * This method is called by the synchronizer during a reset when all controllers
     * have received a syncReset event. The controller continues processing buffers.
     *
     * @return SUCCESS
     */

    virtual Result restart()
      throw(const NMM::SerializedException&);
    /** Enable or disable waiting for presentation.
     * This method enables or disables delaying the presentation of buffers which arrive
     * too early. If disabled, buffers are always presented immediately. Enabled by default.
     *
     * @param enable @c true to enable, @c false to disable waiting for presentation
     */

    virtual Result enableWaitToPresent(const nmm_bool& enable)
      throw(const NMM::SerializedException&);
    /** Set the minimum time to wait.
     * This method sets the minimum time a controller should delay a buffer which arrives too early.
     * If the time for which a buffer would be delayed is smaller than this interval, the buffer
     * is presented immediately.
     *
     * @param min_wait Minimum time to wait
     */

    virtual Result setMinWaitInterval(const Interval& min_wait)
      throw(const NMM::SerializedException&);
    /** Enable or disable first-buffer-in-time notification.
     * This method sets whether the sink controller should notify its
     * sink synchronizer if the first buffer after a syncReset
     * arrived in time (in regard to the theoretical latency).
     * The notification is done by calling
     * ISinkSynchronizer::setFirstBufferInTimeAverageLatency.
     *
     * @param enable @c true to enable, @c false to disable first-buffer-in-time notification
     */

    virtual void enableFirstBufferInTime(const nmm_bool& enable)
      throw(const NMM::SerializedException&);
    /** Enable or disable blocking.
     * This method enables or disables the blocking of the controller (and
     * therefore the blocking of its parent node) when waiting for restart()
     * after having received a syncReset.
     * Blocking is enabled by default.
     *
     * @param enable @c true to enable, @c false to disable blocking
     */

    virtual void enableBlocking(const nmm_bool& enable)
      throw(const NMM::SerializedException&);


  };

  typedef auto_ptr<ISinkController> ISinkController_var;




}

#include "nmm/nmm_suffix.hpp"

#endif
