1 /*****************************************************************************
2 * gtk_preferences.c: functions to handle the preferences dialog box.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: gtk_preferences.c,v 1.18 2002/03/26 22:30:09 gbazin Exp $
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
8 * Loïc Minier <lool@via.ecp.fr>
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble: Our main job is to build a nice interface from the modules config
27 * structure. Once this is done, we need to track each change made by the
28 * user to the data contained in this interface so that when/if he decides to
29 * apply his changes we can quickly commit them into the modules config
30 * structure. (for this last task we use a GHashTable to accumulate the
31 * changes. To commit them, we then just have to circle through it )
33 *****************************************************************************/
34 #include <sys/types.h> /* off_t */
37 #include <videolan/vlc.h>
39 #ifdef MODULE_NAME_IS_gnome
47 #include "interface.h"
49 #include "gtk_support.h"
50 #include "gtk_common.h"
51 #include "gtk_preferences.h"
54 static void GtkCreateConfigDialog( char *, intf_thread_t * );
56 static void GtkConfigOk ( GtkButton *, gpointer );
57 static void GtkConfigApply ( GtkButton *, gpointer );
58 static void GtkConfigCancel ( GtkButton *, gpointer );
59 static void GtkConfigSave ( GtkButton *, gpointer );
61 static void GtkConfigDialogDestroyed ( GtkObject *, gpointer );
63 static void GtkStringChanged ( GtkEditable *, gpointer );
64 static void GtkIntChanged ( GtkEditable *, gpointer );
65 static void GtkBoolChanged ( GtkToggleButton *, gpointer );
67 static void GtkFreeHashTable ( gpointer );
68 static void GtkFreeHashValue ( gpointer, gpointer, gpointer );
69 static void GtkSaveHashValue ( gpointer, gpointer, gpointer );
71 static void GtkPluginConfigure ( GtkButton *, gpointer );
72 static void GtkPluginSelected ( GtkButton *, gpointer );
73 static void GtkPluginHighlighted ( GtkCList *, int, int, GdkEventButton *,
76 /****************************************************************************
77 * Callback for menuitems: display configuration interface window
78 ****************************************************************************/
79 void GtkPreferencesActivate( GtkMenuItem * menuitem, gpointer user_data )
81 intf_thread_t * p_intf;
83 p_intf = GetIntf( GTK_WIDGET(menuitem), (char*)user_data );
85 GtkCreateConfigDialog( "main", p_intf );
88 /****************************************************************************
89 * GtkCreateConfigDialog: dynamically creates the configuration dialog
90 * box from all the configuration data provided by the selected module.
91 ****************************************************************************/
93 /* create a new tooltipped area */
94 #define TOOLTIP( text ) \
95 /* create an event box to catch some events */ \
96 item_event_box = gtk_event_box_new(); \
97 /* add a tooltip on mouseover */ \
98 /* FIXME: have a different text for the private text */ \
99 gtk_tooltips_set_tip( p_intf->p_sys->p_tooltips, \
100 item_event_box, text, text ); \
101 gtk_container_set_border_width( GTK_CONTAINER(item_event_box), 4 );
103 /* draws a right aligned label in side of a widget */
104 #define LABEL_AND_WIDGET( label_text, widget, tooltip ) \
105 gtk_table_resize( GTK_TABLE(category_table), ++rows, 2 ); \
106 item_align = gtk_alignment_new( 1, .5, 0, 0 ); \
107 item_label = gtk_label_new( label_text ); \
108 gtk_container_add( GTK_CONTAINER(item_align), item_label ); \
110 gtk_container_add( GTK_CONTAINER(item_event_box), item_align ); \
111 gtk_table_attach_defaults( GTK_TABLE(category_table), item_event_box, \
112 0, 1, rows - 1, rows ); \
113 item_align = gtk_alignment_new( 0, .5, .5, 0 ); \
114 gtk_container_add( GTK_CONTAINER(item_align), widget ); \
116 gtk_container_add( GTK_CONTAINER(item_event_box), item_align ); \
117 gtk_table_attach_defaults( GTK_TABLE(category_table), item_event_box, \
118 1, 2, rows - 1, rows );
120 static void GtkCreateConfigDialog( char *psz_module_name,
121 intf_thread_t *p_intf )
123 module_t *p_module, *p_module_bis;
128 GHashTable *config_hash_table;
130 GtkWidget *item_event_box;
132 GtkWidget *config_dialog;
133 GtkWidget *config_dialog_vbox;
134 GtkWidget *config_notebook;
135 GtkWidget *category_table = NULL;
136 GtkWidget *category_vbox = NULL;
138 GtkWidget *dialog_action_area;
139 GtkWidget *ok_button;
140 GtkWidget *apply_button;
141 GtkWidget *save_button;
142 GtkWidget *cancel_button;
144 GtkWidget *item_align;
145 GtkWidget *item_frame;
146 GtkWidget *item_hbox;
147 GtkWidget *item_label;
148 GtkWidget *item_vbox;
149 GtkWidget *string_entry;
150 GtkWidget *integer_spinbutton;
152 GtkWidget *bool_checkbutton;
153 GtkWidget *plugin_clist;
154 GtkWidget *plugin_config_button;
155 GtkWidget *plugin_select_button;
158 /* Check if the dialog box is already opened, if so this will save us
159 * quite a bit of work. (the interface will be destroyed when you actually
160 * close the dialog window, but remember that it is only hidden if you
161 * clicked on the action buttons). This trick also allows us not to
162 * duplicate identical dialog windows. */
164 config_dialog = (GtkWidget *)gtk_object_get_data(
165 GTK_OBJECT(p_intf->p_sys->p_window), psz_module_name );
168 /* Yeah it was open */
169 gtk_widget_show( config_dialog );
170 gtk_widget_grab_focus( config_dialog );
175 /* Look for the selected module */
176 for( p_module = p_module_bank->first ; p_module != NULL ;
177 p_module = p_module->next )
180 if( psz_module_name && !strcmp( psz_module_name, p_module->psz_name ) )
183 if( !p_module ) return;
185 /* We found it, now we can start building its configuration interface */
186 /* Create the configuration dialog box */
187 config_dialog = gtk_dialog_new();
188 gtk_window_set_title( GTK_WINDOW(config_dialog), p_module->psz_longname );
190 config_dialog_vbox = GTK_DIALOG(config_dialog)->vbox;
191 gtk_container_set_border_width( GTK_CONTAINER(config_dialog_vbox), 0 );
193 /* Create our config hash table and associate it with the dialog box */
194 config_hash_table = g_hash_table_new( NULL, NULL );
195 gtk_object_set_data_full( GTK_OBJECT(config_dialog),
196 "config_hash_table", config_hash_table,
197 (GtkDestroyNotify)GtkFreeHashTable );
199 /* Create notebook */
200 config_notebook = gtk_notebook_new();
201 gtk_notebook_set_scrollable( GTK_NOTEBOOK(config_notebook), TRUE );
202 gtk_container_add( GTK_CONTAINER(config_dialog_vbox), config_notebook );
204 /* Enumerate config options and add corresponding config boxes */
205 for( i = 0; i < p_module->i_config_lines; i++ )
208 switch( p_module->p_config[i].i_type )
210 case MODULE_CONFIG_HINT_CATEGORY:
212 /* add a new table for right-left alignment */
213 category_table = gtk_table_new( 0, 0, FALSE );
214 gtk_table_set_col_spacings( GTK_TABLE(category_table), 4 );
216 /* the vbox serves only EXPAND / FILL issues in the notebook */
217 category_vbox = gtk_vbox_new( FALSE, 0 );
218 gtk_box_pack_start( GTK_BOX(category_vbox), category_table,
220 gtk_container_set_border_width( GTK_CONTAINER(category_vbox), 4 );
222 /* add category vbox as a notebook page */
223 item_label = gtk_label_new( p_module->p_config[i].psz_text );
224 gtk_notebook_append_page( GTK_NOTEBOOK(config_notebook),
225 category_vbox, item_label );
230 case MODULE_CONFIG_ITEM_PLUGIN:
232 item_frame = gtk_frame_new( p_module->p_config[i].psz_text );
234 gtk_table_resize( GTK_TABLE(category_table), ++rows, 2 );
235 gtk_table_attach_defaults( GTK_TABLE(category_table), item_frame,
236 0, 2, rows - 1, rows );
238 TOOLTIP( p_module->p_config[i].psz_longtext )
239 gtk_container_add( GTK_CONTAINER(item_frame), item_event_box );
241 item_vbox = gtk_vbox_new( FALSE, 4 );
242 gtk_container_add( GTK_CONTAINER(item_event_box), item_vbox );
244 /* create a new clist widget */
246 gchar * titles[] = { "Name", "Description" };
249 gtk_clist_new_with_titles( 2, titles );
251 gtk_clist_column_titles_passive( GTK_CLIST(plugin_clist) );
252 gtk_clist_set_selection_mode( GTK_CLIST(plugin_clist),
253 GTK_SELECTION_SINGLE);
254 gtk_container_add( GTK_CONTAINER(item_vbox), plugin_clist );
256 /* build a list of available plugins */
260 for( p_module_bis = p_module_bank->first ;
261 p_module_bis != NULL ;
262 p_module_bis = p_module_bis->next )
264 if( p_module_bis->i_capabilities &
265 (1 << p_module->p_config[i].i_value) )
267 entry[0] = p_module_bis->psz_name;
268 entry[1] = p_module_bis->psz_longname;
269 gtk_clist_append( GTK_CLIST(plugin_clist), entry );
274 gtk_clist_set_column_auto_resize( GTK_CLIST(plugin_clist),
276 gtk_clist_set_column_auto_resize( GTK_CLIST(plugin_clist),
279 /* connect signals to the plugins list */
280 gtk_signal_connect( GTK_OBJECT(plugin_clist), "select_row",
281 GTK_SIGNAL_FUNC(GtkPluginHighlighted),
284 /* hbox holding the "select" and "configure" buttons */
285 item_hbox = gtk_hbox_new( FALSE, 4 );
286 gtk_container_add( GTK_CONTAINER(item_vbox), item_hbox);
288 /* add configure button */
289 plugin_config_button =
290 gtk_button_new_with_label( _("Configure") );
291 gtk_widget_set_sensitive( plugin_config_button, FALSE );
292 gtk_container_add( GTK_CONTAINER(item_hbox),
293 plugin_config_button );
294 gtk_object_set_data( GTK_OBJECT(plugin_config_button),
296 gtk_object_set_data( GTK_OBJECT(plugin_clist),
297 "config_button", plugin_config_button );
299 /* add select button */
300 plugin_select_button =
301 gtk_button_new_with_label( _("Select") );
302 gtk_container_add( GTK_CONTAINER(item_hbox),
303 plugin_select_button );
305 /* hbox holding the "selected" label and text input */
306 item_hbox = gtk_hbox_new( FALSE, 4 );
307 gtk_container_add( GTK_CONTAINER(item_vbox), item_hbox);
309 item_label = gtk_label_new( _("Selected:") );
310 gtk_container_add( GTK_CONTAINER(item_hbox), item_label );
312 /* add input box with default value */
313 string_entry = gtk_entry_new();
314 gtk_object_set_data( GTK_OBJECT(plugin_clist),
315 "plugin_entry", string_entry );
316 gtk_container_add( GTK_CONTAINER(item_hbox), string_entry );
317 vlc_mutex_lock( p_module->p_config[i].p_lock );
318 gtk_entry_set_text( GTK_ENTRY(string_entry),
319 p_module->p_config[i].psz_value ?
320 p_module->p_config[i].psz_value : "" );
321 vlc_mutex_unlock( p_module->p_config[i].p_lock );
323 /* connect signals to the buttons */
324 gtk_signal_connect( GTK_OBJECT(plugin_config_button), "clicked",
325 GTK_SIGNAL_FUNC(GtkPluginConfigure),
326 (gpointer)plugin_clist );
327 gtk_signal_connect( GTK_OBJECT(plugin_select_button), "clicked",
328 GTK_SIGNAL_FUNC(GtkPluginSelected),
329 (gpointer)plugin_clist );
331 /* connect signal to track changes in the text box */
332 gtk_object_set_data( GTK_OBJECT(string_entry), "config_option",
333 p_module->p_config[i].psz_name );
334 gtk_signal_connect( GTK_OBJECT(string_entry), "changed",
335 GTK_SIGNAL_FUNC(GtkStringChanged),
336 (gpointer)config_dialog );
339 case MODULE_CONFIG_ITEM_STRING:
340 case MODULE_CONFIG_ITEM_FILE:
342 /* add input box with default value */
343 string_entry = gtk_entry_new();
344 vlc_mutex_lock( p_module->p_config[i].p_lock );
345 gtk_entry_set_text( GTK_ENTRY(string_entry),
346 p_module->p_config[i].psz_value ?
347 p_module->p_config[i].psz_value : "" );
348 vlc_mutex_unlock( p_module->p_config[i].p_lock );
350 /* connect signal to track changes in the text box */
351 gtk_object_set_data( GTK_OBJECT(string_entry), "config_option",
352 p_module->p_config[i].psz_name );
353 gtk_signal_connect( GTK_OBJECT(string_entry), "changed",
354 GTK_SIGNAL_FUNC(GtkStringChanged),
355 (gpointer)config_dialog );
357 LABEL_AND_WIDGET( p_module->p_config[i].psz_text,
359 p_module->p_config[i].psz_longtext );
362 case MODULE_CONFIG_ITEM_INTEGER:
364 /* add input box with default value */
365 item_adj = gtk_adjustment_new( p_module->p_config[i].i_value,
366 -1, 99999, 1, 10, 10 );
367 integer_spinbutton = gtk_spin_button_new( GTK_ADJUSTMENT(item_adj),
370 /* connect signal to track changes in the spinbutton value */
371 gtk_object_set_data( GTK_OBJECT(integer_spinbutton),
373 p_module->p_config[i].psz_name );
374 gtk_signal_connect( GTK_OBJECT(integer_spinbutton), "changed",
375 GTK_SIGNAL_FUNC(GtkIntChanged),
376 (gpointer)config_dialog );
378 LABEL_AND_WIDGET( p_module->p_config[i].psz_text,
380 p_module->p_config[i].psz_longtext );
383 case MODULE_CONFIG_ITEM_BOOL:
385 /* add check button */
386 bool_checkbutton = gtk_check_button_new();
387 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(bool_checkbutton),
388 p_module->p_config[i].i_value );
390 /* connect signal to track changes in the button state */
391 gtk_object_set_data( GTK_OBJECT(bool_checkbutton), "config_option",
392 p_module->p_config[i].psz_name );
393 gtk_signal_connect( GTK_OBJECT(bool_checkbutton), "toggled",
394 GTK_SIGNAL_FUNC(GtkBoolChanged),
395 (gpointer)config_dialog );
397 LABEL_AND_WIDGET( p_module->p_config[i].psz_text,
399 p_module->p_config[i].psz_longtext );
404 /* Now let's add the action buttons at the bottom of the page */
406 dialog_action_area = GTK_DIALOG(config_dialog)->action_area;
407 gtk_container_set_border_width( GTK_CONTAINER(dialog_action_area), 4 );
409 /* add a new table for the config option */
410 item_hbox = gtk_hbox_new( FALSE, 0 );
411 gtk_box_pack_end( GTK_BOX(dialog_action_area), item_hbox,
413 item_hbox = gtk_hbox_new( FALSE, 0 );
414 gtk_box_pack_end( GTK_BOX(dialog_action_area), item_hbox,
417 /* Create the OK button */
418 ok_button = gtk_button_new_with_label( _("Ok") );
419 gtk_box_pack_start( GTK_BOX(dialog_action_area), ok_button,
422 apply_button = gtk_button_new_with_label( _("Apply") );
423 gtk_box_pack_start( GTK_BOX(dialog_action_area), apply_button,
426 save_button = gtk_button_new_with_label( _("Save") );
427 gtk_box_pack_start( GTK_BOX(dialog_action_area), save_button,
430 cancel_button = gtk_button_new_with_label( _("Cancel") );
431 gtk_box_pack_start( GTK_BOX(dialog_action_area), cancel_button,
434 gtk_signal_connect( GTK_OBJECT(ok_button), "clicked",
435 GTK_SIGNAL_FUNC(GtkConfigOk),
437 gtk_signal_connect( GTK_OBJECT(apply_button), "clicked",
438 GTK_SIGNAL_FUNC(GtkConfigApply),
440 gtk_signal_connect( GTK_OBJECT(save_button), "clicked",
441 GTK_SIGNAL_FUNC(GtkConfigSave),
443 gtk_signal_connect( GTK_OBJECT(cancel_button), "clicked",
444 GTK_SIGNAL_FUNC(GtkConfigCancel),
447 /* Ok, job done successfully. Let's keep a reference to the dialog box */
448 gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
449 psz_module_name, config_dialog );
450 gtk_object_set_data( GTK_OBJECT(config_dialog), "psz_module_name",
453 /* we want this ref to be destroyed if the object is destroyed */
454 gtk_signal_connect( GTK_OBJECT(config_dialog), "destroy",
455 GTK_SIGNAL_FUNC(GtkConfigDialogDestroyed),
458 gtk_widget_show_all( config_dialog );
462 #undef SCROLLED_WINDOW
466 /****************************************************************************
467 * GtkConfigApply: store the changes to the config inside the modules
468 * configuration structure
469 ****************************************************************************/
470 void GtkConfigApply( GtkButton * button, gpointer user_data )
472 GHashTable *hash_table;
473 hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
474 "config_hash_table" );
475 g_hash_table_foreach( hash_table, GtkSaveHashValue, NULL );
479 void GtkConfigOk( GtkButton * button, gpointer user_data )
481 GtkConfigApply( button, user_data );
482 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
486 void GtkConfigCancel( GtkButton * button, gpointer user_data )
488 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
491 void GtkConfigSave( GtkButton * button, gpointer user_data )
493 GtkConfigApply( button, user_data );
494 config_SaveConfigFile( NULL );
497 /****************************************************************************
498 * GtkPluginHighlighted: display plugin description when an entry is selected
499 * in the clist, and activate the configure button if necessary.
500 ****************************************************************************/
501 void GtkPluginHighlighted( GtkCList *plugin_clist, int row, int column,
502 GdkEventButton *event, gpointer user_data )
504 GtkWidget *config_button;
508 if( gtk_clist_get_text( GTK_CLIST(plugin_clist), row, 0, &psz_name ) )
510 /* look for plugin 'psz_name' */
511 for( p_module = p_module_bank->first ;
513 p_module = p_module->next )
515 if( !strcmp( p_module->psz_name, psz_name ) )
517 gtk_object_set_data( GTK_OBJECT(plugin_clist),
518 "plugin_highlighted", p_module );
519 config_button = gtk_object_get_data( GTK_OBJECT(plugin_clist),
521 if( p_module->i_config_items )
522 gtk_widget_set_sensitive( config_button, TRUE );
524 gtk_widget_set_sensitive( config_button, FALSE );
533 /****************************************************************************
534 * GtkPluginConfigure: display plugin configuration dialog box.
535 ****************************************************************************/
536 void GtkPluginConfigure( GtkButton *button, gpointer user_data )
539 intf_thread_t *p_intf;
541 p_module = (module_t *)gtk_object_get_data( GTK_OBJECT(user_data),
542 "plugin_highlighted" );
544 if( !p_module ) return;
545 p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(button),
547 GtkCreateConfigDialog( p_module->psz_name, (gpointer)p_intf );
551 /****************************************************************************
552 * GtkPluginSelected: select plugin.
553 ****************************************************************************/
554 void GtkPluginSelected( GtkButton *button, gpointer user_data )
559 p_module = (module_t *)gtk_object_get_data( GTK_OBJECT(user_data),
560 "plugin_highlighted" );
561 widget = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
563 if( !p_module ) return;
565 gtk_entry_set_text( GTK_ENTRY(widget), p_module->psz_name );
569 /****************************************************************************
570 * GtkStringChanged: signal called when the user changes a string value.
571 ****************************************************************************/
572 static void GtkStringChanged( GtkEditable *editable, gpointer user_data )
574 module_config_t *p_config;
576 GHashTable *hash_table;
578 hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
579 "config_hash_table" );
580 /* free old p_config */
581 p_config = (module_config_t *)g_hash_table_lookup( hash_table,
582 (gpointer)editable );
583 if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, NULL );
585 p_config = malloc( sizeof(module_config_t) );
586 p_config->i_type = MODULE_CONFIG_ITEM_STRING;
587 p_config->psz_value = gtk_editable_get_chars( editable, 0, -1 );
588 p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(editable),
591 g_hash_table_insert( hash_table, (gpointer)editable,
592 (gpointer)p_config );
595 /****************************************************************************
596 * GtkIntChanged: signal called when the user changes a an integer value.
597 ****************************************************************************/
598 static void GtkIntChanged( GtkEditable *editable, gpointer user_data )
600 module_config_t *p_config;
602 GHashTable *hash_table;
604 hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
605 "config_hash_table" );
607 /* free old p_config */
608 p_config = (module_config_t *)g_hash_table_lookup( hash_table,
609 (gpointer)editable );
610 if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, NULL );
612 p_config = malloc( sizeof(module_config_t) );
613 p_config->i_type = MODULE_CONFIG_ITEM_INTEGER;
614 p_config->i_value = gtk_spin_button_get_value_as_int(
615 GTK_SPIN_BUTTON(editable) );
616 p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(editable),
619 g_hash_table_insert( hash_table, (gpointer)editable,
620 (gpointer)p_config );
623 /****************************************************************************
624 * GtkStringChanged: signal called when the user changes a bool value.
625 ****************************************************************************/
626 static void GtkBoolChanged( GtkToggleButton *button, gpointer user_data )
628 module_config_t *p_config;
630 GHashTable *hash_table;
632 hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
633 "config_hash_table" );
635 /* free old p_config */
636 p_config = (module_config_t *)g_hash_table_lookup( hash_table,
638 if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, NULL );
640 p_config = malloc( sizeof(module_config_t) );
641 p_config->i_type = MODULE_CONFIG_ITEM_BOOL;
642 p_config->i_value = gtk_toggle_button_get_active( button );
643 p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(button),
646 g_hash_table_insert( hash_table, (gpointer)button,
647 (gpointer)p_config );
650 /****************************************************************************
651 * GtkFreeHashTable: signal called when the config hash table is destroyed.
652 ****************************************************************************/
653 static void GtkFreeHashTable( gpointer user_data )
655 GHashTable *hash_table = (GHashTable *)user_data;
657 g_hash_table_foreach( hash_table, GtkFreeHashValue, NULL );
658 g_hash_table_destroy( hash_table );
661 /****************************************************************************
662 * GtkFreeHashValue: signal called when an element of the config hash table
664 ****************************************************************************/
665 static void GtkFreeHashValue( gpointer key, gpointer value, gpointer user_data)
667 module_config_t *p_config = (module_config_t *)value;
669 if( p_config->i_type == MODULE_CONFIG_ITEM_STRING )
670 g_free( p_config->psz_value );
674 /****************************************************************************
675 * GtkSaveHashValue: callback used when enumerating the hash table in
677 ****************************************************************************/
678 static void GtkSaveHashValue( gpointer key, gpointer value, gpointer user_data)
680 module_config_t *p_config = (module_config_t *)value;
682 switch( p_config->i_type )
685 case MODULE_CONFIG_ITEM_STRING:
686 case MODULE_CONFIG_ITEM_FILE:
687 case MODULE_CONFIG_ITEM_PLUGIN:
688 config_PutPszVariable( p_config->psz_name,
689 *p_config->psz_value? p_config->psz_value : NULL );
691 case MODULE_CONFIG_ITEM_INTEGER:
692 case MODULE_CONFIG_ITEM_BOOL:
693 config_PutIntVariable( p_config->psz_name, p_config->i_value );
698 /****************************************************************************
699 * GtkConfigDialogDestroyed: callback triggered when the config dialog box is
701 ****************************************************************************/
702 static void GtkConfigDialogDestroyed( GtkObject *object, gpointer user_data )
704 intf_thread_t *p_intf = (intf_thread_t *)user_data;
705 char *psz_module_name;
707 psz_module_name = gtk_object_get_data( object, "psz_module_name" );
709 /* remove the ref to the dialog box */
710 gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
711 psz_module_name, NULL );