]> git.sesse.net Git - vlc/blobdiff - modules/gui/qt4/components/extended_panels.cpp
Try to fix memleaks
[vlc] / modules / gui / qt4 / components / extended_panels.cpp
index d525f4c2a89869c254caf6969a28ea58237447fd..7172c4b3e3c241643e1d8961bd50c5b8af68de18 100644 (file)
@@ -1,10 +1,11 @@
 /*****************************************************************************
  * extended_panels.cpp : Extended controls panels
  ****************************************************************************
- * Copyright (C) 2006 the VideoLAN team
- * $Id: preferences.cpp 16643 2006-09-13 12:45:46Z zorglub $
+ * Copyright (C) 2006-2007 the VideoLAN team
+ * $Id$
  *
  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
+ *          Antoine Cellerier <dionoea .t videolan d@t org>
  *
  * 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
 #include <QString>
 #include <QFont>
 #include <QGridLayout>
+#include <QSignalMapper>
 
 #include "components/extended_panels.hpp"
+#include "dialogs/preferences.hpp"
+#include "dialogs_provider.hpp"
 #include "qt4.hpp"
 
 #include "../../audio_filter/equalizer_presets.h"
 #include <vlc_aout.h>
 #include <vlc_intf_strings.h>
-#include <assert.h>
+#include <vlc_vout.h>
+#include <vlc_osd.h>
+
+#include <iostream>
+#include <string.h>
+
+#if 0
+class ConfClickHandler : public QObject
+{
+public:
+    ConfClickHandler( intf_thread_t *_p_intf, ExtVideo *_e ) : QObject (_e) {
+        e = _e; p_intf = _p_intf;
+    }
+    virtual ~ConfClickHandler() {}
+    bool eventFilter( QObject *obj, QEvent *evt )
+    {
+        if( evt->type() == QEvent::MouseButtonPress )
+        {
+            e->gotoConf( obj );
+            return true;
+        }
+        return false;
+    }
+private:
+    ExtVideo* e;
+    intf_thread_t *p_intf;
+};
+#endif
+
+QString ModuleFromWidgetName( QObject *obj )
+{
+    return obj->objectName().replace("Enable","");
+}
+
+QString OptionFromWidgetName( QObject *obj )
+{
+    /* Gruik ? ... nah */
+    QString option = obj->objectName().replace( "Slider", "" )
+                                      .replace( "Combo" , "" )
+                                      .replace( "Dial"  , "" )
+                                      .replace( "Check" , "" )
+                                      .replace( "Spin"  , "" )
+                                      .replace( "Text"  , "" );
+    for( char a = 'A'; a <= 'Z'; a++ )
+    {
+        option = option.replace( QString( a ),
+                                 QString( '-' ) + QString( a + 'a' - 'A' ) );
+    }
+    return option;
+}
+
+ExtVideo::ExtVideo( intf_thread_t *_p_intf, QWidget *_parent ) :
+                           QWidget( _parent ) , p_intf( _p_intf )
+{
+    ui.setupUi( this );
+
+#define SETUP_VFILTER( widget ) \
+    { \
+        vlc_object_t *p_obj = (vlc_object_t *) \
+            vlc_object_find_name( p_intf->p_libvlc, \
+                                  #widget, \
+                                  FIND_CHILD ); \
+        QCheckBox *checkbox = qobject_cast<QCheckBox*>(ui.widget##Enable); \
+        QGroupBox *groupbox = qobject_cast<QGroupBox*>(ui.widget##Enable); \
+        if( p_obj ) \
+        { \
+            vlc_object_release( p_obj ); \
+            if( checkbox ) checkbox->setCheckState( Qt::Checked ); \
+            else groupbox->setChecked( true ); \
+        } \
+        else \
+        { \
+            if( checkbox ) checkbox->setCheckState( Qt::Unchecked ); \
+            else groupbox->setChecked( false ); \
+        } \
+    } \
+    CONNECT( ui.widget##Enable, clicked(), this, updateFilters() );
+#define SETUP_VFILTER_OPTION( widget, signal ) \
+    initComboBoxItems( ui.widget ); \
+    setWidgetValue( ui.widget ); \
+    CONNECT( ui.widget, signal, this, updateFilterOptions() );
+
+    SETUP_VFILTER( adjust )
+    SETUP_VFILTER_OPTION( hueSlider, valueChanged(int) )
+    SETUP_VFILTER_OPTION( contrastSlider, valueChanged(int) )
+    SETUP_VFILTER_OPTION( brightnessSlider, valueChanged(int) )
+    SETUP_VFILTER_OPTION( saturationSlider, valueChanged(int) )
+    SETUP_VFILTER_OPTION( gammaSlider, valueChanged(int) )
+    SETUP_VFILTER_OPTION( brightnessThresholdCheck, stateChanged(int) )
+
+    SETUP_VFILTER( extract )
+    SETUP_VFILTER_OPTION( extractComponentText, textChanged(QString) )
+
+    SETUP_VFILTER( colorthres )
+    SETUP_VFILTER_OPTION( colorthresColorText, textChanged(QString) )
+    SETUP_VFILTER_OPTION( colorthresSaturationthresSlider, valueChanged(int) )
+    SETUP_VFILTER_OPTION( colorthresSimilaritythresSlider, valueChanged(int) )
+
+    SETUP_VFILTER( invert )
+
+    SETUP_VFILTER( gradient )
+    SETUP_VFILTER_OPTION( gradientModeCombo, currentIndexChanged(QString) )
+    SETUP_VFILTER_OPTION( gradientTypeCheck, stateChanged(int) )
+    SETUP_VFILTER_OPTION( gradientCartoonCheck, stateChanged(int) )
+
+    SETUP_VFILTER( motionblur )
+    SETUP_VFILTER_OPTION( blurFactorSlider, valueChanged(int) )
+
+    SETUP_VFILTER( motiondetect )
+
+    SETUP_VFILTER( noise )
+
+    SETUP_VFILTER( psychedelic )
+
+    SETUP_VFILTER( sharpen )
+    SETUP_VFILTER_OPTION( sharpenSigmaSlider, valueChanged(int) )
+
+    SETUP_VFILTER( ripple )
+
+    SETUP_VFILTER( wave )
+
+    SETUP_VFILTER( transform )
+    SETUP_VFILTER_OPTION( transformTypeCombo, currentIndexChanged(QString) )
+
+    SETUP_VFILTER( rotate )
+    SETUP_VFILTER_OPTION( rotateAngleDial, valueChanged(int) )
+    ui.rotateAngleDial->setWrapping( true );
+    ui.rotateAngleDial->setNotchesVisible( true );
+
+    SETUP_VFILTER( puzzle )
+    SETUP_VFILTER_OPTION( puzzleRowsSpin, valueChanged(int) )
+    SETUP_VFILTER_OPTION( puzzleColsSpin, valueChanged(int) )
+    SETUP_VFILTER_OPTION( puzzleBlackSlotCheck, stateChanged(int) )
+
+    SETUP_VFILTER( magnify )
+
+    SETUP_VFILTER( clone )
+    SETUP_VFILTER_OPTION( cloneCountSpin, valueChanged(int) )
+
+    SETUP_VFILTER( wall )
+    SETUP_VFILTER_OPTION( wallRowsSpin, valueChanged(int) )
+    SETUP_VFILTER_OPTION( wallColsSpin, valueChanged(int) )
+
+    SETUP_VFILTER( erase )
+    SETUP_VFILTER_OPTION( eraseMaskText, editingFinished() )
+    SETUP_VFILTER_OPTION( eraseYSpin, valueChanged(int) )
+    SETUP_VFILTER_OPTION( eraseXSpin, valueChanged(int) )
+
+    SETUP_VFILTER( marq )
+    SETUP_VFILTER_OPTION( marqMarqueeText, textChanged(QString) )
+    SETUP_VFILTER_OPTION( marqPositionCombo, currentIndexChanged(QString) )
+
+    SETUP_VFILTER( logo )
+    SETUP_VFILTER_OPTION( logoFileText, editingFinished() )
+    SETUP_VFILTER_OPTION( logoYSpin, valueChanged(int) )
+    SETUP_VFILTER_OPTION( logoXSpin, valueChanged(int) )
+    SETUP_VFILTER_OPTION( logoTransparencySlider, valueChanged(int) )
+
+#undef SETUP_VFILTER
+#undef SETUP_VFILTER_OPTION
+}
+
+ExtVideo::~ExtVideo()
+{
+}
+
+void ExtVideo::ChangeVFiltersString( char *psz_name, vlc_bool_t b_add )
+{
+    vout_thread_t *p_vout;
+    char *psz_parser, *psz_string;
+    const char *psz_filter_type;
+
+    /* Please leave p_libvlc_global. This is where cached modules are
+     * stored. We're not trying to find a module instance. */
+    module_t *p_obj = module_FindName( p_intf, psz_name );
+    if( !p_obj )
+    {
+        msg_Err( p_intf, "Unable to find filter module \"%s\n.", psz_name );
+        return;
+    }
+
+    if( module_IsCapable( p_obj, "video filter2" ) )
+    {
+        psz_filter_type = "video-filter";
+    }
+    else if( module_IsCapable( p_obj, "video filter" ) )
+    {
+        psz_filter_type = "vout-filter";
+    }
+    else if( module_IsCapable( p_obj, "sub filter" ) )
+    {
+        psz_filter_type = "sub-filter";
+    }
+    else
+    {
+        vlc_object_release( p_obj );
+        msg_Err( p_intf, "Unknown video filter type." );
+        return;
+    }
+    vlc_object_release( p_obj );
+
+    psz_string = config_GetPsz( p_intf, psz_filter_type );
+
+    if( !psz_string ) psz_string = strdup("");
+
+    psz_parser = strstr( psz_string, psz_name );
+
+    if( b_add )
+    {
+        if( !psz_parser )
+        {
+            psz_parser = psz_string;
+            asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
+                            psz_string, psz_name );
+            free( psz_parser );
+        }
+        else
+        {
+            return;
+        }
+    }
+    else
+    {
+        if( psz_parser )
+        {
+            if( *(psz_parser + strlen(psz_name)) == ':' )
+            {
+                memmove( psz_parser, psz_parser + strlen(psz_name) + 1,
+                         strlen(psz_parser + strlen(psz_name) + 1 ) + 1 );
+            }
+            else
+            {
+                *psz_parser = '\0';
+            }
+
+            /* Remove trailing : : */
+            if( strlen( psz_string ) > 0 &&
+                *( psz_string + strlen( psz_string ) -1 ) == ':' )
+            {
+                *( psz_string + strlen( psz_string ) -1 ) = '\0';
+            }
+        }
+        else
+        {
+            free( psz_string );
+            return;
+        }
+    }
+    /* Vout is not kept, so put that in the config */
+    config_PutPsz( p_intf, psz_filter_type, psz_string );
+    if( !strcmp( psz_filter_type, "video-filter" ) )
+        ui.videoFilterText->setText( psz_string );
+    else if( !strcmp( psz_filter_type, "vout-filter" ) )
+        ui.voutFilterText->setText( psz_string );
+    else if( !strcmp( psz_filter_type, "sub-filter" ) )
+        ui.subpictureFilterText->setText( psz_string );
+
+    /* Try to set on the fly */
+    p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
+                                              FIND_ANYWHERE );
+    if( p_vout )
+    {
+        if( !strcmp( psz_filter_type, "sub-filter" ) )
+            var_SetString( p_vout->p_spu, psz_filter_type, psz_string );
+        else
+            var_SetString( p_vout, psz_filter_type, psz_string );
+        vlc_object_release( p_vout );
+    }
+
+    free( psz_string );
+}
+
+void ExtVideo::updateFilters()
+{
+    QString module = ModuleFromWidgetName( sender() );
+    //std::cout << "Module name: " << module.toStdString() << std::endl;
+
+    QCheckBox *checkbox = qobject_cast<QCheckBox*>(sender());
+    QGroupBox *groupbox = qobject_cast<QGroupBox*>(sender());
+
+    ChangeVFiltersString( qtu(module),
+                          checkbox ? checkbox->isChecked()
+                                   : groupbox->isChecked() );
+}
+
+void ExtVideo::initComboBoxItems( QObject *widget )
+{
+    QComboBox *combobox = qobject_cast<QComboBox*>(widget);
+    if( !combobox ) return;
+    QString option = OptionFromWidgetName( widget );
+    module_config_t *p_item = config_FindConfig( VLC_OBJECT(p_intf),
+                                                 option.toStdString().c_str() );
+    if( p_item )
+    {
+        int i_type = p_item->i_type & CONFIG_ITEM;
+        for( int i_index = 0; i_index < p_item->i_list; i_index++ )
+        {
+            if( i_type == CONFIG_ITEM_INTEGER
+             || i_type == CONFIG_ITEM_BOOL )
+                combobox->addItem( qfu( p_item->ppsz_list_text[i_index] ), p_item->pi_list[i_index] );
+            else if( i_type == CONFIG_ITEM_STRING )
+                combobox->addItem( qfu( p_item->ppsz_list_text[i_index] ), p_item->ppsz_list[i_index] );
+        }
+    }
+    else
+    {
+        msg_Err( p_intf, "Couldn't find option \"%s\".",
+                 option.toStdString().c_str() );
+    }
+}
+
+void ExtVideo::setWidgetValue( QObject *widget )
+{
+    QString module = ModuleFromWidgetName( widget->parent() );
+    //std::cout << "Module name: " << module.toStdString() << std::endl;
+    QString option = OptionFromWidgetName( widget );
+    //std::cout << "Option name: " << option.toStdString() << std::endl;
+
+    vlc_object_t *p_obj = (vlc_object_t *)
+        vlc_object_find_name( p_intf->p_libvlc,
+                              module.toStdString().c_str(),
+                              FIND_CHILD );
+    int i_type;
+    vlc_value_t val;
+
+    if( !p_obj )
+    {
+#if 0
+        msg_Dbg( p_intf,
+                 "Module instance %s not found, looking in config values.",
+                 module.toStdString().c_str() );
+#endif
+        i_type = config_GetType( p_intf, option.toStdString().c_str() ) & 0xf0;
+        switch( i_type )
+        {
+            case VLC_VAR_INTEGER:
+            case VLC_VAR_BOOL:
+                val.i_int = config_GetInt( p_intf, option.toStdString().c_str() );
+                break;
+            case VLC_VAR_FLOAT:
+                val.f_float = config_GetFloat( p_intf, option.toStdString().c_str() );
+                break;
+            case VLC_VAR_STRING:
+                val.psz_string = config_GetPsz( p_intf, option.toStdString().c_str() );
+                break;
+        }
+    }
+    else
+    {
+        i_type = var_Type( p_obj, option.toStdString().c_str() ) & 0xf0;
+        var_Get( p_obj, option.toStdString().c_str(), &val );
+        vlc_object_release( p_obj );
+    }
+
+    /* Try to cast to all the widgets we're likely to encounter. Only
+     * one of the casts is expected to work. */
+    QSlider        *slider        = qobject_cast<QSlider*>       (widget);
+    QCheckBox      *checkbox      = qobject_cast<QCheckBox*>     (widget);
+    QSpinBox       *spinbox       = qobject_cast<QSpinBox*>      (widget);
+    QDoubleSpinBox *doublespinbox = qobject_cast<QDoubleSpinBox*>(widget);
+    QDial          *dial          = qobject_cast<QDial*>         (widget);
+    QLineEdit      *lineedit      = qobject_cast<QLineEdit*>     (widget);
+    QComboBox      *combobox      = qobject_cast<QComboBox*>     (widget);
+
+    if( i_type == VLC_VAR_INTEGER || i_type == VLC_VAR_BOOL )
+    {
+        int i_int = 0;
+        if( slider )        slider->setValue( val.i_int );
+        else if( checkbox ) checkbox->setCheckState( val.i_int? Qt::Checked
+                                                              : Qt::Unchecked );
+        else if( spinbox )  spinbox->setValue( val.i_int );
+        else if( dial )     dial->setValue( (540-val.i_int)%360 );
+        else if( lineedit )
+        {
+            char str[30];
+            sprintf( str, "%06X", val.i_int );
+            lineedit->setText( str );
+        }
+        else if( combobox ) combobox->setCurrentIndex(
+                            combobox->findData( val.i_int ) );
+        else msg_Warn( p_intf, "Oops %s %s %d", __FILE__, __func__, __LINE__ );
+    }
+    else if( i_type == VLC_VAR_FLOAT )
+    {
+        double f_float = 0;
+        if( slider ) slider->setValue( (int)(val.f_float*(double)slider->tickInterval())); /* hack alert! */
+        else if( doublespinbox ) doublespinbox->setValue(val.f_float);
+        else msg_Warn( p_intf, "Oops %s %s %d", __FILE__, __func__, __LINE__ );
+    }
+    else if( i_type == VLC_VAR_STRING )
+    {
+        if( lineedit ) lineedit->setText( qfu(val.psz_string) );
+        else if( combobox ) combobox->setCurrentIndex(
+                            combobox->findData( qfu( val.psz_string ) ) );
+        else msg_Warn( p_intf, "Oops %s %s %d", __FILE__, __func__, __LINE__ );
+        free( val.psz_string );
+    }
+    else
+        msg_Err( p_intf,
+                 "Module %s's %s variable is of an unsupported type (%d)",
+                 module.toStdString().c_str(),
+                 option.toStdString().c_str(),
+                 i_type );
+}
+
+void ExtVideo::updateFilterOptions()
+{
+    QString module = ModuleFromWidgetName( sender()->parent() );
+    //std::cout << "Module name: " << module.toStdString() << std::endl;
+    QString option = OptionFromWidgetName( sender() );
+    //std::cout << "Option name: " << option.toStdString() << std::endl;
+
+    vlc_object_t *p_obj = (vlc_object_t *)
+        vlc_object_find_name( p_intf->p_libvlc,
+                              module.toStdString().c_str(),
+                              FIND_CHILD );
+    if( !p_obj )
+    {
+        msg_Err( p_intf, "Module %s not found.", module.toStdString().c_str() );
+        return;
+    }
+
+    int i_type = var_Type( p_obj, option.toStdString().c_str() );
+    bool b_is_command = ( i_type & VLC_VAR_ISCOMMAND );
+    if( !b_is_command )
+    {
+        msg_Warn( p_intf, "Module %s's %s variable isn't a command. You'll need to restart the filter to take change into account.",
+                 module.toStdString().c_str(),
+                 option.toStdString().c_str() );
+        /* FIXME: restart automatically somewhere near the end of this function */
+    }
+
+    /* Try to cast to all the widgets we're likely to encounter. Only
+     * one of the casts is expected to work. */
+    QSlider        *slider        = qobject_cast<QSlider*>       (sender());
+    QCheckBox      *checkbox      = qobject_cast<QCheckBox*>     (sender());
+    QSpinBox       *spinbox       = qobject_cast<QSpinBox*>      (sender());
+    QDoubleSpinBox *doublespinbox = qobject_cast<QDoubleSpinBox*>(sender());
+    QDial          *dial          = qobject_cast<QDial*>         (sender());
+    QLineEdit      *lineedit      = qobject_cast<QLineEdit*>     (sender());
+    QComboBox      *combobox      = qobject_cast<QComboBox*>     (sender());
+
+    i_type &= 0xf0;
+    if( i_type == VLC_VAR_INTEGER || i_type == VLC_VAR_BOOL )
+    {
+        int i_int = 0;
+        if( slider )        i_int = slider->value();
+        else if( checkbox ) i_int = checkbox->checkState() == Qt::Checked;
+        else if( spinbox )  i_int = spinbox->value();
+        else if( dial )     i_int = (540-dial->value())%360;
+        else if( lineedit ) i_int = lineedit->text().toInt(NULL,16);
+        else if( combobox ) i_int = combobox->itemData(combobox->currentIndex()).toInt();
+        else msg_Warn( p_intf, "Oops %s %s %d", __FILE__, __func__, __LINE__ );
+        config_PutInt( p_intf, option.toStdString().c_str(), i_int );
+        if( b_is_command )
+        {
+            if( i_type == VLC_VAR_INTEGER )
+                var_SetInteger( p_obj, option.toStdString().c_str(), i_int );
+            else
+                var_SetBool( p_obj, option.toStdString().c_str(), i_int );
+        }
+    }
+    else if( i_type == VLC_VAR_FLOAT )
+    {
+        double f_float = 0;
+        if( slider )             f_float = (double)slider->value()
+                                         / (double)slider->tickInterval(); /* hack alert! */
+        else if( doublespinbox ) f_float = doublespinbox->value();
+        else if( lineedit ) f_float = lineedit->text().toDouble();
+        else msg_Warn( p_intf, "Oops %s %s %d", __FILE__, __func__, __LINE__ );
+        config_PutFloat( p_intf, option.toStdString().c_str(), f_float );
+        if( b_is_command )
+            var_SetFloat( p_obj, option.toStdString().c_str(), f_float );
+    }
+    else if( i_type == VLC_VAR_STRING )
+    {
+        char *psz_string = NULL;
+        if( lineedit ) psz_string = strdup(qtu(lineedit->text()));
+        else if( combobox ) psz_string = strdup(qtu(combobox->itemData(
+                                         combobox->currentIndex()).toString()));
+        else msg_Warn( p_intf, "Oops %s %s %d", __FILE__, __func__, __LINE__ );
+        config_PutPsz( p_intf, option.toStdString().c_str(), psz_string );
+        if( b_is_command )
+            var_SetString( p_obj, option.toStdString().c_str(), psz_string );
+        free( psz_string );
+    }
+    else
+        msg_Err( p_intf,
+                 "Module %s's %s variable is of an unsupported type (%d)",
+                 module.toStdString().c_str(),
+                 option.toStdString().c_str(),
+                 i_type );
+
+    vlc_object_release( p_obj );
+}
+
+#if 0
+void ExtVideo::gotoConf( QObject* src )
+{
+#define SHOWCONF(module) \
+    if( src->objectName().contains(module) ) \
+    { \
+        PrefsDialog::getInstance( p_intf )->showModulePrefs( module ); \
+        return; \
+    }
+    SHOWCONF( "clone" );
+    SHOWCONF( "magnify" );
+    SHOWCONF( "wave" );
+    SHOWCONF( "ripple" );
+    SHOWCONF( "invert" );
+    SHOWCONF( "puzzle" );
+    SHOWCONF( "wall" );
+    SHOWCONF( "gradient" );
+    SHOWCONF( "colorthres" )
+}
+#endif
 
 /**********************************************************************
  * Equalizer
 
 static const QString band_frequencies[] =
 {
-    "   60Hz  ", " 170 Hz " , " 310 Hz ", " 600 Hz ", "  1 kHz  ",
-    "  3 kHz  " , "  6 kHz ", " 12 kHz ", " 14 kHz ", " 16 kHz "
+    "  60 Hz  ", " 170 Hz ", " 310 Hz ", " 600 Hz ", "  1 kHz ",
+    "  3 kHz  ", "  6 kHz ", " 12 kHz ", " 14 kHz ", " 16 kHz "
 };
 
 Equalizer::Equalizer( intf_thread_t *_p_intf, QWidget *_parent ) :
@@ -52,6 +571,7 @@ Equalizer::Equalizer( intf_thread_t *_p_intf, QWidget *_parent ) :
     smallFont.setPointSize( smallFont.pointSize() - 3 );
 
     ui.setupUi( this );
+    presetsComboBox = ui.presetsCombo;
 
     ui.preampLabel->setFont( smallFont );
     ui.preampSlider->setMaximum( 400 );
@@ -84,15 +604,15 @@ Equalizer::Equalizer( intf_thread_t *_p_intf, QWidget *_parent ) :
     /* Write down initial values */
     aout_instance_t *p_aout = (aout_instance_t *)vlc_object_find(p_intf,
                                     VLC_OBJECT_AOUT, FIND_ANYWHERE);
-    char *psz_af = NULL;
+    char *psz_af;
     char *psz_bands;
     float f_preamp;
     if( p_aout )
     {
-        psz_af = var_GetString( p_aout, "audio-filter" );
+        psz_af = var_GetNonEmptyString( p_aout, "audio-filter" );
         if( var_GetBool( p_aout, "equalizer-2pass" ) )
             ui.eq2PassCheck->setChecked( true );
-        psz_bands = var_GetString( p_aout, "equalizer-bands" );
+        psz_bands = var_GetNonEmptyString( p_aout, "equalizer-bands" );
         f_preamp = var_GetFloat( p_aout, "equalizer-preamp" );
         vlc_object_release( p_aout );
     }
@@ -106,6 +626,7 @@ Equalizer::Equalizer( intf_thread_t *_p_intf, QWidget *_parent ) :
     }
     if( psz_af && strstr( psz_af, "equalizer" ) != NULL )
         ui.enableCheck->setChecked( true );
+    free( psz_af );
     enable( ui.enableCheck->isChecked() );
 
     setValues( psz_bands, f_preamp );
@@ -120,7 +641,11 @@ void Equalizer::enable()
     bool en = ui.enableCheck->isChecked();
     aout_EnableFilter( VLC_OBJECT( p_intf ), "equalizer",
                        en ? VLC_TRUE : VLC_FALSE );
-    enable( en );
+//    aout_EnableFilter( VLC_OBJECT( p_intf ), "upmixer",
+//                       en ? VLC_TRUE : VLC_FALSE );
+//     aout_EnableFilter( VLC_OBJECT( p_intf ), "vsurround",
+//                       en ? VLC_TRUE : VLC_FALSE );
+     enable( en );
 }
 
 void Equalizer::enable( bool en )
@@ -211,9 +736,9 @@ void Equalizer::setValues( char *psz_bands, float f_preamp )
             sprintf( psz_val, "% 5.1f", f );
             band_texts[i]->setText( band_frequencies[i] + "\n" + psz_val +
                                     "dB" );
-            if( p == NULL ) break;
+            if( p == NULL || *p == '\0' ) break;
             p++;
-            if( *p == 0 )  break;
+            if( *p == '\0' )  break;
         }
     }
     char psz_val[5];
@@ -249,18 +774,177 @@ void Equalizer::setPreset( int preset )
     setValues( psz_values, eqz_preset_10b[preset]->f_preamp );
 }
 
+static int PresetCallback( vlc_object_t *p_this, char const *psz_cmd,
+                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+    char *psz_preset = newval.psz_string;
+    Equalizer *eq = (Equalizer *)p_data;
+    eq->presetsComboBox->setCurrentIndex( eq->presetsComboBox->findText( qfu( psz_preset) ) );
+    return VLC_SUCCESS;
+}
+
 void Equalizer::delCallbacks( aout_instance_t *p_aout )
 {
-//    var_DelCallback( p_aout, "equalizer-bands", EqzCallback, this );
-//    var_DelCallback( p_aout, "equalizer-preamp", EqzCallback, this );
+    //var_DelCallback( p_aout, "equalizer-bands", EqzCallback, this );
+    //var_DelCallback( p_aout, "equalizer-preamp", EqzCallback, this );
+    var_DelCallback( p_aout, "equalizer-preset", PresetCallback, this );
 }
 
 void Equalizer::addCallbacks( aout_instance_t *p_aout )
 {
-//    var_AddCallback( p_aout, "equalizer-bands", EqzCallback, this );
-//    var_AddCallback( p_aout, "equalizer-preamp", EqzCallback, this );
+    //var_AddCallback( p_aout, "equalizer-bands", EqzCallback, this );
+    //var_AddCallback( p_aout, "equalizer-preamp", EqzCallback, this );
+    var_AddCallback( p_aout, "equalizer-preset", PresetCallback, this );
 }
 
+/**********************************************************************
+ * Spatializer
+ **********************************************************************/
+static const char *psz_control_names[] =
+{
+    "Roomsize", "Width" , "Wet", "Dry", "Damp"
+};
+static const QString control_names[] =
+{
+    "Roomsize", "Width" , "Wet", "Dry", "Damp"
+};
+
+Spatializer::Spatializer( intf_thread_t *_p_intf, QWidget *_parent ) :
+    QWidget( _parent ) , p_intf( _p_intf )
+{
+    QFont smallFont = QApplication::font( static_cast<QWidget*>(0) );
+    smallFont.setPointSize( smallFont.pointSize() - 3 );
+
+    ui.setupUi( this );
+
+    QGridLayout *grid = new QGridLayout( ui.frame );
+    grid->setMargin( 0 );
+
+    for( int i = 0 ; i < NUM_SP_CTRL ; i++ )
+    {
+        spatCtrl[i] = new QSlider( Qt::Vertical );
+        if( i < 2)
+        {
+            spatCtrl[i]->setMaximum( 10 );
+            spatCtrl[i]->setValue( 2 );
+        }
+        else
+        {
+            spatCtrl[i]->setMaximum( 10 );
+            spatCtrl[i]->setValue( 0 );
+            spatCtrl[i]->setMinimum( -10 );
+        }
+        oldControlVars[i] = spatCtrl[i]->value();
+        CONNECT( spatCtrl[i], valueChanged(int), this, setInitValues() );
+        ctrl_texts[i] = new QLabel( control_names[i] + "\n" );
+        ctrl_texts[i]->setFont( smallFont );
+        ctrl_readout[i] = new QLabel( "" );
+        ctrl_readout[i]->setFont( smallFont );
+        grid->addWidget( spatCtrl[i], 0, i );
+        grid->addWidget( ctrl_readout[i],1,i);
+        grid->addWidget( ctrl_texts[i], 2, i );
+    }
+
+    BUTTONACT( ui.enableCheck, enable() );
+
+    /* Write down initial values */
+    aout_instance_t *p_aout = (aout_instance_t *)
+        vlc_object_find(p_intf, VLC_OBJECT_AOUT, FIND_ANYWHERE);
+    char *psz_af;
+
+    if( p_aout )
+    {
+        psz_af = var_GetNonEmptyString( p_aout, "audio-filter" );
+        for( int i = 0; i < NUM_SP_CTRL ; i++)
+        {
+            controlVars[i] = var_GetFloat( p_aout,  psz_control_names[i] );
+        }
+        vlc_object_release( p_aout );
+    }
+    else
+    {
+        psz_af = config_GetPsz( p_aout, "audio-filter" );
+        for( int i = 0; i < NUM_SP_CTRL ; i++)
+        {
+            controlVars[i] = config_GetFloat( p_intf,  psz_control_names[i] );
+        }
+    }
+    if( psz_af && strstr( psz_af, "spatializer" ) != NULL )
+        ui.enableCheck->setChecked( true );
+    free( psz_af );
+    enable( ui.enableCheck->isChecked() );
+    setValues( controlVars );
+
+}
+
+Spatializer::~Spatializer()
+{
+}
+
+void Spatializer::enable()
+{
+    bool en = ui.enableCheck->isChecked();
+    aout_EnableFilter( VLC_OBJECT( p_intf ), "spatializer",
+            en ? VLC_TRUE : VLC_FALSE );
+    enable( en );
+}
+
+void Spatializer::enable( bool en )
+{
+    for( int i = 0 ; i< NUM_SP_CTRL; i++ )
+    {
+        spatCtrl[i]->setEnabled( en );
+        ctrl_texts[i]->setEnabled( en );
+        ctrl_readout[i]->setEnabled( en );
+    }
+}
+void Spatializer::setInitValues()
+{
+    setValues(controlVars);
+}
+
+void Spatializer::setValues(float *controlVars)
+{
+    char psz_val[5];
+    char var_name[5];
+    aout_instance_t *p_aout= (aout_instance_t *)
+        vlc_object_find(p_intf, VLC_OBJECT_AOUT, FIND_ANYWHERE);
+
+    for( int i = 0 ; i < NUM_SP_CTRL ; i++ )
+    {
+        float f= (float)(  spatCtrl[i]->value() );
+        sprintf( psz_val, "%.1f", f );
+        ctrl_readout[i]->setText( psz_val );
+    }
+    if( p_aout )
+    {
+        for( int i = 0 ; i < NUM_SP_CTRL ; i++ )
+        {
+            if( oldControlVars[i] != spatCtrl[i]->value() )
+            {
+                var_SetFloat( p_aout, psz_control_names[i],
+                        (float)spatCtrl[i]->value() );
+                config_PutFloat( p_intf, psz_control_names[i],
+                        (float) spatCtrl[i]->value());
+                oldControlVars[i] = (float) spatCtrl[i]->value();
+            }
+        }
+        vlc_object_release( p_aout );
+    }
+    //    printf("set callback values %s %s %d\n", __FILE__,__func__,__LINE__);
+
+}
+void Spatializer::delCallbacks( aout_instance_t *p_aout )
+{
+    //    var_DelCallback( p_aout, "Spatializer-bands", EqzCallback, this );
+    //    var_DelCallback( p_aout, "Spatializer-preamp", EqzCallback, this );
+}
+
+void Spatializer::addCallbacks( aout_instance_t *p_aout )
+{
+    //    var_AddCallback( p_aout, "Spatializer-bands", EqzCallback, this );
+    //    var_AddCallback( p_aout, "Spatializer-preamp", EqzCallback, this );
+}
 
 /**********************************************************************
  * Video filters / Adjust