/*
 * parallelportcontroller.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */

#include <ctype.h>
#include <stdio.h>
#include <unistd.h>
#include <asm/io.h>
#include <linux/errno.h>

#include "parellelportoutputosdosd.h"

#ifdef NTSC_SYSTEM
#define OSDHEIGHT                420 // in pixels
#else
#define OSDHEIGHT                480 // in pixels
#endif
#define OSDWIDTH                 600 // in pixels


#define clrBackground            clrGray50 // this should be tied somehow into current theme

#define PP_ADR_BASE 0x378

#define PP_REG_DATA	 PP_ADR_BASE		/* Centronics data port		*/
#define PP_REG_STAT	(PP_ADR_BASE+1)		/* Centronics status port	*/
#define PP_REG_CTRL	(PP_ADR_BASE+2)		/* Centronics control port	*/

CParallelPortControllerOsd::CParallelPortControllerOsd(void)
:cOsdObject(true), cThread("Parallel Port Controller osd")
{
  m_Osd = NULL;
  m_Active = false;
  m_Font = cFont::GetFont(fontSml);

  m_iStatusData = 0;
  m_iPos = 0;
}

CParallelPortControllerOsd::~CParallelPortControllerOsd(void)
{
 if (m_Active)
 	{
     m_Active = false;
     Cancel(3);
	}

  if (m_Osd)
     delete m_Osd;
}

void CParallelPortControllerOsd::DrawNfoWindow(void)
{
	int offset=0,i;
	char buf[255];

    outb(m_iStatusData, PP_REG_DATA);

	if (m_Osd)
	{
        offset = m_Font->Height();
	     m_Osd->DrawText( 10, offset, "Port Parallel Controller",clrWhite, clrBackground , m_Font);
         offset += 2*m_Font->Height();

		for(i=0;i<8;i++)
		{
			sprintf(buf, "d%d : %d", i , (1&(m_iStatusData>>i)) );
			if( i == m_iPos )
				m_Osd->DrawText(10, offset, buf, clrYellow, clrCyan, m_Font);
			else
				m_Osd->DrawText(10, offset, buf, clrWhite, clrBackground, m_Font);

			offset += m_Font->Height();
		}

        offset += m_Font->Height();
        sprintf(buf, "%02xh %02xh %02xh", m_iStatusData ,inb(PP_REG_STAT),inb(PP_REG_CTRL));
        m_Osd->DrawText(10, offset, buf, clrWhite, clrBackground, m_Font);


	    m_Osd->Flush();
	}
}

void CParallelPortControllerOsd::Action(void)
{
  	m_Active = true;
    while (m_Active)
	{
		DrawNfoWindow();
    	usleep(1000000L);
	}
}

void CParallelPortControllerOsd::Show(void)
{
	eOsdError Result;

  m_Osd = cOsdProvider::NewOsd(100,100);
  if (m_Osd)
  {
    tArea Areas[] = { { 0, 0, OSDWIDTH, OSDHEIGHT/2, 4 } };

	Areas[0].x2 = 399;
	Areas[0].y2 = 305;

    if (m_Osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
    {
        Result = m_Osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
    }
    else
    {
	 	do
		{
	    	printf("cScOsd::Show() try little :");
			Areas[0].y2-=1;
			if( Areas[0].y2 < 10 && Areas[0].x2 > 10 )
			{
				Areas[0].x2 -= 1;
				Areas[0].y2 = OSDWIDTH;
			}
			Result = m_Osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea));
			printf("Areas : 0,0,%d,%d : %d \n",Areas[0].x2,Areas[0].y2,Result);
		}
		while( Result != oeOk && Areas[0].y2>0);
        printf("cScOsd::CanHandleAreas() return oeOk !\n");
//        tArea Areas[] = { { 0, 0, 576, 192, 2 } };
        Result = m_Osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));

    }

    printf("cScOsd::Show() SetAreas return : %d (oeOk = %d )\n",Result,oeOk);
    switch(Result)
    {
    	case oeOk:				printf("oeOk\n");break;
		case oeTooManyAreas:	printf("oeTooManyAreas\n");break;
        case oeTooManyColors:	printf("oeTooManyColors\n");break;
        case oeBppNotSupported:	printf("oeBppNotSupported\n");break;
        case oeAreasOverlap:	printf("oeAreasOverlap\n");break;
        case oeWrongAlignment:	printf("oeWrongAlignment\n");break;
        case oeOutOfMemory:		printf("oeOutOfMemory\n");break;
        case oeUnknown:			printf("oeUnknown\n");break;
	}

     m_Osd->DrawRectangle(0, 0, 399, 305, clrWhite);
     m_Osd->DrawRectangle(2, 2, 395, 301, clrTransparent);
     m_Osd->Flush();
     Start();
  }
}


eOSState CParallelPortControllerOsd::ProcessKey(eKeys Key)
{
    int bit;
    eOSState state = cOsdObject::ProcessKey(Key);
    if (state == osUnknown)
    {
        switch (Key) 
        {
            case kUp|k_Repeat:
            case kUp:
                m_iPos--;
                if( m_iPos < 0 ) m_iPos = 0;
            break;


            case kDown|k_Repeat:
            case kDown:
                m_iPos++;
                if( m_iPos > 7 ) m_iPos = 7;
            break;

            case kOk:
                bit = 1 & (m_iStatusData>>m_iPos);

                if( bit == 0 )
                    m_iStatusData |= (1<<m_iPos);
                else
                    m_iStatusData &= ~(1<<m_iPos);

            break;

            case kBack:
                state = osEnd;

            default:
            break;
        }
        state = osContinue;
    }
    return state;
}
