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