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 #include "modules_inner.h"
25 /*****************************************************************************
27 *****************************************************************************/
30 #include <stdlib.h> /* malloc(), free() */
31 #include <sys/param.h> /* for MAXPATHLEN */
39 #include "interface.h"
41 #include "intf_playlist.h"
43 #include "stream_control.h"
44 #include "input_ext-intf.h"
46 #include "audio_output.h"
49 #include "video_output.h"
54 #include "modules_export.h"
56 #include "macosx_common.h"
58 extern main_t *p_main;
61 /*****************************************************************************
63 *****************************************************************************/
65 //how often to have callback to main loop. Target of 30fps then 30hz + maybe some more...
66 //it doesn't really scale if we move to 2x the hz... something else is slowing us down...
67 #define kMainLoopFrequency (kEventDurationSecond / 45) //45 for good measure
77 kAppleQuit = 7, //is this always the same?
81 kFileCloseDivisor = 3,
84 kControlsPlayORPause = 1,
88 kControlsChapterDiv = 5,
89 kControlsChapterNext = 6,
90 kControlsChapterPrevious = 7,
93 kControlsVolumeDiv = 10,
94 kControlsVolumeUp = 11,
95 kControlsVolumeDown = 12,
96 kControlsVolumeMute = 13,
97 kControlsEjectDiv = 14,
106 kAppleQuit = 8, //is this always the same?
114 kControlsPlayORPause = 1,
119 kControlsChapterNext,
120 kControlsChapterPrevious,
131 //virtual key codes ; raw subtract 0x40 from these values
132 //http://devworld.apple.com/techpubs/mac/Text/Text-577.html#HEADING577-0
138 //http://devworld.apple.com/techpubs/mac/Text/Text-571.html#MARKER-9-18
139 kPeriod = 47, //(decimal)
140 kSpace = 49, //(decimal)
141 kEscape = 53 //(decimal)
146 // Initial Window Constants
149 kAboutWindowOffset = 200,
150 kAboutWindowWidth = 200, //400
151 kAboutWindowHeight = 50 //100
155 /*****************************************************************************
156 * intf_sys_t: description and status of the interface
157 *****************************************************************************/
158 typedef struct intf_sys_s
160 EventLoopTimerRef manageTimer;
162 WindowRef p_aboutWindow;
163 int playback_status; //moved from vout ; prolly didn't belong
164 //there for a good reason ; more like Beos
167 /*****************************************************************************
169 *****************************************************************************/
170 static int intf_Probe ( probedata_t *p_data );
171 static int intf_Open ( intf_thread_t *p_intf );
172 static void intf_Close ( intf_thread_t *p_intf );
173 static void intf_Run ( intf_thread_t *p_intf );
177 static int MakeAboutWindow ( intf_thread_t *p_intf );
179 void CarbonManageCallback ( EventLoopTimerRef inTimer, void *inUserData );
181 OSErr MyOpenDocument(const FSSpecPtr defaultLocationfssPtr);
183 void playorpause ( intf_thread_t *p_intf );
184 void stop ( intf_thread_t *p_intf );
185 void silence ( intf_thread_t *p_intf );
189 void EventLoop( intf_thread_t *p_intf );
190 void DoEvent( intf_thread_t *p_intf , EventRecord *event);
191 void DoMenuCommand( intf_thread_t *p_intf , long menuResult);
192 void DrawWindow(WindowRef window);
193 void DrawAboutWindow(WindowRef window);
196 pascal OSErr QuitEventHandler(const AppleEvent *theEvent, AppleEvent *theReply, SInt32 refCon);
197 static pascal OSStatus MyKeyHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* userData );
198 static pascal OSStatus MyWindowEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData);
202 /*****************************************************************************
203 * Functions exported as capabilities. They are declared as static so that
204 * we don't pollute the namespace too much.
205 *****************************************************************************/
206 void _M( intf_getfunctions )( function_list_t * p_function_list )
208 p_function_list->pf_probe = intf_Probe;
209 p_function_list->functions.intf.pf_open = intf_Open;
210 p_function_list->functions.intf.pf_close = intf_Close;
211 p_function_list->functions.intf.pf_run = intf_Run;
214 /*****************************************************************************
215 * intf_Probe: probe the interface and return a score
216 *****************************************************************************
217 * This function checks the interface can be run and returns a score to the
218 * plugin manager so that it can select the best plugin.
219 *****************************************************************************/
220 static int intf_Probe( probedata_t *p_data )
222 if( TestMethod( INTF_METHOD_VAR, "macosx" ) )
227 /* Under MacOS X, this plugin always works */
231 /*****************************************************************************
232 * intf_Open: initialize interface
233 *****************************************************************************/
234 static int intf_Open( intf_thread_t *p_intf )
239 /* Allocate instance and initialize some members */
240 p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
241 if( p_intf->p_sys == NULL )
248 SetQDGlobalsRandomSeed( TickCount() );
250 // neat menu but don't know if we want it.
251 // Install the Windows menu. Free of charge!
252 // CreateStandardWindowMenu( 0, &windMenu );
253 // InsertMenu( windMenu, 0 );
256 menu = NewMenu( kMenuApple, "\p\024" );
257 AppendMenu( menu, "\pAbout VLCÉ/A" );
258 InsertMenu( menu, 0 );
260 menu = NewMenu( kMenuFile, "\pFile" );
261 AppendMenu( menu, "\pNew Viewer Window/N" );
262 AppendMenu( menu, "\pOpenÉ/O" );
263 AppendMenu( menu, "\p(-" );
264 AppendMenu( menu, "\pClose/W" );
265 //standard OS X application menu quit isn't working nicely
266 AppendMenu( menu, "\pQuit/Q" );
267 InsertMenu( menu, 0 );
269 //BIG HONKING MENU - in order Mac OS 9 dvd player
270 //can't get key codes right for menus... argh that's why they use resources!
272 menu = NewMenu( kMenuControls, "\pControls" );
274 AppendMenu( menu, "\pPlay/," );
275 // SetMenuItemCommandKey(menu, 0, false, kSpace);
276 // SetMenuItemModifiers( menu, 0, kMenuNoCommandModifier);
278 AppendMenu( menu, "\pStop/." );
280 AppendMenu( menu, "\pFast Forward/f" );
281 // SetMenuItemCommandKey(menu, 2, false, kRightArrow);
283 AppendMenu( menu, "\pRewind/r" );
284 // SetMenuItemCommandKey(menu, 3, false, kLeftArrow);
286 AppendMenu( menu, "\p(-" ); //4
288 AppendMenu( menu, "\pNext Chapter/c" );
289 // SetMenuItemCommandKey(menu, 5, false, kRightArrow);
290 // SetMenuItemModifiers( menu, 5, kMenuNoCommandModifier);
292 AppendMenu( menu, "\pPrevious Chapter/p" );
293 // SetMenuItemCommandKey(menu, 6, false, kLeftArrow);
294 // SetMenuItemModifiers( menu, 6, kMenuNoCommandModifier);
296 AppendMenu( menu, "\p(-" ); //7
298 AppendMenu( menu, "\pDVD Menu/v" );
299 // SetMenuItemCommandKey(menu, 8, false, kEscape);
300 // SetMenuItemModifiers( menu, 8, kMenuNoCommandModifier);
302 AppendMenu( menu, "\p(-" ); //9
304 AppendMenu( menu, "\pVolume Up/u" );
305 // SetMenuItemCommandKey(menu, 10, false, kUpArrow);
307 AppendMenu( menu, "\pVolume Down/d" );
308 // SetMenuItemCommandKey(menu, 11, false, kDownArrow);
310 AppendMenu( menu, "\pMute/M" ); //12
312 AppendMenu( menu, "\p(-" ); //13
314 AppendMenu( menu, "\pEject/E" ); //14
316 InsertMenu( menu, 0 );
318 //Hmm, eventually we might want more than one player window, but for now we assume one only (like OS 9 player)
319 //and since we start with a window open, we temporarily disable the 'new' menu
320 DisableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
322 //FIXME - Disabled Menus which are not implemented yet
323 DisableMenuItem( GetMenuHandle(kMenuControls), kControlsDVDMenu);
324 DisableMenuItem( GetMenuHandle(kMenuControls), kControlsEject);
328 if( MakeAboutWindow( p_intf ) )
330 intf_ErrMsg( "vout error: can't make about window" );
337 /*****************************************************************************
338 * intf_Close: destroy interface
339 *****************************************************************************/
340 static void intf_Close( intf_thread_t *p_intf )
342 /* Destroy structure */
343 free( p_intf->p_sys );
346 /*****************************************************************************
347 * intf_Run: main loop
348 *****************************************************************************/
349 static void intf_Run( intf_thread_t *p_intf )
352 EventLoopTimerUPP manageUPP;
355 Eventually we want to use Carbon events, or maybe even write this app in Cocoa
357 //kinda going out of bounds here... need to bring window creation to this file.
360 EventTypeSpec windowEventType = { kEventClassWindow, kEventWindowClose };
361 EventHandlerUPP windowHandlerUPP;
363 EventTypeSpec keyboardEventType = { kEventClassKeyboard, kEventRawKeyDown };
364 EventHandlerUPP keyboardHandlerUPP;
367 manageUPP = NewEventLoopTimerUPP ( CarbonManageCallback );
368 err = InstallEventLoopTimer ( GetCurrentEventLoop(), 0, kMainLoopFrequency, manageUPP, (void *) p_intf, &p_intf->p_sys->manageTimer );
369 assert(err == noErr);
370 DisposeEventLoopTimerUPP(manageUPP);
373 windowHandlerUPP = NewEventHandlerUPP ( MyWindowEventHandler );
374 err = InstallWindowEventHandler ( p_main->p_vout->p_sys->p_window , windowHandlerUPP, GetEventTypeCount(windowEventType), &windowEventType, (void *) p_intf, NULL );
375 assert(err == noErr);
376 DisposeEventHandlerUPP(windowHandlerUPP);
384 RunApplicationEventLoop();
386 err = RemoveEventLoopTimer(p_intf->p_sys->manageTimer);
387 assert(err == noErr);
391 /*****************************************************************************
392 * MakeAboutWindow: similar to MakeWindow in vout_macosx.c ;
393 * open and set-up a Mac OS window to be used for 'about' program...
394 * create it hidden and only show it when requested
395 *****************************************************************************/
396 static int MakeAboutWindow( intf_thread_t *p_intf )
400 int bottom = kAboutWindowHeight;
401 int right = kAboutWindowWidth;
403 WindowAttributes windowAttr = kWindowCloseBoxAttribute |
404 kWindowStandardHandlerAttribute |
405 kWindowInWindowMenuAttribute;
407 SetRect( &p_intf->p_sys->aboutRect, left, top, right, bottom );
408 OffsetRect( &p_intf->p_sys->aboutRect, kAboutWindowOffset, kAboutWindowOffset );
410 CreateNewWindow( kDocumentWindowClass, windowAttr, &p_intf->p_sys->aboutRect, &p_intf->p_sys->p_aboutWindow );
411 if ( p_intf->p_sys->p_aboutWindow == nil )
416 InstallStandardEventHandler(GetWindowEventTarget(p_intf->p_sys->p_aboutWindow));
417 SetWindowTitleWithCFString( p_intf->p_sys->p_aboutWindow, CFSTR("About DVD.app & VLC") );
423 void CarbonManageCallback ( EventLoopTimerRef inTimer, void *inUserData )
425 intf_thread_t * p_intf = (intf_thread_t *) inUserData;
427 /* Manage core vlc functions through the callback */
428 p_intf->pf_manage( p_intf );
432 QuitApplicationEventLoop();
438 void EventLoop( intf_thread_t *p_intf )
445 p_intf->pf_manage( p_intf );
446 gotEvent = WaitNextEvent(everyEvent,&event,32767,nil);
448 DoEvent( p_intf, &event);
449 } while (! p_intf->b_die );
455 void DoEvent( intf_thread_t *p_intf , EventRecord *event)
461 WindowRef whichWindow;
466 part = FindWindow(event->where, &whichWindow);
469 case inMenuBar: /* process a moused menu command */
470 DoMenuCommand( p_intf, MenuSelect(event->where));
477 if (whichWindow != FrontWindow())
478 SelectWindow(whichWindow);
481 case inDrag: /* pass screenBits.bounds */
482 GetRegionBounds(GetGrayRgn(), &tempRect);
483 DragWindow(whichWindow, event->where, &tempRect);
490 p_intf->b_die = true;
496 hit = TrackBox(whichWindow, event->where, part);
499 SetPort(GetWindowPort(whichWindow)); // window must be current port
500 EraseRect(GetWindowPortBounds(whichWindow, &tempRect)); // inval/erase because of ZoomWindow bug
501 ZoomWindow(whichWindow, part, true);
502 InvalWindowRect(whichWindow, GetWindowPortBounds(whichWindow, &tempRect));
510 key = event->message & charCodeMask;
511 if (event->modifiers & cmdKey)
512 if (event->what == keyDown)
513 DoMenuCommand( p_intf, MenuKey(key));
515 case activateEvt: /* if you needed to do something special */
519 DrawWindow((WindowRef) event->message);
522 case kHighLevelEvent:
523 AEProcessAppleEvent( event );
531 //the code for playorpause and stop taken almost directly from the BeOS code
532 void playorpause ( intf_thread_t *p_intf )
536 // pause the playback
537 if (p_intf->p_input != NULL )
539 // mute the volume if currently playing
540 if (p_intf->p_sys->playback_status == PLAYING)
542 vlc_mutex_lock( &p_aout_bank->lock );
543 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
545 p_aout_bank->pp_aout[i_index]->i_savedvolume =
546 p_aout_bank->pp_aout[i_index]->i_volume;
547 p_aout_bank->pp_aout[i_index]->i_volume = 0;
549 vlc_mutex_unlock( &p_aout_bank->lock );
550 p_intf->p_sys->playback_status = PAUSED;
551 SetMenuItemText( GetMenuHandle(kMenuControls), kControlsPlayORPause, "\pPlay");
554 // restore the volume
556 vlc_mutex_lock( &p_aout_bank->lock );
557 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
559 p_aout_bank->pp_aout[i_index]->i_volume =
560 p_aout_bank->pp_aout[i_index]->i_savedvolume;
561 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
563 vlc_mutex_unlock( &p_aout_bank->lock );
564 p_intf->p_sys->playback_status = PLAYING;
565 SetMenuItemText( GetMenuHandle(kMenuControls), kControlsPlayORPause, "\pPause");
568 input_SetStatus(p_intf->p_input, INPUT_STATUS_PAUSE);
572 void stop ( intf_thread_t *p_intf )
576 // this currently stops playback not nicely
577 if( p_intf->p_input != NULL )
579 // silence the sound, otherwise very horrible
580 vlc_mutex_lock( &p_aout_bank->lock );
581 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
583 p_aout_bank->pp_aout[i_index]->i_savedvolume = p_aout_bank->pp_aout[i_index]->i_volume;
584 p_aout_bank->pp_aout[i_index]->i_volume = 0;
586 vlc_mutex_unlock( &p_aout_bank->lock );
589 input_SetStatus( p_intf->p_input, INPUT_STATUS_END );
591 p_intf->p_sys->playback_status = STOPPED;
595 void DoMenuCommand( intf_thread_t *p_intf , long menuResult)
597 short menuID; /* the resource ID of the selected menu */
598 short menuItem; /* the item number of the selected menu */
600 vout_thread_t *p_vout;
602 menuID = HiWord(menuResult); /* use macros to get item & menu number */
603 menuItem = LoWord(menuResult);
611 ShowWindow( p_intf->p_sys->p_aboutWindow );
612 SelectWindow( p_intf->p_sys->p_aboutWindow );
613 DrawAboutWindow( p_intf->p_sys->p_aboutWindow); //kludge
614 EnableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
618 p_intf->b_die = true;
619 //hrmm... don't know what is going on w/ the Quit item in the new application menu...documentation???
631 vlc_mutex_lock( &p_vout_bank->lock );
632 /* XXX: only test the first video output */
633 if( p_vout_bank->i_count )
635 p_vout = p_vout_bank->pp_vout[0];
636 ShowWindow( p_vout->p_sys->p_window );
637 SelectWindow( p_vout->p_sys->p_window );
639 vlc_mutex_unlock( &p_vout_bank->lock );
640 DisableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
641 EnableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
642 //hmm, can't say to play() right now because I don't know if a file is in playlist yet.
643 //need to see if I can tell this or eve if calling play() w/o a file is bad...not sure of either
647 playorpause( p_intf );
649 // starts playing automatically on open? playorpause( p_intf );
653 HideWindow( FrontWindow() );
655 vlc_mutex_lock( &p_vout_bank->lock );
656 /* XXX: only test the first video output */
657 if( p_vout_bank->i_count )
659 p_vout = p_vout_bank->pp_vout[0];
663 vlc_mutex_unlock( &p_vout_bank->lock );
665 if ( ! IsWindowVisible( p_vout->p_sys->p_window ) && ! IsWindowVisible( p_intf->p_sys->p_aboutWindow ) )
667 //calling this even if no file open shouldn't be bad... not sure of opposite situation above
669 EnableMenuItem( GetMenuHandle(kMenuFile), kFileNew);
670 DisableMenuItem( GetMenuHandle(kMenuFile), kFileClose);
676 p_intf->b_die = true;
687 case kControlsPlayORPause:
688 playorpause( p_intf );
695 case kControlsForward:
696 // cycle the fast playback modes
697 if (p_intf->p_input != NULL )
699 vlc_mutex_lock( &p_aout_bank->lock );
700 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
702 p_aout_bank->pp_aout[i_index]->i_savedvolume =
703 p_aout_bank->pp_aout[i_index]->i_volume;
704 p_aout_bank->pp_aout[i_index]->i_volume = 0;
706 vlc_mutex_unlock( &p_aout_bank->lock );
708 input_SetStatus(p_intf->p_input, INPUT_STATUS_FASTER);
712 case kControlsRewind:
713 // cycle the slow playback modes
714 if (p_intf->p_input != NULL )
716 vlc_mutex_lock( &p_aout_bank->lock );
717 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
719 p_aout_bank->pp_aout[i_index]->i_savedvolume =
720 p_aout_bank->pp_aout[i_index]->i_volume;
721 p_aout_bank->pp_aout[i_index]->i_volume = 0;
723 vlc_mutex_unlock( &p_aout_bank->lock );
725 input_SetStatus(p_intf->p_input, INPUT_STATUS_FASTER);
729 case kControlsChapterNext:
730 if( p_intf->p_input != NULL )
732 /* FIXME: temporary hack */
733 p_intf->p_input->b_eof = 1;
737 case kControlsChapterPrevious:
738 if( p_intf->p_input != NULL )
740 /* FIXME: temporary hack */
741 intf_PlaylistPrev( p_main->p_playlist );
742 intf_PlaylistPrev( p_main->p_playlist );
743 p_intf->p_input->b_eof = 1;
747 case kControlsDVDMenu:
752 case kControlsVolumeUp:
754 vlc_mutex_lock( &p_aout_bank->lock );
755 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
757 // ++p_aout_bank->pp_aout[i_index]->i_volume;
758 p_aout_bank->pp_aout[i_index]->i_savedvolume = ++p_aout_bank->pp_aout[i_index]->i_volume;
760 vlc_mutex_unlock( &p_aout_bank->lock );
763 case kControlsVolumeDown:
765 vlc_mutex_lock( &p_aout_bank->lock );
766 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
768 // --p_aout_bank->pp_aout[i_index]->i_volume;
769 p_aout_bank->pp_aout[i_index]->i_savedvolume = --p_aout_bank->pp_aout[i_index]->i_volume;
771 vlc_mutex_unlock( &p_aout_bank->lock );
774 case kControlsVolumeMute:
776 vlc_mutex_lock( &p_aout_bank->lock );
777 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
779 if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
781 p_aout_bank->pp_aout[i_index]->i_volume =
782 p_aout_bank->pp_aout[i_index]->i_savedvolume;
783 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
787 p_aout_bank->pp_aout[i_index]->i_savedvolume =
788 p_aout_bank->pp_aout[i_index]->i_volume;
789 p_aout_bank->pp_aout[i_index]->i_volume = 0;
792 vlc_mutex_unlock( &p_aout_bank->lock );
808 HiliteMenu(0); /* unhighlight what MenuSelect (or MenuKey) hilited */
811 void DrawWindow(WindowRef window)
814 GrafPtr previousPort;
816 GetPort(&previousPort);
817 SetPort(GetWindowPort(window));
819 EraseRect(GetWindowPortBounds(window, &tempRect));
820 DrawControls(window);
821 DrawGrowIcon(window);
823 SetPort(previousPort);
826 void DrawAboutWindow(WindowRef window)
828 GrafPtr previousPort;
830 GetPort(&previousPort);
831 SetPort(GetWindowPort(window));
834 DrawString("\phttp://www.videolan.org");
836 SetPort(previousPort);
841 static pascal OSStatus MyEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData)
846 HICommand commandStruct;
849 OSStatus result = eventNotHandledErr; // report failure by default
851 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(window), NULL, &window);
853 whatHappened = GetEventKind(event);
855 switch (whatHappened)
857 case kEventWindowActivated:
860 case kEventWindowDeactivated:
863 case kEventWindowDrawContent:
868 case kEventWindowBoundsChanged:
869 InvalWindowRect(window, GetWindowPortBounds(window, &bounds));
874 case kEventWindowClickContentRgn:
875 /*DoContentClick(window);
881 case kEventCommandProcess:
882 GetEventParameter (event, kEventParamDirectObject,
883 typeHICommand, NULL, sizeof(HICommand),
884 NULL, &commandStruct);
885 theMenuRef = commandStruct.menu.menuRef;
887 if (theMenuRef == GetMenuHandle(kMenuApple))
889 // Because the event didn't occur *in* the window, the
890 // window reference isn't valid until we set it here
891 window = FrontWindow();
893 theMenuItem = commandStruct.menu.menuItemIndex;
894 switch ( theMenuItem )
897 SetLight(window, true);
900 SetLight(window, false);
910 case kEventMouseMoved:
912 CursorRgn = NewRgn();
913 GetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
914 NULL, sizeof(Point), NULL, &wheresMyMouse);
915 AdjustCursor(wheresMyMouse, CursorRgn);
916 DisposeRgn(CursorRgn);
922 // If nobody handled the event, it gets propagated to the
923 // application-level handler.
930 //FIXME Adding this has introduced or surfaced a lot of bugs...
931 //comented out a lot of things to strip this down to make this a 'quicky'
932 OSErr MyOpenDocument(const FSSpecPtr defaultLocationfssPtr)
934 NavDialogOptions dialogOptions;
935 // AEDesc defaultLocation;
936 // NavEventUPP eventProc = NewNavEventProc(myEventProc);
937 // NavObjectFilterUPP filterProc =
938 // NewNavObjectFilterProc(myFilterProc);
941 // Specify default options for dialog box
942 anErr = NavGetDefaultDialogOptions(&dialogOptions);
945 // Adjust the options to fit our needs
946 // Set default location option
947 // dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
948 // Clear preview option
949 dialogOptions.dialogOptionFlags ^= kNavAllowPreviews;
951 // make descriptor for default location
952 // anErr = AECreateDesc(typeFSS, defaultLocationfssPtr,
953 // sizeof(*defaultLocationfssPtr),
954 // &defaultLocation );
957 // Get 'open' resource. A nil handle being returned is OK,
958 // this simply means no automatic file filtering.
959 NavTypeListHandle typeList = (NavTypeListHandle)GetResource(
961 NavReplyRecord reply;
963 // Call NavGetFile() with specified options and
964 // declare our app-defined functions and type list
965 // anErr = NavGetFile (&defaultLocation, &reply, &dialogOptions,
966 anErr = NavGetFile (nil, &reply, &dialogOptions,
967 // eventProc, nil, filterProc,
970 if (anErr == noErr && reply.validRecord)
972 // Deal with multiple file selection
975 anErr = AECountItems(&(reply.selection), &count);
976 // Set up index for file list
981 for (index = 1; index <= count; index++)
983 AEKeyword theKeyword;
986 FSSpec documentFSSpec;
988 // Get a pointer to selected file
989 anErr = AEGetNthPtr(&(reply.selection), index,
990 typeFSS, &theKeyword,
991 &actualType,&documentFSSpec,
992 sizeof(documentFSSpec),
996 // anErr = DoOpenFile(&documentFSSpec);
999 char path[MAXPATHLEN];
1001 //make an FSRef out of an FSSpec
1002 anErr = FSpMakeFSRef( &documentFSSpec, &newRef);
1007 //make a path out of the FSRef
1008 anErr = FSRefMakePath( &newRef, path, MAXPATHLEN);
1014 //else, ok...add it to playlist!
1015 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, path );
1021 // Dispose of NavReplyRecord, resources, descriptors
1022 anErr = NavDisposeReply(&reply);
1024 if (typeList != NULL)
1026 ReleaseResource( (Handle)typeList);
1028 //(void) AEDisposeDesc(&defaultLocation);
1031 // DisposeRoutineDescriptor(eventProc);
1032 // DisposeRoutineDescriptor(filterProc);