PsychError SCREENPreference(void) { PsychArgFormatType arg1Type; char *preferenceName, *newFontName; const char *tableCreator, *oldDefaultFontName; Boolean preferenceNameArgumentValid, booleanInput, ignoreCase, tempFlag, textAlphaBlendingFlag, suppressAllWarningsFlag; int numInputArgs, i, newFontStyleNumber, newFontSize, tempInt; double returnDoubleValue, inputDoubleValue; //all sub functions should have these two lines PsychPushHelp(useString, synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //check for superfluous or missing arguments PsychErrorExit(PsychCapNumInputArgs(3)); PsychErrorExit(PsychRequireNumInputArgs(1)); PsychErrorExit(PsychCapNumOutputArgs(1)); numInputArgs=PsychGetNumInputArgs(); arg1Type=PsychGetArgType(1); preferenceNameArgumentValid=FALSE; //Cases which require both a window pointer or screen number and preference name. Argument 1 is the wposn and argument 2 is the preference name. if( numInputArgs >= 2 && (PsychIsScreenNumberArg(1) || PsychIsScreenNumberArg(1)) && PsychGetArgType(2)==PsychArgType_char ){ PsychAllocInCharArg(2, kPsychArgRequired, &preferenceName); //preferences which require window pointer or screen number argument which we DO NOT support for(i=0;i<kPsychNumUnsupportedMacVideoPreferences;i++){ if(PsychMatch(preferenceName, unsupportedMacVideoPreferenceNames[i])) PsychErrorExit(PsychError_unsupportedOS9Preference); } //insert here conditionals to act on prefernces which accept a window pointer or screen number argument which we DO support. PsychErrorExit(PsychError_unrecognizedPreferenceName); } //Cases which do not require a wposn. Argument 1 is the preference name. if present Argument 2 is the new value if(arg1Type==PsychArgType_char){ PsychAllocInCharArg(1, kPsychArgRequired, &preferenceName); //Preferernces which we do not support and which do not require a wposn for(i=0;i<kPsychNumUnsupportedMacNonVideoPreferences;i++){ if(PsychMatch(preferenceName, unsupportedMacNonVideoPreferenceNames[i])) PsychErrorExit(PsychError_unsupportedOS9Preference); } //Preferences which we do support if(PsychMatch(preferenceName, "IgnoreCase")){ ignoreCase=!PsychIsPsychMatchCaseSensitive(); PsychCopyOutFlagArg(1, kPsychArgOptional, ignoreCase); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &booleanInput); PsychSetPsychMatchCaseSenstive(!booleanInput); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Tick0Secs")){ if(PsychCopyInDoubleArg(2, kPsychArgOptional, &inputDoubleValue) && inputDoubleValue==PsychGetNanValue()) PsychEstimateGetSecsValueAtTickCountZero(); returnDoubleValue=PsychGetEstimatedSecsValueAtTickCountZero(); PsychCopyOutDoubleArg(1, kPsychArgOptional, returnDoubleValue); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "PsychTableVersion")){ if(numInputArgs==2) PsychErrorExit(PsychError_extraInputArg); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double)PsychPrefStateGet_PsychTableVersion()); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "PsychTableCreator")){ if(numInputArgs==2) PsychErrorExit(PsychError_extraInputArg); tableCreator=PsychPrefStateGet_PsychTableCreator(); PsychCopyOutCharArg(1, kPsychArgOptional, tableCreator); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Process")){ if(numInputArgs==2) PsychErrorExit(PsychError_extraInputArg); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double)getpid()); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultFontName")){ PsychPrefStateGet_DefaultFontName(&oldDefaultFontName); PsychCopyOutCharArg(1, kPsychArgOptional, oldDefaultFontName); if(numInputArgs==2){ PsychAllocInCharArg(2, kPsychArgRequired, &newFontName); PsychPrefStateSet_DefaultFontName(newFontName); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultFontStyle")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_DefaultTextStyle()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &newFontStyleNumber); PsychPrefStateSet_DefaultTextStyle(newFontStyleNumber); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultTextYPositionIsBaseline")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_TextYPositionIsBaseline()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_TextYPositionIsBaseline(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultFontSize")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_DefaultTextSize()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &newFontSize); PsychPrefStateSet_DefaultTextSize(newFontSize); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DebugMakeTexture")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_DebugMakeTexture()); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &tempFlag); PsychPrefStateSet_DebugMakeTexture(tempFlag); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "SkipSyncTests")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_SkipSyncTests()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_SkipSyncTests(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "VisualDebugLevel")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VisualDebugLevel()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VisualDebugLevel(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "VBLTimestampingMode")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VBLTimestampingMode()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VBLTimestampingMode(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "ConserveVRAM")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_ConserveVRAM()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_ConserveVRAM(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Verbosity")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_Verbosity()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_Verbosity(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "EmulateOldPTB")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_EmulateOldPTB()); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &tempFlag); PsychPrefStateSet_EmulateOldPTB(tempFlag); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Enable3DGraphics")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_3DGfx()); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &tempFlag); PsychPrefStateSet_3DGfx(tempFlag); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "TextAlphaBlending")){ textAlphaBlendingFlag=PsychPrefStateGet_TextAlphaBlending(); PsychCopyOutFlagArg(1, kPsychArgOptional, textAlphaBlendingFlag); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &booleanInput); PsychPrefStateSet_TextAlphaBlending(booleanInput); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "SuppressAllWarnings")){ suppressAllWarningsFlag=PsychPrefStateGet_SuppressAllWarnings(); PsychCopyOutFlagArg(1, kPsychArgOptional, suppressAllWarningsFlag); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &booleanInput); PsychPrefStateSet_SuppressAllWarnings(booleanInput); } preferenceNameArgumentValid=TRUE; }else PsychErrorExit(PsychError_unrecognizedPreferenceName); } if(!preferenceNameArgumentValid) PsychErrorExitMsg(PsychError_user, "Invalid arguments to preferences command"); return(PsychError_none); }
PsychError SCREENNull(void) { const double defaultMatrix[] = {1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4}; const double defaultM=2, defaultN=4; double tempValue; double *array; int i, m,n, p, numInArgs, numOutArgs, numNamedOutArgs; char *str; PsychArgFormatType format; const char defaultString[] = "I am the default string\n"; //all sub functions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //demonstrate how we find the function and subfunction names //printf("Psychtoolbox function: %s, subfunction %s\n", PsychGetModuleName(), PsychGetFunctionName() ); //copy all the input argument to their outputs if we have doubles, if not error. numInArgs = PsychGetNumInputArgs(); numOutArgs = PsychGetNumOutputArgs(); numNamedOutArgs = PsychGetNumNamedOutputArgs(); PsychErrorExit(PsychCapNumOutputArgs(numInArgs)); /* printf("number of input arguments: %d\n", numInArgs); printf("number of output arguments: %d\n", numOutArgs); printf("number of named output arguments: %d\n", numNamedOutArgs); */ //iterate over each of the supplied inputs. If the input is a two-dimensional array //of doubles or a character array, then copy it to the output. for(i=1;i<=numInArgs;i++){ format = PsychGetArgType(i); switch(format){ case PsychArgType_double: if(PsychGetArgM(i)==1 && PsychGetArgN(i)==1){ tempValue=i; //if 1x1 double then the default return value is the arg position. PsychCopyInDoubleArg(i, FALSE, &tempValue); PsychCopyOutDoubleArg(i, FALSE, tempValue); }else{ PsychAllocInDoubleMatArg(i, FALSE, &m, &n, &p, &array); PsychCopyOutDoubleMatArg(i, FALSE, m, n, p, array); } break; case PsychArgType_char: str=NULL; //This tells PsychGetCharArg() to use its own (volatile) memory. PsychAllocInCharArg(i, FALSE, &str); PsychCopyOutCharArg(i, FALSE, str); break; case PsychArgType_default: PsychCopyOutCharArg(i, FALSE, defaultString); break; } } return(PsychError_none); }
PsychError SCREENPreference(void) { PsychArgFormatType arg1Type; char *preferenceName, *newFontName; const char *tableCreator, *oldDefaultFontName; psych_bool preferenceNameArgumentValid, booleanInput, ignoreCase, tempFlag, textAlphaBlendingFlag, suppressAllWarningsFlag; int numInputArgs, i, newFontStyleNumber, newFontSize, tempInt, tempInt2, tempInt3, tempInt4; double returnDoubleValue, inputDoubleValue; double maxStddev, maxDeviation, maxDuration; int minSamples; double *dheads = NULL; //all sub functions should have these two lines PsychPushHelp(useString, synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //check for superfluous or missing arguments PsychErrorExit(PsychCapNumInputArgs(5)); PsychErrorExit(PsychRequireNumInputArgs(1)); PsychErrorExit(PsychCapNumOutputArgs(4)); numInputArgs=PsychGetNumInputArgs(); arg1Type=PsychGetArgType(1); preferenceNameArgumentValid=FALSE; //Cases which require both a window pointer or screen number and preference name. Argument 1 is the wposn and argument 2 is the preference name. if( numInputArgs >= 2 && (PsychIsScreenNumberArg(1) || PsychIsScreenNumberArg(1)) && PsychGetArgType(2)==PsychArgType_char ){ PsychAllocInCharArg(2, kPsychArgRequired, &preferenceName); //preferences which require window pointer or screen number argument which we DO NOT support for(i=0;i<kPsychNumUnsupportedMacVideoPreferences;i++){ if(PsychMatch(preferenceName, unsupportedMacVideoPreferenceNames[i])) PsychErrorExit(PsychError_unsupportedOS9Preference); } //insert here conditionals to act on prefernces which accept a window pointer or screen number argument which we DO support. PsychErrorExit(PsychError_unrecognizedPreferenceName); } //Cases which do not require a wposn. Argument 1 is the preference name. if present Argument 2 is the new value if(arg1Type==PsychArgType_char){ PsychAllocInCharArg(1, kPsychArgRequired, &preferenceName); //Preferernces which we do not support and which do not require a wposn for(i=0;i<kPsychNumUnsupportedMacNonVideoPreferences;i++){ if(PsychMatch(preferenceName, unsupportedMacNonVideoPreferenceNames[i])) PsychErrorExit(PsychError_unsupportedOS9Preference); } //Preferences which we do support if(PsychMatch(preferenceName, "IgnoreCase")){ ignoreCase=!PsychIsPsychMatchCaseSensitive(); PsychCopyOutFlagArg(1, kPsychArgOptional, ignoreCase); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &booleanInput); PsychSetPsychMatchCaseSenstive(!booleanInput); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Tick0Secs")){ if(PsychCopyInDoubleArg(2, kPsychArgOptional, &inputDoubleValue) && inputDoubleValue==PsychGetNanValue()) PsychEstimateGetSecsValueAtTickCountZero(); returnDoubleValue=PsychGetEstimatedSecsValueAtTickCountZero(); PsychCopyOutDoubleArg(1, kPsychArgOptional, returnDoubleValue); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "PsychTableVersion")){ if(numInputArgs==2) PsychErrorExit(PsychError_extraInputArg); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double)PsychPrefStateGet_PsychTableVersion()); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "PsychTableCreator")){ if(numInputArgs==2) PsychErrorExit(PsychError_extraInputArg); tableCreator=PsychPrefStateGet_PsychTableCreator(); PsychCopyOutCharArg(1, kPsychArgOptional, tableCreator); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Process")){ if(numInputArgs==2) PsychErrorExit(PsychError_extraInputArg); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) (psych_int64) getpid()); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultFontName")){ PsychPrefStateGet_DefaultFontName(&oldDefaultFontName); PsychCopyOutCharArg(1, kPsychArgOptional, oldDefaultFontName); if(numInputArgs==2){ PsychAllocInCharArg(2, kPsychArgRequired, &newFontName); PsychPrefStateSet_DefaultFontName(newFontName); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "TextEncodingLocale")){ PsychCopyOutCharArg(1, kPsychArgOptional, PsychGetUnicodeTextConversionLocale()); if(numInputArgs==2){ PsychAllocInCharArg(2, kPsychArgRequired, &newFontName); if (!PsychSetUnicodeTextConversionLocale(newFontName)) PsychErrorExitMsg(PsychError_user, "Setting the 'TextEncodingLocale' failed, most likely because you provided an invalid/unknown locale setting string."); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultFontStyle")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_DefaultTextStyle()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &newFontStyleNumber); PsychPrefStateSet_DefaultTextStyle(newFontStyleNumber); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "OverrideMultimediaEngine")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_UseGStreamer()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_UseGStreamer(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultTextYPositionIsBaseline")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_TextYPositionIsBaseline()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_TextYPositionIsBaseline(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "TextAntiAliasing")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_TextAntiAliasing()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_TextAntiAliasing(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "TextRenderer")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_TextRenderer()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_TextRenderer(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultFontSize")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_DefaultTextSize()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &newFontSize); PsychPrefStateSet_DefaultTextSize(newFontSize); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DebugMakeTexture")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_DebugMakeTexture()); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &tempFlag); PsychPrefStateSet_DebugMakeTexture(tempFlag); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "SkipSyncTests")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_SkipSyncTests()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_SkipSyncTests(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "VisualDebugLevel")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VisualDebugLevel()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VisualDebugLevel(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "VBLTimestampingMode")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VBLTimestampingMode()); if(numInputArgs>=2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VBLTimestampingMode(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "SyncTestSettings")){ PsychPrefStateGet_SynctestThresholds(&maxStddev, &minSamples, &maxDeviation, &maxDuration); PsychCopyOutDoubleArg(1, kPsychArgOptional, maxStddev); PsychCopyOutDoubleArg(2, kPsychArgOptional, minSamples); PsychCopyOutDoubleArg(3, kPsychArgOptional, maxDeviation); PsychCopyOutDoubleArg(4, kPsychArgOptional, maxDuration); if(numInputArgs>=2){ PsychCopyInDoubleArg( 2, kPsychArgOptional, &maxStddev); PsychCopyInIntegerArg(3, kPsychArgOptional, &minSamples); PsychCopyInDoubleArg( 4, kPsychArgOptional, &maxDeviation); PsychCopyInDoubleArg( 5, kPsychArgOptional, &maxDuration); PsychPrefStateSet_SynctestThresholds(maxStddev, minSamples, maxDeviation, maxDuration); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "VBLEndlineOverride")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VBLEndlineOverride()); if(numInputArgs>=2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VBLEndlineOverride(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultVideocaptureEngine")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VideoCaptureEngine()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VideoCaptureEngine(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "WindowShieldingLevel")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_WindowShieldingLevel()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_WindowShieldingLevel(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "ConserveVRAM") || PsychMatch(preferenceName, "Workarounds1")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_ConserveVRAM()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_ConserveVRAM(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Verbosity")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_Verbosity()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_Verbosity(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "FrameRectCorrection")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_FrameRectCorrection()); if(numInputArgs==2){ PsychCopyInDoubleArg(2, kPsychArgRequired, &inputDoubleValue); PsychPrefStateSet_FrameRectCorrection(inputDoubleValue); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "EmulateOldPTB")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_EmulateOldPTB()); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &tempFlag); PsychPrefStateSet_EmulateOldPTB(tempFlag); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Enable3DGraphics")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_3DGfx()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_3DGfx(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "TextAlphaBlending")){ textAlphaBlendingFlag=PsychPrefStateGet_TextAlphaBlending(); PsychCopyOutFlagArg(1, kPsychArgOptional, textAlphaBlendingFlag); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &booleanInput); PsychPrefStateSet_TextAlphaBlending(booleanInput); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "SuppressAllWarnings")){ suppressAllWarningsFlag=PsychPrefStateGet_SuppressAllWarnings(); PsychCopyOutFlagArg(1, kPsychArgOptional, suppressAllWarningsFlag); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &booleanInput); PsychPrefStateSet_SuppressAllWarnings(booleanInput); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "SynchronizeDisplays")){ if(numInputArgs >= 2) { // This is a special call: It currently doesn't set a preference setting, // but instead triggers an instantaneous synchronization of all available // display heads, if possible. We may have a more clever and "standard" interface // interface for this later on, but for first tests this will do. // Syncmethod is hard-coded to 0 -> Use whatever's available to sync. // timeout for retries is 5.0 seconds. // Acceptable residual offset is +/- 2 scanlines. // Returns the real residual offset after sync. PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); if (!PsychCopyInIntegerArg(3, kPsychArgOptional, &tempInt3)) { // No screenId specified: Resync default screen or whatever... tempInt2 = 0; if (PsychSynchronizeDisplayScreens(&tempInt2, NULL, &tempInt, tempInt, 5.0, 2)!=PsychError_none) PsychErrorExitMsg(PsychError_user, "Sync failed for reasons mentioned above."); } else { // Specific screenId provided: Resync crtc's associated with this screenId if possible: tempInt2 = 1; if (PsychSynchronizeDisplayScreens(&tempInt2, &tempInt3, &tempInt, tempInt, 5.0, 2)!=PsychError_none) PsychErrorExitMsg(PsychError_user, "Sync failed for reasons mentioned above."); } PsychCopyOutDoubleArg(1, kPsychArgOptional, tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "ScreenToHead")){ // screenId is required: PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); if (tempInt < 0 || tempInt >= PsychGetNumDisplays() || tempInt >= kPsychMaxPossibleDisplays) PsychErrorExitMsg(PsychError_user, "Invalid screenId provided. Out of valid range!"); // Return old mappings for this screenId: for (tempInt2 = 0; (tempInt2 < kPsychMaxPossibleCrtcs) && (PsychPrefStateGet_ScreenToHead(tempInt, tempInt2) >= 0); tempInt2++); PsychAllocOutDoubleMatArg(1, kPsychArgOptional, 2, tempInt2, 1, &dheads); tempInt4 = 0; for (tempInt3 = 0; tempInt3 < tempInt2; tempInt3++) { dheads[tempInt4++] = (double) PsychPrefStateGet_ScreenToHead(tempInt, tempInt3); dheads[tempInt4++] = (double) PsychPrefStateGet_ScreenToCrtcId(tempInt, tempInt3); } // Optionally retrieve and set new mappings for this screenId: if(numInputArgs>=3) { // Set new headId for screenId: PsychCopyInIntegerArg(3, kPsychArgRequired, &tempInt2); if (tempInt2 < 0) PsychErrorExitMsg(PsychError_user, "Invalid negative headId provided!"); // Set new crtcId for screenId: PsychCopyInIntegerArg(4, kPsychArgRequired, &tempInt3); if (tempInt3 < 0) PsychErrorExitMsg(PsychError_user, "Invalid negative crtcId provided!"); // Assign primary head by default (index 0), but allow optionally others as well: tempInt4 = 0; PsychCopyInIntegerArg(5, kPsychArgOptional, &tempInt4); if (tempInt4 < 0 || tempInt4 >= kPsychMaxPossibleCrtcs) PsychErrorExitMsg(PsychError_user, "Invalid rankId provided! Too many heads for one screen!"); PsychPrefStateSet_ScreenToHead(tempInt, tempInt2, tempInt3, tempInt4); } preferenceNameArgumentValid=TRUE; }else PsychErrorExit(PsychError_unrecognizedPreferenceName); } if(!preferenceNameArgumentValid) PsychErrorExitMsg(PsychError_user, "Invalid arguments to preferences command"); return(PsychError_none); }
PsychError MACHPRIORITYMachPriority(void) { //double *returnValue; //int newPriority; const char *outerStructFieldNames[]={"thread", "flavor", "policy"}; const char *policyStructFieldNames[]={"period", "computation", "constraint", "preemptible"}; int numOuterStructDimensions=1, numOuterStructFieldNames=3, numPolicyStructDimensions=1, numPolicyStructFieldNames=4; PsychGenericScriptType *outerStructArray, *policyStructArray; int kernError, numInputArgs; thread_act_t threadID; static thread_policy_flavor_t currentThreadFlavor=THREAD_STANDARD_POLICY; struct thread_time_constraint_policy oldPolicyInfo, newPolicyInfo; mach_msg_type_number_t msgTypeNumber; boolean_t getDefault; char *flavorStr; boolean setNewMode; double *periodArg, *computationArg, *constraintArg, *preemptibleArg; char errorMessageStr[256]; //check to see if the user supplied superfluous arguments PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(4)); //actually we permit only zero or three arguments. numInputArgs=PsychGetNumInputArgs(); if(numInputArgs==4) setNewMode=TRUE; else if(numInputArgs==0) setNewMode=FALSE; else PsychErrorExitMsg(PsychError_user,"Incorrect number of arguments. Either zero or four arguments accepted"); //read the current settings threadID= mach_thread_self(); currentThreadFlavor=THREAD_TIME_CONSTRAINT_POLICY; msgTypeNumber=THREAD_TIME_CONSTRAINT_POLICY_COUNT; getDefault=FALSE; kernError= thread_policy_get(threadID, currentThreadFlavor, (int *)&oldPolicyInfo, &msgTypeNumber, &getDefault); if(kernError != KERN_SUCCESS) PsychErrorExitMsg(PsychError_internal,"\"thread_policy_get()\" returned and error when reading current thread policy"); //fill in the outgoig struct with current thread settings values. //outer struct PsychAllocOutStructArray(1, FALSE, numOuterStructDimensions, numOuterStructFieldNames, outerStructFieldNames, &outerStructArray); PsychSetStructArrayDoubleElement("thread", 0, (double)threadID, outerStructArray); flavorStr=GetFlavorStringFromFlavorConstant(currentThreadFlavor); PsychSetStructArrayStringElement("flavor", 0, flavorStr, outerStructArray); //enclosed policy struct PsychAllocOutStructArray(-1, FALSE, numPolicyStructDimensions, numPolicyStructFieldNames, policyStructFieldNames, &policyStructArray); PsychSetStructArrayDoubleElement("period", 0, (double)oldPolicyInfo.period, policyStructArray); PsychSetStructArrayDoubleElement("computation", 0, (double)oldPolicyInfo.computation, policyStructArray); PsychSetStructArrayDoubleElement("constraint", 0, (double)oldPolicyInfo.constraint, policyStructArray); PsychSetStructArrayDoubleElement("preemptible", 0, (double)oldPolicyInfo.preemptible, policyStructArray); PsychSetStructArrayStructElement("policy",0, policyStructArray, outerStructArray); //Set the priority if(setNewMode){ //if there is only one argument then it must be the flavor argument re PsychAllocInDoubleArg(1, TRUE, &periodArg); PsychAllocInDoubleArg(2, TRUE, &computationArg); PsychAllocInDoubleArg(3, TRUE, &constraintArg); PsychAllocInDoubleArg(4, TRUE, &preemptibleArg); newPolicyInfo.period=(uint32_t)*periodArg; newPolicyInfo.computation=(uint32_t)*computationArg; newPolicyInfo.constraint=(uint32_t)*constraintArg; newPolicyInfo.preemptible=(boolean_t)*preemptibleArg; kernError= thread_policy_set(threadID, THREAD_TIME_CONSTRAINT_POLICY, (int *)&newPolicyInfo, THREAD_TIME_CONSTRAINT_POLICY_COUNT); if(kernError != KERN_SUCCESS){ sprintf(errorMessageStr,"%s%d", "\"thread_policy_set()\" returned and error when setting new thread policy: ", (int)kernError); PsychErrorExitMsg(PsychError_internal, errorMessageStr); } } return(PsychError_none); }
PsychError SCREENDrawDots(void) { PsychWindowRecordType *windowRecord, *parentWindowRecord; int m,n,p,mc,nc,idot_type; int i, nrpoints, nrsize; psych_bool isArgThere, usecolorvector, isdoublecolors, isuint8colors; double *xy, *size, *center, *dot_type, *colors; float *sizef; unsigned char *bytecolors; GLfloat pointsizerange[2]; psych_bool lenient = FALSE; psych_bool usePointSizeArray = FALSE; static psych_bool nocando = FALSE; int oldverbosity; // All sub functions should have these two lines PsychPushHelp(useString, synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; // Check for superfluous arguments PsychErrorExit(PsychCapNumInputArgs(7)); //The maximum number of inputs PsychErrorExit(PsychCapNumOutputArgs(4)); //The maximum number of outputs // Get the window record from the window record argument and get info from the window record PsychAllocInWindowRecordArg(1, kPsychArgRequired, &windowRecord); // Get dot_type argument, if any, as it is already needed for a pure point size range query below: isArgThere = PsychIsArgPresent(PsychArgIn, 6); if(!isArgThere){ idot_type = 0; } else { PsychAllocInDoubleMatArg(6, TRUE, &m, &n, &p, &dot_type); if(p != 1 || n != 1 || m != 1 || (dot_type[0] < 0 || dot_type[0] > 4)) PsychErrorExitMsg(PsychError_user, "dot_type must be 0, 1, 2, 3 or 4"); idot_type = (int) dot_type[0]; } // Query for supported point size range? if (PsychGetNumOutputArgs() > 0) { PsychSetDrawingTarget(windowRecord); // Always query and return aliased range: glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, (GLfloat*) &pointsizerange); PsychCopyOutDoubleArg(3, FALSE, (double) pointsizerange[0]); PsychCopyOutDoubleArg(4, FALSE, (double) pointsizerange[1]); // If driver supports smooth points and usercode doesn't specify a dot type (idot_type 0) // or does not request shader + point-sprite based drawing then return smooth point // size range as "smooth point size range" - query and assign it. Otherwise, ie., code // explicitely wants to use a shader (idot_type >= 3) or has to use one, we will use // point-sprites and that means the GL_ALIASED_POINT_SIZE_RANGE limits apply also to // our shader based smooth dots, so return those: if ((windowRecord->gfxcaps & kPsychGfxCapSmoothPrimitives) && (idot_type < 3)) glGetFloatv(GL_POINT_SIZE_RANGE, (GLfloat*) &pointsizerange); // Whatever the final choice for smooth dots is, return its limits: PsychCopyOutDoubleArg(1, FALSE, (double) pointsizerange[0]); PsychCopyOutDoubleArg(2, FALSE, (double) pointsizerange[1]); // If this was only a query then we are done: if (PsychGetNumInputArgs() < 2) return(PsychError_none); } // Query, allocate and copy in all vectors... nrpoints = 2; nrsize = 0; colors = NULL; bytecolors = NULL; PsychPrepareRenderBatch(windowRecord, 2, &nrpoints, &xy, 4, &nc, &mc, &colors, &bytecolors, 3, &nrsize, &size, (GL_FLOAT == PsychGLFloatType(windowRecord))); isdoublecolors = (colors) ? TRUE:FALSE; isuint8colors = (bytecolors) ? TRUE:FALSE; usecolorvector = (nc>1) ? TRUE:FALSE; // Assign sizef as float-type array of sizes, if float mode active, NULL otherwise: sizef = (GL_FLOAT == PsychGLFloatType(windowRecord)) ? (float*) size : NULL; // Get center argument isArgThere = PsychIsArgPresent(PsychArgIn, 5); if(!isArgThere){ center = (double *) PsychMallocTemp(2 * sizeof(double)); center[0] = 0; center[1] = 0; } else { PsychAllocInDoubleMatArg(5, TRUE, &m, &n, &p, ¢er); if(p!=1 || n!=2 || m!=1) PsychErrorExitMsg(PsychError_user, "center must be a 1-by-2 vector"); } // Turn on antialiasing to draw circles? Or idot_type 4 for shader based square dots? if (idot_type) { // Smooth point rendering supported by gfx-driver and hardware? And user does not request our own stuff? if ((idot_type == 3) || (idot_type == 4) || !(windowRecord->gfxcaps & kPsychGfxCapSmoothPrimitives)) { // No. Need to roll our own shader + point sprite solution. if (!windowRecord->smoothPointShader && !nocando) { parentWindowRecord = PsychGetParentWindow(windowRecord); if (!parentWindowRecord->smoothPointShader) { // Build and assign shader to parent window, but allow this to silently fail: oldverbosity = PsychPrefStateGet_Verbosity(); PsychPrefStateSet_Verbosity(0); parentWindowRecord->smoothPointShader = PsychCreateGLSLProgram(PointSmoothFragmentShaderSrc, PointSmoothVertexShaderSrc, NULL); PsychPrefStateSet_Verbosity(oldverbosity); } if (parentWindowRecord->smoothPointShader) { // Got one compiled - assign it for use: windowRecord->smoothPointShader = parentWindowRecord->smoothPointShader; } else { // Failed. Record this failure so we can avoid retrying at next DrawDots invocation: nocando = TRUE; } } if (windowRecord->smoothPointShader) { // Activate point smooth shader, and point sprite operation on texunit 1 for coordinates on set 1: PsychSetShader(windowRecord, windowRecord->smoothPointShader); glActiveTexture(GL_TEXTURE1); glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); glActiveTexture(GL_TEXTURE0); glEnable(GL_POINT_SPRITE); // Tell shader from where to get its color information: Unclamped high precision colors from texture coordinate set 0, or regular colors from vertex color attribute? glUniform1i(glGetUniformLocation(windowRecord->smoothPointShader, "useUnclampedFragColor"), (windowRecord->defaultDrawShader) ? 1 : 0); // Tell shader if it should shade smooth round dots, or square dots: glUniform1i(glGetUniformLocation(windowRecord->smoothPointShader, "drawRoundDots"), (idot_type != 4) ? 1 : 0); // Tell shader about current point size in pointSize uniform: glEnable(GL_PROGRAM_POINT_SIZE); usePointSizeArray = TRUE; } else if (idot_type != 4) { // Game over for round dot drawing: PsychErrorExitMsg(PsychError_user, "Point smoothing unsupported on your system and our shader based implementation failed as well in Screen('DrawDots')."); } else { // Type 4 requested but unsupported. Fallback to type 0, which is the same, just slower: idot_type = 0; } // Request square dots, without anti-aliasing: Better compatibility with // shader + point sprite operation, and needed for idot_type 0 fallback. glDisable(GL_POINT_SMOOTH); glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, (GLfloat*) &pointsizerange); } else { // User wants hw anti-aliased round smooth dots (idot_type = 1 or 2) and // hardware + driver support this. Request smooth points from hardware: glEnable(GL_POINT_SMOOTH); glGetFloatv(GL_POINT_SIZE_RANGE, (GLfloat*) &pointsizerange); // A dot type of 2 requests highest quality point smoothing: glHint(GL_POINT_SMOOTH_HINT, (idot_type > 1) ? GL_NICEST : GL_DONT_CARE); } } else { glDisable(GL_POINT_SMOOTH); glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, (GLfloat*) &pointsizerange); } // Does ES-GPU only support a fixed point diameter of 1 pixel? if ((pointsizerange[1] <= 1) && PsychIsGLES(windowRecord)) { // Yes. Not much point bailing on this, as it should be easily visible // during testing of a studies code on a OpenGL-ES device. lenient = TRUE; } // Accept optional 'lenient' flag, if provided: PsychCopyInFlagArg(7, FALSE, &lenient); // Set size of a single dot: if (!lenient && ((sizef && (sizef[0] > pointsizerange[1] || sizef[0] < pointsizerange[0])) || (!sizef && (size[0] > pointsizerange[1] || size[0] < pointsizerange[0])))) { printf("PTB-ERROR: You requested a point size of %f units, which is not in the range (%f to %f) supported by your graphics hardware.\n", (sizef) ? sizef[0] : size[0], pointsizerange[0], pointsizerange[1]); PsychErrorExitMsg(PsychError_user, "Unsupported point size requested in Screen('DrawDots')."); } // Setup initial common point size for all points: if (!usePointSizeArray) glPointSize((sizef) ? sizef[0] : (float) size[0]); if (usePointSizeArray) glMultiTexCoord1f(GL_TEXTURE2, (sizef) ? sizef[0] : (float) size[0]); // Setup modelview matrix to perform translation by 'center': glMatrixMode(GL_MODELVIEW); // Make a backup copy of the matrix: glPushMatrix(); // Apply a global translation of (center(x,y)) pixels to all following points: glTranslatef((float) center[0], (float) center[1], 0); // Render the array of 2D-Points - Efficient version: // This command sequence allows fast processing of whole arrays // of vertices (or points, in this case). It saves the call overhead // associated with the original implementation below and is potentially // optimized in specific OpenGL implementations. // Pass a pointer to the start of the point-coordinate array: glVertexPointer(2, PSYCHGLFLOAT, 0, &xy[0]); // Enable fast rendering of arrays: glEnableClientState(GL_VERTEX_ARRAY); if (usecolorvector) { PsychSetupVertexColorArrays(windowRecord, TRUE, mc, colors, bytecolors); } // Render all n points, starting at point 0, render them as POINTS: if ((nrsize == 1) || usePointSizeArray) { // Only one common size provided, or efficient shader based // path in use. We can use the fast path of only submitting // one glDrawArrays call to draw all GL_POINTS. For a single // common size, no further setup is needed. if (nrsize > 1) { // Individual size for each dot provided. Setup texture unit 2 // with a 1D texcoord array that stores per point size info in // texture coordinate set 2. But first validate point sizes: for (i = 0; i < nrpoints; i++) { if (!lenient && ((sizef && (sizef[i] > pointsizerange[1] || sizef[i] < pointsizerange[0])) || (!sizef && (size[i] > pointsizerange[1] || size[i] < pointsizerange[0])))) { printf("PTB-ERROR: You requested a point size of %f units, which is not in the range (%f to %f) supported by your graphics hardware.\n", (sizef) ? sizef[i] : size[i], pointsizerange[0], pointsizerange[1]); PsychErrorExitMsg(PsychError_user, "Unsupported point size requested in Screen('DrawDots')."); } } // Sizes are fine, setup texunit 2: glClientActiveTexture(GL_TEXTURE2); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(1, (sizef) ? GL_FLOAT : GL_DOUBLE, 0, (sizef) ? (const GLvoid*) sizef : (const GLvoid*) size); } // Draw all points: glDrawArrays(GL_POINTS, 0, nrpoints); if (nrsize > 1) { // Individual size for each dot provided. Reset texture unit 2: glTexCoordPointer(1, (sizef) ? GL_FLOAT : GL_DOUBLE, 0, (const GLvoid*) NULL); glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Back to default texunit 0: glClientActiveTexture(GL_TEXTURE0); } } else { // Different size for each dot provided and we can't use our shader based implementation: // We have to do One GL - call per dot: for (i=0; i<nrpoints; i++) { if (!lenient && ((sizef && (sizef[i] > pointsizerange[1] || sizef[i] < pointsizerange[0])) || (!sizef && (size[i] > pointsizerange[1] || size[i] < pointsizerange[0])))) { printf("PTB-ERROR: You requested a point size of %f units, which is not in the range (%f to %f) supported by your graphics hardware.\n", (sizef) ? sizef[i] : size[i], pointsizerange[0], pointsizerange[1]); PsychErrorExitMsg(PsychError_user, "Unsupported point size requested in Screen('DrawDots')."); } // Setup point size for this point: if (!usePointSizeArray) glPointSize((sizef) ? sizef[i] : (float) size[i]); // Render point: glDrawArrays(GL_POINTS, i, 1); } } // Disable fast rendering of arrays: glDisableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, PSYCHGLFLOAT, 0, NULL); if (usecolorvector) PsychSetupVertexColorArrays(windowRecord, FALSE, 0, NULL, NULL); // Restore old matrix from backup copy, undoing the global translation: glPopMatrix(); // turn off antialiasing again if (idot_type) { glDisable(GL_POINT_SMOOTH); if (windowRecord->smoothPointShader) { // Deactivate point smooth shader and point sprite operation on texunit 1: PsychSetShader(windowRecord, 0); glActiveTexture(GL_TEXTURE1); glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_FALSE); glActiveTexture(GL_TEXTURE0); glDisable(GL_POINT_SPRITE); glDisable(GL_PROGRAM_POINT_SIZE); } } // Reset pointsize to 1.0 glPointSize(1); // Mark end of drawing op. This is needed for single buffered drawing: PsychFlushGL(windowRecord); //All psychfunctions require this. return(PsychError_none); }
PsychError SCREENGetCapturedImage(void) { PsychWindowRecordType *windowRecord; PsychWindowRecordType *textureRecord; PsychRectType rect; double summed_intensity; int capturehandle = -1; int waitForImage = TRUE; int specialmode = 0; double timeout, tnow; double presentation_timestamp = 0; int rc=-1; double targetmemptr = 0; double* tsummed = NULL; psych_uint8 *targetmatrixptr = NULL; static rawcapimgdata rawCaptureBuffer = {0, 0, 0, NULL}; // All sub functions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()) {PsychGiveHelp(); return(PsychError_none);}; PsychErrorExit(PsychCapNumInputArgs(6)); // Max. 6 input args. PsychErrorExit(PsychRequireNumInputArgs(2)); // Min. 2 input args required. PsychErrorExit(PsychCapNumOutputArgs(4)); // Max. 4 output args. // Get the window record from the window record argument and get info from the window record PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); // Only onscreen windows allowed: if(!PsychIsOnscreenWindow(windowRecord) && !PsychIsOffscreenWindow(windowRecord)) { PsychErrorExitMsg(PsychError_user, "GetCapturedImage called on something else than an onscreen window or offscreen window."); } // Get the handle: PsychCopyInIntegerArg(2, TRUE, &capturehandle); if (capturehandle==-1) { PsychErrorExitMsg(PsychError_user, "GetCapturedImage called without valid handle to a capture object."); } // Get the 'waitForImage' flag: If waitForImage == true == 1, we'll do a blocking wait for // arrival of a new image. Otherwise we will return with a 0-Handle if there // isn't any new image available. PsychCopyInIntegerArg(3, FALSE, &waitForImage); // Special case waitForImage == 4? This would ask to call into the capture driver, but // not wait for any image to arrive and not return any information. This is only useful // on OS/X and Windows when using the capture engine for video recording to harddisk. In // that case we are not interested at all in the captured live video, we just want it to // get written to harddisk in the background. To keep the video encoder going, we need to // call its SGIdle() routine and waitForImage==4 does just that, call SGIdle(). if (waitForImage == 4) { // Perform the null-call to the capture engine, ie a SGIdle() on OS/X and Windows: PsychGetTextureFromCapture(windowRecord, capturehandle, 4, 0.0, NULL, NULL, NULL, NULL); // Done. Nothing to return... return(PsychError_none); } // Get the optional textureRecord for the optional texture handle. If the calling script // provides the texture handle of an existing Psychtoolbox texture that has a matching // format, then that texture is recycled by overwriting its previous content with the // image data from the new captured image. This can save some overhead for texture destruction // and recreation. While this is probably not noticeable on mid- to high-end gfx cards with // rectangle texture support, it can provide a significant speedup on low-end gfx cards with // only power-of-two texture support. textureRecord = NULL; if ((PsychGetNumInputArgs()>=4) && PsychIsWindowIndexArg(4)) PsychAllocInWindowRecordArg(4, FALSE, &textureRecord); // Get the optional specialmode flag: PsychCopyInIntegerArg(5, FALSE, &specialmode); // Set a 10 second maximum timeout for waiting for new frames: PsychGetAdjustedPrecisionTimerSeconds(&timeout); timeout+=10; while (rc==-1) { // We pass a checkForImage value of 2 if waitForImage>0. This way we can signal if we are in polling or blocking mode. // With the libdc1394 engine this allows to do a real blocking wait in the driver -- much more efficient than the spin-waiting approach! rc = PsychGetTextureFromCapture(windowRecord, capturehandle, ((waitForImage>0 && waitForImage<3) ? 2 : 1), 0.0, NULL, &presentation_timestamp, NULL, &rawCaptureBuffer); PsychGetAdjustedPrecisionTimerSeconds(&tnow); if (rc==-2 || (tnow > timeout)) { // No image available and there won't be any in the future, because capture has been stopped or there is a timeout: if (tnow > timeout) printf("PTB-WARNING: In Screen('GetCapturedImage') timed out waiting for a new frame. No video data in over 10 seconds!\n"); // No new texture available: Return a negative handle: PsychCopyOutDoubleArg(1, TRUE, -1); // ...and an invalid timestamp: PsychCopyOutDoubleArg(2, FALSE, -1); PsychCopyOutDoubleArg(3, FALSE, 0); PsychCopyOutDoubleArg(4, FALSE, 0); // Ready! return(PsychError_none); } else if (rc==-1 && (waitForImage == 0 || waitForImage == 3)) { // We should just poll once and no new texture available: Return a null-handle: PsychCopyOutDoubleArg(1, TRUE, 0); // ...and the current timestamp: PsychCopyOutDoubleArg(2, FALSE, presentation_timestamp); PsychCopyOutDoubleArg(3, FALSE, 0); PsychCopyOutDoubleArg(4, FALSE, 0); // Ready! return(PsychError_none); } else if (rc==-1 && waitForImage != 0) { // No new texture available yet. Just sleep a bit and then retry... PsychYieldIntervalSeconds(0.002); } } // rc == 0 --> New image available: Go ahead... if (waitForImage!=2 && waitForImage!=3) { // Ok, we need a texture for the image. Did script provide an old one for recycling? if (textureRecord) { // Old texture provided for reuse? Some basic sanity check: Everything else is // up to the lower level PsychGetTextureFromCapture() routine. if(!PsychIsOffscreenWindow(textureRecord)) { PsychErrorExitMsg(PsychError_user, "GetCapturedImage provided with something else than a texture as fourth call parameter."); } } else { // No old texture provided: Create a new texture record: PsychCreateWindowRecord(&textureRecord); // Set mode to 'Texture': textureRecord->windowType=kPsychTexture; // We need to assign the screen number of the onscreen-window. textureRecord->screenNumber=windowRecord->screenNumber; // It defaults to a 32 bit texture for captured images. On Linux, this will be overriden, // if optimized formats exist for our purpose: textureRecord->depth=32; textureRecord->nrchannels = 4; // Create default rectangle which describes the dimensions of the image. Will be overwritten // later on. PsychMakeRect(rect, 0, 0, 10, 10); PsychCopyRect(textureRecord->rect, rect); // Other setup stuff: textureRecord->textureMemorySizeBytes= 0; textureRecord->textureMemory=NULL; // Assign parent window and copy its inheritable properties: PsychAssignParentWindow(textureRecord, windowRecord); // Set textureNumber to zero, which means "Not cached, do not recycle" // Todo: Texture recycling like in PsychMovieSupport for higher efficiency! textureRecord->textureNumber = 0; } // Power-of-two texture requested? if (specialmode & 0x01) { // Yes. Spec it: textureRecord->texturetarget = GL_TEXTURE_2D; } } else { // Just want to return summed_intensity and timestamp, not real texture... textureRecord = NULL; } // Default to no calculation of summed image intensity: tsummed = NULL; if ((PsychGetNumOutputArgs() > 3) && !(specialmode & 0x2)) { // Return sum of pixel intensities for all channels of this image: Need to // assign the output pointer for this to happen: tsummed = &summed_intensity; } // Try to fetch an image from the capture object and return it as texture: targetmatrixptr = NULL; // Shall we return a Matlab matrix? if ((PsychGetNumOutputArgs() > 3) && (specialmode & 0x2)) { // We shall return a matrix with raw image data. Allocate a uint8 matrix // of sufficient size: PsychAllocOutUnsignedByteMatArg(4, TRUE, rawCaptureBuffer.depth, rawCaptureBuffer.w, rawCaptureBuffer.h, &targetmatrixptr); tsummed = NULL; } // Shall we return data into preallocated memory buffer? if (specialmode & 0x4) { // Copy in memory address (which itself is encoded in a double value): PsychCopyInDoubleArg(6, TRUE, &targetmemptr); targetmatrixptr = (psych_uint8*) PsychDoubleToPtr(targetmemptr); } if (targetmatrixptr == NULL) { // Standard fetch of a texture and its timestamp: rc = PsychGetTextureFromCapture(windowRecord, capturehandle, 0, 0.0, textureRecord, &presentation_timestamp, tsummed, NULL); } else { // Fetch of a memory raw image buffer + timestamp + possibly a texture: rawCaptureBuffer.data = (void*) targetmatrixptr; rc = PsychGetTextureFromCapture(windowRecord, capturehandle, 0, 0.0, textureRecord, &presentation_timestamp, tsummed, &rawCaptureBuffer); } if (tsummed) { // Return sum of pixel intensities for all channels of this image: PsychCopyOutDoubleArg(4, FALSE, summed_intensity); } // Real texture requested? if (textureRecord) { // Texture ready for consumption. // Assign GLSL filter-/lookup-shaders if needed: usefloatformat is always == 0 as // our current capture engine implementations only return 8 bpc fixed textures. // The 'userRequest' flag is set if specialmode flag is set to 8. PsychAssignHighPrecisionTextureShaders(textureRecord, windowRecord, 0, (specialmode & 8) ? 1 : 0); // specialmode setting 16? Disable auto-mipmap generation: if (specialmode & 16) textureRecord->specialflags |= kPsychDontAutoGenMipMaps; // Mark it valid and return handle to userspace: PsychSetWindowRecordValid(textureRecord); PsychCopyOutDoubleArg(1, TRUE, textureRecord->windowIndex); } else { PsychCopyOutDoubleArg(1, TRUE, 0); } // Return presentation timestamp for this image: PsychCopyOutDoubleArg(2, FALSE, presentation_timestamp); // Return count of pending frames in buffers or of dropped frames: PsychCopyOutDoubleArg(3, FALSE, (double) rc); // Ready! return(PsychError_none); }
PsychError SCREENPreference(void) { PsychArgFormatType arg1Type; char *preferenceName, *newFontName; const char *tableCreator, *oldDefaultFontName; Boolean preferenceNameArgumentValid, booleanInput, ignoreCase, tempFlag, textAlphaBlendingFlag, suppressAllWarningsFlag; int numInputArgs, i, newFontStyleNumber, newFontSize, tempInt, tempInt2, tempInt3; double returnDoubleValue, inputDoubleValue; //all sub functions should have these two lines PsychPushHelp(useString, synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //check for superfluous or missing arguments PsychErrorExit(PsychCapNumInputArgs(3)); PsychErrorExit(PsychRequireNumInputArgs(1)); PsychErrorExit(PsychCapNumOutputArgs(1)); numInputArgs=PsychGetNumInputArgs(); arg1Type=PsychGetArgType(1); preferenceNameArgumentValid=FALSE; //Cases which require both a window pointer or screen number and preference name. Argument 1 is the wposn and argument 2 is the preference name. if( numInputArgs >= 2 && (PsychIsScreenNumberArg(1) || PsychIsScreenNumberArg(1)) && PsychGetArgType(2)==PsychArgType_char ){ PsychAllocInCharArg(2, kPsychArgRequired, &preferenceName); //preferences which require window pointer or screen number argument which we DO NOT support for(i=0;i<kPsychNumUnsupportedMacVideoPreferences;i++){ if(PsychMatch(preferenceName, unsupportedMacVideoPreferenceNames[i])) PsychErrorExit(PsychError_unsupportedOS9Preference); } //insert here conditionals to act on prefernces which accept a window pointer or screen number argument which we DO support. PsychErrorExit(PsychError_unrecognizedPreferenceName); } //Cases which do not require a wposn. Argument 1 is the preference name. if present Argument 2 is the new value if(arg1Type==PsychArgType_char){ PsychAllocInCharArg(1, kPsychArgRequired, &preferenceName); //Preferernces which we do not support and which do not require a wposn for(i=0;i<kPsychNumUnsupportedMacNonVideoPreferences;i++){ if(PsychMatch(preferenceName, unsupportedMacNonVideoPreferenceNames[i])) PsychErrorExit(PsychError_unsupportedOS9Preference); } //Preferences which we do support if(PsychMatch(preferenceName, "IgnoreCase")){ ignoreCase=!PsychIsPsychMatchCaseSensitive(); PsychCopyOutFlagArg(1, kPsychArgOptional, ignoreCase); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &booleanInput); PsychSetPsychMatchCaseSenstive(!booleanInput); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Tick0Secs")){ if(PsychCopyInDoubleArg(2, kPsychArgOptional, &inputDoubleValue) && inputDoubleValue==PsychGetNanValue()) PsychEstimateGetSecsValueAtTickCountZero(); returnDoubleValue=PsychGetEstimatedSecsValueAtTickCountZero(); PsychCopyOutDoubleArg(1, kPsychArgOptional, returnDoubleValue); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "PsychTableVersion")){ if(numInputArgs==2) PsychErrorExit(PsychError_extraInputArg); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double)PsychPrefStateGet_PsychTableVersion()); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "PsychTableCreator")){ if(numInputArgs==2) PsychErrorExit(PsychError_extraInputArg); tableCreator=PsychPrefStateGet_PsychTableCreator(); PsychCopyOutCharArg(1, kPsychArgOptional, tableCreator); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Process")){ if(numInputArgs==2) PsychErrorExit(PsychError_extraInputArg); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double)getpid()); preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultFontName")){ PsychPrefStateGet_DefaultFontName(&oldDefaultFontName); PsychCopyOutCharArg(1, kPsychArgOptional, oldDefaultFontName); if(numInputArgs==2){ PsychAllocInCharArg(2, kPsychArgRequired, &newFontName); PsychPrefStateSet_DefaultFontName(newFontName); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultFontStyle")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_DefaultTextStyle()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &newFontStyleNumber); PsychPrefStateSet_DefaultTextStyle(newFontStyleNumber); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultTextYPositionIsBaseline")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_TextYPositionIsBaseline()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_TextYPositionIsBaseline(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "TextAntiAliasing")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_TextAntiAliasing()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_TextAntiAliasing(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "TextRenderer")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_TextRenderer()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_TextRenderer(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultFontSize")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_DefaultTextSize()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &newFontSize); PsychPrefStateSet_DefaultTextSize(newFontSize); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DebugMakeTexture")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_DebugMakeTexture()); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &tempFlag); PsychPrefStateSet_DebugMakeTexture(tempFlag); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "SkipSyncTests")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_SkipSyncTests()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_SkipSyncTests(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "VisualDebugLevel")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VisualDebugLevel()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VisualDebugLevel(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "VBLTimestampingMode")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VBLTimestampingMode()); if(numInputArgs>=2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VBLTimestampingMode(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "VBLEndlineOverride")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VBLEndlineOverride()); if(numInputArgs>=2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VBLEndlineOverride(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "DefaultVideocaptureEngine")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_VideoCaptureEngine()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_VideoCaptureEngine(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "ConserveVRAM") || PsychMatch(preferenceName, "Workarounds1")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_ConserveVRAM()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_ConserveVRAM(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Verbosity")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_Verbosity()); if(numInputArgs==2){ PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); PsychPrefStateSet_Verbosity(tempInt); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "EmulateOldPTB")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_EmulateOldPTB()); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &tempFlag); PsychPrefStateSet_EmulateOldPTB(tempFlag); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "Enable3DGraphics")){ PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychPrefStateGet_3DGfx()); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &tempFlag); PsychPrefStateSet_3DGfx(tempFlag); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "TextAlphaBlending")){ textAlphaBlendingFlag=PsychPrefStateGet_TextAlphaBlending(); PsychCopyOutFlagArg(1, kPsychArgOptional, textAlphaBlendingFlag); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &booleanInput); PsychPrefStateSet_TextAlphaBlending(booleanInput); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "SuppressAllWarnings")){ suppressAllWarningsFlag=PsychPrefStateGet_SuppressAllWarnings(); PsychCopyOutFlagArg(1, kPsychArgOptional, suppressAllWarningsFlag); if(numInputArgs==2){ PsychCopyInFlagArg(2, kPsychArgRequired, &booleanInput); PsychPrefStateSet_SuppressAllWarnings(booleanInput); } preferenceNameArgumentValid=TRUE; }else if(PsychMatch(preferenceName, "SynchronizeDisplays")){ if(numInputArgs==2){ // This is a special call: It currently doesn't set a preference setting, // but instead triggers an instantaneous synchronization of all available // display heads, if possible. We may have a more clever and "standard" interface // interface for this later on, but for first tests this will do. // Syncmethod is hard-coded to 0 -> Use whatever's available to sync. // timeout for retries is 5.0 seconds. // Acceptable residual offset is +/- 2 scanlines. // Returns the real residual offset after sync. PsychCopyInIntegerArg(2, kPsychArgRequired, &tempInt); tempInt2 = 0; if (PsychSynchronizeDisplayScreens(&tempInt2, NULL, &tempInt, tempInt, 5.0, 2)!=PsychError_none) PsychErrorExitMsg(PsychError_user, "Sync failed for reasons mentioned above."); PsychCopyOutDoubleArg(1, kPsychArgOptional, tempInt); } preferenceNameArgumentValid=TRUE; }else PsychErrorExit(PsychError_unrecognizedPreferenceName); } if(!preferenceNameArgumentValid) PsychErrorExitMsg(PsychError_user, "Invalid arguments to preferences command"); return(PsychError_none); }
PsychError EyelinkMessage(void) { int i, numInArgs; int status = -1; void **args_ptr = NULL; /* argument list, used as a va_list */ char s[256]; char *formatString; PsychArgFormatType format; double tempValue; char *tempString = NULL; //all sub functions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //check to see if the user supplied superfluous arguments // PsychErrorExit(PsychCapNumInputArgs(1)); PsychErrorExit(PsychRequireNumInputArgs(1)); PsychErrorExit(PsychCapNumOutputArgs(1)); // Verify eyelink is up and running EyelinkSystemIsConnected(); EyelinkSystemIsInitialized(); PsychAllocInCharArg(1, TRUE, &formatString); numInArgs = PsychGetNumInputArgs(); if (numInArgs > 1) { args_ptr = (void **)mxMalloc((numInArgs-1) * sizeof(char *)); //iterate over each of the supplied inputs. for(i=2;i<=numInArgs;i++){ format = PsychGetArgType(i); switch(format){ case PsychArgType_double: if(PsychGetArgM(i)==1 && PsychGetArgN(i)==1){ PsychCopyInDoubleArg(i, TRUE, &tempValue); args_ptr[i-2] = (void *) (int) tempValue; } else { PsychGiveHelp(); return(PsychError_user); } break; case PsychArgType_char: args_ptr[i-2] = NULL; PsychAllocInCharArg(i, TRUE, &tempString); args_ptr[i-2] = tempString; break; default: PsychGiveHelp(); return(PsychError_user); break; } } } vsprintf(s, formatString, (va_list)args_ptr); status = eyemsg_printf(s); if (args_ptr != NULL) mxFree(args_ptr); /* if there is an output variable available, assign eyecmd_printf status to it. */ PsychCopyOutDoubleArg(1, FALSE, status); return(PsychError_none); }
PsychError EyelinkCommand(void) { int i = 0; int iNumInArgs = 0; int iStatus = -1; PsychArgFormatType psychArgType = PsychArgType_none; double fTempValue = 0.0; char *pstrTemp = NULL; char *pstrFormat = NULL; void **pArgs = NULL; char strCommand[256]; // Clear strings memset(strCommand, 0, sizeof(strCommand)); // Add help strings PsychPushHelp(useString, synopsisString, seeAlsoString); // Output help if asked if(PsychIsGiveHelp()) { PsychGiveHelp(); return(PsychError_none); } // Check arguments PsychErrorExit(PsychRequireNumInputArgs(1)); // PsychErrorExit(PsychCapNumOutputArgs(0)); PsychErrorExit(PsychCapNumOutputArgs(1)); // Verify eyelink is up and running EyelinkSystemIsConnected(); EyelinkSystemIsInitialized(); // Alloc and grab the input format string PsychAllocInCharArg(1, TRUE, &pstrFormat); iNumInArgs = PsychGetNumInputArgs(); // Alloc and grab input args if (iNumInArgs > 1) { pArgs = (void **)mxMalloc((iNumInArgs-1) * sizeof(char *)); // loop over the args for (i = 2; i <= iNumInArgs; i++) { psychArgType = PsychGetArgType(i); switch(psychArgType) { case PsychArgType_double: if ((PsychGetArgM(i) == 1) && (PsychGetArgN(i) == 1)) { PsychCopyInDoubleArg(i, TRUE, &fTempValue); pArgs[i-2] = (void *) (int) fTempValue; } else { PsychGiveHelp(); return(PsychError_user); } break; case PsychArgType_char: pArgs[i-2] = NULL; PsychAllocInCharArg(i, TRUE, &pstrTemp); pArgs[i-2] = pstrTemp; break; default: PsychGiveHelp(); return(PsychError_user); break; } } } // Build eyelink command and execute vsprintf(strCommand, pstrFormat, (va_list)pArgs); iStatus = eyecmd_printf(strCommand); if (pArgs != NULL) { mxFree(pArgs); } // Copy out the command result PsychCopyOutDoubleArg(1, FALSE, iStatus); return(PsychError_none); }