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 "macosx_common.h"
57 extern main_t *p_main;
60 /*****************************************************************************
62 *****************************************************************************/
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
76 kAppleQuit = 7, //is this always the same?
80 kFileCloseDivisor = 3,
83 kControlsPlayORPause = 1,
87 kControlsChapterDiv = 5,
88 kControlsChapterNext = 6,
89 kControlsChapterPrevious = 7,
92 kControlsVolumeDiv = 10,
93 kControlsVolumeUp = 11,
94 kControlsVolumeDown = 12,
95 kControlsVolumeMute = 13,
96 kControlsEjectDiv = 14,
105 kAppleQuit = 8, //is this always the same?
113 kControlsPlayORPause = 1,
118 kControlsChapterNext,
119 kControlsChapterPrevious,
130 //virtual key codes ; raw subtract 0x40 from these values
131 //http://devworld.apple.com/techpubs/mac/Text/Text-577.html#HEADING577-0
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)
145 // Initial Window Constants
148 kAboutWindowOffset = 200,
149 kAboutWindowWidth = 200, //400
150 kAboutWindowHeight = 50 //100
154 /*****************************************************************************
155 * intf_sys_t: description and status of the interface
156 *****************************************************************************/
157 typedef struct intf_sys_s
159 EventLoopTimerRef manageTimer;
161 WindowRef p_aboutWindow;
162 int playback_status; //moved from vout ; prolly didn't belong
163 //there for a good reason ; more like Beos
166 /*****************************************************************************
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 );
176 static int MakeAboutWindow ( intf_thread_t *p_intf );
178 void CarbonManageCallback ( EventLoopTimerRef inTimer, void *inUserData );
180 OSErr MyOpenDocument(const FSSpecPtr defaultLocationfssPtr);
182 void playorpause ( intf_thread_t *p_intf );
183 void stop ( intf_thread_t *p_intf );
184 void silence ( intf_thread_t *p_intf );
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);
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);
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 )
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;
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 )
221 if( TestMethod( INTF_METHOD_VAR, "macosx" ) )
226 /* Under MacOS X, this plugin always works */
230 /*****************************************************************************
231 * intf_Open: initialize interface
232 *****************************************************************************/
233 static int intf_Open( intf_thread_t *p_intf )
238 /* Allocate instance and initialize some members */
239 p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
240 if( p_intf->p_sys == NULL )
247 SetQDGlobalsRandomSeed( TickCount() );
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 );
255 menu = NewMenu( kMenuApple, "\p\024" );
256 AppendMenu( menu, "\pAbout VLCÉ/A" );
257 InsertMenu( menu, 0 );
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 );
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!
271 menu = NewMenu( kMenuControls, "\pControls" );
273 AppendMenu( menu, "\pPlay/," );
274 // SetMenuItemCommandKey(menu, 0, false, kSpace);
275 // SetMenuItemModifiers( menu, 0, kMenuNoCommandModifier);
277 AppendMenu( menu, "\pStop/." );
279 AppendMenu( menu, "\pFast Forward/f" );
280 // SetMenuItemCommandKey(menu, 2, false, kRightArrow);
282 AppendMenu( menu, "\pRewind/r" );
283 // SetMenuItemCommandKey(menu, 3, false, kLeftArrow);
285 AppendMenu( menu, "\p(-" ); //4
287 AppendMenu( menu, "\pNext Chapter/c" );
288 // SetMenuItemCommandKey(menu, 5, false, kRightArrow);
289 // SetMenuItemModifiers( menu, 5, kMenuNoCommandModifier);
291 AppendMenu( menu, "\pPrevious Chapter/p" );
292 // SetMenuItemCommandKey(menu, 6, false, kLeftArrow);
293 // SetMenuItemModifiers( menu, 6, kMenuNoCommandModifier);
295 AppendMenu( menu, "\p(-" ); //7
297 AppendMenu( menu, "\pDVD Menu/v" );
298 // SetMenuItemCommandKey(menu, 8, false, kEscape);
299 // SetMenuItemModifiers( menu, 8, kMenuNoCommandModifier);
301 AppendMenu( menu, "\p(-" ); //9
303 AppendMenu( menu, "\pVolume Up/u" );
304 // SetMenuItemCommandKey(menu, 10, false, kUpArrow);
306 AppendMenu( menu, "\pVolume Down/d" );
307 // SetMenuItemCommandKey(menu, 11, false, kDownArrow);
309 AppendMenu( menu, "\pMute/M" ); //12
311 AppendMenu( menu, "\p(-" ); //13
313 AppendMenu( menu, "\pEject/E" ); //14
315 InsertMenu( menu, 0 );
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);
321 //FIXME - Disabled Menus which are not implemented yet
322 DisableMenuItem( GetMenuHandle(kMenuControls), kControlsDVDMenu);
323 DisableMenuItem( GetMenuHandle(kMenuControls), kControlsEject);
327 if( MakeAboutWindow( p_intf ) )
329 intf_ErrMsg( "vout error: can't make about window" );
336 /*****************************************************************************
337 * intf_Close: destroy interface
338 *****************************************************************************/
339 static void intf_Close( intf_thread_t *p_intf )
341 /* Destroy structure */
342 free( p_intf->p_sys );
345 /*****************************************************************************
346 * intf_Run: main loop
347 *****************************************************************************/
348 static void intf_Run( intf_thread_t *p_intf )
351 EventLoopTimerUPP manageUPP;
354 Eventually we want to use Carbon events, or maybe even write this app in Cocoa
356 //kinda going out of bounds here... need to bring window creation to this file.
359 EventTypeSpec windowEventType = { kEventClassWindow, kEventWindowClose };
360 EventHandlerUPP windowHandlerUPP;
362 EventTypeSpec keyboardEventType = { kEventClassKeyboard, kEventRawKeyDown };
363 EventHandlerUPP keyboardHandlerUPP;
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);
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);
383 RunApplicationEventLoop();
385 err = RemoveEventLoopTimer(p_intf->p_sys->manageTimer);
386 assert(err == noErr);
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 )
399 int bottom = kAboutWindowHeight;
400 int right = kAboutWindowWidth;
402 WindowAttributes windowAttr = kWindowCloseBoxAttribute |
403 kWindowStandardHandlerAttribute |
404 kWindowInWindowMenuAttribute;
406 SetRect( &p_intf->p_sys->aboutRect, left, top, right, bottom );
407 OffsetRect( &p_intf->p_sys->aboutRect, kAboutWindowOffset, kAboutWindowOffset );
409 CreateNewWindow( kDocumentWindowClass, windowAttr, &p_intf->p_sys->aboutRect, &p_intf->p_sys->p_aboutWindow );
410 if ( p_intf->p_sys->p_aboutWindow == nil )
415 InstallStandardEventHandler(GetWindowEventTarget(p_intf->p_sys->p_aboutWindow));
416 SetWindowTitleWithCFString( p_intf->p_sys->p_aboutWindow, CFSTR("About DVD.app & VLC") );
422 void CarbonManageCallback ( EventLoopTimerRef inTimer, void *inUserData )
424 intf_thread_t * p_intf = (intf_thread_t *) inUserData;
426 /* Manage core vlc functions through the callback */
427 p_intf->pf_manage( p_intf );
431 QuitApplicationEventLoop();
437 void EventLoop( intf_thread_t *p_intf )
444 p_intf->pf_manage( p_intf );
445 gotEvent = WaitNextEvent(everyEvent,&event,32767,nil);
447 DoEvent( p_intf, &event);
448 } while (! p_intf->b_die );
454 void DoEvent( intf_thread_t *p_intf , EventRecord *event)
460 WindowRef whichWindow;
465 part = FindWindow(event->where, &whichWindow);
468 case inMenuBar: /* process a moused menu command */
469 DoMenuCommand( p_intf, MenuSelect(event->where));
476 if (whichWindow != FrontWindow())
477 SelectWindow(whichWindow);
480 case inDrag: /* pass screenBits.bounds */
481 GetRegionBounds(GetGrayRgn(), &tempRect);
482 DragWindow(whichWindow, event->where, &tempRect);
489 p_intf->b_die = true;
495 hit = TrackBox(whichWindow, event->where, part);
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));
509 key = event->message & charCodeMask;
510 if (event->modifiers & cmdKey)
511 if (event->what == keyDown)
512 DoMenuCommand( p_intf, MenuKey(key));
514 case activateEvt: /* if you needed to do something special */
518 DrawWindow((WindowRef) event->message);
521 case kHighLevelEvent:
522 AEProcessAppleEvent( event );
530 //the code for playorpause and stop taken almost directly from the BeOS code
531 void playorpause ( intf_thread_t *p_intf )
535 // pause the playback
536 if (p_intf->p_input != NULL )
538 // mute the volume if currently playing
539 if (p_intf->p_sys->playback_status == PLAYING)
541 vlc_mutex_lock( &p_aout_bank->lock );
542 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
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;
548 vlc_mutex_unlock( &p_aout_bank->lock );
549 p_intf->p_sys->playback_status = PAUSED;
550 SetMenuItemText( GetMenuHandle(kMenuControls), kControlsPlayORPause, "\pPlay");
553 // restore the volume
555 vlc_mutex_lock( &p_aout_bank->lock );
556 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
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;
562 vlc_mutex_unlock( &p_aout_bank->lock );
563 p_intf->p_sys->playback_status = PLAYING;
564 SetMenuItemText( GetMenuHandle(kMenuControls), kControlsPlayORPause, "\pPause");
567 input_SetStatus(p_intf->p_input, INPUT_STATUS_PAUSE);
571 void stop ( intf_thread_t *p_intf )
575 // this currently stops playback not nicely
576 if( p_intf->p_input != NULL )
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++ )
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;
585 vlc_mutex_unlock( &p_aout_bank->lock );
588 input_SetStatus( p_intf->p_input, INPUT_STATUS_END );
590 p_intf->p_sys->playback_status = STOPPED;
594 void DoMenuCommand( intf_thread_t *p_intf , long menuResult)
596 short menuID; /* the resource ID of the selected menu */
597 short menuItem; /* the item number of the selected menu */
599 vout_thread_t *p_vout;
601 menuID = HiWord(menuResult); /* use macros to get item & menu number */
602 menuItem = LoWord(menuResult);
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);
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???
630 vlc_mutex_lock( &p_vout_bank->lock );
631 /* XXX: only test the first video output */
632 if( p_vout_bank->i_count )
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 );
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
646 playorpause( p_intf );
648 // starts playing automatically on open? playorpause( p_intf );
652 HideWindow( FrontWindow() );
654 vlc_mutex_lock( &p_vout_bank->lock );
655 /* XXX: only test the first video output */
656 if( p_vout_bank->i_count )
658 p_vout = p_vout_bank->pp_vout[0];
662 vlc_mutex_unlock( &p_vout_bank->lock );
664 if ( ! IsWindowVisible( p_vout->p_sys->p_window ) && ! IsWindowVisible( p_intf->p_sys->p_aboutWindow ) )
666 //calling this even if no file open shouldn't be bad... not sure of opposite situation above
668 EnableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
669 DisableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
675 p_intf->b_die = true;
686 case kControlsPlayORPause:
687 playorpause( p_intf );
694 case kControlsForward:
695 // cycle the fast playback modes
696 if (p_intf->p_input != NULL )
698 vlc_mutex_lock( &p_aout_bank->lock );
699 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
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;
705 vlc_mutex_unlock( &p_aout_bank->lock );
707 input_SetStatus(p_intf->p_input, INPUT_STATUS_FASTER);
711 case kControlsRewind:
712 // cycle the slow playback modes
713 if (p_intf->p_input != NULL )
715 vlc_mutex_lock( &p_aout_bank->lock );
716 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
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;
722 vlc_mutex_unlock( &p_aout_bank->lock );
724 input_SetStatus(p_intf->p_input, INPUT_STATUS_FASTER);
728 case kControlsChapterNext:
729 if( p_intf->p_input != NULL )
731 /* FIXME: temporary hack */
732 p_intf->p_input->b_eof = 1;
736 case kControlsChapterPrevious:
737 if( p_intf->p_input != NULL )
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;
746 case kControlsDVDMenu:
751 case kControlsVolumeUp:
753 vlc_mutex_lock( &p_aout_bank->lock );
754 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
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;
759 vlc_mutex_unlock( &p_aout_bank->lock );
762 case kControlsVolumeDown:
764 vlc_mutex_lock( &p_aout_bank->lock );
765 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
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;
770 vlc_mutex_unlock( &p_aout_bank->lock );
773 case kControlsVolumeMute:
775 vlc_mutex_lock( &p_aout_bank->lock );
776 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
778 if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
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;
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;
791 vlc_mutex_unlock( &p_aout_bank->lock );
807 HiliteMenu(0); /* unhighlight what MenuSelect (or MenuKey) hilited */
810 void DrawWindow(WindowRef window)
813 GrafPtr previousPort;
815 GetPort(&previousPort);
816 SetPort(GetWindowPort(window));
818 EraseRect(GetWindowPortBounds(window, &tempRect));
819 DrawControls(window);
820 DrawGrowIcon(window);
822 SetPort(previousPort);
825 void DrawAboutWindow(WindowRef window)
827 GrafPtr previousPort;
829 GetPort(&previousPort);
830 SetPort(GetWindowPort(window));
833 DrawString("\phttp://www.videolan.org");
835 SetPort(previousPort);
840 static pascal OSStatus MyEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData)
845 HICommand commandStruct;
848 OSStatus result = eventNotHandledErr; // report failure by default
850 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(window), NULL, &window);
852 whatHappened = GetEventKind(event);
854 switch (whatHappened)
856 case kEventWindowActivated:
859 case kEventWindowDeactivated:
862 case kEventWindowDrawContent:
867 case kEventWindowBoundsChanged:
868 InvalWindowRect(window, GetWindowPortBounds(window, &bounds));
873 case kEventWindowClickContentRgn:
874 /*DoContentClick(window);
880 case kEventCommandProcess:
881 GetEventParameter (event, kEventParamDirectObject,
882 typeHICommand, NULL, sizeof(HICommand),
883 NULL, &commandStruct);
884 theMenuRef = commandStruct.menu.menuRef;
886 if (theMenuRef == GetMenuHandle(kMenuApple))
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();
892 theMenuItem = commandStruct.menu.menuItemIndex;
893 switch ( theMenuItem )
896 SetLight(window, true);
899 SetLight(window, false);
909 case kEventMouseMoved:
911 CursorRgn = NewRgn();
912 GetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
913 NULL, sizeof(Point), NULL, &wheresMyMouse);
914 AdjustCursor(wheresMyMouse, CursorRgn);
915 DisposeRgn(CursorRgn);
921 // If nobody handled the event, it gets propagated to the
922 // application-level handler.
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)
933 NavDialogOptions dialogOptions;
934 // AEDesc defaultLocation;
935 // NavEventUPP eventProc = NewNavEventProc(myEventProc);
936 // NavObjectFilterUPP filterProc =
937 // NewNavObjectFilterProc(myFilterProc);
940 // Specify default options for dialog box
941 anErr = NavGetDefaultDialogOptions(&dialogOptions);
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;
950 // make descriptor for default location
951 // anErr = AECreateDesc(typeFSS, defaultLocationfssPtr,
952 // sizeof(*defaultLocationfssPtr),
953 // &defaultLocation );
956 // Get 'open' resource. A nil handle being returned is OK,
957 // this simply means no automatic file filtering.
958 NavTypeListHandle typeList = (NavTypeListHandle)GetResource(
960 NavReplyRecord reply;
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,
969 if (anErr == noErr && reply.validRecord)
971 // Deal with multiple file selection
974 anErr = AECountItems(&(reply.selection), &count);
975 // Set up index for file list
980 for (index = 1; index <= count; index++)
982 AEKeyword theKeyword;
985 FSSpec documentFSSpec;
987 // Get a pointer to selected file
988 anErr = AEGetNthPtr(&(reply.selection), index,
989 typeFSS, &theKeyword,
990 &actualType,&documentFSSpec,
991 sizeof(documentFSSpec),
995 // anErr = DoOpenFile(&documentFSSpec);
998 char path[MAXPATHLEN];
1000 //make an FSRef out of an FSSpec
1001 anErr = FSpMakeFSRef( &documentFSSpec, &newRef);
1006 //make a path out of the FSRef
1007 anErr = FSRefMakePath( &newRef, path, MAXPATHLEN);
1013 //else, ok...add it to playlist!
1014 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, path );
1020 // Dispose of NavReplyRecord, resources, descriptors
1021 anErr = NavDisposeReply(&reply);
1023 if (typeList != NULL)
1025 ReleaseResource( (Handle)typeList);
1027 //(void) AEDisposeDesc(&defaultLocation);
1030 // DisposeRoutineDescriptor(eventProc);
1031 // DisposeRoutineDescriptor(filterProc);