PsychError EyelinkGetTrackerVersion(void) { int iVersion=0; char strVersion[40]="unknown tracker type"; //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(0)); PsychErrorExit(PsychRequireNumInputArgs(0)); PsychErrorExit(PsychCapNumOutputArgs(2)); // // Verify eyelink is up and running // EyelinkSystemIsConnected(); // EyelinkSystemIsInitialized(); iVersion = eyelink_get_tracker_version(strVersion); // mexPrintf("Tracker Version: '%s'\n", strVersion ); PsychCopyOutDoubleArg(1, TRUE, iVersion); PsychCopyOutCharArg(2, FALSE, strVersion); return(PsychError_none); }
PsychError COCOAEVENTBRIDGEPathToBundle(void) { Boolean isNewArgThereFlag; int newNameLength; char *tempBundleFilePathNameStr, *localBundleFilePathNameStr; //all subfunctions 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(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(1)); //first copy out the old path GetPathToBundleString(&localBundleFilePathNameStr); PsychCopyOutCharArg(1, kPsychArgOptional, localBundleFilePathNameStr); //read in and retain the new name. It arrives in a temporary variable isNewArgThereFlag=PsychAllocInCharArg(1, kPsychArgOptional, &tempBundleFilePathNameStr); if(isNewArgThereFlag){ newNameLength=strlen(tempBundleFilePathNameStr); if(bundleFilePathNameStr != NULL) free((void*)bundleFilePathNameStr); bundleFilePathNameStr=(char*)malloc(sizeof(char) * (newNameLength + 1)); strncpy(bundleFilePathNameStr, tempBundleFilePathNameStr, newNameLength + 1); } return(PsychError_none); }
PsychError SCREENTextFont(void) { boolean doSetByName, doSetByNumber, foundFont; PsychWindowRecordType *windowRecord; PsychFontStructType *fontRecord; int oldTextFontNumber, inputTextFontNumber; char *oldTextFontName, *inputTextFontName; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //check for valid number of arguments PsychErrorExit(PsychRequireNumInputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(2)); PsychErrorExit(PsychCapNumOutputArgs(2)); //Get the window record PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); //Save the old text size value and return it. oldTextFontNumber=windowRecord->textAttributes.textFontNumber; PsychCopyOutDoubleArg(2, FALSE, (double)oldTextFontNumber); oldTextFontName=windowRecord->textAttributes.textFontName; PsychCopyOutCharArg(1, FALSE, oldTextFontName); //Fetch and set the new font if specified by name or number PsychCheckInputArgType(2, kPsychArgOptional, PsychArgType_double | PsychArgType_char); //if the argument is there check that it is the right type. doSetByNumber= PsychCopyInIntegerArg(2, kPsychArgAnything, &inputTextFontNumber); doSetByName= PsychAllocInCharArg(2, kPsychArgAnything, &inputTextFontName); foundFont=0; if(doSetByNumber) foundFont=PsychGetFontRecordFromFontNumber(inputTextFontNumber, &fontRecord); if(doSetByName) foundFont=PsychGetFontRecordFromFontFamilyNameAndFontStyle(inputTextFontName, windowRecord->textAttributes.textStyle, &fontRecord); if(foundFont){ strncpy(windowRecord->textAttributes.textFontName, fontRecord->fontFMFamilyName, 255); windowRecord->textAttributes.textFontNumber= fontRecord->fontNumber; } return(PsychError_none); }
PsychError SCREENTextMode(void) { PsychTextDrawingModeType newCopyMode; Str255 oldCopyModeName; char *newCopyModeName; psych_bool doSetMode; PsychWindowRecordType *windowRecord; psych_bool nameError; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //check for valid number of arguments PsychErrorExit(PsychRequireNumInputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(2)); PsychErrorExit(PsychCapNumOutputArgs(1)); //Get the window record PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); //Get the old copy mode & its name PsychGetTextDrawingModeNameFromTextDrawingModeConstant(oldCopyModeName, 255, windowRecord->textAttributes.textMode); PsychCopyOutCharArg(1, FALSE, oldCopyModeName); //Get the copy new mode string doSetMode= PsychAllocInCharArg(2, FALSE, &newCopyModeName); if(doSetMode){ nameError=PsychGetTextDrawingModeConstantFromTextDrawingModeName(&newCopyMode, newCopyModeName); if(nameError) PsychErrorExitMsg(PsychError_user, "Invalid text copy mode. See Screen('TextModes') for a list of allowable modes"); windowRecord->textAttributes.needsRebuild|=(windowRecord->textAttributes.textMode != newCopyMode) ? TRUE : FALSE; windowRecord->textAttributes.textMode=newCopyMode; } 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; 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 IOPORTWrite(void) { static char useString[] = "[nwritten, when, errmsg, prewritetime, postwritetime, lastchecktime] = IOPort('Write', handle, data [, blocking=1]);"; static char synopsisString[] = "Write data to device, specified by 'handle'.\n" "'data' must be a vector of data items to write, or a matrix (in which case data " "in the matrix will be transmitted in column-major order, ie., first the first " "column, then the 2nd column etc...), either with data elements of uint8 class " "or a (1 Byte per char) character string. The optional flag 'blocking' if " "set to 0 will ask the write function to not block, but return immediately, ie. " "data is sent/written in the background while your code continues to execute - There " "may be an arbitrary delay until data transmission is really finished. The default " "setting is 1, ie. blocking writes - The function waits until data transmission is really " "finished. You can also use blocking == 2 to request a different mode " "for blocking writes, where IOPort is polling for write-completion instead of " "a more cpu friendly wait. This may decrease latency for certain applications. " "Another even more agressive polling method is implemented via blocking == 3 on " "Linux systems with some limited set of hardware, e.g., real native serial ports.\n" "On systems without any support for specific polling modes, the 2 or 3 settings are treated " "as a standard blocking write.\n\n" "Optionally, the function returns the following return arguments:\n" "'nwritten' Number of bytes written -- Should match amount of data provided on success.\n" "'when' A timestamp of write completion: This is only meaningful in blocking mode!\n" "'errmsg' A system defined error message if something wen't wrong.\n" "The following three timestamps are for low-level debugging and special purpose:\n" "'prewritetime' A timestamp taken immediately before submitting the write request. " "'postwritetime' A timestamp taken immediately after submitting the write request. " "'lastchecktime' A timestamp taken at the time of last check for write completion if applicable. "; static char seeAlsoString[] = ""; char errmsg[1024]; int handle, blocking, m, n, p, nwritten; psych_uint8* inData = NULL; char* inChars = NULL; void* writedata = NULL; double timestamp[4] = {0, 0, 0, 0}; errmsg[0] = 0; // Setup online help: PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()) {PsychGiveHelp(); return(PsychError_none); }; PsychErrorExit(PsychCapNumInputArgs(3)); // The maximum number of inputs PsychErrorExit(PsychRequireNumInputArgs(2)); // The required number of inputs PsychErrorExit(PsychCapNumOutputArgs(6)); // The maximum number of outputs // Get required port handle: PsychCopyInIntegerArg(1, kPsychArgRequired, &handle); // Get the data: switch(PsychGetArgType(2)) { case PsychArgType_uint8: PsychAllocInUnsignedByteMatArg(2, kPsychArgRequired, &m, &n, &p, &inData); if (p!=1 || m * n == 0) PsychErrorExitMsg(PsychError_user, "'data' is not a vector or 2D matrix, but some higher dimensional matrix!"); n = m * n; writedata = (void*) inData; break; case PsychArgType_char: PsychAllocInCharArg(2, kPsychArgRequired, &inChars); n = strlen(inChars); writedata = (void*) inChars; break; default: PsychErrorExitMsg(PsychError_user, "Invalid type for 'data' vector: Must be an uint8 or char vector."); } // Get optional blocking flag: Defaults to one -- blocking. blocking = 1; PsychCopyInIntegerArg(3, kPsychArgOptional, &blocking); // Write data: nwritten = PsychWriteIOPort(handle, writedata, n, blocking, errmsg, ×tamp[0]); if (nwritten < 0 && verbosity > 0) printf("IOPort: Error: %s\n", errmsg); PsychCopyOutDoubleArg(1, kPsychArgOptional, nwritten); PsychCopyOutDoubleArg(2, kPsychArgOptional, timestamp[0]); PsychCopyOutCharArg(3, kPsychArgOptional, errmsg); PsychCopyOutDoubleArg(4, kPsychArgOptional, timestamp[1]); PsychCopyOutDoubleArg(5, kPsychArgOptional, timestamp[2]); PsychCopyOutDoubleArg(6, kPsychArgOptional, timestamp[3]); return(PsychError_none); }
PsychError IOPORTRead(void) { static char useString[] = "[data, when, errmsg] = IOPort('Read', handle [, blocking=0] [, amount]);"; static char synopsisString[] = "Read data from device, specified by 'handle'.\n" "Returned 'data' will be a row vector of read data bytes. 'when' will be a receive " "timestamp of when the data read was complete. 'errmsg' will be a human readable " "char string with an error message if any error occured, otherwise an empty string. " "The optional flag 'blocking' if set to 0 will ask the read function to not block, " "but return immediately: The read function will return whatever amount of data is " "currently available in the internal input queue, but at most 'amount' bytes if 'amount' " "is specified. If no data is available, it will return an empty matrix. This is the default.\n" "If 'blocking' is set to 1, you must specify the 'amount' of bytes to receive and the " "function will wait until that exact amount of data is available, then return it." "Even in blocking mode, the function will return if no data becomes available within " "the time period specified by the configuration setting 'ReadTimeout' (see help for " "'OpenSerialPort' for description). In some situations, the read function may return " "less data than requested, e.g., in specific error cases, where a read could only " "get partially satisfied."; static char seeAlsoString[] = "'Write', 'OpenSerialPort', 'ConfigureSerialPort'"; char errmsg[1024]; int handle, blocking, nread, amount, i; psych_uint8* readbuffer; double* outbuffer; double timestamp; errmsg[0] = 0; // Setup online help: PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()) {PsychGiveHelp(); return(PsychError_none); }; PsychErrorExit(PsychCapNumInputArgs(3)); // The maximum number of inputs PsychErrorExit(PsychRequireNumInputArgs(1)); // The required number of inputs PsychErrorExit(PsychCapNumOutputArgs(3)); // The maximum number of outputs // Get required port handle: PsychCopyInIntegerArg(1, kPsychArgRequired, &handle); // Get optional blocking flag: Defaults to 0 -- non-blocking. blocking = 0; PsychCopyInIntegerArg(2, kPsychArgOptional, &blocking); // Get optional maximum or exact amount to read: amount = INT_MAX; if (!PsychCopyInIntegerArg(3, kPsychArgOptional, &amount)) { // Not spec'd: if (blocking > 0) PsychErrorExitMsg(PsychError_user, "When issuing a 'Read' in blocking mode, you must specify the exact 'amount' to read, but 'amount' was omitted!"); } if (amount < 0) PsychErrorExitMsg(PsychError_user, "Invalid (negative) 'amount' of data to read!"); // Read data: nread = PsychReadIOPort(handle, (void**) &readbuffer, amount, blocking, errmsg, ×tamp); // Allocate outbuffer of proper size: PsychAllocOutDoubleMatArg(1, kPsychArgOptional, 1, ((nread >=0) ? nread : 0), 1, &outbuffer); // Copy to outbuffer: We copy our uint8 values to a double matrix. This is arguably a bit of a waste of // memory and bandwidth, but it simplifies interfacing with Octave, old Matlab versions and possible // future runtime environments a lot: if (nread > 0) for (i=0; i<nread; i++) outbuffer[i] = readbuffer[i]; if (nread < 0 && verbosity > 0) printf("IOPort: Error: %s\n", errmsg); // Return timestamp and errmsg, if any: PsychCopyOutDoubleArg(2, kPsychArgOptional, timestamp); PsychCopyOutCharArg(3, kPsychArgOptional, errmsg); return(PsychError_none); }
// Open a serial port on a serial port device: PsychError IOPORTOpenSerialPort(void) { static char useString[] = "[handle, errmsg] = IOPort('OpenSerialPort', port [, configString]);"; static char synopsisString[] = "Open a serial port device, return a 'handle' to it.\n" "If a port can't be opened, the function will abort with error, unless the " "level of verbosity is set to zero, in which case the function will silently " "fail, but return an invalid (negative) handle to signal the failure to the " "calling script. The optional return argument 'errmsg' contains a text string " "which is either empty on success, or contains a descriptive error message. \n" "'port' is usually a name string that defines the serial port device " "to open. On MS-Windows this could be, e.g., 'COM1' or 'COM2' etc. On " "Apple OS/X, it is the path to a BSD device file, e.g., '/dev/cu.usbserial-FT3Z95V5' " "for a serial-over-USB device with unique id FT3Z95V5. On GNU/Linux it could be " "'/dev/ttyS0' for the first real serial port, or '/dev/ttyUSB0' for the first " "serial-over-USB device.\n\n" "The optional string 'configString' is a string with pairs of paramName=paramValue " "tokens, separated by a delimiter, e.g., a space. It allows to specify specific " "values 'paramValue' to specific serial port parameters 'paramName'. Not all " "parameters are supported by all operating systems, and all settings have reasonable " "defaults. Settings unknown to a specific operating system are ignored.\n" "The following is a list of (possibly) supported parameters with their defaults:\n\n" "BaudRate=9600 -- The baud transmission rate of the connection. Standard baud rates include " "110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 128000 and " "256000 bits per second. Not all values may be supported by all operating systems and drivers.\n\n" "Parity=None -- Type of parity checking: None, Even, Odd.\n\n" "DataBits=8 -- Number of data bits per packet: 5,6,7 or 8, on Windows also 16.\n\n" "StopBits=1 -- Number of stop bits per packet: 1 or 2.\n\n" "FlowControl=None -- Type of flow control: None, Hardware (RTS/CTS lines), Software (XON/XOFF characters).\n\n" "Terminator=os default -- Type of terminator, given as ASCII character value, e.g., 13 for char(13) aka CR. Currently unused\n\n" "DTR=os default -- Setting for 'Data Terminal Ready' pin: 0 or 1.\n\n" "RTS=os default -- Setting for 'Request To Send' pin: 0 or 1.\n\n" "BreakBehaviour=Ignore -- Behaviour if a 'Break Condition' is detected on the line: Ignore, Flush, Zero. On Windows, this setting is ignored.\n\n" "OutputBufferSize=4096 -- Size of output buffer in bytes.\n\n" "InputBufferSize=4096 -- Size of input buffer in bytes. You can't read more than that amount per read command.\n\n" "HardwareBufferSizes=input,output -- Set size of the hardware driver internal input and output buffers in bytes. " "E.g., HardwareBufferSizes=32768,8192 would set the input buffer to 32768 bytes and the output buffer to 8192 bytes. " "This function is currently only supported on Windows, ignored on other systems. It is only a polite hint to the driver, " "the serial port driver is free to ignore the request and choose any buffer sizes or buffering strategy it finds appropriate. " "By default, this parameter is not set by IOPort and the hardware driver uses some built-in reasonable setting.\n\n" "The following timeout values are inter-byte timeouts. You specify how much time reception or " "transmission of a single byte is allowed to take. Timeout occurs if more than that time elapses " "between send/reception of two consecutive bytes or if the total amount of time exceeds the " "number of bytes, times the interbyte timeout value. A value of zero means not to use any timeout, " "in which case a blocking read or write may take forever. If a timeout occurs, the read or write " "operation will be aborted. \n" "Granularity of timeout settings is 100 msecs on OS/X and Linux, 1 msec on Windows, all values " "are rounded to the closest value matching that granularity. The minimal timeout is 100 msecs " "on OS/X and Linux, about 6 msecs on Windows.\n\n" "SendTimeout=1.0 -- Interbyte send timeout in seconds. Only used on Windows.\n\n" "ReceiveTimeout=1.0 -- Interbyte receive timeout in seconds.\n\n" "ReceiveLatency=0.000001 -- Latency in seconds for processing of new input bytes. Only used on OS/X.\n\n" "PollLatency=0.0005 (0.005 on Windows) -- Latency between polls in seconds for polling in some 'Read' operations.\n\n" "ProcessingMode=Raw -- Mode of input/output processing: Raw or Cooked. On Windows, only Raw (binary) mode is supported.\n\n" "StartBackgroundRead=readGranularity -- Enable asynchronous background read operations on the port. This is only supported " "on Linux and OS/X for now. A parallel background thread is started which tries to fetch 'readGranularity' bytes of data, " "polling the port every 'PollLatency' seconds for at least 'readGranularity' bytes of data. 'InputBufferSize' must be an " "integral multiple of 'readGranularity' for this to work. Later IOPort('Read') commands will pull collected data from " "the InputBuffer in quanta of at most 'readGranularity' bytes per invocation. This function is useful for background " "data collection from devices that stream some data at a constant rate. You set up background read, let the parallel " "thread do all data collection in the background and collect the data at the end of a session with a sequence of " "IOPort('Read') calls. This way, data collection doesn't clutter your main experiment script.\n\n" "StopBackgroundRead -- Stop running background read operation, discard all pending data.\n\n"; static char seeAlsoString[] = "'CloseAll'"; #if PSYCH_SYSTEM == PSYCH_WINDOWS // Difference to Unices: PollLatency defaults to 5 msecs instead of 0.5 msecs due to shoddy windows scheduler: static char defaultConfig[] = "BaudRate=9600 Parity=None DataBits=8 StopBits=1 FlowControl=None PollLatency=0.005 ReceiveLatency=0.000001 SendTimeout=1.0 ReceiveTimeout=1.0 ProcessingMode=Raw BreakBehaviour=Ignore OutputBufferSize=4096 InputBufferSize=4096"; #else static char defaultConfig[] = "BaudRate=9600 Parity=None DataBits=8 StopBits=1 FlowControl=None PollLatency=0.0005 ReceiveLatency=0.000001 SendTimeout=1.0 ReceiveTimeout=1.0 ProcessingMode=Raw BreakBehaviour=Ignore OutputBufferSize=4096 InputBufferSize=4096"; #endif char finalConfig[2000]; char errmsg[1024]; char* portSpec = NULL; char* configString = NULL; PsychSerialDeviceRecord* device = NULL; int handle; // Setup online help: PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()) {PsychGiveHelp(); return(PsychError_none); }; PsychErrorExit(PsychCapNumInputArgs(2)); // The maximum number of inputs PsychErrorExit(PsychRequireNumInputArgs(1)); // The required number of inputs PsychErrorExit(PsychCapNumOutputArgs(2)); // The maximum number of outputs // Get required portSpec: PsychAllocInCharArg(1, kPsychArgRequired, &portSpec); // Get the optional configString: if (!PsychAllocInCharArg(2, kPsychArgOptional, &configString)) { // No config string specified: Assign default string: sprintf(finalConfig, "%s", defaultConfig); } else { // Config string provided: Prepend it to default string. That way, all settings // spec'd by usercode will override the defaultConfig, but non-specified settings // will be provided by defaultConfig: sprintf(finalConfig, "%s %s", configString, defaultConfig); } // Search for a free slot: if (portRecordCount >= PSYCH_MAX_IOPORTS) PsychErrorExitMsg(PsychError_user, "Maximum number of open Input/Output ports exceeded."); // Iterate until end or free slot: for (handle=0; (handle < PSYCH_MAX_IOPORTS) && (portRecordBank[handle].portType); handle++); if (portRecordBank[handle].portType) PsychErrorExitMsg(PsychError_user, "Maximum number of open Input/Output ports exceeded."); // handle is index into our port record... // Call OS specific open routine for serial port: device = PsychIOOSOpenSerialPort(portSpec, finalConfig, errmsg); // Copy out optional errmsg string: PsychCopyOutCharArg(2, kPsychArgOptional, errmsg); if (device == NULL) { // Special case: Could not open port, but verbosity level is zero, no conventional // error return possible as this would clutter the console with output. Simply cancel // open op and return a negative handle to signal failure to user code: PsychCopyOutDoubleArg(1, kPsychArgRequired, -1); return(PsychError_none); } // If we reach this point, then device is the pointer to the class specific device struct and the // open operation was successfull. Build port struct: portRecordBank[handle].portType = kPsychIOPortSerial; portRecordBank[handle].device = (void*) device; portRecordCount++; // Return handle to new serial port object: PsychCopyOutDoubleArg(1, kPsychArgRequired, (double) handle); 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 SCREENBlendFunction(void) { PsychWindowRecordType *windowRecord; GLenum oldSource, oldDestination, newSource, newDestination; char *oldSoureStr, *oldDestinationStr, *newSourceStr, *newDestinationStr; int oldSourceStrSize, oldDestinationStrSize, isSourceStringValid, isDestinationStringValid; psych_bool isSourceSupplied, isDestinationSupplied, isSourceChoiceValid, isDestinationChoiceValid; double *oldColorMask, *newColorMask; int m, n, p; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumInputArgs(4)); //The maximum number of inputs PsychErrorExit(PsychRequireNumInputArgs(1)); //The required number of inputs PsychErrorExit(PsychCapNumOutputArgs(3)); //The maximum number of outputs //Get the window record or exit with an error if the windex was bogus. PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); //Retreive the old source and destination factors and return them from the Screen call as strings PsychGetAlphaBlendingFactorsFromWindow(windowRecord, &oldSource, &oldDestination); oldSourceStrSize=PsychGetAlphaBlendingFactorStringFromConstant(oldSource, NULL); oldDestinationStrSize=PsychGetAlphaBlendingFactorStringFromConstant(oldDestination, NULL); oldSoureStr=(char *)malloc(sizeof(char) * oldSourceStrSize); oldDestinationStr=(char *)malloc(sizeof(char) * oldDestinationStrSize); PsychGetAlphaBlendingFactorStringFromConstant(oldSource, oldSoureStr); PsychGetAlphaBlendingFactorStringFromConstant(oldDestination, oldDestinationStr); PsychCopyOutCharArg(1, kPsychArgOptional, oldSoureStr); PsychCopyOutCharArg(2, kPsychArgOptional, oldDestinationStr); free((void *)oldSoureStr); free((void *)oldDestinationStr); //Get the new settings if they are present and set them. newSource=oldSource; newDestination=oldDestination; isSourceSupplied= PsychAllocInCharArg(2, kPsychArgOptional, &newSourceStr); isDestinationSupplied= PsychAllocInCharArg(3, kPsychArgOptional, &newDestinationStr); if(isSourceSupplied){ isSourceStringValid=PsychGetAlphaBlendingFactorConstantFromString(newSourceStr, &newSource); if(!isSourceStringValid) PsychErrorExitMsg(PsychError_user, "Supplied string argument 'sourceFactorNew' is invalid"); isSourceChoiceValid=PsychValidateBlendingConstantForSource(newSource); if(!isSourceChoiceValid) PsychErrorExitMsg(PsychError_user, "The blending factor supplied for the source is only valid only for the destination"); } if(isDestinationSupplied){ isDestinationStringValid=PsychGetAlphaBlendingFactorConstantFromString(newDestinationStr, &newDestination); if(!isDestinationStringValid) PsychErrorExitMsg(PsychError_user, "Supplied string argument 'destinationFactorNew' is invalid"); isDestinationChoiceValid=PsychValidateBlendingConstantForDestination(newDestination); if(!isDestinationChoiceValid) PsychErrorExitMsg(PsychError_user, "The blending factor supplied for the destination is only valid only for the source"); } PsychStoreAlphaBlendingFactorsForWindow(windowRecord, newSource, newDestination); // Check if alpha blending is possible for this windowRecord: if ((newSource != GL_ONE || newDestination != GL_ZERO) && !((windowRecord->bpc < 16) || (windowRecord->bpc == 16 && (windowRecord->gfxcaps & kPsychGfxCapFPBlend16)) || (windowRecord->bpc == 32 && (windowRecord->gfxcaps & kPsychGfxCapFPBlend32)))) { // Nope. Alpha blending requested but not possible for this windowRecord with this gfx-hardware. if (PsychPrefStateGet_Verbosity() > 1) { printf("PTB-WARNING: Screen('Blendfunction') called to enable alpha-blending on a window (handle=%i) which doesn't support\n", windowRecord->windowIndex); printf("PTB-WARNING: alpha-blending at its current color resolution of %i bits per color component on your hardware.\n", windowRecord->bpc); printf("PTB-WARNING: Won't enable blending. Either lower the color resolution of the window (see help PsychImaging) or\n"); printf("PTB-WARNING: upgrade your graphics hardware.\n\n"); } } // Create return array with encoded old colormask: PsychAllocOutDoubleMatArg(3, kPsychArgOptional, 1, 4, 1, &oldColorMask); oldColorMask[0] = (windowRecord->colorMask[0]) ? 1 : 0; oldColorMask[1] = (windowRecord->colorMask[1]) ? 1 : 0; oldColorMask[2] = (windowRecord->colorMask[2]) ? 1 : 0; oldColorMask[3] = (windowRecord->colorMask[3]) ? 1 : 0; // Any new colormask provided? if (PsychAllocInDoubleMatArg(4, kPsychArgOptional, &m, &n, &p, &newColorMask)) { // Yes. Assign it: if (p!=1 || m*n != 4) PsychErrorExitMsg(PsychError_user, "The colorMaskNew argument must be a 4 element row- or column vector!"); windowRecord->colorMask[0] = (newColorMask[0] > 0) ? GL_TRUE : GL_FALSE; windowRecord->colorMask[1] = (newColorMask[1] > 0) ? GL_TRUE : GL_FALSE; windowRecord->colorMask[2] = (newColorMask[2] > 0) ? GL_TRUE : GL_FALSE; windowRecord->colorMask[3] = (newColorMask[3] > 0) ? GL_TRUE : GL_FALSE; } return(PsychError_none); }
PsychError SCREENTextFont(void) { psych_bool doSetByName, doSetByNumber, foundFont; PsychWindowRecordType *windowRecord; #if PSYCH_SYSTEM == PSYCH_OSX PsychFontStructType *fontRecord; #endif int oldTextFontNumber, inputTextFontNumber; char *oldTextFontName, *inputTextFontName; int oldTextStyle, newTextStyle; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //check for valid number of arguments PsychErrorExit(PsychRequireNumInputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(3)); PsychErrorExit(PsychCapNumOutputArgs(3)); //Get the window record PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); //Save the old text font value and return it. oldTextFontNumber=windowRecord->textAttributes.textFontNumber; PsychCopyOutDoubleArg(2, FALSE, (double)oldTextFontNumber); oldTextFontName=(char*) windowRecord->textAttributes.textFontName; PsychCopyOutCharArg(1, FALSE, oldTextFontName); oldTextStyle = windowRecord->textAttributes.textStyle; PsychCopyOutDoubleArg(3, FALSE, (double) oldTextStyle); //Fetch and set the new font if specified by name or number PsychCheckInputArgType(2, kPsychArgOptional, PsychArgType_double | PsychArgType_char); //if the argument is there check that it is the right type. doSetByNumber= PsychCopyInIntegerArg(2, kPsychArgAnything, &inputTextFontNumber); doSetByName= PsychAllocInCharArg(2, kPsychArgAnything, &inputTextFontName); foundFont=0; #if PSYCH_SYSTEM == PSYCH_OSX if(doSetByNumber) { foundFont=PsychGetFontRecordFromFontNumber(inputTextFontNumber, &fontRecord); } if(doSetByName) { if (PsychCopyInIntegerArg(3, FALSE, &newTextStyle)) windowRecord->textAttributes.textStyle = newTextStyle; foundFont=PsychGetFontRecordFromFontFamilyNameAndFontStyle(inputTextFontName, windowRecord->textAttributes.textStyle, &fontRecord); } if(foundFont) { strncpy((char*) windowRecord->textAttributes.textFontName, (char*) fontRecord->fontFMFamilyName, 255); windowRecord->textAttributes.textFontNumber = fontRecord->fontNumber; windowRecord->textAttributes.textStyle = fontRecord->fontFMStyle; } else { // Font not found. Is this textrenderer 2 with a font given by name? if (doSetByName && (PsychPrefStateGet_TextRenderer() > 1)) { // Yes: Must be a special font specifier string for the renderer plugin. Just assign it directly: strncpy((char*) windowRecord->textAttributes.textFontName, inputTextFontName, 255); // Don't have a valid fontNumber: Just assign a zero... windowRecord->textAttributes.textFontNumber = 0; } else { // Restore old text style setting: windowRecord->textAttributes.textStyle = oldTextStyle; } } return(PsychError_none); #else // Special case for MS-Windows and Linux: if(doSetByNumber) printf("PTB-WARNING: Sorry, selecting font by number in Screen('TextFont') is not yet supported on Windows or Linux. Command ignored.\n"); if(doSetByName && (strncmp(windowRecord->textAttributes.textFontName, inputTextFontName, 255 )!=0)) { strncpy(windowRecord->textAttributes.textFontName, inputTextFontName, 255); windowRecord->textAttributes.textFontNumber= 0; // Set the rebuild flag: windowRecord->textAttributes.needsRebuild=TRUE; } // New and different text style provided? if (PsychCopyInIntegerArg(3, FALSE, &newTextStyle) && (windowRecord->textAttributes.textStyle != newTextStyle)) { windowRecord->textAttributes.textStyle = newTextStyle; // Set the rebuild flag: windowRecord->textAttributes.needsRebuild=TRUE; } return(PsychError_none); #endif }
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); }
/* Set capture device specific parameters: * Currently, the named parameters are a subset of the parameters supported by the * IIDC specification, mapped to more convenient names. * * Input: pname = Name string to specify the parameter. * value = Either DBL_MAX to not set but only query the parameter, or some other * value, that we try to set in the Firewire camera. * * Returns: Old value of the setting */ double PsychARVideoCaptureSetParameter(int capturehandle, const char* pname, double value) { unsigned int minval, maxval, intval, oldintval; int triggercount; double oldvalue = DBL_MAX; // Initialize return value to the "unknown/unsupported" default. psych_bool assigned = false; psych_bool present = false; // Retrieve device record for handle: PsychVidcapRecordType* capdev = PsychGetARVidcapRecord(capturehandle); oldintval = 0xFFFFFFFF; // Round value to integer: intval = (int) (value + 0.5); // Check parameter name pname and call the appropriate subroutine: if (strcmp(pname, "TriggerCount")==0 || strcmp(pname, "WaitTriggerCount")==0) { // Query of cameras internal trigger counter or waiting for a specific // value in the counter requested. Trigger counters are special features, // (so called "Smart Features" or "Advanced Features" in the IIDC spec) // which are only available on selected cameras. // We currently only know how to do this on Basler cameras. return(-2); } if (strcmp(pname, "PrintParameters")==0) { // Special command: List and print all features... printf("PTB-INFO: The camera provides the following information and featureset:\n"); ar2VideoDispOption(); return(0); } // Return current framerate: if (strcmp(pname, "GetFramerate")==0) { PsychCopyOutDoubleArg(1, FALSE, capdev->fps); return(0); } // Return current ROI of camera, as requested (and potentially modified during // PsychOpenCaptureDevice(). This is a read-only parameter, as the ROI can // only be set during Screen('OpenVideoCapture'). if (strcmp(pname, "GetROI")==0) { PsychCopyOutRectArg(1, FALSE, capdev->roirect); return(0); } // Return vendor name string: if (strcmp(pname, "GetVendorname")==0) { PsychCopyOutCharArg(1, FALSE, "Unknown Vendor"); return(0); } // Return model name string: if (strcmp(pname, "GetModelname")==0) { PsychCopyOutCharArg(1, FALSE, "Unknown Model"); return(0); } // if (strstr(pname, "Brightness")!=0) { // assigned = true; // feature = DC1394_FEATURE_BRIGHTNESS; // } // // if (strstr(pname, "Gain")!=0) { // assigned = true; // feature = DC1394_FEATURE_GAIN; // } // // if (strstr(pname, "Exposure")!=0) { // assigned = true; // feature = DC1394_FEATURE_EXPOSURE; // } // // if (strstr(pname, "Shutter")!=0) { // assigned = true; // feature = DC1394_FEATURE_SHUTTER; // } // // if (strstr(pname, "Sharpness")!=0) { // assigned = true; // feature = DC1394_FEATURE_SHARPNESS; // } // // if (strstr(pname, "Saturation")!=0) { // assigned = true; // feature = DC1394_FEATURE_SATURATION; // } // // if (strstr(pname, "Gamma")!=0) { // assigned = true; // feature = DC1394_FEATURE_GAMMA; // } // Check if feature is present on this camera: // Not supported yet: present = FALSE; // if (dc1394_feature_is_present(capdev->camera, feature, &present)!=DC1394_SUCCESS) { // if(PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Failed to query presence of feature %s on camera %i! Ignored.\n", pname, capturehandle); // fflush(NULL); // } // else if (present) { // Feature is available: /* // Retrieve current value: if (dc1394_feature_get_value(capdev->camera, feature, &oldintval)!=DC1394_SUCCESS) { if(PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Failed to query value of feature %s on camera %i! Ignored.\n", pname, capturehandle); fflush(NULL); } else { // Do we want to set the value? if (value != DBL_MAX) { // Query allowed bounds for its value: if (dc1394_feature_get_boundaries(capdev->camera, feature, &minval, &maxval)!=DC1394_SUCCESS) { if(PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Failed to query valid value range for feature %s on camera %i! Ignored.\n", pname, capturehandle); fflush(NULL); } else { // Sanity check against range: if (intval < minval || intval > maxval) { if(PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Requested setting %i for parameter %s not in allowed range (%i - %i) for camera %i. Ignored.\n", intval, pname, minval, maxval, capturehandle); fflush(NULL); } else { // Ok intval is valid for this feature: Can we manually set this feature? // Switch feature to manual control mode: if (dc1394_feature_set_mode(capdev->camera, feature, DC1394_FEATURE_MODE_MANUAL)!=DC1394_SUCCESS) { if(PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Failed to set feature %s on camera %i to manual control! Ignored.\n", pname, capturehandle); fflush(NULL); } else { // Ok, try to set the features new value: if (dc1394_feature_set_value(capdev->camera, feature, intval)!=DC1394_SUCCESS) { if(PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Failed to set value of feature %s on camera %i to %i! Ignored.\n", pname, capturehandle, intval); fflush(NULL); } } } } } else { // Don't want to set new value. Do we want to reset feature into auto-mode? // Prefixing a parameter name with "Auto" // does not switch the parameter into manual // control mode + set its value, as normal, // but it switches the parameter into automatic // mode, if automatic mode is supported by the // device. if (strstr(pname, "Auto")!=0) { // Switch to automatic control requested - Try it: if (dc1394_feature_set_mode(capdev->camera, feature, DC1394_FEATURE_MODE_AUTO)!=DC1394_SUCCESS) { if(PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Failed to set feature %s on camera %i to automatic control! Ignored.\n", pname, capturehandle); fflush(NULL); } } } } */ } else { if(PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Requested capture device setting %s not available on cam %i. Ignored.\n", pname, capturehandle); fflush(NULL); } // Output a warning on unknown parameters: if (!assigned) { if(PsychPrefStateGet_Verbosity()>1) printf("PTB-WARNING: Screen('SetVideoCaptureParameter', ...) called with unknown parameter %s. Ignored...\n", pname); fflush(NULL); } if (assigned && oldintval!=0xFFFFFFFF) oldvalue = (double) oldintval; // Return the old value. Could be DBL_MAX if parameter was unknown or not accepted for some reason. return(oldvalue); }
PsychError COCOAEVENTBRIDGEGetChar(void) { static Boolean firstTime=TRUE; double returnValue, inputValue; static Boolean wasWindowOpenedFlag=FALSE; Boolean isThere, inputValueBoolean, lostKeyWindowFlag; // InitializeCocoaProc CocoaInitializeCocoa; char readChar[2]; double readTime; int numKeypresses, numOutputArgs; CFDictionaryRef keypressDictionary=NULL, keypressModifierFlags=NULL; CFStringRef keypressCharacter=NULL; CFNumberRef keypressTime=NULL, keypressAddress=NULL, keypressTickCount=NULL; double keypressTimeDouble, keypressTickCountDouble; char keypressCharacterUTF8[2]; CFRange characterRange; UniChar keypressCharacterUnicode[1]; double keypressCharacterAsValue, nowGetSecs, nowTickCount, characterTickCount, keypressAddressDouble; Boolean loadBundleError; //for the return structure in the second argument const char *charTimeFieldNames[]={"ticks", "secs", "address", "alphaLock", "commandKey", "controlKey", "optionKey", "shiftKey", "numericKeypad", "functionKey"}; int numStructElements=1, numStructFieldNames=10; PsychGenericScriptType *charTimeStruct; CFNumberRef alphaLock, commandKey, controlKey, optionKey, shiftKey, numericKeypad, helpKey, functionKey; char alphaLockCFlag, commandKeyCFlag, controlKeyCFlag, optionKeyCFlag, shiftKeyCFlag, numericKeypadCFlag, helpKeyCFlag, functionKeyCFlag; //all subfunctions 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(PsychCapNumOutputArgs(2)); PsychErrorExit(PsychCapNumInputArgs(1)); loadBundleError=LoadCocoaBundle(); if(loadBundleError) PsychErrorExitMsg(PsychError_internal, "Failed to load the cocoa bundle."); //Open the window. OpenGetCharWindow() and MakeGetCharWindowInvisible() only act once if called repeatedly. OpenGetCharWindow(); #ifndef DEBUG_USE_VISIBLE_WINDOW MakeGetCharWindowInvisible(); #endif StartKeyGathering(); MakeKeyWindow(); lostKeyWindowFlag=FALSE; while(GetNumKeypresses() < 1){ PsychWaitIntervalSeconds((double)0.005); //this would become an infinite loop if the user moves focus to another window, because our key collection window would never //receive input. Therefore we detect if our window loses keyWindow status. We could be more forceful about this and bring the //window back into focus, if we have access to NSApplication within our Cocoa bundle. lostKeyWindowFlag=!IsKeyWindow(); if(lostKeyWindowFlag) break; } // StopKeyGathering(); // if(!lostKeyWindowFlag) // RevertKeyWindow(); //restores the key window to what it was before we took it. if(!lostKeyWindowFlag){ keypressDictionary=(CFDictionaryRef)CopyReadNextKeypress(); if(keypressDictionary != NULL){ keypressCharacter=CFDictionaryGetValue(keypressDictionary, CFSTR("character")); keypressTime=CFDictionaryGetValue(keypressDictionary, CFSTR("time")); keypressModifierFlags=CFDictionaryGetValue(keypressDictionary, CFSTR("modifierFlags")); keypressTickCount=CFDictionaryGetValue(keypressDictionary, CFSTR("tickCount")); CFNumberGetValue(keypressTickCount, kCFNumberDoubleType, &keypressTickCountDouble); keypressAddress=CFDictionaryGetValue(keypressDictionary, CFSTR("keyCode")); CFNumberGetValue(keypressAddress, kCFNumberDoubleType, &keypressAddressDouble); characterRange.location=0; characterRange.length=1; CFStringGetCharacters(keypressCharacter, characterRange, keypressCharacterUnicode); if(keypressCharacterUnicode[0] <= (UniChar)127){ //it's a UTF8, MATLAB knows how do display this keypressCharacterUTF8[0]=(char)(keypressCharacterUnicode[0]); //throw out what MATLAB will not print. keypressCharacterUTF8[1]='\0'; //mexPrintf("character: %s\n", keypressCharacterUTF8); PsychCopyOutCharArg(1, kPsychArgOptional, keypressCharacterUTF8); }else{ keypressCharacterAsValue=(double)(keypressCharacterUnicode[0]); //mexPrintf("character: %f\n", keypressCharacterAsValue); PsychCopyOutDoubleArg(1, kPsychArgOptional, keypressCharacterAsValue); } // CFStringGetCString(keypressCharacter, keypressCharacterUTF8, 2, kCFStringEncodingUTF8); CFNumberGetValue(keypressTime, kCFNumberDoubleType ,&keypressTimeDouble); // mexPrintf("time: %d\n", keypressTimeDouble); // PsychCopyOutDoubleArg(2, kPsychArgOptional, keypressTimeDouble); numOutputArgs= PsychGetNumOutputArgs(); if(numOutputArgs==2){ alphaLock= CFDictionaryGetValue(keypressModifierFlags, CFSTR("NSAlphaShiftKeyMask")); CFNumberGetValue(alphaLock, kCFNumberCharType, &alphaLockCFlag); commandKey= CFDictionaryGetValue(keypressModifierFlags, CFSTR("NSCommandKeyMask")); CFNumberGetValue(commandKey, kCFNumberCharType, &commandKeyCFlag); controlKey= CFDictionaryGetValue(keypressModifierFlags, CFSTR("NSControlKeyMask")); CFNumberGetValue(controlKey, kCFNumberCharType, &controlKeyCFlag); optionKey= CFDictionaryGetValue(keypressModifierFlags, CFSTR("NSAlternateKeyMask")); CFNumberGetValue(optionKey, kCFNumberCharType, &optionKeyCFlag); shiftKey= CFDictionaryGetValue(keypressModifierFlags, CFSTR("NSShiftKeyMask")); CFNumberGetValue(shiftKey, kCFNumberCharType, &shiftKeyCFlag); numericKeypad= CFDictionaryGetValue(keypressModifierFlags, CFSTR("NSNumericPadKeyMask")); CFNumberGetValue(numericKeypad, kCFNumberCharType, &numericKeypadCFlag); // helpKey= CFDictionaryGetValue(keypressModifierFlags, CFSTR("NSHelpKeyMask")); // CFNumberGetValue(helpKey, kCFNumberCharType, &helpKeyCFlag); functionKey= CFDictionaryGetValue(keypressModifierFlags, CFSTR("NSFunctionKeyMask")); CFNumberGetValue(functionKey, kCFNumberCharType, &functionKeyCFlag); PsychAllocOutStructArray(2, TRUE, numStructElements, numStructFieldNames, charTimeFieldNames, &charTimeStruct); // missing from OS X // PsychSetStructArrayBooleanElement("mouseButton", 0, , charTimeStruct); // same in OS X and OS 9 PsychSetStructArrayDoubleElement("ticks", 0, keypressTickCountDouble, charTimeStruct); PsychSetStructArrayDoubleElement("secs", 0, keypressTimeDouble, charTimeStruct); PsychSetStructArrayDoubleElement("address", 0, keypressAddressDouble, charTimeStruct); PsychSetStructArrayBooleanElement("alphaLock", 0, (Boolean)alphaLockCFlag, charTimeStruct); PsychSetStructArrayBooleanElement("commandKey", 0, (Boolean)commandKeyCFlag, charTimeStruct); PsychSetStructArrayBooleanElement("controlKey", 0, (Boolean)controlKeyCFlag, charTimeStruct); PsychSetStructArrayBooleanElement("optionKey", 0, (Boolean)optionKeyCFlag, charTimeStruct); // new for OS X PsychSetStructArrayBooleanElement("shiftKey", 0, (Boolean)shiftKeyCFlag, charTimeStruct); PsychSetStructArrayBooleanElement("numericKeypad", 0, (Boolean)numericKeypadCFlag, charTimeStruct); // PsychSetStructArrayBooleanElement("helpKey", 0, (Boolean)helpKeyCFlag, charTimeStruct); PsychSetStructArrayBooleanElement("functionKey", 0, (Boolean)functionKeyCFlag, charTimeStruct); } CFRelease(keypressDictionary); } //close: if(keypressDictionary != NULL){ }else{// if(!lostKeyWindowFlag){ //If we get to here, that means that GetChar was called, set its key gathering window to be the key window, and while waiting //for key input another window was made the key window. How should we handle this case? Here we return nan for both arguments. //If we prefer to return an error, this could be done in the .m file wrapper, "Getchar" instead of here in "CocoaEventBridge('Getchar'); PsychCopyOutDoubleArg(1, kPsychArgOptional, PsychGetNanValue()); PsychCopyOutDoubleArg(2, kPsychArgOptional, PsychGetNanValue()); } return(PsychError_none); }