]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/menus.cpp
* src/misc/variables.c, ALL: improvements to the object variables api.
[vlc] / modules / gui / wxwindows / menus.cpp
1 /*****************************************************************************
2  * menus.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: menus.cpp,v 1.1 2003/05/04 22:42:16 gbazin Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31
32 #include <vlc/vlc.h>
33
34 #ifdef WIN32                                                 /* mingw32 hack */
35 #undef Yield
36 #undef CreateDialog
37 #endif
38
39 /* Let vlc take care of the i18n stuff */
40 #define WXINTL_NO_GETTEXT_MACRO
41
42 #include <wx/wxprec.h>
43 #include <wx/wx.h>
44 #include <wx/listctrl.h>
45
46 #include <vlc/intf.h>
47
48 #include "wxwindows.h"
49
50 class wxMenuItemExt: public wxMenuItem
51 {
52 public:
53     /* Constructor */
54     wxMenuItemExt( wxMenu* parentMenu, int id, const wxString& text,
55                    const wxString& helpString, wxItemKind kind,
56                    char *_psz_var, int _i_object_id, vlc_value_t _val,
57                    int _i_val_type );
58
59     virtual ~wxMenuItemExt();
60
61     char *psz_var;
62     int  i_val_type;
63     int  i_object_id;
64     vlc_value_t val;
65
66 private:
67
68 };
69
70 /*****************************************************************************
71  * Event Table.
72  *****************************************************************************/
73
74 /* IDs for the controls and the menu commands */
75 enum
76 {
77     /* menu items */
78     FirstAutoGenerated_Event = wxID_HIGHEST + 1000,
79     MenuDummy_Event,
80     MenuLast_Event,
81 };
82
83 BEGIN_EVENT_TABLE(Menu, wxMenu)
84     /* Menu events */
85     EVT_MENU(MenuDummy_Event, Menu::OnEntrySelected)
86 END_EVENT_TABLE()
87
88 BEGIN_EVENT_TABLE(MenuEvtHandler, wxEvtHandler)
89     EVT_MENU(-1, MenuEvtHandler::OnMenuEvent)
90 END_EVENT_TABLE()
91
92 void PopupMenu( intf_thread_t *_p_intf, Interface *_p_main_interface )
93 {
94     vlc_object_t *p_object;
95     char *ppsz_varnames[16];
96     int pi_objects[16];
97     int i = 0;
98
99     /* Initializations */
100     memset( pi_objects, 0, 16 * sizeof(int) );
101
102     /* Audio menu */
103     ppsz_varnames[i++] = _("Audio menu");
104     ppsz_varnames[i++] = NULL; /* Separator */
105
106     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_AOUT,
107                                                 FIND_ANYWHERE );
108     if( p_object != NULL )
109     {
110         ppsz_varnames[i] = "audio-device";
111         pi_objects[i++] = p_object->i_object_id;
112         ppsz_varnames[i] = "audio-channels";
113         pi_objects[i++] = p_object->i_object_id;
114         vlc_object_release( p_object );
115     }
116
117     /* Video menu */
118     ppsz_varnames[i++] = NULL; /* Separator */
119     ppsz_varnames[i++] = _("Video menu");
120     ppsz_varnames[i++] = NULL; /* Separator */
121
122     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_VOUT,
123                                                 FIND_ANYWHERE );
124     if( p_object != NULL )
125     {
126         ppsz_varnames[i] = "fullscreen";
127         pi_objects[i++] = p_object->i_object_id;
128         vlc_object_release( p_object );
129     }
130
131     /* Input menu */
132     ppsz_varnames[i++] = NULL; /* Separator */
133     ppsz_varnames[i++] = _("Input menu");
134     ppsz_varnames[i++] = NULL; /* Separator */
135
136     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_INPUT,
137                                                 FIND_ANYWHERE );
138     if( p_object != NULL )
139     {
140         ppsz_varnames[i] = "title";
141         pi_objects[i++] = p_object->i_object_id;
142         ppsz_varnames[i] = "chapter";
143         pi_objects[i++] = p_object->i_object_id;
144         ppsz_varnames[i] = "navigation";
145         pi_objects[i++] = p_object->i_object_id;
146         vlc_object_release( p_object );
147     }
148
149     /* Misc stuff */
150     ppsz_varnames[i++] = NULL; /* Separator */
151     ppsz_varnames[i++] = _("Close");
152
153     /* Build menu */
154     wxMenu *popupmenu = new Menu( _p_intf, _p_main_interface, i,
155                                   ppsz_varnames, pi_objects );
156
157     _p_main_interface->p_popup_menu = popupmenu;
158     wxPoint mousepos = wxGetMousePosition();
159     _p_main_interface->PopupMenu( popupmenu,
160                                  _p_main_interface->ScreenToClient(mousepos).x,
161                                  _p_main_interface->ScreenToClient(mousepos).y
162                                  );
163 }
164
165 wxMenu *AudioMenu( intf_thread_t *_p_intf, Interface *_p_main_interface )
166 {
167     vlc_object_t *p_object;
168     char *ppsz_varnames[4];
169     int pi_objects[4];
170     int i = 0;
171
172     /* Initializations */
173     memset( pi_objects, 0, 4 * sizeof(int) );
174
175     /* Audio menu */
176     ppsz_varnames[i++] = NULL; /* Separator */
177
178     /* Audio menu */
179     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_AOUT,
180                                                 FIND_ANYWHERE );
181     if( p_object != NULL )
182     {
183         ppsz_varnames[i] = "audio-device";
184         pi_objects[i++] = p_object->i_object_id;
185         ppsz_varnames[i] = "audio-channels";
186         pi_objects[i++] = p_object->i_object_id;
187         vlc_object_release( p_object );
188     }
189
190     /* Build menu */
191     return new Menu( _p_intf, _p_main_interface, i,
192                      ppsz_varnames, pi_objects );
193 }
194
195 wxMenu *VideoMenu( intf_thread_t *_p_intf, Interface *_p_main_interface )
196 {
197     vlc_object_t *p_object;
198     char *ppsz_varnames[4];
199     int pi_objects[4];
200     int i = 0;
201
202     /* Initializations */
203     memset( pi_objects, 0, 4 * sizeof(int) );
204
205     ppsz_varnames[i++] = NULL; /* Separator */
206
207     p_object = (vlc_object_t *)vlc_object_find( _p_intf, VLC_OBJECT_VOUT,
208                                                 FIND_ANYWHERE );
209     if( p_object != NULL )
210     {
211         ppsz_varnames[i] = "fullscreen";
212         pi_objects[i++] = p_object->i_object_id;
213         vlc_object_release( p_object );
214     }
215
216     /* Build menu */
217     return new Menu( _p_intf, _p_main_interface, i,
218                      ppsz_varnames, pi_objects );
219 }
220
221 /*****************************************************************************
222  * Constructor.
223  *****************************************************************************/
224 Menu::Menu( intf_thread_t *_p_intf, Interface *_p_main_interface,
225             int i_count, char **ppsz_varnames, int *pi_objects ):
226     wxMenu( )
227 {
228     vlc_object_t *p_object;
229     int i;
230
231     /* Initializations */
232     p_intf = _p_intf;
233     p_main_interface = _p_main_interface;
234
235     i_item_id = MenuLast_Event;
236
237     for( i = 0; i < i_count; i++ )
238     {
239         if( !ppsz_varnames[i] )
240         {
241             AppendSeparator();
242             continue;
243         }
244
245         if( !pi_objects[i] )
246         {
247             Append( MenuDummy_Event, ppsz_varnames[i] );
248             continue;
249         }
250
251         p_object = (vlc_object_t *)vlc_object_get( p_intf, pi_objects[i] );
252         if( p_object == NULL ) continue;
253
254         CreateMenuItem( this, ppsz_varnames[i], p_object );
255         vlc_object_release( p_object );
256     }
257
258 }
259
260 Menu::~Menu()
261 {
262 }
263
264 /*****************************************************************************
265  * Private methods.
266  *****************************************************************************/
267 void Menu::OnEntrySelected( wxCommandEvent& WXUNUSED(event) )
268 {
269 }
270
271 void Menu::CreateMenuItem( wxMenu *menu, char *psz_var,
272                            vlc_object_t *p_object )
273 {
274     wxMenuItemExt *menuitem;
275     vlc_value_t val, text;
276     int i_type;
277
278     /* Check the type of the object variable */
279     i_type = var_Type( p_object, psz_var );
280
281     switch( i_type & VLC_VAR_TYPE )
282     {
283     case VLC_VAR_VOID:
284     case VLC_VAR_BOOL:
285     case VLC_VAR_VARIABLE:
286     case VLC_VAR_STRING:
287     case VLC_VAR_INTEGER:
288         break;
289     default:
290         /* Variable doesn't exist or isn't handled */
291         return;
292     }
293
294     /* Make sure we want to display the variable */
295     if( i_type & VLC_VAR_HASCHOICE )
296     {
297         var_Change( p_object, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
298         if( val.i_int == 0 ) return;
299     }
300
301     /* Get the descriptive name of the variable */
302     var_Change( p_object, psz_var, VLC_VAR_GETTEXT, &text, NULL );
303
304     if( i_type & VLC_VAR_HASCHOICE )
305     {
306         menu->Append( MenuDummy_Event,
307                       text.psz_string ? text.psz_string : psz_var,
308                       CreateChoicesMenu( psz_var, p_object ),
309                       "" /* Nothing for now (maybe use a GETLONGTEXT) */ );
310
311         if( text.psz_string ) free( text.psz_string );
312         return;
313     }
314
315
316     switch( i_type & VLC_VAR_TYPE )
317     {
318     case VLC_VAR_VOID:
319         menuitem = new wxMenuItemExt( menu, ++i_item_id,
320                                       text.psz_string ?
321                                         text.psz_string : psz_var,
322                                       "", wxITEM_NORMAL, strdup(psz_var),
323                                       p_object->i_object_id, val, i_type );
324         menu->Append( menuitem );
325         break;
326
327     case VLC_VAR_BOOL:
328         menuitem = new wxMenuItemExt( menu, ++i_item_id,
329                                       text.psz_string ?
330                                         text.psz_string : psz_var,
331                                       "", wxITEM_CHECK, strdup(psz_var),
332                                       p_object->i_object_id, val, i_type );
333         menu->Append( menuitem );
334         Check( i_item_id -1, val.b_bool ? FALSE : TRUE );
335         break;
336
337     default:
338         if( text.psz_string ) free( text.psz_string );
339         return;
340     }
341
342     if( text.psz_string ) free( text.psz_string );
343 }
344
345 wxMenu *Menu::CreateChoicesMenu( char *psz_var, vlc_object_t *p_object )
346 {
347     vlc_value_t val, val_list, text_list;
348     int i_type, i;
349
350     /* Check the type of the object variable */
351     i_type = var_Type( p_object, psz_var );
352
353     /* Make sure we want to display the variable */
354     if( i_type & VLC_VAR_HASCHOICE )
355     {
356         var_Change( p_object, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
357         if( val.i_int == 0 ) return NULL;
358     }
359     else
360     {
361         return NULL;
362     }
363
364     switch( i_type & VLC_VAR_TYPE )
365     {
366     case VLC_VAR_VOID:
367     case VLC_VAR_BOOL:
368     case VLC_VAR_VARIABLE:
369     case VLC_VAR_STRING:
370     case VLC_VAR_INTEGER:
371         break;
372     default:
373         /* Variable doesn't exist or isn't handled */
374         return NULL;
375     }
376
377     if( var_Get( p_object, psz_var, &val ) < 0 )
378     {
379         return NULL;
380     }
381
382     if( var_Change( p_object, psz_var, VLC_VAR_GETLIST,
383                     &val_list, &text_list ) < 0 )
384     {
385         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
386         return NULL;
387     }
388
389     wxMenu *menu = new wxMenu;
390     for( i = 0; i < val_list.p_list->i_count; i++ )
391     {
392         vlc_value_t another_val;
393         wxMenuItemExt *menuitem;
394
395         switch( i_type & VLC_VAR_TYPE )
396         {
397         case VLC_VAR_VARIABLE:
398           menu->Append( MenuDummy_Event,
399                         text_list.p_list->p_values[i].psz_string ?
400                         text_list.p_list->p_values[i].psz_string :
401                         val_list.p_list->p_values[i].psz_string,
402                         CreateChoicesMenu(
403                             val_list.p_list->p_values[i].psz_string,
404                             p_object ), "" );
405           break;
406
407         case VLC_VAR_STRING:
408           another_val.psz_string =
409               strdup(val_list.p_list->p_values[i].psz_string);
410           menuitem =
411               new wxMenuItemExt( this, ++i_item_id,
412                                  text_list.p_list->p_values[i].psz_string ?
413                                  text_list.p_list->p_values[i].psz_string :
414                                  another_val.psz_string,
415                                  "", wxITEM_RADIO, strdup(psz_var),
416                                  p_object->i_object_id, another_val, i_type );
417
418           menu->Append( menuitem );
419
420           if( !strcmp( val.psz_string,
421                        val_list.p_list->p_values[i].psz_string ) )
422               menu->Check( i_item_id, TRUE );
423           break;
424
425         case VLC_VAR_INTEGER:
426           menuitem =
427               new wxMenuItemExt( this, ++i_item_id,
428                                  text_list.p_list->p_values[i].psz_string ?
429                                  text_list.p_list->p_values[i].psz_string :
430                                  wxString::Format("%d",
431                                  val_list.p_list->p_values[i].i_int),
432                                  "", wxITEM_RADIO, strdup(psz_var),
433                                  p_object->i_object_id,
434                                  val_list.p_list->p_values[i], i_type );
435
436           menu->Append( menuitem );
437
438           if( !((i_type & VLC_VAR_FLAGS) & VLC_VAR_ISCOMMAND) &&
439               val_list.p_list->p_values[i].i_int == val.i_int )
440               menu->Check( i_item_id, TRUE );
441           break;
442
443         default:
444           break;
445         }
446
447     }
448
449     /* clean up everything */
450     if( i_type == VLC_VAR_STRING ) free( val.psz_string );
451     var_Change( p_object, psz_var, VLC_VAR_FREELIST, &val_list, &text_list );
452
453     return menu;
454 }
455
456 /*****************************************************************************
457  * A small helper class which intercepts all popup menu events
458  *****************************************************************************/
459 MenuEvtHandler::MenuEvtHandler( intf_thread_t *_p_intf,
460                                 Interface *_p_main_interface )
461 {
462     /* Initializations */
463     p_intf = _p_intf;
464     p_main_interface = _p_main_interface;
465 }
466
467 MenuEvtHandler::~MenuEvtHandler()
468 {
469 }
470
471 void MenuEvtHandler::OnMenuEvent( wxCommandEvent& event )
472 {
473     wxMenuItem *p_menuitem;
474
475     /* Check if this is an auto generated menu item */
476     if( event.GetId() < FirstAutoGenerated_Event )
477     {
478         event.Skip();
479         return;
480     }
481
482     if( (p_menuitem = p_main_interface->GetMenuBar()->FindItem(event.GetId()))
483         == NULL )
484     {
485         if( p_main_interface->p_popup_menu )
486         {
487             p_menuitem = 
488                 p_main_interface->p_popup_menu->FindItem( event.GetId() );
489         }
490     }
491
492     if( p_menuitem )
493     {
494         wxMenuItemExt *p_menuitemext = (wxMenuItemExt *)p_menuitem;
495         vlc_object_t *p_object;
496
497         p_object = (vlc_object_t *)vlc_object_get( p_intf,
498                                        p_menuitemext->i_object_id );
499         if( p_object == NULL ) return;
500
501         var_Set( p_object, p_menuitemext->psz_var, p_menuitemext->val );
502
503         vlc_object_release( p_object );
504     }
505     else
506         event.Skip();
507 }
508
509 /*****************************************************************************
510  * A small helper class which encapsulate wxMenuitem with some other useful
511  * things.
512  *****************************************************************************/
513 wxMenuItemExt::wxMenuItemExt( wxMenu* parentMenu, int id, const wxString& text,
514     const wxString& helpString, wxItemKind kind,
515     char *_psz_var, int _i_object_id, vlc_value_t _val, int _i_val_type ):
516     wxMenuItem( parentMenu, id, text, helpString, kind )
517 {
518     /* Initializations */
519     psz_var = _psz_var;
520     i_val_type = _i_val_type;
521     i_object_id = _i_object_id;
522     val = _val;
523 };
524
525 wxMenuItemExt::~wxMenuItemExt()
526 {
527     if( psz_var ) free( psz_var );
528     if( ((i_val_type & VLC_VAR_TYPE) == VLC_VAR_STRING)
529         && val.psz_string ) free( val.psz_string );
530 };