/* * postfilter.cpp - wrapper for xine's postprocessing filters * * Copyright (C) 2003-2005 Jürgen Kofler * 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 #include #include #include #include #include #include #include #include #include #include #include #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("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("video")); if( !input ) input = xine_post_input(m_xinePost, const_cast("video in") ); if( !input ) input = xine_post_input(m_xinePost, const_cast("audio")); if( !input ) input = xine_post_input(m_xinePost, const_cast("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("video")); if( !output ) output = xine_post_output(m_xinePost, const_cast("video out")); if( !output ) output = xine_post_output(m_xinePost, const_cast("audio")); if( !output ) output = xine_post_output(m_xinePost, const_cast("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"