using namespace std;
/*
 * recledser.c: A rec-led connected to a serial port
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */

#include <vdr/plugin.h>
#include <vdr/status.h>

#include <iostream>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <getopt.h>





static const char *VERSION        = "0.0.1";
static const char *DESCRIPTION    = "Controls a rec-led connected to a serial port";
static const char *MAINMENUENTRY  = NULL;
class cRecStatus : public cStatus
	{
	private:
	//the serial interface
		int fd;
	//if true the reverse the LED-polarity
		bool inverted_polarity;
	//number of running recordings
		int n_rec;
	public:
		cRecStatus(int f, bool ip);
	//is called when a recording starts/stops
		void Recording(const cDevice *Device, const char *Name);
	//turn on led
		void LEDon();
	//turn off led
		void LEDoff();
	};

class cPluginRecledser : public cPlugin {
private:
	//the serial interface
		int fd;
	//if true the reverse the LED-polarity
		bool inverted_polarity;	
	//status class
		cRecStatus *recstat;
public:
  cPluginRecledser(void);
  virtual ~cPluginRecledser();
  virtual const char *Version(void) { return VERSION; }
  virtual const char *Description(void) { return DESCRIPTION; }
  virtual const char *CommandLineHelp(void);
  virtual bool ProcessArgs(int argc, char *argv[]);
  virtual bool Initialize(void);
  virtual bool Start(void);
  virtual void Housekeeping(void);
  virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
  virtual cOsdObject *MainMenuAction(void);
  virtual cMenuSetupPage *SetupMenu(void);
  virtual bool SetupParse(const char *Name, const char *Value);
  };

cPluginRecledser::cPluginRecledser(void) : cPlugin(), fd(-1), inverted_polarity(false)
{
  // Initialize any member variables here.
  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
}

cPluginRecledser::~cPluginRecledser()
{
//close interface
	if(fd>0) 
		{
		close(fd);
		}
}

const char *cPluginRecledser::CommandLineHelp(void)
{
  return NULL;
}

bool cPluginRecledser::ProcessArgs(int argc, char *argv[])
{
        int c;
        extern char *optarg;
        extern int optind, optopt;
        int underline_root=-1;
        int slevel(0);
        while((c = getopt(argc, argv, "d:i")) !=-1)
                switch(c)
                        {
		//the serial device
			case 'd':
				fd = open(optarg, O_RDWR | O_NOCTTY | O_NDELAY);
				if(fd==-1)
					{
					std::cerr<<"Cannot open'"<<optarg<<"'!"<<endl;
					return false;
					}
				break;
			case 'i':
				inverted_polarity=true;
				break;
			default:
				std::cerr<<"Unknowd option!"<<endl;
				return false;
			}
	if(fd==-1)
		{
		fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
		if(fd==-1)
			{
			std::cerr<<"Cannot open '/dev/ttyS1'!"<<std::endl;
			return false;
			}
		}
  return true;
}

bool cPluginRecledser::Initialize(void)
{
  // Initialize any background activities the plugin shall perform.
  return true;
}

bool cPluginRecledser::Start(void)
{
//create record status class
	recstat = new cRecStatus(fd, inverted_polarity);
  return true;
}

void cPluginRecledser::Housekeeping(void)
{
  // Perform any cleanup or other regular tasks.
}

cOsdObject *cPluginRecledser::MainMenuAction(void)
{
  // Perform the action when selected from the main VDR menu.
  return NULL;
}

cMenuSetupPage *cPluginRecledser::SetupMenu(void)
{
  // Return a setup menu in case the plugin supports one.
  return NULL;
}

bool cPluginRecledser::SetupParse(const char *Name, const char *Value)
{
  // Parse your own setup parameters and store their values.
  return false;
}


//==============================================================================


cRecStatus :: cRecStatus(int f, bool ip): cStatus(), fd(f), inverted_polarity(ip), n_rec(0)
	{
	LEDoff();
	}

void cRecStatus :: Recording(const cDevice *Device, const char *Name)
	{
	if (Name==NULL)
		n_rec--;
	else
		n_rec++;
	if(n_rec==0)
		LEDoff();
	else
		LEDon();
	}
	
void cRecStatus :: LEDon()
	{
	int status;
	ioctl(fd, TIOCMGET, &status);
	if(inverted_polarity)
		status&=~TIOCM_RTS;
	else
		status|=TIOCM_RTS;
	ioctl(fd, TIOCMSET, &status);	
	}

void cRecStatus :: LEDoff()
	{
	int status;
	ioctl(fd, TIOCMGET, &status);
	if(!inverted_polarity)
		status&=~TIOCM_RTS;
	else
		status|=TIOCM_RTS;
	ioctl(fd, TIOCMSET, &status);	
	}



VDRPLUGINCREATOR(cPluginRecledser); // Don't touch this!
