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