/**
 *  pvrinput plugin for the Video Disk Recorder 
 *
 *  menu.c  -  setup menu class
 *
 *  (c) 2005 Andreas Regel <andreas.regel AT powarman.de>
 **/

/***************************************************************************
 *                                                                         *
 *   This program 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; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program;                                              *
 *   if not, write to the Free Software Foundation, Inc.,                  *
 *   59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *
 *                                                                         *
 ***************************************************************************/

#include "device.h"
#include "menu.h"
#include "plugin.h"

static const char * audioBitrateValues[] =
{
	"32",
	"48",
	"56",
	"64",
	"80",
	"96",
	"112",
	"128",
	"160",
	"192",
	"224",
	"256",
	"320",
	"384"
};

static const char * picturePropertyValues[] =
{
	"0%",
	"3%",
	"6%",
	"9%",
	"12%",
	"15%",
	"18%",
	"21%",
	"24%",
	"26%",
	"29%",
	"32%",
	"35%",
	"38%",
	"41%",
	"44%",
	"47%",
	"50%",
	"53%",
	"56%",
	"59%",
	"62%",
	"65%",
	"68%",
	"71%",
	"74%",
	"76%",
	"79%",
	"82%",
	"85%",
	"88%",
	"91%",
	"94%",
	"97%",
	"100%"
};

static const char * bitrateModes[] =
{
	"VBR",
	"CBR"
};

static const char * aspectRatios[] =
{
	"1:1",
	"4:3",
	"16:9",
	"2.21:1",
};


cPvrMenuSetup::cPvrMenuSetup()
{
	static const char * dnrModes[4];
	dnrModes[0] = tr("spatial and temporal");
	dnrModes[1] = tr("temporal only");
	dnrModes[2] = tr("spatial only");
	dnrModes[3] = tr("none");

	newPvrSetup = PvrSetup;

	Add(new cMenuEditBoolItem(tr("Hide main menu entry"), &newPvrSetup.HideMainMenuEntry));
	Add(new cMenuEditIntItem(tr("Wait after tuning (ms)"), &newPvrSetup.WaitAfterTuning, 0, 2000));
	Add(new cMenuEditIntItem(tr("Log level"), &newPvrSetup.LogLevel, 0, 3));
	Add(new cMenuEditStraItem(tr("Brightness"), &newPvrSetup.Brightness, 35, picturePropertyValues));
	Add(new cMenuEditStraItem(tr("Contrast"), &newPvrSetup.Contrast, 35, picturePropertyValues));
	Add(new cMenuEditStraItem(tr("Saturation"), &newPvrSetup.Saturation, 35, picturePropertyValues));
	Add(new cMenuEditStraItem(tr("Hue"), &newPvrSetup.Hue, 35, picturePropertyValues));
	Add(new cMenuEditIntItem(tr("Audio volume"), &newPvrSetup.AudioVolume, 0, 100));
	Add(new cMenuEditIntItem(tr("Video bitrate (kbit/s)"), &newPvrSetup.VideoBitrate, 2000, 15000));
	Add(new cMenuEditStraItem(tr("Audio bitrate (kbit/s)"), &newPvrSetup.AudioBitrate, 14, audioBitrateValues));
	Add(new cMenuEditStraItem(tr("Bitrate mode"), &newPvrSetup.BitrateMode, 2, bitrateModes));
	Add(new cMenuEditStraItem(tr("Aspect ratio"), &newPvrSetup.AspectRatio, 4, aspectRatios));
	Add(new cMenuEditBoolItem(tr("3:2 pulldown"), &newPvrSetup.Pulldown));
	Add(new cMenuEditIntItem(tr("Frames per GOP"), &newPvrSetup.FramesPerGop, 10, 30));
	Add(new cMenuEditIntItem(tr("B-Frames"), &newPvrSetup.BFrames, 0, 5));
	Add(new cMenuEditBoolItem(tr("GOP closed"), &newPvrSetup.GopClosure));
	Add(new cMenuEditStraItem(tr("Noise reduction"), &newPvrSetup.DnrMode, 4, dnrModes));
	Add(new cMenuEditIntItem(tr("DNR spatial"), &newPvrSetup.DnrSpatial, 0, 16));
	Add(new cMenuEditIntItem(tr("DNR temporal"), &newPvrSetup.DnrTemporal, 0, 16));
	Add(new cMenuEditIntItem(tr("DNR type"), &newPvrSetup.DnrType, 0, 16));
}

void cPvrMenuSetup::Store()
{
	SetupStore("HideMainMenuEntry", PvrSetup.HideMainMenuEntry = newPvrSetup.HideMainMenuEntry);
	SetupStore("WaitAfterTuning", PvrSetup.WaitAfterTuning = newPvrSetup.WaitAfterTuning);
	SetupStore("LogLevel", PvrSetup.LogLevel = newPvrSetup.LogLevel);
	SetupStore("Brightness", PvrSetup.Brightness = newPvrSetup.Brightness);
	SetupStore("Contrast", PvrSetup.Contrast = newPvrSetup.Contrast);
	SetupStore("Saturation", PvrSetup.Saturation = newPvrSetup.Saturation);
	SetupStore("Hue", PvrSetup.Hue = newPvrSetup.Hue);
	SetupStore("AudioVolume", PvrSetup.AudioVolume = newPvrSetup.AudioVolume);
	SetupStore("VideoBitrate", PvrSetup.VideoBitrate = newPvrSetup.VideoBitrate);
	SetupStore("AudioBitrate", PvrSetup.AudioBitrate = newPvrSetup.AudioBitrate);
	SetupStore("BitrateMode", PvrSetup.BitrateMode = newPvrSetup.BitrateMode);
	SetupStore("AspectRatio", PvrSetup.AspectRatio = newPvrSetup.AspectRatio);
	SetupStore("Pulldown", PvrSetup.Pulldown = newPvrSetup.Pulldown);
	SetupStore("FramesPerGop", PvrSetup.FramesPerGop = newPvrSetup.FramesPerGop);
	SetupStore("BFrames", PvrSetup.BFrames = newPvrSetup.BFrames);
	SetupStore("GopClosure", PvrSetup.GopClosure = newPvrSetup.GopClosure);
	SetupStore("DnrMode", PvrSetup.DnrMode = newPvrSetup.DnrMode);
	SetupStore("DnrSpatial", PvrSetup.DnrSpatial = newPvrSetup.DnrSpatial);
	SetupStore("DnrTemporal", PvrSetup.DnrTemporal = newPvrSetup.DnrTemporal);
	SetupStore("DnrType", PvrSetup.DnrType = newPvrSetup.DnrType);

	cPvrDevice::ReInitAll();
}


static const char * pictureProperties[] =
{
	"Brightness",
	"Contrast",
	"Saturation",
	"Hue"
};

cPvrMenu::cPvrMenu(void)
:	cOsdObject(),
	border(2),
	margin(4),
	mode(0),
	brightness(PvrSetup.Brightness),
	contrast(PvrSetup.Contrast),
	saturation(PvrSetup.Saturation),
	hue(PvrSetup.Hue)
{
	font = cFont::GetFont(fontOsd);
	width = Setup.OSDWidth;
	height = 2 * font->Height() + 3 * border + 4 * margin;
}

cPvrMenu::~cPvrMenu()
{
	for (int i = 0; i < cPvrDevice::Count(); i++)
	{
		cPvrDevice * pvr = cPvrDevice::Get(i);
		if (pvr)
			pvr->SetPicture(PvrSetup.Brightness, PvrSetup.Contrast, PvrSetup.Saturation, PvrSetup.Hue);
	}
	delete osd;
}

void cPvrMenu::Draw(void)
{
	int titleWidth = font->Width(tr(pictureProperties[mode])) + 2 * border + 2 * margin;
	int titleHeight = font->Height() + border + 2 * margin;
	int titleStart = 50;
	int value = brightness;
	
	switch (mode)
	{
		case 0:
			value = brightness;
			break;
		case 1:
			value = contrast;
			break;
		case 2:
			value = saturation;
			break;
		case 3:
			value = hue;
			break;
	}
	int barWidth = value * (width - font->Width("100%") - 2 * border - 3 * margin) / 34;

	osd->DrawRectangle(0, 0, width - 1, height - 1, clrTransparent);
	osd->DrawRectangle(0, titleHeight, width - 1, height - 1, clrBlack);
	osd->DrawRectangle(titleStart, 0, titleStart + titleWidth - 1, titleHeight - 1, clrBlack);
	osd->DrawText(titleStart + border + margin, border + margin, tr(pictureProperties[mode]), clrWhite, clrBlack, font);
	osd->DrawRectangle(titleStart, 0, titleStart + titleWidth - 1, border - 1, clrWhite);
	osd->DrawRectangle(titleStart, 0, titleStart + border - 1, titleHeight - 1, clrWhite);
	osd->DrawRectangle(titleStart + titleWidth - border, 0, titleStart + titleWidth - 1, titleHeight - 1, clrWhite);
	osd->DrawRectangle(0, titleHeight, width - 1, titleHeight + border - 1, clrWhite);
	osd->DrawRectangle(0, titleHeight, border - 1, height - 1, clrWhite);
	osd->DrawRectangle(0, height - border, width - 1, height - 1, clrWhite);
	osd->DrawRectangle(width - border, titleHeight, width - 1, height - 1, clrWhite);
	osd->DrawText(width - font->Width("100%") - border - margin - 1, border + margin + titleHeight, picturePropertyValues[value], clrWhite, clrBlack, font, font->Width("100%"), 0, taRight);
	osd->DrawRectangle(border + margin, border + margin + titleHeight, border + margin + barWidth - 1, height - border - margin - 1, clrWhite);
	osd->Flush();
}

void cPvrMenu::Show(void)
{
	osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - height);

	tArea area = { 0, 0, width - 1, height - 1, 4 };
	if (osd->CanHandleAreas(&area, 1) == oeOk)
		osd->SetAreas(&area, 1);

	Draw();
}

eOSState cPvrMenu::ProcessKey(eKeys Key)
{
	eOSState state = cOsdObject::ProcessKey(Key);
	if (state == osUnknown)
	{
		switch (Key & ~k_Repeat)
		{
			case kUp:
				mode--;
				if (mode < 0)
					mode = 3;
				Draw();
				break;
			case kDown:
				mode++;
				if (mode > 3)
					mode = 0;
				Draw();
				break;
			case kLeft:
				switch (mode)
				{
					case 0:
						if (brightness > 0)
							brightness--;
						break;
					case 1:
						if (contrast > 0)
							contrast--;
						break;
					case 2:
						if (saturation > 0)
							saturation--;
						break;
					case 3:
						if (hue > 0)
							hue--;
						break;
				}
				for (int i = 0; i < cPvrDevice::Count(); i++)
				{
					cPvrDevice * pvr = cPvrDevice::Get(i);
					if (pvr)
						pvr->SetPicture(brightness, contrast, saturation, hue);
				}
				Draw();
				break;
			case kRight:
				switch (mode)
				{
					case 0:
						if (brightness < 34)
							brightness++;
						break;
					case 1:
						if (contrast < 33)
							contrast++;
						break;
					case 2:
						if (saturation < 33)
							saturation++;
						break;
					case 3:
						if (hue < 34)
							hue++;
						break;
				}
				for (int i = 0; i < cPvrDevice::Count(); i++)
				{
					cPvrDevice * pvr = cPvrDevice::Get(i);
					if (pvr)
						pvr->SetPicture(brightness, contrast, saturation, hue);
				}
				Draw();
				break;
			case kOk:
				PluginPvrInput->SetupStore("Brightness", PvrSetup.Brightness = brightness);
				PluginPvrInput->SetupStore("Contrast", PvrSetup.Contrast = contrast);
				PluginPvrInput->SetupStore("Saturation", PvrSetup.Saturation = saturation);
				PluginPvrInput->SetupStore("Hue", PvrSetup.Hue = hue);
				return osEnd;
			case kBack:
				return osEnd;
			default:
				return state;
		}
		state = osContinue;
	}
	return state;
}

