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 |
Abstract: A skeleton of modern nib-based and Carbon Events-based Carbon application. |
QuickTimeMovieControl demonstrates how to easily add QuickTime movie playback |
to an application. The meat of the sample is the use of the API CreateMovieControl() |
within the routine DisplayMovieInWindow(). |
With little code, using the "Open URL" menu choice, this sample is able to play |
networked QuickTime media such as streaming mp3s, movies, and more. Or you can |
choose to open a file locally for playback. The NavServices filter should make |
only QuickTime media selectable by taking advantage of CanQuickTimeOpenFile(). |
Version: 1.0 |
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. |
Copyright © 2004 Apple Computer, Inc., All Rights Reserved |
*/ |
#include <Carbon/Carbon.h> |
#include <QuickTime/QuickTime.h> |
#define kDistanceFromBottomOfWindow 16 // We move the movie control up 16 pixels so the window resize thumb doesn't cover the control, this space can also be used to display status, etc. |
struct GlobalAppInfo // Application globals |
{ |
IBNibRef mainNibRef; |
}; |
typedef struct GlobalAppInfo GlobalAppInfo; |
static void InstallAppleEventHandlers( void ); |
static OSStatus DoNewWindow( WindowRef *window ); |
static void DoPreferences( void ); |
static OSStatus DoSomething(); |
static OSStatus NavOpenDocument(); |
static pascal Boolean NavOpenFilterProc( AEDesc *theItem, void *info, NavCallBackUserData callBackUD, NavFilterModes filterMode ); |
CFStringRef GetControlCFString( WindowRef window, OSType signature, SInt32 id ); |
static pascal OSStatus URLWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ); |
void SendWindowCloseEvent( WindowRef window ); |
OSStatus SetWindowProxyFSRef( WindowRef window, FSRef *fsRef ); |
OSStatus GetControlBySigAndID( WindowRef window, OSType signature, SInt32 id, ControlRef *control ); |
static OSStatus DisplayMovieInWindow( WindowRef window, FSRef *fsRef, CFStringRef urlCFString ); |
static pascal OSStatus ParentMovieControlWindowEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ); |
static pascal OSStatus MovieControlEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ); |
static OSStatus OpenDocuments( AEDescList docList ); // Add call to DisplayMovieInWindow() |
static pascal OSStatus CommandProcessEventHandler( EventHandlerCallRef nextHandler, EventRef inEvent, void *userData ); // Change kHICommandNew to behave same as kHICommandOpen |
int main( int argc, char *argv[] ); // Added call to EnterMovies() |
GlobalAppInfo g; |
#pragma mark - |
#pragma mark ¥ Main ¥ |
int main( int argc, char *argv[] ) |
{ |
OSStatus status; |
long response; |
const EventTypeSpec commandProcessEvents[] = { { kEventClassCommand, kEventCommandProcess } }; |
BlockZero( &g, sizeof(g) ); // Initialize our globals |
status = Gestalt( gestaltSystemVersion, &response ); |
if ( ! ((status == noErr) && (response >= 0x00001030)) ) // We require Mac OS X 10.3 or greater to run |
{ |
DialogRef alertDialog; |
CreateStandardAlert( kAlertStopAlert, CFSTR("Mac OS X 10.3 (minimum) is required for this application"), NULL, NULL, &alertDialog ); |
RunStandardAlert( alertDialog, NULL, NULL ); |
ExitToShell(); |
} |
status = EnterMovies(); // Initialize QuickTime |
require_noerr( status, CantInitializeQuickTime ); |
// 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"), &g.mainNibRef ); |
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( g.mainNibRef, CFSTR("MenuBar") ); |
require_noerr( status, CantSetMenuBar ); |
EnableMenuCommand( NULL, kHICommandPreferences ); // Enable Preferences menu item |
InstallAppleEventHandlers(); |
InstallApplicationEventHandler( NewEventHandlerUPP(CommandProcessEventHandler), GetEventTypeCount(commandProcessEvents), commandProcessEvents, NULL, NULL ); |
RunApplicationEventLoop(); // Call the event loop |
CantSetMenuBar: |
CantGetNibRef: |
CantInitializeQuickTime: |
return( status ); |
} |
#pragma mark - |
#pragma mark ¥ AppleEvent Handlers ¥ |
static pascal OSErr HandleAppleEventOapp( const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) |
{ |
return( noErr ); |
} |
static pascal OSErr HandleAppleEventRapp( const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) |
{ |
return( noErr ); |
} |
static pascal OSErr HandleAppleEventOdoc( const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) |
{ |
AEDescList docList; |
OSErr err = AEGetParamDesc( theAppleEvent, keyDirectObject, typeAEList, &docList ); |
require_noerr( err, CantGetDocList ); |
err = OpenDocuments( docList ); |
AEDisposeDesc( &docList ); |
CantGetDocList: |
return( err ); |
} |
static pascal OSErr HandleAppleEventPdoc( const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) |
{ |
return( errAEEventNotHandled ); |
} |
static void InstallAppleEventHandlers( void ) |
{ |
OSErr status; |
status = AEInstallEventHandler( kCoreEventClass, kAEOpenApplication, NewAEEventHandlerUPP(HandleAppleEventOapp), 0, false ); require_noerr( status, CantInstallAppleEventHandler ); |
status = AEInstallEventHandler( kCoreEventClass, kAEReopenApplication, NewAEEventHandlerUPP(HandleAppleEventRapp), 0, false ); require_noerr( status, CantInstallAppleEventHandler ); |
status = AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(HandleAppleEventOdoc), 0, false ); require_noerr( status, CantInstallAppleEventHandler ); |
status = AEInstallEventHandler( kCoreEventClass, kAEPrintDocuments, NewAEEventHandlerUPP(HandleAppleEventPdoc), 0, false ); require_noerr( status, CantInstallAppleEventHandler ); |
// Note: Since RunApplicationEventLoop installs a Quit AE Handler, there is no need to do it here. |
CantInstallAppleEventHandler: |
return; |
} |
#pragma mark - |
#pragma mark ¥ CarbonEvent Handlers ¥ |
static pascal OSStatus CommandProcessEventHandler( EventHandlerCallRef nextHandler, EventRef inEvent, void *userData ) |
{ |
HICommand command; |
WindowRef window; |
static EventHandlerUPP urlWindowEventHandlerUPP; |
OSStatus status = eventNotHandledErr; |
const EventTypeSpec windowEvents[] = { { kEventClassCommand, kEventCommandProcess } }; |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); |
switch ( command.commandID ) |
{ |
case kHICommandNew: |
//status = DoNewWindow( NULL ); // We don't want to create a new window without an image in it |
//break; // So, we'll just fall through to the kHICommandOpen case |
case kHICommandOpen: |
status = NavOpenDocument(); |
break; |
case kHICommandPreferences: |
DoPreferences(); |
break; |
case kHICommandRevert: // Place holders, not handled yet |
case kHICommandPageSetup: |
case kHICommandPrint: |
break; |
case 'NURL': // Open from Network URL |
status = CreateWindowFromNib( g.mainNibRef, CFSTR("URLWindow"), &window ); |
if ( urlWindowEventHandlerUPP == NULL ) urlWindowEventHandlerUPP = NewEventHandlerUPP( URLWindowEventHandlerProc ); |
status = InstallWindowEventHandler( window, urlWindowEventHandlerUPP, GetEventTypeCount(windowEvents), windowEvents, window, NULL ); |
ShowWindow( window ); |
break; |
case 'DoIt': // Our own menu to hook in and Do Something... |
status = DoSomething(); |
break; |
} |
return( status ); |
} |
static pascal OSStatus URLWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) |
{ |
#pragma unused ( inCallRef ) |
HICommand command; |
CFStringRef urlCFString; |
OSStatus status = eventNotHandledErr; |
UInt32 eventKind = GetEventKind( inEvent ); |
UInt32 eventClass = GetEventClass( inEvent ); |
WindowRef window = (WindowRef) inUserData; |
switch ( eventClass ) |
{ |
case kEventClassCommand: |
if ( eventKind == kEventCommandProcess ) |
{ |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); |
if ( command.commandID == kHICommandOK ) // OK Button was clicked in window |
{ |
urlCFString = GetControlCFString( window, 'ETxt', 0 ); |
SendWindowCloseEvent( window ); // Close this URL window |
status = DoNewWindow( &window ); // Create a new (Hidden) window |
status = DisplayMovieInWindow( window, NULL, urlCFString ); |
SetWindowTitleWithCFString( window, urlCFString ); // Set the Window title |
if ( status == noErr ) ShowWindow( window ); |
else DisposeWindow( window ); |
if ( urlCFString != NULL ) CFRelease( urlCFString ); |
} |
else if ( command.commandID == kHICommandCancel ) |
{ |
SendWindowCloseEvent( window ); // Close this URL window |
} |
} |
break; |
} |
return( status ); |
} |
#pragma mark - |
#pragma mark ¥ Windows ¥ |
static void DoPreferences( void ) |
{ // Some very basic CFPreferences code would be good here |
DialogRef alertDialog; |
CreateStandardAlert( kAlertStopAlert, CFSTR("No Preferences yet!"), NULL, NULL, &alertDialog ); |
RunStandardAlert( alertDialog, NULL, NULL ); |
} |
static OSStatus DoNewWindow( WindowRef *outWindow ) |
{ |
OSStatus status; |
WindowRef window = NULL; |
status = CreateWindowFromNib( g.mainNibRef, CFSTR("MainWindow"), &window ); // Create a window. "MainWindow" is the name of the window object. This name is set in InterfaceBuilder when the nib is created. |
require_noerr( status, CantCreateWindow ); |
if ( outWindow == NULL ) ShowWindow( window ); // The window was created hidden so show it if the window parameter is NULL, if it's not, it will be the responsibility of the caller to show it. |
SetWindowModified( window, false ); |
CantCreateWindow: |
if ( outWindow != NULL ) *outWindow = window; |
return( status ); |
} |
#pragma mark - |
#pragma mark ¥ Save/Open Document ¥ |
static OSStatus NavOpenDocument() |
{ |
OSStatus status; |
NavDialogCreationOptions options; |
NavReplyRecord navReply; |
static NavObjectFilterUPP navFilterUPP; |
NavDialogRef navDialog = NULL; |
status = NavGetDefaultDialogCreationOptions( &options ); |
require_noerr( status, CantGetDefaultOptions ); |
if ( navFilterUPP == NULL ) navFilterUPP = NewNavObjectFilterUPP( NavOpenFilterProc ); // Filter only documents we can open |
status = NavCreateChooseFileDialog( &options, NULL, NULL, NULL, navFilterUPP, NULL, &navDialog ); |
require_noerr( status, CantCreateDialog ); |
status = NavDialogRun( navDialog ); |
require_noerr( status, CantRunDialog ); |
status = NavDialogGetReply( navDialog, &navReply ); |
require( (status == noErr) || (status == userCanceledErr), CantGetReply ); |
if ( navReply.validRecord ) status = OpenDocuments( navReply.selection ); |
else status = userCanceledErr; |
NavDisposeReply( &navReply ); |
CantGetReply: |
CantRunDialog: |
if ( navDialog != NULL ) NavDialogDispose( navDialog ); |
CantCreateDialog: |
CantGetDefaultOptions: |
return( status ); |
} |
// We use CanQuickTimeOpenFile to determine which files are displayed in ther NavServices open file dialog. |
static pascal Boolean NavOpenFilterProc( AEDesc *theItem, void *info, NavCallBackUserData callBackUD, NavFilterModes filterMode ) |
{ |
FSRef fsRef; |
OSStatus status; |
FSSpec fsSpec; |
FSCatalogInfo fsCatalogInfo; |
Boolean outCanOpenAsMovie; |
Boolean canViewItem = false; |
if ( theItem->descriptorType == typeFSRef ) |
{ |
if ( ((NavFileOrFolderInfo*)info)->isFolder == true ) return( true ); |
status = AEGetDescData( theItem, &fsRef, sizeof(fsRef) ); |
require_noerr( status, CantGetFSRef ); |
status = FSGetCatalogInfo( &fsRef, kFSCatInfoFinderInfo, &fsCatalogInfo, NULL, &fsSpec, NULL ); |
require_noerr( status, CantGetFSRef ); |
status = CanQuickTimeOpenFile( &fsSpec, ((FileInfo *)&fsCatalogInfo.finderInfo)->fileType, 0, NULL, &outCanOpenAsMovie, NULL, kQTDontUseDataToFindImporter | kQTAllowOpeningStillImagesAsMovies | kQTAllowAggressiveImporters ); |
if ( (status == noErr) && (outCanOpenAsMovie==true) ) canViewItem = true; |
} |
CantGetFSRef: |
return( canViewItem ); |
} |
static OSStatus OpenDocuments( AEDescList docList ) |
{ |
long index; |
FSRef fsRef; |
CFStringRef fileName; |
WindowRef window = NULL; |
long count = 0; |
OSStatus status = AECountItems( &docList, &count ); |
require_noerr( status, CantGetCount ); |
for( index = 1; index <= count; index++ ) |
{ |
if ( (status = AEGetNthPtr( &docList, index, typeFSRef, NULL, NULL, &fsRef, sizeof(FSRef), NULL) ) == noErr ) |
{ |
status = DoNewWindow( &window ); // Create a new (Hidden) window |
require_noerr( status, CantCreateWindow ); |
status = LSCopyDisplayNameForRef( &fsRef, &fileName ); // Get the name of the file the Finder displays (may not include file extension) |
require_noerr( status, CantGetName ); |
SetWindowTitleWithCFString( window, fileName ); // Set the Window title |
status = DisplayMovieInWindow( window, &fsRef, NULL ); |
if ( status == noErr ) ShowWindow( window ); // The window was created hidden so show it |
else DisposeWindow( window ); |
} |
} |
CantGetName: |
CantCreateWindow: |
CantGetCount: |
return( status ); |
} |
#pragma mark - |
#pragma mark ¥ Utilities ¥ |
OSStatus GetControlBySigAndID( WindowRef window, OSType signature, SInt32 id, ControlRef *control ) |
{ |
ControlID controlID; |
controlID.id = id; |
controlID.signature = signature; |
return( GetControlByID( window, &controlID, control ) ); |
} |
CFStringRef GetControlCFString( WindowRef window, OSType signature, SInt32 id ) |
{ |
ControlRef control; |
SInt32 dataSize; |
OSStatus err; |
CFStringRef cfString = NULL; |
GetControlBySigAndID( window, signature, id, &control ); |
if ( control == NULL ) goto Bail; |
err = GetControlData( control, 0, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&cfString, &dataSize ); |
if ( err != noErr ) goto Bail; |
return( cfString ); |
Bail: |
if ( cfString != NULL ) CFRelease( cfString ); |
return( NULL ); |
} |
OSStatus SetWindowProxyFSRef( WindowRef window, FSRef *fsRef ) |
{ |
FSSpec fsSpec; |
OSStatus status = fnfErr; |
require( (fsRef != NULL), Bail ); |
status = FSGetCatalogInfo( fsRef, kFSCatInfoNone, NULL, NULL, &fsSpec, NULL ); |
require_noerr( status, Bail ); |
status = SetWindowProxyFSSpec( window, &fsSpec ); |
Bail: |
return( status ); |
} |
void SendWindowCloseEvent( WindowRef window ) |
{ |
EventRef event; |
(void) CreateEvent( NULL, kEventClassWindow, kEventWindowClose, GetCurrentEventTime(), kEventAttributeUserEvent, &event ); |
(void) SetEventParameter( event, kEventParamDirectObject, typeWindowRef, sizeof(window), &window ); |
(void) SendEventToWindow( event, window ); |
(void) ReleaseEvent( event ); |
} |
#pragma mark - |
#pragma mark ¥ Specialized Routines ¥ |
static OSStatus DoSomething() |
{ |
DebugStr( "\pDoSomething Was Called\n" ); |
return( noErr ); |
} |
static OSStatus DisplayMovieInWindow( WindowRef window, FSRef *fsRef, CFStringRef urlCFString ) |
{ |
OSStatus status; |
ControlRef control; |
Rect rect; |
Movie movie; |
OSType dataRefType; |
Handle dataRef = NULL; |
require( ((fsRef != NULL) || (urlCFString != NULL)) && (window != NULL), Bail ); |
if ( urlCFString != NULL ) status = QTNewDataReferenceFromURLCFString( urlCFString, 0, &dataRef, &dataRefType ); |
else status = QTNewDataReferenceFromFSRef( fsRef, 0, &dataRef, &dataRefType ); // http://developer.apple.com/documentation/QuickTime/WhatsNewQT6_4/Chap1/chapter_1_section_6.html |
require_noerr( status, Bail ); |
status = NewMovieFromDataRef( &movie, newMovieActive, 0, dataRef, dataRefType ); |
require_noerr( status, Bail ); |
GetMovieBox( movie, &rect ); // Get the natural bounds of the movie |
if ( rect.right - rect.left < 150 ) rect.right = rect.left + 150; // Just in case the rect is too small |
if ( rect.bottom - rect.top < (80 + kDistanceFromBottomOfWindow) ) rect.bottom = rect.top + (80 + kDistanceFromBottomOfWindow); // Grow it to 80 X 150 |
SizeWindow( window, rect.right - rect.left, rect.bottom - rect.top + kDistanceFromBottomOfWindow, true ); // Start off the window the size the movie was meant for |
status = CreateMovieControl( window, &rect, movie, kMovieControlOptionSetKeysEnabled | kMovieControlOptionLocateTopLeft | kMovieControlOptionEnableEditing | kMovieControlOptionHandleEditingHI, &control ); // http://developer.apple.com/documentation/QuickTime/QT6WhatsNew/Chap1/chapter_1_section_25.html |
// Enabling this code will grow the Movie control with the window. |
// The trick is in growing the control in a flicker-free way. We do this by installing the event handler for the kEventControlBoundsChanged |
// event on the parent control. This is how control redrawing should be done. You may be tempted to install an event on the window target |
// for the kEventWindowBoundsChanging event, but this does cause flicker as the parent control (window) is erased and then the movie frame is drawn. |
// In addition we get notified when the Control is disposed via the kEventControlDispose event at which time we stop the move from playing. This |
// isn't neccesary, but without it the buffers will play through even though the Control was disposed. |
if ( true ) |
{ |
ControlRef parentControl; |
static EventHandlerUPP parentControlEventHandlerUPP; |
static EventHandlerUPP movieControlEventHandlerUPP; |
const EventTypeSpec parentControlEvents[] = { { kEventClassControl, kEventControlBoundsChanged } }; |
const EventTypeSpec movieControlEvents[] = { { kEventClassControl, kEventControlDispose } }; |
SizeControl( control, rect.right - rect.left, rect.bottom - rect.top ); |
GetSuperControl( control, &parentControl ); |
if ( parentControlEventHandlerUPP == NULL ) parentControlEventHandlerUPP = NewEventHandlerUPP( ParentMovieControlWindowEventHandler ); |
status = InstallControlEventHandler( parentControl, parentControlEventHandlerUPP, GetEventTypeCount(parentControlEvents), parentControlEvents, control, NULL ); |
if ( movieControlEventHandlerUPP == NULL ) movieControlEventHandlerUPP = NewEventHandlerUPP( MovieControlEventHandler ); |
status = InstallControlEventHandler( control, movieControlEventHandlerUPP, GetEventTypeCount(movieControlEvents), movieControlEvents, control, NULL ); |
} |
SetWindowProxyFSRef( window, fsRef ); |
Bail: |
if ( dataRef != NULL ) DisposeHandle( dataRef ); |
return( status ); |
} |
// Resize the movie control when the controls parent is resized, in this case the windows root control. |
static pascal OSStatus ParentMovieControlWindowEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) |
{ |
Rect rect; |
ControlRef control = (ControlRef) inUserData; |
UInt32 eventClass = GetEventClass( inEvent ); |
UInt32 eventKind = GetEventKind( inEvent ); |
OSStatus status = eventNotHandledErr; |
switch ( eventClass ) |
{ |
case kEventClassControl: |
if ( eventKind == kEventControlBoundsChanged ) |
{ |
(void) GetEventParameter( inEvent, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &rect ); |
rect.bottom -= kDistanceFromBottomOfWindow; |
SizeControl( control, rect.right - rect.left, rect.bottom - rect.top ); |
} |
break; |
} |
return( status ); |
} |
// Call StopMovie() when the control is disposed. Without calling StopMovie, the audio may continue to play for one or |
// two seconds after the control is disposed. |
static pascal OSStatus MovieControlEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData ) |
{ |
OSStatus err; |
SInt32 dataSize; |
Movie movie; |
ControlRef control = (ControlRef) inUserData; |
UInt32 eventClass = GetEventClass( inEvent ); |
UInt32 eventKind = GetEventKind( inEvent ); |
OSStatus status = eventNotHandledErr; |
switch ( eventClass ) |
{ |
case kEventClassControl: |
if ( eventKind == kEventControlDispose ) |
{ |
err = GetControlData( control, 0, kMovieControlDataMovie, sizeof(Movie), (Ptr)&movie, &dataSize ); // kMovieControlDataMovie tag allows us to get the Movie from the Control |
if ( err == noErr ) |
{ |
CallNextEventHandler( inCallRef, inEvent ); |
DisposeMovie( movie ); |
status = noErr; // We handled the event |
} |
} |
break; |
} |
return( status ); |
} |
Copyright © 2005 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2005-08-10