1 /*****************************************************************************
2 * preferences_widgets.cpp : wxWindows plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2004 VideoLAN
7 * Authors: Gildas Bazin <gbazin@videolan.org>
8 * Sigmund Augdal <sigmunau@idi.ntnu.no>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
29 #include <errno.h> /* ENOMEM */
30 #include <string.h> /* strerror() */
38 #include "wxwindows.h"
39 #include "preferences_widgets.h"
41 /*****************************************************************************
42 * CreateConfigControl wrapper
43 *****************************************************************************/
44 ConfigControl *CreateConfigControl( vlc_object_t *p_this,
45 module_config_t *p_item, wxWindow *parent )
47 ConfigControl *p_control = NULL;
49 switch( p_item->i_type )
51 case CONFIG_ITEM_MODULE:
52 p_control = new ModuleConfigControl( p_this, p_item, parent );
55 case CONFIG_ITEM_STRING:
58 p_control = new StringConfigControl( p_this, p_item, parent );
62 p_control = new StringListConfigControl( p_this, p_item, parent );
66 case CONFIG_ITEM_FILE:
67 case CONFIG_ITEM_DIRECTORY:
68 p_control = new FileConfigControl( p_this, p_item, parent );
71 case CONFIG_ITEM_INTEGER:
74 p_control = new IntegerListConfigControl( p_this, p_item, parent );
76 else if( p_item->i_min != 0 || p_item->i_max != 0 )
78 p_control = new RangedIntConfigControl( p_this, p_item, parent );
82 p_control = new IntegerConfigControl( p_this, p_item, parent );
87 p_control = new KeyConfigControl( p_this, p_item, parent );
90 case CONFIG_ITEM_FLOAT:
91 p_control = new FloatConfigControl( p_this, p_item, parent );
94 case CONFIG_ITEM_BOOL:
95 p_control = new BoolConfigControl( p_this, p_item, parent );
105 /*****************************************************************************
106 * ConfigControl implementation
107 *****************************************************************************/
108 ConfigControl::ConfigControl( vlc_object_t *_p_this,
109 module_config_t *p_item, wxWindow *parent )
110 : wxPanel( parent ), p_this( _p_this ),
111 pf_update_callback( NULL ), p_update_data( NULL ),
112 name( wxU(p_item->psz_name) ), i_type( p_item->i_type ),
113 b_advanced( p_item->b_advanced )
116 sizer = new wxBoxSizer( wxHORIZONTAL );
119 ConfigControl::~ConfigControl()
123 wxSizer *ConfigControl::Sizer()
128 wxString ConfigControl::GetName()
133 int ConfigControl::GetType()
138 vlc_bool_t ConfigControl::IsAdvanced()
143 void ConfigControl::SetUpdateCallback( void (*p_callback)( void * ),
146 pf_update_callback = p_callback;
147 p_update_data = p_data;
150 void ConfigControl::OnUpdate( wxCommandEvent& WXUNUSED(event) )
152 if( pf_update_callback )
154 pf_update_callback( p_update_data );
158 /*****************************************************************************
159 * KeyConfigControl implementation
160 *****************************************************************************/
161 wxString *KeyConfigControl::m_keysList = NULL;
163 KeyConfigControl::KeyConfigControl( vlc_object_t *p_this,
164 module_config_t *p_item, wxWindow *parent )
165 : ConfigControl( p_this, p_item, parent )
167 // Number of keys descriptions
168 unsigned int i_keys = sizeof(vlc_keys)/sizeof(key_descriptor_t);
170 // Init the keys decriptions array
171 if( m_keysList == NULL )
173 m_keysList = new wxString[i_keys];
174 for( unsigned int i = 0; i < i_keys; i++ )
176 m_keysList[i] = wxU(vlc_keys[i].psz_key_string);
180 label = new wxStaticText(this, -1, wxU(p_item->psz_text));
181 alt = new wxCheckBox( this, -1, wxU(_("Alt")) );
182 alt->SetValue( p_item->i_value & KEY_MODIFIER_ALT );
183 ctrl = new wxCheckBox( this, -1, wxU(_("Ctrl")) );
184 ctrl->SetValue( p_item->i_value & KEY_MODIFIER_CTRL );
185 shift = new wxCheckBox( this, -1, wxU(_("Shift")) );
186 shift->SetValue( p_item->i_value & KEY_MODIFIER_SHIFT );
187 combo = new wxComboBox( this, -1, wxT(""), wxDefaultPosition,
188 wxDefaultSize, i_keys, m_keysList,
190 for( unsigned int i = 0; i < i_keys; i++ )
192 combo->SetClientData( i, (void*)vlc_keys[i].i_key_code );
193 if( (unsigned int)vlc_keys[i].i_key_code ==
194 ( ((unsigned int)p_item->i_value) & ~KEY_MODIFIER ) )
196 combo->SetSelection( i );
197 combo->SetValue( wxU(_(vlc_keys[i].psz_key_string)) );
201 sizer->Add( label, 2, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
202 sizer->Add( alt, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
203 sizer->Add( ctrl, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
204 sizer->Add( shift, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
205 sizer->Add( combo, 2, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
207 this->SetSizerAndFit( sizer );
210 KeyConfigControl::~KeyConfigControl()
219 int KeyConfigControl::GetIntValue()
222 if( alt->IsChecked() )
224 result |= KEY_MODIFIER_ALT;
226 if( ctrl->IsChecked() )
228 result |= KEY_MODIFIER_CTRL;
230 if( shift->IsChecked() )
232 result |= KEY_MODIFIER_SHIFT;
234 int selected = combo->GetSelection();
237 result |= (int)combo->GetClientData( selected );
242 /*****************************************************************************
243 * ModuleConfigControl implementation
244 *****************************************************************************/
245 ModuleConfigControl::ModuleConfigControl( vlc_object_t *p_this,
246 module_config_t *p_item,
248 : ConfigControl( p_this, p_item, parent )
253 label = new wxStaticText(this, -1, wxU(p_item->psz_text));
254 combo = new wxComboBox( this, -1, wxL2U(p_item->psz_value),
255 wxDefaultPosition, wxDefaultSize,
256 0, NULL, wxCB_READONLY | wxCB_SORT );
258 /* build a list of available modules */
259 p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
260 combo->Append( wxU(_("Default")), (void *)NULL );
261 combo->SetSelection( 0 );
262 for( int i_index = 0; i_index < p_list->i_count; i_index++ )
264 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
266 if( !strcmp( p_parser->psz_capability, p_item->psz_type ) )
268 combo->Append( wxU(p_parser->psz_longname),
269 p_parser->psz_object_name );
270 if( p_item->psz_value && !strcmp(p_item->psz_value,
271 p_parser->psz_object_name) )
272 combo->SetValue( wxU(p_parser->psz_longname) );
275 vlc_list_release( p_list );
277 combo->SetToolTip( wxU(p_item->psz_longtext) );
278 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
279 sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
281 this->SetSizerAndFit( sizer );
284 ModuleConfigControl::~ModuleConfigControl()
289 wxString ModuleConfigControl::GetPszValue()
291 return wxU( (char *)combo->GetClientData( combo->GetSelection() ));
294 /*****************************************************************************
295 * StringConfigControl implementation
296 *****************************************************************************/
297 StringConfigControl::StringConfigControl( vlc_object_t *p_this,
298 module_config_t *p_item,
300 : ConfigControl( p_this, p_item, parent )
302 label = new wxStaticText(this, -1, wxU(p_item->psz_text));
303 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
304 textctrl = new wxTextCtrl( this, -1,
305 wxL2U(p_item->psz_value),
309 textctrl->SetToolTip( wxU(p_item->psz_longtext) );
310 sizer->Add( textctrl, 1, wxALL, 5 );
312 this->SetSizerAndFit( sizer );
315 StringConfigControl::~StringConfigControl()
320 wxString StringConfigControl::GetPszValue()
322 return textctrl->GetValue();
325 BEGIN_EVENT_TABLE(StringConfigControl, wxPanel)
327 EVT_TEXT(-1, StringConfigControl::OnUpdate)
330 /*****************************************************************************
331 * StringListConfigControl implementation
332 *****************************************************************************/
333 StringListConfigControl::StringListConfigControl( vlc_object_t *p_this,
334 module_config_t *p_item,
336 : ConfigControl( p_this, p_item, parent )
338 psz_default_value = p_item->psz_value;
339 if( psz_default_value ) psz_default_value = strdup( psz_default_value );
341 label = new wxStaticText(this, -1, wxU(p_item->psz_text));
342 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
343 combo = new wxComboBox( this, -1, wxT(""),
344 wxDefaultPosition, wxDefaultSize,
345 0, NULL, wxCB_READONLY );
346 UpdateCombo( p_item );
348 combo->SetToolTip( wxU(p_item->psz_longtext) );
349 sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
351 for( int i = 0; i < p_item->i_action; i++ )
354 new wxButton( this, wxID_HIGHEST+i,
355 wxU(p_item->ppsz_action_text[i]) );
356 sizer->Add( button, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
360 this->SetSizerAndFit( sizer );
363 StringListConfigControl::~StringListConfigControl()
365 if( psz_default_value ) free( psz_default_value );
368 void StringListConfigControl::UpdateCombo( module_config_t *p_item )
370 vlc_bool_t b_found = VLC_FALSE;
373 /* build a list of available options */
374 for( i_index = 0; i_index < p_item->i_list; i_index++ )
376 combo->Append( ( p_item->ppsz_list_text &&
377 p_item->ppsz_list_text[i_index] ) ?
378 wxU(p_item->ppsz_list_text[i_index]) :
379 wxL2U(p_item->ppsz_list[i_index]) );
380 combo->SetClientData( i_index, (void *)p_item->ppsz_list[i_index] );
381 if( ( p_item->psz_value &&
382 !strcmp( p_item->psz_value, p_item->ppsz_list[i_index] ) ) ||
383 ( !p_item->psz_value && !*p_item->ppsz_list[i_index] ) )
385 combo->SetSelection( i_index );
386 combo->SetValue( ( p_item->ppsz_list_text &&
387 p_item->ppsz_list_text[i_index] ) ?
388 wxU(p_item->ppsz_list_text[i_index]) :
389 wxL2U(p_item->ppsz_list[i_index]) );
394 if( p_item->psz_value && !b_found )
396 /* Add custom entry to list */
397 combo->Append( wxL2U(p_item->psz_value) );
398 combo->SetClientData( i_index, (void *)psz_default_value );
399 combo->SetSelection( i_index );
400 combo->SetValue( wxL2U(p_item->psz_value) );
404 BEGIN_EVENT_TABLE(StringListConfigControl, wxPanel)
406 EVT_BUTTON(-1, StringListConfigControl::OnAction)
409 EVT_TEXT(-1, StringListConfigControl::OnUpdate)
412 void StringListConfigControl::OnAction( wxCommandEvent& event )
414 int i_action = event.GetId() - wxID_HIGHEST;
416 module_config_t *p_item = config_FindConfig( p_this, GetName().mb_str() );
417 if( !p_item ) return;
419 if( i_action < 0 || i_action >= p_item->i_action ) return;
422 wxString value = GetPszValue();
423 *((const char **)&val.psz_string) = value.mb_str();
424 p_item->ppf_action[i_action]( p_this, GetName().mb_str(), val, val, 0 );
426 if( p_item->b_dirty )
429 UpdateCombo( p_item );
430 p_item->b_dirty = VLC_FALSE;
434 wxString StringListConfigControl::GetPszValue()
436 int selected = combo->GetSelection();
439 return wxL2U((char *)combo->GetClientData( selected ));
444 /*****************************************************************************
445 * FileConfigControl implementation
446 *****************************************************************************/
447 FileConfigControl::FileConfigControl( vlc_object_t *p_this,
448 module_config_t *p_item,
450 : ConfigControl( p_this, p_item, parent )
452 directory = p_item->i_type == CONFIG_ITEM_DIRECTORY;
453 label = new wxStaticText(this, -1, wxU(p_item->psz_text));
454 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
455 textctrl = new wxTextCtrl( this, -1,
456 wxL2U(p_item->psz_value),
460 textctrl->SetToolTip( wxU(p_item->psz_longtext) );
461 sizer->Add( textctrl, 1, wxALL, 5 );
462 browse = new wxButton( this, wxID_HIGHEST, wxU(_("Browse...")) );
463 sizer->Add( browse, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
465 this->SetSizerAndFit( sizer );
468 BEGIN_EVENT_TABLE(FileConfigControl, wxPanel)
470 EVT_BUTTON(wxID_HIGHEST, FileConfigControl::OnBrowse)
473 void FileConfigControl::OnBrowse( wxCommandEvent& event )
477 wxDirDialog dialog( this, wxU(_("Choose directory")) );
479 if( dialog.ShowModal() == wxID_OK )
481 textctrl->SetValue( dialog.GetPath() );
486 wxFileDialog dialog( this, wxU(_("Choose file")),
487 wxT(""), wxT(""), wxT("*.*"),
488 #if defined( __WXMSW__ )
494 if( dialog.ShowModal() == wxID_OK )
496 textctrl->SetValue( dialog.GetPath() );
501 FileConfigControl::~FileConfigControl()
506 wxString FileConfigControl::GetPszValue()
508 return textctrl->GetValue();
511 /*****************************************************************************
512 * IntegerConfigControl implementation
513 *****************************************************************************/
514 BEGIN_EVENT_TABLE(IntegerConfigControl, wxPanel)
515 EVT_TEXT(-1, IntegerConfigControl::OnUpdate)
516 EVT_COMMAND_SCROLL(-1, IntegerConfigControl::OnUpdate)
519 IntegerConfigControl::IntegerConfigControl( vlc_object_t *p_this,
520 module_config_t *p_item,
522 : ConfigControl( p_this, p_item, parent )
524 label = new wxStaticText(this, -1, wxU(p_item->psz_text));
525 spin = new wxSpinCtrl( this, -1,
526 wxString::Format(wxT("%d"),
528 wxDefaultPosition, wxDefaultSize,
530 -100000000, 100000000, p_item->i_value);
531 spin->SetToolTip( wxU(p_item->psz_longtext) );
532 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
533 sizer->Add( spin, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
535 this->SetSizerAndFit( sizer );
536 i_value = p_item->i_value;
539 IntegerConfigControl::~IntegerConfigControl()
544 int IntegerConfigControl::GetIntValue()
546 /* We avoid using GetValue because of a recursion bug with wxSpinCtrl with
548 return i_value; //spin->GetValue();
551 void IntegerConfigControl::OnUpdate( wxCommandEvent &event )
553 i_value = event.GetInt();
554 ConfigControl::OnUpdate( event );
557 /*****************************************************************************
558 * IntegerListConfigControl implementation
559 *****************************************************************************/
560 IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *p_this,
561 module_config_t *p_item,
563 : ConfigControl( p_this, p_item, parent )
565 label = new wxStaticText(this, -1, wxU(p_item->psz_text));
566 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
567 combo = new wxComboBox( this, -1, wxT(""),
568 wxDefaultPosition, wxDefaultSize,
569 0, NULL, wxCB_READONLY );
571 UpdateCombo( p_item );
573 combo->SetToolTip( wxU(p_item->psz_longtext) );
574 sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
577 this->SetSizerAndFit( sizer );
580 IntegerListConfigControl::~IntegerListConfigControl()
584 void IntegerListConfigControl::UpdateCombo( module_config_t *p_item )
586 /* build a list of available options */
587 for( int i_index = 0; i_index < p_item->i_list; i_index++ )
589 if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
591 combo->Append( wxU(p_item->ppsz_list_text[i_index]) );
595 combo->Append( wxString::Format(wxT("%i"),
596 p_item->pi_list[i_index]) );
598 combo->SetClientData( i_index, (void *)p_item->pi_list[i_index] );
599 if( p_item->i_value == p_item->pi_list[i_index] )
601 combo->SetSelection( i_index );
602 if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
604 combo->SetValue( wxU(p_item->ppsz_list_text[i_index]) );
608 combo->SetValue( wxString::Format(wxT("%i"),
609 p_item->pi_list[i_index]) );
615 BEGIN_EVENT_TABLE(IntegerListConfigControl, wxPanel)
617 EVT_BUTTON(-1, IntegerListConfigControl::OnAction)
620 void IntegerListConfigControl::OnAction( wxCommandEvent& event )
622 int i_action = event.GetId() - wxID_HIGHEST;
624 module_config_t *p_item;
625 p_item = config_FindConfig( p_this, GetName().mb_str() );
626 if( !p_item ) return;
628 if( i_action < 0 || i_action >= p_item->i_action ) return;
631 val.i_int = GetIntValue();
632 p_item->ppf_action[i_action]( p_this, GetName().mb_str(), val, val, 0 );
634 if( p_item->b_dirty )
637 UpdateCombo( p_item );
638 p_item->b_dirty = VLC_FALSE;
642 int IntegerListConfigControl::GetIntValue()
644 int selected = combo->GetSelection();
647 return (int)combo->GetClientData( selected );
652 /*****************************************************************************
653 * RangedIntConfigControl implementation
654 *****************************************************************************/
655 BEGIN_EVENT_TABLE(RangedIntConfigControl, wxPanel)
656 EVT_COMMAND_SCROLL(-1, RangedIntConfigControl::OnUpdate)
659 RangedIntConfigControl::RangedIntConfigControl( vlc_object_t *p_this,
660 module_config_t *p_item,
662 : ConfigControl( p_this, p_item, parent )
664 label = new wxStaticText(this, -1, wxU(p_item->psz_text));
665 slider = new wxSlider( this, -1, p_item->i_value, p_item->i_min,
666 p_item->i_max, wxDefaultPosition, wxDefaultSize,
667 wxSL_LABELS | wxSL_HORIZONTAL );
668 slider->SetToolTip( wxU(p_item->psz_longtext) );
669 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
670 sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
672 this->SetSizerAndFit( sizer );
675 RangedIntConfigControl::~RangedIntConfigControl()
680 int RangedIntConfigControl::GetIntValue()
682 return slider->GetValue();
685 /*****************************************************************************
686 * FloatConfigControl implementation
687 *****************************************************************************/
688 BEGIN_EVENT_TABLE(FloatConfigControl, wxPanel)
689 EVT_TEXT(-1, FloatConfigControl::OnUpdate)
692 FloatConfigControl::FloatConfigControl( vlc_object_t *p_this,
693 module_config_t *p_item,
695 : ConfigControl( p_this, p_item, parent )
697 label = new wxStaticText(this, -1, wxU(p_item->psz_text));
698 textctrl = new wxTextCtrl( this, -1,
699 wxString::Format(wxT("%f"),
701 wxDefaultPosition, wxDefaultSize,
702 wxTE_PROCESS_ENTER );
703 textctrl->SetToolTip( wxU(p_item->psz_longtext) );
704 sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
705 sizer->Add( textctrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
707 this->SetSizerAndFit( sizer );
710 FloatConfigControl::~FloatConfigControl()
715 float FloatConfigControl::GetFloatValue()
718 if( (wxSscanf(textctrl->GetValue(), wxT("%f"), &f_value) == 1) )
723 /*****************************************************************************
724 * BoolConfigControl implementation
725 *****************************************************************************/
726 BEGIN_EVENT_TABLE(BoolConfigControl, wxPanel)
727 EVT_CHECKBOX(-1, BoolConfigControl::OnUpdate)
730 BoolConfigControl::BoolConfigControl( vlc_object_t *p_this,
731 module_config_t *p_item,
733 : ConfigControl( p_this, p_item, parent )
735 checkbox = new wxCheckBox( this, -1, wxU(p_item->psz_text) );
736 if( p_item->i_value ) checkbox->SetValue(TRUE);
737 checkbox->SetToolTip( wxU(p_item->psz_longtext) );
738 sizer->Add( checkbox, 0, wxALL, 5 );
740 this->SetSizerAndFit( sizer );
743 BoolConfigControl::~BoolConfigControl()
748 int BoolConfigControl::GetIntValue()
750 if( checkbox->IsChecked() ) return 1;