1 /*****************************************************************************
2 * intf_macosx.c: MacOS X interface plugin
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
6 * Authors: Colin Delacroix <colin@zoy.org>
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.
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.
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 *****************************************************************************/
23 #define MODULE_NAME macosx
24 #include "modules_inner.h"
26 /*****************************************************************************
28 *****************************************************************************/
31 #include <stdlib.h> /* malloc(), free() */
32 #include <sys/param.h> /* for MAXPATHLEN */
40 #include "interface.h"
42 #include "intf_playlist.h"
44 #include "stream_control.h"
45 #include "input_ext-intf.h"
47 #include "audio_output.h"
50 #include "video_output.h"
55 #include "modules_export.h"
57 #include "macosx_common.h"
59 extern main_t *p_main;
62 /*****************************************************************************
64 *****************************************************************************/
66 //how often to have callback to main loop. Target of 30fps then 30hz + maybe some more...
67 //it doesn't really scale if we move to 2x the hz... something else is slowing us down...
68 #define kMainLoopFrequency (kEventDurationSecond / 45) //45 for good measure
78 kAppleQuit = 7, //is this always the same?
82 kFileCloseDivisor = 3,
85 kControlsPlayORPause = 1,
89 kControlsChapterDiv = 5,
90 kControlsChapterNext = 6,
91 kControlsChapterPrevious = 7,
94 kControlsVolumeDiv = 10,
95 kControlsVolumeUp = 11,
96 kControlsVolumeDown = 12,
97 kControlsVolumeMute = 13,
98 kControlsEjectDiv = 14,
107 kAppleQuit = 8, //is this always the same?
115 kControlsPlayORPause = 1,
120 kControlsChapterNext,
121 kControlsChapterPrevious,
132 //virtual key codes ; raw subtract 0x40 from these values
133 //http://devworld.apple.com/techpubs/mac/Text/Text-577.html#HEADING577-0
139 //http://devworld.apple.com/techpubs/mac/Text/Text-571.html#MARKER-9-18
140 kPeriod = 47, //(decimal)
141 kSpace = 49, //(decimal)
142 kEscape = 53 //(decimal)
147 // Initial Window Constants
150 kAboutWindowOffset = 200,
151 kAboutWindowWidth = 200, //400
152 kAboutWindowHeight = 50 //100
156 /*****************************************************************************
157 * intf_sys_t: description and status of the interface
158 *****************************************************************************/
159 typedef struct intf_sys_s
161 EventLoopTimerRef manageTimer;
163 WindowRef p_aboutWindow;
164 int playback_status; //moved from vout ; prolly didn't belong
165 //there for a good reason ; more like Beos
168 /*****************************************************************************
170 *****************************************************************************/
171 static int intf_Probe ( probedata_t *p_data );
172 static int intf_Open ( intf_thread_t *p_intf );
173 static void intf_Close ( intf_thread_t *p_intf );
174 static void intf_Run ( intf_thread_t *p_intf );
178 static int MakeAboutWindow ( intf_thread_t *p_intf );
180 void CarbonManageCallback ( EventLoopTimerRef inTimer, void *inUserData );
182 OSErr MyOpenDocument(const FSSpecPtr defaultLocationfssPtr);
184 void playorpause ( intf_thread_t *p_intf );
185 void stop ( intf_thread_t *p_intf );
186 void silence ( intf_thread_t *p_intf );
190 void EventLoop( intf_thread_t *p_intf );
191 void DoEvent( intf_thread_t *p_intf , EventRecord *event);
192 void DoMenuCommand( intf_thread_t *p_intf , long menuResult);
193 void DrawWindow(WindowRef window);
194 void DrawAboutWindow(WindowRef window);
197 pascal OSErr QuitEventHandler(const AppleEvent *theEvent, AppleEvent *theReply, SInt32 refCon);
198 static pascal OSStatus MyKeyHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* userData );
199 static pascal OSStatus MyWindowEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData);
203 /*****************************************************************************
204 * Functions exported as capabilities. They are declared as static so that
205 * we don't pollute the namespace too much.
206 *****************************************************************************/
207 void _M( intf_getfunctions )( function_list_t * p_function_list )
209 p_function_list->pf_probe = intf_Probe;
210 p_function_list->functions.intf.pf_open = intf_Open;
211 p_function_list->functions.intf.pf_close = intf_Close;
212 p_function_list->functions.intf.pf_run = intf_Run;
215 /*****************************************************************************
216 * intf_Probe: probe the interface and return a score
217 *****************************************************************************
218 * This function checks the interface can be run and returns a score to the
219 * plugin manager so that it can select the best plugin.
220 *****************************************************************************/
221 static int intf_Probe( probedata_t *p_data )
223 if( TestMethod( INTF_METHOD_VAR, "macosx" ) )
228 /* Under MacOS X, this plugin always works */
232 /*****************************************************************************
233 * intf_Open: initialize interface
234 *****************************************************************************/
235 static int intf_Open( intf_thread_t *p_intf )
240 /* Allocate instance and initialize some members */
241 p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
242 if( p_intf->p_sys == NULL )
249 SetQDGlobalsRandomSeed( TickCount() );
251 // neat menu but don't know if we want it.
252 // Install the Windows menu. Free of charge!
253 // CreateStandardWindowMenu( 0, &windMenu );
254 // InsertMenu( windMenu, 0 );
257 menu = NewMenu( kMenuApple, "\p\024" );
258 AppendMenu( menu, "\pAbout VLCÉ/A" );
259 InsertMenu( menu, 0 );
261 menu = NewMenu( kMenuFile, "\pFile" );
262 AppendMenu( menu, "\pNew Viewer Window/N" );
263 AppendMenu( menu, "\pOpenÉ/O" );
264 AppendMenu( menu, "\p(-" );
265 AppendMenu( menu, "\pClose/W" );
266 //standard OS X application menu quit isn't working nicely
267 AppendMenu( menu, "\pQuit/Q" );
268 InsertMenu( menu, 0 );
270 //BIG HONKING MENU - in order Mac OS 9 dvd player
271 //can't get key codes right for menus... argh that's why they use resources!
273 menu = NewMenu( kMenuControls, "\pControls" );
275 AppendMenu( menu, "\pPlay/," );
276 // SetMenuItemCommandKey(menu, 0, false, kSpace);
277 // SetMenuItemModifiers( menu, 0, kMenuNoCommandModifier);
279 AppendMenu( menu, "\pStop/." );
281 AppendMenu( menu, "\pFast Forward/f" );
282 // SetMenuItemCommandKey(menu, 2, false, kRightArrow);
284 AppendMenu( menu, "\pRewind/r" );
285 // SetMenuItemCommandKey(menu, 3, false, kLeftArrow);
287 AppendMenu( menu, "\p(-" ); //4
289 AppendMenu( menu, "\pNext Chapter/c" );
290 // SetMenuItemCommandKey(menu, 5, false, kRightArrow);
291 // SetMenuItemModifiers( menu, 5, kMenuNoCommandModifier);
293 AppendMenu( menu, "\pPrevious Chapter/p" );
294 // SetMenuItemCommandKey(menu, 6, false, kLeftArrow);
295 // SetMenuItemModifiers( menu, 6, kMenuNoCommandModifier);
297 AppendMenu( menu, "\p(-" ); //7
299 AppendMenu( menu, "\pDVD Menu/v" );
300 // SetMenuItemCommandKey(menu, 8, false, kEscape);
301 // SetMenuItemModifiers( menu, 8, kMenuNoCommandModifier);
303 AppendMenu( menu, "\p(-" ); //9
305 AppendMenu( menu, "\pVolume Up/u" );
306 // SetMenuItemCommandKey(menu, 10, false, kUpArrow);
308 AppendMenu( menu, "\pVolume Down/d" );
309 // SetMenuItemCommandKey(menu, 11, false, kDownArrow);
311 AppendMenu( menu, "\pMute/M" ); //12
313 AppendMenu( menu, "\p(-" ); //13
315 AppendMenu( menu, "\pEject/E" ); //14
317 InsertMenu( menu, 0 );
319 //Hmm, eventually we might want more than one player window, but for now we assume one only (like OS 9 player)
320 //and since we start with a window open, we temporarily disable the 'new' menu
321 DisableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
323 //FIXME - Disabled Menus which are not implemented yet
324 DisableMenuItem( GetMenuHandle(kMenuControls), kControlsDVDMenu);
325 DisableMenuItem( GetMenuHandle(kMenuControls), kControlsEject);
329 if( MakeAboutWindow( p_intf ) )
331 intf_ErrMsg( "vout error: can't make about window" );
338 /*****************************************************************************
339 * intf_Close: destroy interface
340 *****************************************************************************/
341 static void intf_Close( intf_thread_t *p_intf )
343 /* Destroy structure */
344 free( p_intf->p_sys );
347 /*****************************************************************************
348 * intf_Run: main loop
349 *****************************************************************************/
350 static void intf_Run( intf_thread_t *p_intf )
353 EventLoopTimerUPP manageUPP;
356 Eventually we want to use Carbon events, or maybe even write this app in Cocoa
358 //kinda going out of bounds here... need to bring window creation to this file.
361 EventTypeSpec windowEventType = { kEventClassWindow, kEventWindowClose };
362 EventHandlerUPP windowHandlerUPP;
364 EventTypeSpec keyboardEventType = { kEventClassKeyboard, kEventRawKeyDown };
365 EventHandlerUPP keyboardHandlerUPP;
368 manageUPP = NewEventLoopTimerUPP ( CarbonManageCallback );
369 err = InstallEventLoopTimer ( GetCurrentEventLoop(), 0, kMainLoopFrequency, manageUPP, (void *) p_intf, &p_intf->p_sys->manageTimer );
370 assert(err == noErr);
371 DisposeEventLoopTimerUPP(manageUPP);
374 windowHandlerUPP = NewEventHandlerUPP ( MyWindowEventHandler );
375 err = InstallWindowEventHandler ( p_main->p_vout->p_sys->p_window , windowHandlerUPP, GetEventTypeCount(windowEventType), &windowEventType, (void *) p_intf, NULL );
376 assert(err == noErr);
377 DisposeEventHandlerUPP(windowHandlerUPP);
385 RunApplicationEventLoop();
387 err = RemoveEventLoopTimer(p_intf->p_sys->manageTimer);
388 assert(err == noErr);
392 /*****************************************************************************
393 * MakeAboutWindow: similar to MakeWindow in vout_macosx.c ;
394 * open and set-up a Mac OS window to be used for 'about' program...
395 * create it hidden and only show it when requested
396 *****************************************************************************/
397 static int MakeAboutWindow( intf_thread_t *p_intf )
401 int bottom = kAboutWindowHeight;
402 int right = kAboutWindowWidth;
404 WindowAttributes windowAttr = kWindowCloseBoxAttribute |
405 kWindowStandardHandlerAttribute |
406 kWindowInWindowMenuAttribute;
408 SetRect( &p_intf->p_sys->aboutRect, left, top, right, bottom );
409 OffsetRect( &p_intf->p_sys->aboutRect, kAboutWindowOffset, kAboutWindowOffset );
411 CreateNewWindow( kDocumentWindowClass, windowAttr, &p_intf->p_sys->aboutRect, &p_intf->p_sys->p_aboutWindow );
412 if ( p_intf->p_sys->p_aboutWindow == nil )
417 InstallStandardEventHandler(GetWindowEventTarget(p_intf->p_sys->p_aboutWindow));
418 SetWindowTitleWithCFString( p_intf->p_sys->p_aboutWindow, CFSTR("About DVD.app & VLC") );
424 void CarbonManageCallback ( EventLoopTimerRef inTimer, void *inUserData )
426 intf_thread_t * p_intf = (intf_thread_t *) inUserData;
428 /* Manage core vlc functions through the callback */
429 p_intf->pf_manage( p_intf );
433 QuitApplicationEventLoop();
439 void EventLoop( intf_thread_t *p_intf )
446 p_intf->pf_manage( p_intf );
447 gotEvent = WaitNextEvent(everyEvent,&event,32767,nil);
449 DoEvent( p_intf, &event);
450 } while (! p_intf->b_die );
456 void DoEvent( intf_thread_t *p_intf , EventRecord *event)
462 WindowRef whichWindow;
467 part = FindWindow(event->where, &whichWindow);
470 case inMenuBar: /* process a moused menu command */
471 DoMenuCommand( p_intf, MenuSelect(event->where));
478 if (whichWindow != FrontWindow())
479 SelectWindow(whichWindow);
482 case inDrag: /* pass screenBits.bounds */
483 GetRegionBounds(GetGrayRgn(), &tempRect);
484 DragWindow(whichWindow, event->where, &tempRect);
491 p_intf->b_die = true;
497 hit = TrackBox(whichWindow, event->where, part);
500 SetPort(GetWindowPort(whichWindow)); // window must be current port
501 EraseRect(GetWindowPortBounds(whichWindow, &tempRect)); // inval/erase because of ZoomWindow bug
502 ZoomWindow(whichWindow, part, true);
503 InvalWindowRect(whichWindow, GetWindowPortBounds(whichWindow, &tempRect));
511 key = event->message & charCodeMask;
512 if (event->modifiers & cmdKey)
513 if (event->what == keyDown)
514 DoMenuCommand( p_intf, MenuKey(key));
516 case activateEvt: /* if you needed to do something special */
520 DrawWindow((WindowRef) event->message);
523 case kHighLevelEvent:
524 AEProcessAppleEvent( event );
532 //the code for playorpause and stop taken almost directly from the BeOS code
533 void playorpause ( intf_thread_t *p_intf )
537 // pause the playback
538 if (p_intf->p_input != NULL )
540 // mute the volume if currently playing
541 if (p_intf->p_sys->playback_status == PLAYING)
543 vlc_mutex_lock( &p_aout_bank->lock );
544 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
546 p_aout_bank->pp_aout[i_index]->i_savedvolume =
547 p_aout_bank->pp_aout[i_index]->i_volume;
548 p_aout_bank->pp_aout[i_index]->i_volume = 0;
550 vlc_mutex_unlock( &p_aout_bank->lock );
551 p_intf->p_sys->playback_status = PAUSED;
552 SetMenuItemText( GetMenuHandle(kMenuControls), kControlsPlayORPause, "\pPlay");
555 // restore the volume
557 vlc_mutex_lock( &p_aout_bank->lock );
558 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
560 p_aout_bank->pp_aout[i_index]->i_volume =
561 p_aout_bank->pp_aout[i_index]->i_savedvolume;
562 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
564 vlc_mutex_unlock( &p_aout_bank->lock );
565 p_intf->p_sys->playback_status = PLAYING;
566 SetMenuItemText( GetMenuHandle(kMenuControls), kControlsPlayORPause, "\pPause");
569 input_SetStatus(p_intf->p_input, INPUT_STATUS_PAUSE);
573 void stop ( intf_thread_t *p_intf )
577 // this currently stops playback not nicely
578 if( p_intf->p_input != NULL )
580 // silence the sound, otherwise very horrible
581 vlc_mutex_lock( &p_aout_bank->lock );
582 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
584 p_aout_bank->pp_aout[i_index]->i_savedvolume = p_aout_bank->pp_aout[i_index]->i_volume;
585 p_aout_bank->pp_aout[i_index]->i_volume = 0;
587 vlc_mutex_unlock( &p_aout_bank->lock );
590 input_SetStatus( p_intf->p_input, INPUT_STATUS_END );
592 p_intf->p_sys->playback_status = STOPPED;
596 void DoMenuCommand( intf_thread_t *p_intf , long menuResult)
598 short menuID; /* the resource ID of the selected menu */
599 short menuItem; /* the item number of the selected menu */
601 vout_thread_t *p_vout;
603 menuID = HiWord(menuResult); /* use macros to get item & menu number */
604 menuItem = LoWord(menuResult);
612 ShowWindow( p_intf->p_sys->p_aboutWindow );
613 SelectWindow( p_intf->p_sys->p_aboutWindow );
614 DrawAboutWindow( p_intf->p_sys->p_aboutWindow); //kludge
615 EnableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
619 p_intf->b_die = true;
620 //hrmm... don't know what is going on w/ the Quit item in the new application menu...documentation???
632 vlc_mutex_lock( &p_vout_bank->lock );
633 /* XXX: only test the first video output */
634 if( p_vout_bank->i_count )
636 p_vout = p_vout_bank->pp_vout[0];
637 ShowWindow( p_vout->p_sys->p_window );
638 SelectWindow( p_vout->p_sys->p_window );
640 vlc_mutex_unlock( &p_vout_bank->lock );
641 DisableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
642 EnableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
643 //hmm, can't say to play() right now because I don't know if a file is in playlist yet.
644 //need to see if I can tell this or eve if calling play() w/o a file is bad...not sure of either
648 playorpause( p_intf );
650 // starts playing automatically on open? playorpause( p_intf );
654 HideWindow( FrontWindow() );
656 vlc_mutex_lock( &p_vout_bank->lock );
657 /* XXX: only test the first video output */
658 if( p_vout_bank->i_count )
660 p_vout = p_vout_bank->pp_vout[0];
664 vlc_mutex_unlock( &p_vout_bank->lock );
666 if ( ! IsWindowVisible( p_vout->p_sys->p_window ) && ! IsWindowVisible( p_intf->p_sys->p_aboutWindow ) )
668 //calling this even if no file open shouldn't be bad... not sure of opposite situation above
670 EnableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
671 DisableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
677 p_intf->b_die = true;
688 case kControlsPlayORPause:
689 playorpause( p_intf );
696 case kControlsForward:
697 // cycle the fast playback modes
698 if (p_intf->p_input != NULL )
700 vlc_mutex_lock( &p_aout_bank->lock );
701 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
703 p_aout_bank->pp_aout[i_index]->i_savedvolume =
704 p_aout_bank->pp_aout[i_index]->i_volume;
705 p_aout_bank->pp_aout[i_index]->i_volume = 0;
707 vlc_mutex_unlock( &p_aout_bank->lock );
709 input_SetStatus(p_intf->p_input, INPUT_STATUS_FASTER);
713 case kControlsRewind:
714 // cycle the slow playback modes
715 if (p_intf->p_input != NULL )
717 vlc_mutex_lock( &p_aout_bank->lock );
718 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
720 p_aout_bank->pp_aout[i_index]->i_savedvolume =
721 p_aout_bank->pp_aout[i_index]->i_volume;
722 p_aout_bank->pp_aout[i_index]->i_volume = 0;
724 vlc_mutex_unlock( &p_aout_bank->lock );
726 input_SetStatus(p_intf->p_input, INPUT_STATUS_FASTER);
730 case kControlsChapterNext:
731 if( p_intf->p_input != NULL )
733 /* FIXME: temporary hack */
734 p_intf->p_input->b_eof = 1;
738 case kControlsChapterPrevious:
739 if( p_intf->p_input != NULL )
741 /* FIXME: temporary hack */
742 intf_PlaylistPrev( p_main->p_playlist );
743 intf_PlaylistPrev( p_main->p_playlist );
744 p_intf->p_input->b_eof = 1;
748 case kControlsDVDMenu:
753 case kControlsVolumeUp:
755 vlc_mutex_lock( &p_aout_bank->lock );
756 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
758 // ++p_aout_bank->pp_aout[i_index]->i_volume;
759 p_aout_bank->pp_aout[i_index]->i_savedvolume = ++p_aout_bank->pp_aout[i_index]->i_volume;
761 vlc_mutex_unlock( &p_aout_bank->lock );
764 case kControlsVolumeDown:
766 vlc_mutex_lock( &p_aout_bank->lock );
767 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
769 // --p_aout_bank->pp_aout[i_index]->i_volume;
770 p_aout_bank->pp_aout[i_index]->i_savedvolume = --p_aout_bank->pp_aout[i_index]->i_volume;
772 vlc_mutex_unlock( &p_aout_bank->lock );
775 case kControlsVolumeMute:
777 vlc_mutex_lock( &p_aout_bank->lock );
778 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
780 if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
782 p_aout_bank->pp_aout[i_index]->i_volume =
783 p_aout_bank->pp_aout[i_index]->i_savedvolume;
784 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
788 p_aout_bank->pp_aout[i_index]->i_savedvolume =
789 p_aout_bank->pp_aout[i_index]->i_volume;
790 p_aout_bank->pp_aout[i_index]->i_volume = 0;
793 vlc_mutex_unlock( &p_aout_bank->lock );
809 HiliteMenu(0); /* unhighlight what MenuSelect (or MenuKey) hilited */
812 void DrawWindow(WindowRef window)
815 GrafPtr previousPort;
817 GetPort(&previousPort);
818 SetPort(GetWindowPort(window));
820 EraseRect(GetWindowPortBounds(window, &tempRect));
821 DrawControls(window);
822 DrawGrowIcon(window);
824 SetPort(previousPort);
827 void DrawAboutWindow(WindowRef window)
829 GrafPtr previousPort;
831 GetPort(&previousPort);
832 SetPort(GetWindowPort(window));
835 DrawString("\phttp://www.videolan.org");
837 SetPort(previousPort);
842 static pascal OSStatus MyEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData)
847 HICommand commandStruct;
850 OSStatus result = eventNotHandledErr; // report failure by default
852 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(window), NULL, &window);
854 whatHappened = GetEventKind(event);
856 switch (whatHappened)
858 case kEventWindowActivated:
861 case kEventWindowDeactivated:
864 case kEventWindowDrawContent:
869 case kEventWindowBoundsChanged:
870 InvalWindowRect(window, GetWindowPortBounds(window, &bounds));
875 case kEventWindowClickContentRgn:
876 /*DoContentClick(window);
882 case kEventCommandProcess:
883 GetEventParameter (event, kEventParamDirectObject,
884 typeHICommand, NULL, sizeof(HICommand),
885 NULL, &commandStruct);
886 theMenuRef = commandStruct.menu.menuRef;
888 if (theMenuRef == GetMenuHandle(kMenuApple))
890 // Because the event didn't occur *in* the window, the
891 // window reference isn't valid until we set it here
892 window = FrontWindow();
894 theMenuItem = commandStruct.menu.menuItemIndex;
895 switch ( theMenuItem )
898 SetLight(window, true);
901 SetLight(window, false);
911 case kEventMouseMoved:
913 CursorRgn = NewRgn();
914 GetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
915 NULL, sizeof(Point), NULL, &wheresMyMouse);
916 AdjustCursor(wheresMyMouse, CursorRgn);
917 DisposeRgn(CursorRgn);
923 // If nobody handled the event, it gets propagated to the
924 // application-level handler.
931 //FIXME Adding this has introduced or surfaced a lot of bugs...
932 //comented out a lot of things to strip this down to make this a 'quicky'
933 OSErr MyOpenDocument(const FSSpecPtr defaultLocationfssPtr)
935 NavDialogOptions dialogOptions;
936 // AEDesc defaultLocation;
937 // NavEventUPP eventProc = NewNavEventProc(myEventProc);
938 // NavObjectFilterUPP filterProc =
939 // NewNavObjectFilterProc(myFilterProc);
942 // Specify default options for dialog box
943 anErr = NavGetDefaultDialogOptions(&dialogOptions);
946 // Adjust the options to fit our needs
947 // Set default location option
948 // dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
949 // Clear preview option
950 dialogOptions.dialogOptionFlags ^= kNavAllowPreviews;
952 // make descriptor for default location
953 // anErr = AECreateDesc(typeFSS, defaultLocationfssPtr,
954 // sizeof(*defaultLocationfssPtr),
955 // &defaultLocation );
958 // Get 'open' resource. A nil handle being returned is OK,
959 // this simply means no automatic file filtering.
960 NavTypeListHandle typeList = (NavTypeListHandle)GetResource(
962 NavReplyRecord reply;
964 // Call NavGetFile() with specified options and
965 // declare our app-defined functions and type list
966 // anErr = NavGetFile (&defaultLocation, &reply, &dialogOptions,
967 anErr = NavGetFile (nil, &reply, &dialogOptions,
968 // eventProc, nil, filterProc,
971 if (anErr == noErr && reply.validRecord)
973 // Deal with multiple file selection
976 anErr = AECountItems(&(reply.selection), &count);
977 // Set up index for file list
982 for (index = 1; index <= count; index++)
984 AEKeyword theKeyword;
987 FSSpec documentFSSpec;
989 // Get a pointer to selected file
990 anErr = AEGetNthPtr(&(reply.selection), index,
991 typeFSS, &theKeyword,
992 &actualType,&documentFSSpec,
993 sizeof(documentFSSpec),
997 // anErr = DoOpenFile(&documentFSSpec);
1000 char path[MAXPATHLEN];
1002 //make an FSRef out of an FSSpec
1003 anErr = FSpMakeFSRef( &documentFSSpec, &newRef);
1008 //make a path out of the FSRef
1009 anErr = FSRefMakePath( &newRef, path, MAXPATHLEN);
1015 //else, ok...add it to playlist!
1016 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, path );
1022 // Dispose of NavReplyRecord, resources, descriptors
1023 anErr = NavDisposeReply(&reply);
1025 if (typeList != NULL)
1027 ReleaseResource( (Handle)typeList);
1029 //(void) AEDisposeDesc(&defaultLocation);
1032 // DisposeRoutineDescriptor(eventProc);
1033 // DisposeRoutineDescriptor(filterProc);