Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
main.c
/* |
* File: main.c of QTCarbonShell |
* |
* Contains: A skeleton of a modern nib-based and Carbon Events-based QuickTime player application. |
* |
* Version: 1.1.1 |
* |
* Created: 05/10/2009 |
* |
* Copyright: Copyright © 2005-2009 Apple Inc., All Rights Reserved |
* |
* Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in |
* consideration of your agreement to the following terms, and your use, installation, modification |
* or redistribution of this Apple software constitutes acceptance of these terms. If you do |
* not agree with these terms, please do not use, install, modify or redistribute this Apple |
* software. |
* |
* In consideration of your agreement to abide by the following terms, and subject to these terms, |
* Apple grants you a personal, non-exclusive license, under Apple's copyrights in this |
* original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the |
* Apple Software, with or without modifications, in source and/or binary forms; provided that if you |
* redistribute the Apple Software in its entirety and without modifications, you must retain this |
* notice and the following text and disclaimers in all such redistributions of the Apple Software. |
* Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to |
* endorse or promote products derived from the Apple Software without specific prior written |
* permission from Apple. Except as expressly stated in this notice, no other rights or |
* licenses, express or implied, are granted by Apple herein, including but not limited to any |
* patent rights that may be infringed by your derivative works or by other works in which the |
* Apple Software may be incorporated. |
* |
* The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR |
* IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY |
* AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE |
* OR IN COMBINATION WITH YOUR PRODUCTS. |
* |
* IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, |
* REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER |
* UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN |
* IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* <3> 03/14/09 dts minor editorial corrections |
* <2> 07/12/05 dts universal binary updates |
* <1> 05/10/05 dts initial release |
*/ |
//**************************************************** |
#pragma mark * complation directives * |
//**************************************************** |
#pragma mark - |
#pragma mark * includes & imports * |
#include <Carbon/Carbon.h> |
#include <QuickTime/QuickTime.h> |
#include <sys/sysctl.h> // for Get_AltiVecTypeAvailable |
#include "main.h" |
//**************************************************** |
#pragma mark - |
#pragma mark * typedef's, struct's, enums, defines, etc. * |
#if DEBUG_ASSERT_PRODUCTION_CODE |
#define require_orelse_continue(assertion) \ |
{ \ |
if ( !(assertion) ) \ |
continue; \ |
} |
#else |
#define require_orelse_continue(assertion) \ |
{ \ |
if ( !(assertion) ) \ |
{ \ |
DEBUG_ASSERT_MESSAGE( \ |
DEBUG_ASSERT_COMPONENT_NAME_STRING, \ |
#assertion, \ |
0, \ |
0, \ |
__FILE__, \ |
__LINE__, \ |
0); \ |
continue; \ |
} \ |
} |
#endif |
#define kOpenFolderContentsPref CFSTR("Open Folder Contents?") |
#define kOpenFolderRecursivePref CFSTR("Open Folder Recursive?") |
#define kRememberLastPref CFSTR("Remember Last?") |
#define kRememberBoundsPref CFSTR("Remember Bounds?") |
#define kOpenWindowsPref CFSTR("Open Windows") |
#define kOpenWindowAlisKey CFSTR("alis") |
#define kOpenWindowBoundsKey CFSTR("bounds") |
#define kDistanceFromHorizontalEdge 20 |
#define kDistanceFromVerticalEdge 40 |
#define kComboBoxMaxHistory 10 |
// URL window's edit text contol ID |
const ControlID kEditTextViewCID = {'ETXT', 100}; |
// Preferences window's checkboxes' IDs |
const HIViewID kRememberLastHID = {'RLST', 100}; |
const HIViewID kRememberBoundsHID = {'RPOS', 100}; |
const HIViewID kOpenFoldersHID = {'OFLD', 100}; |
const HIViewID kOpenRecursiveHID = {'OFRC', 100}; |
// Do menu command IDs |
enum { |
kHICommandLoop = 'LOOP', |
kHICommandPalindrome = 'PLUP', |
kHICommandFullScreen = 'FScr', |
kQTCarbonShellHICommandDoThis = 'This', |
kQTCarbonShellHICommandDoThat = 'That' |
}; |
// File menu command ID's |
enum { |
kHICommandOpenURL = 'ourl' |
}; |
// Dock menu command ID's |
enum { |
kHICommandPlayMovie = 'PLAY', |
kHICommandStopMovie = 'STOP', |
kHICommandRewindMovie = 'RWND', |
kHICommandQTWebPage = 'QWEB' |
}; |
enum StreamPrerollState { |
kStreamingPrerollStateStarted, |
kStreamingPrerollInProgress, |
kStreamingPrerollDone |
}; |
// window data |
typedef struct { |
WindowRef fWindow; |
UInt8 fWindowTitleBarSlop; |
Boolean fClosing; |
Movie fMovie; |
ControlRef fMovieControl; |
MovieController fMovieController; |
CGrafPtr fDockTileContext; |
MatrixRecord fSavedMovieMatrix; |
Boolean fPlayingInDockTile; |
Handle fDataRef; |
OSType fDataRefType; |
UInt32 fMovieLoadState; |
MouseTrackingRef fMouseTrackingRef; |
Boolean fControlChangingBounds; |
enum StreamPrerollState fStreamingPrerollState; |
Boolean fIsVRMovie; |
EventLoopTimerRef fAsyncLoadingTimer; |
// full screen |
WindowRef fFSWindow; |
Ptr fFSRestoreState; |
EventHandlerRef fFSEventHandlerRef; |
} WindowDataRec, * WindowDataPtr; |
//**************************************************** |
#pragma mark - |
#pragma mark * local (static) function prototypes * |
static pascal OSErr Handle_OpenApplication(const AppleEvent *inAppleEvent, AppleEvent *outAppleEvent, long inHandlerRefcon); |
static pascal OSErr Handle_ReopenApplication(const AppleEvent *inAppleEvent, AppleEvent *outAppleEvent, long inHandlerRefcon); |
static pascal OSErr Handle_OpenDocuments(const AppleEvent *inAppleEvent, AppleEvent *outAppleEvent, long inHandlerRefcon); |
static pascal OSErr Handle_PrintDocuments(const AppleEvent *inAppleEvent, AppleEvent *outAppleEvent, long inHandlerRefcon); |
static void Install_AppleEventHandlers(void); |
static pascal OSStatus Handle_CommandUpdateStatus(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_CommandProcess(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_PrefCommandProcess(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_PrefWindowIsAboutToClose(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_WindowActivatedDeactivated(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_WindowBoundsChanges(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_WindowGetMinMaxIdealSize(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_WindowIsAboutToClose(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_WindowIsClosing(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_URLWindowEvents(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_AppActivateDeactivate(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_MouseExitedEvent(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static pascal OSStatus Handle_FullScreenWindow(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); |
static OSStatus Do_CreateMovieControl(WindowRef inWindowRef, Boolean inMovieControlOptionEnableEditing); |
static pascal Boolean ActionNotificationCallback(MovieController inMC, short inAction, void *params, UInt32 inFlags, UInt32 *outFlags, void *inRefCon); |
static pascal OSStatus Handle_ParentMovieControlWindowEvent(EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData); |
static pascal OSStatus Handle_MovieControlDisposeEvent(EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData); |
static pascal void Timer_AsyncMovieLoading(EventLoopTimerRef inTimer, void *inUserData); |
static void Do_Preferences(void); |
static OSStatus Do_URLWindow(void); |
static OSStatus Do_NewWindow(WindowRef *outWindow); |
static OSStatus Do_BeginFullScreenWindow(WindowRef inWindowRef); |
static pascal Boolean Handle_NavFilter(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode); |
static pascal void Handle_NavEventCallback(NavEventCallbackMessage callbackSelector, NavCBRecPtr callbackParms, NavCallBackUserData callbackUD); |
static OSStatus Do_OpenAWindow(const FSRef *inFSRef, const CFStringRef inURL, const Rect *inBounds); |
static OSStatus Do_OpenWindows(void); |
static OSStatus Do_OpenDocs(AEDescList inDocumentsList); |
static OSStatus Do_Save(WindowRef inWindow); |
static OSStatus Do_SaveAs(WindowRef inWindow); |
static OSStatus Do_CleanUp(void); |
static void AddTo_LastWindows(WindowRef inWindow); |
static void Open_LastWindows(void); |
static void Test_AreWeFinished(void); |
static void Append_FolderItemsToAEDescList(const FSRef* inFSRef, AEDescList inDocumentsList); |
static OSErr FSGetDirectoryItems(const FSRef *inContainerFSRef, FSRef ***outFSRefHandle, ItemCount *outNumRefs, Boolean *outContainerChanged); |
static OSStatus Save_WithFSRefAndWindow(const FSRef* inFSRef, WindowRef inWindow); |
static void Get_Preferences(void); |
static void Set_Preferences(void); |
static void Send_WindowCloseEvent(WindowRef inWindow); |
static void Get_MovieGrowBounds(WindowDataPtr inWdr, HIRect *inOriginalBounds, HIRect *outBestRect); |
static OSStatus Get_WindowPositionFromMovie(Movie inMovie, HIPoint *outPoint); |
static OSType Get_MovieControllerType(Movie inMovie); |
static OSStatus Set_WindowTitleFromMovie(Movie inMovie, WindowRef inWindowRef); |
static void Set_MouseTrackingRegion(WindowRef inWindowRef); |
static Boolean IsStreamedMovie (Movie inMovie); |
static Boolean IsVRMovie(WindowDataPtr wdr); |
static Boolean IsAutoPlayMovie(Movie inMovie); |
static Boolean IsMoviePlaying(MovieController inMC); |
static Boolean IsMovieInteractive(Movie inMovie); |
static Boolean HasAudioTrack(Movie inMovie); |
static void UpdateMovieVolumeSetting(Movie inMovie); |
static OSStatus Display_SaveAsErrorSheet(WindowRef inWindow, OSStatus inError); |
static void Display_StandardAlert(OSStatus inError); |
static void SaveComboBoxValues(HIViewRef inComboBoxView); |
static void RestoreComboBoxValues(HIViewRef inComboBoxView); |
#if __ppc__ |
static int Get_AltiVecTypeAvailable(void); |
static void vFadeDockTile(PixMapHandle inStartPixMap, PixMapHandle inEndPixMap, PixMapHandle inDestPixMap, Rect *inBounds, long inAmount); |
#endif |
static void sFadeDockTile(PixMapHandle inStartPixMap, PixMapHandle inEndPixMap, PixMapHandle inDestPixMap, Rect *inBounds, long inAmount); |
static void Do_This(void); |
static void Do_That(void); |
//**************************************************** |
#pragma mark - |
#pragma mark * exported globals * |
//**************************************************** |
#pragma mark - |
#pragma mark * local (static) globals * |
static Boolean gAutoQuit = false; // if this is true we auto-quit after drag-n-drop (odoc) launch |
static Boolean gIsQuitting = false; |
static FSRef gApplicationBundleFSRef; |
static IBNibRef gIBNibRef; |
static Boolean gOpenFolderContents = true; |
static Boolean gOpenFolderRecursive = false; |
static Boolean gRememberLast = true; |
static Boolean gRememberBounds = true; |
static WindowRef gPreferencesWindow = NULL; |
static CFMutableArrayRef gOpenOnLaunchCFArrayRef = NULL; // the last window(s) info is collected here |
static UInt32 gDocumentCount = 1; |
static SInt32 gSystemVersion; |
// function pointer to either v or s FadeDockTile depending on AltiVec availability |
static void (*FadeDockTile)(PixMapHandle inStartPixMap, PixMapHandle inEndPixMap, PixMapHandle inDestPixMap, Rect *inBounds, long inAmount) = NULL; |
//**************************************************** |
#pragma mark - |
#pragma mark * exported function implementations * |
/***************************************************** |
* |
* main (argc, argv) |
* |
* Purpose: main program entry point |
* |
* Notes: You might want to change this to something more verbose |
* |
* Inputs: argc - the number of elements in the argv array |
* argv - an array of pointers to the parameters to this application |
* |
* Returns: int - error code (0 == no error) |
*/ |
int main(int argc, char* argv[]) |
{ |
OSStatus status; |
// Can we run this particular demo application? |
status = Gestalt(gestaltSystemVersion, &gSystemVersion); |
Boolean ok = ((noErr == status) && (gSystemVersion >= 0x00001030)); |
if (!ok) |
{ |
DialogRef theAlert; |
CreateStandardAlert(kAlertStopAlert, CFSTR("Mac OS X 10.3 (minimum) is required for this application"), NULL, NULL, &theAlert); |
RunStandardAlert(theAlert, NULL, NULL); |
ExitToShell(); |
} |
EnterMovies(); |
Get_Preferences(); // load user preferences |
ProcessSerialNumber psn = {0, kCurrentProcess}; |
status = GetProcessBundleLocation(&psn, &gApplicationBundleFSRef); |
require_noerr(status, CantGetBundleLocation); |
// Create a Nib reference passing the name of the nib file (without the .nib extension) |
// CreateNibReference only searches into the application bundle. |
status = CreateNibReference(CFSTR("main"), &gIBNibRef); |
require_noerr(status, CantGetNibRef); |
// Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar |
// object. This name is set in InterfaceBuilder when the nib is created. |
status = SetMenuBarFromNib(gIBNibRef, CFSTR("MenuBar")); |
require_noerr(status, CantSetMenuBar); |
// Enabling Preferences menu item |
EnableMenuCommand(NULL, kHICommandPreferences); |
// React to User's commands. |
Install_AppleEventHandlers(); |
EventTypeSpec eventTypeCP[] = {{kEventClassCommand, kEventCommandProcess}}; |
status = InstallEventHandler(GetApplicationEventTarget(), Handle_CommandProcess, GetEventTypeCount(eventTypeCP), eventTypeCP, NULL, NULL); |
require_noerr(status, CantInstallEventHandler); |
EventTypeSpec eventTypeCUS[] = {{kEventClassCommand, kEventCommandUpdateStatus}}; |
status = InstallEventHandler(GetApplicationEventTarget(), Handle_CommandUpdateStatus, GetEventTypeCount(eventTypeCUS), eventTypeCUS, NULL, NULL); |
require_noerr(status, CantInstallEventHandler); |
// **** work around a bug in the Carbon Movie Control **** |
// with a VR and interactive movie the Carbon Movie control will not correctly reset the cursor once it has been changed to a cursor specific to the VR or |
// interactive movie -- we only care about these events when we have a VR controller or an interactive movie and in that case we install a Mouse Tracking Region |
// using the CreateMouseTrackingRegion api |
EventTypeSpec eventTypeMouseExited[] = {{kEventClassMouse, kEventMouseExited}}; |
status = InstallApplicationEventHandler(Handle_MouseExitedEvent, GetEventTypeCount(eventTypeMouseExited), eventTypeMouseExited, NULL, NULL); |
require_noerr(status, CantInstallEventHandler); |
if (gSystemVersion < 0x00001040) { |
// **** work around a bug in the Carbon Movie Control **** |
// when the application is deactivated, the carbon movie control will not draw the control in a deactivated state even though it is deactivated |
// this results in a drawing bug that is noticeable if the movie is being played when the application is deacivated (switched out) |
// because this problem does not happen when the control is deactivated in the process of switching to another window in the same application, |
// we handle it at the application level and specifially send mcAction messages to the front most active control to either invalidate or draw |
// on 10.3.x application window activation/deactivation works fine so we need this event handling at the application level |
// on 10.4 we need do this this all the time so we move this event handling to the window level and don't install it here |
EventTypeSpec eventTypeAppActivateDeactivate[] = {{kEventClassApplication, kEventAppDeactivated}, {kEventClassApplication, kEventAppActivated}}; |
status = InstallApplicationEventHandler(Handle_AppActivateDeactivate, GetEventTypeCount(eventTypeAppActivateDeactivate), eventTypeAppActivateDeactivate, NULL, NULL); |
require_noerr(status, CantInstallEventHandler); |
} |
#if __ppc__ |
// set up the FadeDockTile function pointer |
// depending on the availability of altivec |
if (Get_AltiVecTypeAvailable()) { |
FadeDockTile = &vFadeDockTile; |
} else { |
FadeDockTile = &sFadeDockTile; |
} |
#else |
FadeDockTile = &sFadeDockTile; |
#endif |
// Call the event loop |
RunApplicationEventLoop(); |
CantInstallEventHandler: |
CantSetMenuBar: |
CantGetNibRef: |
CantGetBundleLocation: |
return status; |
} // main |
/*****************************************************/ |
#pragma mark - |
#pragma mark * local (static) function implementations * |
#pragma mark * AppleEvent Handlers * |
/***************************************************** |
* |
* Handle_OpenApplication(inAppleEvent, reply, inHandlerRefcon) |
* |
* Purpose: AppleEvent handler for the kAEOpenApplication event |
* |
* Inputs: inAppleEvent - the Apple event |
* reply - our reply to the Apple event |
* inHandlerRefcon - refcon passed to AEInstallEventHandler when this hander was installed |
* |
* Returns: OSErr - error code (0 == no error) |
*/ |
static pascal OSErr Handle_OpenApplication(const AppleEvent *inAppleEvent, AppleEvent *outAppleEvent, long inHandlerRefcon) |
{ |
gAutoQuit = false; // this is NOT a drag-n-drop launch; disable auto-quit |
if (gRememberLast) |
Open_LastWindows(); |
// if no windows are open then... |
WindowRef theWindow = GetFrontWindowOfClass(kDocumentWindowClass, false); |
if (NULL == theWindow) |
Do_NewWindow(NULL); // create an empty window |
return noErr; |
} // Handle_OpenApplication |
/***************************************************** |
* |
* Handle_ReopenApplication(inAppleEvent, reply, inHandlerRefcon) |
* |
* Purpose: AppleEvent handler for the kAEReopenApplication event |
* |
* Inputs: inAppleEvent - the Apple event |
* reply - our reply to the Apple event |
* inHandlerRefcon - refcon passed to AEInstallEventHandler when this hander was installed |
* |
* Returns: OSErr - error code (0 == no error) |
*/ |
static pascal OSErr Handle_ReopenApplication(const AppleEvent *inAppleEvent, AppleEvent *outAppleEvent, long inHandlerRefcon) |
{ |
// We were already running but with no windows so we create an empty one. |
WindowRef theWindow = GetFrontWindowOfClass(kDocumentWindowClass, true); |
if (NULL == theWindow) |
Do_NewWindow(NULL); |
return noErr; |
} // Handle_ReopenApplication |
/***************************************************** |
* |
* Handle_OpenDocuments(inAppleEvent, reply, inHandlerRefcon) |
* |
* Purpose: AppleEvent handler for the kAEOpenDocuments event |
* |
* Inputs: inAppleEvent - the Apple event |
* reply - our reply to the Apple event |
* inHandlerRefcon - refcon passed to AEInstallEventHandler when this hander was installed |
* |
* Returns: OSErr - error code (0 == no error) |
*/ |
static pascal OSErr Handle_OpenDocuments(const AppleEvent *inAppleEvent, AppleEvent *outAppleEvent, long inHandlerRefcon) |
{ |
AEDescList documentsList; |
OSErr err = AEGetParamDesc(inAppleEvent, keyDirectObject, typeAEList, &documentsList); |
require_noerr(err, CantGetDocList); |
err = Do_OpenDocs(documentsList); |
err = noErr; |
AEDisposeDesc(&documentsList); |
CantGetDocList: |
if (gAutoQuit) |
QuitApplicationEventLoop(); |
return err; |
} // Handle_OpenDocuments |
/***************************************************** |
* |
* Handle_PrintDocuments(inAppleEvent, reply, inHandlerRefcon) |
* |
* Purpose: AppleEvent handler for the kAEPrintDocuments event |
* |
* Inputs: inAppleEvent - the Apple event |
* reply - our reply to the Apple event |
* inHandlerRefcon - refcon passed to AEInstallEventHandler when this hander was installed |
* |
* Returns: OSErr - error code (0 == no error) |
*/ |
static pascal OSErr Handle_PrintDocuments(const AppleEvent *inAppleEvent, AppleEvent *outAppleEvent, long inHandlerRefcon) |
{ |
return errAEEventNotHandled; |
} // Handle_PrintDocuments |
/***************************************************** |
* |
* Install_AppleEventHandlers(void) |
* |
* Purpose: installs the AppleEvent handlers |
* |
* Inputs: none |
* |
* Returns: none |
*/ |
static void Install_AppleEventHandlers(void) |
{ |
OSErr status; |
status = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, Handle_OpenApplication, 0, false); |
require_noerr(status, CantInstallAppleEventHandlerOpenAppl); |
status = AEInstallEventHandler(kCoreEventClass, kAEReopenApplication, Handle_ReopenApplication, 0, false); |
require_noerr(status, CantInstallAppleEventHandlerReOpenAppl); |
status = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, Handle_OpenDocuments, 0, false); |
require_noerr(status, CantInstallAppleEventHandlerOpenDocs); |
status = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, Handle_PrintDocuments, 0, false); |
require_noerr(status, CantInstallAppleEventHandlerPrintDocs); |
// Note: Since RunApplicationEventLoop installs a Quit AE Handler, there is no need to do it here. |
CantInstallAppleEventHandlerOpenAppl: |
CantInstallAppleEventHandlerReOpenAppl: |
CantInstallAppleEventHandlerOpenDocs: |
CantInstallAppleEventHandlerPrintDocs: |
return; |
} // Install_AppleEventHandlers |
#pragma mark - |
#pragma mark * CarbonEvent Handlers * |
/***************************************************** |
* |
* Handle_CommandUpdateStatus(inHandlerCallRef, inEvent, inUserData) |
* |
* Purpose: called to update status of the commands, enabling or disabling the menu items |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (NULL) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_CommandUpdateStatus(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
OSStatus status; |
HICommand aCommand; |
GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &aCommand); |
if (gIsQuitting || GetFrontWindowOfClass(kMovableModalWindowClass, true)) |
{ |
switch (aCommand.commandID) |
{ |
case kHICommandAbout: |
case kHICommandPreferences: |
case kHICommandQuit: |
case kHICommandNew: |
case kHICommandOpen: |
case kHICommandOpenURL: |
case kHICommandClose: |
case kHICommandSave: |
case kHICommandSaveAs: |
case kHICommandLoop: |
case kHICommandPalindrome: |
case kHICommandFullScreen: |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
break; |
} |
} |
else |
{ |
WindowRef aWindowRef = GetFrontWindowOfClass(kDocumentWindowClass, true); |
if (NULL == aWindowRef) |
{ |
switch (aCommand.commandID) |
{ |
case kHICommandAbout: |
case kHICommandPreferences: |
case kHICommandQuit: |
case kHICommandNew: |
case kHICommandOpen: |
case kHICommandOpenURL: |
EnableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
break; |
case kHICommandClose: |
case kHICommandSave: |
case kHICommandSaveAs: |
case kHICommandUndo: |
case kHICommandCut: |
case kHICommandCopy: |
case kHICommandPaste: |
case kHICommandClear: |
case kHICommandSelectAll: |
case kHICommandFullScreen: |
case kHICommandLoop: |
case kHICommandPalindrome: |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
break; |
} |
} |
else |
{ |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
if (NULL == wdr) { |
switch (aCommand.commandID) |
{ |
case kHICommandAbout: |
case kHICommandPreferences: |
case kHICommandQuit: |
case kHICommandClose: |
case kHICommandSave: |
case kHICommandSaveAs: |
case kHICommandUndo: |
case kHICommandCut: |
case kHICommandCopy: |
case kHICommandPaste: |
case kHICommandClear: |
case kHICommandSelectAll: |
case kHICommandFullScreen: |
case kHICommandLoop: |
case kHICommandPalindrome: |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
break; |
} |
} else { |
switch (aCommand.commandID) |
{ |
case kHICommandAbout: |
case kHICommandPreferences: |
case kHICommandQuit: |
{ |
EnableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
break; |
} |
case kHICommandClose: |
{ |
if (wdr->fPlayingInDockTile) { |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} else { |
EnableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} |
break; |
} |
case kHICommandSave: |
{ |
if (IsWindowModified(aWindowRef)) { |
EnableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} else { |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} |
break; |
} |
case kHICommandSaveAs: |
{ |
Boolean needsTimeTable; |
QTMovieNeedsTimeTable(wdr->fMovie, &needsTimeTable); |
if ((!IsStreamedMovie(wdr->fMovie) && false == needsTimeTable) || (IsStreamedMovie(wdr->fMovie) && kStreamingPrerollDone == wdr->fStreamingPrerollState)) { |
EnableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} else { |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} |
break; |
} |
// handle the Do menu items |
case kHICommandLoop: |
case kHICommandPalindrome: |
{ |
if (!wdr->fIsVRMovie && !IsMovieInteractive(wdr->fMovie)) { |
EnableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} else { |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} |
break; |
} |
case kHICommandFullScreen: |
{ |
Rect movieBounds; |
// don't let a sound-only movie or a movie playing inthe dock go full screen |
GetMovieNaturalBoundsRect(wdr->fMovie, &movieBounds); |
if (EmptyRect(&movieBounds) || wdr->fPlayingInDockTile || (IsStreamedMovie(wdr->fMovie) && kStreamingPrerollDone != wdr->fStreamingPrerollState)) { |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} else { |
EnableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} |
break; |
} |
// add more here as needed |
case kQTCarbonShellHICommandDoThis: |
case kQTCarbonShellHICommandDoThat: |
break; |
// handle the dock menu items |
case kHICommandPlayMovie: |
case kHICommandStopMovie: |
case kHICommandRewindMovie: |
{ |
status = GetMenuItemProperty(aCommand.menu.menuRef, 0, FOUR_CHAR_CODE('aDTS'), FOUR_CHAR_CODE('wREF'), sizeof(UInt32), NULL, &aWindowRef); |
if (status) break; |
wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
if (wdr->fIsVRMovie || IsMovieInteractive(wdr->fMovie)) { DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); break; } |
if (kHICommandPlayMovie == aCommand.commandID) { |
if (IsMoviePlaying(wdr->fMovieController)) { |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} else { |
EnableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} |
} else if (kHICommandStopMovie == aCommand.commandID) { |
if (IsMoviePlaying(wdr->fMovieController)) { |
EnableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} else { |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} |
} |
break; |
} |
// the Edit menu is handled automatically by the Carbon Movie Control command handler |
// when enabled -- when editing is not enabled we need to make sure to disable these items ourselves |
case kHICommandUndo: |
case kHICommandCut: |
case kHICommandCopy: |
case kHICommandPaste: |
case kHICommandClear: |
case kHICommandSelectAll: |
{ |
DisableMenuItem(aCommand.menu.menuRef, aCommand.menu.menuItemIndex); |
} |
} |
} |
} |
} |
return eventNotHandledErr; |
} // Handle_CommandUpdateStatus |
/***************************************************** |
* |
* Handle_CommandProcess(inHandlerCallRef, inEvent, inUserData) |
* |
* Purpose: called to process commands from Carbon events |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (NULL) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_CommandProcess(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
HICommandExtended aCommand; |
OSStatus status = eventNotHandledErr; |
GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &aCommand); |
WindowRef aWindowRef = GetFrontWindowOfClass(kDocumentWindowClass, true); |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
// when we're doing fullscreen just eat everything |
if (NULL != wdr && NULL != wdr->fFSWindow) return noErr; |
switch (aCommand.commandID) |
{ |
case kHICommandPreferences: |
Do_Preferences(); |
break; |
case kHICommandNew: |
status = Do_NewWindow(NULL); |
break; |
case kHICommandOpen: |
status = Do_OpenWindows(); |
break; |
case kHICommandOpenURL: |
status = Do_URLWindow(); |
break; |
case kHICommandSave: |
status = Do_Save(NULL); |
break; |
case kHICommandSaveAs: |
status = Do_SaveAs(NULL); |
break; |
case kHICommandQuit: |
status = Do_CleanUp(); |
break; |
// handle the dock menu items |
case kHICommandPlayMovie: |
case kHICommandStopMovie: |
case kHICommandRewindMovie: |
{ |
if (kHICommandFromWindow == aCommand.attributes) { |
wdr = (WindowDataPtr)GetWRefCon(aCommand.source.window); |
if (kHICommandPlayMovie == aCommand.commandID) { |
MCDoAction(wdr->fMovieController, mcActionPrerollAndPlay, (void *)fixed1); |
} else if (kHICommandStopMovie == aCommand.commandID) { |
MCDoAction(wdr->fMovieController, mcActionPlay, (void *)0); |
} else { |
GoToBeginningOfMovie(wdr->fMovie); |
} |
} |
break; |
} |
case kHICommandQTWebPage: |
{ |
CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault,CFSTR("http://developer.apple.com/quicktime/"), NULL); |
LSOpenCFURLRef(url, NULL); |
CFRelease(url); |
break; |
} |
// handle Do menu commands |
case kHICommandLoop: |
{ |
CharParameter mark; |
GetItemMark(aCommand.source.menu.menuRef, aCommand.source.menu.menuItemIndex, &mark); |
if (0 == mark) { |
MCDoAction(wdr->fMovieController, mcActionSetLooping, (void *)true); |
SetItemMark(aCommand.source.menu.menuRef, aCommand.source.menu.menuItemIndex, kMenuCheckmarkGlyph); |
} else { |
MCDoAction(wdr->fMovieController, mcActionSetLooping, (void *)false); |
SetItemMark(aCommand.source.menu.menuRef, aCommand.source.menu.menuItemIndex, 0); |
} |
break; |
} |
case kHICommandPalindrome: |
{ |
CharParameter mark; |
GetItemMark(aCommand.source.menu.menuRef, aCommand.source.menu.menuItemIndex, &mark); |
if (0 == mark) { |
MCDoAction(wdr->fMovieController, mcActionSetLoopIsPalindrome, (void *)true); |
SetItemMark(aCommand.source.menu.menuRef, aCommand.source.menu.menuItemIndex, kMenuCheckmarkGlyph); |
} else { |
MCDoAction(wdr->fMovieController, mcActionSetLoopIsPalindrome, (void *)false); |
SetItemMark(aCommand.source.menu.menuRef, aCommand.source.menu.menuItemIndex, 0); |
} |
break; |
} |
case kHICommandFullScreen: |
Do_BeginFullScreenWindow(aWindowRef); |
break; |
// add more here as needed |
case kQTCarbonShellHICommandDoThis: |
Do_This(); |
break; |
case kQTCarbonShellHICommandDoThat: |
Do_That(); |
break; |
} |
return status; |
} // Handle_CommandProcess |
/***************************************************** |
* |
* Handle_PrefCommandProcess(inHandlerCallRef, inEvent, inUserData) |
* |
* Purpose: called to process commands from the preferences window check boxes |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (NULL) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_PrefCommandProcess(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
OSStatus status = noErr; |
HIViewRef aHIViewRef; |
HICommand aCommand; |
GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &aCommand); |
switch (aCommand.commandID) |
{ |
case 'RLST': |
gRememberLast = !gRememberLast; |
status = HIViewFindByID(HIViewGetRoot(gPreferencesWindow), kRememberBoundsHID, &aHIViewRef); |
if (noErr != status) break; |
if (gRememberLast) EnableControl(aHIViewRef); else DisableControl(aHIViewRef); |
break; |
case 'RPOS': |
gRememberBounds = !gRememberBounds; |
break; |
case 'OFLD': |
gOpenFolderContents = !gOpenFolderContents; |
status = HIViewFindByID(HIViewGetRoot(gPreferencesWindow), kOpenRecursiveHID, &aHIViewRef); |
if (noErr != status) break; |
if (gOpenFolderContents) EnableControl(aHIViewRef); else DisableControl(aHIViewRef); |
break; |
case 'OFRC': |
gOpenFolderRecursive = !gOpenFolderRecursive; |
break; |
default: |
status = eventNotHandledErr; |
break; |
} |
if (noErr == status) Set_Preferences(); |
return status; |
} // Handle_PrefCommandProcess |
/***************************************************** |
* |
* Handle_PrefWindowIsAboutToClose(inHandlerCallRef, inEvent, inUserData) |
* |
* Purpose: called as notification that the preferences window is going to close |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (NULL) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_PrefWindowIsAboutToClose(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
gPreferencesWindow = NULL; |
// by returning eventNotHandledErr, we continue with the normal closing of the window |
return eventNotHandledErr; |
} // Handle_PrefWindowIsAboutToClose |
/***************************************************** |
* |
* Handle_WindowActivatedDeactivated(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
* |
* Purpose: called when a window is being activated and deactivated |
* |
* Note: This Event Handler is only installed on Mac OS X versions 10.4 or greater to work around |
* bugs in the Carbon Movie Control when activating windows within the application |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (the WindowRef) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_WindowActivatedDeactivated(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
WindowRef aWindowRef = (WindowRef)inUserData; |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
UInt32 eventKind = GetEventKind(inEvent); |
require(NULL != wdr, CantGetWindowData); |
// **** work around a bug in the Carbon Movie Control **** |
switch(eventKind) { |
case kEventWindowDeactivated: { |
// specifically dispatch a mcActionSuspend event directly to the movie |
// controller where we invalidate the control thereby |
// causing it to do what we want and draw in its deactive state |
MCDoAction(wdr->fMovieController, mcActionSuspend, (void *)0); |
break; |
} |
case kEventWindowActivated: { |
// turn around and specifically dispatch mcActionResume and mcActionActivate |
// events directly to the movie controller -- we force a call to draw |
// in mcActionResume to draw the control its active state -- but without |
// mcActionActivate sent first this won't work so you need both |
MCActivate(wdr->fMovieController, aWindowRef, true); |
MCDoAction(wdr->fMovieController, mcActionResume, (void *)0); |
break; |
} |
default: |
break; |
} |
CantGetWindowData: |
// by returning eventNotHandledErr, we continue with the normal handling of these events |
return eventNotHandledErr; |
} // Handle_WindowActivatedDeactivated |
/***************************************************** |
* |
* Handle_WindowBoundsChanging(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
* |
* Purpose: called when a window is being resized |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (the WindowRef) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_WindowBoundsChanges(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
WindowRef aWindowRef = (WindowRef)inUserData; |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
UInt32 eventKind = GetEventKind(inEvent); |
UInt32 attributes; |
OSStatus status = eventNotHandledErr; |
require(NULL != wdr, CantGetData); |
switch(eventKind) { |
case kEventWindowBoundsChanging: |
{ |
GetEventParameter(inEvent, kEventParamAttributes, typeUInt32, NULL, sizeof(UInt32), NULL, &attributes); |
if (attributes & kWindowBoundsChangeUserResize) { |
HIRect originalBounds, bestRect; |
GetEventParameter(inEvent, kEventParamCurrentBounds, typeHIRect, NULL, sizeof(HIRect), NULL, &originalBounds); |
Get_MovieGrowBounds(wdr, &originalBounds, &bestRect); |
SetEventParameter(inEvent, kEventParamCurrentBounds, typeHIRect, sizeof(HIRect), &bestRect); |
status = noErr; |
} |
break; |
} |
case kEventWindowBoundsChanged: |
{ |
CallNextEventHandler(inHandlerCallRef, inEvent); |
GetEventParameter(inEvent, kEventParamAttributes, typeUInt32, NULL, sizeof(UInt32), NULL, &attributes); |
if (attributes & kWindowBoundsChangeUserDrag) { |
// align the window after we've done everything else |
AlignWindow(aWindowRef, false, NULL, NULL); |
} |
// **** work around a bug in the Carbon Movie Control **** |
// see Handle_MouseExitedEvent |
if ((attributes & kWindowBoundsChangeSizeChanged) && (wdr->fIsVRMovie || IsMovieInteractive(wdr->fMovie))) { |
Set_MouseTrackingRegion(aWindowRef); |
} |
status = noErr; |
break; |
} |
default: |
break; |
} |
CantGetData: |
return status; |
} // Handle_WindowBoundsChanging |
/***************************************************** |
* |
* Handle_WindowGetMinMaxIdealSize(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
* |
* Purpose: called when a window is being resized to figure out min, max, and ideal window size |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (the WindowRef) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_WindowGetMinMaxIdealSize(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
WindowRef aWindowRef = (WindowRef)inUserData; |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
UInt32 eventKind = GetEventKind(inEvent); |
Rect movieNaturalBounds; |
HIPoint dimensions; |
OSStatus status = eventNotHandledErr; |
require(NULL != wdr, CantGetData); |
GetMovieNaturalBoundsRect(wdr->fMovie, &movieNaturalBounds); |
// make sure that the movie has a non-zero |
// width and a minimum height of 16 |
if (movieNaturalBounds.right - movieNaturalBounds.left == 0) { |
MacSetRect(&movieNaturalBounds, 0, 0, 320, 16); |
} |
MacOffsetRect(&movieNaturalBounds, -movieNaturalBounds.left, -movieNaturalBounds.top); |
switch (eventKind) { |
case kEventWindowGetMinimumSize: { |
float movieHalfSizeWidth = movieNaturalBounds.right / 2; |
float movieHalfSizeHeight = movieNaturalBounds.bottom / 2; |
if (movieHalfSizeHeight < 16) { movieHalfSizeHeight = 16; }; |
// min window size adding our slop |
dimensions.x = movieHalfSizeWidth + kDistanceFromHorizontalEdge; |
dimensions.y = movieHalfSizeHeight + kDistanceFromVerticalEdge; |
SetEventParameter(inEvent, kEventParamDimensions, typeHIPoint, sizeof(HIPoint), &dimensions); |
status = noErr; |
break; |
} |
case kEventWindowGetMaximumSize: { |
float movieDoubleSizeWidth = movieNaturalBounds.right * 2; |
float movieDoubleSizeHeight = movieNaturalBounds.bottom * 2; |
if (movieDoubleSizeHeight == 32) { movieDoubleSizeHeight = 16; }; |
// max window size adding our slop |
dimensions.x = movieDoubleSizeWidth + kDistanceFromHorizontalEdge; |
dimensions.y = movieDoubleSizeHeight + kDistanceFromVerticalEdge; |
SetEventParameter(inEvent, kEventParamDimensions, typeHIPoint, sizeof(HIPoint), &dimensions); |
status = noErr; |
break; |
} |
case kEventWindowGetIdealSize: { |
// natural window size adding our slop |
dimensions.x = movieNaturalBounds.right + kDistanceFromHorizontalEdge; |
dimensions.y = movieNaturalBounds.bottom + kDistanceFromVerticalEdge; |
SetEventParameter(inEvent, kEventParamDimensions, typeHIPoint, sizeof(HIPoint), &dimensions); |
status = noErr; |
break; |
} |
default: |
break; |
} |
CantGetData: |
return status; |
} // Handle_WindowGetMinMaxIdealSize |
/***************************************************** |
* |
* Handle_WindowIsAboutToClose(inHandlerCallRef, inEvent, inUserData) |
* |
* Purpose: called as notification that a window is going to close |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (the WindowRef) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_WindowIsAboutToClose(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
WindowRef aWindowRef = (WindowRef) inUserData; |
WindowDataPtr wdr = (WindowDataPtr) GetWRefCon(aWindowRef); |
NavDialogRef theDialog = NULL; |
OSStatus status = noErr; |
require(NULL != wdr, CantGetData); |
if (IsWindowModified(aWindowRef)) { |
wdr->fClosing = true; |
NavDialogCreationOptions navOptions; |
status = NavGetDefaultDialogCreationOptions(&navOptions); |
require_noerr(status, CantGetDefaultOptions); |
navOptions.preferenceKey = 3; |
navOptions.modality = kWindowModalityWindowModal; |
navOptions.parentWindow = aWindowRef; |
status = NavCreateAskSaveChangesDialog(&navOptions, kNavSaveChangesClosingDocument, Handle_NavEventCallback, inUserData, &theDialog); |
require_noerr(status, CantCreateDialog); |
status = NavDialogRun(theDialog); |
require_noerr(status, CantRunDialog); |
// by returning noErr, we cancel the closing of the window so that the user has a chance to save it |
return noErr; |
} else { |
TransitionWindow(aWindowRef, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL); |
} |
// by returning eventNotHandledErr, we continue with the normal closing of the window |
return eventNotHandledErr; |
CantRunDialog: |
if (NULL != theDialog) |
NavDialogDispose(theDialog); |
CantCreateDialog: |
CantGetDefaultOptions: |
CantGetData: |
return status; |
} // Handle_WindowIsAboutToClose |
/***************************************************** |
* |
* Handle_WindowIsClosing(inHandlerCallRef, inEvent, inUserData) |
* |
* Purpose: called as notification that a window is being destroyed |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (the WindowRef) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_WindowIsClosing(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
WindowRef aWindowRef = (WindowRef) inUserData; |
WindowDataPtr wdr = (WindowDataPtr) GetWRefCon(aWindowRef); |
require(NULL != wdr, CantGetData); |
if (NULL != wdr->fDataRef) { |
DisposeHandle(wdr->fDataRef); |
} |
if (NULL != wdr->fMouseTrackingRef) { |
ReleaseMouseTrackingRegion(wdr->fMouseTrackingRef); |
} |
free(wdr); |
CantGetData: |
return eventNotHandledErr; |
} // Handle_WindowIsClosing |
/***************************************************** |
* |
* Handle_WindowDockTile(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
* |
* Purpose: called when a window is being shrunk to and restored from the dock |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (the WindowRef) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_WindowDockTile(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
WindowRef aWindowRef = (WindowRef)inUserData; |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
UInt32 eventKind = GetEventKind(inEvent); |
require(NULL != wdr, CantGetData); |
switch (eventKind) { |
case kEventWindowCollapse: |
{ |
if (wdr->fPlayingInDockTile == false) { |
Rect movieBounds; |
// don't try to draw a sound-only movie in the dock |
GetMovieNaturalBoundsRect(wdr->fMovie, &movieBounds); |
if (EmptyRect(&movieBounds)) goto DontPlayInDockTile; |
if (wdr->fIsVRMovie || IsMovieInteractive(wdr->fMovie)) { |
ReleaseMouseTrackingRegion(wdr->fMouseTrackingRef); |
wdr->fMouseTrackingRef = NULL; |
goto DontPlayInDockTile; |
} |
wdr->fPlayingInDockTile = true; |
} |
break; |
} |
case kEventWindowCollapsed: |
{ |
CGrafPtr savePort; |
GDHandle saveGDH; |
MenuRef dockMenuRef; |
GWorldPtr startTileGWorld, endTileGWorld; |
ImageDescriptionHandle desc; |
Rect dockTileBounds, movieInDockTileBounds; |
HIRect bestRect, originalDockTileBounds; |
RgnHandle dockTileBoundsRgn; |
MatrixRecord movieInDockTileMatrix; |
Rect movieBounds; |
UInt32 currentTime, endTime; |
OSStatus status; |
if (wdr->fPlayingInDockTile == false) goto JustAddWindowMenu; |
// after we collapse to the dock prepare to start movie playback |
// in the dock -- a fade from the application dock tile to a movie |
// frame is also performed to make the transition look cool |
// create a QD context |
// CreateQDContextForCollapsedWindowDockTile calls CreateNewPort so save our port |
GetGWorld(&savePort, &saveGDH); |
status = CreateQDContextForCollapsedWindowDockTile(wdr->fWindow, &wdr->fDockTileContext); |
require_noerr(status, JustAddWindowMenu); |
SetGWorld(savePort, saveGDH); |
// set the movie matrix so the movie looks correct when drawn in the dock |
GetMovieMatrix(wdr->fMovie, &wdr->fSavedMovieMatrix); |
GetPortBounds(wdr->fDockTileContext, &dockTileBounds); |
originalDockTileBounds = CGRectMake(0, 0, dockTileBounds.right, dockTileBounds.bottom); |
Get_MovieGrowBounds(wdr, &originalDockTileBounds, &bestRect); |
MacSetRect(&movieInDockTileBounds, 0, 0, bestRect.size.width, bestRect.size.height); |
movieInDockTileBounds.top = (((dockTileBounds.bottom - dockTileBounds.top) - bestRect.size.height) / 2); |
movieInDockTileBounds.left = ((dockTileBounds.right - dockTileBounds.left) - bestRect.size.width) / 2; |
movieInDockTileBounds.right = movieInDockTileBounds.left + bestRect.size.width; |
movieInDockTileBounds.bottom = movieInDockTileBounds.top + bestRect.size.height; |
SetIdentityMatrix(&movieInDockTileMatrix); |
GetMovieNaturalBoundsRect(wdr->fMovie, &movieBounds); |
MapMatrix(&movieInDockTileMatrix, &movieBounds, &movieInDockTileBounds); |
SetMovieMatrix(wdr->fMovie, &movieInDockTileMatrix); |
dockTileBoundsRgn = NewRgn(); |
RectRgn(dockTileBoundsRgn, &dockTileBounds); |
// create GWords for start and end tile images, note the kNativeEndianPixMap flag |
// this ensures the tile fade code works correctly on Intel-based Macintoshes |
QTNewGWorld(&startTileGWorld, k32ARGBPixelFormat, &dockTileBounds, NULL, NULL, kNativeEndianPixMap); |
QTNewGWorld(&endTileGWorld, k32ARGBPixelFormat, &dockTileBounds, NULL, NULL, kNativeEndianPixMap); |
LockPixels(GetGWorldPixMap(startTileGWorld)); |
LockPixels(GetGWorldPixMap(endTileGWorld)); |
// copy the original dock tile as the start image for the fade |
SetGWorld(startTileGWorld, NULL); |
LockPortBits(wdr->fDockTileContext); |
LockPixels(GetGWorldPixMap(wdr->fDockTileContext)); |
MakeImageDescriptionForPixMap(GetGWorldPixMap(wdr->fDockTileContext), &desc); |
DecompressImage(GetPixBaseAddr(GetGWorldPixMap(wdr->fDockTileContext)), desc, GetGWorldPixMap(startTileGWorld), |
&dockTileBounds, &dockTileBounds, srcCopy, NULL); |
UnlockPixels(GetGWorldPixMap(wdr->fDockTileContext)); |
UnlockPortBits(wdr->fDockTileContext); |
DisposeHandle((Handle)desc); |
// copy a movie frame for the end image for the fade |
SetGWorld(endTileGWorld, NULL); |
SetMovieGWorld(wdr->fMovie, endTileGWorld, NULL); |
MoviesTask(wdr->fMovie, 0); |
// now do the cool fade using either the scalar or altivec(shout-out to geowar) function |
SetGWorld(wdr->fDockTileContext, NULL); |
MCSetControllerPort(wdr->fMovieController, wdr->fDockTileContext); |
MCSetVisible(wdr->fMovieController, false); |
endTime = TickCount() + 30; |
LockPortBits(wdr->fDockTileContext); |
LockPixels(GetGWorldPixMap(wdr->fDockTileContext)); |
while((currentTime = TickCount()) < endTime ) { |
UInt32 amount = (endTime - currentTime) * 0x0100 / 30; |
(*FadeDockTile)(GetGWorldPixMap(startTileGWorld), GetGWorldPixMap(endTileGWorld), GetGWorldPixMap(wdr->fDockTileContext), &dockTileBounds, amount); |
QDFlushPortBuffer(wdr->fDockTileContext, dockTileBoundsRgn); |
} |
UnlockPixels(GetGWorldPixMap(wdr->fDockTileContext)); |
UnlockPortBits(wdr->fDockTileContext); |
DisposeGWorld(startTileGWorld); |
DisposeGWorld(endTileGWorld); |
DisposeRgn(dockTileBoundsRgn); |
JustAddWindowMenu: |
// add our custom window dock menu |
CreateMenuFromNib(gIBNibRef, CFSTR("DockMenu"), &dockMenuRef); |
if (NULL != dockMenuRef) { |
SetMenuItemProperty(dockMenuRef, 0, FOUR_CHAR_CODE('aDTS'), FOUR_CHAR_CODE('wREF'), sizeof(UInt32), &aWindowRef); |
// using kMenuIconResourceType doesn't work on all systems -- it was fixed in 10.4.1 |
SetMenuItemIconHandle(dockMenuRef, 1, kMenuIconResourceType, (Handle)CFSTR("Play.icns")); |
SetMenuItemIconHandle(dockMenuRef, 2, kMenuIconResourceType, (Handle)CFSTR("Stop.icns")); |
SetMenuItemIconHandle(dockMenuRef, 3, kMenuIconResourceType, (Handle)CFSTR("Rewind.icns")); |
SetMenuItemIconHandle(dockMenuRef, 5, kMenuSystemIconSelectorType, (Handle)kGenericURLIcon); |
SetWindowDockTileMenu(aWindowRef, dockMenuRef); |
ReleaseMenu(dockMenuRef); |
} |
break; |
} |
case kEventWindowExpanding: |
{ |
if (wdr->fPlayingInDockTile == true) { |
// done playing in the dock so restore the world |
SetPort(GetWindowPort(wdr->fWindow)); |
MCSetControllerPort(wdr->fMovieController, GetWindowPort(wdr->fWindow)); |
SetMovieMatrix(wdr->fMovie, &wdr->fSavedMovieMatrix ); |
MCMovieChanged(wdr->fMovieController, wdr->fMovie); |
MCSetVisible(wdr->fMovieController, true); |
MCDraw(wdr->fMovieController, wdr->fWindow); |
ReleaseQDContextForCollapsedWindowDockTile(wdr->fWindow, wdr->fDockTileContext); |
wdr->fDockTileContext = NULL; |
wdr->fPlayingInDockTile = false; |
if (wdr->fIsVRMovie || IsMovieInteractive(wdr->fMovie)) { |
Set_MouseTrackingRegion(wdr->fWindow); |
} |
} |
break; |
} |
default: |
break; |
} |
DontPlayInDockTile: |
CantGetData: |
return eventNotHandledErr; |
} // Handle_WindowGetMinMaxIdealSize |
/***************************************************** |
* |
* Handle_URLWindowEventHandler(inHandlerCallRef, inEvent, inUserData) |
* |
* Purpose: called to handle carbon events from the open URL window |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (NULL) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_URLWindowEvents(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
HICommand aCommand; |
UInt32 theEventKind = GetEventKind(inEvent); |
UInt32 theEventClass = GetEventClass(inEvent); |
WindowRef theWindow = (WindowRef)inUserData; |
OSStatus status = noErr; |
// check parameters |
require_action((0 != theEventKind) && (0 != theEventClass) && (0 != theWindow), EventNotHandled, status = eventNotHandledErr); |
switch (theEventClass) { |
case kEventClassCommand: |
{ |
if (theEventKind == kEventCommandProcess) { |
GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &aCommand); |
if (aCommand.commandID == kHICommandOK) { |
ControlID controlID = kEditTextViewCID; |
ControlRef theControl; |
CFStringRef theURL; |
SInt32 dataSize; |
status = GetControlByID(theWindow, &controlID, &theControl); |
require_noerr(status, EventNotHandled); |
status = GetControlData(theControl, 0, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&theURL, &dataSize); |
require_noerr(status, EventNotHandled); |
SaveComboBoxValues(theControl); |
SetThemeCursor(kThemeArrowCursor); // get rid of IBeam if user was editing in text field |
TransitionWindow(theWindow, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL); |
DisposeWindow(theWindow); |
status = Do_OpenAWindow(NULL, theURL, NULL); |
require_noerr(status, EventNotHandled); |
CFRelease(theURL); |
} else if (aCommand.commandID == kHICommandCancel) { |
SetThemeCursor(kThemeArrowCursor); // get rid of IBeam if user was editing in text field |
TransitionWindow(theWindow, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL); |
DisposeWindow(theWindow); |
} |
} |
} |
break; |
default: |
status = eventNotHandledErr; |
break; |
} |
EventNotHandled: |
return status; |
} // Handle_URLWindowEventHandler |
/***************************************************** |
* |
* Handle_AppActivateDeactivate(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
* |
* Purpose: called to handle application activate and deactivate carbon events |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (NULL) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static WindowRef gDeactivatedWindow = NULL; |
static pascal OSStatus Handle_AppActivateDeactivate(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
WindowRef aWindowRef; |
WindowDataPtr wdr; |
UInt32 theEventKind; |
aWindowRef = FrontNonFloatingWindow(); |
require(NULL != aWindowRef, CantGetWindow); |
theEventKind = GetEventKind(inEvent); |
require(0 != theEventKind, CantGetEventKind); |
switch(theEventKind) { |
case kEventAppDeactivated: |
{ |
wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
require(NULL != wdr, CantGetWindowData); |
// app has switched out -- turn around and specifically dispatch a mcActionSuspend |
// event directly to the movie controller where we invalidate the control thereby |
// causing it to do what we want and draw in its deactive state -- because |
// mcActionSuspend is never sent to the movie control in the nomal process of deactivation or |
// switching from one window to another window in the application, we're not running unnecessary code |
MCDoAction(wdr->fMovieController, mcActionSuspend, (void *)0); |
// save a reference to the deactivated window because that's the window that contains the |
// movie controller we need to later send the mcActionResume message to -- we can't just pick |
// the front window because it may be different when the user switches back to the application |
gDeactivatedWindow = aWindowRef; |
} |
break; |
case kEventAppActivated: |
{ |
// app has switched in -- turn around and specifically dispatch a mcActionResume |
// event directly to the movie controller where we force a call to draw thereby |
// causing it to do what we want and draw in its active state -- because |
// mcActionResume is never sent to the movie control in the normal process of activation or |
// switching from one window to another in the application, we're not running unnecessary code |
// do we have a deactivated window |
if (NULL != gDeactivatedWindow) { |
wdr = (WindowDataPtr)GetWRefCon(gDeactivatedWindow); |
require(NULL != wdr, CantGetWindowData); |
MCDoAction(wdr->fMovieController, mcActionResume, (void *)0); |
} |
} |
break; |
default: |
break; |
} |
CantGetWindow: |
CantGetEventKind: |
CantGetWindowData: |
// by returning eventNotHandledErr, we continue with the normal processing of these events |
return eventNotHandledErr; |
} // Handle_AppActivateDeactivate |
/***************************************************** |
* |
* Handle_MouseExitedEvent(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
* |
* Purpose: called to handle carbon events dispatched when the mouse exited a mouse tracking region |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (NULL) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_MouseExitedEvent(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
SetThemeCursor(kThemeArrowCursor); |
return noErr; |
} // Handle_MouseExitedEvent |
/***************************************************** |
* |
* Handle_FullScreenWindowKeyDown(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
* |
* Purpose: called to handle carbon events dispatched when in full screen mode 'esc ' key will end full screen mode |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (NULL) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_FullScreenWindow(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) |
{ |
WindowRef aWindowRef = (WindowRef)inUserData; |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
UInt32 eventClass = GetEventClass(inEvent); |
UInt32 eventKind = GetEventKind(inEvent); |
OSStatus status = eventNotHandledErr; |
require(NULL != wdr, CantGetWindowData); |
switch (eventClass) { |
case kEventClassWindow: |
{ |
// eat the event |
if (kEventWindowClose == eventKind) status = noErr; |
break; |
} |
case kEventClassKeyboard: |
{ |
if (kEventRawKeyDown == eventKind) { |
char charCode; |
UInt32 modifiers; |
GetEventParameter(inEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(typeChar), NULL, &charCode); |
GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(typeUInt32), NULL, &modifiers); |
// 'esc ' key |
if (0x1B == charCode) { |
ControlRef rootControl; |
// we're leaving full screen so set the world back to normal |
SetPort(GetWindowPort(aWindowRef)); |
SetMovieGWorld(wdr->fMovie, GetWindowPort(aWindowRef), NULL); |
SetMovieMatrix(wdr->fMovie, &wdr->fSavedMovieMatrix); |
MCSetControllerPort(wdr->fMovieController, GetWindowPort(aWindowRef)); |
// remove the key down event handler and remove the carbon |
// movie control from the window |
RemoveEventHandler(wdr->fFSEventHandlerRef); |
HIViewRemoveFromSuperview((HIViewRef)wdr->fMovieControl); |
// place the carbon movie control back into the original window |
// and set focus so keyboard and mouse events go where they should |
GetRootControl(aWindowRef, &rootControl); |
if (NULL != rootControl) { |
EmbedControl(wdr->fMovieControl, rootControl); |
SetKeyboardFocus(aWindowRef, wdr->fMovieControl, 1000); // kControlFocusNextPart |
} |
// end full screen |
EndFullScreen(wdr->fFSRestoreState, 0); |
// make sure the movie controller is active |
MCActivate(wdr->fMovieController, wdr->fWindow, true); |
MCDoAction(wdr->fMovieController, mcActionResume, (void *)0); |
// tell the movie controller to sync up with the movie |
MCMovieChanged(wdr->fMovieController, wdr->fMovie); |
// make it visible again |
MCSetVisible(wdr->fMovieController, true); |
wdr->fFSWindow = NULL; |
wdr->fFSRestoreState = NULL; |
wdr->fFSEventHandlerRef = NULL; |
SetThemeCursor(kThemeArrowCursor); |
SelectWindow(wdr->fWindow); // not sure if we need this |
if (wdr->fIsVRMovie || IsMovieInteractive(wdr->fMovie)) { |
Set_MouseTrackingRegion(wdr->fWindow); |
} |
status = noErr; |
} |
} |
break; |
} |
case kEventClassMouse: |
{ |
// **** work around a bug in the Carbon Movie Control **** |
// because the Carbon Movie Control gets and keeps the content view of the first |
// composited window it is placed in, going full screen results in the control trying |
// to use mouse down coordinates from the original view and not the new full screen |
// view -- this means we need to handle mouse down ourselves because the event |
// handler won't work correctly |
if (kEventMouseDown == eventKind) { |
Point where; |
EventTime when = GetEventTime(inEvent); |
UInt32 modifiers; |
GetEventParameter(inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &where); |
GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); |
MCClick(wdr->fMovieController,wdr->fFSWindow, where, EventTimeToTicks(when), modifiers); |
status = noErr; |
} |
break; |
} |
default: |
break; |
} |
CantGetWindowData: |
return status; |
} // Handle_FullScreenWindow |
#pragma mark - |
#pragma mark * Movie Controller/Actions Handler * |
/***************************************************** |
* |
* Do_CreateMovieControl(WindowRef inWindowRef, Boolean inMovieControlOptionEnableEditing) |
* |
* Purpose: called to handle carbon events from the open URL window |
* |
* Inputs: inWindowRef - reference to a window |
* inMovieControlOptionEnableEditing - should the control enable editing |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Do_CreateMovieControl(WindowRef inWindowRef, Boolean inMovieControlOptionEnableEditing) |
{ |
WindowDataPtr wdr; |
Rect movieRect, windowRect, titleBarRect; |
Size outSize; |
HIPoint moviePosition; |
CGrafPtr savedPort; |
Boolean portChanged = false; |
ControlRef parentControl; |
QTMCActionNotificationRecord actionNotifier; |
OSStatus status = paramErr; |
require(NULL != inWindowRef, NoWindowRef); |
wdr = (WindowDataPtr)GetWRefCon(inWindowRef); |
require(NULL != wdr, CantGetWindowData); |
portChanged = QDSwapPort(GetWindowPort(inWindowRef), &savedPort); |
// set the default progress procedure for the movie |
SetMovieProgressProc(wdr->fMovie, (MovieProgressUPP)-1, 0); |
// resize the movie bounding rect and offset to 0,0 |
GetMovieBox(wdr->fMovie, &movieRect); |
MacOffsetRect(&movieRect, -movieRect.left, -movieRect.top); |
SetMovieBox(wdr->fMovie, &movieRect); |
// make sure that the movie has a non-zero width |
// zero height is okay (for example, a music movie with no controller bar) |
// but 16 is a good place to start because we do indeed have a controller |
if (movieRect.right - movieRect.left == 0) { |
MacSetRect(&movieRect, 0, 0, 320, 16); |
} |
windowRect = movieRect; |
// create the movie control |
UInt32 options = kMovieControlOptionLocateTopLeft | |
kMovieControlOptionSetKeysEnabled | |
(inMovieControlOptionEnableEditing ? (kMovieControlOptionEnableEditing | kMovieControlOptionHandleEditingHI) : 0); |
status = CreateMovieControl(inWindowRef, &movieRect, wdr->fMovie, options, &wdr->fMovieControl); |
require_noerr(status, CantCreateMovieControl); |
status = GetControlData(wdr->fMovieControl, kControlEntireControl, kMovieControlDataMovieController, 0, &wdr->fMovieController, &outSize); |
require_noerr(status, CantGetMovieController); |
// size the window correctly adding our slop |
windowRect.right += kDistanceFromHorizontalEdge; |
windowRect.bottom += kDistanceFromVerticalEdge; |
SizeWindow(inWindowRef, windowRect.right, windowRect.bottom, true); |
// if we have a 'none' controller change window attributes appropriately |
OSType mcType = Get_MovieControllerType(wdr->fMovie); |
if (FOUR_CHAR_CODE('none') == mcType) { |
ChangeWindowAttributes(inWindowRef, kWindowNoAttributes, kWindowResizableAttribute | kWindowFullZoomAttribute); |
} |
// if the movie is streaming don't allow it to minimize immediately |
if (IsStreamedMovie(wdr->fMovie)) { |
ChangeWindowAttributes(inWindowRef, kWindowNoAttributes, kWindowCollapseBoxAttribute); |
} |
// set the movie's position if it has a 'WLOC' user data atom |
status = Get_WindowPositionFromMovie(wdr->fMovie, &moviePosition); |
if (noErr == status) { |
MoveWindowStructure(inWindowRef, moviePosition.x, moviePosition.y); |
} |
AlignWindow(inWindowRef, false, NULL, NULL); |
GetWindowBounds(inWindowRef, kWindowTitleBarRgn, &titleBarRect); |
wdr->fWindowTitleBarSlop = titleBarRect.bottom - titleBarRect.top; |
// position the control nicely in the window |
MoveControl(wdr->fMovieControl, kDistanceFromHorizontalEdge / 2, (kDistanceFromVerticalEdge - wdr->fWindowTitleBarSlop) / 2); |
// get the parent embedder control of the movie control |
GetSuperControl(wdr->fMovieControl, &parentControl); |
// install a bounds change event handler on the movie controls parent control |
// so we know when the enclosing control has been resized and can resize |
// the movie control appropriately - we don't care if it's already installed as long as it's installed |
EventTypeSpec parentControlEvents[] = {{kEventClassControl, kEventControlBoundsChanged}}; |
status = InstallControlEventHandler(parentControl, Handle_ParentMovieControlWindowEvent, GetEventTypeCount(parentControlEvents), parentControlEvents, wdr, NULL); |
if (eventHandlerAlreadyInstalledErr == status) status = noErr; |
require_noerr(status, CantInstallControlWindowEventHandler); |
// install a carbon event handler on the movie control so we know when it's being disposed |
EventTypeSpec movieControlEvents[] = {{ kEventClassControl, kEventControlDispose }}; |
status = InstallControlEventHandler(wdr->fMovieControl, Handle_MovieControlDisposeEvent, GetEventTypeCount(movieControlEvents), movieControlEvents, wdr->fMovieControl, NULL); |
require_noerr(status, CantInstallMovieControllerEventHandler); |
// install an action notification procedure that does any application-specific movie controller processing |
actionNotifier.returnSignature = 0; // set to zero when passed to to the Movie Controller, on return will be set to 'noti' if mcActionAddActionNotification is implemented |
actionNotifier.notifyAction = ActionNotificationCallback; // function to be called at action time |
actionNotifier.refcon = inWindowRef; // something to pass to the action function |
actionNotifier.flags = kQTMCActionNotifyBefore | kQTMCActionNotifyAfter; // option flags |
MCDoAction(wdr->fMovieController, mcActionAddActionNotification, (void *)&actionNotifier); |
if (kQTMCActionNotifySignature != actionNotifier.returnSignature) { |
// kQTMCActionNotifySignature gives you the ability to test to see if the movie controller |
// you have actually supports action notifications -- unless you're running on pre |
// QuickTime 6 this check isn't really needed |
status = featureUnsupported; |
goto CantCreateMovieControl; |
} |
// **** work around a bug in the Carbon Movie Control **** |
// see Handle_MouseExitedEvent |
// IsVRMovie sets a boolean flag in our window data record |
if (IsVRMovie(wdr)) { |
Set_MouseTrackingRegion(inWindowRef); |
} |
// set the default movie play hints |
SetMoviePlayHints(wdr->fMovie, hintsAllowDynamicResize, hintsAllowDynamicResize); |
NoWindowRef: |
CantGetWindowData: |
CantCreateMovieControl: |
CantGetMovieController: |
CantInstallControlWindowEventHandler: |
CantInstallMovieControllerEventHandler: |
if (portChanged) QDSwapPort(savedPort, NULL); |
return status; |
} // Do_CreateMovieControl |
/***************************************************** |
* |
* ActionNotificationCallback(MovieController inMC, short inAction, void *params, UInt32 inFlags, UInt32 *outFlags, void *inRefCon) |
* |
* Purpose: an action notification function for a movie controller |
* |
* Inputs: inMC - movie controller |
* inAction - movie controller action |
* params - pointer to a structure that passes information to the callback |
* inFlags - option flags |
* inRefCon - reference constant |
* |
* Outputs: outFlags - option flags |
* |
* Returns: Boolean - return value not used |
* |
* Option Flags: |
* kQTMCActionNotifyBefore - inFlag indicates Action Notification was called before the MCActionFilter procedure |
* kQTMCActionNotifyAfter - inFlag indicates Action Notification was called after the MCActionFilter procedure |
* kQTMCActionNotifyParamChanged - inFlag/outFlag indicating to any other Action Notifications that may be installed that this Action Notification changed a parameter |
* kQTMCActionNotifyCancelled - inFlag/outFlag indicating Action Notification canceled action, setting this flag will cause the movie controller to skip the MCActionFilter |
* procedure and the movie controller action handler, but any Action Notifications marked kQTMCActionNotifyAfter will be called with this flag |
* set in the inFlags |
* kQTMCActionNotifyUserFilterCancelled - inFlag indicates that the MCActionFilter procedure handled the action, this will skip the movie controller action handler |
* but any Action Notifications marked kQTMCActionNotifyAfter will still get called with this flag set in the inFlags |
*/ |
static pascal Boolean ActionNotificationCallback(MovieController inMC, short inAction, void *params, UInt32 inFlags, UInt32 *outFlags, void *inRefCon) |
{ |
#pragma unused(inParams) |
Rect theRect; |
WindowRef aWindowRef = NULL; |
WindowDataPtr wdr = NULL; |
aWindowRef = (WindowRef)inRefCon; |
if (NULL == aWindowRef) { *outFlags = kQTMCActionNotifyCancelled; return 0; } |
wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
if (NULL == wdr) { *outFlags = kQTMCActionNotifyCancelled; return 0; } |
// if a Before action set this flag we don't care about |
// this event at all in the After action so just return |
if (inFlags & kQTMCActionNotifyCancelled) return 0; |
// do work before other controller filters or procs |
if ((inFlags & kQTMCActionNotifyBefore)) { |
switch (inAction) { |
// handle application messages |
case mcActionAppMessageReceived: |
{ |
long message = (long)params; |
switch (message) { |
case kQTAppMessageEnterFullScreenRequested: |
{ |
// if there's no full screen window already go full screen |
if (NULL == wdr->fFSWindow) { |
Do_BeginFullScreenWindow(aWindowRef); |
} |
// skip the rest of the chain |
*outFlags = kQTMCActionNotifyCancelled; |
break; |
} |
case kQTAppMessageExitFullScreenRequested: |
{ |
// if there's a full screen window exit full screen |
if (NULL != wdr->fFSWindow) { |
EventRef aEvent; |
char charCode = 0x1B; // 'esc' |
CreateEvent(NULL, kEventClassKeyboard, kEventRawKeyDown, GetCurrentEventTime(), kEventAttributeUserEvent, &aEvent); |
SetEventParameter(aEvent, kEventParamKeyMacCharCodes, typeChar, sizeof(char), &charCode); |
PostEventToQueue(GetMainEventQueue(), aEvent, kEventPriorityLow); |
ReleaseEvent(aEvent); |
// skip the rest of the chain |
*outFlags = kQTMCActionNotifyCancelled; |
} |
break; |
} |
case kQTAppMessageWindowCloseRequested: |
{ |
// if we're not full screen close the window -- if we are |
// full screen, exit full screen mode |
if (NULL == wdr->fFSWindow) { |
EventRef aEvent; |
CreateEvent(NULL, kEventClassWindow, kEventWindowClose, GetCurrentEventTime(), kEventAttributeUserEvent, &aEvent); |
SetEventParameter(aEvent, kEventParamDirectObject, typeWindowRef, sizeof(WindowRef), &aWindowRef); |
PostEventToQueue(GetMainEventQueue(), aEvent, kEventPriorityLow); |
ReleaseEvent(aEvent); |
} else { |
MCDoAction(inMC, mcActionAppMessageReceived, (void *)kQTAppMessageExitFullScreenRequested); |
} |
// skip the rest of the chain |
*outFlags = kQTMCActionNotifyCancelled; |
break; |
} |
default: |
break; |
} // switch |
} // mcActionAppMessageReceived |
default: |
break; |
} // switch |
} // kQTMCActionNotifyBefore |
// do work after any other controller filters or procs |
if (inFlags & kQTMCActionNotifyAfter) { |
// if we're in the dock or full screen don't process any events |
if (wdr->fPlayingInDockTile || (NULL != wdr->fFSWindow)) return 0; |
switch (inAction) { |
// handle window resizing |
case mcActionControllerSizeChanged: |
{ |
// because editing operations will hit this event first instead of the |
// carbon event handler, and subsequently the SizeWindow call will hit the |
// carbon event handler that will put us back here i.e. infinite loop |
// trying to resize, specifically protect against that state happening |
if (0 == TestAndSet(0, &wdr->fControlChangingBounds)) { |
GetMovieNaturalBoundsRect(wdr->fMovie, &theRect); |
// make sure that the movie has a non-zero |
// width and a minimum height of 16 |
if (theRect.right - theRect.left == 0) { |
MacSetRect(&theRect, 0, 0, 320, 16); |
} |
// size the window correctly adding our slop |
theRect.right += kDistanceFromHorizontalEdge; |
theRect.bottom += kDistanceFromVerticalEdge; |
SizeWindow(aWindowRef, theRect.right, theRect.bottom, true); |
TestAndClear(0, &wdr->fControlChangingBounds); |
} |
break; |
} |
// handle movie editing |
case mcActionMovieEdited: |
{ |
if (!IsStreamedMovie(wdr->fMovie) && !IsMovieInteractive(wdr->fMovie)) { |
GetMovieNaturalBoundsRect(wdr->fMovie, &theRect); |
if (!HasAudioTrack(wdr->fMovie) && (theRect.right - theRect.left == 0)) { |
// empty movie |
SetWindowModified(aWindowRef, false); |
} else { |
SetWindowModified(aWindowRef, true); |
} |
// **** work around a bug in the Carbon Movie Control **** |
// give the MC (yo yo yo) a little help and force |
// an invalidation after editing so stuff draws correctly |
RgnHandle region = MCGetControllerBoundsRgn(inMC); |
MCInvalidate(inMC, aWindowRef, region); |
DisposeRgn(region); |
} |
break; |
} |
// streaming movies can dynamically resize while loading so we want |
// to make sure that we disable the ability to go fullscreen or to the |
// dock if the streaming movie hasn't at least loaded into its playable |
// state at least once as it's dimensions will be incorrect -- to do this |
// we just use some simple state logic and check for it in UpdateStaus |
case mcActionPrerollAndPlay: |
{ |
if (IsStreamedMovie(wdr->fMovie)) { |
if (kStreamingPrerollInProgress == wdr->fStreamingPrerollState) { |
if (GetMovieRate(wdr->fMovie)) { |
wdr->fStreamingPrerollState = kStreamingPrerollDone; |
// allow the window to be minimized |
ChangeWindowAttributes(aWindowRef, kWindowCollapseBoxAttribute, kWindowNoAttributes); |
} |
} else if (kStreamingPrerollDone > wdr->fStreamingPrerollState) { |
wdr->fStreamingPrerollState = kStreamingPrerollStateStarted; |
} |
} |
break; |
} |
case mcActionUseTrackForTimeTable: |
{ |
if (IsStreamedMovie(wdr->fMovie)) { |
if (kStreamingPrerollStateStarted == wdr->fStreamingPrerollState) |
wdr->fStreamingPrerollState = kStreamingPrerollInProgress; |
} |
break; |
} |
// **** work around a bug in the Carbon Movie Control **** |
// see Handle_AppActivateDeactivate on 10.3.x |
// see Handle_WindowActivatedDeactivated on 10.4 |
case mcActionSuspend: |
{ |
RgnHandle region = MCGetControllerBoundsRgn(inMC); |
MCInvalidate(inMC, aWindowRef, region); |
DisposeRgn(region); |
break; |
} |
// **** work around a bug in the Carbon Movie Control **** |
// see Handle_AppActivateDeactivate on 10.3.x |
// see Handle_WindowActivatedDeactivated on 10.4 |
case mcActionResume: |
{ |
MCDraw(inMC, aWindowRef); |
break; |
} |
default: |
break; |
} // switch |
} // kQTMCActionNotifyAfter |
return 0; |
} // ActionNotificationCallback |
/***************************************************** |
* |
* OSStatus Handle_ParentMovieControlWindowEvent(EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData) |
* |
* Purpose: called to resize the movie control when the controls parent is resized, in this case the windows root control |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_ParentMovieControlWindowEvent(EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData) |
{ |
Rect rect; |
WindowDataPtr wdr = (WindowDataPtr)inUserData; |
UInt32 eventClass = GetEventClass(inEvent); |
UInt32 eventKind = GetEventKind(inEvent); |
OSStatus status = eventNotHandledErr; |
require(NULL != wdr, CantGetData); |
switch (eventClass) { |
case kEventClassControl: |
if (eventKind == kEventControlBoundsChanged) { |
TestAndSet(0, &wdr->fControlChangingBounds); |
GetEventParameter(inEvent, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &rect); |
// position the control where we want it in the window |
SizeControl(wdr->fMovieControl, (rect.right - rect.left) - kDistanceFromHorizontalEdge, ((rect.bottom - rect.top) - kDistanceFromVerticalEdge) + 16); |
MoveControl(wdr->fMovieControl, kDistanceFromHorizontalEdge / 2, (kDistanceFromVerticalEdge - wdr->fWindowTitleBarSlop) / 2); |
TestAndClear(0, &wdr->fControlChangingBounds); |
} |
break; |
} |
CantGetData: |
return status; |
} // Handle_ParentMovieControlWindowEvent |
/***************************************************** |
* |
* Handle_MovieControlDisposeEvent(EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData) |
* |
* Purpose: called as notification that the movie control is being disposed |
* |
* Inputs: inHandlerCallRef - reference to the current handler call chain |
* inEvent - the event |
* inUserData - app-specified data you passed in the call to InstallEventHandler (NULL) |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static pascal OSStatus Handle_MovieControlDisposeEvent(EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData) |
{ |
OSStatus err; |
SInt32 dataSize; |
Movie movie; |
ControlRef control; // could also use (ControlRef)inUserData; |
UInt32 eventClass = GetEventClass( inEvent ); |
UInt32 eventKind = GetEventKind( inEvent ); |
OSStatus status = eventNotHandledErr; |
switch (eventClass) { |
case kEventClassControl: |
if (eventKind == kEventControlDispose) { |
GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control); |
// kMovieControlDataMovie tag allows us to get the Movie from the Control |
err = GetControlData(control, 0, kMovieControlDataMovie, sizeof(Movie), (Ptr)&movie, &dataSize); |
if (err == noErr && NULL != movie) { |
CallNextEventHandler(inCallRef, inEvent); |
DisposeMovie(movie); |
status = noErr; |
} |
SetThemeCursor(kThemeArrowCursor); |
} |
break; |
} |
return status; |
} // Handle_MovieControlDisposeEvent |
#pragma mark - |
#pragma mark * CarbonEventLoop Timers * |
/***************************************************** |
* |
* Timer_AsyncMovieLoading(EventLoopTimerRef inTimer, void *inUserData) |
* |
* Purpose: carbon timer function that handles async movie loading |
* |
* Inputs: inTimer - reference to the installed timer |
* inUserData - app-specified data you passed in the call to InstallEventLoopTimer |
* |
* Returns: void |
*/ |
static pascal void Timer_AsyncMovieLoading(EventLoopTimerRef inTimer, void *inUserData) |
{ |
long movieLoadState; |
WindowRef aWindowRef = (WindowRef)inUserData; |
require(NULL != aWindowRef, CantGetWindowRef); |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
require(NULL != wdr, CantGetWindowData); |
if (wdr->fMovie == NULL) return; |
// get the current load state |
movieLoadState = GetMovieLoadState(wdr->fMovie); |
// process the movie according to its current load state |
if (movieLoadState <= kMovieLoadStateError) { |
// an error occurred while attempting to load the movie |
// remove the timer |
RemoveEventLoopTimer(wdr->fAsyncLoadingTimer); |
// close the window |
Send_WindowCloseEvent(wdr->fWindow); |
// notify user |
Display_StandardAlert(kMovieLoadStateError); |
} else if (movieLoadState < kMovieLoadStatePlayable) { |
// we're not playable yet |
// task the movie so it gets time to load |
MoviesTask(wdr->fMovie, 1); |
} else { |
// we are now playable so attach the Movie Control and show the window |
if (NULL == wdr->fMovieController) { |
Do_CreateMovieControl(aWindowRef, ((IsStreamedMovie(wdr->fMovie) || IsMovieInteractive(wdr->fMovie) ? false : true))); |
Set_WindowTitleFromMovie(wdr->fMovie, aWindowRef); |
TransitionWindow(aWindowRef, kWindowZoomTransitionEffect, kWindowShowTransitionAction, NULL); |
if (IsAutoPlayMovie(wdr->fMovie)){ |
MCDoAction(wdr->fMovieController, mcActionAutoPlay, (void *)GetMoviePreferredRate(wdr->fMovie)); |
} |
} |
// movie loading is complete so no remove the timer |
if (movieLoadState == kMovieLoadStateComplete) { |
RemoveEventLoopTimer(wdr->fAsyncLoadingTimer); |
wdr->fAsyncLoadingTimer = NULL; |
} |
} |
wdr->fMovieLoadState = movieLoadState; |
CantGetWindowRef: |
CantGetWindowData: |
return; |
} // Timer_AsyncMovieLoading |
#pragma mark - |
#pragma mark * Windows * |
/***************************************************** |
* |
* Do_Preferences(void) |
* |
* Purpose: routine to display dialog to set our applications preferences |
* |
* Inputs: none |
* |
* Returns: none |
*/ |
static void Do_Preferences(void) |
{ |
#if 0 |
DialogRef theAlert; |
CreateStandardAlert(kAlertStopAlert, CFSTR("No Preferences yet!"), NULL, NULL, &theAlert); |
RunStandardAlert(theAlert, NULL, NULL); |
#else |
// If the Preferences window is already open then just select it to make it front else |
// create a window. "PrefWindow" is the name of the window object. This name is set in |
// InterfaceBuilder when the nib is created. |
if (gPreferencesWindow != NULL) |
{ |
SelectWindow(gPreferencesWindow); |
return; |
} |
OSStatus status = CreateWindowFromNib(gIBNibRef, CFSTR("PrefWindow"), &gPreferencesWindow); |
require_noerr(status, CantCreateWindow); |
EventTypeSpec eventType1[] = {{kEventClassWindow, kEventWindowClose}}; |
status = InstallWindowEventHandler(gPreferencesWindow, Handle_PrefWindowIsAboutToClose, GetEventTypeCount(eventType1), eventType1, NULL, NULL); |
require_noerr(status, CantInstallWindowEventHandler); |
EventTypeSpec eventType2[] = {{kEventClassCommand, kEventCommandProcess}}; |
status = InstallWindowEventHandler(gPreferencesWindow, Handle_PrefCommandProcess, GetEventTypeCount(eventType2), eventType2, NULL, NULL); |
require_noerr(status, CantInstallWindowEventHandler); |
HIViewRef aHIViewRef; |
status = HIViewFindByID(HIViewGetRoot(gPreferencesWindow), kRememberLastHID, &aHIViewRef); |
require_noerr(status, CantGetView); |
SetControl32BitValue(aHIViewRef, gRememberLast ? 1 : 0); |
status = HIViewFindByID(HIViewGetRoot(gPreferencesWindow), kRememberBoundsHID, &aHIViewRef); |
require_noerr(status, CantGetView); |
SetControl32BitValue(aHIViewRef, gRememberBounds ? 1 : 0); |
if (gRememberLast) EnableControl(aHIViewRef); else DisableControl(aHIViewRef); |
status = HIViewFindByID(HIViewGetRoot(gPreferencesWindow), kOpenFoldersHID, &aHIViewRef); |
require_noerr(status, CantGetView); |
SetControl32BitValue(aHIViewRef, gOpenFolderContents ? 1 : 0); |
status = HIViewFindByID(HIViewGetRoot(gPreferencesWindow), kOpenRecursiveHID, &aHIViewRef); |
require_noerr(status, CantGetView); |
SetControl32BitValue(aHIViewRef, gOpenFolderRecursive ? 1 : 0); |
if (gOpenFolderContents) EnableControl(aHIViewRef); else DisableControl(aHIViewRef); |
ShowWindow(gPreferencesWindow); |
CantGetView: |
CantInstallWindowEventHandler: |
CantCreateWindow: |
return; |
#endif |
} // Do_Preferences |
/***************************************************** |
* |
* Do_OpenURLWindow(void) |
* |
* Purpose: called when user selects "Open URL..." item from "File" menu |
* |
* Inputs: none |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Do_URLWindow(void) |
{ |
WindowRef urlWindowRef; |
ControlID controlID = kEditTextViewCID; |
ControlRef theControl; |
OSStatus status = noErr; |
status = CreateWindowFromNib(gIBNibRef, CFSTR("URLWindow"), &urlWindowRef); |
require_noerr(status, CantCreateWindow); |
EventTypeSpec eventType1[] = {{ kEventClassCommand, kEventCommandProcess }}; |
status = InstallWindowEventHandler(urlWindowRef, Handle_URLWindowEvents, GetEventTypeCount(eventType1), eventType1, urlWindowRef, NULL); |
require_noerr(status, CantInstallWindowEventHandler); |
status = GetControlByID(urlWindowRef, &controlID, &theControl); |
require_noerr(status, CantFindControl); |
// Load the saved locations into our ComboBox control list |
RestoreComboBoxValues(theControl); |
TransitionWindow(urlWindowRef, kWindowZoomTransitionEffect, kWindowShowTransitionAction, NULL); |
CantCreateWindow: |
return status; |
CantFindControl: |
CantInstallWindowEventHandler: |
DisposeWindow(urlWindowRef); |
return status; |
} // Do_OpenURLWindow |
/***************************************************** |
* |
* Do_NewWindow(outWindow) |
* |
* Purpose: called to create a new window |
* |
* Notes: called by Handle_CommandProcess() ("File/New" menu item) , |
* Do_OpenDocs (Do_OpenWindows() ("File/Open" menu item) & Handle_OpenDocuments() ('odoc' AppleEvent)) |
* Handle_OpenApplication() & Handle_ReopenApplication() ('oapp' & 'rapp' AppleEvent handlers) |
* |
* Inputs: outWindow - if not NULL, the address where to return the WindowRef |
* - if not NULL, the callee will have to ShowWindow & SetKeyboardFocus |
* |
* Returns: OSStatus - noErr indicates the event was handled |
* - eventNotHandledErr indicates the event was not handled and the Toolbox should take over |
*/ |
static OSStatus Do_NewWindow(WindowRef *outWindow) |
{ |
WindowRef aWindowRef = NULL; |
OSStatus status; |
// Create a window. "MovieWindow" is the name of the window object. This name is set in |
// InterfaceBuilder when the nib is created. |
status = CreateWindowFromNib(gIBNibRef, CFSTR("MovieWindow"), &aWindowRef); |
require_noerr(status, CantCreateWindow); |
SetPortWindowPort(aWindowRef); |
WindowDataPtr wdr = (WindowDataPtr) calloc(1, sizeof(WindowDataRec)); |
SetWRefCon(aWindowRef, (long)wdr); |
wdr->fWindow = aWindowRef; |
EventTypeSpec eventType1[] = {{kEventClassWindow, kEventWindowClose}}; |
status = InstallWindowEventHandler(aWindowRef, Handle_WindowIsAboutToClose, GetEventTypeCount(eventType1), eventType1, (void *)aWindowRef, NULL); |
require_noerr(status, CantInstallWindowEventHandler); |
EventTypeSpec eventType2[] = {{kEventClassWindow, kEventWindowClosed}}; |
status = InstallWindowEventHandler(aWindowRef, Handle_WindowIsClosing, GetEventTypeCount(eventType2), eventType2, (void *)aWindowRef, NULL); |
require_noerr(status, CantInstallWindowEventHandler); |
EventTypeSpec eventType3[] = {{kEventClassWindow, kEventWindowBoundsChanging}, |
{kEventClassWindow, kEventWindowBoundsChanged}}; |
status = InstallWindowEventHandler(aWindowRef, Handle_WindowBoundsChanges, GetEventTypeCount(eventType3), eventType3, (void *)aWindowRef, NULL); |
require_noerr(status, CantInstallWindowEventHandler); |
EventTypeSpec eventType4[] = {{kEventClassWindow, kEventWindowGetMinimumSize}, |
{kEventClassWindow, kEventWindowGetMaximumSize}, |
{kEventClassWindow, kEventWindowGetIdealSize}}; |
status = InstallWindowEventHandler(aWindowRef, Handle_WindowGetMinMaxIdealSize, GetEventTypeCount(eventType4), eventType4, (void *)aWindowRef, NULL); |
require_noerr(status, CantInstallWindowEventHandler); |
EventTypeSpec eventType5[] = {{kEventClassWindow, kEventWindowCollapse}, |
{kEventClassWindow, kEventWindowCollapsed}, |
{kEventClassWindow, kEventWindowExpanding}}; |
status = InstallWindowEventHandler(aWindowRef, Handle_WindowDockTile, GetEventTypeCount(eventType5), eventType5, (void *)aWindowRef, NULL); |
require_noerr(status, CantInstallWindowEventHandler); |
if (gSystemVersion >= 0x00001040) { |
// **** work around a bug in the Carbon Movie Control **** |
// when the window is deactivated, the carbon movie control will not draw the control in the activated state again |
// we handle these events at the window level and specifially send mcAction messages to the front most active control to either invalidate or draw |
// this fixes the problem for both interapplication windows and swiching in or out from the application |
// on 10.3.x we handle activation/deactivation issues at the application level because they only affect us when we're switching in/out of the applicaion |
EventTypeSpec eventType6[] = {{kEventClassWindow, kEventWindowActivated}, |
{kEventClassWindow, kEventWindowDeactivated}}; |
status = InstallWindowEventHandler(aWindowRef, Handle_WindowActivatedDeactivated, GetEventTypeCount(eventType6), eventType6, (void *)aWindowRef, NULL); |
require_noerr(status, CantInstallWindowEventHandler); |
} |
// The window was created hidden so show it now if it's an empty movie |
if (NULL == outWindow) { |
CFStringRef windowTitle; |
wdr->fMovie = NewMovie(newMovieActive); |
require(NULL != wdr->fMovie, CantCreateMovie); |
SetMovieGWorld(wdr->fMovie, GetWindowPort(aWindowRef), NULL); |
status = Do_CreateMovieControl(aWindowRef, true); |
require_noerr(status, CantCreateMovieControl); |
windowTitle = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Untitled %ld"), gDocumentCount++); |
if (NULL != windowTitle) { |
SetWindowTitleWithCFString(aWindowRef, windowTitle); |
CFRelease(windowTitle); |
} |
TransitionWindow(aWindowRef, kWindowZoomTransitionEffect, kWindowShowTransitionAction, NULL); |
} |
SetWindowModified(aWindowRef, false); |
CantCreateMovieControl: |
CantCreateMovie: |
CantInstallWindowEventHandler: |
CantCreateWindow: |
if (NULL != outWindow) |
*outWindow = aWindowRef; |
return status; |
} // Do_NewWindow |
/***************************************************** |
* |
* Do_BeginFullScreenWindow(inWindowRef) |
* |
* Purpose: called by the "Full Screen" menu item to view the curren movie full screen |
* |
* Inputs: inWindow - window containing the movie to be viewed full screen |
* |
* Returns: OSStatus - noErr or error code |
* |
*/ |
static OSStatus Do_BeginFullScreenWindow(WindowRef inWindowRef) |
{ |
short width = 0; |
short height = 0; |
long h = 0, w = 0; |
HIRect bestModeBounds, bestRect; |
RGBColor eraseColorBlack = {0, 0, 0}; |
Rect fullScreenMovieBounds = { 0 }; |
Rect movieBounds; |
MatrixRecord fullScreenMovieMatrix; |
CGrafPtr savePort; |
ControlRef rootControl; |
OSStatus status = paramErr; |
require(NULL != inWindowRef, NoWindowRef); |
GetPort(&savePort); |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(inWindowRef); |
require(NULL != wdr, CantGetWindowData); |
// go though the display modes and pick the highest resolution for full screen |
{ |
CGDirectDisplayID displays[1]; // we only care about the main display |
CGDisplayCount numDisplays; |
CFArrayRef modeList; |
CFDictionaryRef mode; |
CFNumberRef number; |
CFBooleanRef boolean; |
status = CGGetActiveDisplayList(1, displays, &numDisplays); |
require_noerr(status, CantGetDisplayList); |
modeList = CGDisplayAvailableModes(displays[0]); |
require(NULL != modeList, CantGetModeList); |
// examine each mode |
CFIndex cnt = CFArrayGetCount( modeList ); |
for (CFIndex i = 0; i < cnt; i++) { |
long modeHeight = 0, modeWidth = 0; |
long depth; |
Boolean usable, stretched = false; |
// grab the mode dictionary |
mode = CFArrayGetValueAtIndex(modeList, i); |
//CFShow(mode); |
// grab mode params we need |
number = CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel); |
CFNumberGetValue(number, kCFNumberLongType, &depth); |
boolean = CFDictionaryGetValue(mode, kCGDisplayModeUsableForDesktopGUI) ; |
usable = CFBooleanGetValue(boolean); |
boolean = CFDictionaryGetValue(mode, kCGDisplayModeIsStretched); |
if (NULL != boolean) { |
stretched = CFBooleanGetValue(boolean); |
} |
// if the mode passes our criteria, save the height and width |
if (depth >= 32 && usable && !stretched) { |
number = CFDictionaryGetValue(mode, kCGDisplayHeight); |
CFNumberGetValue(number, kCFNumberLongType, &modeHeight); |
number = CFDictionaryGetValue(mode, kCGDisplayWidth); |
CFNumberGetValue(number, kCFNumberLongType, &modeWidth); |
if (modeHeight > h && modeWidth > w) { |
h = modeHeight; |
w = modeWidth; |
} |
} |
} |
} |
// figure out the best rect for the movie within the fullscreen window |
bestModeBounds = CGRectMake(0, 0, w, h); |
Get_MovieGrowBounds(wdr, &bestModeBounds, &bestRect); |
height = h; |
width = w; |
UInt32 flags = 0;//fullScreenCaptureAllDisplays; |
if (!wdr->fIsVRMovie && !IsMovieInteractive(wdr->fMovie)) flags |= fullScreenHideCursor; |
// go full screen |
status = BeginFullScreen(&wdr->fFSRestoreState, NULL, &width, &height, &wdr->fFSWindow, &eraseColorBlack, flags); |
require_noerr(status, CantBeginFullScreen); |
// raw key down event for the esc key which will end the full screen mode |
// window close event so we can eat it |
// mouse down event because the Carbon Movie Controls mouse down won't work when the control is moved to another window |
EventTypeSpec eventType[] = {{kEventClassKeyboard, kEventRawKeyDown}, |
{kEventClassWindow, kEventWindowClose }, |
{kEventClassMouse, kEventMouseDown }}; |
status = InstallWindowEventHandler(wdr->fFSWindow, Handle_FullScreenWindow, GetEventTypeCount(eventType), eventType, inWindowRef, &wdr->fFSEventHandlerRef); |
require_noerr(status, CantInstallWindowEventHandler); |
SetPort(GetWindowPort(wdr->fFSWindow)); |
SetMovieGWorld(wdr->fMovie, GetWindowPort(wdr->fFSWindow), NULL); |
MCSetControllerPort(wdr->fMovieController, GetWindowPort(wdr->fFSWindow)); |
MCSetVisible(wdr->fMovieController, false); |
// center the movie and set the matrix |
fullScreenMovieBounds.top = ((height - bestRect.size.height) / 2); |
fullScreenMovieBounds.left = (width - bestRect.size.width) / 2; |
fullScreenMovieBounds.right = fullScreenMovieBounds.left + bestRect.size.width; |
fullScreenMovieBounds.bottom = fullScreenMovieBounds.top + bestRect.size.height; |
// save the old movie matrix for restore |
GetMovieMatrix(wdr->fMovie, &wdr->fSavedMovieMatrix); |
// set up the new movie matrix |
SetIdentityMatrix(&fullScreenMovieMatrix); |
GetMovieNaturalBoundsRect(wdr->fMovie, &movieBounds); |
MapMatrix(&fullScreenMovieMatrix, &movieBounds, &fullScreenMovieBounds); |
SetMovieMatrix(wdr->fMovie, &fullScreenMovieMatrix); |
MCMovieChanged(wdr->fMovieController, wdr->fMovie); |
// embed the control in the full screen window and set focus |
// we need to install the standard window event handler for keyboad events |
CreateRootControl(wdr->fFSWindow, &rootControl); |
require(NULL != rootControl, CantGetRootControl); |
EmbedControl(wdr->fMovieControl, rootControl); |
SetKeyboardFocus(wdr->fFSWindow, wdr->fMovieControl, 1000); // kControlFocusNextPart |
status = ChangeWindowAttributes(wdr->fFSWindow, kWindowStandardHandlerAttribute, kWindowNoAttributes); |
require_noerr(status, CantChangeWindowAttributes); |
// make sure the movie controller is active |
MCActivate(wdr->fMovieController, wdr->fFSWindow, true); |
MCDoAction(wdr->fMovieController, mcActionResume, (void *)0); |
// not sure if we need this |
SelectWindow(wdr->fFSWindow); |
if (wdr->fIsVRMovie || IsMovieInteractive(wdr->fMovie)) { |
ReleaseMouseTrackingRegion(wdr->fMouseTrackingRef); |
wdr->fMouseTrackingRef = NULL; |
} |
return noErr; |
CantChangeWindowAttributes: |
CantGetRootControl: |
if (NULL != wdr->fFSWindow) { |
EventRef aEvent; |
char charCode = 0x1B; // 'esc' |
CreateEvent(NULL, kEventClassKeyboard, kEventRawKeyDown, GetCurrentEventTime(), kEventAttributeUserEvent, &aEvent); |
SetEventParameter(aEvent, kEventParamKeyMacCharCodes, typeChar, sizeof(char), &charCode); |
PostEventToQueue(GetMainEventQueue(), aEvent, kEventPriorityLow); |
ReleaseEvent(aEvent); |
} |
return status; |
CantBeginFullScreen: |
CantInstallWindowEventHandler: |
CantGetDisplayList: |
CantGetModeList: |
CantGetWindowData: |
SetPort(savePort); |
NoWindowRef: |
return status; |
} // Do_BeginFullScreenWindow |
#pragma mark - |
#pragma mark * Navigation Services * |
/***************************************************** |
* |
* Handle_NavFilter(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) |
* |
* Purpose: filter function that determines whether file objects should be displayed in the browser list and navigation menus |
* |
* Inputs: theItem - a pointer to an Apple event descriptor structure |
* info - a pointer to a NavFileOrFolderInfo structure |
* callBackUD - a pointer to a value set by your application when it calls a Navigation Services dialog creation function |
* filterMode - a value representing which list of objects is currently being filtered |
* |
* Returns: Boolean - true indicates that Navigation Services should display the object |
*/ |
static pascal Boolean Handle_NavFilter(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) |
{ |
LSItemInfoRecord lsInfoRec; |
FSRef fsRef; |
Handle hDataRef = NULL; |
OSType dataRefType; |
OSStatus status; |
Boolean canViewItem = false, |
canOpenAsMovie = false; |
if (typeFSRef == theItem->descriptorType) |
{ |
status = AEGetDescData(theItem, &fsRef, sizeof(fsRef)); |
require_noerr(status, CantGetFSRef); |
// Ask LaunchServices for information about the item |
status = LSCopyItemInfoForRef(&fsRef, kLSRequestAllInfo, &lsInfoRec); |
require((noErr == status) || (kLSApplicationNotFoundErr == status), LaunchServicesError); |
if (0 != (lsInfoRec.flags & kLSItemInfoIsContainer)) { |
canViewItem = true; |
} else { |
UInt32 flags = kQTDontUseDataToFindImporter | |
kQTAllowOpeningStillImagesAsMovies | |
/* kQTAllowImportersThatWouldCreateNewFile |*/ |
kQTAllowAggressiveImporters; |
QTNewDataReferenceFromFSRef(&fsRef, 0, &hDataRef, &dataRefType); |
require(NULL != hDataRef, CantCreateDataRef); |
status = CanQuickTimeOpenDataRef(hDataRef, dataRefType, NULL, &canOpenAsMovie, NULL, flags); |
DisposeHandle(hDataRef); |
require((noErr == status), QuickTimeError); |
if (canOpenAsMovie) { |
canViewItem = true; |
} else { |
status = LSCanRefAcceptItem(&fsRef, &gApplicationBundleFSRef, kLSRolesViewer, kLSAcceptDefault, &canViewItem); |
} |
} |
} |
LaunchServicesError: |
QuickTimeError: |
CantGetFSRef: |
CantCreateDataRef: |
return(canViewItem); |
} // Handle_NavFilter |
/***************************************************** |
* |
* Handle_NavEventCallback(callbackSelector, callbackParms, callbackUD) |
* |
* Purpose: NavDialogs callback |
* |
* Inputs: callbackSelector - Identifies the message type being sent to the client's event proc |
* callbackParms - information that is specific to each event type |
* callbackUD - pointer to user data (passed to NavCreatePutFileDialog) |
* |
* Returns: void |
*/ |
static pascal void Handle_NavEventCallback(NavEventCallbackMessage callbackSelector, NavCBRecPtr callbackParms, NavCallBackUserData callbackUD) |
{ |
WindowRef aWindowRef = (WindowRef) callbackUD; |
NavReplyRecord aNavReplyRecord; |
Boolean gotReply = false; |
FSRef theRef; |
switch (callbackSelector) |
{ |
case kNavCBUserAction: |
switch (callbackParms->userAction) |
{ |
case kNavUserActionSaveAs: |
{ |
OSStatus status; |
FSRef dirRef; |
FSSpec tFSSpec; |
status = NavDialogGetReply(callbackParms->context, &aNavReplyRecord); |
require_noerr(status, CantGetReply); |
gotReply = true; |
if (!aNavReplyRecord.validRecord) |
goto CantGetDir; |
status = AEGetNthPtr(&aNavReplyRecord.selection, 1, typeFSRef, NULL, NULL, &dirRef, sizeof(dirRef), NULL); |
require_noerr(status, CantGetDir); |
CFIndex len = CFStringGetLength(aNavReplyRecord.saveFileName); |
if (len > 255) |
len = 255; |
UniChar buffer[255]; |
CFStringGetCharacters(aNavReplyRecord.saveFileName, CFRangeMake(0, len), buffer); |
status = FSMakeFSRefUnicode(&dirRef, len, buffer, GetApplicationTextEncoding(), &theRef); |
if (fnfErr == status) { // file is not there yet - create it |
status = FSCreateFileUnicode(&dirRef, len, buffer, 0, NULL, &theRef, NULL); |
} |
require_noerr(status, CantMakeFSRef); |
status = Save_WithFSRefAndWindow(&theRef, aWindowRef); |
require_noerr(status, SavingFailed); |
status = NavCompleteSave(&aNavReplyRecord, kNavTranslateInPlace); |
require_noerr(status, CompleteSavingFailed); |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
require(NULL != wdr, CantGetWindowData); |
if (wdr->fClosing) { |
TransitionWindow(aWindowRef, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL); |
DisposeWindow(aWindowRef); |
} else { |
// if the save as was successful we first need to create the FSRef again because |
// the original file was deleted in the Save_WithFSRefAndWindow function |
// then add the new proxy icon and set the new window title |
status = FSMakeFSRefUnicode(&dirRef, len, buffer, GetApplicationTextEncoding(), &theRef); |
require_noerr(status, CantMakeFSRef); |
status = FSGetCatalogInfo(&theRef, kFSCatInfoNone, NULL, NULL, &tFSSpec, NULL); |
require_noerr(status, CantGetFSSpec); |
SetWindowProxyFSSpec(aWindowRef, &tFSSpec); |
SetWindowTitleWithCFString(aWindowRef, aNavReplyRecord.saveFileName); |
} |
NavDisposeReply(&aNavReplyRecord); |
Test_AreWeFinished(); |
return; |
} |
case kNavUserActionSaveChanges: |
{ |
Do_Save(aWindowRef); |
break; |
} |
case kNavUserActionDontSaveChanges: |
{ |
TransitionWindow(aWindowRef, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL); |
DisposeWindow(aWindowRef); |
Test_AreWeFinished(); |
break; |
} |
case kNavUserActionReviewDocuments: |
{ |
Test_AreWeFinished(); |
break; |
} |
case kNavUserActionDiscardDocuments: |
{ |
QuitApplicationEventLoop(); |
break; |
} |
case kNavUserActionCancel: |
{ |
if (gIsQuitting) |
gIsQuitting = false; |
if (NULL != callbackUD) |
{ |
WindowDataPtr wdr = (WindowDataPtr) GetWRefCon(aWindowRef); |
require(NULL != wdr, CantGetWindowData); |
if (wdr->fClosing) |
wdr->fClosing = false; |
} |
break; |
} |
} |
break; |
case kNavCBTerminate: |
{ |
NavDialogDispose(callbackParms->context); |
return; |
} |
} |
CompleteSavingFailed: |
SavingFailed: |
if (gotReply && !aNavReplyRecord.replacing) |
FSDeleteObject(&theRef); |
CantGetFSSpec: |
CantGetWindowData: |
CantMakeFSRef: |
CantGetDir: |
if (gotReply) |
NavDisposeReply(&aNavReplyRecord); |
CantGetReply: |
return; |
} // Handle_NavEventCallback |
#pragma mark - |
#pragma mark * Open/Save/Close Document * |
/***************************************************** |
* |
* Do_OpenAWindow(const FSRef *inFSRef, const CFStringRef inURL, const Rect *inBounds) |
* |
* Purpose: called to open a window and load the file |
* |
* Inputs: inFSRef - file to load, may be NULL |
* inURL - URL to load, may be NULL |
* inBounds - if not NULL, bounds for the window |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Do_OpenAWindow(const FSRef *inFSRef, const CFStringRef inURL, const Rect *inBounds) |
{ |
WindowRef aWindowRef = NULL; |
WindowDataPtr wdr = NULL; |
Handle dataRef = NULL; |
OSType dataRefType; |
short ignoreResID = 0; |
CFStringRef windowTitle = NULL; |
OSStatus status = noErr; |
// check parameters |
require_action(((NULL != inFSRef) || (NULL != inURL)), BadParameter, status = paramErr); |
if (NULL != inFSRef) { |
CFURLRef tCFURLRef = CFURLCreateFromFSRef(NULL, inFSRef); |
require(NULL != tCFURLRef, CantCreateURL); |
QTNewDataReferenceFromFSRef(inFSRef, 0, &dataRef, &dataRefType); |
require(NULL != dataRef, CantCreateDataRef); |
windowTitle = CFURLCopyLastPathComponent(tCFURLRef); |
CFRelease(tCFURLRef); |
} else { |
QTNewDataReferenceFromURLCFString(inURL, 0, &dataRef, &dataRefType); |
require(NULL != dataRef, CantCreateDataRef); |
windowTitle = CFStringCreateCopy(kCFAllocatorDefault, inURL); |
} |
status = Do_NewWindow(&aWindowRef); |
require_noerr(status, CantCreateWindow); |
wdr = (WindowDataPtr)GetWRefCon(aWindowRef); |
require(NULL != wdr, CantGetWindowData); |
// set the window position if we're past the bounds |
// this may change if movie has preferred window position |
// set the initial window title |
// this may change if the movie has a title contained in the movie user data |
if (NULL != inBounds) { |
MoveWindowStructure(aWindowRef, inBounds->left, inBounds->top); |
} |
SetWindowTitleWithCFString(aWindowRef, windowTitle); |
// save the data reference associated with the movie |
wdr->fDataRef = dataRef; |
wdr->fDataRefType = dataRefType; |
if (NULL != inFSRef) { |
FSSpec tFSSpec; |
status = FSGetCatalogInfo(inFSRef, kFSCatInfoNone, NULL, NULL, &tFSSpec, NULL); |
if (noErr == status) { |
SetWindowProxyFSSpec(aWindowRef, &tFSSpec); |
} |
} |
// load the movie async, this call will return immediately but may return a movie that is not fully formed |
status = NewMovieFromDataRef(&wdr->fMovie, newMovieActive | newMovieAsyncOK , &ignoreResID, dataRef, dataRefType); |
require_noerr(status, CantGetMovie); |
SetMovieGWorld(wdr->fMovie, GetWindowPort(aWindowRef), NULL); |
// because we open movies in an async fashion install a timer so we can check the movie |
// status before actually opening the window and attaching the carbon movie control |
// from this point on the rest of the movie loading, window showing, movie control |
// creation mechanism is done from the carbon timer routine Timer_AsyncMovieLoading |
status = InstallEventLoopTimer(GetMainEventLoop(), kEventDurationNoWait, kEventDurationSecond / 60, Timer_AsyncMovieLoading, aWindowRef, &wdr->fAsyncLoadingTimer); |
CFRelease(windowTitle); |
return status; |
CantCreateWindow: |
CantGetWindowData: |
if (NULL != dataRef) |
DisposeHandle(dataRef); |
CantGetMovie: |
if (NULL != aWindowRef) |
DisposeWindow(aWindowRef); |
CFRelease(windowTitle); |
CantCreateURL: |
CantCreateDataRef: |
BadParameter: |
return status; |
} // Do_OpenAWindow |
/***************************************************** |
* |
* Do_OpenWindows(void) |
* |
* Purpose: called when user selects "Open..." item from "File" menu |
* |
* Inputs: none |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Do_OpenWindows(void) |
{ |
OSStatus status; |
NavDialogCreationOptions navOptions; |
status = NavGetDefaultDialogCreationOptions(&navOptions); |
require_noerr(status, CantGetDefaultOptions); |
// value identifies which set of dialog preferences Nav should use |
navOptions.preferenceKey = 1; |
NavDialogRef theDialog = NULL; |
status = NavCreateChooseFileDialog(&navOptions, NULL, NULL, NULL, Handle_NavFilter, NULL, &theDialog); |
require_noerr(status, CantCreateDialog); |
status = NavDialogRun(theDialog); |
require_noerr(status, CantRunDialog); |
NavReplyRecord aNavReplyRecord; |
status = NavDialogGetReply(theDialog, &aNavReplyRecord); |
require((noErr == status) || (userCanceledErr == status), CantGetReply); |
NavDialogDispose(theDialog); |
theDialog = NULL; |
if (aNavReplyRecord.validRecord) |
status = Do_OpenDocs(aNavReplyRecord.selection); |
else |
status = userCanceledErr; |
NavDisposeReply(&aNavReplyRecord); |
CantGetReply: |
CantRunDialog: |
if (NULL != theDialog) |
NavDialogDispose(theDialog); |
CantCreateDialog: |
CantGetDefaultOptions: |
return status; |
} // Do_OpenWindows |
/***************************************************** |
* |
* Do_OpenDocs(inDocumentsList) |
* |
* Purpose: open docs in inDocumentsList |
* |
* Notes: called by Do_OpenWindows() ("File/Open" menu item) & Handle_OpenDocuments() ('odoc' AppleEvent) |
* |
* Inputs: inDocumentsList - list of AEObjects (files) |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Do_OpenDocs(AEDescList inDocumentsList) |
{ |
long index, count = 0; |
OSStatus status = AECountItems(&inDocumentsList, &count); |
require_noerr(status, CantGetCount); |
for (index = 1; index <= count; index++) |
{ |
FSRef tFSRef; |
status = AEGetNthPtr(&inDocumentsList, index, typeFSRef, NULL, NULL, &tFSRef, sizeof(FSRef), NULL); |
require_orelse_continue(noErr == status); |
Boolean aliasFileFlag, folderFlag; |
status = FSIsAliasFile(&tFSRef, &aliasFileFlag, &folderFlag); |
require_orelse_continue(noErr == status); |
if (!folderFlag) { |
status = Do_OpenAWindow(&tFSRef, NULL, NULL); |
} else if (gOpenFolderContents) { |
Append_FolderItemsToAEDescList(&tFSRef, inDocumentsList); |
status = AECountItems(&inDocumentsList, &count); |
} |
require_orelse_continue(noErr == status); |
} |
CantGetCount: |
return status; |
} // Do_OpenDocs |
/***************************************************** |
* |
* Do_Save(inWindow) |
* |
* Purpose: save the data contained in the window |
* |
* Notes: called by Handle_CommandProcess() & Handle_NavEventCallback() |
* |
* Inputs: inWindow - window to save |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Do_Save(WindowRef inWindow) |
{ |
FSSpec tFSSpec; |
FInfo fndrInfo; |
DataHandler dh; |
OSStatus status = noErr; |
if (NULL == inWindow) { |
inWindow = GetFrontWindowOfClass(kDocumentWindowClass, true); |
} |
require(NULL != inWindow, CantGetWindow); |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(inWindow); |
require(NULL != wdr, CantGetWindowData); |
// if the window as a proxy icon we know there's a data reference |
// associated with the window, if not we need to save to a new file |
status = GetWindowProxyFSSpec(inWindow, &tFSSpec); |
if (status != noErr) |
return Do_SaveAs(inWindow); |
status = FSpGetFInfo(&tFSSpec, &fndrInfo); |
require_noerr(status, CantGetFInfo); |
// if the file was not already a 'MooV' file then we must save it with a different name |
if (fndrInfo.fdType != MovieFileType) |
return Do_SaveAs(inWindow); |
////////// |
// |
// if we get here we're just doing a straight Save and we already have a dataRef associated |
// with the Movie -- open the movie storage location and just update the Movie atom |
// |
////////// |
// update the preferred volume setting |
UpdateMovieVolumeSetting(wdr->fMovie); |
status = OpenMovieStorage(wdr->fDataRef, wdr->fDataRefType, kDataHCanWrite, &dh); |
require_noerr(status, CantSave); |
status = UpdateMovieInStorage(wdr->fMovie, dh); |
CloseMovieStorage(dh); |
require_noerr(status, CantSave); |
SetWindowModified(inWindow, false); |
if (wdr->fClosing) { |
TransitionWindow(inWindow, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL); |
DisposeWindow(inWindow); |
} |
Test_AreWeFinished(); |
CantSave: |
CantGetFInfo: |
CantGetWindowData: |
CantGetWindow: |
return status; |
} // Do_Save |
/***************************************************** |
* |
* Do_SaveAs(inWindow) |
* |
* Purpose: save the data contained in the window with a new or different name |
* |
* Notes: called by Handle_CommandProcess() & Do_Save() |
* |
* Inputs: inWindow - window to save |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Do_SaveAs(WindowRef inWindow) |
{ |
OSStatus status = noErr; |
if (NULL == inWindow) { |
inWindow = GetFrontWindowOfClass(kDocumentWindowClass, true); |
} |
require(NULL != inWindow, CantGetWindow); |
NavDialogCreationOptions navOptions; |
status = NavGetDefaultDialogCreationOptions(&navOptions); |
require_noerr(status, CantGetDefaultOptions); |
CFStringRef theFileName; |
CopyWindowTitleAsCFString(inWindow, &theFileName); |
CFMutableStringRef newFileName = CFStringCreateMutableCopy(NULL, 0, theFileName); |
CFRelease(theFileName); |
CFIndex len = CFStringGetLength(newFileName); |
if (len > 255) len = 255; |
UniChar buffer[255]; |
CFStringGetCharacters(newFileName, CFRangeMake(0, len), buffer); |
UniCharCount extIndex; |
status = LSGetExtensionInfo(len, buffer, &extIndex); |
require_noerr(status, CantGetExtension); |
if (extIndex != kLSInvalidExtensionIndex) { |
CFStringReplace(newFileName, CFRangeMake(extIndex, len-extIndex), CFSTR("mov")); |
} else { |
CFStringAppend(newFileName, CFSTR(".mov")); |
} |
navOptions.preferenceKey = 2; // value identifies which set of dialog preferences Nav should use |
navOptions.modality = kWindowModalityWindowModal; |
navOptions.parentWindow = inWindow; |
navOptions.optionFlags |= kNavPreserveSaveFileExtension; |
navOptions.saveFileName = newFileName; |
NavDialogRef theDialog = NULL; |
status = NavCreatePutFileDialog(&navOptions, kTXNTextensionFile, kTXNTextensionFile, Handle_NavEventCallback, (void *)inWindow, &theDialog); |
CFRelease(newFileName); |
require_noerr(status, CantCreateDialog); |
status = NavDialogRun(theDialog); |
require_noerr(status, CantRunDialog); |
return status; |
CantRunDialog: |
if (NULL != theDialog) |
NavDialogDispose(theDialog); |
CantCreateDialog: |
CantGetExtension: |
CantGetDefaultOptions: |
CantGetWindow: |
return status; |
} // Do_SaveAs |
/***************************************************** |
* |
* Do_CleanUp(void) |
* |
* Purpose: called when we get the quit event, checks for unsaved documents, blocks the quit process if need be |
* |
* Inputs: none |
* |
* Returns: OSStatus - noErr indicates that the user has to save some documents, blocks the quitting process |
* eventNotHandledErr indicates that the quit process can continue since there are no unsaved documents |
*/ |
static OSStatus Do_CleanUp(void) |
{ |
UInt32 count = 0; |
WindowRef lastWindow, aWindowRef = GetFrontWindowOfClass(kDocumentWindowClass, true); |
for (; NULL != aWindowRef;) { |
lastWindow = aWindowRef; |
aWindowRef = GetNextWindowOfClass(lastWindow, kDocumentWindowClass, true); |
if (gRememberLast) |
AddTo_LastWindows(lastWindow); // add this windows info to collection of last window info |
if (IsWindowModified(lastWindow)) { |
count++; |
} else { |
TransitionWindow(lastWindow, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL); |
DisposeWindow(lastWindow); |
} |
} |
if (gRememberLast) |
AddTo_LastWindows(NULL); // NULL forces the collected info to be written to the prefs file |
// returning eventNotHandledErr means we will continue with the quitting process |
if (count == 0) |
return eventNotHandledErr; |
gIsQuitting = true; |
if (count == 1) { |
Test_AreWeFinished(); |
// returning noErr means we will stop the quitting process to allow the user to save any unsaved documents |
return noErr; |
} |
OSStatus status = noErr; |
NavDialogCreationOptions navOptions; |
NavDialogRef theDialog = NULL; |
status = NavGetDefaultDialogCreationOptions(&navOptions); |
require_noerr(status, CantGetDefaultOptions); |
navOptions.preferenceKey = 4; |
status = NavCreateAskReviewDocumentsDialog(&navOptions, count, Handle_NavEventCallback, NULL, &theDialog); |
require_noerr(status, CantCreateDialog); |
status = NavDialogRun(theDialog); |
require_noerr(status, CantRunDialog); |
// returning noErr means we will stop the quitting process to allow the user to save any unsaved documents |
return noErr; |
CantRunDialog: |
if (NULL != theDialog) |
NavDialogDispose(theDialog); |
CantCreateDialog: |
CantGetDefaultOptions: |
return status; |
} // Do_CleanUp |
/***************************************************** |
* |
* AddTo_LastWindows(WindowRef inWindow) |
* |
* Purpose: save the window info to use on next application launch |
* |
* Inputs: inWindow - if !NULL append this windows info to gOpenOnLaunchCFArrayRef |
* - if NULL, save gOpenOnLaunchCFArrayRef to applicaiton prefs |
* |
* Returns: none |
*/ |
static void AddTo_LastWindows(WindowRef inWindow) |
{ |
if (NULL != inWindow) |
{ |
if (NULL == gOpenOnLaunchCFArrayRef) { |
WindowRef tWindowRef = GetFrontWindowOfClass( kDocumentWindowClass, true); |
CFIndex count = 0; // holds count of windows |
while (tWindowRef) { |
count++; |
tWindowRef = GetNextWindowOfClass(tWindowRef, kDocumentWindowClass, true); |
} |
gOpenOnLaunchCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks); |
} |
if (NULL != gOpenOnLaunchCFArrayRef) { |
CFMutableDictionaryRef tCFMutableDictionaryRef = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); |
if (NULL != tCFMutableDictionaryRef) { |
OSStatus status; |
FSSpec tFSSpec; |
status = GetWindowProxyFSSpec(inWindow, &tFSSpec); |
if (noErr == status) { |
FSRef tFSRef; |
OSErr err = FSpMakeFSRef(&tFSSpec, &tFSRef); |
if (noErr == err) { |
AliasHandle tAliasHdl; |
err = FSNewAlias(NULL, &tFSRef, &tAliasHdl); |
if (noErr == err) { |
CFDataRef tCFDataRef = CFDataCreate(kCFAllocatorDefault, (UInt8*) *tAliasHdl, GetHandleSize((Handle) tAliasHdl)); |
if (NULL != tCFDataRef) { |
CFDictionaryAddValue(tCFMutableDictionaryRef, kOpenWindowAlisKey, tCFDataRef); |
CFRelease(tCFDataRef); |
} |
DisposeHandle((Handle) tAliasHdl); |
} |
} |
} |
if (gRememberBounds) { |
Rect globalBounds; |
status = GetWindowBounds(inWindow, kWindowStructureRgn, &globalBounds); |
if (noErr == status) { |
CFDataRef tCFDataRef = CFDataCreate(kCFAllocatorDefault, (UInt8*) &globalBounds, sizeof(globalBounds)); |
if (NULL != tCFDataRef) { |
CFDictionaryAddValue(tCFMutableDictionaryRef, kOpenWindowBoundsKey, tCFDataRef); |
CFRelease(tCFDataRef); |
} |
} |
} |
CFArrayAppendValue(gOpenOnLaunchCFArrayRef, (void*) tCFMutableDictionaryRef); |
CFRelease(tCFMutableDictionaryRef); |
} |
} |
} else { |
if (NULL != gOpenOnLaunchCFArrayRef) { |
// set the preferences |
CFPreferencesSetAppValue(kOpenWindowsPref, gOpenOnLaunchCFArrayRef, kCFPreferencesCurrentApplication); |
// sync to disk |
(void) CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); |
CFRelease(gOpenOnLaunchCFArrayRef); |
gOpenOnLaunchCFArrayRef = NULL; |
} |
} |
} // AddTo_LastWindows |
/***************************************************** |
* |
* Open_LastWindows() |
* |
* Purpose: open the windows that were saved at last quit |
* |
* Inputs: none |
* |
* Returns: none |
*/ |
static void Open_LastWindows(void) |
{ |
CFPropertyListRef tCFPropertyListRef = CFPreferencesCopyAppValue(kOpenWindowsPref, kCFPreferencesCurrentApplication); |
require(NULL != tCFPropertyListRef, CantGetPropertyList); |
require(CFArrayGetTypeID() == CFGetTypeID(tCFPropertyListRef), CantGetPropertyList); |
CFIndex index, count = CFArrayGetCount((CFArrayRef) tCFPropertyListRef); |
for (index = count - 1; index >= 0; index--) |
{ |
CFDictionaryRef tCFDictionaryRef = (CFDictionaryRef) CFArrayGetValueAtIndex((CFArrayRef) tCFPropertyListRef, index); |
require_orelse_continue((NULL != tCFDictionaryRef) && (CFDictionaryGetTypeID() == CFGetTypeID(tCFDictionaryRef))); |
CFDataRef tCFDataRef; |
require_orelse_continue(CFDictionaryGetValueIfPresent(tCFDictionaryRef, kOpenWindowAlisKey, (const void **) &tCFDataRef)); |
CFIndex dataSize = CFDataGetLength(tCFDataRef); |
AliasHandle tAliasHdl = (AliasHandle) NewHandle(dataSize); |
require_orelse_continue(NULL != tAliasHdl); |
CFDataGetBytes(tCFDataRef, CFRangeMake(0, dataSize), (UInt8*) *tAliasHdl); |
FSRef tFSRef; |
Boolean wasChanged; |
OSErr err = FSResolveAlias(NULL, tAliasHdl, &tFSRef, &wasChanged); |
require_orelse_continue(noErr == err); |
CFURLRef tCFURLRef = CFURLCreateFromFSRef(kCFAllocatorDefault, &tFSRef); |
require_orelse_continue(NULL != tCFURLRef); |
Rect globalBounds, *pBounds = NULL; |
if (gRememberBounds) |
{ |
if (CFDictionaryGetValueIfPresent(tCFDictionaryRef, kOpenWindowBoundsKey, (const void **) &tCFDataRef)) |
{ |
CFDataGetBytes(tCFDataRef, CFRangeMake(0, sizeof(globalBounds)), (UInt8*) &globalBounds); |
pBounds = &globalBounds; |
} |
} |
Do_OpenAWindow(&tFSRef, NULL, pBounds); |
CFRelease(tCFURLRef); |
} // for/next |
CFRelease(tCFPropertyListRef); |
// delete old preferences |
CFPreferencesSetAppValue(kOpenWindowsPref, NULL, kCFPreferencesCurrentApplication); |
// sync to disk |
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); |
CantGetPropertyList: |
return; |
} // Open_LastWindows |
/***************************************************** |
* |
* Test_AreWeFinished(void) |
* |
* Purpose: handling all unsaved documents one by one until they are all gone and then quit |
* |
* Inputs: none |
* |
* Returns: none |
*/ |
static void Test_AreWeFinished(void) |
{ |
if (gIsQuitting) { |
WindowRef aWindowRef = GetFrontWindowOfClass(kDocumentWindowClass, true); |
if (NULL == aWindowRef) { |
QuitApplicationEventLoop(); |
} else { |
EventRef theEvent; |
CreateEvent(NULL, kEventClassWindow, kEventWindowClose, GetCurrentEventTime(), kEventAttributeUserEvent, &theEvent); |
SendEventToEventTarget(theEvent, GetWindowEventTarget(aWindowRef)); |
ReleaseEvent(theEvent); |
} |
} |
} // Test_AreWeFinished |
/***************************************************** |
* |
* Append_FolderItemsToAEDescList(inFSRef, inDocumentsList) |
* |
* Purpose: handling all unsaved documents one by one until they are all gone and then quit |
* |
* Inputs: inFSRef - FSRef to folder |
* inDocumentsList - AEDescList to append folder items to |
* |
* Returns: none |
*/ |
static void Append_FolderItemsToAEDescList(const FSRef* inFSRef, AEDescList inDocumentsList) |
{ |
long listCount = 0; |
OSStatus status = AECountItems(&inDocumentsList, &listCount); |
require_noerr(status, CantGetCount); |
FSRef** tFSRefHdl; |
ItemCount index, count; |
Boolean containerChanged; |
status = FSGetDirectoryItems(inFSRef, &tFSRefHdl, &count, &containerChanged); |
for (index = 0; index < count; index++) { |
FSRef tFSRef = (*tFSRefHdl)[index]; |
Boolean aliasFileFlag, folderFlag; |
status = FSIsAliasFile(&tFSRef, &aliasFileFlag, &folderFlag); |
require_orelse_continue(noErr == status); |
if (!folderFlag) { // append to inDocumentsList |
status = AEPutPtr(&inDocumentsList, ++listCount, typeFSRef, &tFSRef, sizeof(FSRef)); |
require_orelse_continue(noErr == status); |
} |
else if (gOpenFolderRecursive) |
Append_FolderItemsToAEDescList(&tFSRef, inDocumentsList); |
} |
CantGetCount: |
return; |
} // Append_FolderItemsToAEDescList |
/***************************************************** |
* |
* FSGetDirectoryItems(inContainerFSRef, outFSRefHandle, outNumRefs, outContainerChanged) |
* |
* Purpose: create a handle of FSRef's for all the items in the provided container FSRef |
* |
* Inputs: inContainerFSRef - FSRef for the container |
* outFSRefHandle - address of handle of array of FSRef's |
* outNumRefs - number of FSRef's in output array (handle) |
* outContainerChanged - Boolean, true if container changes while being iterated |
* |
* Returns: OSErr - error code (0 == no error) |
*/ |
static OSErr FSGetDirectoryItems(const FSRef *inContainerFSRef, FSRef ***outFSRefHandle, ItemCount *outNumRefs, Boolean *outContainerChanged) |
{ |
// Grab items 10 at a time. |
enum { kMaxItemsPerBulkCall = 10 }; |
OSErr result; |
OSErr memResult; |
FSIterator iterator; |
FSRef refs[kMaxItemsPerBulkCall]; |
ItemCount actualObjects; |
Boolean changed; |
// check parameters |
require_action((NULL != outFSRefHandle) && (NULL != outNumRefs) && (NULL != outContainerChanged), |
BadParameter, result = paramErr); |
*outNumRefs = 0; |
*outContainerChanged = false; |
*outFSRefHandle = (FSRef**) NewHandle(0); |
require_action(NULL != *outFSRefHandle, NewHandleFailed, result = memFullErr); |
// open an FSIterator |
result = FSOpenIterator(inContainerFSRef, kFSIterateFlat, &iterator); |
require_noerr(result, FSOpenIterator); |
// Call FSGetCatalogInfoBulk in loop to get all items in the container |
do |
{ |
result = FSGetCatalogInfoBulk(iterator, kMaxItemsPerBulkCall, &actualObjects, |
&changed, kFSCatInfoNone, NULL, refs, NULL, NULL); |
// if the container changed, set outContainerChanged for output, but keep going |
if ( changed ) |
{ |
*outContainerChanged = changed; |
} |
// any result other than noErr and errFSNoMoreItems is serious |
require((noErr == result) || (errFSNoMoreItems == result), FSGetCatalogInfoBulk); |
// add objects to output array and count |
if ( 0 != actualObjects ) |
{ |
// concatenate the FSRefs to the end of the handle |
PtrAndHand(refs, (Handle)*outFSRefHandle, actualObjects * sizeof(FSRef)); |
memResult = MemError(); |
require_noerr_action(memResult, MemoryAllocationFailed, result = memResult); |
*outNumRefs += actualObjects; |
} |
} while ( noErr == result ); |
verify_noerr(FSCloseIterator(iterator)); // closing an open iterator should never fail, but... |
return ( noErr ); |
/**********************/ |
MemoryAllocationFailed: |
FSGetCatalogInfoBulk: |
// close the iterator |
verify_noerr(FSCloseIterator(iterator)); |
FSOpenIterator: |
// dispose of handle if already allocated and clear the outputs |
if ( NULL != *outFSRefHandle ) |
{ |
DisposeHandle((Handle)*outFSRefHandle); |
*outFSRefHandle = NULL; |
} |
*outNumRefs = 0; |
NewHandleFailed: |
BadParameter: |
return ( result ); |
} // FSGetDirectoryItems |
/***************************************************** |
* |
* Save_WithFSRefAndWindow(inFSRef, inWindow) |
* |
* Purpose: save the text data contained in the window in the specified file |
* |
* Notes: Called by Handle_NavEventCallback |
* |
* Inputs: inFSRef - reference to file |
* inWindow - reference to window |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Save_WithFSRefAndWindow(const FSRef* inFSRef, WindowRef inWindow) |
{ |
OSStatus status = paramErr; |
Movie newMovie; |
Handle dataRef; |
OSType dataRefType; |
FSSpec tFSSpec; |
long flattenMovieFlags = flattenAddMovieToDataFork | flattenForceMovieResourceBeforeMovieData; |
long createMovieFlags = createMovieFileDontOpenFile | createMovieFileDeleteCurFile; |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(inWindow); |
require(NULL != wdr, CantGetWindowData); |
status = FSGetCatalogInfo(inFSRef, kFSCatInfoNone, NULL, NULL, &tFSSpec, NULL); |
require_noerr(status, CantGetFSSpec); |
status = QTNewDataReferenceFromFSRef(inFSRef, 0, &dataRef, &dataRefType); |
require_noerr(status, CantCreateDataRef); |
newMovie = FlattenMovieDataToDataRef(wdr->fMovie, flattenMovieFlags, dataRef, dataRefType, FOUR_CHAR_CODE('TVOD'), smSystemScript, createMovieFlags); |
status = GetMoviesError(); |
require_noerr_action(status, CantSave, Display_SaveAsErrorSheet(inWindow, status)); |
// make sure the file type is MovieFileType |
FInfo fndrInfo; |
status = FSpGetFInfo(&tFSSpec, &fndrInfo); |
if (noErr == status) { |
if (MovieFileType != fndrInfo.fdType) { |
fndrInfo.fdType = MovieFileType; |
status = FSpSetFInfo(&tFSSpec, &fndrInfo); |
} |
} |
////////// |
// |
// if we get here we've successfully flattened to a new movie file and need to do a few things: |
// 1) close down the current Movie |
// 2) install the new Movie in its place |
// 3) save or replace the data reference |
// |
////////// |
RemoveWindowProxy(inWindow); |
SetWindowModified(inWindow, false); |
// dispose of the existing carbon movie control |
DisposeControl(wdr->fMovieControl); |
// get rid of the old data reference handle |
if (wdr->fDataRef) { |
DisposeHandle(wdr->fDataRef); |
} |
// update what we need |
wdr->fMovie = newMovie; |
wdr->fDataRef = dataRef; |
wdr->fDataRefType = dataRefType; |
// complete the setup |
SetMovieActive(wdr->fMovie, true); |
SetMovieGWorld(wdr->fMovie, GetWindowPort(inWindow), NULL); |
status = Do_CreateMovieControl(inWindow, true); |
return status; |
CantSave: |
if (NULL != dataRef) |
DisposeHandle(dataRef); |
CantCreateDataRef: |
CantGetFSSpec: |
CantGetWindowData: |
return status; |
} // Save_WithFSRefAndWindow |
/*****************************************************/ |
#pragma mark - |
#pragma mark * Preferences * |
/***************************************************** |
* |
* Get_Preferences() |
* |
* Purpose: get's the users preferences |
* |
* Inputs: none |
* |
* Returns: none |
*/ |
static void Get_Preferences(void) |
{ |
Boolean keyExistsAndHasValidFormat, tBoolean; |
tBoolean = CFPreferencesGetAppBooleanValue(kOpenFolderContentsPref, kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat); |
if (keyExistsAndHasValidFormat) |
gOpenFolderContents = tBoolean; |
tBoolean = CFPreferencesGetAppBooleanValue(kOpenFolderRecursivePref, kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat); |
if (keyExistsAndHasValidFormat) |
gOpenFolderRecursive = tBoolean; |
tBoolean = CFPreferencesGetAppBooleanValue(kRememberLastPref, kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat); |
if (keyExistsAndHasValidFormat) |
gRememberLast = tBoolean; |
tBoolean = CFPreferencesGetAppBooleanValue(kRememberBoundsPref, kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat); |
if (keyExistsAndHasValidFormat) |
gRememberBounds = tBoolean; |
} // Get_Preferences |
/***************************************************** |
* |
* Set_Preferences() |
* |
* Purpose: Set's the users preferences |
* |
* Inputs: none |
* |
* Returns: none |
*/ |
static void Set_Preferences(void) |
{ |
CFPreferencesSetAppValue(kOpenFolderContentsPref, gOpenFolderContents ? kCFBooleanTrue : kCFBooleanFalse, kCFPreferencesCurrentApplication); |
CFPreferencesSetAppValue(kOpenFolderRecursivePref, gOpenFolderRecursive ? kCFBooleanTrue : kCFBooleanFalse, kCFPreferencesCurrentApplication); |
CFPreferencesSetAppValue(kRememberLastPref, gRememberLast ? kCFBooleanTrue : kCFBooleanFalse, kCFPreferencesCurrentApplication); |
CFPreferencesSetAppValue(kRememberBoundsPref, gRememberBounds ? kCFBooleanTrue : kCFBooleanFalse, kCFPreferencesCurrentApplication); |
// sync to disk |
(void) CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); |
} // Set_Preferences |
/*****************************************************/ |
#pragma mark - |
#pragma mark * Utility Functions * |
/***************************************************** |
* |
* Send_WindowCloseEvent() |
* |
* Purpose: do this! |
* |
* Inputs: none |
* |
* Returns: none |
*/ |
static void Send_WindowCloseEvent(WindowRef inWindow) |
{ |
EventRef aEvent; |
CreateEvent(NULL, kEventClassWindow, kEventWindowClose, GetCurrentEventTime(), kEventAttributeUserEvent, &aEvent ); |
SetEventParameter(aEvent, kEventParamDirectObject, typeWindowRef, sizeof(inWindow), &inWindow); |
SendEventToWindow(aEvent, inWindow); |
ReleaseEvent(aEvent); |
} // Send_WindowCloseEvent |
/***************************************************** |
* |
* Get_MovieGrowBounds(WindowDataPtr inWdr, HIRect *inOriginalBounds, HIRect *outBestRect) |
* |
* Purpose: called from Handle_WindowBoundsChanges to report calculated grow bounds |
* |
* Inputs: inWdr - window reference |
* inOriginalBounds - the bounds we starting with |
* |
* Outputs: outBestRect - bounds the movie fits into while retaining its aspect ratio |
* |
* Returns: none |
*/ |
static void Get_MovieGrowBounds(WindowDataPtr inWdr, HIRect *inOriginalBounds, HIRect *outBestRect) |
{ |
Rect movieRect; |
float movieRatio, viewRatio; |
float movieWidth, movieHeight; |
float viewWidth, viewHeight; |
float newWidth, newHeight; |
GetMovieNaturalBoundsRect(inWdr->fMovie, &movieRect); |
MacOffsetRect(&movieRect, -movieRect.left, -movieRect.top); |
// make sure that the movie has a non-zero width and a |
// minimum height of 16 because we have a movie controller |
if (movieRect.right - movieRect.left == 0) { |
// don't do the ratio stuff in this case |
MacSetRect(&movieRect, 0, 0, 320, 16); |
// origin doesn't change |
outBestRect->origin = inOriginalBounds->origin; |
newWidth = inOriginalBounds->size.width - kDistanceFromHorizontalEdge; |
newHeight = 16; |
} else { |
// calculate bestRect so that the movie fits into the Window while retaining its aspect ratio |
movieWidth = movieRect.right; |
movieHeight = movieRect.bottom; |
viewWidth = inOriginalBounds->size.width; |
viewHeight = inOriginalBounds->size.height; |
// subtract slop we added to border the movie |
viewWidth -= kDistanceFromHorizontalEdge; |
viewHeight -= kDistanceFromVerticalEdge; |
// origin doesn't change |
outBestRect->origin = inOriginalBounds->origin; |
movieRatio = movieWidth / movieHeight; |
viewRatio = viewWidth / viewHeight; |
if (movieRatio > viewRatio) { |
newHeight = viewWidth / movieRatio; |
newWidth = newHeight * movieRatio; |
} else { |
newWidth = viewHeight * movieRatio; |
newHeight = newWidth / movieRatio; |
} |
} |
// add back slop to boarder the movie |
outBestRect->size.width = newWidth + kDistanceFromHorizontalEdge; |
outBestRect->size.height = newHeight + kDistanceFromVerticalEdge; |
return; |
} // Get_MovieGrowBounds |
/***************************************************** |
* |
* Get_WindowPositionFromMovie(Movie inMovie, HIPoint *outPoint) |
* |
* Purpose: returns the saved window position from a movie |
* |
* Inputs: inMovie - a movie |
* |
* Outputs: outPoint - HIPoint indicating window position |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Get_WindowPositionFromMovie(Movie inMovie, HIPoint *outPoint) |
{ |
UserData userData = NULL; |
Point aPoint; |
OSStatus status = paramErr; |
// make sure we've got a movie |
require(NULL != inMovie, DontHaveAMovie); |
// get the movie's user data list |
userData = GetMovieUserData(inMovie); |
if (userData != NULL) { |
// get the saved window location |
status = GetUserDataItem(userData, &aPoint, sizeof(Point), FOUR_CHAR_CODE('WLOC'), 0); |
if (noErr == status) { |
outPoint->y = EndianS16_BtoN(aPoint.v); |
outPoint->x = EndianS16_BtoN(aPoint.h); |
} |
} |
DontHaveAMovie: |
return status; |
} // Get_WindowPositionFromMovie |
/***************************************************** |
* |
* Get_MovieControllerType(Movie inMovie) |
* |
* Purpose: returns the movie controller type from the movie |
* |
* Inputs: inMovie - a movie |
* |
* Returns: OSType - FourCC indicating the type of controller we have or kUnknownType |
*/ |
OSType Get_MovieControllerType(Movie inMovie) |
{ |
UserData userData; |
OSType mcType = kUnknownType; |
// make sure we've got a movie |
require(NULL != inMovie, DontHaveAMovie); |
userData = GetMovieUserData(inMovie); |
require(NULL != userData, CantGetUserData); |
if (noErr != GetUserDataItem(userData, &mcType, sizeof(mcType), kUserDataMovieControllerType, 0)) mcType = kUnknownType; |
CantGetUserData: |
DontHaveAMovie: |
return mcType; |
} |
/***************************************************** |
* |
* Set_WindowTitleFromMovie(Movie inMovie, WindowRef inWindowRef) |
* |
* Purpose: retrieves the name from a movie and sets the window title |
* |
* Inputs: inMovie - a movie |
* inWindowRef - a reference to the current window |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Set_WindowTitleFromMovie(Movie inMovie, WindowRef inWindowRef) |
{ |
UserData userData = NULL; |
CFStringRef windowTitle = NULL; |
OSStatus status = paramErr; |
// make sure we've got a movie |
require(NULL != inMovie, DontHaveAMovie); |
// get the movie's user data list |
userData = GetMovieUserData(inMovie); |
if (userData != NULL) { |
// get and set the name |
Handle theName = NewHandle(0); |
status = GetUserDataText(userData,theName, kUserDataTextFullName, 1, langEnglish); |
if (GetHandleSize(theName) > 0) { |
windowTitle = CFStringCreateWithBytes(kCFAllocatorDefault, (unsigned char *)*theName, GetHandleSize(theName), kCFStringEncodingMacRoman, false); |
if (NULL != windowTitle) { |
SetWindowTitleWithCFString(inWindowRef, windowTitle); |
CFRelease(windowTitle); |
} |
} |
DisposeHandle(theName); |
} |
DontHaveAMovie: |
return status; |
} // Set_WindowTitleFromMovie |
/***************************************************** |
* |
* Set_MouseTrackingRegion(WindowRef inWindowRef) |
* |
* Purpose: called from CreateCarbonControl if we have a VR movie to set a mouse tracking region region |
* see Handle_MouseExitedEvent for handler that gets called when mouse exits this region |
* |
* Inputs: inWindowRef - reference a window |
* |
* Returns: none |
*/ |
static void Set_MouseTrackingRegion(WindowRef inWindowRef) |
{ |
require(NULL != inWindowRef, NoWindowRef); |
WindowDataPtr wdr = (WindowDataPtr)GetWRefCon(inWindowRef); |
require(NULL != wdr, CantGetWindowData); |
RgnHandle region = MCGetControllerBoundsRgn(wdr->fMovieController); |
require(NULL != region, NoRegion); |
if (NULL != wdr->fMouseTrackingRef) { |
// we have an old MouseTrackingRegion so get rid of it |
ReleaseMouseTrackingRegion(wdr->fMouseTrackingRef); |
wdr->fMouseTrackingRef = NULL; |
} |
MouseTrackingRegionID id = { 'QTCS', 100 }; |
CreateMouseTrackingRegion(inWindowRef, region, NULL, kMouseTrackingOptionsStandard, id, GetApplicationEventTarget(), NULL, &wdr->fMouseTrackingRef); |
DisposeRgn(region); |
NoWindowRef: |
CantGetWindowData: |
NoRegion: |
return; |
} // Set_MouseTrackingRegion |
/***************************************************** |
* |
* IsStreamedMovie(Movie inMovie) |
* |
* Purpose: lets us know if we have a streaming movie |
* |
* Inputs: inMovie - a movie |
* |
* Returns: Boolean - true if we have a streaming track |
*/ |
static Boolean IsStreamedMovie(Movie inMovie) |
{ |
if (NULL == inMovie) return false; |
return (GetMovieIndTrackType(inMovie, 1, kQTSStreamMediaType, movieTrackMediaType | movieTrackEnabledOnly) != NULL); |
} // IsStreamedMovie |
/***************************************************** |
* |
* IsVRMovie(Movie inMovie) |
* |
* Purpose: lets us know if we have a VR Movie |
* |
* Inputs: wdr - a pointer to the window data |
* |
* Returns: Boolean - true if we have a VR movie |
*/ |
Boolean IsVRMovie(WindowDataPtr wdr) |
{ |
Track track; |
QTVRInstance qtvr; |
if (NULL == wdr) return false; |
wdr->fIsVRMovie = false; |
// get the first QTVR track in the movie |
track = QTVRGetQTVRTrack(wdr->fMovie, 1); |
require(NULL != track, NoVRTrack); |
QTVRGetQTVRInstance(&qtvr, track, wdr->fMovieController); |
if (NULL != qtvr) wdr->fIsVRMovie = true; |
NoVRTrack: |
return wdr->fIsVRMovie; |
} |
/***************************************************** |
* |
* IsAutoPlayMovie(Movie inMovie) |
* |
* Purpose: lets us know if the movie was set to autoplay |
* |
* Inputs: inMovie - a movie |
* |
* Returns: Boolean - true if the movie has autoplay set |
*/ |
static Boolean IsAutoPlayMovie(Movie inMovie) |
{ |
UserData userData = NULL; |
Boolean isAutoPlay = false; |
OSStatus status; |
// make sure we've got a movie |
require(NULL != inMovie, DontHaveAMovie); |
// get the movie's user data list |
userData = GetMovieUserData(inMovie); |
require(NULL != userData, CantGetUserData); |
status = GetUserDataItem(userData, &isAutoPlay, sizeof(Boolean), kMovieMediaAutoPlay, 1); |
if (noErr != status) isAutoPlay = false; |
DontHaveAMovie: |
CantGetUserData: |
return isAutoPlay; |
} // IsAutoPlayMovie |
/***************************************************** |
* |
* IsMoviePlaying(MovieController inMC) |
* |
* Purpose: lets us know if the movie is playing |
* |
* Inputs: inMC - a movie controller |
* |
* Returns: Boolean - true if the movie is playing |
*/ |
static Boolean IsMoviePlaying(MovieController inMC) |
{ |
Boolean isPlaying = false; |
long someFlags; |
OSStatus status; |
// make sure we've got a movie controller |
require(NULL != inMC, DontHaveMovieController); |
status = MCGetControllerInfo(inMC, &someFlags); |
require_noerr(status, CantGetMCInfo); |
if (someFlags & mcInfoIsPlaying) isPlaying = true; |
CantGetMCInfo: |
DontHaveMovieController: |
return isPlaying; |
} // IsMoviePlaying |
/***************************************************** |
* |
* static Boolean IsMovieInteractive(Movie inMovie) |
* |
* Purpose: lets us know if the movie is interactive, basically does it have a sprite track |
* |
* Inputs: inMovie - a movie |
* |
* Returns: Boolean - true if the movie is interactive |
*/ |
static Boolean IsMovieInteractive(Movie inMovie) |
{ |
if (NULL == inMovie) return false; |
return (GetMovieIndTrackType(inMovie,1, kCharacteristicProvidesActions, movieTrackCharacteristic) != NULL); |
} // IsMovieInteractive |
/***************************************************** |
* |
* HasAudioTrack(Movie inMovie) |
* |
* Purpose: let us know if we have a sound track in the movie |
* |
* Inputs: inMovie - a movie |
* |
* Returns: Boolean - true if we have a sound track |
*/ |
static Boolean HasAudioTrack(Movie inMovie) |
{ |
if (NULL == inMovie) return false; |
return (GetMovieIndTrackType(inMovie, 1, SoundMediaType, movieTrackMediaType | movieTrackEnabledOnly) != NULL); |
} // HasAudioTrack |
/***************************************************** |
* |
* UpdateMovieVolumeSetting(Movie inMovie) |
* |
* Purpose: saves the current volume setting during save |
* |
* Inputs: inMovie - a movie |
* |
* Returns: none |
*/ |
static void UpdateMovieVolumeSetting(Movie inMovie) |
{ |
UInt16 preferredVolume, currentVolume; |
// make sure we've got a movie |
require(NULL != inMovie, DontHaveAMovie); |
preferredVolume = GetMoviePreferredVolume(inMovie); |
currentVolume = GetMovieVolume(inMovie); |
currentVolume = abs(currentVolume); |
if (preferredVolume != currentVolume) { |
SetMoviePreferredVolume(inMovie, currentVolume); |
} |
DontHaveAMovie: |
return; |
} // UpdateMovieVolumeSetting |
/***************************************************** |
* |
* Display_SaveAsErrorSheet(WindowRef inWindow, OSStatus inError) |
* |
* Purpose: if save_as fails we need to display the error |
* |
* Inputs: inWindow - reference to the current window |
* inError - error to display |
* |
* Returns: OSStatus - error code (0 == no error) |
*/ |
static OSStatus Display_SaveAsErrorSheet(WindowRef inWindow, OSStatus inError) |
{ |
CFStringRef error; |
CFStringRef explanation; |
AlertStdCFStringAlertParamRec params; |
DialogRef sheet; |
OSStatus status = noErr; |
require(NULL != inWindow, DontHaveAWindow); |
error = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Error %ld"), inError); |
if (fBsyErr == inError) { |
// this is a common error when saving movies which may share media in the same movie you're attempting to overwrite |
explanation = CFSTR("Couldn't save the file under the new name because that file has already been opened or is in use."); |
} else { |
explanation = CFSTR("Couldn't save the file under the new name."); |
} |
GetStandardAlertDefaultParams(¶ms, kStdCFStringAlertVersionOne); |
status = CreateStandardSheet(kAlertNoteAlert, error, explanation, ¶ms, GetWindowEventTarget(inWindow), &sheet); |
require_noerr(status, CouldntCreateSheet); |
status = ShowSheetWindow(GetDialogWindow(sheet), inWindow); |
CouldntCreateSheet: |
CFRelease(error); |
DontHaveAWindow: |
return status; |
} // Display_SaveAsErrorSheet |
/***************************************************** |
* |
* Display_StandardAlert(OSStatus inError) |
* |
* Purpose: if opening a movie fails let the user know |
* |
* Inputs: inError - error to display |
* |
* Returns: none |
*/ |
static void Display_StandardAlert(OSStatus inError) |
{ |
CFStringRef error; |
CFStringRef explanation; |
AlertStdCFStringAlertParamRec params; |
DialogRef alertRef; |
DialogItemIndex ignore; |
error = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Error %ld"), inError); |
explanation = CFSTR("The Movie failed to load. If you're trying to open a Movie from a URL you may want to check your network connection."); |
GetStandardAlertDefaultParams(¶ms, kStdCFStringAlertVersionOne); |
CreateStandardAlert(kAlertStopAlert, error, explanation, ¶ms, &alertRef); |
RunStandardAlert(alertRef, NULL, &ignore); |
return; |
} // Display_StandardAlert |
/***************************************************** |
* |
* SaveComboBoxValues(ControlRef inComboBox) |
* |
* Purpose: keep entries in the combobox sorted chronologically, and stored in the "HistoryEntries" application preference |
* See "ComboBoxPrefs" Sample for more detail... |
* |
* Inputs: inComboBox - reference a combo box control |
* |
* Returns: none |
*/ |
static void SaveComboBoxValues(ControlRef inComboBox) |
{ |
OSStatus status; |
CFArrayRef cfArray; |
CFIndex count; |
CFStringRef cfString; |
CFMutableArrayRef cfMutableArray = NULL; |
CFStringRef urlString = NULL; |
// Get the combo box list entries |
status = GetControlData(inComboBox, kHIComboBoxDisclosurePart, kHIComboBoxListTag, sizeof(cfArray), (Ptr)&cfArray, NULL); |
// Make a mutable copy for modification |
cfMutableArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, kComboBoxMaxHistory, cfArray); |
// Get the current entry in the text portion |
status = GetControlData(inComboBox, kControlEditTextPart, kControlEditTextCFStringTag, sizeof(CFStringRef), &urlString, NULL); |
// If the current url is in the list, delete it, to add it to the top of the list |
for (count = CFArrayGetCount( cfMutableArray ) - 1 ; count >= 0 ; count--) { |
cfString = (CFStringRef)CFArrayGetValueAtIndex(cfMutableArray, count); |
// Compare each list entry to the current text entry |
// Remove any duplicates |
if (CFStringCompare( cfString, urlString, kCFCompareCaseInsensitive ) == kCFCompareEqualTo) { |
CFArrayRemoveValueAtIndex( cfMutableArray, count ); |
} |
} |
// Remove extra array values beyond kComboBoxMaxHistory |
for (count = CFArrayGetCount(cfMutableArray ) - 1 ; count >= kComboBoxMaxHistory - 1 ; count--) { |
CFArrayRemoveValueAtIndex(cfMutableArray, count); |
} |
// Insert our new entry at the top of the list |
CFArrayInsertValueAtIndex(cfMutableArray, 0, (const void *)urlString); |
CFPreferencesSetAppValue(CFSTR("HistoryEntries"), cfMutableArray, kCFPreferencesCurrentApplication ); |
// Save the modified list to our application "HistoryEntries" preferences |
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); |
if (cfMutableArray != NULL) CFRelease(cfMutableArray); |
} // SaveComboBoxValues |
/***************************************************** |
* |
* RestoreComboBoxValues(ControlRef inComboBox) |
* |
* Purpose: read in the combo box preferences and populate the combo box with those "HistoryEntries" preferences |
* See "ComboBoxPrefs" Sample for more detail... |
* |
* Inputs: inComboBox - reference a combo box control |
* |
* Returns: none |
*/ |
static void RestoreComboBoxValues(ControlRef inComboBox) |
{ |
CFArrayRef cfArray = NULL; |
cfArray = (CFArrayRef)CFPreferencesCopyAppValue(CFSTR("HistoryEntries"), kCFPreferencesCurrentApplication); |
if (cfArray != NULL) { |
CFStringRef urlString = CFArrayGetValueAtIndex(cfArray, 0); |
SetControlData(inComboBox, kHIComboBoxEditTextPart, kControlEditTextCFStringTag, sizeof(CFStringRef), &urlString); |
SetControlData(inComboBox, kHIComboBoxDisclosurePart, kHIComboBoxListTag, sizeof(cfArray), &cfArray); |
CFRelease(cfArray); |
} |
} // RestoreComboBoxValues |
#if __ppc__ |
/***************************************************** |
* |
* Get_AltiVecTypeAvailable(void) |
* |
* Purpose: lets us know if AltiVec is available |
* |
* Returns: 0 for scalar only, 1 for AltiVec, may return > 1 in the future |
*/ |
static int Get_AltiVecTypeAvailable(void) |
{ |
int sels[2] = { CTL_HW, HW_VECTORUNIT }; |
int vType = 0; // 0 == scalar only |
size_t length = sizeof(vType); |
int error = sysctl(sels, 2, &vType, &length, NULL, 0); |
if(0 == error) return vType; |
return 0; |
} // Get_AltiVecTypeAvailable |
/***************************************************** |
* |
* vFadeDockTile(PixMapHandle inStartPixMap, PixMapHandle inEndPixMap, PixMapHandle inDestPixMap, Rect *inBounds, long inAmount) |
* |
* Purpose: Fades one PixMap to another PixMap drawing the result to a third, altivec implementation |
* |
* Inputs: inStartPixMap - PixMap containing the source image |
* inEndPixMap - PixMap containing the end image |
* inDestPixMap - Destination PixMap, the result of the fade is drawn here |
* inBounds - size of the destination |
* inAmount - blend value |
* |
* Returns: none |
*/ |
static void vFadeDockTile(PixMapHandle inStartPixMap, PixMapHandle inEndPixMap, PixMapHandle inDestPixMap, Rect *inBounds, long inAmount) |
{ |
Ptr baseAddrS = GetPixBaseAddr(inStartPixMap); |
Ptr baseAddrE = GetPixBaseAddr(inEndPixMap); |
Ptr baseAddrD = GetPixBaseAddr(inDestPixMap); |
UInt32 rowBytesS = QTGetPixMapHandleRowBytes(inStartPixMap); |
UInt32 rowBytesE = QTGetPixMapHandleRowBytes(inEndPixMap); |
UInt32 rowBytesD = QTGetPixMapHandleRowBytes(inDestPixMap); |
UInt32 width, height, h, v; |
width = inBounds->right - inBounds->left; |
height = inBounds->bottom - inBounds->top; |
if(inAmount < 0) inAmount = 0; |
if(inAmount > 0x00FF) inAmount = 0x00FF; |
unsigned char a = inAmount & 0xFF; |
vector unsigned char vOne = vec_splat_u8(1); |
vector unsigned char vOnes = vec_splat_u8(-1); |
vector unsigned char vPermEvenOdd = (vector unsigned char)(0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30); |
vector unsigned char vAmount = vec_lde(0, &a); |
vector unsigned char vMove = vec_lvsl(0, &a); |
vAmount = vec_perm(vAmount, vAmount, vMove); |
vAmount = vec_splat(vAmount, 0); |
vector unsigned char vUnamount = vec_sub(vOnes, vAmount); |
for(v = 0; v < height; v++) { |
int index = 0; |
for(h = 0; h < width; h += 4, index += 16) { |
vector unsigned char vS = vec_ld(index, (unsigned char *)baseAddrS); |
vector unsigned char vE = vec_ld(index, (unsigned char *)baseAddrE); |
vector unsigned short vS_Even = vec_add(vec_mule(vS, vAmount), vec_mule(vS, vOne)); |
vector unsigned short vS_Odd = vec_add(vec_mulo(vS, vAmount), vec_mulo(vS, vOne)); |
vector unsigned short vE_Even = vec_add(vec_mule(vE, vUnamount), vec_mule(vE, vOne)); |
vector unsigned short vE_Odd = vec_add(vec_mulo(vE, vUnamount), vec_mulo(vE, vOne)); |
vector unsigned short v_Even = vec_add(vS_Even, vE_Even); |
vector unsigned short v_Odd = vec_add(vS_Odd, vE_Odd); |
vector unsigned char vD = vec_perm((vector unsigned char)v_Even, (vector unsigned char)v_Odd, vPermEvenOdd); |
vec_st(vD, index, (unsigned char *)baseAddrD); |
} |
baseAddrS += rowBytesS; |
baseAddrE += rowBytesE; |
baseAddrD += rowBytesD; |
} |
return; |
} // vFadeDockTile |
#endif |
/***************************************************** |
* |
* sFadeDockTile(PixMapHandle inStartPixMap, PixMapHandle inEndPixMap, PixMapHandle inDestPixMap, Rect *inBounds, long inAmount) |
* |
* Purpose: fase one PixMap to another PixMap drawing the result to a third, scalar implementation |
* |
* Inputs: inStartPixMap - PixMap containing the source image |
* inEndPixMap - PixMap containing the end image |
* inDestPixMap - Destination PixMap, the result of the fade is drawn here |
* inBounds - size of the destination |
* inAmount - blend value |
* |
* Returns: none |
*/ |
static void sFadeDockTile(PixMapHandle inStartPixMap, PixMapHandle inEndPixMap, PixMapHandle inDestPixMap, Rect *inBounds, long inAmount) |
{ |
Ptr baseAddrS, baseAddrE, baseAddrD; |
long rowBytesS, rowBytesE, rowBytesD; |
long width, height, h, v; |
long unamount; |
baseAddrS = GetPixBaseAddr(inStartPixMap ); |
baseAddrE = GetPixBaseAddr(inEndPixMap); |
baseAddrD = GetPixBaseAddr(inDestPixMap); |
rowBytesS = QTGetPixMapHandleRowBytes(inStartPixMap); |
rowBytesE = QTGetPixMapHandleRowBytes(inEndPixMap); |
rowBytesD = QTGetPixMapHandleRowBytes(inDestPixMap); |
width = inBounds->right - inBounds->left; |
height = inBounds->bottom - inBounds->top; |
if(inAmount < 0) inAmount = 0; |
if(inAmount > 0x0100) inAmount = 0x0100; |
unamount = 0x0100 - inAmount; |
for(v = 0; v < height; v++) { |
UInt32 *pixelS = (UInt32 *)baseAddrS; |
UInt32 *pixelE = (UInt32 *)baseAddrE; |
UInt32 *pixelD = (UInt32 *)baseAddrD; |
for(h = 0; h < width; h++) { |
UInt32 s = pixelS[0]; |
UInt32 e = pixelE[0]; |
UInt32 d; |
d = ((((((s >> 24) & 0x0ff) * inAmount) + (((e >> 24) & 0x0ff) * unamount)) << 16) & 0xff000000) |
| ((((((s >> 16) & 0x0ff) * inAmount) + (((e >> 16) & 0x0ff) * unamount)) << 8) & 0x00ff0000) |
| ((((((s >> 8) & 0x0ff) * inAmount) + (((e >> 8) & 0x0ff) * unamount)) ) & 0x0000ff00) |
| ((((((s ) & 0x0ff) * inAmount) + (((e ) & 0x0ff) * unamount)) >> 8) & 0x000000ff); |
pixelD[0] = d; |
pixelS++; |
pixelE++; |
pixelD++; |
} |
baseAddrS += rowBytesS; |
baseAddrE += rowBytesE; |
baseAddrD += rowBytesD; |
} |
return; |
} // sFadeDockTile |
/*****************************************************/ |
#pragma mark - |
#pragma mark * Do this & that! * |
/***************************************************** |
* |
* Do_This() |
* |
* Purpose: do this! |
* |
* Inputs: none |
* |
* Returns: none |
*/ |
static void Do_This(void) |
{ |
printf("Do This!\n"); |
fflush(stdout); |
} |
/***************************************************** |
* |
* Do_That() |
* |
* Purpose: do that! |
* |
* Inputs: none |
* |
* Returns: none |
*/ |
static void Do_That(void) |
{ |
printf("Do That!\n"); |
fflush(stdout); |
} |
Copyright © 2009 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2009-03-19