/* 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_IPAQDISPLAYNODE_HPP_
#define _NMM_IPAQDISPLAYNODE_HPP_

#include "nmm/nmm_prefix.hpp"

#include <linux/vt.h>
#include <linux/fb.h>
#include <termios.h>

#include "nmm/multimedia/sync/GenericUSyncSinkNode.hpp"
#include "nmm/plugins/video/display/interfaces/IVideoDisplayImpl.hpp"
#include "yuv420_to_rgb565.h"


namespace NMM {

  class iPAQInput {
  public:
    enum {H3600_RECORD    = 120,
          H3600_POWER     = 121,
          H3600_CALENDAR  = 122,
          H3600_CONTACTS  = 123,
          H3600_MAIL      = 124,
          H3600_START     = 125,
          H3600_UP        = 103,
          H3600_LEFT      = 105,
          H3600_RIGHT     = 106,
          H3600_DOWN      = 108,
          H3600_ACTION    =  96,
          H3600_RELEASED  = 128};
  private:

    /* Terminal */
    int tty_handle;
    int tty_no;
    int tty_orig;
    struct vt_mode tty_vtm;
    
    /* Touchscreen */
    int ts_handle;
    
    /* Keyboard */
    int kb_oldkbdmode;
    struct termios kb_oldttysets;
      
  }; /* class iPAPInput */


  class iPAQDisplayNode : 
    public GenericUSyncSinkNode,
    public IVideoDisplayImpl {

  public:
    iPAQDisplayNode(const char* name = "iPAQDisplayNode",
                    StreamQueue::Mode queue_mode = StreamQueue::MODE_SUSPEND, 
                    int queue_size = 50);
    ~iPAQDisplayNode();

  protected:
    /**
     * Tries to open the framebuffer device and does some checks 
     * to determine if the framebuffer is an ipaq device. 
     * The LCD is turned on and the brightness level is set to 60.
     * This function will be removed later, because this should be
     * be done in the application.
     * @todo Switch off the cursor.
     * @param No parameter.
     * @return NMM:SUCCESS if the tests success, else NMM:FAILURE.
     */
    virtual Result doInit();


    /**
     * Close used file handles 
     * @param No parameter.
     * @return Always NMM:SUCCESS
     */
    virtual Result doDeinit();


    virtual Result doInitOutput();
    virtual Result doDeinitOutput();


    /**
     * This functions checks the input format and call 
     * some function to calculate offset and pad. Also
     * memory for interal buffering is allocated and
     * the frambuffer is mapped to memory.
     * @param No parameters
     * @return NMM::SUCCESS if success, else NMM::FAILURE.
     */
    virtual Result doActivate();

    /**
     * Clears the LCD, deallocate used memory and unmap 
     * framebuffer memory.
     * @param No parameters
     * @return NMM::SUCCESS if success, else NMM::FAILURE.
     */
    virtual Result doDeactivate();


    /**
     * Copy the incoming buffer to a private buffer
     * and convert to rgb565 colorspace.
     * @param NMM::Buffer
     * @return No return.
     */
    virtual void prepareBuffer(Buffer *in_buffer);


    /**
     * Copy the internal buffer to mapped framebuffer 
     * memory to display the image
     * @param NMM::Buffer
     * @return No return.
     */
    virtual Message* presentBuffer(Buffer *in_buffer);


    /* IVideoDisplay Interface */

    /**
     * Set fullscreen mode.
     * @param Value true for fullscreen, false for windowed display mode.
     * @return No return.
     */
    virtual void setFullscreen(const nmm_bool& fullscreen) {
      if (fullscreen) { /* avoid warning about unused variables */
      }
      return;
    }


    /**
     * Get fullscreen mode.
     * @param No parameters.
     * @return True if the display is in fullscreen mode, false if it is in windowed mode.
     */
    virtual nmm_bool getFullscreen() const {
      return true;
    }


    /**
     * Test if display has fullscreen support.
     * @param No parameters
     * @return True if fullscreen mode can be turned on, false otherwise.
     */
    virtual nmm_bool hasFullscreen() const {
      return true;
    }


    /**
     * Test if display is fullscreen only.
     * @param No parameters.
     * @return True if fullscren mode is the default and cannot be turned off.
     */
    virtual nmm_bool isFullscreenOnly() const {
      return true;
    }


    /**
     * Make a screenshoot and write it to filename
     * @param  filename    .
     * @return True if fullscren mode is the default and cannot be turned off.
     */    
    virtual nmm_bool makeScreenshot(const string& /*filename*/ ) const {
      /* Not implemepnted */
      return false;
    }


    /**
     * FormatChange
     * @param No parameters
     * @return NMM::SUCCESS if the format could changed, else NMM::FAILURE.
     */
    Result FormatChange();


    /**
     * Change the brightness level of the LCD (only H38x model)
     * @param Int value level [0..255]
     * @return NMM::SUCCESS if the brightness could changed, else NMM::FAILURE.
     */
    Result setBrightness(int);


    /**
     * Rotate the LCD by 90,180,270 degree
     */
    // Result setRotate(const int) const {}


    void setLeftWindowAlignment(){}
    void setRightWindowAlignment(){}
    void setCenterWindowAlignment(){}


  private:

    /* typdef to make it easy */
    typedef unsigned char  UBYTE;
    typedef unsigned short UWORD;
  
    /* name/handle of framebuffer device */
    string fb_name;
    int fb_handle;

    /* info about the framebuffer */
    struct fb_var_screeninfo fb_vinfo;
    struct fb_fix_screeninfo fb_finfo;
    long int fb_screensize;
  
  
    /* Pointer to the (f)rame(b)uffer data */
    UWORD *fb_data; 
    UWORD *fb_data_offset; 

    /* Pointer to (p)repare(b)uffer data */
    UWORD *pb_data;

    /* width and height of a image */
    int image_width;
    int image_height;
    int image_size; 
    int image_size_quarter; 

    /* width and height of the framebuffer */
    int screen_width;
    int screen_height;
       
    /**
     * offset : count pixel from (0,0) to startpoint
     * pad    : screen witdh - image width  
     */
    int offset;
    int pad;

    /* current pos in image */
    int xpos;
    int ypos;

    /* different format parameter */
    string colorspace;
    string channelorder;
    int    bitperpixel;
    string format; /* packed or planar */

    /**
     * Defines which formats the node can handle on his input
     * @param No parameters
     * @return No return 
     */
    void declareInputFormats();

    /* different converter to RGB565 */
    enum Converters {                       
      /* None */
      NONE=0, 
                     
      /* YV12 to RGB565 c++ version*/
      YV12_to_RGB565c, 
      
      /* YV12 to RGB565 arm-assembler version */
      YV12_to_RGB565asm, 

      /* RGB with 8Bit/color + 8Bit pading, chanelorder = prgb*/
      RGBX32_to_RGB565 
    };
    Converters convmode;

    /* Tables for YV12 to RGR 565 convert */
    long int crv_tab[256];
    long int cbu_tab[256];
    long int cgu_tab[256];
    long int cgv_tab[256];
    long int tab_76309[256];
    UWORD clpr[1024];
    UWORD clpg[1024];
    UWORD clpb[1024];

    /**
     * Precalculation of different values
     * for faster yv12 to rgbg565 convert
     * @param No parameters
     * @return No return 
     */
    void initTables();

    /* Pointer for different in_buffer readings */
    unsigned int* src_uint;
    unsigned int pixel;
    unsigned char *src0_uchar;
    unsigned char *src1_uchar;
    unsigned char *src2_uchar;
    unsigned char *src3_uchar;
    int y1,y2,u,v;
    int c1, c2, c3, c4;
    int r,g,b;

    /* Pointers to (p)repare(b)uffer write */
    UWORD* dest1;
    UWORD* dest2;  

    AVFrame pic;
    unsigned char *asm_buffer;
  };

}

#include "nmm/nmm_suffix.hpp"

#endif //_NMM_IPAQDISPLAYNODE_HPP_
