1/*
2 * EffectCommand.c --
3 *
4 *		Process the "effect" subcommand.
5 *
6 * Copyright (c) 2000-2003  Mats Bengtsson
7 *
8 * $Id: EffectCommand.c,v 1.5 2005/04/10 14:57:48 matben Exp $
9 */
10
11#include "MoviePlayer.h"
12
13/*
14 * Keep a global record of the effect list, and other useful stuff,
15 * for an n'th source effect. We need this since the dialog is handled in the
16 * event loop, and the parameters must be transported to a callback procedure.
17 */
18
19typedef struct StandardEffectsRecord {
20    MoviePlayer         *movPtr;
21    QTParameterDialog   dialog;			/* Dialog token.
22    									 * Nonzero => serve in event loop */
23    QTAtomContainer     effectList[3]; 	/* Cache for n effect list. Keep
24    									 * Between calls! */
25    QTAtomContainer     theSampleAtom;
26    int                 nTrackEffect;
27    long                trackIDs[2];
28    PicHandle			posterPict[2];
29    TimeValue           movTime;
30    TimeValue           movDuration;
31    Boolean				doneWithDialog;	/* Are we done using the effects
32    									 * parameters dialog box? */
33} StandardEffectsRecord;
34
35/*
36 * The effect dialog callback needs the interpreter, and this is the only way.
37 */
38
39static Tcl_Interp   *gInterp;
40
41/*
42 * Keep a global record of the effect list, and other useful stuff,
43 * for an n'th source effect. We need this since the dialog is handled in the
44 * event loop, and the parameters must be transported to a callback procedure.
45 */
46
47StandardEffectsRecord   *gEffectsPtr = NULL;
48
49static void      	EffectsRespondToDialogSelection( OSErr dialogSelectType );
50static void			EffectsReset( void );
51
52#if TARGET_OS_WIN32
53static void 		EffectsDialogCallback( EventRecord *theEvent,
54							DialogRef theDialog, DialogItemIndex theItemHit );
55LRESULT CALLBACK 	CustomDialogWndProc( HWND theWnd, UINT theMessage,
56                         	UINT wParam, LONG lParam );
57#endif
58
59
60/*
61 *----------------------------------------------------------------------
62 *
63 * EffectsInit, EffectsFree --
64 *
65 *	   	Initializes and frees the StandardEffectsRecord 'gEffectsPtr'.
66 *
67 * Results:
68 *     	None.
69 *
70 * Side effects:
71 *	   	Memory allocated, released.
72 *
73 *----------------------------------------------------------------------
74 */
75
76void
77EffectsInit( void )
78{
79	gEffectsPtr = (StandardEffectsRecord *) ckalloc(sizeof(StandardEffectsRecord));
80	memset( gEffectsPtr, '\0', sizeof(StandardEffectsRecord) );
81    gEffectsPtr->dialog = 0;
82}
83
84void
85EffectsFree( void )
86{
87	int		i;
88
89	EffectsReset();
90
91	/* Free cached effect lists. */
92	for (i = 0; i < 3; i++) {
93		if (gEffectsPtr->effectList[i] != NULL) {
94			QTDisposeAtomContainer( gEffectsPtr->effectList[i] );
95		}
96	}
97	if (gEffectsPtr != NULL) {
98		ckfree( (char *) gEffectsPtr);
99        gEffectsPtr = NULL;
100	}
101}
102
103/*
104 *----------------------------------------------------------------------
105 *
106 * ProcessEffectCmd --
107 *
108 *	   	Process the "effect" command
109 *
110 * Results:
111 *     	Normal TCL results
112 *
113 * Side effects:
114 *	   	Effects, with dialog.
115 *
116 *----------------------------------------------------------------------
117 */
118
119int
120ProcessEffectCmd( Tcl_Interp *interp,
121		MoviePlayer *movPtr,
122		int objc,
123		Tcl_Obj *CONST objv[] )
124{
125    int             nTrackEffect;
126    long			longValue;
127	TimeValue       movTime;
128	TimeValue       movDuration;
129	Track			aTrack = NULL;
130	OSErr           err = noErr;
131	int             result = TCL_OK;
132
133    if (objc == 2) {
134
135        /* Zero source effect. */
136
137	    nTrackEffect = 0;
138    } else if (objc == 3) {
139
140        /* Single source effect. */
141
142	    nTrackEffect = 1;
143		if (Tcl_GetLongFromObj( interp, objv[2], &longValue ) != TCL_OK) {
144			Tcl_AddErrorInfo( interp, "\n	(processing trackOneID value)" );
145			result = TCL_ERROR;
146			goto bail;
147		}
148	    gEffectsPtr->trackIDs[0] = longValue;
149    } else if (objc == 4) {
150
151        /* Two source effect. */
152
153	    nTrackEffect = 2;
154		if (Tcl_GetLongFromObj( interp, objv[2], &longValue ) != TCL_OK) {
155			Tcl_AddErrorInfo( interp, "\n	(processing trackOneID value)" );
156			result = TCL_ERROR;
157			goto bail;
158		}
159	    gEffectsPtr->trackIDs[0] = longValue;
160		if (Tcl_GetLongFromObj( interp, objv[3], &longValue ) != TCL_OK) {
161			Tcl_AddErrorInfo( interp, "\n	(processing trackTwoID value)" );
162			result = TCL_ERROR;
163			goto bail;
164		}
165	    gEffectsPtr->trackIDs[1] = longValue;
166  	} else {
167		Tcl_WrongNumArgs( interp, 0, objv,
168				"pathName effect startTime duration ?trackID? ?trackID?" );
169		result = TCL_ERROR;
170		goto bail;
171  	}
172	gEffectsPtr->nTrackEffect = nTrackEffect;
173
174    if (GetMovieStartTimeFromObj( interp, movPtr->aMovie, objv[0], &longValue ) != TCL_OK) {
175        goto bail;
176    }
177    movTime = longValue;
178    if (GetMovieDurationFromObj( interp, movPtr->aMovie, objv[1], movTime, &longValue ) != TCL_OK) {
179        goto bail;
180    }
181    movDuration = longValue;
182
183	gEffectsPtr->movTime = movTime;
184	gEffectsPtr->movDuration = movDuration;
185	gEffectsPtr->movPtr = movPtr;
186	result = LogUndoState( movPtr, interp );
187
188    /*
189  	 * The effect is going on async; need variable to wait for.
190  	 */
191
192  	Tcl_SetVar( interp, "quicktimetcl::effectfinished", "-1", TCL_GLOBAL_ONLY );
193   	gInterp = interp;
194
195  	err = QTNewAtomContainer( &gEffectsPtr->theSampleAtom );
196  	if (err != noErr) {
197        CheckAndSetErrorResult( interp, err );
198		result = TCL_ERROR;
199		goto bail;
200	}
201
202    /*
203     * If we haven't made and cached the effect list for this n'th source effect,
204     * do it now.
205     */
206
207  	if (gEffectsPtr->effectList[nTrackEffect] == NULL) {
208       	err = QTGetEffectsList(
209                  &(gEffectsPtr->effectList[nTrackEffect]),
210                  nTrackEffect,
211                  nTrackEffect, 0 );
212       	if (err != noErr) {
213          	CheckAndSetErrorResult( interp, err );
214  			result = TCL_ERROR;
215  			goto bail;
216      	}
217  	}
218
219   	/*
220   	 * Make the standard parameter effects dialog.
221   	 * Needs to be served in the event loop.
222     * From the event loop the actual procedure 'EffectsRespondToDialogSelection'
223     * is called to make the effect.
224     */
225
226   	err = QTCreateStandardParameterDialog(
227              gEffectsPtr->effectList[nTrackEffect],/* the effects list */
228              gEffectsPtr->theSampleAtom,          	/* empty container */
229              0,
230              &(gEffectsPtr->dialog) );          	/* identifier for the
231              										 * standard dialog */
232   	if (noErr != err) {
233       	CheckAndSetErrorResult( interp, err );
234		result = TCL_ERROR;
235		goto bail;
236  	}
237
238	/*
239	 *	Insert poster frames into dialog.
240	 */
241
242	if (nTrackEffect >= 1) {
243		aTrack = GetMovieTrack( movPtr->aMovie, gEffectsPtr->trackIDs[0] );
244		if (aTrack != NULL) {
245			gEffectsPtr->posterPict[0] = GetTrackPict( aTrack,
246					GetMoviePosterTime( movPtr->aMovie ));
247			if (gEffectsPtr->posterPict[0] != NULL) {
248				QTParamPreviewRecord			myPreviewRecord;
249
250				myPreviewRecord.sourcePicture = gEffectsPtr->posterPict[0];
251				myPreviewRecord.sourceID = 1;
252				err = QTStandardParameterDialogDoAction( gEffectsPtr->dialog,
253						pdActionSetPreviewPicture, &myPreviewRecord );
254			}
255		}
256	}
257	/* not very clever since it is the same movie...
258	if (nTrackEffect >= 2) {
259		aTrack = GetMovieTrack( movPtr->aMovie, gEffectsPtr->trackIDs[1] );
260		if (aTrack != NULL) {
261			gEffectsPtr->posterPict[1] = GetTrackPict( aTrack,
262					GetMoviePosterTime( movPtr->aMovie ));
263			if (gEffectsPtr->posterPict[1] != NULL) {
264				QTParamPreviewRecord			myPreviewRecord;
265
266				myPreviewRecord.sourcePicture = gEffectsPtr->posterPict[1];
267				myPreviewRecord.sourceID = 2;
268				err = QTStandardParameterDialogDoAction( gEffectsPtr->dialog,
269						pdActionSetPreviewPicture, &myPreviewRecord );
270			}
271		}
272	}
273	*/
274
275	/*
276	 *	Now, the frontmost window is the standard effects parameter dialog box;
277	 * 	on the Mac, we call EffectsHandleDialogEvents in our main event loop
278	 *  to find and process events targeted at the effects parameter dialog box;
279	 *	On Windows, we need to use a different strategy: we install a modeless
280	 *	dialog callback procedure that is called internally by QTML.
281	 */
282
283#if TARGET_OS_WIN32
284	gEffectsPtr->doneWithDialog = false;
285
286	/* Force the dialog box to be drawn. */
287	{
288		EventRecord			myEvent = {0};
289
290		EffectsDialogCallback( &myEvent, FrontWindow(), 0 );
291	}
292	SetModelessDialogCallbackProc( FrontWindow(),
293			(QTModelessCallbackProcPtr) EffectsDialogCallback );
294	QTMLSetWindowWndProc( FrontWindow(), (void *) CustomDialogWndProc );
295#endif
296
297      /* Continues in 'EffectsRespondToDialogSelection'... */
298
299bail:
300	if (result != TCL_OK) {
301	}
302	return result;
303}
304
305/*
306 *----------------------------------------------------------------------
307 *
308 * EffectsHandleDialogEvents --
309 *
310 *      Process events that might be targeted at the standard effects
311 *		parameter dialog box. Return true if the event was completely
312 *		handled.
313 *
314 * Results:
315 *		Boolean telling if event was handled or not.
316 *
317 * Side effects:
318 *  	Dialog procedures called.
319 *
320 *----------------------------------------------------------------------
321 */
322
323Boolean
324EffectsHandleDialogEvents( EventRecord *eventPtr, DialogItemIndex itemIndex )
325{
326    Boolean     isHandled;
327    OSErr       err = noErr;
328
329    if (eventPtr == NULL) {
330        return false;
331    }
332    if (gEffectsPtr == NULL) {
333        return false;
334    }
335    if (gEffectsPtr->dialog == 0) {
336    	return false;
337    }
338    err = QTIsStandardParameterDialogEvent( eventPtr, gEffectsPtr->dialog );
339
340    switch (err) {
341
342        case codecParameterDialogConfirm:
343        case userCanceledErr:
344
345            /* The user clicked the OK or Cancel button.*/
346
347			QTStandardParameterDialogDoAction( gEffectsPtr->dialog, pdActionConfirmDialog, NULL );
348			QTDismissStandardParameterDialog( gEffectsPtr->dialog );
349			gEffectsPtr->dialog = 0L;
350			EffectsRespondToDialogSelection( err );
351			isHandled = true;
352
353            /*
354             * The effect is going on async; set variable to wait for.
355             */
356
357            if (err == userCanceledErr) {
358                Tcl_SetVar( gInterp, "quicktimetcl::effectfinished", "0", TCL_GLOBAL_ONLY );
359            } else {
360                Tcl_SetVar( gInterp, "quicktimetcl::effectfinished", "1", TCL_GLOBAL_ONLY );
361            }
362			break;
363
364		case noErr:
365
366			/*
367			 * The event was completely handled by
368			 * QTIsStandardParameterDialogEvent
369			 */
370
371			isHandled = true;
372			break;
373
374		case featureUnsupported:
375
376			/*
377			 * The event was not handled by QTIsStandardParameterDialogEvent;
378			 * let the event be processed normally.
379			 */
380
381			isHandled = false;
382			break;
383
384		default:
385
386			/*
387			 * The event was not handled by QTIsStandardParameterDialogEvent;
388			 * do not let the event be processed normally.
389			 */
390
391			isHandled = true;
392			break;
393	}
394	return( isHandled );
395}
396
397/*
398 *----------------------------------------------------------------------
399 *
400 * EffectsRespondToDialogSelection --
401 *
402 *     	If dialogSelectType is codecParameterDialogConfirm, make an
403 *		effects movie.
404 *     	If dialogSelectType is userCanceledErr, do any necessary clean up.
405 *
406 * Results:
407 *	   	None.
408 *
409 * Side effects:
410 *	   	New source tracks created, effect track created.
411 *
412 *----------------------------------------------------------------------
413 */
414
415static void
416EffectsRespondToDialogSelection( OSErr dialogSelectType )
417{
418	MoviePlayer     *movPtr;
419	int             nTrackEffect = gEffectsPtr->nTrackEffect;
420	TimeValue       movTime = gEffectsPtr->movTime;
421	TimeValue       movDuration = gEffectsPtr->movDuration;
422	TimeValue       sampleTime;
423	Track           origTrack[2] = {NULL, NULL};
424	Track           srcTrack[2] = {NULL, NULL};
425	Track           videoTrackFX = NULL;
426	Track           aTrack = NULL;
427	Media           myMedia = NULL;
428	Media           videoMediaFX = NULL;
429	Fixed           fixWidth;
430	Fixed           fixHeight;
431	Boolean		    dialogWasCancelled = false;
432	QTAtomContainer	theInputMapContainer = NULL;
433	QTAtom			inputAtom;
434	QTAtom			effectAtom;
435	QTAtomID		effectAtomID;
436	OSType          theEffectCode;
437	OSType			theInputType;
438	OSErr			err = noErr;
439	long			effectCodeSize;
440	Ptr				effectCodePtr = NULL;
441	ImageDescriptionHandle	theDesc = NULL;
442	MediaHandler	mediaHandler;
443	RGBColor        transparentColor = {0x0000, 0x0000, 0x0000};
444	int             copyMovieMedia = false;
445	int 		    timeScale;
446	int             i;
447	long	        aLong;
448	long			refIndex1, refIndex2;
449	int				result = TCL_OK;
450
451    movPtr = gEffectsPtr->movPtr;
452    if (movPtr->aMovie == NULL) {
453    	result = TCL_ERROR;
454     	goto bail;
455    }
456	dialogWasCancelled = (dialogSelectType == userCanceledErr);
457	if (dialogWasCancelled) {
458    	result = TCL_ERROR;
459     	goto bail;
460    }
461
462    /*
463     * First, create any source tracks that is needed by the effect,
464     * and copy the media from the original track.
465     */
466
467    for (i = 0; i <  nTrackEffect; i++) {
468		origTrack[i] = GetMovieTrack( movPtr->aMovie, gEffectsPtr->trackIDs[i] );
469		if (origTrack[i] == NULL) {
470			CheckAndSetErrorResult( gInterp, noErr );
471	    	result = TCL_ERROR;
472            goto bail;
473		}
474        AddEmptyTrackToMovie( origTrack[i], movPtr->aMovie, NULL, 0,
475        		&srcTrack[i] );
476        if (srcTrack[i] == NULL) {
477			CheckAndSetErrorResult( gInterp, noErr );
478	    	result = TCL_ERROR;
479            goto bail;
480        }
481		myMedia = GetTrackMedia( srcTrack[i] );
482		if (myMedia == NULL) {
483			CheckAndSetErrorResult( gInterp, noErr );
484	    	result = TCL_ERROR;
485            goto bail;
486		}
487        if (copyMovieMedia) {
488			if (noErr != BeginMediaEdits( myMedia )) {
489				CheckAndSetErrorResult( gInterp, noErr );
490		    	result = TCL_ERROR;
491            	goto bail;
492			}
493        }
494	    if (noErr != (err = InsertTrackSegment(
495	    		origTrack[i],  			/* source track */
496	            srcTrack[i],           	/* destination track */
497	            movTime,                /* start time */
498	            movDuration,            /* duration */
499	            movTime ))) {        	/* insert time */
500			CheckAndSetErrorResult( gInterp, err );
501	    	result = TCL_ERROR;
502            goto bail;
503	    }
504        if (copyMovieMedia) {
505			if (noErr != EndMediaEdits( myMedia )) {
506				CheckAndSetErrorResult( gInterp, noErr );
507		    	result = TCL_ERROR;
508	            goto bail;
509			}
510        }
511    }
512
513	/*
514	 * Extract the 'what' atom to find out what kind of effect it is.
515	 */
516
517	effectAtom = QTFindChildByIndex( gEffectsPtr->theSampleAtom,
518			kParentAtomIsContainer, kParameterWhatName, kParameterWhatID,
519			&effectAtomID );
520
521	if (noErr != QTLockContainer( gEffectsPtr->theSampleAtom )) {
522		CheckAndSetErrorResult( gInterp, noErr );
523	    result = TCL_ERROR;
524     	goto bail;
525    }
526	if (noErr != QTGetAtomDataPtr( gEffectsPtr->theSampleAtom, effectAtom,
527			&effectCodeSize, &effectCodePtr )) {
528		CheckAndSetErrorResult( gInterp, noErr );
529	    result = TCL_ERROR;
530     	goto bail;
531    }
532	if (effectCodeSize != sizeof(OSType)) {
533	    result = TCL_ERROR;
534     	goto bail;
535	}
536	theEffectCode = *(OSType *) effectCodePtr;		/* "tsk" */
537
538	/* Because the data is read from an atom container. */
539	theEffectCode = EndianU32_BtoN(theEffectCode);
540	if (noErr != QTUnlockContainer( gEffectsPtr->theSampleAtom )) {
541		CheckAndSetErrorResult( gInterp, noErr );
542	    result = TCL_ERROR;
543     	goto bail;
544	}
545
546    /*
547     * Make an empty effect track.
548     */
549
550    if (nTrackEffect > 0) {
551        GetTrackDimensions( origTrack[0], &fixWidth, &fixHeight );
552    } else {
553
554        /*
555         * Here we search for a visual track and pick its dimensions.
556         */
557
558        if (GetFirstVideoTrackInMovie( movPtr->aMovie, &aTrack ) == invalidTrack) {
559            fixWidth = Long2Fix(160);
560            fixHeight = Long2Fix(120);
561        } else {
562            GetTrackDimensions( aTrack, &fixWidth, &fixHeight );
563        }
564    }
565    videoTrackFX = NewMovieTrack( movPtr->aMovie, fixWidth, fixHeight, kNoVolume );
566	if (videoTrackFX == NULL) {
567		CheckAndSetErrorResult( gInterp, noErr );
568	    result = TCL_ERROR;
569     	goto bail;
570    }
571    timeScale = GetMovieTimeScale( movPtr->aMovie );
572	videoMediaFX = NewTrackMedia( videoTrackFX, VideoMediaType, timeScale,
573			NULL, 0 );
574	if (videoMediaFX == NULL) {
575		CheckAndSetErrorResult( gInterp, noErr );
576	    result = TCL_ERROR;
577     	goto bail;
578	}
579
580    /*
581     * An effect track has two important attributes: the effect description
582     * and the input map.
583     * The effect description requires two things:
584     *  1)  The actual description, which's name and parameters are already
585     *		inserted in the atom container 'gEffectsPtr->theSampleAtom'
586     *		using 'QTCreateStandardParameterDialog'.
587     *  2)  The second is atoms naming the sources.
588     *
589     * Add atoms naming the sources.
590     */
591
592	if (nTrackEffect >= 1) {
593		aLong = EndianU32_NtoB( kSourceOneName );
594		QTInsertChild( gEffectsPtr->theSampleAtom, kParentAtomIsContainer,
595				kEffectSourceName, 1, 0, sizeof(aLong), &aLong, NULL );
596	}
597	if (nTrackEffect >= 2) {
598		aLong = EndianU32_NtoB( kSourceTwoName );
599		QTInsertChild( gEffectsPtr->theSampleAtom, kParentAtomIsContainer,
600				kEffectSourceName, 2, 0, sizeof(aLong), &aLong, NULL );
601	}
602
603	theDesc = (ImageDescriptionHandle) NewHandleClear(sizeof(ImageDescription));
604	if (theDesc == NULL) {
605		CheckAndSetErrorResult( gInterp, noErr );
606	    result = TCL_ERROR;
607     	goto bail;
608	}
609
610	/*
611	 * Fill in the fields of the sample description.
612	 */
613
614	(**theDesc).idSize = sizeof(ImageDescription);
615	(**theDesc).cType = theEffectCode;
616	(**theDesc).vendor = kAppleManufacturer;
617	(**theDesc).temporalQuality = codecNormalQuality;
618	(**theDesc).spatialQuality = codecNormalQuality;
619	(**theDesc).width = (short) Fix2Long( fixWidth );
620	(**theDesc).height = (short) Fix2Long( fixHeight );
621	(**theDesc).hRes = 72L << 16;
622	(**theDesc).vRes = 72L << 16;
623	(**theDesc).dataSize = 0L;
624	(**theDesc).frameCount = 1;
625	(**theDesc).depth = 0;
626	(**theDesc).clutID = -1;
627
628	/*
629	 *	Add effects sample to movie.
630	 */
631
632	if (noErr != BeginMediaEdits( videoMediaFX )) {
633		CheckAndSetErrorResult( gInterp, noErr );
634	    result = TCL_ERROR;
635     	goto bail;
636    }
637	if (noErr != AddMediaSample( videoMediaFX, gEffectsPtr->theSampleAtom, 0,
638	        GetHandleSize( gEffectsPtr->theSampleAtom ), movDuration,
639	        (SampleDescriptionHandle) theDesc, 1, 0, &sampleTime )) {
640		CheckAndSetErrorResult( gInterp, noErr );
641	    result = TCL_ERROR;
642     	goto bail;
643    }
644	if (noErr != EndMediaEdits( videoMediaFX )) {
645		CheckAndSetErrorResult( gInterp, noErr );
646	    result = TCL_ERROR;
647     	goto bail;
648    }
649	if (noErr != InsertMediaIntoTrack( videoTrackFX,/* the track */
650			movTime, 								/* insert time in movie's
651													 * time */
652			sampleTime, 							/* media start time in
653													 * media's time */
654			movDuration, 							/* media's duration in
655													 * media's time */
656			fixed1 )) {								/* the media's rate */
657		CheckAndSetErrorResult( gInterp, noErr );
658	    result = TCL_ERROR;
659     	goto bail;
660	}
661	if (gEffectsPtr->theSampleAtom != NULL) {
662		QTDisposeAtomContainer( gEffectsPtr->theSampleAtom );
663		gEffectsPtr->theSampleAtom = NULL;
664	}
665	DisposeHandle( (Handle) theDesc );
666
667    /*
668     * Create and add the input map.
669     */
670
671	QTNewAtomContainer( &theInputMapContainer );
672
673	/* The first input. */
674
675	if (nTrackEffect > 0) {
676		AddTrackReference( videoTrackFX, srcTrack[0], kTrackModifierReference,
677		        &refIndex1 );
678		QTInsertChild( theInputMapContainer, kParentAtomIsContainer,
679				kTrackModifierInput, refIndex1, 0, 0, NULL, &inputAtom );
680
681		theInputType = EndianU32_NtoB( kTrackModifierTypeImage );
682		QTInsertChild( theInputMapContainer, inputAtom, kTrackModifierType,
683				1, 0, sizeof(theInputType), &theInputType, NULL );
684
685		aLong = EndianU32_NtoB( kSourceOneName );
686		QTInsertChild( theInputMapContainer, inputAtom, kEffectDataSourceType,
687				1, 0, sizeof(aLong), &aLong, NULL );
688	}
689
690	/* The second input. */
691
692	if (nTrackEffect > 1) {
693		AddTrackReference( videoTrackFX, srcTrack[1], kTrackModifierReference,
694		        &refIndex2 );
695		QTInsertChild( theInputMapContainer, kParentAtomIsContainer,
696				kTrackModifierInput, refIndex2, 0, 0, NULL, &inputAtom );
697
698		theInputType = EndianU32_NtoB( kTrackModifierTypeImage );
699		QTInsertChild( theInputMapContainer, inputAtom, kTrackModifierType,
700				1, 0, sizeof(theInputType), &theInputType, NULL );
701
702		aLong = EndianU32_NtoB( kSourceTwoName );
703		QTInsertChild( theInputMapContainer, inputAtom, kEffectDataSourceType,
704				1, 0, sizeof(aLong), &aLong, NULL );
705	}
706
707	/*
708	 * Set that mapping.
709	 */
710
711	if (nTrackEffect > 0) {
712		SetMediaInputMap( GetTrackMedia(videoTrackFX), theInputMapContainer );
713	}
714
715	/*
716	 * Set transparent graphics mode for the zero source effect track.
717	 */
718
719	if (nTrackEffect == 0) {
720		mediaHandler = GetMediaHandler( videoMediaFX );
721        MediaSetGraphicsMode( mediaHandler, transparent, &transparentColor );
722	}
723
724bail:
725
726	if (result != TCL_OK) {
727	  	if (srcTrack[0] != NULL) {
728	  		DisposeMovieTrack( srcTrack[0] );
729	  	}
730	  	if (srcTrack[1] != NULL) {
731	  		DisposeMovieTrack( srcTrack[1] );
732	  	}
733	  	if (videoTrackFX != NULL) {
734	  		DisposeMovieTrack( videoTrackFX );
735	  	}
736	}
737	if (theInputMapContainer != NULL) {
738		QTDisposeAtomContainer( theInputMapContainer );
739	}
740  	if (theDesc != NULL) {
741		DisposeHandle( (Handle) theDesc );
742	}
743	EffectsReset();
744
745  	return;
746}
747
748/*
749 *----------------------------------------------------------------------
750 *
751 * EffectsReset --
752 *
753 *		Resets the StandardEffectsRecord 'gEffectsPtr'. Kills any
754 *		poster picts. Keeps any effect lists untouched!
755 *
756 * Results:
757 *		None.
758 *
759 * Side effects:
760 *		Picts may be killed. Not served in event loop.
761 *
762 *----------------------------------------------------------------------
763 */
764
765static void
766EffectsReset( void )
767{
768    if (gEffectsPtr == NULL) {
769        return;
770    }
771    gEffectsPtr->movPtr = NULL;
772	gEffectsPtr->dialog = 0L;
773	gEffectsPtr->trackIDs[0] = 0;
774	gEffectsPtr->trackIDs[1] = 0;
775	gEffectsPtr->nTrackEffect = 0;
776	gEffectsPtr->doneWithDialog = false;
777	if (gEffectsPtr->posterPict[0] != NULL) {
778		KillPicture( gEffectsPtr->posterPict[0] );
779		gEffectsPtr->posterPict[0] = NULL;
780	}
781	if (gEffectsPtr->posterPict[1] != NULL) {
782		KillPicture( gEffectsPtr->posterPict[1] );
783		gEffectsPtr->posterPict[1] = NULL;
784	}
785	if (gEffectsPtr->theSampleAtom != NULL) {
786		QTDisposeAtomContainer( gEffectsPtr->theSampleAtom );
787		gEffectsPtr->theSampleAtom = NULL;
788	}
789}
790
791/*
792 *----------------------------------------------------------------------
793 *
794 * EffectsDialogCallback --
795 *
796 *		This function is called by QTML when it processes events for
797 *		the standard or custom effects parameter dialog box.
798 *
799 * Results:
800 *		None.
801 *
802 * Side effects:
803 *		EffectsHandleDialogEvents called.
804 *
805 *----------------------------------------------------------------------
806 */
807#if TARGET_OS_WIN32 || TARGET_API_MAC_CARBON
808
809static void
810EffectsDialogCallback( EventRecord *theEvent, DialogRef theDialog,
811		DialogItemIndex theItemHit )
812{
813	QTParamDialogEventRecord	myRecord;
814
815	myRecord.theEvent = theEvent;
816	myRecord.whichDialog = theDialog;
817	myRecord.itemHit = theItemHit;
818
819	if (gEffectsPtr->dialog != 0L) {
820		QTStandardParameterDialogDoAction( gEffectsPtr->dialog,
821				pdActionModelessCallback, &myRecord );
822
823		/*
824		 * See if the event is meant for the effects parameter dialog box.
825		 */
826
827		EffectsHandleDialogEvents( theEvent, theItemHit );
828	}
829}
830#endif
831
832#if TARGET_OS_WIN32
833/*
834 *----------------------------------------------------------------------
835 *
836 * CustomDialogWndProc --
837 *
838 *		Handle messages for the custom effects parameters dialog box.
839 *
840 * Results:
841 *		DefWindowProc.
842 *
843 * Side effects:
844 *		DefWindowProc called.
845 *
846 *----------------------------------------------------------------------
847 */
848
849LRESULT CALLBACK
850CustomDialogWndProc( HWND theWnd, UINT theMessage, UINT wParam, LONG lParam )
851{
852	EventRecord			myEvent = {0};
853
854	if (!gEffectsPtr->doneWithDialog && (theMessage == 0x7FFF))
855		EffectsDialogCallback( &myEvent, GetNativeWindowPort(theWnd), 0 );
856
857	return(DefWindowProc( theWnd, theMessage, wParam, lParam ));
858}
859#endif
860
861/*---------------------------------------------------------------------------*/
862