]> git.sesse.net Git - vlc/blobdiff - modules/gui/wince/preferences.cpp
macosx: Blindly remove i_object_id from prefs.m.
[vlc] / modules / gui / wince / preferences.cpp
index 6ecc6ac2c5d934c45b6cbb232ef5aadf90435a96..44018eaf57bdee4cc710558e00abf17029efd078 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * preferences.cpp : WinCE gui plugin for VLC
  *****************************************************************************
- * Copyright (C) 2000-2004 VideoLAN
+ * Copyright (C) 2000-2004 the VideoLAN team
  * $Id$
  *
  * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include <stdlib.h>                                      /* malloc(), free() */
-#include <string.h>                                            /* strerror() */
-#include <stdio.h>
-#include <vlc/vlc.h>
-#include <vlc/intf.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_interface.h>
 
 #include "wince.h"
 
 
 #include "preferences_widgets.h"
 
-#define GENERAL_ID 1242
-#define PLUGIN_ID 1243
-#define CAPABILITY_ID 1244
+#define TYPE_CATEGORY 0
+#define TYPE_CATSUBCAT 1  /* Category with embedded subcategory */
+#define TYPE_SUBCATEGORY 2
+#define TYPE_MODULE 3
 
 /*****************************************************************************
  * Event Table.
@@ -77,7 +79,7 @@ public:
     /*void CleanChanges();*/
 
     void OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent, HINSTANCE hInst );
-        
     ConfigTreeData *FindModuleConfig( ConfigTreeData *config_data );
 
     HWND hwndTV;
@@ -85,9 +87,8 @@ public:
 private:
     intf_thread_t *p_intf;
     PrefsDialog *p_prefs_dialog;
-    vlc_bool_t b_advanced;
+    bool b_advanced;
 
-    HTREEITEM root_item;
     HTREEITEM general_item;
     HTREEITEM plugins_item;
 };
@@ -98,7 +99,7 @@ public:
 
     PrefsPanel() { }
     PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
-                PrefsDialog *, int i_object_id, char *, char * );
+                PrefsDialog *, module_t *p_module, char *, char *, ConfigTreeData * );
     virtual ~PrefsPanel() {}
 
     void Hide();
@@ -115,7 +116,7 @@ private:
     intf_thread_t *p_intf;
     PrefsDialog *p_prefs_dialog;
 
-    vlc_bool_t b_advanced;
+    bool b_advanced;
 
     HWND label;
 
@@ -126,51 +127,49 @@ class ConfigTreeData
 {
 public:
 
-    ConfigTreeData() { b_submodule = 0; panel = NULL; psz_section = NULL;
+    ConfigTreeData() { b_submodule = 0; panel = NULL; psz_name = NULL;
                        psz_help = NULL; }
-    virtual ~ConfigTreeData() { if( panel ) delete panel;
-                                if( psz_section) free(psz_section);
-                                if( psz_help) free(psz_help); }
+    virtual ~ConfigTreeData() { delete panel;
+                                free( psz_name );
+                                free( psz_help ); }
 
-    vlc_bool_t b_submodule;
+    bool b_submodule;
 
     PrefsPanel *panel;
+    module_t *p_module;
     int i_object_id;
-    char *psz_section;
+    int i_subcat_id;
+    int i_type;
+    char *psz_name;
     char *psz_help;
 };
 
 /*****************************************************************************
  * Constructor.
  *****************************************************************************/
-PrefsDialog::PrefsDialog( intf_thread_t *_p_intf, HINSTANCE _hInst )
+PrefsDialog::PrefsDialog( intf_thread_t *p_intf, CBaseWindow *p_parent,
+                          HINSTANCE h_inst )
+  :  CBaseWindow( p_intf, p_parent, h_inst )
 {
     /* Initializations */
-    p_intf = _p_intf;
-    hInst = _hInst;
     prefs_tree = NULL;
 }
 
 /***********************************************************************
 
-FUNCTION: 
+FUNCTION:
   WndProc
 
-PURPOSE: 
+PURPOSE:
   Processes messages sent to the main window.
 
 ***********************************************************************/
-LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
-                              PBOOL pbProcessed )
+LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
 {
     SHINITDLGINFO shidi;
     SHMENUBARINFO mbi;
     RECT rcClient;
 
-    LRESULT lResult = CBaseWindow::WndProc( hwnd, msg, wp, lp, pbProcessed );
-    BOOL bWasProcessed = *pbProcessed;
-    *pbProcessed = TRUE;
-
     switch( msg )
     {
     case WM_INITDIALOG:
@@ -184,10 +183,8 @@ LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
         memset( &mbi, 0, sizeof (SHMENUBARINFO) );
         mbi.cbSize     = sizeof (SHMENUBARINFO);
         mbi.hwndParent = hwnd;
-        mbi.nToolBarId = IDR_DUMMYMENU;
+        mbi.dwFlags    = SHCMBF_EMPTYBAR;
         mbi.hInstRes   = hInst;
-        mbi.nBmpId     = 0;
-        mbi.cBmpImages = 0;
 
         if( !SHCreateMenuBar(&mbi) )
         {
@@ -200,7 +197,7 @@ LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
         // Get the client area rect to put the panels in
         GetClientRect(hwnd, &rcClient);
 
-        /* Create the buttons */            
+        /* Create the buttons */
         advanced_checkbox =
             CreateWindow( _T("BUTTON"), _T("Advanced options"),
                         WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
@@ -228,52 +225,58 @@ LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
         prefs_tree = new PrefsTreeCtrl( p_intf, this, hwnd, hInst );
 
         UpdateWindow( hwnd );
-        return lResult;
+        break;
+
+    case WM_CLOSE:
+        EndDialog( hwnd, LOWORD( wp ) );
+        break;
+
+    case WM_SETFOCUS:
+        SHFullScreen( hwnd, SHFS_SHOWSIPBUTTON );
+        break;
 
     case WM_COMMAND:
         if( LOWORD(wp) == IDOK )
         {
             OnOk();
             EndDialog( hwnd, LOWORD( wp ) );
-            return TRUE;
         }
-        *pbProcessed = bWasProcessed;
-        lResult = FALSE;
-        return lResult;
+        break;
 
     case WM_NOTIFY:
 
-        if ( ( ((LPNMHDR)lp)->hwndFrom == prefs_tree->hwndTV ) &&
-             ( ((LPNMHDR)lp)->code == TVN_SELCHANGED  ) )
+        if( lp && prefs_tree &&
+            ((LPNMHDR)lp)->hwndFrom == prefs_tree->hwndTV &&
+            ((LPNMHDR)lp)->code == TVN_SELCHANGED )
         {
             prefs_tree->OnSelectTreeItem( (NM_TREEVIEW FAR *)(LPNMHDR)lp,
                                           hwnd, hInst );
-            return TRUE;
         }
-
-        *pbProcessed = bWasProcessed;
-        lResult = FALSE;
-        return lResult;
+        break;
 
     case WM_VSCROLL:
     {
         TVITEM tvi = {0};
         tvi.mask = TVIF_PARAM;
         tvi.hItem = TreeView_GetSelection( prefs_tree->hwndTV );
-        TreeView_GetItem( prefs_tree->hwndTV, &tvi );
-        ConfigTreeData *config_data = prefs_tree->FindModuleConfig( (ConfigTreeData *)tvi.lParam );
-        if ( hwnd == config_data->panel->config_window ) 
+    if( !tvi.hItem ) break;
+
+        if( !TreeView_GetItem( prefs_tree->hwndTV, &tvi ) ) break;
+
+        ConfigTreeData *config_data =
+            prefs_tree->FindModuleConfig( (ConfigTreeData *)tvi.lParam );
+        if( config_data && hwnd == config_data->panel->config_window )
         {
             int dy;
             RECT rc;
             GetWindowRect( hwnd, &rc);
             int newvalue = config_data->panel->oldvalue;
-            switch ( GET_WM_VSCROLL_CODE(wp,lp) ) 
+            switch ( GET_WM_VSCROLL_CODE(wp,lp) )
             {
             case SB_BOTTOM       : newvalue = 0; break;
             case SB_TOP          : newvalue = config_data->panel->maxvalue; break;
             case SB_LINEDOWN     : newvalue += 10; break;
-            case SB_PAGEDOWN     : newvalue += rc.bottom - rc.top - 25; break; // faux ! une page c'est la longueur rĂ©elle de notebook
+            case SB_PAGEDOWN     : newvalue += rc.bottom - rc.top - 25; break; // wrong! one page is notebook actual length
             case SB_LINEUP       : newvalue -= 10; break;
             case SB_PAGEUP       : newvalue -= rc.bottom - rc.top - 25; break;
             case SB_THUMBPOSITION:
@@ -286,22 +289,16 @@ LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
             ScrollWindowEx( hwnd, 0, dy, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN );
             UpdateWindow ( hwnd);
 
-            config_data->panel->oldvalue = newvalue;                                
+            config_data->panel->oldvalue = newvalue;
         }
+        break;
     }
-    *pbProcessed = bWasProcessed;
-    lResult = FALSE;
-    return lResult;
 
     default:
-        // the message was not processed
-        // indicate if the base class handled it
-        *pbProcessed = bWasProcessed;
-        lResult = FALSE;
-        return lResult;
+        break;
     }
 
-    return lResult;
+    return FALSE;
 }
 
 /*****************************************************************************
@@ -325,25 +322,25 @@ PrefsTreeCtrl::PrefsTreeCtrl( intf_thread_t *_p_intf,
                               HINSTANCE hInst )
 {
     vlc_list_t      *p_list;
-    module_t        *p_module;
+    module_t        *p_module = NULL;
     module_config_t *p_item;
     int i_index;
 
     INITCOMMONCONTROLSEX iccex;
     RECT rcClient;
-    TVITEM tvi = {0}; 
-    TVINSERTSTRUCT tvins = {0}; 
+    TVITEM tvi = {0};
+    TVINSERTSTRUCT tvins = {0};
     HTREEITEM hPrev;
 
     size_t i_capability_count = 0;
     size_t i_child_index;
 
-    HTREEITEM capability_item;
+    HTREEITEM category_item, subcategory_item;
 
     /* Initializations */
     p_intf = _p_intf;
     p_prefs_dialog = _p_prefs_dialog;
-    b_advanced = VLC_FALSE;
+    b_advanced = false;
 
     /* Create a tree view */
     // Initialize the INITCOMMONCONTROLSEX structure.
@@ -363,17 +360,7 @@ PrefsTreeCtrl::PrefsTreeCtrl( intf_thread_t *_p_intf,
         5, 10 + 2*(15 + 10) + 105 + 5, rcClient.right - 5 - 5, 6*15,
         hwnd, NULL, hInst, NULL );
 
-    tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; 
-    tvi.pszText = _T("root");
-    tvi.cchTextMax = lstrlen(_T("root"));
-    tvi.lParam = (LPARAM) 1; // root level
-    tvins.item = tvi;
-    tvins.hInsertAfter = TVI_FIRST; 
-    tvins.hParent = TVI_ROOT; 
-
-    // Add the item to the tree-view control. 
-    hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins );
-    root_item = hPrev;
+    tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
 
     /* List the plugins */
     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
@@ -383,193 +370,259 @@ PrefsTreeCtrl::PrefsTreeCtrl( intf_thread_t *_p_intf,
      * Build a tree of the main options
      */
     ConfigTreeData *config_data = new ConfigTreeData;
-    config_data->i_object_id = GENERAL_ID;
-    config_data->psz_help = strdup("nothing");//strdup( GENERAL_HELP );
-    config_data->psz_section = strdup( GENERAL_TITLE );
+    config_data->i_object_id = TYPE_CATEGORY;
+    config_data->psz_help = strdup(MAIN_HELP);
+    config_data->psz_name = strdup( GENERAL_TITLE );
     tvi.pszText = _T("General settings");
     tvi.cchTextMax = lstrlen(_T("General settings"));
-    tvi.lParam = (long) config_data;
+    tvi.lParam = (long)config_data;
     tvins.item = tvi;
-    tvins.hInsertAfter = hPrev;
-    tvins.hParent = root_item; //level 2
+    tvins.hInsertAfter = TVI_FIRST;
+    tvins.hParent = TVI_ROOT;
 
     // Add the item to the tree-view control.
     hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
     general_item = hPrev;
 
+    /* Build the categories list */
     for( i_index = 0; i_index < p_list->i_count; i_index++ )
     {
         p_module = (module_t *)p_list->p_values[i_index].p_object;
-        if( !strcmp( p_module->psz_object_name, "main" ) )
+        if( strcmp( module_GetObjName( p_module ), "main" ) == 0 )
             break;
     }
+    /* TODO replace by
+     * p_module = module_GetMainModule( p_intf );
+     */
     if( i_index < p_list->i_count )
     {
+        unsigned int confsize;
+        const char *psz_help;
+        module_config_t * p_config;
+
         /* We found the main module */
 
         /* Enumerate config categories and store a reference so we can
          * generate their config panel them when it is asked by the user. */
-        p_item = p_module->p_config;
+        p_config = module_GetConfig (p_module, &confsize);
 
-        if( p_item ) do
+        for( size_t i = 0; i < confsize; i++ )
         {
-            switch( p_item->i_type )
-            {
-            case CONFIG_HINT_CATEGORY:
-                ConfigTreeData *config_data = new ConfigTreeData;
-                config_data->psz_section = strdup( p_item->psz_text );
-                if( p_item->psz_longtext )
-                {
-                    config_data->psz_help =
-                        strdup( p_item->psz_longtext );
-                }
-                else
-                {
-                    config_data->psz_help = NULL;
-                }
-                config_data->i_object_id = p_module->i_object_id;
-
-                /* Add the category to the tree */
-                // Set the text of the item. 
-                tvi.pszText = _FROMMB(p_item->psz_text); 
-                tvi.cchTextMax = _tcslen(tvi.pszText);
-                tvi.lParam = (long)config_data;
-                tvins.item = tvi;
-                tvins.hInsertAfter = hPrev; 
-                tvins.hParent = general_item; //level 3
-    
-                // Add the item to the tree-view control. 
-                hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
+        /* Work on a new item */
+            module_config_t *p_item = p_config + i;
 
-                break;
-            }
-        }
-        while( p_item->i_type != CONFIG_HINT_END && p_item++ );
+                switch( p_item->i_type )
+                {
+                    case CONFIG_CATEGORY:
+                        if( p_item->value.i == -1 )   break; // Don't display it
+                        config_data = new ConfigTreeData;
+                        config_data->psz_name = strdup( config_CategoryNameGet(p_item->value.i ) );
+                        psz_help = config_CategoryHelpGet( p_item->value.i );
+                        if( psz_help )
+                        {
+                            config_data->psz_help = wraptext( strdup( psz_help ), 72 );
+                        }
+                        else
+                        {
+                            config_data->psz_help = NULL;
+                        }
+
+                        config_data->i_type = TYPE_CATEGORY;
+                        config_data->i_object_id = p_item->value.i;
+                        config_data->p_module =  p_module;
+                        tvi.pszText = _FROMMB(config_data->psz_name);
+                        tvi.cchTextMax = _tcslen(tvi.pszText);
+
+                        /* Add the category to the tree */
+                        tvi.lParam = (long)config_data;
+                        tvins.item = tvi;
+                        tvins.hInsertAfter = hPrev;
+                        tvins.hParent = general_item; //level 3
+
+                        // Add the item to the tree-view control.
+                        hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
+                        break;
+
+                    case CONFIG_SUBCATEGORY:
+                        if( p_item->value.i == -1 ) break; // Don't display it
+                        /* Special case: move the "general" subcategories to their parent category */
+                        if(config_data && p_item->value.i == SUBCAT_VIDEO_GENERAL ||
+                            p_item->value.i == SUBCAT_ADVANCED_MISC ||
+                            p_item->value.i == SUBCAT_INPUT_GENERAL ||
+                            p_item->value.i == SUBCAT_INTERFACE_GENERAL ||
+                            p_item->value.i == SUBCAT_SOUT_GENERAL||
+                            p_item->value.i == SUBCAT_PLAYLIST_GENERAL||
+                            p_item->value.i == SUBCAT_AUDIO_GENERAL )
+                        {
+
+                            config_data->i_type = TYPE_CATSUBCAT;
+                            config_data->i_subcat_id = p_item->value.i;
+                            free( config_data->psz_name );
+                            config_data->psz_name = strdup( config_CategoryNameGet( p_item->value.i ) );
+
+                            free( config_data->psz_help );
+                            const char *psz_help = config_CategoryHelpGet( p_item->value.i );
+                            if( psz_help )
+                            {
+                                config_data->psz_help = wraptext( strdup( psz_help ), 72 );
+                            }
+                            else
+                            {
+                                config_data->psz_help = NULL;
+                            }
+                            continue;
+                        }
+
+                        config_data = new ConfigTreeData;
+
+                        config_data->psz_name = strdup(  config_CategoryNameGet( p_item->value.i ) );
+                        psz_help = config_CategoryHelpGet( p_item->value.i );
+                        if( psz_help )
+                        {
+                            config_data->psz_help = wraptext( strdup( psz_help ), 72 );
+                        }
+                        else
+                        {
+                            config_data->psz_help = NULL;
+                        }
+                        config_data->i_type = TYPE_SUBCATEGORY;
+                        config_data->i_object_id = p_item->value.i;
+
+                        tvi.pszText = _FROMMB(config_data->psz_name);
+                        tvi.cchTextMax = _tcslen(tvi.pszText);
+
+                        tvi.lParam = (long)config_data;
+                        tvins.item = tvi;
+                        tvins.hInsertAfter = hPrev;
+                        tvins.hParent = hPrev;
+
+                        // Add the item to the tree-view control.
+                        TreeView_InsertItem( hwndTV, &tvins );
+                        break;
 
+                }
+         }
         TreeView_SortChildren( hwndTV, general_item, 0 );
+        module_PutConfig( p_config );
     }
-        
-    /*
-     * Build a tree of all the plugins
-     */
-    config_data = new ConfigTreeData;
-    config_data->i_object_id = PLUGIN_ID;
-    config_data->psz_help = strdup("nothing");//strdup( PLUGIN_HELP );
-    config_data->psz_section = strdup("nothing");//strdup( PLUGIN_TITLE );
-    tvi.pszText = _T("Modules");
-    tvi.cchTextMax = lstrlen(_T("Modules"));
-    tvi.lParam = (long) config_data;
-    tvins.item = tvi;
-    tvins.hInsertAfter = hPrev;
-    tvins.hParent = root_item;// level 2
 
-    // Add the item to the tree-view control.
-    hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
-    plugins_item = hPrev;
 
-    i_capability_count = 0;
+    module_config_t *p_config;
+    /*
+    * Build a tree of all the plugins
+    */
     for( i_index = 0; i_index < p_list->i_count; i_index++ )
     {
-        i_child_index = 0;
-
+        /* Take every module */
         p_module = (module_t *)p_list->p_values[i_index].p_object;
 
         /* Exclude the main module */
-        if( !strcmp( p_module->psz_object_name, "main" ) )
+        if( !strcmp( module_GetObjName( p_module ), "main" ) )
             continue;
 
         /* Exclude empty plugins (submodules don't have config options, they
          * are stored in the parent module) */
-        if( p_module->b_submodule )
-            p_item = ((module_t *)p_module->p_parent)->p_config;
-        else
-            p_item = p_module->p_config;
 
-        if( !p_item ) continue;
-        do
+        unsigned int confsize;
+        i_child_index = 0;
+        int i_category = 0, i_subcategory = 0, i_options = 0;
+        bool b_options = false;
+
+        p_config = module_GetConfig( (module_t *) p_module,&confsize);
+
+        /* Loop through the configurations items */
+        for( size_t i = 0; i < confsize; i++ )
         {
+            module_config_t *p_item = p_config + i;
+            if( p_item->i_type == CONFIG_CATEGORY )
+                i_category = p_item->value.i;
+            else if( p_item->i_type == CONFIG_SUBCATEGORY )
+                i_subcategory = p_item->value.i;
+
             if( p_item->i_type & CONFIG_ITEM )
+                b_options = true;
+
+            if( b_options && i_category && i_subcategory )
                 break;
         }
-        while( p_item->i_type != CONFIG_HINT_END && p_item++ );
-        if( p_item->i_type == CONFIG_HINT_END ) continue;
+        module_PutConfig (p_config);
 
-        /* Find the capability child item */
-        /*long cookie; size_t i_child_index;*/
-        capability_item = TreeView_GetChild( hwndTV, plugins_item );
-        while( capability_item != 0 )
-        {
-            TVITEM capability_tvi = {0};
-            TCHAR psz_text[256];
-            i_child_index++;
-
-            capability_tvi.mask = TVIF_TEXT;
-            capability_tvi.pszText = psz_text;
-            capability_tvi.cchTextMax = 256;
-            capability_tvi.hItem = capability_item;
-            TreeView_GetItem( hwndTV, &capability_tvi );
-            if( !strcmp( _TOMB(capability_tvi.pszText),
-                         p_module->psz_capability ) ) break;
-            capability_item =
-                TreeView_GetNextSibling( hwndTV, capability_item );
-        }
+        //if( !i_options ) continue;
+        /* Dummy item, please proceed */
+        if( !b_options || i_category == 0 || i_subcategory == 0 ) continue;
 
-        if( i_child_index == i_capability_count &&
-            p_module->psz_capability && *p_module->psz_capability )
+        category_item = TreeView_GetChild( hwndTV, general_item );
+        while(category_item != 0)
         {
-            /* We didn't find it, add it */
-            ConfigTreeData *config_data = new ConfigTreeData;
-            config_data->psz_section =
-                strdup( GetCapabilityHelp( p_module->psz_capability , 1 ) );
-            config_data->psz_help =
-                strdup( GetCapabilityHelp( p_module->psz_capability , 2 ) );
-            config_data->i_object_id = CAPABILITY_ID;
-            tvi.pszText = _FROMMB(p_module->psz_capability);
-            tvi.cchTextMax = _tcslen(tvi.pszText);
-            tvi.lParam = (long) config_data;
-            tvins.item = tvi;
-            tvins.hInsertAfter = plugins_item; 
-            tvins.hParent = plugins_item;// level 3
-
-            // Add the item to the tree-view control. 
-            capability_item = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
-
-            i_capability_count++;
+            TVITEM category_tvi = {0};
+
+            category_tvi.mask = TVIF_PARAM;
+            category_tvi.lParam = NULL;
+            category_tvi.hItem = category_item;
+            TreeView_GetItem( hwndTV, &category_tvi );
+
+            ConfigTreeData * data = (ConfigTreeData *)category_tvi.lParam;
+
+            if( data->i_object_id == i_category )
+            {
+                subcategory_item = TreeView_GetChild( hwndTV, category_item );
+
+                while(subcategory_item != 0)
+                {
+                    TVITEM subcategory_tvi = {0};
+
+                    subcategory_tvi.mask = TVIF_PARAM;
+                    subcategory_tvi.lParam = NULL;
+                    subcategory_tvi.hItem = subcategory_item;
+                    TreeView_GetItem( hwndTV, &subcategory_tvi );
+
+                    ConfigTreeData * subdata = (ConfigTreeData *)subcategory_tvi.lParam;
+
+                    if( subdata->i_object_id == i_subcategory )
+                    {
+                        config_data = new ConfigTreeData;
+
+                        config_data->psz_name = strdup( module_GetObjName( p_module ) );
+                        config_data->psz_help = NULL;
+                        config_data->i_type = TYPE_MODULE;
+                        config_data->i_object_id = p_item->value.i;
+                        config_data->p_module = p_module;
+
+                        tvi.pszText = _FROMMB(module_GetName( p_module, false ));
+                        tvi.cchTextMax = _tcslen(tvi.pszText);
+
+                        tvi.lParam = (long)config_data;
+                        tvins.item = tvi;
+                        tvins.hInsertAfter = subcategory_item;
+                        tvins.hParent = subcategory_item;
+
+                // Add the item to the tree-view control.
+                        hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
+                        break;
+                    }
+                    subcategory_item = TreeView_GetNextSibling( hwndTV, subcategory_item );
+                }
+
+                break;
+            }
+
+            category_item = TreeView_GetNextSibling( hwndTV, category_item );
         }
 
-        /* Add the plugin to the tree */
-        ConfigTreeData *config_data = new ConfigTreeData;
-        config_data->b_submodule = p_module->b_submodule;
-        config_data->i_object_id = p_module->b_submodule ?
-            ((module_t *)p_module->p_parent)->i_object_id :
-            p_module->i_object_id;
-        config_data->psz_help = NULL;
-        tvi.pszText = _FROMMB(p_module->psz_object_name);
-        tvi.cchTextMax = _tcslen(tvi.pszText);
-        tvi.lParam = (long) config_data;
-        tvins.item = tvi;
-        tvins.hInsertAfter = capability_item; 
-        tvins.hParent = capability_item;// level 4
-
-        // Add the item to the tree-view control. 
-        TreeView_InsertItem( hwndTV, &tvins );
     }
 
     /* Sort all this mess */
-    /*long cookie; size_t i_child_index;*/
-    TreeView_SortChildren( hwndTV, plugins_item, 0 );
-    capability_item = TreeView_GetChild( hwndTV, plugins_item );
-    while( capability_item != 0 )
+    TreeView_SortChildren( hwndTV, general_item, 0 );
+    category_item = TreeView_GetChild( hwndTV, general_item );
+    while( category_item != 0 )
     {
-        TreeView_SortChildren( hwndTV, capability_item, 0 );
-        capability_item = TreeView_GetNextSibling( hwndTV, capability_item );
+        TreeView_SortChildren( hwndTV, category_item, 0 );
+        category_item = TreeView_GetNextSibling( hwndTV, category_item );
     }
 
     /* Clean-up everything */
     vlc_list_release( p_list );
 
-    TreeView_Expand( hwndTV, root_item, TVE_EXPANDPARTIAL |TVE_EXPAND );
     TreeView_Expand( hwndTV, general_item, TVE_EXPANDPARTIAL |TVE_EXPAND );
 }
 
@@ -579,7 +632,6 @@ PrefsTreeCtrl::~PrefsTreeCtrl()
 
 void PrefsTreeCtrl::ApplyChanges()
 {
-    /*long cookie, cookie2;*/
     ConfigTreeData *config_data;
 
     /* Apply changes to the main module */
@@ -600,20 +652,25 @@ void PrefsTreeCtrl::ApplyChanges()
     }
 
     /* Apply changes to the plugins */
-    item = TreeView_GetChild( hwndTV, plugins_item );
+    item = TreeView_GetChild( hwndTV, general_item );
     while( item != 0 )
     {
         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
         while( item2 != 0 )
-        {       
-            TVITEM tvi = {0};
-            tvi.mask = TVIF_PARAM;
-            tvi.hItem = item2;
-            TreeView_GetItem( hwndTV, &tvi );
-            config_data = (ConfigTreeData *)tvi.lParam;
-            if( config_data && config_data->panel )
+        {
+            HTREEITEM item3 = TreeView_GetChild( hwndTV, item2 );
+            while(item3 !=0)
             {
-                config_data->panel->ApplyChanges();
+                TVITEM tvi = {0};
+                tvi.mask = TVIF_PARAM;
+                tvi.hItem = item3;
+                TreeView_GetItem( hwndTV, &tvi );
+                config_data = (ConfigTreeData *)tvi.lParam;
+                if( config_data && config_data->panel )
+                {
+                    config_data->panel->ApplyChanges();
+                }
+                item3 = TreeView_GetNextSibling( hwndTV, item3 );
             }
             item2 = TreeView_GetNextSibling( hwndTV, item2 );
         }
@@ -623,31 +680,31 @@ void PrefsTreeCtrl::ApplyChanges()
 
 ConfigTreeData *PrefsTreeCtrl::FindModuleConfig( ConfigTreeData *config_data )
 {
-    /* We need this complexity because submodules don't have their own config
-     * options. They use the parent module ones. */
-
-    if( !config_data || !config_data->b_submodule )
+    if( !config_data || !config_data->p_module )
     {
         return config_data;
     }
 
-    /*long cookie, cookie2;*/
     ConfigTreeData *config_new;
-    HTREEITEM item = TreeView_GetChild( hwndTV, plugins_item );
+    HTREEITEM item = TreeView_GetChild( hwndTV, general_item );
     while( item != 0 )
     {
         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
         while( item2 != 0 )
-        {       
-            TVITEM tvi = {0};
-            tvi.mask = TVIF_PARAM;
-            tvi.hItem = item2;
-            TreeView_GetItem( hwndTV, &tvi );
-            config_new = (ConfigTreeData *)tvi.lParam;
-            if( config_new && !config_new->b_submodule &&
-                config_new->i_object_id == config_data->i_object_id )
+        {
+            HTREEITEM item3 = TreeView_GetChild( hwndTV, item2 );
+            while( item3 != 0 )
             {
-                return config_new;
+                TVITEM tvi = {0};
+                tvi.mask = TVIF_PARAM;
+                tvi.hItem = item3;
+                TreeView_GetItem( hwndTV, &tvi );
+                config_new = (ConfigTreeData *)tvi.lParam;
+                if( config_new && config_new->p_module == config_data->p_module )
+                {
+                    return config_new;
+                }
+                item3 = TreeView_GetNextSibling( hwndTV, item3 );
             }
             item2 = TreeView_GetNextSibling( hwndTV, item2 );
         }
@@ -684,9 +741,9 @@ void PrefsTreeCtrl::OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent,
             /* The panel hasn't been created yet. Let's do it. */
             config_data->panel =
                 new PrefsPanel( parent, hInst, p_intf, p_prefs_dialog,
-                                config_data->i_object_id,
-                                config_data->psz_section,
-                                config_data->psz_help );
+                                config_data->p_module,
+                                config_data->psz_name,
+                                config_data->psz_help, config_data );
         }
         else
         {
@@ -700,21 +757,20 @@ void PrefsTreeCtrl::OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent,
  *****************************************************************************/
 PrefsPanel::PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
                         PrefsDialog *_p_prefs_dialog,
-                        int i_object_id, char *psz_section, char *psz_help )
+                        module_t *p_module, char *psz_name, char *psz_help, ConfigTreeData * config_data )
 {
-    module_config_t *p_item;
-    module_t *p_module = NULL;
+    module_config_t *p_item, *p_config, *p_end;
 
     /* Initializations */
     p_intf = _p_intf;
     p_prefs_dialog = _p_prefs_dialog;
+    vlc_list_t *p_list = NULL;
 
-    b_advanced = VLC_TRUE;
+    b_advanced = true;
 
-    if( i_object_id == PLUGIN_ID || i_object_id == GENERAL_ID ||
-        i_object_id == CAPABILITY_ID )
+    if( config_data->i_type == TYPE_CATEGORY )
     {
-        label = CreateWindow( _T("STATIC"), _FROMMB(psz_section),
+        label = CreateWindow( _T("STATIC"), _FROMMB(psz_name),
                               WS_CHILD | WS_VISIBLE | SS_LEFT,
                               5, 10 + (15 + 10), 200, 15,
                               parent, NULL, hInst, NULL );
@@ -723,39 +779,79 @@ PrefsPanel::PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
     else
     {
         /* Get a pointer to the module */
-        p_module = (module_t *)vlc_object_get( p_intf,  i_object_id );
-        if( p_module->i_object_type != VLC_OBJECT_MODULE )
+        if( config_data->i_type == TYPE_MODULE )
+        {
+            p_module = config_data->p_module;
+        }
+        else
         {
-            /* 0OOoo something went really bad */
-            return;
+            /* List the plugins */
+            int i_index;
+            bool b_found = false;
+            p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+            if( !p_list ) return;
+
+            for( i_index = 0; i_index < p_list->i_count; i_index++ )
+            {
+                p_module = (module_t *)p_list->p_values[i_index].p_object;
+                if( !strcmp( module_GetObjName(p_module), "main" ) )
+                {
+                    b_found = true;
+                    break;
+                }
+            }
+            if( !p_module && !b_found )
+            {
+                msg_Warn( p_intf, "unable to create preferences "
+                        "(main module not found)" );
+                return;
+            }
         }
 
         /* Enumerate config options and add corresponding config boxes
          * (submodules don't have config options, they are stored in the
          *  parent module) */
-        if( p_module->b_submodule )
-            p_item = ((module_t *)p_module->p_parent)->p_config;
-        else
-            p_item = p_module->p_config;
+        unsigned confsize;
+        p_config = module_GetConfig( (module_t *) p_module,&confsize);
+
+        p_item = p_config;
+        p_end = p_config + confsize;
 
         /* Find the category if it has been specified */
-        if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
+        if( config_data->i_type == TYPE_SUBCATEGORY ||
+            config_data->i_type == TYPE_CATSUBCAT )
         {
-            while( !p_item->i_type == CONFIG_HINT_CATEGORY ||
-                   strcmp( psz_section, p_item->psz_text ) )
+            for( ; p_item && p_item < p_end ; p_item++ )
             {
-                if( p_item->i_type == CONFIG_HINT_END )
+                if( p_item->i_type == CONFIG_SUBCATEGORY &&
+                    ( config_data->i_type == TYPE_SUBCATEGORY &&
+                    p_item->value.i == config_data->i_object_id ) ||
+                    ( config_data->i_type == TYPE_CATSUBCAT &&
+                    p_item->value.i == config_data->i_subcat_id ) )
+                {
                     break;
-                p_item++;
+                }
             }
         }
 
         /* Add a head title to the panel */
-        label = CreateWindow( _T("STATIC"), _FROMMB(psz_section ?
-                        p_item->psz_text : p_module->psz_longname),
+        const char *psz_head;
+        if( config_data->i_type == TYPE_SUBCATEGORY ||
+            config_data->i_type == TYPE_CATSUBCAT )
+        {
+            psz_head = config_data->psz_name;
+            p_item++;
+        }
+        else
+        {
+            psz_head = module_GetLongName(p_module);
+        }
+
+        label = CreateWindow( _T("STATIC"), _FROMMB(psz_head ?
+                psz_head : _("Unknown")),
                         WS_CHILD | WS_VISIBLE | SS_LEFT,
                         5, 10 + (15 + 10), 250, 15,
-                        parent, NULL, hInst, NULL );
+                                 parent, NULL, hInst, NULL );
 
         WNDCLASS wc;
         memset( &wc, 0, sizeof(wc) );
@@ -780,15 +876,20 @@ PrefsPanel::PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
                         parent, NULL, hInst, (void *) _p_prefs_dialog );
 
         int y_pos = 5;
-        if( p_item ) do
+        for( ; p_item && p_item < p_end ; p_item++ )
         {
             /* If a category has been specified, check we finished the job */
-            if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
-                strcmp( psz_section, p_item->psz_text ) )
+            if( ( ( config_data->i_type == TYPE_SUBCATEGORY &&
+                    p_item->value.i != config_data->i_object_id ) ||
+                    ( config_data->i_type == TYPE_CATSUBCAT  &&
+                    p_item->value.i != config_data->i_subcat_id ) ) &&
+                    (p_item->i_type == CONFIG_CATEGORY ||
+                    p_item->i_type == CONFIG_SUBCATEGORY ) )
                 break;
 
-            ConfigControl *control =
-                CreateConfigControl( VLC_OBJECT(p_intf),
+            ConfigControl *control = NULL;
+
+            control = CreateConfigControl( VLC_OBJECT(p_intf),
                                      p_item, config_window,
                                      hInst, &y_pos );
 
@@ -798,8 +899,6 @@ PrefsPanel::PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
             /* Add the config data to our array so we can keep a trace of it */
             config_array.push_back( control );
         }
-        while( p_item->i_type != CONFIG_HINT_END && p_item++ );
-                
         GetWindowRect( config_window, &rc);
         maxvalue = y_pos - (rc.bottom - rc.top) + 5;
         oldvalue = 0;
@@ -822,7 +921,6 @@ void PrefsPanel::Show()
 void PrefsPanel::ApplyChanges()
 {
     vlc_value_t val;
-
     for( size_t i = 0; i < config_array.size(); i++ )
     {
         ConfigControl *control = config_array[i];
@@ -839,7 +937,7 @@ void PrefsPanel::ApplyChanges()
         case CONFIG_ITEM_KEY:
             /* So you don't need to restart to have the changes take effect */
             val.i_int = control->GetIntValue();
-            var_Set( p_intf->p_vlc, control->GetName(), val );
+            var_Set( p_intf->p_libvlc, control->GetName(), val );
         case CONFIG_ITEM_INTEGER:
         case CONFIG_ITEM_BOOL:
             config_PutInt( p_intf, control->GetName(),