1 /*****************************************************************************
2 * preferences.cpp : wxWindows plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2001 VideoLAN
5 * $Id: preferences.cpp,v 1.35 2003/10/17 16:40:09 gbazin Exp $
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
28 #include <errno.h> /* ENOMEM */
29 #include <string.h> /* strerror() */
37 #include "wxwindows.h"
38 #include <wx/notebook.h>
39 #include <wx/textctrl.h>
40 #include <wx/combobox.h>
41 #include <wx/spinctrl.h>
42 #include <wx/statline.h>
43 #include <wx/treectrl.h>
44 #include <wx/clntdata.h>
45 #include <wx/dynarray.h>
48 # define wxRB_SINGLE 0
51 #define GENERAL_ID 1242
52 #define PLUGIN_ID 1243
53 #define CAPABILITY_ID 1244
55 /*****************************************************************************
56 * Classes declarations.
57 *****************************************************************************/
59 class PrefsTreeCtrl : public wxTreeCtrl
64 PrefsTreeCtrl( wxWindow *parent, intf_thread_t *_p_intf,
65 PrefsDialog *p_prefs_dialog, wxBoxSizer *_p_sizer );
66 virtual ~PrefsTreeCtrl();
72 /* Event handlers (these functions should _not_ be virtual) */
73 void OnSelectTreeItem( wxTreeEvent& event );
74 void OnAdvanced( wxCommandEvent& event );
76 ConfigTreeData *FindModuleConfig( ConfigTreeData *config_data );
80 intf_thread_t *p_intf;
81 PrefsDialog *p_prefs_dialog;
84 vlc_bool_t b_advanced;
86 wxTreeItemId root_item;
87 wxTreeItemId general_item;
88 wxTreeItemId plugins_item;
93 ConfigData( wxPanel *_panel, int _i_conf_type,
94 vlc_bool_t _b_advanced, char *psz_name )
95 { panel = _panel; b_advanced = _b_advanced; b_config_list = VLC_FALSE;
96 i_config_type = _i_conf_type; option_name = wxU(psz_name); }
98 vlc_bool_t b_advanced;
100 vlc_bool_t b_config_list;
104 wxComboBox *combobox;
105 wxRadioButton *radio;
106 wxSpinCtrl *spinctrl;
107 wxCheckBox *checkbox;
108 wxTextCtrl *textctrl;
113 wxString option_name;
116 WX_DEFINE_ARRAY(ConfigData *, ArrayOfConfigData);
118 class PrefsPanel : public wxPanel
123 PrefsPanel( wxWindow *parent, intf_thread_t *_p_intf,
124 PrefsDialog *, int i_object_id, char *, char * );
125 virtual ~PrefsPanel() {}
128 void SwitchAdvanced( vlc_bool_t );
131 intf_thread_t *p_intf;
132 PrefsDialog *p_prefs_dialog;
134 vlc_bool_t b_advanced;
136 wxBoxSizer *config_sizer;
137 wxScrolledWindow *config_window;
139 ArrayOfConfigData config_array;
142 class ConfigTreeData : public wxTreeItemData
146 ConfigTreeData() { b_submodule = 0; panel = NULL; psz_section = NULL; }
147 virtual ~ConfigTreeData() { if( panel ) delete panel; }
149 vlc_bool_t b_submodule;
159 class ConfigEvtHandler : public wxEvtHandler
162 ConfigEvtHandler( intf_thread_t *p_intf, PrefsDialog *p_prefs_dialog );
163 virtual ~ConfigEvtHandler();
165 void ConfigEvtHandler::OnCommandEvent( wxCommandEvent& event );
169 DECLARE_EVENT_TABLE()
171 intf_thread_t *p_intf;
172 PrefsDialog *p_prefs_dialog;
175 /*****************************************************************************
177 *****************************************************************************/
179 /* IDs for the controls and the menu commands */
182 Notebook_Event = wxID_HIGHEST,
188 BEGIN_EVENT_TABLE(PrefsDialog, wxFrame)
190 EVT_BUTTON(wxID_OK, PrefsDialog::OnOk)
191 EVT_BUTTON(wxID_CANCEL, PrefsDialog::OnCancel)
192 EVT_BUTTON(wxID_SAVE, PrefsDialog::OnSave)
193 EVT_BUTTON(ResetAll_Event, PrefsDialog::OnResetAll)
194 EVT_CHECKBOX(Advanced_Event, PrefsDialog::OnAdvanced)
196 /* Don't destroy the window when the user closes it */
197 EVT_CLOSE(PrefsDialog::OnCancel)
200 // menu and control ids
203 PrefsTree_Ctrl = wxID_HIGHEST
206 BEGIN_EVENT_TABLE(PrefsTreeCtrl, wxTreeCtrl)
207 EVT_TREE_SEL_CHANGED(PrefsTree_Ctrl, PrefsTreeCtrl::OnSelectTreeItem)
208 EVT_COMMAND(Advanced_Event, wxEVT_USER_FIRST, PrefsTreeCtrl::OnAdvanced)
211 BEGIN_EVENT_TABLE(ConfigEvtHandler, wxEvtHandler)
212 EVT_BUTTON(-1, ConfigEvtHandler::OnCommandEvent)
213 EVT_TEXT(-1, ConfigEvtHandler::OnCommandEvent)
214 EVT_RADIOBOX(-1, ConfigEvtHandler::OnCommandEvent)
215 EVT_SPINCTRL(-1, ConfigEvtHandler::OnCommandEvent)
218 /*****************************************************************************
220 *****************************************************************************/
221 PrefsDialog::PrefsDialog( intf_thread_t *_p_intf, wxWindow *p_parent)
222 : wxFrame( p_parent, -1, wxU(_("Preferences")), wxDefaultPosition,
223 wxSize(700,450), wxDEFAULT_FRAME_STYLE )
225 /* Initializations */
227 SetIcon( *p_intf->p_sys->p_icon );
229 /* Create a panel to put everything in */
230 wxPanel *panel = new wxPanel( this, -1 );
231 panel->SetAutoLayout( TRUE );
233 /* Create the preferences tree control */
234 wxBoxSizer *controls_sizer = new wxBoxSizer( wxHORIZONTAL );
236 new PrefsTreeCtrl( panel, p_intf, this, controls_sizer );
239 wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
241 /* Create the buttons */
242 wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
243 ok_button->SetDefault();
244 wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
246 wxButton *save_button = new wxButton( panel, wxID_SAVE, wxU(_("Save")) );
247 wxButton *reset_button = new wxButton( panel, ResetAll_Event,
248 wxU(_("Reset All")) );
250 wxPanel *dummy_panel = new wxPanel( this, -1 );
251 wxCheckBox *advanced_checkbox =
252 new wxCheckBox( panel, Advanced_Event, wxU(_("Advanced options")) );
254 if( config_GetInt( p_intf, "advanced" ) )
256 advanced_checkbox->SetValue(TRUE);
257 wxCommandEvent dummy_event;
258 dummy_event.SetInt(TRUE);
259 OnAdvanced( dummy_event );
262 /* Place everything in sizers */
263 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
264 button_sizer->Add( ok_button, 0, wxALL, 5 );
265 button_sizer->Add( cancel_button, 0, wxALL, 5 );
266 button_sizer->Add( save_button, 0, wxALL, 5 );
267 button_sizer->Add( reset_button, 0, wxALL, 5 );
268 button_sizer->Add( dummy_panel, 1, wxALL, 5 );
269 button_sizer->Add( advanced_checkbox, 0, wxALL | wxALIGN_RIGHT |
270 wxALIGN_CENTER_VERTICAL, 0 );
271 button_sizer->Layout();
273 wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
274 wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
275 panel_sizer->Add( controls_sizer, 1, wxEXPAND | wxALL, 5 );
276 panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
277 panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
278 wxALL | wxEXPAND, 5 );
279 panel_sizer->Layout();
280 panel->SetSizer( panel_sizer );
281 main_sizer->Add( panel, 1, wxEXPAND, 0 );
282 main_sizer->Layout();
283 SetSizer( main_sizer );
286 PrefsDialog::~PrefsDialog()
290 /*****************************************************************************
292 *****************************************************************************/
295 /*****************************************************************************
297 *****************************************************************************/
298 void PrefsDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
300 prefs_tree->ApplyChanges();
302 prefs_tree->CleanChanges();
305 void PrefsDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
308 prefs_tree->CleanChanges();
311 void PrefsDialog::OnSave( wxCommandEvent& WXUNUSED(event) )
313 prefs_tree->ApplyChanges();
314 config_SaveConfigFile( p_intf, NULL );
318 void PrefsDialog::OnResetAll( wxCommandEvent& WXUNUSED(event) )
320 wxMessageDialog dlg( this,
321 wxU(_("Beware this will reset your VLC Media Player config file.\n"
322 "Are you sure you want to continue?")),
323 wxU(_("Reset config file")), wxYES_NO|wxNO_DEFAULT|wxCENTRE );
325 if ( dlg.ShowModal() == wxID_YES )
327 /* TODO: need to reset all the controls */
328 config_ResetAll( p_intf );
329 prefs_tree->CleanChanges();
330 config_SaveConfigFile( p_intf, NULL );
334 void PrefsDialog::OnAdvanced( wxCommandEvent& event )
336 wxCommandEvent newevent( wxEVT_USER_FIRST, Advanced_Event );
337 newevent.SetInt( event.GetInt() );
339 prefs_tree->AddPendingEvent( newevent );
342 /*****************************************************************************
343 * GetCapabilityHelp: Display the help for one capability.
344 *****************************************************************************/
345 static char * GetCapabilityHelp( char *psz_capability, int i_type)
347 if( psz_capability == NULL) return "";
349 if( !strcasecmp(psz_capability,"access") )
350 return i_type == 1 ? ACCESS_TITLE : ACCESS_HELP;
351 if( !strcasecmp(psz_capability,"audio filter") )
352 return i_type == 1 ? AUDIO_FILTER_TITLE : AUDIO_FILTER_HELP;
353 if( !strcasecmp(psz_capability,"audio output") )
354 return i_type == 1 ? AOUT_TITLE : AOUT_HELP;
355 if( !strcasecmp(psz_capability,"chroma") )
356 return i_type == 1 ? CHROMA_TITLE : CHROMA_HELP;
357 if( !strcasecmp(psz_capability,"decoder") )
358 return i_type == 1 ? DECODER_TITLE : DECODER_HELP;
359 if( !strcasecmp(psz_capability,"demux") )
360 return i_type == 1 ? DEMUX_TITLE : DEMUX_HELP;
361 if( !strcasecmp(psz_capability,"interface") )
362 return i_type == 1 ? INTERFACE_TITLE : INTERFACE_HELP;
363 if( !strcasecmp(psz_capability,"sout access") )
364 return i_type == 1 ? SOUT_TITLE : SOUT_HELP;
365 if( !strcasecmp(psz_capability,"subtitle demux") )
366 return i_type == 1 ? SUBTITLE_DEMUX_TITLE : SUBTITLE_DEMUX_HELP;
367 if( !strcasecmp(psz_capability,"text renderer") )
368 return i_type == 1 ? TEXT_TITLE : TEXT_HELP;
369 if( !strcasecmp(psz_capability,"video output") )
370 return i_type == 1 ? VOUT__TITLE : VOUT_HELP;
371 if( !strcasecmp(psz_capability,"video filter") )
372 return i_type == 1 ? VIDEO_FILTER_TITLE : VIDEO_FILTER_HELP;
377 /*****************************************************************************
378 * PrefsTreeCtrl class definition.
379 *****************************************************************************/
380 PrefsTreeCtrl::PrefsTreeCtrl( wxWindow *_p_parent, intf_thread_t *_p_intf,
381 PrefsDialog *_p_prefs_dialog,
382 wxBoxSizer *_p_sizer )
383 : wxTreeCtrl( _p_parent, PrefsTree_Ctrl, wxDefaultPosition, wxDefaultSize,
384 wxTR_NO_LINES | wxTR_FULL_ROW_HIGHLIGHT |
385 wxTR_LINES_AT_ROOT | wxTR_HIDE_ROOT |
386 wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS | wxSUNKEN_BORDER )
390 module_config_t *p_item;
393 /* Initializations */
395 p_prefs_dialog = _p_prefs_dialog;
397 p_parent = _p_parent;
398 b_advanced = VLC_FALSE;
400 root_item = AddRoot( wxT("") );
402 /* List the plugins */
403 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
404 if( !p_list ) return;
407 * Build a tree of the main options
409 ConfigTreeData *config_data = new ConfigTreeData;
410 config_data->psz_section = NULL;
411 config_data->i_object_id = GENERAL_ID;
412 config_data->psz_help = wraptext( GENERAL_HELP, WRAPCOUNT, ISUTF8 );
413 config_data->psz_section = strdup( GENERAL_TITLE );
414 general_item = AppendItem( root_item, wxU(_("General Settings")),
415 -1, -1, config_data );
417 for( i_index = 0; i_index < p_list->i_count; i_index++ )
419 p_module = (module_t *)p_list->p_values[i_index].p_object;
420 if( !strcmp( p_module->psz_object_name, "main" ) )
423 if( i_index < p_list->i_count )
425 /* We found the main module */
427 /* Enumerate config categories and store a reference so we can
428 * generate their config panel them when it is asked by the user. */
429 p_item = p_module->p_config;
433 switch( p_item->i_type )
435 case CONFIG_HINT_CATEGORY:
436 ConfigTreeData *config_data = new ConfigTreeData;
437 config_data->psz_section = strdup(p_item->psz_text);
438 if( p_item->psz_longtext )
440 config_data->psz_help =
441 wraptext( p_item->psz_longtext, WRAPCOUNT, ISUTF8 );
445 config_data->psz_help = NULL;
447 config_data->i_object_id = p_module->i_object_id;
449 /* Add the category to the tree */
450 AppendItem( general_item, wxU(p_item->psz_text),
451 -1, -1, config_data );
455 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
457 SortChildren( general_item );
462 * Build a tree of all the plugins
464 config_data = new ConfigTreeData;
465 config_data->psz_section = NULL;
466 config_data->i_object_id = PLUGIN_ID;
467 config_data->psz_help = wraptext( PLUGIN_HELP, WRAPCOUNT, ISUTF8 );
468 config_data->psz_section = strdup( PLUGIN_TITLE );
469 plugins_item = AppendItem( root_item, wxU(_("Plugins")),
472 for( i_index = 0; i_index < p_list->i_count; i_index++ )
474 p_module = (module_t *)p_list->p_values[i_index].p_object;
476 /* Exclude the main module */
477 if( !strcmp( p_module->psz_object_name, "main" ) )
480 /* Exclude empty plugins (submodules don't have config options, they
481 * are stored in the parent module) */
482 if( p_module->b_submodule )
483 p_item = ((module_t *)p_module->p_parent)->p_config;
485 p_item = p_module->p_config;
487 if( !p_item ) continue;
490 if( p_item->i_type & CONFIG_ITEM )
493 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
494 if( p_item->i_type == CONFIG_HINT_END ) continue;
496 /* Find the capability child item */
497 long cookie; size_t i_child_index;
498 wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
499 for( i_child_index = 0;
500 i_child_index < GetChildrenCount( plugins_item, FALSE );
503 if( !GetItemText(capability_item).Cmp(
504 wxU(p_module->psz_capability ) ) )
508 capability_item = GetNextChild( plugins_item, cookie );
511 if( i_child_index == GetChildrenCount( plugins_item, FALSE ) &&
512 p_module->psz_capability && *p_module->psz_capability )
514 /* We didn't find it, add it */
515 ConfigTreeData *config_data = new ConfigTreeData;
516 config_data->psz_section =
517 wraptext( GetCapabilityHelp( p_module->psz_capability , 1 ),
519 config_data->psz_help =
520 wraptext( GetCapabilityHelp( p_module->psz_capability , 2 ),
522 config_data->i_object_id = CAPABILITY_ID;
523 capability_item = AppendItem( plugins_item,
524 wxU(p_module->psz_capability),
528 /* Add the plugin to the tree */
529 ConfigTreeData *config_data = new ConfigTreeData;
530 config_data->b_submodule = p_module->b_submodule;
531 config_data->i_object_id = p_module->b_submodule ?
532 ((module_t *)p_module->p_parent)->i_object_id :
533 p_module->i_object_id;
534 config_data->psz_help = NULL;
535 AppendItem( capability_item, wxU(p_module->psz_object_name), -1, -1,
539 /* Sort all this mess */
540 long cookie; size_t i_child_index;
541 SortChildren( plugins_item );
542 wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
543 for( i_child_index = 0;
544 i_child_index < GetChildrenCount( plugins_item, FALSE );
547 capability_item = GetNextChild( plugins_item, cookie );
548 SortChildren( capability_item );
551 /* Clean-up everything */
552 vlc_list_release( p_list );
554 p_sizer->Add( this, 1, wxEXPAND | wxALL, 0 );
557 /* Update Tree Ctrl */
558 #ifndef WIN32 /* Workaround a bug in win32 implementation */
559 SelectItem( GetFirstChild( root_item, cookie ) );
562 Expand( general_item );
565 PrefsTreeCtrl::~PrefsTreeCtrl()
569 void PrefsTreeCtrl::ApplyChanges()
571 long cookie, cookie2;
572 ConfigTreeData *config_data;
574 /* Apply changes to the main module */
575 wxTreeItemId item = GetFirstChild( general_item, cookie );
576 for( size_t i_child_index = 0;
577 i_child_index < GetChildrenCount( general_item, FALSE );
580 config_data = (ConfigTreeData *)GetItemData( item );
581 if( config_data && config_data->panel )
583 config_data->panel->ApplyChanges();
586 item = GetNextChild( general_item, cookie );
589 /* Apply changes to the plugins */
590 item = GetFirstChild( plugins_item, cookie );
591 for( size_t i_child_index = 0;
592 i_child_index < GetChildrenCount( plugins_item, FALSE );
595 wxTreeItemId item2 = GetFirstChild( item, cookie2 );
596 for( size_t i_child_index = 0;
597 i_child_index < GetChildrenCount( item, FALSE );
600 config_data = (ConfigTreeData *)GetItemData( item2 );
601 if( config_data && config_data->panel )
603 config_data->panel->ApplyChanges();
606 item2 = GetNextChild( item, cookie2 );
609 item = GetNextChild( plugins_item, cookie );
613 void PrefsTreeCtrl::CleanChanges()
615 long cookie, cookie2;
616 ConfigTreeData *config_data;
618 config_data = !GetSelection() ? NULL :
619 FindModuleConfig( (ConfigTreeData *)GetItemData( GetSelection() ) );
622 config_data->panel->Hide();
623 p_sizer->Remove( config_data->panel );
626 /* Clean changes for the main module */
627 wxTreeItemId item = GetFirstChild( general_item, cookie );
628 for( size_t i_child_index = 0;
629 i_child_index < GetChildrenCount( general_item, FALSE );
632 config_data = (ConfigTreeData *)GetItemData( item );
633 if( config_data && config_data->panel )
635 delete config_data->panel;
636 config_data->panel = NULL;
639 item = GetNextChild( general_item, cookie );
642 /* Clean changes for the plugins */
643 item = GetFirstChild( plugins_item, cookie );
644 for( size_t i_child_index = 0;
645 i_child_index < GetChildrenCount( plugins_item, FALSE );
648 wxTreeItemId item2 = GetFirstChild( item, cookie2 );
649 for( size_t i_child_index = 0;
650 i_child_index < GetChildrenCount( item, FALSE );
653 config_data = (ConfigTreeData *)GetItemData( item2 );
655 if( config_data && config_data->panel )
657 delete config_data->panel;
658 config_data->panel = NULL;
661 item2 = GetNextChild( item, cookie2 );
664 item = GetNextChild( plugins_item, cookie );
670 OnSelectTreeItem( event );
674 ConfigTreeData *PrefsTreeCtrl::FindModuleConfig( ConfigTreeData *config_data )
676 /* We need this complexity because submodules don't have their own config
677 * options. They use the parent module ones. */
679 if( !config_data || !config_data->b_submodule )
684 long cookie, cookie2;
685 ConfigTreeData *config_new;
686 wxTreeItemId item = GetFirstChild( plugins_item, cookie );
687 for( size_t i_child_index = 0;
688 i_child_index < GetChildrenCount( plugins_item, FALSE );
691 wxTreeItemId item2 = GetFirstChild( item, cookie2 );
692 for( size_t i_child_index = 0;
693 i_child_index < GetChildrenCount( item, FALSE );
696 config_new = (ConfigTreeData *)GetItemData( item2 );
697 if( config_new && !config_new->b_submodule &&
698 config_new->i_object_id == config_data->i_object_id )
703 item2 = GetNextChild( item, cookie2 );
706 item = GetNextChild( plugins_item, cookie );
713 void PrefsTreeCtrl::OnSelectTreeItem( wxTreeEvent& event )
715 ConfigTreeData *config_data;
717 config_data = FindModuleConfig( (ConfigTreeData *)GetItemData(
718 event.GetOldItem() ) );
719 if( config_data && config_data->panel )
721 config_data->panel->Hide();
722 p_sizer->Remove( config_data->panel );
725 /* Don't use event.GetItem() because we also send fake events */
726 config_data = FindModuleConfig( (ConfigTreeData *)GetItemData(
730 if( !config_data->panel )
732 /* The panel hasn't been created yet. Let's do it. */
734 new PrefsPanel( p_parent, p_intf, p_prefs_dialog,
735 config_data->i_object_id,
736 config_data->psz_section,
737 config_data->psz_help );
738 config_data->panel->SwitchAdvanced( b_advanced );
742 config_data->panel->SwitchAdvanced( b_advanced );
743 config_data->panel->Show();
746 p_sizer->Add( config_data->panel, 3, wxEXPAND | wxALL, 0 );
751 void PrefsTreeCtrl::OnAdvanced( wxCommandEvent& event )
753 b_advanced = event.GetInt();
755 ConfigTreeData *config_data = !GetSelection() ? NULL :
756 FindModuleConfig( (ConfigTreeData *)GetItemData( GetSelection() ) );
759 config_data->panel->Hide();
760 p_sizer->Remove( config_data->panel );
766 OnSelectTreeItem( event );
770 /*****************************************************************************
771 * PrefsPanel class definition.
772 *****************************************************************************/
773 PrefsPanel::PrefsPanel( wxWindow* parent, intf_thread_t *_p_intf,
774 PrefsDialog *_p_prefs_dialog,
775 int i_object_id, char *psz_section, char *psz_help )
776 : wxPanel( parent, -1, wxDefaultPosition, wxDefaultSize )
778 module_config_t *p_item;
786 wxCheckBox *checkbox;
787 wxTextCtrl *textctrl;
791 vlc_bool_t b_has_advanced = VLC_FALSE;
792 module_t *p_module = NULL;
794 /* Initializations */
796 p_prefs_dialog =_p_prefs_dialog,
798 b_advanced = VLC_TRUE;
799 SetAutoLayout( TRUE );
801 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
804 if( i_object_id == PLUGIN_ID || i_object_id == GENERAL_ID ||
805 i_object_id == CAPABILITY_ID )
807 label = new wxStaticText( this, -1,wxU(_( psz_section )));
808 wxFont heading_font = label->GetFont();
809 heading_font.SetPointSize( heading_font.GetPointSize() + 5 );
810 label->SetFont( heading_font );
811 sizer->Add( label, 0, wxEXPAND | wxLEFT, 10 );
812 sizer->Add( new wxStaticLine( this, 0 ), 0,
813 wxEXPAND | wxLEFT | wxRIGHT, 2 );
815 help = new wxStaticText( this, -1, wxU(_( psz_help ) ) );
816 sizer->Add( help ,0 ,wxEXPAND | wxALL, 5 );
818 config_sizer = NULL; config_window = NULL;
822 /* Get a pointer to the module */
823 p_module = (module_t *)vlc_object_get( p_intf, i_object_id );
824 if( p_module->i_object_type != VLC_OBJECT_MODULE )
826 /* 0OOoo something went really bad */
830 /* Enumerate config options and add corresponding config boxes
831 * (submodules don't have config options, they are stored in the
833 if( p_module->b_submodule )
834 p_item = ((module_t *)p_module->p_parent)->p_config;
836 p_item = p_module->p_config;
838 /* Find the category if it has been specified */
839 if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
841 while( !p_item->i_type == CONFIG_HINT_CATEGORY ||
842 strcmp( psz_section, p_item->psz_text ) )
844 if( p_item->i_type == CONFIG_HINT_END )
850 /* Add a head title to the panel */
851 label = new wxStaticText( this, -1,
852 wxU(_(psz_section ? p_item->psz_text :
853 p_module->psz_longname )));
854 wxFont heading_font = label->GetFont();
855 heading_font.SetPointSize( heading_font.GetPointSize() + 5 );
856 label->SetFont( heading_font );
857 sizer->Add( label, 0, wxEXPAND | wxLEFT, 10 );
858 sizer->Add( new wxStaticLine( this, 0 ), 0,
859 wxEXPAND | wxLEFT | wxRIGHT, 2 );
861 /* Now put all the config options into a scrolled window */
862 config_sizer = new wxBoxSizer( wxVERTICAL );
863 config_window = new wxScrolledWindow( this, -1, wxDefaultPosition,
864 wxDefaultSize, wxSTATIC_BORDER | wxHSCROLL | wxVSCROLL );
865 config_window->SetAutoLayout( TRUE );
866 config_window->SetScrollRate( 5, 5 );
870 /* If a category has been specified, check we finished the job */
871 if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
872 strcmp( psz_section, p_item->psz_text ) )
875 /* put each config option in a separate panel so we can hide
876 * advanced options easily */
877 wxPanel *panel = new wxPanel( config_window, -1, wxDefaultPosition,
879 wxBoxSizer *panel_sizer = new wxBoxSizer( wxHORIZONTAL );
880 ConfigData *config_data =
881 new ConfigData( panel, p_item->i_type,
882 p_item->b_advanced, p_item->psz_name );
884 switch( p_item->i_type )
886 case CONFIG_ITEM_MODULE:
887 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
888 combo = new wxComboBox( panel, -1, wxU(p_item->psz_value),
889 wxDefaultPosition, wxDefaultSize,
890 0, NULL, wxCB_READONLY | wxCB_SORT );
892 /* build a list of available modules */
893 p_list = vlc_list_find( p_intf,
894 VLC_OBJECT_MODULE, FIND_ANYWHERE );
895 combo->Append( wxU(_("Default")), (void *)NULL );
896 combo->SetSelection( 0 );
897 for( int i_index = 0; i_index < p_list->i_count; i_index++ )
899 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
901 if( !strcmp( p_parser->psz_capability, p_item->psz_type ) )
903 combo->Append( wxU(p_parser->psz_longname),
904 p_parser->psz_object_name );
905 if( p_item->psz_value && !strcmp(p_item->psz_value,
906 p_parser->psz_object_name) )
907 combo->SetValue( wxU(p_parser->psz_longname) );
910 vlc_list_release( p_list );
912 combo->SetToolTip( wxU(p_item->psz_longtext) );
913 config_data->control.combobox = combo;
914 panel_sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL
916 panel_sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL
920 case CONFIG_ITEM_STRING:
921 case CONFIG_ITEM_FILE:
922 case CONFIG_ITEM_DIRECTORY:
923 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
924 panel_sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL
927 if( !p_item->ppsz_list )
929 textctrl = new wxTextCtrl( panel, -1,
930 wxU(p_item->psz_value),
934 textctrl->SetToolTip( wxU(p_item->psz_longtext) );
935 config_data->control.textctrl = textctrl;
936 panel_sizer->Add( textctrl, 1, wxALL, 5 );
940 combo = new wxComboBox( panel, -1, wxU(p_item->psz_value),
941 wxDefaultPosition, wxDefaultSize,
942 0, NULL, wxCB_READONLY|wxCB_SORT );
944 /* build a list of available options */
945 for( int i_index = 0; p_item->ppsz_list[i_index];
948 combo->Append( wxU(p_item->ppsz_list[i_index]) );
949 if( p_item->psz_value && !strcmp( p_item->psz_value,
950 p_item->ppsz_list[i_index] ) )
951 combo->SetSelection( i_index );
954 if( p_item->psz_value )
955 combo->SetValue( wxU(p_item->psz_value) );
956 combo->SetToolTip( wxU(p_item->psz_longtext) );
957 config_data->control.combobox = combo;
958 config_data->b_config_list = VLC_TRUE;
959 panel_sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL
963 if( p_item->i_type == CONFIG_ITEM_FILE )
965 button = new wxButton( panel, -1, wxU(_("Browse...")) );
966 panel_sizer->Add( button, 0, wxALIGN_CENTER_VERTICAL
968 button->SetClientData((void *)config_data);
970 if( p_item->b_advanced ) b_has_advanced = VLC_TRUE;
973 case CONFIG_ITEM_INTEGER:
974 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
975 spin = new wxSpinCtrl( panel, -1,
976 wxString::Format(wxT("%d"),
978 wxDefaultPosition, wxDefaultSize,
980 -16000, 16000, p_item->i_value);
981 spin->SetToolTip( wxU(p_item->psz_longtext) );
982 config_data->control.spinctrl = spin;
983 panel_sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL
985 panel_sizer->Add( spin, 0, wxALIGN_CENTER_VERTICAL
988 spin->SetClientData((void *)config_data);
989 if( p_item->b_advanced ) b_has_advanced = VLC_TRUE;
992 case CONFIG_ITEM_KEY:
994 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
995 wxCheckBox *alt = new wxCheckBox( panel, -1, wxU(_("Alt")) );
996 alt->SetValue( p_item->i_value & KEY_MODIFIER_ALT );
997 wxCheckBox *ctrl = new wxCheckBox( panel, -1, wxU(_("Ctrl")) );
998 ctrl->SetValue( p_item->i_value & KEY_MODIFIER_CTRL );
999 wxCheckBox *shift = new wxCheckBox( panel, -1,
1001 shift->SetValue( p_item->i_value & KEY_MODIFIER_SHIFT );
1002 combo = new wxComboBox( panel, -1, wxU("f"),
1003 wxDefaultPosition, wxDefaultSize, 0
1004 , NULL, wxCB_READONLY | wxCB_SORT );
1005 for( int i=0; i < sizeof(keys)/sizeof(key_descriptor_s); i++ )
1007 combo->Append( wxU(_(keys[i].psz_key_string)),
1008 (void*)&keys[i].i_key_code );
1010 combo->SetValue( wxU( KeyToString(
1011 p_item->i_value&~KEY_MODIFIER )));
1012 config_data->control.combobox = combo;
1013 panel_sizer->Add( label, 2, wxALIGN_CENTER_VERTICAL
1014 | wxALL | wxEXPAND, 5 );
1015 panel_sizer->Add( alt, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
1016 panel_sizer->Add( ctrl, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5);
1017 panel_sizer->Add( shift, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5);
1018 panel_sizer->Add( combo, 2, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5);
1022 case CONFIG_ITEM_FLOAT:
1023 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
1024 textctrl = new wxTextCtrl( panel, -1,
1025 wxString::Format(wxT("%f"),
1027 wxDefaultPosition, wxDefaultSize,
1028 wxTE_PROCESS_ENTER );
1029 textctrl->SetToolTip( wxU(p_item->psz_longtext) );
1030 config_data->control.textctrl = textctrl;
1031 panel_sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL
1033 panel_sizer->Add( textctrl, 0, wxALIGN_CENTER_VERTICAL
1035 if( p_item->b_advanced ) b_has_advanced = VLC_TRUE;
1038 case CONFIG_ITEM_BOOL:
1039 checkbox = new wxCheckBox( panel, -1, wxU(p_item->psz_text) );
1040 if( p_item->i_value ) checkbox->SetValue(TRUE);
1041 checkbox->SetToolTip( wxU(p_item->psz_longtext) );
1042 config_data->control.checkbox = checkbox;
1043 panel_sizer->Add( checkbox, 0, wxALL, 5 );
1044 if( p_item->b_advanced ) b_has_advanced = VLC_TRUE;
1048 delete panel; panel = NULL;
1054 /* Don't add items that were not recognized */
1055 if( panel == NULL ) continue;
1057 panel_sizer->Layout();
1058 panel->SetSizerAndFit( panel_sizer );
1060 /* Add the config data to our array so we can keep a trace of it */
1061 config_array.Add( config_data );
1063 config_sizer->Add( panel, 0, wxEXPAND | wxALL, 2 );
1065 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
1067 config_sizer->Layout();
1068 config_window->SetSizer( config_sizer );
1069 sizer->Add( config_window, 1, wxEXPAND | wxALL, 5 );
1071 /* And at last put a useful help string if available */
1072 if( psz_help && *psz_help )
1074 sizer->Add( new wxStaticLine( this, 0 ), 0,
1075 wxEXPAND | wxLEFT | wxRIGHT, 2 );
1076 help = new wxStaticText( this, -1, wxU(_(psz_help)),
1077 wxDefaultPosition, wxDefaultSize,
1080 sizer->Add( help ,0 ,wxEXPAND | wxALL, 5 );
1084 /* Intercept all menu events in our custom event handler */
1085 config_window->PushEventHandler(
1086 new ConfigEvtHandler( p_intf, p_prefs_dialog ) );
1092 void PrefsPanel::ApplyChanges()
1094 for( size_t i = 0; i < config_array.GetCount(); i++ )
1096 ConfigData *config_data = config_array.Item(i);
1098 switch( config_data->i_config_type )
1100 case CONFIG_ITEM_MODULE:
1101 config_PutPsz( p_intf, config_data->option_name.mb_str(), (char *)
1102 config_data->control.combobox->GetClientData(
1103 config_data->control.combobox->GetSelection() ) );
1105 case CONFIG_ITEM_STRING:
1106 case CONFIG_ITEM_FILE:
1107 case CONFIG_ITEM_DIRECTORY:
1108 if( !config_data->b_config_list )
1109 config_PutPsz( p_intf, config_data->option_name.mb_str(),
1110 config_data->control.textctrl->GetValue().mb_str() );
1112 config_PutPsz( p_intf, config_data->option_name.mb_str(),
1113 config_data->control.combobox->GetValue().mb_str() );
1115 case CONFIG_ITEM_BOOL:
1116 config_PutInt( p_intf, config_data->option_name.mb_str(),
1117 config_data->control.checkbox->IsChecked() );
1119 case CONFIG_ITEM_INTEGER:
1120 config_PutInt( p_intf, config_data->option_name.mb_str(),
1121 config_data->control.spinctrl->GetValue() );
1123 case CONFIG_ITEM_FLOAT:
1126 if( (wxSscanf(config_data->control.textctrl->GetValue(),
1127 wxT("%f"), &f_value) == 1) )
1128 config_PutFloat( p_intf, config_data->option_name.mb_str(),
1136 void PrefsPanel::SwitchAdvanced( vlc_bool_t b_new_advanced )
1138 if( b_advanced == b_new_advanced ) return;
1140 if( config_sizer && config_window )
1142 b_advanced = b_new_advanced;
1144 for( size_t i = 0; i < config_array.GetCount(); i++ )
1146 ConfigData *config_data = config_array.Item(i);
1147 if( config_data->b_advanced )
1149 config_data->panel->Show( b_advanced );
1150 config_sizer->Show( config_data->panel, b_advanced );
1154 config_sizer->Layout();
1155 config_window->FitInside();
1156 config_window->Refresh();
1161 /*****************************************************************************
1162 * A small helper class which intercepts all events
1163 *****************************************************************************/
1164 ConfigEvtHandler::ConfigEvtHandler( intf_thread_t *_p_intf,
1165 PrefsDialog *_p_prefs_dialog )
1167 /* Initializations */
1169 p_prefs_dialog = _p_prefs_dialog;
1172 ConfigEvtHandler::~ConfigEvtHandler()
1176 void ConfigEvtHandler::OnCommandEvent( wxCommandEvent& event )
1178 if( !event.GetEventObject() )
1184 ConfigData *config_data = (ConfigData *)
1185 ((wxEvtHandler *)event.GetEventObject())->GetClientData();
1193 if( config_data->i_config_type == CONFIG_ITEM_FILE )
1195 wxFileDialog dialog( p_prefs_dialog, wxU(_("Open file")),
1196 wxT(""), wxT(""), wxT("*.*"),
1197 #if defined( __WXMSW__ )
1203 if( dialog.ShowModal() == wxID_OK )
1205 config_data->control.textctrl->SetValue( dialog.GetPath() );
1209 switch( config_data->i_config_type )
1211 case CONFIG_ITEM_MODULE:
1213 case CONFIG_ITEM_STRING:
1215 case CONFIG_ITEM_FILE:
1217 case CONFIG_ITEM_INTEGER:
1219 case CONFIG_ITEM_FLOAT:
1221 case CONFIG_ITEM_BOOL: