]> git.sesse.net Git - vlc/blob - modules/gui/wince/preferences.cpp
Removes trailing spaces. Removes tabs.
[vlc] / modules / gui / wince / preferences.cpp
1 /*****************************************************************************
2  * preferences.cpp : WinCE gui plugin for VLC
3  *****************************************************************************
4  * Copyright (C) 2000-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *
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.
14  *
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.
19  *
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <vlc/vlc.h>
29 #include <vlc_interface.h>
30
31 #include "wince.h"
32
33 #include <winuser.h>
34 #include <windows.h>
35 #include <windowsx.h>
36 #include <commctrl.h>
37 #include <commdlg.h>
38
39 #include <vlc_config_cat.h>
40
41 #include "preferences_widgets.h"
42
43 #define GENERAL_ID 1242
44 #define PLUGIN_ID 1243
45 #define CAPABILITY_ID 1244
46
47 /*****************************************************************************
48  * Event Table.
49  *****************************************************************************/
50
51 /* IDs for the controls and the menu commands */
52 enum
53 {
54     Notebook_Event,
55     MRL_Event,
56     ResetAll_Event,
57     Advanced_Event
58 };
59
60 /*****************************************************************************
61  * Classes declarations.
62  *****************************************************************************/
63 class ConfigTreeData;
64 class PrefsTreeCtrl
65 {
66 public:
67
68     PrefsTreeCtrl() { }
69     PrefsTreeCtrl( intf_thread_t *_p_intf, PrefsDialog *p_prefs_dialog,
70                    HWND hwnd, HINSTANCE _hInst );
71     virtual ~PrefsTreeCtrl();
72
73     void ApplyChanges();
74     /*void CleanChanges();*/
75
76     void OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent, HINSTANCE hInst );
77  
78     ConfigTreeData *FindModuleConfig( ConfigTreeData *config_data );
79
80     HWND hwndTV;
81
82 private:
83     intf_thread_t *p_intf;
84     PrefsDialog *p_prefs_dialog;
85     vlc_bool_t b_advanced;
86
87     HTREEITEM general_item;
88     HTREEITEM plugins_item;
89 };
90
91 class PrefsPanel
92 {
93 public:
94
95     PrefsPanel() { }
96     PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
97                 PrefsDialog *, int i_object_id, char *, char * );
98     virtual ~PrefsPanel() {}
99
100     void Hide();
101     void Show();
102
103     HWND config_window;
104
105     int oldvalue;
106     int maxvalue;
107
108     void ApplyChanges();
109
110 private:
111     intf_thread_t *p_intf;
112     PrefsDialog *p_prefs_dialog;
113
114     vlc_bool_t b_advanced;
115
116     HWND label;
117
118     vector<ConfigControl *> config_array;
119 };
120
121 class ConfigTreeData
122 {
123 public:
124
125     ConfigTreeData() { b_submodule = 0; panel = NULL; psz_section = NULL;
126                        psz_help = NULL; }
127     virtual ~ConfigTreeData() { if( panel ) delete panel;
128                                 if( psz_section) free(psz_section);
129                                 if( psz_help) free(psz_help); }
130
131     vlc_bool_t b_submodule;
132
133     PrefsPanel *panel;
134     int i_object_id;
135     char *psz_section;
136     char *psz_help;
137 };
138
139 /*****************************************************************************
140  * Constructor.
141  *****************************************************************************/
142 PrefsDialog::PrefsDialog( intf_thread_t *p_intf, CBaseWindow *p_parent,
143                           HINSTANCE h_inst )
144   :  CBaseWindow( p_intf, p_parent, h_inst )
145 {
146     /* Initializations */
147     prefs_tree = NULL;
148 }
149
150 /***********************************************************************
151
152 FUNCTION:
153   WndProc
154
155 PURPOSE:
156   Processes messages sent to the main window.
157
158 ***********************************************************************/
159 LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
160 {
161     SHINITDLGINFO shidi;
162     SHMENUBARINFO mbi;
163     RECT rcClient;
164
165     switch( msg )
166     {
167     case WM_INITDIALOG:
168         shidi.dwMask = SHIDIM_FLAGS;
169         shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN |
170             SHIDIF_FULLSCREENNOMENUBAR;//SHIDIF_SIZEDLGFULLSCREEN;
171         shidi.hDlg = hwnd;
172         SHInitDialog( &shidi );
173
174         //Create the menubar
175         memset( &mbi, 0, sizeof (SHMENUBARINFO) );
176         mbi.cbSize     = sizeof (SHMENUBARINFO);
177         mbi.hwndParent = hwnd;
178         mbi.dwFlags    = SHCMBF_EMPTYBAR;
179         mbi.hInstRes   = hInst;
180
181         if( !SHCreateMenuBar(&mbi) )
182         {
183             MessageBox(hwnd, _T("SHCreateMenuBar Failed"), _T("Error"), MB_OK);
184             //return -1;
185         }
186
187         hwndCB = mbi.hwndMB;
188
189         // Get the client area rect to put the panels in
190         GetClientRect(hwnd, &rcClient);
191
192         /* Create the buttons */
193         advanced_checkbox =
194             CreateWindow( _T("BUTTON"), _T("Advanced options"),
195                         WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
196                         5, 10, 15, 15, hwnd, NULL, hInst, NULL );
197         SendMessage( advanced_checkbox, BM_SETCHECK, BST_UNCHECKED, 0 );
198
199         advanced_label = CreateWindow( _T("STATIC"), _T("Advanced options"),
200                         WS_CHILD | WS_VISIBLE | SS_LEFT,
201                         5 + 15 + 5, 10, 110, 15,
202                         hwnd, NULL, hInst, NULL);
203
204         if( config_GetInt( p_intf, "advanced" ) )
205         {
206             SendMessage( advanced_checkbox, BM_SETCHECK, BST_CHECKED, 0 );
207             /*dummy_event.SetInt(TRUE);
208               OnAdvanced( dummy_event );*/
209         }
210
211         reset_button = CreateWindow( _T("BUTTON"), _T("Reset All"),
212                         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
213                         rcClient.right - 5 - 80, 10 - 3, 80, 15 + 6,
214                         hwnd, NULL, hInst, NULL );
215
216         /* Create the preferences tree control */
217         prefs_tree = new PrefsTreeCtrl( p_intf, this, hwnd, hInst );
218
219         UpdateWindow( hwnd );
220         break;
221
222     case WM_CLOSE:
223         EndDialog( hwnd, LOWORD( wp ) );
224         break;
225
226     case WM_SETFOCUS:
227         SHFullScreen( hwnd, SHFS_SHOWSIPBUTTON );
228         break;
229
230     case WM_COMMAND:
231         if( LOWORD(wp) == IDOK )
232         {
233             OnOk();
234             EndDialog( hwnd, LOWORD( wp ) );
235         }
236         break;
237
238     case WM_NOTIFY:
239
240         if( lp && prefs_tree &&
241             ((LPNMHDR)lp)->hwndFrom == prefs_tree->hwndTV &&
242             ((LPNMHDR)lp)->code == TVN_SELCHANGED )
243         {
244             prefs_tree->OnSelectTreeItem( (NM_TREEVIEW FAR *)(LPNMHDR)lp,
245                                           hwnd, hInst );
246         }
247         break;
248
249     case WM_VSCROLL:
250     {
251         TVITEM tvi = {0};
252         tvi.mask = TVIF_PARAM;
253         tvi.hItem = TreeView_GetSelection( prefs_tree->hwndTV );
254     if( !tvi.hItem ) break;
255
256         if( !TreeView_GetItem( prefs_tree->hwndTV, &tvi ) ) break;
257
258         ConfigTreeData *config_data =
259             prefs_tree->FindModuleConfig( (ConfigTreeData *)tvi.lParam );
260         if( config_data && hwnd == config_data->panel->config_window )
261         {
262             int dy;
263             RECT rc;
264             GetWindowRect( hwnd, &rc);
265             int newvalue = config_data->panel->oldvalue;
266             switch ( GET_WM_VSCROLL_CODE(wp,lp) )
267             {
268             case SB_BOTTOM       : newvalue = 0; break;
269             case SB_TOP          : newvalue = config_data->panel->maxvalue; break;
270             case SB_LINEDOWN     : newvalue += 10; break;
271             case SB_PAGEDOWN     : newvalue += rc.bottom - rc.top - 25; break; // wrong! one page is notebook actual length
272             case SB_LINEUP       : newvalue -= 10; break;
273             case SB_PAGEUP       : newvalue -= rc.bottom - rc.top - 25; break;
274             case SB_THUMBPOSITION:
275             case SB_THUMBTRACK   : newvalue = GET_WM_VSCROLL_POS(wp,lp); break;
276             }
277             newvalue = max(0,min(config_data->panel->maxvalue,newvalue));
278             SetScrollPos( hwnd,SB_VERT,newvalue,TRUE);//SB_CTL si hwnd=hwndScrollBar, SB_VERT si window
279             dy = config_data->panel->oldvalue - newvalue;
280
281             ScrollWindowEx( hwnd, 0, dy, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN );
282             UpdateWindow ( hwnd);
283
284             config_data->panel->oldvalue = newvalue;
285         }
286         break;
287     }
288
289     default:
290         break;
291     }
292
293     return FALSE;
294 }
295
296 /*****************************************************************************
297  * Private methods.
298  *****************************************************************************/
299
300 /*****************************************************************************
301  * Events methods.
302  *****************************************************************************/
303 void PrefsDialog::OnOk( void )
304 {
305     prefs_tree->ApplyChanges();
306     config_SaveConfigFile( p_intf, NULL );
307 }
308
309 /*****************************************************************************
310  * PrefsTreeCtrl class definition.
311  *****************************************************************************/
312 PrefsTreeCtrl::PrefsTreeCtrl( intf_thread_t *_p_intf,
313                               PrefsDialog *_p_prefs_dialog, HWND hwnd,
314                               HINSTANCE hInst )
315 {
316     vlc_list_t      *p_list;
317     module_t        *p_module;
318     module_config_t *p_item;
319     int i_index;
320
321     INITCOMMONCONTROLSEX iccex;
322     RECT rcClient;
323     TVITEM tvi = {0};
324     TVINSERTSTRUCT tvins = {0};
325     HTREEITEM hPrev;
326
327     size_t i_capability_count = 0;
328     size_t i_child_index;
329
330     HTREEITEM capability_item;
331
332     /* Initializations */
333     p_intf = _p_intf;
334     p_prefs_dialog = _p_prefs_dialog;
335     b_advanced = VLC_FALSE;
336
337     /* Create a tree view */
338     // Initialize the INITCOMMONCONTROLSEX structure.
339     iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
340     iccex.dwICC = ICC_TREEVIEW_CLASSES;
341
342     // Registers Statusbar control classes from the common control dll
343     InitCommonControlsEx( &iccex );
344
345     // Get the client area rect to put the tv in
346     GetClientRect(hwnd, &rcClient);
347
348     // Create the tree-view control.
349     hwndTV = CreateWindowEx( 0, WC_TREEVIEW, NULL,
350         WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES |
351         TVS_LINESATROOT | TVS_HASBUTTONS,
352         5, 10 + 2*(15 + 10) + 105 + 5, rcClient.right - 5 - 5, 6*15,
353         hwnd, NULL, hInst, NULL );
354
355     tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
356
357     /* List the plugins */
358     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
359     if( !p_list ) return;
360
361     /*
362      * Build a tree of the main options
363      */
364     ConfigTreeData *config_data = new ConfigTreeData;
365     config_data->i_object_id = GENERAL_ID;
366     config_data->psz_help = strdup("nothing");//strdup( GENERAL_HELP );
367     config_data->psz_section = strdup( GENERAL_TITLE );
368     tvi.pszText = _T("General settings");
369     tvi.cchTextMax = lstrlen(_T("General settings"));
370     tvi.lParam = (long)config_data;
371     tvins.item = tvi;
372     tvins.hInsertAfter = TVI_FIRST;
373     tvins.hParent = TVI_ROOT;
374
375     // Add the item to the tree-view control.
376     hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
377     general_item = hPrev;
378
379     for( i_index = 0; i_index < p_list->i_count; i_index++ )
380     {
381         p_module = (module_t *)p_list->p_values[i_index].p_object;
382         if( !strcmp( p_module->psz_object_name, "main" ) )
383             break;
384     }
385     if( i_index < p_list->i_count )
386     {
387         /* We found the main module */
388
389         /* Enumerate config categories and store a reference so we can
390          * generate their config panel them when it is asked by the user. */
391         p_item = p_module->p_config;
392
393         if( p_item ) do
394         {
395             switch( p_item->i_type )
396             {
397             case CONFIG_HINT_CATEGORY:
398                 ConfigTreeData *config_data = new ConfigTreeData;
399                 config_data->psz_section = strdup( p_item->psz_text );
400                 if( p_item->psz_longtext )
401                 {
402                     config_data->psz_help =
403                         strdup( p_item->psz_longtext );
404                 }
405                 else
406                 {
407                     config_data->psz_help = NULL;
408                 }
409                 config_data->i_object_id = p_module->i_object_id;
410
411                 /* Add the category to the tree */
412                 // Set the text of the item.
413                 tvi.pszText = _FROMMB(p_item->psz_text);
414                 tvi.cchTextMax = _tcslen(tvi.pszText);
415                 tvi.lParam = (long)config_data;
416                 tvins.item = tvi;
417                 tvins.hInsertAfter = hPrev;
418                 tvins.hParent = general_item; //level 3
419  
420                 // Add the item to the tree-view control.
421                 hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
422
423                 break;
424             }
425         }
426         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
427
428         TreeView_SortChildren( hwndTV, general_item, 0 );
429     }
430  
431     /*
432      * Build a tree of all the plugins
433      */
434     config_data = new ConfigTreeData;
435     config_data->i_object_id = PLUGIN_ID;
436     config_data->psz_help = strdup("nothing");//strdup( PLUGIN_HELP );
437     config_data->psz_section = strdup("nothing");//strdup( PLUGIN_TITLE );
438     tvi.pszText = _T("Modules");
439     tvi.cchTextMax = lstrlen(_T("Modules"));
440     tvi.lParam = (long)config_data;
441     tvins.item = tvi;
442     tvins.hInsertAfter = TVI_LAST;
443     tvins.hParent = TVI_ROOT;
444
445     // Add the item to the tree-view control.
446     hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
447     plugins_item = hPrev;
448
449     i_capability_count = 0;
450     for( i_index = 0; i_index < p_list->i_count; i_index++ )
451     {
452         i_child_index = 0;
453
454         p_module = (module_t *)p_list->p_values[i_index].p_object;
455
456         /* Exclude the main module */
457         if( !strcmp( p_module->psz_object_name, "main" ) )
458             continue;
459
460         /* Exclude empty plugins (submodules don't have config options, they
461          * are stored in the parent module) */
462         if( p_module->b_submodule )
463             p_item = ((module_t *)p_module->p_parent)->p_config;
464         else
465             p_item = p_module->p_config;
466
467         if( !p_item ) continue;
468         do
469         {
470             if( p_item->i_type & CONFIG_ITEM )
471                 break;
472         }
473         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
474         if( p_item->i_type == CONFIG_HINT_END ) continue;
475
476         /* Find the capability child item */
477         /*long cookie; size_t i_child_index;*/
478         capability_item = TreeView_GetChild( hwndTV, plugins_item );
479         while( capability_item != 0 )
480         {
481             TVITEM capability_tvi = {0};
482             TCHAR psz_text[256];
483             i_child_index++;
484
485             capability_tvi.mask = TVIF_TEXT;
486             capability_tvi.pszText = psz_text;
487             capability_tvi.cchTextMax = 256;
488             capability_tvi.hItem = capability_item;
489             TreeView_GetItem( hwndTV, &capability_tvi );
490             if( !strcmp( _TOMB(capability_tvi.pszText),
491                          p_module->psz_capability ) ) break;
492  
493             capability_item =
494                 TreeView_GetNextSibling( hwndTV, capability_item );
495         }
496
497         if( i_child_index == i_capability_count &&
498             p_module->psz_capability && *p_module->psz_capability )
499         {
500             /* We didn't find it, add it */
501             ConfigTreeData *config_data = new ConfigTreeData;
502             config_data->psz_section =
503                 strdup( GetCapabilityHelp( p_module->psz_capability , 1 ) );
504             config_data->psz_help =
505                 strdup( GetCapabilityHelp( p_module->psz_capability , 2 ) );
506             config_data->i_object_id = CAPABILITY_ID;
507             tvi.pszText = _FROMMB(p_module->psz_capability);
508             tvi.cchTextMax = _tcslen(tvi.pszText);
509             tvi.lParam = (long)config_data;
510             tvins.item = tvi;
511             tvins.hInsertAfter = plugins_item;
512             tvins.hParent = plugins_item;// level 3
513
514             // Add the item to the tree-view control.
515             capability_item = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
516
517             i_capability_count++;
518         }
519
520         /* Add the plugin to the tree */
521         ConfigTreeData *config_data = new ConfigTreeData;
522         config_data->b_submodule = p_module->b_submodule;
523         config_data->i_object_id = p_module->b_submodule ?
524             ((module_t *)p_module->p_parent)->i_object_id :
525             p_module->i_object_id;
526         config_data->psz_help = NULL;
527         tvi.pszText = _FROMMB(p_module->psz_object_name);
528         tvi.cchTextMax = _tcslen(tvi.pszText);
529         tvi.lParam = (long)config_data;
530         tvins.item = tvi;
531         tvins.hInsertAfter = capability_item;
532         tvins.hParent = capability_item;// level 4
533
534         // Add the item to the tree-view control.
535         TreeView_InsertItem( hwndTV, &tvins );
536     }
537
538     /* Sort all this mess */
539     /*long cookie; size_t i_child_index;*/
540     TreeView_SortChildren( hwndTV, plugins_item, 0 );
541     capability_item = TreeView_GetChild( hwndTV, plugins_item );
542     while( capability_item != 0 )
543     {
544         TreeView_SortChildren( hwndTV, capability_item, 0 );
545         capability_item = TreeView_GetNextSibling( hwndTV, capability_item );
546     }
547
548     /* Clean-up everything */
549     vlc_list_release( p_list );
550
551     TreeView_Expand( hwndTV, general_item, TVE_EXPANDPARTIAL |TVE_EXPAND );
552 }
553
554 PrefsTreeCtrl::~PrefsTreeCtrl()
555 {
556 }
557
558 void PrefsTreeCtrl::ApplyChanges()
559 {
560     /*long cookie, cookie2;*/
561     ConfigTreeData *config_data;
562
563     /* Apply changes to the main module */
564     HTREEITEM item = TreeView_GetChild( hwndTV, general_item );
565     while( item != 0 )
566     {
567         TVITEM tvi = {0};
568         tvi.mask = TVIF_PARAM;
569         tvi.hItem = item;
570         TreeView_GetItem( hwndTV, &tvi );
571         config_data = (ConfigTreeData *)tvi.lParam;
572         if( config_data && config_data->panel )
573         {
574             config_data->panel->ApplyChanges();
575         }
576
577         item = TreeView_GetNextSibling( hwndTV, item );
578     }
579
580     /* Apply changes to the plugins */
581     item = TreeView_GetChild( hwndTV, plugins_item );
582     while( item != 0 )
583     {
584         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
585         while( item2 != 0 )
586         {
587             TVITEM tvi = {0};
588             tvi.mask = TVIF_PARAM;
589             tvi.hItem = item2;
590             TreeView_GetItem( hwndTV, &tvi );
591             config_data = (ConfigTreeData *)tvi.lParam;
592             if( config_data && config_data->panel )
593             {
594                 config_data->panel->ApplyChanges();
595             }
596             item2 = TreeView_GetNextSibling( hwndTV, item2 );
597         }
598         item = TreeView_GetNextSibling( hwndTV, item );
599     }
600 }
601
602 ConfigTreeData *PrefsTreeCtrl::FindModuleConfig( ConfigTreeData *config_data )
603 {
604     /* We need this complexity because submodules don't have their own config
605      * options. They use the parent module ones. */
606
607     if( !config_data || !config_data->b_submodule )
608     {
609         return config_data;
610     }
611
612     /*long cookie, cookie2;*/
613     ConfigTreeData *config_new;
614     HTREEITEM item = TreeView_GetChild( hwndTV, plugins_item );
615     while( item != 0 )
616     {
617         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
618         while( item2 != 0 )
619         {
620             TVITEM tvi = {0};
621             tvi.mask = TVIF_PARAM;
622             tvi.hItem = item2;
623             TreeView_GetItem( hwndTV, &tvi );
624             config_new = (ConfigTreeData *)tvi.lParam;
625             if( config_new && !config_new->b_submodule &&
626                 config_new->i_object_id == config_data->i_object_id )
627             {
628                 return config_new;
629             }
630             item2 = TreeView_GetNextSibling( hwndTV, item2 );
631         }
632         item = TreeView_GetNextSibling( hwndTV, item );
633     }
634
635     /* Found nothing */
636     return NULL;
637 }
638
639 void PrefsTreeCtrl::OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent,
640                                       HINSTANCE hInst )
641 {
642     ConfigTreeData *config_data = NULL;
643
644     if( pnmtv->itemOld.hItem )
645         config_data = FindModuleConfig( (ConfigTreeData *)pnmtv->itemOld.lParam );
646
647     if( config_data && config_data->panel )
648     {
649         config_data->panel->Hide();
650     }
651
652     /* Don't use event.GetItem() because we also send fake events */
653     TVITEM tvi = {0};
654     tvi.mask = TVIF_PARAM;
655     tvi.hItem = TreeView_GetSelection( hwndTV );
656     TreeView_GetItem( hwndTV, &tvi );
657     config_data = FindModuleConfig( (ConfigTreeData *)tvi.lParam );
658     if( config_data )
659     {
660         if( !config_data->panel )
661         {
662             /* The panel hasn't been created yet. Let's do it. */
663             config_data->panel =
664                 new PrefsPanel( parent, hInst, p_intf, p_prefs_dialog,
665                                 config_data->i_object_id,
666                                 config_data->psz_section,
667                                 config_data->psz_help );
668         }
669         else
670         {
671             config_data->panel->Show();
672         }
673     }
674 }
675
676 /*****************************************************************************
677  * PrefsPanel class definition.
678  *****************************************************************************/
679 PrefsPanel::PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
680                         PrefsDialog *_p_prefs_dialog,
681                         int i_object_id, char *psz_section, char *psz_help )
682 {
683     module_config_t *p_item;
684     module_t *p_module = NULL;
685
686     /* Initializations */
687     p_intf = _p_intf;
688     p_prefs_dialog = _p_prefs_dialog;
689
690     b_advanced = VLC_TRUE;
691
692     if( i_object_id == PLUGIN_ID || i_object_id == GENERAL_ID ||
693         i_object_id == CAPABILITY_ID )
694     {
695         label = CreateWindow( _T("STATIC"), _FROMMB(psz_section),
696                               WS_CHILD | WS_VISIBLE | SS_LEFT,
697                               5, 10 + (15 + 10), 200, 15,
698                               parent, NULL, hInst, NULL );
699         config_window = NULL;
700     }
701     else
702     {
703         /* Get a pointer to the module */
704         p_module = (module_t *)vlc_object_get( p_intf,  i_object_id );
705         if( p_module->i_object_type != VLC_OBJECT_MODULE )
706         {
707             /* 0OOoo something went really bad */
708             return;
709         }
710
711         /* Enumerate config options and add corresponding config boxes
712          * (submodules don't have config options, they are stored in the
713          *  parent module) */
714         if( p_module->b_submodule )
715             p_item = ((module_t *)p_module->p_parent)->p_config;
716         else
717             p_item = p_module->p_config;
718
719         /* Find the category if it has been specified */
720         if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
721         {
722             while( !(p_item->i_type == CONFIG_HINT_CATEGORY) ||
723                    strcmp( psz_section, p_item->psz_text ) )
724             {
725                 if( p_item->i_type == CONFIG_HINT_END ) break;
726                 p_item++;
727             }
728         }
729
730         /* Add a head title to the panel */
731         label = CreateWindow( _T("STATIC"), _FROMMB(psz_section ?
732                         p_item->psz_text : p_module->psz_longname),
733                         WS_CHILD | WS_VISIBLE | SS_LEFT,
734                         5, 10 + (15 + 10), 250, 15,
735                         parent, NULL, hInst, NULL );
736
737         WNDCLASS wc;
738         memset( &wc, 0, sizeof(wc) );
739         wc.style          = CS_HREDRAW | CS_VREDRAW;
740         wc.lpfnWndProc    = (WNDPROC) _p_prefs_dialog->BaseWndProc;
741         wc.cbClsExtra     = 0;
742         wc.cbWndExtra     = 0;
743         wc.hInstance      = hInst;
744         wc.hIcon          = 0;
745         wc.hCursor        = 0;
746         wc.hbrBackground  = (HBRUSH) GetStockObject(WHITE_BRUSH);
747         wc.lpszMenuName   = 0;
748         wc.lpszClassName  = _T("PrefsPanelClass");
749         RegisterClass(&wc);
750
751         RECT rc;
752         GetWindowRect( parent, &rc);
753         config_window = CreateWindow( _T("PrefsPanelClass"),
754                         _T("config_window"),
755                         WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER,
756                         5, 10 + 2*(15 + 10), rc.right - 5 - 7, 105,
757                         parent, NULL, hInst, (void *) _p_prefs_dialog );
758
759         int y_pos = 5;
760         if( p_item ) do
761         {
762             /* If a category has been specified, check we finished the job */
763             if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
764                 strcmp( psz_section, p_item->psz_text ) )
765                 break;
766
767             ConfigControl *control =
768                 CreateConfigControl( VLC_OBJECT(p_intf),
769                                      p_item, config_window,
770                                      hInst, &y_pos );
771
772             /* Don't add items that were not recognized */
773             if( control == NULL ) continue;
774
775             /* Add the config data to our array so we can keep a trace of it */
776             config_array.push_back( control );
777         }
778         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
779  
780         GetWindowRect( config_window, &rc);
781         maxvalue = y_pos - (rc.bottom - rc.top) + 5;
782         oldvalue = 0;
783         SetScrollRange( config_window, SB_VERT, 0, maxvalue, TRUE );
784     }
785 }
786
787 void PrefsPanel::Hide()
788 {
789     ShowWindow( label, SW_HIDE );
790     if( config_window ) ShowWindow( config_window, SW_HIDE );
791 }
792
793 void PrefsPanel::Show()
794 {
795     ShowWindow( label, SW_SHOW );
796     if( config_window ) ShowWindow( config_window, SW_SHOW );
797 }
798
799 void PrefsPanel::ApplyChanges()
800 {
801     vlc_value_t val;
802
803     for( size_t i = 0; i < config_array.size(); i++ )
804     {
805         ConfigControl *control = config_array[i];
806
807         switch( control->GetType() )
808         {
809         case CONFIG_ITEM_STRING:
810         case CONFIG_ITEM_FILE:
811         case CONFIG_ITEM_DIRECTORY:
812         case CONFIG_ITEM_MODULE:
813             config_PutPsz( p_intf, control->GetName(),
814                            control->GetPszValue() );
815             break;
816         case CONFIG_ITEM_KEY:
817             /* So you don't need to restart to have the changes take effect */
818             val.i_int = control->GetIntValue();
819             var_Set( p_intf->p_libvlc, control->GetName(), val );
820         case CONFIG_ITEM_INTEGER:
821         case CONFIG_ITEM_BOOL:
822             config_PutInt( p_intf, control->GetName(),
823                            control->GetIntValue() );
824             break;
825         case CONFIG_ITEM_FLOAT:
826             config_PutFloat( p_intf, control->GetName(),
827                              control->GetFloatValue() );
828             break;
829         }
830     }
831 }