]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/menus.cpp
Disable intf-switch in the interface (Refs:#564) - Not working correctly, neither...
[vlc] / modules / gui / wxwidgets / menus.cpp
1 /*****************************************************************************
2  * menus.cpp : wxWidgets plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 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 #include <vlc/intf.h>
34
35 #include "wxwidgets.hpp"
36 #include "interface.hpp"
37
38 class wxMenuItemExt: public wxMenuItem
39 {
40 public:
41     /* Constructor */
42     wxMenuItemExt( wxMenu* parentMenu, int id, const wxString& text,
43                    const wxString& helpString, wxItemKind kind,
44                    char *_psz_var, int _i_object_id, vlc_value_t _val,
45                    int _i_val_type );
46
47     virtual ~wxMenuItemExt();
48
49     char *psz_var;
50     int  i_val_type;
51     int  i_object_id;
52     vlc_value_t val;
53
54 private:
55
56 };
57
58 class Menu: public wxMenu
59 {
60 public:
61     /* Constructor */
62     Menu( intf_thread_t *p_intf, int i_start_id );
63     virtual ~Menu();
64
65     void Populate( int i_count, char **ppsz_names, int *pi_objects );
66     void Clear();
67
68 private:
69     wxMenu *Menu::CreateDummyMenu();
70     void   Menu::CreateMenuItem( wxMenu *, char *, vlc_object_t * );
71     wxMenu *Menu::CreateChoicesMenu( char *, vlc_object_t *, bool );
72
73     DECLARE_EVENT_TABLE();
74
75     intf_thread_t *p_intf;
76
77     int i_start_id;
78     int i_item_id;
79 };
80
81 /*****************************************************************************
82  * Event Table.
83  *****************************************************************************/
84
85 /* IDs for the controls and the menu commands */
86 enum
87 {
88     /* menu items */
89     MenuDummy_Event = wxID_HIGHEST + 1000,
90     OpenFileSimple_Event = wxID_HIGHEST + 1100,
91     OpenFile_Event,
92     OpenDirectory_Event,
93     OpenDisc_Event,
94     OpenNet_Event,
95     OpenCapture_Event,
96     MediaInfo_Event,
97     Messages_Event,
98     Preferences_Event,
99     Play_Event,
100     Pause_Event,
101     Previous_Event,
102     Next_Event,
103     Stop_Event,
104     FirstAutoGenerated_Event = wxID_HIGHEST + 1999,
105     SettingsMenu_Events = wxID_HIGHEST + 5000,
106     AudioMenu_Events = wxID_HIGHEST + 2000,
107     VideoMenu_Events = wxID_HIGHEST + 3000,
108     NavigMenu_Events = wxID_HIGHEST + 4000,
109     PopupMenu_Events = wxID_HIGHEST + 6000,
110     Hotkeys_Events = wxID_HIGHEST + 7000
111 };
112
113 BEGIN_EVENT_TABLE(Menu, wxMenu)
114 END_EVENT_TABLE()
115
116 BEGIN_EVENT_TABLE(MenuEvtHandler, wxEvtHandler)
117     EVT_MENU(OpenFileSimple_Event, MenuEvtHandler::OnShowDialog)
118     EVT_MENU(OpenFile_Event, MenuEvtHandler::OnShowDialog)
119     EVT_MENU(OpenDirectory_Event, MenuEvtHandler::OnShowDialog)
120     EVT_MENU(OpenDisc_Event, MenuEvtHandler::OnShowDialog)
121     EVT_MENU(OpenNet_Event, MenuEvtHandler::OnShowDialog)
122     EVT_MENU(OpenCapture_Event, MenuEvtHandler::OnShowDialog)
123     EVT_MENU(MediaInfo_Event, MenuEvtHandler::OnShowDialog)
124     EVT_MENU(Messages_Event, MenuEvtHandler::OnShowDialog)
125     EVT_MENU(Preferences_Event, MenuEvtHandler::OnShowDialog)
126     EVT_MENU(-1, MenuEvtHandler::OnMenuEvent)
127 END_EVENT_TABLE()
128
129 wxMenu *OpenStreamMenu( intf_thread_t *p_intf )
130 {
131     wxMenu *menu = new wxMenu;
132     menu->Append( OpenFileSimple_Event, wxU(_("Quick &Open File...")) );
133     menu->Append( OpenFile_Event, wxU(_("Open &File...")) );
134     menu->Append( OpenDirectory_Event, wxU(_("Open D&irectory...")) );
135     menu->Append( OpenDisc_Event, wxU(_("Open &Disc...")) );
136     menu->Append( OpenNet_Event, wxU(_("Open &Network Stream...")) );
137     menu->Append( OpenCapture_Event, wxU(_("Open &Capture Device...")) );
138     return menu;
139 }
140
141 wxMenu *MiscMenu( intf_thread_t *p_intf )
142 {
143     wxMenu *menu = new wxMenu;
144     menu->Append( MediaInfo_Event, wxU(_("Media &Info...")) );
145     menu->Append( Messages_Event, wxU(_("&Messages...")) );
146     menu->Append( Preferences_Event, wxU(_("&Preferences...")) );
147     return menu;
148 }
149
150 void PopupMenu( intf_thread_t *p_intf, wxWindow *p_parent,
151                 const wxPoint& pos )
152 {
153 #define MAX_POPUP_ITEMS 45
154
155     int minimal = config_GetInt( p_intf, "wx-minimal" );
156
157     vlc_object_t *p_object, *p_input;
158     char *ppsz_varnames[MAX_POPUP_ITEMS];
159     int pi_objects[MAX_POPUP_ITEMS];
160     int i = 0, i_last_separator = 0;
161
162     /* Initializations */
163     memset( pi_objects, 0, MAX_POPUP_ITEMS * sizeof(int) );
164
165     /* Input menu */
166     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
167                                                 FIND_ANYWHERE );
168     if( p_object != NULL )
169     {
170         ppsz_varnames[i] = "bookmark";
171         pi_objects[i++] = p_object->i_object_id;
172         ppsz_varnames[i] = "title";
173         pi_objects[i++] = p_object->i_object_id;
174         ppsz_varnames[i] = "chapter";
175         pi_objects[i++] = p_object->i_object_id;
176         ppsz_varnames[i] = "program";
177         pi_objects[i++] = p_object->i_object_id;
178         ppsz_varnames[i] = "navigation";
179         pi_objects[i++] = p_object->i_object_id;
180         ppsz_varnames[i] = "dvd_menus";
181         pi_objects[i++] = p_object->i_object_id;
182
183         ppsz_varnames[i] = "video-es";
184         pi_objects[i++] = p_object->i_object_id;
185         ppsz_varnames[i] = "audio-es";
186         pi_objects[i++] = p_object->i_object_id;
187         ppsz_varnames[i] = "spu-es";
188         pi_objects[i++] = p_object->i_object_id;
189     }
190     p_input = p_object;
191     if( !p_input ) goto interfacemenu;
192
193     /* Video menu */
194     if( i != i_last_separator ) ppsz_varnames[i++] = NULL; /* Separator */
195     i_last_separator = i;
196
197     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
198                                                 FIND_ANYWHERE );
199     if( p_object != NULL )
200     {
201         vlc_object_t *p_dec_obj;
202
203         ppsz_varnames[i] = "fullscreen";
204         pi_objects[i++] = p_object->i_object_id;
205         ppsz_varnames[i] = "zoom";
206         pi_objects[i++] = p_object->i_object_id;
207         ppsz_varnames[i] = "deinterlace";
208         pi_objects[i++] = p_object->i_object_id;
209         ppsz_varnames[i] = "aspect-ratio";
210         pi_objects[i++] = p_object->i_object_id;
211         ppsz_varnames[i] = "crop";
212         pi_objects[i++] = p_object->i_object_id;
213         ppsz_varnames[i] = "video-on-top";
214         pi_objects[i++] = p_object->i_object_id;
215         ppsz_varnames[i] = "directx-wallpaper";
216         pi_objects[i++] = p_object->i_object_id;
217         ppsz_varnames[i] = "video-snapshot";
218         pi_objects[i++] = p_object->i_object_id;
219
220         p_dec_obj = (vlc_object_t *)vlc_object_find( p_object,
221                                                      VLC_OBJECT_DECODER,
222                                                      FIND_PARENT );
223         if( p_dec_obj != NULL )
224         {
225             ppsz_varnames[i] = "ffmpeg-pp-q";
226             pi_objects[i++] = p_dec_obj->i_object_id;
227             vlc_object_release( p_dec_obj );
228         }
229
230         vlc_object_release( p_object );
231     }
232
233     /* Audio menu */
234     if( i != i_last_separator ) ppsz_varnames[i++] = NULL; /* Separator */
235     i_last_separator  = i;
236
237     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
238                                                 FIND_ANYWHERE );
239     if( p_object != NULL )
240     {
241         ppsz_varnames[i] = "audio-device";
242         pi_objects[i++] = p_object->i_object_id;
243         ppsz_varnames[i] = "audio-channels";
244         pi_objects[i++] = p_object->i_object_id;
245         ppsz_varnames[i] = "visual";
246         pi_objects[i++] = p_object->i_object_id;
247         ppsz_varnames[i] = "equalizer";
248         pi_objects[i++] = p_object->i_object_id;
249         vlc_object_release( p_object );
250     }
251
252  interfacemenu:
253     /* Interface menu */
254     if( i != i_last_separator ) ppsz_varnames[i++] = NULL; /* Separator */
255     i_last_separator = i;
256
257     /* vlc_object_find is needed because of the dialogs provider case */
258     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_INTF,
259                                                 FIND_PARENT );
260     if( p_object != NULL )
261     {
262 #if 0
263 #if (wxCHECK_VERSION(2,5,0))
264         ppsz_varnames[i] = "intf-switch";
265         pi_objects[i++] = p_object->i_object_id;
266 #endif
267 #endif
268         ppsz_varnames[i] = "intf-add";
269         pi_objects[i++] = p_object->i_object_id;
270         ppsz_varnames[i] = "intf-skins";
271         pi_objects[i++] = p_object->i_object_id;
272
273         vlc_object_release( p_object );
274     }
275
276     /* Build menu */
277     Menu popupmenu( p_intf, PopupMenu_Events );
278     popupmenu.Populate( i, ppsz_varnames, pi_objects );
279
280     /* Add static entries */
281     if( p_input != NULL )
282     {
283         vlc_value_t val;
284         popupmenu.InsertSeparator( 0 );
285         if (!minimal)
286         {
287         popupmenu.Insert( 0, Stop_Event, wxU(_("Stop")) );
288         popupmenu.Insert( 0, Previous_Event, wxU(_("Previous")) );
289         popupmenu.Insert( 0, Next_Event, wxU(_("Next")) );
290         }
291
292         var_Get( p_input, "state", &val );
293         if( val.i_int == PAUSE_S )
294             popupmenu.Insert( 0, Play_Event, wxU(_("Play")) );
295         else
296             popupmenu.Insert( 0, Pause_Event, wxU(_("Pause")) );
297
298         vlc_object_release( p_input );
299     }
300     else
301     {
302         playlist_t * p_playlist =
303             (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
304                                            FIND_ANYWHERE );
305         if( p_playlist && p_playlist->i_size )
306         {
307             popupmenu.InsertSeparator( 0 );
308             popupmenu.Insert( 0, Play_Event, wxU(_("Play")) );
309         }
310         if( p_playlist ) vlc_object_release( p_playlist );
311     }
312
313     popupmenu.Append( MenuDummy_Event, wxU(_("Miscellaneous")),
314                       MiscMenu( p_intf ), wxT("") );
315     if (!minimal)
316     {
317     popupmenu.Append( MenuDummy_Event, wxU(_("Open")),
318                       OpenStreamMenu( p_intf ), wxT("") );
319     }
320
321     p_intf->p_sys->p_popup_menu = &popupmenu;
322     p_parent->PopupMenu( &popupmenu, pos.x, pos.y );
323     p_intf->p_sys->p_popup_menu = NULL;
324 }
325
326 wxMenu *AudioMenu( intf_thread_t *_p_intf, wxWindow *p_parent, wxMenu *p_menu )
327 {
328 #define MAX_AUDIO_ITEMS 10
329
330     vlc_object_t *p_object;
331     char *ppsz_varnames[MAX_AUDIO_ITEMS];
332     int pi_objects[MAX_AUDIO_ITEMS];
333     int i = 0;
334
335     /* Initializations */
336     memset( pi_objects, 0, MAX_AUDIO_ITEMS * sizeof(int) );
337
338     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_INPUT,
339                                                 FIND_ANYWHERE );
340     if( p_object != NULL )
341     {
342         ppsz_varnames[i] = "audio-es";
343         pi_objects[i++] = p_object->i_object_id;
344         vlc_object_release( p_object );
345     }
346
347     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_AOUT,
348                                                 FIND_ANYWHERE );
349     if( p_object != NULL )
350     {
351         ppsz_varnames[i] = "audio-device";
352         pi_objects[i++] = p_object->i_object_id;
353         ppsz_varnames[i] = "audio-channels";
354         pi_objects[i++] = p_object->i_object_id;
355         ppsz_varnames[i] = "visual";
356         pi_objects[i++] = p_object->i_object_id;
357         ppsz_varnames[i] = "equalizer";
358         pi_objects[i++] = p_object->i_object_id;
359         vlc_object_release( p_object );
360     }
361
362     /* Build menu */
363     Menu *p_vlc_menu = (Menu *)p_menu;
364     if( !p_vlc_menu )
365         p_vlc_menu = new Menu( _p_intf, AudioMenu_Events );
366     else
367         p_vlc_menu->Clear();
368
369     p_vlc_menu->Populate( i, ppsz_varnames, pi_objects );
370
371     return p_vlc_menu;
372 }
373
374 wxMenu *VideoMenu( intf_thread_t *_p_intf, wxWindow *p_parent, wxMenu *p_menu )
375 {
376 #define MAX_VIDEO_ITEMS 15
377
378     vlc_object_t *p_object;
379     char *ppsz_varnames[MAX_VIDEO_ITEMS];
380     int pi_objects[MAX_VIDEO_ITEMS];
381     int i = 0;
382
383     /* Initializations */
384     memset( pi_objects, 0, MAX_VIDEO_ITEMS * sizeof(int) );
385
386     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_INPUT,
387                                                 FIND_ANYWHERE );
388     if( p_object != NULL )
389     {
390         ppsz_varnames[i] = "video-es";
391         pi_objects[i++] = p_object->i_object_id;
392         ppsz_varnames[i] = "spu-es";
393         pi_objects[i++] = p_object->i_object_id;
394         vlc_object_release( p_object );
395     }
396
397     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_VOUT,
398                                                 FIND_ANYWHERE );
399     if( p_object != NULL )
400     {
401         vlc_object_t *p_dec_obj;
402
403         ppsz_varnames[i] = "fullscreen";
404         pi_objects[i++] = p_object->i_object_id;
405         ppsz_varnames[i] = "zoom";
406         pi_objects[i++] = p_object->i_object_id;
407         ppsz_varnames[i] = "deinterlace";
408         pi_objects[i++] = p_object->i_object_id;
409         ppsz_varnames[i] = "aspect-ratio";
410         pi_objects[i++] = p_object->i_object_id;
411         ppsz_varnames[i] = "crop";
412         pi_objects[i++] = p_object->i_object_id;
413         ppsz_varnames[i] = "video-on-top";
414         pi_objects[i++] = p_object->i_object_id;
415         ppsz_varnames[i] = "directx-wallpaper";
416         pi_objects[i++] = p_object->i_object_id;
417         ppsz_varnames[i] = "video-snapshot";
418         pi_objects[i++] = p_object->i_object_id;
419
420         p_dec_obj = (vlc_object_t *)vlc_object_find( p_object,
421                                                      VLC_OBJECT_DECODER,
422                                                      FIND_PARENT );
423         if( p_dec_obj != NULL )
424         {
425             ppsz_varnames[i] = "ffmpeg-pp-q";
426             pi_objects[i++] = p_dec_obj->i_object_id;
427             vlc_object_release( p_dec_obj );
428         }
429
430         vlc_object_release( p_object );
431     }
432
433     /* Build menu */
434     Menu *p_vlc_menu = (Menu *)p_menu;
435     if( !p_vlc_menu )
436         p_vlc_menu = new Menu( _p_intf, VideoMenu_Events );
437     else
438         p_vlc_menu->Clear();
439
440     p_vlc_menu->Populate( i, ppsz_varnames, pi_objects );
441
442     return p_vlc_menu;
443 }
444
445 wxMenu *NavigMenu( intf_thread_t *_p_intf, wxWindow *p_parent, wxMenu *p_menu )
446 {
447 #define MAX_NAVIG_ITEMS 15
448
449     vlc_object_t *p_object;
450     char *ppsz_varnames[MAX_NAVIG_ITEMS];
451     int pi_objects[MAX_NAVIG_ITEMS];
452     int i = 0;
453
454     /* Initializations */
455     memset( pi_objects, 0, MAX_NAVIG_ITEMS * sizeof(int) );
456
457     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_INPUT,
458                                                 FIND_ANYWHERE );
459     if( p_object != NULL )
460     {
461         ppsz_varnames[i] = "bookmark";
462         pi_objects[i++] = p_object->i_object_id;
463         ppsz_varnames[i] = "title";
464         pi_objects[i++] = p_object->i_object_id;
465         ppsz_varnames[i] = "chapter";
466         pi_objects[i++] = p_object->i_object_id;
467         ppsz_varnames[i] = "program";
468         pi_objects[i++] = p_object->i_object_id;
469         ppsz_varnames[i] = "navigation";
470         pi_objects[i++] = p_object->i_object_id;
471         ppsz_varnames[i] = "dvd_menus";
472         pi_objects[i++] = p_object->i_object_id;
473
474         ppsz_varnames[i] = "prev-title";
475         pi_objects[i++] = p_object->i_object_id;
476         ppsz_varnames[i] = "next-title";
477         pi_objects[i++] = p_object->i_object_id;
478         ppsz_varnames[i] = "prev-chapter";
479         pi_objects[i++] = p_object->i_object_id;
480         ppsz_varnames[i] = "next-chapter";
481         pi_objects[i++] = p_object->i_object_id;
482
483         vlc_object_release( p_object );
484     }
485
486     /* Build menu */
487     Menu *p_vlc_menu = (Menu *)p_menu;
488     if( !p_vlc_menu )
489         p_vlc_menu = new Menu( _p_intf, NavigMenu_Events );
490     else
491         p_vlc_menu->Clear();
492
493     p_vlc_menu->Populate( i, ppsz_varnames, pi_objects );
494
495     return p_vlc_menu;
496 }
497
498 wxMenu *SettingsMenu( intf_thread_t *_p_intf, wxWindow *p_parent,
499                       wxMenu *p_menu )
500 {
501 #define MAX_SETTINGS_ITEMS 10
502
503     vlc_object_t *p_object;
504     char *ppsz_varnames[MAX_SETTINGS_ITEMS];
505     int pi_objects[MAX_SETTINGS_ITEMS];
506     int i = 0;
507
508     /* Initializations */
509     memset( pi_objects, 0, MAX_SETTINGS_ITEMS * sizeof(int) );
510
511     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_INTF,
512                                                 FIND_PARENT );
513     if( p_object != NULL )
514     {
515 #if 0
516 #if (wxCHECK_VERSION(2,5,0))
517         ppsz_varnames[i] = "intf-switch";
518         pi_objects[i++] = p_object->i_object_id;
519 #endif
520 #endif
521         ppsz_varnames[i] = "intf-add";
522         pi_objects[i++] = p_object->i_object_id;
523         vlc_object_release( p_object );
524     }
525
526     /* Build menu */
527     Menu *p_vlc_menu = (Menu *)p_menu;
528     if( !p_vlc_menu )
529         p_vlc_menu = new Menu( _p_intf, SettingsMenu_Events );
530     else
531         p_vlc_menu->Clear();
532
533     p_vlc_menu->Populate( i, ppsz_varnames, pi_objects );
534
535     return p_vlc_menu;
536 }
537
538 /*****************************************************************************
539  * Constructor.
540  *****************************************************************************/
541 Menu::Menu( intf_thread_t *_p_intf, int _i_start_id ) : wxMenu( )
542 {
543     /* Initializations */
544     p_intf = _p_intf;
545     i_start_id = _i_start_id;
546 }
547
548 Menu::~Menu()
549 {
550 }
551
552 /*****************************************************************************
553  * Public methods.
554  *****************************************************************************/
555 void Menu::Populate( int i_count, char **ppsz_varnames, int *pi_objects )
556 {
557     vlc_object_t *p_object;
558     vlc_bool_t b_section_empty = VLC_FALSE;
559     int i;
560
561     i_item_id = i_start_id;
562
563     for( i = 0; i < i_count; i++ )
564     {
565         if( !ppsz_varnames[i] )
566         {
567             if( b_section_empty )
568             {
569                 Append( MenuDummy_Event + i, wxU(_("Empty")) );
570                 Enable( MenuDummy_Event + i, FALSE );
571             }
572
573             AppendSeparator();
574             b_section_empty = VLC_TRUE;
575             continue;
576         }
577
578         if( !pi_objects[i] )
579         {
580             Append( MenuDummy_Event, wxU(ppsz_varnames[i]) );
581             b_section_empty = VLC_FALSE;
582             continue;
583         }
584
585         p_object = (vlc_object_t *)vlc_object_get( p_intf, pi_objects[i] );
586         if( p_object == NULL ) continue;
587
588         b_section_empty = VLC_FALSE;
589         CreateMenuItem( this, ppsz_varnames[i], p_object );
590         vlc_object_release( p_object );
591     }
592
593     /* Special case for empty menus */
594     if( GetMenuItemCount() == 0 || b_section_empty )
595     {
596         Append( MenuDummy_Event + i, wxU(_("Empty")) );
597         Enable( MenuDummy_Event + i, FALSE );
598     }
599 }
600
601 /* Work-around helper for buggy wxGTK */
602 static void RecursiveDestroy( wxMenu *menu )
603 {
604     wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
605     for( ; node; )
606     {
607         wxMenuItem *item = node->GetData();
608         node = node->GetNext();
609
610         /* Delete the submenus */
611         wxMenu *submenu = item->GetSubMenu();
612         if( submenu )
613         {
614             RecursiveDestroy( submenu );
615         }
616         menu->Delete( item );
617     }
618 }
619
620 void Menu::Clear( )
621 {
622     RecursiveDestroy( this );
623 }
624
625 /*****************************************************************************
626  * Private methods.
627  *****************************************************************************/
628 static bool IsMenuEmpty( char *psz_var, vlc_object_t *p_object,
629                          bool b_root = TRUE )
630 {
631     vlc_value_t val, val_list;
632     int i_type, i_result, i;
633
634     /* Check the type of the object variable */
635     i_type = var_Type( p_object, psz_var );
636
637     /* Check if we want to display the variable */
638     if( !(i_type & VLC_VAR_HASCHOICE) ) return FALSE;
639
640     var_Change( p_object, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
641     if( val.i_int == 0 ) return TRUE;
642
643     if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE )
644     {
645         if( val.i_int == 1 && b_root ) return TRUE;
646         else return FALSE;
647     }
648
649     /* Check children variables in case of VLC_VAR_VARIABLE */
650     if( var_Change( p_object, psz_var, VLC_VAR_GETLIST, &val_list, NULL ) < 0 )
651     {
652         return TRUE;
653     }
654
655     for( i = 0, i_result = TRUE; i < val_list.p_list->i_count; i++ )
656     {
657         if( !IsMenuEmpty( val_list.p_list->p_values[i].psz_string,
658                           p_object, FALSE ) )
659         {
660             i_result = FALSE;
661             break;
662         }
663     }
664
665     /* clean up everything */
666     var_Change( p_object, psz_var, VLC_VAR_FREELIST, &val_list, NULL );
667
668     return i_result;
669 }
670
671 void Menu::CreateMenuItem( wxMenu *menu, char *psz_var,
672                            vlc_object_t *p_object )
673 {
674     wxMenuItemExt *menuitem;
675     vlc_value_t val, text;
676     int i_type;
677
678     /* Check the type of the object variable */
679     i_type = var_Type( p_object, psz_var );
680
681     switch( i_type & VLC_VAR_TYPE )
682     {
683     case VLC_VAR_VOID:
684     case VLC_VAR_BOOL:
685     case VLC_VAR_VARIABLE:
686     case VLC_VAR_STRING:
687     case VLC_VAR_INTEGER:
688     case VLC_VAR_FLOAT:
689         break;
690     default:
691         /* Variable doesn't exist or isn't handled */
692         return;
693     }
694
695     /* Make sure we want to display the variable */
696     if( IsMenuEmpty( psz_var, p_object ) ) return;
697
698     /* Get the descriptive name of the variable */
699     var_Change( p_object, psz_var, VLC_VAR_GETTEXT, &text, NULL );
700
701     if( i_type & VLC_VAR_HASCHOICE )
702     {
703         menu->Append( MenuDummy_Event,
704                       wxU(text.psz_string ? text.psz_string : psz_var),
705                       CreateChoicesMenu( psz_var, p_object, TRUE ),
706                       wxT("")/* Nothing for now (maybe use a GETLONGTEXT) */ );
707
708         if( text.psz_string ) free( text.psz_string );
709         return;
710     }
711
712
713     switch( i_type & VLC_VAR_TYPE )
714     {
715     case VLC_VAR_VOID:
716         var_Get( p_object, psz_var, &val );
717         menuitem = new wxMenuItemExt( menu, ++i_item_id,
718                                       wxU(text.psz_string ?
719                                         text.psz_string : psz_var),
720                                       wxT(""), wxITEM_NORMAL, strdup(psz_var),
721                                       p_object->i_object_id, val, i_type );
722         menu->Append( menuitem );
723         break;
724
725     case VLC_VAR_BOOL:
726         var_Get( p_object, psz_var, &val );
727         val.b_bool = !val.b_bool;
728         menuitem = new wxMenuItemExt( menu, ++i_item_id,
729                                       wxU(text.psz_string ?
730                                         text.psz_string : psz_var),
731                                       wxT(""), wxITEM_CHECK, strdup(psz_var),
732                                       p_object->i_object_id, val, i_type );
733         menu->Append( menuitem );
734         Check( i_item_id, val.b_bool ? FALSE : TRUE );
735         break;
736     }
737
738     if( text.psz_string ) free( text.psz_string );
739 }
740
741 wxMenu *Menu::CreateChoicesMenu( char *psz_var, vlc_object_t *p_object,
742                                  bool b_root )
743 {
744     vlc_value_t val, val_list, text_list;
745     int i_type, i;
746
747     /* Check the type of the object variable */
748     i_type = var_Type( p_object, psz_var );
749
750     /* Make sure we want to display the variable */
751     if( IsMenuEmpty( psz_var, p_object, b_root ) ) return NULL;
752
753     switch( i_type & VLC_VAR_TYPE )
754     {
755     case VLC_VAR_VOID:
756     case VLC_VAR_BOOL:
757     case VLC_VAR_VARIABLE:
758     case VLC_VAR_STRING:
759     case VLC_VAR_INTEGER:
760     case VLC_VAR_FLOAT:
761         break;
762     default:
763         /* Variable doesn't exist or isn't handled */
764         return NULL;
765     }
766
767     if( var_Change( p_object, psz_var, VLC_VAR_GETLIST,
768                     &val_list, &text_list ) < 0 )
769     {
770         return NULL;
771     }
772
773     wxMenu *menu = new wxMenu;
774     for( i = 0; i < val_list.p_list->i_count; i++ )
775     {
776         vlc_value_t another_val;
777         wxMenuItemExt *menuitem;
778
779         switch( i_type & VLC_VAR_TYPE )
780         {
781         case VLC_VAR_VARIABLE:
782           menu->Append( MenuDummy_Event,
783                         wxU(text_list.p_list->p_values[i].psz_string ?
784                         text_list.p_list->p_values[i].psz_string :
785                         val_list.p_list->p_values[i].psz_string),
786                         CreateChoicesMenu(
787                             val_list.p_list->p_values[i].psz_string,
788                             p_object, FALSE ), wxT("") );
789           break;
790
791         case VLC_VAR_STRING:
792           var_Get( p_object, psz_var, &val );
793
794           another_val.psz_string =
795               strdup(val_list.p_list->p_values[i].psz_string);
796           menuitem =
797               new wxMenuItemExt( menu, ++i_item_id,
798                                  wxU(text_list.p_list->p_values[i].psz_string ?
799                                  text_list.p_list->p_values[i].psz_string :
800                                  another_val.psz_string), wxT(""),
801                                  i_type & VLC_VAR_ISCOMMAND ?
802                                    wxITEM_NORMAL : wxITEM_RADIO,
803                                  strdup(psz_var),
804                                  p_object->i_object_id, another_val, i_type );
805
806           menu->Append( menuitem );
807
808           if( !(i_type & VLC_VAR_ISCOMMAND) && val.psz_string &&
809               !strcmp( val.psz_string,
810                        val_list.p_list->p_values[i].psz_string ) )
811               menu->Check( i_item_id, TRUE );
812
813           if( val.psz_string ) free( val.psz_string );
814           break;
815
816         case VLC_VAR_INTEGER:
817           var_Get( p_object, psz_var, &val );
818
819           menuitem =
820               new wxMenuItemExt( menu, ++i_item_id,
821                                  text_list.p_list->p_values[i].psz_string ?
822                                  (wxString)wxU(
823                                    text_list.p_list->p_values[i].psz_string) :
824                                  wxString::Format(wxT("%d"),
825                                  val_list.p_list->p_values[i].i_int), wxT(""),
826                                  i_type & VLC_VAR_ISCOMMAND ?
827                                    wxITEM_NORMAL : wxITEM_RADIO,
828                                  strdup(psz_var),
829                                  p_object->i_object_id,
830                                  val_list.p_list->p_values[i], i_type );
831
832           menu->Append( menuitem );
833
834           if( !(i_type & VLC_VAR_ISCOMMAND) &&
835               val_list.p_list->p_values[i].i_int == val.i_int )
836               menu->Check( i_item_id, TRUE );
837           break;
838
839         case VLC_VAR_FLOAT:
840           var_Get( p_object, psz_var, &val );
841
842           menuitem =
843               new wxMenuItemExt( menu, ++i_item_id,
844                                  text_list.p_list->p_values[i].psz_string ?
845                                  (wxString)wxU(
846                                    text_list.p_list->p_values[i].psz_string) :
847                                  wxString::Format(wxT("%.2f"),
848                                  val_list.p_list->p_values[i].f_float),wxT(""),
849                                  i_type & VLC_VAR_ISCOMMAND ?
850                                    wxITEM_NORMAL : wxITEM_RADIO,
851                                  strdup(psz_var),
852                                  p_object->i_object_id,
853                                  val_list.p_list->p_values[i], i_type );
854
855           menu->Append( menuitem );
856
857           if( !(i_type & VLC_VAR_ISCOMMAND) &&
858               val_list.p_list->p_values[i].f_float == val.f_float )
859               menu->Check( i_item_id, TRUE );
860           break;
861
862         default:
863           break;
864         }
865     }
866
867     /* clean up everything */
868     var_Change( p_object, psz_var, VLC_VAR_FREELIST, &val_list, &text_list );
869
870     return menu;
871 }
872
873 /*****************************************************************************
874  * A small helper class which intercepts all popup menu events
875  *****************************************************************************/
876 MenuEvtHandler::MenuEvtHandler( intf_thread_t *_p_intf,
877                                 Interface *_p_main_interface )
878 {
879     /* Initializations */
880     p_intf = _p_intf;
881     p_main_interface = _p_main_interface;
882 }
883
884 MenuEvtHandler::~MenuEvtHandler()
885 {
886 }
887
888 void MenuEvtHandler::OnShowDialog( wxCommandEvent& event )
889 {
890     if( p_intf->p_sys->pf_show_dialog )
891     {
892         int i_id;
893
894         switch( event.GetId() )
895         {
896         case OpenFileSimple_Event:
897             i_id = INTF_DIALOG_FILE_SIMPLE;
898             break;
899         case OpenFile_Event:
900             i_id = INTF_DIALOG_FILE;
901             break;
902         case OpenDirectory_Event:
903             i_id = INTF_DIALOG_DIRECTORY;
904             break;
905         case OpenDisc_Event:
906             i_id = INTF_DIALOG_DISC;
907             break;
908         case OpenNet_Event:
909             i_id = INTF_DIALOG_NET;
910             break;
911         case OpenCapture_Event:
912             i_id = INTF_DIALOG_CAPTURE;
913             break;
914         case MediaInfo_Event:
915             i_id = INTF_DIALOG_FILEINFO;
916             break;
917         case Messages_Event:
918             i_id = INTF_DIALOG_MESSAGES;
919             break;
920         case Preferences_Event:
921             i_id = INTF_DIALOG_PREFS;
922             break;
923         default:
924             i_id = INTF_DIALOG_FILE;
925             break;
926
927         }
928
929         p_intf->p_sys->pf_show_dialog( p_intf, i_id, 1, 0 );
930     }
931 }
932
933 void MenuEvtHandler::OnMenuEvent( wxCommandEvent& event )
934 {
935     wxMenuItem *p_menuitem = NULL;
936     int i_hotkey_event = p_intf->p_sys->i_first_hotkey_event;
937     int i_hotkeys = p_intf->p_sys->i_hotkeys;
938
939     if( event.GetId() >= Play_Event && event.GetId() <= Stop_Event )
940     {
941         input_thread_t *p_input;
942         playlist_t * p_playlist =
943             (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
944                                            FIND_ANYWHERE );
945         if( !p_playlist ) return;
946
947         switch( event.GetId() )
948         {
949         case Play_Event:
950         case Pause_Event:
951             p_input =
952                 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
953                                                    FIND_ANYWHERE );
954             if( !p_input ) playlist_Play( p_playlist );
955             else
956             {
957                 vlc_value_t val;
958                 var_Get( p_input, "state", &val );
959                 if( val.i_int != PAUSE_S ) val.i_int = PAUSE_S;
960                 else val.i_int = PLAYING_S;
961                 var_Set( p_input, "state", val );
962                 vlc_object_release( p_input );
963             }
964             break;
965         case Stop_Event:
966             playlist_Stop( p_playlist );
967             break;
968         case Previous_Event:
969             playlist_Prev( p_playlist );
970             break;
971         case Next_Event:
972             playlist_Next( p_playlist );
973             break;
974         }
975
976         vlc_object_release( p_playlist );
977         return;
978     }
979
980     /* Check if this is an auto generated menu item */
981     if( event.GetId() < FirstAutoGenerated_Event )
982     {
983         event.Skip();
984         return;
985     }
986
987     /* Check if this is an hotkey event */
988     if( event.GetId() >= i_hotkey_event &&
989         event.GetId() < i_hotkey_event + i_hotkeys )
990     {
991         vlc_value_t val;
992
993         val.i_int =
994             p_intf->p_vlc->p_hotkeys[event.GetId() - i_hotkey_event].i_key;
995
996         /* Get the key combination and send it to the hotkey handler */
997         var_Set( p_intf->p_vlc, "key-pressed", val );
998         return;
999     }
1000
1001     if( !p_main_interface ||
1002         (p_menuitem = p_main_interface->GetMenuBar()->FindItem(event.GetId()))
1003         == NULL )
1004     {
1005         if( p_intf->p_sys->p_popup_menu )
1006         {
1007             p_menuitem =
1008                 p_intf->p_sys->p_popup_menu->FindItem( event.GetId() );
1009         }
1010     }
1011
1012     if( p_menuitem )
1013     {
1014         wxMenuItemExt *p_menuitemext = (wxMenuItemExt *)p_menuitem;
1015         vlc_object_t *p_object;
1016
1017         p_object = (vlc_object_t *)vlc_object_get( p_intf,
1018                                        p_menuitemext->i_object_id );
1019         if( p_object == NULL ) return;
1020
1021         wxMutexGuiLeave(); // We don't want deadlocks
1022         var_Set( p_object, p_menuitemext->psz_var, p_menuitemext->val );
1023         //wxMutexGuiEnter();
1024
1025         vlc_object_release( p_object );
1026     }
1027     else
1028         event.Skip();
1029 }
1030
1031 /*****************************************************************************
1032  * A small helper class which encapsulate wxMenuitem with some other useful
1033  * things.
1034  *****************************************************************************/
1035 wxMenuItemExt::wxMenuItemExt( wxMenu* parentMenu, int id, const wxString& text,
1036     const wxString& helpString, wxItemKind kind,
1037     char *_psz_var, int _i_object_id, vlc_value_t _val, int _i_val_type ):
1038     wxMenuItem( parentMenu, id, text, helpString, kind )
1039 {
1040     /* Initializations */
1041     psz_var = _psz_var;
1042     i_val_type = _i_val_type;
1043     i_object_id = _i_object_id;
1044     val = _val;
1045 };
1046
1047 wxMenuItemExt::~wxMenuItemExt()
1048 {
1049     if( psz_var ) free( psz_var );
1050     if( ((i_val_type & VLC_VAR_TYPE) == VLC_VAR_STRING)
1051         && val.psz_string ) free( val.psz_string );
1052 };