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