]> git.sesse.net Git - vlc/blob - modules/gui/win32/preferences.cpp
* ./src/misc/modules.c: the module linked list is going bye bye. We now use
[vlc] / modules / gui / win32 / preferences.cpp
1 /*****************************************************************************\r
2  * preferences.cpp: the "Preferences" dialog box\r
3  *****************************************************************************\r
4  * Copyright (C) 2002 VideoLAN\r
5  *\r
6  * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program; if not, write to the Free Software\r
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
21  *****************************************************************************/\r
22 \r
23 #include <vcl.h>\r
24 #pragma hdrstop\r
25 \r
26 #include <stdlib.h>                                      /* malloc(), free() */\r
27 #include <string.h>                                                /* strcmp */\r
28 \r
29 #include <vlc/vlc.h>\r
30 #include <vlc/intf.h>\r
31 \r
32 #include "preferences.h"\r
33 #include "win32_common.h"\r
34 \r
35 //---------------------------------------------------------------------------\r
36 //#pragma package(smart_init)\r
37 #pragma link "CSPIN"\r
38 #pragma resource "*.dfm"\r
39 \r
40 extern intf_thread_t *p_intfGlobal;\r
41 \r
42 \r
43 /****************************************************************************\r
44  * Functions to help components creation\r
45  ****************************************************************************/\r
46 __fastcall TGroupBoxPref::TGroupBoxPref( TComponent* Owner,\r
47             module_config_t *p_config_arg ) : TGroupBox( Owner )\r
48 {\r
49     p_config = p_config_arg;\r
50     Caption = p_config->psz_text;\r
51 }\r
52 //---------------------------------------------------------------------------\r
53 TListView * __fastcall TGroupBoxPref::CreateListView( TWinControl *Parent,\r
54             int Left, int Width, int Top, int Height, TViewStyle ViewStyle )\r
55 {\r
56     TListView *ListView = new TListView( Parent );\r
57     ListView->Parent = Parent;\r
58     ListView->ViewStyle = ViewStyle;\r
59     ListView->Left = Left;\r
60     ListView->Width = Width;\r
61     ListView->Top = Top;\r
62     ListView->Height = Height;\r
63     return ListView;\r
64 }\r
65 //---------------------------------------------------------------------------\r
66 TButton * __fastcall TGroupBoxPref::CreateButton( TWinControl *Parent,\r
67             int Left, int Width, int Top, int Height, AnsiString Caption )\r
68 {\r
69     TButton *Button = new TButton( Parent );\r
70     Button->Parent = Parent;\r
71     Button->Left = Left;\r
72     Button->Width = Width;\r
73     Button->Top = Top;\r
74     Button->Height = Height;\r
75     Button->Caption = Caption;\r
76     return Button;\r
77 }\r
78 //---------------------------------------------------------------------------\r
79 TCheckBox * __fastcall TGroupBoxPref::CreateCheckBox( TWinControl *Parent,\r
80             int Left, int Width, int Top, int Height, AnsiString Caption )\r
81 {\r
82     TCheckBox *CheckBox = new TCheckBox( Parent );\r
83     CheckBox->Parent = Parent;\r
84     CheckBox->Left = Left;\r
85     CheckBox->Width = Width;\r
86     CheckBox->Top = Top;\r
87     CheckBox->Height = Height;\r
88     CheckBox->Caption = Caption;\r
89     return CheckBox;\r
90 }\r
91 //---------------------------------------------------------------------------\r
92 TLabel * __fastcall TGroupBoxPref::CreateLabel( TWinControl *Parent,\r
93             int Left, int Width, int Top, int Height, AnsiString Caption,\r
94             bool WordWrap )\r
95 {\r
96     TLabel *Label = new TLabel( Parent );\r
97     Label->Parent = Parent;\r
98     Label->Caption = Caption;\r
99     Label->Left = Left;\r
100     Label->Width = Width;\r
101     Label->Top = Top;\r
102     Label->Height = Height;\r
103     Label->WordWrap = WordWrap;\r
104     return Label;\r
105 }\r
106 //---------------------------------------------------------------------------\r
107 TEdit * __fastcall TGroupBoxPref::CreateEdit( TWinControl *Parent,\r
108             int Left, int Width, int Top, int Height, AnsiString Text )\r
109 {\r
110     TEdit *Edit = new TEdit( Parent );\r
111     Edit->Parent = Parent;\r
112     Edit->Left = Left;\r
113     Edit->Width = Width;\r
114     Edit->Top = Top;\r
115     Edit->Height = Height;\r
116     Edit->Text = Text;\r
117     return Edit;\r
118 }\r
119 //---------------------------------------------------------------------------\r
120 TCSpinEdit * __fastcall TGroupBoxPref::CreateSpinEdit( TWinControl *Parent,\r
121             int Left, int Width, int Top, int Height,\r
122             long Min, long Max, long Value )\r
123 {\r
124     TCSpinEdit *SpinEdit = new TCSpinEdit( Parent );\r
125     SpinEdit->Parent = Parent;\r
126     SpinEdit->Left = Left;\r
127     SpinEdit->Width = Width;\r
128     SpinEdit->Top = Top;\r
129     SpinEdit->Height = Height;\r
130     SpinEdit->MinValue = Min;\r
131     SpinEdit->MaxValue = Max;\r
132     SpinEdit->Value = Value;\r
133     return SpinEdit;\r
134 }\r
135 //---------------------------------------------------------------------------\r
136 void __fastcall TGroupBoxPref::UpdateChanges()\r
137 {\r
138 }\r
139 \r
140 \r
141 /****************************************************************************\r
142  * GroupBox for module management\r
143  ****************************************************************************/\r
144 __fastcall TGroupBoxPlugin::TGroupBoxPlugin( TComponent* Owner,\r
145             module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
146 {\r
147     /* init listview */\r
148     ListView = CreateListView( this, 16, 164, 24, 160, vsReport );\r
149     ListView->ReadOnly = true;\r
150     ListView->Columns->Add();\r
151     ListView->Columns->Items[0]->Width = 160;\r
152     ListView->Columns->Items[0]->Caption = "Name";//p_config->psz_text;\r
153     ListView->OnSelectItem = ListViewSelectItem;\r
154 \r
155     /* init description label */\r
156     LabelDesc = CreateLabel( this, 230, 225, 50, 52,\r
157                              p_config->psz_longtext, true );\r
158 \r
159     /* init hint label */\r
160     LabelHint = CreateLabel( this, 230, 225, 135, 13, "", false );\r
161 \r
162     /* init configure button */\r
163     ButtonConfig = CreateButton( this, 16, 70, 192, 25, "Configure" );\r
164     ButtonConfig->Enabled = false;\r
165     ButtonConfig->OnClick = ButtonConfigClick;\r
166 \r
167     /* init select button */\r
168     ButtonSelect = CreateButton( this, 110, 70, 192, 25, "Select" );\r
169     ButtonSelect->OnClick = ButtonSelectClick;\r
170 \r
171     /* init 'Selected' label */\r
172     LabelSelected = CreateLabel( this, 230, 45, 198, 13, "Selected", false );\r
173 \r
174     /* init 'Selected' edit */\r
175     Edit = CreateEdit( this, 280, 164, 194, 21, "" );\r
176     vlc_mutex_lock( p_config->p_lock );\r
177     Edit->Text = p_config->psz_value ? p_config->psz_value : "";\r
178     vlc_mutex_unlock( p_config->p_lock );\r
179 \r
180     Height = 233;\r
181 };\r
182 //---------------------------------------------------------------------------\r
183 void __fastcall TGroupBoxPlugin::ListViewSelectItem( TObject *Sender,\r
184         TListItem *Item, bool Selected )\r
185 {\r
186     module_t *p_module;\r
187     AnsiString Name;\r
188 \r
189     Name = Item->Caption;\r
190     if( Name != "" )\r
191     {\r
192         /* look for module 'Name' */\r
193         for( p_module = p_intfGlobal->p_vlc->p_module_bank->first ;\r
194              p_module != NULL ;\r
195              p_module = p_module->next )\r
196         {\r
197             if( strcmp( p_module->psz_object_name, Name.c_str() ) == 0 )\r
198             {\r
199                 ModuleSelected = p_module;\r
200                 LabelHint->Caption = p_module->psz_longname ?\r
201                                      p_module->psz_longname : "";\r
202                 ButtonConfig->Enabled = p_module->i_config_items ? true : false;\r
203 \r
204                 break;\r
205             }\r
206         }\r
207     }\r
208 }\r
209 //---------------------------------------------------------------------------\r
210 void __fastcall TGroupBoxPlugin::ButtonSelectClick( TObject *Sender )\r
211 {\r
212     if( !ModuleSelected ) return;\r
213     Edit->Text = ModuleSelected->psz_object_name;\r
214 }\r
215 //---------------------------------------------------------------------------\r
216 void __fastcall TGroupBoxPlugin::ButtonConfigClick( TObject *Sender )\r
217 {\r
218     p_intfGlobal->p_sys->p_window->\r
219                         CreatePreferences( ModuleSelected->psz_object_name );\r
220 }\r
221 //---------------------------------------------------------------------------\r
222 void __fastcall TGroupBoxPlugin::UpdateChanges()\r
223 {\r
224     /* XXX: Necessary, since c_str() returns only a temporary pointer... */\r
225     free( p_config->psz_value );\r
226     p_config->psz_value = (char *)malloc( Edit->Text.Length() + 1 );\r
227     strcpy( p_config->psz_value, Edit->Text.c_str() );\r
228 }\r
229 \r
230 \r
231 /****************************************************************************\r
232  * GroupBox for string management\r
233  ****************************************************************************/\r
234 __fastcall TGroupBoxString::TGroupBoxString( TComponent* Owner,\r
235             module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
236 {\r
237     /* init description label */\r
238     LabelDesc = CreateLabel( this, 230, 225, 24, 26,\r
239                              p_config->psz_longtext, true );\r
240 \r
241     /* init edit */\r
242     Edit = CreateEdit( this, 16, 164, 24, 21, "" );\r
243     vlc_mutex_lock( p_config->p_lock );\r
244     Edit->Text = p_config->psz_value ? p_config->psz_value : "";\r
245     vlc_mutex_unlock( p_config->p_lock );\r
246 \r
247     /* vertical alignment */\r
248     Height = LabelDesc->Height + 24;\r
249     LabelDesc->Top = Top + ( Height - LabelDesc->Height ) / 2 + 4;\r
250     Edit->Top = Top + ( Height - Edit->Height ) / 2 + 4;\r
251 };\r
252 //---------------------------------------------------------------------------\r
253 void __fastcall TGroupBoxString::UpdateChanges()\r
254 {\r
255     /* XXX: Necessary, since c_str() returns only a temporary pointer... */\r
256     free( p_config->psz_value );\r
257     p_config->psz_value = (char *)malloc( Edit->Text.Length() + 1 );\r
258     strcpy( p_config->psz_value, Edit->Text.c_str() );\r
259 }\r
260 \r
261 \r
262 /****************************************************************************\r
263  * GroupBox for integer management\r
264  ****************************************************************************/\r
265 __fastcall TGroupBoxInteger::TGroupBoxInteger( TComponent* Owner,\r
266             module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
267 {\r
268     /* init description label */\r
269     LabelDesc = CreateLabel( this, 230, 225, 19, 26,\r
270                              p_config->psz_longtext, true );\r
271 \r
272     /* init spinedit */\r
273     SpinEdit = CreateSpinEdit( this, 16, 164, 24, 21,\r
274                                -1, 100000, p_config->i_value );\r
275 \r
276     /* vertical alignment */\r
277     Height = LabelDesc->Height + 24;\r
278     LabelDesc->Top = Top + ( Height - LabelDesc->Height ) / 2 + 4;\r
279     SpinEdit->Top = Top + ( Height - SpinEdit->Height ) / 2 + 4;\r
280 };\r
281 //---------------------------------------------------------------------------\r
282 void __fastcall TGroupBoxInteger::UpdateChanges()\r
283 {\r
284     /* Warning: we're casting from long to int */\r
285     p_config->i_value = (int)SpinEdit->Value;\r
286 }\r
287 \r
288 \r
289 /****************************************************************************\r
290  * GroupBox for boolean management\r
291  ****************************************************************************/\r
292 __fastcall TGroupBoxBool::TGroupBoxBool( TComponent* Owner,\r
293             module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
294 {\r
295     /* init description label */\r
296     LabelDesc = CreateLabel( this, 230, 225, 19, 26,\r
297                              p_config->psz_longtext, true );\r
298 \r
299     /* init checkbox */\r
300     CheckBox = CreateCheckBox( this, 16, 184, 28, 17, p_config->psz_text );\r
301     CheckBox->Checked = p_config->i_value;\r
302 \r
303     /* vertical alignment */\r
304     Height = LabelDesc->Height + 24;\r
305     LabelDesc->Top = Top + ( Height - LabelDesc->Height ) / 2 + 4;\r
306     CheckBox->Top = Top + ( Height - CheckBox->Height ) / 2 + 4;\r
307 };\r
308 //---------------------------------------------------------------------------\r
309 void __fastcall TGroupBoxBool::UpdateChanges()\r
310 {\r
311     p_config->i_value = CheckBox->Checked ? 1 : 0;\r
312 }\r
313 \r
314 \r
315 /****************************************************************************\r
316  * Callbacks for the dialog\r
317  ****************************************************************************/\r
318 //---------------------------------------------------------------------------\r
319 __fastcall TPreferencesDlg::TPreferencesDlg( TComponent* Owner )\r
320         : TForm( Owner )\r
321 {\r
322     Icon = p_intfGlobal->p_sys->p_window->Icon;\r
323 }\r
324 //---------------------------------------------------------------------------\r
325 void __fastcall TPreferencesDlg::FormClose( TObject *Sender,\r
326       TCloseAction &Action )\r
327 {\r
328     Action = caHide;\r
329 }\r
330 //---------------------------------------------------------------------------\r
331 void __fastcall TPreferencesDlg::FormShow( TObject *Sender )\r
332 {\r
333 /*\r
334     p_intfGlobal->p_sys->p_window->MenuPreferences->Checked = true;\r
335     p_intfGlobal->p_sys->p_window->PopupPreferences->Checked = true;\r
336 */\r
337 }\r
338 //---------------------------------------------------------------------------\r
339 void __fastcall TPreferencesDlg::FormHide( TObject *Sender )\r
340 {\r
341 /*\r
342     p_intfGlobal->p_sys->p_window->MenuPreferences->Checked = false;\r
343     p_intfGlobal->p_sys->p_window->PopupPreferences->Checked = false;\r
344 */\r
345 }\r
346 \r
347 \r
348 /****************************************************************************\r
349  * CreateConfigDialog: dynamically creates the configuration dialog\r
350  * box from all the configuration data provided by the selected module.\r
351  ****************************************************************************/\r
352 #define ADD_PANEL                               \\r
353 {                                               \\r
354             Panel = new TPanel( this );         \\r
355             Panel->Parent = ScrollBox;          \\r
356             Panel->Caption = "";                \\r
357             Panel->BevelOuter = bvNone;         \\r
358             Panel->Height = 12;                 \\r
359 }\r
360 \r
361 void __fastcall TPreferencesDlg::CreateConfigDialog( char *psz_module_name )\r
362 {\r
363     module_t           *p_module;\r
364     module_t          **pp_parser;\r
365     vlc_list_t         *p_list;\r
366 \r
367     module_config_t    *p_item;\r
368     int                 i_pages, i_ctrl;\r
369     \r
370     TTabSheet          *TabSheet;\r
371     TScrollBox         *ScrollBox;\r
372     TPanel             *Panel;\r
373     TGroupBoxPlugin    *GroupBoxPlugin;\r
374     TGroupBoxString    *GroupBoxString;\r
375     TGroupBoxInteger   *GroupBoxInteger;\r
376     TGroupBoxBool      *GroupBoxBool;\r
377     TListItem          *ListItem;\r
378 \r
379     /* Look for the selected module */\r
380     for( p_module = p_intfGlobal->p_vlc->p_module_bank->first ; p_module != NULL ;\r
381          p_module = p_module->next )\r
382     {\r
383         if( psz_module_name\r
384              && !strcmp( psz_module_name, p_module->psz_object_name ) )\r
385         {\r
386             break;\r
387         }\r
388     }\r
389     if( !p_module ) return;\r
390 \r
391     /*\r
392      * We found it, now we can start building its configuration interface\r
393      */\r
394 \r
395     /* Enumerate config options and add corresponding config boxes */\r
396     p_item = p_module->p_config;\r
397     if( p_item ) do\r
398     {\r
399         switch( p_item->i_type )\r
400         {\r
401         case CONFIG_HINT_CATEGORY:\r
402 \r
403             /* create a new tabsheet. */\r
404             TabSheet = new TTabSheet( this );\r
405             TabSheet->PageControl = PageControlPref;\r
406             TabSheet->Caption = p_item->psz_text;\r
407             TabSheet->Visible = true;\r
408 \r
409             /* pack a scrollbox into the tabsheet */\r
410             ScrollBox = new TScrollBox( this );\r
411             ScrollBox->Parent = TabSheet;\r
412             ScrollBox->Align = alClient;\r
413             ScrollBox->BorderStyle = bsNone;\r
414             ScrollBox->HorzScrollBar->Tracking = true;\r
415             ScrollBox->VertScrollBar->Tracking = true;\r
416 \r
417             break;\r
418 \r
419         case CONFIG_ITEM_MODULE:\r
420 \r
421             /* add new groupbox for the config option */\r
422             GroupBoxPlugin = new TGroupBoxPlugin( this, p_item );\r
423             GroupBoxPlugin->Parent = ScrollBox;\r
424 \r
425             /* add panel as separator */\r
426             ADD_PANEL;\r
427 \r
428             /* Look for valid modules */\r
429             p_list = vlc_list_find( p_intfGlobal, VLC_OBJECT_MODULE, FIND_ANYWHERE );\r
430             pp_parser = (module_t **)p_list->pp_objects;\r
431 \r
432             for( ; *pp_parser ; pp_parser++ )\r
433             {\r
434                 if( !strcmp( (*pp_parser)->psz_capability, p_item->psz_type ) )\r
435                 {\r
436                     ListItem = GroupBoxPlugin->ListView->Items->Add();\r
437                     ListItem->Caption = (*pp_parser)->psz_object_name;\r
438                 }\r
439             }\r
440 \r
441             vlc_list_release( p_list );\r
442 \r
443             break;\r
444 \r
445         case CONFIG_ITEM_FILE:\r
446 \r
447         case CONFIG_ITEM_STRING:\r
448 \r
449             /* add new groupbox for the config option */\r
450             GroupBoxString = new TGroupBoxString( this, p_item );\r
451             GroupBoxString->Parent = ScrollBox;\r
452 \r
453             /* add panel as separator */\r
454             ADD_PANEL;\r
455 \r
456             break;\r
457 \r
458         case CONFIG_ITEM_INTEGER:\r
459 \r
460             /* add new groupbox for the config option */\r
461             GroupBoxInteger = new TGroupBoxInteger( this, p_item );\r
462             GroupBoxInteger->Parent = ScrollBox;\r
463 \r
464             /* add panel as separator */\r
465             ADD_PANEL;\r
466 \r
467             break;\r
468 \r
469         case CONFIG_ITEM_BOOL:\r
470 \r
471             /* add new groupbox for the config option */\r
472             GroupBoxBool = new TGroupBoxBool( this, p_item );\r
473             GroupBoxBool->Parent = ScrollBox;\r
474 \r
475             /* add panel as separator */\r
476             ADD_PANEL;\r
477 \r
478             break;\r
479         }\r
480         \r
481         p_item++;\r
482     }\r
483     while( p_item->i_type != CONFIG_HINT_END );\r
484 \r
485     /* Reorder groupboxes inside the tabsheets */\r
486     for( i_pages = 0; i_pages < PageControlPref->PageCount; i_pages++ )\r
487     {\r
488         /* get scrollbox from the tabsheet */\r
489         ScrollBox = (TScrollBox *)PageControlPref->Pages[i_pages]->Controls[0];\r
490 \r
491         for( i_ctrl = ScrollBox->ControlCount - 1; i_ctrl >= 0 ; i_ctrl-- )\r
492         {\r
493             ScrollBox->Controls[i_ctrl]->Align = alTop;\r
494         }\r
495     }\r
496 \r
497     /* set active tabsheet\r
498      * FIXME: i don't know why, but both lines are necessary */\r
499     PageControlPref->ActivePageIndex = 1;\r
500     PageControlPref->ActivePageIndex = 0;\r
501 }\r
502 #undef ADD_PANEL\r
503 //---------------------------------------------------------------------------\r
504 void __fastcall TPreferencesDlg::ButtonOkClick( TObject *Sender )\r
505 {\r
506     ButtonApplyClick( Sender );\r
507     Hide();\r
508 }\r
509 //---------------------------------------------------------------------------\r
510 void __fastcall TPreferencesDlg::ButtonApplyClick( TObject *Sender )\r
511 {\r
512     TScrollBox *ScrollBox;\r
513     TGroupBoxPref *GroupBox;\r
514     int i, j;\r
515 \r
516     for( i = 0; i < PageControlPref->PageCount; i++ )\r
517     {\r
518         /* get scrollbox from the tabsheet */\r
519         ScrollBox = (TScrollBox *)PageControlPref->Pages[i]->Controls[0];\r
520 \r
521         for( j = 0; j < ScrollBox->ControlCount ; j++ )\r
522         {\r
523             /* skip the panels */\r
524             if( ScrollBox->Controls[j]->InheritsFrom( __classid( TGroupBoxPref ) ) )\r
525             {\r
526                 GroupBox = (TGroupBoxPref *)ScrollBox->Controls[j];\r
527                 GroupBox->UpdateChanges();\r
528                 SaveValue( GroupBox->p_config );\r
529             }\r
530         }\r
531     }\r
532 }\r
533 //---------------------------------------------------------------------------\r
534 void __fastcall TPreferencesDlg::ButtonSaveClick( TObject *Sender )\r
535 {\r
536     ButtonApplyClick( Sender );\r
537     config_SaveConfigFile( p_intfGlobal, NULL );\r
538 }\r
539 //---------------------------------------------------------------------------\r
540 void __fastcall TPreferencesDlg::ButtonCancelClick( TObject *Sender )\r
541 {\r
542     Hide();\r
543 }\r
544 //---------------------------------------------------------------------------\r
545 void __fastcall TPreferencesDlg::SaveValue( module_config_t *p_config )\r
546 {\r
547     switch( p_config->i_type )\r
548     {\r
549         case CONFIG_ITEM_STRING:\r
550         case CONFIG_ITEM_FILE:\r
551         case CONFIG_ITEM_MODULE:\r
552             config_PutPsz( p_intfGlobal, p_config->psz_name,\r
553                            *p_config->psz_value ? p_config->psz_value : NULL );\r
554             break;\r
555         case CONFIG_ITEM_INTEGER:\r
556         case CONFIG_ITEM_BOOL:\r
557             config_PutInt( p_intfGlobal, p_config->psz_name,\r
558                            p_config->i_value );\r
559             break;\r
560     }\r
561 }\r
562 //---------------------------------------------------------------------------\r
563 \r