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