]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/menus.cpp
* modules/gui/wxwindows/*: The wxwindows interface is now a "dialogs provider" module...
[vlc] / modules / gui / wxwindows / menus.cpp
1 /*****************************************************************************
2  * menus.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: menus.cpp,v 1.16 2003/07/17 17:30:40 gbazin Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31
32 #include <vlc/vlc.h>
33
34 #ifdef WIN32                                                 /* mingw32 hack */
35 #undef Yield
36 #undef CreateDialog
37 #endif
38
39 /* Let vlc take care of the i18n stuff */
40 #define WXINTL_NO_GETTEXT_MACRO
41
42 #include <wx/wxprec.h>
43 #include <wx/wx.h>
44 #include <wx/listctrl.h>
45
46 #include <vlc/intf.h>
47
48 #if defined MODULE_NAME_IS_skins
49 #   include "../skins/src/skin_common.h"
50 #endif
51
52 #include "wxwindows.h"
53
54 class wxMenuItemExt: public wxMenuItem
55 {
56 public:
57     /* Constructor */
58     wxMenuItemExt( wxMenu* parentMenu, int id, const wxString& text,
59                    const wxString& helpString, wxItemKind kind,
60                    char *_psz_var, int _i_object_id, vlc_value_t _val,
61                    int _i_val_type );
62
63     virtual ~wxMenuItemExt();
64
65     char *psz_var;
66     int  i_val_type;
67     int  i_object_id;
68     vlc_value_t val;
69
70 private:
71
72 };
73
74 /*****************************************************************************
75  * Event Table.
76  *****************************************************************************/
77
78 /* IDs for the controls and the menu commands */
79 enum
80 {
81     /* menu items */
82     MenuDummy_Event = wxID_HIGHEST + 1000,
83     OpenFileSimple_Event,
84     OpenFile_Event,
85     OpenDisc_Event,
86     OpenNet_Event,
87     FirstAutoGenerated_Event = wxID_HIGHEST + 1999,
88     AudioMenu_Events = wxID_HIGHEST + 2000,
89     VideoMenu_Events = wxID_HIGHEST + 3000,
90     NavigMenu_Events = wxID_HIGHEST + 4000,
91     PopupMenu_Events = wxID_HIGHEST + 5000
92 };
93
94 BEGIN_EVENT_TABLE(Menu, wxMenu)
95 END_EVENT_TABLE()
96
97 BEGIN_EVENT_TABLE(MenuEvtHandler, wxEvtHandler)
98     EVT_MENU(OpenFileSimple_Event, MenuEvtHandler::OnShowDialog)
99     EVT_MENU(OpenFile_Event, MenuEvtHandler::OnShowDialog)
100     EVT_MENU(OpenDisc_Event, MenuEvtHandler::OnShowDialog)
101     EVT_MENU(OpenNet_Event, MenuEvtHandler::OnShowDialog)
102     EVT_MENU(-1, MenuEvtHandler::OnMenuEvent)
103 END_EVENT_TABLE()
104
105 wxMenu *OpenStreamMenu( intf_thread_t *p_intf )
106 {
107     wxMenu *menu = new wxMenu;
108     menu->Append( OpenFileSimple_Event, wxU(_("Simple &Open ...")) );
109     menu->Append( OpenFile_Event, wxU(_("Open &File...")) );
110     menu->Append( OpenDisc_Event, wxU(_("Open &Disc...")) );
111     menu->Append( OpenNet_Event, wxU(_("Open &Network Stream...")) );
112     return menu;
113 }
114
115 void PopupMenu( intf_thread_t *p_intf, wxWindow *p_parent,
116                 const wxPoint& pos )
117 {
118     vlc_object_t *p_object;
119     char *ppsz_varnames[29];
120     int pi_objects[29];
121     int i = 0;
122
123     /* Initializations */
124     memset( pi_objects, 0, 29 * sizeof(int) );
125
126     /* Audio menu */
127     ppsz_varnames[i++] = _("Audio menu");
128     ppsz_varnames[i++] = NULL; /* Separator */
129
130     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
131                                                 FIND_ANYWHERE );
132     if( p_object != NULL )
133     {
134         ppsz_varnames[i] = "audio-device";
135         pi_objects[i++] = p_object->i_object_id;
136         ppsz_varnames[i] = "audio-channels";
137         pi_objects[i++] = p_object->i_object_id;
138         vlc_object_release( p_object );
139     }
140
141     /* Video menu */
142     ppsz_varnames[i++] = NULL; /* Separator */
143     ppsz_varnames[i++] = _("Video menu");
144     ppsz_varnames[i++] = NULL; /* Separator */
145
146     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
147                                                 FIND_ANYWHERE );
148     if( p_object != NULL )
149     {
150         ppsz_varnames[i] = "fullscreen";
151         pi_objects[i++] = p_object->i_object_id;
152         ppsz_varnames[i] = "deinterlace";
153         pi_objects[i++] = p_object->i_object_id;
154         ppsz_varnames[i] = "directx-on-top";
155         pi_objects[i++] = p_object->i_object_id;
156         vlc_object_release( p_object );
157     }
158
159     /* Input menu */
160     ppsz_varnames[i++] = NULL; /* Separator */
161     ppsz_varnames[i++] = _("Input menu");
162     ppsz_varnames[i++] = NULL; /* Separator */
163
164     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
165                                                 FIND_ANYWHERE );
166     if( p_object != NULL )
167     {
168         ppsz_varnames[i] = "title";
169         pi_objects[i++] = p_object->i_object_id;
170         ppsz_varnames[i] = "chapter";
171         pi_objects[i++] = p_object->i_object_id;
172         ppsz_varnames[i] = "navigation";
173         pi_objects[i++] = p_object->i_object_id;
174         ppsz_varnames[i] = "program";
175         pi_objects[i++] = p_object->i_object_id;
176
177         ppsz_varnames[i] = "video-es";
178         pi_objects[i++] = p_object->i_object_id;
179         ppsz_varnames[i] = "audio-es";
180         pi_objects[i++] = p_object->i_object_id;
181         ppsz_varnames[i] = "spu-es";
182         pi_objects[i++] = p_object->i_object_id;
183
184         vlc_object_release( p_object );
185     }
186
187     /* Build menu */
188     Menu popupmenu( p_intf, p_parent, i,
189                      ppsz_varnames, pi_objects, PopupMenu_Events );
190
191 #if 1
192     /* Add static entries */
193     popupmenu.AppendSeparator();
194     popupmenu.Append( MenuDummy_Event, wxU("Open"),
195                       OpenStreamMenu( p_intf ), wxT("") );
196     popupmenu.AppendSeparator();
197     popupmenu.Append( MenuDummy_Event, wxU(_("Close Menu")) );
198 #endif
199
200     p_intf->p_sys->p_popup_menu = &popupmenu;
201     p_parent->PopupMenu( &popupmenu, pos.x, pos.y );
202     p_intf->p_sys->p_popup_menu = NULL;
203 }
204
205 wxMenu *AudioMenu( intf_thread_t *_p_intf, wxWindow *p_parent )
206 {
207     vlc_object_t *p_object;
208     char *ppsz_varnames[5];
209     int pi_objects[5];
210     int i = 0;
211
212     /* Initializations */
213     memset( pi_objects, 0, 5 * sizeof(int) );
214
215     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_AOUT,
216                                                 FIND_ANYWHERE );
217     if( p_object != NULL )
218     {
219         ppsz_varnames[i] = "audio-device";
220         pi_objects[i++] = p_object->i_object_id;
221         ppsz_varnames[i] = "audio-channels";
222         pi_objects[i++] = p_object->i_object_id;
223         vlc_object_release( p_object );
224     }
225
226     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_INPUT,
227                                                 FIND_ANYWHERE );
228     if( p_object != NULL )
229     {
230         ppsz_varnames[i] = "audio-es";
231         pi_objects[i++] = p_object->i_object_id;
232         vlc_object_release( p_object );
233     }
234
235     /* Build menu */
236     return new Menu( _p_intf, p_parent, i,
237                      ppsz_varnames, pi_objects, AudioMenu_Events );
238 }
239
240 wxMenu *VideoMenu( intf_thread_t *_p_intf, wxWindow *p_parent )
241 {
242     vlc_object_t *p_object;
243     char *ppsz_varnames[6];
244     int pi_objects[6];
245     int i = 0;
246
247     /* Initializations */
248     memset( pi_objects, 0, 6 * sizeof(int) );
249
250     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_VOUT,
251                                                 FIND_ANYWHERE );
252     if( p_object != NULL )
253     {
254         ppsz_varnames[i] = "fullscreen";
255         pi_objects[i++] = p_object->i_object_id;
256         ppsz_varnames[i] = "deinterlace";
257         pi_objects[i++] = p_object->i_object_id;
258         ppsz_varnames[i] = "directx-on-top";
259         pi_objects[i++] = p_object->i_object_id;
260         vlc_object_release( p_object );
261     }
262
263     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_INPUT,
264                                                 FIND_ANYWHERE );
265     if( p_object != NULL )
266     {
267         ppsz_varnames[i] = "video-es";
268         pi_objects[i++] = p_object->i_object_id;
269         ppsz_varnames[i] = "spu-es";
270         pi_objects[i++] = p_object->i_object_id;
271         vlc_object_release( p_object );
272     }
273
274     /* Build menu */
275     return new Menu( _p_intf, p_parent, i,
276                      ppsz_varnames, pi_objects, VideoMenu_Events );
277 }
278
279 wxMenu *NavigMenu( intf_thread_t *_p_intf, wxWindow *p_parent )
280 {
281     vlc_object_t *p_object;
282     char *ppsz_varnames[10];
283     int pi_objects[10];
284     int i = 0;
285
286     /* Initializations */
287     memset( pi_objects, 0, 4 * sizeof(int) );
288
289     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_INPUT,
290                                                 FIND_ANYWHERE );
291     if( p_object != NULL )
292     {
293         ppsz_varnames[i] = "title";
294         pi_objects[i++] = p_object->i_object_id;
295         ppsz_varnames[i] = "chapter";
296         pi_objects[i++] = p_object->i_object_id;
297         ppsz_varnames[i] = "navigation";
298         pi_objects[i++] = p_object->i_object_id;
299         ppsz_varnames[i] = "program";
300         pi_objects[i++] = p_object->i_object_id;
301
302         ppsz_varnames[i] = "prev-title";
303         pi_objects[i++] = p_object->i_object_id;
304         ppsz_varnames[i] = "next-title";
305         pi_objects[i++] = p_object->i_object_id;
306         ppsz_varnames[i] = "prev-chapter";
307         pi_objects[i++] = p_object->i_object_id;
308         ppsz_varnames[i] = "next-chapter";
309         pi_objects[i++] = p_object->i_object_id;
310
311         vlc_object_release( p_object );
312     }
313
314     /* Build menu */
315     return new Menu( _p_intf, p_parent, i,
316                      ppsz_varnames, pi_objects, NavigMenu_Events );
317 }
318
319 /*****************************************************************************
320  * Constructor.
321  *****************************************************************************/
322 Menu::Menu( intf_thread_t *_p_intf, wxWindow *p_parent,
323             int i_count, char **ppsz_varnames, int *pi_objects,
324             int i_start_id ): wxMenu( )
325 {
326     vlc_object_t *p_object;
327     int i;
328
329     /* Initializations */
330     p_intf = _p_intf;
331
332     i_item_id = i_start_id;
333
334     for( i = 0; i < i_count; i++ )
335     {
336         if( !ppsz_varnames[i] )
337         {
338             AppendSeparator();
339             continue;
340         }
341
342         if( !pi_objects[i] )
343         {
344             Append( MenuDummy_Event, wxU(ppsz_varnames[i]) );
345             continue;
346         }
347
348         p_object = (vlc_object_t *)vlc_object_get( p_intf, pi_objects[i] );
349         if( p_object == NULL ) continue;
350
351         CreateMenuItem( this, ppsz_varnames[i], p_object );
352         vlc_object_release( p_object );
353     }
354
355     /* Special case for empty menus */
356     if( GetMenuItemCount() == 0 )
357     {
358         Append( MenuDummy_Event, wxU(_("Empty")) );
359         Enable( MenuDummy_Event, FALSE );
360     }
361 }
362
363 Menu::~Menu()
364 {
365 }
366
367 /*****************************************************************************
368  * Private methods.
369  *****************************************************************************/
370 void Menu::CreateMenuItem( wxMenu *menu, char *psz_var,
371                            vlc_object_t *p_object )
372 {
373     wxMenuItemExt *menuitem;
374     vlc_value_t val, text;
375     int i_type;
376
377     /* Check the type of the object variable */
378     i_type = var_Type( p_object, psz_var );
379
380     switch( i_type & VLC_VAR_TYPE )
381     {
382     case VLC_VAR_VOID:
383     case VLC_VAR_BOOL:
384     case VLC_VAR_VARIABLE:
385     case VLC_VAR_STRING:
386     case VLC_VAR_INTEGER:
387         break;
388     default:
389         /* Variable doesn't exist or isn't handled */
390         return;
391     }
392
393     /* Make sure we want to display the variable */
394     if( i_type & VLC_VAR_HASCHOICE )
395     {
396         var_Change( p_object, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
397         if( val.i_int == 0 ) return;
398         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
399             return;
400     }
401
402     /* Get the descriptive name of the variable */
403     var_Change( p_object, psz_var, VLC_VAR_GETTEXT, &text, NULL );
404
405     var_Get( p_object, psz_var, &val );
406
407     if( i_type & VLC_VAR_HASCHOICE )
408     {
409         menu->Append( MenuDummy_Event,
410                       wxU(text.psz_string ? text.psz_string : psz_var),
411                       CreateChoicesMenu( psz_var, p_object ),
412                       wxT("")/* Nothing for now (maybe use a GETLONGTEXT) */ );
413
414         if( text.psz_string ) free( text.psz_string );
415         return;
416     }
417
418
419     switch( i_type & VLC_VAR_TYPE )
420     {
421     case VLC_VAR_VOID:
422         menuitem = new wxMenuItemExt( menu, ++i_item_id,
423                                       wxU(text.psz_string ?
424                                         text.psz_string : psz_var),
425                                       wxT(""), wxITEM_NORMAL, strdup(psz_var),
426                                       p_object->i_object_id, val, i_type );
427         menu->Append( menuitem );
428         break;
429
430     case VLC_VAR_BOOL:
431         val.b_bool = !val.b_bool;
432         menuitem = new wxMenuItemExt( menu, ++i_item_id,
433                                       wxU(text.psz_string ?
434                                         text.psz_string : psz_var),
435                                       wxT(""), wxITEM_CHECK, strdup(psz_var),
436                                       p_object->i_object_id, val, i_type );
437         menu->Append( menuitem );
438         Check( i_item_id, val.b_bool ? FALSE : TRUE );
439         break;
440
441     default:
442         if( text.psz_string ) free( text.psz_string );
443         return;
444     }
445
446     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
447     if( text.psz_string ) free( text.psz_string );
448 }
449
450 wxMenu *Menu::CreateChoicesMenu( char *psz_var, vlc_object_t *p_object )
451 {
452     vlc_value_t val, val_list, text_list;
453     int i_type, i;
454
455     /* Check the type of the object variable */
456     i_type = var_Type( p_object, psz_var );
457
458     /* Make sure we want to display the variable */
459     if( i_type & VLC_VAR_HASCHOICE )
460     {
461         var_Change( p_object, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
462         if( val.i_int == 0 ) return NULL;
463         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
464             return NULL;
465     }
466     else
467     {
468         return NULL;
469     }
470
471     switch( i_type & VLC_VAR_TYPE )
472     {
473     case VLC_VAR_VOID:
474     case VLC_VAR_BOOL:
475     case VLC_VAR_VARIABLE:
476     case VLC_VAR_STRING:
477     case VLC_VAR_INTEGER:
478         break;
479     default:
480         /* Variable doesn't exist or isn't handled */
481         return NULL;
482     }
483
484     if( var_Get( p_object, psz_var, &val ) < 0 )
485     {
486         return NULL;
487     }
488
489     if( var_Change( p_object, psz_var, VLC_VAR_GETLIST,
490                     &val_list, &text_list ) < 0 )
491     {
492         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
493         return NULL;
494     }
495
496     wxMenu *menu = new wxMenu;
497     for( i = 0; i < val_list.p_list->i_count; i++ )
498     {
499         vlc_value_t another_val;
500         wxMenuItemExt *menuitem;
501
502         switch( i_type & VLC_VAR_TYPE )
503         {
504         case VLC_VAR_VARIABLE:
505           menu->Append( MenuDummy_Event,
506                         wxU(text_list.p_list->p_values[i].psz_string ?
507                         text_list.p_list->p_values[i].psz_string :
508                         val_list.p_list->p_values[i].psz_string),
509                         CreateChoicesMenu(
510                             val_list.p_list->p_values[i].psz_string,
511                             p_object ), wxT("") );
512           break;
513
514         case VLC_VAR_STRING:
515           another_val.psz_string =
516               strdup(val_list.p_list->p_values[i].psz_string);
517           menuitem =
518               new wxMenuItemExt( menu, ++i_item_id,
519                                  wxU(text_list.p_list->p_values[i].psz_string ?
520                                  text_list.p_list->p_values[i].psz_string :
521                                  another_val.psz_string),
522                                  wxT(""), wxITEM_RADIO, strdup(psz_var),
523                                  p_object->i_object_id, another_val, i_type );
524
525           menu->Append( menuitem );
526
527           if( !strcmp( val.psz_string,
528                        val_list.p_list->p_values[i].psz_string ) )
529               menu->Check( i_item_id, TRUE );
530           break;
531
532         case VLC_VAR_INTEGER:
533           menuitem =
534               new wxMenuItemExt( menu, ++i_item_id,
535                                  text_list.p_list->p_values[i].psz_string ?
536                                  (wxString)wxU(
537                                    text_list.p_list->p_values[i].psz_string) :
538                                  wxString::Format(wxT("%d"),
539                                  val_list.p_list->p_values[i].i_int),
540                                  wxT(""), wxITEM_RADIO, strdup(psz_var),
541                                  p_object->i_object_id,
542                                  val_list.p_list->p_values[i], i_type );
543
544           menu->Append( menuitem );
545
546           if( val_list.p_list->p_values[i].i_int == val.i_int )
547               menu->Check( i_item_id, TRUE );
548           break;
549
550         default:
551           break;
552         }
553     }
554
555     /* clean up everything */
556     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
557     var_Change( p_object, psz_var, VLC_VAR_FREELIST, &val_list, &text_list );
558
559     return menu;
560 }
561
562 void Menu::OnShowDialog( wxCommandEvent& event )
563 {
564     if( p_intf->p_sys->pf_show_dialog )
565     {
566         int i_id;
567
568         switch( event.GetId() )
569         {
570         case OpenFileSimple_Event:
571             i_id = INTF_DIALOG_FILE_SIMPLE;
572             break;
573         case OpenFile_Event:
574             i_id = INTF_DIALOG_FILE;
575             break;
576         case OpenDisc_Event:
577             i_id = INTF_DIALOG_DISC;
578             break;
579         case OpenNet_Event:
580             i_id = INTF_DIALOG_NET;
581             break;
582         default:
583             i_id = INTF_DIALOG_FILE;
584             break;
585
586         }
587
588         p_intf->p_sys->pf_show_dialog( p_intf, i_id, 1 );
589     }
590 }
591
592 /*****************************************************************************
593  * A small helper class which intercepts all popup menu events
594  *****************************************************************************/
595 MenuEvtHandler::MenuEvtHandler( intf_thread_t *_p_intf,
596                                 Interface *_p_main_interface )
597 {
598     /* Initializations */
599     p_intf = _p_intf;
600     p_main_interface = _p_main_interface;
601 }
602
603 MenuEvtHandler::~MenuEvtHandler()
604 {
605 }
606
607 void MenuEvtHandler::OnShowDialog( wxCommandEvent& event )
608 {
609     if( p_intf->p_sys->pf_show_dialog )
610     {
611         int i_id;
612
613         switch( event.GetId() )
614         {
615         case OpenFileSimple_Event:
616             i_id = INTF_DIALOG_FILE_SIMPLE;
617             break;
618         case OpenFile_Event:
619             i_id = INTF_DIALOG_FILE;
620             break;
621         case OpenDisc_Event:
622             i_id = INTF_DIALOG_DISC;
623             break;
624         case OpenNet_Event:
625             i_id = INTF_DIALOG_NET;
626             break;
627         default:
628             i_id = INTF_DIALOG_FILE;
629             break;
630
631         }
632
633         p_intf->p_sys->pf_show_dialog( p_intf, i_id, 1 );
634     }
635 }
636
637 void MenuEvtHandler::OnMenuEvent( wxCommandEvent& event )
638 {
639     wxMenuItem *p_menuitem = NULL;
640
641     /* Check if this is an auto generated menu item */
642     if( event.GetId() < FirstAutoGenerated_Event )
643     {
644         event.Skip();
645         return;
646     }
647
648     if( !p_main_interface ||
649         (p_menuitem = p_main_interface->GetMenuBar()->FindItem(event.GetId()))
650         == NULL )
651     {
652         if( p_intf->p_sys->p_popup_menu )
653         {
654             p_menuitem = 
655                 p_intf->p_sys->p_popup_menu->FindItem( event.GetId() );
656         }
657     }
658
659     if( p_menuitem )
660     {
661         wxMenuItemExt *p_menuitemext = (wxMenuItemExt *)p_menuitem;
662         vlc_object_t *p_object;
663
664         p_object = (vlc_object_t *)vlc_object_get( p_intf,
665                                        p_menuitemext->i_object_id );
666         if( p_object == NULL ) return;
667
668         var_Set( p_object, p_menuitemext->psz_var, p_menuitemext->val );
669
670         vlc_object_release( p_object );
671     }
672     else
673         event.Skip();
674 }
675
676 /*****************************************************************************
677  * A small helper class which encapsulate wxMenuitem with some other useful
678  * things.
679  *****************************************************************************/
680 wxMenuItemExt::wxMenuItemExt( wxMenu* parentMenu, int id, const wxString& text,
681     const wxString& helpString, wxItemKind kind,
682     char *_psz_var, int _i_object_id, vlc_value_t _val, int _i_val_type ):
683     wxMenuItem( parentMenu, id, text, helpString, kind )
684 {
685     /* Initializations */
686     psz_var = _psz_var;
687     i_val_type = _i_val_type;
688     i_object_id = _i_object_id;
689     val = _val;
690 };
691
692 wxMenuItemExt::~wxMenuItemExt()
693 {
694     if( psz_var ) free( psz_var );
695     if( ((i_val_type & VLC_VAR_TYPE) == VLC_VAR_STRING)
696         && val.psz_string ) free( val.psz_string );
697 };