]> git.sesse.net Git - vlc/blobdiff - plugins/gtk/gtk_preferences.c
* ALL: the first libvlc commit.
[vlc] / plugins / gtk / gtk_preferences.c
index a9e425f7bfe0d87498e8bc26eabbf4e253d59476..8e635dec9bfee871608134cbfcd13bfdfda860b3 100644 (file)
@@ -2,7 +2,7 @@
  * gtk_preferences.c: functions to handle the preferences dialog box.
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
- * $Id: gtk_preferences.c,v 1.21 2002/03/31 22:59:01 gbazin Exp $
+ * $Id: gtk_preferences.c,v 1.30 2002/06/01 12:31:59 sam Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *          Loïc Minier <lool@via.ecp.fr>
@@ -34,7 +34,8 @@
 #include <sys/types.h>                                              /* off_t */
 #include <stdlib.h>
 
-#include <videolan/vlc.h>
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
 
 #ifdef MODULE_NAME_IS_gnome
 #   include <gnome.h>
@@ -44,8 +45,6 @@
 
 #include <string.h>
 
-#include "interface.h"
-
 #include "gtk_support.h"
 #include "gtk_common.h"
 #include "gtk_preferences.h"
@@ -62,15 +61,16 @@ static void GtkConfigDialogDestroyed ( GtkObject *, gpointer );
 
 static void GtkStringChanged     ( GtkEditable *, gpointer );
 static void GtkIntChanged        ( GtkEditable *, gpointer );
+static void GtkFloatChanged      ( GtkEditable *, gpointer );
 static void GtkBoolChanged       ( GtkToggleButton *, gpointer );
 
 static void GtkFreeHashTable     ( gpointer );
 static void GtkFreeHashValue     ( gpointer, gpointer, gpointer );
-static void GtkSaveHashValue     ( gpointer, gpointer, gpointer );
+static gboolean GtkSaveHashValue ( gpointer, gpointer, gpointer );
 
-static void GtkPluginConfigure   ( GtkButton *, gpointer );
-static void GtkPluginSelected    ( GtkButton *, gpointer );
-static void GtkPluginHighlighted ( GtkCList *, int, int, GdkEventButton *,
+static void GtkModuleConfigure   ( GtkButton *, gpointer );
+static void GtkModuleSelected    ( GtkButton *, gpointer );
+static void GtkModuleHighlighted ( GtkCList *, int, int, GdkEventButton *,
                                    gpointer );
 
 /****************************************************************************
@@ -118,7 +118,7 @@ static void GtkCreateConfigDialog( char *psz_module_name,
                                    intf_thread_t *p_intf )
 {
     module_t *p_module, *p_module_bis;
-    int i;
+    module_config_t *p_item;
 
     guint rows = 0;
 
@@ -149,11 +149,12 @@ static void GtkCreateConfigDialog( char *psz_module_name,
     GtkWidget *item_vbox;
     GtkWidget *string_entry;
     GtkWidget *integer_spinbutton;
+    GtkWidget *float_spinbutton;
     GtkObject *item_adj;
     GtkWidget *bool_checkbutton;
-    GtkWidget *plugin_clist;
-    GtkWidget *plugin_config_button;
-    GtkWidget *plugin_select_button;
+    GtkWidget *module_clist;
+    GtkWidget *module_config_button;
+    GtkWidget *module_select_button;
 
     gint category_max_height;
 
@@ -175,12 +176,15 @@ static void GtkCreateConfigDialog( char *psz_module_name,
 
 
     /* Look for the selected module */
-    for( p_module = p_module_bank->first ; p_module != NULL ;
+    for( p_module = p_intf->p_vlc->module_bank.first ; p_module != NULL ;
          p_module = p_module->next )
     {
 
-        if( psz_module_name && !strcmp( psz_module_name, p_module->psz_name ) )
+        if( psz_module_name
+             && !strcmp( psz_module_name, p_module->psz_object_name ) )
+        {
             break;
+        }
     }
     if( !p_module ) return;
 
@@ -190,14 +194,16 @@ static void GtkCreateConfigDialog( char *psz_module_name,
 #ifdef MODULE_NAME_IS_gnome
     config_dialog = gnome_dialog_new( p_module->psz_longname, NULL );
     config_dialog_vbox = GNOME_DIALOG(config_dialog)->vbox;
-    category_max_height = config_GetIntVariable( "gnome_prefs_maxh" );
 #else
     config_dialog = gtk_dialog_new();
     gtk_window_set_title( GTK_WINDOW(config_dialog), p_module->psz_longname );
     config_dialog_vbox = GTK_DIALOG(config_dialog)->vbox;
-    category_max_height = config_GetIntVariable( "gtk_prefs_maxh" );
 #endif
 
+    gtk_object_set_data( GTK_OBJECT(config_dialog), "p_intf", p_intf );
+
+    category_max_height = config_GetInt( p_intf, MODULE_STRING "-prefs-maxh" );
+
     gtk_window_set_policy( GTK_WINDOW(config_dialog), TRUE, TRUE, FALSE );
     gtk_container_set_border_width( GTK_CONTAINER(config_dialog_vbox), 0 );
 
@@ -213,10 +219,10 @@ static void GtkCreateConfigDialog( char *psz_module_name,
     gtk_container_add( GTK_CONTAINER(config_dialog_vbox), config_notebook );
 
     /* Enumerate config options and add corresponding config boxes */
-    for( i = 0; i < p_module->i_config_lines; i++ )
+    p_item = p_module->p_config;
+    do
     {
-
-        switch( p_module->p_config[i].i_type )
+        switch( p_item->i_type )
         {
 
         case MODULE_CONFIG_HINT_CATEGORY:
@@ -270,26 +276,27 @@ static void GtkCreateConfigDialog( char *psz_module_name,
                                           _requisition.height );
 
             }
-            if( p_module->p_config[i].i_type == MODULE_CONFIG_HINT_END ) break;
-
 
             /*
              * Now we can start taking care of the new category
              */
 
-            /* create a new table for right-left alignment of children */
-            category_table = gtk_table_new( 0, 0, FALSE );
-            gtk_table_set_col_spacings( GTK_TABLE(category_table), 4 );
-            rows = 0;
+            if( p_item->i_type == MODULE_CONFIG_HINT_CATEGORY )
+            {
+                /* create a new table for right-left alignment of children */
+                category_table = gtk_table_new( 0, 0, FALSE );
+                gtk_table_set_col_spacings( GTK_TABLE(category_table), 4 );
+                rows = 0;
 
-            /* create a new category label */
-            category_label = gtk_label_new( p_module->p_config[i].psz_text );
+                /* create a new category label */
+                category_label = gtk_label_new( p_item->psz_text );
+            }
 
             break;
 
-        case MODULE_CONFIG_ITEM_PLUGIN:
+        case MODULE_CONFIG_ITEM_MODULE:
 
-            item_frame = gtk_frame_new( p_module->p_config[i].psz_text );
+            item_frame = gtk_frame_new( p_item->psz_text );
 
             gtk_table_resize( GTK_TABLE(category_table), ++rows, 2 );
             gtk_table_attach_defaults( GTK_TABLE(category_table), item_frame,
@@ -300,42 +307,41 @@ static void GtkCreateConfigDialog( char *psz_module_name,
 
             /* create a new clist widget */
             {
-                gchar * titles[] = { "Name", "Description" };
+                gchar * titles[] = { _("Name"), _("Description") };
 
-                plugin_clist =
-                    gtk_clist_new_with_titles( 2, titles );
+                module_clist = gtk_clist_new_with_titles( 2, titles );
             }
-            gtk_clist_column_titles_passive( GTK_CLIST(plugin_clist) );
-            gtk_clist_set_selection_mode( GTK_CLIST(plugin_clist),
+            gtk_object_set_data( GTK_OBJECT(module_clist), "p_intf", p_intf );
+            gtk_clist_column_titles_passive( GTK_CLIST(module_clist) );
+            gtk_clist_set_selection_mode( GTK_CLIST(module_clist),
                                           GTK_SELECTION_SINGLE);
-            gtk_container_add( GTK_CONTAINER(item_vbox), plugin_clist );
+            gtk_container_add( GTK_CONTAINER(item_vbox), module_clist );
 
-            /* build a list of available plugins */
+            /* build a list of available modules */
             {
                 gchar * entry[2];
 
-                for( p_module_bis = p_module_bank->first ;
+                for( p_module_bis = p_intf->p_vlc->module_bank.first ;
                      p_module_bis != NULL ;
                      p_module_bis = p_module_bis->next )
                 {
-                    if( p_module_bis->i_capabilities &
-                        (1 << p_module->p_config[i].i_value) )
+                    if( p_module_bis->i_capabilities & (1 << p_item->i_value) )
                     {
-                        entry[0] = p_module_bis->psz_name;
+                        entry[0] = p_module_bis->psz_object_name;
                         entry[1] = p_module_bis->psz_longname;
-                        gtk_clist_append( GTK_CLIST(plugin_clist), entry );
+                        gtk_clist_append( GTK_CLIST(module_clist), entry );
                     }
                 }
             }
 
-            gtk_clist_set_column_auto_resize( GTK_CLIST(plugin_clist),
+            gtk_clist_set_column_auto_resize( GTK_CLIST(module_clist),
                                               0, TRUE );
-            gtk_clist_set_column_auto_resize( GTK_CLIST(plugin_clist),
+            gtk_clist_set_column_auto_resize( GTK_CLIST(module_clist),
                                               1, TRUE );
 
-            /* connect signals to the plugins list */
-            gtk_signal_connect( GTK_OBJECT(plugin_clist), "select_row",
-                                GTK_SIGNAL_FUNC(GtkPluginHighlighted),
+            /* connect signals to the modules list */
+            gtk_signal_connect( GTK_OBJECT(module_clist), "select_row",
+                                GTK_SIGNAL_FUNC(GtkModuleHighlighted),
                                 NULL );
 
             /* hbox holding the "select" and "configure" buttons */
@@ -343,25 +349,25 @@ static void GtkCreateConfigDialog( char *psz_module_name,
             gtk_container_add( GTK_CONTAINER(item_vbox), item_hbox);
 
             /* add configure button */
-            plugin_config_button =
+            module_config_button =
                 gtk_button_new_with_label( _("Configure") );
-            gtk_widget_set_sensitive( plugin_config_button, FALSE );
+            gtk_widget_set_sensitive( module_config_button, FALSE );
             gtk_container_add( GTK_CONTAINER(item_hbox),
-                               plugin_config_button );
-            gtk_object_set_data( GTK_OBJECT(plugin_config_button),
+                               module_config_button );
+            gtk_object_set_data( GTK_OBJECT(module_config_button),
                                  "p_intf", p_intf );
-            gtk_object_set_data( GTK_OBJECT(plugin_clist),
-                                 "config_button", plugin_config_button );
+            gtk_object_set_data( GTK_OBJECT(module_clist),
+                                 "config_button", module_config_button );
 
             /* add select button */
-            plugin_select_button =
+            module_select_button =
                 gtk_button_new_with_label( _("Select") );
             gtk_container_add( GTK_CONTAINER(item_hbox),
-                               plugin_select_button );
+                               module_select_button );
             /* add a tooltip on mouseover */
             gtk_tooltips_set_tip( p_intf->p_sys->p_tooltips,
-                                  plugin_select_button,
-                                  p_module->p_config[i].psz_longtext, "" );
+                                  module_select_button,
+                                  p_item->psz_longtext, "" );
 
             /* hbox holding the "selected" label and text input */
             item_hbox = gtk_hbox_new( FALSE, 4 );
@@ -372,30 +378,28 @@ static void GtkCreateConfigDialog( char *psz_module_name,
 
             /* add input box with default value */
             string_entry = gtk_entry_new();
-            gtk_object_set_data( GTK_OBJECT(plugin_clist),
-                                 "plugin_entry", string_entry );
+            gtk_object_set_data( GTK_OBJECT(module_clist),
+                                 "module_entry", string_entry );
             gtk_container_add( GTK_CONTAINER(item_hbox), string_entry );
-            vlc_mutex_lock( p_module->p_config[i].p_lock );
+            vlc_mutex_lock( p_item->p_lock );
             gtk_entry_set_text( GTK_ENTRY(string_entry),
-                                p_module->p_config[i].psz_value ?
-                                p_module->p_config[i].psz_value : "" );
-            vlc_mutex_unlock( p_module->p_config[i].p_lock );
+                                p_item->psz_value ? p_item->psz_value : "" );
+            vlc_mutex_unlock( p_item->p_lock );
             /* add a tooltip on mouseover */
             gtk_tooltips_set_tip( p_intf->p_sys->p_tooltips,
-                                  string_entry,
-                                  p_module->p_config[i].psz_longtext, "" );
+                                  string_entry, p_item->psz_longtext, "" );
 
             /* connect signals to the buttons */
-            gtk_signal_connect( GTK_OBJECT(plugin_config_button), "clicked",
-                                GTK_SIGNAL_FUNC(GtkPluginConfigure),
-                                (gpointer)plugin_clist );
-            gtk_signal_connect( GTK_OBJECT(plugin_select_button), "clicked",
-                                GTK_SIGNAL_FUNC(GtkPluginSelected),
-                                (gpointer)plugin_clist );
+            gtk_signal_connect( GTK_OBJECT(module_config_button), "clicked",
+                                GTK_SIGNAL_FUNC(GtkModuleConfigure),
+                                (gpointer)module_clist );
+            gtk_signal_connect( GTK_OBJECT(module_select_button), "clicked",
+                                GTK_SIGNAL_FUNC(GtkModuleSelected),
+                                (gpointer)module_clist );
 
             /* connect signal to track changes in the text box */
             gtk_object_set_data( GTK_OBJECT(string_entry), "config_option",
-                                 p_module->p_config[i].psz_name );
+                                 p_item->psz_name );
             gtk_signal_connect( GTK_OBJECT(string_entry), "changed",
                                 GTK_SIGNAL_FUNC(GtkStringChanged),
                                 (gpointer)config_dialog );
@@ -406,43 +410,58 @@ static void GtkCreateConfigDialog( char *psz_module_name,
 
             /* add input box with default value */
             string_entry = gtk_entry_new();
-            vlc_mutex_lock( p_module->p_config[i].p_lock );
+            vlc_mutex_lock( p_item->p_lock );
             gtk_entry_set_text( GTK_ENTRY(string_entry),
-                                p_module->p_config[i].psz_value ?
-                                p_module->p_config[i].psz_value : "" );
-            vlc_mutex_unlock( p_module->p_config[i].p_lock );
+                                p_item->psz_value ? p_item->psz_value : "" );
+            vlc_mutex_unlock( p_item->p_lock );
 
             /* connect signal to track changes in the text box */
             gtk_object_set_data( GTK_OBJECT(string_entry), "config_option",
-                                 p_module->p_config[i].psz_name );
+                                 p_item->psz_name );
             gtk_signal_connect( GTK_OBJECT(string_entry), "changed",
                                 GTK_SIGNAL_FUNC(GtkStringChanged),
                                 (gpointer)config_dialog );
 
-            LABEL_AND_WIDGET( p_module->p_config[i].psz_text,
-                              string_entry,
-                              p_module->p_config[i].psz_longtext );
+            LABEL_AND_WIDGET( p_item->psz_text,
+                              string_entry, p_item->psz_longtext );
             break;
 
         case MODULE_CONFIG_ITEM_INTEGER:
 
             /* add input box with default value */
-            item_adj = gtk_adjustment_new( p_module->p_config[i].i_value,
+            item_adj = gtk_adjustment_new( p_item->i_value,
                                            -1, 99999, 1, 10, 10 );
             integer_spinbutton = gtk_spin_button_new( GTK_ADJUSTMENT(item_adj),
                                                       1, 0 );
 
             /* connect signal to track changes in the spinbutton value */
             gtk_object_set_data( GTK_OBJECT(integer_spinbutton),
-                                 "config_option",
-                                 p_module->p_config[i].psz_name );
+                                 "config_option", p_item->psz_name );
             gtk_signal_connect( GTK_OBJECT(integer_spinbutton), "changed",
                                 GTK_SIGNAL_FUNC(GtkIntChanged),
                                 (gpointer)config_dialog );
 
-            LABEL_AND_WIDGET( p_module->p_config[i].psz_text,
-                              integer_spinbutton,
-                              p_module->p_config[i].psz_longtext );
+            LABEL_AND_WIDGET( p_item->psz_text,
+                              integer_spinbutton, p_item->psz_longtext );
+            break;
+
+        case MODULE_CONFIG_ITEM_FLOAT:
+
+            /* add input box with default value */
+            item_adj = gtk_adjustment_new( p_item->f_value,
+                                           0, 99999, 0.01, 10, 10 );
+            float_spinbutton = gtk_spin_button_new( GTK_ADJUSTMENT(item_adj),
+                                                    0.01, 2 );
+
+            /* connect signal to track changes in the spinbutton value */
+            gtk_object_set_data( GTK_OBJECT(float_spinbutton),
+                                 "config_option", p_item->psz_name );
+            gtk_signal_connect( GTK_OBJECT(float_spinbutton), "changed",
+                                GTK_SIGNAL_FUNC(GtkFloatChanged),
+                                (gpointer)config_dialog );
+
+            LABEL_AND_WIDGET( p_item->psz_text,
+                              float_spinbutton, p_item->psz_longtext );
             break;
 
         case MODULE_CONFIG_ITEM_BOOL:
@@ -450,22 +469,23 @@ static void GtkCreateConfigDialog( char *psz_module_name,
             /* add check button */
             bool_checkbutton = gtk_check_button_new();
             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(bool_checkbutton),
-                                          p_module->p_config[i].i_value );
+                                          p_item->i_value );
 
             /* connect signal to track changes in the button state */
             gtk_object_set_data( GTK_OBJECT(bool_checkbutton), "config_option",
-                                 p_module->p_config[i].psz_name );
+                                 p_item->psz_name );
             gtk_signal_connect( GTK_OBJECT(bool_checkbutton), "toggled",
                                 GTK_SIGNAL_FUNC(GtkBoolChanged),
                                 (gpointer)config_dialog );
 
-            LABEL_AND_WIDGET( p_module->p_config[i].psz_text,
-                              bool_checkbutton,
-                              p_module->p_config[i].psz_longtext );
+            LABEL_AND_WIDGET( p_item->psz_text,
+                              bool_checkbutton, p_item->psz_longtext );
             break;
 
         }
+
     }
+    while( p_item->i_type != MODULE_CONFIG_HINT_END && p_item++ );
 
 #ifndef MODULE_NAME_IS_gnome
     /* Now let's add the action buttons at the bottom of the page */
@@ -503,7 +523,7 @@ static void GtkCreateConfigDialog( char *psz_module_name,
     cancel_button =
         GTK_WIDGET(g_list_last(GNOME_DIALOG(config_dialog)->buttons)->data);
 #else
-    ok_button = gtk_button_new_with_label( _("Ok") );
+    ok_button = gtk_button_new_with_label( _("OK") );
     gtk_box_pack_start( GTK_BOX(dialog_action_area), ok_button,
                         TRUE, TRUE, 0 );
 
@@ -523,6 +543,9 @@ static void GtkCreateConfigDialog( char *psz_module_name,
     gtk_signal_connect( GTK_OBJECT(ok_button), "clicked",
                         GTK_SIGNAL_FUNC(GtkConfigOk),
                         config_dialog );
+    gtk_widget_set_sensitive( apply_button, FALSE );
+    gtk_object_set_data( GTK_OBJECT(config_dialog), "apply_button",
+                         apply_button );
     gtk_signal_connect( GTK_OBJECT(apply_button), "clicked",
                         GTK_SIGNAL_FUNC(GtkConfigApply),
                         config_dialog );
@@ -554,15 +577,24 @@ static void GtkCreateConfigDialog( char *psz_module_name,
 
 /****************************************************************************
  * GtkConfigApply: store the changes to the config inside the modules
- * configuration structure
+ * configuration structure and clear the hash table.
  ****************************************************************************/
 void GtkConfigApply( GtkButton * button, gpointer user_data )
 {
+    intf_thread_t *p_intf;
     GHashTable *hash_table;
+    GtkWidget *apply_button;
+
     hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
                                                     "config_hash_table" );
-    g_hash_table_foreach( hash_table, GtkSaveHashValue, NULL );
+    p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(user_data),
+                                                   "p_intf" );
+    g_hash_table_foreach_remove( hash_table, GtkSaveHashValue, (void*)p_intf );
 
+    /* change the highlight status of the Apply button */
+    apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+                                                    "apply_button" );
+    gtk_widget_set_sensitive( apply_button, FALSE );
 }
 
 void GtkConfigOk( GtkButton * button, gpointer user_data )
@@ -579,33 +611,41 @@ void GtkConfigCancel( GtkButton * button, gpointer user_data )
 
 void GtkConfigSave( GtkButton * button, gpointer user_data )
 {
+    intf_thread_t *p_intf;
+
+    p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(user_data),
+                                                   "p_intf" );
     GtkConfigApply( button, user_data );
-    config_SaveConfigFile( NULL );
+    config_SaveConfigFile( p_intf->p_this, NULL );
 }
 
 /****************************************************************************
- * GtkPluginHighlighted: display plugin description when an entry is selected
+ * GtkModuleHighlighted: display module description when an entry is selected
  *   in the clist, and activate the configure button if necessary.
  ****************************************************************************/
-void GtkPluginHighlighted( GtkCList *plugin_clist, int row, int column,
+void GtkModuleHighlighted( GtkCList *module_clist, int row, int column,
                            GdkEventButton *event, gpointer user_data )
 {
+    intf_thread_t *p_intf;
     GtkWidget *config_button;
     module_t *p_module;
     char *psz_name;
 
-    if( gtk_clist_get_text( GTK_CLIST(plugin_clist), row, 0, &psz_name ) )
+    p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(module_clist),
+                                                   "p_intf" );
+
+    if( gtk_clist_get_text( GTK_CLIST(module_clist), row, 0, &psz_name ) )
     {
-        /* look for plugin 'psz_name' */
-        for( p_module = p_module_bank->first ;
+        /* look for module 'psz_name' */
+        for( p_module = p_intf->p_vlc->module_bank.first ;
              p_module != NULL ;
              p_module = p_module->next )
         {
-          if( !strcmp( p_module->psz_name, psz_name ) )
+          if( !strcmp( p_module->psz_object_name, psz_name ) )
           {
-              gtk_object_set_data( GTK_OBJECT(plugin_clist),
-                                   "plugin_highlighted", p_module );
-              config_button = gtk_object_get_data( GTK_OBJECT(plugin_clist),
+              gtk_object_set_data( GTK_OBJECT(module_clist),
+                                   "module_highlighted", p_module );
+              config_button = gtk_object_get_data( GTK_OBJECT(module_clist),
                                                    "config_button" );
               if( p_module->i_config_items )
                   gtk_widget_set_sensitive( config_button, TRUE );
@@ -620,38 +660,38 @@ void GtkPluginHighlighted( GtkCList *plugin_clist, int row, int column,
 }
 
 /****************************************************************************
- * GtkPluginConfigure: display plugin configuration dialog box.
+ * GtkModuleConfigure: display module configuration dialog box.
  ****************************************************************************/
-void GtkPluginConfigure( GtkButton *button, gpointer user_data )
+void GtkModuleConfigure( GtkButton *button, gpointer user_data )
 {
     module_t *p_module;
     intf_thread_t *p_intf;
 
     p_module = (module_t *)gtk_object_get_data( GTK_OBJECT(user_data),
-                                                "plugin_highlighted" );
+                                                "module_highlighted" );
 
     if( !p_module ) return;
     p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(button),
                                                    "p_intf" );
-    GtkCreateConfigDialog( p_module->psz_name, (gpointer)p_intf );
+    GtkCreateConfigDialog( p_module->psz_object_name, (gpointer)p_intf );
 
 }
 
 /****************************************************************************
- * GtkPluginSelected: select plugin.
+ * GtkModuleSelected: select module.
  ****************************************************************************/
-void GtkPluginSelected( GtkButton *button, gpointer user_data )
+void GtkModuleSelected( GtkButton *button, gpointer user_data )
 {
     module_t *p_module;
     GtkWidget *widget;
 
     p_module = (module_t *)gtk_object_get_data( GTK_OBJECT(user_data),
-                                                "plugin_highlighted" );
+                                                "module_highlighted" );
     widget = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
-                                               "plugin_entry" );
+                                               "module_entry" );
     if( !p_module ) return;
 
-    gtk_entry_set_text( GTK_ENTRY(widget), p_module->psz_name );
+    gtk_entry_set_text( GTK_ENTRY(widget), p_module->psz_object_name );
 
 }
 
@@ -660,16 +700,19 @@ void GtkPluginSelected( GtkButton *button, gpointer user_data )
  ****************************************************************************/
 static void GtkStringChanged( GtkEditable *editable, gpointer user_data )
 {
+    intf_thread_t *p_intf;
     module_config_t *p_config;
-
     GHashTable *hash_table;
+    GtkWidget *apply_button;
 
+    p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(editable),
+                                                   "p_intf" );
     hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
                                                     "config_hash_table" );
     /* free old p_config */
     p_config = (module_config_t *)g_hash_table_lookup( hash_table,
                                                        (gpointer)editable );
-    if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, NULL );
+    if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, (void *)p_intf );
 
     p_config = malloc( sizeof(module_config_t) );
     p_config->i_type = MODULE_CONFIG_ITEM_STRING;
@@ -679,16 +722,26 @@ static void GtkStringChanged( GtkEditable *editable, gpointer user_data )
 
     g_hash_table_insert( hash_table, (gpointer)editable,
                          (gpointer)p_config );
+
+    /* change the highlight status of the Apply button */
+    apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+                                                    "apply_button" );
+    gtk_widget_set_sensitive( apply_button, TRUE );
 }
 
 /****************************************************************************
- * GtkIntChanged: signal called when the user changes a an integer value.
+ * GtkIntChanged: signal called when the user changes an integer value.
  ****************************************************************************/
 static void GtkIntChanged( GtkEditable *editable, gpointer user_data )
 {
+    intf_thread_t *p_intf;
     module_config_t *p_config;
-
     GHashTable *hash_table;
+    GtkWidget *apply_button;
+
+    p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(editable),
+                                                   "p_intf" );
+    gtk_spin_button_update( GTK_SPIN_BUTTON(editable) );
 
     hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
                                                     "config_hash_table" );
@@ -696,35 +749,81 @@ static void GtkIntChanged( GtkEditable *editable, gpointer user_data )
     /* free old p_config */
     p_config = (module_config_t *)g_hash_table_lookup( hash_table,
                                                        (gpointer)editable );
-    if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, NULL );
+    if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, (void *)p_intf );
 
     p_config = malloc( sizeof(module_config_t) );
     p_config->i_type = MODULE_CONFIG_ITEM_INTEGER;
-    p_config->i_value =  gtk_spin_button_get_value_as_int(
-                             GTK_SPIN_BUTTON(editable) );
+    p_config->i_value = gtk_spin_button_get_value_as_int(
+                            GTK_SPIN_BUTTON(editable) );
+    p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(editable),
+                                                      "config_option" );
+
+    g_hash_table_insert( hash_table, (gpointer)editable,
+                         (gpointer)p_config );
+
+    /* change the highlight status of the Apply button */
+    apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+                                                    "apply_button" );
+    gtk_widget_set_sensitive( apply_button, TRUE );
+}
+
+/****************************************************************************
+ * GtkFloatChanged: signal called when the user changes a float value.
+ ****************************************************************************/
+static void GtkFloatChanged( GtkEditable *editable, gpointer user_data )
+{
+    intf_thread_t *p_intf;
+    module_config_t *p_config;
+    GHashTable *hash_table;
+    GtkWidget *apply_button;
+
+    p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(editable),
+                                                   "p_intf" );
+    gtk_spin_button_update( GTK_SPIN_BUTTON(editable) );
+
+    hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
+                                                    "config_hash_table" );
+
+    /* free old p_config */
+    p_config = (module_config_t *)g_hash_table_lookup( hash_table,
+                                                       (gpointer)editable );
+    if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, (void *)p_intf );
+
+    p_config = malloc( sizeof(module_config_t) );
+    p_config->i_type = MODULE_CONFIG_ITEM_FLOAT;
+    p_config->f_value = gtk_spin_button_get_value_as_float(
+                           GTK_SPIN_BUTTON(editable) );
     p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(editable),
                                                       "config_option" );
 
     g_hash_table_insert( hash_table, (gpointer)editable,
                          (gpointer)p_config );
+
+    /* change the highlight status of the Apply button */
+    apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+                                                    "apply_button" );
+    gtk_widget_set_sensitive( apply_button, TRUE );
 }
 
 /****************************************************************************
- * GtkStringChanged: signal called when the user changes a bool value.
+ * GtkBoolChanged: signal called when the user changes a bool value.
  ****************************************************************************/
 static void GtkBoolChanged( GtkToggleButton *button, gpointer user_data )
 {
+    intf_thread_t *p_intf;
     module_config_t *p_config;
-
     GHashTable *hash_table;
+    GtkWidget *apply_button;
 
+    p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(button),
+                                                   "p_intf" );
     hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
                                                     "config_hash_table" );
 
     /* free old p_config */
     p_config = (module_config_t *)g_hash_table_lookup( hash_table,
                                                        (gpointer)button );
-    if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, NULL );
+    if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, (void *)p_intf );
 
     p_config = malloc( sizeof(module_config_t) );
     p_config->i_type = MODULE_CONFIG_ITEM_BOOL;
@@ -734,6 +833,11 @@ static void GtkBoolChanged( GtkToggleButton *button, gpointer user_data )
 
     g_hash_table_insert( hash_table, (gpointer)button,
                          (gpointer)p_config );
+
+    /* change the highlight status of the Apply button */
+    apply_button = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
+                                                    "apply_button" );
+    gtk_widget_set_sensitive( apply_button, TRUE );
 }
 
 /****************************************************************************
@@ -742,8 +846,10 @@ static void GtkBoolChanged( GtkToggleButton *button, gpointer user_data )
 static void GtkFreeHashTable( gpointer user_data )
 {
     GHashTable *hash_table = (GHashTable *)user_data;
+    intf_thread_t *p_intf =
+      (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(hash_table), "p_intf" );
 
-    g_hash_table_foreach( hash_table, GtkFreeHashValue, NULL );
+    g_hash_table_foreach( hash_table, GtkFreeHashValue, (void *)p_intf );
     g_hash_table_destroy( hash_table );
 }
 
@@ -753,10 +859,10 @@ static void GtkFreeHashTable( gpointer user_data )
  ****************************************************************************/
 static void GtkFreeHashValue( gpointer key, gpointer value, gpointer user_data)
 {
-    module_config_t *p_config = (module_config_t *)value;
+    module_config_t * p_config = (module_config_t *)value;
 
     if( p_config->i_type == MODULE_CONFIG_ITEM_STRING )
-        g_free( p_config->psz_value );
+        if( p_config->psz_value ) g_free( p_config->psz_value );
     free( p_config );
 }
 
@@ -764,24 +870,37 @@ static void GtkFreeHashValue( gpointer key, gpointer value, gpointer user_data)
  * GtkSaveHashValue: callback used when enumerating the hash table in
  * GtkConfigApply().
  ****************************************************************************/
-static void GtkSaveHashValue( gpointer key, gpointer value, gpointer user_data)
+static gboolean GtkSaveHashValue( gpointer key, gpointer value,
+                                  gpointer user_data )
 {
-    module_config_t *p_config = (module_config_t *)value;
+    intf_thread_t *   p_intf   = (intf_thread_t *)user_data;
+    module_config_t * p_config = (module_config_t *)value;
 
     switch( p_config->i_type )
     {
 
     case MODULE_CONFIG_ITEM_STRING:
     case MODULE_CONFIG_ITEM_FILE:
-    case MODULE_CONFIG_ITEM_PLUGIN:
-        config_PutPszVariable( p_config->psz_name,
-            *p_config->psz_value? p_config->psz_value : NULL );
+    case MODULE_CONFIG_ITEM_MODULE:
+        config_PutPsz( p_intf, p_config->psz_name,
+                       *p_config->psz_value ? p_config->psz_value : NULL );
         break;
     case MODULE_CONFIG_ITEM_INTEGER:
     case MODULE_CONFIG_ITEM_BOOL:
-        config_PutIntVariable( p_config->psz_name, p_config->i_value );
+        config_PutInt( p_intf, p_config->psz_name, p_config->i_value );
+        break;
+    case MODULE_CONFIG_ITEM_FLOAT:
+        config_PutFloat( p_intf, p_config->psz_name, p_config->f_value );
         break;
     }
+
+    /* free the hash value we allocated */
+    if( p_config->i_type == MODULE_CONFIG_ITEM_STRING )
+        g_free( p_config->psz_value );
+    free( p_config );
+
+    /* return TRUE so glib will free the hash entry */
+    return TRUE;
 }
 
 /****************************************************************************