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