/*
   (c) Copyright 2012  Xylon d.o.o.

   This file is subject to the terms and conditions of the MIT License:

   Permission is hereby granted, free of charge, to any person
   obtaining a copy of this software and associated documentation
   files (the "Software"), to deal in the Software without restriction,
   including without limitation the rights to use, copy, modify, merge,
   publish, distribute, sublicense, and/or sell copies of the Software,
   and to permit persons to whom the Software is furnished to do so,
   subject to the following conditions:

   The above copyright notice and this permission notice shall be
   included in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <unistd.h>
#include <errno.h>
#ifdef QOS_PATCH
#include <stdlib.h>
#endif

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "perfmon.h"
#include "filter.h"

//Macros Definition
#define CURSOR_TIMER_INTERVAL 500

//Default GUI win.
#define APP_HEIGHT_1920_MAX 300
#define APP_HEIGHT_1920_MIN  80

//Auto Mode
#define AUTO_MODE_SLEEP_TIME 2
#ifdef QOS_PATCH
#define QOS_OFF 0
#define QOS_STATIC 1
#define QOS_DYNAMIC 2
#define ATG_DEFAULT_CLK 0
#define ATG_LOW_CLK 1
#define ATG_HIGH_CLK 2
#endif

MainWindow::MainWindow(QWidget *parent, bool apm_enable, int pr_enable) :
	QMainWindow(parent),
	apm_enable(apm_enable),
	pr_enable(pr_enable),
	ui(new Ui::MainWindow)
{
	int iret;
	int i, j;
	int height = vlib_get_active_height();

	iWindowHeightInMinMode = APP_HEIGHT_1920_MIN;
	iWindowHeightInMaxMode = APP_HEIGHT_1920_MAX;

	// Populate pixmap vector with the names of pixmap to attached GUI Label
	// using QT Resource file
	pixmapVec.push_back(":/zynq/images/TPG_Sobel_off.png"); //Index 0
	pixmapVec.push_back(":/zynq/images/TPG_software_sobel.png");
	pixmapVec.push_back(":/zynq/images/TPG_Hardware_sobel.png");
	pixmapVec.push_back(":/zynq/images/ExternalVideo_Sobel_off.png");
	pixmapVec.push_back(":/zynq/images/ExternalVideo_software_sobel.png");
	pixmapVec.push_back(":/zynq/images/ExternalVideo_Hardware_sobel.png");
	pixmapVec.push_back(":/zynq/images/default.png");

	qws = QWSServer::instance();
	qws->setBackground(QBrush(QColor(0, 0, 0, 0)));

	// Splash screen show the default Zynq image located in images directory.
	QSplashScreen splash(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));
	QRect rect = splash.geometry();
	splash.setGeometry(rect);
	splash.show();
	sleep(3);

	ui->setupUi(this);

	QWidget::setWindowFlags(Qt::FramelessWindowHint);

	splash.finish(this);

	if (apm_enable) {
		/* Initialize perf-mon */
		iret = perf_monitor_init();
		if (iret != EXIT_SUCCESS) {
			printf("TRD :: perfmon_init failed\n");
			exit(EXIT_FAILURE);
		}
	} else {
		printf("TRD :: Skip AXI Performance monitoring\n");
	}

	vlib_drm_set_layer0_position (LAYER0_X_POS, height-this->height());

	/* set the cursor on top of window */
	cursor = new QCursor();
	cursor->setPos(0, 0);
	this->setCursor(*cursor);
	checkCursorTimer = new QTimer();

	/* Try to put cursor always on viewable area.*/
	connect(checkCursorTimer, SIGNAL(timeout()), this, SLOT(CheckCursorActivity()));
	checkCursorTimer->start(CURSOR_TIMER_INTERVAL);

	// Enable mouse move tracking
	setMouseTracking(true);
	centralWidget()->setMouseTracking(true);

	// By default app will be in maximized state.
	isAppStateMaximized = true;

	// Set the TRD application release version.
	ui->labelBaseTrdReleaseVersion->setText(RELEASE_VERSION);

	// Video Source
	ui->groupBoxVideoSource->setEnabled(false);
	ui->comboBoxVideoSource->blockSignals(true);
	for (i = 0, j = 0; i < VIDEO_SRC_CNT; i++) {
		if (vlib_video_src_get_enabled((video_src) i)) {
			ui->comboBoxVideoSource->addItem(QString::fromUtf8(vlib_video_src_display_text((video_src) i)));
			vlib_video_src_set_index((video_src) i, j++);
		}
	}
	ui->comboBoxVideoSource->setCurrentIndex(vlib_video_src_get_index(VIDEO_SRC_TPG));
	ui->comboBoxVideoSource->blockSignals(false);

#ifndef QOS_PATCH
	// Test Pattern
	ui->groupBoxTestPattern->setEnabled(false);
	ui->comboBoxTestPattern->blockSignals(true);
	// start with i=1 to omit passthrough
	for (i = 1; i < TPG_TEST_PATTERN_CNT; i++)
		ui->comboBoxTestPattern->addItem(QString::fromUtf8(vlib_tpg_get_pattern_menu_name(i)));
	ui->comboBoxTestPattern->setCurrentIndex(TPG_TEST_PATTERN_DEFAULT-1);
	ui->comboBoxTestPattern->blockSignals(false);
	vlib_tpg_set_pattern(TPG_TEST_PATTERN_DEFAULT);
#endif
	// Filter Type
	ui->groupBoxFilterType->setEnabled(false);
	ui->comboBoxFilterType->blockSignals(true);
	for (i = 0, j = 0; i < FILTER_TYPE_CNT; i++) {
		if (filter_type_is_static((filter_type) i) || pr_enable) {
			ui->comboBoxFilterType->addItem(QString::fromUtf8(filter_type_display_text((filter_type) i)));
			filter_type_set_index((filter_type) i, j++);
		}
	}
	ui->comboBoxFilterType->setCurrentIndex(filter_type_get_index(FILTER_TYPE_SOBEL));
	ui->comboBoxFilterType->blockSignals(false);

	// Filter Mode
	ui->groupBoxFilterMode->setEnabled(false);
	ui->radioButtonFilterModeOff->setChecked(true);

#ifndef QOS_PATCH
	// Sobel Controls
	ui->groupBoxSobelControls->setEnabled(false);
	ui->labelSobelControlsThreshold->setText(QString::number(HLS_SOBEL_HIGH_THRESH_VAL));
	ui->sliderSobelControlsThreshold->setValue(HLS_SOBEL_HIGH_THRESH_VAL);
	if(HLS_SOBEL_INVERT_VAL)
		ui->checkBoxSobelControlsInvert->setChecked(true);
	else
		ui->checkBoxSobelControlsInvert->setChecked(false);
#endif
	// set new state
	videoCtrl = VIDEO_CTRL_OFF;
	config.src = VIDEO_SRC_TPG;
	config.type = FILTER_TYPE_SOBEL;
	config.mode = FILTER_MODE_OFF;

	// Set the default images on display panels.
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));
	ui->labelLogoDisplay->setPixmap(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));

	// CPU Plot
	ui->plotCpu->cpu1Label = ui->labelPerformanceCpu0Val;
	ui->plotCpu->cpu2Label = ui->labelPerformanceCpu1Val;

	// Memory Plot
	ui->plotMemory->hpPort0 = ui->labelPerformanceHp0Val;
	ui->plotMemory->hpPort2 = ui->labelPerformanceHp2Val;

#ifdef QOS_PATCH
	// Test Pattern
	ui->groupBoxAQoS_P->setEnabled(false);
	ui->comboBoxAQoS_P->blockSignals(true);

	for (i = 0; i < AW_P_MAX; i++) {
		ui->comboBoxAQoS_P->addItem(QString::fromUtf8(vlib_peak_rate_display_text((aw_p) i)));
	}
	ui->comboBoxAQoS_P->setCurrentIndex(AW_P_MAX - 1);
	ui->comboBoxAQoS_P->blockSignals(false);

	ui->groupBoxATG->setEnabled(false);
	ui->groupBoxBQoS->setEnabled(false);

	ui->groupBoxATG_ACP->setEnabled(false);
	ui->groupBoxAQoS->setEnabled(false);
	ui->groupBoxAQoS_P->setEnabled(false);
	bqos_en = QOS_OFF;
	atg_en = false;
	atg_acp = false;
	aqos_en = false;
	peak_index = AW_P_MAX - 1;
#endif
}

MainWindow::~MainWindow()
{
#ifdef QOS_PATCH
	// Disable ATG controllers by disabling the GPIOs
	if (atg_en) {
		system("/bin/sh /media/card/bin/atg_on.sh 0");
		ui->radioButtonATGOn->setChecked(false);
		ui->radioButtonATGOff->setChecked(true);
		atg_en = false;
		if (bqos_en) {
			system("/bin/sh /media/card/bin/qos_on.sh 0");
			ui->radioButtonBQoSStatic->setChecked(false);
			ui->radioButtonBQoSDynamic->setChecked(false);
			ui->radioButtonBQoSOff->setChecked(true);
			bqos_en = QOS_OFF;
		}
		ui->groupBoxBQoS->setEnabled(false);
	}
	ui->groupBoxATG->setEnabled(false);

	if (atg_acp) {
		system("/bin/sh /media/card/bin/atg_acp.sh 0");
		ui->radioButtonATG_ACPOn->setChecked(false);
		ui->radioButtonATG_ACPOff->setChecked(true);
		atg_acp = false;
		if (aqos_en) {
			system("/bin/sh /media/card/bin/aqos_en.sh 0 -1");
			ui->radioButtonAQoSOn->setChecked(false);
			ui->radioButtonAQoSOff->setChecked(true);
			aqos_en = false;
		}
		ui->groupBoxAQoS->setEnabled(false);
		ui->groupBoxAQoS_P->setEnabled(false);
	}
	ui->groupBoxATG_ACP->setEnabled(false);
#endif

	checkCursorTimer->stop();
	delete checkCursorTimer;
	delete cursor;
	delete ui;
}

//Invoked when video controls On is clicked
void MainWindow::on_radioButtonVideoControlsOn_clicked(bool checked)
{
	if (!checked || videoCtrl == VIDEO_CTRL_ON)
		return;

	// stop autoloop
	if (videoCtrl == VIDEO_CTRL_AUTO && autoloop != 0) {
		pthread_cancel(autoloop);
		pthread_join(autoloop, NULL);
		autoloop = 0;
	}

	// set new state
	videoCtrl = VIDEO_CTRL_ON;

	// configure and start video pipeline
	vlib_change_mode(config);

	// update UI
	ui->groupBoxVideoSource->setEnabled(true);
#ifndef QOS_PATCH
	if (config.src == VIDEO_SRC_TPG)
		ui->groupBoxTestPattern->setEnabled(true);
#endif
	ui->groupBoxFilterType->setEnabled(true);
	ui->groupBoxFilterMode->setEnabled(true);
#ifdef QOS_PATCH
	ui->groupBoxATG->setEnabled(true);
	ui->groupBoxATG_ACP->setEnabled(true);
#else
	if (config.type == FILTER_TYPE_SOBEL && config.mode != FILTER_MODE_OFF)
		ui->groupBoxSobelControls->setEnabled(true);
#endif
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
}

//Invoked when video controls Off is clicked
void MainWindow::on_radioButtonVideoControlsOff_clicked(bool checked)
{
	if (!checked || videoCtrl == VIDEO_CTRL_OFF)
		return;

	// stop autoloop
	if (videoCtrl == VIDEO_CTRL_AUTO && autoloop != 0) {
		pthread_cancel(autoloop);
		pthread_join(autoloop, NULL);
		autoloop = 0;
	}

	// set new state
	videoCtrl = VIDEO_CTRL_OFF;

	// stop video pipeline
	vlib_pipeline_stop();

	// update UI
	ui->groupBoxVideoSource->setEnabled(false);
	ui->groupBoxFilterType->setEnabled(false);
	ui->groupBoxFilterMode->setEnabled(false);
#ifndef QOS_PATCH
	ui->groupBoxTestPattern->setEnabled(false);
	ui->groupBoxSobelControls->setEnabled(false);
#else
	// Disable ATG controllers by disabling the GPIOs
	if (atg_en) {
		system("/bin/sh /media/card/bin/atg_on.sh 0");
		ui->radioButtonATGOn->setChecked(false);
		ui->radioButtonATGOff->setChecked(true);
		if (bqos_en) {
			system("/bin/sh /media/card/bin/qos_on.sh 0");
			ui->radioButtonBQoSStatic->setChecked(false);
			ui->radioButtonBQoSDynamic->setChecked(false);
			ui->radioButtonBQoSOff->setChecked(true);
			bqos_en = QOS_OFF;
		}
		ui->groupBoxBQoS->setEnabled(false);
		atg_en = false;
	}
	ui->groupBoxATG->setEnabled(false);

	if (atg_acp) {
		system("/bin/sh /media/card/bin/atg_acp.sh 0");
		ui->radioButtonATG_ACPOn->setChecked(false);
		ui->radioButtonATG_ACPOff->setChecked(true);
		atg_acp = false;
		if (aqos_en) {
			system("/bin/sh /media/card/bin/aqos_en.sh 0 -1");
			ui->radioButtonAQoSOn->setChecked(false);
			ui->radioButtonAQoSOff->setChecked(true);
			aqos_en = false;
		}
		ui->groupBoxAQoS->setEnabled(false);
		ui->groupBoxAQoS_P->setEnabled(false);
	}
	ui->groupBoxATG_ACP->setEnabled(false);
	
#endif
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));
	qws->setBackground(QBrush(QColor(0, 0, 0, 0)));
}

#ifdef QOS_PATCH
//Invoked when ATG On is clicked
void MainWindow::on_radioButtonATGOn_clicked(bool checked)
{
	if (!checked || atg_en) {
		printf("return ATG on function\n");
		return;
	}

	system("/bin/sh /media/card/bin/atg_on.sh 1");
	ui->groupBoxBQoS->setEnabled(true);
	ui->groupBoxATG_ACP->setEnabled(false);
	atg_en = true;
}

//Invoked when ATG Off is clicked
void MainWindow::on_radioButtonATGOff_clicked(bool checked)
{
	if (!checked || !atg_en) {
		printf("return ATG off function\n");
		return;
	}

	// Disable ATG controllers by disabling the GPIOs
	system("/bin/sh /media/card/bin/atg_on.sh 0");
	if (bqos_en) {
		system("/bin/sh /media/card/bin/qos_on.sh 0");
		ui->radioButtonBQoSStatic->setChecked(false);
		ui->radioButtonBQoSDynamic->setChecked(false);
		ui->radioButtonBQoSOff->setChecked(true);
		bqos_en = QOS_OFF;
	}
	ui->groupBoxBQoS->setEnabled(false);
	ui->groupBoxATG_ACP->setEnabled(true);
	atg_en = false;
}

//Invoked when ATG_ACP off is clicked
void MainWindow::on_radioButtonATG_ACPOff_clicked(bool checked)
{
	if (!checked || (atg_acp == false)) {
		printf("return ATG_ACP off function\n");
		return;
	}

	// Enable ATG_ACP off for ACP
	system("/bin/sh /media/card/bin/atg_acp.sh 0");
	atg_acp = false;
	if (aqos_en) {
		system("/bin/sh /media/card/bin/aqos_en.sh 0 7");
		ui->radioButtonAQoSOn->setChecked(false);
		ui->radioButtonAQoSOff->setChecked(true);
		aqos_en = false;
	}
	ui->groupBoxAQoS->setEnabled(false);
	ui->groupBoxAQoS_P->setEnabled(false);
	ui->groupBoxATG->setEnabled(true);
}

//Invoked when ATG_ACP On is clicked
void MainWindow::on_radioButtonATG_ACPOn_clicked(bool checked)
{
	if (!checked || (atg_acp == true)) {
		printf("return ATG_ACP on function\n");
		return;
	}

	ui->groupBoxATG->setEnabled(false);
	// Enable ATG_ACP for ACP
	system("/bin/sh /media/card/bin/atg_acp.sh 1");
	ui->groupBoxAQoS->setEnabled(true);
	atg_acp = true;
}

//Invoked when Advanced QoS off is clicked
void MainWindow::on_radioButtonAQoSOff_clicked(bool checked)
{
	if (!checked || (aqos_en == false)) {
		printf("return AQoS off function\n");
		return;
	}

	// set new state
	videoCtrl = VIDEO_CTRL_OFF;

	// stop video pipeline
	vlib_pipeline_stop();

	// update UI
	ui->groupBoxVideoSource->setEnabled(false);
	ui->groupBoxFilterType->setEnabled(false);
	ui->groupBoxFilterMode->setEnabled(false);
	ui->groupBoxATG->setEnabled(false);
	ui->groupBoxBQoS->setEnabled(false);
	ui->groupBoxAQoS->setEnabled(false);
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));
	qws->setBackground(QBrush(QColor(0, 0, 0, 0)));

	// Enable AQoS off for ACP
	system("/bin/sh /media/card/bin/aqos_en.sh 0 7");
	// set new state
	videoCtrl = VIDEO_CTRL_ON;

	// configure and start video pipeline
	vlib_change_mode(config);

	// update UI
	ui->groupBoxVideoSource->setEnabled(true);
	ui->groupBoxFilterType->setEnabled(true);
	ui->groupBoxFilterMode->setEnabled(true);
	ui->groupBoxATG->setEnabled(false);
	ui->groupBoxBQoS->setEnabled(false);
	ui->groupBoxAQoS->setEnabled(true);
	ui->groupBoxAQoS_P->setEnabled(true);
	ui->comboBoxAQoS_P->setCurrentIndex(AW_P_MAX - 1);
	ui->groupBoxAQoS_P->setEnabled(false);
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
	aqos_en = false;
}

//Invoked when Advanced QoS on is clicked
void MainWindow::on_radioButtonAQoSOn_clicked(bool checked)
{
	if (!checked || (aqos_en == true)) {
		printf("return AQoS on function\n");
		return;
	}

	// set new state
	videoCtrl = VIDEO_CTRL_OFF;

	// stop video pipeline
	vlib_pipeline_stop();

	// update UI
	ui->groupBoxVideoSource->setEnabled(false);
	ui->groupBoxFilterType->setEnabled(false);
	ui->groupBoxFilterMode->setEnabled(false);
	ui->groupBoxATG->setEnabled(false);
	ui->groupBoxBQoS->setEnabled(false);
	ui->groupBoxAQoS->setEnabled(false);
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));
	qws->setBackground(QBrush(QColor(0, 0, 0, 0)));

	// Enable AQoS for ACP
	system("/bin/sh /media/card/bin/aqos_en.sh 1 7");
	// set new state
	videoCtrl = VIDEO_CTRL_ON;

	// configure and start video pipeline
	vlib_change_mode(config);

	// update UI
	ui->groupBoxVideoSource->setEnabled(true);
	ui->groupBoxFilterType->setEnabled(true);
	ui->groupBoxFilterMode->setEnabled(true);
	ui->groupBoxATG->setEnabled(false);
	ui->groupBoxBQoS->setEnabled(false);
	ui->groupBoxAQoS->setEnabled(true);
	ui->groupBoxAQoS_P->setEnabled(true);
	ui->comboBoxAQoS_P->setCurrentIndex(peak_index);
	
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
	aqos_en = true;
}

//Invoked when Basic QoS Off is clicked
void MainWindow::on_radioButtonBQoSOff_clicked(bool checked)
{
	if(!checked || (bqos_en == QOS_OFF)) {
		printf("return QoS Basic off function\n");
		return;
	}
	
	// set new state
	videoCtrl = VIDEO_CTRL_OFF;

	// stop video pipeline
	vlib_pipeline_stop();

	// update UI
	ui->groupBoxVideoSource->setEnabled(false);
	ui->groupBoxFilterType->setEnabled(false);
	ui->groupBoxFilterMode->setEnabled(false);
	ui->groupBoxATG->setEnabled(false);
	ui->groupBoxBQoS->setEnabled(false);
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));
	qws->setBackground(QBrush(QColor(0, 0, 0, 0)));
	//Unset the static priority value to AFI QoS fields
	system("/bin/sh /media/card/bin/qos_on.sh 0");
	// set new state
	videoCtrl = VIDEO_CTRL_ON;

	// configure and start video pipeline
	vlib_change_mode(config);

	// update UI
	ui->groupBoxVideoSource->setEnabled(true);
	ui->groupBoxFilterType->setEnabled(true);
	ui->groupBoxFilterMode->setEnabled(true);
	ui->groupBoxATG->setEnabled(true);
	ui->groupBoxBQoS->setEnabled(true);

	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
	bqos_en = QOS_OFF;
}

//Invoked when Basic QoS Static is clicked
void MainWindow::on_radioButtonBQoSStatic_clicked(bool checked)
{
	if(!checked || (bqos_en == QOS_STATIC)) {
		printf("return Basic QoS Static function\n");
		return;
	}

	// set new state
	videoCtrl = VIDEO_CTRL_OFF;

	// stop video pipeline
	vlib_pipeline_stop();

	// update UI
	ui->groupBoxVideoSource->setEnabled(false);
	ui->groupBoxFilterType->setEnabled(false);
	ui->groupBoxFilterMode->setEnabled(false);
	ui->groupBoxATG->setEnabled(false);
	ui->groupBoxBQoS->setEnabled(false);
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));
	qws->setBackground(QBrush(QColor(0, 0, 0, 0)));

	//Set the static priority value to AFI QoS fields
	system("/bin/sh /media/card/bin/qos_on.sh 1");
	// set new state
	videoCtrl = VIDEO_CTRL_ON;

	// configure and start video pipeline
	vlib_change_mode(config);

	// update UI
	ui->groupBoxVideoSource->setEnabled(true);
	ui->groupBoxFilterType->setEnabled(true);
	ui->groupBoxFilterMode->setEnabled(true);
	ui->groupBoxATG->setEnabled(true);
	ui->groupBoxBQoS->setEnabled(true);
	
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
	bqos_en = QOS_STATIC;
}

//Invoked when QoS Dynamic is clicked
void MainWindow::on_radioButtonBQoSDynamic_clicked(bool checked)
{
	if(!checked || (bqos_en == QOS_DYNAMIC)) {
		printf("return Basic QoS Dynamic function\n");
		return;
	}

	// set new state
	videoCtrl = VIDEO_CTRL_OFF;

	// stop video pipeline
	vlib_pipeline_stop();

	// update UI
	ui->groupBoxVideoSource->setEnabled(false);
	ui->groupBoxFilterType->setEnabled(false);
	ui->groupBoxFilterMode->setEnabled(false);
	ui->groupBoxATG->setEnabled(false);
	ui->groupBoxBQoS->setEnabled(false);
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));
	qws->setBackground(QBrush(QColor(0, 0, 0, 0)));

	//Set the Dynamic priority value to AFI QoS fields
	system("/bin/sh /media/card/bin/qos_on.sh 2");
	// set new state
	videoCtrl = VIDEO_CTRL_ON;

	// configure and start video pipeline
	vlib_change_mode(config);

	// update UI
	ui->groupBoxVideoSource->setEnabled(true);
	ui->groupBoxFilterType->setEnabled(true);
	ui->groupBoxFilterMode->setEnabled(true);
	ui->groupBoxATG->setEnabled(true);
	ui->groupBoxBQoS->setEnabled(true);

	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
	bqos_en = QOS_DYNAMIC;
}

//Invoked if video source is changed
void MainWindow::on_comboBoxAQoS_P_currentIndexChanged(int index)
{
	switch (index) {
		case 0:
			system("/bin/sh /media/card/bin/aqos_en.sh 1 1");
			break;
		case 1:
			system("/bin/sh /media/card/bin/aqos_en.sh 1 2");
			break;
		case 2:
			system("/bin/sh /media/card/bin/aqos_en.sh 1 3");
			break;
		case 3:
			system("/bin/sh /media/card/bin/aqos_en.sh 1 4");
			break;
		case 4:
			system("/bin/sh /media/card/bin/aqos_en.sh 1 5");
			break;
		case 5:
			system("/bin/sh /media/card/bin/aqos_en.sh 1 6");
			break;
		case 6:
			system("/bin/sh /media/card/bin/aqos_en.sh 1 7");
			break;
		case 7:
			system("/bin/sh /media/card/bin/aqos_en.sh 1 8");
			break;
		default:
			printf("unknown index %d", index);
			break;
	}
	peak_index = index;
}

#else
static void *autoloop_fptr(void *ptr)
{
	unsigned int i, j;
	int ret;
	vlib_config config;
	int pr_enable = *((int *) ptr);

	while (1) {
		for (i = 0; i < VIDEO_SRC_CNT; i++) {
			if (vlib_video_src_get_enabled((video_src) i))
				config.src = (video_src) i;
			else
				continue;

			config.type = (filter_type) 0;
			config.mode = FILTER_MODE_OFF;
			ret = vlib_change_mode(config);
			if (ret)
				continue;

			sleep(AUTO_MODE_SLEEP_TIME);

			for (j = 0; j < FILTER_TYPE_CNT; j++) {
				if (filter_type_is_static((filter_type) j) || pr_enable)
					config.type = (filter_type) j;
				else
					continue;

				config.mode = FILTER_MODE_HW;
				vlib_change_mode(config);
				sleep(AUTO_MODE_SLEEP_TIME);
			}
		}
	}
	return NULL;
};

//Invoked when video controls Auto is clicked
void MainWindow::on_radioButtonVideoControlsAuto_clicked(bool checked)
{
	if (!checked || videoCtrl == VIDEO_CTRL_AUTO)
		return;

	// set new state
	videoCtrl = VIDEO_CTRL_AUTO;

	// update UI
	ui->groupBoxVideoSource->setEnabled(false);
#ifndef QOS_PATCH
	ui->groupBoxTestPattern->setEnabled(false);
#endif
	ui->groupBoxFilterType->setEnabled(false);
	ui->groupBoxFilterMode->setEnabled(false);
	ui->groupBoxSobelControls->setEnabled(false);
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(PIXMAP_INDEX_ZYNQ)));
	qws->setBackground(QBrush(QColor(0, 0, 0, 0)));

	// create new thread that cycles through selected options
	pthread_create(&autoloop, NULL, autoloop_fptr, (void *) &pr_enable);
}
#endif

//Invoked if video source is changed
void MainWindow::on_comboBoxVideoSource_currentIndexChanged(int index)
{
	video_src src = config.src;
	config.src = vlib_video_src_from_index(index);

	// configure and start video pipeline
	int ret = vlib_change_mode(config);
	if (ret == VLIB_ERROR) {
		printf("Video Input Warning\n");

		config.src = src;
		ui->comboBoxVideoSource->blockSignals(true);
		ui->comboBoxVideoSource->setCurrentIndex(vlib_video_src_get_index(config.src));
		ui->comboBoxVideoSource->blockSignals(false);

		// switch to maximized mode to show message
		if(ui->pushButtonMinMax->text().compare(MIN_TEXT) != 0)
			on_pushButtonMinMax_clicked();

		// display pop-up message box
		QString msgBoxHeader = "Warning";
		QString warnContent = "Video input not supported.\n"
							  "Check if source is powered and connected.\n"
							  "Check if input resolution and stride are supported.\n"
							  "Continue with previous mode.";
		QMessageBox mb(msgBoxHeader, warnContent,
					   QMessageBox::Warning,
					   QMessageBox::Default,
					   QMessageBox::Ok,
					   QMessageBox::Escape);
		mb.setGeometry(500,110,100,100);
		mb.exec();

		return;
	}
#ifndef QOS_PATCH
	// update UI
	if (config.src == VIDEO_SRC_TPG)
		ui->groupBoxTestPattern->setEnabled(true);
	else
		ui->groupBoxTestPattern->setEnabled(false);
#endif
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
}
#ifndef QOS_PATCH
//Invoked if test pattern is changed
void MainWindow::on_comboBoxTestPattern_currentIndexChanged(int index)
{
	// set index+1 since passthrough pattern is omitted
	vlib_tpg_set_pattern(index+1);
}
#endif
//Invoked if filter type is changed
void MainWindow::on_comboBoxFilterType_currentIndexChanged(int index)
{
	filter_type type = config.type;
	config.type = filter_type_from_index(index);

	// don't reconfigure pipeline if filter mode is off
	if (config.mode == FILTER_MODE_OFF)
		return;

	// check if hw filter module is available
	if (config.mode == FILTER_MODE_HW) {
		// restore previous filter type
		if (pr_enable && filter_type_pr_buf(config.type) == NULL) {
			printf("HW module for filter '%s' not available\n",
				   filter_type_display_text(config.type));

			config.type = type;
			ui->comboBoxFilterType->blockSignals(true);
			ui->comboBoxFilterType->setCurrentIndex(filter_type_get_index(config.type));
			ui->comboBoxFilterType->blockSignals(false);

			// switch to maximized mode to show message
			if(ui->pushButtonMinMax->text().compare(MIN_TEXT) != 0)
				on_pushButtonMinMax_clicked();

			// display pop-up message box
			QString msgBoxHeader = "Warning";
			QString warnContent = "No hardware filter module found for current selection.\n"
								  "Continue with previous mode.";
			QMessageBox mb(msgBoxHeader, warnContent,
						   QMessageBox::Warning,
						   QMessageBox::Default,
						   QMessageBox::Ok,
						   QMessageBox::Escape);
			mb.setGeometry(800,110,100,100);
			mb.exec();

			return;
		}
	}
#ifndef QOS_PATCH
	// enable sobel controls if sobel filter is selected
	if (config.type == FILTER_TYPE_SOBEL)
		ui->groupBoxSobelControls->setEnabled(true);
	else
		ui->groupBoxSobelControls->setEnabled(false);
#endif
	// configure and start video pipeline
	vlib_change_mode(config);
}

//Invoked if filter mode is off
void MainWindow::on_radioButtonFilterModeOff_clicked(bool checked)
{
	if (!checked || config.mode == FILTER_MODE_OFF)
		return;

	// set new mode
	config.mode = FILTER_MODE_OFF;

	// configure and start video pipeline
	vlib_change_mode(config);

#ifndef QOS_PATCH
	// update UI
	ui->groupBoxSobelControls->setEnabled(false);
#endif
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
}

#ifndef QOS_PATCH
//Invoked if filter mode is sw
void MainWindow::on_radioButtonFilterModeSw_clicked(bool checked)
{
	if (!checked || config.mode == FILTER_MODE_SW)
		return;

	// set new mode
	config.mode = FILTER_MODE_SW;

	// configure and start video pipeline
	vlib_change_mode(config);
	if (config.type == FILTER_TYPE_SOBEL)
		ui->groupBoxSobelControls->setEnabled(true);

	// update UI
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
}
#endif


//Invoked if filter mode is hw
void MainWindow::on_radioButtonFilterModeHw_clicked(bool checked)
{
	if(!checked || config.mode == FILTER_MODE_HW)
		return;

	// set new mode
	filter_mode mode = config.mode;
	config.mode = FILTER_MODE_HW;

	// restore previous filter type
	if (pr_enable && filter_type_pr_buf(config.type) == NULL) {
		printf("HW module for filter '%s' not available\n",
			   filter_type_display_text(config.type));

		config.mode = mode;
	#ifndef QOS_PATCH
		if (config.mode == FILTER_MODE_SW)
			ui->radioButtonFilterModeSw->setChecked(true);
	#endif
		if (config.mode == FILTER_MODE_OFF)
			ui->radioButtonFilterModeOff->setChecked(true);

		// switch to maximized mode to show message
		if(ui->pushButtonMinMax->text().compare(MIN_TEXT) != 0)
			on_pushButtonMinMax_clicked();

		// display pop-up message box
		QString msgBoxHeader = "Warning";
		QString warnContent = "No hardware filter module found for current selection";
		QMessageBox mb(msgBoxHeader, warnContent,
					   QMessageBox::Warning,
					   QMessageBox::Default,
					   QMessageBox::Ok,
					   QMessageBox::Escape);
		mb.setGeometry(800,110,100,100);
		mb.exec();

		return;
	}

	// configure and start video pipeline
	vlib_change_mode(config);
#ifndef QOS_PATCH
	if (config.type == FILTER_TYPE_SOBEL)
		ui->groupBoxSobelControls->setEnabled(true);
#endif
	// update UI
	ui->labelDataFlowDisplay->setPixmap(QPixmap(pixmapVec.at(
			config.src * PIXMAP_OFFSET_EXT + config.mode)));
}

//called when the timer expires every 500 msec
void MainWindow::CheckCursorActivity()
{
	QPoint cursorCoords = this->mapFromGlobal(QCursor::pos());

	//Reset the cursor position if out of sync ie if user try to move the
	//mouse below the application display area , it just a hack to keep cursor always
	// in a viewable area.
	if(isAppStateMaximized && cursorCoords.y() >= iWindowHeightInMaxMode-10)
		cursor->setPos(cursorCoords.x(), iWindowHeightInMaxMode-10);

	if(!isAppStateMaximized && cursorCoords.y() >= iWindowHeightInMinMode-10)
		cursor->setPos(cursorCoords.x(), iWindowHeightInMinMode-10);

	//Update the current cursor position.
	this->setCursor(*cursor);
	cursorPos = cursorCoords;
}
#ifndef QOS_PATCH
//Invokes when transparency slider is moved.
void MainWindow::on_sliderGuiTransparency_valueChanged(int ival)
{
	int itransparencyVal=ival;

	ui->labelGuiTransparency->setText(QString::number(itransparencyVal));
	// Convert the GUI alpha range (0-50) to range (0-150)
	itransparencyVal = ival * TRANSPARENCY_FACTOR;
	vlib_drm_set_layer0_transparency(itransparencyVal);
}
#endif

//Invoked when Mainwindow is minimized or maximized
void MainWindow::on_pushButtonMinMax_clicked()
{
	int iscreenHeight=vlib_get_active_height();

	if((ui->pushButtonMinMax->text().compare(MIN_TEXT))==0) {
		//If current app state is to be minimized .
		vlib_drm_set_layer0_position (LAYER0_X_POS,iscreenHeight-iWindowHeightInMinMode);
		//Assuming X pixels is height of window in minimized mode.
		ui->pushButtonMinMax->setText(MAX_TEXT);
		isAppStateMaximized=false;
	} else {
		//currently application was maximized
		//Assuming X pixels is height of window in maximized mode.
		vlib_drm_set_layer0_position (LAYER0_X_POS,iscreenHeight-iWindowHeightInMaxMode);
		ui->pushButtonMinMax->setText(MIN_TEXT);
		isAppStateMaximized=true;
	}
}

//For handling window close event .
void MainWindow::closeEvent(QCloseEvent *event)
{
	/* Stop the video pipeline */
	vlib_pipeline_stop();
	vlib_drm_set_layer0_position(LAYER0_X_POS,LAYER0_Y_POS);
#ifndef QOS_PATCH
	vlib_drm_set_layer0_transparency(LAYER0_TRANSPARENCY);
#endif
	vlib_drm_uninit();
	vlib_uninit();
	if (apm_enable)
		perf_monitor_deinit();
	(void) event;
}

//Invoked on every mouse move.Monitor cursor position , If cursor reaches near any non-viewable
//area it is moved back to viewable area
void MainWindow::mouseMoveEvent(__attribute__((unused))QMouseEvent *event)
{
	QPoint cursorCoords;
	/* Get central widget cursor position coordinates */
	cursorCoords = this->mapFromGlobal(QCursor::pos());

	//Check if QT application is in maximized state
	if(isAppStateMaximized) {
		//If cursor position goes below the viewable area
		// bring it back.
		if(cursorCoords.y() >=iWindowHeightInMaxMode-10)
			cursor->setPos(cursorCoords.x(),iWindowHeightInMaxMode-10);
	} else {
		//If cursor position goes below the viewable area
		// bring it back.
		if(cursorCoords.y() >= iWindowHeightInMinMode-10)
			cursor->setPos(cursorCoords.x(),iWindowHeightInMinMode-10);
	}

	//Update the cursor position.
	this->setCursor(*cursor);
}

#ifndef QOS_PATCH
void MainWindow::on_checkBoxSobelControlsInvert_clicked(bool checked)
{
	if(ui->radioButtonFilterModeSw->isChecked() || ui->radioButtonFilterModeHw->isChecked())
		v4l2_sobel_invert(checked);
}

void MainWindow::on_sliderSobelControlsThreshold_valueChanged(int val)
{
	if(ui->radioButtonFilterModeSw->isChecked() || ui->radioButtonFilterModeHw->isChecked()) {
		v4l2_sobel_thresh(val, HLS_SOBEL_LOW_THRESH_VAL);
		ui->labelSobelControlsThreshold->setText(QString::number(val));
	}
}
#endif
