/* 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_GENERICFIREWIRENODE_HPP
#define NMM_GENERICFIREWIRENODE_HPP

#include "nmm/nmm_prefix.hpp"



#include "nmm/multimedia/GenericSourceNode.hpp"

#include "nmm/utils/thread/Thread.hpp"
#include "nmm/utils/thread/ThreadMutex.hpp"
#include "nmm/comm/messaging/BufferManager.hpp"
#include "nmm/multimedia/sync/StreamTimer.hpp"

#include <l1394/l1394_eventhandle.h>
#include <l1394/l1394_device.h>

namespace L1394 {
  class Device;
  class Frame;
}

namespace NMM{
class Buffer;


/* \class GenericFireWireNode
 * This class creates a wrapper-node for a FireWire device.
 *
 * A GenericFireWireNode controls a L1394::Device object.
 */

class GenericFireWireNode : public GenericSourceNode, protected L1394::EventHandle, public BufferManager {
public:

/**
  * Constructor
  */
  GenericFireWireNode(const char* name = "FireWireNode",
		      StreamQueue::Mode = StreamQueue::MODE_SUSPEND,
		      int = StreamQueue::DEFAULT_SIZE);

/**
  * Destructor
  */
  ~GenericFireWireNode();


  Result getGuid(u_int64_t& guid);
  Result getDevice(string& dev);

  virtual void setDevice(L1394::Device* _device) { device = _device; }


  static void initOutputFormat(Property&, L1394::Device&  );

protected:

  /**
    * This method returns a frame from the device
    */
  virtual Message* processBuffer(Buffer*);

  virtual Result doActivate();

  /* \fn doStart()
   * \brief This function starts the current device
   */
  virtual Result doStart();

  /* \fn doStop()
   * \brief This function stops a started device
   */
  virtual Result doStop();

  /** Initialize the FireWireNode */
  virtual Result doInit();
  virtual Result doInitOutput();
 /*
   Buffermanager
  */
  virtual Buffer* requestBuffer (const size_t size) const;

  /**
   * Release a buffer. This is called from the Buffer class when
   * the corresponding buffer's reference count has dropped to 0.
   * \param buffer The buffer to be released.
   */
  virtual void releaseBuffer (Buffer* buffer) const;
  virtual void erase() const;

  /*
    L1394-specific event handling
  */
  virtual void nodeDestroy  (const Node *node);
  virtual void nodeDisabled (const Node *node);
  virtual void nodeEnabled  (const Node *node);

protected:
  inline L1394::Device* getInternalDevice() {return device;}
  static void createOutputFormat(L1394::Device&, L1394::Videomode video_mode, Format*);

private:
  int test_count;
  mutable list<L1394::Frame*> frame_list;

  L1394::Device*  device;

  static int channel;
  int max_buffer;

  typedef multimap<size_t, Buffer*> bufset_t;
  mutable bufset_t bufs;
  mutable int buffer_count;

  ThreadMutex mutex;
  ThreadMutex internal_mutex;
  StreamTimer* timer;
  mutable int number;

};
}

#include "nmm/nmm_suffix.hpp"

#endif

