]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/extrapanel.cpp
Save equalizer values so that they don't get overriden on filter enable
[vlc] / modules / gui / wxwindows / extrapanel.cpp
1 /*****************************************************************************
2  * extrapanel.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2004, 2003 VideoLAN
5  * $Id$
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/aout.h>
29 #include <aout_internal.h>
30 #include <vlc/vout.h>
31 #include <vlc/intf.h>
32
33 #include <math.h>
34
35 #include "wxwindows.h"
36
37 /*****************************************************************************
38  * Local class declarations.
39  *****************************************************************************/
40
41 /* FIXME */
42 #define SMOOTH_TIP N_( "If this setting is not zero, the bands will move " \
43                 "together when you move one. The higher the value is, the " \
44                 "more correlated their movement will be." )
45
46 static int IntfBandsCallback( vlc_object_t *, char const *,
47                               vlc_value_t, vlc_value_t, void * );
48 static int IntfPreampCallback( vlc_object_t *, char const *,
49                                vlc_value_t, vlc_value_t, void * );
50 static void ChangeFiltersString( intf_thread_t *, aout_instance_t *,
51                                  char *, vlc_bool_t );
52 static void ChangeVFiltersString( intf_thread_t *, char *, vlc_bool_t );
53
54
55 /* IDs for the controls and the menu commands */
56 enum
57 {
58     Notebook_Event,
59
60     Adjust_Event,
61     RestoreDefaults_Event,
62
63     Hue_Event,
64     Contrast_Event,
65     Brightness_Event,
66     Saturation_Event,
67     Gamma_Event,
68     Ratio_Event,
69
70     FiltersInfo_Event,
71
72     Filter0_Event, Filter1_Event, Filter2_Event, Filter3_Event, Filter4_Event,
73     Filter5_Event, Filter6_Event, Filter7_Event, Filter8_Event, Filter9_Event,
74
75     EqEnable_Event,
76     Eq2Pass_Event,
77     EqRestore_Event,
78
79     Smooth_Event,
80
81     Preamp_Event,
82
83     Band0_Event,Band1_Event,Band2_Event,Band3_Event,Band4_Event,
84     Band5_Event,Band6_Event,Band7_Event,Band8_Event,Band9_Event,
85
86     NormVol_Event, NVSlider_Event, HeadPhone_Event
87 };
88
89 BEGIN_EVENT_TABLE( ExtraPanel, wxPanel )
90     EVT_IDLE( ExtraPanel::OnIdle )
91
92     /* Equalizer */
93     EVT_CHECKBOX( EqEnable_Event, ExtraPanel::OnEnableEqualizer )
94     EVT_CHECKBOX( Eq2Pass_Event, ExtraPanel::OnEq2Pass )
95     EVT_BUTTON( EqRestore_Event, ExtraPanel::OnEqRestore )
96
97     EVT_COMMAND_SCROLL( Preamp_Event, ExtraPanel::OnPreamp )
98     EVT_COMMAND_SCROLL( Smooth_Event, ExtraPanel::OnEqSmooth )
99
100     EVT_COMMAND_SCROLL(Band0_Event, ExtraPanel::OnChangeEqualizer)
101     EVT_COMMAND_SCROLL(Band1_Event, ExtraPanel::OnChangeEqualizer)
102     EVT_COMMAND_SCROLL(Band2_Event, ExtraPanel::OnChangeEqualizer)
103     EVT_COMMAND_SCROLL(Band3_Event, ExtraPanel::OnChangeEqualizer)
104     EVT_COMMAND_SCROLL(Band4_Event, ExtraPanel::OnChangeEqualizer)
105     EVT_COMMAND_SCROLL(Band5_Event, ExtraPanel::OnChangeEqualizer)
106     EVT_COMMAND_SCROLL(Band6_Event, ExtraPanel::OnChangeEqualizer)
107     EVT_COMMAND_SCROLL(Band7_Event, ExtraPanel::OnChangeEqualizer)
108     EVT_COMMAND_SCROLL(Band8_Event, ExtraPanel::OnChangeEqualizer)
109     EVT_COMMAND_SCROLL(Band9_Event, ExtraPanel::OnChangeEqualizer)
110
111     /* Video */
112     EVT_CHECKBOX( Adjust_Event, ExtraPanel::OnEnableAdjust )
113     EVT_BUTTON( RestoreDefaults_Event, ExtraPanel::OnRestoreDefaults )
114
115     EVT_COMMAND_SCROLL(Hue_Event, ExtraPanel::OnAdjustUpdate)
116     EVT_COMMAND_SCROLL(Contrast_Event, ExtraPanel::OnAdjustUpdate)
117     EVT_COMMAND_SCROLL(Brightness_Event, ExtraPanel::OnAdjustUpdate)
118     EVT_COMMAND_SCROLL(Saturation_Event, ExtraPanel::OnAdjustUpdate)
119     EVT_COMMAND_SCROLL(Gamma_Event, ExtraPanel::OnAdjustUpdate)
120
121     EVT_BUTTON( FiltersInfo_Event, ExtraPanel::OnFiltersInfo )
122
123     EVT_CHECKBOX( Filter0_Event, ExtraPanel::OnSelectFilter )
124     EVT_CHECKBOX( Filter1_Event, ExtraPanel::OnSelectFilter )
125     EVT_CHECKBOX( Filter2_Event, ExtraPanel::OnSelectFilter )
126     EVT_CHECKBOX( Filter3_Event, ExtraPanel::OnSelectFilter )
127     EVT_CHECKBOX( Filter4_Event, ExtraPanel::OnSelectFilter )
128     EVT_CHECKBOX( Filter5_Event, ExtraPanel::OnSelectFilter )
129     EVT_CHECKBOX( Filter6_Event, ExtraPanel::OnSelectFilter )
130     EVT_CHECKBOX( Filter7_Event, ExtraPanel::OnSelectFilter )
131     EVT_CHECKBOX( Filter8_Event, ExtraPanel::OnSelectFilter )
132     EVT_CHECKBOX( Filter9_Event, ExtraPanel::OnSelectFilter )
133
134     /* Audio */
135     EVT_CHECKBOX( NormVol_Event, ExtraPanel::OnNormvol )
136     EVT_CHECKBOX( HeadPhone_Event, ExtraPanel::OnHeadphone )
137
138     EVT_COMMAND_SCROLL( NVSlider_Event, ExtraPanel::OnNormvolSlider )
139
140 END_EVENT_TABLE()
141
142 struct filter {
143     char *psz_filter;
144     char *psz_name;
145     char *psz_help;
146 };
147
148 static const struct filter vfilters[] =
149 {
150     { "clone", "Image clone", "Creates several clones of the image" },
151     { "distort", "Distortion", "Adds distorsion effects" },
152     { "invert", "Image inversion" , "Inverts the image colors" },
153     { "crop", "Image cropping", "Crops the image" },
154     { "motionblur", "Blurring", "Creates a motion blurring on the image" },
155     { "transform", "Transformation", "Rotates or flips the image" },
156     { NULL, NULL, NULL } /* Do not remove this line */
157 };
158
159 /*****************************************************************************
160  * Constructor.
161  *****************************************************************************/
162 ExtraPanel::ExtraPanel( intf_thread_t *_p_intf, wxWindow *_p_parent ):
163         wxPanel( _p_parent , -1, wxDefaultPosition, wxDefaultSize )
164 {
165
166     p_intf = _p_intf;
167     p_parent = _p_parent;
168     SetAutoLayout( TRUE );
169
170     wxBoxSizer *extra_sizer = new wxBoxSizer( wxHORIZONTAL );
171
172     notebook = new wxNotebook( this, Notebook_Event );
173
174     wxNotebookSizer *notebook_sizer = new wxNotebookSizer( notebook );
175
176     notebook->AddPage( VideoPanel( notebook ), wxU(_("Video")) );
177     notebook->AddPage( EqzPanel( notebook ), wxU(_("Equalizer")) );
178     notebook->AddPage( AudioPanel( notebook ), wxU(_("Audio")) );
179
180     extra_sizer->Add( notebook_sizer, 1, wxEXPAND, 0 );
181
182     SetSizerAndFit( extra_sizer );
183     extra_sizer->Layout();
184 }
185
186 ExtraPanel::~ExtraPanel()
187 {
188 }
189
190 /* Video Panel constructor */
191 wxPanel *ExtraPanel::VideoPanel( wxWindow *parent )
192 {
193     char *psz_filters;
194
195     wxPanel *panel = new wxPanel( parent, -1 );
196     wxBoxSizer *panel_sizer = new wxBoxSizer( wxHORIZONTAL );
197
198     /* Create static box to surround the adjust controls */
199     wxStaticBox *adjust_box =
200            new wxStaticBox( panel, -1, wxU(_("Adjust Image")) );
201     wxStaticBoxSizer *adjust_sizer =
202         new wxStaticBoxSizer( adjust_box, wxVERTICAL );
203     adjust_sizer->SetMinSize( -1, 50 );
204
205     /* Create flex grid */
206     wxFlexGridSizer *adjust_gridsizer =
207         new wxFlexGridSizer( 6, 2, 0, 0);
208     adjust_gridsizer->AddGrowableCol(1);
209
210     /* Create the adjust button */
211     wxCheckBox * adjust_check = new wxCheckBox( panel, Adjust_Event,
212                                                  wxU(_("Enable")));
213
214     /* Create the restore to defaults button */
215     restoredefaults_button =
216         new wxButton( panel, RestoreDefaults_Event,
217         wxU(_("Restore Defaults")), wxDefaultPosition);
218
219     wxStaticText *hue_text = new wxStaticText( panel, -1,
220                                        wxU(_("Hue")) );
221     hue_slider = new wxSlider ( panel, Hue_Event, 0, 0,
222                                 360, wxDefaultPosition, wxDefaultSize );
223
224     wxStaticText *contrast_text = new wxStaticText( panel, -1,
225                                        wxU(_("Contrast")) );
226     contrast_slider = new wxSlider ( panel, Contrast_Event, 0, 0,
227                                 200, wxDefaultPosition, wxDefaultSize);
228
229     wxStaticText *brightness_text = new wxStaticText( panel, -1,
230                                        wxU(_("Brightness")) );
231     brightness_slider = new wxSlider ( panel, Brightness_Event, 0, 0,
232                            200, wxDefaultPosition, wxDefaultSize) ;
233
234     wxStaticText *saturation_text = new wxStaticText( panel, -1,
235                                           wxU(_("Saturation")) );
236     saturation_slider = new wxSlider ( panel, Saturation_Event, 0, 0,
237                            300, wxDefaultPosition, wxDefaultSize );
238
239     wxStaticText *gamma_text = new wxStaticText( panel, -1,
240                                           wxU(_("Gamma")) );
241     gamma_slider = new wxSlider ( panel, Gamma_Event, 0, 0,
242                            100, wxDefaultPosition, wxDefaultSize );
243
244     adjust_gridsizer->Add( adjust_check, 1, wxEXPAND|wxALL, 2 );
245     adjust_gridsizer->Add( restoredefaults_button, 1, wxEXPAND|wxALL, 2 );
246     adjust_gridsizer->Add( hue_text, 1, wxEXPAND|wxALL, 2 );
247     adjust_gridsizer->Add( hue_slider, 1, wxEXPAND|wxALL, 2 );
248     adjust_gridsizer->Add( contrast_text, 1, wxEXPAND|wxALL, 2 );
249     adjust_gridsizer->Add( contrast_slider, 1, wxEXPAND|wxALL, 2 );
250     adjust_gridsizer->Add( brightness_text, 1, wxEXPAND|wxALL, 2 );
251     adjust_gridsizer->Add( brightness_slider, 1, wxEXPAND|wxALL, 2 );
252     adjust_gridsizer->Add( saturation_text, 1, wxEXPAND|wxALL, 2 );
253     adjust_gridsizer->Add( saturation_slider, 1, wxEXPAND|wxALL, 2 );
254     adjust_gridsizer->Add( gamma_text, 1, wxEXPAND|wxALL, 2 );
255     adjust_gridsizer->Add( gamma_slider, 1, wxEXPAND|wxALL, 2 );
256
257     adjust_sizer->Add( adjust_gridsizer, 1, wxEXPAND|wxALL, 2);
258
259     panel_sizer->Add( adjust_sizer , 1, wxTOP, 2 );
260
261 #if 0
262     /* Create sizer to surround the other controls */
263     wxBoxSizer *other_sizer = new wxBoxSizer( wxVERTICAL );
264
265     wxStaticBox *video_box =
266             new wxStaticBox( panel, -1, wxU(_("Video Options")) );
267     /* Create the sizer for the frame */
268     wxStaticBoxSizer *video_sizer =
269        new wxStaticBoxSizer( video_box, wxVERTICAL );
270     video_sizer->SetMinSize( -1, 50 );
271
272     static const wxString ratio_array[] =
273     {
274         wxT("4:3"),
275         wxT("16:9"),
276     };
277
278     wxBoxSizer *ratio_sizer = new wxBoxSizer( wxHORIZONTAL );
279     wxStaticText *ratio_text = new wxStaticText( panel, -1,
280                                           wxU(_("Aspect Ratio")) );
281
282     ratio_combo = new wxComboBox( panel, Ratio_Event, wxT(""),
283                                   wxDefaultPosition, wxSize( 80 , -1),
284                                   WXSIZEOF(ratio_array), ratio_array,
285                                   0 );
286
287     ratio_sizer->Add( ratio_text, 0, wxALL, 2 );
288     ratio_sizer->Add( ratio_combo, 0, wxALL, 2 );
289     ratio_sizer->Layout();
290
291     video_sizer->Add( ratio_sizer  , 0 , wxALL , 2 );
292     video_sizer->Layout();
293 #endif
294
295     wxStaticBox *filter_box =
296                   new wxStaticBox( panel, -1, wxU(_("Video Filters")) );
297     wxStaticBoxSizer *filter_sizer =
298                    new wxStaticBoxSizer( filter_box, wxHORIZONTAL );
299
300     wxBoxSizer *t_col_sizer = new wxBoxSizer( wxVERTICAL );
301
302
303     for( int i = 0 ; vfilters[i].psz_filter != NULL ; i++ )
304     {
305         wxCheckBox *box = new wxCheckBox( panel, Filter0_Event + i,
306                                           wxU( _( vfilters[i].psz_name ) ) );
307         t_col_sizer->Add( box, 0, wxALL, 4 );
308         box->SetToolTip( wxU( _( vfilters[i].psz_help ) ) );
309     }
310
311     filter_sizer->Add( t_col_sizer );
312     filter_sizer->Add( new wxButton( panel, FiltersInfo_Event,
313                             wxU(_("More info" ) ) ), 0, wxALL, 4 );
314 #if 0
315     other_sizer->Add( video_sizer, 0, wxALL | wxEXPAND , 0);
316     other_sizer->Add( filter_sizer, 0, wxALL | wxEXPAND , 0);
317     other_sizer->Layout();
318     panel_sizer->Add(other_sizer , 1 );
319 #endif
320
321     panel_sizer->Add( filter_sizer, 1, wxTOP|wxLEFT, 2 );
322
323     panel->SetSizerAndFit( panel_sizer );
324
325     /* Layout the whole panel */
326     panel_sizer->Layout();
327
328     panel_sizer->SetSizeHints( panel );
329
330     /* Write down initial values */
331     psz_filters = config_GetPsz( p_intf, "filter" );
332     if( psz_filters && strstr( psz_filters, "adjust" ) )
333     {
334         adjust_check->SetValue( 1 );
335         restoredefaults_button->Enable();
336         saturation_slider->Enable();
337         contrast_slider->Enable();
338         brightness_slider->Enable();
339         hue_slider->Enable();
340         gamma_slider->Enable();
341     }
342     else
343     {
344         adjust_check->SetValue( 0 );
345         restoredefaults_button->Disable();
346         saturation_slider->Disable();
347         contrast_slider->Disable();
348         brightness_slider->Disable();
349         hue_slider->Disable();
350         gamma_slider->Disable();
351     }
352     if( psz_filters ) free( psz_filters );
353
354     int i_value = config_GetInt( p_intf, "hue" );
355     if( i_value > 0 && i_value < 360 )
356         hue_slider->SetValue( i_value );
357     float f_value;
358     f_value = config_GetFloat( p_intf, "saturation" );
359     if( f_value > 0 && f_value < 5 )
360         saturation_slider->SetValue( (int)(100 * f_value) );
361     f_value = config_GetFloat( p_intf, "contrast" );
362     if( f_value > 0 && f_value < 4 )
363         contrast_slider->SetValue( (int)(100 * f_value) );
364     f_value = config_GetFloat( p_intf, "brightness" );
365     if( f_value > 0 && f_value < 2 )
366         brightness_slider->SetValue( (int)(100 * f_value) );
367     f_value = config_GetFloat( p_intf, "gamma" );
368     if( f_value > 0 && f_value < 10 )
369         gamma_slider->SetValue( (int)(10 * f_value) );
370
371     return panel;
372 }
373
374 /* Audio panel constructor */
375 wxPanel *ExtraPanel::AudioPanel( wxWindow *parent )
376 {
377     char *psz_filters;
378
379     wxPanel *panel = new wxPanel( parent, -1 );
380     wxBoxSizer *panel_sizer = new wxBoxSizer( wxHORIZONTAL );
381
382     /* Create static box to surround the adjust controls */
383     wxStaticBox *filter_box =
384            new wxStaticBox( panel, -1, wxU(_("Audio filters")) );
385     wxStaticBoxSizer *filter_sizer =
386         new wxStaticBoxSizer( filter_box, wxVERTICAL );
387     filter_sizer->SetMinSize( -1, 50 );
388
389     wxCheckBox * headphone_check = new wxCheckBox( panel, HeadPhone_Event,
390                                     wxU(_("Headphone virtualization")));
391     headphone_check->SetToolTip( wxU(_("This filter gives the feeling of a "
392              "5.1 speaker set when using a headphone." ) ) );
393
394     wxCheckBox * normvol_check = new wxCheckBox( panel, NormVol_Event,
395                                     wxU(_("Volume normalization")));
396     normvol_check->SetToolTip( wxU(_("This filter prevents the audio output "
397                          "power from going over a defined value." ) ) );
398
399     wxStaticText *normvol_label = new wxStaticText( panel, -1,
400                                    wxU( _("Maximum level") ) );
401
402     wxSlider *normvol_slider = new wxSlider ( panel, NVSlider_Event, 20, 5,
403                            100, wxDefaultPosition, wxSize( 100, -1 ) );
404
405     filter_sizer->Add( headphone_check, 0, wxALL, 4 );
406     filter_sizer->Add( normvol_check, 0, wxALL, 4 );
407     filter_sizer->Add( normvol_label, 0, wxALL, 4 );
408     filter_sizer->Add( normvol_slider, 0, wxALL, 4 );
409
410     panel_sizer->Add( filter_sizer, 1, wxTOP, 2 );
411     panel->SetSizerAndFit( panel_sizer );
412     panel_sizer->Layout();
413     panel_sizer->SetSizeHints( panel );
414
415     /* Write down initial values */
416     psz_filters = config_GetPsz( p_intf, "audio-filter" );
417     if( psz_filters )
418     {
419         headphone_check->SetValue( strstr( psz_filters, "headphone" ) );
420         normvol_check->SetValue( strstr( psz_filters, "normvol" ) );
421         free( psz_filters );
422     }
423     else
424     {
425         headphone_check->SetValue( 0 );
426         normvol_check->SetValue( 0 );
427     }
428
429     return panel;
430 }
431
432
433 static const wxString band_frequencies[] =
434 {
435     wxT(" 60 Hz"),
436     wxT("170 Hz"),
437     wxT("310 Hz"),
438     wxT("600 Hz"),
439     wxT(" 1 kHz"),
440     wxT(" 3 kHz"),
441     wxT(" 6 kHz"),
442     wxT("12 kHz"),
443     wxT("14 kHz"),
444     wxT("16 kHz")
445 };
446
447 /* Equalizer Panel constructor */
448 wxPanel *ExtraPanel::EqzPanel( wxWindow *parent )
449 {
450     wxPanel *panel = new wxPanel( parent, -1 );
451     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
452
453     /* Create static box to surround the adjust controls */
454     wxBoxSizer *top_sizer =
455         new wxBoxSizer( wxHORIZONTAL );
456
457     /* Create the enable button */
458     eq_chkbox =  new wxCheckBox( panel, EqEnable_Event,
459                             wxU(_("Enable") ) );
460     eq_chkbox->SetToolTip( wxU(_("Enable the equalizer. You can either "
461     "manually change the bands or use a preset (Audio Menu->Equalizer)." ) ) );
462     top_sizer->Add( eq_chkbox, 0, wxALL, 2 );
463
464     eq_2p_chkbox =  new wxCheckBox( panel, Eq2Pass_Event,
465                             wxU(_("2 Pass") ) );
466
467     eq_2p_chkbox->SetToolTip( wxU(_("If you enable this settting, the "
468      "equalizer filter will be applied twice. The effect will be sharper.") ) );
469
470     top_sizer->Add( eq_2p_chkbox, 0, wxALL, 2 );
471
472     top_sizer->Add( 0, 0, 1, wxALL, 2 );
473
474     top_sizer->Add( new wxButton( panel, EqRestore_Event,
475                                   wxU( _("Restore Defaults") ) ),
476                     0, wxALL, 2 );
477     top_sizer->Add( 0, 0, 1, wxALL, 2 );
478
479     wxStaticText *smooth_text = new wxStaticText( panel, -1, wxU( "Smooth :" ));
480     smooth_text->SetToolTip( wxU( SMOOTH_TIP ) );
481     top_sizer->Add( smooth_text, 0, wxALL, 2 );
482
483     smooth_slider =new wxSlider( panel, Smooth_Event, 0, 0, 10 ,
484                     wxDefaultPosition, wxSize( 100, -1 ) );
485     smooth_slider->SetToolTip( wxU( SMOOTH_TIP ) );
486     top_sizer->Add( smooth_slider, 0, wxALL, 2 );
487     i_smooth = 0;
488
489     /* Create flex grid */
490     wxFlexGridSizer *eq_gridsizer =
491         new wxFlexGridSizer( 2, 12, 0, 0);
492     eq_gridsizer->AddGrowableRow( 0 );
493     eq_gridsizer->AddGrowableCol( 1 );
494
495     preamp_slider = new wxSlider( panel, Preamp_Event, 80, 0, 400,
496                     wxDefaultPosition, wxSize( -1 , 90 ) , wxSL_VERTICAL );
497     eq_gridsizer->Add( preamp_slider, 1, wxEXPAND|wxALL, 2 );
498
499     eq_gridsizer->Add( 0, 0, 1, wxALL, 2 );
500
501     for( int i = 0 ; i < 10 ; i++ )
502     {
503         band_sliders[i] = new wxSlider( panel, Band0_Event + i, 200, 0, 400,
504                     wxDefaultPosition, wxSize( -1 , 90 ) , wxSL_VERTICAL );
505
506         i_values[i] = 200;
507         eq_gridsizer->Add( band_sliders[i], 1, wxEXPAND|wxALL, 2 );
508     }
509
510     preamp_text = new wxStaticText( panel, -1, wxT( "Preamp\n12.0dB" ) );
511     wxFont font= preamp_text->GetFont();
512     font.SetPointSize(7);
513     preamp_text->SetFont( font );
514     eq_gridsizer->Add( preamp_text, wxALL, 2 );
515
516     eq_gridsizer->Add( 0, 0, 1 );
517
518     for( int i = 0 ; i < 10 ; i++ )
519     {
520         band_texts[i] = new wxStaticText( panel, -1,
521                                 band_frequencies[i] + wxU("\n0.0dB" ) ) ;
522         eq_gridsizer->Add( band_texts[i], 1, wxEXPAND|wxALL, 2 );
523         wxFont font= band_texts[i]->GetFont();
524         font.SetPointSize(7);
525         band_texts[i]->SetFont( font );
526     }
527
528     panel_sizer->Add( top_sizer , 0 , wxTOP | wxEXPAND, 5 );
529     panel_sizer->Add( eq_gridsizer , 0 , wxEXPAND, 0 );
530
531     panel->SetSizer( panel_sizer );
532
533     panel_sizer->Layout();
534
535     panel_sizer->SetSizeHints( panel );
536
537     CheckAout();
538     return panel;
539 }
540
541 /*******************************************************
542  * Event handlers
543  *******************************************************/
544
545 /* Keep aout up to date and update the bands if needed */
546 void ExtraPanel::OnIdle( wxIdleEvent &event )
547 {
548     CheckAout();
549     if( b_update == VLC_TRUE )
550     {
551         if( b_my_update == VLC_TRUE )
552         {
553             b_update = b_my_update = VLC_FALSE;
554             return;
555         }
556         char *p = psz_bands;
557         for( int i = 0; i < 10; i++ )
558         {
559                 float f;
560                 char psz_val[5];
561                 int i_val;
562                 /* Read dB -20/20*/
563                 f = strtof( p, &p );
564                 i_val= (int)( ( f + 20 ) * 10 );
565                 band_sliders[i]->SetValue( 400 - i_val );
566                 i_values[i] = 400 - i_val;
567                 sprintf( psz_val, "%.1f", f );
568                 band_texts[i]->SetLabel( band_frequencies[i] + wxT("\n") +
569                                                 wxU( psz_val ) + wxT("dB") );
570                 if( p == NULL )
571                 {
572                     break;
573                 }
574                 p++;
575                 if( *p == 0 )
576                     break;
577         }
578         char psz_val[5];
579         int i_val = (int)( ( f_preamp + 20 ) * 10 );
580         sprintf( psz_val, "%.1f", f_preamp );
581         preamp_slider->SetValue( 400 - i_val );
582         const wxString preamp = wxT("Preamp\n");
583         preamp_text->SetLabel( preamp + wxU( psz_val ) + wxT( "dB" ) );
584         eq_chkbox->SetValue( TRUE );
585         b_update = VLC_FALSE;
586     }
587 }
588
589 /*************************
590  *  Equalizer Panel events
591  *************************/
592 void ExtraPanel::OnEnableEqualizer( wxCommandEvent &event )
593 {
594     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
595                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
596     ChangeFiltersString( p_intf,p_aout, "equalizer",
597                          event.IsChecked() ? VLC_TRUE : VLC_FALSE );
598
599     if( p_aout != NULL )
600         vlc_object_release( p_aout );
601 }
602
603 void ExtraPanel::OnEqRestore( wxCommandEvent &event )
604 {
605     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
606                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
607     if( p_aout == NULL )
608     {
609         vlc_value_t val;
610         vlc_bool_t b_previous = eq_chkbox->IsChecked();
611         val.f_float = 12.0;
612         IntfPreampCallback( NULL, NULL, val,val, this );
613         config_PutFloat( p_intf, "equalizer-preamp", 12.0 );
614         val.psz_string = strdup( "0 0 0 0 0 0 0 0 0 0" );
615         IntfBandsCallback( NULL, NULL, val,val, this );
616         config_PutPsz( p_intf, "equalizer-bands",
617                                 "0 0 0 0 0 0 0 0 0 0");
618         config_PutPsz( p_intf, "equalizer-preset","flat" );
619         eq_chkbox->SetValue( b_previous );
620     }
621     else
622     {
623         var_SetFloat( p_aout, "equalizer-preamp", 12.0 );
624         config_PutFloat( p_intf, "equalizer-preamp", 12.0 );
625         var_SetString( p_aout, "equalizer-bands",
626                                 "0 0 0 0 0 0 0 0 0 0");
627         config_PutPsz( p_intf, "equalizer-bands",
628                                 "0 0 0 0 0 0 0 0 0 0");
629         var_SetString( p_aout , "equalizer-preset" , "flat" );
630         config_PutPsz( p_intf, "equalizer-preset","flat" );
631         vlc_object_release( p_aout );
632     }
633 }
634
635 void ExtraPanel::OnEq2Pass( wxCommandEvent &event )
636 {
637     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
638                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
639
640     vlc_bool_t b_2p = event.IsChecked() ? VLC_TRUE : VLC_FALSE;
641
642     if( p_aout == NULL )
643     {
644         config_PutInt( p_intf, "equalizer-2pass", b_2p );
645     }
646     else
647     {
648         var_SetBool( p_aout, "equalizer-2pass", b_2p );
649         config_PutInt( p_intf, "equalizer-2pass", b_2p );
650         if( eq_chkbox->IsChecked() )
651         {
652             for( int i = 0; i < p_aout->i_nb_inputs; i++ )
653             {
654                 p_aout->pp_inputs[i]->b_restart = VLC_TRUE;
655             }
656         }
657         vlc_object_release( p_aout );
658     }
659 }
660
661 void ExtraPanel::OnEqSmooth( wxScrollEvent &event )
662 {
663     /* Max smoothing : 70% */
664     i_smooth = event.GetPosition() * 7;
665 }
666
667 void ExtraPanel::OnPreamp( wxScrollEvent &event )
668 {
669     float f= (float)( 400 - event.GetPosition() ) / 10 - 20 ;
670     char psz_val[5];
671
672     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
673                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
674
675     sprintf( psz_val, "%.1f", f );
676     const wxString preamp = wxT("Preamp\n");
677     preamp_text->SetLabel( preamp + wxU( psz_val ) + wxT( "dB" ) );
678
679     if( p_aout == NULL )
680     {
681         config_PutFloat( p_intf, "equalizer-preamp", f );
682     }
683     else
684     {
685         var_SetFloat( p_aout, "equalizer-preamp", f );
686         config_PutFloat( p_intf, "equalizer-preamp", f );
687         b_my_update = VLC_TRUE;
688         vlc_object_release( p_aout );
689     }
690 }
691
692 void ExtraPanel::OnChangeEqualizer( wxScrollEvent &event )
693 {
694     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
695                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
696     char psz_values[102];
697     memset( psz_values, 0, 102 );
698
699
700     /* Smoothing */
701     int i_diff = event.GetPosition() - i_values[  event.GetId() - Band0_Event ];
702     i_values[ event.GetId() - Band0_Event] = event.GetPosition();
703
704     for( int i = event.GetId() + 1 ; i <= Band9_Event ; i++ )
705     {
706         int i_new = band_sliders[ i-Band0_Event ]->GetValue() +
707            (int)( i_diff * pow( (float)i_smooth / 100 , i- event.GetId() ) ) ;
708         if( i_new < 0 ) i_new = 0;
709         if( i_new > 400 ) i_new = 400;
710         band_sliders[ i-Band0_Event ]->SetValue( i_new );
711     }
712     for( int i = Band0_Event ; i < event.GetId() ; i++ )
713     {
714         int i_new =   band_sliders[ i-Band0_Event ]->GetValue() +
715            (int)( i_diff * pow( (float)i_smooth / 100 , event.GetId() - i  ) );
716         if( i_new < 0 ) i_new = 0;
717         if( i_new > 400 ) i_new = 400;
718         band_sliders[ i-Band0_Event ]->SetValue( i_new );
719     }
720
721     /* Write the new bands values */
722     for( int i = 0 ; i < 10 ; i++ )
723     {
724         char psz_val[5];
725         float f_val = (float)( 400 - band_sliders[i]->GetValue() ) / 10- 20 ;
726         sprintf( psz_values, "%s %f", psz_values, f_val );
727         sprintf( psz_val, "%.1f", f_val );
728         band_texts[i]->SetLabel( band_frequencies[i] + wxT("\n") +
729                         wxU( psz_val ) + wxT("dB" ) );
730     }
731     if( p_aout == NULL )
732     {
733         config_PutPsz( p_intf, "equalizer-bands", psz_values );
734     }
735     else
736     {
737         var_SetString( p_aout, "equalizer-bands", psz_values );
738         config_PutPsz( p_intf, "equalizer-bands", psz_values );
739         b_my_update = VLC_TRUE;
740         vlc_object_release( p_aout );
741     }
742 }
743
744 /***********************
745  * Audio Panel events
746  ***********************/
747 void ExtraPanel::OnHeadphone( wxCommandEvent &event )
748 {
749     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
750                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
751     ChangeFiltersString( p_intf , p_aout, "headphone",
752                          event.IsChecked() ? VLC_TRUE : VLC_FALSE );
753     if( p_aout != NULL )
754         vlc_object_release( p_aout );
755 }
756
757 void ExtraPanel::OnNormvol( wxCommandEvent &event )
758 {
759     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
760                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
761     ChangeFiltersString( p_intf , p_aout, "normvol",
762                          event.IsChecked() ? VLC_TRUE : VLC_FALSE );
763     if( p_aout != NULL )
764         vlc_object_release( p_aout );
765 }
766
767 void ExtraPanel::OnNormvolSlider( wxScrollEvent &event )
768 {
769     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
770                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
771     if( p_aout != NULL )
772     {
773         var_SetFloat( p_aout, "norm-max-level", (float)event.GetPosition()/10 );
774         vlc_object_release( p_aout );
775     }
776     else
777     {
778         config_PutFloat( p_intf, "norm-max-level",
779                         (float)event.GetPosition()/10 );
780     }
781 }
782 /***********************
783  *  Video Panel events
784  ***********************/
785 void ExtraPanel::OnEnableAdjust(wxCommandEvent& event)
786 {
787     ChangeVFiltersString( p_intf,  "adjust",
788                           event.IsChecked() ? VLC_TRUE : VLC_FALSE );
789
790     if( event.IsChecked() )
791     {
792         restoredefaults_button->Enable();
793         brightness_slider->Enable();
794         saturation_slider->Enable();
795         contrast_slider->Enable();
796         hue_slider->Enable();
797         gamma_slider->Enable();
798     }
799     else
800     {
801         restoredefaults_button->Disable();
802         brightness_slider->Disable();
803         saturation_slider->Disable();
804         contrast_slider->Disable();
805         hue_slider->Disable();
806         gamma_slider->Disable();
807     }
808 }
809
810 void ExtraPanel::OnRestoreDefaults( wxCommandEvent &event)
811 {
812     hue_slider->SetValue(0);
813     saturation_slider->SetValue(100);
814     brightness_slider->SetValue(100);
815     contrast_slider->SetValue(100),
816     gamma_slider->SetValue(10);
817
818     wxScrollEvent *hscroll_event = new wxScrollEvent(0, Hue_Event, 0);
819     OnAdjustUpdate(*hscroll_event);
820
821     wxScrollEvent *sscroll_event = new wxScrollEvent(0, Saturation_Event, 100);
822     OnAdjustUpdate(*sscroll_event);
823
824     wxScrollEvent *bscroll_event = new wxScrollEvent(0, Brightness_Event, 100);
825     OnAdjustUpdate(*bscroll_event);
826
827     wxScrollEvent *cscroll_event = new wxScrollEvent(0, Contrast_Event, 100);
828     OnAdjustUpdate(*cscroll_event);
829
830     wxScrollEvent *gscroll_event = new wxScrollEvent(0, Gamma_Event, 10);
831     OnAdjustUpdate(*gscroll_event);
832
833 }
834
835 void ExtraPanel::OnAdjustUpdate( wxScrollEvent &event)
836 {
837     vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find(p_intf,
838                                  VLC_OBJECT_VOUT, FIND_ANYWHERE);
839     if( p_vout == NULL )
840     {
841         switch( event.GetId() )
842         {
843             case Hue_Event:
844                 config_PutInt( p_intf , "hue" , event.GetPosition() );
845                 break;
846
847             case Saturation_Event:
848                 config_PutFloat( p_intf , "saturation" ,
849                                 (float)event.GetPosition()/100 );
850                 break;
851
852             case Brightness_Event:
853                 config_PutFloat( p_intf , "brightness" ,
854                                 (float)event.GetPosition()/100 );
855                 break;
856
857             case Contrast_Event:
858                 config_PutFloat( p_intf , "contrast" ,
859                                 (float)event.GetPosition()/100 );
860                 break;
861
862             case Gamma_Event:
863                 config_PutFloat( p_intf , "gamma" ,
864                                 (float)event.GetPosition()/10 );
865                 break;
866         }
867     }
868     else
869     {
870         vlc_value_t val;
871         switch( event.GetId() )
872         {
873             case Hue_Event:
874                 val.i_int = event.GetPosition();
875                 var_Set( p_vout, "hue", val );
876                 config_PutInt( p_intf , "hue" , event.GetPosition() );
877                 break;
878
879             case Saturation_Event:
880                 val.f_float = (float)event.GetPosition() / 100;
881                 var_Set( p_vout, "saturation", val );
882                 config_PutFloat( p_intf , "saturation" ,
883                                 (float)event.GetPosition()/100 );
884                 break;
885
886             case Brightness_Event:
887                 val.f_float = (float)event.GetPosition() / 100;
888                 var_Set( p_vout, "brightness", val );
889                 config_PutFloat( p_intf , "brightness" ,
890                                 (float)event.GetPosition()/100 );
891                 break;
892
893             case Contrast_Event:
894                 val.f_float = (float)event.GetPosition() / 100;
895                 var_Set( p_vout, "contrast", val );
896                 config_PutFloat( p_intf , "contrast" ,
897                                 (float)event.GetPosition()/100 );
898                 break;
899
900             case Gamma_Event:
901                 val.f_float = (float)event.GetPosition() / 10;
902                 var_Set( p_vout, "gamma", val );
903                 config_PutFloat( p_intf , "gamma" ,
904                                 (float)event.GetPosition()/10 );
905                 break;
906         }
907         vlc_object_release(p_vout);
908     }
909 }
910
911 /* FIXME */
912 void ExtraPanel::OnRatio( wxCommandEvent& event )
913 {
914    config_PutPsz( p_intf, "aspect-ratio", ratio_combo->GetValue().mb_str() );
915 }
916
917
918 void ExtraPanel::OnSelectFilter(wxCommandEvent& event)
919 {
920     int i_filter = event.GetId() - Filter0_Event ;
921     if( vfilters[i_filter].psz_filter  )
922     {
923         ChangeVFiltersString( p_intf, vfilters[i_filter].psz_filter ,
924                               event.IsChecked() ? VLC_TRUE : VLC_FALSE );
925     }
926 }
927
928 void ExtraPanel::OnFiltersInfo(wxCommandEvent& event)
929 {
930     wxMessageBox( wxU( _("Select the video effects filters to apply. "
931                   "You must restart the stream for these settings to "
932                   "take effect.\n"
933                   "To configure the filters, go to the Preferences, "
934                   "and go to Modules/Video Filters. "
935                   "You can then configure each filter.\n"
936                   "If you want fine control over the filters ( to choose "
937                   "the order in which they are applied ), you need to enter "
938                   "manually a filters string (Preferences / General / Video)."
939                   ) ),
940                     wxU( _("More information" ) ), wxOK | wxICON_INFORMATION,
941                     this->p_parent );
942 }
943 /**********************************
944  * Other functions
945  **********************************/
946 void ExtraPanel::CheckAout()
947 {
948     aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf,
949                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
950     if( p_aout != NULL )
951     {
952         if( p_aout != p_intf->p_sys->p_aout )
953         {
954             /* We want to know if someone changes the bands */
955             if( var_AddCallback( p_aout, "equalizer-bands",
956                                     IntfBandsCallback, this ) )
957             {
958                 /* The variable does not exist yet, wait */
959                 vlc_object_release( p_aout );
960                 return;
961             }
962             if( var_AddCallback( p_aout, "equalizer-preamp",
963                                     IntfPreampCallback, this )  )
964             {
965                 vlc_object_release( p_aout );
966                 return;
967             }
968             /* Ok, we have our variables, make a first update round */
969             p_intf->p_sys->p_aout = p_aout;
970
971             f_preamp = var_GetFloat( p_aout, "equalizer-preamp" );
972             psz_bands = var_GetString( p_aout, "equalizer-bands" );
973             b_update = VLC_TRUE;
974         }
975         vlc_object_release( p_aout );
976     }
977 }
978
979
980 static void ChangeVFiltersString( intf_thread_t *p_intf,
981                                  char *psz_name, vlc_bool_t b_add )
982 {
983     vout_thread_t *p_vout;
984     char *psz_parser, *psz_string;
985
986     psz_string = config_GetPsz( p_intf, "filter" );
987
988     if( !psz_string ) psz_string = strdup("");
989
990     psz_parser = strstr( psz_string, psz_name );
991
992     if( b_add )
993     {
994         if( !psz_parser )
995         {
996             psz_parser = psz_string;
997             asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
998                             psz_string, psz_name );
999             free( psz_parser );
1000         }
1001         else
1002         {
1003             return;
1004         }
1005     }
1006     else
1007     {
1008         if( psz_parser )
1009         {
1010             memmove( psz_parser, psz_parser + strlen(psz_name) +
1011                             (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ),
1012                             strlen(psz_parser + strlen(psz_name)) + 1 );
1013
1014             /* Remove trailing : : */
1015             if( *(psz_string+strlen(psz_string ) -1 ) == ':' )
1016             {
1017                 *(psz_string+strlen(psz_string ) -1 ) = '\0';
1018             }
1019          }
1020          else
1021          {
1022              free( psz_string );
1023              return;
1024          }
1025     }
1026     /* Vout is not kept, so put that in the config */
1027     config_PutPsz( p_intf, "filter", psz_string );
1028
1029     /* Try to set on the fly */
1030     p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
1031                                               FIND_ANYWHERE );
1032     if( p_vout )
1033     {
1034         var_SetString( p_vout, "filter", psz_string );
1035         vlc_object_release( p_vout );
1036     }
1037
1038     free( psz_string );
1039 }
1040
1041
1042 static void ChangeFiltersString( intf_thread_t *p_intf,
1043                                  aout_instance_t * p_aout,
1044                                  char *psz_name, vlc_bool_t b_add )
1045 {
1046     char *psz_parser, *psz_string;
1047
1048     if( p_aout )
1049     {
1050         psz_string = var_GetString( p_aout, "audio-filter" );
1051     }
1052     else
1053     {
1054         psz_string = config_GetPsz( p_intf, "audio-filter" );
1055     }
1056
1057     if( !psz_string ) psz_string = strdup("");
1058
1059     psz_parser = strstr( psz_string, psz_name );
1060
1061     if( b_add )
1062     {
1063         if( !psz_parser )
1064         {
1065             psz_parser = psz_string;
1066             asprintf( &psz_string, (*psz_string) ? "%s,%s" : "%s%s",
1067                             psz_string, psz_name );
1068             free( psz_parser );
1069         }
1070         else
1071         {
1072             return;
1073         }
1074     }
1075     else
1076     {
1077         if( psz_parser )
1078         {
1079             memmove( psz_parser, psz_parser + strlen(psz_name) +
1080                             (*(psz_parser + strlen(psz_name)) == ',' ? 1 : 0 ),
1081                             strlen(psz_parser + strlen(psz_name)) + 1 );
1082
1083             if( *(psz_string+strlen(psz_string ) -1 ) == ',' )
1084             {
1085                 *(psz_string+strlen(psz_string ) -1 ) = '\0';
1086             }
1087          }
1088          else
1089          {
1090              free( psz_string );
1091              return;
1092          }
1093     }
1094
1095     if( p_aout == NULL )
1096     {
1097         config_PutPsz( p_intf, "audio-filter", psz_string );
1098     }
1099     else
1100     {
1101         var_SetString( p_aout, "audio-filter", psz_string );
1102         for( int i = 0; i < p_aout->i_nb_inputs; i++ )
1103         {
1104             p_aout->pp_inputs[i]->b_restart = VLC_TRUE;
1105         }
1106     }
1107     free( psz_string );
1108 }
1109
1110
1111 static int IntfBandsCallback( vlc_object_t *p_this, char const *psz_cmd,
1112                           vlc_value_t oldval, vlc_value_t newval, void *param )
1113 {
1114     ExtraPanel *p_panel = (ExtraPanel *)param;
1115
1116     p_panel->psz_bands = strdup( newval.psz_string );
1117     p_panel->b_update = VLC_TRUE;
1118
1119     return VLC_SUCCESS;
1120 }
1121
1122 static int IntfPreampCallback( vlc_object_t *p_this, char const *psz_cmd,
1123                           vlc_value_t oldval, vlc_value_t newval, void *param )
1124 {
1125     ExtraPanel *p_panel = (ExtraPanel *)param;
1126
1127     p_panel->f_preamp = newval.f_float;
1128     p_panel->b_update = VLC_TRUE;
1129
1130     return VLC_SUCCESS;
1131 }
1132
1133 #if 0
1134 /**********************************************************************
1135  * A small window to contain the extrapanel in its undocked state
1136  **********************************************************************/
1137 BEGIN_EVENT_TABLE(ExtraWindow, wxFrame)
1138 END_EVENT_TABLE()
1139
1140
1141 ExtraWindow::ExtraWindow( intf_thread_t *_p_intf, wxWindow *p_parent,
1142                           wxPanel *_extra_panel ):
1143        wxFrame( p_parent, -1, wxU(_("Extended controls")), wxDefaultPosition,
1144                  wxDefaultSize, wxDEFAULT_FRAME_STYLE )
1145 {
1146         fprintf(stderr,"Creating extrawindow\n");
1147     p_intf = _p_intf;
1148     SetIcon( *p_intf->p_sys->p_icon );
1149
1150     wxBoxSizer *window_sizer = new wxBoxSizer( wxVERTICAL );
1151     SetSizer( window_sizer );
1152 //    panel = new ExtraPanel(  p_intf, this );//_extra_panel;
1153
1154     panel = _extra_panel;
1155     window_sizer->Add( panel );
1156
1157     window_sizer->Layout();
1158     window_sizer->Fit( this );
1159
1160     Show();
1161 }
1162
1163 ExtraWindow::~ExtraWindow()
1164 {
1165     delete panel;
1166 }
1167 #endif