|
|
|
/*
|
|
|
|
* postfilter.cpp - wrapper for xine's postprocessing filters
|
|
|
|
*
|
|
|
|
* Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
|
|
|
|
* Copyright (C) 2003-2005 Miguel Freitas
|
|
|
|
*
|
|
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <kpushbutton.h>
|
|
|
|
#include <kseparator.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqwidget.h>
|
|
|
|
#include <tqobject.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <tqgroupbox.h>
|
|
|
|
#include <tqtextedit.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "postfilter.h"
|
|
|
|
|
|
|
|
PostFilter::PostFilter(const TQString& name, xine_t* engine, xine_audio_port_t* audioDriver,
|
|
|
|
xine_video_port_t* videoDriver, TQWidget *parent) : TQObject(parent), m_data(NULL), m_groupBox(NULL)
|
|
|
|
{
|
|
|
|
m_filterName = name;
|
|
|
|
kdDebug() << "PostFilter: Create Postprocessing Filter: " << m_filterName << endl;
|
|
|
|
|
|
|
|
m_xineEngine = engine;
|
|
|
|
|
|
|
|
m_xinePost = xine_post_init(m_xineEngine, m_filterName.ascii(), 0, &audioDriver, &videoDriver );
|
|
|
|
if(m_xinePost)
|
|
|
|
{
|
|
|
|
xine_post_in_t* inputAPI = NULL;
|
|
|
|
|
|
|
|
m_groupBox = new TQGroupBox(name, parent);
|
|
|
|
m_groupBox->setSizePolicy(TQSizePolicy (TQSizePolicy::Minimum, TQSizePolicy::Fixed));
|
|
|
|
TQGridLayout* grid = new TQGridLayout(m_groupBox, 2, 2);
|
|
|
|
grid->setMargin( 20 );
|
|
|
|
grid->setSpacing( 5 );
|
|
|
|
int row = 0;
|
|
|
|
|
|
|
|
if ((inputAPI = (xine_post_in_t*)xine_post_input(m_xinePost, const_cast<char*>("parameters"))))
|
|
|
|
{
|
|
|
|
m_xinePostAPI = (xine_post_api_t*)inputAPI->data;
|
|
|
|
m_xinePostDescr = m_xinePostAPI->get_param_descr();
|
|
|
|
m_xinePostParameter = m_xinePostDescr->parameter;
|
|
|
|
|
|
|
|
m_data = new char[m_xinePostDescr->struct_size];
|
|
|
|
m_xinePostAPI->get_parameters(m_xinePost, m_data);
|
|
|
|
|
|
|
|
TQLabel* descr;
|
|
|
|
|
|
|
|
while (m_xinePostParameter->type != POST_PARAM_TYPE_LAST)
|
|
|
|
{
|
|
|
|
kdDebug() << "PostFilter: Parameter: " << m_xinePostParameter->name << endl;
|
|
|
|
if (m_xinePostParameter->readonly) continue;
|
|
|
|
|
|
|
|
switch (m_xinePostParameter->type)
|
|
|
|
{
|
|
|
|
case POST_PARAM_TYPE_INT:
|
|
|
|
{
|
|
|
|
if (m_xinePostParameter->enum_values)
|
|
|
|
{
|
|
|
|
PostFilterParameterCombo* parameter = new
|
|
|
|
PostFilterParameterCombo(m_xinePostParameter->name, m_xinePostParameter->offset,
|
|
|
|
*(int*)(m_data+m_xinePostParameter->offset),
|
|
|
|
m_xinePostParameter->enum_values, m_groupBox );
|
|
|
|
connect(parameter, TQT_SIGNAL(signalIntValue(int, int)), this, TQT_SLOT(slotApplyIntValue(int, int)));
|
|
|
|
m_parameterList.append(parameter);
|
|
|
|
|
|
|
|
grid->addWidget(parameter->getWidget(), row, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PostFilterParameterInt* parameter = new
|
|
|
|
PostFilterParameterInt(m_xinePostParameter->name, m_xinePostParameter->offset,
|
|
|
|
*(int*)(m_data+m_xinePostParameter->offset),
|
|
|
|
(int)m_xinePostParameter->range_min, (int)m_xinePostParameter->range_max,
|
|
|
|
m_groupBox);
|
|
|
|
|
|
|
|
connect(parameter, TQT_SIGNAL( signalIntValue(int, int)), this, TQT_SLOT( slotApplyIntValue(int, int)));
|
|
|
|
m_parameterList.append(parameter);
|
|
|
|
|
|
|
|
grid->addWidget(parameter->getWidget(), row, 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case POST_PARAM_TYPE_DOUBLE:
|
|
|
|
{
|
|
|
|
PostFilterParameterDouble* parameter = new
|
|
|
|
PostFilterParameterDouble(m_xinePostParameter->name, m_xinePostParameter->offset,
|
|
|
|
*(double*)(m_data+m_xinePostParameter->offset),
|
|
|
|
(double)m_xinePostParameter->range_min, (double)m_xinePostParameter->range_max,
|
|
|
|
m_groupBox);
|
|
|
|
|
|
|
|
connect(parameter, TQT_SIGNAL(signalDoubleValue(int, double)), this, TQT_SLOT(slotApplyDoubleValue(int, double)));
|
|
|
|
m_parameterList.append(parameter);
|
|
|
|
|
|
|
|
grid->addWidget(parameter->getWidget(), row, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case POST_PARAM_TYPE_CHAR:
|
|
|
|
{
|
|
|
|
PostFilterParameterChar* parameter = new
|
|
|
|
PostFilterParameterChar(m_xinePostParameter->name, m_xinePostParameter->offset,
|
|
|
|
(char*)(m_data+m_xinePostParameter->offset), m_xinePostParameter->size,
|
|
|
|
m_groupBox);
|
|
|
|
|
|
|
|
connect( parameter, TQT_SIGNAL(signalCharValue(int, const TQString&)), this, TQT_SLOT(slotApplyCharValue(int, const TQString&)));
|
|
|
|
m_parameterList.append(parameter);
|
|
|
|
|
|
|
|
grid->addWidget(parameter->getWidget(), row, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case POST_PARAM_TYPE_STRING:
|
|
|
|
case POST_PARAM_TYPE_STRINGLIST: break; /* not implemented */
|
|
|
|
case POST_PARAM_TYPE_BOOL:
|
|
|
|
{
|
|
|
|
PostFilterParameterBool* parameter = new
|
|
|
|
PostFilterParameterBool(m_xinePostParameter->name, m_xinePostParameter->offset,
|
|
|
|
(bool) *(int*)(m_data+m_xinePostParameter->offset), m_groupBox);
|
|
|
|
|
|
|
|
connect(parameter, TQT_SIGNAL(signalIntValue(int, int)), this, TQT_SLOT(slotApplyIntValue(int, int)));
|
|
|
|
m_parameterList.append(parameter);
|
|
|
|
|
|
|
|
grid->addWidget(parameter->getWidget(), row, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
descr = new TQLabel(TQString::fromUtf8(m_xinePostParameter->description ), m_groupBox);
|
|
|
|
descr->setAlignment(TQLabel::WordBreak | TQLabel::AlignVCenter);
|
|
|
|
grid->addWidget(descr, row, 1);
|
|
|
|
row++;
|
|
|
|
m_xinePostParameter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
KSeparator* sep = new KSeparator(KSeparator::Horizontal, m_groupBox);
|
|
|
|
grid->addMultiCellWidget(sep, row, row, 0, 1);
|
|
|
|
row++;
|
|
|
|
KPushButton* deleteButton = new KPushButton(i18n("Delete Filter"), m_groupBox);
|
|
|
|
deleteButton->setSizePolicy (TQSizePolicy (TQSizePolicy::Minimum, TQSizePolicy::Fixed));
|
|
|
|
connect(deleteButton, TQT_SIGNAL(clicked()), this, TQT_SLOT( slotDeletePressed()));
|
|
|
|
grid->addWidget(deleteButton, row, 0);
|
|
|
|
|
|
|
|
if(inputAPI)
|
|
|
|
{
|
|
|
|
KPushButton* helpButton = new KPushButton(i18n("Help"), m_groupBox);
|
|
|
|
helpButton->setSizePolicy(TQSizePolicy (TQSizePolicy::Minimum, TQSizePolicy::Fixed));
|
|
|
|
connect(helpButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotHelpPressed()));
|
|
|
|
grid->addWidget(helpButton, row, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent)
|
|
|
|
m_groupBox->show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PostFilter::~PostFilter()
|
|
|
|
{
|
|
|
|
kdDebug() << "PostFilter: Delete Postprocessing Filter: " << m_filterName << endl;
|
|
|
|
if(m_xinePost)
|
|
|
|
{
|
|
|
|
delete m_groupBox;
|
|
|
|
delete [] m_data;
|
|
|
|
xine_post_dispose(m_xineEngine, m_xinePost);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PostFilter::slotApplyIntValue(int offset, int val)
|
|
|
|
{
|
|
|
|
kdDebug() << "PostFilter: " << m_filterName << " Apply integer value " << val << " on offset " << offset << endl;
|
|
|
|
*(int*)(m_data+offset) = val;
|
|
|
|
m_xinePostAPI->set_parameters(m_xinePost, m_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PostFilter::slotApplyDoubleValue(int offset, double val)
|
|
|
|
{
|
|
|
|
kdDebug() << "PostFilter: " << m_filterName << " Apply double value " << val << " on offset " << offset << endl;
|
|
|
|
*(double*)(m_data+offset) = val;
|
|
|
|
m_xinePostAPI->set_parameters(m_xinePost, m_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PostFilter::slotApplyCharValue(int offset, const TQString& val)
|
|
|
|
{
|
|
|
|
kdDebug() << "PostFilter: " << m_filterName << " Apply char value '" << val << "' on offset " << offset << endl;
|
|
|
|
sprintf((char *)(m_data+offset), "%s", val.latin1());
|
|
|
|
m_xinePostAPI->set_parameters(m_xinePost, m_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
xine_post_in_t* PostFilter::getInput() const
|
|
|
|
{
|
|
|
|
xine_post_in_t* input = NULL;
|
|
|
|
|
|
|
|
kdDebug() << "PostFilter: Get input" << endl;
|
|
|
|
if(m_xinePost)
|
|
|
|
{
|
|
|
|
/* look for known input ports */
|
|
|
|
input = xine_post_input(m_xinePost, const_cast<char*>("video"));
|
|
|
|
if( !input )
|
|
|
|
input = xine_post_input(m_xinePost, const_cast<char*>("video in") );
|
|
|
|
if( !input )
|
|
|
|
input = xine_post_input(m_xinePost, const_cast<char*>("audio"));
|
|
|
|
if( !input )
|
|
|
|
input = xine_post_input(m_xinePost, const_cast<char*>("audio in"));
|
|
|
|
}
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
xine_post_out_t* PostFilter::getOutput() const
|
|
|
|
{
|
|
|
|
xine_post_out_t* output = NULL;
|
|
|
|
|
|
|
|
kdDebug() << "PostFilter: Get output" << endl;
|
|
|
|
|
|
|
|
if(m_xinePost)
|
|
|
|
{
|
|
|
|
/* look for known output ports */
|
|
|
|
output = xine_post_output(m_xinePost, const_cast<char*>("video"));
|
|
|
|
if( !output )
|
|
|
|
output = xine_post_output(m_xinePost, const_cast<char*>("video out"));
|
|
|
|
if( !output )
|
|
|
|
output = xine_post_output(m_xinePost, const_cast<char*>("audio"));
|
|
|
|
if( !output )
|
|
|
|
output = xine_post_output(m_xinePost, const_cast<char*>("audio out"));
|
|
|
|
|
|
|
|
if(!output)
|
|
|
|
{
|
|
|
|
/* fallback to the first available output port.
|
|
|
|
* some video plugins have funky port names :)
|
|
|
|
*/
|
|
|
|
const char *const *outs = xine_post_list_outputs(m_xinePost);
|
|
|
|
return (xine_post_out_t*)xine_post_output(m_xinePost, (char *) *outs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PostFilter::slotHelpPressed()
|
|
|
|
{
|
|
|
|
kdDebug() << "PostFilter: Help pressed" << endl;
|
|
|
|
|
|
|
|
PostFilterHelp* filterHelp = new PostFilterHelp(NULL, m_filterName.ascii(), TQString::fromUtf8(m_xinePostAPI->get_help()));
|
|
|
|
filterHelp->exec();
|
|
|
|
|
|
|
|
delete filterHelp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString PostFilter::getConfig()
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* returns a string like "filtername:parameter=value,parameter=value,..."
|
|
|
|
*/
|
|
|
|
|
|
|
|
TQString configString;
|
|
|
|
TQTextOStream configStream(&configString);
|
|
|
|
|
|
|
|
configStream << m_filterName << ":";
|
|
|
|
for (uint i = 0; i < m_parameterList.count(); i++)
|
|
|
|
{
|
|
|
|
configStream << m_parameterList.at( i )->name() << "=" << m_parameterList.at( i )->getValue();
|
|
|
|
if( i != m_parameterList.count()-1 )
|
|
|
|
configStream << ",";
|
|
|
|
}
|
|
|
|
|
|
|
|
kdDebug() << "PostFilter: GetConfig " << configString << endl;
|
|
|
|
|
|
|
|
return configString;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PostFilter::setConfig(const TQString &configString)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* expects a string like filtername:parameter=value,parameter=value,...
|
|
|
|
* or filtername:parameter="value",parameter="value",...
|
|
|
|
*/
|
|
|
|
|
|
|
|
kdDebug() << "PostFilter: SetConfig " << configString << endl;
|
|
|
|
|
|
|
|
TQString configStr;
|
|
|
|
if (configString.section(':',0,0) == m_filterName)
|
|
|
|
{
|
|
|
|
configStr = configString.section(':',1,1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kdWarning() << "PostFilter: Config string doesn't match filter name " << m_filterName << endl;
|
|
|
|
kdDebug() << "PostFilter: Don't apply new configuration" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int i = 0; i < configStr.contains(',') + 1; i++ )
|
|
|
|
{
|
|
|
|
TQString parameterConfig = configStr.section(',', i, i);
|
|
|
|
TQString parameterName = parameterConfig.section('=', 0, 0);
|
|
|
|
TQString parameterValue = parameterConfig.section('=', 1, 1);
|
|
|
|
parameterValue = parameterValue.remove('"');
|
|
|
|
|
|
|
|
for (uint j = 0; j < m_parameterList.count(); j++)
|
|
|
|
{
|
|
|
|
if(parameterName == m_parameterList.at(j)->name())
|
|
|
|
{
|
|
|
|
kdDebug() << "PostFilter: Set parameter '" << parameterName << "' to value '" << parameterValue << "'" << endl;
|
|
|
|
m_parameterList.at(j)->setValue(parameterValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PostFilterParameterInt::PostFilterParameterInt(const TQString& name, int offset, int value, int min, int max, TQWidget* parent)
|
|
|
|
: PostFilterParameter (name, offset, parent )
|
|
|
|
{
|
|
|
|
m_numInput = new KIntNumInput(value, parent);
|
|
|
|
m_numInput->setRange( min, max, 1, false);
|
|
|
|
connect(m_numInput, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotIntValue(int)));
|
|
|
|
}
|
|
|
|
|
|
|
|
PostFilterParameterDouble::PostFilterParameterDouble(const TQString& name, int offset, double value, double min, double max, TQWidget* parent)
|
|
|
|
: PostFilterParameter (name, offset, parent )
|
|
|
|
{
|
|
|
|
m_numInput = new KDoubleNumInput(parent);
|
|
|
|
m_numInput->setValue(value);
|
|
|
|
m_numInput->setRange(min, max, 0.01, false);
|
|
|
|
connect(m_numInput, TQT_SIGNAL(valueChanged( double)), this, TQT_SLOT(slotDoubleValue( double)));
|
|
|
|
}
|
|
|
|
|
|
|
|
PostFilterParameterChar::PostFilterParameterChar(const TQString& name, int offset, char *value, int size, TQWidget* parent)
|
|
|
|
: PostFilterParameter (name, offset, parent )
|
|
|
|
{
|
|
|
|
m_charInput = new KLineEdit(value, parent);
|
|
|
|
m_charInput->setMaxLength(size);
|
|
|
|
connect(m_charInput, TQT_SIGNAL(returnPressed(const TQString&)), this, TQT_SLOT(slotCharValue(const TQString&)));
|
|
|
|
}
|
|
|
|
|
|
|
|
PostFilterParameterCombo::PostFilterParameterCombo(const TQString& name, int offset, int value, char **enums, TQWidget* parent)
|
|
|
|
: PostFilterParameter (name, offset, parent)
|
|
|
|
{
|
|
|
|
m_comboBox = new KComboBox(parent);
|
|
|
|
for (int i = 0; enums[i]; i++)
|
|
|
|
{
|
|
|
|
m_comboBox->insertItem(enums[i]);
|
|
|
|
}
|
|
|
|
m_comboBox->setCurrentItem(value);
|
|
|
|
connect(m_comboBox, TQT_SIGNAL( activated(int)), this, TQT_SLOT( slotIntValue(int)));
|
|
|
|
}
|
|
|
|
|
|
|
|
PostFilterParameterBool::PostFilterParameterBool(const TQString& name, int offset, bool value, TQWidget* parent)
|
|
|
|
: PostFilterParameter (name, offset, parent )
|
|
|
|
{
|
|
|
|
m_checkBox = new TQCheckBox(parent);
|
|
|
|
m_checkBox->setChecked(value);
|
|
|
|
connect(m_checkBox, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotBoolValue( bool)));
|
|
|
|
}
|
|
|
|
|
|
|
|
PostFilterHelp::PostFilterHelp(TQWidget *parent, const char *name, const TQString& text)
|
|
|
|
: KDialogBase( parent, name, true, TQString(name) + " - " + i18n("Help"), KDialogBase::Close )
|
|
|
|
{
|
|
|
|
setInitialSize( TQSize(500,500) );
|
|
|
|
|
|
|
|
TQWidget* mainWidget = makeMainWidget();
|
|
|
|
TQGridLayout* grid = new TQGridLayout( mainWidget, 1, 1 );
|
|
|
|
grid->setSpacing( 5 );
|
|
|
|
|
|
|
|
//TQString help = TQString::fromUtf8(text);
|
|
|
|
m_textEdit = new TQTextEdit(text, TQString(), mainWidget, name);
|
|
|
|
m_textEdit->setReadOnly(true);
|
|
|
|
grid->addWidget(m_textEdit, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PostFilterHelp::~PostFilterHelp()
|
|
|
|
{
|
|
|
|
delete m_textEdit;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "postfilter.moc"
|