/*
 *  void PsychQTExitMovies() - Shutdown handler.
 *
 *  This routine is called by Screen('CloseAll') and on clear Screen time to
 *  do final cleanup. It deletes all Quicktime textures and releases all Quicktime
 *  movie objects.
 *
 */
void PsychQTExitMovies(void)
{
    PsychWindowRecordType	**windowRecordArray;
    int				i, numWindows; 
    
    // Release all Quicktime related OpenGL textures:
    PsychCreateVolatileWindowRecordPointerList(&numWindows, &windowRecordArray);
    for(i=0; i<numWindows; i++) {
        // Delete all Quicktime textures:
        if ((windowRecordArray[i]->windowType == kPsychTexture) && (windowRecordArray[i]->targetSpecific.QuickTimeGLTexture !=NULL)) { 
            PsychCloseWindow(windowRecordArray[i]);
        }
    }
    PsychDestroyVolatileWindowRecordPointerList(windowRecordArray);
    
    // Release all movies:
    PsychQTDeleteAllMovies();
    
    // Shutdown Quicktime toolbox: We skip this, because according to Apple its not necessary,
    // and for some reason it reliably hangs Matlab, so one has to force-quit it :-(
    // Don't do this: ExitMovies();

#if PSYCH_SYSTEM == PSYCH_WINDOWS
    // Shutdown Quicktime core system:
    ExitMovies();
    
    // Shutdown Quicktime for Windows compatibility layer:
    TerminateQTML();
#endif
    
    return;
}
/*
 *  void PsychGSExitMovies() - Shutdown handler.
 *
 *  This routine is called by Screen('CloseAll') and on clear Screen time to
 *  do final cleanup. It deletes all textures and releases all movie objects.
 *
 */
void PsychGSExitMovies(void)
{
    PsychWindowRecordType	**windowRecordArray;
    int				i, numWindows; 
    
    // Release all Quicktime related OpenGL textures:
    PsychCreateVolatileWindowRecordPointerList(&numWindows, &windowRecordArray);
    for(i=0; i<numWindows; i++) {
        // Delete all Quicktime textures:
        if ((windowRecordArray[i]->windowType == kPsychTexture) && (windowRecordArray[i]->targetSpecific.QuickTimeGLTexture !=NULL)) { 
            PsychCloseWindow(windowRecordArray[i]);
        }
    }
    PsychDestroyVolatileWindowRecordPointerList(windowRecordArray);
    
    // Release all movies:
    PsychGSDeleteAllMovies();

    firsttime = TRUE;
    
    return;
}
PsychError SCREENClose(void)

{

	PsychWindowRecordType 	*windowRecord;

        int			screenNumber;

        PsychWindowRecordType	**windowRecordArray;

        int			i, numWindows; 

	

        windowRecord=NULL;

        

	//all subfunctions should have these two lines.  

	PsychPushHelp(useString, synopsisString, seeAlsoString);

	if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};

	

	PsychErrorExit(PsychCapNumInputArgs(1));      //The maximum number of inputs

        PsychErrorExit(PsychRequireNumInputArgs(0));  //The minimum required number of inputs	

	PsychErrorExit(PsychCapNumOutputArgs(0));     //The maximum number of outputs

	

	//Get the window record or exit with an error if the windex was bogus.

	// PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord);        

	PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, kPsychArgOptional, &windowRecord);

        

        // Window handle of a specific window provided?

        if (windowRecord==NULL) {

            // No window handle provided: In this case, we close/destroy all textures:

            PsychCreateVolatileWindowRecordPointerList(&numWindows, &windowRecordArray);

            for(i=0;i<numWindows;i++) {

                if (windowRecordArray[i]->windowType==kPsychTexture) PsychCloseWindow(windowRecordArray[i]);

            }

            PsychDestroyVolatileWindowRecordPointerList(windowRecordArray);

            return(PsychError_none);	

        }

        

        // Window handle of a specific window or texture provided: Close it...

        if(PsychIsLastOnscreenWindow(windowRecord)){

		screenNumber=windowRecord->screenNumber;

		PsychCloseWindow(windowRecord);

		PsychReleaseScreen(screenNumber);

	}else	

		PsychCloseWindow(windowRecord);

    

	return(PsychError_none);	

}
// Implement closing of all onscreen- and offscreen windows, release of all captured displays,
// releasing of all internal textures and memory buffers, stopping of internal helper threads,
// etc....
// This routine is normally called by SCREENCloseAll, but can be also called by the exit-handler,
// and diverse error-handlers for cleanup.
void ScreenCloseAllWindows(void)
{
    PsychWindowRecordType	**windowRecordArray;
    int						i, numWindows, numScreens;
    static unsigned int     recursionLevel = 0;
    
    // Recursive self-call?
    if (recursionLevel > 0) {
        // Ohoh: We are recursively calling ourselves, probably due to some
        // error condition triggered during our execution. This is bad, we need
        // to break the infinite recursion. How? We output a recursion warning,
        // then return as no-op:
        printf("PTB-ERROR: Error during error handling! ScreenCloseAllWindows() called recursively! Trying to break out of this vicious cycle...\n");
        printf("PTB-ERROR: Maybe it is a good idea to exit and restart Matlab/Octave.\n");

        // Skip to the release screen routine and hope for the best:
        goto critical_abort;
    }
    
    recursionLevel++;
    
    // Cold-Reset the drawing target:
    PsychColdResetDrawingTarget();

	// Reset the "userspaceGL" flag which tells PTB that userspace GL rendering was active
	// due to Screen('BeginOpenGL') command.
	PsychSetUserspaceGLFlag(FALSE);
	
	// Check for stale texture ressources:
	PsychRessourceCheckAndReminder(TRUE);	
	
    // Shutdown Quicktime subsystems if active:
	PsychExitMovieWriting();
    PsychExitMovies();
    PsychExitVideoCapture();

    // Close the windows: We do it reverse (descending) order so textures get closed
    // before the onscreen windows. In theory this shouldn't matter, but in practice,
    // more stress on the PsychCloseWindow() path. If we have bugs there, chances are
    // higher they get exposed this way, which long-term is a good thing(TM).
    PsychCreateVolatileWindowRecordPointerList(&numWindows, &windowRecordArray);
    for(i = numWindows - 1; i >= 0; i--) {
		if (PsychPrefStateGet_Verbosity()>5) { printf("PTB-DEBUG: In ScreenCloseAllWindows(): Destroying window %i\n", i); fflush(NULL); }
		PsychCloseWindow(windowRecordArray[i]);
	}
    PsychDestroyVolatileWindowRecordPointerList(windowRecordArray);

critical_abort:

    // Release all captured displays, unhide the cursor on each of them:
    numScreens=PsychGetNumDisplays();
    for(i=0;i<numScreens;i++){
        if(PsychIsScreenCaptured(i)) {
			PsychRestoreScreenSettings(i);
			PsychReleaseScreen(i);
		}
		 
		PsychShowCursor(i, -1);
    }

    recursionLevel--;
    
    return;
}