]> git.sesse.net Git - vlc/blob - modules/gui/wince/menus.cpp
* modules/gui/wince: added a popup menu for the main interface.
[vlc] / modules / gui / wince / menus.cpp
1 /*****************************************************************************
2  * menus.cpp : WinCE gui plugin for VLC
3  *****************************************************************************
4  * Copyright (C) 2000-2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31 #include <vlc/vlc.h>
32 #include <vlc/intf.h>
33
34 #include "wince.h"
35
36 /*****************************************************************************
37  * Event Table.
38  *****************************************************************************/
39
40 /* IDs for the controls and the menu commands */
41 enum
42 {
43     /* menu items */
44     MenuDummy_Event = 1000,
45     OpenFileSimple_Event = 1100,
46     OpenFile_Event,
47     OpenDisc_Event,
48     OpenNet_Event,
49     FirstAutoGenerated_Event = 1999,
50     SettingsMenu_Events = 2000,
51     AudioMenu_Events = 3000,
52     VideoMenu_Events = 4000,
53     NavigMenu_Events = 5000,
54     PopupMenu_Events = 6000
55 };
56
57 HMENU OpenStreamMenu( intf_thread_t *p_intf )
58 {
59     HMENU hmenu = CreatePopupMenu();
60     AppendMenu( hmenu, MF_STRING, ID_FILE_QUICKOPEN,
61                 _T("Quick &Open File...") );
62     AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFILE,
63                 _T("Open &File...") );
64     AppendMenu( hmenu, MF_STRING, ID_FILE_OPENNET,
65                 _T("Open &Network Stream...") );
66     return hmenu;
67 }
68
69 HMENU MiscMenu( intf_thread_t *p_intf )
70 {
71     HMENU hmenu = CreatePopupMenu();
72     AppendMenu( hmenu, MF_STRING, ID_VIEW_STREAMINFO, _T("Media &Info...") );
73     AppendMenu( hmenu, MF_STRING, ID_VIEW_MESSAGES, _T("&Messages...") );
74     AppendMenu( hmenu, MF_STRING, ID_PREFERENCES, _T("&Preferences...") );
75     return hmenu;
76 }
77
78 void PopupMenu( intf_thread_t *p_intf, HWND p_parent, POINT point )
79 {
80 #define MAX_POPUP_ITEMS 45
81
82     vlc_object_t *p_object, *p_input;
83     char *ppsz_varnames[MAX_POPUP_ITEMS];
84     int pi_objects[MAX_POPUP_ITEMS];
85     vector<MenuItemExt*>::iterator iter;
86     int i = 0, i_last_separator = 0;
87
88     /* Initializations */
89     memset( pi_objects, 0, MAX_POPUP_ITEMS * sizeof(int) );
90
91     /* Input menu */
92     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
93                                                 FIND_ANYWHERE );
94     if( p_object != NULL )
95     {
96         ppsz_varnames[i] = "bookmark";
97         pi_objects[i++] = p_object->i_object_id;
98         ppsz_varnames[i] = "title";
99         pi_objects[i++] = p_object->i_object_id;
100         ppsz_varnames[i] = "chapter";
101         pi_objects[i++] = p_object->i_object_id;
102         ppsz_varnames[i] = "program";
103         pi_objects[i++] = p_object->i_object_id;
104         ppsz_varnames[i] = "navigation";
105         pi_objects[i++] = p_object->i_object_id;
106         ppsz_varnames[i] = "dvd_menus";
107         pi_objects[i++] = p_object->i_object_id;
108
109         ppsz_varnames[i] = "video-es";
110         pi_objects[i++] = p_object->i_object_id;
111         ppsz_varnames[i] = "audio-es";
112         pi_objects[i++] = p_object->i_object_id;
113         ppsz_varnames[i] = "spu-es";
114         pi_objects[i++] = p_object->i_object_id;
115     }
116     p_input = p_object;
117     if( !p_input ) goto interfacemenu;
118
119     /* Video menu */
120     if( i != i_last_separator ) ppsz_varnames[i++] = NULL; /* Separator */
121     i_last_separator = i;
122
123     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
124                                                 FIND_ANYWHERE );
125     if( p_object != NULL )
126     {
127         vlc_object_t *p_dec_obj;
128
129         ppsz_varnames[i] = "fullscreen";
130         pi_objects[i++] = p_object->i_object_id;
131         ppsz_varnames[i] = "zoom";
132         pi_objects[i++] = p_object->i_object_id;
133         ppsz_varnames[i] = "deinterlace";
134         pi_objects[i++] = p_object->i_object_id;
135         ppsz_varnames[i] = "aspect-ratio";
136         pi_objects[i++] = p_object->i_object_id;
137         ppsz_varnames[i] = "crop";
138         pi_objects[i++] = p_object->i_object_id;
139         ppsz_varnames[i] = "video-on-top";
140         pi_objects[i++] = p_object->i_object_id;
141         ppsz_varnames[i] = "directx-wallpaper";
142         pi_objects[i++] = p_object->i_object_id;
143         ppsz_varnames[i] = "video-snapshot";
144         pi_objects[i++] = p_object->i_object_id;
145
146         p_dec_obj = (vlc_object_t *)vlc_object_find( p_object,
147                                                      VLC_OBJECT_DECODER,
148                                                      FIND_PARENT );
149         if( p_dec_obj != NULL )
150         {
151             ppsz_varnames[i] = "ffmpeg-pp-q";
152             pi_objects[i++] = p_dec_obj->i_object_id;
153             vlc_object_release( p_dec_obj );
154         }
155
156         vlc_object_release( p_object );
157     }
158
159     /* Audio menu */
160     if( i != i_last_separator ) ppsz_varnames[i++] = NULL; /* Separator */
161     i_last_separator  = i;
162
163     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
164                                                 FIND_ANYWHERE );
165     if( p_object != NULL )
166     {
167         ppsz_varnames[i] = "audio-device";
168         pi_objects[i++] = p_object->i_object_id;
169         ppsz_varnames[i] = "audio-channels";
170         pi_objects[i++] = p_object->i_object_id;
171         ppsz_varnames[i] = "visual";
172         pi_objects[i++] = p_object->i_object_id;
173         ppsz_varnames[i] = "equalizer";
174         pi_objects[i++] = p_object->i_object_id;
175         vlc_object_release( p_object );
176     }
177
178  interfacemenu:
179     /* Interface menu */
180     if( i != i_last_separator ) ppsz_varnames[i++] = NULL; /* Separator */
181     i_last_separator = i;
182
183     /* vlc_object_find is needed because of the dialogs provider case */
184     p_object = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_INTF,
185                                                 FIND_PARENT );
186     if( p_object != NULL )
187     {
188         /* Nothing for now */
189         vlc_object_release( p_object );
190     }
191
192     /* Build menu */
193     vector<MenuItemExt*> popup_menu;
194     HMENU hmenu = CreatePopupMenu();
195     RefreshMenu( p_intf, &popup_menu, hmenu, i,
196                  ppsz_varnames, pi_objects, PopupMenu_Events );
197
198     /* Add static entries */
199     if( p_input != NULL )
200     {
201         vlc_value_t val;
202         AppendMenu( hmenu, MF_SEPARATOR, 0, _T("") );
203         AppendMenu( hmenu, MF_STRING, StopStream_Event, _T("Stop") );
204         AppendMenu( hmenu, MF_STRING, PrevStream_Event, _T("Previous") );
205         AppendMenu( hmenu, MF_STRING, NextStream_Event, _T("Next") );
206
207         var_Get( p_input, "state", &val );
208         if( val.i_int == PAUSE_S )
209             AppendMenu( hmenu, MF_STRING, PlayStream_Event, _T("Play") );
210         else
211             AppendMenu( hmenu, MF_STRING, PlayStream_Event, _T("Pause") );
212
213         vlc_object_release( p_input );
214     }
215     else
216     {
217         playlist_t * p_playlist =
218             (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
219                                            FIND_ANYWHERE );
220         if( p_playlist && p_playlist->i_size )
221         {
222             AppendMenu( hmenu, MF_SEPARATOR, 0, _T("") );
223             AppendMenu( hmenu, MF_STRING, PlayStream_Event, _T("Play") );
224         }
225         if( p_playlist ) vlc_object_release( p_playlist );
226     }
227
228     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)MiscMenu( p_intf ),
229                 _T("Miscellaneous") );
230     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)OpenStreamMenu( p_intf ),
231                 _T("Open") );
232
233     TrackPopupMenu( hmenu, 0, point.x, point.y, 0, p_parent, 0 );
234     PostMessage( p_parent, WM_NULL, 0, 0 );
235     DestroyMenu( hmenu );
236 }
237
238 void RefreshAudioMenu( intf_thread_t *p_intf, HMENU hMenu )
239 {
240 #define MAX_AUDIO_ITEMS 10
241
242     vlc_object_t *p_object;
243     char *ppsz_varnames[MAX_AUDIO_ITEMS];
244     int pi_objects[MAX_AUDIO_ITEMS];
245     vector<MenuItemExt*>::iterator iter;
246     int i;
247
248     /* Delete old menu */
249     int count = wce_GetMenuItemCount( hMenu );
250     for( i = 0; i <= count; i++ ) RemoveMenu( hMenu, 0, MF_BYPOSITION );
251         
252     if( p_intf->p_sys->p_audio_menu )
253     {
254         for( iter = p_intf->p_sys->p_audio_menu->begin();
255              iter != p_intf->p_sys->p_audio_menu->end(); iter++ )
256             delete *iter;
257         p_intf->p_sys->p_audio_menu->clear();
258     }
259     else p_intf->p_sys->p_audio_menu = new vector<MenuItemExt*>;
260
261     /* Initializations */
262     memset( pi_objects, 0, MAX_AUDIO_ITEMS * sizeof(int) );
263     i = 0;
264
265     p_object = (vlc_object_t *)
266         vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
267     if( p_object != NULL )
268     {
269         ppsz_varnames[i] = "audio-es";
270         pi_objects[i++] = p_object->i_object_id;
271         vlc_object_release( p_object );
272     }
273
274     p_object = (vlc_object_t *)
275         vlc_object_find( p_intf, VLC_OBJECT_AOUT, FIND_ANYWHERE );
276     if( p_object != NULL )
277     {
278         ppsz_varnames[i] = "audio-device";
279         pi_objects[i++] = p_object->i_object_id;
280         ppsz_varnames[i] = "audio-channels";
281         pi_objects[i++] = p_object->i_object_id;
282         ppsz_varnames[i] = "visual";
283         pi_objects[i++] = p_object->i_object_id;
284         vlc_object_release( p_object );
285     }
286
287     /* Build menu */
288     RefreshMenu( p_intf, p_intf->p_sys->p_audio_menu,
289                  hMenu, i, ppsz_varnames, pi_objects, AudioMenu_Events );
290 }
291
292 void RefreshVideoMenu( intf_thread_t *p_intf, HMENU hMenu )
293 {
294 #define MAX_VIDEO_ITEMS 15
295
296     vlc_object_t *p_object;
297     char *ppsz_varnames[MAX_VIDEO_ITEMS];
298     int pi_objects[MAX_VIDEO_ITEMS];
299     vector<MenuItemExt*>::iterator iter;
300     int i;
301
302     /* Delete old menu */
303     int count = wce_GetMenuItemCount( hMenu );
304     for( i = 0; i <= count; i++ ) RemoveMenu( hMenu, 0, MF_BYPOSITION );
305         
306     if( p_intf->p_sys->p_video_menu )
307     {
308         for( iter = p_intf->p_sys->p_video_menu->begin();
309              iter != p_intf->p_sys->p_video_menu->end(); iter++ )
310             delete *iter;
311         p_intf->p_sys->p_video_menu->clear();
312     }
313     else p_intf->p_sys->p_video_menu = new vector<MenuItemExt*>;
314         
315     /* Initializations */
316     memset( pi_objects, 0, MAX_VIDEO_ITEMS * sizeof(int) );
317     i = 0;
318
319     p_object = (vlc_object_t *)
320         vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
321     if( p_object != NULL )
322     {
323         ppsz_varnames[i] = "video-es";
324         pi_objects[i++] = p_object->i_object_id;
325         ppsz_varnames[i] = "spu-es";
326         pi_objects[i++] = p_object->i_object_id;
327         vlc_object_release( p_object );
328     }
329
330     p_object = (vlc_object_t *)
331         vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
332     if( p_object != NULL )
333     {
334         vlc_object_t *p_dec_obj;
335
336         ppsz_varnames[i] = "fullscreen";
337         pi_objects[i++] = p_object->i_object_id;
338 #ifdef WINCE
339         ppsz_varnames[i] = "transform";
340         pi_objects[i++] = p_object->i_object_id;
341 #endif
342         ppsz_varnames[i] = "zoom";
343         pi_objects[i++] = p_object->i_object_id;
344         ppsz_varnames[i] = "deinterlace";
345         pi_objects[i++] = p_object->i_object_id;
346         ppsz_varnames[i] = "aspect-ratio";
347         pi_objects[i++] = p_object->i_object_id;
348         ppsz_varnames[i] = "crop";
349         pi_objects[i++] = p_object->i_object_id;
350         ppsz_varnames[i] = "directx-on-top";
351         pi_objects[i++] = p_object->i_object_id;
352
353         p_dec_obj = (vlc_object_t *)
354             vlc_object_find( p_object, VLC_OBJECT_DECODER, FIND_PARENT );
355         if( p_dec_obj != NULL )
356         {
357             ppsz_varnames[i] = "ffmpeg-pp-q";
358             pi_objects[i++] = p_dec_obj->i_object_id;
359             vlc_object_release( p_dec_obj );
360         }
361
362         vlc_object_release( p_object );
363     }
364
365     /* Build menu */
366     RefreshMenu( p_intf, p_intf->p_sys->p_video_menu, hMenu, i,
367                  ppsz_varnames, pi_objects, VideoMenu_Events );
368 }
369
370 void RefreshNavigMenu( intf_thread_t *p_intf, HMENU hMenu )
371 {
372 #define MAX_NAVIG_ITEMS 10
373
374     vlc_object_t *p_object;
375     char *ppsz_varnames[MAX_NAVIG_ITEMS];
376     int pi_objects[MAX_NAVIG_ITEMS];
377     vector<MenuItemExt*>::iterator iter;
378     int i;
379
380     /* Delete old menu */
381     int count = wce_GetMenuItemCount( hMenu );
382     for( i = 0; i <= count; i++ ) RemoveMenu( hMenu, 0, MF_BYPOSITION );
383         
384     if( p_intf->p_sys->p_navig_menu )
385     {
386         for( iter = p_intf->p_sys->p_navig_menu->begin();
387              iter != p_intf->p_sys->p_navig_menu->end(); iter++ )
388             delete *iter;
389         p_intf->p_sys->p_navig_menu->clear();
390     }
391     else p_intf->p_sys->p_navig_menu = new vector<MenuItemExt*>;
392
393     /* Initializations */
394     memset( pi_objects, 0, MAX_NAVIG_ITEMS * sizeof(int) );
395     i = 0;
396
397     p_object = (vlc_object_t *)
398         vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
399     if( p_object != NULL )
400     {
401         ppsz_varnames[i] = "title";
402         pi_objects[i++] = p_object->i_object_id;
403         ppsz_varnames[i] = "chapter";
404         pi_objects[i++] = p_object->i_object_id;
405         ppsz_varnames[i] = "program";
406         pi_objects[i++] = p_object->i_object_id;
407         ppsz_varnames[i] = "navigation";
408         pi_objects[i++] = p_object->i_object_id;
409         ppsz_varnames[i] = "dvd_menus";
410         pi_objects[i++] = p_object->i_object_id;
411
412         ppsz_varnames[i] = "prev-title";
413         pi_objects[i++] = p_object->i_object_id;
414         ppsz_varnames[i] = "next-title";
415         pi_objects[i++] = p_object->i_object_id;
416         ppsz_varnames[i] = "prev-chapter";
417         pi_objects[i++] = p_object->i_object_id;
418         ppsz_varnames[i] = "next-chapter";
419         pi_objects[i++] = p_object->i_object_id;
420
421         vlc_object_release( p_object );
422     }
423
424     /* Build menu */
425     RefreshMenu( p_intf, p_intf->p_sys->p_navig_menu, hMenu, i,
426                  ppsz_varnames, pi_objects, NavigMenu_Events );
427 }
428
429 void RefreshSettingsMenu( intf_thread_t *p_intf, HMENU hMenu )
430 {
431 #define MAX_SETTINGS_ITEMS 10
432
433     vlc_object_t *p_object;
434     char *ppsz_varnames[MAX_SETTINGS_ITEMS];
435     int pi_objects[MAX_SETTINGS_ITEMS];
436     vector<MenuItemExt*>::iterator iter;
437     int i;
438
439     /* Delete old menu */
440     int count = wce_GetMenuItemCount( hMenu );
441     for( i = 0; i <= count; i++ ) RemoveMenu( hMenu, 0, MF_BYPOSITION );
442
443     if( p_intf->p_sys->p_settings_menu )
444     {
445         for( iter = p_intf->p_sys->p_settings_menu->begin();
446              iter != p_intf->p_sys->p_settings_menu->end(); iter++ )
447             delete(*iter);
448         p_intf->p_sys->p_settings_menu->clear();
449     }
450     else p_intf->p_sys->p_settings_menu = new vector<MenuItemExt*>;
451
452     /* Initializations */
453     memset( pi_objects, 0, MAX_SETTINGS_ITEMS * sizeof(int) );
454     i = 0;
455
456     AppendMenu( hMenu, MF_STRING, ID_PREFERENCES, _T("&Preferences...") );
457
458     p_object = (vlc_object_t *)
459         vlc_object_find( p_intf, VLC_OBJECT_INTF, FIND_PARENT );
460     if( p_object != NULL )
461     {
462         ppsz_varnames[i] = "intf-switch";
463         pi_objects[i++] = p_object->i_object_id;
464         ppsz_varnames[i] = "intf-add";
465         pi_objects[i++] = p_object->i_object_id;
466         vlc_object_release( p_object );
467     }
468
469     /* Build menu */
470     RefreshMenu( p_intf, p_intf->p_sys->p_settings_menu, hMenu, i,
471                  ppsz_varnames, pi_objects, SettingsMenu_Events );
472 }
473
474 /*****************************************************************************
475  * Refresh the menu.
476  *****************************************************************************/
477 void RefreshMenu( intf_thread_t *p_intf, vector<MenuItemExt*> *_p_menuList,
478                   HMENU hMenu , int i_count, char **ppsz_varnames, 
479                   int *pi_objects, int i_start_id )
480 {
481     vlc_object_t *p_object;
482     vlc_bool_t b_section_empty = VLC_FALSE;
483     int i;
484
485     /* Initializations */
486     int i_item_id = i_start_id;
487
488     for( i = 0; i < i_count; i++ )
489     {
490         if( !ppsz_varnames[i] )
491         {
492             if( b_section_empty )
493             {
494                 AppendMenu( hMenu, MF_GRAYED | MF_STRING,
495                             MenuDummy_Event + i, _T("Empty") );
496             }
497
498             AppendMenu( hMenu, MF_SEPARATOR, 0, _T("") );
499             b_section_empty = VLC_TRUE;
500             continue;
501         }
502
503         if( !pi_objects[i] )
504         {
505             AppendMenu( hMenu, MF_GRAYED | MF_STRING,
506                         MenuDummy_Event, _FROMMB(ppsz_varnames[i]) );
507
508             b_section_empty = VLC_FALSE;
509             continue;
510         }
511
512         p_object = (vlc_object_t *)vlc_object_get( p_intf, pi_objects[i] );
513         if( p_object == NULL ) continue;
514
515         b_section_empty = VLC_FALSE;
516         CreateMenuItem( p_intf, _p_menuList, hMenu, ppsz_varnames[i],
517                         p_object, &i_item_id );
518         vlc_object_release( p_object );
519     }
520
521     /* Special case for empty menus */
522     if( wce_GetMenuItemCount(hMenu) == 0 || b_section_empty )
523     {
524         AppendMenu( hMenu, MF_GRAYED | MF_STRING,
525                     MenuDummy_Event + i, _T("Empty") );
526     }
527 }
528
529 /*****************************************************************************
530  * Private methods.
531  *****************************************************************************/
532 void CreateMenuItem( intf_thread_t *p_intf, vector<MenuItemExt*> *_p_menuList,
533                      HMENU hMenu, char *psz_var, vlc_object_t *p_object,
534                      int *pi_item_id )
535 {
536     MenuItemExt *pMenuItemExt;
537     HMENU hMenuItem;
538     vlc_value_t val, text;
539     int i_type;
540
541     /* Check the type of the object variable */
542     i_type = var_Type( p_object, psz_var );
543
544     switch( i_type & VLC_VAR_TYPE )
545     {
546     case VLC_VAR_VOID:
547     case VLC_VAR_BOOL:
548     case VLC_VAR_VARIABLE:
549     case VLC_VAR_STRING:
550     case VLC_VAR_INTEGER:
551     case VLC_VAR_FLOAT:
552         break;
553     default:
554         /* Variable doesn't exist or isn't handled */
555         return;
556     }
557
558     /* Make sure we want to display the variable */
559     if( i_type & VLC_VAR_HASCHOICE )
560     {
561         var_Change( p_object, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
562         if( val.i_int == 0 ) return;
563         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
564             return;
565     }
566
567     /* Get the descriptive name of the variable */
568     var_Change( p_object, psz_var, VLC_VAR_GETTEXT, &text, NULL );
569
570     var_Get( p_object, psz_var, &val );
571
572     if( i_type & VLC_VAR_HASCHOICE )
573     {
574         hMenuItem = CreateChoicesMenu( p_intf, _p_menuList, psz_var,
575                                        p_object, pi_item_id );
576         AppendMenu( hMenu, MF_STRING | MF_POPUP, (UINT)hMenuItem,
577                     _FROMMB(text.psz_string ? text.psz_string : psz_var) );
578         if( text.psz_string ) free( text.psz_string );
579         return;
580     }
581
582     switch( i_type & VLC_VAR_TYPE )
583     {
584     case VLC_VAR_VOID:
585         AppendMenu( hMenu, MF_STRING , ++(*pi_item_id),
586                     _FROMMB(text.psz_string ? text.psz_string : psz_var) );
587         pMenuItemExt = new MenuItemExt( p_intf, *pi_item_id, psz_var,
588                                         p_object->i_object_id, val, i_type );
589         _p_menuList->push_back( pMenuItemExt );
590         break;
591
592     case VLC_VAR_BOOL:
593         val.b_bool = !val.b_bool;
594         AppendMenu( hMenu, MF_STRING | MF_CHECKED, ++(*pi_item_id),
595                     _FROMMB(text.psz_string ? text.psz_string : psz_var) );
596         pMenuItemExt = new MenuItemExt( p_intf, *pi_item_id, psz_var,
597                                         p_object->i_object_id, val, i_type );
598         _p_menuList->push_back( pMenuItemExt );
599         CheckMenuItem( hMenu, *pi_item_id ,
600                        ( val.b_bool ? MF_UNCHECKED : MF_CHECKED ) |
601                        MF_BYCOMMAND ); 
602         break;
603
604     default:
605         if( text.psz_string ) free( text.psz_string );
606         return;
607     }
608
609     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
610     if( text.psz_string ) free( text.psz_string );
611 }
612
613 HMENU CreateChoicesMenu( intf_thread_t *p_intf,
614                          vector<MenuItemExt*> *_p_menuList, char *psz_var, 
615                          vlc_object_t *p_object, int *pi_item_id )
616 {
617     MenuItemExt *pMenuItemExt;
618     vlc_value_t val, val_list, text_list;
619     int i_type, i;
620     HMENU hSubMenu = CreatePopupMenu();
621
622     /* Check the type of the object variable */
623     i_type = var_Type( p_object, psz_var );
624
625     /* Make sure we want to display the variable */
626     if( i_type & VLC_VAR_HASCHOICE )
627     {
628         var_Change( p_object, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
629         if( val.i_int == 0 ) return NULL;
630         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
631             return NULL;
632     }
633     else
634     {
635         return NULL;
636     }
637
638     switch( i_type & VLC_VAR_TYPE )
639     {
640     case VLC_VAR_VOID:
641     case VLC_VAR_BOOL:
642     case VLC_VAR_VARIABLE:
643     case VLC_VAR_STRING:
644     case VLC_VAR_INTEGER:
645         break;
646     default:
647         /* Variable doesn't exist or isn't handled */
648         return NULL;
649     }
650
651     if( var_Get( p_object, psz_var, &val ) < 0 ) return NULL;
652
653     if( var_Change( p_object, psz_var, VLC_VAR_GETLIST,
654                     &val_list, &text_list ) < 0 )
655     {
656         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
657         return NULL;
658     }
659
660     for( i = 0; i < val_list.p_list->i_count; i++ )
661     {
662         vlc_value_t another_val;
663         HMENU hMenuItem;
664         char *psz_tmp;
665
666         switch( i_type & VLC_VAR_TYPE )
667         {
668         case VLC_VAR_VARIABLE:
669             hMenuItem = CreateChoicesMenu( p_intf, _p_menuList,
670               val_list.p_list->p_values[i].psz_string, p_object, pi_item_id );
671             AppendMenu( hSubMenu, MF_STRING | MF_POPUP, (UINT)hMenuItem,
672                         _FROMMB(text_list.p_list->p_values[i].psz_string ?
673                           text_list.p_list->p_values[i].psz_string :
674                           val_list.p_list->p_values[i].psz_string) );
675             break;
676
677         case VLC_VAR_STRING:
678             another_val.psz_string =
679                 strdup(val_list.p_list->p_values[i].psz_string);
680             AppendMenu( hSubMenu, MF_STRING, ++(*pi_item_id),
681                         _FROMMB(text_list.p_list->p_values[i].psz_string ?
682                           text_list.p_list->p_values[i].psz_string :
683                           val_list.p_list->p_values[i].psz_string) );
684             pMenuItemExt = new MenuItemExt( p_intf, *pi_item_id, psz_var,
685                           p_object->i_object_id, another_val, i_type );
686             _p_menuList->push_back( pMenuItemExt );
687
688             if( !(i_type & VLC_VAR_ISCOMMAND) && val.psz_string &&
689                 !strcmp( val.psz_string,
690                          val_list.p_list->p_values[i].psz_string ) )
691               CheckMenuItem( hSubMenu, *pi_item_id, MF_CHECKED | MF_BYCOMMAND);
692             break;
693
694         case VLC_VAR_INTEGER:
695             asprintf( &psz_tmp, "%d", val_list.p_list->p_values[i].i_int );
696             AppendMenu( hSubMenu, MF_STRING, ++(*pi_item_id),
697                         _FROMMB(text_list.p_list->p_values[i].psz_string ?
698                           text_list.p_list->p_values[i].psz_string : psz_tmp));
699             pMenuItemExt = new MenuItemExt( p_intf, *pi_item_id, psz_var,
700                 p_object->i_object_id, val_list.p_list->p_values[i], i_type );
701             _p_menuList->push_back( pMenuItemExt );
702
703             if( val_list.p_list->p_values[i].i_int == val.i_int )
704               CheckMenuItem( hSubMenu, *pi_item_id, MF_CHECKED | MF_BYCOMMAND);
705             break;
706
707         default:
708             break;
709         }
710     }
711
712     /* Clean up everything */
713     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
714     var_Change( p_object, psz_var, VLC_VAR_FREELIST, &val_list, &text_list );
715
716     return hSubMenu;
717 }
718
719 int wce_GetMenuItemCount(HMENU hMenu)
720 {
721     const int MAX_NUM_ITEMS = 256;
722     int iPos, iCount;
723
724     MENUITEMINFO mii;
725     memset( (char *)&mii, 0, sizeof(MENUITEMINFO) );
726     mii.cbSize = sizeof(MENUITEMINFO);
727
728     iCount = 0;
729     for( iPos = 0; iPos < MAX_NUM_ITEMS; iPos++ )
730     {
731         if( !GetMenuItemInfo(hMenu, (UINT)iPos, TRUE, &mii) ) break;
732         iCount++;
733     }
734
735     return iCount;
736 }
737
738 void OnMenuEvent( intf_thread_t *p_intf, int id )
739 {
740     MenuItemExt *p_menuitemext = NULL;
741     vector<MenuItemExt*>::iterator iter;
742
743     for( iter = p_intf->p_sys->p_settings_menu->begin();
744          iter != p_intf->p_sys->p_settings_menu->end(); iter++ )
745         if( (*iter)->id == id )
746         {
747             p_menuitemext = *iter;
748             break;
749         }
750     for( iter = p_intf->p_sys->p_audio_menu->begin();
751          iter != p_intf->p_sys->p_audio_menu->end(); iter++ ) 
752         if( (*iter)->id == id )
753         {
754             p_menuitemext = *iter;
755             break;
756         }
757     for( iter = p_intf->p_sys->p_video_menu->begin();
758          iter != p_intf->p_sys->p_video_menu->end(); iter++ )
759         if( (*iter)->id == id )
760         {
761             p_menuitemext = *iter;
762             break;
763         }
764     for( iter = p_intf->p_sys->p_navig_menu->begin();
765          iter != p_intf->p_sys->p_navig_menu->end(); iter++ )
766         if( (*iter)->id == id )
767         {
768             p_menuitemext = *iter;
769             break;
770         }
771
772     if( p_menuitemext )
773     {
774         vlc_object_t *p_object = (vlc_object_t *)
775             vlc_object_get( p_intf, p_menuitemext->i_object_id );
776         if( p_object == NULL ) return;
777
778         var_Set( p_object, p_menuitemext->psz_var, p_menuitemext->val );
779         int i_type = var_Type( p_object, p_menuitemext->psz_var );
780         switch( i_type & VLC_VAR_TYPE )
781         {
782         case VLC_VAR_VOID:
783         case VLC_VAR_BOOL:
784         case VLC_VAR_VARIABLE:
785         case VLC_VAR_STRING:
786         case VLC_VAR_INTEGER:
787             break;
788         default:
789             /* Variable doesn't exist or isn't handled */
790             return;
791         }
792
793         vlc_object_release( p_object );
794     }
795 }
796
797 /*****************************************************************************
798  * A small helper class which encapsulate wxMenuitem with some other useful
799  * things.
800  *****************************************************************************/
801 MenuItemExt::MenuItemExt( intf_thread_t *p_intf, int _id, char *_psz_var,
802                           int _i_object_id, vlc_value_t _val, int _i_val_type )
803 {
804     /* Initializations */
805     id = _id;
806     p_intf = p_intf;
807     psz_var = strdup( _psz_var );
808     i_val_type = _i_val_type;
809     i_object_id = _i_object_id;
810     val = _val;
811 };
812
813 MenuItemExt::~MenuItemExt()
814 {
815     if( psz_var ) free( psz_var );
816     if( ((i_val_type & VLC_VAR_TYPE) == VLC_VAR_STRING)
817         && val.psz_string ) free( val.psz_string );
818 };