src/video_output/video_output.c: Fixed double free in filter removal
[vlc.git] / modules / gui / qt4 / components / extended_panels.cpp
1 /*****************************************************************************
2  * extended_panels.cpp : Extended controls panels
3  ****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
5  * $Id: preferences.cpp 16643 2006-09-13 12:45:46Z zorglub $
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include <QLabel>
25 #include <QVariant>
26 #include <QString>
27 #include <QFont>
28 #include <QGridLayout>
29 #include <QSignalMapper>
30
31 #include "components/extended_panels.hpp"
32 #include "dialogs/prefs_dialog.hpp"
33 #include "dialogs_provider.hpp"
34 #include "qt4.hpp"
35
36 #include "../../audio_filter/equalizer_presets.h"
37 #include <vlc_aout.h>
38 #include <vlc_intf_strings.h>
39 #include <vlc_vout.h>
40 #include <assert.h>
41
42 class ConfClickHandler : public QObject
43 {
44 public:
45     ConfClickHandler( intf_thread_t *_p_intf, ExtVideo *_e ) : QObject (_e) {
46         e = _e; p_intf = _p_intf;
47     }
48     virtual ~ConfClickHandler() {}
49     bool eventFilter( QObject *obj, QEvent *evt )
50     {
51         if( evt->type() == QEvent::MouseButtonPress )
52         {
53             e->gotoConf( obj );
54             return true;
55         }
56         return false;
57     }
58 private:
59     ExtVideo* e;
60     intf_thread_t *p_intf;
61 };
62
63 #define SETUP_VFILTER( widget, conf, tooltip, labtooltip ) \
64     ui.widget##Check->setToolTip( tooltip ); \
65     if (conf ) {\
66         ui.widget##Label->setToolTip( labtooltip ); \
67         ui.widget##Label->setPixmap( QPixmap(":/pixmaps/go-next.png") ); \
68         ui.widget##Label->installEventFilter(h); \
69     } \
70     CONNECT( ui.widget##Check, clicked(), this, updateFilters() ); \
71
72 ExtVideo::ExtVideo( intf_thread_t *_p_intf, QWidget *_parent ) :
73                            QWidget( _parent ) , p_intf( _p_intf )
74 {
75     ConfClickHandler* h = new ConfClickHandler( p_intf, this );
76
77     ui.setupUi( this );
78
79     SETUP_VFILTER( clone, true, qtr(I_CLONE_TIP),
80                                 qtr("Configure the clone filter") );
81     SETUP_VFILTER( magnify, false, qtr(I_MAGNIFY_TIP),
82                                 qtr("Configure the magnification effect"));
83     SETUP_VFILTER( wave, false, qtr(I_WAVE_TIP),
84                                 qtr("Configure the waves effect"));
85     SETUP_VFILTER( ripple, false, qtr(I_RIPPLE_TIP),
86                                   qtr("Configure the \"water\" effect"));
87     SETUP_VFILTER( invert, false, qtr(I_INVERT_TIP),
88                                   qtr("Configure the color inversion effect"));
89     SETUP_VFILTER( puzzle, true, qtr(I_PUZZLE_TIP),
90                                   qtr("Configure the puzzle effect"));
91     SETUP_VFILTER( wall, true, qtr(I_WALL_TIP),
92                                qtr("Configure the wall filter") );
93     SETUP_VFILTER( gradient, true, qtr(I_GRADIENT_TIP),
94                                    qtr("Configure the \"gradient\" effect"));
95     SETUP_VFILTER( colorthres, true, qtr(I_COLORTHRES_TIP),
96                                    qtr("Configure the color detection effect"));
97 }
98
99 ExtVideo::~ExtVideo()
100 {
101 }
102
103 static void ChangeVFiltersString( intf_thread_t *p_intf,
104                                  char *psz_name, vlc_bool_t b_add )
105 {
106     vout_thread_t *p_vout;
107     char *psz_parser, *psz_string;
108
109     psz_string = config_GetPsz( p_intf, "video-filter" );
110
111     if( !psz_string ) psz_string = strdup("");
112
113     psz_parser = strstr( psz_string, psz_name );
114
115     if( b_add )
116     {
117         if( !psz_parser )
118         {
119             psz_parser = psz_string;
120             asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
121                             psz_string, psz_name );
122             free( psz_parser );
123         }
124         else
125         {
126             return;
127         }
128     }
129     else
130     {
131         if( psz_parser )
132         {
133             if( *(psz_parser + strlen(psz_name)) == ':' )
134             {
135                 memmove( psz_parser, psz_parser + strlen(psz_name) + 1,
136                          strlen(psz_parser + strlen(psz_name) + 1 ) + 1 );
137             }
138             else
139             {
140                 *psz_parser = '\0';
141             }
142
143             /* Remove trailing : : */
144             if( strlen( psz_string ) > 0 &&
145                 *( psz_string + strlen( psz_string ) -1 ) == ':' )
146             {
147                 *( psz_string + strlen( psz_string ) -1 ) = '\0';
148             }
149         }
150         else
151         {
152             free( psz_string );
153             return;
154         }
155     }
156     /* Vout is not kept, so put that in the config */
157     config_PutPsz( p_intf, "video-filter", psz_string );
158
159     /* Try to set on the fly */
160     p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
161                                               FIND_ANYWHERE );
162     if( p_vout )
163     {
164         var_SetString( p_vout, "video-filter", psz_string );
165         vlc_object_release( p_vout );
166     }
167
168     free( psz_string );
169 }
170
171 void ExtVideo::updateFilters()
172 {
173     QCheckBox* filter = qobject_cast<QCheckBox*>(sender());
174     QString module = filter->objectName().replace("Check", "");
175
176     ChangeVFiltersString( p_intf, qtu(module), filter->isChecked() );
177 }
178
179 void ExtVideo::gotoConf( QObject* src )
180 {
181 #define SHOWCONF(module) \
182     if( src->objectName().contains(module) ) \
183     { \
184         PrefsDialog::getInstance( p_intf )->showModulePrefs( module ); \
185         return; \
186     }
187     SHOWCONF( "clone" );
188     SHOWCONF( "magnify" );
189     SHOWCONF( "wave" );
190     SHOWCONF( "ripple" );
191     SHOWCONF( "invert" );
192     SHOWCONF( "puzzle" );
193     SHOWCONF( "wall" );
194     SHOWCONF( "gradient" );
195     SHOWCONF( "colorthres" )
196 }
197
198 /**********************************************************************
199  * Equalizer
200  **********************************************************************/
201
202 static const QString band_frequencies[] =
203 {
204     "   60Hz  ", " 170 Hz " , " 310 Hz ", " 600 Hz ", "  1 kHz  ",
205     "  3 kHz  " , "  6 kHz ", " 12 kHz ", " 14 kHz ", " 16 kHz "
206 };
207
208 Equalizer::Equalizer( intf_thread_t *_p_intf, QWidget *_parent ) :
209                             QWidget( _parent ) , p_intf( _p_intf )
210 {
211     QFont smallFont = QApplication::font( static_cast<QWidget*>(0) );
212     smallFont.setPointSize( smallFont.pointSize() - 3 );
213
214     ui.setupUi( this );
215
216     ui.preampLabel->setFont( smallFont );
217     ui.preampSlider->setMaximum( 400 );
218     for( int i = 0 ; i < NB_PRESETS ; i ++ )
219     {
220         ui.presetsCombo->addItem( qtr( preset_list_text[i] ),
221                                   QVariant( i ) );
222     }
223     CONNECT( ui.presetsCombo, activated( int ), this, setPreset( int ) );
224
225     BUTTONACT( ui.enableCheck, enable() );
226     BUTTONACT( ui.eq2PassCheck, set2Pass() );
227
228     CONNECT( ui.preampSlider, valueChanged(int), this, setPreamp() );
229
230     QGridLayout *grid = new QGridLayout( ui.frame );
231     grid->setMargin( 0 );
232     for( int i = 0 ; i < BANDS ; i++ )
233     {
234         bands[i] = new QSlider( Qt::Vertical );
235         bands[i]->setMaximum( 400 );
236         bands[i]->setValue( 200 );
237         CONNECT( bands[i], valueChanged(int), this, setBand() );
238         band_texts[i] = new QLabel( band_frequencies[i] + "\n0.0dB" );
239         band_texts[i]->setFont( smallFont );
240         grid->addWidget( bands[i], 0, i );
241         grid->addWidget( band_texts[i], 1, i );
242     }
243
244     /* Write down initial values */
245     aout_instance_t *p_aout = (aout_instance_t *)vlc_object_find(p_intf,
246                                     VLC_OBJECT_AOUT, FIND_ANYWHERE);
247     char *psz_af = NULL;
248     char *psz_bands;
249     float f_preamp;
250     if( p_aout )
251     {
252         psz_af = var_GetString( p_aout, "audio-filter" );
253         if( var_GetBool( p_aout, "equalizer-2pass" ) )
254             ui.eq2PassCheck->setChecked( true );
255         psz_bands = var_GetString( p_aout, "equalizer-bands" );
256         f_preamp = var_GetFloat( p_aout, "equalizer-preamp" );
257         vlc_object_release( p_aout );
258     }
259     else
260     {
261         psz_af = config_GetPsz( p_intf, "audio-filter" );
262         if( config_GetInt( p_intf, "equalizer-2pass" ) )
263             ui.eq2PassCheck->setChecked( true );
264         psz_bands = config_GetPsz( p_intf, "equalizer-bands" );
265         f_preamp = config_GetFloat( p_intf, "equalizer-preamp" );
266     }
267     if( psz_af && strstr( psz_af, "equalizer" ) != NULL )
268         ui.enableCheck->setChecked( true );
269     enable( ui.enableCheck->isChecked() );
270
271     setValues( psz_bands, f_preamp );
272 }
273
274 Equalizer::~Equalizer()
275 {
276 }
277
278 void Equalizer::enable()
279 {
280     bool en = ui.enableCheck->isChecked();
281     aout_EnableFilter( VLC_OBJECT( p_intf ), "equalizer",
282                        en ? VLC_TRUE : VLC_FALSE );
283     enable( en );
284 }
285
286 void Equalizer::enable( bool en )
287 {
288     ui.eq2PassCheck->setEnabled( en );
289     ui.preampLabel->setEnabled( en );
290     ui.preampSlider->setEnabled( en  );
291     for( int i = 0 ; i< BANDS; i++ )
292     {
293         bands[i]->setEnabled( en ); band_texts[i]->setEnabled( en );
294     }
295 }
296
297 void Equalizer::set2Pass()
298 {
299     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
300                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
301     vlc_bool_t b_2p = ui.eq2PassCheck->isChecked();
302
303     if( p_aout == NULL )
304         config_PutInt( p_intf, "equalizer-2pass", b_2p );
305     else
306     {
307         var_SetBool( p_aout, "equalizer-2pass", b_2p );
308         config_PutInt( p_intf, "equalizer-2pass", b_2p );
309         for( int i = 0; i < p_aout->i_nb_inputs; i++ )
310         {
311             p_aout->pp_inputs[i]->b_restart = VLC_TRUE;
312         }
313         vlc_object_release( p_aout );
314     }
315 }
316
317 void Equalizer::setPreamp()
318 {
319     float f= (float)(  ui.preampSlider->value() ) /10 - 20;
320     char psz_val[5];
321     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
322                                        VLC_OBJECT_AOUT, FIND_ANYWHERE);
323
324     sprintf( psz_val, "%.1f", f );
325     ui.preampLabel->setText( qtr("Preamp\n") + psz_val + qtr("dB") );
326     if( p_aout )
327     {
328         delCallbacks( p_aout );
329         var_SetFloat( p_aout, "equalizer-preamp", f );
330         addCallbacks( p_aout );
331         vlc_object_release( p_aout );
332     }
333     config_PutFloat( p_intf, "equalizer-preamp", f );
334 }
335
336 void Equalizer::setBand()
337 {
338     char psz_values[102]; memset( psz_values, 0, 102 );
339
340     /**\todo smoothing */
341
342     for( int i = 0 ; i< BANDS ; i++ )
343     {
344         char psz_val[5];
345         float f_val = (float)(  bands[i]->value() ) / 10 - 20 ;
346         sprintf( psz_values, "%s %f", psz_values, f_val );
347         sprintf( psz_val, "% 5.1f", f_val );
348         band_texts[i]->setText( band_frequencies[i] + "\n" + psz_val + "dB" );
349     }
350     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
351                                           VLC_OBJECT_AOUT, FIND_ANYWHERE);
352     if( p_aout )
353     {
354         delCallbacks( p_aout );
355         var_SetString( p_aout, "equalizer-bands", psz_values );
356         addCallbacks( p_aout );
357         vlc_object_release( p_aout );
358     }
359 }
360 void Equalizer::setValues( char *psz_bands, float f_preamp )
361 {
362     char *p = psz_bands;
363     if ( p )
364     {
365         for( int i = 0; i < 10; i++ )
366         {
367             char psz_val[5];
368             float f = strtof( p, &p );
369             int  i_val= (int)( ( f + 20 ) * 10 );
370             bands[i]->setValue(  i_val );
371             sprintf( psz_val, "% 5.1f", f );
372             band_texts[i]->setText( band_frequencies[i] + "\n" + psz_val +
373                                     "dB" );
374             if( p == NULL || *p == '\0' ) break;
375             p++;
376             if( *p == '\0' )  break;
377         }
378     }
379     char psz_val[5];
380     int i_val = (int)( ( f_preamp + 20 ) * 10 );
381     sprintf( psz_val, "%.1f", f_preamp );
382     ui.preampSlider->setValue( i_val );
383     ui.preampLabel->setText( qtr("Preamp\n") + psz_val + qtr("dB") );
384 }
385
386 void Equalizer::setPreset( int preset )
387 {
388     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
389                                                 VLC_OBJECT_AOUT, FIND_ANYWHERE);
390
391     char psz_values[102]; memset( psz_values, 0, 102 );
392     for( int i = 0 ; i< 10 ;i++ )
393         sprintf( psz_values, "%s %.1f", psz_values,
394                                         eqz_preset_10b[preset]->f_amp[i] );
395
396     if( p_aout )
397     {
398         delCallbacks( p_aout );
399         var_SetString( p_aout, "equalizer-bands", psz_values );
400         var_SetFloat( p_aout, "equalizer-preamp",
401                       eqz_preset_10b[preset]->f_preamp );
402         addCallbacks( p_aout );
403         vlc_object_release( p_aout );
404     }
405     config_PutPsz( p_intf, "equalizer-bands", psz_values );
406     config_PutFloat( p_intf, "equalizer-preamp",
407                     eqz_preset_10b[preset]->f_preamp );
408
409     setValues( psz_values, eqz_preset_10b[preset]->f_preamp );
410 }
411
412 void Equalizer::delCallbacks( aout_instance_t *p_aout )
413 {
414 //    var_DelCallback( p_aout, "equalizer-bands", EqzCallback, this );
415 //    var_DelCallback( p_aout, "equalizer-preamp", EqzCallback, this );
416 }
417
418 void Equalizer::addCallbacks( aout_instance_t *p_aout )
419 {
420 //    var_AddCallback( p_aout, "equalizer-bands", EqzCallback, this );
421 //    var_AddCallback( p_aout, "equalizer-preamp", EqzCallback, this );
422 }
423
424
425 /**********************************************************************
426  * Video filters / Adjust
427  **********************************************************************/
428
429 /**********************************************************************
430  * Audio filters
431  **********************************************************************/
432
433 /**********************************************************************
434  * Extended playbak controls
435  **********************************************************************/