]> git.sesse.net Git - vlc/blob - plugins/macosx/intf_macosx.c
* Fixed the BeOS compile typo.
[vlc] / plugins / macosx / intf_macosx.c
1 /*****************************************************************************
2  * intf_macosx.c: MacOS X interface plugin
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  *
6  * Authors: Colin Delacroix <colin@zoy.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 #define MODULE_NAME macosx
24 #include "modules_inner.h"
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include "defs.h"
30
31 #include <stdlib.h>                                      /* malloc(), free() */
32 #include <sys/param.h>                                    /* for MAXPATHLEN */
33
34 #include "config.h"
35 #include "common.h"
36 #include "threads.h"
37 #include "mtime.h"
38 #include "tests.h"
39
40 #include "interface.h"
41 #include "intf_msg.h"
42 #include "intf_playlist.h"
43
44 #include "stream_control.h"
45 #include "input_ext-intf.h"
46
47 #include "audio_output.h"
48
49 #include "video.h"
50 #include "video_output.h"
51
52 #include "main.h"
53
54 #include "modules.h"
55 #include "modules_export.h"
56
57 #include "macosx_common.h"
58
59 extern main_t *p_main;
60
61
62 /*****************************************************************************
63  * Constants & more
64  *****************************************************************************/
65
66 //how often to have callback to main loop.  Target of 30fps then 30hz + maybe some more...
67 //it doesn't really scale if we move to 2x the hz...  something else is slowing us down...
68 #define kMainLoopFrequency  (kEventDurationSecond / 45)         //45 for good measure
69
70 // Menu defs
71 enum
72 {
73 /*    kMenuApple  = 128,
74     kMenuFile   = 129,
75     kMenuControls   = 130,
76
77     kAppleAbout = 1, 
78     kAppleQuit = 7, //is this always the same?
79
80     kFileNew   = 1, 
81     kFileOpen   = 2, 
82     kFileCloseDivisor   = 3,
83     kFileClose   = 4,
84
85     kControlsPlayORPause   = 1, 
86     kControlsStop   = 2, 
87     kControlsForward   = 3, 
88     kControlsRewind   = 4, 
89     kControlsChapterDiv   = 5, 
90     kControlsChapterNext   = 6, 
91     kControlsChapterPrevious   = 7, 
92     kControlsDVDdiv   = 8, 
93     kControlsDVDMenu   = 9, 
94     kControlsVolumeDiv   = 10, 
95     kControlsVolumeUp   = 11, 
96     kControlsVolumeDown   = 12, 
97     kControlsVolumeMute   = 13, 
98     kControlsEjectDiv   = 14, 
99     kControlsEject   = 15 
100 */
101
102     kMenuApple  = 128,
103     kMenuFile,
104     kMenuControls,
105
106     kAppleAbout = 1, 
107     kAppleQuit = 8, //is this always the same?
108
109     kFileNew   = 1, 
110     kFileOpen,
111     kFileCloseDivisor,
112     kFileClose,
113     kFileQuitHack,
114
115     kControlsPlayORPause   = 1, 
116     kControlsStop,
117     kControlsForward,
118     kControlsRewind,
119     kControlsChapterDiv,
120     kControlsChapterNext,
121     kControlsChapterPrevious,
122     kControlsDVDdiv,
123     kControlsDVDMenu,
124     kControlsVolumeDiv,
125     kControlsVolumeUp,
126     kControlsVolumeDown,
127     kControlsVolumeMute,
128     kControlsEjectDiv,
129     kControlsEject 
130
131 #if 0
132 //virtual key codes ; raw subtract 0x40 from these values
133 //http://devworld.apple.com/techpubs/mac/Text/Text-577.html#HEADING577-0
134     kLeftArrow = 0x7B,
135     kRightArrow = 0x7C,
136     kDownArrow = 0x7D,
137     kUpArrow = 0x7E,
138
139 //http://devworld.apple.com/techpubs/mac/Text/Text-571.html#MARKER-9-18    
140     kPeriod = 47, //(decimal)
141     kSpace = 49, //(decimal)
142     kEscape = 53 //(decimal)
143 #endif
144
145 };
146
147 // Initial Window Constants
148 enum
149 {
150     kAboutWindowOffset = 200,
151     kAboutWindowWidth = 200, //400
152     kAboutWindowHeight = 50 //100
153 };
154
155
156 /*****************************************************************************
157  * intf_sys_t: description and status of the interface
158  *****************************************************************************/
159 typedef struct intf_sys_s
160 {
161     EventLoopTimerRef manageTimer;
162     Rect aboutRect;
163     WindowRef   p_aboutWindow;
164     int playback_status; //moved from vout ; prolly didn't belong
165                                 //there for a good reason ; more like Beos
166 } intf_sys_t;
167
168 /*****************************************************************************
169  * Local prototypes.
170  *****************************************************************************/
171 static int  intf_Probe     ( probedata_t *p_data );
172 static int  intf_Open      ( intf_thread_t *p_intf );
173 static void intf_Close     ( intf_thread_t *p_intf );
174 static void intf_Run       ( intf_thread_t *p_intf );
175
176 /* OS Specific */
177
178 static int MakeAboutWindow              ( intf_thread_t *p_intf );
179
180 void CarbonManageCallback ( EventLoopTimerRef inTimer, void *inUserData );
181
182 OSErr MyOpenDocument(const FSSpecPtr defaultLocationfssPtr);
183
184 void playorpause ( intf_thread_t *p_intf );
185 void stop ( intf_thread_t *p_intf );
186 void silence ( intf_thread_t *p_intf );
187
188
189 #ifndef CarbonEvents
190 void EventLoop( intf_thread_t *p_intf );
191 void DoEvent( intf_thread_t *p_intf , EventRecord *event);
192 void DoMenuCommand( intf_thread_t *p_intf , long menuResult);
193 void DrawWindow(WindowRef window);
194 void DrawAboutWindow(WindowRef window);
195 #else
196 /*
197 pascal OSErr    QuitEventHandler(const AppleEvent *theEvent, AppleEvent *theReply, SInt32 refCon);
198 static pascal OSStatus MyKeyHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* userData );
199 static pascal OSStatus MyWindowEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData);
200 */
201 #endif
202
203 /*****************************************************************************
204  * Functions exported as capabilities. They are declared as static so that
205  * we don't pollute the namespace too much.
206  *****************************************************************************/
207 void _M( intf_getfunctions )( function_list_t * p_function_list )
208 {
209     p_function_list->pf_probe = intf_Probe;
210     p_function_list->functions.intf.pf_open  = intf_Open;
211     p_function_list->functions.intf.pf_close = intf_Close;
212     p_function_list->functions.intf.pf_run   = intf_Run;
213 }
214
215 /*****************************************************************************
216  * intf_Probe: probe the interface and return a score
217  *****************************************************************************
218  * This function checks the interface can be run and returns a score to the
219  * plugin manager so that it can select the best plugin.
220  *****************************************************************************/
221 static int intf_Probe( probedata_t *p_data )
222 {
223     if( TestMethod( INTF_METHOD_VAR, "macosx" ) )
224     {
225         return( 999 );
226     }
227
228     /* Under MacOS X, this plugin always works */
229     return( 100 );
230 }
231
232 /*****************************************************************************
233  * intf_Open: initialize interface
234  *****************************************************************************/
235 static int intf_Open( intf_thread_t *p_intf )
236 {
237     MenuHandle menu;
238 //    MenuRef windMenu;
239
240     /* Allocate instance and initialize some members */
241     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
242     if( p_intf->p_sys == NULL )
243     {
244         return( 1 );
245     };
246
247     /* Init Mac stuff */
248     InitCursor();
249     SetQDGlobalsRandomSeed( TickCount() );
250
251 // neat menu but don't know if we want it.
252 // Install the Windows menu. Free of charge!
253 //    CreateStandardWindowMenu( 0, &windMenu );
254 //    InsertMenu( windMenu, 0 );
255 //    DrawMenuBar();
256
257     menu = NewMenu( kMenuApple, "\p\024" );
258     AppendMenu( menu, "\pAbout VLCÉ/A" );
259     InsertMenu( menu, 0 );
260
261     menu = NewMenu( kMenuFile, "\pFile" );
262     AppendMenu( menu, "\pNew Viewer Window/N" );
263     AppendMenu( menu, "\pOpenÉ/O" );
264     AppendMenu( menu, "\p(-" );
265     AppendMenu( menu, "\pClose/W" );
266     //standard OS X application menu quit isn't working nicely
267     AppendMenu( menu, "\pQuit/Q" );
268     InsertMenu( menu, 0 );
269
270 //BIG HONKING MENU - in order Mac OS 9 dvd player
271 //can't get key codes right for menus... argh that's why they use resources!
272
273     menu = NewMenu( kMenuControls, "\pControls" );
274
275     AppendMenu( menu, "\pPlay/," );
276 //    SetMenuItemCommandKey(menu, 0, false, kSpace);
277 //    SetMenuItemModifiers( menu, 0, kMenuNoCommandModifier);
278
279     AppendMenu( menu, "\pStop/." );
280
281     AppendMenu( menu, "\pFast Forward/f" );
282 //    SetMenuItemCommandKey(menu, 2, false, kRightArrow);
283
284     AppendMenu( menu, "\pRewind/r" );
285 //    SetMenuItemCommandKey(menu, 3, false, kLeftArrow);
286
287     AppendMenu( menu, "\p(-" ); //4
288
289     AppendMenu( menu, "\pNext Chapter/c" );
290 //    SetMenuItemCommandKey(menu, 5, false, kRightArrow);
291 //    SetMenuItemModifiers( menu, 5, kMenuNoCommandModifier);
292
293     AppendMenu( menu, "\pPrevious Chapter/p" );
294 //    SetMenuItemCommandKey(menu, 6, false, kLeftArrow);
295 //    SetMenuItemModifiers( menu, 6, kMenuNoCommandModifier);
296
297     AppendMenu( menu, "\p(-" ); //7
298
299     AppendMenu( menu, "\pDVD Menu/v" );
300 //    SetMenuItemCommandKey(menu, 8, false, kEscape);
301 //    SetMenuItemModifiers( menu, 8, kMenuNoCommandModifier);
302
303     AppendMenu( menu, "\p(-" ); //9
304
305     AppendMenu( menu, "\pVolume Up/u" );
306 //    SetMenuItemCommandKey(menu, 10, false, kUpArrow);
307
308     AppendMenu( menu, "\pVolume Down/d" );
309 //    SetMenuItemCommandKey(menu, 11, false, kDownArrow);
310
311     AppendMenu( menu, "\pMute/M" ); //12
312
313     AppendMenu( menu, "\p(-" ); //13
314
315     AppendMenu( menu, "\pEject/E" ); //14
316
317     InsertMenu( menu, 0 );
318
319 //Hmm, eventually we might want more than one player window, but for now we assume one only (like OS 9 player)
320 //and since we start with a window open, we temporarily disable the 'new' menu
321     DisableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
322
323 //FIXME - Disabled Menus which are not implemented yet
324     DisableMenuItem( GetMenuHandle(kMenuControls), kControlsDVDMenu);
325     DisableMenuItem( GetMenuHandle(kMenuControls), kControlsEject);
326
327     DrawMenuBar();
328
329     if( MakeAboutWindow( p_intf ) )
330     {
331         intf_ErrMsg( "vout error: can't make about window" );
332         return( 1 );
333     }
334
335     return( 0 );
336 }
337
338 /*****************************************************************************
339  * intf_Close: destroy interface
340  *****************************************************************************/
341 static void intf_Close( intf_thread_t *p_intf )
342 {
343     /* Destroy structure */
344     free( p_intf->p_sys );
345 }
346
347 /*****************************************************************************
348  * intf_Run: main loop
349  *****************************************************************************/
350 static void intf_Run( intf_thread_t *p_intf )
351 {
352     OSStatus err;
353     EventLoopTimerUPP manageUPP;
354
355 /*
356 Eventually we want to use Carbon events, or maybe even write this app in Cocoa
357  
358 //kinda going out of bounds here... need to bring window creation to this file.
359     main_t *p_main;
360
361     EventTypeSpec windowEventType = { kEventClassWindow, kEventWindowClose };
362     EventHandlerUPP windowHandlerUPP;
363
364     EventTypeSpec keyboardEventType = { kEventClassKeyboard, kEventRawKeyDown };
365     EventHandlerUPP keyboardHandlerUPP;
366 */
367
368     manageUPP = NewEventLoopTimerUPP ( CarbonManageCallback );
369     err = InstallEventLoopTimer ( GetCurrentEventLoop(), 0, kMainLoopFrequency, manageUPP, (void *) p_intf, &p_intf->p_sys->manageTimer );
370     assert(err == noErr);
371     DisposeEventLoopTimerUPP(manageUPP);
372
373 /*
374     windowHandlerUPP = NewEventHandlerUPP ( MyWindowEventHandler );
375     err = InstallWindowEventHandler ( p_main->p_vout->p_sys->p_window , windowHandlerUPP,       GetEventTypeCount(windowEventType), &windowEventType, (void *) p_intf, NULL );
376     assert(err == noErr);
377     DisposeEventHandlerUPP(windowHandlerUPP);
378 */
379
380
381 #ifndef CarbonEvents
382     //UGLY Event Loop!
383     EventLoop( p_intf );
384 #else
385     RunApplicationEventLoop();
386 #endif
387     err = RemoveEventLoopTimer(p_intf->p_sys->manageTimer);
388     assert(err == noErr);
389 }
390
391
392 /*****************************************************************************
393  * MakeAboutWindow: similar to MakeWindow in vout_macosx.c ; 
394  * open and set-up a Mac OS window to be used for 'about' program... 
395  * create it hidden and only show it when requested
396  *****************************************************************************/
397 static int MakeAboutWindow( intf_thread_t *p_intf )
398 {
399     int left = 0;
400     int top = 0;
401     int bottom = kAboutWindowHeight;
402     int right = kAboutWindowWidth;
403
404     WindowAttributes windowAttr = kWindowCloseBoxAttribute |
405                                     kWindowStandardHandlerAttribute |
406                                     kWindowInWindowMenuAttribute;
407     
408     SetRect( &p_intf->p_sys->aboutRect, left, top, right, bottom );
409     OffsetRect( &p_intf->p_sys->aboutRect, kAboutWindowOffset, kAboutWindowOffset );
410
411     CreateNewWindow( kDocumentWindowClass, windowAttr, &p_intf->p_sys->aboutRect, &p_intf->p_sys->p_aboutWindow );
412     if ( p_intf->p_sys->p_aboutWindow == nil )
413     {
414         return( 1 );
415     }
416
417     InstallStandardEventHandler(GetWindowEventTarget(p_intf->p_sys->p_aboutWindow));
418     SetWindowTitleWithCFString( p_intf->p_sys->p_aboutWindow, CFSTR("About DVD.app & VLC") );
419     
420     return( 0 );
421 }
422
423
424 void CarbonManageCallback ( EventLoopTimerRef inTimer, void *inUserData )
425 {
426     intf_thread_t * p_intf = (intf_thread_t *) inUserData;
427
428     /* Manage core vlc functions through the callback */
429     p_intf->pf_manage( p_intf );
430     
431     if ( p_intf->b_die )
432     {
433         QuitApplicationEventLoop();
434     }
435 }
436
437 #ifndef CarbonEvents
438
439 void EventLoop( intf_thread_t *p_intf )
440 {
441     Boolean     gotEvent;
442     EventRecord event;
443     
444     do
445     {
446     p_intf->pf_manage( p_intf );
447         gotEvent = WaitNextEvent(everyEvent,&event,32767,nil);
448         if (gotEvent)
449             DoEvent( p_intf, &event);
450     } while (! p_intf->b_die );
451     
452     //ExitToShell();                                    
453 }
454
455
456 void DoEvent( intf_thread_t *p_intf , EventRecord *event)
457 {
458     short       part;
459     Boolean     hit;
460     char        key;
461     Rect        tempRect;
462     WindowRef   whichWindow;
463         
464     switch (event->what) 
465     {
466         case mouseDown:
467             part = FindWindow(event->where, &whichWindow);
468             switch (part)
469             {
470                 case inMenuBar:  /* process a moused menu command */
471                     DoMenuCommand( p_intf, MenuSelect(event->where));
472                     break;
473                     
474                 case inSysWindow:
475                     break;
476                 
477                 case inContent:
478                     if (whichWindow != FrontWindow()) 
479                         SelectWindow(whichWindow);
480                     break;
481                 
482                 case inDrag:    /* pass screenBits.bounds */
483                     GetRegionBounds(GetGrayRgn(), &tempRect);
484                     DragWindow(whichWindow, event->where, &tempRect);
485                     break;
486                     
487                 case inGrow:
488                     break;
489                     
490                 case inGoAway:
491                     p_intf->b_die = true;
492                     return;
493                     break;
494                     
495                 case inZoomIn:
496                 case inZoomOut:
497                     hit = TrackBox(whichWindow, event->where, part);
498                     if (hit) 
499                     {
500                         SetPort(GetWindowPort(whichWindow));   // window must be current port
501                         EraseRect(GetWindowPortBounds(whichWindow, &tempRect));   // inval/erase because of ZoomWindow bug
502                         ZoomWindow(whichWindow, part, true);
503                         InvalWindowRect(whichWindow, GetWindowPortBounds(whichWindow, &tempRect));      
504                     }
505                     break;
506                 }
507                 break;
508                 
509                 case keyDown:
510                 case autoKey:
511                     key = event->message & charCodeMask;
512                     if (event->modifiers & cmdKey)
513                         if (event->what == keyDown)
514                             DoMenuCommand( p_intf, MenuKey(key));
515                             
516                 case activateEvt:              /* if you needed to do something special */
517                     break;
518                     
519                 case updateEvt:
520                         DrawWindow((WindowRef) event->message);
521                     break;
522                         
523                 case kHighLevelEvent:
524                         AEProcessAppleEvent( event );
525                     break;
526                 
527                 case diskEvt:
528                     break;
529         }
530 }
531
532 //the code for playorpause and stop taken almost directly from the BeOS code
533 void playorpause ( intf_thread_t *p_intf )
534 {
535     int i_index;
536
537     // pause the playback
538     if (p_intf->p_input != NULL )
539     {
540         // mute the volume if currently playing
541         if (p_intf->p_sys->playback_status == PLAYING)
542         {
543             vlc_mutex_lock( &p_aout_bank->lock );
544             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
545             {
546                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
547                                     p_aout_bank->pp_aout[i_index]->i_volume;
548                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
549             }
550             vlc_mutex_unlock( &p_aout_bank->lock );
551             p_intf->p_sys->playback_status = PAUSED;
552             SetMenuItemText( GetMenuHandle(kMenuControls), kControlsPlayORPause, "\pPlay");
553         }
554         else
555         // restore the volume
556         {
557             vlc_mutex_lock( &p_aout_bank->lock );
558             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
559             {
560                 p_aout_bank->pp_aout[i_index]->i_volume =
561                                 p_aout_bank->pp_aout[i_index]->i_savedvolume;
562                 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
563             }
564             vlc_mutex_unlock( &p_aout_bank->lock );
565             p_intf->p_sys->playback_status = PLAYING;
566             SetMenuItemText( GetMenuHandle(kMenuControls), kControlsPlayORPause, "\pPause");
567         }
568         //snooze(400000);
569         input_SetStatus(p_intf->p_input, INPUT_STATUS_PAUSE);
570     }
571 }
572
573 void stop ( intf_thread_t *p_intf )
574 {
575     int i_index;
576
577     // this currently stops playback not nicely
578     if( p_intf->p_input != NULL )
579     {
580         // silence the sound, otherwise very horrible
581         vlc_mutex_lock( &p_aout_bank->lock );
582         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
583         {
584             p_aout_bank->pp_aout[i_index]->i_savedvolume = p_aout_bank->pp_aout[i_index]->i_volume;
585             p_aout_bank->pp_aout[i_index]->i_volume = 0;
586         }
587         vlc_mutex_unlock( &p_aout_bank->lock );
588
589         //snooze( 400000 );
590         input_SetStatus( p_intf->p_input, INPUT_STATUS_END );
591     }
592     p_intf->p_sys->playback_status = STOPPED;
593 }
594
595
596 void DoMenuCommand( intf_thread_t *p_intf , long menuResult)
597 {
598     short       menuID;         /* the resource ID of the selected menu */
599     short       menuItem;       /* the item number of the selected menu */
600     int i_index;
601     vout_thread_t *p_vout;
602
603     menuID = HiWord(menuResult);    /* use macros to get item & menu number */
604     menuItem = LoWord(menuResult);
605
606     switch (menuID) 
607     {
608         case kMenuApple:
609             switch (menuItem) 
610             {
611                 case kAppleAbout:
612                     ShowWindow( p_intf->p_sys->p_aboutWindow );
613                     SelectWindow( p_intf->p_sys->p_aboutWindow );
614                     DrawAboutWindow( p_intf->p_sys->p_aboutWindow); //kludge
615                     EnableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
616                     break;
617                     
618                 case kAppleQuit:
619                     p_intf->b_die = true;
620                     //hrmm... don't know what is going on w/ the Quit item in the new application menu...documentation???
621                     break;
622                                 
623                 default:
624                     break;
625             }
626             break;
627         
628         case kMenuFile:
629             switch (menuItem) 
630             {
631                 case kFileNew:
632                     vlc_mutex_lock( &p_vout_bank->lock );
633                     /* XXX: only test the first video output */
634                     if( p_vout_bank->i_count )
635                     {
636                         p_vout = p_vout_bank->pp_vout[0];
637                         ShowWindow( p_vout->p_sys->p_window );
638                         SelectWindow( p_vout->p_sys->p_window );
639                     }
640                     vlc_mutex_unlock( &p_vout_bank->lock );
641                     DisableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
642                     EnableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
643                     //hmm, can't say to play() right now because I don't know if a file is in playlist yet.
644                     //need to see if I can tell this or eve if calling play() w/o a file is bad...not sure of either
645                     break;
646
647                 case kFileOpen:
648                     playorpause( p_intf );
649                     MyOpenDocument(nil);
650                     // starts playing automatically on open? playorpause( p_intf );
651                     break;
652
653                 case kFileClose:
654                     HideWindow( FrontWindow() );
655
656                     vlc_mutex_lock( &p_vout_bank->lock );
657                     /* XXX: only test the first video output */
658                     if( p_vout_bank->i_count )
659                     {
660                         p_vout = p_vout_bank->pp_vout[0];
661                         printf("ok\n");
662                     }
663                         else printf("NO\n");
664                     vlc_mutex_unlock( &p_vout_bank->lock );
665
666                     if ( ! IsWindowVisible( p_vout->p_sys->p_window ) && ! IsWindowVisible( p_intf->p_sys->p_aboutWindow ) )
667                     {
668                         //calling this even if no file open shouldn't be bad... not sure of opposite situation above
669                         stop( p_intf );
670                         EnableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
671                         DisableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
672                     }
673                     break;
674                     
675                 case kFileQuitHack:
676                         stop( p_intf );
677                         p_intf->b_die = true;
678                     break;
679                     
680                 default:
681                     break;
682             }
683             break;
684                 
685         case kMenuControls:
686             switch (menuItem) 
687             {
688                 case kControlsPlayORPause:
689                         playorpause( p_intf );
690                     break;
691
692                 case kControlsStop:
693                         stop( p_intf );
694                     break;
695
696                 case kControlsForward:
697                 // cycle the fast playback modes
698                     if (p_intf->p_input != NULL )
699                     {
700                         vlc_mutex_lock( &p_aout_bank->lock );
701                         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
702                         {
703                             p_aout_bank->pp_aout[i_index]->i_savedvolume =
704                                                 p_aout_bank->pp_aout[i_index]->i_volume;
705                             p_aout_bank->pp_aout[i_index]->i_volume = 0;
706                         }
707                         vlc_mutex_unlock( &p_aout_bank->lock );
708                         //snooze(400000);
709                         input_SetStatus(p_intf->p_input, INPUT_STATUS_FASTER);
710                     }
711                     break;
712
713                 case kControlsRewind:
714                 // cycle the slow playback modes
715                     if (p_intf->p_input != NULL )
716                     {
717                         vlc_mutex_lock( &p_aout_bank->lock );
718                         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
719                         {
720                             p_aout_bank->pp_aout[i_index]->i_savedvolume =
721                                                 p_aout_bank->pp_aout[i_index]->i_volume;
722                             p_aout_bank->pp_aout[i_index]->i_volume = 0;
723                         }
724                         vlc_mutex_unlock( &p_aout_bank->lock );
725                         //snooze(400000);
726                         input_SetStatus(p_intf->p_input, INPUT_STATUS_FASTER);
727                     }
728                     break;
729                 
730                 case kControlsChapterNext:
731                     if( p_intf->p_input != NULL )
732                     {
733                         /* FIXME: temporary hack */
734                         p_intf->p_input->b_eof = 1;
735                     }
736                     break;
737
738                 case kControlsChapterPrevious:
739                     if( p_intf->p_input != NULL )
740                     {
741                         /* FIXME: temporary hack */
742                         intf_PlaylistPrev( p_main->p_playlist );
743                         intf_PlaylistPrev( p_main->p_playlist );
744                         p_intf->p_input->b_eof = 1;
745                     }
746                     break;
747
748                 case kControlsDVDMenu:
749                     //Fixme
750                     SysBeep(30);
751                     break;
752
753                 case kControlsVolumeUp:
754                 // adjust the volume
755                     vlc_mutex_lock( &p_aout_bank->lock );
756                     for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
757                     {
758 //                            ++p_aout_bank->pp_aout[i_index]->i_volume;
759                             p_aout_bank->pp_aout[i_index]->i_savedvolume = ++p_aout_bank->pp_aout[i_index]->i_volume;
760                     }
761                     vlc_mutex_unlock( &p_aout_bank->lock );
762                     break;
763
764                 case kControlsVolumeDown:
765                 // adjust the volume
766                     vlc_mutex_lock( &p_aout_bank->lock );
767                     for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
768                     {
769 //                            --p_aout_bank->pp_aout[i_index]->i_volume;
770                             p_aout_bank->pp_aout[i_index]->i_savedvolume = --p_aout_bank->pp_aout[i_index]->i_volume;
771                     }
772                     vlc_mutex_unlock( &p_aout_bank->lock );
773                     break;
774
775                 case kControlsVolumeMute:
776                 // mute
777                     vlc_mutex_lock( &p_aout_bank->lock );
778                     for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
779                     {
780                         if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
781                         {
782                             p_aout_bank->pp_aout[i_index]->i_volume =
783                                             p_aout_bank->pp_aout[i_index]->i_savedvolume;
784                             p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
785                         }
786                         else
787                         {
788                             p_aout_bank->pp_aout[i_index]->i_savedvolume =
789                                                 p_aout_bank->pp_aout[i_index]->i_volume;
790                             p_aout_bank->pp_aout[i_index]->i_volume = 0;
791                         }
792                     }
793                     vlc_mutex_unlock( &p_aout_bank->lock );
794                     break;
795
796                 case kControlsEject:
797                     //Fixme
798                     SysBeep(30);
799                     break;
800                     
801                 default:
802                     break;
803             }
804             break;
805
806         default:
807             break;
808     }
809     HiliteMenu(0);      /* unhighlight what MenuSelect (or MenuKey) hilited */
810 }
811
812 void DrawWindow(WindowRef window)
813 {
814     Rect tempRect;
815     GrafPtr previousPort;
816     
817     GetPort(&previousPort);
818     SetPort(GetWindowPort(window));
819     BeginUpdate(window);
820     EraseRect(GetWindowPortBounds(window, &tempRect));
821     DrawControls(window);
822     DrawGrowIcon(window);
823     EndUpdate(window);
824     SetPort(previousPort);
825 }
826
827 void DrawAboutWindow(WindowRef window)
828 {
829     GrafPtr previousPort;
830
831     GetPort(&previousPort);
832     SetPort(GetWindowPort(window));
833     
834     MoveTo(10,30);
835     DrawString("\phttp://www.videolan.org");
836
837     SetPort(previousPort);
838 }
839
840 #else
841
842 static pascal OSStatus MyEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData)
843 {
844     WindowRef                     window;
845     Rect                          bounds;
846     UInt32                        whatHappened;
847     HICommand                     commandStruct;
848     MenuRef                       theMenuRef;
849     UInt16                        theMenuItem;
850     OSStatus                      result = eventNotHandledErr; // report failure by default
851     
852     GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(window), NULL, &window);
853     
854     whatHappened = GetEventKind(event);
855     
856     switch (whatHappened)
857     {
858         case kEventWindowActivated:
859             break;
860         
861         case kEventWindowDeactivated:
862             break;
863         
864         case kEventWindowDrawContent:
865             //DoUpdate(window);
866             result = noErr;
867             break;
868
869         case kEventWindowBoundsChanged:
870             InvalWindowRect(window, GetWindowPortBounds(window, &bounds));
871             //DoUpdate(window);
872             result = noErr;
873             break;
874
875         case kEventWindowClickContentRgn:
876             /*DoContentClick(window);
877             DoUpdate(window);
878             AdjustMenus();*/
879             result = noErr;
880             break;
881
882         case kEventCommandProcess:
883             GetEventParameter (event, kEventParamDirectObject, 
884                                         typeHICommand, NULL, sizeof(HICommand), 
885                                         NULL, &commandStruct);
886             theMenuRef = commandStruct.menu.menuRef;
887
888             if (theMenuRef == GetMenuHandle(kMenuApple)) 
889                 {
890                     // Because the event didn't occur *in* the window, the 
891                     // window reference isn't valid until we set it here 
892                     window = FrontWindow(); 
893
894                     theMenuItem = commandStruct.menu.menuItemIndex;
895                     switch ( theMenuItem ) 
896                             {
897                                 case iStop:
898                                         SetLight(window, true);
899                                         break;
900                                 case iGo:
901                                         SetLight(window, false);
902                                         break;
903                             }
904                     DoUpdate(window);
905                     AdjustMenus();
906                     result = noErr;
907                 }
908             */
909             break; 
910
911         case kEventMouseMoved:
912             /*
913             CursorRgn = NewRgn();
914             GetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
915                                         NULL, sizeof(Point), NULL, &wheresMyMouse);
916             AdjustCursor(wheresMyMouse, CursorRgn);
917             DisposeRgn(CursorRgn);
918             */
919             result = noErr;
920             break;
921
922         default: 
923             // If nobody handled the event, it gets propagated to the
924             // application-level handler.
925             break;
926     }
927     return result;
928 }
929 #endif
930
931 //FIXME Adding this has introduced or surfaced a lot of bugs...
932 //comented out a lot of things to strip this down to make this a 'quicky'
933 OSErr MyOpenDocument(const FSSpecPtr defaultLocationfssPtr)
934 {
935     NavDialogOptions    dialogOptions;
936 //    AEDesc              defaultLocation;
937 //    NavEventUPP         eventProc = NewNavEventProc(myEventProc);
938 //    NavObjectFilterUPP  filterProc = 
939 //                        NewNavObjectFilterProc(myFilterProc);
940     OSErr               anErr = noErr;
941     
942     //  Specify default options for dialog box
943     anErr = NavGetDefaultDialogOptions(&dialogOptions);
944     if (anErr == noErr)
945     {
946         //  Adjust the options to fit our needs
947         //  Set default location option
948 //        dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
949         //  Clear preview option
950         dialogOptions.dialogOptionFlags ^= kNavAllowPreviews;
951         
952         // make descriptor for default location
953 //        anErr = AECreateDesc(typeFSS, defaultLocationfssPtr,
954 //                             sizeof(*defaultLocationfssPtr),
955 //                             &defaultLocation );
956         if (anErr == noErr)
957         {
958             // Get 'open' resource. A nil handle being returned is OK,
959             // this simply means no automatic file filtering.
960             NavTypeListHandle typeList = (NavTypeListHandle)GetResource(
961                                         'open', 128);
962             NavReplyRecord reply;
963             
964             // Call NavGetFile() with specified options and
965             // declare our app-defined functions and type list
966 //            anErr = NavGetFile (&defaultLocation, &reply, &dialogOptions,
967             anErr = NavGetFile (nil, &reply, &dialogOptions,
968 //                                eventProc, nil, filterProc,
969                                 nil, nil, nil,
970                                 typeList, nil);
971             if (anErr == noErr && reply.validRecord)
972             {
973                 //  Deal with multiple file selection
974                 long    count;
975                 
976                 anErr = AECountItems(&(reply.selection), &count);
977                 // Set up index for file list
978                 if (anErr == noErr)
979                 {
980                     long index;
981                     
982                     for (index = 1; index <= count; index++)
983                     {
984                         AEKeyword   theKeyword;
985                         DescType    actualType;
986                         Size        actualSize;
987                         FSSpec      documentFSSpec;
988                         
989                         // Get a pointer to selected file
990                         anErr = AEGetNthPtr(&(reply.selection), index,
991                                             typeFSS, &theKeyword,
992                                             &actualType,&documentFSSpec,
993                                             sizeof(documentFSSpec),
994                                             &actualSize);
995                         if (anErr == noErr)
996                         {
997 //                            anErr = DoOpenFile(&documentFSSpec);
998 //HERE
999                             FSRef newRef;
1000                             char path[MAXPATHLEN];
1001                             
1002                             //make an FSRef out of an FSSpec
1003                             anErr = FSpMakeFSRef( &documentFSSpec, &newRef);
1004                             if (anErr != noErr)
1005                             {
1006                                 return(anErr);
1007                             }
1008                             //make a path out of the FSRef
1009                             anErr = FSRefMakePath( &newRef, path, MAXPATHLEN);
1010                             if (anErr != noErr)
1011                             {
1012                                 return(anErr);
1013                             }
1014                             
1015                             //else, ok...add it to playlist!
1016                             intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, path );
1017
1018                             
1019                         }
1020                     }
1021                 }
1022                 //  Dispose of NavReplyRecord, resources, descriptors
1023                 anErr = NavDisposeReply(&reply);
1024             }
1025             if (typeList != NULL)
1026             {
1027                 ReleaseResource( (Handle)typeList);
1028             }
1029             //(void) AEDisposeDesc(&defaultLocation);
1030         }
1031     }
1032 //    DisposeRoutineDescriptor(eventProc);
1033 //    DisposeRoutineDescriptor(filterProc);
1034     return anErr;
1035 }
1036