/*****************************************************************************
 *
 * confaudmp2mencoderdialog.cpp -- Input the MP2 audio codec parameters.
 *
 * Copyright (C) 2010 Starbuck <starbuck@labdv.com>
 *
 *****************************************************************************/

#include "../video/video_functions.h"

#include "confaudmp2mencoderdialog.h"
#include "../encoder/encoder.h"
#include "macros.h"
#include <QtGui>

ConfAudMp2MEncoderDialog::ConfAudMp2MEncoderDialog(encoder_audio_settings_t *settings, 
	audio_t *track, QWidget *parent)
	: QDialog(parent)
{
	callerSettings = settings;
	audioSource = track;

	// Local copy allows to cancel changes
	encSettings = new encoder_audio_settings_t( *settings );

	setMinimumSize( 280, 360 );
	setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

	verticalLayout = new QVBoxLayout(this);

	// Global buttons
	buttonBox = new QDialogButtonBox(this);

	buttonBox->setOrientation(Qt::Horizontal);
	buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);

	// Build all tabs
	tabWidget = new QTabWidget(this);
	tabWidget->setMovable(false);

	mainTab = new QWidget();

	tabWidget->addTab(mainTab, QString());

	verticalLayout->addWidget(tabWidget);
	verticalLayout->addWidget(buttonBox);

	tabWidget->setCurrentIndex(0);

	// Main tab 
	mainTabVLayout = new QVBoxLayout(mainTab);
	mainTabVLayout->setSpacing(12);

	// - Bitrate
	bitrateGroupBox = new QGroupBox(mainTab);
	bitrateHLayout = new QHBoxLayout(bitrateGroupBox);
	bitrateLabel = new QLabel(bitrateGroupBox);
	bitrateLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
	bitrateComboBox = new QComboBox(bitrateGroupBox);
	bitrateHSpacer = new QSpacerItem(40, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);
	maxvbrLabel = new QLabel(bitrateGroupBox);
	maxvbrComboBox = new QComboBox(bitrateGroupBox);
	maxvbrLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

	bitrateHLayout->addWidget(bitrateLabel);
	bitrateHLayout->addWidget(bitrateComboBox);
	bitrateHLayout->addItem(bitrateHSpacer);
	bitrateHLayout->addWidget(maxvbrLabel);
	bitrateHLayout->addWidget(maxvbrComboBox);

	mainTabVLayout->addWidget(bitrateGroupBox);

	// - Bitrate allocation
	br_allocGroupBox = new QGroupBox(mainTab);
	br_allocVLayout = new QVBoxLayout(br_allocGroupBox);
	br_allocComboBox = new QComboBox(br_allocGroupBox);
	
	br_allocVLayout->addWidget(br_allocComboBox);

	mainTabVLayout->addWidget(br_allocGroupBox);

	// -- VBR range
	vbr_rangeHLayout = new QHBoxLayout();
	vbr_rangeLabel = new QLabel(br_allocGroupBox);
	vbr_rangeSlider = new QSlider(br_allocGroupBox);
	vbr_rangeLineEdit = new QLineEdit(br_allocGroupBox);

	vbr_rangeSlider->setOrientation(Qt::Horizontal);
	vbr_rangeSlider->setInvertedAppearance(false);
	vbr_rangeSlider->setTickPosition(QSlider::NoTicks);

	vbr_rangeLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
	vbr_rangeSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
	vbr_rangeLineEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
	vbr_rangeLineEdit->setMaxLength(4);
	vbr_rangeLineEdit->setMaximumWidth(40);

	vbr_rangeHLayout->addWidget(vbr_rangeLabel);
	vbr_rangeHLayout->addWidget(vbr_rangeSlider);
	vbr_rangeHLayout->addWidget(vbr_rangeLineEdit);

	br_allocVLayout->addLayout(vbr_rangeHLayout);

	// - Sampling rate
	srateGroupBox = new QGroupBox(mainTab);
	srateHLayout = new QHBoxLayout(srateGroupBox);
	srateComboBox = new QComboBox(srateGroupBox);
	srateHSpacer = new QSpacerItem(40, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);

	srateHLayout->addWidget(srateComboBox);
	srateHLayout->addItem(srateHSpacer);

	mainTabVLayout->addWidget(srateGroupBox);

	// - Channel mode and psychoacoustic model
	modeGroupBox = new QGroupBox(mainTab);
	modeHLayout = new QHBoxLayout(modeGroupBox);
	stereoComboBox = new QComboBox(modeGroupBox);
	psyComboBox = new QComboBox(modeGroupBox);

	modeHLayout->addWidget(stereoComboBox);
	modeHLayout->addWidget(psyComboBox);

	mainTabVLayout->addWidget(modeGroupBox);

	// - Preset
	presetGroupBox = new QGroupBox(mainTab);
	presetVLayout = new QVBoxLayout(presetGroupBox);
	presetDvdCheckBox = new QCheckBox(presetGroupBox);
	presetSvcdCheckBox = new QCheckBox(presetGroupBox);
	presetVcdCheckBox = new QCheckBox(presetGroupBox);
	
	presetVLayout->addWidget(presetDvdCheckBox);
	presetVLayout->addWidget(presetSvcdCheckBox);
	presetVLayout->addWidget(presetVcdCheckBox);

	mainTabVLayout->addWidget(presetGroupBox);

	// - Spacer
	verticalSpacer = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);

	mainTabVLayout->addItem(verticalSpacer);

	// - Default settings
	defaultHLayout = new QHBoxLayout();
	defaultPushButton = new QPushButton(mainTab);
	defaultHSpacer = new QSpacerItem(40, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);

	defaultHLayout->addWidget(defaultPushButton);
	defaultHLayout->addItem(defaultHSpacer);

	mainTabVLayout->addLayout(defaultHLayout);

	// Captions
	setWindowTitle( tr("MPEG-1 Layer II audio encoder") );

	tabWidget->setTabText(tabWidget->indexOf(mainTab), tr("Audio settings") );

	bitrateGroupBox->setTitle( tr(" Bitrate ( kbps ) ") );
	bitrateLabel->setText( tr("Minimum:") );
	maxvbrLabel->setText( tr("Maximum:") );

	br_allocGroupBox->setTitle( tr(" Bitrate allocation ") );
	vbr_rangeLabel->setText( tr("- VBR range") );

	srateGroupBox->setTitle( tr(" Sampling rate ") );
	modeGroupBox->setTitle( tr(" Stereo mode - Psychoacoustic model ") );

	presetGroupBox->setTitle( tr(" Standard MP2 audio presets ") );
	presetDvdCheckBox->setText( tr("DVD") );
	presetSvcdCheckBox->setText( tr("SVCD") );
	presetVcdCheckBox->setText( tr("VideoCD") );
	
	defaultPushButton->setText( tr("Default settings") );

	// Tool tips and What's this
	setToolTip();
	setWhatsThis();

	setAttribute(Qt::WA_AlwaysShowToolTips);

	vbr_rangeSlider->setRange( -50, 50 );
	vbr_rangeValidator = new QIntValidator( -50, 50, this );
	vbr_rangeLineEdit->setValidator( vbr_rangeValidator );

	populateBitrate();
	populateBrAllocation();
	populateSampling();
	populateStereo();
	populatePsy();

	// Signals which don't change settings
	connect(vbr_rangeLineEdit, SIGNAL(textChanged(QString)), 
		this, SLOT(vbr_rangeLineEditChanged(QString)));
	connect(vbr_rangeSlider, SIGNAL(valueChanged(int)), 
		this, SLOT(vbr_rangeSliderChanged(int)));

	// Update controls from current settings before connecting signals
	updateControls();

	// Now connect other signals (which controls are up-to-date)
	connect(bitrateComboBox, SIGNAL(activated(int)), 
		this, SLOT(selectBitrate(int)));
	connect(maxvbrComboBox, SIGNAL(activated(int)), 
		this, SLOT(selectVbrMax(int)));

	connect(br_allocComboBox, SIGNAL(activated(int)), 
		this, SLOT(selectBrAllocation(int)));

	connect(srateComboBox, SIGNAL(activated(int)), 
		this, SLOT(selectSampling(int)));

	connect(stereoComboBox, SIGNAL(activated(int)), 
		this, SLOT(selectStereo(int)));

	connect(psyComboBox, SIGNAL(activated(int)), 
		this, SLOT(selectPsy(int)));

	connect(presetDvdCheckBox, SIGNAL(clicked()), 
		this, SLOT(selectPresetDvd()));
	connect(presetSvcdCheckBox, SIGNAL(clicked()), 
		this, SLOT(selectPresetSvcd()));
	connect(presetVcdCheckBox, SIGNAL(clicked()), 
		this, SLOT(selectPresetVcd()));

	connect(defaultPushButton, SIGNAL(clicked()), 
		this, SLOT(defaultPushButtonClicked()));

	// Global buttons
	connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
	connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
}

void ConfAudMp2MEncoderDialog::accept()
{
	*callerSettings = *encSettings;

	QDialog::accept();
}

void ConfAudMp2MEncoderDialog::updateControls()
{
	int idx1, idx2;
	bool vcd, svcd, dvd;

	vbr_rangeSlider->setValue( encSettings->mp2.vbr );
	vbr_rangeLineEdit->setText( QString::number(encSettings->mp2.vbr) );

	if ( encSettings->mp2.vbr != 0 )
	{
		br_allocComboBox->setCurrentIndex( 1 ); // VBR
		
		bitrateLabel->setVisible(true);
		maxvbrLabel->setVisible(true);
		maxvbrComboBox->setVisible(true);
		vbr_rangeLabel->setEnabled(true);
		vbr_rangeSlider->setEnabled(true);
		vbr_rangeLineEdit->setEnabled(true);

		bitrateComboBox->setToolTip( boxToolTip("br", tr("None"), "<112-384>",
							tr("Minimum bitrate allowed per frame in kbit/s.")) );

	}
	else
	{
		br_allocComboBox->setCurrentIndex( 0 ); // CBR

		bitrateLabel->setVisible(false);
		maxvbrLabel->setVisible(false);
		maxvbrComboBox->setVisible(false);
		vbr_rangeLabel->setEnabled(false);
		vbr_rangeSlider->setEnabled(false);
		vbr_rangeLineEdit->setEnabled(false);

		bitrateComboBox->setToolTip( boxToolTip("br", tr("None"), "<32-384>",
							tr("Sets the constant bitrate in kbit/s. "
"Birates defined in ISO/IEC 11172-3: 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 and 384 kbit/s. ")) );
	}

	idx1 = bitrateComboBox->findData( encSettings->mp2.bitrate );

	if ( idx1 == -1 ) // should not happened
	{
		bitrateComboBox->setCurrentIndex( 0 );
		encSettings->mp2.bitrate = bitrateComboBox->itemData( 0 ).toInt();
	}
	else
	{
		bitrateComboBox->setCurrentIndex( idx1 );
	}

	idx1 = maxvbrComboBox->findData( encSettings->mp2.maxvbr );

	if ( idx1 == -1 ) // should not happened
	{
		maxvbrComboBox->setCurrentIndex( 0 );
		encSettings->mp2.maxvbr = maxvbrComboBox->itemData( 0 ).toInt();
	}
	else
	{
		maxvbrComboBox->setCurrentIndex( idx1 );
	}

	idx1 = srateComboBox->findData( encSettings->mp2.srate );

	if ( idx1 == -1 ) // should not happened
	{
		srateComboBox->setCurrentIndex( 0 );
		encSettings->mp2.srate = srateComboBox->itemData( 0 ).toInt();
	}
	else
	{
		srateComboBox->setCurrentIndex( idx1 );
	}

	idx1 = stereoComboBox->findData( encSettings->mp2.stereo );

	if ( idx1 == -1 ) // should not happened
	{
		stereoComboBox->setCurrentIndex( 0 );
		encSettings->mp2.stereo = stereoComboBox->itemData( 0 ).toInt();
	}
	else
	{
		stereoComboBox->setCurrentIndex( idx1 );
	}

	idx1 = psyComboBox->findData( encSettings->mp2.psy );

	if ( idx1 == -1 ) // should not happened
	{
		idx2 = psyComboBox->findData( 2 ); 
	
		if ( idx2 == -1 ) // should not happened
		{
			psyComboBox->setCurrentIndex( 0 ); // desperate!
			encSettings->mp2.psy = psyComboBox->itemData( 0 ).toInt();
		}
		else
		{
			psyComboBox->setCurrentIndex( idx2 ); // default
			encSettings->mp2.psy = psyComboBox->itemData( idx2 ).toInt();
		}
	}
	else
	{
		psyComboBox->setCurrentIndex( idx1 );
	}

	vcd = encSettings->mp2.bitrate == 224
			&& encSettings->mp2.vbr == 0
			&& encSettings->mp2.srate == 44100;

	svcd = encSettings->mp2.bitrate <= 384
			&& encSettings->mp2.srate == 44100;

	dvd = encSettings->mp2.bitrate <= 384
			&& encSettings->mp2.srate == 48000;

	presetVcdCheckBox->setChecked(vcd);
	presetSvcdCheckBox->setChecked(svcd);
	presetDvdCheckBox->setChecked(dvd);
}

void ConfAudMp2MEncoderDialog::populateBitrate()
{
	bitrateComboBox->clear();

	QList<int> iso, isoMonoOnly, isoStereoOnly;

	iso << 32 << 48 << 56 << 64 << 80 << 96 << 112 << 128 << 160 << 192 << 224 << 256 << 320 << 384;
	isoMonoOnly << 32 << 48 << 56 << 80;
	isoStereoOnly << 224 << 256 << 320 << 384;

	QListIterator<int> isoRates(iso);
	while ( isoRates.hasNext() )
	{
		int rate = isoRates.next();

		if ( encSettings->mp2.vbr != 0 && rate >= 112 )
		{
			bitrateComboBox->addItem( tr("%1 kbits/s").arg(rate), rate );
		}
		else if ( encSettings->mp2.vbr == 0 )
		{
			if ( encSettings->mp2.stereo == "mono" )
			{
				if ( !isoStereoOnly.contains(rate) ) bitrateComboBox->addItem( tr("%1 kbits/s").arg(rate), rate );
			}
			else if ( !isoMonoOnly.contains(rate) )
			{
				bitrateComboBox->addItem( tr("%1 kbits/s").arg(rate), rate );
			}
		}
	}

	int index = bitrateComboBox->findData( encSettings->mp2.bitrate );

	if ( index == -1 )
	{
		bitrateComboBox->setCurrentIndex( 0 );
		encSettings->mp2.bitrate = bitrateComboBox->itemData( 0 ).toInt();
	}
	else
	{
		bitrateComboBox->setCurrentIndex( index );
	}

	populateVbrMax(encSettings->mp2.bitrate);
}

void ConfAudMp2MEncoderDialog::populateVbrMax(const int br)
{
	maxvbrComboBox->clear();

	QList<int> iso;

	iso << 32 << 48 << 56 << 64 << 80 << 96 << 112 << 128 << 160 << 192 << 224 << 256 << 320 << 384;

	QListIterator<int> isoRates(iso);
	while ( isoRates.hasNext() )
	{
		int rate = isoRates.next();

		if ( rate > br ) maxvbrComboBox->addItem( tr("%1 kbits/s").arg(rate), rate );
	}

	int index = maxvbrComboBox->findData( encSettings->mp2.maxvbr );

	if ( index == -1 )
	{
		maxvbrComboBox->setCurrentIndex( maxvbrComboBox->count() - 1 );
		encSettings->mp2.maxvbr = maxvbrComboBox->itemData( maxvbrComboBox->currentIndex() ).toInt();
	}
	else
	{
		maxvbrComboBox->setCurrentIndex( index );
	}
}

void ConfAudMp2MEncoderDialog::populateBrAllocation()
{
	br_allocComboBox->clear();

	br_allocComboBox->addItem( tr("CBR - Constant Bit Rate"), "cbr" );
	br_allocComboBox->addItem( tr("VBR - Variable Bit Rate"), "vbr" );

	if ( encSettings->mp2.vbr == 0 )
	{
		br_allocComboBox->setCurrentIndex( 0 ); // CBR
	}
	else
	{
		br_allocComboBox->setCurrentIndex( 1 ); // VBR
	}
}

void ConfAudMp2MEncoderDialog::populateSampling()
{
	srateComboBox->clear();

	QMap<int, QString> sampling;
	sampling.insert( 0, tr("(input rate)") );
	sampling.insert( 44100, tr("44,100 Hz") );
	sampling.insert( 48000, tr("48,000 Hz") );

	QMapIterator<int, QString> i(sampling);
	while ( i.hasNext() )
	{
		i.next();

		srateComboBox->addItem( i.value(), i.key() );
	}

	int index = srateComboBox->findData( encSettings->mp2.srate );

	if ( index == -1 ) // should not happened
	{
		srateComboBox->setCurrentIndex( 0 );
		encSettings->mp2.srate = srateComboBox->itemData( 0 ).toInt();
	}
	else
	{
		srateComboBox->setCurrentIndex( index );
	}
}

void ConfAudMp2MEncoderDialog::populateStereo()
{
	stereoComboBox->clear();

	QMap<QString, QString> stereo;
	stereo.insert( "unset", tr("Default: auto") );
	stereo.insert( "stereo", tr("Stereo") );
	stereo.insert( "jstereo", tr("Joint-Stereo") );
	stereo.insert( "dual", tr("Dual-Channel") );
	stereo.insert( "mono", tr("Mono") );

	QMapIterator<QString, QString> i(stereo);
	while ( i.hasNext() )
	{
		i.next();

		stereoComboBox->addItem( i.value(), i.key() );
	}

	int index = stereoComboBox->findData( encSettings->mp2.stereo );

	if ( index == -1 ) // should not happened
	{
		stereoComboBox->setCurrentIndex( 0 );
		encSettings->mp2.stereo = stereoComboBox->itemData( 0 ).toString();
	}
	else
	{
		stereoComboBox->setCurrentIndex( index );
	}
}

void ConfAudMp2MEncoderDialog::populatePsy()
{
	psyComboBox->clear();

	QMap<int, QString> psy;

	// Ref: http://www.twolame.org/doc/psycho.html
	psy.insert( -1, tr("PAM Model -1 (very fast)") );
	psy.insert( 0, tr("PAM Model 0 (fast)") );
	psy.insert( 1, tr("PAM Model 1 (ISO)") );
	psy.insert( 2, tr("PAM Model 2 (ISO, default)") );
	psy.insert( 3, tr("PAM Model 3 (new PAM1)") );
	psy.insert( 4, tr("PAM Model 4 (clean PAM2)") );

	QMapIterator<int, QString> i(psy);
	while ( i.hasNext() )
	{
		i.next();

		psyComboBox->addItem( i.value(), i.key() );
	}

	int idx1 = psyComboBox->findData( encSettings->mp2.psy );

	if ( idx1 == -1 ) // should not happened
	{
		int idx2 = psyComboBox->findData( 2 ); 
	
		if ( idx2 == -1 ) // should not happened
		{
			psyComboBox->setCurrentIndex( 0 ); // desperate!
			encSettings->mp2.psy = psyComboBox->itemData( 0 ).toInt();
		}
		else
		{
			psyComboBox->setCurrentIndex( idx2 ); // default
			encSettings->mp2.psy = psyComboBox->itemData( idx2 ).toInt();
		}
	}
	else
	{
		psyComboBox->setCurrentIndex( idx1 );
	}
}

void ConfAudMp2MEncoderDialog::selectBitrate(const int index)
{
	// Do nothing if combobox is empty or reset
	if (index < 0)
	{
		return;
	}

	encSettings->mp2.bitrate = bitrateComboBox->itemData( index ).toInt();

	populateVbrMax(encSettings->mp2.bitrate);

	updateControls();
}

void ConfAudMp2MEncoderDialog::selectVbrMax(const int index)
{
	// Do nothing if combobox is empty or reset
	if (index < 0)
	{
		return;
	}

	encSettings->mp2.maxvbr = maxvbrComboBox->itemData( index ).toInt();

	updateControls();
}

void ConfAudMp2MEncoderDialog::vbr_rangeLineEditChanged(const QString &value)
{
	encSettings->mp2.vbr = value.toInt();

	vbr_rangeSlider->setValue( encSettings->mp2.vbr );

	updateControls();
}

void ConfAudMp2MEncoderDialog::vbr_rangeSliderChanged(const int value)
{
	encSettings->mp2.vbr = value;

	vbr_rangeLineEdit->setText( QString::number(value) );
}

void ConfAudMp2MEncoderDialog::selectBrAllocation(const int index)
{
	// Do nothing if combobox is empty or reset
	if (index < 0)
	{
		return;
	}

	if ( br_allocComboBox->itemData( index ).toString() ==  "vbr" )
	{
		encSettings->mp2.vbr = 5;

	}
	else
	{
		encSettings->mp2.vbr = 0;
		encSettings->mp2.maxvbr = encSettings->mp2.bitrate;
	}

	populateBitrate();
	updateControls();
}

void ConfAudMp2MEncoderDialog::selectSampling(const int index)
{
	// Do nothing if combobox is empty or reset
	if (index < 0)
	{
		return;
	}

	encSettings->mp2.srate = srateComboBox->itemData( index ).toInt();

	updateControls();
}

void ConfAudMp2MEncoderDialog::selectStereo(const int index)
{
	// Do nothing if combobox is empty or reset
	if (index < 0)
	{
		return;
	}

	encSettings->mp2.stereo = stereoComboBox->itemData( index ).toInt();

	populateBitrate();
}

void ConfAudMp2MEncoderDialog::selectPsy(const int index)
{
	// Do nothing if empty or reset
	if (index < 0)
	{
		return;
	}

	encSettings->mp2.psy = psyComboBox->itemData( index ).toInt();
}

void ConfAudMp2MEncoderDialog::selectPresetDvd()
{
	encSettings->mp2.dvd();

	populateVbrMax(encSettings->mp2.bitrate);
	updateControls();
}

void ConfAudMp2MEncoderDialog::selectPresetSvcd()
{
	encSettings->mp2.svcd();

	populateVbrMax(encSettings->mp2.bitrate);
	updateControls();
}

void ConfAudMp2MEncoderDialog::selectPresetVcd()
{
	encSettings->mp2.vcd();

	populateVbrMax(encSettings->mp2.bitrate);
	updateControls();
}

void ConfAudMp2MEncoderDialog::defaultPushButtonClicked()
{
	encSettings->mp2.clear();

	updateControls();
}

void ConfAudMp2MEncoderDialog::setToolTip()
{
	br_allocGroupBox->setToolTip( simpleToolTip( tr("TwoLame/TooLame MP2 encoders may produce "
"crappy VBR audio, if so, choose CBR allocation, it usually fixes this." )) );

	maxvbrComboBox->setToolTip( boxToolTip("maxvbr", tr("None"), "<br-384>",
						tr("Maximum bitrate allowed per frame in kbit/s.")) );

	vbr_rangeLabel->setToolTip( boxToolTip("vbr", tr("0"), "<-50-50>",
						tr("Variability range; if negative the encoder shifts the average bitrate "
"towards the lower limit, if positive towards the higher. When set to 0 CBR is used (default).")) );
	vbr_rangeSlider->setToolTip( vbr_rangeLabel->toolTip() );
	vbr_rangeLineEdit->setToolTip( vbr_rangeLabel->toolTip() );

	stereoComboBox->setToolTip( boxToolTip("mode", "mono for 1-channel audio, stereo otherwise", "<stereo | jstereo | mono | dual>",
						tr("Default: mono for 1-channel audio, stereo otherwise.")) );
	
	psyComboBox->setToolTip( boxToolTip("psy", "2", "<-1-4>",
						tr("Psychoacoustic model (default: PAM2)."
#ifdef WIN32
" See WhatsThis...")) );
#else						
" Ref: http://www.twolame.org/doc/psycho.html")) );
#endif
}

void ConfAudMp2MEncoderDialog::setWhatsThis()
{
#ifdef WIN32
#pragma message (Reminder "why not using QTextDocument with insertHtml(), insertList() and insertTable() - " __FUNCTION__)
#endif

	psyComboBox->setWhatsThis( tr("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html>\n"
"<head>\n"
"<meta name=\"qrichtext\" content=\"1\" />\n"
"<style type=\"text/css\">\n"
"p, li {\n"
"	white-space: pre-wrap;\n"
"}\n"
".centercell {\n"
"	text-align: center;\n"
"}\n"
".mybold {\n"
"	font-weight: 600;\n"
"}\n"
"</style>\n"
"</head>\n"
"<body style=\" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n"
"<p><span class=\"mybold\"> Psychoacoustic Models </span></p>\n"
"<p>In MPEG audio encoding, a psychoacoustic model (PAM) is used to determine which are the sonically important"
" parts of the waveform that is being encoded. The PAM looks for loud sounds which may mask soft sounds, noise"
" which may affect the level of sounds nearby, sounds which are too soft for us to hear and should be ignored and"
" so on. The information from the PAM is used to determine which parts of the spectrum should get more bits and"
" thus be encoded at greater quality - and which parts are inaudible/unimportant and should thus get fewer bits.</p>\n"
"<p>In MPEG Audio LayerII encoding, 1152 sound samples are read in - this constitutes a frame. For each frame the"
" PAM outputs just 32 values (The values are the Signal to Masking Ratio [SMR] in that subband). This is important!"
" There are only 32 values to determine how to alloctate bits for 1152 samples - this is a pretty coarse technique.</p>\n"
"<p>The different PAMs listed below use different techniques to decide on these 32 values. Some models are better"
" than others - meaning that the 32 values chosen are pretty good at spreading the bits where they should go. Even"
" with a really bad PAM (e.g. Model -1) you can still get satisfactory results a lot of the time. All of these"
" models have strengths and weaknesses. The model you end up using will be the one that produces the best sound for"
" your ears, for your audio.</p>\n"
"<p>\n"
"<p><hr><span class=\"mybold\">Psychoacoustic Model -1 </span>\n"
" doesn't actually look at the samples being encoded to decide upon the output values. There is simply a set"
" of 32 default values which are used, regardless of input.<br><br>\n"
"<b>Pros:</b> Faaaast. Low complexity. Surprisingly good. \"Surprising\" in that the other PAMs go"
" to the effort of calculating FFTs and subbands and masking, and this one does absolutely nothing. Zip. Nada."
" Diddly Squat. This model might be the best example of why it is hard to make a good model - if having no"
" computations sounds OK, how do you improve on it?<br><br>\n"
"<b>Cons:</b> Absolutely no attempt to consider any of the masking effects that would help the audio sound better.</p>\n"
"<p><hr><span class=\"mybold\">Psychoacoustic Model 0 </span>\n"
" looks at the sizes of the scalefactors for the audio and combines it with the Absolute Threshold"
" of Hearing (ATH) to make the 32 SMR values.<br><br>\n"
"<b>Pros:</b> Faaast. Low complexity.<br><br>\n"
"<b>Cons:</b> This model has absolutely no mathematical basis and does not use any perceptual model of hearing."
" It simply juggles some of the numbers of the input sound to determine the values. Feel free to hack the daylights"
" out of this PAM - add multipliers, constants, log-tables anything. Tweak it until you begin to like the sound.</p>\n"
"<p><hr><span class=\"mybold\">Psychoacoustic Model 1 and 2 </span>\n"
" are from the ISO standard. Just because they are the standard, doesn't mean that they are any"
" good. Look at LAME which basically threw out the MP3 standard psycho models and made their own (GPSYCHO).<br><br>\n"
"<b>Pros:</b> A reference for future PAMs<br><br>\n"
"<b>Cons:</b> Terrible ISO code, buggy tables, poor documentation.</p>\n"
"<p><hr><span class=\"mybold\">Psychoacoustic Model 3 </span>\n"
" is a re-implementation of psychoacoustic model 1. ISO11172 was used as the guide for re-writing this PAM from"
" the ground up.<br><br>\n"
"<b>Pros:</b> No more obscure tables of values from the ISO code. Hopefully a good base to work upon for tweaking PAMs<br><br>\n"
"<b>Cons:</b> At the moment, doesn't really sound any better than PAM1.</p>\n"
"<p><hr><span class=\"mybold\">Psychoacoustic Model 4 </span>\n"
" is a cleaned up version of PAM2.<br><br>\n"
"<b>Pros:</b> Faster than PAM2. No more obscure tables of values from the ISO standard. Hopefully a good base to work from for improving the PAMs<br><br>\n"
"<b>Cons:</b> Still has the same \"warbling\"/\"Davros\" problems as PAM2.</p>\n"
"<p><hr>\n"
"Ref: <a href=\">http://www.twolame.org/doc/psycho.html\">http://www.twolame.org/doc/psycho.html</a> (Psychoacoustic Models in TwoLAME) </p>\n"
"</body>\n"
"</html>") );
}

QString ConfAudMp2MEncoderDialog::simpleToolTip( const QString &text )
{
	return tr( "<p>%1</p>" ).arg(Qt::escape(text));
}

QString ConfAudMp2MEncoderDialog::labelToolTip( const QString &defaults, const QString &details )
{
	QString strDefault( tr("Default: ") ); 

	return tr(	"<p><b>%1</b> %2</p>"
				"<p></p>"
				"<p>%3</p>" )
				.arg(Qt::escape(strDefault)).arg(Qt::escape(defaults))
				.arg(Qt::escape(details));
}

QString ConfAudMp2MEncoderDialog::editToolTip( const QString &name, const QString &range )
{
	return tr("<b>%1</b> %2").arg( Qt::escape(name) ).arg( Qt::escape(range) );
}

QString ConfAudMp2MEncoderDialog::boxToolTip( const QString &name, const QString &defaults, const QString &range, const QString &details )
{
	QString strDefault( tr("Default: ") ); 

	return tr(	"<p><b>%1</b> %2</p>"
				"<p></p>"
				"<p><b>%3</b> %4</p>"
				"<p></p>"
				"<p>%5</p>" )
				.arg(Qt::escape(name)).arg(Qt::escape(range))
				.arg(Qt::escape(strDefault)).arg(Qt::escape(defaults))
				.arg(Qt::escape(details));
}
