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