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