You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kaffeine/kaffeine/src/player-parts/xine-part/postfilter.cpp

399 lines
14 KiB

/*
* 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, TQ_SIGNAL(signalIntValue(int, int)), this, TQ_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, TQ_SIGNAL( signalIntValue(int, int)), this, TQ_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, TQ_SIGNAL(signalDoubleValue(int, double)), this, TQ_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, TQ_SIGNAL(signalCharValue(int, const TQString&)), this, TQ_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, TQ_SIGNAL(signalIntValue(int, int)), this, TQ_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, TQ_SIGNAL(clicked()), this, TQ_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, TQ_SIGNAL(clicked()), this, TQ_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, TQ_SIGNAL(valueChanged(int)), this, TQ_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, TQ_SIGNAL(valueChanged( double)), this, TQ_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, TQ_SIGNAL(returnPressed(const TQString&)), this, TQ_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, TQ_SIGNAL( activated(int)), this, TQ_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, TQ_SIGNAL(toggled(bool)), this, TQ_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"